summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore2
-rw-r--r--src/CMakeLists.txt162
-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/alchemist_recipe.hpp11
-rw-r--r--src/alchemist_recipe_fwd.hpp3
-rw-r--r--src/alloc_entry.hpp20
-rw-r--r--src/alloc_entry_fwd.hpp3
-rw-r--r--src/angband.h26
-rw-r--r--src/angband.rc15
-rw-r--r--src/artifact_select_flag.hpp18
-rw-r--r--src/artifact_select_flag_fwd.hpp3
-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)463
-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)878
-rw-r--r--src/bldg.hpp9
-rw-r--r--src/body.hpp12
-rw-r--r--src/cave.cc (renamed from src/cave.c)1067
-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)531
-rw-r--r--src/cmd1.hpp25
-rw-r--r--src/cmd2.cc (renamed from src/cmd2.c)962
-rw-r--r--src/cmd2.hpp34
-rw-r--r--src/cmd3.cc (renamed from src/cmd3.c)731
-rw-r--r--src/cmd3.hpp24
-rw-r--r--src/cmd4.cc (renamed from src/cmd4.c)834
-rw-r--r--src/cmd4.hpp28
-rw-r--r--src/cmd5.cc (renamed from src/cmd5.c)760
-rw-r--r--src/cmd5.hpp16
-rw-r--r--src/cmd6.cc (renamed from src/cmd6.c)4978
-rw-r--r--src/cmd6.hpp18
-rw-r--r--src/cmd7.cc (renamed from src/cmd7.c)1036
-rw-r--r--src/cmd7.hpp30
-rw-r--r--src/cmovie.c496
-rw-r--r--src/config.h66
-rw-r--r--src/corrupt.cc (renamed from src/corrupt.c)51
-rw-r--r--src/corrupt.hpp47
-rw-r--r--src/defines.h869
-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)754
-rw-r--r--src/dungeon.h14
-rw-r--r--src/dungeon.hpp6
-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.h2377
-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)416
-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)17
-rw-r--r--src/gen_evol.hpp6
-rw-r--r--src/gen_maze.cc (renamed from src/gen_maze.c)23
-rw-r--r--src/gen_maze.hpp5
-rw-r--r--src/generate.cc (renamed from src/generate.c)563
-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)26
-rw-r--r--src/gods.hpp13
-rw-r--r--src/h-basic.h10
-rw-r--r--src/h-config.h185
-rw-r--r--src/h-define.h19
-rw-r--r--src/h-system.h44
-rw-r--r--src/h-type.h8
-rw-r--r--src/help.cc (renamed from src/help.c)21
-rw-r--r--src/help.hpp11
-rw-r--r--src/help_info.hpp17
-rw-r--r--src/hiscore.cc (renamed from src/hiscore.c)6
-rw-r--r--src/hiscore.hpp (renamed from src/hiscore.h)24
-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/sglib.h1952
-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)1426
-rw-r--r--src/init1.hpp27
-rw-r--r--src/init2.c2738
-rw-r--r--src/init2.cc1525
-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/joke.cc (renamed from src/joke.c)17
-rw-r--r--src/joke.hpp5
-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)2499
-rw-r--r--src/loadsave.h16
-rw-r--r--src/loadsave.hpp7
-rw-r--r--src/lua_bind.c342
-rw-r--r--src/lua_bind.cc277
-rw-r--r--src/lua_bind.hpp34
-rw-r--r--src/magic_power.hpp15
-rw-r--r--src/maid-x11.c855
-rw-r--r--src/main-crb.c5963
-rw-r--r--src/main-gcu.c178
-rw-r--r--src/main-gtk2.c2575
-rw-r--r--src/main-sdl.c134
-rw-r--r--src/main-win.c816
-rw-r--r--src/main-x11.c485
-rw-r--r--src/main-xaw.c1880
-rw-r--r--src/main-xxx.c785
-rw-r--r--src/main.c303
-rw-r--r--src/martial_arts.hpp18
-rw-r--r--src/melee1.cc (renamed from src/melee1.c)93
-rw-r--r--src/melee1.hpp7
-rw-r--r--src/melee2.cc (renamed from src/melee2.c)636
-rw-r--r--src/melee2.hpp12
-rw-r--r--src/messages.cc (renamed from src/messages.c)16
-rw-r--r--src/messages.h13
-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.cc (renamed from src/mimic.c)39
-rw-r--r--src/mimic.hpp10
-rw-r--r--src/module_type.hpp64
-rw-r--r--src/modules.cc (renamed from src/modules.c)151
-rw-r--r--src/modules.h15
-rw-r--r--src/modules.hpp11
-rw-r--r--src/monster1.cc (renamed from src/monster1.c)101
-rw-r--r--src/monster1.hpp5
-rw-r--r--src/monster2.cc (renamed from src/monster2.c)410
-rw-r--r--src/monster2.hpp52
-rw-r--r--src/monster3.cc (renamed from src/monster3.c)71
-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.hpp90
-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)22
-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/object1.cc (renamed from src/object1.c)1051
-rw-r--r--src/object1.hpp46
-rw-r--r--src/object2.cc (renamed from src/object2.c)535
-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.hpp86
-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_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.c403
-rw-r--r--src/plots.h68
-rw-r--r--src/power_type.hpp19
-rw-r--r--src/powers.cc (renamed from src/powers.c)253
-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.cc (renamed from src/q_bounty.c)85
-rw-r--r--src/q_bounty.hpp8
-rw-r--r--src/q_dragons.cc (renamed from src/q_dragons.c)37
-rw-r--r--src/q_dragons.hpp5
-rw-r--r--src/q_eol.cc (renamed from src/q_eol.c)98
-rw-r--r--src/q_eol.hpp5
-rw-r--r--src/q_evil.cc (renamed from src/q_evil.c)38
-rw-r--r--src/q_evil.hpp5
-rw-r--r--src/q_fireprof.cc (renamed from src/q_fireprof.c)111
-rw-r--r--src/q_fireprof.hpp7
-rw-r--r--src/q_god.cc (renamed from src/q_god.c)85
-rw-r--r--src/q_god.hpp6
-rw-r--r--src/q_haunted.cc (renamed from src/q_haunted.c)39
-rw-r--r--src/q_haunted.hpp5
-rw-r--r--src/q_hobbit.cc (renamed from src/q_hobbit.c)119
-rw-r--r--src/q_hobbit.hpp5
-rw-r--r--src/q_invas.cc (renamed from src/q_invas.c)92
-rw-r--r--src/q_invas.hpp5
-rw-r--r--src/q_library.cc (renamed from src/q_library.c)36
-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.cc144
-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)141
-rw-r--r--src/q_one.hpp5
-rw-r--r--src/q_poison.cc (renamed from src/q_poison.c)78
-rw-r--r--src/q_poison.hpp5
-rw-r--r--src/q_rand.cc (renamed from src/q_rand.c)302
-rw-r--r--src/q_rand.hpp8
-rw-r--r--src/q_shroom.cc (renamed from src/q_shroom.c)206
-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)52
-rw-r--r--src/q_thief.hpp5
-rw-r--r--src/q_thrain.cc (renamed from src/q_thrain.c)93
-rw-r--r--src/q_thrain.hpp5
-rw-r--r--src/q_troll.cc (renamed from src/q_troll.c)79
-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)66
-rw-r--r--src/q_wight.hpp5
-rw-r--r--src/q_wolves.cc (renamed from src/q_wolves.c)39
-rw-r--r--src/q_wolves.hpp5
-rw-r--r--src/quark.cc (renamed from src/quark.c)16
-rw-r--r--src/quark.h18
-rw-r--r--src/quark.hpp12
-rw-r--r--src/quest.cc17
-rw-r--r--src/quest.hpp3
-rw-r--r--src/quest_type.hpp27
-rw-r--r--src/randart.cc (renamed from src/randart.c)77
-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.cc (renamed from src/range.c)4
-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.cc (renamed from src/script.c)12
-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)559
-rw-r--r--src/skills.hpp27
-rw-r--r--src/skills_defs.hpp64
-rw-r--r--src/spell_type.cc (renamed from src/spell_type.c)184
-rw-r--r--src/spell_type.hpp (renamed from src/spell_type.h)73
-rw-r--r--src/spell_type_fwd.hpp (renamed from src/spell_type_fwd.h)13
-rw-r--r--src/spells1.cc (renamed from src/spells1.c)381
-rw-r--r--src/spells1.hpp32
-rw-r--r--src/spells2.cc (renamed from src/spells2.c)2409
-rw-r--r--src/spells2.hpp115
-rw-r--r--src/spells3.cc (renamed from src/spells3.c)1126
-rw-r--r--src/spells3.hpp445
-rw-r--r--src/spells4.cc (renamed from src/spells4.c)343
-rw-r--r--src/spells4.hpp43
-rw-r--r--src/spells5.cc (renamed from src/spells5.c)436
-rw-r--r--src/spells5.hpp9
-rw-r--r--src/spells6.cc (renamed from src/spells6.c)106
-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.c3582
-rw-r--r--src/squeltch.cc596
-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)262
-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/string_list.c52
-rw-r--r--src/tables.cc (renamed from src/tables.c)278
-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)183
-rw-r--r--src/traps.hpp13
-rw-r--r--src/tval_desc.hpp17
-rw-r--r--src/types.h2771
-rw-r--r--src/util.cc (renamed from src/util.c)524
-rw-r--r--src/util.h22
-rw-r--r--src/util.hpp76
-rw-r--r--src/variable.cc (renamed from src/variable.c)532
-rw-r--r--src/variable.h40
-rw-r--r--src/variable.hpp317
-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)123
-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)80
-rw-r--r--src/wizard1.hpp3
-rw-r--r--src/wizard2.cc (renamed from src/wizard2.c)199
-rw-r--r--src/wizard2.hpp8
-rw-r--r--src/xtra1.cc (renamed from src/xtra1.c)859
-rw-r--r--src/xtra1.hpp24
-rw-r--r--src/xtra2.cc (renamed from src/xtra2.c)656
-rw-r--r--src/xtra2.hpp94
-rw-r--r--src/z-form.c167
-rw-r--r--src/z-form.h18
-rw-r--r--src/z-rand.h8
-rw-r--r--src/z-term.c986
-rw-r--r--src/z-term.h101
-rw-r--r--src/z-util.c172
-rw-r--r--src/z-util.h60
-rw-r--r--src/z-virt.c145
-rw-r--r--src/z-virt.h164
414 files changed, 26524 insertions, 51745 deletions
diff --git a/src/.gitignore b/src/.gitignore
index be576d7b..0799f693 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,3 @@
-/tolua
+/harness
/tome
w_*.c
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 03c1771b..dcd1e518 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,29 +1,136 @@
-SET(SRCS
- main-gcu.c main-x11.c main-xaw.c main-sdl.c main-gtk2.c
- z-rand.c z-util.c z-form.c z-virt.c z-term.c
- variable.c tables.c plots.c util.c cave.c dungeon.c
- melee1.c melee2.c messages.c modules.c
- q_god.c
- object1.c object2.c randart.c squeltch.c traps.c
- monster1.c monster2.c monster3.c
- xtra1.c xtra2.c skills.c powers.c gods.c
- spells1.c spells2.c spells3.c spells4.c spells5.c spells6.c
- spell_type.c
- corrupt.c joke.c mimic.c
- status.c files.c notes.c loadsave.c string_list.c
- cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c
- help.c hiscore.c range.c
- generate.c gen_maze.c gen_evol.c wild.c levels.c store.c bldg.c
- cmovie.c
- wizard2.c init2.c birth.c wizard1.c init1.c main.c
- quark.c
- # Lua bits:
- lua_bind.c script.c
+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
+ 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.c
+ z-term.c
+ z-util.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,12 +145,13 @@ if(WIN32)
endif(MINGW)
endif(WIN32)
-
# tome executable
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
-ADD_EXECUTABLE(tome ${EXECUTABLE_OPTIONS} ${SRCS})
-TARGET_LINK_LIBRARIES(tome ${LIBS})
+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/alchemist_recipe.hpp b/src/alchemist_recipe.hpp
new file mode 100644
index 00000000..e87531f6
--- /dev/null
+++ b/src/alchemist_recipe.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct alchemist_recipe
+{
+ int sval_essence;
+ byte tval;
+ byte sval;
+ byte qty;
+};
diff --git a/src/alchemist_recipe_fwd.hpp b/src/alchemist_recipe_fwd.hpp
new file mode 100644
index 00000000..d1a8bb77
--- /dev/null
+++ b/src/alchemist_recipe_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct alchemist_recipe;
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 6bfbb984..ccf5295a 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,7 +26,6 @@ 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,19 +38,9 @@ extern "C" {
/*
- * SGLIB
- */
-#include "sglib.h"
-
-
-/*
- * 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 "spell_type_fwd.h"
-#include "externs.h"
-#include "plots.h"
/***** Some copyright messages follow below *****/
@@ -110,8 +93,3 @@ extern "C" {
#ifdef __cplusplus
} /* extern "C" */
#endif
-
-#endif
-
-
-
diff --git a/src/angband.rc b/src/angband.rc
index 547d43a1..37856f4a 100644
--- a/src/angband.rc
+++ b/src/angband.rc
@@ -101,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_select_flag.hpp b/src/artifact_select_flag.hpp
new file mode 100644
index 00000000..313f3a19
--- /dev/null
+++ b/src/artifact_select_flag.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+
+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 */
+ char *desc; /* Display this description to select flag */
+ u32b xp; /* xp cost for this flag */
+ bool_ pval; /* indicates this flag benifits from pval */
+ char *item_desc; /* Description of required item */
+ char *item_descp; /* Description of required item; plural */
+ 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 */
+};
diff --git a/src/artifact_select_flag_fwd.hpp b/src/artifact_select_flag_fwd.hpp
new file mode 100644
index 00000000..f56ec3c9
--- /dev/null
+++ b/src/artifact_select_flag_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct artifact_select_flag;
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 85939b8e..9716cc8b 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,10 +5,57 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
-
-#include "messages.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 <string>
/*
* How often the autoroller will update the display and pause
@@ -57,7 +100,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",
@@ -67,7 +110,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",
@@ -75,7 +118,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",
@@ -94,7 +137,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;
@@ -185,9 +228,6 @@ static void save_prev_data(void)
}
previous_char.luck = p_ptr->luck_base;
- /* Save the weapon specialty */
- previous_char.weapon = 0;
-
/* Save the history */
for (i = 0; i < 4; i++)
{
@@ -222,9 +262,6 @@ static void load_prev_data(bool_ save)
}
temp.luck = p_ptr->luck_base;
- /* Save the weapon specialty */
- temp.weapon = 0;
-
/* Save the history */
for (i = 0; i < 4; i++)
{
@@ -274,12 +311,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++)
{
@@ -334,22 +365,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++;
- }
}
}
@@ -418,25 +437,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,11 +468,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;
@@ -549,7 +551,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;
@@ -618,7 +620,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;
@@ -804,7 +806,11 @@ static void player_wipe(void)
wipe_saved();
/* 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));
+
+ /* Level 1 is the first level */
+ p_ptr->lev = 1;
/* Not dead yet */
p_ptr->lives = 0;
@@ -838,9 +844,9 @@ static void player_wipe(void)
for (i = 0; i < MAX_Q_IDX; i++)
{
quest[i].status = QUEST_STATUS_UNTAKEN;
- for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++)
+ for (auto &quest_data : quest[i].data)
{
- quest[i].data[j] = 0;
+ quest_data = 0;
}
}
@@ -964,12 +970,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;
@@ -1005,8 +1005,6 @@ 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; i++)
{
@@ -1088,8 +1086,8 @@ static void player_outfit_spellbook(cptr spell_name)
static void player_outfit(void)
{
int i;
- cptr class_name = spp_ptr->title + c_name;
- cptr subrace_name = rmp_ptr->title + rmp_name;
+ cptr class_name = spp_ptr->title;
+ cptr subrace_name = rmp_ptr->title;
/*
* Get an adventurer guide describing a bit of the
@@ -1223,14 +1221,14 @@ static void player_outfit(void)
identify_pack_fully();
}
- if (streq(rmp_ptr->title + rmp_name, "Vampire"))
+ 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(HOOK_BIRTH_OBJECTS, "()");
+ process_hooks_new(HOOK_BIRTH_OBJECTS, NULL, NULL);
meta_inertia_control_hook_birth_objects();
{
@@ -1287,169 +1285,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;
-
- /* If module says a monster race is friendly, then skip */
- if (modules[game_module_idx].race_status != NULL)
- {
- s16b *status = (*modules[game_module_idx].race_status)(q_ptr->r_idx);
- if ((status != NULL) && (*status >= 0))
- {
- continue;
- }
- }
-
- /* Assume no explosion attacks */
- ok = TRUE;
-
- /* Reject monsters with exploding attacks */
- for (k = 0; k < 4; k++)
- {
- if (r_ptr->blow[k].method == RBM_EXPLODE) ok = FALSE;
- }
- if (!ok) continue;
-
- /* No mutliple uniques */
- if ((r_ptr->flags1 & RF1_UNIQUE) &&
- ((q_ptr->type != 1) || (r_ptr->max_num == -1))) continue;
-
- /* No single non uniques */
- if ((!(r_ptr->flags1 & RF1_UNIQUE)) && (q_ptr->type == 1)) continue;
-
- /* Level restriction */
- min_level = (rl > RQ_LEVEL_CAP) ? RQ_LEVEL_CAP : rl;
-
- /* Accept monsters matching the level restriction */
- if (r_ptr->level > min_level) break;
- }
-
- /* Arg could not find anything ??? */
- if (!tries)
- {
- if (wizard)
- {
- message_add(format("Could not find quest monster on lvl %d", rl), TERM_RED);
- }
- q_ptr->type = 0;
- }
- else
- {
- if (r_ptr->flags1 & RF1_UNIQUE)
- {
- r_ptr->max_num = -1;
- }
-
- q_ptr->done = FALSE;
-
- if (wizard)
- {
- message_add(format("Quest for %d on lvl %d",
- q_ptr->r_idx, rl), TERM_RED);
- }
- }
-
- lvl += step;
- }
-
- dungeon_type = old_type;
-}
-
int dump_classes(s16b *classes, int sel, u32b *restrictions)
{
int n = 0;
char buf[80];
- char *desc;
-
- cptr str;
-
- C_MAKE(desc, c_head->text_size, char);
/* Clean up */
clear_from(12);
@@ -1462,7 +1302,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)
{
@@ -1472,14 +1311,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)
@@ -1498,8 +1343,6 @@ int dump_classes(s16b *classes, int sel, u32b *restrictions)
n++;
}
- C_FREE(desc, c_head->text_size, char);
-
return (n);
}
@@ -1508,11 +1351,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);
@@ -1527,7 +1365,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)
{
@@ -1536,14 +1373,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));
@@ -1559,8 +1402,6 @@ int dump_specs(int sel)
}
}
- C_FREE(desc, c_head->text_size, char);
-
return (n);
}
@@ -1569,11 +1410,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);
@@ -1585,7 +1421,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)
{
@@ -1594,14 +1429,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));
@@ -1617,8 +1458,6 @@ int dump_races(int sel)
}
}
- C_FREE(desc, rp_head->text_size, char);
-
return (n);
}
@@ -1628,11 +1467,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);
@@ -1645,7 +1479,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)
{
@@ -1655,16 +1488,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));
@@ -1680,8 +1519,6 @@ int dump_rmods(int sel, int *racem, int max)
}
}
- C_FREE(desc, rmp_head->text_size, char);
-
return (n);
}
@@ -1754,8 +1591,6 @@ static bool_ player_birth_aux_ask()
u32b restrictions[2];
- cptr str;
-
char c;
char p2 = ')';
@@ -1842,10 +1677,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));
}
@@ -1878,10 +1712,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);
@@ -1927,7 +1760,7 @@ static bool_ player_birth_aux_ask()
if ((k >= 0) && (k < n)) break;
if (c == '?')
{
- help_race(race_info[sel].title + rp_name);
+ help_race(race_info[sel].title);
}
else if (c == '=')
{
@@ -1973,10 +1806,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);
@@ -2053,7 +1885,7 @@ static bool_ player_birth_aux_ask()
}
else if (c == '?')
{
- help_subrace(race_mod_info[racem[sel]].title + rmp_name);
+ help_subrace(race_mod_info[racem[sel]].title);
}
k = (islower(c) ? A2I(c) : -1);
@@ -2199,7 +2031,7 @@ static bool_ player_birth_aux_ask()
if ((k >= 0) && (k < n)) break;
if (c == '?')
{
- help_class(class_info[class_types[sel]].title + c_name);
+ help_class(class_info[class_types[sel]].title);
}
else if (c == '=')
{
@@ -2281,7 +2113,7 @@ static bool_ player_birth_aux_ask()
if ((k >= 0) && (k < n)) break;
if (c == '?')
{
- help_class(class_info[p_ptr->pclass].spec[sel].title + c_name);
+ help_class(class_info[p_ptr->pclass].spec[sel].title);
}
else if (c == '=')
{
@@ -2327,10 +2159,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);
@@ -2342,7 +2173,7 @@ 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;
}
@@ -2449,7 +2280,7 @@ static bool_ player_birth_aux_ask()
}
/* A god that like us ? more grace ! */
- if (PRACE_FLAGS(PR1_GOD_FRIEND))
+ if (race_flags1_p(PR1_GOD_FRIEND))
{
set_grace(200);
}
@@ -2477,10 +2308,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)
@@ -2571,9 +2401,8 @@ 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;
@@ -2671,9 +2500,6 @@ static bool_ player_birth_aux_point(void)
/* Roll for social class */
get_history();
- /*** Generate ***/
- process_hooks(HOOK_BIRTH, "()");
-
/* Get luck */
p_ptr->luck_base = rp_ptr->luck + rmp_ptr->luck + rand_range( -5, 5);
p_ptr->luck_max = p_ptr->luck_base;
@@ -2687,24 +2513,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];
@@ -2946,7 +2756,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);
@@ -3021,11 +2831,8 @@ static bool_ player_birth_aux_auto()
/* Make sure they see everything */
Term_fresh();
- /* Do not wait for a key */
- inkey_scan = TRUE;
-
/* Check for a keypress */
- if (inkey()) break;
+ if (inkey_scan()) break;
}
}
@@ -3050,9 +2857,6 @@ static bool_ player_birth_aux_auto()
/* Roll for gold */
get_money();
- /*** Generate ***/
- process_hooks(HOOK_BIRTH, "()");
-
/* Input loop */
while (TRUE)
{
@@ -3574,9 +3378,6 @@ void player_birth(void)
wild_map[j][i].known = FALSE;
}
}
-
- /* Select bounty monsters. */
- select_bounties();
}
@@ -3732,7 +3533,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++)
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 6b785d2a..dd433323 100644
--- a/src/bldg.c
+++ b/src/bldg.cc
@@ -13,10 +13,33 @@
* 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"
/* remember building location */
static int building_loc = 0;
@@ -25,7 +48,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 +119,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 +197,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 +445,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 +540,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 +630,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 +701,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 +722,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;
@@ -896,7 +769,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 +896,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 +906,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 +938,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 +1090,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 +1131,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 +1162,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 +1195,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 +1343,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,83 +1392,6 @@ 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);
-
- req = get_quantity(prompt, req);
-
- p_ptr->loan -= req;
- p_ptr->au -= req;
-
- if (!p_ptr->loan) p_ptr->loan_time = 0;
-
- msg_format("You pay back %i gold pieces", req);
- paid = TRUE;
- break;
- }
-
case BACT_DROP_ITEM:
{
quest_bounty_drop_item();
@@ -2063,14 +1425,8 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
}
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)
@@ -2110,121 +1466,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/cave.c b/src/cave.cc
index ab1ce56e..1dc5cbdb 100644
--- a/src/cave.c
+++ b/src/cave.cc
@@ -1,10 +1,29 @@
-/* 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 <cassert>
+#include <vector>
+#include <iterator>
+#include <algorithm>
/*
* Support for Adam Bolt's tileset, lighting and transparency effects
@@ -347,24 +366,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 +387,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,16 +472,8 @@ static void image_random(byte *ap, char *cp)
}
-/*
- * The 16x16 tile of the terrain supports lighting
- */
-static bool_ feat_supports_lighting(byte feat)
-{
- return (f_info[feat].flags1 & FF1_SUPPORT_LIGHT) != 0;
-}
-
-char get_shimmer_color()
+static char get_shimmer_color()
{
switch (randint(7))
{
@@ -856,60 +822,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)
@@ -922,12 +853,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 ****/
@@ -955,8 +881,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;
}
@@ -965,67 +890,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)
@@ -1059,8 +956,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))
@@ -1068,62 +964,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];
}
}
}
@@ -1132,8 +996,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))
@@ -1144,44 +1007,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 */
}
}
}
@@ -1211,10 +1050,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;
@@ -1224,15 +1059,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)
@@ -1244,8 +1074,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();
}
@@ -1269,10 +1098,8 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
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)
@@ -1284,8 +1111,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();
}
@@ -1301,28 +1127,6 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
{
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;
@@ -1337,16 +1141,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))
{
@@ -1426,12 +1220,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();
}
@@ -1443,67 +1233,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;
+ int percent = p_ptr->chp * 10 / p_ptr->mhp;
- if (percent < 7)
- {
- c = I2D(percent);
- if (percent < 3) a = TERM_L_RED;
- }
- }
-
- break;
- }
-
- case GRAPHICS_OLD:
+ if (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 */
@@ -1515,48 +1254,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)
@@ -1569,7 +1288,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 ****/
@@ -1607,7 +1326,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
@@ -1771,15 +1490,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)
@@ -1816,10 +1530,8 @@ void map_info_default(int y, int x, byte *ap, char *cp)
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)
@@ -1831,8 +1543,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();
}
@@ -1958,10 +1669,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;
}
@@ -1971,7 +1678,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;
}
@@ -2001,24 +1707,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);
- }
}
@@ -2070,20 +1758,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;
@@ -2096,8 +1779,7 @@ void note_spot(int y, int x)
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;
}
}
@@ -2136,39 +1818,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);
}
}
@@ -2200,33 +1860,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);
}
}
@@ -2382,11 +2023,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;
@@ -2396,9 +2032,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
*/
@@ -2425,32 +2058,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;
@@ -2469,7 +2092,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);
@@ -2521,54 +2144,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;
@@ -3193,38 +2774,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)
@@ -3282,8 +2831,6 @@ errr vinfo_init(void)
long m;
- vinfo_hack *hack;
-
int num_grids = 0;
int queue_head = 0;
@@ -3292,8 +2839,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)
@@ -3304,8 +2851,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)
@@ -3321,25 +2868,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);
}
}
@@ -3352,21 +2899,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));
@@ -3409,14 +2950,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)
{
@@ -3497,10 +3038,6 @@ errr vinfo_init(void)
}
- /* Kill hack */
- KILL(hack, vinfo_hack);
-
-
/* Success */
return (0);
}
@@ -4258,32 +3795,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;
@@ -4523,8 +4034,7 @@ void wiz_lite(void)
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;
}
}
@@ -4859,7 +4369,7 @@ void health_track(int m_idx)
health_who = m_idx;
/* Redraw (later) */
- p_ptr->redraw |= (PR_HEALTH);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -4898,15 +4408,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; */
@@ -4917,7 +4422,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 */
@@ -4927,7 +4432,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 */
@@ -4950,7 +4455,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 */
@@ -4958,33 +4463,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)))
{
@@ -4996,6 +4484,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
*/
@@ -5024,3 +4531,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 a349ac12..02ad1fd8 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,9 +6,45 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "quark.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"
#define MAX_VAMPIRIC_DRAIN 100
@@ -527,30 +559,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))
@@ -562,7 +587,7 @@ void search(void)
msg_print("You have found a trap.");
/* Disturb */
- disturb(0, 0);
+ disturb(0);
}
/* Secret door */
@@ -577,20 +602,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;
@@ -608,7 +626,7 @@ void search(void)
object_known(o_ptr);
/* Notice it */
- disturb(0, 0);
+ disturb(0);
}
}
}
@@ -644,7 +662,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];
@@ -655,7 +673,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);
}
}
}
@@ -814,7 +832,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)
@@ -1207,7 +1225,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);
@@ -1333,7 +1351,7 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
if (!effect || check_hit2(power, rlev, ac))
{
/* Always disturbing */
- disturb(1, 0);
+ disturb(1);
/* Describe the attack method */
switch (method)
@@ -1726,7 +1744,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);
@@ -2186,7 +2204,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)
{
@@ -2214,13 +2232,6 @@ void py_attack(int y, int x, int max_blow)
/* Extract monster name (or "it") */
monster_desc(m_name, m_ptr, 0);
- /* Dont even bother */
- if (r_ptr->flags7 & RF7_IM_MELEE)
- {
- msg_format("%^s is immune to melee attacks.");
- return;
- }
-
/* Auto-Recall if possible and visible */
if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego);
@@ -2440,7 +2451,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))
{
@@ -2467,9 +2478,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 = get_level_s(MELKOR_CURSE, 100);
+ int lv = get_level(MELKOR_CURSE, 100, 1);
if (lv >= 10)
{
@@ -2865,7 +2876,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;
@@ -2903,7 +2914,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);
}
@@ -2931,6 +2942,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.
@@ -3099,8 +3223,6 @@ 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)) {
@@ -3188,13 +3310,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))
{
@@ -3209,7 +3324,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)
{
@@ -3244,7 +3359,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);
}
@@ -3256,61 +3371,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;
}
}
@@ -3326,7 +3415,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
energy_use = 0;
}
- disturb(0, 0); /* To avoid a loop with running */
+ disturb(0); /* To avoid a loop with running */
oktomove = FALSE;
}
@@ -3349,7 +3438,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;
@@ -3384,9 +3473,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);
@@ -3404,13 +3490,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 */
@@ -3423,16 +3509,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 */
@@ -3458,7 +3544,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 = '_';
@@ -3467,7 +3553,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);
@@ -3481,7 +3567,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)))
{
@@ -3500,7 +3586,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);
@@ -3902,9 +3988,6 @@ static bool_ run_test(void)
int option = 0, option2 = 0;
- cave_type *c_ptr;
-
-
/* Where we came from */
prev_dir = find_prevdir;
@@ -3916,9 +3999,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];
@@ -3927,7 +4007,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 */
@@ -3940,15 +4020,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);
@@ -4122,7 +4197,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))
@@ -4154,7 +4229,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))
@@ -4283,7 +4358,7 @@ void run_step(int dir)
msg_print("You cannot run in that direction.");
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Done */
return;
@@ -4303,7 +4378,7 @@ void run_step(int dir)
if (run_test())
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Done */
return;
@@ -4323,45 +4398,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)
@@ -4374,7 +4410,7 @@ void do_cmd_pet(void)
char power_desc[36][80];
- bool_ flag, redraw;
+ bool_ flag;
int ask;
@@ -4453,80 +4489,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();
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
- prt("", y++, x);
-
- while (ctr < num)
- {
- strnfmt(dummy, 80, "%c) %s", I2A(ctr), power_desc[ctr]);
- prt(dummy, y + ctr, x);
- ctr++;
- }
+ /* Show the list */
+ {
+ byte y = 1, x = 0;
+ int ctr = 0;
+ char dummy[80];
- if (ctr < 17)
- {
- prt("", y + ctr, x);
- }
- else
- {
- prt("", y + 17, x);
- }
- }
+ strcpy(dummy, "");
- /* Hide the list */
- else
- {
- /* Hide list */
- redraw = FALSE;
+ prt("", y++, x);
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
- }
+ while (ctr < num)
+ {
+ strnfmt(dummy, 80, "%c) %s", I2A(ctr), power_desc[ctr]);
+ prt(dummy, y + ctr, x);
+ ctr++;
+ }
- /* Redo asking */
- continue;
+ if (ctr < 17)
+ {
+ prt("", y + ctr, x);
}
+ else
+ {
+ prt("", y + 17, x);
+ }
+ }
+ /* Get a command from the user */
+ while (!flag && get_com(out_val, &choice))
+ {
if (choice == '\r' && num == 1)
{
choice = 'a';
@@ -4574,11 +4585,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)
@@ -4809,35 +4817,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;
@@ -4851,8 +4855,6 @@ bool_ do_cmd_integrate_body()
p_ptr->wraith_form = FALSE;
p_ptr->disembodied = FALSE;
do_cmd_redraw();
-
- return TRUE;
}
/*
@@ -4985,15 +4987,16 @@ bool_ execute_inscription(byte i, byte y, byte x)
{
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];
+ m_ptr = &m_list[c_ptr->m_idx];
r_ptr = race_inf(m_ptr);
if (r_ptr->flags7 & RF7_CAN_FLY)
@@ -5005,34 +5008,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 20ef50af..768e79c0 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,54 @@
* 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 <chrono>
+#include <thread>
+
+using std::this_thread::sleep_for;
+using std::chrono::milliseconds;
void do_cmd_immovable_special(void);
@@ -79,23 +122,10 @@ static bool_ do_cmd_bash_fountain(int y, int x)
*/
static bool_ stair_hooks(stairs_direction direction)
{
- cptr direction_s = (direction == STAIRS_UP) ? "up" : "down";
-
- /* Old-style hooks */
- if (process_hooks(HOOK_STAIR, "(s)", direction_s))
- {
- return TRUE; /* Prevent movement */
- }
-
- /* New-style hooks */
- {
- hook_stair_in in = { direction };
- hook_stair_out out = { TRUE }; /* Allow by default */
-
- process_hooks_new(HOOK_STAIR, &in, &out);
-
- return (!out.allow);
- }
+ hook_stair_in in = { direction };
+ hook_stair_out out = { TRUE }; /* Allow by default */
+ process_hooks_new(HOOK_STAIR, &in, &out);
+ return (!out.allow);
}
@@ -484,10 +514,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 */
@@ -509,8 +542,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
{
@@ -549,7 +581,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;
@@ -568,31 +600,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;
}
@@ -604,20 +614,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; */
@@ -741,7 +745,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);
}
}
@@ -1130,8 +1134,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;
@@ -1165,7 +1168,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;
@@ -1220,11 +1223,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);
}
@@ -1300,8 +1300,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;
@@ -1332,7 +1331,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;
@@ -1377,7 +1376,7 @@ void do_cmd_close(void)
}
/* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -1410,7 +1409,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);
@@ -1464,7 +1463,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];
@@ -1501,7 +1500,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))
@@ -1518,7 +1517,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 */
@@ -1543,7 +1542,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;
}
}
@@ -1623,7 +1622,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;
}
}
@@ -1657,7 +1656,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;
}
}
@@ -1688,7 +1687,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 */
@@ -1711,7 +1710,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;
}
}
@@ -1768,7 +1767,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;
@@ -1821,124 +1820,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);
}
@@ -2029,7 +1911,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;
@@ -2048,9 +1930,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;
@@ -2149,8 +2035,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;
@@ -2175,7 +2060,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;
@@ -2234,7 +2119,7 @@ void do_cmd_disarm(void)
}
/* Cancel repeat unless told not to */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -2386,7 +2271,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;
@@ -2443,7 +2328,7 @@ void do_cmd_bash(void)
}
/* Unless valid action taken, cancel bash */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -2474,7 +2359,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;
@@ -2531,7 +2416,7 @@ void do_cmd_alter(void)
}
/* Cancel repetition unless we can continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -2656,7 +2541,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;
@@ -2698,7 +2583,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);
}
@@ -2778,7 +2835,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;
@@ -2810,7 +2867,7 @@ void do_cmd_stay(int pickup)
if (c_ptr->feat == FEAT_SHOP)
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Hack -- enter store */
command_new = '_';
@@ -2830,7 +2887,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;
@@ -2900,7 +2957,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();
@@ -3082,8 +3139,6 @@ void do_cmd_fire(void)
char o_name[80];
- cptr q, s;
-
int msec = delay_factor * delay_factor * delay_factor;
@@ -3112,14 +3167,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);
@@ -3261,7 +3317,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();
}
@@ -3270,7 +3326,7 @@ void do_cmd_fire(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -3491,7 +3547,7 @@ void do_cmd_fire(void)
*/
void do_cmd_throw(void)
{
- int dir, item;
+ int dir;
s32b special = 0;
@@ -3510,8 +3566,6 @@ void do_cmd_throw(void)
object_type *q_ptr;
- object_type *o_ptr;
-
bool_ hit_body = FALSE;
bool_ hit_wall = FALSE;
@@ -3524,20 +3578,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 */
@@ -3677,7 +3731,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();
}
@@ -3686,7 +3740,7 @@ void do_cmd_throw(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -4004,7 +4058,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();
}
@@ -4013,7 +4067,7 @@ void do_cmd_boomerang(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -4180,7 +4234,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();
}
@@ -4189,188 +4243,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);
@@ -4572,13 +4454,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;
@@ -4586,9 +4468,9 @@ 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)
@@ -4608,7 +4490,7 @@ 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 *o_ptr)
+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);
@@ -4621,11 +4503,11 @@ static void do_cmd_sacrifice_aule()
{
int item;
- item_tester_hook = item_tester_hook_sacrifice_aule;
if (!get_item(&item,
"Sacrifice which item? ",
"You have nothing to sacrifice.",
- USE_INVEN))
+ USE_INVEN,
+ item_tester_hook_sacrifice_aule))
{
return;
}
@@ -4653,7 +4535,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
@@ -4661,7 +4543,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;
@@ -4679,7 +4561,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? "))
@@ -4707,15 +4589,18 @@ void do_cmd_sacrifice(void)
}
else
{
+ /* Get an item */
int item;
- object_type *o_ptr;
-
- /* Restrict choices to food */
- item_tester_hook = item_tester_hook_sacrifiable;
+ if (!get_item(&item,
+ "Sacrifice which item? ",
+ "You have nothing to sacrifice.",
+ (USE_INVEN),
+ item_tester_hook_sacrificable))
+ {
+ return;
+ }
- /* Get an item */
- if (!get_item(&item, "Sacrifice which item? ", "You have nothing to sacrifice.", (USE_INVEN))) return;
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Piety for corpses is based on monster level */
if (o_ptr->tval == TV_CORPSE)
@@ -4736,7 +4621,7 @@ void do_cmd_sacrifice(void)
}
}
- GOD(GOD_AULE)
+ if (p_ptr->pgod == GOD_AULE)
{
do_cmd_sacrifice_aule();
}
@@ -4751,147 +4636,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 */
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;
/* 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 */
{
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;
}
@@ -4900,26 +4752,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))
{
@@ -4927,10 +4769,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;
@@ -4945,7 +4787,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)
@@ -4955,7 +4797,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);
@@ -4982,7 +4824,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();
@@ -4990,7 +4832,7 @@ void do_cmd_steal()
}
/* Verify the item */
- if (ver && !verify("Try", 0 - monst_list[k]))
+ if (ver && !verify("Try", -objects[k]))
{
done = TRUE;
@@ -4998,7 +4840,7 @@ void do_cmd_steal()
}
/* Accept that choice */
- item = monst_list[k];
+ item = objects[k];
done = TRUE;
break;
@@ -5036,17 +4878,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;
@@ -5060,8 +4896,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)
@@ -5070,7 +4907,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);
@@ -5082,7 +4919,7 @@ void do_cmd_steal()
inven_carry(o_ptr, FALSE);
}
- /* Delete it */
+ /* Delete source item */
o_list[item].k_idx = 0;
}
@@ -5098,24 +4935,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)
@@ -5125,18 +4954,20 @@ 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))
{
- 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.");
- }
+ msg_print("The monster does not want your item.");
}
/* Take a turn, even if the offer is declined */
@@ -5172,7 +5003,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..41030995
--- /dev/null
+++ b/src/cmd2.hpp
@@ -0,0 +1,34 @@
+#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_create_artifact(object_type *q_ptr);
+extern void do_cmd_steal(void);
diff --git a/src/cmd3.c b/src/cmd3.cc
index 88c5346d..06300982 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,10 +5,42 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
-
-#include "quark.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 <cassert>
+#include <algorithm>
+#include <memory>
+#include <utility>
/*
* Display p_ptr->inventory
@@ -29,16 +57,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();
@@ -90,16 +112,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();
@@ -140,7 +156,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);
@@ -202,27 +218,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);
@@ -255,7 +271,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);
@@ -310,19 +332,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;
@@ -441,7 +450,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);
}
@@ -453,23 +462,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))
@@ -491,7 +495,7 @@ void do_cmd_takeoff(void)
/* Recalculate hitpoint */
p_ptr->update |= (PU_HP);
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -500,27 +504,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))
@@ -546,8 +547,8 @@ void do_cmd_drop(void)
}
}
-
/* See how many items */
+ int amt = 1;
if (o_ptr->number > 1)
{
/* Get a quantity */
@@ -570,37 +571,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 */
@@ -620,17 +617,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))
@@ -679,7 +674,7 @@ void do_cmd_destroy(void)
/* Create an automatizer rule */
if (automatizer_create)
{
- automatizer_add_rule(o_ptr, TRUE);
+ automatizer_add_rule(o_ptr);
}
/*
@@ -706,24 +701,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 */
@@ -741,20 +733,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)
@@ -782,26 +772,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 */
@@ -809,6 +794,7 @@ void do_cmd_inscribe(void)
msg_print(NULL);
/* Start with nothing */
+ char out_val[80];
strcpy(out_val, "");
/* Use old inscription */
@@ -837,17 +823,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;
}
@@ -856,30 +840,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)
@@ -908,14 +887,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;
}
@@ -924,31 +903,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;
@@ -1270,107 +1243,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
*/
@@ -1405,18 +1346,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, "'):");
}
@@ -1436,7 +1375,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;
@@ -1457,11 +1396,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, "
@@ -1508,11 +1443,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];
@@ -1530,22 +1463,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;
}
@@ -1563,41 +1495,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)
@@ -1658,10 +1583,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;
}
}
@@ -1670,17 +1596,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);
}
@@ -1690,7 +1612,7 @@ void do_cmd_query_symbol(void)
*/
bool_ research_mon()
{
- int i, n, r_idx;
+ int i, r_idx;
char sym, query;
@@ -1715,13 +1637,8 @@ bool_ research_mon()
bool_ recall = FALSE;
- u16b why = 0;
-
monster_race *r2_ptr;
- u16b *who;
-
-
/* Hack -- Remember "cheat_know" flag */
oldcheat = cheat_know;
@@ -1729,9 +1646,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)
{
@@ -1752,7 +1666,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];
@@ -1769,15 +1684,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;
@@ -1785,24 +1699,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;
@@ -1873,10 +1777,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;
}
}
@@ -1885,8 +1790,7 @@ bool_ research_mon()
{
if (i-- == 0)
{
- i = n - 1;
- if (!expand_list) break;
+ i = who.size() - 1;
}
}
}
@@ -1895,9 +1799,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;
@@ -1958,131 +1859,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)
@@ -2137,16 +1913,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))
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 da606cc6..c18718ae 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,10 +5,42 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
-
-#include "messages.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 <cassert>
+#include <memory>
+#include <string>
+#include <vector>
+#include <algorithm>
/*
* Hack -- redraw the screen
@@ -60,7 +88,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);
@@ -209,7 +237,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();
}
@@ -449,63 +477,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);
}
@@ -513,15 +531,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)
@@ -534,8 +556,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;
}
@@ -545,7 +568,6 @@ static void do_cmd_options_cheat(cptr info)
case '2':
{
k = (k + 1) % n;
-
break;
}
@@ -553,10 +575,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;
}
@@ -564,9 +588,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;
}
@@ -578,6 +606,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);
+ }
+ }
}
@@ -728,152 +804,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++)
+ if (option_info[i].o_page == page)
{
- byte a = TERM_WHITE;
-
- /* Color current option */
- if (i == k) a = TERM_L_BLUE;
-
- /* Display the option text */
- strnfmt(buf, 80, "%-48s: %s (%s)",
- option_info[opt[i]].o_desc,
- (*option_info[opt[i]].o_var ? "yes" : "no "),
- option_info[opt[i]].o_text);
- c_prt(a, buf, i + 2, 0);
- }
-
- /* Hilite current option */
- move_cursor(k + 2, 50);
-
- /* Get a key */
- ch = inkey();
-
- /*
- * Hack -- Try to translate the key into a direction
- * to allow the use of roguelike keys for navigation
- */
- dir = get_keymap_dir(ch);
- if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) ch = I2D(dir);
-
- /* Analyze */
- switch (ch)
- {
- case ESCAPE:
- {
- return;
- }
-
- case '-':
- case '8':
- {
- k = (n + k - 1) % n;
-
- break;
- }
-
- case ' ':
- case '\n':
- case '\r':
- case '2':
- {
- k = (k + 1) % n;
-
- break;
- }
-
- case 'y':
- case 'Y':
- case '6':
- {
- if (read_only) break;
-
- (*option_info[opt[k]].o_var) = TRUE;
- k = (k + 1) % n;
-
- break;
- }
-
- case 'n':
- case 'N':
- case '4':
- {
- if (read_only) break;
-
- (*option_info[opt[k]].o_var) = FALSE;
- k = (k + 1) % n;
-
- break;
- }
-
- default:
- {
- bell();
-
- break;
- }
+ 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);
}
@@ -1565,11 +1516,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 */
@@ -1998,11 +1946,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.");
@@ -2021,10 +1967,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 */
@@ -2180,11 +2124,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 */
@@ -2234,7 +2179,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,
@@ -2288,7 +2233,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,
@@ -2326,33 +2271,19 @@ void do_cmd_visuals(void)
/* Label the object */
Term_putstr(5, 17, -1, TERM_WHITE,
format("Monster = %d, Name = %-40.40s",
- r, (r_name + r_ptr->name)));
+ r, r_ptr->name));
/* Label the Default values */
Term_putstr(10, 19, -1, TERM_WHITE,
format("Default attr/char = %3u / %3u", da, (dc & 0xFF)));
Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>");
Term_putch(43, 19, da, dc);
- if (use_bigtile)
- {
- if (da & 0x80)
- Term_putch(44, 19, 255, 255);
- else
- Term_putch(44, 19, 0, ' ');
- }
/* Label the Current values */
Term_putstr(10, 20, -1, TERM_WHITE,
format("Current attr/char = %3u / %3u", ca, (cc & 0xFF)));
Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>");
Term_putch(43, 20, ca, cc);
- if (use_bigtile)
- {
- if (ca & 0x80)
- Term_putch(44, 20, 255, 255);
- else
- Term_putch(44, 20, 0, ' ');
- }
/* Prompt */
Term_putstr(0, 22, -1, TERM_WHITE,
@@ -2367,10 +2298,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);
}
}
@@ -2387,41 +2318,27 @@ void do_cmd_visuals(void)
{
object_kind *k_ptr = &k_info[k];
- byte da = (byte)k_ptr->d_attr;
- char dc = (byte)k_ptr->d_char;
- byte ca = (byte)k_ptr->x_attr;
- char cc = (byte)k_ptr->x_char;
+ byte da = k_ptr->d_attr;
+ char dc = k_ptr->d_char;
+ byte ca = k_ptr->x_attr;
+ char cc = k_ptr->x_char;
/* Label the object */
Term_putstr(5, 17, -1, TERM_WHITE,
format("Object = %d, Name = %-40.40s",
- k, (k_name + k_ptr->name)));
+ k, k_ptr->name));
/* Label the Default values */
Term_putstr(10, 19, -1, TERM_WHITE,
format("Default attr/char = %3u / %3u", da, (dc & 0xFF)));
Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>");
Term_putch(43, 19, da, dc);
- if (use_bigtile)
- {
- if (da & 0x80)
- Term_putch(44, 19, 255, 255);
- else
- Term_putch(44, 19, 0, ' ');
- }
/* Label the Current values */
Term_putstr(10, 20, -1, TERM_WHITE,
format("Current attr/char = %3u / %3u", ca, (cc & 0xFF)));
Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>");
Term_putch(43, 20, ca, cc);
- if (use_bigtile)
- {
- if (ca & 0x80)
- Term_putch(44, 20, 255, 255);
- else
- Term_putch(44, 20, 0, ' ');
- }
/* Prompt */
Term_putstr(0, 22, -1, TERM_WHITE,
@@ -2436,10 +2353,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);
}
}
@@ -2456,41 +2373,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,
@@ -2505,10 +2408,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;
@@ -2733,16 +2636,16 @@ void do_cmd_colors(void)
if (i == ESCAPE) break;
/* Analyze */
- if (i == 'n') a = (byte)(a + 1);
- if (i == 'N') a = (byte)(a - 1);
- if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
- if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
- if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
- if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
- if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
- if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
- if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
- if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
+ if (i == 'n') a = (a + 1);
+ if (i == 'N') a = (a - 1);
+ if (i == 'k') angband_color_table[a][0] = (angband_color_table[a][0] + 1);
+ if (i == 'K') angband_color_table[a][0] = (angband_color_table[a][0] - 1);
+ if (i == 'r') angband_color_table[a][1] = (angband_color_table[a][1] + 1);
+ if (i == 'R') angband_color_table[a][1] = (angband_color_table[a][1] - 1);
+ if (i == 'g') angband_color_table[a][2] = (angband_color_table[a][2] + 1);
+ if (i == 'G') angband_color_table[a][2] = (angband_color_table[a][2] - 1);
+ if (i == 'b') angband_color_table[a][3] = (angband_color_table[a][3] + 1);
+ if (i == 'B') angband_color_table[a][3] = (angband_color_table[a][3] - 1);
/* Hack -- react to changes */
Term_xtra(TERM_XTRA_REACT, 0);
@@ -2843,7 +2746,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;
}
@@ -3022,127 +2925,106 @@ 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;
+ int y, x;
+ int wid, hgt;
- byte a = 0;
- char c = ' ';
+ byte a = 0;
+ char c = ' ';
- FILE *fff;
+ FILE *fff;
- char buf[1024];
+ char buf[1024];
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt");
+ /* Build the filename */
+ path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt");
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
+ /* File type is "TEXT" */
+ FILE_TYPE(FILE_TYPE_TEXT);
- /* 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;
}
@@ -3159,13 +3041,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;
@@ -3173,6 +3048,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];
@@ -3190,6 +3066,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];
@@ -3214,18 +3091,11 @@ void do_cmd_knowledge_artifacts(void)
{
cave_type *c_ptr = &cave[y][x];
- s16b this_o_idx, next_o_idx = 0;
-
/* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type const * o_ptr = &o_list[this_o_idx];
/* Ignore random artifacts */
if (o_ptr->tval == TV_RANDART) continue;
@@ -3252,21 +3122,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;
@@ -3395,9 +3258,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_);
}
@@ -3434,7 +3294,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 */
@@ -3448,54 +3308,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];
@@ -3507,26 +3341,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))
@@ -3539,44 +3377,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);
@@ -3588,7 +3404,7 @@ static void do_cmd_knowledge_uniques(void)
}
-void plural_aux(char *name)
+static void plural_aux(char *name)
{
int name_len = strlen(name);
@@ -3819,7 +3635,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);
}
}
@@ -3837,8 +3653,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++;
}
}
@@ -3850,19 +3665,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);
}
@@ -3873,7 +3688,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);
@@ -3972,7 +3787,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]));
}
}
@@ -4024,7 +3839,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]);
}
@@ -4044,7 +3859,7 @@ void do_cmd_knowledge_towns(void)
/*
* List corruptions
*/
-void do_cmd_knowledge_corruptions(void)
+static void do_cmd_knowledge_corruptions(void)
{
FILE *fff;
@@ -4569,57 +4384,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 9571ce99..05483b91 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,80 @@
* included in all such copies.
*/
-
-#include "angband.h"
-
-#include <assert.h>
-
-#include "spell_type.h"
-#include "quark.h"
+#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 "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 <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 +110,71 @@ bool_ is_magestaff()
return (FALSE);
}
+
+static void browse_school_spell(int book, int spell_idx, object_type *o_ptr)
+{
+ int i;
+ int num = 0, where = 1;
+ int ask;
+ char choice;
+ char out_val[160];
+
+ /* Show choices */
+ window_stuff();
+
+ num = school_book_length(book);
+
+ /* Build a prompt (accept all spells) */
+ strnfmt(out_val, 78, "(Spells %c-%c, ESC=exit) cast which spell? ",
+ I2A(0), I2A(num - 1));
+
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
+
+ /* Display a list of spells */
+ where = print_book(book, spell_idx, o_ptr);
+
+ /* Get a spell from the user */
+ while (get_com(out_val, &choice))
+ {
+ /* Display a list of spells */
+ where = 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 */
+ 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 +189,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;
@@ -265,8 +346,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 +368,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 +407,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 +424,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 +451,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 +466,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 +478,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 +496,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 +557,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 +578,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 +590,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);
}
}
@@ -2057,7 +1813,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);
@@ -2073,74 +1829,82 @@ 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];
-
strcpy(buf, "Manathrust");
if (!get_string("Spell name? ", buf, 79))
- return FALSE;
+ {
+ return boost::none;
+ }
- spell = find_spell(buf);
- if (spell == -1) return FALSE;
+ int const spell = find_spell(buf);
+ if (spell == -1)
+ {
+ return boost::none;
+ }
- for (i = 0; i < INVEN_TOTAL; i++)
+ 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 (school_book_contains_spell(o_ptr->sval, spell))
{
- *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, object_type *o_ptr)
+bool_ is_ok_spell(s32b spell_idx, s32b pval)
{
spell_type *spell = spell_at(spell_idx);
- assert(o_ptr != NULL);
- if (get_level(spell_idx, 50, 0) == 0)
+ // 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;
}
-
- if (o_ptr->pval < spell_type_minimum_pval(spell))
+ // 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;
}
@@ -2157,24 +1921,31 @@ s32b get_school_spell(cptr do_what, s16b force_book)
int ask;
bool_ flag;
char out_val[160];
- char buf2[40];
- char buf3[40];
object_type *o_ptr, forge;
int tmp;
int sval, pval;
u32b f1, f2, f3, f4, f5, esp;
hack_force_spell = -1;
- hack_force_spell_obj = NULL;
+ 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);
@@ -2211,7 +1982,7 @@ s32b get_school_spell(cptr do_what, s16b force_book)
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;
@@ -2287,7 +2058,7 @@ s32b get_school_spell(cptr do_what, s16b force_book)
spell = spell_x(sval, pval, i);
/* Do we need to do some pre test */
- ok = is_ok_spell(spell, o_ptr);
+ ok = is_ok_spell(spell, o_ptr->pval);
/* Require "okay" spells */
if (!ok)
@@ -2308,7 +2079,7 @@ s32b get_school_spell(cptr do_what, s16b force_book)
bool_ ok;
/* Require "okay" spells */
- ok = is_ok_spell(hack_force_spell, hack_force_spell_obj);
+ ok = is_ok_spell(hack_force_spell, hack_force_spell_pval);
if (ok)
{
flag = TRUE;
@@ -2367,80 +2138,13 @@ void cast_school_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 */
- window_stuff();
-
- num = school_book_length(book);
-
- /* Build a prompt (accept all spells) */
- strnfmt(out_val, 78, "(Spells %c-%c, ESC=exit) cast which spell? ",
- I2A(0), I2A(num - 1));
-
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
-
- /* Display a list of spells */
- where = print_book(book, pval, o_ptr);
-
- /* Get a spell from the user */
- while (get_com(out_val, &choice))
- {
- /* Display a list of spells */
- where = print_book(book, pval, o_ptr);
-
- /* Note verify */
- ask = (isupper(choice));
-
- /* Lowercase */
- if (ask) choice = tolower(choice);
-
- /* Extract request */
- i = (islower(choice) ? A2I(choice) : -1);
-
- /* Totally Illegal */
- if ((i < 0) || (i >= num))
- {
- bell();
- continue;
- }
-
- /* Restore the screen */
- Term_load();
-
- /* Display a list of spells */
- where = print_book(book, pval, o_ptr);
- print_spell_desc(spell_x(book, pval, i), where);
- }
-
-
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
-
- /* Show choices */
- window_stuff();
-}
-
/* Can it contains a schooled spell ? */
-static bool_ hook_school_can_spellable(object_type *o_ptr)
+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));
}
/*
@@ -2450,7 +2154,6 @@ void do_cmd_copy_spell()
{
int spell = get_school_spell("copy", 0);
int item;
- object_type *o_ptr;
if (spell == -1) return;
@@ -2461,9 +2164,12 @@ void do_cmd_copy_spell()
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;
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 bfe364e5..97ee2cb0 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,9 +6,52 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "spell_type.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 <boost/algorithm/string/predicate.hpp>
+#include <cassert>
+
+using boost::algorithm::iequals;
/*
* Forward declare
@@ -23,31 +62,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;
+ };
}
@@ -908,13 +957,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;
}
@@ -923,32 +973,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);
@@ -966,12 +1012,7 @@ void do_cmd_eat_food(void)
/* Scripted foods */
hook_eat_in in = { o_ptr };
hook_eat_out out = { FALSE };
-
- if (process_hooks_ret(HOOK_EAT, "d", "(O)", o_ptr))
- {
- ident = process_hooks_return[0].num;
- }
- else if (process_hooks_new(HOOK_EAT, &in, &out))
+ if (process_hooks_new(HOOK_EAT, &in, &out))
{
ident = out.ident;
}
@@ -1254,7 +1295,7 @@ void do_cmd_eat_food(void)
/* 2% chance of getting the mold power */
if (magik(2))
{
- ADD_POWER(p_ptr->powers_mod, PWR_GROW_MOLD);
+ p_ptr->powers_mod[PWR_GROW_MOLD] = TRUE;
p_ptr->update |= PU_POWERS;
}
@@ -1449,7 +1490,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 */
@@ -1462,9 +1503,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.");
}
@@ -1497,29 +1538,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))
{
@@ -1573,7 +1605,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));
@@ -1604,32 +1637,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);
@@ -1652,8 +1680,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)
{
@@ -1715,8 +1743,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)) ||
@@ -1738,12 +1772,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;
}
@@ -2126,7 +2161,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;
}
@@ -2345,7 +2380,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
potions of corruption. */
if (game_module_idx == MODULE_THEME)
{
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == GOD_MELKOR)
{
msg_print("Your quaffing of this potion pleases Melkor!");
set_grace(p_ptr->grace + 2);
@@ -2400,7 +2435,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int 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);
@@ -2455,29 +2490,24 @@ 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;
+ int ident, lev;
object_type *q_ptr, forge;
- cptr q, s;
-
-
- /* Restrict choices to potions */
- item_tester_hook = item_tester_hook_quaffable;
-
- /* Set up the extra finder */
- get_item_hook_find_obj_what = "Potion full name? ";
- get_item_extra_hook = get_item_hook_find_obj;
-
/* Get an item */
- q = "Quaff which potion? ";
- s = "You have no potions to quaff.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return;
+ 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 */
@@ -2548,6 +2578,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)
@@ -2623,91 +2739,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)
@@ -2842,12 +2873,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;
}
@@ -2860,15 +2893,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)
{
@@ -2888,33 +2912,32 @@ 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;
/* Corruption */
if (player_has_corruption(CORRUPT_BALROG_AURA) && magik(5))
@@ -2932,13 +2955,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];
@@ -2979,7 +3000,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;
@@ -3055,7 +3076,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))
{
@@ -3078,7 +3099,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))
{
@@ -3335,8 +3356,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;
}
@@ -3362,7 +3386,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
{
@@ -3576,7 +3600,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);
@@ -3619,10 +3643,13 @@ void do_cmd_read_scroll(void)
/* Destroy scroll */
inc_stack_size(item, -1);
+ /* Alchemists end up with a "drained" scroll instead */
if (get_skill(SKILL_ALCHEMY))
{
if (item >= 0)
{
+ object_type *q_ptr, forge;
+
q_ptr = &forge;
object_prep(q_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_NOTHING));
object_aware(q_ptr);
@@ -3642,7 +3669,9 @@ void set_stick_mode(object_type *o_ptr)
{
s32b bonus = o_ptr->pval3 & 0xFFFF;
s32b max = o_ptr->pval3 >> 16;
-
+ // 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;
}
@@ -3650,6 +3679,9 @@ void set_stick_mode(object_type *o_ptr)
/* Remove 'stick mode' */
void unset_stick_mode()
{
+ // 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;
}
@@ -3658,15 +3690,17 @@ void unset_stick_mode()
/*
* Activate a device
*/
-static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge)
+static void activate_stick(object_type *o_ptr, bool_ *obvious, bool_ *use_charge)
{
- spell_type *spell = spell_at(s);
+ spell_type *spell = spell_at(o_ptr->pval2);
casting_result ret;
assert(obvious != NULL);
assert(use_charge != NULL);
- ret = spell_type_produce_effect(spell, -1);
+ set_stick_mode(o_ptr);
+ ret = spell_type_produce_effect(spell);
+ unset_stick_mode();
switch (ret)
{
@@ -3697,16 +3731,10 @@ static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge)
*/
void do_cmd_use_staff(void)
{
- int item, ident, chance;
-
bool_ obvious, use_charge;
- object_type *o_ptr;
-
u32b f1, f2, f3, f4, f5, esp;
- cptr q, s;
-
/* No magic */
if (p_ptr->antimagic)
{
@@ -3714,20 +3742,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))
@@ -3736,17 +3764,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 = spell_chance(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);
@@ -3769,9 +3801,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;
}
@@ -3781,9 +3810,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;
}
@@ -3791,9 +3817,8 @@ void do_cmd_use_staff(void)
/* Sound */
sound(SOUND_ZAP);
-
/* Analyze the staff */
- activate_stick(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);
@@ -3809,9 +3834,6 @@ void do_cmd_use_staff(void)
/* Hack -- some uses are "free" */
if (!use_charge)
{
- /* Leave device mode */
- unset_stick_mode();
-
return;
}
@@ -3861,9 +3883,6 @@ void do_cmd_use_staff(void)
{
floor_item_charges(0 - item);
}
-
- /* Leave device mode */
- unset_stick_mode();
}
@@ -3891,12 +3910,6 @@ void do_cmd_aim_wand(void)
{
bool_ obvious, use_charge;
- int item, ident, chance;
-
- object_type *o_ptr;
-
- cptr q, s;
-
u32b f1, f2, f3, f4, f5, esp;
@@ -3907,21 +3920,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))
@@ -3933,14 +3945,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 = spell_chance(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);
@@ -3957,9 +3973,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;
}
@@ -3969,19 +3982,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);
-
/* Analyze the wand */
- activate_stick(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);
@@ -3992,9 +4000,6 @@ void do_cmd_aim_wand(void)
/* Hack -- some uses are "free" */
if (!use_charge)
{
- /* Leave device mode */
- unset_stick_mode();
-
return;
}
@@ -4022,9 +4027,6 @@ void do_cmd_aim_wand(void)
{
floor_item_charges(0 - item);
}
-
- /* Leave device mode */
- unset_stick_mode();
}
@@ -4045,25 +4047,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));
}
@@ -4074,10 +4075,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;
@@ -4089,16 +4086,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);
@@ -4140,14 +4139,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;
@@ -4159,21 +4154,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 */
@@ -4573,11 +4566,7 @@ void do_cmd_zap_rod(void)
}
default:
- {
- process_hooks(HOOK_ZAP, "(d,d)", o_ptr->tval, o_ptr->sval);
-
- break;
- }
+ break;
}
@@ -4612,26 +4601,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
*/
@@ -4676,7 +4655,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...");
@@ -4778,6 +4757,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
@@ -4793,24 +4919,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);
@@ -4917,12 +5040,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 */
@@ -5026,7 +5143,6 @@ void do_cmd_activate(void)
const char *activation_aux(object_type * o_ptr, bool_ doit, int item)
{
- static char buf[256];
int plev = get_skill(SKILL_DEVICE);
int i = 0, ii = 0, ij = 0, k, dir, dummy = 0;
@@ -5063,2686 +5179,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)
{
- struct spell_type *spell_ptr = spell_at(-spell);
- if (doit)
+ case ACT_GILGALAD:
{
- spell_type_produce_effect(spell_ptr, item);
- o_ptr->timeout = spell_type_activation_roll_timeout(spell_ptr);
+ 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:
{
- spell_type_activation_description(spell_ptr, buf);
- return buf;
+ 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(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);
-
- o_ptr->timeout = 45;
+ 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_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(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();
- /* 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++;
- c_ptr = &cave[y][x];
+ /* No longer in the array */
+ c_ptr->info &= ~(CAVE_TEMP);
- if (distance(y, x, p_ptr->py, p_ptr->px) > 6) continue;
+ /* Darken the grid */
+ c_ptr->info &= ~(CAVE_GLOW);
- if (c_ptr->info & CAVE_GLOW)
+ /* Hack -- Forget "boring" grids */
+ if (cave_plain_floor_grid(c_ptr) &&
+ !(c_ptr->info & (CAVE_TRDT)))
{
- light++;
-
- /* No longer in the array */
- c_ptr->info &= ~(CAVE_TEMP);
-
- /* Darken the grid */
- c_ptr->info &= ~(CAVE_GLOW);
-
- /* Hack -- Forget "boring" grids */
- if (cave_plain_floor_grid(c_ptr) &&
- !(c_ptr->info & (CAVE_TRDT)))
- {
- /* Forget the grid */
- c_ptr->info &= ~(CAVE_MARK);
-
- /* Notice */
- note_spot(y, x);
- }
-
- /* Process affected monsters */
- if (c_ptr->m_idx)
- {
- /* Update the monster */
- update_mon(c_ptr->m_idx, FALSE);
- }
-
- /* Redraw */
- lite_spot(y, x);
+ /* Forget the grid */
+ c_ptr->info &= ~(CAVE_MARK);
+
+ /* Notice */
+ note_spot(y, x);
+ }
+
+ /* Process affected monsters */
+ if (c_ptr->m_idx)
+ {
+ /* Update the monster */
+ update_mon(c_ptr->m_idx, FALSE);
}
+
+ /* Redraw */
+ lite_spot(y, x);
}
}
+ }
- if (!get_aim_dir(&dir)) return (FALSE);
+ if (!get_aim_dir(&dir)) return (FALSE);
- msg_print("The light around you is absorbed... "
- "and released in a powerful bolt!");
- fire_bolt(GF_LITE, dir, damroll(light, p_ptr->lev));
+ msg_print("The light around you is absorbed... "
+ "and released in a powerful bolt!");
+ fire_bolt(GF_LITE, dir, damroll(light, p_ptr->lev));
- /* Timeout is set before return */
+ /* Timeout is set before return */
- break;
- }
- /* Horns of DragonKind (Note that these are new egos)*/
- case ACT_BA_FIRE_H:
- {
- if (!doit) return "large fire ball (300) every 100 turns";
- fire_ball(GF_FIRE, 5, 300, 7);
+ break;
+ }
+ /* Horns of DragonKind (Note that these are new egos)*/
+ case ACT_BA_FIRE_H:
+ {
+ if (!doit) return "large fire ball (300) every 100 turns";
+ fire_ball(GF_FIRE, 5, 300, 7);
- o_ptr->timeout = 100;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- break;
- }
- case ACT_BA_COLD_H:
- {
- if (!doit) return "large cold ball (300) every 100 turns";
- fire_ball(GF_COLD, 5, 300, 7);
+ break;
+ }
+ case ACT_BA_COLD_H:
+ {
+ if (!doit) return "large cold ball (300) every 100 turns";
+ fire_ball(GF_COLD, 5, 300, 7);
- o_ptr->timeout = 100;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- break;
- }
- case ACT_BA_ELEC_H:
- {
- if (!doit) return "large lightning ball (300) every 100 turns";
- fire_ball(GF_ELEC, 5, 300, 7);
+ break;
+ }
+ case ACT_BA_ELEC_H:
+ {
+ if (!doit) return "large lightning ball (300) every 100 turns";
+ fire_ball(GF_ELEC, 5, 300, 7);
- o_ptr->timeout = 100;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- break;
- }
- case ACT_BA_ACID_H:
- {
- if (!doit) return "large acid ball (300) every 100 turns";
- fire_ball(GF_ACID, 5, 300, 7);
+ break;
+ }
+ case ACT_BA_ACID_H:
+ {
+ if (!doit) return "large acid ball (300) every 100 turns";
+ fire_ball(GF_ACID, 5, 300, 7);
- o_ptr->timeout = 100;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- break;
- }
+ break;
+ }
- case ACT_SPIN:
- {
- if (!doit) return "spinning around every 50+d25 turns";
- do_spin();
+ case ACT_SPIN:
+ {
+ if (!doit) return "spinning around every 50+d25 turns";
+ do_spin();
- o_ptr->timeout = 50 + randint(25);
+ o_ptr->timeout = 50 + randint(25);
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- /* Done */
- break;
- }
- case ACT_NOLDOR:
- {
- if (!doit) return "detect treasure every 10+d20 turns";
- detect_treasure(DEFAULT_RADIUS);
+ /* Done */
+ break;
+ }
+ case ACT_NOLDOR:
+ {
+ if (!doit) return "detect treasure every 10+d20 turns";
+ detect_treasure(DEFAULT_RADIUS);
- o_ptr->timeout = 10 + randint(20);
+ o_ptr->timeout = 10 + randint(20);
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- /* Done */
- break;
+ /* Done */
+ break;
+ }
+ case ACT_SPECTRAL:
+ {
+ if (!doit) return "wraith-form every 50+d50 turns";
+ if (!p_ptr->wraith_form)
+ {
+ set_shadow(20 + randint(20));
}
- case ACT_SPECTRAL:
+ else
{
- if (!doit) return "wraith-form every 50+d50 turns";
- if (!p_ptr->wraith_form)
- {
- set_shadow(20 + randint(20));
- }
- else
- {
- set_shadow(p_ptr->tim_wraith + randint(20));
- }
+ set_shadow(p_ptr->tim_wraith + randint(20));
+ }
- o_ptr->timeout = 50 + randint(50);
+ o_ptr->timeout = 50 + randint(50);
- /* Window stuff */
- p_ptr->window |= PW_INVEN | PW_EQUIP;
+ /* Window stuff */
+ p_ptr->window |= PW_INVEN | PW_EQUIP;
- /* Done */
- break;
+ /* Done */
+ break;
+ }
+ case ACT_JUMP:
+ {
+ if (!doit) return "phasing every 10+d10 turns";
+ teleport_player(10);
+ o_ptr->timeout = 10 + randint(10);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
+
+ /* Done */
+ break;
+ }
+
+ case ACT_DEST_TELE:
+ {
+ if (!doit) return "teleportation and destruction of the ring";
+ if (!item)
+ {
+ msg_print("You can't activate this when it's there!");
}
- case ACT_JUMP:
+ if (get_check("This will destroy the ring. Do you wish to continue? "))
{
- if (!doit) return "phasing every 10+d10 turns";
- teleport_player(10);
- o_ptr->timeout = 10 + randint(10);
+ msg_print("The ring explodes into a space distortion.");
+ teleport_player(200);
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* It explodes, doesn't it ? */
+ take_hit(damroll(2, 10), "an exploding ring");
- /* Done */
- break;
+ inc_stack_size_ex(item, -255, OPTIMIZE, NO_DESCRIBE);
}
- case ACT_DEST_TELE:
- {
- if (!doit) return "teleportation and destruction of the ring";
- if (!item)
- {
- msg_print("You can't activate this when it's there!");
- }
- if (get_check("This will destroy the ring. Do you wish to continue? "))
- {
- msg_print("The ring explodes into a space distortion.");
- teleport_player(200);
+ break;
+ }
+ /*amulet of serpents dam 100, rad 2 timeout 40+d60 */
+ case ACT_BA_POIS_4:
+ {
+ if (!doit) return "venom breathing every 40+d60 turns";
+ /* Get a direction for breathing (or abort) */
+ if (!get_aim_dir(&dir)) break;
- /* It explodes, doesn't it ? */
- take_hit(damroll(2, 10), "an exploding ring");
+ msg_print("You breathe venom...");
+ fire_ball(GF_POIS, dir, 100, 2);
- inc_stack_size_ex(item, -255, OPTIMIZE, NO_DESCRIBE);
- }
+ o_ptr->timeout = rand_int(60) + 40;
- break;
- }
- /*amulet of serpents dam 100, rad 2 timeout 40+d60 */
- case ACT_BA_POIS_4:
- {
- if (!doit) return "venom breathing every 40+d60 turns";
- /* Get a direction for breathing (or abort) */
- if (!get_aim_dir(&dir)) break;
+ /* Window stuff */
+ p_ptr->window |= PW_INVEN | PW_EQUIP;
- msg_print("You breathe venom...");
- fire_ball(GF_POIS, dir, 100, 2);
+ /* Done */
+ break;
+ }
+ /*rings of X 50,50+d50 dur 20+d20 */
+ case ACT_BA_COLD_4:
+ {
+ if (!doit) return "ball of cold and resist cold every 50+d50 turns";
+ /* Get a direction for breathing (or abort) */
+ if (!get_aim_dir(&dir)) break;
- o_ptr->timeout = rand_int(60) + 40;
+ fire_ball(GF_COLD, dir, 50, 2);
+ (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.cc
index 3d3b1bb2..4338cb52 100644
--- a/src/cmd7.c
+++ b/src/cmd7.cc
@@ -1,7 +1,3 @@
-/* File: cmd7.c */
-
-/* Purpose: More Class commands */
-
/*
* Copyright (c) 1999 Dark God
*
@@ -10,10 +6,39 @@
* included in all such copies.
*/
-
-#include "angband.h"
-
-#include "quark.h"
+#include "cmd7.hpp"
+
+#include "alchemist_recipe.hpp"
+#include "artifact_select_flag.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"
/*
* Describe class powers of Mindcrafters
@@ -714,7 +739,7 @@ void do_cmd_mindcraft(void)
}
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -810,13 +835,13 @@ void do_cmd_mimic_lore()
/* Redraw title */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
}
-static bool_ mimic_forbid_travel(char *fmt)
+static bool_ mimic_forbid_travel(void *, void *, void *)
{
u32b value = p_ptr->mimic_extra >> 16;
u32b att = p_ptr->mimic_extra & 0xFFFF;
@@ -849,7 +874,7 @@ void do_cmd_mimic(void)
static bool_ added_hooks = FALSE;
if(!added_hooks)
{
- add_hook(HOOK_FORBID_TRAVEL, mimic_forbid_travel, "mimic_forbid_travel");
+ add_hook_new(HOOK_FORBID_TRAVEL, mimic_forbid_travel, "mimic_forbid_travel", NULL);
added_hooks = TRUE;
}
@@ -1123,7 +1148,7 @@ void do_cmd_mimic(void)
}
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1190,16 +1215,6 @@ void do_cmd_beastmaster(void)
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)
@@ -1226,12 +1241,14 @@ int show_flags(byte group, int pval)
{
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)",
+ a_select_flags[i].desc);
+ if ( wizard )
+ {
+ sprintf(ttt, "%c) %s (exp " FMTu32b ")",
(items < 26) ? I2A(items) : ('0' + items - 26),
- al_name + a_select_flags[i].desc,
- (long int) a_select_flags[i].xp);
+ a_select_flags[i].desc,
+ a_select_flags[i].xp);
+ }
/* Note: Somebody is VERY clever, and it wasn't me. Text printed as
* TERM_DARK is actually printed as TERM_BLUE *SPACES* to prevent the
@@ -1265,9 +1282,11 @@ int show_flags(byte group, int pval)
break; /* Just in Case*/
}
}
- /* For alchemists who have the stone, at least show all the flags... */
- if ((alchemist_has_stone() || wizard) && color == TERM_DARK)
+
+ if (wizard && color == TERM_DARK)
+ {
color = TERM_BLUE;
+ }
if (items < 16) x = 5;
else x = 45;
@@ -1353,7 +1372,7 @@ s32b get_flags_exp(int pval, int oldpval)
}
}
}
- if ( alchemist_has_stone() ) exp = exp / 4;
+
return exp;
}
@@ -1400,7 +1419,7 @@ int calc_rqty(int i, int pval, int oldpval)
*/
-int check_artifact_items(int pval, int oldpval, int mode)
+static int check_artifact_items(int pval, int oldpval, int mode)
{
int i, j, k, row = 1 , col = 15, rqty, orqty, trqty;
bool_ good = TRUE;
@@ -1548,9 +1567,9 @@ int check_artifact_items(int pval, int oldpval, int mode)
*/
if ( mode == 0 )
{
- char *o_name = al_name + a_select_flags[i].item_desc;
+ char *o_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;
+ o_name = a_select_flags[i].item_descp;
if ( rqty )
{
@@ -1679,12 +1698,12 @@ bool_ artifact_display_or_use(int pval, int oldpval, bool_ use)
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 ),
+ 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 ),
+ k_info[lookup_kind(TV_BATERIE, i + 1)].name ),
row++, col);
}
@@ -1749,7 +1768,7 @@ void display_activation_info(int num)
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, format(" Item :%s ", 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);
@@ -1783,7 +1802,7 @@ void select_an_activation(void)
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 */
+ act_list[max++] = a_select_flags[i].desc; /* Description */
}
/* Select from that list, using the util.c function display_list to display the scrolled list */
@@ -2330,7 +2349,7 @@ void do_cmd_create_artifact(object_type *q_ptr)
* 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)
+static bool_ alchemist_exists(int tval, int sval, int ego, int artifact)
{
int al_idx;
@@ -2359,19 +2378,24 @@ bool_ alchemist_exists(int tval, int sval, int ego, int artifact)
/*
* Hook to determine if an object can have things extracted from it.
*/
-bool_ item_tester_hook_extractable(object_type *o_ptr)
+bool item_tester_hook_extractable(object_type const *o_ptr)
{
/* No artifacts */
- if (artifact_p(o_ptr)) return (FALSE);
+ if (artifact_p(o_ptr))
+ {
+ return false;
+ }
/* No cursed things */
- if (cursed_p(o_ptr)) return (FALSE);
+ 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));
}
@@ -2379,7 +2403,7 @@ bool_ item_tester_hook_extractable(object_type *o_ptr)
/*
* Hook to determine if an object is empowerable (NOT rechargeable)
*/
-bool_ item_tester_hook_empower(object_type *o_ptr)
+static bool item_tester_hook_empower(object_type const *o_ptr)
{
int sval = -1;
int lev = get_skill(SKILL_ALCHEMY);
@@ -2391,14 +2415,14 @@ bool_ item_tester_hook_empower(object_type *o_ptr)
/* Never Empower a cursed item */
if ( cursed_p(o_ptr))
{
- return FALSE;
+ 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;
+ return true;
switch ( o_ptr->tval)
{
@@ -2435,7 +2459,7 @@ bool_ item_tester_hook_empower(object_type *o_ptr)
/* Disallow ego dragon armour before you can create artifacts.*/
case TV_DRAG_ARMOR:
if ( lev < 25)
- return FALSE;
+ return false;
/* FALL THROUGH! no break here. */
/* weapons */
@@ -2471,24 +2495,24 @@ bool_ item_tester_hook_empower(object_type *o_ptr)
/* Disallow ANY creation of ego items below level 5*/
if ( lev < 5)
- return FALSE;
+ 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;
+ 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;
+ return false;
/* Otherwise... */
- return TRUE;
+ return true;
default:
- return FALSE;
+ return false;
}
/* Return to the traditional alchemist objects.
@@ -2501,7 +2525,7 @@ bool_ item_tester_hook_empower(object_type *o_ptr)
if ((o_ptr->name2 || artifact_p(o_ptr)) &&
o_ptr->tval != TV_RING && o_ptr->tval != TV_AMULET)
- return FALSE;
+ return false;
/* return true if it's a 'of nothing' item;
* does nothing for TV_ROD_MAIN and TV_BOOK
@@ -2517,7 +2541,7 @@ bool_ item_tester_hook_empower(object_type *o_ptr)
}
/* Extract a rod tip from a rod */
-void rod_tip_extract(object_type *o_ptr)
+static void rod_tip_extract(object_type *o_ptr)
{
object_type *q_ptr;
object_type forge;
@@ -2547,7 +2571,7 @@ void rod_tip_extract(object_type *o_ptr)
/* Begin & finish an art */
-void do_cmd_toggle_artifact(object_type *o_ptr)
+static void do_cmd_toggle_artifact(object_type *o_ptr)
{
char o_name[80];
@@ -2555,11 +2579,8 @@ void do_cmd_toggle_artifact(object_type *o_ptr)
{
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;
- }
+ 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)))
{
@@ -2622,7 +2643,7 @@ void do_cmd_toggle_artifact(object_type *o_ptr)
* 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)
+static bool_ alchemist_items_check(int tval, int sval, int ego, int tocreate, bool_ message)
{
int al_idx, j;
bool_ exists = FALSE;
@@ -2648,8 +2669,7 @@ bool_ alchemist_items_check(int tval, int sval, int ego, int tocreate, bool_ mes
/* Randomly decrease the number of essences created */
if ( randint(3) == 1
- && randint(52) > get_skill(SKILL_ALCHEMY)
- && !alchemist_has_stone())
+ && randint(52) > get_skill(SKILL_ALCHEMY))
o_ptr->number /= randint(2) + 1;
if ( o_ptr->number == 0)
continue;
@@ -2717,7 +2737,7 @@ bool_ alchemist_items_check(int tval, int sval, int ego, int tocreate, bool_ mes
/* This function lists all the ingredients
* needed to create something.
*/
-void alchemist_display_recipe(int tval, int sval, int ego)
+static void alchemist_display_recipe(int tval, int sval, int ego)
{
int al_idx;
int row = 1, col = 15;
@@ -2736,7 +2756,7 @@ void alchemist_display_recipe(int tval, int sval, int ego)
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 ),
+ k_info[lookup_kind(TV_BATERIE, alchemist_recipes[al_idx].sval_essence)].name),
row++, col);
}
@@ -2748,8 +2768,7 @@ void alchemist_display_recipe(int tval, int sval, int ego)
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);
+ apply_magic(o_ptr, get_skill(SKILL_ALCHEMY) * 2, FALSE, FALSE, FALSE, boost::make_optional(0));
object_aware(o_ptr);
object_known(o_ptr);
/* the 0 mode means only the text, leaving off any numbers */
@@ -2758,7 +2777,7 @@ void alchemist_display_recipe(int tval, int sval, int ego)
else
{
/* Display the ego item name */
- strcpy(o_name, e_name + e_info[ego].name);
+ strcpy(o_name, e_info[ego].name);
}
/* Display a short message about it, and wait for a key. */
@@ -2767,14 +2786,6 @@ void alchemist_display_recipe(int tval, int sval, int ego)
}
/*
- *
- * 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:
@@ -2783,7 +2794,7 @@ void alchemist_display_recipe(int tval, int sval, int ego)
char selectchar[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*():;,.<=>[]{}/=?+'~";
byte selectitem[256];
-void strip_and_print(char *str, int color, int num)
+void strip_and_print(const char *str, int color, int num)
{
int row = 2 + (num % 20), col = 40 * (num / 20);
int ch, max_len = 0;
@@ -2830,11 +2841,235 @@ void strip_and_print(char *str, int color, int num)
c_prt(color, format("[%c] %s", ch, string), row, col);
}
+/* 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. :)
+ */
+static int alchemist_recipe_select(int *tval, int sval, int ego, bool_ recipe)
+{
+ int i, mod40 = 0, num, max_num = 0;
+
+ cptr tval_desc2 = "";
+ char ch;
+ bool_ done = FALSE;
+
+ int choice[60];
+ int validc[60];
+
+ const char *string;
+
+
+ /* Save and clear the screen */
+ character_icky = TRUE;
+ Term_save();
+ Term_clear();
+
+ /* Base object type chosen, fill in tval */
+ for ( num = 0 ; num < 40 ; num ++)
+ if (tvals[num].tval == *tval)
+ {
+ tval_desc2 = tvals[num].desc;
+ }
+
+ while (!done)
+ {
+ Term_clear();
+ if (ego)
+ {
+ /* Find matching ego items */
+ for (num = 0, i = 1; (num < 40) && (i < max_e_idx) ; i++)
+ {
+ int j;
+ ego_item_type *e_ptr = &e_info[i];
+
+ /* Skip if unknown ego type */
+ if ( !(alchemist_known_egos[i / 32] & (1 << (i % 32))))
+ continue;
+
+ /* search in permitted tvals/svals for allowed egos */
+ for ( j = 0 ; j < 6 ; j ++ )
+ if ( e_ptr->tval[j] == *tval
+ && sval >= e_ptr->min_sval[j]
+ && sval <= e_ptr->max_sval[j])
+ {
+ int color = TERM_GREEN;
+
+ /*Reject if not opposite end of name
+ prefixes only on postfix egos,
+ postfixes only on prefix egos.
+ */
+ if (ego != -1 && e_ptr->before == e_info[ego].before)
+ continue;
+
+ /*Color it red of the alchemist doesn't have the essences to create it*/
+ if (!alchemist_items_check(*tval, 0, i, 0, TRUE))
+ color = TERM_RED;
+
+ /* add this ego to the list*/
+ strip_and_print(e_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_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 );
+}
+
/* 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)
+static void alchemist_recipe_book(void)
{
int num, max_num, i, al_idx, bat, kidx;
int choice[61], choice2[61];
@@ -2909,8 +3144,10 @@ void alchemist_recipe_book(void)
}
}
else
+ {
/* add this essence to the list*/
- strip_and_print(k_name + k_info[kidx].name, TERM_WHITE, num);
+ strip_and_print(k_info[kidx].name, TERM_WHITE, num);
+ }
choice[num++] = i;
}
@@ -3022,7 +3259,7 @@ void alchemist_recipe_book(void)
break;
}
}
- strcat(names, e_name + e_ptr->name);
+ strcat(names, e_ptr->name);
}
else
{
@@ -3039,7 +3276,7 @@ void alchemist_recipe_book(void)
break;
}
strcat(names, " of ");
- strcat(names, k_name + k_info[kidx].name);
+ strcat(names, k_info[kidx].name);
}
@@ -3108,230 +3345,6 @@ void alchemist_recipe_book(void)
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.
*/
@@ -3352,7 +3365,6 @@ void alchemist_learn_all(int lev)
void alchemist_learn_ego(int ego)
{
- char *name;
int i;
/* some Paranoia*/
@@ -3360,7 +3372,7 @@ void alchemist_learn_ego(int ego)
return;
/* Get the ego items name */
- name = e_name + e_info[ego].name;
+ const char *name = e_info[ego].name;
while (strchr(name, ' '))
name = strchr(name, ' ') + 1;
@@ -3369,7 +3381,6 @@ void alchemist_learn_ego(int ego)
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
{
@@ -3385,13 +3396,11 @@ void alchemist_learn_ego(int ego)
/* 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*/
+ if ( strstr(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;
@@ -3443,7 +3452,7 @@ int alchemist_learn_object(object_type *o_ptr)
/* Alchemist has gained a level - set the ego flags
* for all egos <= lev/4.
*/
-void alchemist_gain_level(int lev)
+static void alchemist_gain_level(int lev)
{
object_type forge;
object_type *o_ptr = &forge;
@@ -3560,8 +3569,6 @@ void do_cmd_alchemist(void)
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.
@@ -3633,11 +3640,10 @@ void do_cmd_alchemist(void)
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;
+ if (!get_item(&item,
+ "Empower which item? ",
+ "You have no empowerable items.",
+ (USE_INVEN | USE_FLOOR), item_tester_hook_empower)) return;
/* Get the item */
o_ptr = get_object(item);
@@ -3826,8 +3832,7 @@ void do_cmd_alchemist(void)
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);
+ apply_magic(o_ptr, askill * 2, FALSE, FALSE, FALSE, boost::make_optional(0));
if ( o_ptr->tval == TV_WAND || o_ptr->tval == TV_STAFF)
o_ptr->pval = 0;
value = object_value_real(o_ptr);
@@ -3869,10 +3874,6 @@ void do_cmd_alchemist(void)
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];
@@ -3900,7 +3901,7 @@ void do_cmd_alchemist(void)
/* Redraw gold */
p_ptr->au -= i;
- p_ptr->redraw |= (PR_GOLD);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Set fully identified
@@ -3936,7 +3937,7 @@ void do_cmd_alchemist(void)
msg_format("Your attempt backfires! Your %s explodes!", o_name);
take_hit(damroll(3, level - askill ) , "Alchemical Explosion");
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Combine / Reorder the pack (later) */
@@ -3963,12 +3964,12 @@ void do_cmd_alchemist(void)
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;
+ if (!get_item(&item,
+ "Extract from which item? ",
+ "You have no item to extract power from.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_extractable)) return;
/* Get the item */
o_ptr = get_object(item);
@@ -4130,8 +4131,7 @@ void do_cmd_alchemist(void)
s_ptr->number = 1;
/* Force creation of non ego non cursed */
- hack_apply_magic_power = -99;
- apply_magic(s_ptr, 0, FALSE, FALSE, FALSE);
+ apply_magic(s_ptr, 0, FALSE, FALSE, FALSE, boost::make_optional(0));
/* Hack -- remove possible curse */
if (cursed_p(s_ptr))
@@ -4214,14 +4214,15 @@ void do_cmd_alchemist(void)
{
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;
+ if (!get_item(&item,
+ "Recharge which item? ",
+ "You have no rechargable items.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_recharge()))
+ {
+ return;
+ }
/* Get the item */
o_ptr = get_object(item);
@@ -4298,7 +4299,7 @@ void do_cmd_pray(void)
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;
+ p_ptr->redraw |= PR_WIPE | PR_FRAME | PR_MAP;
energy_use = 100;
}
}
@@ -4404,7 +4405,7 @@ static random_spell* select_spell_from_batch(int batch)
mut_max = spell_num - batch * 10;
}
- strnfmt(tmp, 160, "(a-%c, A-%cto browse, / to rename, - to comment) Select a power: ",
+ 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);
@@ -4686,7 +4687,7 @@ void do_cmd_powermage(void)
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
return;
}
@@ -4756,7 +4757,7 @@ void do_cmd_powermage(void)
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -4788,8 +4789,8 @@ void brand_ammo(int brand_type, int bolts_only)
if ((a < INVEN_PACK) && (rand_int(100) < 50))
{
object_type *o_ptr = &p_ptr->inventory[a];
- char *ammo_name;
- char *aura_name;
+ const char *ammo_name;
+ const char *aura_name;
char msg[48];
int aura_type, r;
@@ -4854,13 +4855,6 @@ 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.");
@@ -4943,7 +4937,7 @@ void do_cmd_possessor()
p_ptr->chp = 1;
/* Display the hitpoints */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
}
}
}
@@ -4971,12 +4965,14 @@ void do_cmd_possessor()
/*
* Hook to determine if an object is contertible in an arrow/bolt
*/
-static bool_ item_tester_hook_convertible(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_convertible()
{
- if ((o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_SKELETON)) return TRUE;
-
- /* Assume not */
- return (FALSE);
+ using namespace object_filter;
+ static auto instance =
+ Or(
+ TVal(TV_JUNK),
+ TVal(TV_SKELETON));
+ return instance;
}
@@ -5091,14 +5087,12 @@ void do_cmd_archer(void)
{
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;
+ 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;
@@ -5129,14 +5123,12 @@ void do_cmd_archer(void)
{
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;
+ 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;
@@ -5337,7 +5329,7 @@ void do_cmd_necromancer(void)
p_ptr->chp_frac = 0;
/* Display the hitpoints */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -5471,7 +5463,7 @@ void do_cmd_necromancer(void)
p_ptr->chp_frac = 0;
/* Display the hitpoints */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -5529,72 +5521,29 @@ void do_cmd_necromancer(void)
}
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* 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)
+static bool item_tester_hook_runestone(object_type const *o_ptr)
{
- if (o_ptr->tval != TV_RUNE1) return (FALSE);
-
- /* Assume yes */
- return (TRUE);
+ return ((o_ptr->tval == TV_RUNE2) &&
+ (o_ptr->sval == RUNE_STONE) &&
+ (o_ptr->pval == 0));
}
-
-/*
- * Hook to determine if an object is "rune-able"
- */
-static bool_ item_tester_hook_runeable2(object_type *o_ptr)
+static bool item_tester_hook_runestone_full(object_type const *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);
+ return ((o_ptr->tval == TV_RUNE2) &&
+ (o_ptr->sval == RUNE_STONE) &&
+ (o_ptr->pval != 0));
}
-
/*
* math.h(sqrt) is banned of angband so ... :)
*/
@@ -5761,7 +5710,7 @@ int rune_exec(rune_spell *spell, int cost)
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
return (mana_used);
}
@@ -5853,7 +5802,7 @@ int rune_exec(rune_spell *spell, int cost)
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
return (mana_used);
}
@@ -5902,44 +5851,43 @@ bool_ test_runespell(rune_spell *spell)
*/
bool_ get_runespell(rune_spell *spell)
{
- int item, power_rune = 0, rune2 = 0, plev = get_skill(SKILL_RUNECRAFT);
+ s32b rune_combine = 0;
- s32b power;
-
- int type = 0;
-
- object_type *o_ptr;
-
- cptr q, s;
+ /* 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))));
+ };
- bool_ OK = FALSE;
+ /* 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;
+ }
- 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;
+ object_type *o_ptr = get_object(item);
+ type = o_ptr->sval;
+ }
+ /* Choose secondary rune(s) */
+ int rune2 = 0;
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;
+ int item;
+ if (!get_item(&item, q, nullptr, (USE_INVEN | USE_FLOOR), rune2_filter))
+ {
+ break;
+ }
- /* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
rune_combine |= 1 << o_ptr->sval;
rune2 |= 1 << o_ptr->sval;
@@ -5951,9 +5899,14 @@ bool_ get_runespell(rune_spell *spell)
return (FALSE);
}
- power = get_quantity("Which amount of Mana?",
- p_ptr->csp - (power_rune * (plev / 5)));
- if (power < 1) power = 1;
+ 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;
@@ -6003,7 +5956,7 @@ void do_cmd_rune(void)
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -6263,7 +6216,7 @@ void do_cmd_rune_cast()
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -6274,10 +6227,6 @@ void do_cmd_runestone()
{
rune_spell s_ptr;
- object_type *o_ptr;
-
- cptr q, s;
-
int item;
@@ -6316,16 +6265,18 @@ void do_cmd_runestone()
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;
+ 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 */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
s_ptr.type = o_ptr->pval;
s_ptr.rune2 = o_ptr->pval2;
@@ -6342,7 +6293,7 @@ void do_cmd_runestone()
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -6366,7 +6317,7 @@ void do_cmd_rune_add_mem()
if (rune_num >= MAX_RUNES)
{
- msg_print("You have already learn the maximun number of runespells!");
+ msg_print("You have already learned the maximum number of runespells!");
return;
}
@@ -6386,7 +6337,7 @@ void do_cmd_rune_add_mem()
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -6397,10 +6348,6 @@ void do_cmd_rune_carve()
{
rune_spell s_ptr;
- object_type *o_ptr;
-
- cptr q, s;
-
int item, i;
char out_val[80];
@@ -6427,16 +6374,18 @@ void do_cmd_rune_carve()
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;
+ 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 */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
o_ptr->pval = s_ptr.type;
o_ptr->pval2 = s_ptr.rune2;
@@ -6489,7 +6438,7 @@ void do_cmd_rune_carve()
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -6531,7 +6480,7 @@ void do_cmd_rune_del()
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -6752,17 +6701,15 @@ void do_cmd_unbeliever()
/*
* Hook to determine if an object is totemable
*/
-static bool_ item_tester_hook_totemable(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_totemable()
{
- /* 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);
+ using namespace object_filter;
+ static auto instance = And(
+ TVal(TV_CORPSE),
+ Or(
+ SVal(SV_CORPSE_CORPSE),
+ SVal(SV_CORPSE_SKELETON)));
+ return instance;
}
@@ -6771,14 +6718,7 @@ static bool_ item_tester_hook_totemable(object_type *o_ptr)
*/
void do_cmd_summoner_extract()
{
- object_type *o_ptr, forge, *q_ptr;
-
- cptr q, s;
-
- int item, r;
-
- bool_ partial;
-
+ object_type forge, *q_ptr;
/* Not when confused */
if (p_ptr->confused)
@@ -6794,17 +6734,21 @@ void do_cmd_summoner_extract()
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;
+ 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 */
- o_ptr = get_object(item);
-
+ object_type *o_ptr = get_object(item);
+ bool_ partial;
if (r_info[o_ptr->pval2].flags1 & RF1_UNIQUE)
{
partial = FALSE;
@@ -6814,7 +6758,7 @@ void do_cmd_summoner_extract()
partial = get_check("Do you want to create a partial totem?");
}
- r = o_ptr->pval2;
+ int r = o_ptr->pval2;
inc_stack_size(item, -1);
@@ -6952,20 +6896,16 @@ void do_cmd_summoner_summon()
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;
+ if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR), object_filter::TVal(TV_TOTEM))) return;
/* Access the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Take a turn */
energy_use = 100;
@@ -7089,26 +7029,6 @@ void do_cmd_summoner(void)
/*
- * 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)
@@ -7327,19 +7247,18 @@ void do_cmd_symbiotic(void)
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;
+ if (!get_item(&item,
+ "Awaken which monster? ",
+ "You have no monster to awaken.",
+ (USE_FLOOR),
+ object_filter::TVal(TV_HYPNOS)))
+ {
+ return;
+ }
- o_ptr = &o_list[0 - item];
+ object_type *o_ptr = &o_list[0 - item];
d = 2;
while (d < 100)
@@ -7414,14 +7333,11 @@ void do_cmd_symbiotic(void)
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);
+ p_ptr->redraw |= (PR_FRAME);
break;
}
@@ -7459,7 +7375,7 @@ void do_cmd_symbiotic(void)
msg_format("%s is healed.", symbiote_name(TRUE));
/* Display the monster hitpoints */
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
break;
}
@@ -7556,7 +7472,7 @@ void do_cmd_symbiotic(void)
}
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
diff --git a/src/cmd7.hpp b/src/cmd7.hpp
new file mode 100644
index 00000000..da96bb57
--- /dev/null
+++ b/src/cmd7.hpp
@@ -0,0 +1,30 @@
+#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 int alchemist_learn_object(object_type *o_ptr);
+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 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 cb258925..290ec624 100644
--- a/src/config.h
+++ b/src/config.h
@@ -30,16 +30,12 @@
* 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.
*/
@@ -60,53 +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: Maximum flow depth
@@ -117,18 +71,6 @@
/*
- * 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: Set the "default" path to the angband "lib" directory.
*
* See "main.c" for usage, and note that this value is only used on
@@ -157,13 +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_MODULES
-#else
#define PRIVATE_USER_PATH "~/.tome"
-#endif
/*
diff --git a/src/corrupt.c b/src/corrupt.cc
index a4c579d4..d1a7c530 100644
--- a/src/corrupt.c
+++ b/src/corrupt.cc
@@ -1,5 +1,35 @@
-#include "angband.h"
-#include <assert.h>
+#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 <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
@@ -57,18 +87,18 @@ static void player_gain_vampire()
player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE];
/* Be a Vampire and be proud of it */
- cptr title = get_subrace_title(SUBRACE_SAVE);
- if (streq(title, " ") || streq(title, "Vampire"))
+ cptr title = rmp_ptr->title;
+ if (streq(title, "Vampire"))
{
title = "Vampire";
rmp_ptr->place = FALSE;
- set_subrace_title(SUBRACE_SAVE, title);
+ set_subrace_title(rmp_ptr, title);
}
else
{
char buf[512];
sprintf(buf, "Vampire %s", title);
- set_subrace_title(SUBRACE_SAVE, buf);
+ set_subrace_title(rmp_ptr, buf);
}
/* Bonus/and .. not bonus :) */
@@ -668,7 +698,6 @@ bool_ player_has_corruption(int corruption_idx)
static bool_ player_can_gain_corruption(int corruption_idx)
{
- cptr r_name = rp_ptr->title + rp_name;
bool_ allowed = TRUE; /* Allowed by default */
assert(corruption_idx >= 0);
@@ -676,7 +705,7 @@ static bool_ player_can_gain_corruption(int corruption_idx)
if (corruption_idx == CORRUPT_TROLL_BLOOD)
{
/* Ok trolls should not get this one. never. */
- if (streq(r_name, "Troll"))
+ if (streq(rp_ptr->title, "Troll"))
{
allowed = FALSE;
}
@@ -686,7 +715,7 @@ static bool_ player_can_gain_corruption(int corruption_idx)
if (game_module_idx == MODULE_THEME)
{
- if (streq(r_name, "Maia"))
+ if (streq(rp_ptr->title, "Maia"))
{
/* We use a whitelist of corruptions for Maiar */
bool_ allow = FALSE;
@@ -734,7 +763,7 @@ static bool_ player_allow_corruption(int corruption_idx)
/* Vampire teeth is special */
if (corruption_idx == CORRUPT_VAMPIRE_TEETH)
{
- if (PRACE_FLAG(PR1_NO_SUBRACE_CHANGE))
+ if (race_flags1_p(PR1_NO_SUBRACE_CHANGE))
{
return TRUE;
}
@@ -750,7 +779,7 @@ static bool_ player_allow_corruption(int corruption_idx)
static void player_set_corruption(int c, bool_ set)
{
p_ptr->corruptions[c] = set;
- p_ptr->redraw = p_ptr->redraw | PR_BASIC;
+ p_ptr->redraw = p_ptr->redraw | PR_FRAME;
p_ptr->update = p_ptr->update | PU_BONUS | PU_TORCH | PU_BODY | PU_POWERS;
}
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 d8a5d4f2..2c05acf5 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -46,11 +46,6 @@
#define SAVEFILE_VERSION 105
/*
- * This value is not currently used
- */
-#define VERSION_EXTRA 0
-
-/*
* Maximum amount of Angband windows.
*/
#define ANGBAND_TERM_MAX 8
@@ -126,17 +121,10 @@
#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
@@ -184,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.
@@ -254,13 +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 */
-
-/*
* Maximum value storable in a "byte" (hard-coded)
*/
#define MAX_UCHAR 255
@@ -275,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 */
@@ -351,7 +318,6 @@
#define NASTY_MON 50 /* 1/chance of inflated monster level */
-
/*
* Refueling constants
*/
@@ -393,7 +359,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
@@ -415,67 +380,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)
*/
@@ -522,14 +431,9 @@
#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
@@ -537,7 +441,6 @@
#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
@@ -604,45 +507,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") ***/
@@ -724,9 +588,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 */
@@ -826,24 +687,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") ***/
@@ -1321,9 +1164,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 ***/
@@ -1408,7 +1256,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
@@ -2185,7 +2032,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
@@ -2222,38 +2068,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)
@@ -2862,9 +2679,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 */
@@ -3042,11 +2856,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
*/
@@ -3120,7 +2929,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
@@ -3361,7 +3169,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 */
/*
@@ -3468,386 +3275,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
@@ -3938,55 +3369,34 @@
#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
@@ -4114,13 +3524,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
@@ -4142,14 +3546,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
@@ -4180,8 +3576,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
@@ -4196,7 +3590,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 */
@@ -4216,80 +3609,6 @@
#define SF1_MUSEUM 0x00000400L
/*
- * 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_MERCHANT 57
-#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
-
-#define ADD_POWER(pow, p) ((pow)[(p)] = TRUE)
-
-/*
* Shield effect options
*/
#define SHIELD_NONE 0x0000
@@ -4355,45 +3674,6 @@
#define MAX_MODULES 2
/*
- * Corruptions
- */
-#define CORRUPT_BALROG_AURA 0
-#define CORRUPT_BALROG_WINGS 1
-#define CORRUPT_BALROG_STRENGTH 2
-#define CORRUPT_BALROG_FORM 3
-#define CORRUPT_DEMON_SPIRIT 4
-#define CORRUPT_DEMON_HIDE 5
-#define CORRUPT_DEMON_BREATH 6
-#define CORRUPT_DEMON_REALM 7
-#define CORRUPT_RANDOM_TELEPORT 8
-#define CORRUPT_ANTI_TELEPORT 9
-#define CORRUPT_TROLL_BLOOD 10
-#define CORRUPT_VAMPIRE_TEETH 11
-#define CORRUPT_VAMPIRE_STRENGTH 12
-#define CORRUPT_VAMPIRE_VAMPIRE 13
-#define MUT1_SPIT_ACID 14
-#define MUT1_BR_FIRE 15
-#define MUT1_HYPN_GAZE 16
-#define MUT1_TELEKINES 17
-#define MUT1_VTELEPORT 18
-#define MUT1_MIND_BLST 19
-#define MUT1_VAMPIRISM 20
-#define MUT1_SMELL_MET 21
-#define MUT1_SMELL_MON 22
-#define MUT1_BLINK 23
-#define MUT1_EAT_ROCK 24
-#define MUT1_SWAP_POS 25
-#define MUT1_SHRIEK 26
-#define MUT1_ILLUMINE 27
-#define MUT1_DET_CURSE 28
-#define MUT1_BERSERK 29
-#define MUT1_MIDAS_TCH 30
-#define MUT1_GROW_MOLD 31
-#define MUT1_RESIST 32
-#define MUT1_EARTHQUAKE 33
-#define CORRUPTIONS_MAX 34
-
-/*
* Races
*/
#define RACE_HUMAN 0
@@ -4428,7 +3708,6 @@
* Hooks
*/
#define HOOK_MONSTER_DEATH 0
-#define HOOK_OPEN 1
#define HOOK_GEN_QUEST 2
#define HOOK_END_TURN 3
#define HOOK_FEELING 4
@@ -4452,66 +3731,26 @@
#define HOOK_NEW_MONSTER_END 22
#define HOOK_AIM 24
#define HOOK_USE 25
-#define HOOK_ACTIVATE 26
-#define HOOK_ZAP 27
-#define HOOK_CALC_POWERS 30
-#define HOOK_KEYPRESS 31
#define HOOK_CHAT 32
#define HOOK_MON_SPEAK 33
#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_WIELD_SLOT 46
-#define HOOK_STORE_STOCK 47
#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_CALC_MANA 60
-#define HOOK_LOAD_END 61
#define HOOK_RECALL 62
#define HOOK_BODY_PARTS 65
-#define HOOK_APPLY_MAGIC 66
-#define HOOK_PLAYER_EXP 67
-#define HOOK_BIRTH 68
#define HOOK_MON_ASK_HELP 69
-#define HOOK_LEARN_ABILITY 70
-#define HOOK_MOVED 71
#define HOOK_GAME_START 72
-#define HOOK_TAKEOFF 73
-#define HOOK_CALC_WEIGHT 74
#define HOOK_FORBID_TRAVEL 75
-#define HOOK_DEBUG_COMMAND 76
-#define MAX_HOOKS 77
-
-#define HOOK_TYPE_C 0
-#define HOOK_TYPE_NEW 2
-
-/*
- * 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 HELP_MAX 64
/*
* Special weapon effects
@@ -4540,69 +3779,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
@@ -4613,11 +3789,6 @@
#define MAX_MELEE 3
-/*
- * Player specialities, should be external but ti would be a mess
- */
-#define MAX_SPEC 20
-
/*
* Spellbinder triggers
@@ -4642,10 +3813,6 @@
#define GOD_MANDOS 9
#define MAX_GODS 10
-#define GOD(g) if (p_ptr->pgod == (g))
-#define PRAY_GOD(g) if ((p_ptr->pgod == (g)) && (p_ptr->praying))
-#define NOT_PRAY_GOD(g) if ((p_ptr->pgod == (g)) && (!p_ptr->praying))
-
/*
* Command numbers for do_cmd_cli().
*
@@ -4728,3 +3895,21 @@
#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..637d2773
--- /dev/null
+++ b/src/dice.cc
@@ -0,0 +1,98 @@
+#include "dice.hpp"
+
+#include "z-rand.h"
+
+#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 8df85977..62eaf211 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,23 +6,93 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include <assert.h>
-
-#include "quark.h"
-#include "spell_type.h"
+#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 <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))
@@ -61,7 +127,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];
@@ -128,7 +194,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);
@@ -150,7 +216,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];
@@ -219,7 +285,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)
{
@@ -230,9 +296,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:
@@ -257,8 +322,7 @@ static byte select_sense(object_type *o_ptr)
case TV_BOOMERANG:
case TV_TRAPKIT:
{
- return 1;
- break;
+ return combat;
}
case TV_POTION:
@@ -269,22 +333,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.
@@ -296,21 +359,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;
@@ -340,24 +390,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;
@@ -368,37 +415,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)
- {
- feel = (heavy_combat ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr));
- }
- else
+ /* Skip non-sensed items */
+ if (!sense)
{
- 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...",
@@ -423,6 +472,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)
@@ -632,7 +695,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);
@@ -689,7 +752,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);
@@ -737,7 +800,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);
}
}
@@ -774,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);
}
}
}
@@ -785,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;
@@ -805,117 +868,6 @@ static int process_lasting_spell(s16b 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;
@@ -929,14 +881,13 @@ static void check_music()
{
msg_print("You stop your spell.");
p_ptr->music_extra = 0;
- p_ptr->music_extra2 = 0;
}
else
{
p_ptr->csp -= use_mana;
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -947,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];
@@ -992,7 +943,7 @@ void apply_effect(int y, int x)
/* XXX XXX XXX */
-bool_ is_recall = FALSE;
+static bool_ is_recall = FALSE;
/*
@@ -1012,7 +963,7 @@ static void process_world_corruptions()
}
else
{
- disturb(0, 0);
+ disturb(0);
msg_print("Your corruption takes over you, you teleport!");
teleport_player(50);
}
@@ -1067,10 +1018,10 @@ static bool_ grace_delay_trigger()
*/
static void process_world_gods()
{
- const char *race_name = rp_ptr->title + rp_name;
- const char *subrace_name = rmp_ptr->title + rmp_name;
+ const char *race_name = rp_ptr->title;
+ const char *subrace_name = rmp_ptr->title;
- GOD(GOD_VARDA)
+ if (p_ptr->pgod == GOD_VARDA)
{
if (grace_delay_trigger())
{
@@ -1100,7 +1051,7 @@ static void process_world_gods()
}
}
- GOD(GOD_ULMO)
+ if (p_ptr->pgod == GOD_ULMO)
{
if (grace_delay_trigger())
{
@@ -1142,7 +1093,7 @@ static void process_world_gods()
}
}
- GOD(GOD_AULE)
+ if (p_ptr->pgod == GOD_AULE)
{
if (grace_delay_trigger())
{
@@ -1224,7 +1175,7 @@ static void process_world_gods()
}
}
- GOD(GOD_MANDOS)
+ if (p_ptr->pgod == GOD_MANDOS)
{
if (grace_delay_trigger())
{
@@ -1327,9 +1278,6 @@ static void process_world(void)
}
}
- /* Handle class special actions */
- gere_class_special();
-
/* Check the fate */
if (fate_option && (p_ptr->lev > 10))
{
@@ -1458,104 +1406,10 @@ static void process_world(void)
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))
{
@@ -1621,7 +1475,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))
{
@@ -1657,7 +1511,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);
@@ -1799,7 +1653,7 @@ static void process_world(void)
{
/* Message */
msg_print("You faint from the lack of food.");
- disturb(1, 0);
+ disturb(1);
/* Hack -- faint (bypass free action) */
(void)set_paralyzed(1 + rand_int(5));
@@ -1861,7 +1715,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);
@@ -1873,47 +1727,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);
}
}
@@ -1930,7 +1802,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)
{
@@ -1997,7 +1869,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);
@@ -2063,24 +1935,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)
{
@@ -2139,12 +1999,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)
{
@@ -2203,12 +2057,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)
{
@@ -2407,19 +2255,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))
{
@@ -2442,7 +2277,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);
@@ -2506,7 +2341,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;
}
@@ -2779,7 +2614,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);
}
}
@@ -2818,14 +2653,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.");
}
}
@@ -2847,7 +2682,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))
@@ -2868,11 +2703,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);
@@ -2887,7 +2722,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;
}
@@ -2898,7 +2733,7 @@ static void process_world(void)
}
/* Redraw */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2914,11 +2749,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);
@@ -2975,7 +2810,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);
@@ -2990,7 +2825,7 @@ static void process_world(void)
}
else if (get_check("Teleport? "))
{
- disturb(0, 0);
+ disturb(0);
teleport_player(50);
}
}
@@ -3150,8 +2985,7 @@ static void process_world(void)
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;
}
@@ -3275,7 +3109,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;
}
@@ -3329,7 +3163,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)
@@ -3434,12 +3268,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.
*
@@ -3452,9 +3280,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)
{
@@ -3494,7 +3319,7 @@ static void process_command(void)
p_ptr->update |= (PU_MONSTERS);
/* Redraw "title" */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
break;
}
@@ -3526,7 +3351,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;
}
@@ -3732,7 +3557,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;
@@ -3884,13 +3709,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();
@@ -3969,13 +3787,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();
@@ -4006,18 +3817,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();
@@ -4036,13 +3837,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;
}
@@ -4053,13 +3847,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();
@@ -4072,13 +3859,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();
@@ -4091,13 +3871,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();
@@ -4131,13 +3904,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();
@@ -4150,13 +3916,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();
@@ -4169,13 +3928,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();
@@ -4188,7 +3940,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.");
}
@@ -4271,13 +4023,6 @@ static void process_command(void)
/*** System Commands ***/
- /* Hack -- User interface */
- case '!':
- {
- (void)Term_user(0);
- break;
- }
-
/* Single line from a pref file */
case '"':
{
@@ -4399,22 +4144,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 '#':
{
@@ -4511,7 +4240,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;
@@ -4553,7 +4282,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);
}
}
@@ -4584,9 +4313,9 @@ void process_player(void)
if (stop)
{
- disturb(0, 0);
+ disturb(0);
}
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
}
@@ -4596,17 +4325,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.");
@@ -4656,7 +4382,7 @@ void process_player(void)
o_ptr = &p_ptr->inventory[item];
/* Disturbing */
- disturb(0, 0);
+ disturb(0);
/* Warning */
msg_print("Your pack overflows!");
@@ -4708,7 +4434,7 @@ void process_player(void)
resting--;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
p_ptr->did_nothing = TRUE;
@@ -4739,7 +4465,7 @@ void process_player(void)
command_rep--;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Redraw stuff */
redraw_stuff();
@@ -4784,7 +4510,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;
@@ -4816,8 +4542,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;
@@ -4853,7 +4578,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++)
@@ -4998,11 +4723,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)
@@ -5093,7 +4817,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);
@@ -5274,12 +4998,7 @@ static void dungeon(void)
process_world();
/* Process the appropriate hooks */
- process_hooks(HOOK_END_TURN, "(d)", is_quest(dun_level));
-
- {
- hook_end_turn_in in = { is_quest(dun_level) };
- process_hooks_new(HOOK_END_TURN, &in, NULL);
- }
+ process_hooks_new(HOOK_END_TURN, NULL, NULL);
/* Make it pulsate and live !!!! */
if ((dungeon_flags1 & DF1_EVOLVE) && dun_level)
@@ -5357,13 +5076,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);
@@ -5374,12 +5093,20 @@ static void load_all_pref_files(void)
/* Process that file */
process_pref_file(buf);
- /* Process player specific automatizer sets */
- /* TODO: Disabled temporarily because it causes duplicate
- * rules on save and subsequent game load. */
- /* sprintf(buf2, "%s.atm", player_name); */
- /* path_build(buf, sizeof(buf), ANGBAND_DIR_USER, buf2); */
- /* automatizer_init(buf); */
+ /* 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
+ }
}
/*
@@ -5527,11 +5254,10 @@ 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))
+ if (race_flags1_p(PR1_UNDEAD))
{
turn = (10L * DAY / 2) + (START_DAY * 10) + 1;
}
@@ -5582,7 +5308,7 @@ void play_game(bool_ new_game)
if (init_v_info()) quit("Cannot initialize vaults");
/* Initialize hooks */
- init_hooks();
+ init_hooks_quests();
init_hooks_help();
init_hooks_module();
@@ -5606,7 +5332,6 @@ 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" */
@@ -5723,7 +5448,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;
}
@@ -5827,7 +5552,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;
@@ -5846,7 +5570,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_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 8fd9e5e5..00000000
--- a/src/externs.h
+++ /dev/null
@@ -1,2377 +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 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 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[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];
-
-
-/* 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_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 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_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 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_ rogue_like_commands;
-extern bool_ quick_messages;
-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_ 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_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 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 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_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 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_ *m_allow_special;
-extern bool_ *k_allow_special;
-extern bool_ *a_allow_special;
-extern bool_ rand_birth;
-extern bool_ joke_monsters;
-extern bool_ center_player;
-extern s16b plots[MAX_PLOTS];
-extern random_quest random_quests[MAX_RANDOM_QUEST];
-extern bool_ exp_need;
-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 s32b extra_savefile_parts;
-extern bool_ player_char_health;
-extern s16b school_spells_count;
-extern spell_type *school_spells[SCHOOL_SPELLS_MAX];
-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 bool_ linear_stats;
-extern int max_bact;
-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 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();
-
-/* plots.c */
-extern FILE *hook_file;
-extern bool_ check_hook(int h_idx);
-extern void wipe_hooks(void);
-extern void dump_hooks(int h_idx);
-extern void init_hooks(void);
-extern hooks_chain* add_hook(int h_idx, hook_type hook, cptr name);
-extern void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data);
-extern void add_hook_script(int h_idx, char *script, cptr name);
-extern void del_hook(int h_idx, hook_type hook);
-extern void del_hook_name(int h_idx, cptr name);
-extern s32b get_next_arg(char *fmt);
-extern int process_hooks_restart;
-extern hook_return process_hooks_return[20];
-extern bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...);
-extern bool_ process_hooks(int h_idx, char *fmt, ...);
-extern bool_ process_hooks_new(int h_idx, void *in, void *out);
-
-extern void initialize_bookable_spells();
-
-/* help.c */
-extern void init_hooks_help();
-extern void help_race(cptr race);
-extern void help_subrace(cptr subrace);
-extern void help_class(cptr klass);
-extern void help_god(cptr god);
-extern void help_skill(cptr skill);
-extern void help_ability(cptr ability);
-
-/* birth.c */
-extern void print_desc_aux(cptr txt, int y, int x);
-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 bool_ is_ok_spell(s32b spell_idx, object_type *o_ptr);
-extern s32b get_school_spell(cptr do_what, s16b force_book);
-extern void do_cmd_copy_spell(void);
-extern void cast_school_spell(void);
-extern void browse_school_spell(int book, int pval, object_type *o_ptr);
-extern int find_spell(const 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 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);
-
-/* corrupt.c */
-extern void gain_random_corruption();
-extern void dump_corruptions(FILE *OutFile, bool_ color, bool_ header);
-extern void lose_corruption();
-extern bool_ player_has_corruption(int corruption_idx);
-extern void player_gain_corruption(int corruption_idx);
-extern s16b get_corruption_power(int corruption_idx);
-
-/* 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 predict_score_gui(bool_ *initialized, bool_ *game_in_progress);
-extern void close_game(void);
-extern errr get_rnd_line(char * file_name, char * output);
-extern 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();
-extern void reinit_gods(s16b new_size);
-extern void reinit_quests(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;
-
-/* joke.c */
-extern bool_ gen_joke_monsters(void *data, void *in, void *out);
-
-/* loadsave.c */
-extern bool_ file_exist(cptr 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);
-
-/* 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 void mon_handle_fear(monster_type *m_ptr, int dam, bool_ *fear);
-extern int check_hit2(int power, int level, int ac);
-extern int get_attack_power(int effect);
-extern bool_ carried_make_attack_normal(int r_idx);
-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_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);
-
-/* 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_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_ 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);
-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);
-
-/* spells3.c */
-s32b get_level_s(int sp, int max);
-
-extern s32b NOXIOUSCLOUD;
-extern s32b AIRWINGS;
-extern s32b INVISIBILITY;
-extern s32b POISONBLOOD;
-extern s32b THUNDERSTORM;
-extern s32b STERILIZE;
-
-casting_result air_noxious_cloud(int);
-char *air_noxious_cloud_info();
-casting_result air_wings_of_winds(int);
-char *air_wings_of_winds_info();
-casting_result air_invisibility(int);
-char *air_invisibility_info();
-casting_result air_poison_blood(int);
-char *air_poison_blood_info();
-casting_result air_thunderstorm(int);
-char *air_thunderstorm_info();
-casting_result air_sterilize(int);
-char *air_sterilize_info();
-
-extern s32b BLINK;
-extern s32b DISARM;
-extern s32b TELEPORT;
-extern s32b TELEAWAY;
-extern s32b RECALL;
-extern s32b PROBABILITY_TRAVEL;
-
-casting_result convey_blink(int);
-char *convey_blink_info();
-casting_result convey_disarm(int);
-char *convey_disarm_info();
-casting_result convey_teleport(int);
-char *convey_teleport_info();
-casting_result convey_teleport_away(int);
-char *convey_teleport_away_info();
-casting_result convey_recall(int);
-char *convey_recall_info();
-casting_result convey_probability_travel(int);
-char *convey_probability_travel_info();
-
-extern s32b DEMON_BLADE;
-extern s32b DEMON_MADNESS;
-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(int);
-char *demonology_demon_blade_info();
-casting_result demonology_demon_madness(int);
-char *demonology_demon_madness_info();
-casting_result demonology_demon_field(int);
-char *demonology_demon_field_info();
-casting_result demonology_doom_shield(int);
-char *demonology_doom_shield_info();
-casting_result demonology_unholy_word(int);
-char *demonology_unholy_word_info();
-casting_result demonology_demon_cloak(int);
-char *demonology_demon_cloak_info();
-casting_result demonology_summon_demon(int);
-char *demonology_summon_demon_info();
-casting_result demonology_discharge_minion(int);
-char *demonology_discharge_minion_info();
-casting_result demonology_control_demon(int);
-char *demonology_control_demon_info();
-
-extern s32b STARIDENTIFY;
-extern s32b IDENTIFY;
-extern s32b VISION;
-extern s32b SENSEHIDDEN;
-extern s32b REVEALWAYS;
-extern s32b SENSEMONSTERS;
-
-casting_result divination_greater_identify(int);
-char *divination_greater_identify_info();
-casting_result divination_identify(int);
-char *divination_identify_info();
-casting_result divination_vision(int);
-char *divination_vision_info();
-casting_result divination_sense_hidden(int);
-char *divination_sense_hidden_info();
-casting_result divination_reveal_ways(int);
-char *divination_reveal_ways_info();
-casting_result divination_sense_monsters(int);
-char *divination_sense_monsters_info();
-
-extern s32b STONESKIN;
-extern s32b DIG;
-extern s32b STONEPRISON;
-extern s32b STRIKE;
-extern s32b SHAKE;
-
-casting_result earth_stone_skin(int);
-char *earth_stone_skin_info();
-casting_result earth_dig(int);
-char *earth_dig_info();
-casting_result earth_stone_prison(int);
-char *earth_stone_prison_info();
-casting_result earth_strike(int);
-char *earth_strike_info();
-casting_result earth_shake(int);
-char *earth_shake_info();
-
-extern s32b ERU_SEE;
-extern s32b ERU_LISTEN;
-extern s32b ERU_UNDERSTAND;
-extern s32b ERU_PROT;
-
-casting_result eru_see_the_music(int);
-char *eru_see_the_music_info();
-casting_result eru_listen_to_the_music(int);
-char *eru_listen_to_the_music_info();
-casting_result eru_know_the_music(int);
-char *eru_know_the_music_info();
-casting_result eru_lay_of_protection(int);
-char *eru_lay_of_protection_info();
-
-extern s32b GLOBELIGHT;
-extern s32b FIREFLASH;
-extern s32b FIERYAURA;
-extern s32b FIREWALL;
-extern s32b FIREGOLEM;
-
-casting_result fire_globe_of_light(int);
-char *fire_globe_of_light_info();
-casting_result fire_fireflash(int);
-char *fire_fireflash_info();
-casting_result fire_fiery_shield(int);
-char *fire_fiery_shield_info();
-casting_result fire_firewall(int);
-char *fire_firewall_info();
-casting_result fire_golem(int);
-char *fire_golem_info();
-
-extern s32b CALL_THE_ELEMENTS;
-extern s32b CHANNEL_ELEMENTS;
-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(int);
-char *geomancy_call_the_elements_info();
-casting_result geomancy_channel_elements(int);
-char *geomancy_channel_elements_info();
-casting_result geomancy_elemental_wave(int);
-char *geomancy_elemental_wave_info();
-casting_result geomancy_vaporize(int);
-char *geomancy_vaporize_info();
-bool_ geomancy_vaporize_depends();
-casting_result geomancy_geolysis(int);
-char *geomancy_geolysis_info();
-bool_ geomancy_geolysis_depends();
-casting_result geomancy_dripping_tread(int);
-char *geomancy_dripping_tread_info();
-bool_ geomancy_dripping_tread_depends();
-casting_result geomancy_grow_barrier(int);
-char *geomancy_grow_barrier_info();
-bool_ geomancy_grow_barrier_depends();
-casting_result geomancy_elemental_minion(int);
-char *geomancy_elemental_minion_info();
-
-extern s32b MANATHRUST;
-extern s32b DELCURSES;
-extern s32b RESISTS;
-extern s32b MANASHIELD;
-
-casting_result mana_manathrust(int);
-char *mana_manathrust_info();
-casting_result mana_remove_curses(int);
-char *mana_remove_curses_info();
-casting_result mana_elemental_shield(int);
-char *mana_elemental_shield_info();
-casting_result mana_disruption_shield(int);
-char *mana_disruption_shield_info();
-
-extern s32b MANWE_SHIELD;
-extern s32b MANWE_AVATAR;
-extern s32b MANWE_BLESS;
-extern s32b MANWE_CALL;
-
-casting_result manwe_wind_shield(int);
-char *manwe_wind_shield_info();
-casting_result manwe_avatar(int);
-char *manwe_avatar_info();
-casting_result manwe_blessing(int);
-char *manwe_blessing_info();
-casting_result manwe_call(int);
-char *manwe_call_info();
-
-extern s32b MELKOR_CURSE;
-extern s32b MELKOR_CORPSE_EXPLOSION;
-extern s32b MELKOR_MIND_STEAL;
-
-void do_melkor_curse(int m_idx);
-
-casting_result melkor_curse(int);
-char *melkor_curse_info();
-casting_result melkor_corpse_explosion(int);
-char *melkor_corpse_explosion_info();
-casting_result melkor_mind_steal(int);
-char *melkor_mind_steal_info();
-
-extern s32b RECHARGE;
-extern s32b SPELLBINDER;
-extern s32b DISPERSEMAGIC;
-extern s32b TRACKER;
-extern s32b INERTIA_CONTROL;
-extern timer_type *TIMER_INERTIA_CONTROL;
-
-casting_result meta_recharge(int);
-char *meta_recharge_info();
-casting_result meta_spellbinder(int);
-char *meta_spellbinder_info();
-casting_result meta_disperse_magic(int);
-char *meta_disperse_magic_info();
-casting_result meta_tracker(int);
-char *meta_tracker_info();
-casting_result meta_inertia_control(int);
-char *meta_inertia_control_info();
-
-void meta_inertia_control_timer_callback();
-void meta_inertia_control_calc_mana(int *msp);
-void meta_inertia_control_hook_birth_objects();
-
-extern s32b CHARM;
-extern s32b CONFUSE;
-extern s32b ARMOROFFEAR;
-extern s32b STUN;
-
-casting_result mind_charm(int);
-char *mind_charm_info();
-casting_result mind_confuse(int);
-char *mind_confuse_info();
-casting_result mind_armor_of_fear(int);
-char *mind_armor_of_fear_info();
-casting_result mind_stun(int);
-char *mind_stun_info();
-
-extern s32b MAGELOCK;
-extern s32b SLOWMONSTER;
-extern s32b ESSENCESPEED;
-extern s32b BANISHMENT;
-
-casting_result tempo_magelock(int);
-char *tempo_magelock_info();
-casting_result tempo_slow_monster(int);
-char *tempo_slow_monster_info();
-casting_result tempo_essence_of_speed(int);
-char *tempo_essence_of_speed_info();
-casting_result tempo_banishment(int);
-char *tempo_banishment_info();
-
-extern s32b TULKAS_AIM;
-extern s32b TULKAS_WAVE;
-extern s32b TULKAS_SPIN;
-
-casting_result tulkas_divine_aim(int);
-char *tulkas_divine_aim_info();
-casting_result tulkas_wave_of_power(int);
-char *tulkas_wave_of_power_info();
-casting_result tulkas_whirlwind(int);
-char *tulkas_whirlwind_info();
-
-extern s32b DRAIN;
-extern s32b GENOCIDE;
-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(int);
-char *udun_drain_info();
-casting_result udun_genocide(int);
-char *udun_genocide_info();
-casting_result udun_wraithform(int);
-char *udun_wraithform_info();
-casting_result udun_flame_of_udun(int);
-char *udun_flame_of_udun_info();
-
-extern s32b TIDALWAVE;
-extern s32b ICESTORM;
-extern s32b ENTPOTION;
-extern s32b VAPOR;
-extern s32b GEYSER;
-
-casting_result water_tidal_wave(int);
-char *water_tidal_wave_info();
-casting_result water_ice_storm(int);
-char *water_ice_storm_info();
-casting_result water_ent_potion(int);
-char *water_ent_potion_info();
-casting_result water_vapor(int);
-char *water_vapor_info();
-casting_result water_geyser(int);
-char *water_geyser_info();
-
-extern s32b YAVANNA_CHARM_ANIMAL;
-extern s32b YAVANNA_GROW_GRASS;
-extern s32b YAVANNA_TREE_ROOTS;
-extern s32b YAVANNA_WATER_BITE;
-extern s32b YAVANNA_UPROOT;
-
-casting_result yavanna_charm_animal(int);
-char *yavanna_charm_animal_info();
-casting_result yavanna_grow_grass(int);
-char *yavanna_grow_grass_info();
-casting_result yavanna_tree_roots(int);
-char *yavanna_tree_roots_info();
-casting_result yavanna_water_bite(int);
-char *yavanna_water_bite_info();
-casting_result yavanna_uproot(int);
-char *yavanna_uproot_info();
-
-extern s32b GROWTREE;
-extern s32b HEALING;
-extern s32b RECOVERY;
-extern s32b REGENERATION;
-extern s32b SUMMONANNIMAL;
-extern s32b GROW_ATHELAS;
-
-casting_result nature_grow_trees(int);
-char *nature_grow_trees_info();
-casting_result nature_healing(int);
-char *nature_healing_info();
-casting_result nature_recovery(int);
-char *nature_recovery_info();
-casting_result nature_regeneration(int);
-char *nature_regeneration_info();
-casting_result nature_summon_animal(int);
-char *nature_summon_animal_info();
-casting_result nature_grow_athelas(int);
-char *nature_grow_athelas_info();
-
-extern s32b DEVICE_HEAL_MONSTER;
-extern s32b DEVICE_SPEED_MONSTER;
-extern s32b DEVICE_WISH;
-extern s32b DEVICE_SUMMON;
-extern s32b DEVICE_MANA;
-extern s32b DEVICE_NOTHING;
-extern s32b DEVICE_LEBOHAUM;
-extern s32b DEVICE_MAGGOT;
-extern s32b DEVICE_HOLY_FIRE;
-extern s32b DEVICE_ETERNAL_FLAME;
-extern s32b DEVICE_DURANDIL;
-extern s32b DEVICE_THUNDERLORDS;
-extern s32b DEVICE_RADAGAST;
-extern s32b DEVICE_VALAROMA;
-
-casting_result device_heal_monster(int);
-char *device_heal_monster_info();
-casting_result device_haste_monster(int);
-char *device_haste_monster_info();
-casting_result device_wish(int);
-char *device_wish_info();
-casting_result device_summon_monster(int);
-char *device_summon_monster_info();
-casting_result device_mana(int);
-char *device_mana_info();
-casting_result device_nothing(int);
-char *device_nothing_info();
-casting_result device_lebohaum(int);
-char *device_lebohaum_info();
-casting_result device_maggot(int);
-char *device_maggot_info();
-casting_result device_holy_fire(int);
-char *device_holy_fire_info();
-casting_result device_eternal_flame(int);
-char *device_eternal_flame_info();
-casting_result device_durandil(int);
-char *device_durandil_info();
-casting_result device_thunderlords(int);
-char *device_thunderlords_info();
-casting_result device_radagast(int);
-char *device_radagast_info();
-casting_result device_valaroma(int);
-char *device_valaroma_info();
-
-extern s32b MUSIC_STOP;
-extern s32b MUSIC_HOLD;
-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);
-char *music_stop_singing_info();
-
-int music_holding_pattern_lasting();
-casting_result music_holding_pattern_spell(int);
-char *music_holding_pattern_info();
-
-int music_illusion_pattern_lasting();
-casting_result music_illusion_pattern_spell(int);
-char *music_illusion_pattern_info();
-
-int music_stun_pattern_lasting();
-casting_result music_stun_pattern_spell(int);
-char *music_stun_pattern_info();
-
-int music_song_of_the_sun_lasting();
-casting_result music_song_of_the_sun_spell(int);
-char *music_song_of_the_sun_info();
-
-int music_flow_of_life_lasting();
-casting_result music_flow_of_life_spell(int);
-char *music_flow_of_life_info();
-
-int music_heroic_ballad_lasting();
-casting_result music_heroic_ballad_spell(int);
-char *music_heroic_ballad_info();
-
-int music_hobbit_melodies_lasting();
-casting_result music_hobbit_melodies_spell(int);
-char *music_hobbit_melodies_info();
-
-int music_clairaudience_lasting();
-casting_result music_clairaudience_spell(int);
-char *music_clairaudience_info();
-
-casting_result music_blow_spell(int);
-char *music_blow_info();
-
-casting_result music_gush_of_wind_spell(int);
-char *music_gush_of_wind_info();
-
-casting_result music_horns_of_ylmir_spell(int);
-char *music_horns_of_ylmir_info();
-
-casting_result music_ambarkanta_spell(int);
-char *music_ambarkanta_info();
-
-extern s32b AULE_FIREBRAND;
-extern s32b AULE_ENCHANT_WEAPON;
-extern s32b AULE_ENCHANT_ARMOUR;
-extern s32b AULE_CHILD;
-
-casting_result aule_firebrand_spell(int);
-char *aule_firebrand_info();
-casting_result aule_enchant_weapon_spell(int);
-char *aule_enchant_weapon_info();
-casting_result aule_enchant_armour_spell(int);
-char *aule_enchant_armour_info();
-casting_result aule_child_spell(int);
-char *aule_child_info();
-
-extern s32b MANDOS_TEARS_LUTHIEN;
-extern s32b MANDOS_SPIRIT_FEANTURI;
-extern s32b MANDOS_TALE_DOOM;
-extern s32b MANDOS_CALL_HALLS;
-
-casting_result mandos_tears_of_luthien_spell(int);
-char *mandos_tears_of_luthien_info();
-casting_result mandos_spirit_of_the_feanturi_spell(int);
-char *mandos_spirit_of_the_feanturi_info();
-casting_result mandos_tale_of_doom_spell(int);
-char *mandos_tale_of_doom_info();
-casting_result mandos_call_to_the_halls_spell(int);
-char *mandos_call_to_the_halls_info();
-
-extern s32b ULMO_BELEGAER;
-extern s32b ULMO_DRAUGHT_ULMONAN;
-extern s32b ULMO_CALL_ULUMURI;
-extern s32b ULMO_WRATH;
-
-casting_result ulmo_song_of_belegaer_spell(int);
-char *ulmo_song_of_belegaer_info();
-casting_result ulmo_draught_of_ulmonan_spell(int);
-char *ulmo_draught_of_ulmonan_info();
-casting_result ulmo_call_of_the_ulumuri_spell(int);
-char *ulmo_call_of_the_ulumuri_info();
-casting_result ulmo_wrath_of_ulmo_spell(int);
-char *ulmo_wrath_of_ulmo_info();
-
-extern s32b VARDA_LIGHT_VALINOR;
-extern s32b VARDA_CALL_ALMAREN;
-extern s32b VARDA_EVENSTAR;
-extern s32b VARDA_STARKINDLER;
-
-casting_result varda_light_of_valinor_spell(int);
-char *varda_light_of_valinor_info();
-casting_result varda_call_of_almaren_spell(int);
-char *varda_call_of_almaren_info();
-casting_result varda_evenstar_spell(int);
-char *varda_evenstar_info();
-casting_result varda_star_kindler_spell(int);
-char *varda_star_kindler_info();
-
-/* spells4.c */
-
-SGLIB_DEFINE_LIST_PROTOTYPES(spell_idx_list, compare_spell_idx, next);
-
-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_type *school_books_at(int sval);
-void school_book_add_spell(school_book_type *school_book, s32b spell_idx);
-void random_book_setup(s16b sval, s32b spell_idx);
-int print_spell(cptr label, byte color, int y, s32b s);
-int print_book(s16b sval, s32b pval, object_type *obj);
-int school_book_length(int sval);
-int spell_x(int sval, int pval, int i);
-bool_ school_book_contains_spell(int sval, s32b spell_idx);
-void lua_cast_school_spell(s32b spell_idx, bool_ no_cost);
-
-void device_allocation_init(device_allocation *device_allocation, byte tval);
-device_allocation *device_allocation_new(byte tval);
-
-void dice_init(dice_type *dice, long base, long num, long sides);
-bool_ dice_parse(dice_type *dice, cptr s);
-void dice_parse_checked(dice_type *dice, cptr s);
-long dice_roll(dice_type *dice);
-void dice_print(dice_type *dice, char *buf);
-
-/* spells5.c */
-void school_spells_init();
-spell_type *spell_at(s32b index);
-s16b get_random_spell(s16b random_type, int lev);
-
-/* spells6.c */
-
-SGLIB_DEFINE_LIST_PROTOTYPES(school_provider, compare_school_provider, next);
-
-void schools_init();
-school_type *school_at(int index);
-
-void mana_school_calc_mana(int *msp);
-
-/* range.c */
-extern void range_init(range_type *range, s32b min, s32b max);
-
-/* 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 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 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(void (*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);
-
-/* mimic.c */
-extern s16b resolve_mimic_name(cptr name);
-extern s16b find_random_mimic_shape(byte level, bool_ limit);
-extern cptr get_mimic_name(s16b mf_idx);
-extern cptr get_mimic_object_name(s16b mf_idx);
-extern byte get_mimic_level(s16b mf_idx);
-extern s32b get_mimic_random_duration(s16b mf_idx);
-extern byte calc_mimic();
-extern void calc_mimic_power();
-
-/* xtra1.c */
-extern void fix_message(void);
-extern void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pval, s16b tval, s16b to_h, s16b to_d, s16b to_a);
-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 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 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_precognition(int v);
-extern bool_ set_tim_deadly(int v);
-extern bool_ set_tim_res_time(int v);
-extern bool_ set_tim_reflect(int v);
-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 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(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 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 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 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;
-extern void automatizer_init(cptr file_name);
-
-
-/*
- * 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_init(void);
-
-/* modules.c */
-extern void module_reset_dir(cptr dir, cptr new_path);
-extern cptr force_module;
-extern bool_ select_module(void);
-extern bool_ module_savefile_loadable(cptr savefile_mod);
-extern void tome_intro();
-extern void theme_intro();
-extern s16b *theme_race_status(int r_idx);
-extern void init_hooks_module();
-extern int find_module(cptr name);
-
-
-/* lua_bind.c */
-
-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 s32b lua_get_level(spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus);
-extern s32b get_level_device(s32b s, s32b max, s32b min);
-extern int get_mana(s32b s);
-extern s32b get_power(s32b s);
-extern s32b spell_chance(s32b s);
-extern s32b get_level(s32b s, s32b max, s32b min);
-extern void get_level_school(s32b s, s32b max, s32b min, s32b *level, bool_ *na);
-
-extern s32b get_level_max_stick;
-extern s32b get_level_use_stick;
-
-extern void set_target(int y, int x);
-extern void get_target(int dir, int *y, int *x);
-
-extern void get_map_size(char *name, int *ysize, int *xsize);
-extern void load_map(char *name, int *y, int *x);
-
-extern 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 void increase_mana(int delta);
-
-extern timer_type *TIMER_AGGRAVATE_EVIL;
-
-void timer_aggravate_evil_enable();
-void timer_aggravate_evil_callback();
-
-/* skills.c */
-extern void dump_skills(FILE *fff);
-extern s16b find_skill(cptr name);
-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);
-extern bool_ god_enabled(struct deity_type *deity);
-extern deity_type *god_at(byte god_idx);
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 664c96d7..2ff6a909 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,10 +6,55 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "hiscore.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 <memory>
+#include <unordered_set>
/*
* Extract the first few "tokens" from a buffer
@@ -429,9 +470,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);
}
@@ -464,10 +505,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;
}
@@ -478,7 +523,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 =
@@ -508,7 +553,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];
@@ -850,19 +895,19 @@ static cptr process_pref_file_expr(char **sp, char *fp)
/* 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 */
@@ -1029,7 +1074,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];
@@ -1562,28 +1607,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;
@@ -1591,13 +1636,13 @@ 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;
}
- GOD(GOD_AULE)
+ if (p_ptr->pgod == GOD_AULE)
{
if (p_ptr->grace > 5000)
{
@@ -1605,7 +1650,7 @@ void player_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
}
}
- GOD(GOD_MANDOS)
+ if (p_ptr->pgod == GOD_MANDOS)
{
(*f2) |= TR2_RES_NETHER;
@@ -1622,7 +1667,7 @@ void player_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
}
}
- GOD(GOD_ULMO)
+ if (p_ptr->pgod == GOD_ULMO)
{
(*f5) |= TR5_WATER_BREATH;
@@ -2175,8 +2220,8 @@ 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 */
@@ -2281,11 +2326,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
{
/*
@@ -2322,10 +2373,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
{
/*
@@ -2347,8 +2402,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);
}
}
@@ -2456,7 +2513,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++)
@@ -2469,46 +2526,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)
- {
- if (*head == st_ptr) return FALSE;
- ++head;
- }
- /* make room for the new one in the array */
- if (*store_list)
- {
- head = *store_list;
- *store_list = C_RNEW(*store_list_count + 1, store_type *);
- C_COPY(*store_list, head, *store_list_count, store_type *);
- C_FREE(head, *store_list_count, store_type *);
- }
- else
+ // Already seen store?
+ if (seen_stores->find(st_ptr) != seen_stores->end())
{
- *store_list = RNEW(store_type *);
+ return FALSE;
}
- /* update data */
- (*store_list)[*store_list_count] = st_ptr;
- ++*store_list_count;
-
+ // Add
+ seen_stores->insert(st_ptr);
return TRUE;
}
@@ -2526,8 +2563,6 @@ 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);
@@ -2619,19 +2654,12 @@ errr file_character(cptr name, bool_ full)
}
/* List the patches */
- hook_file = fff;
-
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
@@ -2664,7 +2692,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");
@@ -2672,7 +2700,7 @@ 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.");
{
@@ -2727,8 +2755,8 @@ 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 */
{
@@ -2830,24 +2858,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;
@@ -2933,9 +2967,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;
@@ -2945,7 +2976,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;
@@ -3015,9 +3047,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);
}
@@ -3145,9 +3174,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);
}
@@ -3488,9 +3514,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);
@@ -3519,9 +3542,6 @@ 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 = "html";
cptr link_prefix = "";
cptr link_suffix = "";
@@ -3530,7 +3550,8 @@ bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_
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;
@@ -3565,9 +3586,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);
@@ -3811,13 +3829,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)
{
@@ -4050,7 +4116,7 @@ void process_player_name(bool_ sf)
#endif
-#if defined(WINDOWS) || defined(MSDOS)
+#if defined(WINDOWS)
/* Hack -- max length */
if (k > 8) k = 8;
@@ -4215,7 +4281,7 @@ void do_cmd_save_game(void)
if (!is_autosave)
{
/* Disturb the player */
- disturb(1, 0);
+ disturb(1);
}
/* Clear messages */
@@ -4271,7 +4337,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;
@@ -4281,12 +4347,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 (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% */
@@ -4368,8 +4433,6 @@ long total_points(void)
}
temp += Total * 50;
- temp += total_bounties * 100;
-
if (total_winner) temp += 1000000;
@@ -4429,7 +4492,7 @@ static void print_tomb(void)
FILE *fp;
- time_t ct = time((time_t)0);
+ time_t ct = time(nullptr);
/* Clear screen */
@@ -4467,7 +4530,7 @@ static void print_tomb(void)
/* Normal */
else
{
- p = cp_ptr->titles[(p_ptr->lev - 1) / 5] + c_text;
+ p = cp_ptr->titles[(p_ptr->lev - 1) / 5];
}
center_string(buf, player_name);
@@ -4480,7 +4543,7 @@ static void print_tomb(void)
put_str(buf, 8, 11);
- center_string(buf, spp_ptr->title + c_name);
+ center_string(buf, spp_ptr->title);
put_str(buf, 10, 11);
(void)sprintf(tmp, "Level: %d", (int)p_ptr->lev);
@@ -4623,8 +4686,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;
}
@@ -4633,8 +4695,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;
}
@@ -4750,7 +4811,7 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig
cptr gold, when, aged;
- int in_arena, in_quest;
+ int in_quest;
/* Hack -- indicate death in yellow */
attr = (j == note) ? TERM_YELLOW : TERM_WHITE;
@@ -4786,7 +4847,6 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig
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 */
@@ -4796,8 +4856,11 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig
/* 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" */
@@ -4807,12 +4870,7 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig
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);
@@ -4855,48 +4913,14 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig
/*
- * 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];
- int highscore_fd;
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_USER, "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(highscore_fd, from, to, -1, NULL);
-
- /* Shut the high score file */
- fd_close(highscore_fd);
-
- /* 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;
@@ -4964,13 +4988,11 @@ void show_highclass(int building)
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++;
}
@@ -4981,21 +5003,15 @@ 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);
- 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);
+ player_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);
}
}
@@ -5015,7 +5031,7 @@ 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];
@@ -5024,7 +5040,7 @@ void race_score(int race_num)
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 */
@@ -5060,7 +5076,7 @@ void race_score(int 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;
@@ -5072,7 +5088,7 @@ 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);
}
@@ -5180,7 +5196,7 @@ static errr top_twenty(void)
/* Clear the record */
- WIPE(&the_score, high_score);
+ memset(&the_score, 0, sizeof(high_score));
/* Save the version */
sprintf(the_score.what, "%ld.%ld.%ld",
@@ -5217,10 +5233,7 @@ 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);
@@ -5258,7 +5271,7 @@ out:
/*
* Predict the players location, and display it.
*/
-errr predict_score(void)
+static errr predict_score(void)
{
int j;
@@ -5282,7 +5295,9 @@ errr predict_score(void)
}
/* 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",
@@ -5319,10 +5334,7 @@ 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!)");
@@ -5592,7 +5604,7 @@ void close_game(void)
/*
* Grab a randomly selected line in lib/file/file_name
*/
-errr get_rnd_line(char *file_name, char *output)
+errr get_rnd_line(const char *file_name, char *output)
{
FILE *fp;
@@ -5669,7 +5681,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;
@@ -5717,7 +5729,7 @@ char *get_line(char* fname, cptr fdir, char *linbuf, int line)
* understand such complexities -- and added extra error checkings
* and made sure fd is always closed -- pelpel
*/
-errr get_xtra_line(char *file_name, monster_type *m_ptr, char *output)
+errr get_xtra_line(const char *file_name, monster_type *m_ptr, char *output)
{
FILE *fp;
char buf[1024];
diff --git a/src/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..f71e3704
--- /dev/null
+++ b/src/flags_group.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * For level gaining artifacts, artifact creation, ...
+ */
+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..f6cee5a7 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,15 @@
* 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"
/*
* Generate a game of life level :) and make it evolve
@@ -48,7 +51,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 +85,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..9a3706fa 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,14 @@
* 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 <memory>
/*
* If we wasted static memory for this, it would look like:
@@ -20,7 +23,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 +148,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 +211,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 +285,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 44e331a6..0f24f7d2 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,40 @@
* 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 <cassert>
+#include <memory>
+#include <vector>
+
#define SAFE_MAX_ATTEMPTS 5000
/*
@@ -273,12 +302,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 +312,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;
@@ -1004,7 +1024,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));
}
}
@@ -2731,8 +2751,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);
}
@@ -3445,7 +3464,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);
}
}
}
@@ -3827,7 +3846,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);
}
@@ -3883,7 +3902,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);
}
/*
@@ -4721,7 +4740,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 */
@@ -5288,7 +5307,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;
@@ -5335,22 +5354,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);
}
@@ -5366,8 +5376,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");
@@ -5400,16 +5409,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++)
@@ -5444,9 +5447,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);
}
@@ -6642,7 +6642,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;
@@ -6794,7 +6794,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++)
@@ -7176,34 +7179,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
}
}
}
@@ -7211,34 +7214,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
@@ -7518,6 +7504,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
*
@@ -7525,7 +7592,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;
@@ -7585,7 +7651,7 @@ static bool_ cave_gen(void)
{
if (!strcmp(generator->name, generator_name))
{
- if (!generator->generator(generator->name))
+ if (!generator->generator())
return FALSE;
break;
}
@@ -7593,18 +7659,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);
@@ -7629,21 +7694,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))
@@ -7671,7 +7735,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;
@@ -7804,8 +7868,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)
{
@@ -7822,8 +7886,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));
@@ -7832,8 +7895,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));
@@ -7843,8 +7905,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));
@@ -7940,13 +8001,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);
}
}
@@ -7992,13 +8051,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);
}
}
}
@@ -8009,64 +8066,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;
@@ -8081,139 +8098,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
@@ -8291,7 +8175,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;
@@ -8317,7 +8201,6 @@ 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 */
@@ -8336,7 +8219,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;
@@ -8422,7 +8305,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))
@@ -8438,33 +8321,11 @@ void generate_cave(void)
{
for (x = 0; x < MAX_WID; x++)
{
- /* No flags */
- cave[y][x].info = 0;
+ /* Wipe */
+ cave[y][x].wipe();
/* No features */
cave_set_feat(y, x, FEAT_PERM_INNER);
-
- /* No objects */
- cave[y][x].o_idx = 0;
-
- /* No monsters */
- cave[y][x].m_idx = 0;
-
- /* No traps */
- cave[y][x].t_idx = 0;
-
- /* No mimic */
- cave[y][x].mimic = 0;
-
- /* No effects */
- cave[y][x].effect = 0;
-
- /* No inscription */
- cave[y][x].inscription = 0;
-
- /* No flow */
- cave[y][x].cost = 0;
- cave[y][x].when = 0;
}
}
@@ -8498,33 +8359,11 @@ void generate_cave(void)
{
for (x = 0; x < MAX_WID; x++)
{
- /* No flags */
- cave[y][x].info = 0;
+ /* Wipe */
+ cave[y][x].wipe();
/* No features */
cave_set_feat(y, x, FEAT_PERM_INNER);
-
- /* No objects */
- cave[y][x].o_idx = 0;
-
- /* No monsters */
- cave[y][x].m_idx = 0;
-
- /* No traps */
- cave[y][x].t_idx = 0;
-
- /* No mimic */
- cave[y][x].mimic = 0;
-
- /* No effect */
- cave[y][x].effect = 0;
-
- /* No inscription */
- cave[y][x].inscription = 0;
-
- /* No flow */
- cave[y][x].cost = 0;
- cave[y][x].when = 0;
}
}
@@ -8563,17 +8402,10 @@ void generate_cave(void)
/* No fated level here yet */
fate_flag = FALSE;
- /* Build the arena -KMW- */
- if (p_ptr->inside_arena)
- {
- /* Small arena */
- arena_gen();
- }
-
/* Quest levels -KMW- */
- else if (p_ptr->inside_quest)
+ if (p_ptr->inside_quest)
{
- quest_gen();
+ process_hooks_new(HOOK_GEN_QUEST, NULL, NULL);
}
/* Special levels */
@@ -8601,7 +8433,7 @@ void generate_cave(void)
if (!p_ptr->wild_mode)
{
/* Make the wilderness */
- wilderness_gen(0);
+ wilderness_gen();
}
/* Small wilderness mode */
@@ -8814,7 +8646,10 @@ void generate_cave(void)
}
/* Put the kept monsters -- DG */
- if (!p_ptr->wild_mode) replace_all_friends();
+ if (!p_ptr->wild_mode)
+ {
+ replace_all_friends();
+ }
/* Hack -- Clear used up fates */
for (i = 0; i < MAX_FATES; i++)
diff --git a/src/generate.hpp b/src/generate.hpp
new file mode 100644
index 00000000..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 f940e21a..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
@@ -88,7 +95,7 @@ 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.");
@@ -99,7 +106,7 @@ void follow_god(int god, bool_ silent)
/*
* Show religious info.
*/
-bool_ show_god_info(bool_ ext)
+bool_ show_god_info()
{
int pgod = p_ptr->pgod;
@@ -198,3 +205,8 @@ int find_god(cptr name)
}
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..fc2721ef 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.
@@ -32,102 +33,6 @@
/* #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 +52,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 +65,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(MACINTOSH) && !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
@@ -204,20 +89,12 @@
# 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)
+#if defined(MACINTOSH) && !defined(applec)
# define FILE_TYPE_TEXT 'TEXT'
# define FILE_TYPE_DATA 'DATA'
# define FILE_TYPE_SAVE 'SAVE'
@@ -227,48 +104,6 @@
#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 c1b17e1f..f7759668 100644
--- a/src/h-system.h
+++ b/src/h-system.h
@@ -25,16 +25,11 @@
# include <sys/types.h>
-# if defined(Pyramid) || 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,31 +42,22 @@
# 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
+#if !defined(MACINTOSH)
# include <memory.h>
-# endif
#endif
-#if !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>
@@ -83,32 +69,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
@@ -118,10 +84,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 145d4729..bcf013bb 100644
--- a/src/h-type.h
+++ b/src/h-type.h
@@ -72,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 */
diff --git a/src/help.c b/src/help.cc
index 7aae360e..29ebf033 100644
--- a/src/help.c
+++ b/src/help.cc
@@ -1,7 +1,3 @@
-/* File: help.c */
-
-/* Purpose: ingame help */
-
/*
* Copyright (c) 2001 DarkGod
* Copyright (c) 2012 Bardur Arantsson
@@ -11,7 +7,20 @@
* included in all such copies.
*/
-#include "angband.h"
+#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 19
@@ -316,7 +325,7 @@ static bool_ trigger_fountain(void *in, void *out) {
static bool_ trigger_found_object(void *in, void *out) {
hook_move_in *p = (hook_move_in *) in;
- return cave[p->y][p->x].o_idx != 0;
+ return !cave[p->y][p->x].o_idxs.empty();
}
static bool_ trigger_found_altar(void *in, void *out) {
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.c b/src/hiscore.cc
index 357026da..971b84cd 100644
--- a/src/hiscore.c
+++ b/src/hiscore.cc
@@ -1,8 +1,8 @@
-#include "hiscore.h"
+#include "hiscore.hpp"
-#include <assert.h>
+#include "util.hpp"
-#include "angband.h"
+#include <cassert>
int highscore_seek(int highscore_fd, int i)
{
diff --git a/src/hiscore.h b/src/hiscore.hpp
index 0eed91b4..0b1b713d 100644
--- a/src/hiscore.h
+++ b/src/hiscore.hpp
@@ -1,11 +1,11 @@
-#ifndef H_267bf1c1_eada_4b18_9558_d96330fa7258
-#define H_267bf1c1_eada_4b18_9558_d96330fa7258
+#pragma once
-#include "h-type.h"
+#include "h-basic.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+/**
+ * Maximum number of high scores in the high score file
+ */
+constexpr int MAX_HISCORES = 100;
/*
* Semi-Portable High Score List Entry (128 bytes) -- BEN
@@ -47,10 +47,10 @@ struct high_score
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 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 exit_bldg[4]; /* Can the player exit arena? Goal obtained? -KMW- */
+ char unused_4[4]; /* Kept for compatibility only */
char how[32]; /* Method of death (string) */
};
@@ -81,9 +81,3 @@ int highscore_where(int highscore_fd, high_score *score);
* best) or -1 on "failure"
*/
int highscore_add(int highscore_fd, high_score *score);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif
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/sglib.h b/src/include/sglib.h
deleted file mode 100644
index 1a4780fa..00000000
--- a/src/include/sglib.h
+++ /dev/null
@@ -1,1952 +0,0 @@
-/*
-
- This is SGLIB version 1.0.3
-
- (C) by Marian Vittek, Bratislava, http://www.xref-tech.com/sglib, 2003-5
-
- License Conditions: You can use a verbatim copy (including this
- copyright notice) of sglib freely in any project, commercial or not.
- You can also use derivative forms freely under terms of Open Source
- Software license or under terms of GNU Public License. If you need
- to use a derivative form in a commercial project, or you need sglib
- under any other license conditions, contact the author.
-
-
-
-*/
-
-
-#ifndef _SGLIB__h_
-#define _SGLIB__h_
-
-/* the assert is used exclusively to write unexpected error messages */
-#include <assert.h>
-
-
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-/* - LEVEL - 0 INTERFACE - */
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------------ STATIC ARRAYS ------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-/*
-
- Basic algorithms for sorting arrays. Multiple depending arrays can
- be rearranged using user defined 'elem_exchangers'
-
-*/
-
-/* HEAP - SORT (level 0) */
-
-#define SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator) {\
- SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-
-#define SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, elem_exchanger) {\
- int _k_;\
- for(_k_=(max)/2; _k_>=0; _k_--) {\
- SGLIB___ARRAY_HEAP_DOWN(type, a, _k_, max, comparator, elem_exchanger);\
- }\
- for(_k_=(max)-1; _k_>=0; _k_--) {\
- elem_exchanger(type, a, 0, _k_);\
- SGLIB___ARRAY_HEAP_DOWN(type, a, 0, _k_, comparator, elem_exchanger);\
- }\
-}
-
-#define SGLIB___ARRAY_HEAP_DOWN(type, a, ind, max, comparator, elem_exchanger) {\
- type _t_;\
- int _m_, _l_, _r_, _i_;\
- _i_ = (ind);\
- _m_ = _i_;\
- do {\
- _i_ = _m_; \
- _l_ = 2*_i_+1;\
- _r_ = _l_+1;\
- if (_l_ < (max)){\
- if (comparator(((a)[_m_]), ((a)[_l_])) < 0) _m_ = _l_;\
- if (_r_ < (max)) {\
- if (comparator(((a)[_m_]), ((a)[_r_])) < 0) _m_ = _r_;\
- }\
- }\
- if (_m_ != _i_) {\
- elem_exchanger(type, a, _i_, _m_);\
- }\
- } while (_m_ != _i_);\
-}
-
-
-/* QUICK - SORT (level 0) */
-
-#define SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator) {\
- SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-
-#define SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, elem_exchanger) {\
- int _i_, _j_, _p_, _stacki_, _start_, _end_;\
- /* can sort up to 2^64 elements */\
- int _startStack_[64]; \
- int _endStack_[64];\
- type _tmp_;\
- _startStack_[0] = 0;\
- _endStack_[0] = (max);\
- _stacki_ = 1;\
- while (_stacki_ > 0) {\
- _stacki_ --;\
- _start_ = _startStack_[_stacki_];\
- _end_ = _endStack_[_stacki_];\
- while (_end_ - _start_ > 2) {\
- _p_ = _start_;\
- _i_ = _start_ + 1;\
- _j_ = _end_ - 1;\
- while (_i_<_j_) {\
- for(; _i_<=_j_ && comparator(((a)[_i_]),((a)[_p_]))<=0; _i_++) ;\
- if (_i_ > _j_) {\
- /* all remaining elements lesseq than pivot */\
- elem_exchanger(type, a, _j_, _p_);\
- _i_ = _j_;\
- } else {\
- for(; _i_<=_j_ && comparator(((a)[_j_]),((a)[_p_]))>=0; _j_--) ;\
- if (_i_ > _j_) {\
- /* all remaining elements greater than pivot */\
- elem_exchanger(type, a, _j_, _p_);\
- _i_ = _j_;\
- } else if (_i_ < _j_) {\
- elem_exchanger(type, a, _i_, _j_);\
- if (_i_+2 < _j_) {_i_++; _j_--;}\
- else if (_i_+1 < _j_) _i_++;\
- }\
- }\
- }\
- /* O.K. i==j and pivot is on a[i] == a[j] */\
- /* handle recursive calls without recursion */\
- if (_i_-_start_ > 1 && _end_-_j_ > 1) {\
- /* two recursive calls, use array-stack */\
- if (_i_-_start_ < _end_-_j_-1) {\
- _startStack_[_stacki_] = _j_+1;\
- _endStack_[_stacki_] = _end_;\
- _stacki_ ++;\
- _end_ = _i_;\
- } else {\
- _startStack_[_stacki_] = _start_;\
- _endStack_[_stacki_] = _i_;\
- _stacki_ ++;\
- _start_ = _j_+1;\
- }\
- } else {\
- if (_i_-_start_ > 1) {\
- _end_ = _i_;\
- } else {\
- _start_ = _j_+1;\
- }\
- }\
- }\
- if (_end_ - _start_ == 2) {\
- if (comparator(((a)[_start_]),((a)[_end_-1])) > 0) {\
- elem_exchanger(type, a, _start_, _end_-1);\
- }\
- }\
- }\
-}
-
-/* BINARY SEARCH (level 0) */
-
-#define SGLIB_ARRAY_BINARY_SEARCH(type, a, start_index, end_index, key, comparator, found, result_index) {\
- int _kk_, _cc_, _ii_, _jj_, _ff_;\
- _ii_ = (start_index); \
- _jj_ = (end_index);\
- _ff_ = 0;\
- while (_ii_ <= _jj_ && _ff_==0) {\
- _kk_ = (_jj_+_ii_)/2;\
- _cc_ = comparator(((a)[_kk_]), (key));\
- if (_cc_ == 0) {\
- (result_index) = _kk_; \
- _ff_ = 1;\
- } else if (_cc_ < 0) {\
- _ii_ = _kk_+1;\
- } else {\
- _jj_ = _kk_-1;\
- }\
- }\
- if (_ff_ == 0) {\
- /* not found, but set its resulting place in the array */\
- (result_index) = _jj_+1;\
- }\
- (found) = _ff_;\
-}
-
-/* -------------------------------- queue (in an array) ------------------ */
-/* queue is a quadruple (a,i,j,dim) such that: */
-/* a is the array storing values */
-/* i is the index of the first used element in the array */
-/* j is the index of the first free element in the array */
-/* dim is the size of the array a */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-#define SGLIB_QUEUE_INIT(type, a, i, j) { i = j = 0; }
-#define SGLIB_QUEUE_IS_EMPTY(type, a, i, j) ((i)==(j))
-#define SGLIB_QUEUE_IS_FULL(type, a, i, j, dim) ((i)==((j)+1)%(dim))
-#define SGLIB_QUEUE_FIRST_ELEMENT(type, a, i, j) (a[i])
-#define SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim) {\
- if (SGLIB_QUEUE_IS_FULL(type, a, i, j, dim)) assert(0 && "the queue is full");\
- (j) = ((j)+1) % (dim);\
-}
-#define SGLIB_QUEUE_ADD(type, a, elem, i, j, dim) {\
- a[j] = (elem);\
- SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim);\
-}
-#define SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim) {\
- if (SGLIB_QUEUE_IS_EMPTY(type, a, i, j)) assert(0 && "the queue is empty");\
- (i) = ((i)+1) % (dim);\
-}
-#define SGLIB_QUEUE_DELETE(type, a, i, j, dim) {\
- SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim);\
-}
-
-/* ----------------- priority queue (heap) (in an array) -------------------- */
-/* heap is a triple (a,i,dim) such that: */
-/* a is the array storing values */
-/* i is the index of the first free element in the array */
-/* dim is the size of the array a */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-#define SGLIB_HEAP_INIT(type, a, i) { i = 0; }
-#define SGLIB_HEAP_IS_EMPTY(type, a, i) ((i)==0)
-#define SGLIB_HEAP_IS_FULL(type, a, i, dim) ((i)==(dim))
-#define SGLIB_HEAP_FIRST_ELEMENT(type, a, i) (a[0])
-#define SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, elem_exchanger) {\
- int _i_;\
- if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\
- _i_ = (i)++;\
- while (_i_ > 0 && comparator(a[_i_/2], a[_i_]) < 0) {\
- elem_exchanger(type, a, (_i_/2), _i_);\
- _i_ = _i_/2;\
- }\
-}
-#define SGLIB_HEAP_ADD(type, a, elem, i, dim, comparator) {\
- if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\
- a[i] = (elem);\
- SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-#define SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, elem_exchanger) {\
- if (SGLIB_HEAP_IS_EMPTY(type, a, i)) assert(0 && "the heap is empty");\
- (i)--;\
- a[0] = a[i];\
- SGLIB___ARRAY_HEAP_DOWN(type, a, 0, i, comparator, elem_exchanger);\
-}
-#define SGLIB_HEAP_DELETE(type, a, i, dim, comparator) {\
- SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-
-
-/* ----------------- hashed table of pointers (in an array) -------------------- */
-
-/*
-
- This hashed table is storing pointers to objects (not containers).
- In this table there is a one-to-one mapping between 'objects' stored
- in the table and indexes where they are placed. Each index is
- pointing to exactly one 'object' and each 'object' stored in the
- table occurs on exactly one index. Once an object is stored in the
- table, it can be represented via its index.
-
- In case of collision while adding an object the index shifted
- by SGLIB_HASH_TAB_SHIFT_CONSTANT (constant can be redefined)
-
- You can NOT delete an element from such hash table. The only
- justification (I can see) for this data structure is an exchange
- file format, having an index table at the beginning and then
- refering objects via indexes.
-
- !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!!
-
-*/
-
-#define SGLIB_HASH_TAB_INIT(type, table, dim) {\
- int _i_;\
- for(_i_ = 0; _i_ < (dim); _i_++) (table)[_i_] = NULL;\
-}
-
-#define SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, member){\
- unsigned _pos_;\
- type *_elem_;\
- SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, _pos_, _elem_);\
- (member) = (table)[_pos_];\
- if (_elem_ == NULL) {\
- if ((table)[_pos_] != NULL) assert(0 && "the hash table is full");\
- (table)[_pos_] = (elem);\
- }\
-}
-
-#define SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, resultIndex, resultMember) {\
- unsigned _i_;\
- int _count_;\
- type *_e_;\
- _count = 0;\
- _i_ = hash_function(elem);\
- _i_ %= (dim);\
- while ((_e_=(table)[_i_])!=NULL && comparator(_e_, (elem))!=0 && _count_<(dim)) {\
- _count_ ++;\
- _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\
- }\
- (resultIndex) = _i_;\
- if (_count_ < (dim)) (resultMember) = _e_;\
- else (resultMember) = NULL;\
-}
-
-#define SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, resultIndex) {\
- unsigned _i_;\
- int _c_;\
- type *_e_;\
- _count = 0;\
- _i_ = hash_function(elem);\
- _i_ %= (dim);\
- while ((_e_=(table)[_i_])!=NULL && _e_!=(elem) && _c_<(dim)) {\
- _c_ ++;\
- _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\
- }\
- if (_e_==(elem)) (resultIndex) = _i_;\
- else (resultIndex) = -1;\
-}
-
-#define SGLIB_HASH_TAB_MAP_ON_ELEMENTS(type, table, dim, iteratedIndex, iteratedVariable, command) {\
- unsigned iteratedIndex;\
- type *iteratedVariable;\
- for(iteratedIndex=0; iteratedIndex < (dim); iteratedIndex++) {\
- iteratedVariable = (table)[iteratedIndex];\
- if (iteratedVariable != NULL) {command;}\
- }\
-}
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-/* ------------------------------------ lists (level 0) --------------------- */
-
-#define SGLIB_LIST_ADD(type, list, elem, next) {\
- (elem)->next = (list);\
- (list) = (elem);\
-}
-
-#define SGLIB_LIST_CONCAT(type, first, second, next) {\
- if ((first)==NULL) {\
- (first) = (second);\
- } else {\
- type *_p_;\
- for(_p_ = (first); _p_->next!=NULL; _p_=_p_->next) ;\
- _p_->next = (second);\
- }\
-}
-
-#define SGLIB_LIST_DELETE(type, list, elem, next) {\
- type **_p_;\
- for(_p_ = &(list); *_p_!=NULL && *_p_!=(elem); _p_= &(*_p_)->next) ;\
- assert(*_p_!=NULL && "element is not member of the container, use DELETE_IF_MEMBER instead"!=NULL);\
- *_p_ = (*_p_)->next;\
-}
-
-#define SGLIB_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\
- (member) = _p_;\
- if (_p_ == NULL) {\
- SGLIB_LIST_ADD(type, list, elem, next);\
- }\
-}
-
-#define SGLIB_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\
- type **_p_;\
- for(_p_ = &(list); *_p_!=NULL && comparator((*_p_), (elem)) != 0; _p_= &(*_p_)->next) ;\
- (member) = *_p_;\
- if (*_p_ != NULL) {\
- *_p_ = (*_p_)->next;\
- }\
-}
-
-#define SGLIB_LIST_IS_MEMBER(type, list, elem, next, result) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && _p_ != (elem); _p_= _p_->next) ;\
- (result) = (_p_!=NULL);\
-}
-
-#define SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\
- (member) = _p_;\
-}
-
-#define SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\
- type *_ne_;\
- type *iteratedVariable;\
- (iteratedVariable) = (list); \
- while ((iteratedVariable)!=NULL) {\
- _ne_ = (iteratedVariable)->next;\
- {command;};\
- (iteratedVariable) = _ne_;\
- }\
-}
-
-#define SGLIB_LIST_LEN(type, list, next, result) {\
- type *_ce_;\
- (result) = 0;\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, list, _ce_, next, (result)++);\
-}
-
-#define SGLIB_LIST_REVERSE(type, list, next) {\
- type *_list_,*_tmp_,*_res_;\
- _list_ = (list);\
- _res_ = NULL;\
- while (_list_!=NULL) {\
- _tmp_ = _list_->next; _list_->next = _res_;\
- _res_ = _list_; _list_ = _tmp_;\
- }\
- (list) = _res_;\
-}
-
-#define SGLIB_LIST_SORT(type, list, comparator, next) {\
- /* a non-recursive merge sort on lists */\
- type *_r_;\
- type *_a_, *_b_, *_todo_, *_t_, **_restail_;\
- int _i_, _n_, _contFlag_;\
- _r_ = (list);\
- _contFlag_ = 1;\
- for(_n_ = 1; _contFlag_; _n_ = _n_+_n_) {\
- _todo_ = _r_; _r_ = NULL; _restail_ = &_r_; _contFlag_ =0;\
- while (_todo_!=NULL) {\
- _a_ = _todo_;\
- for(_i_ = 1, _t_ = _a_; _i_ < _n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\
- if (_t_ ==NULL) {\
- *_restail_ = _a_;\
- break;\
- }\
- _b_ = _t_->next; _t_->next=NULL;\
- for(_i_ =1, _t_ = _b_; _i_<_n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\
- if (_t_ ==NULL) {\
- _todo_ =NULL;\
- } else {\
- _todo_ = _t_->next; _t_->next=NULL;\
- }\
- /* merge */\
- while (_a_!=NULL && _b_!=NULL) {\
- if (comparator(_a_, _b_) < 0) {\
- *_restail_ = _a_; _restail_ = &(_a_->next); _a_ = _a_->next;\
- } else {\
- *_restail_ = _b_; _restail_ = &(_b_->next); _b_ = _b_->next;\
- }\
- }\
- if (_a_!=NULL) *_restail_ = _a_;\
- else *_restail_ = _b_;\
- while (*_restail_!=NULL) _restail_ = &((*_restail_)->next);\
- _contFlag_ =1;\
- }\
- }\
- (list) = _r_;\
-}
-
-/* --------------------------------- sorted list (level 0) --------------------- */
-/*
- All operations suppose that the list is sorted and they preserve
- this property.
-*/
-
-
-#define SGLIB_SORTED_LIST_ADD(type, list, elem, comparator, next) {\
- type **_e_;\
- int _cmpres_;\
- SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmpres_, _e_);\
- (elem)->next = *_e_;\
- *_e_ = (elem);\
-}
-
-#define SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\
- type **_e_;\
- int _cmp_res_;\
- SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\
- if (_cmp_res_ != 0) {\
- (elem)->next = *_e_;\
- *_e_ = (elem);\
- (member) = NULL;\
- } else {\
- (member) = *_e_;\
- }\
-}
-
-#define SGLIB_SORTED_LIST_DELETE(type, list, elem, next) {\
- SGLIB_LIST_DELETE(type, list, elem, next);\
-}
-
-#define SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\
- type **_e_;\
- int _cmp_res_;\
- SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\
- if (_cmp_res_ == 0) {\
- (member) = *_e_;\
- *_e_ = (*_e_)->next;\
- } else {\
- (member) = NULL;\
- }\
-}
-
-#define SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\
- type *_p_;\
- int _cmpres_ = 1;\
- for(_p_ = (list); _p_!=NULL && (_cmpres_=comparator(_p_, (elem))) < 0; _p_=_p_->next) ;\
- if (_cmpres_ != 0) (member) = NULL;\
- else (member) = _p_;\
-}
-
-#define SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) < 0; _p_=_p_->next) ;\
- while (_p_ != NULL && _p_ != (elem) && comparator(_p_, (elem)) == 0) _p_=_p_->next;\
- (result) = (_p_ == (elem));\
-}
-
-#define SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, comparator_result, member_ptr) {\
- (comparator_result) = -1;\
- for((member_ptr) = &(list); \
- *(member_ptr)!=NULL && ((comparator_result)=comparator((*member_ptr), (elem))) < 0; \
- (member_ptr) = &(*(member_ptr))->next) ;\
-}
-
-#define SGLIB_SORTED_LIST_LEN(type, list, next, result) {\
- SGLIB_LIST_LEN(type, list, next, result);\
-}
-
-#define SGLIB_SORTED_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command);\
-}
-
-
-/* ------------------------------- double linked list (level 0) ------------------------- */
-/*
- Lists with back pointer to previous element. Those lists implements deletion
- of an element in a constant time.
-*/
-
-#define SGLIB___DL_LIST_CREATE_SINGLETON(type, list, elem, previous, next) {\
- (list) = (elem);\
- (list)->next = (list)->previous = NULL;\
-}
-
-#define SGLIB_DL_LIST_ADD_AFTER(type, place, elem, previous, next) {\
- if ((place) == NULL) {\
- SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\
- } else {\
- (elem)->next = (place)->next;\
- (elem)->previous = (place);\
- (place)->next = (elem);\
- if ((elem)->next != NULL) (elem)->next->previous = (elem);\
- }\
-}
-
-#define SGLIB_DL_LIST_ADD_BEFORE(type, place, elem, previous, next) {\
- if ((place) == NULL) {\
- SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\
- } else {\
- (elem)->next = (place);\
- (elem)->previous = (place)->previous;\
- (place)->previous = (elem);\
- if ((elem)->previous != NULL) (elem)->previous->next = (elem);\
- }\
-}
-
-#define SGLIB_DL_LIST_ADD(type, list, elem, previous, next) {\
- SGLIB_DL_LIST_ADD_BEFORE(type, list, elem, previous, next)\
-}
-
-#define SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, the_add_operation) {\
- type *_dlp_;\
- for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\
- if (_dlp_ == NULL && (list) != NULL) {\
- for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\
- }\
- (member) = _dlp_;\
- if (_dlp_ == NULL) {\
- the_add_operation(type, list, elem, previous, next);\
- }\
-}
-
-#define SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
- SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_BEFORE);\
-}
-
-#define SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
- SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_AFTER);\
-}
-
-#define SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
- SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD);\
-}
-
-#define SGLIB_DL_LIST_CONCAT(type, first, second, previous, next) {\
- if ((first)==NULL) {\
- (first) = (second);\
- } else if ((second)!=NULL) {\
- type *_dlp_;\
- for(_dlp_ = (first); _dlp_->next!=NULL; _dlp_=_dlp_->next) ;\
- SGLIB_DL_LIST_ADD_AFTER(type, _dlp_, second, previous, next);\
- }\
-}
-
-#define SGLIB_DL_LIST_DELETE(type, list, elem, previous, next) {\
- type *_l_;\
- _l_ = (list);\
- if (_l_ == (elem)) {\
- if ((elem)->previous != NULL) _l_ = (elem)->previous;\
- else _l_ = (elem)->next;\
- }\
- if ((elem)->next != NULL) (elem)->next->previous = (elem)->previous;\
- if ((elem)->previous != NULL) (elem)->previous->next = (elem)->next;\
- (list) = _l_;\
-}
-
-#define SGLIB_DL_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, previous, next, member) {\
- type *_dlp_;\
- for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\
- if (_dlp_ == NULL && (list) != NULL) {\
- for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\
- }\
- (member) = _dlp_;\
- if (_dlp_ != NULL) {\
- SGLIB_DL_LIST_DELETE(type, list, _dlp_, previous, next);\
- }\
-}
-
-#define SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result) {\
- type *_dlp_;\
- SGLIB_LIST_IS_MEMBER(type, list, elem, previous, result);\
- if (result == 0 && (list) != NULL) {\
- _dlp_ = (list)->next;\
- SGLIB_LIST_IS_MEMBER(type, _dlp_, elem, next, result);\
- }\
-}
-
-#define SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, member) {\
- type *_dlp_;\
- SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, previous, member);\
- if ((member) == NULL && (list) != NULL) {\
- _dlp_ = (list)->next;\
- SGLIB_LIST_FIND_MEMBER(type, _dlp_, elem, comparator, next, member);\
- }\
-}
-
-#define SGLIB_DL_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, next, command) {\
- type *_dl_;\
- type *iteratedVariable;\
- if ((list)!=NULL) {\
- _dl_ = (list)->next;\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, command);\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, _dl_, iteratedVariable, next, command);\
- }\
-}
-
-#define SGLIB_DL_LIST_SORT(type, list, comparator, previous, next) {\
- type *_dll_, *_dlp_, *_dlt_;\
- _dll_ = (list);\
- if (_dll_ != NULL) {\
- for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\
- SGLIB_LIST_SORT(type, _dll_, comparator, next);\
- SGLIB___DL_LIST_CREATE_FROM_LIST(type, _dll_, previous, next);\
- (list) = _dll_;\
- }\
-}
-
-#define SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result) {\
- type *_dll_;\
- _dll_ = (list);\
- if (_dll_ != NULL) {\
- for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\
- }\
- (result) = _dll_;\
-}
-
-#define SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result) {\
- type *_dll_;\
- _dll_ = (list);\
- if (_dll_ != NULL) {\
- for(; _dll_->next!=NULL; _dll_=_dll_->next) ;\
- }\
- (result) = _dll_;\
-}
-
-#define SGLIB_DL_LIST_LEN(type, list, previous, next, result) {\
- type *_dl_;\
- int _r1_, _r2_;\
- if ((list)==NULL) {\
- (result) = 0;\
- } else {\
- SGLIB_LIST_LEN(type, list, previous, _r1_);\
- _dl_ = (list)->next;\
- SGLIB_LIST_LEN(type, _dl_, next, _r2_);\
- (result) = _r1_ + _r2_;\
- }\
-}
-
-#define SGLIB_DL_LIST_REVERSE(type, list, previous, next) {\
- type *_list_,*_nlist_,*_dlp_,*_dln_;\
- _list_ = (list);\
- if (_list_!=NULL) {\
- _nlist_ = _list_->next;\
- while (_list_!=NULL) {\
- _dln_ = _list_->next; \
- _dlp_ = _list_->previous; \
- _list_->next = _dlp_;\
- _list_->previous = _dln_;\
- _list_ = _dlp_;\
- }\
- while (_nlist_!=NULL) {\
- _dln_ = _nlist_->next; \
- _dlp_ = _nlist_->previous; \
- _nlist_->next = _dlp_;\
- _nlist_->previous = _dln_;\
- _nlist_ = _dln_;\
- }\
- }\
-}
-
-#define SGLIB___DL_LIST_CREATE_FROM_LIST(type, list, previous, next) {\
- type *_dlp_, *_dlt_;\
- _dlp_ = NULL;\
- for(_dlt_ = (list); _dlt_!=NULL; _dlt_ = _dlt_->next) {\
- _dlt_->previous = _dlp_;\
- _dlp_ = _dlt_;\
- }\
-}
-
-
-/* ------------------------------- binary tree traversal (level 0) -------------------- */
-
-
-#define SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, iteratedVariable, order, left, right, command) {\
- /* this is non-recursive implementation of tree traversal */\
- /* it maintains the path to the current node in the array '_path_' */\
- /* the _path_[0] contains the root of the tree; */\
- /* the _path_[_pathi_] contains the _current_element_ */\
- /* the macro does not use the _current_element_ after execution of command */\
- /* command can destroy it, it can free the element for example */\
- type *_path_[SGLIB_MAX_TREE_DEEP];\
- type *_right_[SGLIB_MAX_TREE_DEEP];\
- char _pass_[SGLIB_MAX_TREE_DEEP];\
- type *_cn_;\
- int _pathi_;\
- type *iteratedVariable;\
- _cn_ = (tree);\
- _pathi_ = 0;\
- while (_cn_!=NULL) {\
- /* push down to leftmost innermost element */\
- while(_cn_!=NULL) {\
- _path_[_pathi_] = _cn_;\
- _right_[_pathi_] = _cn_->right;\
- _pass_[_pathi_] = 0;\
- _cn_ = _cn_->left;\
- if (order == 0) {\
- iteratedVariable = _path_[_pathi_];\
- {command;}\
- }\
- _pathi_ ++;\
- if (_pathi_ >= SGLIB_MAX_TREE_DEEP) assert(0 && "the binary_tree is too deep");\
- }\
- do {\
- _pathi_ --;\
- if ((order==1 && _pass_[_pathi_] == 0)\
- || (order == 2 && (_pass_[_pathi_] == 1 || _right_[_pathi_]==NULL))) {\
- iteratedVariable = _path_[_pathi_];\
- {command;}\
- }\
- _pass_[_pathi_] ++;\
- } while (_pathi_>0 && _right_[_pathi_]==NULL) ;\
- _cn_ = _right_[_pathi_];\
- _right_[_pathi_] = NULL;\
- _pathi_ ++;\
- }\
-}
-
-#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, left, right, command) {\
- SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 1, left, right, command);\
-}
-
-#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_PREORDER(type, tree, _current_element_, left, right, command) {\
- SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 0, left, right, command);\
-}
-
-#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_POSTORDER(type, tree, _current_element_, left, right, command) {\
- SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 2, left, right, command);\
-}
-
-#define SGLIB___BIN_TREE_FIND_MEMBER(type, tree, elem, left, right, comparator, res) {\
- type *_s_;\
- int _c_;\
- _s_ = (tree);\
- while (_s_!=NULL) {\
- _c_ = comparator((elem), _s_);\
- if (_c_ < 0) _s_ = _s_->left;\
- else if (_c_ > 0) _s_ = _s_->right;\
- else break;\
- }\
- (res) = _s_;\
-}
-
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-/* - LEVEL - 1 INTERFACE - */
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------------ STATIC ARRAYS ------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-/* ----------------------------- array sorting (level 1) ---------------------- */
-
-#define SGLIB_DEFINE_ARRAY_SORTING_PROTOTYPES(type, comparator) \
- extern void sglib_##type##_array_quick_sort(type *a, int max);\
- extern void sglib_##type##_array_heap_sort(type *a, int max);\
-
-
-#define SGLIB_DEFINE_ARRAY_SORTING_FUNCTIONS(type, comparator) \
- void sglib_##type##_array_quick_sort(type *a, int max) {\
- SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator);\
- }\
- void sglib_##type##_array_heap_sort(type *a, int max) {\
- SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator);\
- }\
-
-
-/* ----------------------------- array queue (level 1) ------------------- */
-/* sglib's queue is stored in a fixed sized array */
-/* queue_type MUST be a structure containing fields: */
-/* afield is the array storing elem_type */
-/* ifield is the index of the first element in the queue */
-/* jfield is the index of the first free element after the queue */
-/* dim is the size of the array afield */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-
-#define SGLIB_DEFINE_QUEUE_PROTOTYPES(queue_type, elem_type, afield, ifield, jfield, dim) \
- extern void sglib_##queue_type##_init(queue_type *q); \
- extern int sglib_##queue_type##_is_empty(queue_type *q); \
- extern int sglib_##queue_type##_is_full(queue_type *q); \
- extern elem_type sglib_##queue_type##_first_element(queue_type *q); \
- extern elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q); \
- extern void sglib_##queue_type##_add_next(queue_type *q); \
- extern void sglib_##queue_type##_add(queue_type *q, elem_type elem); \
- extern void sglib_##queue_type##_delete_first(queue_type *q); \
- extern void sglib_##queue_type##_delete(queue_type *q);
-
-
-#define SGLIB_DEFINE_QUEUE_FUNCTIONS(queue_type, elem_type, afield, ifield, jfield, dim) \
- void sglib_##queue_type##_init(queue_type *q) {\
- SGLIB_QUEUE_INIT(elem_type, q->afield, q->ifield, q->jfield);\
- }\
- int sglib_##queue_type##_is_empty(queue_type *q) {\
- return(SGLIB_QUEUE_IS_EMPTY(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- int sglib_##queue_type##_is_full(queue_type *q) {\
- return(SGLIB_QUEUE_IS_FULL(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- elem_type sglib_##queue_type##_first_element(queue_type *q) {\
- return(SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q) {\
- return(& SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- void sglib_##queue_type##_add_next(queue_type *q) {\
- SGLIB_QUEUE_ADD_NEXT(elem_type, q->afield, q->ifield, q->jfield, dim);\
- }\
- void sglib_##queue_type##_add(queue_type *q, elem_type elem) {\
- SGLIB_QUEUE_ADD(elem_type, q->afield, elem, q->ifield, q->jfield, dim);\
- }\
- void sglib_##queue_type##_delete_first(queue_type *q) {\
- SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\
- }\
- void sglib_##queue_type##_delete(queue_type *q) {\
- SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\
- }
-
-
-/* ------------------------ array heap (level 1) ------------------------- */
-/* sglib's heap is a priority queue implemented in a fixed sized array */
-/* heap_type MUST be a structure containing fields: */
-/* afield is the array of size dim storing elem_type */
-/* ifield is the index of the first free element after the queue */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-
-#define SGLIB_DEFINE_HEAP_PROTOTYPES(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \
- extern void sglib_##heap_type##_init(heap_type *q); \
- extern int sglib_##heap_type##_is_empty(heap_type *q); \
- extern int sglib_##heap_type##_is_full(heap_type *q); \
- extern elem_type sglib_##heap_type##_first_element(heap_type *q); \
- extern elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q); \
- extern void sglib_##heap_type##_add_next(heap_type *q); \
- extern void sglib_##heap_type##_add(heap_type *q, elem_type elem); \
- extern void sglib_##heap_type##_delete_first(heap_type *q); \
- extern void sglib_##heap_type##_delete(heap_type *q)
-
-#define SGLIB_DEFINE_HEAP_FUNCTIONS(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \
- void sglib_##heap_type##_init(heap_type *q) {\
- SGLIB_HEAP_INIT(elem_type, q->afield, q->ifield);\
- }\
- int sglib_##heap_type##_is_empty(heap_type *q) {\
- return(SGLIB_HEAP_IS_EMPTY(elem_type, q->afield, q->ifield));\
- }\
- int sglib_##heap_type##_is_full(heap_type *q) {\
- return(SGLIB_HEAP_IS_FULL(elem_type, q->afield, q->ifield));\
- }\
- elem_type sglib_##heap_type##_first_element(heap_type *q) {\
- return(SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\
- }\
- elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q) {\
- return(& SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\
- }\
- void sglib_##heap_type##_add_next(heap_type *q) {\
- SGLIB_HEAP_ADD_NEXT(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
- }\
- void sglib_##heap_type##_add(heap_type *q, elem_type elem) {\
- SGLIB_HEAP_ADD(elem_type, q->afield, elem, q->ifield, dim, comparator, elem_exchanger);\
- }\
- void sglib_##heap_type##_delete_first(heap_type *q) {\
- SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
- }\
- void sglib_##heap_type##_delete(heap_type *q) {\
- SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
- }
-
-
-/* ------------------------ hashed table (level 1) ------------------------- */
-/*
-
- sglib's hash table is an array storing directly pointers to objects (not containers).
- In this table there is a one-to-one mapping between 'objects' stored
- in the table and indexes where they are placed. Each index is
- pointing to exactly one 'object' and each 'object' stored in the
- table occurs on exactly one index. Once an object is stored in the
- table, it can be represented via its index.
-
- type - is the type of elements
- dim - is the size of the hash array
- hash_function - is a hashing function mapping type* to unsigned
- comparator - is a comparator on elements
-
- !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!!
-*/
-
-#define SGLIB_DEFINE_HASHED_TABLE_PROTOTYPES(type, dim, hash_function, comparator) \
- struct sglib_hashed_##type##_iterator {\
- int currentIndex;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_hashed_##type##_init(type *table[dim]);\
- extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\
- extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\
- extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\
- extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \
- extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \
- extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it);
-
-#define SGLIB_DEFINE_HASHED_TABLE_FUNCTIONS(type, dim, hash_function, comparator) \
- struct sglib_hashed_##type##_iterator {\
- int currentIndex;\
- type **table;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- void sglib_hashed_##type##_init(type *table[dim]) {\
- SGLIB_HASH_TAB_INIT(type, table, dim);\
- }\
- int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\
- SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, *member);\
- }\
- int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\
- int ind;\
- SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, ind);\
- return(ind != -1);\
- }\
- type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\
- type *mmb;\
- int ind;\
- SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, ind, mmb);\
- return(mmb);\
- }\
- type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\
- int i;\
- it->table = table;\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- for(i=0; i<(dim) && table[i]==NULL; i++) ;\
- it->currentIndex = i;\
- if (i<(dim)) return(table[i]);\
- return(NULL);\
- }\
- type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\
- sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL);\
- }\
- type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\
- return(table[it->currentIndex]);\
- }\
- type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\
- i=it->currentIndex;\
- if (i<(dim)) {\
- for(i++; i<(dim) && table[i]==NULL; i++) ;\
- }\
- it->currentIndex = i;\
- if (i<(dim)) return(table[i]);\
- return(NULL);\
- }
-
-
-/* ------------------- hashed container (only for level 1) -------------------- */
-/*
- hashed container is a table of given fixed size containing another
- (dynamic) base container in each cell. Once an object should be
- inserted into the hashed container, a hash function is used to
- determine the cell where the object belongs and the object is
- inserted into the base container stored in this cell. Usually the
- base container is simply a list or a sorted list, but it can be a
- red-black tree as well.
-
- parameters:
- type - the type of the container stored in each cell.
- dim - the size of the hashed array
- hash_function - the hashing function hashing 'type *' to unsigned.
-
-*/
-
-#define SGLIB_DEFINE_HASHED_CONTAINER_PROTOTYPES(type, dim, hash_function) \
- struct sglib_hashed_##type##_iterator {\
- struct sglib_##type##_iterator containerIt;\
- type **table;\
- int currentIndex;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_hashed_##type##_init(type *table[dim]);\
- extern void sglib_hashed_##type##_add(type *table[dim], type *elem);\
- extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\
- extern void sglib_hashed_##type##_delete(type *table[dim], type *elem);\
- extern int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb);\
- extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\
- extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\
- extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \
- extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \
- extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it);
-
-#define SGLIB_DEFINE_HASHED_CONTAINER_FUNCTIONS(type, dim, hash_function) \
- /*extern unsigned hash_function(type *elem);*/\
- void sglib_hashed_##type##_init(type *table[dim]) {\
- unsigned i;\
- for(i=0; i<(dim); i++) table[i] = NULL;\
- }\
- void sglib_hashed_##type##_add(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- sglib_##type##_add(&(table)[i], elem);\
- }\
- int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_add_if_not_member(&(table)[i], elem, member));\
- }\
- void sglib_hashed_##type##_delete(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- sglib_##type##_delete(&(table)[i], elem);\
- }\
- int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_delete_if_member(&(table)[i], elem, memb));\
- }\
- int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_is_member((table)[i], elem));\
- }\
- type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_find_member((table)[i], elem));\
- }\
- type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\
- type *e;\
- it->table = table;\
- it->currentIndex = 0;\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- e = sglib_##type##_it_init_on_equal(&it->containerIt, table[it->currentIndex], it->subcomparator, it->equalto);\
- if (e==NULL) e = sglib_hashed_##type##_it_next(it);\
- return(e);\
- }\
- type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\
- return(sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL));\
- }\
- type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\
- return(sglib_##type##_it_current(&it->containerIt));\
- }\
- type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\
- type *e;\
- e = sglib_##type##_it_next(&it->containerIt);\
- while (e==NULL && (++(it->currentIndex))<(dim)) {\
- e = sglib_##type##_it_init_on_equal(&it->containerIt, it->table[it->currentIndex], it->subcomparator, it->equalto);\
- }\
- return(e);\
- }
-
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-
-/* ------------------------------------ list (level 1) -------------------------------- */
-
-#define SGLIB_DEFINE_LIST_PROTOTYPES(type, comparator, next) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- type *nextelem;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_##type##_add(type **list, type *elem);\
- extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
- extern void sglib_##type##_concat(type **first, type *second);\
- extern void sglib_##type##_delete(type **list, type *elem);\
- extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_is_member(type *list, type *elem);\
- extern type *sglib_##type##_find_member(type *list, type *elem);\
- extern void sglib_##type##_sort(type **list);\
- extern int sglib_##type##_len(type *list);\
- extern void sglib_##type##_reverse(type **list);\
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
-
-#define SGLIB_DEFINE_LIST_FUNCTIONS(type, comparator, next) \
- int sglib_##type##_is_member(type *list, type *elem) {\
- int result;\
- SGLIB_LIST_IS_MEMBER(type, list, elem, next, result);\
- return(result);\
- }\
- type *sglib_##type##_find_member(type *list, type *elem) {\
- type *result;\
- SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\
- return(result);\
- }\
- int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member==NULL);\
- }\
- void sglib_##type##_add(type **list, type *elem) {\
- SGLIB_LIST_ADD(type, *list, elem, next);\
- }\
- void sglib_##type##_concat(type **first, type *second) {\
- SGLIB_LIST_CONCAT(type, *first, second, next);\
- }\
- void sglib_##type##_delete(type **list, type *elem) {\
- SGLIB_LIST_DELETE(type, *list, elem, next);\
- }\
- int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
- SGLIB_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member!=NULL);\
- }\
- void sglib_##type##_sort(type **list) { \
- SGLIB_LIST_SORT(type, *list, comparator, next);\
- }\
- int sglib_##type##_len(type *list) {\
- int res;\
- SGLIB_LIST_LEN(type, list, next, res);\
- return(res);\
- }\
- void sglib_##type##_reverse(type **list) {\
- SGLIB_LIST_REVERSE(type, *list, next);\
- }\
- \
- type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- it->nextelem = list;\
- return(sglib_##type##_it_next(it));\
- }\
- type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
- return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
- }\
- type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
- }\
- type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- type *ce, *eq;\
- int (*scp)(type *, type *);\
- ce = it->nextelem;\
- it->nextelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\
- }\
- it->currentelem = ce;\
- if (ce != NULL) it->nextelem = ce->next;\
- return(ce);\
- }
-
-/* ----------------------------- sorted list (level 1) ----------------------------------- */
-
-
-#define SGLIB_DEFINE_SORTED_LIST_PROTOTYPES(type, comparator, next) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- type *nextelem;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_##type##_add(type **list, type *elem);\
- extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
- extern void sglib_##type##_delete(type **list, type *elem);\
- extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_is_member(type *list, type *elem);\
- extern type *sglib_##type##_find_member(type *list, type *elem);\
- extern int sglib_##type##_len(type *list);\
- extern void sglib_##type##_sort(type **list);\
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
-
-#define SGLIB_DEFINE_SORTED_LIST_FUNCTIONS(type, comparator, next) \
- int sglib_##type##_is_member(type *list, type *elem) {\
- int result;\
- SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result);\
- return(result);\
- }\
- type *sglib_##type##_find_member(type *list, type *elem) {\
- type *result;\
- SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\
- return(result);\
- }\
- int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member==NULL);\
- }\
- void sglib_##type##_add(type **list, type *elem) {\
- SGLIB_SORTED_LIST_ADD(type, *list, elem, comparator, next);\
- }\
- void sglib_##type##_delete(type **list, type *elem) {\
- SGLIB_SORTED_LIST_DELETE(type, *list, elem, next);\
- }\
- int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
- SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member!=NULL);\
- }\
- int sglib_##type##_len(type *list) {\
- int res;\
- SGLIB_SORTED_LIST_LEN(type, list, next, res);\
- return(res);\
- }\
- void sglib_##type##_sort(type **list) { \
- SGLIB_LIST_SORT(type, *list, comparator, next);\
- }\
- \
- type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- it->nextelem = list;\
- return(sglib_##type##_it_next(it));\
- }\
- type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
- return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
- }\
- type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
- }\
- type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- type *ce, *eq;\
- int (*scp)(type *, type *);\
- int c;\
- ce = it->nextelem;\
- it->nextelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && (c=scp(ce, eq)) < 0) ce = ce->next;\
- if (ce != NULL && c > 0) ce = NULL;\
- }\
- it->currentelem = ce;\
- if (ce != NULL) it->nextelem = ce->next;\
- return(ce);\
- }
-
-
-/* ----------------------------- double linked list (level 1) ------------------------------ */
-
-
-#define SGLIB_DEFINE_DL_LIST_PROTOTYPES(type, comparator, previous, next) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- type *prevelem;\
- type *nextelem;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_##type##_add(type **list, type *elem);\
- extern void sglib_##type##_add_before(type **list, type *elem);\
- extern void sglib_##type##_add_after(type **list, type *elem);\
- extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member);\
- extern void sglib_##type##_concat(type **first, type *second);\
- extern void sglib_##type##_delete(type **list, type *elem);\
- extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_is_member(type *list, type *elem);\
- extern type *sglib_##type##_find_member(type *list, type *elem);\
- extern type *sglib_##type##_get_first(type *list);\
- extern type *sglib_##type##_get_last(type *list);\
- extern void sglib_##type##_sort(type **list);\
- extern int sglib_##type##_len(type *list);\
- extern void sglib_##type##_reverse(type **list);\
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
-
-#define SGLIB_DEFINE_DL_LIST_FUNCTIONS(type, comparator, previous, next) \
- void sglib_##type##_add(type **list, type *elem) {\
- SGLIB_DL_LIST_ADD(type, *list, elem, previous, next);\
- }\
- void sglib_##type##_add_after(type **list, type *elem) {\
- SGLIB_DL_LIST_ADD_AFTER(type, *list, elem, previous, next);\
- }\
- void sglib_##type##_add_before(type **list, type *elem) {\
- SGLIB_DL_LIST_ADD_BEFORE(type, *list, elem, previous, next);\
- }\
- int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member==NULL);\
- }\
- int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member==NULL);\
- }\
- int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member==NULL);\
- }\
- void sglib_##type##_concat(type **first, type *second) {\
- SGLIB_DL_LIST_CONCAT(type, *first, second, previous, next);\
- }\
- void sglib_##type##_delete(type **list, type *elem) {\
- SGLIB_DL_LIST_DELETE(type, *list, elem, previous, next);\
- }\
- int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member!=NULL);\
- }\
- int sglib_##type##_is_member(type *list, type *elem) {\
- int result;\
- SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result);\
- return(result);\
- }\
- type *sglib_##type##_find_member(type *list, type *elem) {\
- type *result;\
- SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, result);\
- return(result);\
- }\
- type *sglib_##type##_get_first(type *list) {\
- type *result;\
- SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result);\
- return(result);\
- }\
- type *sglib_##type##_get_last(type *list) {\
- type *result;\
- SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result);\
- return(result);\
- }\
- void sglib_##type##_sort(type **list) {\
- SGLIB_DL_LIST_SORT(type, *list, comparator, previous, next);\
- }\
- int sglib_##type##_len(type *list) {\
- int res;\
- SGLIB_DL_LIST_LEN(type, list, previous, next, res);\
- return(res);\
- }\
- void sglib_##type##_reverse(type **list) {\
- SGLIB_DL_LIST_REVERSE(type, *list, previous, next);\
- }\
- \
- type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- it->prevelem = list;\
- it->nextelem = list;\
- if (list != NULL) it->nextelem = list->next;\
- return(sglib_##type##_it_next(it));\
- }\
- type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
- return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
- }\
- type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
- }\
- type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- type *ce, *eq;\
- int (*scp)(type *, type *);\
- ce = it->prevelem;\
- it->prevelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && scp(eq, ce)!=0) ce = ce->previous;\
- }\
- if (ce != NULL) {\
- it->prevelem = ce->previous;\
- } else {\
- ce = it->nextelem;\
- it->nextelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\
- }\
- if (ce != NULL) it->nextelem = ce->next;\
- }\
- it->currentelem = ce;\
- return(ce);\
- }
-
-
-/* --------------------------------- red-black trees (level 1) -------------------------------- */
-
-/*
-
-This implementation requires pointers to left and right sons (no
-parent pointer is needed) and one bit of additional information
-storing the color of the node. The implementation follows discrepancy
-fixing rules from:
-http://www.cis.ohio-state.edu/~gurari/course/cis680/cis680Ch11.html
-
-*/
-
-#define SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK) {\
- type *t, *tl, *a, *b, *c, *ar, *bl, *br, *cl, *cr;\
- t = *tree;\
- tl = t->leftt;\
- if (t->rightt!=NULL && SGLIB___GET_VALUE(t->rightt->bits)==RED) {\
- if (SGLIB___GET_VALUE(tl->bits)==RED) {\
- if ((tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) \
- || (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED)) {\
- SGLIB___SET_VALUE(t->leftt->bits,BLACK);\
- SGLIB___SET_VALUE(t->rightt->bits,BLACK);\
- SGLIB___SET_VALUE(t->bits,RED);\
- }\
- }\
- } else {\
- if (SGLIB___GET_VALUE(tl->bits)==RED) {\
- if (tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) {\
- a = t; b = tl; c = tl->leftt;\
- br = b->rightt;\
- a->leftt = br;\
- b->leftt = c; b->rightt = a;\
- SGLIB___SET_VALUE(a->bits,RED);\
- SGLIB___SET_VALUE(b->bits,BLACK);\
- *tree = b;\
- } else if (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED) {\
- a = t; b = tl; ar=a->rightt;\
- bl=b->leftt; c=b->rightt;\
- cl=c->leftt; cr=c->rightt;\
- b->rightt = cl;\
- a->leftt = cr;\
- c->leftt = b;\
- c->rightt = a;\
- SGLIB___SET_VALUE(c->bits,BLACK);\
- SGLIB___SET_VALUE(a->bits,RED);\
- *tree = c;\
- }\
- }\
- }\
-}
-
-#define SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK, res) {\
- type *t, *a, *b, *c, *d, *ar, *bl, *br, *cl, *cr, *dl, *dr;\
- t = a = *tree;\
- assert(t!=NULL);\
- ar = a->rightt;\
- b = t->leftt;\
- if (b==NULL) {\
- assert(SGLIB___GET_VALUE(t->bits)==RED);\
- SGLIB___SET_VALUE(t->bits,BLACK);\
- res = 0;\
- } else {\
- bl = b->leftt;\
- br = b->rightt;\
- if (SGLIB___GET_VALUE(b->bits)==RED) {\
- if (br==NULL) {\
- *tree = b;\
- SGLIB___SET_VALUE(b->bits,BLACK);\
- b->rightt = a;\
- a->leftt = br;\
- res = 0;\
- } else {\
- c = br;\
- assert(c!=NULL && SGLIB___GET_VALUE(c->bits)==BLACK);\
- cl = c->leftt;\
- cr = c->rightt;\
- if ((cl==NULL||SGLIB___GET_VALUE(cl->bits)==BLACK) && (cr==NULL||SGLIB___GET_VALUE(cr->bits)==BLACK)) {\
- *tree = b;\
- b->rightt = a;\
- SGLIB___SET_VALUE(b->bits,BLACK);\
- a->leftt = c;\
- SGLIB___SET_VALUE(c->bits,RED);\
- res = 0;\
- } else if (cl!=NULL && SGLIB___GET_VALUE(cl->bits)==RED) {\
- if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\
- d = cr;\
- dl = d->leftt;\
- dr = d->rightt;\
- *tree = d;\
- SGLIB___SET_VALUE(d->bits,BLACK);\
- d->leftt = b;\
- c->rightt = dl;\
- d->rightt = a;\
- a->leftt = dr;\
- res = 0;\
- } else {\
- *tree = c;\
- c->leftt = b;\
- c->rightt = a;\
- b->leftt = bl;\
- b->rightt = cl;\
- a->leftt = cr;\
- SGLIB___SET_VALUE(cl->bits,BLACK);\
- res = 0;\
- }\
- } else if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\
- assert(cl==NULL || SGLIB___GET_VALUE(cl->bits)==BLACK);\
- d = cr;\
- dl = d->leftt;\
- dr = d->rightt;\
- *tree = d;\
- SGLIB___SET_VALUE(d->bits,BLACK);\
- d->leftt = b;\
- c->rightt = dl;\
- d->rightt = a;\
- a->leftt = dr;\
- res = 0;\
- } else {\
- assert(0);\
- res = 0;\
- }\
- }\
- } else {\
- if ((bl==NULL || SGLIB___GET_VALUE(bl->bits)==BLACK) && (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK)) {\
- res = (SGLIB___GET_VALUE(a->bits)==BLACK);\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- SGLIB___SET_VALUE(b->bits,RED);\
- } else if (bl!=NULL && SGLIB___GET_VALUE(bl->bits)==RED) {\
- if (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK) {\
- *tree = b;\
- SGLIB___SET_VALUE(b->bits,SGLIB___GET_VALUE(a->bits));\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- b->rightt = a;\
- a->leftt = br;\
- SGLIB___SET_VALUE(bl->bits,BLACK);\
- res = 0;\
- } else {\
- assert(bl!=NULL);\
- assert(br!=NULL);\
- assert(SGLIB___GET_VALUE(bl->bits)==RED);\
- assert(SGLIB___GET_VALUE(br->bits)==RED);\
- c = br;\
- cl = c->leftt;\
- cr = c->rightt;\
- *tree = c;\
- SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- c->leftt = b;\
- c->rightt = a;\
- b->rightt = cl;\
- a->leftt = cr;\
- res = 0;\
- }\
- } else {\
- assert(br!=NULL && SGLIB___GET_VALUE(br->bits)==RED);\
- c = br;\
- cl = c->leftt;\
- cr = c->rightt;\
- *tree = c;\
- SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- c->leftt = b;\
- c->rightt = a;\
- b->rightt = cl;\
- a->leftt = cr;\
- res = 0;\
- }\
- }\
- }\
-}
-
-
-#define SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, bits, comparator, RED, BLACK) \
-static void sglib___##type##_fix_left_insertion_discrepancy(type **tree) {\
- SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK);\
-}\
-\
-static void sglib___##type##_fix_right_insertion_discrepancy(type **tree) {\
- SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK);\
-}\
-\
-static int sglib___##type##_fix_left_deletion_discrepancy(type **tree) {\
- int res;\
- SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK, res);\
- return(res);\
-}\
-\
-static int sglib___##type##_fix_right_deletion_discrepancy(type **tree) {\
- int res;\
- SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK, res);\
- return(res);\
-}\
-\
-static void sglib___##type##_add_recursive(type **tree, type *elem) {\
- int cmp;\
- type *t;\
- t = *tree;\
- if (t == NULL) {\
- SGLIB___SET_VALUE(elem->bits,RED);\
- *tree =elem;\
- } else {\
- cmp = comparator(elem, t);\
- if (cmp < 0 || (cmp==0 && elem<t)) {\
- sglib___##type##_add_recursive(&t->left, elem);\
- if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_left_insertion_discrepancy(tree);\
- } else {\
- sglib___##type##_add_recursive(&t->right, elem);\
- if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_right_insertion_discrepancy(tree);\
- }\
- }\
-}\
-\
-static int sglib___##type##_delete_rightmost_leaf(type **tree, type **theLeaf) {\
- type *t;\
- int res, deepDecreased;\
- t = *tree;\
- res = 0;\
- assert(t!=NULL);\
- if (t->right == NULL) {\
- *theLeaf = t;\
- if (t->left!=NULL) {\
- if (SGLIB___GET_VALUE(t->bits)==BLACK && SGLIB___GET_VALUE(t->left->bits)==BLACK) res = 1;\
- SGLIB___SET_VALUE(t->left->bits,BLACK);\
- *tree = t->left;\
- } else {\
- *tree = NULL;\
- res = (SGLIB___GET_VALUE(t->bits)==BLACK);\
- }\
- } else {\
- deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->right, theLeaf);\
- if (deepDecreased) res = sglib___##type##_fix_right_deletion_discrepancy(tree);\
- }\
- return(res);\
-}\
-\
-int sglib___##type##_delete_recursive(type **tree, type *elem) {\
- type *t, *theLeaf;\
- int cmp, res, deepDecreased;\
- t = *tree;\
- res = 0;\
- if (t==NULL) {\
- assert(0 && "The element to delete not found in the tree, use 'delete_if_member'"!=NULL);\
- } else {\
- cmp = comparator(elem, t);\
- if (cmp < 0 || (cmp==0 && elem<t)) {\
- deepDecreased = sglib___##type##_delete_recursive(&t->left, elem);\
- if (deepDecreased) {\
- res = sglib___##type##_fix_left_deletion_discrepancy(tree);\
- }\
- } else if (cmp > 0 || (cmp==0 && elem>t)) {\
- deepDecreased = sglib___##type##_delete_recursive(&t->right, elem);\
- if (deepDecreased) {\
- res = sglib___##type##_fix_right_deletion_discrepancy(tree);\
- }\
- } else {\
- assert(elem==t && "Deleting an element which is non member of the tree, use 'delete_if_member'"!=NULL);\
- if (t->left == NULL) {\
- if (t->right == NULL) {\
- /* a leaf, delete, it; */\
- *tree = NULL;\
- res = (SGLIB___GET_VALUE(t->bits)==BLACK);\
- } else {\
- if (SGLIB___GET_VALUE(t->bits)==0 && SGLIB___GET_VALUE(t->right->bits)==0) res = 1;\
- SGLIB___SET_VALUE(t->right->bits,BLACK);\
- *tree = t->right;\
- }\
- } else {\
- /* propagate deletion until righmost leaf of left subtree */\
- deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->left, &theLeaf);\
- theLeaf->left = t->left;\
- theLeaf->right = t->right;\
- SGLIB___SET_VALUE(theLeaf->bits,SGLIB___GET_VALUE(t->bits));\
- *tree = theLeaf;\
- if (deepDecreased) res = sglib___##type##_fix_left_deletion_discrepancy(tree);\
- }\
- }\
- }\
- return(res);\
-}\
-\
-void sglib_##type##_add(type **tree, type *elem) {\
- elem->left = elem->right = NULL;\
- sglib___##type##_add_recursive(tree, elem);\
- SGLIB___SET_VALUE((*tree)->bits,BLACK);\
-}\
-\
-void sglib_##type##_delete(type **tree, type *elem) {\
- sglib___##type##_delete_recursive(tree, elem);\
- if (*tree!=NULL) SGLIB___SET_VALUE((*tree)->bits,BLACK);\
-}\
-\
-type *sglib_##type##_find_member(type *t, type *elem) {\
- type *res;\
- SGLIB___BIN_TREE_FIND_MEMBER(type, t, elem, left, right, comparator, res);\
- return(res);\
-}\
-\
-int sglib_##type##_is_member(type *t, type *elem) {\
- int cmp;\
- while (t!=NULL) {\
- cmp = comparator(elem, t);\
- if (cmp < 0 || (cmp==0 && elem<t)) {\
- t = t->left;\
- } else if (cmp > 0 || (cmp==0 && elem>t)) {\
- t = t->right;\
- } else {\
- assert(t == elem);\
- return(1);\
- }\
- }\
- return(0);\
-}\
-\
-int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb) {\
- if ((*memb=sglib_##type##_find_member(*tree, elem))!=NULL) {\
- sglib_##type##_delete(tree, *memb);\
- return(1);\
- } else {\
- return(0);\
- }\
-}\
-int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb) {\
- if ((*memb=sglib_##type##_find_member(*tree, elem))==NULL) {\
- sglib_##type##_add(tree, elem);\
- return(1);\
- } else {\
- return(0);\
- }\
-}\
-int sglib_##type##_len(type *t) {\
- int n;\
- type *e;\
- n = 0;\
- SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, t, e, left, right, n++);\
- return(n);\
-}\
-\
-void sglib__##type##_it_compute_current_elem(struct sglib_##type##_iterator *it) {\
- int i,j,cmp;\
- type *s, *eqt;\
- int (*subcomparator)(type *, type *);\
- eqt = it->equalto;\
- subcomparator = it->subcomparator;\
- it->currentelem = NULL;\
- while(it->pathi > 0 && it->currentelem==NULL) {\
- i = it->pathi-1;\
- if (i >= 0) {\
- if (it->pass[i] >= 2) {\
- /* goto up */\
- it->pathi --;\
- } else {\
- if (it->pass[i] == 0) {\
- /* goto left */\
- s = it->path[i]->left;\
- } else {\
- /* goto right */\
- s = it->path[i]->right;\
- }\
- if (eqt != NULL) {\
- if (subcomparator == NULL) {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, comparator, s);\
- } else {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, subcomparator, s);\
- }\
- }\
- if (s != NULL) {\
- j = i+1;\
- it->path[j] = s;\
- it->pass[j] = 0;\
- it->pathi ++;\
- }\
- it->pass[i] ++;\
- }\
- }\
- if (it->pathi>0 && it->order == it->pass[it->pathi-1]) {\
- it->currentelem = it->path[it->pathi-1];\
- }\
- }\
-}\
-type *sglib__##type##_it_init(struct sglib_##type##_iterator *it, type *tree, int order, int (*subcomparator)(type *, type *), type *equalto) {\
- type *t;\
- assert(it!=NULL);\
- it->order = order;\
- it->equalto = equalto;\
- it->subcomparator = subcomparator;\
- if (equalto == NULL) { \
- t = tree;\
- } else {\
- if (subcomparator == NULL) {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, comparator, t);\
- } else {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, subcomparator, t);\
- }\
- }\
- if (t == NULL) {\
- it->pathi = 0;\
- it->currentelem = NULL;\
- } else {\
- it->pathi = 1;\
- it->pass[0] = 0;\
- it->path[0] = t;\
- if (order == 0) {\
- it->currentelem = t;\
- } else {\
- sglib__##type##_it_compute_current_elem(it);\
- }\
- }\
- return(it->currentelem);\
-}\
-type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 0, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 1, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto) {\
- return(sglib__##type##_it_init(it, tree, 1, subcomparator, equalto));\
-}\
-type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
-}\
-type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- sglib__##type##_it_compute_current_elem(it);\
- return(it->currentelem);\
-}\
-\
-static void sglib___##type##_consistency_check_recursive(type *t, int *pathdeep, int cdeep) {\
- if (t==NULL) {\
- if (*pathdeep < 0) *pathdeep = cdeep;\
- else assert(*pathdeep == cdeep);\
- } else {\
- if (t->left!=NULL) assert(comparator(t->left, t) <= 0);\
- if (t->right!=NULL) assert(comparator(t, t->right) <= 0);\
- if (SGLIB___GET_VALUE(t->bits) == RED) {\
- assert(t->left == NULL || SGLIB___GET_VALUE(t->left->bits)==BLACK);\
- assert(t->right == NULL || SGLIB___GET_VALUE(t->right->bits)==BLACK);\
- sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep);\
- sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep);\
- } else {\
- sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep+1);\
- sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep+1);\
- }\
- }\
-}\
-\
-void sglib___##type##_consistency_check(type *t) {\
- int pathDeep;\
- assert(t==NULL || SGLIB___GET_VALUE(t->bits) == BLACK);\
- pathDeep = -1;\
- sglib___##type##_consistency_check_recursive(t, &pathDeep, 0);\
-}
-
-
-#define SGLIB_DEFINE_RBTREE_PROTOTYPES(type, left, right, colorbit, comparator) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- char pass[SGLIB_MAX_TREE_DEEP];\
- type *path[SGLIB_MAX_TREE_DEEP];\
- short int pathi;\
- short int order;\
- type *equalto;\
- int (*subcomparator)(type *, type *);\
- };\
- extern void sglib___##type##_consistency_check(type *t); \
- extern void sglib_##type##_add(type **tree, type *elem); \
- extern int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb); \
- extern void sglib_##type##_delete(type **tree, type *elem); \
- extern int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb); \
- extern int sglib_##type##_is_member(type *t, type *elem); \
- extern type *sglib_##type##_find_member(type *t, type *elem); \
- extern int sglib_##type##_len(type *t); \
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it); \
-
-
-#define SGLIB_DEFINE_RBTREE_FUNCTIONS(type, left, right, colorbit, comparator) \
- SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, colorbit, comparator, 1, 0)
-
-
-
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-/* - SUPPLEMENTARY DEFINITIONS - */
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-#define SGLIB___GET_VALUE(x) (x)
-#define SGLIB___SET_VALUE(x, value) {(x) = (value);}
-#define SGLIB_ARRAY_ELEMENTS_EXCHANGER(type, a, i, j) {type _sgl_aee_tmp_; _sgl_aee_tmp_=(a)[(i)]; (a)[(i)]=(a)[(j)]; (a)[(j)]= _sgl_aee_tmp_;}
-
-
-#define SGLIB_SAFE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?1:((x)<(y)?-1:0)))
-#define SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?-1:((x)<(y)?1:0)))
-#define SGLIB_FAST_NUMERIC_COMPARATOR(x, y) ((int)((x) - (y)))
-#define SGLIB_FAST_REVERSE_NUMERIC_COMPARATOR(x, y) ((int)((y) - (x)))
-#define SGLIB_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_NUMERIC_COMPARATOR(x, y)
-#define SGLIB_REVERSE_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y)
-
-#ifndef SGLIB_MAX_TREE_DEEP
-#define SGLIB_MAX_TREE_DEEP 128
-#endif
-
-#ifndef SGLIB_HASH_TAB_SHIFT_CONSTANT
-#define SGLIB_HASH_TAB_SHIFT_CONSTANT 16381 /* should be a prime */
-/* #define SGLIB_HASH_TAB_SHIFT_CONSTANT 536870912*/ /* for large tables :) */
-#endif
-
-#endif /* _SGLIB__h_ */
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 cc589bde..1f2023f0 100644
--- a/src/init1.c
+++ b/src/init1.cc
@@ -1,8 +1,56 @@
-/* File: init1.c */
-
-/* Purpose: Initialization (part 1) -BEN- */
-
-#include "angband.h"
+#include "init1.hpp"
+
+#include "ability_type.hpp"
+#include "alchemist_recipe.hpp"
+#include "artifact_type.hpp"
+#include "artifact_select_flag.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 <boost/algorithm/string/predicate.hpp>
+
+using boost::algorithm::iequals;
+using boost::algorithm::ends_with;
/*
@@ -363,7 +411,7 @@ static cptr r_info_flags7[] =
"AI_PLAYER",
"NO_THEFT",
"SPIRIT",
- "IM_MELEE",
+ "XXX7X20",
"XXX7X21",
"XXX7X22",
"XXX7X23",
@@ -637,9 +685,9 @@ cptr k_info_flags4[] =
"CHEAPNESS",
"FOUNTAIN",
"ANTIMAGIC_50",
- "ANTIMAGIC_30",
- "ANTIMAGIC_20",
- "ANTIMAGIC_10",
+ "XXX5",
+ "XXX5",
+ "XXX5",
"EASY_USE",
"IM_NETHER",
"RECHARGED",
@@ -1394,6 +1442,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 +1542,47 @@ static byte monster_ego_modify(char c)
}
}
-/*
- * Implements fp stacks, for included files
+/**
+ * Version of strdup() which just aborts if an allocation
+ * error occurs.
*/
-static FILE *fp_stack[10];
-static int fp_stack_idx = 0;
-
-/*
- * Must be caleld before the main loop
- */
-static void fp_stack_init(FILE *fp)
-{
- fp_stack[0] = fp;
- fp_stack_idx = 0;
-}
-
-static void fp_stack_push(cptr name)
+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 +1596,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 +1617,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 +1691,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 +1793,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,7 +1801,7 @@ 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 */
@@ -1792,15 +1821,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 +1831,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++;
@@ -1842,13 +1861,6 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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 +1883,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 +1933,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 +1941,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 +1963,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... */
@@ -2049,7 +2036,7 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* Find it in the list */
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);
@@ -2299,7 +2286,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 +2294,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 +2316,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... */
@@ -2427,7 +2402,7 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* Find it in the list */
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);
@@ -2713,7 +2688,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 +2696,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 +2723,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;
}
@@ -2950,7 +2906,7 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* Find it in the list */
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);
@@ -3132,18 +3088,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 +3108,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 +3308,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,13 +3326,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);
@@ -3406,9 +3337,10 @@ 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 */
@@ -3417,22 +3349,14 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
/* 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++;
@@ -3463,13 +3387,6 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
/* 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 +3409,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 +3417,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 +3434,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,14 +3502,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);
@@ -3647,47 +3539,26 @@ 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++;
@@ -3717,13 +3588,6 @@ errr init_f_info_txt(FILE *fp, char *buf)
/* 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 +3610,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 +3618,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);
+ /* Copy name */
+ assert(!f_ptr->name);
+ f_ptr->name = my_strdup(s);
- /* Advance and Save the name index */
- if (!f_ptr->name) f_ptr->name = ++f_head->name_size;
-
- /* Append chars to the name */
- strcpy(f_name + f_head->name_size, s);
-
- /* Advance the index */
- f_head->name_size += strlen(s);
-
- /* Default "mimic" */
+ /* 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 +3642,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 +3816,9 @@ 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,10 +3932,10 @@ 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 */
@@ -4114,13 +3952,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++;
@@ -4150,13 +3983,6 @@ errr init_k_info_txt(FILE *fp, char *buf)
/* 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 +4005,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 +4013,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;
+ assert(!k_ptr->name);
+ k_ptr->name = my_strdup(s);
- /* Append chars to the name */
- strcpy(k_name + k_head->name_size, 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 +4037,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;
@@ -4354,7 +4156,7 @@ errr init_k_info_txt(FILE *fp, char *buf)
/* Find it in the list */
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);
@@ -4368,17 +4170,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 +4188,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 +4209,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;
+ }
}
}
@@ -4497,11 +4299,6 @@ errr init_k_info_txt(FILE *fp, char *buf)
}
- /* Complete the "name" and "text" sizes */
- ++k_head->name_size;
- ++k_head->text_size;
-
-
/* No version yet */
if (!okay) return (2);
@@ -4592,11 +4389,12 @@ int init_al_info_essence(char *essence)
/*
* Initialize the "al_info" array, by parsing an ascii "template" file
*/
-errr init_al_info_txt(FILE *fp, char *buf)
+errr init_al_info_txt(FILE *fp)
{
int al_idx = 0, a_idx = 0;
char *s, *t;
struct artifact_select_flag *a_ptr = NULL;
+ char buf[1024];
/* Not ready yet */
bool_ okay = FALSE;
@@ -4607,13 +4405,8 @@ errr init_al_info_txt(FILE *fp, char *buf)
/* 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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -4642,13 +4435,6 @@ errr init_al_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -4813,71 +4599,47 @@ errr init_al_info_txt(FILE *fp, char *buf)
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);
+ /* Copy plural description */
+ assert(!a_ptr->item_descp);
+ a_ptr->item_descp = my_strdup(s);
/* Next... */
continue;
}
- /* Process 'D' for "Description" */
+ /* Process 'D' for "Description" (one line only) */
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);
+ /* Copy description */
+ assert(!a_ptr->desc);
+ a_ptr->desc = my_strdup(s);
/* Next... */
continue;
}
- /* Process 'd' for "Item Description" */
+ /* Process 'd' for "Item Description" (one line only) */
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);
-
+ /* Reject if we already have a description */
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);
+ /* Copy description */
+ assert(!a_ptr->item_desc);
+ a_ptr->item_desc = my_strdup(s);
/* Next... */
continue;
@@ -4890,9 +4652,6 @@ errr init_al_info_txt(FILE *fp, char *buf)
/* 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,10 +4767,10 @@ 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 */
@@ -5029,8 +4788,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++;
@@ -5060,13 +4818,6 @@ errr init_a_info_txt(FILE *fp, char *buf)
/* 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 +4840,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 +4848,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 +4885,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;
@@ -5240,7 +4972,7 @@ errr init_a_info_txt(FILE *fp, char *buf)
/* Find it in the list */
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);
@@ -5308,17 +5040,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... */
@@ -5331,11 +5056,6 @@ errr init_a_info_txt(FILE *fp, char *buf)
}
- /* Complete the "name" and "text" sizes */
- ++a_head->name_size;
- ++a_head->text_size;
-
-
/* No version yet */
if (!okay) return (2);
@@ -5347,10 +5067,11 @@ 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;
@@ -5369,8 +5090,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++;
@@ -5400,13 +5120,6 @@ errr init_set_info_txt(FILE *fp, char *buf)
/* 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 +5144,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 +5152,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);
-
- /* 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);
+ /* Copy name */
+ assert(!set_ptr->name);
+ set_ptr->name = my_strdup(s);
- /* Needed hack */
+ /* Initialize */
set_ptr->num = 0;
set_ptr->num_use = 0;
for (z = 0; z < 6; z++)
@@ -5483,17 +5188,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 +5263,9 @@ 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,10 +5274,10 @@ 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 */
@@ -5606,8 +5295,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++;
@@ -5637,13 +5325,6 @@ errr init_s_info_txt(FILE *fp, char *buf)
/* 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 +5461,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 +5469,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 +5495,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 +5521,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 +5601,9 @@ 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,10 +5611,10 @@ 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 */
@@ -5985,8 +5632,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++;
@@ -6016,13 +5662,6 @@ errr init_ab_info_txt(FILE *fp, char *buf)
/* 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 +5681,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 +5689,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 +5720,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 +5746,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);
-
- /* Advance and Save the text index */
- if (!ab_ptr->action_desc) ab_ptr->action_desc = ++ab_head->text_size;
+ /* Copy name */
+ assert(!ab_ptr->action_desc);
+ ab_ptr->action_desc = my_strdup(txt);
- /* 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 +5900,9 @@ 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 +5914,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,10 +6132,10 @@ 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 */
@@ -6547,8 +6153,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++;
@@ -6578,13 +6183,6 @@ errr init_e_info_txt(FILE *fp, char *buf)
/* 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 +6205,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 +6213,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 +6226,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 +6235,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 +6279,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;
@@ -6765,7 +6364,7 @@ errr init_e_info_txt(FILE *fp, char *buf)
/* Find it in the list */
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);
@@ -6778,16 +6377,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 + 2);
+ if (e_ptr->activate == -1)
{
- e_ptr->activate = get_activation(buf + 11);
- if (e_ptr->activate == -1)
- return 1;
- }
- else if (prefix(buf + 2, "SPELL="))
- {
- e_ptr->activate = -find_spell(buf + 8);
- if (e_ptr->activate == -( -1))
return 1;
}
@@ -6912,11 +6504,6 @@ errr init_e_info_txt(FILE *fp, char *buf)
}
- /* Complete the "name" and "text" sizes */
- ++e_head->name_size;
- ++e_head->text_size;
-
-
/* No version yet */
if (!okay) return (2);
@@ -7048,10 +6635,10 @@ 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 */
@@ -7069,8 +6656,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++;
@@ -7100,13 +6686,6 @@ errr init_ra_info_txt(FILE *fp, char *buf)
/* 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 +6716,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;
@@ -7254,7 +6833,7 @@ errr init_ra_info_txt(FILE *fp, char *buf)
/* Find it in the list */
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);
@@ -7455,10 +7034,10 @@ 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 */
@@ -7475,13 +7054,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++;
@@ -7511,13 +7085,6 @@ errr init_r_info_txt(FILE *fp, char *buf)
/* 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 +7107,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 +7115,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);
+ /* Allocate name string. */
+ assert(!r_ptr->name); // Sanity check that we aren't overwriting anything
+ r_ptr->name = my_strdup(s);
- /* Advance and Save the name index */
- if (!r_ptr->name) r_ptr->name = ++r_head->name_size;
-
- /* Append chars to the name */
- strcpy(r_name + r_head->name_size, s);
-
- /* Advance the index */
- r_head->name_size += strlen(s);
+ /* 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 +7143,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 +7396,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 */
@@ -8095,10 +7644,10 @@ 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;
@@ -8117,14 +7666,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++;
@@ -8154,13 +7697,6 @@ errr init_re_info_txt(FILE *fp, char *buf)
/* 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 +7719,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 +7727,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,10 +8128,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);
@@ -8639,10 +8163,10 @@ 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 */
@@ -8651,21 +8175,14 @@ errr init_t_info_txt(FILE *fp, char *buf)
/* 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++;
@@ -8695,13 +8212,6 @@ errr init_t_info_txt(FILE *fp, char *buf)
/* 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 +8234,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 +8242,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 +8290,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 +8333,9 @@ 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 +8496,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;
@@ -9031,14 +8520,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++;
@@ -9068,13 +8551,6 @@ errr init_d_info_txt(FILE *fp, char *buf)
/* 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 +8573,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 +8581,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);
+ /* Copy name */
+ assert(!d_ptr->name);
+ d_ptr->name = my_strdup(s);
- /* Advance and Save the name index */
- if (!d_ptr->name) d_ptr->name = ++d_head->name_size;
-
- /* Append chars to the name */
- strcpy(d_name + d_head->name_size, s);
-
- /* Advance the index */
- d_head->name_size += strlen(s);
+ /* Initialize description */
+ d_ptr->text = my_strdup("");
/* HACK -- Those ones HAVE to have a set default value */
d_ptr->size_x = -1;
@@ -9164,17 +8635,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;
@@ -9588,10 +9050,6 @@ errr init_d_info_txt(FILE *fp, char *buf)
}
- /* Complete the "name" and "text" sizes */
- ++d_head->name_size;
- ++d_head->text_size;
-
/* No version yet */
if (!okay) return (2);
@@ -9657,10 +9115,10 @@ 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 */
@@ -9676,14 +9134,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++;
@@ -9713,13 +9165,6 @@ errr init_st_info_txt(FILE *fp, char *buf)
/* 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 +9187,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 +9195,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 +9231,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,11 +9369,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);
@@ -9946,10 +9379,10 @@ 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 */
@@ -9965,14 +9398,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++;
@@ -10002,13 +9429,6 @@ errr init_ba_info_txt(FILE *fp, char *buf)
/* 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 +9451,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 +9459,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,11 +9513,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);
@@ -10116,10 +9523,10 @@ 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 */
@@ -10128,21 +9535,14 @@ errr init_ow_info_txt(FILE *fp, char *buf)
/* 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++;
@@ -10172,13 +9572,6 @@ errr init_ow_info_txt(FILE *fp, char *buf)
/* 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 +9594,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 +9602,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;
@@ -10321,11 +9706,6 @@ 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);
@@ -10360,10 +9740,10 @@ static errr grab_one_wf_info_flag(wilderness_type_info *wf_ptr, cptr what)
/*
* 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 buf[1024];
char *s, *t;
/* Not ready yet */
@@ -10372,21 +9752,14 @@ errr init_wf_info_txt(FILE *fp, char *buf)
/* 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++;
@@ -10416,13 +9789,6 @@ errr init_wf_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -10445,7 +9811,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;
@@ -10453,17 +9819,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;
@@ -10472,23 +9830,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;
@@ -10574,11 +9924,6 @@ errr init_wf_info_txt(FILE *fp, char *buf)
return (6);
}
-
- /* Complete the "name" and "text" sizes */
- ++wf_head->name_size;
- ++wf_head->text_size;
-
/* No version yet */
if (!okay) return (2);
@@ -11399,6 +10744,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;
@@ -11580,19 +10926,19 @@ static cptr process_dungeon_file_expr(char **sp, char *fp)
/* 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 */
diff --git a/src/init1.hpp b/src/init1.hpp
new file mode 100644
index 00000000..69bcec9b
--- /dev/null
+++ b/src/init1.hpp
@@ -0,0 +1,27 @@
+#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_al_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 9c1c2afa..00000000
--- a/src/init2.c
+++ /dev/null
@@ -1,2738 +0,0 @@
-/* File: init2.c */
-
-/* Purpose: Initialisation (part 2) -BEN- */
-
-#include "angband.h"
-
-#include <assert.h>
-
-#include "messages.h"
-#include "quark.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_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, "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_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);
-}
-
-
-/**
- * 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;
- }
-}
-
-
-/*
- * 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();
-
- /* Initialize game */
- 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;
-
- /* 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 */
- 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;
-}
-
-/*
- * 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_USER, "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 scripting... (script)]");
- 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 */
- path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "automat.atm");
- automatizer_init(buf);
-
- /* 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..f80b832a
--- /dev/null
+++ b/src/init2.cc
@@ -0,0 +1,1525 @@
+#include "init2.hpp"
+#include "init2.h"
+
+#include "ability_type.hpp"
+#include "alchemist_recipe.hpp"
+#include "alloc_entry.hpp"
+#include "artifact_select_flag.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);
+ }
+
+ };
+
+ struct al_info_traits {
+
+ static constexpr char const *name = "al_info.txt";
+
+ static void allocate()
+ {
+ alchemist_recipes = make_array<alchemist_recipe>(max_al_idx);
+ a_select_flags = make_array<artifact_select_flag>(max_al_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_al_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;
+}
+
+/*
+ * 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) */
+ 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)
+ {
+ /* 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");
+
+ /* 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 alchemy info */
+ note("[Initialising arrays... (alchemy)]");
+ if (init_x_info<al_info_traits>()) quit("Cannot initialise alchemy");
+
+ /* 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/joke.c b/src/joke.cc
index 0ff01557..fa660243 100644
--- a/src/joke.c
+++ b/src/joke.cc
@@ -1,10 +1,15 @@
-#include "angband.h"
+#include "joke.hpp"
-static void gen_joke_place_monster(r_idx)
+#include "monster2.hpp"
+#include "options.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
+static void gen_joke_place_monster(int r_idx)
{
- int try;
+ int try_;
- for (try = 0; try < 1000; try++)
+ for (try_ = 0; try_ < 1000; try_++)
{
int x = randint(cur_hgt - 4) + 2;
int y = randint(cur_wid - 4) + 2;
@@ -24,9 +29,9 @@ bool_ gen_joke_monsters(void *data, void *in, void *out)
(dun_level == 72))
{
int r_idx = test_monster_name("Neil, the Sorceror");
- m_allow_special[r_idx + 1] = TRUE;
+ m_allow_special[r_idx] = TRUE;
gen_joke_place_monster(r_idx);
- m_allow_special[r_idx + 1] = FALSE;
+ m_allow_special[r_idx] = 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/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 1b142e59..13e4911f 100644
--- a/src/loadsave.c
+++ b/src/loadsave.cc
@@ -1,48 +1,56 @@
-/* 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"
-
-#include "messages.h"
-#include "quark.h"
-
-static void do_byte(byte *, int);
-static void do_bool(bool_ *, int);
-static void do_u16b(u16b *, int);
-static void do_s16b(s16b *, int);
-static void do_u32b(u32b *, int);
-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 <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)
@@ -76,14 +84,103 @@ 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;
@@ -91,22 +188,76 @@ static void do_xtra(int k_idx, int flag)
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);
@@ -126,8 +277,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);
@@ -136,23 +287,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);
@@ -221,17 +382,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);
@@ -244,14 +466,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)
{
@@ -261,7 +483,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)
{
@@ -297,7 +519,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);
@@ -321,12 +543,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)
{
@@ -351,7 +573,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");
}
@@ -392,10 +614,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 */
@@ -407,10 +629,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));
}
@@ -420,13 +642,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++)
{
@@ -470,19 +692,19 @@ 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);
@@ -556,9 +778,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);
@@ -567,27 +789,27 @@ 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(&tmp16s, flag); /* compat */
- if (flag == LS_SAVE) { tmp16s = CORRUPTIONS_MAX; }
+ if (flag == ls_flag_t::SAVE) { tmp16s = CORRUPTIONS_MAX; }
do_s16b(&tmp16s, flag);
if (tmp16s > CORRUPTIONS_MAX) {
quit("Too many corruptions");
@@ -595,12 +817,12 @@ static bool_ do_extra(int flag)
for (i = 0; i < tmp16s; i++)
{
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
tmp8u = p_ptr->corruptions[i];
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
p_ptr->corruptions[i] = tmp8u;
}
@@ -610,12 +832,12 @@ static bool_ do_extra(int 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);
@@ -625,21 +847,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);
@@ -647,9 +869,9 @@ 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;
+ if (flag == ls_flag_t::SAVE) tmp16s = POWER_MAX;
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > POWER_MAX))
+ if ((flag == ls_flag_t::LOAD) && (tmp16s > POWER_MAX))
note(format("Too many (%u) powers!", tmp16s));
for (i = 0; i < POWER_MAX; i++)
do_byte((byte*)&p_ptr->powers_mod[i], flag);
@@ -668,13 +890,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);
@@ -699,12 +922,12 @@ 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;
@@ -719,9 +942,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);
@@ -732,489 +955,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(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;
-}
-
-/*
- * 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)
+static void do_monster(monster_type *m_ptr, ls_flag_t 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_bool(bool_ *f, int flag)
-{
- byte b = *f;
- do_byte(&b, flag);
- if (flag == LS_LOAD)
- {
- *f = b;
- }
-}
-
-static void do_u16b(u16b *v, int flag)
-{
- if (flag == LS_LOAD)
- {
- (*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)
-{
- do_u16b((u16b *)ip, flag);
-}
+ 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)
-{
- do_u32b((u32b *)ip, flag);
-}
+ 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();
-}
/*
@@ -1276,7 +1068,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;
@@ -1321,15 +1113,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);
@@ -1372,42 +1164,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];
@@ -1499,143 +1296,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)
{
- MAKE(m_ptr->mind, monster_mind);
+ 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);
}
- /* Special race */
- tmp = (m_ptr->sr_ptr) ? TRUE : FALSE;
- do_byte((byte*)&tmp, flag);
- if (tmp)
+ /* Dungeon items */
+ for (i = 1; i < tmp16b; i++)
{
- if (flag == LS_LOAD)
+ int o_idx;
+
+ object_type *o_ptr;
+
+ if (flag == ls_flag_t::SAVE)
{
- MAKE(m_ptr->sr_ptr, monster_race);
+ 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 */
}
- do_u32b(&m_ptr->sr_ptr->name, flag);
- do_u32b(&m_ptr->sr_ptr->text, flag);
+ /* Until the end of the loop, this is all ls_flag_t::LOAD */
- do_u16b(&m_ptr->sr_ptr->hdice, flag);
- do_u16b(&m_ptr->sr_ptr->hside, flag);
+ /* Get a new record */
+ o_idx = o_pop();
- do_s16b(&m_ptr->sr_ptr->ac, flag);
+ /* Oops */
+ if (i != o_idx)
+ {
+ note(format("Object allocation error (%d <> %d)", i, o_idx));
+ return (FALSE);
+ }
- do_s16b(&m_ptr->sr_ptr->sleep, flag);
- do_byte(&m_ptr->sr_ptr->aaf, flag);
- do_byte(&m_ptr->sr_ptr->speed, flag);
- do_s32b(&m_ptr->sr_ptr->mexp, flag);
+ /* Acquire place */
+ o_ptr = &o_list[o_idx];
- do_s32b(&m_ptr->sr_ptr->weight, flag);
+ /* Read the item */
+ do_item(o_ptr, ls_flag_t::LOAD);
- do_byte(&m_ptr->sr_ptr->freq_inate, flag);
- do_byte(&m_ptr->sr_ptr->freq_spell, flag);
+ /* Monster */
+ if (o_ptr->held_m_idx)
+ {
+ /* Monster */
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- 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);
+ /* Place the object */
+ m_ptr->hold_o_idxs.push_back(o_idx);
+ }
- /* Attacks */
- for (i = 0; i < 4; i++)
+ /* Dungeon */
+ else
{
- 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);
+ /* Access the item location */
+ c_ptr = &cave[o_ptr->iy][o_ptr->ix];
+
+ /* Place the object */
+ c_ptr->o_idxs.push_back(o_idx);
}
+ }
- for (i = 0; i < BODY_MAX; i++)
- do_byte(&m_ptr->sr_ptr->body_parts[i], flag);
+ /*** Monsters ***/
- do_byte(&m_ptr->sr_ptr->level, flag);
- do_byte(&m_ptr->sr_ptr->rarity, flag);
+ if (flag == ls_flag_t::SAVE)
+ {
+ tmp16b = m_max;
+
+ if (no_companions)
+ {
+ for (i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
- do_byte((byte*)&m_ptr->sr_ptr->d_char, flag);
- do_byte(&m_ptr->sr_ptr->d_attr, flag);
+ if (m_ptr->status == MSTATUS_COMPANION) tmp16b--;
+ }
+ }
+
+ /* Write the monster count */
+ do_u16b(&tmp16b, flag);
- do_byte((byte*)&m_ptr->sr_ptr->x_char, flag);
- do_byte(&m_ptr->sr_ptr->x_attr, flag);
+ tmp16b = m_max;
+ }
+ else
+ /* Read the monster count */
+ do_u16b(&tmp16b, flag);
- do_s16b(&m_ptr->sr_ptr->max_num, flag);
- do_byte(&m_ptr->sr_ptr->cur_num, flag);
+ /* Validate */
+ if ((flag == ls_flag_t::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_flag_t::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_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();
+
+ /* 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_flag_t::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_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;
+
+ /* Acquire monster */
+ m_ptr = &km_list[i];
+
+ /* 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];
@@ -1683,7 +1726,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;
@@ -1701,38 +1744,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_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);
/* 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))
{
@@ -1742,17 +1780,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;
@@ -1771,7 +1806,7 @@ static void do_randomizer(int flag)
}
/* Accept */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
Rand_quick = FALSE;
}
@@ -1789,7 +1824,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;
@@ -1805,10 +1840,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;
@@ -1817,7 +1852,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;
@@ -1827,14 +1862,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);
@@ -1911,7 +1946,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++)
@@ -1958,33 +1993,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;
@@ -2001,7 +2018,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;
@@ -2013,7 +2030,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);
@@ -2058,7 +2075,7 @@ static bool_ do_inventory(int flag)
}
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
u16b i;
u16b sent = 0xFFFF;
@@ -2069,7 +2086,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);
@@ -2080,7 +2097,7 @@ 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];
@@ -2088,19 +2105,18 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be
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(&tmp8u, flag);
@@ -2108,13 +2124,13 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be
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);
do_byte(&zero, flag);
@@ -2122,300 +2138,6 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be
}
}
-/*
- * Handle dungeon
- *
- * The monsters/objects must be loaded in the same order
- * that they were stored, since the actual indexes matter.
- */
-static bool_ do_dungeon(int flag, bool_ no_companions)
-{
- int i;
-
- cave_type *c_ptr;
-
- /* Read specific */
- u16b tmp16b = 0;
-
- my_sentinel("Before do_dungeon", 324, flag);
-
- /* Header info */
- do_s16b(&dun_level, flag);
- do_byte(&dungeon_type, flag);
- do_s16b(&num_repro, flag);
- do_s16b(&p_ptr->py, flag);
- do_s16b(&p_ptr->px, flag);
- do_s16b(&cur_hgt, flag);
- do_s16b(&cur_wid, flag);
- do_s16b(&max_panel_rows, flag);
- do_s16b(&max_panel_cols, flag);
-
- do_u32b(&dungeon_flags1, flag);
- do_u32b(&dungeon_flags2, flag);
-
- /* Last teleportation */
- do_s16b(&last_teleportation_y, flag);
- do_s16b(&last_teleportation_y, flag);
-
- /* Spell effects */
- tmp16b = MAX_EFFECTS;
- do_u16b(&tmp16b, flag);
-
- if ((flag == LS_LOAD) && (tmp16b > MAX_EFFECTS))
- {
- quit("Too many spell effects");
- }
-
- for (i = 0; i < tmp16b; ++i)
- {
- do_s16b(&effects[i].type, flag);
- do_s16b(&effects[i].dam, flag);
- do_s16b(&effects[i].time, flag);
- do_u32b(&effects[i].flags, flag);
- do_s16b(&effects[i].cx, flag);
- do_s16b(&effects[i].cy, flag);
- do_s16b(&effects[i].rad, flag);
- }
-
- /* TO prevent bugs with evolving dungeons */
- for (i = 0; i < 100; i++)
- {
- do_s16b(&floor_type[i], flag);
- do_s16b(&fill_type[i], flag);
- }
-
- if ((flag == LS_LOAD) && (!dun_level && !p_ptr->inside_quest))
- {
- int xstart = 0;
- int ystart = 0;
- /* Init the wilderness */
- process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
-
- /* Init the town */
- xstart = 0;
- ystart = 0;
- init_flags = 0;
- process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
- }
-
- do_grid(flag);
-
- /*** Objects ***/
-
- if (flag == LS_SAVE) compact_objects(0);
- if (flag == LS_SAVE) compact_monsters(0);
- if (flag == LS_SAVE)
- {
- tmp16b = o_max;
-
- if (no_companions)
- {
- for (i = 1; i < o_max; i++)
- {
- object_type *o_ptr = &o_list[i];
-
- if (o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) tmp16b--;
- }
- }
-
- /* Item count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = o_max;
- }
- else
- /* Read item count */
- do_u16b(&tmp16b, flag);
-
- /* Verify maximum */
- if ((flag == LS_LOAD) && (tmp16b > max_o_idx))
- {
- note(format("Too many (%d) object entries!", tmp16b));
- return (FALSE);
- }
-
- /* Dungeon items */
- for (i = 1; i < tmp16b; i++)
- {
- int o_idx;
-
- object_type *o_ptr;
-
- if (flag == LS_SAVE)
- {
- o_ptr = &o_list[i];
- /* Don't save objects held by companions when no_companions is set */
- if (no_companions && o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) continue;
-
- do_item(o_ptr, LS_SAVE);
- continue; /* Saving is easy */
- }
- /* Until the end of the loop, this is all LS_LOAD */
-
- /* Get a new record */
- o_idx = o_pop();
-
- /* Oops */
- if (i != o_idx)
- {
- note(format("Object allocation error (%d <> %d)", i, o_idx));
- return (FALSE);
- }
-
-
- /* Acquire place */
- o_ptr = &o_list[o_idx];
-
- /* Read the item */
- do_item(o_ptr, LS_LOAD);
-
- /* Monster */
- if (o_ptr->held_m_idx)
- {
- monster_type *m_ptr;
-
- /* Monster */
- m_ptr = &m_list[o_ptr->held_m_idx];
-
- /* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
-
- /* Place the object */
- m_ptr->hold_o_idx = o_idx;
- }
-
- /* Dungeon */
- else
- {
- /* Access the item location */
- c_ptr = &cave[o_ptr->iy][o_ptr->ix];
-
- /* Build a stack */
- o_ptr->next_o_idx = c_ptr->o_idx;
-
- /* Place the object */
- c_ptr->o_idx = o_idx;
- }
- }
-
- /*** Monsters ***/
-
- if (flag == LS_SAVE)
- {
- tmp16b = m_max;
-
- if (no_companions)
- {
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
-
- if (m_ptr->status == MSTATUS_COMPANION) tmp16b--;
- }
- }
-
- /* Write the monster count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = m_max;
- }
- else
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
-
- /* Validate */
- if ((flag == LS_LOAD) && (tmp16b > max_m_idx))
- {
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
- }
-
- /* Read the monsters */
- for (i = 1; i < tmp16b; i++)
- {
- int m_idx;
- monster_type *m_ptr;
- monster_race *r_ptr;
-
- if (flag == LS_SAVE)
- {
- m_ptr = &m_list[i];
-
- /* Don't save companions when no_companions is set */
- if (no_companions && m_ptr->status == MSTATUS_COMPANION) continue;
-
- do_monster(m_ptr, LS_SAVE);
- continue; /* Easy to save a monster */
- }
- /* From here on, it's all LS_LOAD */
- /* Get a new record */
- m_idx = m_pop();
-
- /* Oops */
- if (i != m_idx)
- {
- note(format("Monster allocation error (%d <> %d)", i, m_idx));
- return (FALSE);
- }
-
- /* Acquire monster */
- m_ptr = &m_list[m_idx];
-
- /* Read the monster */
- do_monster(m_ptr, LS_LOAD);
-
- /* Access grid */
- c_ptr = &cave[m_ptr->fy][m_ptr->fx];
-
- /* Mark the location */
- c_ptr->m_idx = m_idx;
-
- /* Controlled ? */
- if (m_ptr->mflag & MFLAG_CONTROL)
- p_ptr->control = m_idx;
-
- /* Access race */
- r_ptr = &r_info[m_ptr->r_idx];
-
- /* Count XXX XXX XXX */
- r_ptr->cur_num++;
- }
-
- /* Read the kept monsters */
-
- tmp16b = (flag == LS_SAVE && !no_companions) ? max_m_idx : 0;
-
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
-
- /* Hack -- verify */
- if ((flag == LS_LOAD) && (tmp16b > max_m_idx))
- {
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
- }
- for (i = 1; i < tmp16b; i++)
- {
- monster_type *m_ptr;
-
- /* Acquire monster */
- m_ptr = &km_list[i];
-
- /* Read the monster */
- do_monster(m_ptr, flag);
- }
-
- /*** Success ***/
-
- /* The dungeon is ready */
- if (flag == LS_LOAD) character_dungeon = TRUE;
-
- /* Success */
- return (TRUE);
-}
-
/* Returns TRUE if we successfully load the dungeon */
bool_ load_dungeon(char *ext)
{
@@ -2441,7 +2163,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;
@@ -2458,26 +2180,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,7 +2200,7 @@ void do_fate(int i, int flag)
/*
* Load/save timers.
*/
-static void do_timers(int flag)
+static void do_timers(ls_flag_t flag)
{
timer_type *t_ptr;
@@ -2508,20 +2213,93 @@ static void do_timers(int 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;
- bool_ *reals;
- u16b real_max = 0;
-
/* Mention the savefile version */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
if (vernum < 100)
{
@@ -2533,15 +2311,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;
@@ -2550,7 +2327,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;
@@ -2559,8 +2336,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);
@@ -2572,7 +2352,7 @@ 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);
@@ -2592,11 +2372,11 @@ static bool_ do_savefile_aux(int flag)
do_messages(flag);
/* 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);
@@ -2610,11 +2390,11 @@ static bool_ do_savefile_aux(int flag)
}
/* 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);
@@ -2622,25 +2402,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) 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);
@@ -2657,7 +2437,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);
}
@@ -2665,21 +2445,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);
@@ -2696,11 +2476,11 @@ static bool_ do_savefile_aux(int flag)
}
/* Sanity check number of quests */
- if (flag == LS_SAVE) max_quests_ldsv = MAX_Q_IDX;
+ 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))
+ if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv != MAX_Q_IDX))
{
note(format("Invalid number of quests (%u)!", max_quests_ldsv));
return (FALSE);
@@ -2709,13 +2489,13 @@ static bool_ do_savefile_aux(int flag)
for (i = 0; i < MAX_Q_IDX; i++)
{
do_s16b(&quest[i].status, flag);
- for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++)
+ 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)
+ if ((flag == ls_flag_t::LOAD) && (quest[i].init != NULL))
{
quest[i].init(i);
}
@@ -2729,7 +2509,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;
@@ -2738,11 +2518,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 */
@@ -2759,9 +2539,9 @@ static bool_ do_savefile_aux(int flag)
}
/* 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);
@@ -2780,10 +2560,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);
@@ -2796,11 +2576,11 @@ static bool_ do_savefile_aux(int flag)
}
/* 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);
@@ -2813,11 +2593,11 @@ static bool_ do_savefile_aux(int flag)
}
/* 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);
@@ -2830,11 +2610,11 @@ static bool_ do_savefile_aux(int flag)
}
/* 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);
@@ -2851,10 +2631,10 @@ static bool_ do_savefile_aux(int flag)
/* 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);
@@ -2866,7 +2646,7 @@ 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);
@@ -2877,66 +2657,33 @@ static bool_ do_savefile_aux(int flag)
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_);
+ /* 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
@@ -2946,7 +2693,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);
}
}
@@ -2955,21 +2702,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;
@@ -2981,256 +2729,269 @@ 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++)
+ 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))
{
- for (j = 0; j < max_wild_y; j++)
- {
- wild_map[j][i].seed = rand_int(0x10000000);
- }
+ /* Give a message */
+ msg_format("Savefile does not exist: %s", savefile);
+ msg_print(NULL);
+
+ /* Allow this */
+ return (TRUE);
}
-}
-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];
-}
+ /* Okay */
+ if (!err)
+ {
+ /* Open the savefile */
+ fd = fd_open(savefile, O_RDONLY);
-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;
+ /* No file */
+ if (fd < 0) err = -1;
- int part; /* Which section of the grid we're on */
+ /* Message (below) */
+ if (err) what = "Cannot open savefile";
+ }
- for (part = 0; part < 9; part++) /* There are 8 fields to the grid, each stored
- in a seperate RLE data structure */
+ /* Process file */
+ if (!err)
{
- 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;
+ byte tmp8u = 0;
- case 1:
- tmp8u = c_ptr->feat;
- break;
+ /* Open the file XXX XXX XXX XXX Should use Angband file interface */
+ fff = my_fopen(savefile, "rb");
+/* fff = fdopen(fd, "r"); */
- case 2:
- tmp8u = c_ptr->mimic;
- 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 3:
- tmp16s = c_ptr->special;
- break;
+ /* XXX XXX XXX XXX Should use Angband file interface */
+ my_fclose(fff);
+ /* fclose(fff) */
- case 4:
- tmp16s = c_ptr->special2;
- break;
+ /* Close the file */
+ fd_close(fd);
+ }
- case 5:
- tmp16s = c_ptr->t_idx;
- break;
+ /* Process file */
+ if (!err)
+ {
- case 6:
- tmp16s = c_ptr->inscription;
- break;
+ /* Extract version */
+ sf_major = VERSION_MAJOR;
+ sf_minor = VERSION_MINOR;
+ sf_patch = VERSION_PATCH;
- case 7:
- tmp8u = c_ptr->mana;
- break;
+ /* Clear screen */
+ Term_clear();
- 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)
+ /* Attempt to load */
+ err = rd_savefile();
+
+ /* Message (below) */
+ if (err) what = "Cannot parse savefile";
+ }
+
+ /* Paranoia */
+ if (!err)
+ {
+ /* Invalid turn */
+ if (!turn) err = -1;
+
+ /* Message (below) */
+ if (err) what = "Broken savefile";
+ }
+
+
+ /* Okay */
+ if (!err)
+ {
+ /* Player is dead */
+ if (death)
+ {
+ /* Player is no longer "dead" */
+ death = FALSE;
+
+ /* Cheat death (unless the character retired) */
+ if (arg_wizard && !total_winner)
{
- 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;
- }
+ /* A character was loaded */
+ character_loaded = TRUE;
+
+ /* Done */
+ return (TRUE);
}
+
+ /* Count lives */
+ sf_lives++;
+
+ /* Forget turns */
+ turn = old_turn = 0;
+
+ /* Done */
+ return (TRUE);
}
- if (flag == LS_LOAD)
+
+ /* A character was loaded */
+ character_loaded = TRUE;
+
+ /* Still alive */
+ if (p_ptr->chp >= 0)
{
- 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;
+ /* Reset cause of death */
+ (void)strcpy(died_from, "(alive and well)");
+ }
- case 1:
- c_ptr->feat = tmp8u;
- break;
+ /* Success */
+ return (TRUE);
+ }
- case 2:
- c_ptr->mimic = tmp8u;
- break;
- case 3:
- c_ptr->special = tmp16s;
- break;
+ /* Message */
+ msg_format("Error (%s) reading %d.%d.%d savefile.",
+ what, sf_major, sf_minor, sf_patch);
+ msg_print(NULL);
- case 4:
- c_ptr->special2 = tmp16s;
- break;
+ /* Oops */
+ return (FALSE);
+}
- case 5:
- c_ptr->t_idx = tmp16s;
- break;
- case 6:
- c_ptr->inscription = tmp16s;
- break;
- case 7:
- c_ptr->mana = tmp8u;
- break;
+/*
+ * Medium level player saver
+ */
+static bool_ save_player_aux(char *name)
+{
+ bool_ ok = FALSE;
+ int fd = -1;
+ int mode = 0644;
- case 8:
- c_ptr->effect = tmp16s;
- break;
- }
- if (++x >= xmax)
- {
- /* Wrap */
- x = 0;
- if ((++y) >= ymax) break;
- }
- }
- }
+ /* 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_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);
}
}
+
+ /* Failure */
+ if (!ok) return (FALSE);
+
+ /* Success */
+ return (TRUE);
}
-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 */
+/*
+ * Attempt to save the player in a savefile
+ */
+bool_ save_player(void)
{
- if (flag == LS_SAVE)
- {
- do_u16b(&value, flag);
- return;
- }
- if (flag == LS_LOAD)
+ 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))
{
- u16b found;
- do_u16b(&found, flag);
- if (found == value) /* All is good */
- return;
- /* All is bad */
- note(format("Savefile broken %s", place));
- return;
+ 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;
}
- note(format("Impossible has occurred")); /* Programmer error */
- exit(0);
+
+ 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_bind.c b/src/lua_bind.c
deleted file mode 100644
index a15e9eb8..00000000
--- a/src/lua_bind.c
+++ /dev/null
@@ -1,342 +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 <assert.h>
-
-#include "spell_type.h"
-
-/*
- * 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);
-}
-
-/*
- * 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;
-}
-
-/** This is the function to use when casting through a stick */
-s32b get_level_device(s32b s, s32b max, s32b min)
-{
- int lvl;
- spell_type *spell = spell_at(s);
-
- /* No max specified ? assume 50 */
- if (max <= 0) {
- max = 50;
- }
- /* No min specified ? */
- if (min <= 0) {
- min = 1;
- }
-
- lvl = s_info[SKILL_DEVICE].value;
- lvl = lvl + (get_level_use_stick * SKILL_STEP);
-
- /* Sticks are limited */
- if (lvl - ((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;
-}
-
-int get_mana(s32b s)
-{
- spell_type *spell = spell_at(s);
- range_type mana_range;
- spell_type_mana_range(spell, &mana_range);
- return get_level(s, mana_range.max, mana_range.min);
-}
-
-/** Returns spell chance of failure for spell */
-s32b spell_chance(s32b s)
-{
- spell_type *s_ptr = spell_at(s);
- int level = get_level(s, 50, 1);
-
- /* Extract the base spell failure rate */
- if (get_level_use_stick > -1)
- {
- int minfail;
- s32b chance = spell_type_failure_rate(s_ptr);
-
- /* Reduce failure rate by "effective" level adjustment */
- chance -= (level - 1);
-
- /* Extract the minimum failure rate */
- minfail = 15 - get_skill_scale(SKILL_DEVICE, 25);
-
- /* Return the chance */
- return clamp_failure_chance(chance, minfail);
- }
- else
- {
- s32b chance = 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 get_level(s32b s, s32b max, s32b min)
-{
- /** Ahah shall we use Magic device instead ? */
- if (get_level_use_stick > -1) {
- return get_level_device(s, max, min);
- } else {
- s32b level;
- bool_ notused;
- get_level_school(s, max, min, &level, &notused);
- return level;
- }
-}
-
-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);
-}
-
-/*
- * 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);
-}
-
-
-
-void increase_mana(int delta)
-{
- p_ptr->csp += delta;
- p_ptr->redraw |= PR_MANA;
-
- if (p_ptr->csp < 0)
- {
- p_ptr->csp = 0;
- }
- if (p_ptr->csp > p_ptr->msp)
- {
- p_ptr->csp = p_ptr->msp;
- }
-}
-
-timer_type *TIMER_AGGRAVATE_EVIL = 0;
-
-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.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 100644
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 c6a3a412..00000000
--- a/src/main-crb.c
+++ /dev/null
@@ -1,5963 +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 (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
- *
- * 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
-
- /* 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
-
- 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
- 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 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.
- */
-
-#define USE_DOUBLE_TILES
-#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 */
- 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;
-
- /* 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;
- }
-
- /* 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();
-}
-
-
-/*
- * 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();
-
- /* User double-clicked savefile; no savefile screen */
- no_begin_screen = TRUE;
-
- /* Play a game */
- play_game(FALSE);
-
- /* Quit */
- quit(NULL);
- }
-}
-
-
-
-
-/*
- * Menus
- *
- * The standard menus are:
- *
- * Apple (128) = { About, -, ... }
- * 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
-#define ITEM_CLOSE 1
-#define ITEM_SAVE 2
-#ifdef HAS_SCORE_MENU
-#define ITEM_SCORE 4
-#define ITEM_QUIT 5
-#else
-#define ITEM_QUIT 4
-#endif /* HAS_SCORE_MENU */
-
-/* Edit menu */
-#define MENU_EDIT 130
-#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_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);
- }
-
- /* 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_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)
- {
-
- /* 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 */
- do_cmd_save_game();
-
- break;
- }
-
-#ifdef HAS_SCORE_MENU
-
- /* Show score */
- case ITEM_SCORE:
- {
- predict_score_gui(&initialized, &game_in_progress);
-
- /* 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 */
- do_cmd_save_game();
- }
-
- /* 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_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 */
- do_cmd_save_game();
-
- /* 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)
- {
-
- 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)
- {
- /* 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
- */
-static void *hook_rnfree(void *v, size_t size)
-{
-
-#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;
-
- /* 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);
-
- /* 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();
-
- /* 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 /* MACINTOSH || MACH_O_CARBON */
-
diff --git a/src/main-gcu.c b/src/main-gcu.c
index 4e259a65..3e1d1ff0 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
-
/*
@@ -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();
@@ -851,7 +736,7 @@ 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 +749,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]);
@@ -995,7 +845,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 +853,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 +866,6 @@ errr init_gcu(int argc, char **argv)
}
-#ifdef USE_GRAPHICS
-
- /* Set graphics flag */
- use_graphics = arg_graphics;
-
-#endif
#ifdef A_COLOR
@@ -1106,12 +944,6 @@ errr init_gcu(int argc, char **argv)
/*** Low level preparation ***/
-#ifdef USE_GETCH
-
- /* Paranoia -- Assume no waiting */
- nodelay(stdscr, FALSE);
-
-#endif
/* Prepare */
raw();
diff --git a/src/main-gtk2.c b/src/main-gtk2.c
index 102a8b7b..bdf7f6a4 100644
--- a/src/main-gtk2.c
+++ b/src/main-gtk2.c
@@ -30,28 +30,15 @@
* 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.
- *
- * ZAngband has its own enhanced main-gtk.c as mentioned above, and
- * you *should* use it :-)
- *
*/
-#define USE_DOUBLE_TILES /* Mogami's bigtile patch */
-
-
#ifdef USE_GTK2
/* Force ANSI standard */
@@ -66,11 +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 <assert.h>
/*
@@ -93,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 */
/*
@@ -135,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;
};
@@ -242,42 +199,6 @@ static cptr get_default_font(int term)
#define can_save TRUE
-/*
- * 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;
-
-
-
-
-/**** Low level routines - memory allocation ****/
-
-/*
- * Hook to "release" memory
- */
-static vptr hook_rnfree(vptr v, huge size)
-{
- /* 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));
-}
-
/**** Low level routines - colours and graphics ****/
@@ -330,1799 +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);
-}
-
-
-/*
- * 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];
- }
-}
-
-
-/*
- * 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 */
- reset_visuals();
-}
-
-#endif /* USE_GRAPHICS */
@@ -2139,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;
@@ -2156,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 */
}
@@ -2294,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),
@@ -2326,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 */
/*
@@ -2708,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);
@@ -2769,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);
@@ -3064,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 */
}
@@ -3144,128 +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;
-
- /* T.o.M.E. requires this as well */
- arg_bigtile = use_bigtile;
-
- /* 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 */
/*
@@ -3650,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);
@@ -3666,9 +1279,6 @@ static errr term_data_init(term_data *td, int i)
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 */
@@ -3752,37 +1362,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,
@@ -3838,13 +1417,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);
}
}
@@ -3890,10 +1469,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);
}
}
@@ -4058,51 +1637,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 */
/*
@@ -4211,23 +1745,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 */
}
@@ -4375,12 +1892,6 @@ 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);
@@ -4399,10 +1910,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++)
@@ -4423,68 +1931,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;
- arg_bigtile = TRUE;
- 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]);
- }
-
-#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);
+ fprintf(stderr, "Ignoring option: %s", argv[i]);
}
-#endif /* USE_GRAPHICS */
/* Initialise colours */
gdk_rgb_init();
diff --git a/src/main-sdl.c b/src/main-sdl.c
index 840859e9..7a534ad5 100644
--- a/src/main-sdl.c
+++ b/src/main-sdl.c
@@ -25,11 +25,15 @@
#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>
/*************************************************
@@ -64,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
@@ -95,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;
@@ -115,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
@@ -581,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:
{
/*
@@ -607,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,
@@ -638,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 */
@@ -718,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 */
@@ -1190,7 +1107,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 */
@@ -1380,7 +1298,6 @@ void moveTerminal(int x, int y)
void bringToTop(int current)
{
term_data *td;
- term_data *tc;
int n = 0;
int i;
@@ -1555,8 +1472,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*/
@@ -1849,8 +1765,6 @@ static errr term_data_init(term_data *td, int i)
t->soft_cursor = TRUE;
/* Picture routine flags */
- t->always_pict = FALSE;
- t->higher_pict = FALSE;
t->always_text = FALSE;
/* Erase with "white space" */
@@ -1950,7 +1864,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 */
@@ -2053,25 +1967,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"))
{
@@ -2168,13 +2063,6 @@ errr init_sdl(int argc, char **argv)
/* load and render the font */
loadAndRenderFont(arg_font_name,arg_font_size);
- /* Graphics! ----
- If graphics are selected, then load graphical tiles! */
- if (arg_graphics_type != NO_GRAPHICS)
- {
- /* load graphics tiles */
- }
-
/* Initialize the working surface and crayon surface used for rendering
text in different colors. */
diff --git a/src/main-win.c b/src/main-win.c
index 2d740034..05742c86 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
@@ -167,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
@@ -250,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
@@ -443,40 +430,9 @@ 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 */
-
/*
* Full path to ANGBAND.INI
@@ -498,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;
@@ -893,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)
{
@@ -936,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);
@@ -961,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)
{
@@ -1021,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;
@@ -1083,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];
@@ -1123,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
@@ -1301,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;
}
@@ -1328,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';
@@ -1445,16 +1246,6 @@ static void term_data_redraw(term_data *td)
/*
- * Interact with the User
- */
-static errr Term_user_win(int n)
-{
- /* Success */
- return (0);
-}
-
-
-/*
* React to global changes
*/
static errr Term_xtra_win_react(void)
@@ -1509,52 +1300,9 @@ 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 */
for (i = 0; i < MAX_TERM_DATA; i++)
@@ -1680,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)
@@ -1772,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:
{
@@ -1814,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);
@@ -1877,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);
@@ -2010,197 +1680,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 ***/
@@ -2218,20 +1697,15 @@ 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 = ' ';
/* 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);
@@ -2258,7 +1732,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;
@@ -2275,7 +1749,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;
@@ -2570,52 +2044,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" */
@@ -2977,114 +2417,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 */
@@ -3126,55 +2458,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;
@@ -3454,15 +2743,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;
@@ -3666,15 +2948,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;
@@ -3833,7 +3108,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;
}
@@ -3872,7 +3151,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);
@@ -3905,7 +3184,7 @@ 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 ***/
@@ -3930,45 +3209,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); */
@@ -4025,7 +3274,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 9a106bd6..6d122744 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,15 +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 -- 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).
+ */
+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);
+}
+
+
/*
@@ -707,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 ***/
@@ -942,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;
@@ -1009,11 +1082,7 @@ 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;
-
+ ifnt->twid = ifnt->wid;
/* Success */
return (0);
@@ -1046,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))
@@ -1059,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;
@@ -1214,14 +1283,6 @@ struct term_data
infowin *win;
-#ifdef USE_GRAPHICS
-
- XImage *tiles;
-
- /* Tempory storage for overlaying tiles. */
- XImage *TmpImage;
-
-#endif
};
@@ -2104,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());
@@ -2176,11 +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);
+ /* 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;
@@ -2225,170 +2233,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 */
@@ -2527,7 +2371,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);
@@ -2539,7 +2387,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);
@@ -2656,17 +2508,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 */
@@ -2678,27 +2519,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"))
{
@@ -2708,7 +2528,7 @@ errr init_x11(int argc, char *argv[])
continue;
}
- plog_fmt("Ignoring option: %s", argv[i]);
+ fprintf(stderr, "Ignoring option: %s", argv[i]);
}
@@ -2717,7 +2537,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);
@@ -2727,8 +2551,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 */
@@ -2775,102 +2602,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 8de36a95..00000000
--- a/src/main-xaw.c
+++ /dev/null
@@ -1,1880 +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);
-}
-
-
-/*
- * 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 10500ab6..a20eb6b6 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"
@@ -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,132 +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 '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.
*
@@ -242,50 +111,18 @@ int main(int argc, char *argv[])
bool_ new_game = FALSE;
- int show_score = 0;
-
cptr mstr = NULL;
bool_ args = TRUE;
- int player_uid;
-
-
-
- /* 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 */
@@ -311,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':
{
@@ -339,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':
{
@@ -367,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,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"))
@@ -430,51 +238,25 @@ usage:
puts(" -h This help");
puts(" -n Start a new character");
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
@@ -487,9 +269,6 @@ usage:
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");
@@ -533,19 +312,6 @@ usage:
}
#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"))))
@@ -592,9 +358,6 @@ usage:
/* 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);
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 157656a9..4eabe223 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,33 @@
* 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 <boost/algorithm/string/predicate.hpp>
+
+using boost::algorithm::iequals;
/*
* Critical blow. All hits that do 95% of total possible damage,
@@ -261,7 +281,7 @@ bool_ carried_make_attack_normal(int r_idx)
if (!effect || check_hit(power, rlev))
{
/* Always disturbing */
- disturb(1, 0);
+ disturb(1);
/* Hack -- Apply "protection from evil" */
if ((p_ptr->protevil > 0) &&
@@ -1280,7 +1300,7 @@ bool_ carried_make_attack_normal(int r_idx)
case RBM_CHARGE:
/* Disturbing */
- disturb(1, 0);
+ disturb(1);
/* Message */
msg_format("%s misses you.", sym_name);
@@ -1525,7 +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);
}
}
@@ -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 4f63959d..05d91f3c 100644
--- a/src/melee2.c
+++ b/src/melee2.cc
@@ -1,30 +1,57 @@
-/* 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 "messages.h"
-#include "quark.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 <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
@@ -38,7 +65,7 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
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 */
if (r_ptr->flags7 & RF7_NO_DEATH) return FALSE;
@@ -256,10 +283,7 @@ void mon_handle_fear(monster_type *m_ptr, int dam, bool_ *fear)
*
* 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.
*/
@@ -298,61 +322,20 @@ static void remove_bad_spells(int m_idx, u32b *f4p, u32b *f5p, u32b *f6p)
/* 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;
@@ -946,7 +929,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;
@@ -961,12 +944,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(buf, TERM_WHITE);
+ message_add(s, TERM_WHITE);
p_ptr->window |= PW_MESSAGE;
}
}
@@ -1155,7 +1146,7 @@ static bool_ monst_spell_monst(int m_idx)
case 96 + 0:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_m) monster_msg("You hear a shriek.");
else monster_msg("%^s shrieks at %s.", m_name, t_name);
wake_up = TRUE;
@@ -1171,7 +1162,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_S_ANIMAL */
case 96 + 2:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons an animal!", m_name);
for (k = 0; k < 1; k++)
@@ -1188,7 +1179,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);
@@ -1200,7 +1191,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);
@@ -1212,7 +1203,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);
@@ -1224,7 +1215,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);
@@ -1238,7 +1229,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);
@@ -1249,7 +1240,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);
@@ -1262,7 +1253,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);
@@ -1275,7 +1266,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);
@@ -1288,7 +1279,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);
@@ -1301,7 +1292,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);
@@ -1314,7 +1305,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);
@@ -1327,7 +1318,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);
@@ -1340,7 +1331,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);
@@ -1353,7 +1344,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);
@@ -1366,7 +1357,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);
@@ -1379,7 +1370,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);
@@ -1392,7 +1383,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);
@@ -1405,7 +1396,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);
@@ -1418,7 +1409,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);
@@ -1431,7 +1422,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);
@@ -1444,7 +1435,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);
@@ -1457,7 +1448,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);
@@ -1470,7 +1461,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);
@@ -1483,7 +1474,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);
@@ -1496,7 +1487,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);
@@ -1509,7 +1500,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);
@@ -1522,7 +1513,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);
@@ -1535,7 +1526,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);
@@ -1548,7 +1539,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);
@@ -1561,7 +1552,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);
@@ -1572,7 +1563,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);
@@ -1584,7 +1575,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);
@@ -1596,7 +1587,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);
@@ -1608,7 +1599,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);
@@ -1620,7 +1611,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);
@@ -1632,7 +1623,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);
@@ -1645,7 +1636,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);
@@ -1657,7 +1648,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);
@@ -1693,7 +1684,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)
@@ -1712,7 +1703,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)
{
@@ -1757,7 +1748,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)
{
/* */
@@ -1803,7 +1794,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)
@@ -1824,7 +1815,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)
@@ -1844,7 +1835,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)
@@ -1864,7 +1855,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)
@@ -1883,7 +1874,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,
@@ -1894,7 +1885,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,
@@ -1905,7 +1896,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,
@@ -1916,7 +1907,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,
@@ -1934,7 +1925,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,
@@ -1945,7 +1936,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,
@@ -1956,7 +1947,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,
@@ -1967,7 +1958,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,
@@ -1978,7 +1969,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,
@@ -1989,7 +1980,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,
@@ -2001,7 +1992,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)
@@ -2025,7 +2016,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"));
@@ -2051,7 +2042,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)
@@ -2075,7 +2066,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)
@@ -2099,7 +2090,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))
@@ -2123,7 +2114,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);
@@ -2154,7 +2145,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
@@ -2185,7 +2176,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)
@@ -2232,7 +2223,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)
@@ -2250,7 +2241,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_ANIMALS */
case 160 + 3:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons some animals!", m_name);
for (k = 0; k < 4; k++)
@@ -2267,7 +2258,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;
@@ -2279,7 +2270,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;
@@ -2302,7 +2293,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);
@@ -2348,7 +2339,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)
@@ -2382,7 +2373,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_BUG */
case 160 + 13:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically codes some software bugs.", m_name);
for (k = 0; k < 6; k++)
@@ -2399,7 +2390,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_RNG */
case 160 + 14:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically codes some RNGs.", m_name);
for (k = 0; k < 6; k++)
@@ -2417,7 +2408,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_THUNDERLORD */
case 160 + 15:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a Thunderlord!", m_name);
for (k = 0; k < 1; k++)
@@ -2434,7 +2425,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_SUMMON_KIN */
case 160 + 16:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons %s %s.",
m_name, m_poss,
@@ -2457,7 +2448,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.");
@@ -2471,7 +2462,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_MONSTER */
case 160 + 18:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons help!", m_name);
for (k = 0; k < 1; k++)
@@ -2488,7 +2479,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_MONSTERS */
case 160 + 19:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons monsters!", m_name);
for (k = 0; k < 8; k++)
@@ -2505,7 +2496,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_ANT */
case 160 + 20:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons ants.", m_name);
for (k = 0; k < 6; k++)
@@ -2522,7 +2513,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_SPIDER */
case 160 + 21:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons spiders.", m_name);
for (k = 0; k < 6; k++)
@@ -2539,7 +2530,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HOUND */
case 160 + 22:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons hounds.", m_name);
for (k = 0; k < 6; k++)
@@ -2556,7 +2547,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HYDRA */
case 160 + 23:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons hydras.", m_name);
for (k = 0; k < 6; k++)
@@ -2573,7 +2564,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_ANGEL */
case 160 + 24:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons an angel!", m_name);
for (k = 0; k < 1; k++)
@@ -2590,7 +2581,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_DEMON */
case 160 + 25:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a demon!", m_name);
for (k = 0; k < 1; k++)
@@ -2607,7 +2598,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_UNDEAD */
case 160 + 26:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons an undead adversary!", m_name);
for (k = 0; k < 1; k++)
@@ -2624,7 +2615,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_DRAGON */
case 160 + 27:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a dragon!", m_name);
for (k = 0; k < 1; k++)
@@ -2641,7 +2632,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HI_UNDEAD */
case 160 + 28:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons greater undead!", m_name);
for (k = 0; k < 8; k++)
@@ -2661,7 +2652,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HI_DRAGON */
case 160 + 29:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons ancient dragons!", m_name);
for (k = 0; k < 8; k++)
@@ -2681,7 +2672,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_WRAITH */
case 160 + 30:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a wraith!", m_name);
@@ -2701,7 +2692,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_UNIQUE */
case 160 + 31:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons special opponents!", m_name);
for (k = 0; k < 8; k++)
@@ -2905,14 +2896,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
@@ -2926,12 +2909,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
@@ -2940,7 +2917,7 @@ 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;
@@ -2963,9 +2940,6 @@ bool_ make_attack_spell(int m_idx)
/* Assume "normal" target */
bool_ normal = TRUE;
- /* Assume "projectable" */
- bool_ direct = TRUE;
-
/* Target location */
if (m_ptr->target > -1)
{
@@ -3003,9 +2977,6 @@ bool_ make_attack_spell(int m_idx)
/* Sometimes forbid inate attacks (breaths) */
if (rand_int(100) >= (chance * 2)) no_inate = TRUE;
- /* XXX XXX XXX Handle "track_target" option (?) */
-
-
/* Hack -- require projectable player */
if (normal)
{
@@ -3152,8 +3123,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;
@@ -3168,7 +3138,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++)
@@ -3182,7 +3152,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,
@@ -3194,7 +3164,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));
@@ -3205,7 +3175,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));
@@ -3216,7 +3186,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));
@@ -3227,7 +3197,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));
@@ -3238,7 +3208,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,
@@ -3250,7 +3220,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,
@@ -3262,7 +3232,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,
@@ -3274,7 +3244,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,
@@ -3286,7 +3256,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,
@@ -3299,7 +3269,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,
@@ -3311,7 +3281,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,
@@ -3323,7 +3293,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,
@@ -3335,7 +3305,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,
@@ -3347,7 +3317,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,
@@ -3359,7 +3329,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,
@@ -3371,7 +3341,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,
@@ -3383,7 +3353,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,
@@ -3395,7 +3365,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,
@@ -3406,7 +3376,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,
@@ -3417,7 +3387,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,
@@ -3428,7 +3398,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,
@@ -3440,7 +3410,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,
@@ -3451,7 +3421,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,
@@ -3462,7 +3432,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,
@@ -3473,7 +3443,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);
@@ -3484,7 +3454,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,
@@ -3496,7 +3466,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);
@@ -3507,7 +3477,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,
@@ -3520,7 +3490,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,
@@ -3532,7 +3502,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,
@@ -3544,7 +3514,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,
@@ -3556,7 +3526,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,
@@ -3568,7 +3538,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,
@@ -3580,7 +3550,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,
@@ -3592,7 +3562,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.");
@@ -3604,7 +3574,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,
@@ -3615,7 +3585,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,
@@ -3627,13 +3597,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);
@@ -3656,7 +3625,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);
@@ -3669,7 +3638,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)
@@ -3685,8 +3654,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.");
@@ -3722,8 +3690,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.");
@@ -3771,8 +3738,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)
@@ -3790,8 +3756,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)
@@ -3809,8 +3774,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)
@@ -3828,8 +3792,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)
@@ -3847,7 +3810,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));
@@ -3859,7 +3822,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));
@@ -3871,7 +3834,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));
@@ -3883,7 +3846,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));
@@ -3902,7 +3865,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);
@@ -3914,7 +3877,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));
@@ -3925,7 +3888,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);
@@ -3936,7 +3899,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));
@@ -3947,7 +3910,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));
@@ -3959,7 +3922,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));
@@ -3970,8 +3933,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)
@@ -3993,8 +3955,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)
@@ -4016,8 +3977,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)
@@ -4039,8 +3999,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)
{
@@ -4061,8 +4020,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 +4044,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);
@@ -4116,7 +4074,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)
{
@@ -4137,7 +4095,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_HEAL */
case 160 + 2:
{
- disturb(1, 0);
+ disturb(1);
/* Message */
if (blind)
@@ -4184,7 +4142,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)
@@ -4201,7 +4159,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++)
@@ -4215,7 +4173,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;
@@ -4224,7 +4182,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;
@@ -4233,8 +4191,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;
@@ -4243,8 +4200,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;
@@ -4253,8 +4209,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)
@@ -4276,8 +4231,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);
@@ -4287,8 +4241,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();
@@ -4298,8 +4251,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)
@@ -4320,7 +4272,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++)
@@ -4334,7 +4286,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++)
@@ -4348,7 +4300,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++)
@@ -4362,7 +4314,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,
@@ -4382,7 +4334,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.");
@@ -4393,7 +4345,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++)
@@ -4407,7 +4359,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++)
@@ -4421,7 +4373,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++)
@@ -4435,7 +4387,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++)
@@ -4449,7 +4401,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++)
@@ -4463,7 +4415,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++)
@@ -4477,7 +4429,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++)
@@ -4491,7 +4443,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++)
@@ -4505,7 +4457,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++)
@@ -4519,7 +4471,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++)
@@ -4533,7 +4485,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++)
@@ -4550,7 +4502,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++)
@@ -4567,7 +4519,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);
@@ -4587,7 +4539,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++)
@@ -5108,10 +5060,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;
}
}
@@ -5469,7 +5423,6 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
/* 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;
@@ -5541,7 +5494,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)
@@ -5946,7 +5899,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);
@@ -6137,7 +6090,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);
}
}
}
@@ -6176,7 +6129,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);
}
}
}
@@ -6392,41 +6345,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);
}
}
}
@@ -6741,7 +6692,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;
@@ -6982,8 +6933,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;
@@ -7043,7 +6992,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 */
@@ -7053,16 +7002,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;
@@ -7142,8 +7089,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);
@@ -7157,18 +7103,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);
}
}
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.c b/src/messages.cc
index e88cf58e..a4ce949d 100644
--- a/src/messages.c
+++ b/src/messages.cc
@@ -1,6 +1,10 @@
-#include "messages.h"
+#include "messages.hpp"
-#include "angband.h"
+#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")
@@ -83,10 +87,10 @@ static char *message__buf;
void message_init()
{
/* Message variables */
- C_MAKE(message__ptr, MESSAGE_MAX, u16b);
- C_MAKE(message__color, MESSAGE_MAX, byte);
- C_MAKE(message__count, MESSAGE_MAX, u16b);
- C_MAKE(message__buf, MESSAGE_BUF, char);
+ 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;
diff --git a/src/messages.h b/src/messages.h
deleted file mode 100644
index 401c5727..00000000
--- a/src/messages.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef H_f6dac2dc_0449_4764_9942_1c1fe7a70bc4
-#define H_f6dac2dc_0449_4764_9942_1c1fe7a70bc4
-
-#include "h-type.h"
-
-void message_init();
-s16b message_num();
-cptr message_str(int age);
-byte message_color(int age);
-byte message_type(int age);
-void message_add(cptr msg, byte color);
-
-#endif
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.c b/src/mimic.cc
index 90c8a62a..b888ec52 100644
--- a/src/mimic.c
+++ b/src/mimic.cc
@@ -1,5 +1,38 @@
-#include "angband.h"
-#include <assert.h>
+#include "mimic.hpp"
+
+#include "player_type.hpp"
+#include "skill_type.hpp"
+#include "stats.hpp"
+#include "variable.hpp"
+#include "xtra1.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()
{
@@ -371,7 +404,7 @@ static s32b fire_elemental_calc()
/*
* Mimicry forms
*/
-mimic_form_type mimic_forms[MIMIC_FORMS_MAX] =
+static mimic_form_type mimic_forms[MIMIC_FORMS_MAX] =
{
{ /* 0 */
{ MODULE_TOME, MODULE_THEME, -1 },
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.cc
index 8376e3fb..611afe63 100644
--- a/src/modules.c
+++ b/src/modules.cc
@@ -1,7 +1,3 @@
-/* File: modules.c */
-
-/* Purpose: T-engine modules */
-
/*
* Copyright (c) 2003 DarkGod
*
@@ -10,26 +6,102 @@
* included in all such copies.
*/
-#include "angband.h"
+#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;
-static void module_reset_dir_aux(cptr *dir, cptr new_path)
+/*
+ * 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);
- string_free(*dir);
- *dir = string_make(buf);
+ 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));
}
-void module_reset_dir(cptr dir, cptr new_path)
+static void module_reset_dir(cptr dir, cptr new_path)
{
- cptr *d = 0;
+ char **d = 0;
char buf[1025];
if (!strcmp(dir, "core")) d = &ANGBAND_DIR_CORE;
@@ -39,37 +111,30 @@ void module_reset_dir(cptr dir, cptr new_path)
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 (
!strcmp(dir, "user") ||
- !strcmp(dir, "note") ||
- !strcmp(dir, "cmov"))
+ !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);
- string_free(*d);
- *d = string_make(buf);
+
+ 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));
}
}
-#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);
@@ -79,8 +144,8 @@ void module_reset_dir(cptr dir, cptr new_path)
/* 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);
+ free(*d);
+ *d = strdup(buf);
}
}
@@ -167,7 +232,6 @@ static void init_module(module_type *module_ptr)
module_reset_dir("help", dir);
module_reset_dir("note", dir);
module_reset_dir("save", dir);
- module_reset_dir("scpt", dir);
module_reset_dir("user", dir);
module_reset_dir("pref", dir);
}
@@ -220,7 +284,8 @@ bool_ select_module()
{
/* Process the module */
init_module(&modules[sel]);
- game_module = string_make(modules[sel].meta.name);
+
+ game_module = modules[sel].meta.name;
activate_module(sel);
@@ -290,7 +355,8 @@ bool_ select_module()
/* Process the module */
init_module(&modules[x]);
- game_module = string_make(modules[x].meta.name);
+
+ game_module = modules[x].meta.name;
activate_module(x);
@@ -320,14 +386,13 @@ static bool_ dleft(byte c, cptr str, int y, int o)
time = time + 1;
if (time >= 4)
{
- Term_xtra(TERM_XTRA_DELAY, 1);
+ sleep_for(milliseconds(1));
time = 0;
}
Term_redraw_section(a - 1, y, a, y);
a = a + 1;
- inkey_scan = TRUE;
- if (inkey()) {
+ if (inkey_scan()) {
return TRUE;
}
}
@@ -340,9 +405,9 @@ static bool_ dleft(byte c, cptr str, int y, int o)
static bool_ dright(byte c, cptr str, int y, int o)
{
- int x = 39 - (strlen(str) / 2) + o;
- int i = 1;
- while (i <= strlen(str))
+ int 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;
@@ -354,20 +419,17 @@ static bool_ dright(byte c, cptr str, int y, int o)
Term_putch(a, y, c, str[i-1]);
time = time + 1;
if (time >= 4) {
- Term_xtra(TERM_XTRA_DELAY, 1);
+ sleep_for(milliseconds(1));
time = 0;
}
Term_redraw_section(a, y, a + 1, y);
a = a - 1;
- inkey_scan = TRUE;
- if (inkey()) {
+ if (inkey_scan()) {
return TRUE;
}
}
}
-
- i = i + 1;
}
return FALSE;
}
@@ -403,7 +465,6 @@ static bool_ show_intro(intro_text intro_texts[])
/* Wait for key */
Term_putch(0, 0, TERM_DARK, 32);
- inkey_scan = FALSE;
inkey();
/* Continue */
@@ -419,7 +480,7 @@ void tome_intro()
{ 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, }
+ { NULL , TERM_WHITE , NULL, 0, 0, }
};
intro_text intro2[] =
{
@@ -432,7 +493,7 @@ void tome_intro()
{ 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, }
+ { NULL , TERM_WHITE , NULL, 0, 0, }
};
screen_save();
@@ -467,7 +528,7 @@ void theme_intro()
{ 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, },
+ { NULL , TERM_WHITE , NULL, 0, 0, },
};
struct intro_text intro2[] =
{
@@ -480,7 +541,7 @@ void theme_intro()
{ 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, },
+ { NULL , TERM_WHITE , NULL, 0, 0, },
};
screen_save();
@@ -719,7 +780,7 @@ static bool_ theme_push_past(void *data, void *in_, void *out_)
if (m_ptr->status >= MSTATUS_NEUTRAL)
{
- if ((cave_floor_bold(p->y, p->x) == TRUE) ||
+ if (cave_floor_bold(p->y, p->x) ||
(mr_ptr->flags2 == RF2_PASS_WALL))
{
char buf[128];
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/monster1.c b/src/monster1.cc
index 68882d27..77f916a7 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.
@@ -337,7 +342,7 @@ static void roff_aux(int r_idx, int ego, int remem)
char buf[2048];
/* Simple method */
- strcpy(buf, r_text + r_ptr->text);
+ strcpy(buf, r_ptr->text);
/* Dump it */
text_out(buf);
@@ -373,31 +378,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;
}
@@ -523,16 +514,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");
@@ -551,7 +542,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));
}
}
@@ -1087,9 +1078,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;
@@ -1517,7 +1508,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;
}
}
@@ -1548,24 +1539,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, "'):");
}
@@ -1616,9 +1611,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);
@@ -1663,7 +1660,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];
@@ -1674,7 +1671,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];
@@ -1685,7 +1682,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];
@@ -1696,7 +1693,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];
@@ -1707,7 +1704,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];
@@ -1718,7 +1715,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];
@@ -1729,7 +1726,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];
@@ -1740,7 +1737,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];
@@ -1751,7 +1748,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];
@@ -1764,7 +1761,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];
@@ -1777,7 +1774,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];
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 5ed4758a..513ebf03 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,56 @@
* 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 <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 +67,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 +134,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 +163,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 +207,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 +217,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 +230,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 +254,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;
}
@@ -239,7 +277,7 @@ monster_race* race_info_idx(int r_idx, int ego)
if (!ego) return r_ptr;
/* Copy the base monster */
- COPY(nr_ptr, r_ptr, monster_race);
+ *nr_ptr = *r_ptr;
/* Adjust the values */
for (i = 0; i < 4; i++)
@@ -316,6 +354,11 @@ monster_race* race_info_idx(int r_idx, int ego)
return nr_ptr;
}
+monster_race* race_inf(monster_type *m_ptr)
+{
+ return race_info_idx(m_ptr->r_idx, m_ptr->ego);
+}
+
static cptr horror_desc[MAX_HORROR] =
{
"abominable",
@@ -383,18 +426,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,21 +433,15 @@ 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;
+ int y = m_ptr->fy;
+ int x = m_ptr->fx;
/* Hack -- Reduce the racial counter */
r_ptr->cur_num--;
@@ -438,7 +463,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 +478,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 +511,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 +567,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 +605,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 +617,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();
}
@@ -739,15 +737,8 @@ void wipe_m_list(void)
/* Monster is gone */
cave[m_ptr->fy][m_ptr->fx].m_idx = 0;
- /* Delete mind & special race if needed */
- if (m_ptr->sr_ptr)
- KILL(m_ptr->sr_ptr, monster_race);
- 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" */
@@ -1226,19 +1217,24 @@ 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);
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 +1253,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
{
@@ -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,7 +1527,7 @@ 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;
@@ -1595,7 +1596,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;
}
@@ -1878,7 +1879,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 +1890,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 +1922,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 +1930,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 +1957,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 +1978,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 +2024,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 +2108,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;
@@ -2125,25 +2124,15 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
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 +2140,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 +2147,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 +2170,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 +2177,43 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
if ((cave[y][x].feat >= FEAT_PATTERN_START)
&& (cave[y][x].feat <= FEAT_PATTERN_XTRA2))
{
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
/* Paranoia */
if (!r_idx)
{
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
/* Paranoia */
if (!r_ptr->name)
{
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
/* Are we allowed to continue ? */
- if (process_hooks(HOOK_NEW_MONSTER, "(d)", r_idx))
{
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
- return 0;
+ 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)
{
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
/* Now could we generate an Ego Monster */
/* Grab the special race if needed */
- if (place_monster_one_race)
- {
- r_ptr = place_monster_one_race;
- }
- else
- {
- r_ptr = race_info_idx(r_idx, ego);
- }
+ r_ptr = race_info_idx(r_idx, ego);
if (!monster_can_cross_terrain(cave[y][x].feat, r_ptr))
{
if (wizard) cmsg_print(TERM_L_RED, "WARNING: Refused monster: cannot cross terrain");
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2248,7 +2221,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 +2228,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 +2235,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 +2243,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 +2250,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 +2258,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 +2266,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 +2276,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 +2286,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,7 +2297,7 @@ 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);
}
@@ -2345,7 +2311,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
/* Mega-Hack -- catch "failure" */
if (!c_ptr->m_idx)
{
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2357,10 +2322,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
m_ptr->r_idx = r_idx;
m_ptr->ego = ego;
- /* No special, no mind */
- m_ptr->sr_ptr = place_monster_one_race;
- m_ptr->mind = NULL;
-
/* Place the monster at the location */
m_ptr->fy = y;
m_ptr->fx = x;
@@ -2383,7 +2344,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;
@@ -2578,7 +2539,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;
@@ -2655,8 +2616,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
r_ptr->on_saved = TRUE;
}
- place_monster_one_race = NULL;
-
/* Processs hooks */
{
hook_new_monster_end_in in = { m_ptr };
@@ -2745,7 +2704,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;
@@ -2824,7 +2783,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 */
@@ -2882,7 +2841,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)) ||
@@ -3068,7 +3027,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];
@@ -3233,7 +3192,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;
}
@@ -3282,14 +3241,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;
}
@@ -3302,21 +3261,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;
}
@@ -3742,25 +3701,21 @@ 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)
@@ -3773,11 +3728,12 @@ void message_pain(int m_idx, int dam)
/* Get the monster name */
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;
}
@@ -3792,76 +3748,76 @@ void message_pain(int m_idx, int dam)
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);
}
}
@@ -3884,7 +3840,7 @@ void update_smart_learn(int m_idx, int what)
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 */
@@ -4003,26 +3959,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);
@@ -4035,5 +3987,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..ffe7b3cd
--- /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"
+
+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 monster_race* race_info_idx(int r_idx, int ego);
+extern monster_race* race_inf(monster_type *m_ptr);
+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, monster_race *r_ptr);
diff --git a/src/monster3.c b/src/monster3.cc
index a2b5fb38..e7e8e6da 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,24 @@
* 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"
/*
* Is the mon,ster in friendly state(pet, friend, ..)
@@ -189,7 +202,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 +277,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 +345,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 +356,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 +389,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.hpp b/src/monster_type.hpp
new file mode 100644
index 00000000..912c97d0
--- /dev/null
+++ b/src/monster_type.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_blow.hpp"
+
+#include <cassert>
+#include <vector>
+
+/**
+ * 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 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..26960073 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
@@ -89,7 +93,7 @@ void add_note(char *note, char code)
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 */
@@ -99,7 +103,6 @@ void add_note(char *note, char code)
/* 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 */
@@ -135,7 +138,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,
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/object1.c b/src/object1.cc
index dd27c27e..95cd0522 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,10 +6,55 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "quark.h"
-#include "spell_type.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 <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".
@@ -26,6 +67,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
*/
@@ -278,7 +325,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];
@@ -337,39 +384,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()"
@@ -680,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
*/
@@ -759,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)
{
@@ -941,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];
@@ -1027,7 +984,7 @@ 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)
{
object_kind *k_ptr = &k_info[o_ptr->k_idx];
@@ -1322,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 = "";
@@ -1397,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;
}
@@ -1414,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~";
@@ -1422,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;
}
@@ -1432,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~";
@@ -1444,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~";
@@ -1456,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~";
@@ -1470,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;
}
@@ -1481,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 \"#\"";
@@ -1501,7 +1462,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
{
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~";
@@ -1516,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~";
@@ -1585,9 +1546,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;
}
@@ -1596,7 +1557,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;
}
@@ -1605,7 +1566,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;
}
@@ -1614,7 +1575,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;
@@ -1662,7 +1622,7 @@ 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;
+ basenm = k_ptr->name;
if (o_ptr->sval == 255)
{
modstr = spell_type_name(spell_at(o_ptr->pval));
@@ -1673,23 +1633,16 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* 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 */
@@ -1712,11 +1665,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;
}
}
@@ -1793,12 +1746,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, ' ');
}
}
@@ -1871,12 +1824,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, ' ');
}
}
@@ -1917,8 +1870,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);
}
}
@@ -1959,7 +1911,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 */
@@ -1999,7 +1953,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);
}
}
@@ -2012,12 +1966,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);
}
}
}
@@ -2043,16 +1997,15 @@ 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);
@@ -2092,9 +2045,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, ")");
}
}
@@ -2557,8 +2514,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];
}
@@ -2581,14 +2538,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;
@@ -2803,18 +2757,9 @@ void display_ammo_damage(object_type *o_ptr)
}
/*
- * Output spell description
- */
-static void print_device_desc_callback(void *data, cptr text)
-{
- text_out("\n");
- text_out(text);
-}
-
-/*
* Describe a magic stick powers
*/
-void describe_device(object_type *o_ptr)
+static void describe_device(object_type *o_ptr)
{
char buf[128];
@@ -2824,24 +2769,29 @@ void describe_device(object_type *o_ptr)
/* Enter device mode */
set_stick_mode(o_ptr);
+ // Spell reference
+ auto spell = spell_at(o_ptr->pval2);
+
text_out("\nSpell description:\n");
- spell_type_description_foreach(spell_at(o_ptr->pval2),
- print_device_desc_callback,
- NULL);
+ spell_type_description_foreach(spell,
+ [] (std::string const &text) -> void {
+ text_out("\n");
+ text_out(text.c_str());
+ });
text_out("\nSpell level: ");
sprintf(buf, FMTs32b, get_level(o_ptr->pval2, 50, 0));
text_out_c(TERM_L_BLUE, buf);
text_out("\nMinimum Magic Device level to increase spell level: ");
- text_out_c(TERM_L_BLUE, format("%d", spell_type_skill_level(spell_at(o_ptr->pval2))));
+ text_out_c(TERM_L_BLUE, format("%d", spell_type_skill_level(spell)));
text_out("\nSpell fail: ");
- sprintf(buf, FMTs32b, spell_chance(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, spell_type_info(spell_at(o_ptr->pval2)));
+ text_out_c(TERM_YELLOW, spell_type_info(spell));
/* Leave device mode */
unset_stick_mode();
@@ -2862,15 +2812,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;
}
@@ -2882,7 +2842,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];
@@ -2934,7 +2894,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");
}
@@ -2942,14 +2902,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");
}
}
@@ -3041,7 +2999,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. ");
}
@@ -3858,12 +3816,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)
{
@@ -3923,7 +3881,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;
@@ -3945,7 +3903,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;
@@ -3966,7 +3924,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;
@@ -3996,16 +3954,12 @@ 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 + rp_name;
+ cptr race_name = rp_ptr->title;
if (streq(race_name, "Dragon") ||
streq(race_name, "Eagle"))
@@ -4186,7 +4140,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);
}
@@ -4194,7 +4148,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;
@@ -4299,7 +4253,7 @@ cptr mention_use(int i)
*/
cptr describe_use(int i)
{
- cptr p;
+ cptr p = nullptr;
switch (i)
{
@@ -4397,45 +4351,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());
}
@@ -4445,7 +4396,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());
}
@@ -4472,7 +4423,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;
@@ -4524,7 +4475,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;
@@ -4613,8 +4564,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);
@@ -4630,20 +4583,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);
+ show_inven_aux(FALSE, FALSE, filter);
}
-void show_equip()
+void show_inven_full()
{
- show_equip_aux(FALSE, FALSE);
+ item_tester_full = true;
+ show_inven(object_filter::True());
+ item_tester_full = false;
+}
+
+static void show_equip(object_filter_t const &filter)
+{
+ show_equip_aux(FALSE, FALSE, filter);
+}
+
+void show_equip_full()
+{
+ item_tester_full = true;
+ show_equip(object_filter::True());
+ item_tester_full = false;
}
/*
* Display the equipment.
*/
-void show_equip_aux(bool_ mirror, bool_ everything)
+void show_equip_aux(bool_ mirror, bool_ everything, object_filter_t const &filter)
{
int i, j, k, l;
int row, col, len, lim, idx;
@@ -4730,7 +4697,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;
@@ -4754,7 +4721,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;
@@ -4849,8 +4816,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);
@@ -4977,16 +4946,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);
}
@@ -5056,61 +5025,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;
@@ -5125,8 +5078,6 @@ 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;
@@ -5137,7 +5088,9 @@ void show_floor(int y, int x)
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++)
@@ -5212,8 +5165,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 = ' ';
@@ -5226,7 +5178,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;
@@ -5238,7 +5189,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;
@@ -5257,28 +5208,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);
}
@@ -5289,7 +5228,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;
@@ -5312,8 +5250,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 */
@@ -5324,19 +5262,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 ? std::move(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;
@@ -5345,7 +5280,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)
@@ -5435,7 +5370,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
n2 = I2A(i2);
/* Redraw */
- show_inven();
+ show_inven(filter);
}
/* Equipment screen */
@@ -5446,7 +5381,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 */
@@ -5460,7 +5395,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 */
@@ -5526,8 +5461,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,");
}
@@ -5680,7 +5615,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;
@@ -5739,7 +5674,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;
@@ -5761,11 +5696,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)
+ {
+ break;
+ }
+ // Find by name
+ if (auto i = select_by_name(filter))
{
- (*cp) = i;
+ (*cp) = *i;
item = TRUE;
done = TRUE;
}
@@ -5822,7 +5761,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;
@@ -5854,12 +5793,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)
{
@@ -5947,17 +5880,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);
@@ -6029,7 +5961,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);
@@ -6043,21 +5975,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)
{
@@ -6065,6 +5995,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 */
@@ -6074,51 +6005,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) */
- i = weight_limit();
+ /* Extract the "weight limit" (in tenth pounds) */
+ int i = weight_limit();
- /* Calculate current encumbarance */
- j = calc_total_weight();
+ /* Calculate current encumbarance */
+ int j = calc_total_weight();
- /* Apply encumbarance from weight */
- if (j > i / 2) old_enc = ((j - (i / 2)) / (i / 10));
+ /* Apply encumbarance from weight */
+ int old_enc = 0;
+ 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 */
- if (j > i / 2) new_enc = ((j - (i / 2)) / (i / 10));
+ /* Apply encumbarance from weight */
+ int new_enc = 0;
+ 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 */
@@ -6149,10 +6064,6 @@ 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 };
@@ -6199,60 +6110,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();
+ /* Copy list of objects since we're going to manipulate the list itself */
+ auto const object_idxs(c_ptr->o_idxs);
- /* 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();
-
- /* 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)
@@ -6261,139 +6131,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);
}
+ }
- /* Count non-gold */
- floor_num++;
+ /* Sense floor tile */
+ sense_objects(floor_object_idxs);
+}
+
+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;
@@ -6418,7 +6323,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];
@@ -6427,7 +6332,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;
@@ -6488,7 +6393,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;
@@ -6535,7 +6440,7 @@ void gain_flag_group_flag(object_type *o_ptr, bool_ silent)
break;
}
- if (!silent)
+ /* Message */
{
char o_name[80];
@@ -6572,13 +6477,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
@@ -6607,8 +6512,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);
@@ -6626,10 +6537,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);
@@ -6661,7 +6577,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];
@@ -6690,7 +6606,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 b82691ea..b0e33365 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,9 +6,44 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "spell_type.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 <algorithm>
+#include <cassert>
+#include <type_traits>
+#include <vector>
/*
* Calculate the player's total inventory weight.
@@ -35,123 +66,36 @@ s32b calc_total_weight(void)
*/
void excise_object_idx(int o_idx)
{
- object_type *j_ptr;
-
- s16b this_o_idx, next_o_idx = 0;
-
- s16b prev_o_idx = 0;
-
+ /* Function to remove from list */
+ auto remove_it = [o_idx](std::vector<s16b> *v) -> void {
+ v->erase(
+ std::remove(
+ v->begin(),
+ v->end(),
+ o_idx),
+ v->end());
+ };
/* Object */
- j_ptr = &o_list[o_idx];
+ object_type *o_ptr = &o_list[o_idx];
/* Monster */
- if (j_ptr->held_m_idx)
+ if (o_ptr->held_m_idx)
{
- monster_type *m_ptr;
-
/* Monster */
- m_ptr = &m_list[j_ptr->held_m_idx];
-
- /* Scan all objects in the grid */
- for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
-
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Done */
- if (this_o_idx == o_idx)
- {
- /* No previous */
- if (prev_o_idx == 0)
- {
- /* Remove from list */
- m_ptr->hold_o_idx = next_o_idx;
- }
-
- /* Real previous */
- else
- {
- object_type *k_ptr;
-
- /* Previous object */
- k_ptr = &o_list[prev_o_idx];
-
- /* Remove from list */
- k_ptr->next_o_idx = next_o_idx;
- }
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- /* Forget next pointer */
- o_ptr->next_o_idx = 0;
-
- /* Done */
- break;
- }
-
- /* Save prev_o_idx */
- prev_o_idx = this_o_idx;
- }
+ /* Remove object from list of held objects, if present. */
+ remove_it(&m_ptr->hold_o_idxs);
}
-
/* Dungeon */
else
{
- cave_type *c_ptr;
-
- int y = j_ptr->iy;
- int x = j_ptr->ix;
-
/* Grid */
- c_ptr = &cave[y][x];
-
- /* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
-
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Done */
- if (this_o_idx == o_idx)
- {
- /* No previous */
- if (prev_o_idx == 0)
- {
- /* Remove from list */
- c_ptr->o_idx = next_o_idx;
- }
-
- /* Real previous */
- else
- {
- object_type *k_ptr;
-
- /* Previous object */
- k_ptr = &o_list[prev_o_idx];
-
- /* Remove from list */
- k_ptr->next_o_idx = next_o_idx;
- }
+ 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);
}
}
@@ -197,28 +141,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);
@@ -228,7 +161,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);
@@ -240,76 +173,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];
@@ -504,13 +405,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 */
@@ -526,11 +425,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" */
@@ -807,6 +706,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));
+}
+
/*
@@ -818,6 +728,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;
+}
/*
@@ -830,12 +747,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];
@@ -899,7 +824,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;
@@ -1135,7 +1060,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;
@@ -1449,7 +1374,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;
@@ -1505,7 +1430,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;
@@ -1710,9 +1635,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 */
}
@@ -1818,13 +1740,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);
@@ -1904,7 +1819,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));
}
@@ -1914,7 +1830,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;
}
@@ -1926,7 +1842,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;
@@ -2383,17 +2299,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;
@@ -2402,7 +2316,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)
{
@@ -2438,16 +2352,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)
@@ -2483,12 +2395,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;
@@ -2525,8 +2435,6 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good)
}
}
- C_FREE(ok_ego, max_e_idx, int);
-
/* Return */
return (ret);
}
@@ -2607,8 +2515,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:
@@ -2754,8 +2660,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:
@@ -2837,8 +2741,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:
@@ -3228,31 +3130,6 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
}
/*
- * Get a spell for a given stick(wand, staff, rod)
- */
-long get_random_stick(byte tval, int level)
-{
- int tries;
-
- for (tries = 0; tries < 1000; tries++)
- {
- long spell_idx = rand_int(school_spells_count);
- spell_type *spell = spell_at(spell_idx);
- device_allocation *device_allocation = 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;
-}
-
-
-/*
* Randomized level
*/
static int randomized_level_in_range(range_type *range, int level)
@@ -3321,8 +3198,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:
@@ -3434,8 +3309,7 @@ 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 = get_random_stick(TV_WAND, dun_level);
-
+ auto spl = get_random_stick(TV_WAND, dun_level);
if (spl == -1)
{
spl = MANATHRUST;
@@ -4010,8 +3884,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];
@@ -4112,15 +3985,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;
@@ -4286,7 +4155,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]))
@@ -4419,7 +4288,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;
@@ -4444,7 +4313,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];
@@ -4637,7 +4506,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];
@@ -4674,9 +4542,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;
}
@@ -4685,7 +4550,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];
@@ -4825,7 +4690,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;
@@ -4995,10 +4860,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);
@@ -5010,11 +4873,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);
@@ -5084,6 +4944,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);
@@ -5143,11 +5007,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);
@@ -5183,10 +5044,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];
@@ -5266,15 +5123,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;
@@ -5286,9 +5138,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;
@@ -5375,15 +5224,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))
@@ -5400,6 +5244,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 */
@@ -5446,11 +5291,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;
@@ -5817,7 +5659,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;
@@ -5990,7 +5832,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 */
@@ -6374,72 +6215,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))
@@ -6447,27 +6233,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);
@@ -6479,11 +6263,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);
@@ -6679,13 +6460,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..40a77589
--- /dev/null
+++ b/src/object_kind.hpp
@@ -0,0 +1,86 @@
+#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 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) */
+};
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_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 afc59350..00000000
--- a/src/plots.c
+++ /dev/null
@@ -1,403 +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 <assert.h>
-
-#include "messages.h"
-#include "quark.h"
-
-/******** Hooks stuff *********/
-FILE *hook_file;
-
-#define MAX_ARGS 50
-
-static hooks_chain *hooks_heads[MAX_HOOKS];
-
-/* Wipe hooks and init them with quest hooks */
-void wipe_hooks()
-{
- int i;
-
- for (i = 0; i < MAX_HOOKS; i++)
- {
- hooks_heads[i] = NULL;
- }
-}
-void init_hooks()
-{
- int i;
-
- for (i = 0; i < MAX_Q_IDX; i++)
- {
- if (quest[i].init != NULL)
- {
- quest[i].init(i);
- }
- }
-}
-
-void dump_hooks(int h_idx)
-{
- int min = 0, max = MAX_HOOKS, i;
-
- if (h_idx != -1)
- {
- min = h_idx;
- max = h_idx + 1;
- }
-
- for (i = min; i < max; i++)
- {
- hooks_chain *c = hooks_heads[i];
-
- /* Find it */
- while (c != NULL)
- {
- msg_format("%s(%s)", c->name, (c->type == HOOK_TYPE_C) ? "C" : "Lua");
-
- c = c->next;
- }
- }
-}
-
-/* Check a hook */
-bool_ check_hook(int h_idx)
-{
- hooks_chain *c = hooks_heads[h_idx];
-
- return (c != NULL);
-}
-
-/* Add a hook */
-hooks_chain* add_hook(int h_idx, hook_type hook, cptr name)
-{
- hooks_chain *new_, *c = hooks_heads[h_idx];
-
- /* Find it */
- while ((c != NULL) && (strcmp(c->name, name)))
- {
- c = c->next;
- }
-
- /* If not already in the list, add it */
- if (c == NULL)
- {
- MAKE(new_, hooks_chain);
- new_->hook = hook;
- sprintf(new_->name, "%s", name);
- new_->next = hooks_heads[h_idx];
- hooks_heads[h_idx] = new_;
- return (new_);
- }
- else return (c);
-}
-
-void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data)
-{
- hooks_chain *c = add_hook(h_idx, NULL, name);
- c->hook_f = hook_f;
- c->hook_data = data;
- c->type = HOOK_TYPE_NEW;
-}
-
-/* Remove a hook */
-void del_hook(int h_idx, hook_type hook)
-{
- hooks_chain *c = hooks_heads[h_idx], *p = NULL;
-
- /* Find it */
- while ((c != NULL) && (c->hook != hook))
- {
- p = c;
- c = c->next;
- }
-
- /* Remove it */
- if (c != NULL)
- {
- if (p == NULL)
- {
- hooks_heads[h_idx] = c->next;
- FREE(c, hooks_chain);
- }
- else
- {
- p->next = c->next;
- FREE(c, hooks_chain);
- }
- }
-}
-
-void del_hook_name(int h_idx, cptr name)
-{
- hooks_chain *c = hooks_heads[h_idx], *p = NULL;
-
- /* Find it */
- while ((c != NULL) && (strcmp(c->name, name)))
- {
- p = c;
- c = c->next;
- }
-
- /* Remove it */
- if (c != NULL)
- {
- if (p == NULL)
- {
- hooks_heads[h_idx] = c->next;
- FREE(c, hooks_chain);
- }
- else
- {
- p->next = c->next;
- FREE(c, hooks_chain);
- }
- }
-}
-
-/* get the next argument */
-static hook_return param_pile[MAX_ARGS];
-static int get_next_arg_pos = 0;
-static int get_next_arg_pile_pos = 0;
-s32b get_next_arg(char *fmt)
-{
- while (TRUE)
- {
- switch (fmt[get_next_arg_pos++])
- {
- case 'd':
- case 'l':
- return (param_pile[get_next_arg_pile_pos++].num);
- case ')':
- get_next_arg_pos--;
- return 0;
- case '(':
- case ',':
- break;
- }
- }
-}
-char* get_next_arg_str(char *fmt)
-{
- while (TRUE)
- {
- switch (fmt[get_next_arg_pos++])
- {
- case 's':
- return (char*)(param_pile[get_next_arg_pile_pos++].str);
- case ')':
- get_next_arg_pos--;
- return 0;
- case '(':
- case ',':
- break;
- }
- }
-}
-
-/* Actually process the hooks */
-int process_hooks_restart = FALSE;
-hook_return process_hooks_return[20];
-static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap)
-{
- hooks_chain *c = hooks_heads[h_idx];
- va_list real_ap;
-
- while (c != NULL)
- {
- if (c->type == HOOK_TYPE_C)
- {
- int i = 0, nb = 0;
-
- /* Push all args in the pile */
- i = 0;
- COPY(&real_ap, ap, va_list);
- while (fmt[i])
- {
- switch (fmt[i])
- {
- case 'O':
- param_pile[nb++].o_ptr = va_arg(real_ap, object_type *);
- break;
- case 's':
- param_pile[nb++].str = va_arg(real_ap, char *);
- break;
- case 'd':
- case 'l':
- param_pile[nb++].num = va_arg(real_ap, s32b);
- break;
- case '(':
- case ')':
- case ',':
- break;
- }
- i++;
- }
-
- get_next_arg_pos = 0;
- get_next_arg_pile_pos = 0;
- if (c->hook(fmt))
- {
- return TRUE;
- }
-
- /* Should we restart ? */
- if (process_hooks_restart)
- {
- c = hooks_heads[h_idx];
- process_hooks_restart = FALSE;
- }
- else
- {
- c = c->next;
- }
- }
- else if (c->type == HOOK_TYPE_NEW)
- {
- /* Skip; handled in process_hooks_new */
- c = c->next;
- }
- else
- {
- msg_format("Unkown hook type %d, name %s", c->type, c->name);
- c = c->next;
- }
- }
-
- return FALSE;
-}
-
-bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...)
-{
- va_list ap;
- bool_ r;
-
- va_start(ap, fmt);
- r = vprocess_hooks_return (h_idx, ret, fmt, &ap);
- va_end(ap);
- return (r);
-}
-
-bool_ process_hooks(int h_idx, char *fmt, ...)
-{
- va_list ap;
- bool_ ret;
-
- va_start(ap, fmt);
- ret = vprocess_hooks_return (h_idx, "", fmt, &ap);
- va_end(ap);
- return (ret);
-}
-
-bool_ process_hooks_new(int h_idx, void *in, void *out)
-{
- hooks_chain *c = hooks_heads[h_idx];
-
- while (c != NULL)
- {
- /* Only new-style hooks; skip the rest. */
- if (c->type != HOOK_TYPE_NEW)
- {
- c = c->next;
- continue;
- }
-
- /* Invoke hook function; stop processing if
- the hook returns TRUE */
- if (c->hook_f(c->hook_data, in, out))
- {
- return TRUE;
- }
-
- /* Should we restart processing at the beginning? */
- if (process_hooks_restart)
- {
- c = hooks_heads[h_idx];
- process_hooks_restart = FALSE;
- }
- else
- {
- c = c->next;
- }
- }
-
- return FALSE;
-}
-
-/******** Plots & Quest stuff ********/
-
-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"
-
-/*************************** Bounty Quest *************************/
-#include "q_bounty.c"
-
-/************************** Library Quest *************************/
-#include "q_library.c"
-
-/************************* Fireproofing Quest *********************/
-#include "q_fireprof.c"
diff --git a/src/plots.h b/src/plots.h
deleted file mode 100644
index 91115856..00000000
--- a/src/plots.h
+++ /dev/null
@@ -1,68 +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);
-
-/******* Plot Bounty Quest ********/
-extern bool_ quest_bounty_init_hook(int q_idx);
-extern bool_ quest_bounty_drop_item();
-extern bool_ quest_bounty_get_item();
-extern bool_ quest_bounty_describe(FILE *fff);
-
-/******* Plot Library Quest *******/
-extern bool_ quest_library_init_hook(int q);
-extern bool_ quest_library_describe(FILE *fff);
-extern void quest_library_building(bool_ *paid, bool_ *recreate);
-
-/******* Plot Fireproof Quest *********/
-extern void quest_fireproof_building(bool_ *paid, bool_ *recreate);
-extern bool_ quest_fireproof_init_hook(int q);
-extern bool_ quest_fireproof_describe(FILE *fff);
-
-/******* Plot God Quest **************/
-extern bool_ quest_god_describe(FILE *);
-extern bool_ quest_god_init_hook(int q);
diff --git a/src/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 afc4a13a..ce715859 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,14 +6,42 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "quark.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"
/*
* 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;
@@ -82,7 +106,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);
@@ -170,199 +194,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();
@@ -762,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];
@@ -1053,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);
@@ -1248,16 +1074,11 @@ static void power_activate(int power)
break;
default:
-
- if (!process_hooks(HOOK_ACTIVATE_POWER, "(d)", power))
- {
- msg_format("Warning power_activate() called with invalid power(%d).", power);
- energy_use = 0;
- }
+ abort();
break;
}
- p_ptr->redraw |= (PR_HP | PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->window |= (PW_PLAYER);
}
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.c b/src/q_bounty.cc
index 01b119be..bb84d48d 100644
--- a/src/q_bounty.c
+++ b/src/q_bounty.cc
@@ -1,18 +1,77 @@
-#undef cquest
+#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_ bounty_item_tester_hook(object_type *o_ptr)
+static bool_ lua_mon_hook_bounty(int r_idx)
{
- if ((o_ptr->tval == TV_CORPSE) && (o_ptr->pval2 == bounty_quest_monster))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ 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)
@@ -28,7 +87,7 @@ bool_ quest_bounty_drop_item()
if (cquest.status == QUEST_STATUS_UNTAKEN)
{
cquest.status = QUEST_STATUS_TAKEN;
- bounty_quest_monster = lua_get_new_bounty_monster(3 + (p_ptr->lev * 3) / 2);
+ 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);
@@ -52,13 +111,13 @@ bool_ quest_bounty_get_item()
}
// Get the corpse.
- item_tester_hook = bounty_item_tester_hook;
int item = -1;
bool_ ret =
get_item(&item,
"What corpse to return?",
"You have no corpse to return.",
- USE_INVEN);
+ USE_INVEN,
+ bounty_item_tester_hook);
if (!ret) {
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..d6f5b1fb 100644
--- a/src/q_dragons.c
+++ b/src/q_dragons.cc
@@ -1,7 +1,21 @@
-#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"
+
#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 +103,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 +125,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 +135,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 +155,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..cfccd156 100644
--- a/src/q_eol.c
+++ b/src/q_eol.cc
@@ -1,7 +1,30 @@
-#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 <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 +84,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 +108,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 +135,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 +153,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 +192,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 +201,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 +210,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..511644a3 100644
--- a/src/q_evil.c
+++ b/src/q_evil.cc
@@ -1,7 +1,21 @@
-#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"
+
#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 +68,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 +92,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 +103,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 +123,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.c b/src/q_fireprof.cc
index 3afa348f..b11c9667 100644
--- a/src/q_fireprof.c
+++ b/src/q_fireprof.cc
@@ -1,4 +1,22 @@
-#undef cquest
+#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 <cassert>
+
#define cquest (quest[QUEST_FIREPROOF])
#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0)
@@ -65,38 +83,27 @@ static int fireproof_get_sval()
return cquest.data[1];
}
-static bool_ item_tester_hook_eligible(object_type *o_ptr)
+static bool item_tester_hook_eligible(object_type const *o_ptr)
{
/* check it's the 'marked' item */
- if ((o_ptr->tval == fireproof_get_settings()->tval) &&
+ return ((o_ptr->tval == fireproof_get_settings()->tval) &&
(o_ptr->sval == fireproof_get_sval()) &&
- (o_ptr->pval2 == fireproof_get_sval()))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ (o_ptr->pval2 == fireproof_get_sval()));
}
-static bool_ item_tester_hook_proofable(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_proofable()
{
- u32b f1, f2, f3, f4, f5, esp;
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* is it a book/staff/scroll, is it already fireproof? */
- if (((o_ptr->tval == TV_BOOK) ||
- (o_ptr->tval == TV_SCROLL) ||
- (o_ptr->tval == TV_STAFF))
- && ((f3 & TR3_IGNORE_FIRE) == 0))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ 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;
}
/*
@@ -157,30 +164,27 @@ static bool_ fireproof_enough_points(object_type *o_ptr, int *stack)
static bool_ fireproof()
{
- int ret, item, stack = 0;
- object_type *obj2 = NULL;
- bool_ ret2;
-
- item_tester_hook = item_tester_hook_proofable;
- ret = get_item(&item,
- "Which item shall I fireproof?",
- "You have no more items I can fireproof, come back when you have some.",
- USE_INVEN);
+ 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 */
- obj2 = get_object(item);
+ object_type *obj2 = get_object(item);
/* check we have enough points (if we 'got' an item) */
- if (ret == TRUE) {
- ret2 = fireproof_enough_points(obj2, &stack);
- }
-
- /* did either routine fail? */
- if ((ret == FALSE) || (ret2 == FALSE))
+ int stack = 0;
+ if (!fireproof_enough_points(obj2, &stack))
{
return FALSE;
}
- else
+
+ /* Do the actual fireproofing */
{
bool_ carry_it;
object_type *obj3;
@@ -278,8 +282,7 @@ void quest_fireproof_building(bool_ *paid, bool_ *recreate)
snprintf(pni, sizeof(pni), "You have no %s to return", settings->tval_name_plural);
/* ask for item */
- item_tester_hook = item_tester_hook_eligible;
- ret = get_item(&item_idx, p, pni, USE_INVEN);
+ ret = get_item(&item_idx, p, pni, USE_INVEN, item_tester_hook_eligible);
/* didn't get the item? */
if (!ret)
@@ -377,10 +380,10 @@ void quest_fireproof_building(bool_ *paid, bool_ *recreate)
}
}
-static bool_ fireproof_get_hook(char *fmt)
+static bool_ fireproof_get_hook(void *, void *in_, void *)
{
- object_type *o_ptr = param_pile[0].o_ptr;
- assert(o_ptr != NULL);
+ 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
@@ -397,7 +400,7 @@ static bool_ fireproof_get_hook(char *fmt)
return FALSE;
}
-static bool_ fireproof_stair_hook(char *fmt)
+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 */
@@ -479,7 +482,7 @@ bool_ quest_fireproof_describe(FILE *hook_file)
return TRUE;
}
-static bool_ fireproof_gen_hook(char *fmt)
+static bool_ fireproof_gen_hook(void *, void *, void *)
{
fireproof_settings const *settings = fireproof_get_settings();
@@ -575,9 +578,9 @@ bool_ quest_fireproof_init_hook(int q)
if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
(cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_GEN_QUEST, fireproof_gen_hook , "fireproof_gen_hook");
- add_hook(HOOK_GET , fireproof_get_hook , "fireproof_get_hook");
- add_hook(HOOK_STAIR , fireproof_stair_hook, "fireproof_stair_hook");
+ 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;
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.c b/src/q_god.cc
index 82f90a25..754802fd 100644
--- a/src/q_god.c
+++ b/src/q_god.cc
@@ -1,9 +1,25 @@
-#include "angband.h"
+#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 <assert.h>
-#include "quark.h"
-
#define cquest (quest[QUEST_GOD])
#define cquest_quests_given (cquest.data[0])
#define cquest_relics_found (cquest.data[1])
@@ -149,8 +165,8 @@ static byte get_relic_num()
assert(FALSE);
}
-static void get_home_coordinates(int *home1_y, int *home1_x, char **home1,
- int *home2_y, int *home2_x, char **home2)
+static void get_home_coordinates(int *home1_y, int *home1_x, const char **home1,
+ int *home2_y, int *home2_x, const char **home2)
{
/* Which are the waypoints? */
if (p_ptr->pgod != GOD_MELKOR)
@@ -223,8 +239,8 @@ static void print_directions(bool_ feel_it, void (*pfunc)(cptr, void *), void *p
{
int home1_y, home1_x;
int home2_y, home2_x;
- char *home1 = NULL;
- char *home2 = NULL;
+ const char *home1 = NULL;
+ const char *home2 = NULL;
char *home1_axis = NULL;
char *home2_axis = NULL;
cptr home1_distance = NULL;
@@ -865,7 +881,7 @@ static void quest_god_set_god_dungeon_attributes_mandos()
d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_UNDEAD | RF3_EVIL;
}
-static bool_ quest_god_level_end_gen_hook(char *fmt)
+static bool_ quest_god_level_end_gen_hook(void *, void *, void *)
{
/* Check for dungeon */
if ((dungeon_type != DUNGEON_GOD) ||
@@ -922,9 +938,10 @@ static bool_ quest_god_level_end_gen_hook(char *fmt)
return FALSE;
}
-static bool_ quest_god_player_level_hook(char *fmt)
+static bool_ quest_god_player_level_hook(void *, void *in_, void *)
{
- s32b gained = get_next_arg(fmt);
+ struct hook_player_level_in *in = static_cast<struct hook_player_level_in *>(in_);
+ s32b gained = in->gained_levels;
if (gained <= 0)
{
@@ -982,16 +999,13 @@ static bool_ quest_god_player_level_hook(char *fmt)
return FALSE;
}
-static bool_ quest_god_get_hook(char *fmt)
+static bool_ quest_god_get_hook(void *, void *in_, void *)
{
- s32b item;
- object_type *o_ptr = NULL;
+ hook_get_in *in = static_cast<hook_get_in *>(in_);
- get_next_arg("d"); /* ignore first arg */
- item = get_next_arg("d");
+ s32b item = -in->o_idx; /* Note the negation */
- item = -item; /* Workaround */
- o_ptr = get_object(item);
+ 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) &&
@@ -1040,8 +1054,11 @@ static bool_ quest_god_get_hook(char *fmt)
return FALSE;
}
-static bool_ quest_god_char_dump_hook(char *fmt)
+static bool_ quest_god_char_dump_hook(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;
@@ -1067,9 +1084,7 @@ static bool_ quest_god_char_dump_hook(char *fmt)
}
}
- fprintf(hook_file, "\n You found %s of the relic pieces%s.",
- relics_text,
- append_text);
+ fprintf(f, "\n You found %s of the relic pieces%s.", relics_text, append_text);
}
return FALSE;
@@ -1141,26 +1156,26 @@ static void quest_god_dungeon_setup(int d_idx)
set_god_dungeon_attributes();
}
-static bool_ quest_god_enter_dungeon_hook(char *fmt)
+static bool_ quest_god_enter_dungeon_hook(void *, void *in_, void *)
{
- s32b d_idx = get_next_arg(fmt);
- quest_god_dungeon_setup(d_idx);
+ 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(char *fmt)
+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(char *fmt)
+static bool_ quest_god_stair_hook(void *, void *, void *)
{
quest_god_dungeon_setup(dungeon_type);
return FALSE;
}
-static bool_ quest_god_birth_objects_hook(char *fmt)
+static bool_ quest_god_birth_objects_hook(void *, void *, void *)
{
cquest_quests_given = 0;
cquest_relics_found = 0;
@@ -1179,18 +1194,18 @@ bool_ quest_god_init_hook(int q)
if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
(cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_LEVEL_END_GEN, quest_god_level_end_gen_hook, "q_god_level_end_gen");
- add_hook(HOOK_ENTER_DUNGEON, quest_god_enter_dungeon_hook, "q_god_enter_dungeon");
- add_hook(HOOK_GEN_LEVEL_BEGIN, quest_god_gen_level_begin_hook, "q_god_gen_level_begin");
- add_hook(HOOK_STAIR, quest_god_stair_hook, "q_god_hook_stair");
- add_hook(HOOK_GET, quest_god_get_hook, "q_god_get");
- add_hook(HOOK_CHAR_DUMP, quest_god_char_dump_hook, "q_god_char_dump");
- add_hook(HOOK_PLAYER_LEVEL, quest_god_player_level_hook, "q_god_player_level");
+ 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(HOOK_BIRTH_OBJECTS, quest_god_birth_objects_hook, "q_god_birth_objects");
+ 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..cbfaa176 100644
--- a/src/q_haunted.c
+++ b/src/q_haunted.cc
@@ -1,7 +1,22 @@
-#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"
+
#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 +101,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 +123,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 +134,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 +154,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 b80638ad..bc3659e9 100644
--- a/src/q_hobbit.c
+++ b/src/q_hobbit.cc
@@ -1,12 +1,34 @@
-#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 <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 +49,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 +78,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 +110,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 +171,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 +184,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 */
@@ -181,18 +212,18 @@ bool_ quest_hobbit_init_hook(int q_idx)
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 985062af..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,15 +92,16 @@ 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)
+
+static bool_ quest_invasion_turn_hook(void *, void *, void *)
{
if (cquest.status != QUEST_STATUS_UNTAKEN) return (FALSE);
if (p_ptr->lev < 45) return (FALSE);
@@ -102,28 +121,33 @@ bool_ quest_invasion_turn_hook(char *fmt)
cquest.status = QUEST_STATUS_TAKEN;
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;
@@ -131,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)
{
@@ -174,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.c b/src/q_library.cc
index bbbcae4c..979fbb2f 100644
--- a/src/q_library.c
+++ b/src/q_library.cc
@@ -1,4 +1,23 @@
-#undef cquest
+#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 <cassert>
+
#define cquest (quest[QUEST_LIBRARY])
#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0)
@@ -141,7 +160,7 @@ static void quest_library_finalize_book()
int i = 0;
for (i = 1; i <= 3; i++)
{
- school_book_type *school_book = school_books_at(BOOK_PLAYER);
+ school_book *school_book = school_books_at(BOOK_PLAYER);
school_book_add_spell(school_book, library_quest_book_get_slot(i));
}
}
@@ -243,7 +262,6 @@ static void library_quest_fill_book()
library_quest_print_spells(first, current);
- inkey_scan = FALSE;
ch = inkey();
dir = get_keymap_dir(ch);
@@ -294,7 +312,7 @@ static void library_quest_fill_book()
screen_load();
}
-static bool_ quest_library_gen_hook()
+static bool_ quest_library_gen_hook(void *, void *, void *)
{
/* Only if player doing this quest */
if (p_ptr->inside_quest != QUEST_LIBRARY)
@@ -337,7 +355,7 @@ static bool_ quest_library_gen_hook()
return TRUE;
}
-static bool_ quest_library_stair_hook()
+static bool_ quest_library_stair_hook(void *, void *, void *)
{
bool_ ret;
@@ -373,7 +391,7 @@ static bool_ quest_library_stair_hook()
}
}
-static bool_ quest_library_monster_death_hook(char *fmt)
+static bool_ quest_library_monster_death_hook(void *, void *, void *)
{
int i, count = -1;
@@ -490,9 +508,9 @@ bool_ quest_library_init_hook(int q)
if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
(cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_GEN_QUEST , quest_library_gen_hook , "library_gen_hook");
- add_hook(HOOK_STAIR , quest_library_stair_hook , "library_stair_hook");
- add_hook(HOOK_MONSTER_DEATH, quest_library_monster_death_hook, "library_monster_death_hook");
+ 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. */
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..21bc95c9
--- /dev/null
+++ b/src/q_nazgul.cc
@@ -0,0 +1,144 @@
+#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 <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..1aa77610 100644
--- a/src/q_one.c
+++ b/src/q_one.cc
@@ -1,14 +1,36 @@
-#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"
+
#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 +47,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 +74,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 +88,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 +117,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 +172,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 +210,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 +228,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 +308,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 +355,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 0c3987df..d8ecf949 100644
--- a/src/q_poison.c
+++ b/src/q_poison.cc
@@ -1,4 +1,23 @@
-#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"
+
#define cquest (quest[QUEST_POISON])
static int wild_locs[4][2] =
@@ -21,7 +40,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 +102,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 +117,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 +143,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 +178,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 +224,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 +236,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 */
@@ -225,14 +249,14 @@ bool_ quest_poison_init_hook(int q_idx)
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 0cc69a6d..5b265624 100644
--- a/src/q_rand.c
+++ b/src/q_rand.cc
@@ -1,5 +1,196 @@
+#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 <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;
@@ -20,19 +211,18 @@ bool_ is_randhero(int level)
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 +231,18 @@ static 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,10 +278,6 @@ static void do_get_new_obj(int y, int x)
}
}
}
-
- for (i = 0; i < 3; i++)
- C_KILL(items[i], 100, char);
-
}
static void princess_death(s32b m_idx, s32b r_idx)
@@ -190,14 +376,15 @@ static 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 +400,11 @@ static void hero_death(s32b m_idx, s32b r_idx)
}
}
-static 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);
@@ -243,14 +428,14 @@ static bool_ quest_random_death_hook(char *fmt)
return (FALSE);
}
-static bool_ quest_random_turn_hook(char *fmt)
+static bool_ quest_random_turn_hook(void *, void *, void *)
{
quest[QUEST_RANDOM].data[0] = 0;
quest[QUEST_RANDOM].data[1] = 0;
return (FALSE);
}
-static bool_ quest_random_feeling_hook(char *fmt)
+static bool_ quest_random_feeling_hook(void *, void *, void *)
{
if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE);
if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE);
@@ -262,14 +447,14 @@ static 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);
}
-static bool_ quest_random_gen_hero_hook(char *fmt)
+static bool_ quest_random_gen_hero_hook(void *, void *, void *)
{
int i;
@@ -300,9 +485,12 @@ static bool_ quest_random_gen_hero_hook(char *fmt)
return (FALSE);
}
-static bool_ quest_random_gen_hook(char *fmt)
+static bool_ quest_random_gen_hook(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;
@@ -316,9 +504,6 @@ static 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);
@@ -383,10 +568,11 @@ static bool_ quest_random_gen_hook(char *fmt)
return (TRUE);
}
-static 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++)
@@ -407,22 +593,22 @@ static 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);
@@ -441,14 +627,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",
@@ -459,12 +643,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 c0133e74..f3a7dd12 100644
--- a/src/q_shroom.c
+++ b/src/q_shroom.cc
@@ -1,14 +1,39 @@
-#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 <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 +58,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 +100,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 +201,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 +209,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);
+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))
+ {
+ 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);
- if (cquest.status == QUEST_STATUS_UNTAKEN)
+ 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
{
- cptr m_name;
+ msg_format("You still have %d mushrooms to bring back!", cquest.data[1] - cquest.data[0]);
+ }
+}
- m_name = get_next_arg_str(fmt);
+static bool_ quest_shroom_speak_hook(void *, void *in_, void *)
+{
+ struct hook_mon_speak_in *in = static_cast<struct hook_mon_speak_in *>(in_);
+ s32b m_idx = in->m_idx;
- msg_format("%^s asks your help.", m_name);
+ if (m_list[m_idx].r_idx != get_farmer_maggot()) return (FALSE);
+
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ msg_format("%^s asks your help.", in->m_name);
process_hooks_new(HOOK_MON_ASK_HELP, NULL, NULL);
}
else
{
- /* 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_chat_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_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 +273,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 */
@@ -280,17 +294,17 @@ bool_ quest_shroom_init_hook(int q_idx)
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..5019d9d5 100644
--- a/src/q_thief.c
+++ b/src/q_thief.cc
@@ -1,7 +1,25 @@
-#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"
+
#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 +74,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 +124,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 +133,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 +160,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 +183,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 6180706c..4cdb8566 100644
--- a/src/q_thrain.c
+++ b/src/q_thrain.cc
@@ -1,17 +1,44 @@
-#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 <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 +74,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 +108,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 +130,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 +171,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 +184,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 +197,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,12 +226,14 @@ 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])
@@ -219,15 +246,15 @@ bool_ quest_thrain_init_hook(int q)
}
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..7227c1c3 100644
--- a/src/q_troll.c
+++ b/src/q_troll.cc
@@ -1,7 +1,30 @@
-#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 <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 +56,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 +93,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 +111,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 +126,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 +170,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..499535ca 100644
--- a/src/q_wight.c
+++ b/src/q_wight.cc
@@ -1,7 +1,27 @@
-#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 <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 +55,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 +107,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 +119,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 +136,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 +160,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..117e8d42 100644
--- a/src/q_wolves.c
+++ b/src/q_wolves.cc
@@ -1,7 +1,22 @@
-#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"
+
#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 +84,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 +106,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 +117,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 +137,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.c b/src/quark.cc
index 32efaaa0..45072ded 100644
--- a/src/quark.c
+++ b/src/quark.cc
@@ -1,6 +1,8 @@
-#include "quark.h"
+#include "quark.hpp"
-#include "angband.h"
+#include "z-util.h"
+
+#include <cassert>
/*
* The number of quarks
@@ -20,7 +22,11 @@ static cptr *quark__str = NULL;
void quark_init()
{
quark__num = 0;
- C_MAKE(quark__str, QUARK_MAX, cptr);
+ quark__str = new cptr[QUARK_MAX];
+
+ for (int i = 0; i < QUARK_MAX; i++) {
+ quark__str[i] = nullptr;
+ }
}
@@ -45,6 +51,8 @@ void quark_init()
*/
s16b quark_add(cptr str)
{
+ assert(str != nullptr);
+
int i;
/* Look for an existing quark */
@@ -61,7 +69,7 @@ s16b quark_add(cptr str)
quark__num = i + 1;
/* Add a new quark */
- quark__str[i] = string_make(str);
+ quark__str[i] = strdup(str);
/* Return the index */
return (i);
diff --git a/src/quark.h b/src/quark.h
deleted file mode 100644
index 9488b105..00000000
--- a/src/quark.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef H_eeb941c7_1a44_405a_8db3_ba14732c5b94
-#define H_eeb941c7_1a44_405a_8db3_ba14732c5b94
-
-#include "h-type.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void quark_init();
-cptr quark_str(s16b num);
-s16b quark_add(cptr str);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif
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_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 10fd51b0..451bf948 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,9 +6,23 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "quark.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 <memory>
+#include <vector>
/* Chance of using syllables to form the name instead of the "template" files */
#define TABLE_NAME 45
@@ -25,21 +35,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)
{
@@ -71,16 +79,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)
@@ -110,8 +116,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);
}
@@ -264,7 +268,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;
@@ -283,7 +286,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)
@@ -293,7 +299,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];
@@ -327,7 +333,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);
@@ -404,26 +409,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.c b/src/range.cc
index 647f0576..7bd407c7 100644
--- a/src/range.c
+++ b/src/range.cc
@@ -1,4 +1,6 @@
-#include <angband.h>
+#include "range.hpp"
+
+#include <cassert>
void range_init(range_type *range, s32b min, s32b 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.cc
index 40f43f95..84f7c3e4 100644
--- a/src/script.c
+++ b/src/script.cc
@@ -1,7 +1,3 @@
-/* File: script.c */
-
-/* Purpose: scripting in lua */
-
/*
* Copyright (c) 2001 Dark God
*
@@ -10,7 +6,13 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "script.h"
+
+#include "init2.hpp"
+#include "q_library.hpp"
+#include "spells4.hpp"
+#include "spells5.hpp"
+#include "spells6.hpp"
void init_lua_init()
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 4df3c1b3..330aa9ba 100644
--- a/src/skills.c
+++ b/src/skills.cc
@@ -1,7 +1,3 @@
-/* File: skills.c */
-
-/* Purpose: player skills */
-
/*
* Copyright (c) 2001 DarkGod
*
@@ -10,15 +6,53 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include <math.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 <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;
@@ -36,9 +70,14 @@ void increase_skill(int i, s16b *invest)
if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1))
{
int hgt, wid;
+ char buf[256];
+
+ sprintf(buf,
+ "Cannot raise a skill value above " FMTs32b " + player level.",
+ max_skill_overage);
Term_get_size(&wid, &hgt);
- msg_box(format("Cannot raise a skill value above %i + player level.", max_skill_overage), (int)(hgt / 2), (int)(wid / 2));
+ msg_box(buf, hgt / 2, wid / 2);
return;
}
@@ -55,7 +94,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;
@@ -86,8 +125,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 */
@@ -101,7 +142,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 */
@@ -141,15 +185,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);
@@ -178,17 +216,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;
@@ -200,15 +232,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;
@@ -251,17 +281,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");
@@ -285,7 +315,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++)
{
@@ -311,17 +341,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,
@@ -375,7 +405,6 @@ void recalc_skills(bool_ init)
abandon_god(GOD_ALL);
}
- process_hooks(HOOK_RECALC_SKILLS, "()");
process_hooks_new(HOOK_RECALC_SKILLS, NULL, NULL);
/* Update stuffs */
@@ -383,14 +412,14 @@ void recalc_skills(bool_ init)
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;
@@ -448,11 +477,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);
@@ -460,11 +484,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;
@@ -478,6 +502,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 */
@@ -491,7 +516,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 */
@@ -537,13 +562,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 */
@@ -556,7 +581,7 @@ void do_cmd_skill()
/* Contextual help */
if (c == '?')
{
- help_skill(s_info[table[sel][0]].name + s_name);
+ help_skill(s_info[table[sel][0]].name);
}
/* Handle boundaries and scrolling */
@@ -575,7 +600,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 */
@@ -594,14 +619,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();
@@ -613,13 +630,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",
@@ -640,6 +657,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;
@@ -725,7 +747,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;
@@ -755,21 +777,23 @@ void select_default_melee()
/*
* Print a batch of skills.
*/
-static void print_skill_batch(int *p, cptr *p_desc, int start, int max)
+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;
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]));
prt(buff, 2 + j, 20);
j++;
@@ -778,37 +802,30 @@ static void print_skill_batch(int *p, cptr *p_desc, int start, int max)
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;
- 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;
@@ -816,22 +833,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;
@@ -839,12 +855,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;
@@ -855,7 +871,7 @@ int do_cmd_activate_skill_aux()
while (1)
{
- print_skill_batch(p, p_desc, start, max);
+ print_skill_batch(p, start);
which = inkey();
if (which == ESCAPE)
@@ -866,14 +882,20 @@ int do_cmd_activate_skill_aux()
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;
}
@@ -886,22 +908,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;
@@ -912,16 +935,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;
}
@@ -1008,12 +1028,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;
@@ -1161,7 +1175,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);
}
@@ -1240,104 +1254,69 @@ void init_skill(s32b value, s32b mod, int i)
}
/*
- * Perform weighted random selection without replacement according to
- * the algorithm given in "Weighted Random Sampling" (2005, Eframidis,
- * Spirakis)
+ * Perform weighted random shuffle according to the algorithm given in
+ * "Weighted Random Sampling" (2005, Efraimidis, Spirakis).
*
- * @param n is the total number of items to choose from.
- * @param k is the total number of items to choose.
- * @param weights is the array of weights.
- * @param indexes is the output array containing the chosen permutation.
- * The first k values will be set to a value in [0, n[ according to
- * which item was chosen.
+ * @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 void wrs_without_replacement(size_t n, size_t k, s32b unscaled_weights[], size_t indexes[])
+static std::vector<size_t> wrs(const std::vector<s32b> &unscaled_weights)
{
- size_t i;
- s32b scale;
- double *weights = NULL;
- double *keys = NULL;
- size_t *permutation = NULL;
-
- assert(k <= n);
-
- /* Allocate working memory */
- keys = C_RNEW(n, double);
- weights = C_RNEW(n, double);
- permutation = C_RNEW(n, double);
-
- /* Calculate the scale of the weights. */
- scale = 0;
- for (i = 0; i < n; i++)
- {
- scale += unscaled_weights[i];
- }
+ const size_t n = unscaled_weights.size();
/* Rescale weights into unit interval for numerical stability */
- for (i = 0; i < n; i++) {
- weights[i] =
- ((double) unscaled_weights[i]) /
- ((double) scale);
- }
+ std::vector<double> weights(unscaled_weights.size());
+ {
+ s32b scale = 0;
+ for (s32b weight: unscaled_weights)
+ {
+ scale += weight;
+ }
- /* Generate the keys to use for selection. This is where the
- magic happens. */
- for (i = 0; i < n; i++) {
- double u = ((double) rand_int(100000)) / ((double) 100000);
- keys[i] = pow(u, 1/weights[i]);
+ for (size_t i = 0; i < n; i++) {
+ weights[i] =
+ ((double) unscaled_weights[i]) /
+ ((double) scale);
+ }
}
- /* Generate the initial permutation */
- for (i = 0; i < n; i++) {
- permutation[i] = i;
+ /* 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);
}
- /* Select the k indexes with the largest keys */
- for (i = 0; i < k; i++) {
- /* Find maximal value and its index */
- int max_idx = i;
- double max_value = keys[max_idx];
- size_t j;
- for (j = i+1; j < n; j++) {
- if (keys[j] > max_value) {
- max_idx = j;
- max_value = keys[j];
- }
- }
+ /* 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));
- /* Swap into k'th position */
- if (max_idx != i) {
- double tmp_key;
- size_t tmp_idx;
- /* Swap keys */
- tmp_key = keys[i];
- keys[i] = keys[max_idx];
- keys[max_idx] = tmp_key;
- /* Swap indexes in permutation */
- tmp_idx = permutation[i];
- permutation[i] = permutation[max_idx];
- permutation[max_idx] = tmp_idx;
- }
-
- /* Output the k'th choice. */
- indexes[i] = permutation[i];
+ /* 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));
}
-
- /* Clean up */
- C_FREE(keys, n, double);
- C_FREE(weights, n, double);
- C_FREE(permutation, n, size_t);
+ 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];
int available_skills[MAX_SKILLS];
int max_a = 0, res, i;
- size_t indexes[LOST_SWORD_NSKILLS];
- s32b weights[MAX_SKILLS];
/* Check if some skills didn't influence other stuff */
recalc_skills(TRUE);
@@ -1353,11 +1332,13 @@ void do_get_new_skill()
}
/* Perform the selection */
+ std::vector<s32b> weights;
for (i = 0; i < max_a; i++) {
- weights[i] = s_info[available_skills[i]].random_gain_chance;
+ weights.push_back(s_info[available_skills[i]].random_gain_chance);
}
- wrs_without_replacement(max_a, LOST_SWORD_NSKILLS, weights, indexes);
+ std::vector<size_t> indexes = wrs(weights);
+ assert(indexes.size() >= LOST_SWORD_NSKILLS);
/* Extract the information needed from the skills */
for (i = 0; i < LOST_SWORD_NSKILLS; i++)
@@ -1396,7 +1377,12 @@ void do_get_new_skill()
}
skl[i] = s_idx;
- items[i] = (char *)string_make(format("%-40s: +%02ld.%03ld value, +%01d.%03d modifier", s_ptr->name + s_name, val[i] / SKILL_STEP, val[i] % SKILL_STEP, mod[i] / SKILL_STEP, mod[i] % SKILL_STEP));
+ 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)
@@ -1404,7 +1390,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)
@@ -1439,7 +1425,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;
@@ -1451,23 +1437,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 (i = 0; i < LOST_SWORD_NSKILLS; i++)
- {
- string_free(items[i]);
- }
-
/* Check if some skills didn't influence other stuff */
recalc_skills(FALSE);
}
@@ -1488,8 +1468,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 */
@@ -1505,7 +1487,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;
@@ -1550,22 +1532,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;
}
@@ -1573,7 +1551,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;
}
@@ -1582,28 +1560,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;
}
/*
@@ -1611,28 +1570,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");
@@ -1642,7 +1604,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;
@@ -1657,14 +1619,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];
@@ -1683,7 +1649,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)
@@ -1702,14 +1668,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();
@@ -1717,30 +1680,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 */
@@ -1775,28 +1752,38 @@ if (ab_info[i].name)
/* Contextual help */
if (c == '?')
{
- help_ability(ab_info[table[sel]].name + ab_name);
+ 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);
}
/*
@@ -1811,25 +1798,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..59e1f059
--- /dev/null
+++ b/src/skills_defs.hpp
@@ -0,0 +1,64 @@
+#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_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
+#define MAX_SKILLS 200
diff --git a/src/spell_type.c b/src/spell_type.cc
index b8bec0cd..6cf6e35b 100644
--- a/src/spell_type.c
+++ b/src/spell_type.cc
@@ -1,6 +1,16 @@
-#include "spell_type.h"
+#include "spell_type.hpp"
-#include "angband.h"
+#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
@@ -11,23 +21,23 @@ struct spell_type
{
cptr name; /* Name */
byte skill_level; /* Required level (to learn) */
- string_list *description; /* List of strings */
+ std::vector<std::string> m_description; /* List of strings */
- casting_result (*effect_func)(int o_idx); /* Spell effect function */
- char* (*info_func)(); /* Information function */
+ 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 */
- casting_type casting_type; /* Type of casting required */
+ 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 */
- device_allocation *device_allocation; /* Allocation table 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 */
@@ -38,10 +48,36 @@ struct spell_type
range_type mana_range;
- dice_type activation_timeout; /* Timeout for activation (if any) */
-
- int school_idxs_count;
+ 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)
@@ -53,31 +89,6 @@ static void school_idx_add_new(spell_type *spell, s32b i)
spell->school_idxs_count++;
}
-void spell_type_init(spell_type *spell, cptr name)
-{
- assert(spell != NULL);
-
- memset(spell, 0, sizeof(spell_type));
-
- spell->name = name;
- spell->description = NULL;
- spell->effect_func = NULL;
- spell->info_func = NULL;
- spell->lasting_func = NULL;
- spell->depend_func = NULL;
-
- spell->device_allocation = NULL;
-
- spell->school_idxs_count = 0;
-
- spell->random_type = -1;
-
- spell->castable_while_blind = FALSE;
- spell->castable_while_confused = FALSE;
-
- spell_type_set_inertia(spell, -1, -1);
-}
-
void spell_type_set_inertia(spell_type *spell, s32b difficulty, s32b delay)
{
assert(spell != NULL);
@@ -87,8 +98,8 @@ void spell_type_set_inertia(spell_type *spell, s32b difficulty, s32b delay)
void spell_type_init_music(spell_type *spell,
s16b minimum_pval,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx))
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
{
assert(spell != NULL);
@@ -107,8 +118,8 @@ void spell_type_init_music(spell_type *spell,
void spell_type_init_music_lasting(spell_type *spell,
s16b minimum_pval,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx),
+ const char* (*info_func)(),
+ casting_result (*effect_func)(),
int (*lasting_func)())
{
spell_type_init_music(
@@ -123,8 +134,8 @@ void spell_type_init_music_lasting(spell_type *spell,
void spell_type_init_mage(spell_type *spell,
random_type random_type,
s32b school_idx,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx))
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
{
assert(spell != NULL);
@@ -153,8 +164,8 @@ void spell_type_init_mage(spell_type *spell,
void spell_type_init_priest(spell_type *spell,
s32b school_idx,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx))
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
{
assert(spell != NULL);
@@ -169,8 +180,8 @@ void spell_type_init_priest(spell_type *spell,
}
void spell_type_init_device(spell_type *spell,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx))
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
{
assert(spell != NULL);
@@ -182,8 +193,8 @@ void spell_type_init_device(spell_type *spell,
}
void spell_type_init_demonology(spell_type *spell,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx))
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
{
spell_type_init_mage(spell,
NO_RANDOM,
@@ -193,8 +204,8 @@ void spell_type_init_demonology(spell_type *spell,
}
void spell_type_init_geomancy(spell_type *spell,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx),
+ const char* (*info_func)(),
+ casting_result (*effect_func)(),
bool_ (*depend_func)())
{
spell_type_init_mage(spell,
@@ -206,13 +217,6 @@ void spell_type_init_geomancy(spell_type *spell,
spell->depend_func = depend_func;
}
-void spell_type_set_activation_timeout(spell_type *spell, cptr timeout_s)
-{
- assert(spell != NULL);
-
- dice_parse_checked(&spell->activation_timeout, timeout_s);
-}
-
void spell_type_set_difficulty(spell_type *spell, byte skill_level, s32b failure_rate)
{
assert(spell != NULL);
@@ -246,7 +250,7 @@ void spell_type_describe(spell_type *spell, cptr line)
{
assert(spell != NULL);
- string_list_append(&spell->description, line);
+ spell->m_description.push_back(std::string(line));
}
void spell_type_add_school(spell_type *spell, s32b school_idx)
@@ -265,15 +269,13 @@ void spell_type_add_device_allocation(spell_type *spell, struct device_allocatio
{
assert(spell != NULL);
assert(a != NULL);
-
- sglib_device_allocation_add(&spell->device_allocation, a);
+ spell->m_device_allocation.push_back(a);
}
spell_type *spell_type_new(cptr name)
{
- spell_type *spell = malloc(sizeof(spell_type));
+ spell_type *spell = new spell_type(name);
assert(spell != NULL);
- spell_type_init(spell, name);
return spell;
}
@@ -283,10 +285,10 @@ int spell_type_produce_effect_lasting(spell_type *spell)
return spell->lasting_func();
}
-casting_result spell_type_produce_effect(spell_type *spell, int o_idx)
+casting_result spell_type_produce_effect(spell_type *spell)
{
assert(spell->effect_func != NULL);
- return spell->effect_func(o_idx);
+ return spell->effect_func();
}
cptr spell_type_name(spell_type *spell)
@@ -303,18 +305,11 @@ int spell_type_skill_level(spell_type *spell)
return spell->skill_level;
}
-void spell_type_description_foreach(spell_type *spell, void (*callback)(void *data, cptr text), void *data)
+void spell_type_description_foreach(spell_type *spell, std::function<void (std::string const &text)> callback)
{
- string_list *sl;
- struct sglib_string_list_iterator it;
-
- assert(callback != NULL);
-
- for (sl = sglib_string_list_it_init(&it, spell->description);
- sl != NULL;
- sl = sglib_string_list_it_next(&it))
+ for (auto line: spell->m_description)
{
- callback(data, sl->s);
+ callback(line);
}
}
@@ -323,35 +318,13 @@ long spell_type_roll_charges(spell_type *spell)
return dice_roll(&spell->device_charges);
}
-void spell_type_activation_description(spell_type *spell, char *buf)
-{
- char turns[32];
-
- dice_print(&spell->activation_timeout, turns);
-
- assert(spell->description != NULL);
- assert(spell->description->s != NULL);
-
- sprintf(buf, "%s every %s turns", spell->description->s, turns);
-}
-
-int spell_type_activation_roll_timeout(spell_type *spell)
-{
- return dice_roll(&spell->activation_timeout);
-}
-
device_allocation *spell_type_device_allocation(spell_type *spell, byte tval)
{
- struct sglib_device_allocation_iterator it;
- device_allocation *device_allocation;
-
- for (device_allocation = sglib_device_allocation_it_init(&it, spell->device_allocation);
- device_allocation != NULL;
- device_allocation = sglib_device_allocation_it_next(&it))
+ for (auto device_allocation_ptr: spell->m_device_allocation)
{
- if (device_allocation->tval == tval)
+ if (device_allocation_ptr->tval == tval)
{
- return device_allocation;
+ return device_allocation_ptr;
}
}
@@ -386,19 +359,14 @@ s16b spell_type_random_type(spell_type *spell)
return spell->random_type;
}
-bool_ spell_type_school_foreach(spell_type *spell, bool_ (*callback)(void *data, s32b school_idx), void *data)
+std::vector<s32b> const spell_type_get_schools(spell_type *spell)
{
- int i;
-
- for (i = 0; i < spell->school_idxs_count; i++)
+ std::vector<s32b> school_idxs;
+ for (size_t i = 0; i < spell->school_idxs_count; i++)
{
- if (!callback(data, spell->school_idxs[i]))
- {
- return FALSE;
- }
+ school_idxs.push_back(spell->school_idxs[i]);
}
-
- return TRUE;
+ return school_idxs;
}
bool_ spell_type_inertia(spell_type *spell, s32b *difficulty, s32b *delay)
diff --git a/src/spell_type.h b/src/spell_type.hpp
index 32d6c7b6..43758103 100644
--- a/src/spell_type.h
+++ b/src/spell_type.hpp
@@ -1,65 +1,56 @@
-#ifndef H_e7e01ebf_e19f_439d_b88d_cad51446a7a0
-#define H_e7e01ebf_e19f_439d_b88d_cad51446a7a0
+#pragma once
-#include "spell_type_fwd.h"
-
-#include "h-type.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Forward declarations
- */
-struct device_allocation;
-struct range_type;
+#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
*/
-typedef enum { USE_SPELL_POINTS, USE_PIETY } casting_type;
+enum casting_type { USE_SPELL_POINTS, USE_PIETY };
/*
* Does the spell appear on spell random books?
*/
-typedef enum { RANDOM, NO_RANDOM } random_type;
+enum random_type { RANDOM, NO_RANDOM };
/*
* Spell functions
*/
-void spell_type_init(spell_type *spell, cptr name);
void spell_type_init_music(spell_type *spell,
s16b minimum_pval,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx));
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
void spell_type_init_music_lasting(spell_type *spell,
s16b minimum_pval,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx),
+ 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,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx));
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
void spell_type_init_priest(spell_type *spell,
s32b school_idx,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx));
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
void spell_type_init_device(spell_type *spell,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx));
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
void spell_type_init_demonology(spell_type *spell,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx));
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
void spell_type_init_geomancy(spell_type *spell,
- char* (*info_func)(),
- casting_result (*effect_func)(int o_idx),
+ const char* (*info_func)(),
+ casting_result (*effect_func)(),
bool_ (*depend_func)());
-void spell_type_set_activation_timeout(spell_type *spell, cptr timeout_s);
void spell_type_set_inertia(spell_type *spell, s32b difficulty, s32b delay);
void spell_type_set_difficulty(spell_type *spell, byte skill_level, s32b failure_rate);
void spell_type_set_mana(spell_type *spell, s32b min, s32b max);
@@ -70,34 +61,26 @@ void spell_type_describe(spell_type *spell, cptr line);
void spell_type_add_school(spell_type *spell, s32b school_idx);
void spell_type_set_device_charges(spell_type *spell, cptr charges_s);
-void spell_type_add_device_allocation(spell_type *spell, struct device_allocation *a);
+void spell_type_add_device_allocation(spell_type *spell, device_allocation *a);
spell_type *spell_type_new(cptr name);
int spell_type_produce_effect_lasting(spell_type *spell);
-casting_result spell_type_produce_effect(spell_type *spell, int o_idx);
+casting_result spell_type_produce_effect(spell_type *spell);
cptr spell_type_name(spell_type *spell);
int spell_type_skill_level(spell_type *spell);
-void spell_type_description_foreach(spell_type *spell, void (*callback)(void *data, cptr text), void *data);
long spell_type_roll_charges(spell_type *spell);
-void spell_type_activation_description(spell_type *spell, char *buf);
-int spell_type_activation_roll_timeout(spell_type *spell);
struct device_allocation *spell_type_device_allocation(spell_type *spell, byte tval);
bool_ spell_type_uses_piety_to_cast(spell_type *spell);
bool_ spell_type_castable_while_blind(spell_type *spell);
bool_ spell_type_castable_while_confused(spell_type *spell);
s16b spell_type_minimum_pval(spell_type *spell);
s16b spell_type_random_type(spell_type *spell);
-bool_ spell_type_school_foreach(spell_type *spell, bool_ (*callback)(void *data, s32b school_idx), void *data);
+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);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif
+void spell_type_description_foreach(spell_type *spell, std::function<void (std::string const &text)>);
diff --git a/src/spell_type_fwd.h b/src/spell_type_fwd.hpp
index 4664592c..a3b27d27 100644
--- a/src/spell_type_fwd.h
+++ b/src/spell_type_fwd.hpp
@@ -1,9 +1,4 @@
-#ifndef H_ce003b12_cf58_444f_a927_5451f6dd8af1
-#define H_ce003b12_cf58_444f_a927_5451f6dd8af1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#pragma once
/*
* Spell effect function result
@@ -19,9 +14,3 @@ typedef enum {
*/
typedef struct spell_type spell_type;
struct spell_type;
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif
diff --git a/src/spells1.c b/src/spells1.cc
index 5aec03bf..ccfb59a2 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,9 +6,49 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "spell_type.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 <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
@@ -23,6 +59,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
@@ -175,7 +229,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 = '_';
@@ -251,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 */
@@ -303,7 +357,7 @@ void teleport_away(int m_idx, int dis)
/*
* 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;
@@ -571,7 +625,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);
@@ -801,7 +855,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);
@@ -818,7 +872,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;
@@ -937,7 +991,7 @@ 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);
}
@@ -1294,7 +1348,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))
@@ -1325,7 +1379,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 */
@@ -1341,7 +1395,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
{
@@ -1353,14 +1407,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);
@@ -1430,7 +1484,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);
@@ -1479,7 +1533,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; */
@@ -1527,14 +1581,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);
@@ -2103,75 +2157,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.
*
@@ -2669,13 +2654,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.
*
@@ -2691,18 +2677,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;
@@ -2721,7 +2705,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)
@@ -2740,23 +2727,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];
@@ -2809,28 +2806,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 */
@@ -2871,28 +2877,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 */
@@ -2931,24 +2946,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) */
@@ -2959,9 +2980,8 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
}
}
-
- /* Length */
- return (n);
+ /* Done */
+ return gp;
}
@@ -3904,8 +3924,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;
@@ -3925,11 +3943,12 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
/* 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;
@@ -3938,10 +3957,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);
@@ -4348,8 +4364,6 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
char killer [80];
- cptr name = (r_name + r_ptr->name);
-
/* Is the monster "seen"? */
bool_ seen;
@@ -4821,8 +4835,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;
@@ -4842,8 +4856,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;
@@ -5419,7 +5433,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;
@@ -5432,7 +5446,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.";
@@ -5711,7 +5725,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.";
@@ -6725,7 +6739,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.";
@@ -7216,7 +7230,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;
}
@@ -7249,13 +7263,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)
@@ -7273,7 +7285,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 */
@@ -8118,7 +8130,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?" */
@@ -8272,7 +8284,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;
@@ -8295,11 +8307,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;
@@ -8382,22 +8391,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;
@@ -8436,7 +8449,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();
@@ -8462,7 +8475,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));
}
}
}
@@ -8543,7 +8556,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];
@@ -8580,7 +8593,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));
}
}
@@ -8588,7 +8601,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];
@@ -8625,7 +8638,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++;
@@ -8658,7 +8671,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++;
@@ -8685,7 +8698,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++;
@@ -8770,7 +8783,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++;
@@ -8950,6 +8963,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;
}
@@ -9003,7 +9020,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 8778e49f..631ff30e 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,51 @@
* 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 <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 +59,7 @@
* since it is usually tested several times...
*/
-void summon_dragon_riders();
+static void summon_dragon_riders();
/*
@@ -111,7 +151,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 +349,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)
@@ -348,27 +454,9 @@ bool_ do_inc_stat(int stat)
*/
void identify_hooks(int i, object_type *o_ptr, identify_mode mode)
{
- cptr mode_s = NULL;
-
- switch (mode)
- {
- case IDENT_NORMAL:
- mode_s = "normal";
- break;
- case IDENT_FULL:
- mode_s = "full";
- break;
- default:
- assert(FALSE);
- }
-
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", i, mode_s);
-
- {
- hook_identify_in in = { o_ptr, mode };
- process_hooks_new(HOOK_IDENTIFY, &in, NULL);
- }
+ hook_identify_in in = { o_ptr, mode };
+ process_hooks_new(HOOK_IDENTIFY, &in, NULL);
}
@@ -456,7 +544,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;
@@ -595,23 +683,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)
@@ -633,12 +722,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 */
@@ -683,7 +769,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);
@@ -1202,10 +1288,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.";
@@ -2013,7 +2095,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); */
@@ -2209,83 +2291,75 @@ bool_ detect_treasure(int rad)
/*
- * Detect all "gold" objects on the current panel
+ * Detect all (string) monsters on current panel
*/
-bool_ hack_no_detect_message = FALSE;
-bool_ detect_objects_gold(int rad)
+static bool_ detect_monsters_string(cptr chars, int rad)
{
int i, y, x;
-
- bool_ detect = FALSE;
+ bool_ flag = FALSE;
- /* Scan objects */
- for (i = 1; i < o_max; i++)
+ /* Scan monsters */
+ for (i = 1; i < m_max; i++)
{
- object_type *o_ptr = &o_list[i];
+ monster_type *m_ptr = &m_list[i];
+ monster_race *r_ptr = race_inf(m_ptr);
- /* 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 */
+ 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))
{
- /* 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
+ /* Update monster recall window */
+ if (monster_race_idx == m_ptr->r_idx)
{
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
+ /* Window stuff */
+ 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;
}
}
/* Describe */
- if (detect && (!hack_no_detect_message))
- {
- msg_print("You sense the presence of treasure!");
- }
-
- if (detect_monsters_string("$", rad))
+ if (flag)
{
- detect = TRUE;
+ /* Describe result */
+ msg_print("You sense the presence of monsters!");
}
/* Result */
- return (detect);
+ return (flag);
}
+
/*
- * Detect all "normal" objects on the current panel
+ * Detect all "gold" objects on the current panel
*/
-bool_ detect_objects_normal(int rad)
+bool_ detect_objects_gold(int rad)
{
int i, y, x;
@@ -2325,8 +2399,8 @@ bool_ detect_objects_normal(int rad)
/* Only detect nearby objects */
if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
- /* Detect "real" objects */
- if (o_ptr->tval != TV_GOLD)
+ /* Detect "gold" objects */
+ if (o_ptr->tval == TV_GOLD)
{
/* Hack -- memorize it */
o_ptr->marked = TRUE;
@@ -2340,12 +2414,12 @@ 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("You sense the presence of treasure!");
}
- if (detect_monsters_string("!=?|", rad))
+ if (detect_monsters_string("$", rad))
{
detect = TRUE;
}
@@ -2356,22 +2430,16 @@ bool_ detect_objects_normal(int rad)
/*
- * 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 "normal" objects on the current panel
*/
-bool_ detect_objects_magic(int rad)
+bool_ detect_objects_normal(int rad)
{
- int i, y, x, tv;
+ int i, y, x;
bool_ detect = FALSE;
- /* Scan all objects */
+ /* Scan objects */
for (i = 1; i < o_max; i++)
{
object_type *o_ptr = &o_list[i];
@@ -2404,19 +2472,10 @@ bool_ detect_objects_magic(int rad)
/* Only detect nearby objects */
if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
- /* Examine the tval */
- tv = o_ptr->tval;
-
- /* Artifacts, misc magic items, or enchanted wearables */
- if (artifact_p(o_ptr) || ego_item_p(o_ptr) || o_ptr->art_name ||
- (tv == TV_AMULET) || (tv == TV_RING) || (tv == TV_BATERIE) ||
- (tv == TV_STAFF) || (tv == TV_WAND) || (tv == TV_ROD) || (tv == TV_ROD_MAIN) ||
- (tv == TV_SCROLL) || (tv == TV_POTION) || (tv == TV_POTION2) ||
- (tv == TV_DAEMON_BOOK) ||
- (tv == TV_SYMBIOTIC_BOOK) || (tv == TV_MUSIC_BOOK) ||
- ((o_ptr->to_a > 0) || (o_ptr->to_h + o_ptr->to_d > 0)))
+ /* Detect "real" objects */
+ if (o_ptr->tval != TV_GOLD)
{
- /* Memorize the item */
+ /* Hack -- memorize it */
o_ptr->marked = TRUE;
/* Redraw */
@@ -2430,10 +2489,15 @@ bool_ detect_objects_magic(int rad)
/* Describe */
if (detect)
{
- msg_print("You sense the presence of magic objects!");
+ msg_print("You sense the presence of objects!");
+ }
+
+ if (detect_monsters_string("!=?|", rad))
+ {
+ detect = TRUE;
}
- /* Return result */
+ /* Result */
return (detect);
}
@@ -2565,140 +2629,6 @@ bool_ detect_monsters_invis(int rad)
/*
- * Detect all "evil" monsters on current panel
- */
-bool_ detect_monsters_evil(int rad)
-{
- int i, y, x;
- bool_ flag = FALSE;
-
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect evil monsters */
- if (r_ptr->flags3 & (RF3_EVIL))
- {
- /* Take note that they are evil */
- r_ptr->r_flags3 |= (RF3_EVIL);
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- /* Describe result */
- msg_print("You sense the presence of evil creatures!");
- }
-
- /* Result */
- return (flag);
-}
-
-
-
-
-/*
- * Detect all (string) monsters on current panel
- */
-bool_ detect_monsters_string(cptr chars, int rad)
-{
- int i, y, x;
- bool_ flag = FALSE;
-
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect evil monsters */
- if (strchr(chars, r_ptr->d_char))
- {
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- /* Describe result */
- msg_print("You sense the presence of monsters!");
- }
-
- /* Result */
- return (flag);
-}
-
-
-/*
* A "generic" detect monsters routine, tagged to flags3
*/
bool_ detect_monsters_xxx(u32b match_flag, int rad)
@@ -2779,11 +2709,6 @@ bool_ detect_monsters_xxx(u32b match_flag, int rad)
return (flag);
}
-/* Detect good monsters */
-bool_ detect_monsters_good(int rad)
-{
- return (detect_monsters_xxx(RF3_GOOD, rad));
-}
/*
@@ -2837,9 +2762,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)
@@ -2868,95 +2793,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;
}
@@ -3156,24 +3058,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);
@@ -3220,231 +3124,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)
{
@@ -3750,509 +3429,6 @@ 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)
-{
- if (artifact_bias == BIAS_CHAOS && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_CHAOTIC))
- {
- o_ptr->art_flags1 |= TR1_CHAOTIC;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_PRIESTLY &&
- (o_ptr->tval == TV_SWORD || o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_AXE) &&
- !(o_ptr->art_flags3 & TR3_BLESSED))
- {
- /* A free power for "priestly" random artifacts */
- o_ptr->art_flags3 |= TR3_BLESSED;
- }
-
- else if (artifact_bias == BIAS_NECROMANTIC && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_VAMPIRIC))
- {
- o_ptr->art_flags1 |= TR1_VAMPIRIC;
- if (randint(2) == 1) return;
- }
- if (!(o_ptr->art_flags1 & TR1_BRAND_POIS) && (randint(2) == 1))
- {
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_RANGER && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_SLAY_ANIMAL))
- {
- o_ptr->art_flags1 |= TR1_SLAY_ANIMAL;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_ROGUE && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_POIS))
- {
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_POIS && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_POIS))
- {
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_FIRE && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_FIRE))
- {
- o_ptr->art_flags1 |= TR1_BRAND_FIRE;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_COLD && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_COLD))
- {
- o_ptr->art_flags1 |= TR1_BRAND_COLD;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_ELEC && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_ELEC))
- {
- o_ptr->art_flags1 |= TR1_BRAND_ELEC;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_ACID && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_ACID))
- {
- o_ptr->art_flags1 |= TR1_BRAND_ACID;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_LAW && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_SLAY_EVIL))
- {
- o_ptr->art_flags1 |= TR1_SLAY_EVIL;
- if (randint(2) == 1) return;
- }
- if (!(o_ptr->art_flags1 & TR1_SLAY_UNDEAD))
- {
- o_ptr->art_flags1 |= TR1_SLAY_UNDEAD;
- if (randint(2) == 1) return;
- }
- if (!(o_ptr->art_flags1 & TR1_SLAY_DEMON))
- {
- o_ptr->art_flags1 |= TR1_SLAY_DEMON;
- if (randint(2) == 1) return;
- }
- }
-
- if (!(o_ptr->tval == TV_BOW))
- {
- switch (randint(34))
- {
- case 1:
- case 2:
- o_ptr->art_flags1 |= TR1_SLAY_ANIMAL;
- /* if (is_scroll) msg_print("You start hating animals.");*/
- break;
-
- case 3:
- case 4:
- o_ptr->art_flags1 |= TR1_SLAY_EVIL;
- /* if (is_scroll) msg_print("You hate evil creatures.");*/
- if (!artifact_bias && (randint(2) == 1))
- artifact_bias = BIAS_LAW;
- else if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_PRIESTLY;
- break;
-
- case 5:
- case 6:
- o_ptr->art_flags1 |= TR1_SLAY_UNDEAD;
- /* if (is_scroll) msg_print("You hate undead creatures.");*/
- if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_PRIESTLY;
- break;
-
- case 7:
- case 8:
- o_ptr->art_flags1 |= TR1_SLAY_DEMON;
- /* if (is_scroll) msg_print("You hate demons.");*/
- if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_PRIESTLY;
- break;
-
- case 9:
- case 10:
- o_ptr->art_flags1 |= TR1_SLAY_ORC;
- /* if (is_scroll) msg_print("You hate orcs.");*/
- break;
-
- case 11:
- case 12:
- o_ptr->art_flags1 |= TR1_SLAY_TROLL;
- /* if (is_scroll) msg_print("You hate trolls.");*/
- break;
-
- case 13:
- case 14:
- o_ptr->art_flags1 |= TR1_SLAY_GIANT;
- /* if (is_scroll) msg_print("You hate giants.");*/
- break;
-
- case 15:
- case 16:
- o_ptr->art_flags1 |= TR1_SLAY_DRAGON;
- /* if (is_scroll) msg_print("You hate dragons.");*/
- break;
-
- case 17:
- o_ptr->art_flags1 |= TR1_KILL_DRAGON;
- /* if (is_scroll) msg_print("You feel an intense hatred of dragons.");*/
- break;
-
- case 18:
- case 19:
- if (o_ptr->tval == TV_SWORD)
- {
- o_ptr->art_flags1 |= TR1_VORPAL;
- /* if (is_scroll) msg_print("It looks extremely sharp!");*/
- if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_WARRIOR;
- }
- else random_slay(o_ptr, is_scroll);
- break;
-
- case 20:
- o_ptr->art_flags1 |= TR1_IMPACT;
- /* if (is_scroll) msg_print("The ground trembles beneath you.");*/
- break;
-
- case 21:
- case 22:
- o_ptr->art_flags1 |= TR1_BRAND_FIRE;
- /* if (is_scroll) msg_print("It feels hot!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_FIRE;
- break;
-
- case 23:
- case 24:
- o_ptr->art_flags1 |= TR1_BRAND_COLD;
- /* if (is_scroll) msg_print("It feels cold!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_COLD;
- break;
-
- case 25:
- case 26:
- o_ptr->art_flags1 |= TR1_BRAND_ELEC;
- /* if (is_scroll) msg_print("Ouch! You get zapped!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_ELEC;
- break;
-
- case 27:
- case 28:
- o_ptr->art_flags1 |= TR1_BRAND_ACID;
- /* if (is_scroll) msg_print("Its smell makes you feel dizzy.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_ACID;
- break;
-
- case 29:
- case 30:
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- /* if (is_scroll) msg_print("It smells rotten.");*/
- if (!artifact_bias && (randint(3) != 1))
- artifact_bias = BIAS_POIS;
- else if (!artifact_bias && randint(6) == 1)
- artifact_bias = BIAS_NECROMANTIC;
- else if (!artifact_bias)
- artifact_bias = BIAS_ROGUE;
- break;
-
- case 31:
- case 32:
- o_ptr->art_flags1 |= TR1_VAMPIRIC;
- /* if (is_scroll) msg_print("You think it bit you!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_NECROMANTIC;
- break;
-
- default:
- o_ptr->art_flags1 |= TR1_CHAOTIC;
- /* if (is_scroll) msg_print("It looks very confusing.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_CHAOS;
- break;
- }
- }
- else
- {
- switch (randint(6))
- {
- case 1:
- case 2:
- case 3:
- o_ptr->art_flags3 |= TR3_XTRA_MIGHT;
- /* if (is_scroll) msg_print("It looks mightier than before."); */
- if (!artifact_bias && randint(9) == 1)
- artifact_bias = BIAS_RANGER;
- break;
-
- default:
- o_ptr->art_flags3 |= TR3_XTRA_SHOTS;
- /* if (is_scroll) msg_print("It seems faster!"); */
- if (!artifact_bias && randint(9) == 1)
- artifact_bias = BIAS_RANGER;
- break;
- }
- }
-}
-
-
-
-
-/*
- * Determines if an item is not identified
- */
-static bool_ item_tester_hook_unknown(object_type *o_ptr)
-{
- return (object_known_p(o_ptr) ? FALSE : TRUE);
-}
-
-
/*
@@ -4283,22 +3459,16 @@ static void note_found_object(object_type *o_ptr)
*/
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);
@@ -4314,6 +3484,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 */
@@ -4377,9 +3548,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);
}
/*
@@ -4388,20 +3559,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);
@@ -4416,6 +3586,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 */
@@ -4454,27 +3625,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;
}
@@ -4501,31 +3664,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" */
@@ -4828,47 +3988,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)
@@ -4877,14 +3996,6 @@ bool_ banish_evil(int dist)
}
-/*
- * Turn undead
- */
-bool_ turn_undead(void)
-{
- return (project_hack(GF_TURN_UNDEAD, p_ptr->lev));
-}
-
/*
* Dispel undead monsters
@@ -4918,22 +4029,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.
@@ -5022,70 +4117,6 @@ bool_ get_genocide_race(cptr msg, char *typ)
return FALSE;
}
-/*
- * Inflict dam damage of type typee to all monster of the given race
- */
-bool_ invoke(int dam, int typee)
-{
- int i;
- char typ;
- bool_ result = FALSE;
- int msec = delay_factor * delay_factor * delay_factor;
-
- if (dungeon_flags2 & DF2_NO_GENO) return (FALSE);
-
- /* Hack -- when you are fated to die, you cant cheat :) */
- if (dungeon_type == DUNGEON_DEATH)
- {
- msg_print("A mysterious force stops the genocide.");
- return FALSE;
- }
-
- /* Get a monster symbol */
- if (!get_genocide_race("Target a monster to select the race to invoke on.", &typ)) return FALSE;
-
- /* Delete the monsters of that "type" */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Hack -- Skip Unique Monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) continue;
-
- /* Hack -- Skip Quest Monsters */
- if (m_ptr->mflag & MFLAG_QUEST) continue;
-
- /* Skip "wrong" monsters */
- if (r_ptr->d_char != typ) continue;
-
- project_m(0, 0, m_ptr->fy, m_ptr->fx, dam, typee);
-
- /* Visual feedback */
- move_cursor_relative(p_ptr->py, p_ptr->px);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-
- /* Handle */
- handle_stuff();
-
- /* Fresh */
- Term_fresh();
-
- /* Delay */
- Term_xtra(TERM_XTRA_DELAY, msec);
-
- /* Take note */
- result = TRUE;
- }
-
- return (result);
-}
-
/*
* Delete all non-unique/non-quest monsters of a given "type" from the level
@@ -5120,8 +4151,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
{
@@ -5131,7 +4163,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;
@@ -5153,7 +4185,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;
@@ -5168,7 +4200,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);
@@ -5245,8 +4277,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
{
@@ -5256,7 +4289,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;
@@ -5278,7 +4311,7 @@ bool_ mass_genocide(bool_ player_cast)
Term_fresh();
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
/* Note effect */
result = TRUE;
@@ -5293,7 +4326,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);
@@ -5339,7 +4372,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 */
@@ -5393,89 +4431,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).
@@ -5483,7 +4438,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;
@@ -5492,15 +4447,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;
}
@@ -5807,7 +4759,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 */
@@ -6011,7 +4963,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);
@@ -6416,62 +5368,6 @@ 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)
@@ -6570,7 +5466,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);
@@ -6623,7 +5519,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);
@@ -6672,7 +5568,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);
@@ -6720,28 +5616,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
@@ -6770,19 +5644,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
@@ -6815,13 +5676,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;
@@ -6829,20 +5683,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;
@@ -6857,13 +5697,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;
@@ -6871,13 +5704,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;
@@ -6885,13 +5711,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;
@@ -6899,13 +5718,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;
@@ -6920,16 +5732,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;
@@ -6937,13 +5739,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];
@@ -7039,6 +5834,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
@@ -7233,72 +6094,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;
@@ -7310,7 +6105,7 @@ void summon_cyber(void)
}
}
-void summon_dragon_riders()
+static void summon_dragon_riders()
{
int i;
int max_dr = (dun_level / 50) + randint(6);
@@ -7322,230 +6117,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
@@ -7573,14 +6144,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
@@ -7592,15 +6155,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)
@@ -7619,15 +6173,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)
@@ -7636,28 +6181,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;
@@ -7716,7 +6245,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)
@@ -7826,7 +6355,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);
@@ -7840,20 +6369,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)
@@ -7872,26 +6402,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);
}
}
@@ -7900,7 +6445,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)
@@ -7919,7 +6464,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;
}
@@ -7927,34 +6476,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);
@@ -7979,26 +6518,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;
}
@@ -8017,7 +6559,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);
@@ -8035,26 +6577,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
*/
@@ -8304,6 +6826,19 @@ void geomancy_dig(int oy, int ox, int dir, int length)
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:
@@ -8328,18 +6863,16 @@ void channel_the_elements(int y, int x, int level)
case FEAT_SHAL_WATER:
{
- int dir, type;
+ int dir;
if (!get_aim_dir(&dir)) break;
- type = (get_skill(SKILL_WATER) >= 18) ? GF_WAVE : GF_WATER;
-
if (get_skill(SKILL_WATER) >= 8)
{
- fire_beam(type, dir, damroll(3, get_skill(SKILL_WATER)));
+ fire_beam(water_type(), dir, damroll(3, get_skill(SKILL_WATER)));
}
else
{
- fire_bolt(type, dir, damroll(3, get_skill(SKILL_WATER)));
+ fire_bolt(water_type(), dir, damroll(3, get_skill(SKILL_WATER)));
}
break;
@@ -8347,18 +6880,16 @@ void channel_the_elements(int y, int x, int level)
case FEAT_DEEP_WATER:
{
- int dir, type;
+ int dir;
if (!get_aim_dir(&dir)) break;
- type = (get_skill(SKILL_WATER) >= 18) ? GF_WAVE : GF_WATER;
-
if (get_skill(SKILL_WATER) >= 8)
{
- fire_beam(type, dir, damroll(5, get_skill(SKILL_WATER)));
+ fire_beam(water_type(), dir, damroll(5, get_skill(SKILL_WATER)));
}
else
{
- fire_bolt(type, dir, damroll(5, get_skill(SKILL_WATER)));
+ fire_bolt(water_type(), dir, damroll(5, get_skill(SKILL_WATER)));
}
break;
@@ -8384,8 +6915,8 @@ void channel_the_elements(int y, int x, int level)
case FEAT_SAND:
{
int type, dur;
-
- type = (get_level(FIERYAURA, 50, 1) >= 8) ? SHIELD_GREAT_FIRE : SHIELD_FIRE;
+
+ 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));
@@ -8399,15 +6930,7 @@ void channel_the_elements(int y, int x, int level)
int dir;
if (!get_aim_dir(&dir)) break;
- if (get_skill(SKILL_FIRE) >= 15)
- {
- fire_bolt(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15));
- }
- else
- {
- fire_bolt(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15));
- }
-
+ fire_bolt(fire_type(), dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15));
break;
}
@@ -8416,15 +6939,7 @@ void channel_the_elements(int y, int x, int level)
int dir;
if (!get_aim_dir(&dir)) break;
- if (get_skill(SKILL_FIRE) >= 15)
- {
- fire_ball(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3);
- }
- else
- {
- fire_ball(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3);
- }
-
+ fire_ball(fire_type(), dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3);
break;
}
diff --git a/src/spells2.hpp b/src/spells2.hpp
new file mode 100644
index 00000000..1806e6b0
--- /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.c b/src/spells3.cc
index 269e861a..e209feb1 100644
--- a/src/spells3.c
+++ b/src/spells3.cc
@@ -1,8 +1,36 @@
-#include "angband.h"
-
-#include <assert.h>
-
-#include "spell_type.h"
+#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 <algorithm>
+#include <cassert>
+#include <vector>
s32b NOXIOUSCLOUD = -1; /* Identifier */
s32b AIRWINGS = -1; /* Identifier */
@@ -126,14 +154,8 @@ s32b DEVICE_WISH;
s32b DEVICE_SUMMON;
s32b DEVICE_MANA;
s32b DEVICE_NOTHING;
-s32b DEVICE_LEBOHAUM;
-s32b DEVICE_MAGGOT;
s32b DEVICE_HOLY_FIRE;
-s32b DEVICE_ETERNAL_FLAME;
-s32b DEVICE_DURANDIL;
s32b DEVICE_THUNDERLORDS;
-s32b DEVICE_RADAGAST = -1;
-s32b DEVICE_VALAROMA = -1;
s32b MUSIC_STOP;
s32b MUSIC_HOLD;
@@ -169,11 +191,22 @@ s32b VARDA_CALL_ALMAREN;
s32b VARDA_EVENSTAR;
s32b VARDA_STARKINDLER;
-s32b get_level_s(int sp, int max)
+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;
@@ -197,7 +230,11 @@ static casting_result cplus(casting_result old, bool_ effect)
}
}
-casting_result air_noxious_cloud(int item)
+GENERATE_MONSTER_LOOKUP_FN(get_fire_golem, "Fire golem")
+
+// -------------------------------------------------------------
+
+casting_result air_noxious_cloud()
{
int dir, type;
@@ -219,7 +256,7 @@ casting_result air_noxious_cloud(int item)
return CAST_OBVIOUS;
}
-char *air_noxious_cloud_info()
+const char *air_noxious_cloud_info()
{
static char buf[128];
sprintf(buf,
@@ -229,7 +266,7 @@ char *air_noxious_cloud_info()
return buf;
}
-casting_result air_wings_of_winds(int item)
+casting_result air_wings_of_winds()
{
if (get_level_s(AIRWINGS, 50) >= 16)
{
@@ -249,14 +286,14 @@ casting_result air_wings_of_winds(int item)
return CAST_HIDDEN;
}
-char *air_wings_of_winds_info()
+const char *air_wings_of_winds_info()
{
static char buf[128];
sprintf(buf, "dur " FMTs32b "+d10", (5 + get_level_s(AIRWINGS, 25)));
return buf;
}
-casting_result air_invisibility(int item)
+casting_result air_invisibility()
{
if (p_ptr->tim_invisible == 0)
{
@@ -266,7 +303,7 @@ casting_result air_invisibility(int item)
return CAST_HIDDEN;
}
-char *air_invisibility_info()
+const char *air_invisibility_info()
{
static char buf[128];
sprintf(buf, "dur " FMTs32b "+d20 power " FMTs32b,
@@ -275,7 +312,7 @@ char *air_invisibility_info()
return buf;
}
-casting_result air_poison_blood(int item)
+casting_result air_poison_blood()
{
casting_result result = NO_CAST;
@@ -293,7 +330,7 @@ casting_result air_poison_blood(int item)
return result;
}
-char *air_poison_blood_info()
+const char *air_poison_blood_info()
{
static char buf[128];
sprintf(buf,
@@ -302,7 +339,7 @@ char *air_poison_blood_info()
return buf;
}
-casting_result air_thunderstorm(int item)
+casting_result air_thunderstorm()
{
if (p_ptr->tim_thunder == 0)
{
@@ -312,7 +349,7 @@ casting_result air_thunderstorm(int item)
return CAST_HIDDEN;
}
-char *air_thunderstorm_info()
+const char *air_thunderstorm_info()
{
static char buf[128];
sprintf(buf,
@@ -323,13 +360,13 @@ char *air_thunderstorm_info()
return buf;
}
-casting_result air_sterilize(int item)
+casting_result air_sterilize()
{
set_no_breeders((30) + 20 + get_level_s(STERILIZE, 70));
return CAST_OBVIOUS;
}
-char *air_sterilize_info()
+const char *air_sterilize_info()
{
static char buf[128];
sprintf(buf,
@@ -338,7 +375,7 @@ char *air_sterilize_info()
return buf;
}
-casting_result convey_blink(int item)
+casting_result convey_blink()
{
if (get_level_s(BLINK, 50) >= 30)
{
@@ -356,7 +393,7 @@ casting_result convey_blink(int item)
}
}
-char *convey_blink_info()
+const char *convey_blink_info()
{
static char buf[128];
sprintf(buf,
@@ -365,7 +402,7 @@ char *convey_blink_info()
return buf;
}
-casting_result convey_disarm(int item)
+casting_result convey_disarm()
{
casting_result result = NO_CAST;
@@ -378,19 +415,14 @@ casting_result convey_disarm(int item)
return result;
}
-char *convey_disarm_info()
-{
- return "";
-}
-
-casting_result convey_teleport(int item)
+casting_result convey_teleport()
{
p_ptr->energy -= (25 - get_level_s(TELEPORT, 50));
teleport_player(100 + get_level_s(TELEPORT, 100));
return CAST_OBVIOUS;
}
-char *convey_teleport_info()
+const char *convey_teleport_info()
{
static char buf[128];
sprintf(buf,
@@ -399,7 +431,7 @@ char *convey_teleport_info()
return buf;
}
-casting_result convey_teleport_away(int item)
+casting_result convey_teleport_away()
{
if (get_level_s(TELEAWAY, 50) >= 20)
{
@@ -426,11 +458,6 @@ casting_result convey_teleport_away(int item)
}
}
-char *convey_teleport_away_info()
-{
- return "";
-}
-
static int recall_get_d()
{
int d = 21 - get_level_s(RECALL, 15);
@@ -451,7 +478,7 @@ static int recall_get_f()
return f;
}
-casting_result convey_recall(int item)
+casting_result convey_recall()
{
int x,y;
cave_type *c_ptr;
@@ -476,9 +503,13 @@ casting_result convey_recall(int item)
swap_position(y, x);
return CAST_OBVIOUS;
}
- else if (c_ptr->o_idx > 0)
+ else if (!c_ptr->o_idxs.empty())
{
- set_target(y, x);
+ // 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);
@@ -495,7 +526,7 @@ casting_result convey_recall(int item)
}
}
-char *convey_recall_info()
+const char *convey_recall_info()
{
static char buf[128];
int d = recall_get_d();
@@ -507,12 +538,12 @@ char *convey_recall_info()
return buf;
}
-casting_result convey_probability_travel(int item)
+casting_result convey_probability_travel()
{
return cast(set_prob_travel(randint(20) + get_level_s(PROBABILITY_TRAVEL, 60)));
}
-char *convey_probability_travel_info()
+const char *convey_probability_travel_info()
{
static char buf[128];
sprintf(buf,
@@ -521,7 +552,7 @@ char *convey_probability_travel_info()
return buf;
}
-casting_result demonology_demon_blade(int item)
+casting_result demonology_demon_blade()
{
int rad, type;
@@ -544,7 +575,7 @@ casting_result demonology_demon_blade(int item)
PROJECT_STOP | PROJECT_KILL));
}
-char *demonology_demon_blade_info()
+const char *demonology_demon_blade_info()
{
static char buf[128];
sprintf(buf,
@@ -554,7 +585,7 @@ char *demonology_demon_blade_info()
return buf;
}
-casting_result demonology_demon_madness(int item)
+casting_result demonology_demon_madness()
{
casting_result result = NO_CAST;
int dir, type, y1, x1, y2, x2;
@@ -574,8 +605,24 @@ casting_result demonology_demon_madness(int item)
type = GF_CHARM;
}
- /* Calc the coordinates of arrival */
- get_target(dir, &y1, &x1);
+ // 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);
@@ -595,7 +642,7 @@ casting_result demonology_demon_madness(int item)
return result;
}
-char *demonology_demon_madness_info()
+const char *demonology_demon_madness_info()
{
static char buf[128];
sprintf(buf,
@@ -605,7 +652,7 @@ char *demonology_demon_madness_info()
return buf;
}
-casting_result demonology_demon_field(int item)
+casting_result demonology_demon_field()
{
int dir;
@@ -621,7 +668,7 @@ casting_result demonology_demon_field(int item)
30 + get_level_s(DEMON_FIELD, 100)));
}
-char *demonology_demon_field_info()
+const char *demonology_demon_field_info()
{
static char buf[128];
sprintf(buf,
@@ -631,7 +678,7 @@ char *demonology_demon_field_info()
return buf;
}
-casting_result demonology_doom_shield(int item)
+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),
@@ -640,7 +687,7 @@ casting_result demonology_doom_shield(int item)
10 + get_level_s(DOOM_SHIELD, 15)));
}
-char *demonology_doom_shield_info()
+const char *demonology_doom_shield_info()
{
static char buf[128];
sprintf(buf,
@@ -651,7 +698,7 @@ char *demonology_doom_shield_info()
return buf;
}
-casting_result demonology_unholy_word(int item)
+casting_result demonology_unholy_word()
{
int x, y;
cave_type *c_ptr = NULL;
@@ -708,7 +755,7 @@ casting_result demonology_unholy_word(int item)
}
}
-char *demonology_unholy_word_info()
+const char *demonology_unholy_word_info()
{
static char buf[128];
sprintf(buf,
@@ -717,12 +764,12 @@ char *demonology_unholy_word_info()
return buf;
}
-casting_result demonology_demon_cloak(int item)
+casting_result demonology_demon_cloak()
{
return cast(set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0)));
}
-char *demonology_demon_cloak_info()
+const char *demonology_demon_cloak_info()
{
static char buf[128];
sprintf(buf,
@@ -731,7 +778,7 @@ char *demonology_demon_cloak_info()
return buf;
}
-casting_result demonology_summon_demon(int item)
+casting_result demonology_summon_demon()
{
int type, level, minlevel;
@@ -762,7 +809,7 @@ casting_result demonology_summon_demon(int item)
}
}
-char *demonology_summon_demon_info()
+const char *demonology_summon_demon_info()
{
static char buf[128];
sprintf(buf,
@@ -771,7 +818,7 @@ char *demonology_summon_demon_info()
return buf;
}
-casting_result demonology_discharge_minion(int item)
+casting_result demonology_discharge_minion()
{
cave_type *c_ptr;
int x, y;
@@ -813,7 +860,7 @@ casting_result demonology_discharge_minion(int item)
}
}
-char *demonology_discharge_minion_info()
+const char *demonology_discharge_minion_info()
{
static char buf[128];
sprintf(buf,
@@ -823,7 +870,7 @@ char *demonology_discharge_minion_info()
return buf;
}
-casting_result demonology_control_demon(int item)
+casting_result demonology_control_demon()
{
int dir;
if (!get_aim_dir(&dir))
@@ -834,7 +881,7 @@ casting_result demonology_control_demon(int item)
return cast(fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level_s(CONTROL_DEMON, 250), 0));
}
-char *demonology_control_demon_info()
+const char *demonology_control_demon_info()
{
static char buf[128];
sprintf(buf,
@@ -843,7 +890,7 @@ char *demonology_control_demon_info()
return buf;
}
-casting_result divination_greater_identify(int item)
+casting_result divination_greater_identify()
{
if (get_check("Cast on yourself?"))
{
@@ -856,12 +903,7 @@ casting_result divination_greater_identify(int item)
return CAST_OBVIOUS;
}
-char *divination_greater_identify_info()
-{
- return "";
-}
-
-casting_result divination_identify(int item)
+casting_result divination_identify()
{
if (get_level_s(IDENTIFY, 50) >= 27)
{
@@ -887,7 +929,7 @@ casting_result divination_identify(int item)
}
}
-char *divination_identify_info()
+const char *divination_identify_info()
{
static char buf[128];
@@ -902,7 +944,7 @@ char *divination_identify_info()
}
}
-casting_result divination_vision(int item)
+casting_result divination_vision()
{
if (get_level_s(VISION, 50) >= 25)
{
@@ -916,12 +958,7 @@ casting_result divination_vision(int item)
}
-char *divination_vision_info()
-{
- return "";
-}
-
-casting_result divination_sense_hidden(int item)
+casting_result divination_sense_hidden()
{
casting_result result = NO_CAST;
@@ -934,7 +971,7 @@ casting_result divination_sense_hidden(int item)
return result;
}
-char *divination_sense_hidden_info()
+const char *divination_sense_hidden_info()
{
static char buf[128];
@@ -955,7 +992,7 @@ char *divination_sense_hidden_info()
return buf;
}
-casting_result divination_reveal_ways(int item)
+casting_result divination_reveal_ways()
{
casting_result result = NO_CAST;
result = cplus(result, detect_doors(10 + get_level(REVEALWAYS, 40, 0)));
@@ -963,7 +1000,7 @@ casting_result divination_reveal_ways(int item)
return result;
}
-char *divination_reveal_ways_info()
+const char *divination_reveal_ways_info()
{
static char buf[128];
sprintf(buf,
@@ -972,7 +1009,7 @@ char *divination_reveal_ways_info()
return buf;
}
-casting_result divination_sense_monsters(int item)
+casting_result divination_sense_monsters()
{
casting_result result = NO_CAST;
@@ -984,7 +1021,7 @@ casting_result divination_sense_monsters(int item)
return result;
}
-char *divination_sense_monsters_info()
+const char *divination_sense_monsters_info()
{
static char buf[128];
@@ -1005,7 +1042,7 @@ char *divination_sense_monsters_info()
return buf;
}
-casting_result earth_stone_skin(int item)
+casting_result earth_stone_skin()
{
int type;
@@ -1022,7 +1059,7 @@ casting_result earth_stone_skin(int item)
3 + get_level_s(STONESKIN, 5)));
}
-char *earth_stone_skin_info()
+const char *earth_stone_skin_info()
{
static char buf[128];
@@ -1046,7 +1083,7 @@ char *earth_stone_skin_info()
return buf;
}
-casting_result earth_dig(int item)
+casting_result earth_dig()
{
int dir;
if (!get_aim_dir(&dir))
@@ -1057,12 +1094,7 @@ casting_result earth_dig(int item)
return cast(wall_to_mud(dir));
}
-char *earth_dig_info()
-{
- return "";
-}
-
-casting_result earth_stone_prison(int item)
+casting_result earth_stone_prison()
{
int x,y;
@@ -1083,12 +1115,7 @@ casting_result earth_stone_prison(int item)
return CAST_OBVIOUS;
}
-char *earth_stone_prison_info()
-{
- return "";
-}
-
-casting_result earth_strike(int item)
+casting_result earth_strike()
{
int dir, dmg;
@@ -1108,7 +1135,7 @@ casting_result earth_strike(int item)
}
}
-char *earth_strike_info()
+const char *earth_strike_info()
{
static char buf[128];
int dmg = 50 + get_level_s(STRIKE, 50);
@@ -1125,7 +1152,7 @@ char *earth_strike_info()
return buf;
}
-casting_result earth_shake(int item)
+casting_result earth_shake()
{
int x,y;
@@ -1145,14 +1172,14 @@ casting_result earth_shake(int item)
return CAST_OBVIOUS;
}
-char *earth_shake_info()
+const char *earth_shake_info()
{
static char buf[128];
sprintf(buf, "rad " FMTs32b, (4 + get_level_s(SHAKE, 10)));
return buf;
}
-casting_result eru_see_the_music(int item)
+casting_result eru_see_the_music()
{
casting_result result = NO_CAST;
@@ -1177,7 +1204,7 @@ casting_result eru_see_the_music(int item)
return result;
}
-char *eru_see_the_music_info()
+const char *eru_see_the_music_info()
{
static char buf[128];
sprintf(buf,
@@ -1186,7 +1213,7 @@ char *eru_see_the_music_info()
return buf;
}
-casting_result eru_listen_to_the_music(int item)
+casting_result eru_listen_to_the_music()
{
casting_result result = NO_CAST;
@@ -1207,12 +1234,7 @@ casting_result eru_listen_to_the_music(int item)
return result;
}
-char *eru_listen_to_the_music_info()
-{
- return "";
-}
-
-casting_result eru_know_the_music(int item)
+casting_result eru_know_the_music()
{
if (get_level_s(ERU_UNDERSTAND, 50) >= 10)
{
@@ -1225,17 +1247,12 @@ casting_result eru_know_the_music(int item)
}
}
-char *eru_know_the_music_info()
-{
- return "";
-}
-
-casting_result eru_lay_of_protection(int item)
+casting_result eru_lay_of_protection()
{
return cast(fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0)));
}
-char *eru_lay_of_protection_info()
+const char *eru_lay_of_protection_info()
{
static char buf[128];
sprintf(buf,
@@ -1244,7 +1261,7 @@ char *eru_lay_of_protection_info()
return buf;
}
-casting_result fire_globe_of_light(int item)
+casting_result fire_globe_of_light()
{
casting_result result = NO_CAST;
@@ -1271,7 +1288,7 @@ casting_result fire_globe_of_light(int item)
return result;
}
-char *fire_globe_of_light_info()
+const char *fire_globe_of_light_info()
{
static char buf[128];
@@ -1289,7 +1306,7 @@ char *fire_globe_of_light_info()
return buf;
}
-casting_result fire_fireflash(int item)
+casting_result fire_fireflash()
{
int dir;
int type = GF_FIRE;
@@ -1309,7 +1326,7 @@ casting_result fire_fireflash(int item)
2 + get_level_s(FIREFLASH, 5)));
}
-char *fire_fireflash_info()
+const char *fire_fireflash_info()
{
static char buf[128];
sprintf(buf,
@@ -1319,7 +1336,7 @@ char *fire_fireflash_info()
return buf;
}
-casting_result fire_fiery_shield(int item)
+casting_result fire_fiery_shield()
{
int type = SHIELD_FIRE;
if (get_level_s(FIERYAURA, 50) >= 8)
@@ -1334,7 +1351,7 @@ casting_result fire_fiery_shield(int item)
5 + get_level_s(FIERYAURA, 7)));
}
-char *fire_fiery_shield_info()
+const char *fire_fiery_shield_info()
{
static char buf[128];
sprintf(buf,
@@ -1345,7 +1362,7 @@ char *fire_fiery_shield_info()
return buf;
}
-casting_result fire_firewall(int item)
+casting_result fire_firewall()
{
int dir;
int type = GF_FIRE;
@@ -1365,7 +1382,7 @@ casting_result fire_firewall(int item)
return CAST_OBVIOUS;
}
-char *fire_firewall_info()
+const char *fire_firewall_info()
{
static char buf[128];
sprintf(buf,
@@ -1375,17 +1392,19 @@ char *fire_firewall_info()
return buf;
}
-bool_ item_tester_hook_fire_golem(object_type *o_ptr)
+object_filter_t const &item_tester_hook_fire_golem()
{
- return ((o_ptr->tval == TV_LITE) &&
- ((o_ptr->sval == SV_LITE_TORCH) ||
- (o_ptr->sval == SV_LITE_LANTERN)));
+ 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(int ignored)
+casting_result fire_golem()
{
- int item, x, y, m_idx;
-
/* Can we reconnect ? */
if (do_control_reconnect())
{
@@ -1393,11 +1412,12 @@ casting_result fire_golem(int ignored)
return NO_CAST;
}
- item_tester_hook = item_tester_hook_fire_golem;
+ 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))
+ USE_INVEN | USE_EQUIP,
+ item_tester_hook_fire_golem()))
{
return NO_CAST;
}
@@ -1405,11 +1425,15 @@ casting_result fire_golem(int ignored)
/* Destroy the source object */
inc_stack_size(item, -1);
- /* Summon it */
- m_allow_special[1043 + 1] = TRUE;
+ /* Find a place for it */
+ int x, y;
find_position(p_ptr->py, p_ptr->px, &y, &x);
- m_idx = place_monster_one(y, x, 1043, 0, FALSE, MSTATUS_FRIEND);
- m_allow_special[1043 + 1] = FALSE;
+
+ /* 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)
@@ -1422,7 +1446,7 @@ casting_result fire_golem(int ignored)
return CAST_OBVIOUS;
}
-char *fire_golem_info()
+const char *fire_golem_info()
{
static char buf[128];
sprintf(buf,
@@ -1431,7 +1455,7 @@ char *fire_golem_info()
return buf;
}
-casting_result geomancy_call_the_elements(int item)
+casting_result geomancy_call_the_elements()
{
int dir = 0;
@@ -1451,7 +1475,7 @@ casting_result geomancy_call_the_elements(int item)
return CAST_OBVIOUS;
}
-char *geomancy_call_the_elements_info()
+const char *geomancy_call_the_elements_info()
{
static char buf[128];
sprintf(buf,
@@ -1460,23 +1484,18 @@ char *geomancy_call_the_elements_info()
return buf;
}
-casting_result geomancy_channel_elements(int item)
+casting_result geomancy_channel_elements()
{
channel_the_elements(p_ptr->py, p_ptr->px, get_level_s(CHANNEL_ELEMENTS, 50));
return CAST_OBVIOUS;
}
-char *geomancy_channel_elements_info()
-{
- return "";
-}
-
typedef struct eff_type eff_type;
struct eff_type {
s16b feat;
s16b low_effect;
s16b high_effect;
- s16b damage;
+ int damage;
};
static eff_type *geomancy_find_effect(eff_type effs[], int feat)
@@ -1516,7 +1535,7 @@ static u32b dir_to_eff_flags(int dir)
return 0;
}
-casting_result geomancy_elemental_wave(int item)
+casting_result geomancy_elemental_wave()
{
int dir = 0, y = 0, x = 0;
eff_type *eff_ptr = NULL;
@@ -1576,12 +1595,7 @@ casting_result geomancy_elemental_wave(int item)
}
}
-char *geomancy_elemental_wave_info()
-{
- return "";
-}
-
-casting_result geomancy_vaporize(int item)
+casting_result geomancy_vaporize()
{
eff_type *eff_ptr = NULL;
eff_type t[] = {
@@ -1627,7 +1641,7 @@ casting_result geomancy_vaporize(int item)
}
}
-char *geomancy_vaporize_info()
+const char *geomancy_vaporize_info()
{
static char buf[128];
sprintf(buf,
@@ -1642,7 +1656,7 @@ bool_ geomancy_vaporize_depends()
return get_skill(SKILL_AIR) >= 4;
}
-casting_result geomancy_geolysis(int item)
+casting_result geomancy_geolysis()
{
int dir = 0;
@@ -1657,7 +1671,7 @@ casting_result geomancy_geolysis(int item)
return CAST_OBVIOUS;
}
-char *geomancy_geolysis_info()
+const char *geomancy_geolysis_info()
{
static char buf[128];
sprintf(buf,
@@ -1671,7 +1685,7 @@ bool_ geomancy_geolysis_depends()
return get_skill(SKILL_EARTH) >= 7;
}
-casting_result geomancy_dripping_tread(int item)
+casting_result geomancy_dripping_tread()
{
if (p_ptr->dripping_tread == 0)
{
@@ -1687,7 +1701,7 @@ casting_result geomancy_dripping_tread(int item)
return CAST_OBVIOUS;
}
-char *geomancy_dripping_tread_info()
+const char *geomancy_dripping_tread_info()
{
static char buf[128];
sprintf(buf,
@@ -1701,7 +1715,7 @@ bool_ geomancy_dripping_tread_depends()
return get_skill(SKILL_WATER) >= 10;
}
-casting_result geomancy_grow_barrier(int item)
+casting_result geomancy_grow_barrier()
{
int dir = 0;
@@ -1717,11 +1731,6 @@ casting_result geomancy_grow_barrier(int item)
return CAST_OBVIOUS;
}
-char *geomancy_grow_barrier_info()
-{
- return "";
-}
-
bool_ geomancy_grow_barrier_depends()
{
return get_skill(SKILL_EARTH) >= 12;
@@ -1757,7 +1766,7 @@ int geomancy_count_elements(cptr *elements)
return i;
}
-casting_result geomancy_elemental_minion(int item)
+casting_result geomancy_elemental_minion()
{
int dir = 0;
int x = 0, y = 0;
@@ -1852,7 +1861,7 @@ casting_result geomancy_elemental_minion(int item)
}
}
-char *geomancy_elemental_minion_info()
+const char *geomancy_elemental_minion_info()
{
static char buf[128];
sprintf(buf,
@@ -1867,7 +1876,7 @@ static void get_manathrust_dam(s16b *num, s16b *sides)
*sides = 1 + get_level_s(MANATHRUST, 20);
}
-casting_result mana_manathrust(int item)
+casting_result mana_manathrust()
{
int dir;
s16b num = 0;
@@ -1882,7 +1891,7 @@ casting_result mana_manathrust(int item)
return cast(fire_bolt(GF_MANA, dir, damroll(num, sides)));
}
-char *mana_manathrust_info()
+const char *mana_manathrust_info()
{
s16b num = 0;
s16b sides = 0;
@@ -1896,7 +1905,7 @@ char *mana_manathrust_info()
return buf;
}
-casting_result mana_remove_curses(int item)
+casting_result mana_remove_curses()
{
casting_result result = NO_CAST;
@@ -1917,12 +1926,7 @@ casting_result mana_remove_curses(int item)
return result;
}
-char *mana_remove_curses_info()
-{
- return "";
-}
-
-casting_result mana_elemental_shield(int item)
+casting_result mana_elemental_shield()
{
casting_result res = NO_CAST;
@@ -1949,7 +1953,7 @@ casting_result mana_elemental_shield(int item)
return res;
}
-char *mana_elemental_shield_info()
+const char *mana_elemental_shield_info()
{
static char buf[128];
sprintf(buf,
@@ -1958,7 +1962,7 @@ char *mana_elemental_shield_info()
return buf;
}
-casting_result mana_disruption_shield(int item)
+casting_result mana_disruption_shield()
{
if (get_level_s(MANASHIELD, 50) >= 5)
{
@@ -1975,7 +1979,7 @@ casting_result mana_disruption_shield(int item)
return NO_CAST;
}
-char *mana_disruption_shield_info()
+const char *mana_disruption_shield_info()
{
static char buf[128];
sprintf(buf,
@@ -1984,7 +1988,7 @@ char *mana_disruption_shield_info()
return buf;
}
-casting_result manwe_wind_shield(int item)
+casting_result manwe_wind_shield()
{
casting_result res = NO_CAST;
s32b dur = get_level_s(MANWE_SHIELD, 50) + 10 + randint(20);
@@ -2010,7 +2014,7 @@ casting_result manwe_wind_shield(int item)
return res;
}
-char *manwe_wind_shield_info()
+const char *manwe_wind_shield_info()
{
static char buf[128];
@@ -2037,7 +2041,7 @@ char *manwe_wind_shield_info()
return buf;
}
-casting_result manwe_avatar(int item)
+casting_result manwe_avatar()
{
s16b mimic_idx = resolve_mimic_name("Maia");
assert(mimic_idx >= 0);
@@ -2047,7 +2051,7 @@ casting_result manwe_avatar(int item)
p_ptr->lev));
}
-char *manwe_avatar_info()
+const char *manwe_avatar_info()
{
static char buf[128];
sprintf(buf,
@@ -2056,7 +2060,7 @@ char *manwe_avatar_info()
return buf;
}
-casting_result manwe_blessing(int item)
+casting_result manwe_blessing()
{
casting_result res = NO_CAST;
s32b dur = get_level_s(MANWE_BLESS, 70) + 30 + randint(40);
@@ -2081,7 +2085,7 @@ casting_result manwe_blessing(int item)
return res;
}
-char *manwe_blessing_info()
+const char *manwe_blessing_info()
{
static char buf[128];
sprintf(buf,
@@ -2090,7 +2094,7 @@ char *manwe_blessing_info()
return buf;
}
-casting_result manwe_call(int item)
+casting_result manwe_call()
{
int y = 0, x = 0, m_idx = -1, r_idx = -1;
@@ -2110,7 +2114,7 @@ casting_result manwe_call(int item)
return NO_CAST;
}
-char *manwe_call_info()
+const char *manwe_call_info()
{
static char buf[128];
sprintf(buf,
@@ -2140,7 +2144,7 @@ void do_melkor_curse(int m_idx)
m_ptr->hp = m_ptr->maxhp;
}
- p_ptr->redraw |= PR_HEALTH;
+ p_ptr->redraw |= PR_FRAME;
}
if (get_level_s(MELKOR_CURSE, 50) >= 25)
@@ -2209,7 +2213,7 @@ void do_melkor_curse(int m_idx)
m_ptr->csleep = 0;
}
-casting_result melkor_curse(int item)
+casting_result melkor_curse()
{
int dir = 0;
@@ -2230,12 +2234,7 @@ casting_result melkor_curse(int item)
}
}
-char *melkor_curse_info()
-{
- return "";
-}
-
-casting_result melkor_corpse_explosion(int item)
+casting_result melkor_corpse_explosion()
{
return cast(fire_ball(GF_CORPSE_EXPL,
0,
@@ -2243,7 +2242,7 @@ casting_result melkor_corpse_explosion(int item)
2 + get_level_s(MELKOR_CORPSE_EXPLOSION, 5)));
}
-char *melkor_corpse_explosion_info()
+const char *melkor_corpse_explosion_info()
{
static char buf[128];
sprintf(buf,
@@ -2252,7 +2251,7 @@ char *melkor_corpse_explosion_info()
return buf;
}
-casting_result melkor_mind_steal(int item)
+casting_result melkor_mind_steal()
{
int dir = 0;
@@ -2293,7 +2292,7 @@ casting_result melkor_mind_steal(int item)
}
}
-char *melkor_mind_steal_info()
+const char *melkor_mind_steal_info()
{
static char buf[128];
sprintf(buf,
@@ -2302,12 +2301,12 @@ char *melkor_mind_steal_info()
return buf;
}
-casting_result meta_recharge(int item)
+casting_result meta_recharge()
{
return cast(recharge(60 + get_level_s(RECHARGE, 140)));
}
-char *meta_recharge_info()
+const char *meta_recharge_info()
{
static char buf[128];
sprintf(buf,
@@ -2326,16 +2325,15 @@ static int get_spellbinder_max()
return i;
}
-casting_result meta_spellbinder(int item)
+casting_result meta_spellbinder()
{
if (p_ptr->spellbinder_num != 0)
{
- typedef struct trigger trigger;
struct trigger {
int idx;
cptr desc;
};
- trigger triggers[] = {
+ struct trigger triggers[] = {
{ SPELLBINDER_HP75, "75% HP", },
{ SPELLBINDER_HP50, "50% HP", },
{ SPELLBINDER_HP25, "25% HP", },
@@ -2419,7 +2417,7 @@ casting_result meta_spellbinder(int item)
}
}
-char *meta_spellbinder_info()
+const char *meta_spellbinder_info()
{
static char buf[128];
sprintf(buf,
@@ -2429,7 +2427,7 @@ char *meta_spellbinder_info()
return buf;
}
-casting_result meta_disperse_magic(int item)
+casting_result meta_disperse_magic()
{
casting_result res = NO_CAST;
@@ -2449,7 +2447,6 @@ casting_result meta_disperse_magic(int item)
if (get_level_s(DISPERSEMAGIC, 50) >= 15)
{
res = cplus(res, set_stun(0));
- res = cplus(res, set_meditation(0));
res = cplus(res, set_cut(0));
}
if (get_level_s(DISPERSEMAGIC, 50) >= 20)
@@ -2465,12 +2462,7 @@ casting_result meta_disperse_magic(int item)
return res;
}
-char *meta_disperse_magic_info()
-{
- return "";
-}
-
-casting_result meta_tracker(int item)
+casting_result meta_tracker()
{
if ((last_teleportation_y < 0) ||
(last_teleportation_x < 0))
@@ -2484,11 +2476,6 @@ casting_result meta_tracker(int item)
return CAST_OBVIOUS;
}
-char *meta_tracker_info()
-{
- return "";
-}
-
static void stop_inertia_controlled_spell()
{
assert(TIMER_INERTIA_CONTROL != NULL);
@@ -2503,7 +2490,7 @@ void meta_inertia_control_hook_birth_objects()
stop_inertia_controlled_spell();
}
-casting_result meta_inertia_control(int item)
+casting_result meta_inertia_control()
{
s32b s, difficulty, delay;
spell_type *spell;
@@ -2547,7 +2534,7 @@ casting_result meta_inertia_control(int item)
return CAST_OBVIOUS;
}
-char *meta_inertia_control_info()
+const char *meta_inertia_control_info()
{
static char buf[128];
sprintf(buf,
@@ -2591,7 +2578,7 @@ static int mind_charm_power()
return 10 + get_level_s(CHARM, 150);
}
-casting_result mind_charm(int item)
+casting_result mind_charm()
{
int pwr = mind_charm_power();
int level = get_level_s(CHARM, 50);
@@ -2619,7 +2606,7 @@ casting_result mind_charm(int item)
}
}
-char *mind_charm_info()
+const char *mind_charm_info()
{
static char buf[128];
sprintf(buf,
@@ -2633,7 +2620,7 @@ static int mind_confuse_power()
return 10 + get_level_s(CONFUSE, 150);
}
-casting_result mind_confuse(int item)
+casting_result mind_confuse()
{
int pwr = mind_confuse_power();
int level = get_level_s(CONFUSE, 50);
@@ -2661,7 +2648,7 @@ casting_result mind_confuse(int item)
}
}
-char *mind_confuse_info()
+const char *mind_confuse_info()
{
static char buf[128];
sprintf(buf,
@@ -2685,7 +2672,7 @@ static int mind_armor_of_fear_power_dice()
return 5 + get_level_s(ARMOROFFEAR, 20);
}
-casting_result mind_armor_of_fear(int item)
+casting_result mind_armor_of_fear()
{
return cast(set_shield(randint(10) + mind_armor_of_fear_base_duration(),
10,
@@ -2694,7 +2681,7 @@ casting_result mind_armor_of_fear(int item)
mind_armor_of_fear_power_dice()));
}
-char *mind_armor_of_fear_info()
+const char *mind_armor_of_fear_info()
{
static char buf[128];
sprintf(buf,
@@ -2710,7 +2697,7 @@ static int mind_stun_power()
return 10 + get_level_s(STUN, 150);
}
-casting_result mind_stun(int item)
+casting_result mind_stun()
{
int dir;
@@ -2729,7 +2716,7 @@ casting_result mind_stun(int item)
}
}
-char *mind_stun_info()
+const char *mind_stun_info()
{
static char buf[128];
sprintf(buf,
@@ -2738,7 +2725,7 @@ char *mind_stun_info()
return buf;
}
-casting_result tempo_magelock(int item)
+casting_result tempo_magelock()
{
if (get_level_s(MAGELOCK, 50) >= 30)
{
@@ -2778,17 +2765,12 @@ casting_result tempo_magelock(int item)
}
}
-char *tempo_magelock_info()
-{
- return "";
-}
-
static s32b tempo_slow_monster_power()
{
return 40 + get_level_s(SLOWMONSTER, 160);
}
-casting_result tempo_slow_monster(int item)
+casting_result tempo_slow_monster()
{
int dir;
s32b pwr;
@@ -2809,7 +2791,7 @@ casting_result tempo_slow_monster(int item)
}
}
-char *tempo_slow_monster_info()
+const char *tempo_slow_monster_info()
{
static char buf[128];
s32b pwr = tempo_slow_monster_power();
@@ -2835,7 +2817,7 @@ static s32b tempo_essence_of_speed_bonus()
return 5 + get_level_s(ESSENCESPEED, 20);
}
-casting_result tempo_essence_of_speed(int item)
+casting_result tempo_essence_of_speed()
{
if (p_ptr->fast == 0)
{
@@ -2845,7 +2827,7 @@ casting_result tempo_essence_of_speed(int item)
return NO_CAST;
}
-char *tempo_essence_of_speed_info()
+const char *tempo_essence_of_speed_info()
{
static char buf[128];
sprintf(buf,
@@ -2860,7 +2842,7 @@ static s32b tempo_banishment_power()
return 40 + get_level_s(BANISHMENT, 160);
}
-casting_result tempo_banishment(int item)
+casting_result tempo_banishment()
{
casting_result result = NO_CAST;
s32b pwr = tempo_banishment_power();
@@ -2876,7 +2858,7 @@ casting_result tempo_banishment(int item)
return result;
}
-char *tempo_banishment_info()
+const char *tempo_banishment_info()
{
static char buf[128];
sprintf(buf,
@@ -2885,7 +2867,7 @@ char *tempo_banishment_info()
return buf;
}
-casting_result tulkas_divine_aim(int item)
+casting_result tulkas_divine_aim()
{
casting_result result = NO_CAST;
s32b dur = get_level_s(TULKAS_AIM, 50) + randint(10);
@@ -2899,7 +2881,7 @@ casting_result tulkas_divine_aim(int item)
return result;
}
-char *tulkas_divine_aim_info()
+const char *tulkas_divine_aim_info()
{
static char buf[128];
sprintf(buf,
@@ -2908,7 +2890,7 @@ char *tulkas_divine_aim_info()
return buf;
}
-casting_result tulkas_wave_of_power(int item)
+casting_result tulkas_wave_of_power()
{
int dir;
@@ -2920,7 +2902,7 @@ casting_result tulkas_wave_of_power(int item)
return cast(fire_bolt(GF_ATTACK, dir, get_level_s(TULKAS_WAVE, p_ptr->num_blow)));
}
-char *tulkas_wave_of_power_info()
+const char *tulkas_wave_of_power_info()
{
static char buf[128];
sprintf(buf,
@@ -2929,50 +2911,32 @@ char *tulkas_wave_of_power_info()
return buf;
}
-casting_result tulkas_whirlwind(int item)
+casting_result tulkas_whirlwind()
{
return cast(fire_ball(GF_ATTACK, 0, 1, 1));
}
-char *tulkas_whirlwind_info()
-{
- return "";
-}
-
-static bool_ check_school_is_udun(void *data, s32b school_idx)
-{
- int *count = (int *) data;
-
- if ((school_idx == SCHOOL_UDUN) ||
- (school_idx == SCHOOL_MELKOR))
- {
- (*count)++;
- }
-
- /* Keep going */
- return TRUE;
-}
-
/* Return the number of Udun/Melkor spells in a given book */
int udun_in_book(s32b sval, s32b pval)
{
int count = 0;
- school_book_type *school_book;
- spell_idx_list *spell_idx = NULL;
- struct sglib_spell_idx_list_iterator it;
random_book_setup(sval, pval);
/* Get the school book */
- school_book = school_books_at(sval);
+ school_book *school_book = school_books_at(sval);
/* Go through spells */
- for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list);
- spell_idx != NULL;
- spell_idx = sglib_spell_idx_list_it_next(&it))
- {
- spell_type *spell = spell_at(spell_idx->i);
- spell_type_school_foreach(spell, check_school_is_udun, &count);
+ 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;
@@ -2981,55 +2945,47 @@ int udun_in_book(s32b sval, s32b pval)
int levels_in_book(s32b sval, s32b pval)
{
int levels = 0;
- school_book_type *school_book;
- spell_idx_list *spell_idx = NULL;
- struct sglib_spell_idx_list_iterator it;
random_book_setup(sval, pval);
/* Get the school book */
- school_book = school_books_at(sval);
+ school_book *school_book = school_books_at(sval);
/* Parse all spells */
- for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list);
- spell_idx != NULL;
- spell_idx = sglib_spell_idx_list_it_next(&it))
+ for (auto spell_idx : school_book->spell_idxs)
{
- s32b s = spell_idx->i;
- spell_type *spell = spell_at(s);
-
+ spell_type *spell = spell_at(spell_idx);
levels += spell_type_skill_level(spell);
}
return levels;
}
-static bool_ udun_object_is_drainable(object_type *o_ptr)
+static object_filter_t const &udun_object_is_drainable()
{
- return ((o_ptr->tval == TV_WAND) ||
- (o_ptr->tval == TV_ROD_MAIN) ||
- (o_ptr->tval == TV_STAFF));
+ using namespace object_filter;
+ static auto instance = Or(
+ TVal(TV_WAND),
+ TVal(TV_ROD_MAIN),
+ TVal(TV_STAFF));
+ return instance;
}
-casting_result udun_drain(int ignored)
+casting_result udun_drain()
{
- int item;
- object_type *o_ptr = NULL;
-
/* Ask for an item */
- item_tester_hook = udun_object_is_drainable;
+ int item;
if (!get_item(&item,
"What item to drain?",
"You have nothing you can drain",
- USE_INVEN))
+ USE_INVEN,
+ udun_object_is_drainable()))
{
return NO_CAST;
}
/* Drain */
-
- /* get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
switch (o_ptr->tval)
{
@@ -3068,12 +3024,7 @@ casting_result udun_drain(int ignored)
return CAST_OBVIOUS;
}
-char *udun_drain_info()
-{
- return "";
-}
-
-casting_result udun_genocide(int item)
+casting_result udun_genocide()
{
if (get_level_s(GENOCIDE, 50) < 10)
{
@@ -3094,22 +3045,17 @@ casting_result udun_genocide(int item)
return CAST_OBVIOUS;
}
-char *udun_genocide_info()
-{
- return "";
-}
-
static int udun_wraithform_base_duration()
{
return 20 + get_level_s(WRAITHFORM, 40);
}
-casting_result udun_wraithform(int item)
+casting_result udun_wraithform()
{
return cast(set_shadow(randint(30) + udun_wraithform_base_duration()));
}
-char *udun_wraithform_info()
+const char *udun_wraithform_info()
{
static char buf[128];
sprintf(buf,
@@ -3123,14 +3069,14 @@ static int udun_flame_of_udun_base_duration()
return 5 + get_level_s(FLAMEOFUDUN, 30);
}
-casting_result udun_flame_of_udun(int item)
+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)));
}
-char *udun_flame_of_udun_info()
+const char *udun_flame_of_udun_info()
{
static char buf[128];
sprintf(buf,
@@ -3149,7 +3095,7 @@ static int tidal_wave_duration()
return 6 + get_level_s(TIDALWAVE, 10);
}
-casting_result water_tidal_wave(int item)
+casting_result water_tidal_wave()
{
fire_wave(GF_WAVE,
0,
@@ -3160,7 +3106,7 @@ casting_result water_tidal_wave(int item)
return CAST_OBVIOUS;
}
-char *water_tidal_wave_info()
+const char *water_tidal_wave_info()
{
static char buf[128];
sprintf(buf,
@@ -3185,7 +3131,7 @@ static int water_ice_storm_duration()
return 20 + get_level_s(ICESTORM, 70);
}
-casting_result water_ice_storm(int item)
+casting_result water_ice_storm()
{
int type = GF_COLD;
@@ -3204,7 +3150,7 @@ casting_result water_ice_storm(int item)
return CAST_OBVIOUS;
}
-char *water_ice_storm_info()
+const char *water_ice_storm_info()
{
static char buf[128];
sprintf(buf,
@@ -3220,7 +3166,7 @@ static int water_ent_potion_base_duration()
return 25 + get_level_s(ENTPOTION, 40);;
}
-casting_result water_ent_potion(int item)
+casting_result water_ent_potion()
{
set_food(PY_FOOD_MAX - 1);
msg_print("The Ent's Potion fills your stomach.");
@@ -3237,7 +3183,7 @@ casting_result water_ent_potion(int item)
return CAST_OBVIOUS;
}
-char *water_ent_potion_info()
+const char *water_ent_potion_info()
{
if (get_level_s(ENTPOTION, 50) >= 12)
{
@@ -3268,7 +3214,7 @@ static int water_vapor_duration()
return 5;
}
-casting_result water_vapor(int item)
+casting_result water_vapor()
{
fire_cloud(GF_WATER,
0,
@@ -3278,7 +3224,7 @@ casting_result water_vapor(int item)
return CAST_OBVIOUS;
}
-char *water_vapor_info()
+const char *water_vapor_info()
{
static char buf[128];
sprintf(buf,
@@ -3298,7 +3244,7 @@ static void get_geyser_damage(int *dice, int *sides)
*sides = 3 + get_level_s(GEYSER, 35);
}
-casting_result water_geyser(int item)
+casting_result water_geyser()
{
int dir, dice, sides;
@@ -3314,7 +3260,7 @@ casting_result water_geyser(int item)
damroll(dice, sides)));
}
-char *water_geyser_info()
+const char *water_geyser_info()
{
static char buf[128];
int dice, sides;
@@ -3338,7 +3284,7 @@ static int charm_animal_radius()
return get_level_s(YAVANNA_CHARM_ANIMAL, 2);
}
-casting_result yavanna_charm_animal(int item)
+casting_result yavanna_charm_animal()
{
int dir;
@@ -3353,7 +3299,7 @@ casting_result yavanna_charm_animal(int item)
charm_animal_radius()));
}
-char *yavanna_charm_animal_info()
+const char *yavanna_charm_animal_info()
{
static char buf[128];
sprintf(buf,
@@ -3368,13 +3314,13 @@ static int yavanna_grow_grass_radius()
return get_level_s(YAVANNA_GROW_GRASS, 4);
}
-casting_result yavanna_grow_grass(int item)
+casting_result yavanna_grow_grass()
{
grow_grass(yavanna_grow_grass_radius());
return CAST_OBVIOUS;
}
-char *yavanna_grow_grass_info()
+const char *yavanna_grow_grass_info()
{
static char buf[128];
sprintf(buf,
@@ -3398,14 +3344,14 @@ static int tree_roots_damage()
return 10 + get_level_s(YAVANNA_TREE_ROOTS, 20);
}
-casting_result yavanna_tree_roots(int item)
+casting_result yavanna_tree_roots()
{
return cast(set_roots(tree_roots_duration(),
tree_roots_ac(),
tree_roots_damage()));
}
-char *yavanna_tree_roots_info()
+const char *yavanna_tree_roots_info()
{
static char buf[128];
sprintf(buf,
@@ -3426,7 +3372,7 @@ static int water_bite_damage()
return 10 + get_level_s(YAVANNA_WATER_BITE, 50);
}
-casting_result yavanna_water_bite(int item)
+casting_result yavanna_water_bite()
{
int rad = 0;
@@ -3442,7 +3388,7 @@ casting_result yavanna_water_bite(int item)
PROJECT_STOP | PROJECT_KILL));
}
-char *yavanna_water_bite_info()
+const char *yavanna_water_bite_info()
{
static char buf[128];
sprintf(buf,
@@ -3457,7 +3403,7 @@ static int uproot_mlevel()
return 30 + get_level_s(YAVANNA_UPROOT, 70);
}
-casting_result yavanna_uproot(int item)
+casting_result yavanna_uproot()
{
int dir, x, y;
cave_type *c_ptr;
@@ -3501,7 +3447,7 @@ casting_result yavanna_uproot(int item)
}
}
-char *yavanna_uproot_info()
+const char *yavanna_uproot_info()
{
static char buf[128];
sprintf(buf,
@@ -3515,13 +3461,13 @@ static int nature_grow_trees_radius()
return 2 + get_level_s(GROWTREE, 7);
}
-casting_result nature_grow_trees(int item)
+casting_result nature_grow_trees()
{
grow_trees(nature_grow_trees_radius());
return CAST_OBVIOUS;
}
-char *nature_grow_trees_info()
+const char *nature_grow_trees_info()
{
static char buf[128];
sprintf(buf,
@@ -3540,12 +3486,12 @@ static int nature_healing_hp()
return p_ptr->mhp * nature_healing_percentage() / 100;
}
-casting_result nature_healing(int item)
+casting_result nature_healing()
{
return cast(hp_player(nature_healing_hp()));
}
-char *nature_healing_info()
+const char *nature_healing_info()
{
static char buf[128];
sprintf(buf,
@@ -3555,7 +3501,7 @@ char *nature_healing_info()
return buf;
}
-casting_result nature_recovery(int item)
+casting_result nature_recovery()
{
casting_result result = NO_CAST;
@@ -3582,11 +3528,6 @@ casting_result nature_recovery(int item)
return result;
}
-char *nature_recovery_info()
-{
- return "";
-}
-
static int regeneration_base_duration()
{
return 5 + get_level_s(REGENERATION, 50);
@@ -3597,7 +3538,7 @@ static int regeneration_power()
return 300 + get_level_s(REGENERATION, 700);
}
-casting_result nature_regeneration(int item)
+casting_result nature_regeneration()
{
if (p_ptr->tim_regen == 0)
{
@@ -3607,7 +3548,7 @@ casting_result nature_regeneration(int item)
return NO_CAST;
}
-char *nature_regeneration_info()
+const char *nature_regeneration_info()
{
static char buf[128];
sprintf(buf,
@@ -3622,7 +3563,7 @@ static int summon_animal_level()
return 25 + get_level_s(SUMMONANNIMAL, 50);
}
-casting_result nature_summon_animal(int item)
+casting_result nature_summon_animal()
{
summon_specific_level = summon_animal_level();
return cast(summon_specific_friendly(p_ptr->py,
@@ -3632,7 +3573,7 @@ casting_result nature_summon_animal(int item)
TRUE));
}
-char *nature_summon_animal_info()
+const char *nature_summon_animal_info()
{
static char buf[128];
sprintf(buf,
@@ -3641,7 +3582,7 @@ char *nature_summon_animal_info()
return buf;
}
-casting_result nature_grow_athelas(int item)
+casting_result nature_grow_athelas()
{
if (p_ptr->black_breath)
{
@@ -3653,17 +3594,12 @@ casting_result nature_grow_athelas(int item)
return CAST_HIDDEN;
}
-char *nature_grow_athelas_info()
-{
- return "";
-}
-
static int device_heal_monster_hp()
{
return 20 + get_level_s(DEVICE_HEAL_MONSTER, 380);
}
-casting_result device_heal_monster(int item)
+casting_result device_heal_monster()
{
int dir;
@@ -3675,7 +3611,7 @@ casting_result device_heal_monster(int item)
return cast(fire_ball(GF_OLD_HEAL, dir, device_heal_monster_hp(), 0));
}
-char *device_heal_monster_info()
+const char *device_heal_monster_info()
{
static char buf[128];
sprintf(buf,
@@ -3684,7 +3620,7 @@ char *device_heal_monster_info()
return buf;
}
-casting_result device_haste_monster(int item)
+casting_result device_haste_monster()
{
int dir;
@@ -3696,23 +3632,18 @@ casting_result device_haste_monster(int item)
return cast(fire_ball(GF_OLD_SPEED, dir, 1, 0));
}
-char *device_haste_monster_info()
+const char *device_haste_monster_info()
{
return "speed +10";
}
-casting_result device_wish(int item)
+casting_result device_wish()
{
make_wish();
return CAST_OBVIOUS;
}
-char *device_wish_info()
-{
- return "";
-}
-
-casting_result device_summon_monster(int item)
+casting_result device_summon_monster()
{
casting_result result = NO_CAST;
int i;
@@ -3725,23 +3656,18 @@ casting_result device_summon_monster(int item)
return result;
}
-char *device_summon_monster_info()
-{
- return "";
-}
-
static int device_mana_pct()
{
return 20 + get_level_s(DEVICE_MANA, 50);
}
-casting_result device_mana(int item)
+casting_result device_mana()
{
increase_mana((p_ptr->msp * device_mana_pct()) / 100);
return CAST_OBVIOUS;
}
-char *device_mana_info()
+const char *device_mana_info()
{
static char buf[128];
sprintf(buf,
@@ -3750,58 +3676,22 @@ char *device_mana_info()
return buf;
}
-casting_result device_nothing(int item)
+casting_result device_nothing()
{
return CAST_HIDDEN;
}
-char *device_nothing_info()
-{
- return "";
-}
-
-casting_result device_lebohaum(int item)
-{
- msg_print("You hear a little song in your head in some unknown tongue:");
- msg_print("'Avec le casque Lebohaum y a jamais d'anicroches, je parcours les dongeons,");
- msg_print("j'en prend plein la caboche. Avec le casque Lebohaum, tout ces monstres a la");
- msg_print("con, je leur met bien profond: c'est moi le maitre du dongeon!'");
- return CAST_OBVIOUS;
-}
-
-char *device_lebohaum_info()
-{
- return "";
-}
-
-casting_result device_maggot(int item)
-{
- int dir;
-
- if (!get_aim_dir(&dir))
- {
- return NO_CAST;
- }
-
- return cast(fire_ball(GF_TURN_ALL, dir, 40, 2));
-}
-
-char *device_maggot_info()
-{
- return "power 40 rad 2";
-}
-
static int holy_fire_damage()
{
return 50 + get_level_s(DEVICE_HOLY_FIRE, 300);
}
-casting_result device_holy_fire(int item)
+casting_result device_holy_fire()
{
return cast(project_hack(GF_HOLY_FIRE, holy_fire_damage()));
}
-char *device_holy_fire_info()
+const char *device_holy_fire_info()
{
static char buf[128];
sprintf(buf,
@@ -3810,116 +3700,7 @@ char *device_holy_fire_info()
return buf;
}
-static int get_eternal_artifact_idx(object_type *o_ptr)
-{
- if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_LONG_SWORD)) {
- return 147;
- } else if ((o_ptr->tval == TV_MSTAFF) && (o_ptr->sval == SV_MSTAFF)) {
- return 127;
- } else if ((o_ptr->tval == TV_BOW) && (o_ptr->sval == SV_HEAVY_XBOW)) {
- return 152;
- } else if ((o_ptr->tval == TV_DRAG_ARMOR) && (o_ptr->sval == SV_DRAGON_POWER)) {
- return 17;
- }
-
- if (game_module_idx == MODULE_THEME)
- {
- if ((o_ptr->tval == TV_HAFTED) && (o_ptr->sval == SV_LUCERN_HAMMER)) {
- return 241;
- } else if ((o_ptr->tval == TV_POLEARM) && (o_ptr->sval == SV_TRIDENT)) {
- return 242;
- } else if ((o_ptr->tval == TV_AXE) && (o_ptr->sval == SV_BROAD_AXE)) {
- return 243;
- } else if ((o_ptr->tval == TV_BOW) && (o_ptr->sval == SV_LONG_BOW)) {
- return 245;
- } else if ((o_ptr->tval == TV_BOOMERANG) && (o_ptr->sval == SV_BOOM_METAL)) {
- return 247;
- } else if ((o_ptr->tval == TV_BOW) && (o_ptr->sval == SV_SLING)) {
- return 246;
- } else if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_RAPIER)) {
- return 244;
- } else if ((o_ptr->tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_SPELL)) {
- return 248;
- }
- }
-
- /* Not usable */
- return -1;
-}
-
-static bool_ eternal_flame_item_tester_hook(object_type *o_ptr)
-{
- if ((o_ptr->name1 > 0) ||
- (o_ptr->name2 > 0))
- {
- return FALSE;
- }
-
- return (get_eternal_artifact_idx(o_ptr) >= 0);
-}
-
-casting_result device_eternal_flame(int flame_item)
-{
- int item;
- object_type *o_ptr = NULL;
- int artifact_idx = -1;
-
- item_tester_hook = eternal_flame_item_tester_hook;
- if (!get_item(&item,
- "Which object do you want to imbue?",
- "You have no objects to imbue.",
- USE_INVEN))
- {
- return NO_CAST;
- }
-
- /* Get the artifact idx */
- artifact_idx = get_eternal_artifact_idx(o_ptr);
- assert(artifact_idx >= 0);
-
- /* Forge the item */
- o_ptr = get_object(item);
- o_ptr->name1 = artifact_idx;
-
- apply_magic(o_ptr, -1, TRUE, TRUE, TRUE);
-
- o_ptr->found = OBJ_FOUND_SELFMADE;
-
- inven_item_increase(flame_item, -1);
- inven_item_describe(flame_item);
- inven_item_optimize(flame_item);
-
- return CAST_OBVIOUS;
-}
-
-char *device_eternal_flame_info()
-{
- return "";
-}
-
-casting_result device_durandil(int item)
-{
- msg_print("You hear a little song in your head in some unknown tongue:");
- msg_print("'Les epees Durandils sont forgees dans les mines par des nains.");
- msg_print("Avec ca c'est facile de tuer un troll avec une seule main. Pas besoin");
- msg_print("de super entrainement nis de niveau 28. Quand tu sors l'instrument");
- msg_print("c'est l'ennemi qui prend la fuite! Avec ton epee Durandil quand tu");
- msg_print("parcours les chemins, tu massacre sans peine les brigands et les gobelins,");
- msg_print("les rats geants, les ogres mutants, les zombies et les liches, tu les");
- msg_print("decoupe en tranches comme si c'etait des parts de quiches.");
- msg_print("Les epees Durandil! Les epees Durandil!");
- msg_print("Quand tu la sort dans un dongeon au moins t'as pas l'air debile.");
- msg_print("C'est l'arme des bourins qui savent etre subtils.");
- msg_print("Ne partez pas a l'aventure sans votre epee Durandil!'");
- return CAST_OBVIOUS;
-}
-
-char *device_durandil_info()
-{
- return "";
-}
-
-casting_result device_thunderlords(int item)
+casting_result device_thunderlords()
{
switch (game_module_idx)
{
@@ -3957,78 +3738,17 @@ casting_result device_thunderlords(int item)
}
}
-char *device_thunderlords_info()
-{
- return "";
-}
-
-casting_result device_radagast(int item)
-{
- cmsg_print(TERM_GREEN, "The staff's power cleanses you completely!");
- remove_all_curse();
- do_res_stat(A_STR, TRUE);
- do_res_stat(A_CON, TRUE);
- do_res_stat(A_DEX, TRUE);
- do_res_stat(A_WIS, TRUE);
- do_res_stat(A_INT, TRUE);
- do_res_stat(A_CHR, TRUE);
- restore_level();
- // clean_corruptions(); TODO: Do we want to implement this?
- hp_player(5000);
- heal_insanity(5000);
- set_poisoned(0);
- set_blind(0);
- set_confused(0);
- set_image(0);
- set_stun(0);
- set_cut(0);
- set_parasite(0, 0);
-
- if (p_ptr->black_breath)
- {
- msg_print("The hold of the Black Breath on you is broken!");
- }
- p_ptr->black_breath = FALSE;
-
- p_ptr->update |= PU_BONUS;
- p_ptr->window |= PW_PLAYER;
-
- return CAST_OBVIOUS;
-}
-
-char *device_radagast_info()
-{
- return "";
-}
-
-casting_result device_valaroma(int item)
-{
- int power = 5 * p_ptr->lev;
- banish_evil(power);
- return CAST_HIDDEN;
-}
-
-char *device_valaroma_info()
-{
- return "";
-}
-
void static start_lasting_spell(int spl)
{
p_ptr->music_extra = -spl;
}
-casting_result music_stop_singing_spell(int item)
+casting_result music_stop_singing_spell()
{
start_lasting_spell(0);
return CAST_OBVIOUS;
}
-char *music_stop_singing_info()
-{
- return "";
-}
-
static int holding_pattern_power()
{
return 10 + get_level_s(MUSIC_HOLD, 100);
@@ -4040,13 +3760,13 @@ int music_holding_pattern_lasting()
return get_mana(MUSIC_HOLD);
}
-casting_result music_holding_pattern_spell(int item)
+casting_result music_holding_pattern_spell()
{
start_lasting_spell(MUSIC_HOLD);
return CAST_OBVIOUS;
}
-char *music_holding_pattern_info()
+const char *music_holding_pattern_info()
{
static char buf[128];
sprintf(buf,
@@ -4066,13 +3786,13 @@ int music_illusion_pattern_lasting()
return get_mana(MUSIC_CONF);
}
-casting_result music_illusion_pattern_spell(int item)
+casting_result music_illusion_pattern_spell()
{
start_lasting_spell(MUSIC_CONF);
return CAST_OBVIOUS;
}
-char *music_illusion_pattern_info()
+const char *music_illusion_pattern_info()
{
static char buf[128];
sprintf(buf,
@@ -4092,13 +3812,13 @@ int music_stun_pattern_lasting()
return get_mana(MUSIC_STUN);
}
-casting_result music_stun_pattern_spell(int item)
+casting_result music_stun_pattern_spell()
{
start_lasting_spell(MUSIC_STUN);
return CAST_OBVIOUS;
}
-char *music_stun_pattern_info()
+const char *music_stun_pattern_info()
{
static char buf[128];
sprintf(buf,
@@ -4113,17 +3833,12 @@ int music_song_of_the_sun_lasting()
return 1;
}
-casting_result music_song_of_the_sun_spell(int item)
+casting_result music_song_of_the_sun_spell()
{
start_lasting_spell(MUSIC_LITE);
return CAST_OBVIOUS;
}
-char *music_song_of_the_sun_info()
-{
- return "";
-}
-
int flow_of_life_hp()
{
return 7 + get_level_s(MUSIC_HEAL, 100);
@@ -4135,13 +3850,13 @@ int music_flow_of_life_lasting()
return get_mana(MUSIC_HEAL);
}
-casting_result music_flow_of_life_spell(int item)
+casting_result music_flow_of_life_spell()
{
start_lasting_spell(MUSIC_HEAL);
return CAST_OBVIOUS;
}
-char *music_flow_of_life_info()
+const char *music_flow_of_life_info()
{
static char buf[128];
sprintf(buf,
@@ -4168,17 +3883,12 @@ int music_heroic_ballad_lasting()
return get_mana(MUSIC_HERO);
}
-casting_result music_heroic_ballad_spell(int item)
+casting_result music_heroic_ballad_spell()
{
start_lasting_spell(MUSIC_HERO);
return CAST_OBVIOUS;
}
-char *music_heroic_ballad_info()
-{
- return "";
-}
-
int music_hobbit_melodies_lasting()
{
set_shield(5, 10 + get_level_s(MUSIC_TIME, 50), 0, 0, 0);
@@ -4189,13 +3899,13 @@ int music_hobbit_melodies_lasting()
return get_mana(MUSIC_TIME);
}
-casting_result music_hobbit_melodies_spell(int item)
+casting_result music_hobbit_melodies_spell()
{
start_lasting_spell(MUSIC_TIME);
return CAST_OBVIOUS;
}
-char *music_hobbit_melodies_info()
+const char *music_hobbit_melodies_info()
{
static char buf[128];
if (get_level_s(MUSIC_TIME, 50) >= 15)
@@ -4222,13 +3932,13 @@ int music_clairaudience_lasting()
return get_mana(MUSIC_MIND);
}
-casting_result music_clairaudience_spell(int item)
+casting_result music_clairaudience_spell()
{
start_lasting_spell(MUSIC_MIND);
return CAST_OBVIOUS;
}
-char *music_clairaudience_info()
+const char *music_clairaudience_info()
{
static char buf[128];
@@ -4244,7 +3954,7 @@ char *music_clairaudience_info()
}
}
-casting_result music_blow_spell(int item)
+casting_result music_blow_spell()
{
fire_ball(GF_SOUND,
0,
@@ -4253,7 +3963,7 @@ casting_result music_blow_spell(int item)
return CAST_OBVIOUS;
}
-char *music_blow_info()
+const char *music_blow_info()
{
static char buf[128];
sprintf(buf,
@@ -4264,7 +3974,7 @@ char *music_blow_info()
return buf;
}
-casting_result music_gush_of_wind_spell(int item)
+casting_result music_gush_of_wind_spell()
{
fire_ball(GF_AWAY_ALL,
0,
@@ -4273,7 +3983,7 @@ casting_result music_gush_of_wind_spell(int item)
return CAST_OBVIOUS;
}
-char *music_gush_of_wind_info()
+const char *music_gush_of_wind_info()
{
static char buf[128];
sprintf(buf,
@@ -4283,33 +3993,28 @@ char *music_gush_of_wind_info()
return buf;
}
-casting_result music_horns_of_ylmir_spell(int item)
+casting_result music_horns_of_ylmir_spell()
{
- earthquake(p_ptr->py, p_ptr->px, 2 + get_level_s(SHAKE, 10));
+ earthquake(p_ptr->py, p_ptr->px, 2 + get_level_s(MUSIC_YLMIR, 10));
return CAST_OBVIOUS;
}
-char *music_horns_of_ylmir_info()
+const char *music_horns_of_ylmir_info()
{
static char buf[128];
sprintf(buf,
"rad " FMTs32b,
- 2 + get_level_s(SHAKE, 10));
+ 2 + get_level_s(MUSIC_YLMIR, 10));
return buf;
}
-casting_result music_ambarkanta_spell(int item)
+casting_result music_ambarkanta_spell()
{
alter_reality();
return CAST_OBVIOUS;
}
-char *music_ambarkanta_info()
-{
- return "";
-}
-
-casting_result aule_firebrand_spell(int item)
+casting_result aule_firebrand_spell()
{
int rad = 0;
int type = GF_FIRE;
@@ -4332,7 +4037,7 @@ casting_result aule_firebrand_spell(int item)
PROJECT_STOP | PROJECT_KILL));
}
-char *aule_firebrand_info()
+const char *aule_firebrand_info()
{
s32b level = get_level_s(AULE_FIREBRAND, 50);
static char buf[128];
@@ -4344,34 +4049,27 @@ char *aule_firebrand_info()
return buf;
}
-static bool_ aule_enchant_weapon_item_tester(object_type *o_ptr)
+static object_filter_t const &aule_enchant_weapon_item_tester()
{
- if (o_ptr->name1 > 0)
- {
- return FALSE;
- }
-
- switch (o_ptr->tval)
- {
- case TV_MSTAFF:
- case TV_BOW:
- case TV_HAFTED:
- case TV_POLEARM:
- case TV_SWORD:
- case TV_AXE:
- return TRUE;
-
- default:
- return FALSE;
- }
+ 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(int ignored)
+casting_result aule_enchant_weapon_spell()
{
s32b level = get_level_s(AULE_ENCHANT_WEAPON, 50);
s16b num_h, num_d, num_p;
- int item;
- object_type *o_ptr = NULL;
num_h = 1 + randint(level/12);
num_d = 0;
@@ -4386,16 +4084,17 @@ casting_result aule_enchant_weapon_spell(int ignored)
num_p = 1;
}
- item_tester_hook = aule_enchant_weapon_item_tester;
+ int item;
if (!get_item(&item,
"Which object do you want to enchant?",
"You have no objects to enchant.",
- USE_INVEN))
+ USE_INVEN,
+ aule_enchant_weapon_item_tester()))
{
return NO_CAST;
}
- o_ptr = get_object(item);
+ 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;
@@ -4404,7 +4103,7 @@ casting_result aule_enchant_weapon_spell(int ignored)
return CAST_OBVIOUS;
}
-char *aule_enchant_weapon_info()
+const char *aule_enchant_weapon_info()
{
static char buf[128];
sprintf(buf,
@@ -4413,37 +4112,32 @@ char *aule_enchant_weapon_info()
return buf;
}
-bool_ aule_enchant_armor_item_tester(object_type *o_ptr)
+static object_filter_t const &aule_enchant_armor_item_tester()
{
- if (o_ptr->name1 > 0)
- {
- return FALSE;
- }
-
- switch (o_ptr->tval)
- {
- case TV_BOOTS:
- case TV_GLOVES:
- case TV_HELM:
- case TV_CROWN:
- case TV_SHIELD:
- case TV_CLOAK:
- case TV_SOFT_ARMOR:
- case TV_HARD_ARMOR:
- case TV_DRAG_ARMOR:
- return TRUE;
-
- default:
- return FALSE;
- }
+ 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(int ignored)
+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;
- object_type *o_ptr = NULL;
num_a = 1 + randint(level/10);
num_h = 0;
@@ -4459,16 +4153,16 @@ casting_result aule_enchant_armour_spell(int ignored)
num_p = 1;
}
- item_tester_hook = aule_enchant_armor_item_tester;
if (!get_item(&item,
"Which object do you want to enchant?",
"You have no objects to enchant.",
- USE_INVEN))
+ USE_INVEN,
+ aule_enchant_armor_item_tester()))
{
return NO_CAST;
}
- o_ptr = get_object(item);
+ 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;
@@ -4478,7 +4172,7 @@ casting_result aule_enchant_armour_spell(int ignored)
return CAST_OBVIOUS;
}
-char *aule_enchant_armour_info()
+const char *aule_enchant_armour_info()
{
static char buf[128];
sprintf(buf,
@@ -4487,7 +4181,7 @@ char *aule_enchant_armour_info()
return buf;
}
-casting_result aule_child_spell(int item)
+casting_result aule_child_spell()
{
int y, x;
s16b m_idx;
@@ -4507,7 +4201,7 @@ casting_result aule_child_spell(int item)
}
}
-char *aule_child_info()
+const char *aule_child_info()
{
static char buf[128];
sprintf(buf,
@@ -4521,7 +4215,7 @@ static int tears_of_luthien_hp()
return 10 * get_level_s(MANDOS_TEARS_LUTHIEN, 30);
}
-casting_result mandos_tears_of_luthien_spell(int item)
+casting_result mandos_tears_of_luthien_spell()
{
casting_result result = NO_CAST;
@@ -4533,7 +4227,7 @@ casting_result mandos_tears_of_luthien_spell(int item)
return result;
}
-char *mandos_tears_of_luthien_info()
+const char *mandos_tears_of_luthien_info()
{
static char buf[128];
sprintf(buf,
@@ -4542,7 +4236,7 @@ char *mandos_tears_of_luthien_info()
return buf;
}
-casting_result mandos_spirit_of_the_feanturi_spell(int item)
+casting_result mandos_spirit_of_the_feanturi_spell()
{
casting_result result = NO_CAST;
s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50);
@@ -4565,7 +4259,7 @@ casting_result mandos_spirit_of_the_feanturi_spell(int item)
return result;
}
-char *mandos_spirit_of_the_feanturi_info()
+const char *mandos_spirit_of_the_feanturi_info()
{
static char buf[128];
s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50) ;
@@ -4585,12 +4279,12 @@ static int tale_of_doom_duration()
return 5 + get_level_s(MANDOS_TALE_DOOM,10);
}
-casting_result mandos_tale_of_doom_spell(int item)
+casting_result mandos_tale_of_doom_spell()
{
return cast(set_tim_precognition(tale_of_doom_duration()));
}
-char *mandos_tale_of_doom_info()
+const char *mandos_tale_of_doom_info()
{
static char buf[128];
sprintf(buf,
@@ -4604,17 +4298,16 @@ int call_to_the_halls_mlev()
return 20 + get_level(MANDOS_CALL_HALLS, 70, 0);
}
-casting_result mandos_call_to_the_halls_spell(int item)
+casting_result mandos_call_to_the_halls_spell()
{
-#define N_SUMMONS 2
int y, x;
- s16b m_idx, r_idx;
- s16b summons[N_SUMMONS] = {
+ s16b m_idx;
+ std::vector<int> summons {
test_monster_name("Experienced spirit"),
- test_monster_name("Wise spirit"),
+ test_monster_name("Wise spirit")
};
- r_idx = summons[rand_int(N_SUMMONS)];
+ int r_idx = summons[rand_int(summons.size())];
assert(r_idx >= 0);
find_position(p_ptr->py, p_ptr->px, &y, &x);
@@ -4625,10 +4318,9 @@ casting_result mandos_call_to_the_halls_spell(int item)
return CAST_OBVIOUS;
}
return NO_CAST;
-#undef N_SUMMONS
}
-char *mandos_call_to_the_halls_info()
+const char *mandos_call_to_the_halls_info()
{
static char buf[128];
sprintf(buf,
@@ -4643,7 +4335,7 @@ static void get_belegaer_damage(int *dice, int *sides)
*sides = 3 + get_level_s(ULMO_BELEGAER, 35);
}
-casting_result ulmo_song_of_belegaer_spell(int item)
+casting_result ulmo_song_of_belegaer_spell()
{
int dir, dice, sides;
@@ -4659,7 +4351,7 @@ casting_result ulmo_song_of_belegaer_spell(int item)
damroll(dice, sides)));
}
-char *ulmo_song_of_belegaer_info()
+const char *ulmo_song_of_belegaer_info()
{
static char buf[128];
int dice, sides;
@@ -4677,7 +4369,7 @@ int draught_of_ulmonan_hp()
return 5 * get_level_s(ULMO_DRAUGHT_ULMONAN, 50);
}
-casting_result ulmo_draught_of_ulmonan_spell(int item)
+casting_result ulmo_draught_of_ulmonan_spell()
{
casting_result result = NO_CAST;
s32b level = get_level_s(ULMO_DRAUGHT_ULMONAN, 50);
@@ -4705,7 +4397,7 @@ casting_result ulmo_draught_of_ulmonan_spell(int item)
return result;
}
-char *ulmo_draught_of_ulmonan_info()
+const char *ulmo_draught_of_ulmonan_info()
{
static char buf[128];
sprintf(buf,
@@ -4719,17 +4411,16 @@ 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 item)
+casting_result ulmo_call_of_the_ulumuri_spell()
{
-#define N_SUMMONS 2
int x,y;
- s16b m_idx, r_idx;
- s16b summons[N_SUMMONS] = {
+ s16b m_idx;
+ std::vector<int> summons {
test_monster_name("Water spirit"),
test_monster_name("Water elemental")
};
- r_idx = summons[rand_int(N_SUMMONS)];
+ int r_idx = summons[rand_int(summons.size())];
assert(r_idx >= 0);
find_position(p_ptr->py, p_ptr->px, &y, &x);
@@ -4742,10 +4433,9 @@ casting_result ulmo_call_of_the_ulumuri_spell(int item)
}
return NO_CAST;
-#undef N_SUMMONS
}
-char *ulmo_call_of_the_ulumuri_info()
+const char *ulmo_call_of_the_ulumuri_info()
{
static char buf[128];
sprintf(buf,
@@ -4764,7 +4454,7 @@ static int wrath_of_ulmo_duration()
return 10 + get_level_s(ULMO_WRATH, 14);
}
-casting_result ulmo_wrath_of_ulmo_spell(int item)
+casting_result ulmo_wrath_of_ulmo_spell()
{
int dir, type = GF_WATER;
@@ -4785,7 +4475,7 @@ casting_result ulmo_wrath_of_ulmo_spell(int item)
return CAST_OBVIOUS;
}
-char *ulmo_wrath_of_ulmo_info()
+const char *ulmo_wrath_of_ulmo_info()
{
static char buf[128];
sprintf(buf,
@@ -4805,7 +4495,7 @@ static int light_of_valinor_radius()
return 5 + get_level_s(VARDA_LIGHT_VALINOR, 6);
}
-casting_result varda_light_of_valinor_spell(int item)
+casting_result varda_light_of_valinor_spell()
{
casting_result result = NO_CAST;
@@ -4831,7 +4521,7 @@ casting_result varda_light_of_valinor_spell(int item)
return result;
}
-char *varda_light_of_valinor_info()
+const char *varda_light_of_valinor_info()
{
static char buf[128];
if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 15)
@@ -4848,7 +4538,7 @@ char *varda_light_of_valinor_info()
}
}
-casting_result varda_call_of_almaren_spell(int item)
+casting_result varda_call_of_almaren_spell()
{
int power = 5 * p_ptr->lev;
if (get_level_s(VARDA_CALL_ALMAREN, 50) >= 20)
@@ -4862,12 +4552,7 @@ casting_result varda_call_of_almaren_spell(int item)
return CAST_OBVIOUS;
}
-char *varda_call_of_almaren_info()
-{
- return "";
-}
-
-casting_result varda_evenstar_spell(int item)
+casting_result varda_evenstar_spell()
{
wiz_lite_extra();
if (get_level_s(VARDA_EVENSTAR, 50) >= 40)
@@ -4879,11 +4564,6 @@ casting_result varda_evenstar_spell(int item)
return CAST_OBVIOUS;
}
-char *varda_evenstar_info()
-{
- return "";
-}
-
static int star_kindler_bursts()
{
return p_ptr->lev / 5;
@@ -4894,7 +4574,7 @@ static int star_kindler_damage()
return 20 + get_level_s(VARDA_STARKINDLER, 100);
}
-casting_result varda_star_kindler_spell(int item)
+casting_result varda_star_kindler_spell()
{
int dir, i, n = star_kindler_bursts();
@@ -4914,7 +4594,7 @@ casting_result varda_star_kindler_spell(int item)
return CAST_OBVIOUS;
}
-char *varda_star_kindler_info()
+const char *varda_star_kindler_info()
{
static char buf[128];
sprintf(buf,
diff --git a/src/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.c b/src/spells4.cc
index c977742d..3c877bf2 100644
--- a/src/spells4.c
+++ b/src/spells4.cc
@@ -1,10 +1,29 @@
-#include "angband.h"
-
-#include <assert.h>
-
-#include "spell_type.h"
+#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 <algorithm>
+#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;
+}
-school_book_type school_books[SCHOOL_BOOKS_SIZE];
s32b SCHOOL_AIR;
s32b SCHOOL_AULE;
@@ -32,13 +51,6 @@ s32b SCHOOL_VARDA;
s32b SCHOOL_WATER;
s32b SCHOOL_YAVANNA;
-static int compare_spell_idx(spell_idx_list *a, spell_idx_list *b)
-{
- return SGLIB_NUMERIC_COMPARATOR(a->i, b->i);
-}
-
-SGLIB_DEFINE_LIST_FUNCTIONS(spell_idx_list, compare_spell_idx, next);
-
static bool_ uses_piety_to_cast(int s)
{
return spell_type_uses_piety_to_cast(spell_at(s));
@@ -69,22 +81,16 @@ s32b get_power(s32b s)
return uses_piety_to_cast(s) ? p_ptr->grace : p_ptr->csp;
}
-static void print_spell_desc_callback(void *data, cptr text)
-{
- int *y = (int *) data;
-
- c_prt(TERM_L_BLUE, text, *y, 0);
- (*y) += 1;
-}
-
/* Output the describtion when it is used as a spell */
void print_spell_desc(int s, int y)
{
spell_type *spell = spell_at(s);
spell_type_description_foreach(spell,
- print_spell_desc_callback,
- &y);
+ [&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))
{
@@ -105,115 +111,59 @@ void print_spell_desc(int s, int y)
}
}
-school_book_type *school_books_at(int i)
+school_book *school_books_at(int i)
{
assert(i >= 0);
assert(i < SCHOOL_BOOKS_SIZE);
- return &school_books[i];
+ return &school_books()[i];
}
-static void school_book_init(school_book_type *school_book)
+void school_book_add_spell(school_book *school_book, s32b spell_idx)
{
- school_book->spell_idx_list = NULL;
-}
-
-static void spell_idx_init(spell_idx_list *p, s32b spell_idx)
-{
- assert(p != NULL);
-
- p->i = spell_idx;
- p->next = NULL;
-}
-
-static spell_idx_list *new_spell_idx(void *ctx, s32b spell_idx)
-{
- spell_idx_list *e = malloc(sizeof(spell_idx_list));
- spell_idx_init(e, spell_idx);
- return e;
-}
-
-void school_book_add_spell(school_book_type *school_book, s32b spell_idx)
-{
- spell_idx_list *e;
-
- assert(school_book != NULL);
-
- e = new_spell_idx(school_book, spell_idx);
- sglib_spell_idx_list_add(&school_book->spell_idx_list, e);
+ 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_type *school_book = school_books_at(sval);
-
- if (sval == BOOK_RANDOM)
- {
- return 1;
- }
-
- /* Parse all spells */
- return sglib_spell_idx_list_len(school_book->spell_idx_list);
+ school_book *school_book = school_books_at(sval);
+ return school_book->spell_idxs.size();
}
-int spell_x(int sval, int pval, int i)
+int spell_x(int sval, int spell_idx, int i)
{
assert(i >= 0);
if (sval == BOOK_RANDOM)
{
- return pval;
+ return spell_idx;
}
else
{
- school_book_type *school_book;
- spell_idx_list *spell_idx = NULL;
- struct sglib_spell_idx_list_iterator it;
-
- school_book = school_books_at(sval);
-
- for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list);
- (spell_idx != NULL) && (i > 0);
- spell_idx = sglib_spell_idx_list_it_next(&it))
- {
- i--;
- }
-
- assert(spell_idx != NULL); /* Went off the end of the list? */
-
- return spell_idx->i;
+ 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)
{
- school_book_type *school_book = NULL;
- spell_idx_list e;
-
random_book_setup(sval, spell_idx);
-
- school_book = school_books_at(sval);
-
- spell_idx_init(&e, spell_idx);
- return NULL != sglib_spell_idx_list_find_member(school_book->spell_idx_list, &e);
+ 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));
}
-void push_spell(int book_idx, s32b spell_idx)
+static void push_spell(int book_idx, s32b spell_idx)
{
- school_book_type *school_book = school_books_at(book_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()
{
- int i;
-
- /* Initialize the new school books */
- for (i = 0; i<SCHOOL_BOOKS_SIZE; i++)
- {
- school_book_init(&school_books[i]);
- }
-
/* 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. */
@@ -435,37 +385,34 @@ void random_book_setup(s16b sval, s32b spell_idx)
{
if (sval == BOOK_RANDOM)
{
- school_book_type *school_book = school_books_at(sval);
-
- assert(school_book->spell_idx_list != NULL);
- school_book->spell_idx_list->i = spell_idx;
+ school_book *school_book = school_books_at(sval);
+ school_book->spell_idxs.clear();
+ school_book->spell_idxs.push_back(spell_idx);
}
}
-static bool_ spell_school_name_callback(void *data, s32b sch)
+static std::string spell_school_name(spell_type *spell)
{
- school_type *school = school_at(sch);
- char *buf = (char *) data;
+ std::ostringstream buf;
+ bool first = true;
- /* Add separator? */
- if (buf[0] != '\0')
+ for (s32b school_idx : spell_type_get_schools(spell))
{
- strcat(buf, "/");
+ 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;
}
- /* Add school name */
- strcat(buf, school->name);
-
- /* Keep going */
- return TRUE;
-}
-
-static void spell_school_name(char *buf, spell_type *spell)
-{
- buf[0] = '\0';
- spell_type_school_foreach(spell,
- spell_school_name_callback,
- buf);
+ return buf.str();
}
int print_spell(cptr label_, byte color, int y, s32b s)
@@ -473,14 +420,14 @@ int print_spell(cptr label_, byte color, int y, s32b s)
s32b level;
bool_ na;
spell_type *spell = spell_at(s);
- char sch_str[128];
cptr spell_info = spell_type_info(spell);
cptr label = (label_ == NULL) ? "" : label_;
char level_str[8] = "n/a";
char buf[128];
- get_level_school(s, 50, -50, &level, &na);
- spell_school_name(sch_str, spell);
+ get_level_school(spell, 50, -50, &level, &na);
+
+ std::string sch_str(spell_school_name(spell));
if (!na)
{
@@ -490,48 +437,42 @@ int print_spell(cptr label_, byte color, int y, s32b s)
sprintf(buf, "%s%-20s%-16s %s %4d %3d%% %s",
label,
spell_type_name(spell_at(s)),
- sch_str,
+ sch_str.c_str(),
level_str,
get_mana(s),
- (int) spell_chance(s),
+ (int) spell_chance_book(s),
spell_info);
c_prt(color, buf, y, 0);
return y + 1;
}
-int print_book(s16b sval, s32b pval, object_type *obj)
+int print_book(s16b sval, s32b spell_idx, object_type *obj)
{
int y = 2;
int i;
- school_book_type *school_book;
- spell_idx_list *spell_idx;
- struct sglib_spell_idx_list_iterator it;
- random_book_setup(sval, pval);
+ random_book_setup(sval, spell_idx);
- school_book = school_books_at(sval);
+ school_book *school_book = school_books_at(sval);
/* Parse all spells */
i = 0;
- for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list);
- spell_idx != NULL;
- spell_idx = sglib_spell_idx_list_it_next(&it))
+ for (auto spell_idx : school_book->spell_idxs)
{
- s32b s = spell_idx->i;
byte color = TERM_L_DARK;
bool_ is_ok;
char label[8];
- is_ok = is_ok_spell(s, obj);
+ is_ok = is_ok_spell(spell_idx, obj->pval);
if (is_ok)
{
- color = (get_mana(s) > get_power(s)) ? TERM_ORANGE : TERM_L_GREEN;
+ 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, s);
+ y = print_spell(label, color, y, spell_idx);
i++;
}
@@ -592,9 +533,9 @@ void lua_cast_school_spell(s32b s, bool_ no_cost)
}
/* Invoke the spell effect */
- if (!magik(spell_chance(s)))
+ if (!magik(spell_chance_book(s)))
{
- use = (spell_type_produce_effect(spell, -1) != NO_CAST);
+ use = (spell_type_produce_effect(spell) != NO_CAST);
}
else
{
@@ -612,7 +553,7 @@ void lua_cast_school_spell(s32b s, bool_ no_cost)
}
else
{
- spell_type_produce_effect(spell, -1);
+ spell_type_produce_effect(spell);
}
/* Use the mana/piety */
@@ -626,124 +567,6 @@ void lua_cast_school_spell(s32b s, bool_ no_cost)
}
/* Refresh player */
- p_ptr->redraw |= PR_MANA;
+ p_ptr->redraw |= PR_FRAME;
p_ptr->window |= PW_PLAYER;
}
-
-void device_allocation_init(device_allocation *device_allocation, byte tval)
-{
- assert(device_allocation != NULL);
-
- device_allocation->tval = tval;
- device_allocation->rarity = 0;
- range_init(&device_allocation->base_level, 0, 0);
- range_init(&device_allocation->max_level, 0, 0);
- device_allocation->next = NULL;
-}
-
-device_allocation *device_allocation_new(byte tval)
-{
- device_allocation *d = malloc(sizeof(device_allocation));
- device_allocation_init(d, tval);
- return d;
-}
-
-int compare_device_allocation(device_allocation *a, device_allocation *b)
-{
- return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval);
-}
-
-SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next);
-
-void dice_init(dice_type *dice, long base, long num, long sides)
-{
- assert(dice != NULL);
-
- 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/spells4.hpp b/src/spells4.hpp
new file mode 100644
index 00000000..99203ef8
--- /dev/null
+++ b/src/spells4.hpp
@@ -0,0 +1,43 @@
+#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 print_book(s16b sval, s32b spell_idx, object_type *obj);
+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.c b/src/spells5.cc
index 7ad0d3b9..ca6351b6 100644
--- a/src/spells5.c
+++ b/src/spells5.cc
@@ -1,10 +1,17 @@
-#include <angband.h>
+#include "spells5.hpp"
-#include <assert.h>
+#include "spell_type.hpp"
+#include "device_allocation.hpp"
+#include "spells3.hpp"
+#include "spells4.hpp"
+#include "variable.hpp"
-#include "spell_type.h"
+#include <cassert>
-static spell_type *spell_new(s32b *index, cptr id, cptr name)
+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);
@@ -16,6 +23,11 @@ static spell_type *spell_new(s32b *index, cptr id, cptr name)
return spell;
}
+static cptr no_info()
+{
+ return "";
+}
+
spell_type *spell_at(s32b index)
{
assert(index >= 0);
@@ -59,37 +71,39 @@ s16b get_random_spell(s16b random_type, int level)
return -1;
}
-static void spells_init_tome()
+/*
+ * Get a spell for a device of a given tval (wand or staff).
+ */
+s16b get_random_stick(byte tval, int level)
{
- {
- spell_type *spell = spell_new(&DEVICE_LEBOHAUM, "DEVICE_LEBOHAUM", "Artifact Lebauhaum");
- spell_type_set_activation_timeout(spell, "3");
- spell_type_describe(spell, "sing a cheerful song");
- spell_type_set_mana(spell, 0, 0);
- spell_type_set_difficulty(spell, 1, 0);
- spell_type_init_device(spell,
- device_lebohaum_info,
- device_lebohaum);
- }
+ int tries;
+ for (tries = 0; tries < 1000; tries++)
{
- spell_type *spell = spell_new(&DEVICE_DURANDIL, "DEVICE_DURANDIL", "Artifact Durandil");
- spell_type_set_activation_timeout(spell, "3");
- spell_type_describe(spell, "sing a cheerful song");
- spell_type_set_mana(spell, 0, 0);
- spell_type_set_difficulty(spell, 1, 0);
- spell_type_init_device(spell,
- device_durandil_info,
- device_durandil);
+ 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, "DEVICE_THUNDERLORDS", "Artifact Thunderlords");
+ 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,
- device_thunderlords_info,
+ no_info,
device_thunderlords);
spell_type_set_device_charges(spell, "3+d3");
@@ -107,14 +121,14 @@ static void spells_init_tome()
static void spells_init_theme()
{
{
- spell_type *spell = spell_new(&GROW_ATHELAS, "GROW_ATHELAS", "Grow Athelas");
+ 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,
- nature_grow_athelas_info,
+ no_info,
nature_grow_athelas);
spell_type_set_device_charges(spell, "1+d3");
@@ -129,7 +143,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&AULE_FIREBRAND, "AULE_FIREBRAND", "Firebrand");
+ 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");
@@ -142,7 +156,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&AULE_ENCHANT_WEAPON, "AULE_ENCHANT_WEAPON", "Enchant Weapon");
+ 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");
@@ -156,7 +170,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&AULE_ENCHANT_ARMOUR, "AULE_ENCHANT_ARMOUR", "Enchant Armour");
+ 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");
@@ -170,7 +184,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&AULE_CHILD, "AULE_CHILD", "Child of Aule");
+ 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);
@@ -182,7 +196,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&VARDA_LIGHT_VALINOR, "VARDA_LIGHT_VALINOR", "Light of Valinor");
+ 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");
@@ -195,19 +209,19 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&VARDA_CALL_ALMAREN, "VARDA_CALL_ALMAREN", "Call of Almaren");
+ 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,
- varda_call_of_almaren_info,
+ no_info,
varda_call_of_almaren_spell);
}
{
- spell_type *spell = spell_new(&VARDA_EVENSTAR, "VARDA_EVENSTAR", "Evenstar");
+ 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");
@@ -216,12 +230,12 @@ static void spells_init_theme()
spell_type_set_difficulty(spell, 20, 20);
spell_type_init_priest(spell,
SCHOOL_VARDA,
- varda_evenstar_info,
+ no_info,
varda_evenstar_spell);
}
{
- spell_type *spell = spell_new(&VARDA_STARKINDLER, "VARDA_STARKINDLER", "Star Kindler");
+ 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);
@@ -233,7 +247,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&ULMO_BELEGAER, "ULMO_BELEGAER", "Song of Belegaer");
+ 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);
@@ -245,7 +259,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&ULMO_DRAUGHT_ULMONAN, "ULMO_DRAUGHT_ULMONAN", "Draught of Ulmonan");
+ 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");
@@ -260,7 +274,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&ULMO_CALL_ULUMURI, "ULMO_CALL_ULUMURI", "Call of the Ulumuri");
+ 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);
@@ -272,7 +286,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&ULMO_WRATH, "ULMO_WRATH", "Wrath of Ulmo");
+ 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);
@@ -284,7 +298,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&MANDOS_TEARS_LUTHIEN, "MANDOS_TEARS_LUTHIEN", "Tears of Luthien");
+ 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);
@@ -295,7 +309,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&MANDOS_SPIRIT_FEANTURI, "MANDOS_SPIRIT_FEANTURI", "Feanturi");
+ 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");
@@ -308,7 +322,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&MANDOS_TALE_DOOM, "MANDOS_TALE_DOOM", "Tale of Doom");
+ 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);
@@ -319,7 +333,7 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&MANDOS_CALL_HALLS, "MANDOS_CALL_HALLS", "Call to the Halls");
+ 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);
@@ -331,12 +345,12 @@ static void spells_init_theme()
}
{
- spell_type *spell = spell_new(&DEVICE_THUNDERLORDS, "DEVICE_THUNDERLORDS", "Artifact Thunderlords");
+ 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,
- device_thunderlords_info,
+ no_info,
device_thunderlords);
spell_type_set_device_charges(spell, "5+d5");
@@ -349,28 +363,6 @@ static void spells_init_theme()
spell_type_add_device_allocation(spell, device_allocation);
}
}
-
- {
- spell_type *spell = spell_new(&DEVICE_RADAGAST, "DEVICE_RADAGAST", "Artifact Radagast");
- spell_type_set_activation_timeout(spell, "15000");
- spell_type_describe(spell, "purity and health");
- spell_type_set_mana(spell, 0, 0);
- spell_type_set_difficulty(spell, 1, 10);
- spell_type_init_device(spell,
- device_radagast_info,
- device_radagast);
- }
-
- {
- spell_type *spell = spell_new(&DEVICE_VALAROMA, "DEVICE_VALAROMA", "Artifact Valaroma");
- spell_type_set_activation_timeout(spell, "250");
- spell_type_describe(spell, "banish evil (level x5)");
- spell_type_set_mana(spell, 0, 0);
- spell_type_set_difficulty(spell, 1, 25);
- spell_type_init_device(spell,
- device_valaroma_info,
- device_valaroma);
- }
}
void school_spells_init()
@@ -386,7 +378,7 @@ void school_spells_init()
/* Spells */
{
- spell_type *spell = spell_new(&GLOBELIGHT, "GLOBELIGHT", "Globe of Light");
+ 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");
@@ -411,7 +403,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&FIREFLASH, "FIREFLASH", "Fireflash");
+ 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);
@@ -434,7 +426,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&FIERYAURA, "FIERYAURA", "Fiery Shield");
+ 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);
@@ -458,7 +450,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&FIREWALL, "FIREWALL", "Firewall");
+ 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);
@@ -481,7 +473,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&FIREGOLEM, "FIREGOLEM", "Fire Golem");
+ 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");
@@ -505,7 +497,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MANATHRUST, "MANATHRUST", "Manathrust");
+ 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);
@@ -528,7 +520,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DELCURSES, "DELCURSES", "Remove Curses");
+ 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);
@@ -537,7 +529,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_MANA,
- mana_remove_curses_info,
+ no_info,
mana_remove_curses);
spell_type_set_device_charges(spell, "3+d8");
@@ -552,7 +544,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&RESISTS, "RESISTS", "Elemental Shield");
+ 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);
@@ -565,7 +557,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MANASHIELD, "MANASHIELD", "Disruption 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");
@@ -581,7 +573,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&TIDALWAVE, "TIDALWAVE", "Tidal Wave");
+ 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);
@@ -605,7 +597,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&ICESTORM, "ICESTORM", "Ice Storm");
+ 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);
@@ -629,7 +621,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&ENTPOTION, "ENTPOTION", "Ent's Potion");
+ 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.");
@@ -644,7 +636,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&VAPOR, "VAPOR", "Vapor");
+ 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);
@@ -657,7 +649,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&GEYSER, "GEYSER", "Geyser");
+ 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);
@@ -670,7 +662,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&NOXIOUSCLOUD, "NOXIOUSCLOUD", "Noxious Cloud");
+ 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");
@@ -694,7 +686,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&AIRWINGS, "AIRWINGS", "Wings of Winds");
+ 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);
@@ -719,7 +711,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&INVISIBILITY, "INVISIBILITY", "Invisibility");
+ 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);
@@ -732,7 +724,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&POISONBLOOD, "POISONBLOOD", "Poison Blood");
+ 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);
@@ -756,7 +748,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&THUNDERSTORM, "THUNDERSTORM", "Thunderstorm");
+ 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");
@@ -783,7 +775,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&STERILIZE, "STERILIZE", "Sterilize");
+ 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);
@@ -805,7 +797,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&STONESKIN, "STONESKIN", "Stone Skin");
+ 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);
@@ -819,14 +811,14 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DIG, "DIG", "Dig");
+ 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,
- earth_dig_info,
+ no_info,
earth_dig);
spell_type_set_device_charges(spell, "15+d5");
@@ -841,7 +833,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&STONEPRISON, "STONEPRISON", "Stone Prison");
+ 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);
@@ -849,7 +841,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_EARTH,
- earth_stone_prison_info,
+ no_info,
earth_stone_prison);
spell_type_set_device_charges(spell, "5+d3");
@@ -864,7 +856,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&STRIKE, "STRIKE", "Strike");
+ 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");
@@ -888,7 +880,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&SHAKE, "SHAKE", "Shake");
+ 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);
@@ -912,7 +904,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&BLINK, "BLINK", "Phase Door");
+ 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);
@@ -926,7 +918,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DISARM, "DISARM", "Disarm");
+ 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");
@@ -935,7 +927,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_CONVEYANCE,
- convey_disarm_info,
+ no_info,
convey_disarm);
spell_type_set_device_charges(spell, "10+d15");
@@ -950,7 +942,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&TELEPORT, "TELEPORT", "Teleportation");
+ 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);
@@ -973,7 +965,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&TELEAWAY, "TELEAWAY", "Teleport Away");
+ 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");
@@ -982,7 +974,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_CONVEYANCE,
- convey_teleport_away_info,
+ no_info,
convey_teleport_away);
spell_type_set_device_charges(spell, "3+d5");
@@ -997,7 +989,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&RECALL, "RECALL", "Recall");
+ 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.");
@@ -1011,7 +1003,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&PROBABILITY_TRAVEL, "PROBABILITY_TRAVEL", "Probability Travel");
+ 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");
@@ -1036,7 +1028,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&GROWTREE, "GROWTREE", "Grow Trees");
+ 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);
@@ -1050,7 +1042,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&HEALING, "HEALING", "Healing");
+ 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);
@@ -1072,7 +1064,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&RECOVERY, "RECOVERY", "Recovery");
+ 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");
@@ -1083,7 +1075,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_NATURE,
- nature_recovery_info,
+ no_info,
nature_recovery);
spell_type_set_device_charges(spell, "5+d10");
@@ -1098,7 +1090,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&REGENERATION, "REGENERATION", "Regeneration");
+ 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);
@@ -1111,7 +1103,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&SUMMONANNIMAL, "SUMMONANNIMAL", "Summon Animal");
+ 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);
@@ -1133,7 +1125,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&STARIDENTIFY, "STARIDENTIFY", "Greater Identify");
+ 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);
@@ -1141,12 +1133,12 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_DIVINATION,
- divination_greater_identify_info,
+ no_info,
divination_greater_identify);
}
{
- spell_type *spell = spell_new(&IDENTIFY, "IDENTIFY", "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");
@@ -1171,7 +1163,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&VISION, "VISION", "Vision");
+ 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);
@@ -1180,7 +1172,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_DIVINATION,
- divination_vision_info,
+ no_info,
divination_vision);
spell_type_set_device_charges(spell, "4+d6");
@@ -1195,7 +1187,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&SENSEHIDDEN, "SENSEHIDDEN", "Sense Hidden");
+ 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);
@@ -1219,7 +1211,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&REVEALWAYS, "REVEALWAYS", "Reveal Ways");
+ 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);
@@ -1242,7 +1234,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&SENSEMONSTERS, "SENSEMONSTERS", "Sense Monsters");
+ 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);
@@ -1266,7 +1258,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MAGELOCK, "MAGELOCK", "Magelock");
+ 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");
@@ -1275,7 +1267,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_TEMPORAL,
- tempo_magelock_info,
+ no_info,
tempo_magelock);
spell_type_set_device_charges(spell, "7+d5");
@@ -1290,7 +1282,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&SLOWMONSTER, "SLOWMONSTER", "Slow Monster");
+ 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);
@@ -1313,7 +1305,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&ESSENCESPEED, "ESSENCESPEED", "Essence of Speed");
+ 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);
@@ -1337,7 +1329,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&BANISHMENT, "BANISHMENT", "Banishment");
+ 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);
@@ -1362,7 +1354,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&RECHARGE, "RECHARGE", "Recharge");
+ 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);
@@ -1374,7 +1366,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&SPELLBINDER, "SPELLBINDER", "Spellbinder");
+ 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");
@@ -1391,7 +1383,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DISPERSEMAGIC, "DISPERSEMAGIC", "Disperse Magic");
+ 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");
@@ -1406,7 +1398,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_META,
- meta_disperse_magic_info,
+ no_info,
meta_disperse_magic);
spell_type_set_device_charges(spell, "5+d5");
@@ -1421,7 +1413,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&TRACKER, "TRACKER", "Tracker");
+ 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);
@@ -1430,12 +1422,12 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_META,
- meta_tracker_info,
+ no_info,
meta_tracker);
}
{
- spell_type *spell = spell_new(&INERTIA_CONTROL, "INERTIA_CONTROL", "Inertia Control");
+ 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.");
@@ -1449,7 +1441,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&CHARM, "CHARM", "Charm");
+ 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");
@@ -1473,7 +1465,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&CONFUSE, "CONFUSE", "Confuse");
+ 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");
@@ -1497,7 +1489,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&ARMOROFFEAR, "ARMOROFFEAR", "Armor of Fear");
+ 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);
@@ -1511,7 +1503,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&STUN, "STUN", "Stun");
+ 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);
@@ -1524,7 +1516,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DRAIN, "DRAIN", "Drain");
+ 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);
@@ -1532,12 +1524,12 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_UDUN,
- udun_drain_info,
+ no_info,
udun_drain);
}
{
- spell_type *spell = spell_new(&GENOCIDE, "GENOCIDE", "Genocide");
+ 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);
@@ -1546,7 +1538,7 @@ void school_spells_init()
spell_type_init_mage(spell,
RANDOM,
SCHOOL_UDUN,
- udun_genocide_info,
+ no_info,
udun_genocide);
spell_type_set_device_charges(spell, "2+d2");
@@ -1561,7 +1553,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&WRAITHFORM, "WRAITHFORM", "Wraithform");
+ 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);
@@ -1575,7 +1567,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&FLAMEOFUDUN, "FLAMEOFUDUN", "Flame of Udun");
+ 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);
@@ -1589,7 +1581,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&CALL_THE_ELEMENTS, "CALL_THE_ELEMENTS", "Call the Elements");
+ 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");
@@ -1605,7 +1597,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&CHANNEL_ELEMENTS, "CHANNEL_ELEMENTS", "Channel 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.");
@@ -1625,12 +1617,12 @@ void school_spells_init()
spell_type_init_mage(spell,
NO_RANDOM,
SCHOOL_GEOMANCY,
- geomancy_channel_elements_info,
+ no_info,
geomancy_channel_elements);
}
{
- spell_type *spell = spell_new(&ELEMENTAL_WAVE, "ELEMENTAL_WAVE", "Elemental Wave");
+ 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.");
@@ -1640,12 +1632,12 @@ void school_spells_init()
spell_type_init_mage(spell,
NO_RANDOM,
SCHOOL_GEOMANCY,
- geomancy_elemental_wave_info,
+ no_info,
geomancy_elemental_wave);
}
{
- spell_type *spell = spell_new(&VAPORIZE, "VAPORIZE", "Vaporize");
+ 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);
@@ -1658,7 +1650,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&GEOLYSIS, "GEOLYSIS", "Geolysis");
+ 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);
@@ -1672,7 +1664,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DRIPPING_TREAD, "DRIPPING_TREAD", "Dripping Tread");
+ 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);
@@ -1685,7 +1677,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&GROW_BARRIER, "GROW_BARRIER", "Grow Barrier");
+ 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);
@@ -1693,13 +1685,13 @@ void school_spells_init()
spell_type_set_castable_while_blind(spell, TRUE);
spell_type_init_geomancy(
spell,
- geomancy_grow_barrier_info,
+ no_info,
geomancy_grow_barrier,
geomancy_grow_barrier_depends);
}
{
- spell_type *spell = spell_new(&ELEMENTAL_MINION, "ELEMENTAL_MINION", "Elemental Minion");
+ 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");
@@ -1716,7 +1708,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&ERU_SEE, "ERU_SEE", "See the Music");
+ 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");
@@ -1732,7 +1724,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&ERU_LISTEN, "ERU_LISTEN", "Listen to the Music");
+ 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");
@@ -1741,12 +1733,12 @@ void school_spells_init()
spell_type_set_difficulty(spell, 7, 25);
spell_type_init_priest(spell,
SCHOOL_ERU,
- eru_listen_to_the_music_info,
+ no_info,
eru_listen_to_the_music);
}
{
- spell_type *spell = spell_new(&ERU_UNDERSTAND, "ERU_UNDERSTAND", "Know 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");
@@ -1754,12 +1746,12 @@ void school_spells_init()
spell_type_set_difficulty(spell, 30, 50);
spell_type_init_priest(spell,
SCHOOL_ERU,
- eru_know_the_music_info,
+ no_info,
eru_know_the_music);
}
{
- spell_type *spell = spell_new(&ERU_PROT, "ERU_PROT", "Lay of Protection");
+ 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);
@@ -1770,7 +1762,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MANWE_SHIELD, "MANWE_SHIELD", "Wind Shield");
+ 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");
@@ -1783,7 +1775,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MANWE_AVATAR, "MANWE_AVATAR", "Avatar");
+ 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);
@@ -1794,7 +1786,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MANWE_BLESS, "MANWE_BLESS", "Manwe's Blessing");
+ 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");
@@ -1809,7 +1801,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MANWE_CALL, "MANWE_CALL", "Manwe's Call");
+ 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);
@@ -1821,7 +1813,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&TULKAS_AIM, "TULKAS_AIM", "Divine Aim");
+ 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);
@@ -1833,7 +1825,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&TULKAS_WAVE, "TULKAS_WAVE", "Wave of Power");
+ 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);
@@ -1844,18 +1836,18 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&TULKAS_SPIN, "TULKAS_SPIN", "Whirlwind");
+ 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,
- tulkas_whirlwind_info,
+ no_info,
tulkas_whirlwind);
}
{
- spell_type *spell = spell_new(&MELKOR_CURSE, "MELKOR_CURSE", "Curse");
+ 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");
@@ -1865,12 +1857,12 @@ void school_spells_init()
spell_type_set_difficulty(spell, 1, 20);
spell_type_init_priest(spell,
SCHOOL_MELKOR,
- melkor_curse_info,
+ no_info,
melkor_curse);
}
{
- spell_type *spell = spell_new(&MELKOR_CORPSE_EXPLOSION, "MELKOR_CORPSE_EXPLOSION", "Corpse Explosion");
+ 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);
@@ -1882,7 +1874,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MELKOR_MIND_STEAL, "MELKOR_MIND_STEAL", "Mind Steal");
+ 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);
@@ -1894,7 +1886,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&YAVANNA_CHARM_ANIMAL, "YAVANNA_CHARM_ANIMAL", "Charm Animal");
+ 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);
@@ -1905,7 +1897,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&YAVANNA_GROW_GRASS, "YAVANNA_GROW_GRASS", "Grow Grass");
+ 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);
@@ -1917,7 +1909,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&YAVANNA_TREE_ROOTS, "YAVANNA_TREE_ROOTS", "Tree Roots");
+ 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.");
@@ -1930,7 +1922,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&YAVANNA_WATER_BITE, "YAVANNA_WATER_BITE", "Water Bite");
+ 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);
@@ -1942,7 +1934,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&YAVANNA_UPROOT, "YAVANNA_UPROOT", "Uproot");
+ 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);
@@ -1953,7 +1945,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEMON_BLADE, "DEMON_BLADE", "Demon Blade");
+ 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");
@@ -1975,7 +1967,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEMON_MADNESS, "DEMON_MADNESS", "Demon Madness");
+ 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);
@@ -1985,7 +1977,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEMON_FIELD, "DEMON_FIELD", "Demon Field");
+ 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);
@@ -1995,7 +1987,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DOOM_SHIELD, "DOOM_SHIELD", "Doom Shield");
+ 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);
@@ -2006,7 +1998,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&UNHOLY_WORD, "UNHOLY_WORD", "Unholy Word");
+ 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");
@@ -2018,7 +2010,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEMON_CLOAK, "DEMON_CLOAK", "Demon Cloak");
+ 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);
@@ -2028,7 +2020,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEMON_SUMMON, "DEMON_SUMMON", "Summon Demon");
+ 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);
@@ -2039,7 +2031,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DISCHARGE_MINION, "DISCHARGE_MINION", "Discharge Minion");
+ 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);
@@ -2049,7 +2041,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&CONTROL_DEMON, "CONTROL_DEMON", "Control Demon");
+ 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);
@@ -2059,7 +2051,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_HEAL_MONSTER, "DEVICE_HEAL_MONSTER", "Heal Monster");
+ 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);
@@ -2079,7 +2071,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_SPEED_MONSTER, "DEVICE_SPEED_MONSTER", "Haste Monster");
+ 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);
@@ -2099,12 +2091,12 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_WISH, "DEVICE_WISH", "Wish");
+ 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,
- device_wish_info,
+ no_info,
device_wish);
spell_type_set_device_charges(spell, "1+d2");
@@ -2119,12 +2111,12 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_SUMMON, "DEVICE_SUMMON", "Summon");
+ 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,
- device_summon_monster_info,
+ no_info,
device_summon_monster);
spell_type_set_device_charges(spell, "1+d20");
@@ -2139,7 +2131,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_MANA, "DEVICE_MANA", "Mana");
+ 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);
@@ -2159,12 +2151,12 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_NOTHING, "DEVICE_NOTHING", "Nothing");
+ 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,
- device_nothing_info,
+ no_info,
device_nothing);
spell_type_set_device_charges(spell, "0+d0");
@@ -2187,18 +2179,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_MAGGOT, "DEVICE_MAGGOT", "Artifact Maggot");
- spell_type_set_activation_timeout(spell, "10+d50");
- spell_type_describe(spell, "terrify");
- spell_type_set_mana(spell, 7, 7);
- spell_type_set_difficulty(spell, 1, 20);
- spell_type_init_device(spell,
- device_maggot_info,
- device_maggot);
- }
-
- {
- spell_type *spell = spell_new(&DEVICE_HOLY_FIRE, "DEVICE_HOLY_FIRE", "Holy Fire of Mithrandir");
+ 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);
@@ -2219,30 +2200,19 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&DEVICE_ETERNAL_FLAME, "DEVICE_ETERNAL_FLAME", "Artifact Eternal Flame");
- spell_type_set_activation_timeout(spell, "0");
- spell_type_describe(spell, "Imbuing an object with the eternal fire");
- spell_type_set_mana(spell, 0, 0);
- spell_type_set_difficulty(spell, 1, 0);
- spell_type_init_device(spell,
- device_eternal_flame_info,
- device_eternal_flame);
- }
-
- {
- spell_type *spell = spell_new(&MUSIC_STOP, "MUSIC_STOP", "Stop singing(I)");
+ 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,
- music_stop_singing_info,
+ no_info,
music_stop_singing_spell);
}
{
- spell_type *spell = spell_new(&MUSIC_HOLD, "MUSIC_HOLD", "Holding Pattern(I)");
+ 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);
@@ -2257,7 +2227,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_CONF, "MUSIC_CONF", "Illusion Pattern(II)");
+ 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);
@@ -2272,7 +2242,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_STUN, "MUSIC_STUN", "Stun Pattern(IV)");
+ 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);
@@ -2287,7 +2257,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_LITE, "MUSIC_LITE", "Song of the Sun(I)");
+ 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);
@@ -2296,13 +2266,13 @@ void school_spells_init()
spell_type_init_music_lasting(
spell,
1,
- music_song_of_the_sun_info,
+ no_info,
music_song_of_the_sun_spell,
music_song_of_the_sun_lasting);
}
{
- spell_type *spell = spell_new(&MUSIC_HEAL, "MUSIC_HEAL", "Flow of Life(II)");
+ 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);
@@ -2316,7 +2286,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_HERO, "MUSIC_HERO", "Heroic Ballad(II)");
+ 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");
@@ -2327,13 +2297,13 @@ void school_spells_init()
spell_type_init_music_lasting(
spell,
2,
- music_heroic_ballad_info,
+ no_info,
music_heroic_ballad_spell,
music_heroic_ballad_lasting);
}
{
- spell_type *spell = spell_new(&MUSIC_TIME, "MUSIC_TIME", "Hobbit Melodies(III)");
+ 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.");
@@ -2348,7 +2318,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_MIND, "MUSIC_MIND", "Clairaudience(IV)");
+ 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.");
@@ -2364,7 +2334,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_BLOW, "MUSIC_BLOW", "Blow(I)");
+ 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);
@@ -2375,7 +2345,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_WIND, "MUSIC_WIND", "Gush of Wind(II)");
+ 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);
@@ -2386,7 +2356,7 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_YLMIR, "MUSIC_YLMIR", "Horns of Ylmir(III)");
+ 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);
@@ -2397,14 +2367,14 @@ void school_spells_init()
}
{
- spell_type *spell = spell_new(&MUSIC_AMBARKANTA, "MUSIC_AMBARKANTA", "Ambarkanta(IV)");
+ 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,
- music_ambarkanta_info,
+ no_info,
music_ambarkanta_spell);
}
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.c b/src/spells6.cc
index 5db4e18e..a4564ae3 100644
--- a/src/spells6.c
+++ b/src/spells6.cc
@@ -1,34 +1,46 @@
-#include <angband.h>
+#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 */
-#include <assert.h>
+ s16b skill_idx; /* Skill used for determining the boost */
-#include "spell_type.h"
+ long mul; /* Multiplier */
-static int compare_school_provider(school_provider *a, school_provider *b)
-{
- return SGLIB_NUMERIC_COMPARATOR(a->deity_idx, b->deity_idx);
-}
-
-static void school_provider_init(school_provider *p, byte deity_idx, long mul, long div)
-{
- assert(p != NULL);
+ long div; /* Divisor */
+};
- p->deity_idx = deity_idx;
- p->skill_idx = SKILL_PRAY;
- p->mul = mul;
- p->div = div;
- p->next = NULL;
-}
+struct school_provider_list {
+public:
+ std::vector<school_provider> v;
+};
-static school_provider *school_provider_new(byte deity_idx, long mul, long div)
+static school_provider school_provider_new(byte deity_idx, long mul, long div)
{
- school_provider *p = malloc(sizeof(school_provider));
- school_provider_init(p, deity_idx, mul, div);
+ school_provider p;
+ p.deity_idx = deity_idx;
+ p.skill_idx = SKILL_PRAY;
+ p.mul = mul;
+ p.div = div;
return p;
}
-SGLIB_DEFINE_LIST_FUNCTIONS(school_provider, compare_school_provider, next);
-
school_type *school_at(int index)
{
assert(index >= 0);
@@ -41,8 +53,10 @@ 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;
@@ -96,14 +110,15 @@ static school_type *god_school_new(s32b *school_idx, byte god)
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_provider *school_provider = school_provider_new(god, mul, div);
- sglib_school_provider_add(&school->providers, school_provider);
+ school->providers->v.push_back(school_provider_new(god, mul, div));
}
}
@@ -136,23 +151,17 @@ static bool_ geomancy_depends_satisfied()
long get_provided_levels(school_type *school)
{
- school_provider *school_provider = NULL;
- struct sglib_school_provider_iterator school_provider_it;
-
- for (school_provider = sglib_school_provider_it_init(&school_provider_it, school->providers);
- school_provider != NULL;
- school_provider = sglib_school_provider_it_next(&school_provider_it))
+ for (auto school_provider: school->providers->v)
{
- if (school_provider->deity_idx == p_ptr->pgod)
+ if (school_provider.deity_idx == p_ptr->pgod)
{
- return (s_info[school_provider->skill_idx].value * school_provider->mul) / school_provider->div;
+ return (s_info[school_provider.skill_idx].value * school_provider.mul) / school_provider.div;
}
}
return 0;
}
-typedef struct get_level_school_callback_data get_level_school_callback_data;
struct get_level_school_callback_data {
bool_ allow_spell_power;
long bonus;
@@ -160,9 +169,8 @@ struct get_level_school_callback_data {
long num;
};
-static bool_ get_level_school_callback(void *data_, int school_idx)
+static bool get_level_school_callback(struct get_level_school_callback_data *data, int school_idx)
{
- get_level_school_callback_data *data = data_;
school_type *school = school_at(school_idx);
long r = 0, s = 0, p = 0, ok = 0;
@@ -170,7 +178,7 @@ static bool_ get_level_school_callback(void *data_, int school_idx)
if ((school->deity_idx > 0) &&
(school->deity_idx != p_ptr->pgod))
{
- return FALSE;
+ return false;
}
/* Take the basic skill value */
@@ -180,7 +188,7 @@ static bool_ get_level_school_callback(void *data_, int school_idx)
if ((school->depends_satisfied != NULL) &&
(!school->depends_satisfied()))
{
- return FALSE;
+ return false;
}
/* Include effects of Sorcery (if applicable) */
@@ -219,7 +227,7 @@ static bool_ get_level_school_callback(void *data_, int school_idx)
/* All schools must be non-zero to be able to use it. */
if (ok <= 0)
{
- return FALSE;
+ return false;
}
/* Apply it */
@@ -227,13 +235,11 @@ static bool_ get_level_school_callback(void *data_, int school_idx)
data->num += 1;
/* Keep going */
- return TRUE;
+ return true;
}
-void get_level_school(s32b spell_idx, s32b max, s32b min, s32b *level, bool_ *na)
+void get_level_school(spell_type *spell, s32b max, s32b min, s32b *level, bool_ *na)
{
- spell_type *spell = spell_at(spell_idx);
-
assert(level != NULL);
assert(na != NULL);
@@ -252,12 +258,16 @@ void get_level_school(s32b spell_idx, s32b max, s32b min, s32b *level, bool_ *na
data.lvl = 0;
data.num = 0;
- /* Go through all the spell's schools. */
- if (!spell_type_school_foreach(spell, get_level_school_callback, &data))
+ // 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))
{
- *level = min;
- *na = TRUE;
- return;
+ if (!get_level_school_callback(&data, school_idx))
+ {
+ *level = min;
+ *na = TRUE;
+ return;
+ }
}
/* Add the Spellpower skill as a bonus on top */
@@ -378,7 +388,7 @@ void schools_init()
/* Placeholder schools */
{
school_new(&SCHOOL_DEVICE, "Device", SKILL_DEVICE);
- school_new(&SCHOOL_DEVICE, "Music", SKILL_MUSIC);
+ school_new(&SCHOOL_MUSIC, "Music", SKILL_MUSIC);
}
}
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 5bf67cd5..00000000
--- a/src/squeltch.c
+++ /dev/null
@@ -1,3582 +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 <jansson.h>
-
-#include "quark.h"
-
-#define RULES_MAX 4096
-#define STACK_MAX 1024
-
-typedef enum { BAD, VERY_BAD, AVERAGE,
- GOOD, VERY_GOOD, SPECIAL,
- TERRIBLE, NONE, CHEST_EMPTY,
- CHEST_DISARMED } status_type;
-
-struct status_map_type {
- status_type status;
- cptr status_s;
-};
-
-status_type object_status(object_type *o_ptr)
-{
- if (!object_known_p(o_ptr))
- {
- switch (o_ptr->sense)
- {
- case SENSE_CURSED: return BAD;
- case SENSE_WORTHLESS: return VERY_BAD;
- case SENSE_AVERAGE: return AVERAGE;
- case SENSE_GOOD_LIGHT: return GOOD;
- case SENSE_GOOD_HEAVY: return GOOD;
- case SENSE_EXCELLENT: return VERY_GOOD;
- case SENSE_SPECIAL: return SPECIAL;
- case SENSE_TERRIBLE: return TERRIBLE;
- default: return NONE;
- }
- }
- else
- {
- s16b slot = wield_slot_ideal(o_ptr, TRUE);
-
- if (artifact_p(o_ptr))
- {
- if (!(o_ptr->ident & IDENT_CURSED))
- {
- return SPECIAL;
- }
- else
- {
- return TERRIBLE;
- }
- }
- else if ((o_ptr->name2 > 0) ||
- (o_ptr->name2b > 0))
- {
- if (!(o_ptr->ident & IDENT_CURSED))
- {
- return VERY_GOOD;
- }
- else
- {
- return VERY_BAD;
- }
- }
- else if ((slot == INVEN_WIELD) ||
- (slot == INVEN_BOW) ||
- (slot == INVEN_AMMO) ||
- (slot == INVEN_TOOL))
- {
- if (o_ptr->to_h + o_ptr->to_d < 0)
- {
- return BAD;
- }
- else if (o_ptr->to_h + o_ptr->to_d > 0)
- {
- return GOOD;
- }
- else
- {
- return AVERAGE;
- }
- }
- else if ((slot >= INVEN_BODY) &&
- (slot <= INVEN_FEET))
- {
- if (o_ptr->to_a < 0)
- {
- return BAD;
- }
- else if (o_ptr->to_a > 0)
- {
- return GOOD;
- }
- else
- {
- return AVERAGE;
- }
- }
- else if (slot == INVEN_RING)
- {
- if ((o_ptr->to_d + o_ptr->to_h < 0) ||
- (o_ptr->to_a < 0) ||
- (o_ptr->pval < 0))
- {
- return BAD;
- }
- else
- {
- return AVERAGE;
- }
- }
- else if (slot == INVEN_NECK)
- {
- if (o_ptr->pval < 0)
- {
- return BAD;
- }
- else
- {
- return AVERAGE;
- }
- }
- else if (o_ptr->tval == TV_CHEST)
- {
- if (o_ptr->pval == 0)
- {
- return CHEST_EMPTY;
- }
- else if (o_ptr->pval < 0)
- {
- return CHEST_DISARMED;
- }
- else
- {
- return AVERAGE;
- }
- }
- else
- {
- return AVERAGE;
- }
- }
-}
-
-#define STATUS_MAP_SIZE 10
-struct status_map_type status_map[STATUS_MAP_SIZE] = {
- { BAD, "bad" },
- { VERY_BAD, "very bad" },
- { AVERAGE, "average" },
- { GOOD, "good" },
- { VERY_GOOD, "very good" },
- { SPECIAL, "special" },
- { TERRIBLE, "terrible" },
- { NONE, "none" },
- { CHEST_EMPTY, "(empty chest)" },
- { CHEST_DISARMED, "(disarmed chest)" },
-};
-
-static cptr status_to_string(status_type status)
-{
- int i;
-
- for (i = 0; i < STATUS_MAP_SIZE; i++)
- {
- if (status_map[i].status == status)
- {
- return status_map[i].status_s;
- }
- }
-
- assert(FALSE);
- return NULL;
-}
-
-static bool_ status_from_string(cptr s, status_type *status)
-{
- int i;
-
- for (i = 0; i < STATUS_MAP_SIZE; i++)
- {
- if (streq(status_map[i].status_s, s))
- {
- *status = status_map[i].status;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/* Type of automatizer actions */
-typedef enum { AUTO_DESTROY,
- AUTO_PICKUP,
- AUTO_INSCRIBE } action_type;
-
-/* Convert action to/from string */
-struct action_map_type {
- action_type action;
- cptr action_s;
-};
-
-#define ACTION_MAP_SIZE 3
-struct action_map_type action_map[ACTION_MAP_SIZE] = {
- { AUTO_DESTROY, "destroy" },
- { AUTO_PICKUP, "pickup" },
- { AUTO_INSCRIBE, "inscribe" }
-};
-
-static cptr action_to_string(action_type action)
-{
- int i = 0;
-
- for (i = 0; i < ACTION_MAP_SIZE; i++)
- {
- if (action == action_map[i].action)
- {
- return action_map[i].action_s;
- }
- }
-
- assert(FALSE);
- return NULL;
-}
-
-static bool_ action_from_string(cptr s, action_type *action)
-{
- int i = 0;
-
- for (i = 0; i < ACTION_MAP_SIZE; i++)
- {
- if (streq(action_map[i].action_s, s))
- {
- *action = action_map[i].action;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/* Identification state */
-typedef enum { IDENTIFIED, NOT_IDENTIFIED } identification_state;
-
-#define S_IDENTIFIED "identified"
-#define S_NOT_IDENTIFIED "not identified"
-
-cptr identification_state_to_string(identification_state i)
-{
- switch (i)
- {
- case IDENTIFIED: return S_IDENTIFIED;
- case NOT_IDENTIFIED: return S_NOT_IDENTIFIED;
- }
-
- assert(FALSE);
- return NULL;
-}
-
-bool_ identification_state_from_string(cptr s, identification_state *state)
-{
- if (streq(s, S_IDENTIFIED))
- {
- *state = IDENTIFIED;
- return TRUE;
- }
- else if (streq(s, S_NOT_IDENTIFIED))
- {
- *state = NOT_IDENTIFIED;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-/* Match type */
-typedef enum { M_AND , M_OR , M_NOT , M_NAME , M_CONTAIN ,
- M_INSCRIBED, M_DISCOUNT, M_SYMBOL , M_STATE , M_STATUS ,
- M_TVAL , M_SVAL , M_RACE , M_SUBRACE , M_CLASS ,
- M_LEVEL , M_SKILL , M_ABILITY, M_INVENTORY, M_EQUIPMENT }
- match_type;
-
-struct match_type_map {
- match_type i;
- cptr s;
-};
-
-#define MATCH_TYPE_MAP_SIZE 20
-struct match_type_map match_type_map[MATCH_TYPE_MAP_SIZE] = {
- { M_AND, "and" },
- { M_OR, "or" },
- { M_NOT, "not" },
- { M_NAME, "name" },
- { M_CONTAIN, "contain" },
- { M_INSCRIBED, "inscribed" },
- { M_DISCOUNT, "discount" },
- { M_SYMBOL, "symbol" },
- { M_STATE, "state" },
- { M_STATUS, "status" },
- { M_TVAL, "tval" },
- { M_SVAL, "sval" },
- { M_RACE, "race" },
- { M_SUBRACE, "subrace" },
- { M_CLASS, "class" },
- { M_LEVEL, "level" },
- { M_SKILL, "skill" },
- { M_ABILITY, "ability" },
- { M_INVENTORY, "inventory" },
- { M_EQUIPMENT, "equipment" },
-};
-
-cptr match_type_to_string(match_type m)
-{
- int i;
-
- for (i = 0; i < MATCH_TYPE_MAP_SIZE; i++)
- {
- if (match_type_map[i].i == m)
- {
- return match_type_map[i].s;
- }
- }
-
- assert(FALSE);
- return NULL;
-}
-
-bool_ match_type_from_string(cptr s, match_type *match)
-{
- int i;
-
- for (i = 0; i < MATCH_TYPE_MAP_SIZE; i++)
- {
- if (streq(match_type_map[i].s, s))
- {
- *match = match_type_map[i].i;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/* Forward declarations */
-typedef struct condition_type condition_type;
-struct condition_type;
-
-/* List of conditions */
-typedef struct condition_list condition_list;
-struct condition_list {
- condition_type *condition;
- condition_list *next;
-};
-
-int compare_condition_list(condition_list *a, condition_list *b)
-{
- assert(FALSE);
-}
-
-SGLIB_DEFINE_LIST_PROTOTYPES(condition_list, compare_condition_list, next);
-SGLIB_DEFINE_LIST_FUNCTIONS(condition_list, compare_condition_list, next);
-
-/* Condition instance */
-struct condition_type
-{
- /* What do we want to match? */
- match_type match;
- /* Sub-conditions for logical connectives; if applicable */
- struct {
- condition_list *c;
- } conditions;
- /* Sub-condition for cases where there is only a single subcondition */
- condition_type *subcondition;
- /* Tval to match if applicable. */
- byte tval;
- /* Sval range if applicable. */
- struct {
- byte min;
- byte max;
- } sval_range;
- /* Discount range. */
- struct {
- int min;
- int max;
- } discount;
- /* Level range */
- struct {
- int min;
- int max;
- } level_range;
- /* Skill range */
- struct {
- s16b min;
- s16b max;
- s16b skill_idx;
- } skill_range;
- /* Identification state to match if applicable */
- identification_state identification_state;
- /* Status to match if applicable */
- status_type status;
- /* Name to match */
- char *name;
- /* Symbol to match if applicable */
- char symbol;
- /* Inscription to find */
- char *inscription;
- /* Subrace to match if applicable */
- char *subrace;
- /* Race to match if applicable */
- char *race;
- /* Class to match if applicable */
- char *klass;
- /* Ability to match if applicable */
- s16b ability;
- /* Comment */
- char *comment;
-};
-
-static condition_type *condition_new(match_type match)
-{
- condition_type *cp = malloc(sizeof(condition_type));
- memset(cp, 0, sizeof(condition_type));
- cp->match = match;
- return cp;
-}
-
-static condition_type *condition_new_tval(byte tval)
-{
- condition_type *cp = condition_new(M_TVAL);
- cp->tval = tval;
- return cp;
-}
-
-static condition_type *condition_new_sval(byte min, byte max)
-{
- condition_type *cp = condition_new(M_SVAL);
- cp->sval_range.min = min;
- cp->sval_range.max = max;
- return cp;
-}
-
-static condition_type *condition_new_and()
-{
- condition_type *cp = condition_new(M_AND);
- return cp;
-}
-
-static condition_type *condition_new_or()
-{
- condition_type *cp = condition_new(M_OR);
- return cp;
-}
-
-static condition_type *condition_new_not()
-{
- condition_type *cp = condition_new(M_NOT);
- return cp;
-}
-
-static condition_type *condition_new_name(cptr name)
-{
- condition_type *cp = condition_new(M_NAME);
- cp->name = strdup(name);
- return cp;
-}
-
-static condition_type *condition_new_contain(cptr name)
-{
- condition_type *cp = condition_new(M_CONTAIN);
- cp->name = strdup(name);
- return cp;
-}
-
-static condition_type *condition_new_inscribed(cptr name)
-{
- condition_type *cp = condition_new(M_INSCRIBED);
- cp->inscription = strdup(name);
- return cp;
-}
-
-static condition_type *condition_new_status(status_type status)
-{
- condition_type *cp = condition_new(M_STATUS);
- cp->status = status;
- return cp;
-}
-
-static condition_type *condition_new_state(identification_state state)
-{
- condition_type *cp = condition_new(M_STATE);
- cp->identification_state = state;
- return cp;
-}
-
-static condition_type *condition_new_discount(int min, int max)
-{
- condition_type *cp = condition_new(M_DISCOUNT);
- cp->discount.min = min;
- cp->discount.max = max;
- return cp;
-}
-
-static condition_type *condition_new_symbol(char c)
-{
- condition_type *cp = condition_new(M_SYMBOL);
- cp->symbol = c;
- return cp;
-}
-
-static condition_type *condition_new_race(cptr race)
-{
- condition_type *cp = condition_new(M_RACE);
- cp->race = strdup(race);
- return cp;
-}
-
-static condition_type *condition_new_subrace(cptr subrace)
-{
- condition_type *cp = condition_new(M_SUBRACE);
- cp->subrace = strdup(subrace);
- return cp;
-}
-
-static condition_type *condition_new_class(cptr klass)
-{
- condition_type *cp = condition_new(M_CLASS);
- cp->klass = strdup(klass);
- return cp;
-}
-
-static condition_type *condition_new_level(int min, int max)
-{
- condition_type *cp = condition_new(M_LEVEL);
- cp->level_range.min = min;
- cp->level_range.max = max;
- return cp;
-}
-
-static condition_type *condition_new_skill(s16b min, s16b max, s16b skill_idx)
-{
- condition_type *cp = condition_new(M_SKILL);
- cp->skill_range.min = min;
- cp->skill_range.max = max;
- cp->skill_range.skill_idx = skill_idx;
- return cp;
-}
-
-static condition_type *condition_new_ability(s16b ability_idx)
-{
- condition_type *cp = condition_new(M_ABILITY);
- cp->ability = ability_idx;
- return cp;
-}
-
-static condition_type *condition_new_inventory()
-{
- condition_type *cp = condition_new(M_INVENTORY);
- return cp;
-}
-
-static condition_type *condition_new_equipment()
-{
- condition_type *cp = condition_new(M_EQUIPMENT);
- return cp;
-}
-
-static void condition_and_add(condition_type *and_c, condition_type *c)
-{
- if (and_c == NULL || c == NULL)
- {
- return;
- }
-
- assert(and_c != NULL);
- assert(c != NULL);
- assert((and_c->match == M_AND) || (and_c->match == M_OR));
-
- condition_list *cl = malloc(sizeof(condition_list));
- cl->condition = c;
- cl->next = NULL;
-
- sglib_condition_list_add(&and_c->conditions.c, cl);
-}
-
-static void condition_or_add(condition_type *or_c, condition_type *c)
-{
- condition_and_add(or_c, c);
-}
-
-static void condition_destroy(condition_type **cp)
-{
- condition_type *c = NULL;
- assert(cp != NULL);
- assert(*cp != NULL);
-
- c = *cp;
-
- /* Free sub-conditions if any */
- {
- condition_list *current = NULL;
- condition_list *next = NULL;
-
- for (current = c->conditions.c;
- current != NULL;
- current = next)
- {
- condition_destroy(&current->condition);
- next = current->next;
- free(current);
- }
- }
-
- /* Free sub-condition if any */
- if (c->subcondition)
- {
- condition_destroy(&c->subcondition);
- }
-
- /* Free name if any */
- if (c->name)
- {
- free(c->name);
- c->name = NULL;
- }
-
- /* Free inscription if any */
- if (c->inscription)
- {
- free(c->inscription);
- c->inscription = NULL;
- }
-
- /* Free subrace if any */
- if (c->subrace)
- {
- free(c->subrace);
- c->subrace = NULL;
- }
-
- /* Free race if any */
- if (c->race)
- {
- free(c->race);
- c->race = NULL;
- }
-
- /* Free class if any */
- if (c->klass)
- {
- free(c->klass);
- c->klass = NULL;
- }
-
- /* Free comment if any */
- if (c->comment)
- {
- free(c->comment);
- c->comment = NULL;
- }
-
- /* Free the condition itself */
- free(*cp);
- *cp = NULL;
-}
-
-static bool_ condition_eval(condition_type *c, object_type *o_ptr)
-{
- bool_ is_and = (c->match == M_AND);
- bool_ is_or = (c->match == M_OR);
-
- switch (c->match)
- {
- case M_AND:
- case M_OR:
- {
- struct sglib_condition_list_iterator it;
- struct condition_list *child = NULL;
-
- for (child = sglib_condition_list_it_init(&it, c->conditions.c);
- child != NULL;
- child = sglib_condition_list_it_next(&it))
- {
- if (is_and && (!condition_eval(child->condition, o_ptr)))
- {
- return FALSE;
- }
-
- if (is_or && condition_eval(child->condition, o_ptr))
- {
- return TRUE;
- }
- }
-
- if (is_and)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
-
- case M_NOT:
- {
- if (c->subcondition == NULL)
- {
- return TRUE;
- }
-
- return !condition_eval(c->subcondition, o_ptr);
- }
-
- case M_INVENTORY:
- {
- int i;
-
- if (c->subcondition == NULL)
- {
- return FALSE;
- }
-
- for (i = 0; i < INVEN_WIELD; i++)
- {
- if (condition_eval(c->subcondition, &p_ptr->inventory[i]))
- {
- return TRUE;
- }
- }
-
- return FALSE;
- }
-
- case M_EQUIPMENT:
- {
- int i;
-
- if (c->subcondition == NULL)
- {
- return FALSE;
- }
-
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
- {
- if (condition_eval(c->subcondition, &p_ptr->inventory[i]))
- {
- return TRUE;
- }
- }
-
- return FALSE;
- }
-
- case M_NAME:
- {
- char buf1[128];
- char buf2[128];
-
- object_desc(buf1, o_ptr, -1, 0);
- strlower(buf1);
-
- sprintf(buf2, "%s", c->name);
- strlower(buf2);
-
- return streq(buf1, buf2);
- }
-
- case M_CONTAIN:
- {
- char buf1[128];
- char buf2[128];
-
- object_desc(buf1, o_ptr, -1, 0);
- strlower(buf1);
-
- sprintf(buf2, "%s", c->name);
- strlower(buf2);
-
- return (strstr(buf1, buf2) != NULL);
- }
-
- case M_SYMBOL:
- {
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
-
- return k_ptr->d_char == c->symbol;
- }
-
- case M_INSCRIBED:
- {
- char buf1[128];
- char buf2[128];
-
- if (o_ptr->note == 0)
- {
- return FALSE;
- }
-
- sprintf(buf1, "%s", quark_str(o_ptr->note));
- strlower(buf1);
-
- sprintf(buf2, "%s", c->inscription);
- strlower(buf2);
-
- return (strstr(buf1, buf2) != NULL);
- }
-
- case M_DISCOUNT:
- {
- return (object_aware_p(o_ptr) &&
- (o_ptr->discount >= c->discount.min) &&
- (o_ptr->discount <= c->discount.max));
- }
-
- case M_TVAL:
- {
- return (o_ptr->tval == c->tval);
- }
-
- case M_SVAL:
- {
- return (object_aware_p(o_ptr) &&
- (o_ptr->sval >= c->sval_range.min) &&
- (o_ptr->sval <= c->sval_range.max));
- }
-
- case M_STATUS:
- {
- return c->status == object_status(o_ptr);
- }
-
- case M_STATE:
- {
- switch (c->identification_state)
- {
- case IDENTIFIED:
- return object_known_p(o_ptr);
- case NOT_IDENTIFIED:
- return !object_known_p(o_ptr);
- default:
- assert(FALSE);
- }
- }
-
- case M_RACE:
- {
- char buf1[128];
- char buf2[128];
-
- sprintf(buf1, "%s", rp_ptr->title + rp_name);
- strlower(buf1);
-
- sprintf(buf2, "%s", c->race);
- strlower(buf2);
-
- return streq(buf1, buf2);
- }
-
- case M_SUBRACE:
- {
- char buf1[128];
- char buf2[128];
-
- sprintf(buf1, "%s", rmp_ptr->title + rmp_name);
- strlower(buf1);
-
- sprintf(buf2, "%s", c->subrace);
- strlower(buf2);
-
- return streq(buf1, buf2);
- }
-
- case M_CLASS:
- {
- char buf1[128];
- char buf2[128];
-
- sprintf(buf1, "%s", spp_ptr->title + c_name);
- strlower(buf1);
-
- sprintf(buf2, "%s", c->klass);
- strlower(buf2);
-
- return streq(buf1, buf2);
- }
-
- case M_LEVEL:
- {
- return ((p_ptr->lev >= c->level_range.min) &&
- (p_ptr->lev <= c->level_range.max));
- }
-
- case M_SKILL:
- {
- s16b sk = get_skill(c->skill_range.skill_idx);
- return ((sk >= c->skill_range.min) &&
- (sk <= c->skill_range.max));
- }
-
- case M_ABILITY:
- {
- return has_ability(c->ability);
- }
-
- }
-
- /* Don't match by default */
- return FALSE;
-}
-
-static json_t *condition_to_json(condition_type *c)
-{
- json_t *json = NULL;
-
- if (c == NULL)
- {
- return json_null();
- }
-
- json = json_object();
- json_object_set_new(json, "type",
- json_string(match_type_to_string(c->match)));
-
- switch (c->match)
- {
- case M_AND:
- case M_OR:
- {
- struct sglib_condition_list_iterator it;
- struct condition_list *child = NULL;
-
- json_t *conditions_json = json_array();
-
- for (child = sglib_condition_list_it_init(&it, c->conditions.c);
- child != NULL;
- child = sglib_condition_list_it_next(&it))
- {
- json_array_append_new(conditions_json,
- condition_to_json(child->condition));
- }
-
- json_object_set_new(json, "conditions", conditions_json);
- break;
- }
-
- case M_NOT:
- case M_INVENTORY:
- case M_EQUIPMENT:
- {
- json_object_set_new(json, "condition",
- condition_to_json(c->subcondition));
- break;
- }
-
- case M_NAME:
- {
- json_object_set_new(json, "name",
- json_string(c->name));
- break;
- }
-
- case M_CONTAIN:
- {
- json_object_set_new(json, "contain",
- json_string(c->name));
- break;
- }
-
- case M_SYMBOL:
- {
- json_object_set_new(json, "symbol",
- json_string(format("%c", c->symbol)));
- break;
- }
-
- case M_INSCRIBED:
- {
- json_object_set_new(json, "inscription",
- json_string(c->inscription));
- break;
- }
-
- case M_DISCOUNT:
- {
- json_object_set_new(json, "min",
- json_integer(c->discount.min));
- json_object_set_new(json, "max",
- json_integer(c->discount.max));
- break;
- }
-
- case M_TVAL:
- {
- json_object_set_new(json, "tval",
- json_integer(c->tval));
- break;
- }
-
- case M_SVAL:
- {
- json_object_set_new(json, "min",
- json_integer(c->sval_range.min));
- json_object_set_new(json, "max",
- json_integer(c->sval_range.max));
- break;
- }
-
- case M_STATUS:
- {
- json_object_set_new(json, "status",
- json_string(status_to_string(c->status)));
- break;
- }
-
- case M_STATE:
- {
- json_object_set_new(json, "state",
- json_string(identification_state_to_string(c->identification_state)));
- break;
- }
-
- case M_RACE:
- {
- json_object_set_new(json, "race",
- json_string(c->race));
- break;
- }
-
- case M_SUBRACE:
- {
- json_object_set_new(json, "subrace",
- json_string(c->subrace));
- break;
- }
-
- case M_CLASS:
- {
- json_object_set_new(json, "class",
- json_string(c->klass));
- break;
- }
-
- case M_LEVEL:
- {
- json_object_set_new(json, "min",
- json_integer(c->level_range.min));
- json_object_set_new(json, "max",
- json_integer(c->level_range.max));
- break;
- }
-
- case M_SKILL:
- {
- json_object_set_new(json, "name",
- json_string(s_info[c->skill_range.skill_idx].name + s_name));
- json_object_set_new(json, "min",
- json_integer(c->skill_range.min));
- json_object_set_new(json, "max",
- json_integer(c->skill_range.max));
- break;
- }
-
- case M_ABILITY:
- {
- json_object_set_new(json, "ability",
- json_string(ab_info[c->ability].name + ab_name));
- break;
- }
-
- }
-
- return json;
-}
-
-/*
- * Cursor to maintain position in condition tree
- */
-static condition_type *cursor_stack[STACK_MAX];
-static int cursor_count = 0;
-
-static void cursor_push(condition_type *condition)
-{
- assert(cursor_count < STACK_MAX);
-
- cursor_stack[cursor_count] = condition;
- cursor_count++;
-}
-
-static condition_type *cursor_pop()
-{
- condition_type *c = NULL;
-
- assert(cursor_count > 0);
-
- c = cursor_stack[cursor_count-1];
- cursor_stack[cursor_count] = NULL;
- cursor_count--;
- return c;
-}
-
-static condition_type *cursor_top()
-{
- assert(cursor_count > 0);
-
- return cursor_stack[cursor_count - 1];
-}
-
-static void cursor_clear()
-{
- while (cursor_count > 0)
- {
- cursor_pop();
- }
-}
-
-/* Rule */
-typedef struct arule_type arule_type;
-struct arule_type {
- /* Rule name */
- char *name;
- /* Which action do we take? */
- action_type action; /* Which action to take */
- /* Which module does this rule apply to? */
- int module_idx;
- /* Inscription to use for inscription rules. */
- char *inscription;
- /* Condition. */
- condition_type *condition; /* Condition for rule match */
-};
-
-/* Initialize a rule */
-static arule_type *rule_new(cptr name, action_type action, int module_idx, condition_type *condition, cptr inscription)
-{
- arule_type *rp = malloc(sizeof(arule_type));
- rp->name = strdup(name);
- rp->action = action;
- rp->module_idx = module_idx;
- rp->condition = condition;
- rp->inscription = (inscription == NULL) ? NULL : strdup(inscription);
- return rp;
-}
-
-static void rule_set_name(arule_type *rule, cptr new_name)
-{
- if (rule->name)
- {
- free(rule->name);
- }
-
- rule->name = strdup(new_name);
-}
-
-static void rule_destroy(arule_type **rp)
-{
- if ((*rp)->name)
- {
- free((*rp)->name);
- }
-
- if ((*rp)->inscription)
- {
- free((*rp)->inscription);
- }
-
- if ((*rp)->condition)
- {
- condition_destroy(&(*rp)->condition);
- }
-
- free(*rp);
- *rp = NULL;
-}
-
-/* Current list of rules. */
-static arule_type *rules[RULES_MAX];
-static int rules_count = 0; /* Number of rules currently in list */
-
-static int rules_append(arule_type *rule)
-{
- assert(rules_count < RULES_MAX);
-
- rules[rules_count] = rule;
- rules_count++;
- return rules_count-1;
-}
-
-static void rules_remove(arule_type *rule)
-{
- int i, j;
-
- for (i = 0; i < rules_count; i++)
- {
- if (rules[i] == rule)
- {
- /* Free the rule */
- rule_destroy(&rule);
- /* Move rest of rest "up" */
- for (j = i+1; j < rules_count; j++)
- {
- rules[j-1] = rules[j];
- }
- /* We're done */
- rules_count--;
- return;
- }
- }
-}
-
-static void rules_swap(int i, int j)
-{
- arule_type *tmp_rptr = NULL;
-
- assert(i >= 0);
- assert(i < rules_count);
-
- assert(j >= 0);
- assert(j < rules_count);
-
- tmp_rptr = rules[i];
- rules[i] = rules[j];
- rules[j] = tmp_rptr;
-}
-
-static bool_* automatizer_auto_destroy(object_type *o_ptr, int item_idx)
-{
- static bool_ TRUE_VAL = TRUE;
-
- /* Must be identified */
- if (object_aware_p(o_ptr) == FALSE)
- {
- return NULL;
- }
-
- /* Inscribed things won't be destroyed! */
- if (o_ptr->note)
- {
- return NULL;
- }
-
- /* Ignore artifacts; cannot be destroyed anyway. */
- if (artifact_p(o_ptr))
- {
- return NULL;
- }
-
- /* Cannot destroy CURSE_NO_DROP objects. */
- {
- u32b f1, f2, f3, f4, f5, esp;
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if ((f4 & TR4_CURSE_NO_DROP) != 0)
- {
- return NULL;
- }
- }
-
- /* Destroy! */
- msg_print("<Auto-destroy>");
-
- inc_stack_size(item_idx, -o_ptr->number);
- return &TRUE_VAL;
-}
-
-static bool_* automatizer_auto_pickup(object_type *o_ptr, int item_idx)
-{
- static bool_ TRUE_VAL = TRUE;
-
- if (item_idx >= 0)
- {
- return NULL;
- }
-
- if (!inven_carry_okay(o_ptr))
- {
- return NULL;
- }
-
- msg_print("<Auto-pickup>");
-
- object_pickup(-item_idx);
- return &TRUE_VAL;
-}
-
-/* Apply rules */
-static bool_ apply_rule(arule_type *rule, object_type *o_ptr, int item_idx)
-{
- /* Check module */
- if (rule->module_idx != game_module_idx)
- {
- return FALSE;
- }
-
- /* Check condition */
- assert (rule->condition != NULL);
- if (condition_eval(rule->condition, o_ptr))
- {
- switch (rule->action)
- {
-
- case AUTO_DESTROY:
- {
- if (automatizer_auto_destroy(o_ptr, item_idx) == NULL)
- return FALSE;
- break;
- }
-
- case AUTO_PICKUP:
- {
- if (automatizer_auto_pickup(o_ptr, item_idx) == NULL)
- return FALSE;
- break;
- }
-
- case AUTO_INSCRIBE:
- {
- /* Already inscribed? */
- if (o_ptr->note != 0)
- {
- return FALSE;
- }
-
- /* Inscribe */
- msg_format("<Auto-Inscribe {%s}>", rule->inscription);
- o_ptr->note = quark_add(rule->inscription);
- break;
- }
-
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static bool_ apply_rules(object_type *o_ptr, int item_idx)
-{
- int i;
-
- for (i = 0; i < rules_count; i++)
- {
- if (apply_rule(rules[i], o_ptr, item_idx))
- {
- return TRUE;
- }
- }
-
- /* Don't keep trying */
- return FALSE;
-}
-
-static json_t *rule_to_json(arule_type *rule)
-{
- json_t *rule_json = json_object();
-
- json_object_set_new(rule_json,
- "name",
- json_string(rule->name));
- json_object_set_new(rule_json,
- "action",
- json_string(action_to_string(rule->action)));
- json_object_set_new(rule_json,
- "module",
- json_string(modules[rule->module_idx].meta.name));
-
- if (rule->inscription)
- {
- json_object_set_new(rule_json,
- "inscription",
- json_string(rule->inscription));
- }
-
- json_object_set_new(rule_json,
- "condition",
- condition_to_json(rule->condition));
-
- return rule_json;
-}
-
-static json_t *rules_to_json()
-{
- int i;
- json_t *rules_json = json_array();
-
- for (i = 0; i < rules_count; i++)
- {
- json_array_append_new(rules_json, rule_to_json(rules[i]));
- }
-
- return rules_json;
-}
-
-/* Check the floor for "crap" */
-void squeltch_grid(void)
-{
- s16b this_o_idx, next_o_idx = 0;
-
- if (!automatizer_enabled) return;
-
- /* Scan the pile of objects */
- for (this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; this_o_idx; this_o_idx = next_o_idx)
- {
- /* Acquire object */
- object_type * o_ptr = &o_list[this_o_idx];
-
- /* We've now seen one of these */
- if (!k_info[o_ptr->k_idx].flavor)
- {
- object_aware(o_ptr);
- }
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Apply rules */
- apply_rules(o_ptr, -this_o_idx);
- }
-}
-
-
-/* Check the inventory for "crap" */
-void squeltch_inventory(void)
-{
- int i;
- int num_iter = 0;
- bool_ found = TRUE;
-
- if (!automatizer_enabled) return;
-
- while (found && num_iter ++ < 100)
- {
- /* Sometimes an index in the inventory is skipped */
- found = FALSE;
-
- for (i = 0; i < INVEN_PACK; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
-
- if (apply_rules(o_ptr, i))
- {
- found = TRUE;
- break;
- }
- }
- }
- if (num_iter >= 100)
- {
- cmsg_format(TERM_VIOLET, "'apply_rules' ran too often.");
- }
-}
-
-/********************** The interface **********************/
-static void get_rule_names(cptr *list)
-{
- int i;
-
- for (i = 0; i < rules_count; i++)
- {
- list[i] = rules[i]->name;
- }
-}
-
-typedef struct condition_metadata condition_metadata;
-struct condition_metadata {
- match_type match;
- cptr description[3];
- condition_type *(*create_condition)();
-};
-
-#define TYPES_LIST_SIZE 21
-
-static condition_type *create_condition_name()
-{
- cptr s = lua_input_box("Object name to match?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- return condition_new_name(s);
-}
-
-static condition_type *create_condition_contain()
-{
- cptr s = lua_input_box("Word to find in object name?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- return condition_new_contain(s);
-}
-
-static condition_type *create_condition_inscribed()
-{
- cptr s = lua_input_box("Word to find in object inscription?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- return condition_new_inscribed(s);
-}
-
-static condition_type *create_condition_discount()
-{
- int min, max;
-
- {
- cptr s = lua_input_box("Min discount?", 79);
- if (sscanf(s, "%d", &min) < 1)
- {
- return NULL;
- }
- }
-
- {
- cptr s = lua_input_box("Max discount?", 79);
- if (sscanf(s, "%d", &max) < 1)
- {
- return NULL;
- }
- }
-
- return condition_new_discount(min, max);
-}
-
-static condition_type *create_condition_symbol()
-{
- char c;
- cptr s = lua_input_box("Symbol to match?", 1);
- if (sscanf(s, "%c", &c) < 1)
- {
- return NULL;
- }
-
- return condition_new_symbol(c);
-}
-
-static condition_type *create_condition_status()
-{
- status_type status;
- char c;
-
- c = lua_msg_box("[t]errible, [v]ery bad, [b]ad, "
- "[a]verage, [G]ood, [V]ery good, [S]pecial?");
-
- switch (c)
- {
- case 't': status = TERRIBLE; break;
- case 'v': status = VERY_BAD; break;
- case 'b': status = BAD; break;
- case 'a': status = AVERAGE; break;
- case 'G': status = GOOD; break;
- case 'V': status = VERY_GOOD; break;
- case 'S': status = SPECIAL; break;
- default: return NULL;
- }
-
- return condition_new_status(status);
-}
-
-static condition_type *create_condition_state()
-{
- identification_state s;
- char c;
-
- c = lua_msg_box("[i]dentified, [n]on identified?");
-
- switch (c)
- {
- case 'i': s = IDENTIFIED; break;
- case 'n': s = NOT_IDENTIFIED; break;
- default: return NULL;
- }
-
- return condition_new_state(s);
-}
-
-static condition_type *create_condition_tval()
-{
- int tval;
- cptr s = lua_input_box("Tval to match?", 79);
- if (sscanf(s, "%d", &tval) < 1)
- {
- return NULL;
- }
-
- return condition_new_tval(tval);
-}
-
-static condition_type *create_condition_sval()
-{
- int sval_min, sval_max;
-
- {
- cptr s = lua_input_box("Min sval?", 79);
- if (sscanf(s, "%d", &sval_min) < 1)
- {
- return NULL;
- }
- }
-
- {
- cptr s = lua_input_box("Max sval?", 79);
- if (sscanf(s, "%d", &sval_max) < 1)
- {
- return NULL;
- }
- }
-
- return condition_new_sval(sval_min, sval_max);
-}
-
-static condition_type *create_condition_race()
-{
- cptr s = lua_input_box("Player race to match?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- return condition_new_race(s);
-}
-
-static condition_type *create_condition_subrace()
-{
- cptr s = lua_input_box("Player subrace to match?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- return condition_new_subrace(s);
-}
-
-static condition_type *create_condition_class()
-{
- cptr s = lua_input_box("Player class to match?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- return condition_new_class(s);
-}
-
-static condition_type *create_condition_level()
-{
- int min, max;
-
- {
- cptr s = lua_input_box("Min player level?", 79);
- if (sscanf(s, "%d", &min) < 1)
- {
- return NULL;
- }
- }
-
- {
- cptr s = lua_input_box("Max player level?", 79);
- if (sscanf(s, "%d", &max) < 1)
- {
- return NULL;
- }
- }
-
- return condition_new_level(min, max);
-}
-
-static condition_type *create_condition_skill()
-{
- int min, max;
- s16b skill_idx;
-
- {
- cptr s = lua_input_box("Min skill level?", 79);
- if (sscanf(s, "%d", &min) < 1)
- {
- return NULL;
- }
- }
-
- {
- cptr s = lua_input_box("Max skill level?", 79);
- if (sscanf(s, "%d", &max) < 1)
- {
- return NULL;
- }
- }
-
- {
- cptr s = lua_input_box("Skill name?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- skill_idx = find_skill_i(s);
- if (skill_idx < 0)
- {
- return NULL;
- }
- }
-
- return condition_new_skill(min, max, skill_idx);
-}
-
-static condition_type *create_condition_ability()
-{
- s16b ai;
- cptr s = lua_input_box("Ability name?", 79);
- if (strlen(s) == 0)
- {
- return NULL;
- }
-
- ai = find_ability(s);
- if (ai < 0)
- {
- return NULL;
- }
-
- return condition_new_ability(ai);
-}
-
-static condition_metadata types_list[TYPES_LIST_SIZE] =
-{
- { M_AND,
- { "Check is true if all rules within it are true",
- NULL },
- condition_new_and,
- },
- { M_OR,
- { "Check is true if at least one rule within it is true",
- NULL },
- condition_new_or,
- },
- { M_NOT,
- { "Invert the result of its child rule",
- NULL },
- condition_new_not,
- },
- { M_NAME,
- { "Check is true if object name matches name",
- NULL },
- create_condition_name,
- },
- { M_CONTAIN,
- { "Check is true if object name contains word",
- NULL },
- create_condition_contain,
- },
- { M_INSCRIBED,
- { "Check is true if object inscription contains word",
- NULL },
- create_condition_inscribed,
- },
- { M_DISCOUNT,
- { "Check is true if object discount is between two values",
- NULL },
- create_condition_discount,
- },
- { M_SYMBOL,
- { "Check is true if object symbol is ok",
- NULL },
- create_condition_symbol,
- },
- { M_STATE,
- { "Check is true if object is identified/unidentified",
- NULL },
- create_condition_state,
- },
- { M_STATUS,
- { "Check is true if object status is ok",
- NULL },
- create_condition_status,
- },
- { M_TVAL,
- { "Check is true if object tval(from k_info.txt) is ok",
- NULL },
- create_condition_tval,
- },
- { M_SVAL,
- { "Check is true if object sval(from k_info.txt) is between",
- "two values",
- NULL },
- create_condition_sval,
- },
- { M_RACE,
- { "Check is true if player race is ok",
- NULL },
- create_condition_race,
- },
- { M_SUBRACE,
- { "Check is true if player subrace is ok",
- NULL },
- create_condition_subrace,
- },
- { M_CLASS,
- { "Check is true if player class is ok",
- NULL },
- create_condition_class,
- },
- { M_LEVEL,
- { "Check is true if player level is between 2 values",
- NULL },
- create_condition_level,
- },
- { M_SKILL,
- { "Check is true if player skill level is between 2 values",
- NULL },
- create_condition_skill,
- },
- { M_ABILITY,
- { "Check is true if player has the ability",
- NULL },
- create_condition_ability,
- },
- { M_INVENTORY,
- { "Check is true if something in player's inventory matches",
- "the contained rule",
- NULL },
- condition_new_inventory,
- },
- { M_EQUIPMENT,
- { "Check is true if something in player's equipment matches",
- "the contained rule",
- NULL },
- condition_new_equipment,
- },
-};
-
-static void display_desc(condition_metadata *condition_metadata)
-{
- int i;
-
- assert(condition_metadata != NULL);
-
- for (i = 0; condition_metadata->description[i] != NULL; i++)
- {
- c_prt(TERM_WHITE, condition_metadata->description[i], i + 1, 17);
- }
-}
-
-/* Create a new rule */
-static condition_metadata *automatizer_select_condition_type()
-{
- int wid, hgt, max = TYPES_LIST_SIZE, begin = 0, sel = 0, i;
- char c;
- cptr types_names[TYPES_LIST_SIZE];
-
- /* Create list of names for display */
- for (i = 0; i < TYPES_LIST_SIZE; i++)
- {
- types_names[i] = match_type_to_string(types_list[i].match);
- }
-
- while (1)
- {
- Term_clear();
- Term_get_size(&wid, &hgt);
-
- display_list(0, 0, hgt - 1, 15, "Rule types", types_names, max, begin, sel, TERM_L_GREEN);
-
- display_desc(&types_list[sel]);
-
- c = inkey();
-
- if (c == ESCAPE) break;
- else if (c == '8')
- {
- sel--;
- if (sel < 0)
- {
- sel = max - 1;
- begin = max - hgt;
- if (begin < 0) begin = 0;
- }
- if (sel < begin) begin = sel;
- }
- else if (c == '2')
- {
- sel++;
- if (sel >= max)
- {
- sel = 0;
- begin = 0;
- }
- if (sel >= begin + hgt - 1) begin++;
- }
- else if (c == '\r')
- {
- return &types_list[sel];
- }
- }
- return NULL;
-}
-
-static void adjust_begin(int *begin, int *sel, int max, int hgt)
-{
- if (*sel < 0)
- {
- *sel = max - 1;
- *begin = *sel - hgt + 3;
- if (*begin < 0) *begin = 0;
- }
- if (*sel < *begin) *begin = *sel;
-
- if (*sel >= max)
- {
- *sel = 0;
- *begin = 0;
- }
- if (*sel >= *begin + hgt - 2) (*begin)++;
-}
-
-static int create_new_rule()
-{
- action_type action;
- char name[20] = { '\0' };
- char *inscription = NULL;
- int wid = 0, hgt = 0;
- char typ;
- arule_type *rule = NULL;
-
- Term_get_size(&wid, &hgt);
-
- sprintf(name, "%s", "No name");
- if (!input_box("Name?", hgt / 2, wid / 2, name, sizeof(name)))
- {
- return -1;
- }
-
- typ = lua_msg_box("[D]estroy, [P]ickup, [I]nscribe?");
-
- switch (typ)
- {
- case 'd':
- case 'D':
- action = AUTO_DESTROY;
- break;
-
- case 'p':
- case 'P':
- action = AUTO_PICKUP;
- break;
-
- case 'i':
- case 'I':
- {
- char *i = NULL;
-
- action = AUTO_INSCRIBE;
-
- i = lua_input_box("Inscription?", 79);
- if ((i == NULL) || (strlen(i) == 0))
- {
- return -1;
- }
-
- inscription = i;
-
- break;
- }
-
- default:
- return -1;
- }
-
- /* Make rule */
- rule = rule_new(name, action, game_module_idx, NULL, inscription);
-
- /* Append to list of rules */
- return rules_append(rule);
-}
-
-static void add_child(condition_type *current)
-{
- condition_metadata *metadata = NULL;
-
- switch (current->match)
- {
- case M_NOT:
- case M_EQUIPMENT:
- case M_INVENTORY:
- {
- if (current->subcondition != NULL)
- {
- return;
- }
-
- metadata = automatizer_select_condition_type();
- if (metadata == NULL)
- {
- return;
- }
-
- current->subcondition = metadata->create_condition();
- break;
- }
-
- case M_AND:
- metadata = automatizer_select_condition_type();
- if (metadata == NULL)
- {
- return;
- }
- condition_and_add(current, metadata->create_condition());
- break;
-
- case M_OR:
- metadata = automatizer_select_condition_type();
- if (metadata == NULL)
- {
- return;
- }
- condition_or_add(current, metadata->create_condition());
- break;
-
- default:
- /* No other types of conditions have children */
- break;
- }
-}
-
-static int tree_indent = 0;
-static int tree_write_out_y = 0;
-static int tree_write_out_x = 0;
-static int tree_write_out_h = 0;
-static int tree_write_out_w = 0;
-static int tree_write_y = 0;
-static int tree_write_x = 0;
-static int tree_write_off_x = 0;
-static int tree_write_off_y = 0;
-
-static void tree_write(byte color, cptr line)
-{
- cptr p = line;
-
- for (p = line; *p != '\0'; p++)
- {
- char c = *p;
- int x = tree_write_x - tree_write_off_x + 3*tree_indent;
- int y = tree_write_y - tree_write_off_y;
-
- if (c != '\n')
- {
- if ((y >= 0) &&
- (y < tree_write_out_h) &&
- (x >= 0) &&
- (x < tree_write_out_w))
- {
- Term_putch(x + tree_write_out_x,
- y + tree_write_out_y,
- color,
- c);
- }
-
- tree_write_x += 1;
- }
- else
- {
- tree_write_x = 0;
- tree_write_y += 1;
- }
- }
-}
-
-static void display_condition(condition_type *condition)
-{
- byte bcol = TERM_L_GREEN;
- byte ecol = TERM_GREEN;
- int i;
-
- assert(condition != NULL);
-
- /* If this condition is present in the cursor stack,
- then we use the "active" colors. */
- for (i = 0; i < cursor_count; i++)
- {
- if (cursor_stack[i] == condition)
- {
- bcol = TERM_VIOLET;
- ecol = TERM_VIOLET;
- break;
- }
- }
-
- tree_indent++;
-
- switch (condition->match)
- {
- case M_INVENTORY:
- case M_EQUIPMENT:
- {
- cptr where_s = (condition->match == M_INVENTORY)
- ? "inventory"
- : "equipment";
-
- tree_write(ecol, "Something in your ");
- tree_write(bcol, where_s);
- tree_write(ecol, " matches the following:");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_SKILL:
- {
- cptr skill_name =
- s_info[condition->skill_range.skill_idx].name + s_name;
-
- tree_write(ecol, "Your skill in ");
- tree_write(bcol, skill_name);
- tree_write(ecol, " is from ");
- tree_write(TERM_WHITE, format("%d", (int) condition->skill_range.min));
- tree_write(ecol, " to ");
- tree_write(TERM_WHITE, format("%d", (int) condition->skill_range.max));
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_ABILITY:
- {
- cptr ability_name =
- ab_info[condition->ability].name + ab_name;
-
- tree_write(ecol, "You have the ");
- tree_write(bcol, ability_name);
- tree_write(ecol, " ability");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_LEVEL:
- {
- tree_write(ecol, "Your ");
- tree_write(bcol, "level");
- tree_write(ecol, " is from ");
-
- tree_write(TERM_WHITE, format("%d", condition->level_range.min));
- tree_write(ecol, " to ");
- tree_write(TERM_WHITE, format("%d", condition->level_range.max));
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_SVAL:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "sval");
- tree_write(ecol, " is from ");
- tree_write(TERM_WHITE, format("%d", condition->sval_range.min));
- tree_write(ecol, " to ");
- tree_write(TERM_WHITE, format("%d", condition->sval_range.max));
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_DISCOUNT:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "discount");
- tree_write(ecol, " is from ");
- tree_write(TERM_WHITE, format("%d", condition->discount.min));
- tree_write(ecol, " to ");
- tree_write(TERM_WHITE, format("%d", condition->discount.max));
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_AND:
- {
- struct sglib_condition_list_iterator it;
- struct condition_list *child = NULL;
-
- tree_write(ecol, "All of the following are true:");
- tree_write(TERM_WHITE, "\n");
-
- for (child = sglib_condition_list_it_init(&it, condition->conditions.c);
- child != NULL;
- child = sglib_condition_list_it_next(&it))
- {
- display_condition(child->condition);
- }
-
- break;
- }
-
- case M_OR:
- {
- struct sglib_condition_list_iterator it;
- struct condition_list *child = NULL;
-
- tree_write(ecol, "At least one of the following are true:");
- tree_write(TERM_WHITE, "\n");
-
- for (child = sglib_condition_list_it_init(&it, condition->conditions.c);
- child != NULL;
- child = sglib_condition_list_it_next(&it))
- {
- display_condition(child->condition);
- }
-
- break;
- }
-
- case M_NOT:
- {
- tree_write(ecol, "Negate the following:");
- tree_write(TERM_WHITE, "\n");
- if (condition->subcondition != NULL)
- {
- display_condition(condition->subcondition);
- }
- break;
- }
-
- case M_NAME:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "name");
- tree_write(ecol, " is \"");
- tree_write(TERM_WHITE, condition->name);
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_CONTAIN:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "name");
- tree_write(ecol, " contains \"");
- tree_write(TERM_WHITE, condition->name);
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_INSCRIBED:
- {
- tree_write(ecol, "It is ");
- tree_write(bcol, "inscribed");
- tree_write(ecol, " with ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, condition->inscription);
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_SYMBOL:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "symbol");
- tree_write(ecol, " is ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, format("%c", condition->symbol));
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_STATE:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "state");
- tree_write(ecol, " is ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, identification_state_to_string(condition->identification_state));
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_STATUS:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "status");
- tree_write(ecol, " is ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, status_to_string(condition->status));
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_TVAL:
- {
- tree_write(ecol, "Its ");
- tree_write(bcol, "tval");
- tree_write(ecol, " is ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, format("%d", condition->tval));
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_RACE:
- {
- tree_write(ecol, "Player ");
- tree_write(bcol, "race");
- tree_write(ecol, " is ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, condition->race);
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_SUBRACE:
- {
- tree_write(ecol, "Player ");
- tree_write(bcol, "subrace");
- tree_write(ecol, " is ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, condition->subrace);
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case M_CLASS:
- {
- tree_write(ecol, "Player ");
- tree_write(bcol, "class");
- tree_write(ecol, " is ");
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, condition->klass);
- tree_write(ecol, "\"");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- }
-
- tree_indent--;
-}
-
-static void display_rule(arule_type *rule)
-{
- cptr action_s;
- int hgt, wid;
-
- action_s = action_to_string(rule->action);
-
- Term_get_size(&wid, &hgt);
-
- tree_write_out_y = 1;
- tree_write_out_x = 16;
- tree_write_out_h = hgt - 4 - 1;
- tree_write_out_w = wid - 1 - 15 - 1;
- tree_write_y = 0;
- tree_write_x = 0;
-
- switch (rule->action)
- {
- case AUTO_DESTROY:
- case AUTO_PICKUP:
- {
- tree_write(TERM_GREEN, "A rule named \"");
- tree_write(TERM_WHITE, rule->name);
- tree_write(TERM_GREEN, "\" to ");
- tree_write(TERM_L_GREEN, action_s);
- tree_write(TERM_GREEN, " when");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- case AUTO_INSCRIBE:
- {
- tree_write(TERM_GREEN, "A rule named \"");
- tree_write(TERM_WHITE, rule->name);
- tree_write(TERM_GREEN, "\" to ");
- tree_write(TERM_L_GREEN, "inscribe");
- tree_write(TERM_GREEN, " an item with \"");
- tree_write(TERM_WHITE, rule->inscription);
- tree_write(TERM_GREEN, "\" when");
- tree_write(TERM_WHITE, "\n");
- break;
- }
-
- }
-
- /* Write out the condition */
- if (rule->condition != NULL)
- {
- display_condition(rule->condition);
- }
-}
-
-static void adjust_current(int sel)
-{
- if (rules_count == 0)
- {
- cursor_clear();
- return;
- }
-
- tree_write_off_y = 0;
- tree_write_off_x = 0;
-
- /* Put the top-level condition into cursor */
- cursor_clear();
- if (rules[sel]->condition != NULL)
- {
- cursor_push(rules[sel]->condition);
- }
-}
-
-static void tree_scroll_up()
-{
- tree_write_off_y = tree_write_off_y - 1;
-}
-
-static void tree_scroll_down()
-{
- tree_write_off_y = tree_write_off_y + 1;
-}
-
-static void tree_scroll_left()
-{
- tree_write_off_x = tree_write_off_x + 1;
-}
-
-static void tree_scroll_right()
-{
- tree_write_off_x = tree_write_off_x - 1;
-}
-
-static void automatizer_save_rules()
-{
- char name[30] = { '\0' };
- char buf[1025];
- char ch;
- int hgt, wid;
-
- Term_get_size(&wid, &hgt);
-
- sprintf(name, "automat.atm");
- if (!input_box("Save name?", hgt / 2, wid / 2, name, sizeof(name)))
- {
- return;
- }
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_USER, name);
-
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
- if (file_exist(buf))
- {
- c_put_str(TERM_WHITE, "File exists, continue?[y/n]",
- hgt / 2,
- wid / 2 - 14);
- ch = inkey();
- if ((ch != 'Y') && (ch != 'y'))
- {
- return;
- }
- }
-
- /* Write to file */
- {
- json_t *rules_json = rules_to_json();
- int status = json_dump_file(rules_json, buf, JSON_INDENT(2) | JSON_SORT_KEYS);
- if (status == 0)
- {
- c_put_str(TERM_WHITE, "Saved rules in file ",
- hgt / 2,
- wid / 2 - 14);
- }
- else
- {
- c_put_str(TERM_WHITE, "Saving rules failed! ",
- hgt / 2,
- wid / 2 - 14);
- }
-
- /* Deallocate JSON */
- json_decref(rules_json);
-
- /* Wait for keypress */
- inkey();
- }
-}
-
-static void rename_rule(arule_type *rule)
-{
- char name[16];
- int wid, hgt;
-
- assert(rule != NULL);
-
- Term_get_size(&wid, &hgt);
-
- sprintf(name, "%s", rule->name);
- if (input_box("New name?", hgt / 2, wid / 2, name, sizeof(name)))
- {
- rule_set_name(rule, name);
- }
-}
-
-static void add_new_condition(arule_type *current_rule)
-{
- /* Top-level condition? */
- if (current_rule->condition == NULL)
- {
- condition_metadata *metadata = NULL;
-
- /* Sanity check for navigation stack */
- assert(cursor_count == 0);
-
- /* Select type of clause */
- metadata = automatizer_select_condition_type();
- if (metadata == NULL)
- {
- return;
- }
-
- /* Create the condition directly; we can
- always add a top-level condition so there's
- no need for the sanity checking in
- add_child(). */
- current_rule->condition = metadata->create_condition();
- if (current_rule->condition != NULL)
- {
- cursor_push(current_rule->condition);
- }
- }
- else
- {
- condition_type *current_condition = cursor_top();
- add_child(current_condition);
- }
-}
-
-static void tree_go_right()
-{
- condition_type *top = cursor_top();
-
- /* Can only go right if the currently selected condition
- has children. */
- switch (top->match)
- {
- case M_AND:
- case M_OR:
- {
- /* Pick first child */
- struct sglib_condition_list_iterator it;
- condition_list *i = sglib_condition_list_it_init(&it, top->conditions.c);
- /* Move right if possible */
- if (i != NULL)
- {
- cursor_push(i->condition);
- }
- break;
- }
-
- case M_NOT:
- case M_INVENTORY:
- case M_EQUIPMENT:
- {
- if (top->subcondition != NULL)
- {
- cursor_push(top->subcondition);
- }
- break;
- }
-
- default:
- /* Not possible to move */
- break;
- }
-}
-
-static void tree_go_left()
-{
- if (cursor_count > 1)
- {
- cursor_pop();
- }
-}
-
-static void tree_go_up()
-{
- if (cursor_count > 1)
- {
- condition_type *prev_top = cursor_pop();
- condition_type *top = cursor_top();
-
- switch (top->match)
- {
- case M_AND:
- case M_OR:
- {
- struct sglib_condition_list_iterator it;
- condition_list *child = NULL;
- condition_list *prev_child = NULL;
-
- /* We have a list of children */
- for (child = sglib_condition_list_it_init(&it, top->conditions.c);
- child != NULL;
- child = sglib_condition_list_it_next(&it))
- {
- if (child->condition == prev_top)
- {
- /* Do we have a previous child? */
- if (prev_child == NULL)
- {
- /* No predecessor; don't move */
- cursor_push(prev_top);
- break;
- }
- else
- {
- cursor_push(prev_child->condition);
- break; /* Done */
- }
- }
- /* Keep track of previous child */
- prev_child = child;
- }
-
- break;
- }
-
- default:
- {
- /* No other match types have children; restore
- original top. */
- cursor_push(prev_top);
- break;
- }
-
- }
- }
-}
-
-static void tree_go_down()
-{
- if (cursor_count > 1)
- {
- condition_type *prev_top = cursor_pop();
- condition_type *top = cursor_top();
-
- switch (top->match)
- {
- case M_AND:
- case M_OR:
- {
- struct sglib_condition_list_iterator it;
- condition_list *child = NULL;
-
- /* We have a list of children */
- for (child = sglib_condition_list_it_init(&it, top->conditions.c);
- child != NULL;
- child = sglib_condition_list_it_next(&it))
- {
- if (child->condition == prev_top)
- {
- /* Move to next child (if any) */
- child = sglib_condition_list_it_next(&it);
- if (child == NULL)
- {
- /* No successor; don't move */
- cursor_push(prev_top);
- break;
- }
- else
- {
- cursor_push(child->condition);
- break; /* Done */
- }
- }
- }
-
- break;
- }
-
- default:
- {
- /* No other match types have multiple children; restore
- original top. */
- cursor_push(prev_top);
- break;
- }
-
- }
- }
-}
-
-static int automatizer_del_self(int sel)
-{
- /* If the cursor is at the top level then
- we want to delete the rule itself */
- if (cursor_count < 1)
- {
- rules_remove(rules[sel]);
- return sel - 1; /* Move selection up */
- }
- else if (cursor_count == 1)
- {
- cursor_pop();
- condition_destroy(&rules[sel]->condition);
- return sel;
- }
- else
- {
- condition_type *prev_top = cursor_pop();
- condition_type *top = cursor_top();
-
- /* Jump up a level; this is a simple way to ensure a
- valid cursor. We could be a little cleverer here by
- trying to move inside the current level, but it's a
- little complicated. */
- tree_go_left();
-
- /* Now we can remove the condition from its parent */
- switch (top->match)
- {
-
- case M_AND:
- case M_OR:
- {
- struct sglib_condition_list_iterator it;
- condition_list *item = NULL;
-
- /* We have a list of children */
- for (item = sglib_condition_list_it_init(&it, top->conditions.c);
- item != NULL;
- item = sglib_condition_list_it_next(&it))
- {
- if (item->condition == prev_top)
- {
- /* Found */
- break;
- }
- }
-
- /* Must have found item; otherwise internal structure
- is damaged. */
- assert (item != NULL);
- sglib_condition_list_delete(&top->conditions.c, item);
-
- /* Destroy the condition */
- condition_destroy(&prev_top);
- break;
- }
-
- case M_NOT:
- case M_EQUIPMENT:
- case M_INVENTORY:
- {
- assert(top->subcondition != NULL);
- condition_destroy(&top->subcondition);
- break;
- }
-
- default:
- /* If we get here, something's wrong with the
- navigation structures. */
- assert(FALSE);
- break;
- }
-
- /* Keep selection */
- return sel;
- }
-}
-
-#define ACTIVE_LIST 0
-#define ACTIVE_RULE 1
-void do_cmd_automatizer()
-{
- int wid = 0, hgt = 0;
- char c;
- int max, begin = 0, sel = 0;
- int active = ACTIVE_LIST;
- cptr keys;
- cptr keys2;
- cptr keys3;
- cptr rule_names[RULES_MAX];
-
- Term_get_size(&wid, &hgt);
-
- if (!automatizer_enabled)
- {
- if (msg_box("Automatizer is currently disabled, enable it? (y/n)", hgt / 2, wid / 2) == 'y')
- {
- automatizer_enabled = TRUE;
- }
- else
- return;
- }
-
- screen_save();
-
- adjust_current(sel);
-
- while (1)
- {
- Term_clear();
- Term_get_size(&wid, &hgt);
-
- max = rules_count;
- get_rule_names(rule_names);
- display_list(0, 0, hgt - 1, 15, "Rules", rule_names, max, begin, sel, (active == ACTIVE_LIST) ? TERM_L_GREEN : TERM_GREEN);
-
- draw_box(0, 15, hgt - 4, wid - 1 - 15);
- if (active == ACTIVE_RULE)
- {
- keys = "#Bup#W/#Bdown#W/#Bleft#W/#Bright#W to navitage rule, #B9#W/#B3#W/#B7#W/#B1#W to scroll";
- keys2 = "#Btab#W for switch, #Ba#Wdd clause, #Bd#Welete clause/rule";
- keys3 = "#G?#W for Automatizer help";
- }
- else
- {
- keys = "#Bup#W/#Bdown#W to scroll, #Btab#W to switch to the rule window";
- keys2 = "#Bu#W/#Bd#W to move rules, #Bn#Wew rule, #Br#Wename rule, #Bs#Wave rules";
- keys3 = "#Rk#W to #rdisable#W the automatizer, #G?#W for Automatizer help";
- }
- display_message(17, hgt - 3, strlen(keys), TERM_WHITE, keys);
- display_message(17, hgt - 2, strlen(keys2), TERM_WHITE, keys2);
- display_message(17, hgt - 1, strlen(keys3), TERM_WHITE, keys3);
-
- if (max)
- {
- display_rule(rules[sel]);
- }
-
- c = inkey();
-
- if (c == ESCAPE) break;
- if (active == ACTIVE_LIST)
- {
- if (c == '?')
- {
- screen_save();
- show_file("automat.txt", "Automatizer help", 0, 0);
- screen_load();
- }
- else if (c == '8')
- {
- if (!max) continue;
- sel--;
- adjust_begin(&begin, &sel, max, hgt);
- adjust_current(sel);
- }
- else if (c == '2')
- {
- if (!max) continue;
- sel++;
- adjust_begin(&begin, &sel, max, hgt);
- adjust_current(sel);
- }
- else if (c == 'u')
- {
- if (sel > 0)
- {
- rules_swap(sel-1, sel);
- sel -= 1;
-
- adjust_begin(&begin, &sel, max, hgt);
- adjust_current(sel);
- }
- }
- else if (c == 'd')
- {
- if (!max) continue;
-
- if (sel < rules_count - 1)
- {
- rules_swap(sel, sel+1);
- sel += 1;
-
- adjust_begin(&begin, &sel, max, hgt);
- adjust_current(sel);
- }
- }
- else if (c == 'n')
- {
- int i = create_new_rule();
- if (i >= 0)
- {
- sel = i;
- adjust_current(sel);
- active = ACTIVE_RULE;
- }
- }
- else if (c == 's')
- {
- automatizer_save_rules();
- }
- else if (c == 'r')
- {
- if (!max) continue;
-
- rename_rule(rules[sel]);
- continue;
- }
- else if (c == 'k')
- {
- automatizer_enabled = FALSE;
- break;
- }
- else if (c == '\t')
- {
- if (!max) continue;
- active = ACTIVE_RULE;
- }
- }
- else if (active == ACTIVE_RULE)
- {
- if (c == '?')
- {
- screen_save();
- show_file("automat.txt", "Automatizer help", 0, 0);
- screen_load();
- }
- else if (c == '8')
- {
- tree_go_up();
- }
- else if (c == '2')
- {
- tree_go_down();
- }
- else if (c == '6')
- {
- tree_go_right();
- }
- else if (c == '4')
- {
- tree_go_left();
- }
- else if (c == '9')
- {
- tree_scroll_up();
- }
- else if (c == '3')
- {
- tree_scroll_down();
- }
- else if (c == '7')
- {
- tree_scroll_left();
- }
- else if (c == '1')
- {
- tree_scroll_right();
- }
- else if (c == 'a')
- {
- add_new_condition(rules[sel]);
- }
- else if (c == 'd')
- {
- if (max)
- {
- int new_sel;
-
- new_sel = automatizer_del_self(sel);
- if ((sel != new_sel) && (new_sel >= 0))
- {
- sel = new_sel;
- adjust_begin(&begin, &sel, max, hgt);
- adjust_current(sel);
- }
- else if (new_sel == -1)
- {
- active = ACTIVE_LIST;
- }
- }
- }
- else if (c == '\t')
- {
- active = ACTIVE_LIST;
- }
- }
- }
-
- screen_load();
-}
-
-static void easy_add_rule(action_type action, cptr mode, bool_ do_status, object_type *o_ptr)
-{
- condition_type *condition = NULL;
-
- if (streq(mode, "tval"))
- {
- condition = condition_new_tval(o_ptr->tval);
- }
- else if (streq(mode, "tsval"))
- {
- condition_type *sval_condition =
- condition_new_sval(o_ptr->sval, o_ptr->sval);
- condition_type *tval_condition =
- condition_new_tval(o_ptr->tval);
-
- condition = condition_new_and();
- condition_and_add(condition, tval_condition);
- condition_and_add(condition, sval_condition);
- }
- else if (streq(mode, "name"))
- {
- char buf[128];
- object_desc(buf, o_ptr, -1, 0);
- strlower(buf);
-
- condition = condition_new_name(buf);
- }
-
- /* Use object status? */
- if (do_status == TRUE)
- {
- status_type status = object_status(o_ptr);
- condition_type *status_condition =
- condition_new_status(status);
- condition_type *and_condition =
- condition_new_and();
-
- condition_and_add(and_condition, condition);
- condition_and_add(and_condition, status_condition);
- /* Replace condition */
- condition = and_condition;
- }
-
- /* Build rule */
- {
- static arule_type *rule = NULL;
- /* Make rule */
- rule = rule_new(action_to_string(action),
- action,
- game_module_idx,
- condition,
- NULL);
-
- /* Append to list of rules */
- rules_append(rule);
- }
-
- msg_print("Rule added. Please go to the Automatizer screen (press = then T)");
- msg_print("to save the modified ruleset.");
-}
-
-/* Add a new rule in an easy way */
-bool_ automatizer_create = FALSE;
-void automatizer_add_rule(object_type *o_ptr, bool_ destroy)
-{
- char ch;
- bool_ do_status = FALSE;
- action_type action = AUTO_DESTROY;
-
- if (!destroy)
- {
- action = AUTO_PICKUP;
- }
-
- while (TRUE)
- {
- if (!get_com(format("%s all of the same [T]ype, [F]amily or [N]ame, also use [S]tatus (%s)? ", (destroy) ? "Destroy" : "Pickup", (do_status) ? "Yes" : "No"), &ch))
- {
- break;
- }
-
- if (ch == 'S' || ch == 's')
- {
- do_status = !do_status;
- continue;
- }
-
- if (ch == 'T' || ch == 't')
- {
- easy_add_rule(action, "tsval", do_status, o_ptr);
- break;
- }
-
- if (ch == 'F' || ch == 'f')
- {
- easy_add_rule(action, "tval", do_status, o_ptr);
- break;
- }
-
- if (ch == 'N' || ch == 'n')
- {
- easy_add_rule(action, "name", do_status, o_ptr);
- break;
- }
- }
-}
-
-static condition_type *parse_condition(json_t *condition_json)
-{
- cptr type_s = NULL;
- match_type match;
-
- if ((condition_json == NULL) || json_is_null(condition_json))
- {
- return NULL;
- }
-
- if (json_unpack(condition_json,
- "{s:s}",
- "type", &type_s) < 0)
- {
- msg_print("Missing/invalid 'type' in condition");
- return NULL;
- }
-
- if (!match_type_from_string(type_s, &match))
- {
- msg_format("Invalid 'type' in condition: %s", type_s);
- return NULL;
- }
-
- switch (match)
- {
- case M_AND:
- case M_OR:
- {
- json_t *conditions_j = json_object_get(condition_json,
- "conditions");
-
- if ((conditions_j == NULL) ||
- (json_is_null(conditions_j)))
- {
- return NULL;
- }
- else if (json_is_array(conditions_j))
- {
- int i;
- json_t *subcondition_j = NULL;
- condition_type *condition = condition_new(match);
- condition_type *subcondition = NULL;
-
- for (i = 0; i < json_array_size(conditions_j); i++)
- {
- subcondition_j =
- json_array_get(conditions_j, i);
- subcondition =
- parse_condition(subcondition_j);
-
- if (subcondition != NULL)
- {
- condition_and_add(condition, subcondition);
- }
- }
-
- return condition;
- }
- else
- {
- msg_print("'conditions' property has invalid type");
- return NULL;
- }
-
- break;
- }
-
- case M_NOT:
- case M_INVENTORY:
- case M_EQUIPMENT:
- {
- json_t *condition_j = json_object_get(condition_json,
- "condition");
-
- if ((condition_j == NULL) ||
- (json_is_null(condition_j)))
- {
- return NULL;
- }
- else if (json_is_object(condition_j))
- {
- condition_type *condition =
- condition_new(match);
- condition->subcondition =
- parse_condition(condition_j);
- return condition;
- }
- else
- {
- msg_print("Invlalid 'condition' property");
- return NULL;
- }
- }
-
- case M_NAME:
- {
- cptr s = NULL;
- if (json_unpack(condition_json,
- "{s:s}",
- "name", &s) < 0)
- {
- msg_print("Missing/invalid 'name' property");
- return NULL;
- }
-
- return condition_new_name(s);
- }
-
- case M_CONTAIN:
- {
- cptr s = NULL;
- if (json_unpack(condition_json,
- "{s:s}",
- "contain", &s) < 0)
- {
- msg_print("Missing/invalid 'contain' property");
- return NULL;
- }
-
- return condition_new_contain(s);
- }
-
- case M_SYMBOL:
- {
- cptr s = NULL;
- int sl;
- if (json_unpack(condition_json, "{s:s}", "symbol", &s) < 0)
- {
- msg_print("Missing/invalid 'symbol' property");
- return NULL;
- }
-
- sl = strlen(s);
- if (sl == 0)
- {
- msg_print("Invalid 'symbol' property: Too short");
- return NULL;
- }
- if (sl > 1)
- {
- msg_print("Invalid 'symbol' property: Too long");
- return NULL;
- }
-
- return condition_new_symbol(s[0]);
- }
-
- case M_INSCRIBED:
- {
- cptr s = NULL;
- if (json_unpack(condition_json, "{s:s}", "inscription", &s) < 0)
- {
- msg_print("Missing/invalid 'inscription' property");
- return NULL;
- }
-
- return condition_new_inscribed(s);
- }
-
- case M_DISCOUNT:
- {
- int min, max;
-
- if (json_unpack(condition_json, "{s:i,s:i}",
- "min", &min,
- "max", &max) < 0)
- {
- msg_print("Missing/invalid 'min'/'max' properties");
- return NULL;
- }
-
- return condition_new_discount(min, max);
- }
-
- case M_TVAL:
- {
- int tval;
-
- if (json_unpack(condition_json, "{s:i}", "tval", &tval) < 0)
- {
- msg_print("Missing/invalid 'tval' property");
- return NULL;
- }
-
- return condition_new_tval(tval);
- }
-
- case M_SVAL:
- {
- int min, max;
-
- if (json_unpack(condition_json, "{s:i,s:i}",
- "min", &min,
- "max", &max) < 0)
- {
- msg_print("Missing/invalid 'min'/'max' properties");
- return NULL;
- }
-
- return condition_new_sval(min, max);
- }
-
- case M_STATUS:
- {
- cptr s;
- status_type status;
-
- if (json_unpack(condition_json, "{s:s}", "status", &s) < 0)
- {
- msg_print("Missing/invalid 'status' property");
- return NULL;
- }
-
- if (!status_from_string(s, &status))
- {
- msg_format("Invalid 'status' property: %s", s);
- return NULL;
- }
-
- return condition_new_status(status);
- }
-
- case M_STATE:
- {
- cptr s;
- identification_state state;
-
- if (json_unpack(condition_json, "{s:s}", "state", &s) < 0)
- {
- msg_print("Missing/invalid 'state' property");
- return NULL;
- }
-
- if (!identification_state_from_string(s, &state))
- {
- msg_format("Invalid 'state' property: %s", s);
- return NULL;
- }
-
- return condition_new_state(state);
- }
-
- case M_RACE:
- {
- cptr s;
-
- if (json_unpack(condition_json, "{s:s}", "race", &s) < 0)
- {
- msg_print("Missing/invalid 'race' property");
- return NULL;
- }
-
- return condition_new_race(s);
- }
-
- case M_SUBRACE:
- {
- cptr s;
-
- if (json_unpack(condition_json, "{s:s}", "subrace", &s) < 0)
- {
- msg_print("Missing/invalid 'subrace' property");
- return NULL;
- }
-
- return condition_new_subrace(s);
- }
-
- case M_CLASS:
- {
- cptr s;
-
- if (json_unpack(condition_json, "{s:s}", "class", &s) < 0)
- {
- msg_print("Missing/invalid 'class' property");
- return NULL;
- }
-
- return condition_new_class(s);
- }
-
- case M_LEVEL:
- {
- int min, max;
-
- if (json_unpack(condition_json, "{s:i,s:i}",
- "min", &min,
- "max", &max) < 0)
- {
- msg_print("Missing/invalid 'min'/'max' properties");
- return NULL;
- }
-
- return condition_new_level(min, max);
- }
-
- case M_SKILL:
- {
- cptr s;
- s16b si;
- int min, max;
-
- if (json_unpack(condition_json, "{s:i,s:i,s:s}",
- "min", &min,
- "max", &max,
- "name", &s) < 0)
- {
- msg_print("Missing/invalid 'min'/'max'/'name' properties");
- return NULL;
- }
-
- si = find_skill_i(s);
- if (si < 0)
- {
- msg_print("Invalid 'name' property");
- return NULL;
- }
-
- return condition_new_skill(min, max, si);
- }
-
- case M_ABILITY:
- {
- cptr a;
- s16b ai;
-
- if (json_unpack(condition_json, "{s:s}",
- "ability", &a) < 0)
- {
- msg_print("Missing/invalid 'ability' property");
- return NULL;
- }
-
- ai = find_ability(a);
- if (ai < 0)
- {
- msg_print("Invalid 'ability' property");
- return NULL;
- }
-
- return condition_new_ability(ai);
- }
-
- }
-
- /* Could not parse */
- return NULL;
-}
-
-static void parse_rule(json_t *rule_json)
-{
- char *rule_name_s = NULL;
- char *rule_action_s = NULL;
- char *rule_module_s = NULL;
- json_t *rule_inscription_j = NULL;
- arule_type *rule = NULL;
- action_type action;
- int module_idx;
-
- if (!json_is_object(rule_json))
- {
- msg_print("Rule is not an object");
- return;
- }
-
- /* Retrieve the attributes */
- if (json_unpack(rule_json,
- "{s:s,s:s,s:s}",
- "name", &rule_name_s,
- "action", &rule_action_s,
- "module", &rule_module_s) < 0)
- {
- msg_print("Rule missing required field(s)");
- return;
- }
-
- /* Get the optional inscription */
- rule_inscription_j = json_object_get(rule_json, "inscription");
-
- /* Convert attributes */
- if (!action_from_string((cptr) rule_action_s, &action))
- {
- msg_format("Invalid rule action '%s'", rule_action_s);
- return;
- }
-
- module_idx = find_module((cptr) rule_module_s);
- if (module_idx < 0)
- {
- msg_format("Skipping rule for unrecognized module '%s'",
- (cptr) rule_module_s);
- return;
- }
-
- /* Sanity check: Inscription */
- if (action == AUTO_INSCRIBE)
- {
- if (rule_inscription_j == NULL)
- {
- msg_print("Inscription rule missing 'inscription' attribute");
- return;
- }
- if (!json_is_string(rule_inscription_j))
- {
- msg_print("Inscription rule 'inscription' attribute wrong type");
- return;
- }
- }
-
- /* Create rule */
- rule = rule_new(rule_name_s,
- action,
- module_idx,
- NULL,
- json_string_value(rule_inscription_j));
- rules_append(rule);
-
- /* Parse the conditions */
- rule->condition = parse_condition(json_object_get(rule_json, "condition"));
-}
-
-static void parse_rules(json_t *rules)
-{
- int i;
-
- if (!json_is_array(rules))
- {
- msg_format("Error 'rules' is not an array");
- return;
- }
-
- for (i = 0; i < json_array_size(rules); i++)
- {
- json_t *rule = json_array_get(rules, i);
- parse_rule(rule);
- }
-}
-
-/**
- * Initialize the automatizer. This function may be called multiple
- * times with different file names -- it should NOT clear any
- * automatizer state (including loaded rules).
- */
-void automatizer_init(cptr file_path)
-{
- json_t *rules_json = NULL;
- json_error_t error;
-
- /* Does the file exist? */
- if (!file_exist(file_path))
- {
- /* No big deal, we'll just skip */
- goto out;
- }
-
- /* Parse file */
- rules_json = json_load_file(file_path, 0, &error);
- if (rules_json == NULL)
- {
- msg_format("Error parsing automatizer rules from '%s'.", file_path);
- msg_format("Line %d, Column %d", error.line, error.column);
- msg_print(NULL);
- goto out;
- }
-
- /* Go through all the found rules */
- parse_rules(rules_json);
-
-out:
- if (rules_json == NULL)
- {
- json_decref(rules_json);
- }
-}
diff --git a/src/squeltch.cc b/src/squeltch.cc
new file mode 100644
index 00000000..8e8c5b8f
--- /dev/null
+++ b/src/squeltch.cc
@@ -0,0 +1,596 @@
+/*
+ * 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);
+
+ // File type is "TEXT"
+ FILE_TYPE(FILE_TYPE_TEXT);
+
+ if (file_exist(buf))
+ {
+ c_put_str(TERM_WHITE, "File exists, continue?[y/n]",
+ hgt / 2,
+ wid / 2 - 14);
+ ch = inkey();
+ if ((ch != 'Y') && (ch != 'y'))
+ {
+ return;
+ }
+ }
+
+ // Write to file
+ {
+ auto rules_json = automatizer->to_json();
+
+ int status = json_dump_file(rules_json.get(), buf,
+ JSON_INDENT(2) |
+ JSON_SORT_KEYS);
+ if (status == 0)
+ {
+ c_put_str(TERM_WHITE, "Saved rules in file ",
+ hgt / 2,
+ wid / 2 - 14);
+ }
+ else
+ {
+ c_put_str(TERM_WHITE, "Saving rules failed! ",
+ hgt / 2,
+ wid / 2 - 14);
+ }
+
+ // Wait for keypress
+ inkey();
+ }
+}
+
+static void rename_rule(Rule *rule)
+{
+ char name[16];
+ int wid, hgt;
+
+ assert(rule != nullptr);
+
+ Term_get_size(&wid, &hgt);
+
+ sprintf(name, "%s", rule->get_name());
+ if (input_box("New name?", hgt / 2, wid / 2, name, sizeof(name)))
+ {
+ 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 ff5e89dc..8e9512cd 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,10 +6,40 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "spell_type.h"
-#include "quark.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 <cassert>
#define STORE_GENERAL_STORE "General Store"
#define STORE_ARMOURY "Armoury"
@@ -73,7 +99,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);
@@ -281,6 +307,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 */
@@ -294,14 +323,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);
}
@@ -593,7 +622,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);
@@ -608,17 +637,26 @@ 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 + st_name;
+ 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;
+ }
/* What do stores buy? */
if (streq(store_name, STORE_GENERAL_STORE))
@@ -636,7 +674,7 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_DIGGING:
case TV_CLOAK:
case TV_BOTTLE:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_ARMOURY))
@@ -652,7 +690,7 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_SOFT_ARMOR:
case TV_HARD_ARMOR:
case TV_DRAG_ARMOR:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_WEAPONSMITH))
@@ -670,7 +708,7 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_SWORD:
case TV_AXE:
case TV_MSTAFF:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_TEMPLE))
@@ -682,34 +720,34 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_POTION2:
case TV_POTION:
case TV_HAFTED:
- return TRUE;
+ 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;
+ return true;
}
else if ((o_ptr->tval == TV_POLEARM) &&
is_blessed(o_ptr))
{
- return TRUE;
+ return true;
}
else if ((o_ptr->tval == TV_SWORD) &&
is_blessed(o_ptr))
{
- return TRUE;
+ return true;
}
else if ((o_ptr->tval == TV_AXE) &&
is_blessed(o_ptr))
{
- return TRUE;
+ return true;
}
else if ((o_ptr->tval == TV_BOOMERANG) &&
is_blessed(o_ptr))
{
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_ALCHEMY))
@@ -721,7 +759,7 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_POTION:
case TV_BATERIE:
case TV_BOTTLE:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_MAGIC))
@@ -740,24 +778,24 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_POTION:
case TV_MSTAFF:
case TV_RANDART:
- return TRUE;
+ 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;
+ return true;
}
else if ((o_ptr->tval == TV_BOOK) &&
(o_ptr->sval != BOOK_RANDOM))
{
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_BLACK_MARKET))
{
- return TRUE;
+ return true;
}
else if (streq(store_name, STORE_BOOKS))
{
@@ -768,7 +806,7 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_MUSIC_BOOK:
case TV_DAEMON_BOOK:
case TV_DRUID_BOOK:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_PETS))
@@ -786,7 +824,7 @@ static bool_ store_will_buy(object_type *o_ptr)
case TV_ARROW:
case TV_BOW:
case TV_POTION2:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_RUNIC_MAGIC))
@@ -795,7 +833,7 @@ static bool_ store_will_buy(object_type *o_ptr)
{
case TV_RUNE1:
case TV_RUNE2:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_CONSTRUCTION_SUPPLIES))
@@ -804,7 +842,7 @@ static bool_ store_will_buy(object_type *o_ptr)
{
case TV_LITE:
case TV_DIGGING:
- return TRUE;
+ return true;
}
}
else if (streq(store_name, STORE_MUSIC))
@@ -813,7 +851,7 @@ static bool_ store_will_buy(object_type *o_ptr)
}
/* Assume not okay */
- return (FALSE);
+ return false;
}
@@ -1213,16 +1251,9 @@ 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()))
- {
- obj_all_done = TRUE;
- q_ptr = process_hooks_return[0].o_ptr;
- }
-
/* Magic Shop */
- else if (streq(st_info[st_ptr->st_idx].name + st_name, STORE_MAGIC) &&
- magik(20))
+ if (streq(st_info[st_ptr->st_idx].name, STORE_MAGIC) &&
+ magik(20))
{
s16b spell;
@@ -1237,7 +1268,7 @@ static void store_create(void)
}
/* Temple */
- else if (streq(st_info[st_ptr->st_idx].name + st_name, STORE_TEMPLE) &&
+ else if (streq(st_info[st_ptr->st_idx].name, STORE_TEMPLE) &&
magik(20))
{
s16b spell;
@@ -1450,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;
}
@@ -1513,7 +1538,7 @@ static void display_entry(int pos)
if (x > p_ptr->au) color = TERM_L_DARK;
/* Actually draw the price */
- strnfmt(out_val, 160, "%9ld ", (long)x);
+ strnfmt(out_val, 160, "%9ld ", static_cast<long>(x));
c_put_str(color, out_val, i + 6, 68);
}
}
@@ -1564,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);
}
@@ -1594,10 +1619,8 @@ void display_store(void)
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 */
@@ -1610,15 +1633,14 @@ void display_store(void)
/* 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 */
@@ -1831,8 +1853,8 @@ static bool_ sell_haggle(object_type *o_ptr, s32b *price)
/* Sell the whole pile */
cur_ask *= o_ptr->number;
- /* Describe the object (fully) */
- object_desc_store(o_name, o_ptr, TRUE, 3);
+ /* Describe the object */
+ object_desc(o_name, o_ptr, TRUE, 3);
/* Prompt */
strnfmt(out_val, sizeof(out_val), "%s: " FMTs32b, "Price", cur_ask);
@@ -2190,7 +2212,7 @@ void store_purchase(void)
}
else
{
- q = p_ptr->au / (best + (best / 10));
+ q = p_ptr->au / best;
}
if (o_ptr->number < q)
q = o_ptr->number;
@@ -2272,7 +2294,7 @@ void store_purchase(void)
object_desc(o_name, j_ptr, TRUE, 3);
/* Message */
- msg_format("You bought %s for %ld gold.", o_name, (long)price);
+ msg_format("You bought %s for " FMTs32b " gold.", o_name, price);
/* Erase the inscription */
j_ptr->note = 0;
@@ -2432,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);
@@ -2604,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);
@@ -3026,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 '"':
{
@@ -3409,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);
@@ -3601,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).
*
@@ -3862,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);
@@ -3870,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/string_list.c b/src/string_list.c
deleted file mode 100644
index 8a63cc3c..00000000
--- a/src/string_list.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "angband.h"
-
-int compare_string_list(string_list *a, string_list *b)
-{
- if (a == b)
- {
- return 0;
- }
-
- return strcmp(a->s, b->s);
-}
-
-SGLIB_DEFINE_LIST_FUNCTIONS(string_list, compare_string_list, next);
-
-/*
- * Initialize a string_list value. Copies the input string.
- */
-void string_list_init(string_list *sl, cptr s)
-{
- assert(sl != NULL);
-
- sl->s = string_make(s);
- sl->next = NULL;
-}
-
-/*
- * Destroy string_value.
- */
-void string_list_destroy(string_list *sl)
-{
- assert(sl != NULL);
-
- /* Free contained string */
- if (sl->s) {
- string_free(sl->s);
- sl->s = NULL;
- }
-
- /* We do NOT free the rest of the list. */
- sl->next = NULL;
-}
-
-/**
- * Append a string to a string_list.
- */
-void string_list_append(string_list **slist, cptr s)
-{
- string_list *e = malloc(sizeof(string_list));
- string_list_init(e, s);
-
- sglib_string_list_add(slist, e);
-}
diff --git a/src/tables.c b/src/tables.cc
index 1d5f1c49..42244d6c 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"
@@ -1364,21 +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" },
-
{ &ring_bell, FALSE, 1, 18,
"ring_bell", "Audible bell (on errors, etc)" },
/* Changed to default to FALSE -- it's so extremely annoying!!! -TY */
@@ -1427,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" },
@@ -1442,41 +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_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" },
@@ -1486,18 +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" },
-
{ &small_levels, TRUE, 3, 17,
"small_levels", "Allow unusually small dungeon levels" },
@@ -1509,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" },
@@ -1562,9 +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" },
-
{ &auto_more, FALSE, 5, 4,
"auto_more", "Automatically clear '-more-' prompts" },
@@ -1580,9 +1450,6 @@ option_type option_info[] =
/*** Birth Options ***/
- { &maximize, TRUE, 6, 1,
- "maximize", "Maximise stats" },
-
{ &preserve, TRUE, 6, 2,
"preserve", "Preserve artifacts" },
@@ -1598,24 +1465,14 @@ option_type option_info[] =
{ &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 ***/
@@ -2346,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 */
{
@@ -2476,43 +2333,6 @@ 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.
*/
@@ -2603,8 +2423,7 @@ deity_type deity_info[MAX_GODS] =
{ 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.",
"",
"",
"",
@@ -2652,8 +2471,7 @@ deity_type deity_info[MAX_GODS] =
{ MODULE_THEME, -1, },
"Ulmo",
{
- "Ulmo is called Lord of Waters, he rules all that is water"
- "on Arda.",
+ "Ulmo is called Lord of Waters, he rules all that is water on Arda.",
"",
"",
"",
@@ -2977,7 +2795,7 @@ 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,
},
};
@@ -3385,10 +3203,12 @@ power_type powers_type[POWER_MAX] =
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,
},
{
@@ -3466,7 +3286,7 @@ quest_type quest[MAX_Q_IDX] =
0,
NULL,
- quest_null_hook,
+ NULL,
{0, 0},
NULL,
},
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 999f9acc..bc4ef99f 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,36 @@
* 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"
bool_ do_player_trap_call_out(void)
{
@@ -346,7 +371,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 +464,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 +487,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 */
@@ -639,17 +656,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);
@@ -868,7 +882,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 +890,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 +924,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 +1179,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 +1382,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 +1392,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 +1897,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 +1915,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 +1986,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 +2000,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);
}
}
@@ -2133,26 +2145,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));
}
/*
@@ -2197,46 +2194,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];
@@ -2519,7 +2516,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;
@@ -2622,7 +2619,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);
@@ -2728,8 +2725,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;
@@ -2756,9 +2751,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);
@@ -2998,8 +2994,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 */
@@ -3044,8 +3039,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);
}
}
@@ -3086,8 +3080,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 d9cae3cf..00000000
--- a/src/types.h
+++ /dev/null
@@ -1,2771 +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.
- */
-
-
-/*
- * String list.
- */
-typedef struct string_list string_list;
-struct string_list {
- /* The string list owns the string */
- cptr s;
- /* Next */
- string_list *next;
-};
-
-int compare_string_list(string_list *a, string_list *b);
-SGLIB_DEFINE_LIST_PROTOTYPES(string_list, compare_string, next);
-
-void string_list_init(string_list *sl, cptr s); /* Initialize element; copies string */
-void string_list_destroy(string_list *sl); /* Destroy element */
-void string_list_append(string_list **slist, cptr s); /* Append string */
-
-
-
-/*
- * Template file header information (see "init.c"). 16 bytes.
- *
- * 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 */
-
- s16b inflation; /* Inflation */
-
- 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 */
-
- 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 */
- bool_ activated[HELP_MAX]; /* help item #i activated? */
-};
-
-
-/*
- * 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. */
- 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 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 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 */
-
- 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[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 */
-};
-
-
-/* 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
-{
- int modules[3]; /* terminated with -1 */
- 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);
-
-typedef struct hook_move_in hook_move_in;
-struct hook_move_in {
- int y;
- int x;
-};
-
-typedef struct hook_get_in hook_get_in;
-struct hook_get_in {
- object_type *o_ptr;
- int o_idx;
-};
-
-typedef struct hook_end_turn_in hook_end_turn_in;
-struct hook_end_turn_in {
- bool_ is_quest;
-};
-
-typedef struct hook_player_level_in hook_player_level_in;
-struct hook_player_level_in {
- int gained_levels;
-};
-
-typedef enum { IDENT_NORMAL, IDENT_FULL } identify_mode;
-
-typedef struct hook_identify_in hook_identify_in;
-struct hook_identify_in {
- object_type *o_ptr;
- identify_mode mode;
-};
-
-typedef struct hook_give_in hook_give_in;
-struct hook_give_in {
- int m_idx;
- int item;
-};
-
-typedef struct hook_eat_in hook_eat_in;
-struct hook_eat_in {
- object_type *o_ptr;
-};
-
-typedef struct hook_eat_out hook_eat_out;
-struct hook_eat_out {
- bool_ ident;
-};
-
-typedef enum { STAIRS_UP, STAIRS_DOWN } stairs_direction;
-
-typedef struct hook_stair_in hook_stair_in;
-struct hook_stair_in {
- stairs_direction direction;
-};
-
-typedef struct hook_stair_out hook_stair_out;
-struct hook_stair_out {
- bool_ allow;
-};
-
-typedef struct hook_new_monster_end_in hook_new_monster_end_in;
-struct hook_new_monster_end_in {
- monster_type *m_ptr;
-};
-
-/*
- * Structure for the "quests"
- */
-typedef struct quest_type quest_type;
-
-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. */
-};
-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;
- bool_ (*hook_f)(void *, void *, void *);
- void *hook_data;
- 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. */
-};
-
-/*
- * Range
- */
-typedef struct range_type range_type;
-struct range_type
-{
- s32b min;
- s32b max;
-};
-
-/*
- * Dice
- */
-typedef struct dice_type dice_type;
-struct dice_type
-{
- long base; /* Base value to which roll is added. */
- long num; /* Number of dice */
- long sides; /* Sides per dice */
-};
-
-/*
- * Device allocation for skill
- */
-typedef struct device_allocation device_allocation;
-struct device_allocation
-{
- byte tval;
- s32b rarity;
- range_type base_level;
- range_type max_level;
- /* Next device allocation in the list */
- device_allocation *next;
-};
-
-int compare_device_allocation(device_allocation *a, device_allocation *b);
-SGLIB_DEFINE_LIST_PROTOTYPES(device_allocation, compare_device_allocation, next);
-
-
-/*
- * Skills !
- */
-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 */
-};
-
-typedef struct school_provider school_provider;
-struct school_provider
-{
- byte deity_idx; /* Deity which provides school levels */
-
- s16b skill_idx; /* Skill used for determining the boost */
-
- long mul; /* Multiplier */
-
- long div; /* Divisor */
-
- school_provider *next; /* Next provider in list */
-};
-
-typedef struct school_type school_type;
-struct school_type
-{
- cptr name; /* Name */
- s16b skill; /* Skill used for that school */
- bool_ spell_power; /* Does spell power affect spells in this school? */
- bool_ sorcery; /* Does Sorcery affect this school? */
-
- int deity_idx; /* Deity; if <=0, no deity required */
- deity_type *deity; /* Direct pointer to deity */
-
- int (*bonus_levels)(); /* Calculate number of bonus levels */
-
- bool_ (*depends_satisfied)(); /* Are dependendies satisfied? */
-
- school_provider *providers; /* List of secondary providers of this school */
-};
-
-/*
- * Spell index list.
- */
-typedef struct spell_idx_list spell_idx_list;
-struct spell_idx_list {
- s32b i; /* Spell index */
- spell_idx_list *next; /* for list */
-};
-
-/*
- * School book.
- */
-typedef struct school_book_type school_book_type;
-struct school_book_type {
- spell_idx_list *spell_idx_list;
-};
-
-/*
- * Desc for GF_FOO
- */
-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 */
-
- void (*callback)(); /* The C function to call upon firing */
-};
-
-/*
- * 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) */
-};
-
-/**
- * Module metadata
- */
-typedef struct module_meta_type module_meta_type;
-struct module_meta_type
-{
- /* Module name */
- cptr name;
-
- /* Module version number */
- struct {
- s32b major;
- s32b minor;
- s32b patch;
- } version;
-
- /* Module author */
- struct {
- cptr name;
- cptr email;
- } author;
-
- /* Module description */
- cptr desc;
-
- /* Save file tag */
- cptr save_file_tag;
-
- /* Module directory */
- cptr module_dir;
-};
-
-/**
- * Modules
- */
-typedef struct module_type module_type;
-struct module_type
-{
- /* Metadata about the module: author, description, etc. */
- module_meta_type meta;
-
- /* Random artifact generation chances */
- struct {
- s32b weapon_chance;
- s32b armor_chance;
- s32b jewelry_chance;
- } randarts;
-
- /* Max player level. */
- int max_plev;
-
- /* Skills */
- struct {
- /* Skill points per level */
- s32b skill_per_level;
- /* Maximum "overage" for skill points, i.e. how many skill
- points you can go above your current level. */
- s32b max_skill_overage;
- } skills;
-
- /* 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);
-};
-
-/**
- * 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 */
-};
-
-/**
- * Mimicry forms
- */
-typedef struct mimic_duration_type mimic_duration_type;
-struct mimic_duration_type
-{
- s16b min;
- s16b max;
-};
-
-typedef struct mimic_form_type mimic_form_type;
-struct mimic_form_type
-{
- int modules[3]; /* Modules where this mimicry form is available; terminated with a -1 entry */
- cptr name; /* Name of mimicry form */
- cptr obj_name; /* Object mimicry form name */
- cptr desc; /* Description */
- cptr realm; /* Realm of mimicry */
- bool_ limit; /* If true, the form is not available except through special means */
- byte level;
- byte rarity;
- mimic_duration_type duration;
- s32b (*calc)(); /* Callback to calculate bonuses; return number of blows to add */
- void (*power)(); /* Callback to calculate powers */
-};
diff --git a/src/util.c b/src/util.cc
index ba52c89b..675a02d1 100644
--- a/src/util.c
+++ b/src/util.cc
@@ -2,113 +2,36 @@
/* Purpose: Angband utilities -BEN- */
-
-#include "angband.h"
-
-#include "messages.h"
-#include "quark.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.
@@ -132,9 +55,6 @@ void user_name(char *buf, int id)
strcpy(buf, "PLAYER");
}
-#endif /* SET_UID */
-
-
/*
@@ -337,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];
@@ -347,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 */
}
@@ -541,28 +442,6 @@ 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
@@ -577,27 +456,10 @@ int fd_make(cptr file, int mode)
/* Hack -- Try to parse the path */
if (path_parse(buf, 1024, file)) return ( -1);
-#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 */
}
@@ -614,91 +476,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);
}
@@ -902,40 +683,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;
@@ -959,8 +706,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;
@@ -972,7 +718,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;
@@ -1204,8 +950,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)
@@ -1482,7 +1228,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 */
@@ -1492,11 +1238,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;
@@ -1508,22 +1254,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;
@@ -1567,7 +1297,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();
@@ -1579,11 +1312,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;
}
@@ -1675,7 +1405,7 @@ static char inkey_aux(void)
if (w >= 100) break;
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, w);
+ sleep_for(milliseconds(w));
}
}
@@ -1751,6 +1481,8 @@ static char inkey_aux(void)
*/
static cptr inkey_next = NULL;
+bool_ inkey_flag = FALSE;
+
/*
* Get a keypress from the user.
@@ -1761,11 +1493,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.
*
@@ -1810,11 +1537,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;
@@ -1827,13 +1551,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);
@@ -1844,20 +1568,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);
@@ -1896,9 +1606,6 @@ char inkey(void)
/* Hack -- activate main screen */
Term_activate(angband_term[0]);
- /* Mega-Hack -- reset saved flag */
- character_saved = FALSE;
-
/* Only once */
done = TRUE;
}
@@ -1943,7 +1650,7 @@ char inkey(void)
if (w >= 100) break;
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, w);
+ sleep_for(milliseconds(w));
}
}
@@ -1962,13 +1669,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;
@@ -2025,7 +1727,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 */
@@ -2033,6 +1735,14 @@ char inkey(void)
return (ch);
}
+char inkey(void) {
+ return inkey_real(FALSE);
+}
+
+char inkey_scan() {
+ return inkey_real(TRUE);
+}
+
/*
* Hack -- flush
*/
@@ -2117,13 +1827,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;
@@ -2639,9 +2350,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);
@@ -3644,7 +3357,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;
@@ -3653,13 +3365,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;
@@ -3668,10 +3378,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);
}
@@ -3690,10 +3397,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);
}
@@ -3783,12 +3488,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);
@@ -3797,10 +3508,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;
@@ -3814,9 +3526,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 */
@@ -3828,7 +3540,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;
}
@@ -3845,7 +3557,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;
@@ -3980,27 +3692,16 @@ 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(void (*callback)(), s32b delay)
{
- timer_type *t_ptr = NULL;
+ 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;
@@ -4012,26 +3713,6 @@ timer_type *new_timer(void (*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;
-
- FREE(t_ptr, timer_type);
- }
- else
- cmsg_print(TERM_VIOLET, "Unknown timer!");
-}
-
int get_keymap_mode()
{
if (rogue_like_commands)
@@ -4043,3 +3724,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..5cb2f058
--- /dev/null
+++ b/src/util.hpp
@@ -0,0 +1,76 @@
+#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_month_name(int month, bool_ full, bool_ compact);
+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_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 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_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 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/variable.c b/src/variable.cc
index ac67e308..ca4aca01 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,7 +6,13 @@
* 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"
int max_macrotrigger = 0;
@@ -26,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
@@ -34,13 +35,10 @@ 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 */
@@ -49,11 +47,8 @@ u16b sf_saves; /* Number of "saves" during this life */
* Run-time aruments
*/
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
@@ -62,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 */
@@ -109,20 +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 */
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 */
@@ -132,7 +118,6 @@ 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 */
bool_ hack_mind;
int artifact_bias;
@@ -148,7 +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;
char summon_kin_type; /* Hack, by Julian Lighton: summon 'relatives' */
int total_friends = 0;
@@ -182,110 +166,6 @@ int text_out_indent = 0;
*/
-/* 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_ 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_ 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_ 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_ 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_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 */
@@ -318,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
*/
@@ -419,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]
@@ -498,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]
@@ -605,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;
@@ -651,7 +454,7 @@ 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];
@@ -697,177 +500,117 @@ 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"
@@ -895,144 +638,84 @@ cptr ANGBAND_GRAF = "old";
* Path name: The main "lib" directory
* This variable is not actually used anywhere in the code
*/
-cptr ANGBAND_DIR;
+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;
@@ -1048,11 +731,9 @@ bool_ (*get_mon_num2_hook)(int r_idx);
*/
bool_ (*get_obj_num_hook)(int k_idx);
-
-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;
@@ -1137,7 +818,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
@@ -1204,18 +885,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];
@@ -1246,30 +915,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;
-/* 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;
+/* Special levels */
+bool_ special_lvls;
/*
* Such an ugly hack ...
@@ -1279,21 +932,6 @@ bool_ *k_allow_special;
bool_ *a_allow_special;
/*
- * Gives a random object to newly created characters
- */
-bool_ rand_birth;
-
-/*
- * Which monsters are allowed ?
- */
-bool_ joke_monsters;
-
-/*
- * Center view
- */
-bool_ center_player = FALSE;
-
-/*
* Plots
*/
s16b plots[MAX_PLOTS];
@@ -1304,27 +942,12 @@ s16b plots[MAX_PLOTS];
random_quest random_quests[MAX_RANDOM_QUEST];
/*
- * Show exp left
- */
-bool_ exp_need;
-
-/*
- * 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;
@@ -1342,26 +965,8 @@ hist_type *bg;
int max_bg_idx;
/*
- * Variable savefile stuff
- */
-s32b extra_savefile_parts = 0;
-
-/*
- * Quests
- */
-quest_type quest[MAX_Q_IDX];
-
-/*
- * Display the player as a special symbol when in bad health ?
- */
-bool_ player_char_health;
-
-
-/*
* The spell list of schools
*/
-s16b school_spells_count = 0;
-spell_type *school_spells[SCHOOL_SPELLS_MAX];
s16b schools_count = 0;
school_type schools[SCHOOLS_MAX];
@@ -1381,11 +986,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;
@@ -1397,14 +997,10 @@ int cli_total = 0;
int max_bact = 127;
/*
- * Ingame contextual help
- */
-bool_ option_ingame_help = TRUE;
-
-/*
* Automatizer enabled status
*/
bool_ automatizer_enabled = FALSE;
+bool_ automatizer_create = FALSE;
/*
* Location of the last teleportation thath affected the level
@@ -1454,3 +1050,57 @@ 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_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 }
+};
diff --git a/src/variable.h b/src/variable.h
new file mode 100644
index 00000000..90a462b5
--- /dev/null
+++ b/src/variable.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "angband.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern cptr ANGBAND_SYS;
+extern cptr ANGBAND_KEYBOARD;
+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..74c74f77
--- /dev/null
+++ b/src/variable.hpp
@@ -0,0 +1,317 @@
+#pragma once
+
+#include "angband.h"
+#include "ability_type_fwd.hpp"
+#include "alchemist_recipe_fwd.hpp"
+#include "alloc_entry_fwd.hpp"
+#include "artifact_select_flag_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 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 artifact_select_flag *a_select_flags;
+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 cptr ANGBAND_GRAF;
+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_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 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 279b79d9..e9def091 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,28 @@
* 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 <memory>
/*
@@ -49,7 +65,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 +89,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 +149,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 +189,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 +203,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 +348,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 +391,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 +399,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 +407,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 +415,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 +423,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 +532,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;
@@ -533,7 +561,8 @@ void wilderness_gen(int refresh)
}
}
- process_hooks(HOOK_WILD_GEN, "(d)", FALSE);
+ struct hook_wild_gen_in in = { FALSE };
+ process_hooks_new(HOOK_WILD_GEN, &in, NULL);
}
/*
@@ -601,7 +630,8 @@ void wilderness_gen_small()
}
}
- 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 */
@@ -956,8 +986,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;
@@ -974,8 +1002,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++)
@@ -990,7 +1018,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);
@@ -1029,7 +1056,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);
}
}
@@ -1047,8 +1074,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;
@@ -1110,8 +1135,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++)
@@ -1126,7 +1151,6 @@ static void town_gen_circle(int t_idx, int qy, int qx)
}
}
}
- C_FREE(rooms, max_st_idx, int);
/* Some inhabitants(leveled .. hehe :) */
@@ -1160,7 +1184,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);
}
}
@@ -1178,11 +1202,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);
@@ -1205,7 +1227,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..476def67 100644
--- a/src/wizard1.c
+++ b/src/wizard1.cc
@@ -1,9 +1,23 @@
-/* File: wizard1.c */
-
-/* Purpose: Spoiler generation -BEN- */
-
-#include "angband.h"
-
+#include "wizard1.hpp"
+
+#include "alchemist_recipe.hpp"
+#include "artifact_select_flag.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
@@ -281,8 +295,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 */
@@ -1311,10 +1324,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];
@@ -1342,7 +1351,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 +1366,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 +1437,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))
{
@@ -1529,7 +1535,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 +1594,7 @@ static void spoil_mon_info(cptr fname)
/* Describe */
- spoil_out(r_text + r_ptr->text);
+ spoil_out(r_ptr->text);
spoil_out(" ");
@@ -2325,7 +2331,7 @@ static void spoil_mon_info(cptr fname)
}
-char *long_intro =
+static const char *long_intro =
"Essences are the tools of the trade for Alchemists, "
"and unfortunately are useless for any other class. "
"Alchemists use essences to create magical items for them to use.\n\n"
@@ -2480,8 +2486,8 @@ static void spoil_bateries(cptr fname)
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));
+ a_select_flags[i].desc,
+ a_select_flags[i].item_desc));
/* cycle through all alchemist_recipies*/
for ( j = 0 ; j < max_al_idx ; j++ )
{
@@ -2492,7 +2498,7 @@ static void spoil_bateries(cptr fname)
)
{
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));
+ k_info[lookup_kind(TV_BATERIE, alchemist_recipes[j].sval_essence)].name));
}
}
}
@@ -2517,7 +2523,7 @@ static void spoil_bateries(cptr fname)
/* print item desc (ego (tval=1)or item)*/
if (ar_ptr->tval == 1)
{
- strcpy(o_name, e_name + e_info[ar_ptr->sval].name);
+ strcpy(o_name, e_info[ar_ptr->sval].name);
}
else
{
@@ -2537,7 +2543,7 @@ static void spoil_bateries(cptr fname)
}
/* print essence required*/
spoil_out(format(" %d %s", ar_ptr->qty,
- k_name + k_info[lookup_kind(TV_BATERIE, ar_ptr->sval_essence)].name));
+ k_info[lookup_kind(TV_BATERIE, ar_ptr->sval_essence)].name));
}
spoil_out(NULL);
@@ -2572,7 +2578,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);
@@ -2652,16 +2658,10 @@ static void spoil_spells(cptr fname)
}
-
-/*
- * Forward declare
- */
-extern void do_cmd_spoilers(void);
-
/*
* Create Spoiler files -BEN-
*/
-void do_cmd_spoilers(void)
+void do_cmd_spoilers()
{
int i;
diff --git a/src/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 66ddaa38..7bce50c7 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,44 @@
* 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"
/*
* 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 +54,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 +77,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 +94,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 +137,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);
@@ -479,60 +503,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
@@ -543,7 +513,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 */
@@ -816,8 +786,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 */
@@ -889,7 +858,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;
@@ -970,11 +939,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();
@@ -1109,30 +1075,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 */
@@ -1143,7 +1101,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);
@@ -1152,6 +1111,8 @@ static void do_cmd_wiz_play(void)
/* The main loop */
while (TRUE)
{
+ char ch;
+
/* Display the item */
wiz_display_item(q_ptr);
@@ -1421,7 +1382,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;
@@ -1504,8 +1464,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;
+ }
}
}
@@ -1526,7 +1492,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;
@@ -1538,9 +1503,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;
}
@@ -1566,7 +1538,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 */
{
@@ -1578,24 +1550,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;
@@ -1670,7 +1628,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;
@@ -1797,7 +1755,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);
@@ -1866,7 +1824,7 @@ void do_cmd_debug(void)
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;
@@ -1903,8 +1861,7 @@ void do_cmd_debug(void)
/* 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 638a2102..87ecd62f 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,9 +6,49 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include "messages.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 <cassert>
/*
* Converts stat num into a six-char (right justified) string
@@ -117,6 +153,12 @@ s16b modify_stat_value(int value, int amount)
}
}
+ /* Clip to permissible range */
+ if (value < 3)
+ {
+ value = 3;
+ }
+
/* Return new value */
return (value);
}
@@ -274,7 +316,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];
}
@@ -311,20 +353,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)
@@ -490,7 +525,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];
@@ -499,10 +534,6 @@ static void prt_depth(void)
{
strcpy(depths, " ");
}
- else if (p_ptr->inside_arena)
- {
- strcpy(depths, "Arena");
- }
else if (get_dungeon_name(depths))
{
/* Empty */
@@ -517,28 +548,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
@@ -563,132 +579,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);
- }
- 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);
- }
+ c_prt(TERM_ORANGE, format("%13s", depths), row, col);
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);
}
@@ -699,7 +592,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;
@@ -804,14 +697,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;
@@ -836,58 +729,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);
}
}
@@ -896,22 +898,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);
}
}
@@ -933,32 +939,37 @@ static void prt_stun(void)
*/
static void health_redraw(void)
{
+ 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 */
@@ -1002,15 +1013,15 @@ 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) */
if (m_ptr->stunned) {
- Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "ssssssssss");
+ Term_putstr(col + 1, row, len, attr, "ssssssssss");
} else if (m_ptr->confused) {
- Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "cccccccccc");
+ Term_putstr(col + 1, row, len, attr, "cccccccccc");
} else {
- Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "**********");
+ Term_putstr(col + 1, row, len, attr, "**********");
}
}
}
@@ -1020,13 +1031,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();
@@ -1059,41 +1070,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();
}
@@ -1412,10 +1397,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;
@@ -1479,11 +1462,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++;
@@ -1506,19 +1489,6 @@ 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.
- */
-static void calc_spells(void)
-{
- p_ptr->new_spells = 0;
-}
-
-
-/*
* Calculate powers of player given the current set of corruptions.
*/
static void calc_powers_corruption()
@@ -1566,9 +1536,6 @@ static void calc_powers(void)
/* Calculate powers granted by corruptions */
calc_powers_corruption();
- /* Hooked powers */
- process_hooks(HOOK_CALC_POWERS, "()");
-
/* Add objects powers */
for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
{
@@ -1633,8 +1600,7 @@ static void calc_powers(void)
/*
* Calculate the player's sanity
*/
-
-void calc_sanity(void)
+static void calc_sanity()
{
int bonus, msane;
@@ -1659,7 +1625,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);
}
}
@@ -1711,7 +1677,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;
@@ -1777,19 +1743,7 @@ 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);
@@ -1811,7 +1765,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);
@@ -1871,6 +1825,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 */
@@ -1888,7 +1844,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;
@@ -1931,9 +1887,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 */
@@ -1955,7 +1915,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);
@@ -2073,9 +2033,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);
}
@@ -2378,7 +2335,7 @@ int get_archery_skill()
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;
@@ -2386,7 +2343,7 @@ static 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;
@@ -2408,7 +2365,7 @@ static 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;
@@ -2417,7 +2374,7 @@ static 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;
@@ -2432,13 +2389,13 @@ static 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;
@@ -2450,7 +2407,7 @@ static void calc_gods()
}
/* Aule provides to-hit/damage bonuses and fire resistance */
- GOD(GOD_AULE)
+ if (p_ptr->pgod == GOD_AULE)
{
if (p_ptr->grace > 0)
{
@@ -2476,7 +2433,7 @@ static void calc_gods()
/* Mandos provides nether resistance and, while praying,
nether immunity and prevents teleportation. */
- GOD(GOD_MANDOS)
+ if (p_ptr->pgod == GOD_MANDOS)
{
p_ptr->resist_neth = TRUE;
@@ -2495,7 +2452,7 @@ static void calc_gods()
/* Ulmo provides water breath and, while praying can
provide poison resistance and magic breath. */
- GOD(GOD_ULMO)
+ if (p_ptr->pgod == GOD_ULMO)
{
p_ptr->water_breath = TRUE;
@@ -2734,37 +2691,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;
@@ -2788,6 +2714,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
@@ -2872,9 +2825,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;
@@ -3070,22 +3020,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]);
}
@@ -3192,7 +3138,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);
@@ -3217,7 +3163,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);
@@ -3233,7 +3179,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);
@@ -3279,7 +3225,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;
@@ -3425,27 +3371,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)
{
@@ -3456,12 +3387,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)
{
@@ -3489,13 +3414,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)
{
@@ -3584,12 +3502,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) */
@@ -3608,7 +3522,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);
@@ -3692,13 +3606,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" */
@@ -4221,7 +4135,6 @@ void update_stuff(void)
if (p_ptr->update & (PU_SPELLS))
{
p_ptr->update &= ~(PU_SPELLS);
- calc_spells();
}
if (p_ptr->update & (PU_POWERS))
@@ -4272,7 +4185,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();
}
}
@@ -4294,10 +4207,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))
{
@@ -4314,182 +4223,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();
}
}
@@ -4595,26 +4332,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;
@@ -4951,3 +4668,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 f437c6d1..6ddf4ac9 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,49 +6,64 @@
* included in all such copies.
*/
-#include "angband.h"
-
-#include <assert.h>
-
-#include "quark.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 <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"
@@ -118,7 +128,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);
@@ -172,7 +182,7 @@ static bool_ set_simple_field(
/* Disturb */
if (disturb_state)
- disturb(0, 0);
+ disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -365,26 +375,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)
@@ -396,28 +386,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)
@@ -519,10 +487,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);
@@ -555,7 +523,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);
@@ -616,7 +584,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();
@@ -640,7 +608,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();
@@ -664,7 +632,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();
@@ -691,7 +659,7 @@ static bool_ set_paralyzed_aux(int v)
if (notice)
{
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -816,7 +784,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);
@@ -944,26 +912,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)
@@ -1178,7 +1126,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);
@@ -1242,26 +1190,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)
@@ -1405,7 +1333,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();
@@ -1429,7 +1357,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)
@@ -1545,7 +1473,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;
}
@@ -1560,13 +1488,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();
@@ -1590,7 +1518,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)
@@ -1753,7 +1681,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;
}
@@ -1768,13 +1696,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();
@@ -1982,13 +1910,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();
@@ -2023,7 +1951,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();
@@ -2042,7 +1970,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);
@@ -2065,7 +1993,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;
@@ -2083,7 +2011,7 @@ void check_experience(void)
p_ptr->skill_last_level = p_ptr->lev;
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 */
@@ -2102,7 +2030,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);
@@ -2119,8 +2047,6 @@ 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);
@@ -2196,7 +2122,7 @@ void gain_exp(s32b amount)
}
}
- 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))
{
@@ -2209,9 +2135,6 @@ void gain_exp(s32b amount)
/* Gain some experience */
p_ptr->exp += amount / num;
- /* Hook it! */
- process_hooks(HOOK_PLAYER_EXP, "(d)", amount / num);
-
/* Slowly recover from experience drainage */
if (p_ptr->exp < p_ptr->max_exp)
{
@@ -2235,9 +2158,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();
}
@@ -2253,7 +2173,7 @@ void lose_exp(s32b amount)
*/
int get_coin_type(monster_race *r_ptr)
{
- cptr name = (r_name + r_ptr->name);
+ cptr name = r_ptr->name;
/* Analyze "coin" monsters */
if (r_ptr->d_char == '$')
@@ -2588,8 +2508,6 @@ void monster_death(int m_idx)
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);
@@ -2608,7 +2526,10 @@ void monster_death(int m_idx)
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);
@@ -2628,7 +2549,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);
@@ -2639,27 +2560,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;
@@ -2681,13 +2592,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;
@@ -2737,7 +2648,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))
{
@@ -2773,13 +2684,13 @@ 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++)
{
@@ -2806,7 +2717,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;
@@ -2844,7 +2755,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;
@@ -2883,7 +2794,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;
@@ -2900,32 +2811,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;
@@ -3205,7 +3116,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
/* 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;
@@ -3246,7 +3157,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 */
@@ -3359,35 +3270,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 */
@@ -3438,11 +3352,8 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
{
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');
}
@@ -3486,7 +3397,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;
}
/*
@@ -3689,7 +3599,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();
@@ -3741,7 +3651,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();
@@ -3789,7 +3699,7 @@ 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);
@@ -3837,6 +3747,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,
@@ -3844,7 +3766,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;
@@ -3893,7 +3815,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);
@@ -3918,7 +3840,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];
@@ -4107,11 +4029,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);
@@ -4121,7 +4038,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)
@@ -4133,18 +4050,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 */
@@ -4187,9 +4102,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;
@@ -4272,8 +4184,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;
@@ -4338,14 +4248,15 @@ static int target_set_aux(int y, int x, int mode, cptr info)
/* 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
@@ -4424,9 +4335,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);
@@ -4464,19 +4376,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 */
@@ -4486,17 +4394,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 ";
@@ -4504,29 +4421,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)
{
@@ -4535,7 +4452,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
{
@@ -4580,11 +4497,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 */
@@ -4612,20 +4529,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)
@@ -4639,8 +4555,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 */
@@ -4824,7 +4739,6 @@ bool_ target_set(int mode)
if (++m == temp_n)
{
m = 0;
- if (!expand_list) done = TRUE;
}
break;
}
@@ -4834,7 +4748,6 @@ bool_ target_set(int mode)
if (m-- == 0)
{
m = temp_n - 1;
- if (!expand_list) done = TRUE;
}
break;
}
@@ -5362,102 +5275,6 @@ bool_ tgt_pt(int *x, int *y)
return success;
}
-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);
-}
-
/*
* Set "p_ptr->grace", notice observable changes
*/
@@ -5467,11 +5284,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];
@@ -5572,7 +5389,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;
@@ -5589,7 +5406,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;
@@ -5695,7 +5512,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))
@@ -5707,20 +5524,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;
@@ -5748,7 +5571,7 @@ 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))
{
@@ -5773,28 +5596,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();
+ }
}
/*
@@ -5816,7 +5658,7 @@ 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();
diff --git a/src/xtra2.hpp b/src/xtra2.hpp
new file mode 100644
index 00000000..cb16f6d9
--- /dev/null
+++ b/src/xtra2.hpp
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_race_fwd.hpp"
+#include "object_type_fwd.hpp"
+#include "player_race_mod_fwd.hpp"
+
+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(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 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..b9a78fca 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 */
@@ -762,29 +681,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 +700,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..61702432 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"
*/
@@ -32,23 +29,12 @@ 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.h b/src/z-rand.h
index 39cc958c..ba17dabe 100644
--- a/src/z-rand.h
+++ b/src/z-rand.h
@@ -1,7 +1,4 @@
-/* File: z-rand.h */
-
-#ifndef INCLUDED_Z_RAND_H
-#define INCLUDED_Z_RAND_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -91,6 +88,3 @@ extern s32b maxroll(s16b num, s16b sides);
#ifdef __cplusplus
} /* extern "C" */
#endif
-
-
-#endif
diff --git a/src/z-term.c b/src/z-term.c
index 4e89ffb7..891c10f3 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,10 @@
*
* 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
@@ -211,26 +195,13 @@
* 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.
+ * of the "always_text" flag 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 +225,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 +236,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 +284,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 +319,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 +342,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 */
@@ -498,18 +395,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 +405,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 +429,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 +445,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;
@@ -711,321 +478,6 @@ 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()"
- */
-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));
- }
- }
-}
-
-
/*
* Flush a row of the current window (see "Term_fresh")
*
@@ -1172,21 +624,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 +649,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
@@ -1233,10 +661,6 @@ static void Term_fresh_row_text(int y, int x1, int x2)
* 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.
@@ -1298,7 +722,6 @@ errr Term_fresh(void)
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" */
@@ -1307,16 +730,6 @@ errr Term_fresh(void)
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;
- }
-
/* Physically erase the entire window */
Term_xtra(TERM_XTRA_CLEAR, 0);
@@ -1329,25 +742,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,32 +782,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)
+ if (oa || Term->always_text)
{
(void)((*Term->text_hook)(tx, ty, 1, oa, &oc));
}
@@ -1460,40 +836,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 +977,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 +1011,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++;
@@ -1788,12 +1136,6 @@ errr Term_erase(int x, int y, int n)
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 +1146,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 +1165,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;
@@ -1886,23 +1216,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 +1248,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 +1302,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 +1329,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);
@@ -2156,14 +1474,6 @@ errr Term_inkey(char *ch, bool_ wait, bool_ take)
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 */
-
/* Wait */
if (wait)
{
@@ -2218,7 +1528,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 +1551,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 +1579,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);
@@ -2327,52 +1637,10 @@ errr Term_load_from(term_win *save, bool_ final)
/* 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;
+ free(save);
}
- /* Assume change */
- Term->y1 = 0;
- Term->y2 = h - 1;
-
/* Success */
return (0);
}
@@ -2392,7 +1660,6 @@ 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);
@@ -2402,8 +1669,7 @@ errr Term_resize(int w, int h)
/* 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 +1688,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 +1702,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 +1714,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 +1723,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 +1744,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 +1758,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 +1865,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 +1882,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 +1912,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 +1922,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 +1930,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);
@@ -2735,42 +1972,3 @@ errr term_init(term *t, int w, int h, int k)
/* 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..a52a5c27 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"
*
@@ -98,23 +74,12 @@ struct term_win
* - 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"
@@ -151,8 +116,6 @@ 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
@@ -168,35 +131,23 @@ 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,14 +162,11 @@ 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);
@@ -229,14 +177,36 @@ struct term
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 +221,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 +230,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 +262,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);
@@ -326,8 +279,6 @@ extern term_win* Term_save_to(void);
extern errr Term_load(void);
extern errr Term_load_from(term_win *save, bool_ final);
-extern errr Term_exchange(void);
-
extern errr Term_resize(int w, int h);
extern errr Term_activate(term *t);
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 92632080..00000000
--- a/src/z-virt.c
+++ /dev/null
@@ -1,145 +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"
-
-
-/*
- * 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);
-
- /* 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));
-
- /* 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 58aed382..00000000
--- a/src/z-virt.h
+++ /dev/null
@@ -1,164 +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"
-
-/*
- * 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