From: Martin Read Date: Sat, 15 Feb 2014 12:31:21 +0000 (+0000) Subject: Rearrangement and cleanup X-Git-Tag: stretchy-levels~13 X-Git-Url: http://git.blackswordsonics.com/?a=commitdiff_plain;h=87ac49cc5cf26ed091cf43cd417a1ba39fd5f15b;p=victrix-abyssi Rearrangement and cleanup * MANIFEST, Makefile: Add coord.cc, poke dependencies * coord.cc: New file to house coordinate/offset constants. * default.permons: Set power values for new demons * map.cc: Clean up stale code accessing stale members of Level * map.hh: Prune stale members from Level; add Doxygen comments * permon.hh, permobj.hh: De-confusing sloccount * rng.cc: Relocate random_step() from main.cc * u.cc: Relocate do_player_action() from main.cc * victrix-abyssi.hh: Relocate save_game() prototype from main.cc --- diff --git a/MANIFEST b/MANIFEST index d576661..ba2f42d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -6,6 +6,7 @@ Doxyfile man/victrix-abyssi.6 combat.cc combat.hh +coord.cc coord.hh core.hh default.permobjs diff --git a/Makefile b/Makefile index 151f64b..a5de63c 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:=combat.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 sorcery.o u.o util.o +HANDWRITTEN_OBJS:=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 sorcery.o u.o util.o OBJS:=$(GENERATED_OBJS) $(HANDWRITTEN_OBJS) GAME:=victrix-abyssi MAJVERS:=0 @@ -95,13 +95,15 @@ permons.cc pmon_id.hh: $(srcdir)/default.permons $(srcdir)/pmon_comp ## Dependencies for the build combat.o: $(srcdir)/combat.cc $(srcdir)/combat.hh $(srcdir)/victrix-abyssi.hh $(srcdir)/monsters.hh $(srcdir)/objects.hh $(srcdir)/notify.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh +coord.o: $(srcdir)/coord.cc $(srcdir)/coord.hh + display-nc.o: $(srcdir)/display-nc.cc $(srcdir)/victrix-abyssi.hh $(srcdir)/display.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh log.o: $(srcdir)/log.cc $(srcdir)/objects.hh $(srcdir)/monsters.hh $(srcdir)/player.hh $(srcdir)/map.hh $(srcdir)/util.h main.o: $(srcdir)/main.cc $(srcdir)/combat.hh $(srcdir)/victrix-abyssi.hh $(srcdir)/monsters.hh $(srcdir)/notify.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh -map.o: $(srcdir)/map.cc $(srcdir)/victrix-abyssi.hh $(srcdir)/notify.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh +map.o: $(srcdir)/map.cc $(srcdir)/victrix-abyssi.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)/victrix-abyssi.hh $(srcdir)/monsters.hh $(srcdir)/notify.hh $(srcdir)/objects.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh @@ -109,14 +111,9 @@ mon2.o: $(srcdir)/mon2.cc $(srcdir)/victrix-abyssi.hh $(srcdir)/sorcery.hh $(src notify-local-tty.o: $(srcdir)/notify-local-tty.cc $(srcdir)/victrix-abyssi.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 -# NOTICE: $(srcdir)/permobj.cc does not depend on ./pobj_id.hh because they are both -# generated from the same input file and should not be hand-edited. If you -# file a bug report over this, I will close it NOTABUG; if you submit a -# patch to add such a dependency, I will reject it out of hand. - -permobj.o: $(srcdir)/permobj.cc $(srcdir)/core.hh $(srcdir)/permobj.hh ./pobj_id.hh +permobj.o: ./permobj.cc $(srcdir)/core.hh $(srcdir)/permobj.hh -permons.o: $(srcdir)/permons.cc $(srcdir)/core.hh $(srcdir)/permon.hh ./pmon_id.hh +permons.o: ./permons.cc $(srcdir)/core.hh $(srcdir)/permon.hh pmon2.o: $(srcdir)/pmon2.cc $(srcdir)/victrix-abyssi.hh $(srcdir)/notify.hh $(srcdir)/monsters.hh ./pobj_id.hh ./pmon_id.hh $(srcdir)/player.hh diff --git a/coord.cc b/coord.cc new file mode 100644 index 0000000..b9a60f0 --- /dev/null +++ b/coord.cc @@ -0,0 +1,57 @@ +/* \file coord.cc + * \brief Positions and offsets - common constants + */ + +/* 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 "coord.hh" +#include + +/* Coord/Offset constants */ + +/*! \brief A Coord representing an invalid location */ +Coord const Nowhere = { INT_MIN, INT_MIN }; +/*! \brief One step northward */ +Offset const North = { -1, 0 }; +/*! \brief One step northeast */ +Offset const Northeast = { -1, 1 }; +/*! \brief One step east */ +Offset const East = { 0, 1 }; +/*! \brief One step southeast */ +Offset const Southeast = { 1, 1 }; +/*! \brief One step south */ +Offset const South = { 1, 0 }; +/*! \brief One step southwest */ +Offset const Southwest = { 1, -1 }; +/*! \brief One step west */ +Offset const West = { 0, -1 }; +/*! \brief One step northwest */ +Offset const Northwest = { -1, -1 }; +/*! \brief The additive identity offset */ +Offset const Stationary = { 0, 0 }; + +/* coord.cc */ +// vim:cindent diff --git a/default.permons b/default.permons index 7201328..8fbdb5a 100644 --- a/default.permons +++ b/default.permons @@ -468,6 +468,7 @@ ascii '1' utf8 "1" colour l_green rarity 90 +power 30 hp 250 mhit 20 mdam 20 @@ -485,6 +486,7 @@ ascii '1' utf8 "1" colour purple rarity 90 +power 30 hp 150 mhit 50 mdam 10 @@ -502,6 +504,7 @@ ascii '1' utf8 "1" colour iron rarity 90 +power 30 hp 300 mhit 30 mdam 30 diff --git a/main.cc b/main.cc index 3544227..fc93498 100644 --- a/main.cc +++ b/main.cc @@ -2,7 +2,7 @@ * \brief main core of Victrix Abyssi */ -/* Copyright 2005-2013 Martin Read +/* Copyright 2005-2014 Martin Read * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,280 +43,17 @@ #include #include -/* Coord/Offset constants */ -Coord const Nowhere = { INT_MIN, INT_MIN }; -Offset const North = { -1, 0 }; -Offset const Northeast = { -1, 1 }; -Offset const East = { 0, 1 }; -Offset const Southeast = { 1, 1 }; -Offset const South = { 1, 0 }; -Offset const Southwest = { 1, -1 }; -Offset const West = { 0, -1 }; -Offset const Northwest = { -1, -1 }; -Offset const Stationary = { 0, 0 }; - -void save_game(void); static void main_loop(void); bool game_finished; int32_t game_tick; bool wizard_mode = WIZARD_MODE; -/*! \brief pick a random Chebyshev cardinal - */ -Offset random_step(void) -{ - switch (zero_die(8)) - { - case 0: - return Northwest; - case 1: - return North; - case 2: - return Northwest; - case 3: - return West; - case 4: - return East; - case 5: - return Southwest; - case 6: - return South; - case 7: - return Southeast; - } - return Stationary; -} - void new_game(char const *name) { u_init(name); make_new_level(); } -std::deque past_actions; - -enum Combo_phase -{ - Combo_invalid, - Combo_link, - Combo_finisher -}; - -/* \brief Process action combos - * - * This function is responsible for detecting whether the most recently - * attempted action is a possible step in a combo, a combo finisher, or a - * combo-invalid move (for example, quaffing a potion is a combo breaker). It - * uses the contents of the deque past_actions to make the decision. - * - * \param act Pointer to attempted action - * \param revised_act Pointer to storage location for revised action - * \return true if revised_act was written to; false otherwise - */ - -bool detect_combo(Action const *act, Action *revised_act) -{ - //Combo_phase p; - // for now, we use if rather than switch because there are only two - // valid action types in a combo: move, and attack. - if (act->cmd == WALK) - { - *revised_act = *act; - return true; - } - else if (act->cmd == ATTACK) - { - *revised_act = *act; - return true; - } - else - { - return false; - } -} - -Action_cost do_player_action(Action *act) -{ - int slot; - Offset step; - Action redact; - bool rewritten = detect_combo(act, &redact); - if (rewritten) - { - act = &redact; - } - switch (act->cmd) - { - 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(); - return Cost_none; - - case ALLOCATE_SKILL_POINT: - 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(slot, Noise_std); - } - break; - - case WEAR_ARMOUR: - slot = act->details[0]; - return wear_armour(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_DOWN_STAIRS: - if (lvl.terrain_at(u.pos) == STAIRS) - { - 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; -} - void main_loop(void) { int i; @@ -379,6 +116,8 @@ void main_loop(void) } } +/*! \brief main() + */ int main(void) { load_config(); @@ -393,4 +132,4 @@ int main(void) } /* main.cc */ -// vim:cindent +// vim:cindent:expandtab diff --git a/map.cc b/map.cc index 332f918..406b0e1 100644 --- a/map.cc +++ b/map.cc @@ -124,10 +124,6 @@ Coord Level::random_point(int margin) const void leave_level(void) { int i; - memset(lvl.objs, -1, sizeof lvl.objs); - memset(lvl.mons, -1, sizeof lvl.mons); - memset(lvl.terrain, 0, sizeof lvl.terrain); - memset(lvl.flags, 0, sizeof lvl.flags); for (i = 0; i < 100; i++) { /* Throw away each monster */ diff --git a/map.hh b/map.hh index 724bba3..28dfaee 100644 --- a/map.hh +++ b/map.hh @@ -129,18 +129,13 @@ public: class Level { public: - Chunk ***chunks; - Offset origin_off; - int chunks_high; - int chunks_wide; - int objs[DUN_HEIGHT][DUN_WIDTH]; - int mons[DUN_HEIGHT][DUN_WIDTH]; - Terrain terrain[DUN_HEIGHT][DUN_WIDTH]; - uint32_t flags[DUN_HEIGHT][DUN_WIDTH]; - uint32_t region_number[CHUNK_EDGE][CHUNK_EDGE]; - Terrain dead_space; - level_theme theme; - level_layout layout; + Chunk ***chunks; //!< 16x16 subsections of the level, not necessarily dense + Offset origin_off; //!< Don't force a map size change to recalculate all Coords + int chunks_high; //!< Chunkwise size of level in the y-direction + int chunks_wide; //!< Chunkwise size of level in the x-direction + Terrain dead_space; //!< Terrain to fill new chunks with and return for Coords in unpopulated chunks + level_theme theme; //!< Will affect monster and maybe item generation + level_layout layout; //!< Determines generation algorithm Terrain terrain_at(Coord c) const { Coord rc = c + origin_off; diff --git a/permobj.hh b/permobj.hh index 84fe02d..b77d87d 100644 --- a/permobj.hh +++ b/permobj.hh @@ -67,7 +67,8 @@ enum poclass_num { #define POF_DRESS 0x00010000u /*! \brief The 'permanent object' database */ -struct Permobj { +class Permobj { +public: char const *name; //!< English-language name of item char const *plural; //!< English-language plural of item char const *description; //!< English-language description of item diff --git a/permon.hh b/permon.hh index 9b8c058..0fc6fcb 100644 --- a/permon.hh +++ b/permon.hh @@ -33,7 +33,6 @@ #include "core.hh" #endif -/* XXX struct permon */ #include "pmon_id.hh" #define PMF_RESIST_FIRE 0x00000001 @@ -61,7 +60,9 @@ #define PMF_SMALL 0x80000000 #define PERMON_FLAG_FIELDS 2 -struct Permon { +/*! \brief Describes the baseline stats of a specific kind of monster */ +class Permon { +public: char const *name; char const *plural; char const *description; diff --git a/rng.cc b/rng.cc index 18324da..6647a43 100644 --- a/rng.cc +++ b/rng.cc @@ -139,5 +139,30 @@ int one_die(int sides) return rval; } +/*! \brief pick a random Chebyshev cardinal */ +Offset random_step(void) +{ + switch (zero_die(8)) + { + case 0: + return Northwest; + case 1: + return North; + case 2: + return Northwest; + case 3: + return West; + case 4: + return East; + case 5: + return Southwest; + case 6: + return South; + case 7: + return Southeast; + } + return Stationary; +} + /* rng.cc */ // vim:cindent diff --git a/u.cc b/u.cc index 88f3b83..74ce705 100644 --- a/u.cc +++ b/u.cc @@ -1,9 +1,9 @@ /*! \file u.cc - * \brief player-character + * \brief Player-character functions and data */ /* - * Copyright 2005-2013 Martin Read + * Copyright 2005-2014 Martin Read * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,6 +33,7 @@ #include #include #include +#include struct Player u; @@ -526,6 +527,233 @@ bool Player::resists(Damtyp dtype) const return resistances[dtype]; } -// vim:cindent -/* u.c */ -// vim:cindent +/*! \brief Action history for combo detection */ +std::deque past_actions; + +/*! \brief Constants used in combo detection logic */ +enum Combo_phase +{ + Combo_invalid, + Combo_link, + Combo_finisher +}; + +/* \brief Process action combos + * + * This function is responsible for detecting whether the most recently + * attempted action is a possible step in a combo, a combo finisher, or a + * combo-invalid move (for example, quaffing a potion is a combo breaker). It + * uses the contents of the deque past_actions to make the decision. + * + * \todo Actually detect some combos + * \param act Pointer to attempted action + * \param revised_act Pointer to storage location for revised action + * \return true if revised_act was written to; false otherwise + */ + +bool detect_combo(Action const *act, Action *revised_act) +{ + //Combo_phase p; + // for now, we use if rather than switch because there are only two + // valid action types in a combo: move, and attack. + if (act->cmd == WALK) + { + *revised_act = *act; + return true; + } + else if (act->cmd == ATTACK) + { + *revised_act = *act; + return true; + } + else + { + return false; + } +} + +/*! \brief Process a player action. */ +Action_cost do_player_action(Action *act) +{ + int slot; + Offset step; + Action redact; + bool rewritten = detect_combo(act, &redact); + if (rewritten) + { + act = &redact; + } + switch (act->cmd) + { + 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(); + return Cost_none; + + case ALLOCATE_SKILL_POINT: + 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(slot, Noise_std); + } + break; + + case WEAR_ARMOUR: + slot = act->details[0]; + return wear_armour(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_DOWN_STAIRS: + if (lvl.terrain_at(u.pos) == STAIRS) + { + 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; +} + +/* u.cc */ +// vim:cindent:expandtab diff --git a/victrix-abyssi.hh b/victrix-abyssi.hh index ed7ffd1..39572a2 100644 --- a/victrix-abyssi.hh +++ b/victrix-abyssi.hh @@ -85,6 +85,7 @@ extern void load_config(void); extern void wrapped_system(char const *cmd); extern void wrapped_fread(void *buf, size_t size, size_t nmemb, FILE *stream); extern int load_game(void); +extern void save_game(void); #endif