From c029ecb267a4094852bb2cbef3b0bfa8b8b35134 Mon Sep 17 00:00:00 2001 From: Martin Read Date: Mon, 10 Mar 2014 17:43:18 +0000 Subject: [PATCH] More switch-slaying, some thematic changes * level connections are now magic portals rather than stairs * some switches are now table searches (maybe someday I'll make them efficient) * all sorts of bugslay associated with the above --- MANIFEST | 7 +- Makefile | 14 ++- cave.cc | 4 +- core.hh | 2 + deeds.cc | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++ display-nc.cc | 35 +++--- map.cc | 2 + map.hh | 2 +- mon1.cc | 88 +-------------- mon3.cc | 112 +++++++++++++++++++ monsters.hh | 9 +- notify-local-tty.cc | 7 +- notify.hh | 1 + obj1.cc | 57 +--------- obj2.cc | 89 ++++++++++++++++ objects.hh | 15 +++ player.hh | 5 +- u.cc | 195 ++------------------------------- 18 files changed, 596 insertions(+), 350 deletions(-) create mode 100644 deeds.cc create mode 100644 mon3.cc create mode 100644 obj2.cc diff --git a/MANIFEST b/MANIFEST index d0f0f08..c73258c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -10,6 +10,7 @@ combat.hh coord.cc coord.hh core.hh +deeds.cc default.permobjs default.permons display.hh @@ -21,14 +22,16 @@ main.cc map.cc map.hh mapgen.hh +mon1.cc mon2.cc -monsters.cc +mon3.cc monsters.hh notes.txt notify.hh notify-local-tty.cc -objects.cc objects.hh +obj1.cc +obj2.cc permobj.hh permon.hh player.hh diff --git a/Makefile b/Makefile index 4959542..7fa3a1c 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ vpath %.o . GENERATED_OBJS:=permobj.o permons.o GENERATED_SOURCE:=permobj.cc pobj_id.hh permons.cc pmon_id.hh GENERATED_MAKES:=dirs.mk features.mk -HANDWRITTEN_OBJS:=cave.o combat.o coord.o display-nc.o fov.o log.o main.o map.o monsters.o mon2.o notify-local-tty.o objects.o pmon2.o rng.o shrine.o sorcery.o u.o util.o +HANDWRITTEN_OBJS:=cave.o combat.o coord.o deeds.o display-nc.o fov.o log.o main.o map.o mon1.o mon2.o mon3.o notify-local-tty.o obj1.o obj2.o pmon2.o rng.o shrine.o sorcery.o u.o util.o OBJS:=$(GENERATED_OBJS) $(HANDWRITTEN_OBJS) GAME:=obumbrata MAJVERS:=1 @@ -99,6 +99,8 @@ combat.o: $(srcdir)/combat.cc $(srcdir)/combat.hh $(srcdir)/$(GAME).hh $(srcdir) coord.o: $(srcdir)/coord.cc $(srcdir)/coord.hh +deeds.o: $(srcdir)/deeds.cc $(srcdir)/combat.hh $(srcdir)/$(GAME).hh $(srcdir)/notify.hh $(srcdir)/monsters.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh + display-nc.o: $(srcdir)/display-nc.cc $(srcdir)/$(GAME).hh $(srcdir)/display.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh $(srcdir)/map.hh $(srcdir)/objects.hh $(srcdir)/monsters.hh $(srcdir)/permon.hh $(srcdir)/permobj.hh log.o: $(srcdir)/log.cc $(srcdir)/objects.hh $(srcdir)/monsters.hh $(srcdir)/player.hh $(srcdir)/map.hh $(srcdir)/util.h @@ -107,9 +109,11 @@ main.o: $(srcdir)/main.cc $(srcdir)/combat.hh $(srcdir)/$(GAME).hh $(srcdir)/mon map.o: $(srcdir)/map.cc $(srcdir)/$(GAME).hh $(srcdir)/map.hh $(srcdir)/core.hh $(srcdir)/notify.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh -monsters.o: $(srcdir)/monsters.cc $(srcdir)/$(GAME).hh $(srcdir)/monsters.hh $(srcdir)/notify.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh +mon1.o: $(srcdir)/mon1.cc $(srcdir)/$(GAME).hh $(srcdir)/monsters.hh $(srcdir)/notify.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh + +mon2.o: $(srcdir)/mon2.cc $(srcdir)/$(GAME).hh $(srcdir)/sorcery.hh $(srcdir)/monsters.hh $(srcdir)/map.hh $(srcdir)/notify.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh -mon2.o: $(srcdir)/mon2.cc $(srcdir)/$(GAME).hh $(srcdir)/sorcery.hh $(srcdir)/monsters.hh $(srcdir)/notify.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh +mon3.o: $(srcdir)/mon3.cc $(srcdir)/$(GAME).hh $(srcdir)/monsters.hh $(srcdir)/notify.hh $(srcdir)/map.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh notify-local-tty.o: $(srcdir)/notify-local-tty.cc $(srcdir)/$(GAME).hh $(srcdir)/combat.hh $(srcdir)/monsters.hh $(srcdir)/notify.hh $(srcdir)/objects.hh $(srcdir)/sorcery.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh @@ -119,7 +123,9 @@ permons.o: ./permons.cc $(srcdir)/core.hh $(srcdir)/permon.hh pmon2.o: $(srcdir)/pmon2.cc $(srcdir)/$(GAME).hh $(srcdir)/notify.hh $(srcdir)/monsters.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh -objects.o: $(srcdir)/objects.cc $(srcdir)/$(GAME).hh $(srcdir)/notify.hh $(srcdir)/objects.hh $(srcdir)/monsters.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh +obj1.o: $(srcdir)/obj1.cc $(srcdir)/$(GAME).hh $(srcdir)/notify.hh $(srcdir)/objects.hh $(srcdir)/monsters.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh + +obj2.o: $(srcdir)/obj2.cc $(srcdir)/$(GAME).hh $(srcdir)/notify.hh $(srcdir)/objects.hh $(srcdir)/monsters.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh shrine.o: $(srcdir)/shrine.cc $(srcdir)/$(GAME).hh $(srcdir)/notify.hh $(srcdir)/objects.hh $(srcdir)/monsters.hh $(srcdir)/map.hh $(srcdir)/mapgen.hh sorcery.o: $(srcdir)/sorcery.cc $(srcdir)/$(GAME).hh $(srcdir)/notify.hh $(srcdir)/sorcery.hh $(srcdir)/objects.hh $(srcdir)/monsters.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh diff --git a/cave.cc b/cave.cc index e5d8c5d..fff560b 100644 --- a/cave.cc +++ b/cave.cc @@ -41,7 +41,7 @@ void place_cave_stairs(Level *l) c = l->random_point(1); } while (!(terrain_props[l->terrain_at(c)].flags & TFLAG_floor) || (l->flags_at(c) & MAPFLAG_HARDWALL)); - l->add_stairs_at(c, STAIRS_DOWN, l->self.naive_next()); + l->add_stairs_at(c, PORTAL_ONWARD, l->self.naive_next()); do { d = l->random_point(1); @@ -49,7 +49,7 @@ void place_cave_stairs(Level *l) } while (!(terrain_props[l->terrain_at(d)].flags & TFLAG_floor) || (l->flags_at(d) & MAPFLAG_HARDWALL) || (d.dist_cheb(c) < (10 - (stair_tries / 40)))); - l->add_stairs_at(d, STAIRS_UP, l->self.naive_prev()); + l->add_stairs_at(d, PORTAL_LANDING, l->self.naive_prev()); } /*! \brief Excavate a cave level. diff --git a/core.hh b/core.hh index 9e88c8b..4117e36 100644 --- a/core.hh +++ b/core.hh @@ -122,6 +122,8 @@ enum Game_cmd { /* combos begin here */ CMD_POWER_ATTACK }; +#define LAST_COMMAND (CMD_POWER_ATTACK) +#define NUM_COMMANDS (1 + LAST_COMMAND) /*! \brief Identification code for ways to die * diff --git a/deeds.cc b/deeds.cc new file mode 100644 index 0000000..a144801 --- /dev/null +++ b/deeds.cc @@ -0,0 +1,302 @@ +/*! \file deeds.cc + * \brief Player-character action implementations + */ + +/* + * Copyright © 2014 Martin Read + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "obumbrata.hh" +#include "combat.hh" +#include "objects.hh" +#include "player.hh" +#include +#include +#include +#include + +static Action_cost deed_walk(Action const *act) +{ + Offset step = { (int32_t) act->details[0], (int32_t) act->details[1] }; + return move_player(step); +} + +static Action_cost deed_stand_still(Action const *act) +{ + return Cost_std; +} + +static Action_cost deed_ascend(Action const *act) +{ + Terrain t = lvl.terrain_at(u.pos); + if (terrain_props[t].flags & TFLAG_portal) + { + if (terrain_props[t].flags & TFLAG_ascend) + { + notify_inert_portal(); + } + else + { + leave_level(); + make_new_level(); + } + } + else + { + if (terrain_props[t].flags & TFLAG_ascend) + { + notify_ascent_blocked(); + } + else + { + debug_ascend_non_stairs(); + } + } + return Cost_none; +} + +static Action_cost deed_descend(Action const *act) +{ + Terrain t = lvl.terrain_at(u.pos); + if (terrain_props[t].flags & TFLAG_descend) + { + leave_level(); + make_new_level(); + } + else + { + debug_descend_non_stairs(); + } + return Cost_none; +} + +static Action_cost deed_attack(Action const *act) +{ + Offset step = { (int32_t) act->details[0], (int32_t) act->details[1] }; + return player_attack(step); +} + +static Action_cost deed_get(Action const *act) +{ + if (lvl.obj_at(u.pos) != NO_OBJ) + { + attempt_pickup(); + return Cost_std; + } + else + { + notify_nothing_to_get(); + return Cost_none; + } +} + +static Action_cost deed_drop(Action const *act) +{ + int slot = (int) act->details[0]; + return drop_obj(slot); +} + +static Action_cost deed_wield(Action const *act) +{ + int slot = (int) act->details[0]; + if (slot == SLOT_NOTHING) + { + return player_unwield(Noise_std); + } + else + { + return player_wield(u.inventory[slot], Noise_std); + } +} + +static Action_cost deed_armour_on(Action const *act) +{ + int slot = (int) act->details[0]; + return wear_armour(u.inventory[slot]); +} + +static Action_cost deed_armour_off(Action const *act) +{ + if (u.armour != NO_OBJ) + { + /* this actually belongs in a sensible place. */ + int saved_armour = u.armour; + if ((u.resistances[DT_FIRE] == RESIST_ARMOUR) && + (lvl.terrain_at(u.pos) == LAVA)) + { + notify_lava_blocks_unequip(); + return Cost_none; + } + u.armour = NO_OBJ; + recalc_defence(); + notify_armour_unequip(saved_armour); + return Cost_std; + } + else + { + debug_take_off_no_armour(); + return Cost_none; + } +} + +static Action_cost deed_ring_on(Action const *act) +{ + int slot = act->details[0]; + return put_on_ring(u.inventory[slot]); +} + +static Action_cost deed_ring_off(Action const *act) +{ + return remove_ring(); +} + +static Action_cost deed_quaff(Action const *act) +{ + int slot = act->details[0]; + return quaff_potion(u.inventory[slot]); +} + +static Action_cost deed_read(Action const *act) +{ + int slot = act->details[0]; + return read_scroll(u.inventory[slot]); +} + +static Action_cost deed_ringmagic(Action const *act) +{ + if (u.ring == NO_OBJ) + { + notify_magic_no_ring(); + return Cost_none; + } + return magic_ring(); +} + +static Action_cost deed_zap(Action const *act) +{ + if (u.weapon == NO_OBJ) + { + notify_zap_no_weapon(); + return Cost_none; + } + return zap_weapon(); +} + +static Action_cost deed_emanate(Action const *act) +{ + if (u.armour == NO_OBJ) + { + notify_emanate_no_armour(); + return Cost_none; + } + return emanate_armour(); +} + +static Action_cost deed_eat(Action const *act) +{ + int slot = act->details[0]; + return eat_food(u.inventory[slot]); +} + +static Action_cost deed_combo_powatk(Action const *act) +{ + Offset step = { (int32_t) act->details[0], (int32_t) act->details[1] }; + return player_power_attack(step); +} + +static Action_cost deed_wiz_descend(Action const *act) +{ + if (wizard_mode) + { + leave_level(); + make_new_level(); + } + else + { + debug_wizmode_violation(); + } + return Cost_none; +} + +static Action_cost deed_wiz_levup(Action const *act) +{ + if (wizard_mode) + { + if (lev_threshold(u.level) != INT_MAX) + { + gain_experience((lev_threshold(u.level) - u.experience) + 1); + } + } + else + { + debug_wizmode_violation(); + } + return Cost_none; +} + +static Action_cost deed_quit(Action const *act) +{ + game_finished = 1; + return Cost_none; +} + +static Action_cost deed_save(Action const *act) +{ + game_finished = 1; + save_game(); + return Cost_none; +} + +deed_func deed_funcs[NUM_COMMANDS] = +{ + deed_walk, + deed_stand_still, + deed_ascend, + deed_descend, + deed_attack, + deed_get, + deed_drop, + deed_wield, + deed_armour_on, + deed_armour_off, + deed_ring_on, + deed_ring_off, + deed_quaff, + deed_read, + nullptr, // deed_throw + deed_eat, + deed_emanate, + deed_zap, + deed_ringmagic, + nullptr, // deed_use_skill + nullptr, // deed_alloc_skill + deed_save, + deed_quit, + deed_wiz_levup, + deed_wiz_descend, + deed_combo_powatk +}; + +/* deeds.cc */ +// vim:cindent:expandtab diff --git a/display-nc.cc b/display-nc.cc index 1716361..2bd3722 100644 --- a/display-nc.cc +++ b/display-nc.cc @@ -1298,17 +1298,29 @@ void get_player_action(Action *act) break; case '<': { - Terrain t = lvl.terrain_at(u.pos); - if (terrain_props[t].flags & TFLAG_ascend) + Terrain t = lvl.terrain_at(u.pos); + if (terrain_props[t].flags & TFLAG_portal) + { + if (terrain_props[t].flags & TFLAG_ascend) + { + act->cmd = GO_UP_STAIRS; + return; + } + else + { + act->cmd = GO_DOWN_STAIRS; + return; + } + } + else if (terrain_props[t].flags & TFLAG_ascend) { - act->cmd = GO_UP_STAIRS; - return; + act->cmd = GO_UP_STAIRS; + return; } else { - print_msg("There are no stairs here.\n"); + print_msg("There are no portals or upward stairs here.\n"); } - // TODO accept this keystroke as "enter portal" too } break; case '>': @@ -1321,9 +1333,8 @@ void get_player_action(Action *act) } else { - print_msg("There are no stairs here.\n"); + print_msg("There are no stairs or portals here.\n"); } - // TODO accept this keystroke as "enter portal" too } break; case '5': @@ -1476,7 +1487,8 @@ void print_help(void) print_msg("e eat something edible\n"); print_msg("g pick up an item (also 0 or comma)\n"); print_msg("d drop an item\n"); - print_msg("> go down stairs\n"); + print_msg("< go down stairs or enter a magic portal\n"); + print_msg("> go down stairs or enter a magic portal\n"); print_msg("5 do nothing (wait until next action)\n"); print_msg(". do nothing (wait until next action)\n"); print_msg("\nPress any key to continue...\n"); @@ -1485,8 +1497,7 @@ void print_help(void) print_msg("z activate your weapon's magical power (if any)\n"); print_msg("m activate your ring's magical power (if any)\n"); print_msg("E activate your armour's magical power (if any)\n"); - print_msg("\nPress any key to continue...\n"); - wgetch(message_window); + print_msg("\n"); print_msg("OTHER COMMANDS\n"); print_msg("S save and exit\n"); print_msg("X quit without saving\n"); @@ -1501,7 +1512,7 @@ void print_help(void) print_msg("SYMBOLS\n"); print_msg("@ you\n"); print_msg(". floor\n"); - print_msg("> stairs down\n"); + print_msg("☊ magic portal\n"); print_msg("# wall\n"); print_msg("+ a door\n"); print_msg(") a weapon\n"); diff --git a/map.cc b/map.cc index 6331846..a132974 100644 --- a/map.cc +++ b/map.cc @@ -659,6 +659,8 @@ Terrain_props terrain_props[NUM_TERRAINS] = { "altar", '_', "_", Gcol_l_grey, 0 }, { "upward stairs", '<', "<", Gcol_l_grey, TFLAG_ascend }, { "downward stairs", '>', ">", Gcol_l_grey, TFLAG_descend }, + { "inert portal", '^', "☊", Gcol_d_grey, TFLAG_portal | TFLAG_ascend }, + { "active portal", '^', "☊", Gcol_white, TFLAG_portal | TFLAG_descend }, { "lava", '}', "≈", Gcol_red, TFLAG_fire_hazard }, { "water", '}', "≈", Gcol_blue, TFLAG_drown_hazard }, }; diff --git a/map.hh b/map.hh index 9be8a98..60a3ff1 100644 --- a/map.hh +++ b/map.hh @@ -36,7 +36,7 @@ #include /* XXX enum terrain_num */ enum Terrain { - WALL = 0, MASONRY_WALL, AMETHYST_WALL, IRON_WALL, SKIN_WALL, BONE_WALL, DOOR, FLOOR, AMETHYST_FLOOR, IRON_FLOOR, SKIN_FLOOR, BONE_FLOOR, ALTAR, STAIRS_UP, STAIRS_DOWN, LAVA, WATER + WALL = 0, MASONRY_WALL, AMETHYST_WALL, IRON_WALL, SKIN_WALL, BONE_WALL, DOOR, FLOOR, AMETHYST_FLOOR, IRON_FLOOR, SKIN_FLOOR, BONE_FLOOR, ALTAR, STAIRS_UP, STAIRS_DOWN, PORTAL_LANDING, PORTAL_ONWARD, LAVA, WATER }; #define MAX_TERRAIN (WATER) #define NUM_TERRAINS (1 + MAX_TERRAIN) diff --git a/mon1.cc b/mon1.cc index 04f8a59..7676b78 100644 --- a/mon1.cc +++ b/mon1.cc @@ -162,93 +162,7 @@ Mon_handle create_mon(int pm_idx, Coord c) return NO_MON; } -/* The rules: - * A monster gets eight entries. - */ - -struct Death_drop_entry -{ - int pm_ref; - void (*func)(Coord c); -}; - -void goblin_death_drop(Coord c) -{ - if (!zero_die(4)) - { - create_obj_near(PO_DAGGER, 1, c); - } -} - -void thug_death_drop(Coord c) -{ - if (!zero_die(4)) - { - create_obj_near(PO_MACE, 1, c); - } - else if (!zero_die(3)) - { - create_obj_near(PO_LEATHER_ARMOUR, 1, c); - } -} - -void hunter_death_drop(Coord c) -{ - if (!zero_die(6)) - { - create_obj_near(PO_BOW, 1, c); - } -} - -void duellist_death_drop(Coord c) -{ - if (!zero_die(6)) - { - create_obj_near(PO_LONG_SWORD, 1, c); - } -} - -void wizard_death_drop(Coord c) -{ - if (!zero_die(4)) - { - create_obj_class_near(POCLASS_SCROLL, 1, false, c); - } - else if (!zero_die(3)) - { - create_obj_class_near(POCLASS_POTION, 1, false, c); - } -} - -void warlord_death_drop(Coord c) -{ - if (!zero_die(3)) - { - create_obj_near(PO_RUNESWORD, 1, c); - } -} - -void demon_death_drop(Coord c) -{ - if (!zero_die(100)) - { - create_obj_near(PO_DEVIL_SPLEEN, 1, c); - } -} - -Death_drop_entry death_drops[] = -{ - { PM_GOBLIN, goblin_death_drop }, - { PM_THUG, thug_death_drop }, - { PM_GOON, thug_death_drop }, - { PM_HUNTER, hunter_death_drop }, - { PM_DUELLIST, duellist_death_drop }, - { PM_WIZARD, wizard_death_drop }, - { PM_WARLORD, warlord_death_drop }, - { PM_DEMON, demon_death_drop }, - { NO_PMON, nullptr } -}; - +/*! \brief Handle a monster's death drop. */ void death_drop(Mon_handle mon) { Mon const *mptr = mon_snap(mon); diff --git a/mon3.cc b/mon3.cc new file mode 100644 index 0000000..9212d3e --- /dev/null +++ b/mon3.cc @@ -0,0 +1,112 @@ +/*! \file mon3.cc + * \brief Death drop tables and similar things + */ + +/* Copyright © 2014 Martin Read + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define MON3_CC +#include "obumbrata.hh" +#include "monsters.hh" +#include "objects.hh" + +static void goblin_death_drop(Coord c) +{ + if (!zero_die(4)) + { + create_obj_near(PO_DAGGER, 1, c); + } +} + +static void thug_death_drop(Coord c) +{ + if (!zero_die(4)) + { + create_obj_near(PO_MACE, 1, c); + } + else if (!zero_die(3)) + { + create_obj_near(PO_LEATHER_ARMOUR, 1, c); + } +} + +static void hunter_death_drop(Coord c) +{ + if (!zero_die(6)) + { + create_obj_near(PO_BOW, 1, c); + } +} + +static void duellist_death_drop(Coord c) +{ + if (!zero_die(6)) + { + create_obj_near(PO_LONG_SWORD, 1, c); + } +} + +static void wizard_death_drop(Coord c) +{ + if (!zero_die(4)) + { + create_obj_class_near(POCLASS_SCROLL, 1, false, c); + } + else if (!zero_die(3)) + { + create_obj_class_near(POCLASS_POTION, 1, false, c); + } +} + +static void warlord_death_drop(Coord c) +{ + if (!zero_die(3)) + { + create_obj_near(PO_RUNESWORD, 1, c); + } +} + +static void demon_death_drop(Coord c) +{ + if (!zero_die(100)) + { + create_obj_near(PO_DEVIL_SPLEEN, 1, c); + } +} + +Death_drop_entry death_drops[] = +{ + { PM_GOBLIN, goblin_death_drop }, + { PM_THUG, thug_death_drop }, + { PM_GOON, thug_death_drop }, + { PM_HUNTER, hunter_death_drop }, + { PM_DUELLIST, duellist_death_drop }, + { PM_WIZARD, wizard_death_drop }, + { PM_WARLORD, warlord_death_drop }, + { PM_DEMON, demon_death_drop }, + { NO_PMON, nullptr } +}; + +/* mon3.cc */ +// vim:cindent diff --git a/monsters.hh b/monsters.hh index 8f634b9..d04a98b 100644 --- a/monsters.hh +++ b/monsters.hh @@ -81,9 +81,16 @@ inline Mon const *mon_snap(Mon_handle mon) return ((iter == monsters.end()) ? nullptr : &(iter->second)); } +struct Death_drop_entry +{ + int pm_ref; + void (*func)(Coord c); +}; + +extern Death_drop_entry death_drops[]; + #define PLAYER_MON (-2) -/* XXX monsters.c data and funcs */ void update_mon(Mon_handle mon); void mon_acts(Mon_handle mon); void death_drop(Mon_handle mon); diff --git a/notify-local-tty.cc b/notify-local-tty.cc index ecb5742..2a9585a 100644 --- a/notify-local-tty.cc +++ b/notify-local-tty.cc @@ -275,6 +275,11 @@ void notify_ascent_blocked(void) print_msg("A mysterious force prevents you climbing the stairs.\n"); } +void notify_inert_portal(void) +{ + print_msg("This side of the portal is completely inert.\n"); +} + void notify_wasted_gain(void) { print_msg("You feel disappointed.\n"); @@ -979,7 +984,7 @@ void notify_tick(void) void notify_change_of_depth(void) { status_updated = true; - print_msg("Welcome to level %d of the Abyss.\n", depth); + print_msg("Welcome to level %d.\n", depth); } void notify_load_complete(void) diff --git a/notify.hh b/notify.hh index 325e670..157aa98 100644 --- a/notify.hh +++ b/notify.hh @@ -163,6 +163,7 @@ void notify_tick(void); void notify_change_of_depth(void); void notify_load_complete(void); void notify_ascent_blocked(void); +void notify_inert_portal(void); // Debugging notifications void debug_move_oob(Coord c); diff --git a/obj1.cc b/obj1.cc index 0d5c014..c1fc9ca 100644 --- a/obj1.cc +++ b/obj1.cc @@ -200,67 +200,16 @@ Action_cost eat_food(Obj_handle obj) return Cost_std; } -/*! \brief Effect of quaffing a body potion */ -static void body_potion_quaff(void) -{ - gain_body(1); -} - -/*! \brief Effect of quaffing a agility potion */ -static void agility_potion_quaff(void) -{ - gain_agility(1); -} - -/*! \brief Effect of quaffing a healing potion */ -static void healing_potion_quaff(void) -{ - int healpercent = inc_flat(30, 50); - int healamount = (healpercent * ((u.hpmax > 60) ? u.hpmax : 60)) / 100; - heal_u(healamount, 1, 1); -} - -/*! \brief Effect of quaffing a restoration potion */ -static void restoration_potion_quaff(void) -{ - notify_quaff_potion_restoration(); - if (u.bdam && ((!u.adam) || zero_die(2))) - { - u.bdam = 0; - notify_body_restore(); - } - else if (u.adam) - { - u.adam = 0; - notify_agility_restore(); - } -} - -struct Potion_table_entry -{ - int pobj; - void (*quaff_func)(void); -}; - -static Potion_table_entry quaff_table[] = -{ - { PO_BODY_POTION, body_potion_quaff }, - { PO_AGILITY_POTION, agility_potion_quaff }, - { PO_HEALING_POTION, healing_potion_quaff }, - { PO_RESTORATION_POTION, restoration_potion_quaff }, - { NO_POBJ, nullptr }, -}; - /*! \brief Consume a potion */ Action_cost quaff_potion(Obj_handle obj) { Obj *optr = obj_snapv(obj); int i; - for (i = 0; quaff_table[i].pobj != NO_POBJ; ++i) + for (i = 0; potion_table[i].pobj != NO_POBJ; ++i) { - if (quaff_table[i].pobj == optr->po_ref) + if (potion_table[i].pobj == optr->po_ref) { - quaff_table[i].quaff_func(); + potion_table[i].quaff_func(); consume_obj(obj); return Cost_std; } diff --git a/obj2.cc b/obj2.cc new file mode 100644 index 0000000..382f08b --- /dev/null +++ b/obj2.cc @@ -0,0 +1,89 @@ +/* \file obj2.cc + * \brief Per-PO object use functions for Obumbrata et Velata + */ + +/* Copyright © 2014 Martin Read + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define OBJ2_CC +#include "obumbrata.hh" +#include "objects.hh" +#include "monsters.hh" + +#include + +/*! \brief Effect of quaffing a body potion */ +static void body_potion_quaff(void) +{ + gain_body(1); +} + +/*! \brief Effect of quaffing a agility potion */ +static void agility_potion_quaff(void) +{ + gain_agility(1); +} + +/*! \brief Effect of quaffing a healing potion */ +static void healing_potion_quaff(void) +{ + int healpercent = inc_flat(30, 50); + int healamount = (healpercent * ((u.hpmax > 60) ? u.hpmax : 60)) / 100; + heal_u(healamount, 1, 1); +} + +/*! \brief Effect of quaffing a restoration potion */ +static void restoration_potion_quaff(void) +{ + notify_quaff_potion_restoration(); + if (u.bdam && ((!u.adam) || zero_die(2))) + { + u.bdam = 0; + notify_body_restore(); + } + else if (u.adam) + { + u.adam = 0; + notify_agility_restore(); + } +} + +/*! \brief Lookup table for effects of operations involving potions */ +Potion_table_entry potion_table[] = +{ + { PO_BODY_POTION, body_potion_quaff }, + { PO_AGILITY_POTION, agility_potion_quaff }, + { PO_HEALING_POTION, healing_potion_quaff }, + { PO_RESTORATION_POTION, restoration_potion_quaff }, + { NO_POBJ, nullptr } +}; + +/*! \brief Lookup table for effects of reading scrolls */ +Scroll_table_entry scroll_table[] = +{ + { NO_POBJ, nullptr } +}; + +/* obj2.cc */ +// vim:cindent diff --git a/objects.hh b/objects.hh index be1a951..eb4c65f 100644 --- a/objects.hh +++ b/objects.hh @@ -56,6 +56,21 @@ public: extern std::map objects; extern Obj_handle first_free_obj_handle; +struct Potion_table_entry +{ + int pobj; + void (*quaff_func)(void); +}; +extern Potion_table_entry potion_table[]; + +struct Scroll_table_entry +{ + int pobj; + void (*read_func)(void); +}; + +extern Scroll_table_entry scroll_table[]; + /* XXX objects.cc data and funcs */ void asprint_obj_name(char **s, Obj_handle obj); void sprint_obj_name(char *s, Obj_handle obj, int len); diff --git a/player.hh b/player.hh index deb0864..de73524 100644 --- a/player.hh +++ b/player.hh @@ -79,9 +79,12 @@ public: #define SLOT_CANCEL (-1) #define SLOT_NOTHING (-2) -/* XXX u.c data and funcs */ extern Player u; +typedef Action_cost (*deed_func)(Action const *act); + +extern deed_func deed_funcs[NUM_COMMANDS]; + void u_init(char const *name); void write_char_dump(void); int do_death(Death d, char const *what); diff --git a/u.cc b/u.cc index b4fc5a7..48cda87 100644 --- a/u.cc +++ b/u.cc @@ -138,6 +138,8 @@ Action_cost move_player(Offset delta) case DOOR: case STAIRS_UP: case STAIRS_DOWN: + case PORTAL_LANDING: + case PORTAL_ONWARD: case ALTAR: reloc_player(c); return Cost_std; @@ -684,203 +686,26 @@ bool action_rewrite(Action const *act, Action *revised_act) */ Action_cost do_player_action(Action *act) { - int slot; - Offset step; Action redact; bool rewritten = action_rewrite(act, &redact); if (rewritten) { act = &redact; } - switch (act->cmd) + if (act->cmd == REJECTED_ACTION) { - case REJECTED_ACTION: return Cost_none; - - case CMD_POWER_ATTACK: - step.y = act->details[0]; - step.x = act->details[1]; - return player_power_attack(step); - - case WALK: - step.y = act->details[0]; - step.x = act->details[1]; - return move_player(step); - - case ATTACK: - step.y = act->details[0]; - step.x = act->details[1]; - return player_attack(step); - - case USE_ACTIVE_SKILL: - debug_unimplemented(); + } + if (act->cmd > LAST_COMMAND) + { return Cost_none; - - case ALLOCATE_SKILL_POINT: + } + if (deed_funcs[act->cmd] == nullptr) + { debug_unimplemented(); return Cost_none; - - case GET_ITEM: - if (lvl.obj_at(u.pos) != NO_OBJ) - { - attempt_pickup(); - return Cost_std; - } - else - { - notify_nothing_to_get(); - return Cost_none; - } - - case WIELD_WEAPON: - slot = act->details[0]; - if (slot == SLOT_NOTHING) - { - return player_unwield(Noise_std); - } - else - { - return player_wield(u.inventory[slot], Noise_std); - } - break; - - case WEAR_ARMOUR: - slot = act->details[0]; - return wear_armour(u.inventory[slot]); - - case EMANATE_ARMOUR: - if (u.armour == NO_OBJ) - { - notify_emanate_no_armour(); - return Cost_none; - } - return emanate_armour(); - - case ZAP_WEAPON: - if (u.weapon == NO_OBJ) - { - notify_zap_no_weapon(); - return Cost_none; - } - return zap_weapon(); - - case MAGIC_RING: - if (u.weapon == NO_OBJ) - { - notify_magic_no_ring(); - return Cost_none; - } - return magic_ring(); - - case TAKE_OFF_ARMOUR: - if (u.armour != NO_OBJ) - { - int saved_armour = u.armour; - if ((u.resistances[DT_FIRE] == RESIST_ARMOUR) && - (lvl.terrain_at(u.pos) == LAVA)) - { - notify_lava_blocks_unequip(); - return Cost_none; - } - u.armour = NO_OBJ; - recalc_defence(); - notify_armour_unequip(saved_armour); - return Cost_std; - } - else - { - debug_take_off_no_armour(); - return Cost_none; - } - - case GO_UP_STAIRS: - if (lvl.terrain_at(u.pos) == STAIRS_UP) - { - notify_ascent_blocked(); - } - else - { - debug_ascend_non_stairs(); - } - return Cost_none; - - case GO_DOWN_STAIRS: - if (lvl.terrain_at(u.pos) == STAIRS_DOWN) - { - leave_level(); - make_new_level(); - } - else - { - debug_descend_non_stairs(); - } - return Cost_none; - - case STAND_STILL: - return Cost_std; - - case READ_SCROLL: - slot = act->details[0]; - return read_scroll(u.inventory[slot]); - - case EAT_FOOD: - slot = act->details[0]; - return eat_food(u.inventory[slot]); - - case QUAFF_POTION: - slot = act->details[0]; - return quaff_potion(u.inventory[slot]); - - case THROW_FLASK: - return Cost_none; - - case REMOVE_RING: - return remove_ring(); - - case PUT_ON_RING: - slot = act->details[0]; - return put_on_ring(u.inventory[slot]); - - case DROP_ITEM: - slot = act->details[0]; - return drop_obj(slot); - - case SAVE_GAME: - game_finished = 1; - save_game(); - return Cost_none; - - case QUIT: - game_finished = 1; - return Cost_none; - - case WIZARD_DESCEND: - if (wizard_mode) - { - leave_level(); - make_new_level(); - } - else - { - debug_wizmode_violation(); - } - return Cost_none; - - case WIZARD_LEVELUP: - if (wizard_mode) - { - if (lev_threshold(u.level) != INT_MAX) - { - gain_experience((lev_threshold(u.level) - u.experience) + 1); - } - } - else - { - debug_wizmode_violation(); - } - return Cost_none; } - return Cost_none; + return deed_funcs[act->cmd](act); } void player_cleanup(void) -- 2.11.0