From b98200378bfe1f7567d8190e8af6a45587405c06 Mon Sep 17 00:00:00 2001 From: Martin Read Date: Sun, 9 Mar 2014 21:46:15 +0000 Subject: [PATCH] All sorts of fun and frolics with serialization mainly. Also, say hello to the blood elemental. --- Makefile | 4 ++-- default.permons | 19 +++++++++++++++++-- log.cc | 8 ++++++-- map.cc | 10 ++++++++-- monsters.hh | 1 + objects.cc | 28 ++++++++++++++++++---------- objects.hh | 1 + pmon_comp | 16 +++++++++++----- u.cc | 39 +++++++++++++++++++++++++-------------- 9 files changed, 89 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 9c22d89..4959542 100644 --- a/Makefile +++ b/Makefile @@ -18,9 +18,9 @@ PATCHVERS:=0 COMMON_CFLAGS:=-Wall -Wwrite-strings -Wunreachable-code -Wformat -Werror=format-security -fstack-protector --param=ssp-buffer-size=4 -DMAJVERS=$(MAJVERS) -DMINVERS=$(MINVERS) -DPATCHVERS=$(PATCHVERS)-std=gnu11 -D_FORTIFY_SOURCE=2 -I$(srcdir) COMMON_CXXFLAGS:=-Wall -Wwrite-strings -Wno-unused-but-set-variable -Wredundant-decls -Wunreachable-code -Wformat -Werror=format-security -fstack-protector --param=ssp-buffer-size=4 -DMAJVERS=$(MAJVERS) -DMINVERS=$(MINVERS) -DPATCHVERS=$(PATCHVERS) -std=gnu++11 -D_FORTIFY_SOURCE=2 -I$(srcdir) PRODUCTION_CFLAGS:=$(COMMON_CFLAGS) -O2 -DEVELOPMENT_CFLAGS:=$(COMMON_CFLAGS) -g -O1 -Werror +DEVELOPMENT_CFLAGS:=$(COMMON_CFLAGS) -g -Werror PRODUCTION_CXXFLAGS:=$(COMMON_CXXFLAGS) -O2 -DEVELOPMENT_CXXFLAGS:=$(COMMON_CXXFLAGS) -g -O1 -Werror +DEVELOPMENT_CXXFLAGS:=$(COMMON_CXXFLAGS) -g -Werror LIBS=-lpanelw -lncursesw -lxdg-basedir -lm ARCHIVEDIR:=$(GAME)-$(MAJVERS).$(MINVERS).$(PATCHVERS) ARCHIVENAME:=$(GAME)_$(MAJVERS).$(MINVERS).$(PATCHVERS) diff --git a/default.permons b/default.permons index 1dd48ee..2239a69 100644 --- a/default.permons +++ b/default.permons @@ -637,8 +637,8 @@ CONTAINS_BLOOD monster ice monster desc A ponderous, shambling half-humanoid figure of ice and snow. -ascii 'I' -utf8 "I" +ascii 'E' +utf8 "E" colour white rarity 50 power 6 @@ -657,6 +657,21 @@ ARCHER HUMANOID MADE_OF_ICE +monster blood elemental +desc A heaving shape of blood in the form of a breaking wave. +ascii 'E' +utf8 "E" +colour red +rarity 50 +power 15 +hp 100 +mhit 15 +mdam 20 +defence 10 +experience 150 +CONTAINS_BLOOD +BURSTS_ON_DEATH + monster dragon desc A bulky beast of scales and fangs and fumes, capable of spewing searing flames to roast its enemies and rumoured to have a preference for char-grilled princess. ascii 'D' diff --git a/log.cc b/log.cc index ee90474..e345c3c 100644 --- a/log.cc +++ b/log.cc @@ -279,7 +279,7 @@ static void serialize_object(FILE *fp, Obj const& obj) /*! \brief Read the player */ static void deserialize_player(FILE *fp, Player *player) { - deserialize_cstring(fp, player->name, 17); + deserialize_cstring(fp, player->name, 16); deserialize_monhandle(fp, &(player->mh)); deserialize_coord(fp, &(player->pos)); deserialize_int(fp, &(player->body)); @@ -316,7 +316,7 @@ static void deserialize_player(FILE *fp, Player *player) /*! \brief Write the player */ static void serialize_player(FILE *fp, Player const& player) { - serialize_cstring(fp, player.name, 17); + serialize_cstring(fp, player.name, 16); serialize_monhandle(fp, player.mh); serialize_coord(fp, player.pos); serialize_int(fp, player.body); @@ -368,6 +368,8 @@ void save_game(void) } serialize_int(fp, depth); serialize_int(fp, game_tick); + serialize_objhandle(fp, first_free_obj_handle); + serialize_monhandle(fp, first_free_mon_handle); serialize_player(fp, u); serialize_level(fp, &lvl); for (auto iter = monsters.begin(); iter != monsters.end(); ++iter) @@ -431,6 +433,8 @@ int load_game(void) } deserialize_int(fp, &depth); deserialize_int(fp, &game_tick); + deserialize_objhandle(fp, &first_free_obj_handle); + deserialize_monhandle(fp, &first_free_mon_handle); deserialize_player(fp, &u); deserialize_level(fp, &lvl); while (1) diff --git a/map.cc b/map.cc index 7934185..6331846 100644 --- a/map.cc +++ b/map.cc @@ -692,11 +692,13 @@ void deserialize_chunk(FILE *fp, Chunk *c) static uint32_t deserializable_terrain[CHUNK_EDGE][CHUNK_EDGE]; static uint32_t deserializable_flags[CHUNK_EDGE][CHUNK_EDGE]; static uint32_t deserializable_regions[CHUNK_EDGE][CHUNK_EDGE]; + static uint32_t deserializable_decals[CHUNK_EDGE][CHUNK_EDGE]; int i; int j; wrapped_fread(deserializable_terrain, 4, CHUNK_EDGE * CHUNK_EDGE, fp); wrapped_fread(deserializable_flags, 4, CHUNK_EDGE * CHUNK_EDGE, fp); wrapped_fread(deserializable_regions, 4, CHUNK_EDGE * CHUNK_EDGE, fp); + wrapped_fread(deserializable_decals, 4, CHUNK_EDGE * CHUNK_EDGE, fp); for (i = 0; i < CHUNK_EDGE; ++i) { for (j = 0; j < CHUNK_EDGE; ++j) @@ -704,6 +706,7 @@ void deserialize_chunk(FILE *fp, Chunk *c) c->terrain[i][j] = (Terrain) ntohl(deserializable_terrain[i][j]); c->flags[i][j] = ntohl(deserializable_flags[i][j]); c->region_number[i][j] = ntohl(deserializable_regions[i][j]); + c->decals[i][j] = (Decal_tag) ntohl(deserializable_decals[i][j]); /* objs and mons will get accurately set once we've loaded the * objs and mons. */ c->objs[i][j] = NO_OBJ; @@ -718,6 +721,7 @@ void serialize_chunk(FILE *fp, Chunk const *c) static uint32_t serializable_terrain[CHUNK_EDGE][CHUNK_EDGE]; static uint32_t serializable_flags[CHUNK_EDGE][CHUNK_EDGE]; static uint32_t serializable_regions[CHUNK_EDGE][CHUNK_EDGE]; + static uint32_t serializable_decals[CHUNK_EDGE][CHUNK_EDGE]; int i; int j; for (i = 0; i < CHUNK_EDGE; ++i) @@ -727,11 +731,13 @@ void serialize_chunk(FILE *fp, Chunk const *c) serializable_terrain[i][j] = htonl(c->terrain[i][j]); serializable_flags[i][j] = htonl(c->flags[i][j]); serializable_regions[i][j] = htonl(c->region_number[i][j]); + serializable_decals[i][j] = htonl(c->decals[i][j]); } } fwrite(serializable_terrain, 4, CHUNK_EDGE * CHUNK_EDGE, fp); fwrite(serializable_flags, 4, CHUNK_EDGE * CHUNK_EDGE, fp); fwrite(serializable_regions, 4, CHUNK_EDGE * CHUNK_EDGE, fp); + fwrite(serializable_decals, 4, CHUNK_EDGE * CHUNK_EDGE, fp); } /*! \brief Serialize a Level */ @@ -747,7 +753,6 @@ void serialize_level(FILE *fp, Level const *l) fwrite(tmp_shorts, sizeof tmp_shorts[0], 2, fp); tmp_pair[0] = htonl(l->origin_off.y); tmp_pair[1] = htonl(l->origin_off.x); - fprintf(stderr, "Before saving: origin off is %d %d\n", l->origin_off.y, l->origin_off.x); fwrite(tmp_pair, sizeof tmp_pair[0], 2, fp); tmp = htonl(l->dead_space); fwrite(&tmp, sizeof tmp, 1, fp); @@ -793,7 +798,6 @@ void deserialize_level(FILE *fp, Level *l) wrapped_fread(tmp_pair, sizeof tmp_pair[0], 2, fp); l->origin_off.y = (int32_t) ntohl(tmp_pair[0]); l->origin_off.x = (int32_t) ntohl(tmp_pair[1]); - fprintf(stderr, "After reloading: origin off is %d %d\n", l->origin_off.y, l->origin_off.x); wrapped_fread(&tmp, sizeof tmp, 1, fp); l->dead_space = Terrain(ntohl(tmp)); wrapped_fread(&tmp, sizeof tmp, 1, fp); @@ -820,12 +824,14 @@ void deserialize_level(FILE *fp, Level *l) while (1); } +/*! \brief Rotate a connection bitmask */ uint32_t rotate_connection_mask(uint32_t val, int clockwise_steps) { clockwise_steps &= 0x3; return ((val << clockwise_steps) | ((val & 0xf) >> (4 - clockwise_steps))) & 0xf; } +/*! \brief Clean up everything level-related */ void level_cleanup(void) { monsters.clear(); diff --git a/monsters.hh b/monsters.hh index 6554eac..8f634b9 100644 --- a/monsters.hh +++ b/monsters.hh @@ -67,6 +67,7 @@ public: }; #include extern std::map monsters; +extern Mon_handle first_free_mon_handle; inline Mon *mon_snapv(Mon_handle mon) { diff --git a/objects.cc b/objects.cc index 07914e1..35aa86f 100644 --- a/objects.cc +++ b/objects.cc @@ -31,6 +31,8 @@ #include "objects.hh" #include "monsters.hh" +#include + std::map objects; const Obj_handle NO_OBJ = 0u; @@ -57,6 +59,7 @@ char const potion_colours[20][16] = { "navy blue", "bottle green", "amber", "lilac", "ivory" }; +/*! \brief Read a magic scroll */ Action_cost read_scroll(Obj_handle obj) { Obj *optr = obj_snapv(obj); @@ -164,6 +167,7 @@ bool consume_obj(Obj_handle obj) return false; } +/*! \brief Consume a food */ Action_cost eat_food(Obj_handle obj) { Obj *optr = obj_snapv(obj); @@ -196,6 +200,7 @@ Action_cost eat_food(Obj_handle obj) return Cost_std; } +/*! \brief Consume a potion */ Action_cost quaff_potion(Obj_handle obj) { Obj *optr = obj_snapv(obj); @@ -404,7 +409,6 @@ Obj_handle create_obj_near(int po_idx, int quantity, Coord c) } if (panic_count < 1) { - // TODO debugging report for failure return NO_OBJ; } Obj_handle obj = create_obj(po_idx, quantity, false, c); @@ -429,6 +433,7 @@ Obj_handle create_obj(int po_idx, int quantity, bool with_you, Coord c) } } Obj o; + memset(o.meta, '\0', sizeof o.meta); o.self = obj; o.po_ref = po_idx; o.flags = OF_USED | (with_you ? OF_WITH_YOU : 0); @@ -567,18 +572,21 @@ void attempt_pickup(void) { int i; int stackable; - stackable = po_is_stackable(objects[lvl.obj_at(u.pos)].po_ref); + Obj_handle oh = lvl.obj_at(u.pos); + Obj *optr = obj_snapv(oh); + Obj *invptr; + stackable = po_is_stackable(optr->po_ref); if (stackable) { for (i = 0; i < 19; i++) { - if ((objects[u.inventory[i]].po_ref == objects[lvl.obj_at(u.pos)].po_ref)) - { - int stale_obj = lvl.obj_at(u.pos); - objects[u.inventory[i]].quan += objects[lvl.obj_at(u.pos)].quan; - objects[stale_obj].flags &= ~OF_USED; + invptr = obj_snapv(u.inventory[i]); + if (invptr && (invptr->po_ref == optr->po_ref)) + { + invptr->quan += optr->quan; + optr->flags &= ~OF_USED; lvl.set_obj_at(u.pos, NO_OBJ); - notify_get_item(stale_obj, i); + notify_get_item(oh, i); return; } } @@ -597,8 +605,8 @@ void attempt_pickup(void) } u.inventory[i] = lvl.obj_at(u.pos); lvl.set_obj_at(u.pos, NO_OBJ); - objects[u.inventory[i]].flags |= OF_WITH_YOU; - objects[u.inventory[i]].pos = Nowhere; + optr->flags |= OF_WITH_YOU; + optr->pos = Nowhere; notify_get_item(NO_OBJ, i); } diff --git a/objects.hh b/objects.hh index 7e0396d..be1a951 100644 --- a/objects.hh +++ b/objects.hh @@ -54,6 +54,7 @@ public: int durability; /* Weapons and armour degrade with use. */ }; extern std::map objects; +extern Obj_handle first_free_obj_handle; /* XXX objects.cc data and funcs */ void asprint_obj_name(char **s, Obj_handle obj); diff --git a/pmon_comp b/pmon_comp index 207f50c..0d3576a 100755 --- a/pmon_comp +++ b/pmon_comp @@ -13,6 +13,8 @@ sub usage() our @monsters; +our $max_flag_index = 1; + our %flag_indices = ( 'RESIST_FIRE' => 0, @@ -69,15 +71,19 @@ sub flag_string($) else { my $name; + my $i; + for ($i = 0; $i <= $max_flag_index; ++$i) + { + $#flag_fields = $i if ($i > $#flag_fields); + if (!defined($flag_fields[$i])) + { + $flag_fields[$i] = "0 "; + } + } for $name (@$aref) { die("Attempt to generate a flag string containing an undefined flag $name!") if !exists($flag_indices{$name}); my $idx = $flag_indices{$name}; - $#flag_fields = $idx if ($idx > $#flag_fields); - if (!defined($flag_fields[$idx])) - { - $flag_fields[$idx] = "0 "; - } $flag_fields[$idx] .= "| PMF_$name "; } } diff --git a/u.cc b/u.cc index 7f42579..b4fc5a7 100644 --- a/u.cc +++ b/u.cc @@ -40,12 +40,12 @@ struct Player u; bool wielding_ranged_weapon(void) { - return permobjs[objects[u.weapon].po_ref].flags[0] & POF_RANGED_WEAPON; + return (u.weapon != NO_OBJ) && (permobjs[objects[u.weapon].po_ref].flags[0] & POF_RANGED_WEAPON); } bool wielding_melee_weapon(void) { - return permobjs[objects[u.weapon].po_ref].flags[0] & POF_MELEE_WEAPON; + return (u.weapon != NO_OBJ) && (permobjs[objects[u.weapon].po_ref].flags[0] & POF_MELEE_WEAPON); } void recalc_defence(void) @@ -58,9 +58,10 @@ void recalc_defence(void) u.speed = (u.leadfoot ? 0 : 1); if (u.armour != NO_OBJ) { - u.defence = u.armourmelt ? 0 : permobjs[objects[u.armour].po_ref].power; + Obj const *armour = obj_snap(u.armour); + u.defence = u.armourmelt ? 0 : permobjs[armour->po_ref].power; u.defence += u.withering ? (u.agility / 10) : (u.agility / 5); - switch (objects[u.armour].po_ref) + switch (armour->po_ref) { case PO_DRAGONHIDE_ARMOUR: case PO_METEORIC_PLATE_ARMOUR: @@ -79,7 +80,8 @@ void recalc_defence(void) } if (u.ring != NO_OBJ) { - switch (objects[u.ring].po_ref) + Obj const *ring = obj_snap(u.ring); + switch (ring->po_ref) { case PO_FIRE_RING: u.resistances[DT_FIRE] |= RESIST_RING; @@ -107,9 +109,10 @@ Action_cost move_player(Offset delta) { if (u.weapon != NO_OBJ) { - if ((objects[u.weapon].po_ref == PO_BOW) || - (objects[u.weapon].po_ref == PO_CROSSBOW) || - (objects[u.weapon].po_ref == PO_THUNDERBOW)) + Obj const *wep = obj_snap(u.weapon); + if ((wep->po_ref == PO_BOW) || + (wep->po_ref == PO_CROSSBOW) || + (wep->po_ref == PO_THUNDERBOW)) { notify_swing_bow(); return Cost_none; @@ -154,11 +157,15 @@ Action_cost move_player(Offset delta) return Cost_none; } case WATER: - if ((u.ring != NO_OBJ) && (objects[u.ring].po_ref == PO_FROST_RING)) + if (u.ring != NO_OBJ) { - if (lvl.terrain_at(u.pos) != WATER) + Obj const *ring = obj_snap(u.ring); + if (ring->po_ref == PO_FROST_RING) { - notify_start_waterwalk(); + if (lvl.terrain_at(u.pos) != WATER) + { + notify_start_waterwalk(); + } } reloc_player(c); return Cost_std; @@ -434,6 +441,9 @@ Pass_fail teleport_u(void) void update_player(void) { + Obj const *ring = obj_snap(u.ring); + //Obj const *weapon = obj_snap(u.weapon); + //Obj const *armour = obj_snap(u.armour); if (!(game_tick % 5) && (u.food >= 0) && (u.hpcur < u.hpmax)) { /* Heal player for one hit point; do not allow HP gain, @@ -449,8 +459,8 @@ void update_player(void) /* Once you hit the nutrition endstop, your ring of regeneration stops * working, and like normal regen, it won't raise you above 75% HP if * your food counter is negative. */ - if (((game_tick % 10) == 5) && - (objects[u.ring].po_ref == PO_REGENERATION_RING) && + if (((game_tick % 10) == 5) && (ring) && + (ring->po_ref == PO_REGENERATION_RING) && (u.hpcur < ((u.food >= 0) ? u.hpmax : ((u.hpmax * 3) / 4))) && (u.food > MIN_FOOD)) { @@ -463,7 +473,8 @@ void update_player(void) { int food_use = 1; int squeal = 0; - if ((objects[u.ring].po_ref == PO_REGENERATION_RING) && !(game_tick % 2) && (u.food > MIN_FOOD)) + if (ring && (ring->po_ref == PO_REGENERATION_RING) && + !(game_tick % 2) && (u.food > MIN_FOOD)) { /* If you are still less hungry than MIN_FOOD nutrition, * use one more food every second tick if you are -- 2.11.0