From: Martin Read Date: Sat, 8 Mar 2014 18:59:27 +0000 (+0000) Subject: Snapshotting something that builds but is certainly flaky X-Git-Tag: 1.0.0~23 X-Git-Url: http://git.blackswordsonics.com/?a=commitdiff_plain;h=c61320ed924889c969e34853fc46b69131837fdd;p=obumbrata Snapshotting something that builds but is certainly flaky --- diff --git a/cave.cc b/cave.cc index 42b83a8..e5d8c5d 100644 --- a/cave.cc +++ b/cave.cc @@ -31,41 +31,41 @@ #include "monsters.hh" #include "mapgen.hh" -void place_cave_stairs(void) +void place_cave_stairs(Level *l) { Coord c; Coord d; int stair_tries = 0; do { - c = lvl.random_point(1); - } while (!(terrain_props[lvl.terrain_at(c)].flags & TFLAG_floor) || - (lvl.flags_at(c) & MAPFLAG_HARDWALL)); - lvl.add_stairs_at(c, STAIRS_DOWN, lvl.self.naive_next()); + 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()); do { - d = lvl.random_point(1); + d = l->random_point(1); ++stair_tries; - } while (!(terrain_props[lvl.terrain_at(d)].flags & TFLAG_floor) || - (lvl.flags_at(d) & MAPFLAG_HARDWALL) || + } while (!(terrain_props[l->terrain_at(d)].flags & TFLAG_floor) || + (l->flags_at(d) & MAPFLAG_HARDWALL) || (d.dist_cheb(c) < (10 - (stair_tries / 40)))); - lvl.add_stairs_at(d, STAIRS_UP, lvl.self.naive_prev()); + l->add_stairs_at(d, STAIRS_UP, l->self.naive_prev()); } /*! \brief Excavate a cave level. * * This algorithm runs two random walks on the map. */ -void build_level_cave(void) +void build_level_cave(Level *l) { Coord c = { GUIDE_EDGE_SIZE / 2, GUIDE_EDGE_SIZE / 2 }; int num_pools; int walk_data[4] = { 1, FLOOR, WALL, FLOOR }; - initialize_chunks(&lvl, GUIDE_EDGE_CHUNKS, GUIDE_EDGE_CHUNKS, true); - run_random_walk_unbounded(c, excavation_write, walk_data, LEVGEN_WALK_CELLS); + initialize_chunks(l, GUIDE_EDGE_CHUNKS, GUIDE_EDGE_CHUNKS, true); + run_random_walk_unbounded(l, c, excavation_write, walk_data, LEVGEN_WALK_CELLS); //run_random_walk_unbounded(c, excavation_write, walk_data, LEVGEN_WALK_CELLS); - if ((lvl.theme != THEME_UNDEAD) && (depth > 20) && !zero_die(4)) + if ((l->theme != THEME_UNDEAD) && (depth > 20) && !zero_die(4)) { num_pools = inc_flat(1, 4); walk_data[0] = 2; @@ -85,29 +85,29 @@ void build_level_cave(void) { int pool_size = inc_flat(9, 36); do { - c = lvl.random_point(2); - } while (lvl.terrain_at(c) != FLOOR); - run_random_walk(c, excavation_write, walk_data, pool_size); + c = l->random_point(2); + } while (l->terrain_at(c) != FLOOR); + run_random_walk(l, c, excavation_write, walk_data, pool_size); --num_pools; } - place_cave_stairs(); + place_cave_stairs(l); } /*! \brief Excavate a cave level with intrusions */ -void build_level_intrusions(void) +void build_level_intrusions(Level *l) { Coord c = { GUIDE_EDGE_SIZE / 2, GUIDE_EDGE_SIZE / 2 }; int i; int walk_data[4] = { 1, FLOOR, WALL, FLOOR }; - initialize_chunks(&lvl, GUIDE_EDGE_CHUNKS, GUIDE_EDGE_CHUNKS, true); + initialize_chunks(l, GUIDE_EDGE_CHUNKS, GUIDE_EDGE_CHUNKS, true); for (i = 0; i < 6; ++i) { - place_random_intrusion(WALL); + place_random_intrusion(l, WALL); } - run_random_walk_unbounded(c, excavation_write, walk_data, LEVGEN_WALK_CELLS); + run_random_walk_unbounded(l, c, excavation_write, walk_data, LEVGEN_WALK_CELLS); /* and now the stairs */ - place_cave_stairs(); + place_cave_stairs(l); } /* cave.cc */ diff --git a/combat.cc b/combat.cc index 8a14113..fe9664c 100644 --- a/combat.cc +++ b/combat.cc @@ -42,7 +42,7 @@ int player_melee_base(void) int damage; if (u.weapon != NO_OBJ) { - dmgbase = permobjs[objects[u.weapon].obj_id].power + (u.body / 10); + dmgbase = permobjs[objects[u.weapon].po_ref].power + (u.body / 10); damage = dmgbase / 3 + one_die(dmgbase - dmgbase / 3); } else @@ -54,10 +54,10 @@ int player_melee_base(void) /*! \brief Calculate the effect of the player's damage amplifier ring */ -bool ring_effectiveness(int mon, int ring_pobj, int damage, int *bonus_damage, int *vamp_healing) +bool ring_effectiveness(Mon_handle mon, int ring_pobj, int damage, int *bonus_damage, int *vamp_healing) { bool rv = false; - int pm = monsters[mon].mon_id; + int pm = monsters[mon].pm_ref; *vamp_healing = 0; switch (ring_pobj) { @@ -94,17 +94,17 @@ bool ring_effectiveness(int mon, int ring_pobj, int damage, int *bonus_damage, i * \param mon Monster hit * \param damage Rolled damage before rings are applied */ -void resolve_player_melee(int mon, int damage) +void resolve_player_melee(Mon_handle mon, int damage) { bool ring_eff; int ring_bonus; int healing = 0; if (u.ring != NO_OBJ) { - ring_eff = ring_effectiveness(mon, objects[u.ring].obj_id, damage, &ring_bonus, &healing); + ring_eff = ring_effectiveness(mon, objects[u.ring].po_ref, damage, &ring_bonus, &healing); if (ring_eff) { - notify_ring_boost(mon, objects[u.ring].obj_id); + notify_ring_boost(mon, objects[u.ring].po_ref); damage += ring_bonus; } } @@ -128,7 +128,7 @@ Action_cost player_power_attack(Offset delta) { Coord c = u.pos + delta; int damage; - int mon = lvl.mon_at(c); + Mon_handle mon = lvl.mon_at(c); /* Power Attack: Always hit, do +75% damage. */ notify_player_combo_powatk(mon); damage = (player_melee_base() * 7) / 4; @@ -155,13 +155,13 @@ Action_cost player_attack(Offset delta) return Cost_std; } -int uhitm(int mon) +int uhitm(Mon_handle mon) { Mon *mp; int tohit; int damage; int hitbase = u.agility + u.level; - mp = monsters + mon; + mp = mon_snapv(mon); tohit = hitbase / 3 + zero_die(hitbase - hitbase / 3); if (tohit < mp->defence) { @@ -182,13 +182,13 @@ int ushootm(Offset step) int range; Coord c = u.pos + step; bool done = false; - int mon; + Mon_handle mon; Mon *mptr; Obj *wep; Permobj *pwep; int damage; - wep = objects + u.weapon; - pwep = permobjs + wep->obj_id; + wep = obj_snapv(u.weapon); + pwep = permobjs + wep->po_ref; damage = one_die(pwep->power); for (range = 1; !done; ++range, (c += step)) { @@ -196,7 +196,7 @@ int ushootm(Offset step) if (mon != NO_MON) { done = true; - mptr = monsters + mon; + mptr = mon_snapv(mon); tohit = zero_die(u.agility + u.level - range); if (range == 1) { @@ -212,7 +212,7 @@ int ushootm(Offset step) notify_player_hurt_mon(mon, damage); } damage_mon(mon, damage, true); - if ((mptr->used) && (wep->obj_id == PO_THUNDERBOW)) + if ((mptr->flags & MF_ALIVE) && (wep->po_ref == PO_THUNDERBOW)) { int kb = knockback_mon(mon, step, true, true); switch (kb) @@ -243,12 +243,12 @@ int ushootm(Offset step) return 0; } -int mhitu(int mon, Damtyp dtype) +int mhitu(Mon_handle mon, Damtyp dtype) { int tohit; int damage; int unaffected; - Mon *mptr = monsters + mon; + Mon *mptr = mon_snapv(mon); tohit = zero_die(mptr->mtohit + 5); if (tohit < u.defence) { @@ -307,19 +307,19 @@ test_unaffected: else { notify_player_touch_effect(dtype); - if ((mptr->mon_id == PM_VAMPIRE) && !u.resists(DT_NECRO)) + if ((mptr->pm_ref == PM_VAMPIRE) && !u.resists(DT_NECRO)) { heal_mon(mon, damage * 2 / 5, 1); - } else if ((tohit - u.defence >= 5) && (mptr->mon_id == PM_SNAKE)) + } else if ((tohit - u.defence >= 5) && (mptr->pm_ref == PM_SNAKE)) { drain_body(1, "snake venom", 0); } - damage_u(damage, DEATH_KILLED_MON, permons[mptr->mon_id].name); + damage_u(damage, DEATH_KILLED_MON, permons[mptr->pm_ref].name); } return 1; } -int mshootu(int mon) +int mshootu(Mon_handle mon) { Mon *mptr; Mon *bystander; @@ -333,14 +333,14 @@ int mshootu(int mon) int evasion; int defence; Damtyp dtype; - mptr = monsters + mon; + mptr = mon_snapv(mon); c = mptr->pos; /* dy, dx == trajectory of missile */ delta = u.pos.delta(c); step = mysign(delta); /* Don't get the bonus that applies to melee attacks. */ tohit = zero_die(mptr->rtohit); - dtype = permons[mptr->mon_id].rdtyp; + dtype = permons[mptr->pm_ref].rdtyp; notify_mon_ranged_attack(mon); if ((dtype == DT_NECRO) || (dtype == DT_ELEC)) { @@ -360,7 +360,7 @@ int mshootu(int mon) /* Move projectile one square before looking for targets. */ for ((done = 0), (c = mptr->pos + step); !done; c += step) { - int victim; + Mon_handle victim; if ((lvl.terrain_at(c) == WALL) || (lvl.terrain_at(c) == DOOR)) { done = 1; @@ -376,7 +376,7 @@ int mshootu(int mon) if (!unaffected) { damage = one_die(mptr->rdam); - damage_u(damage, DEATH_KILLED_MON, permons[mptr->mon_id].name); + damage_u(damage, DEATH_KILLED_MON, permons[mptr->pm_ref].name); } return 1; } @@ -388,11 +388,11 @@ int mshootu(int mon) else if (victim != NO_MON) { done = 1; - bystander = monsters + victim; + bystander = mon_snapv(victim); switch (dtype) { case DT_COLD: - if (pmon_resists_cold(bystander->mon_id)) + if (pmon_resists_cold(bystander->pm_ref)) { unaffected = 1; } @@ -402,7 +402,7 @@ int mshootu(int mon) } break; case DT_FIRE: - if (pmon_resists_fire(bystander->mon_id)) + if (pmon_resists_fire(bystander->pm_ref)) { unaffected = 1; } @@ -412,7 +412,7 @@ int mshootu(int mon) } break; case DT_NECRO: - if (pmon_is_undead(bystander->mon_id)) + if (pmon_is_undead(bystander->pm_ref)) { unaffected = 1; } diff --git a/combat.hh b/combat.hh index a65c4f8..c2be288 100644 --- a/combat.hh +++ b/combat.hh @@ -39,13 +39,12 @@ #define agility_modifier() (u.withering ? (u.agility / 10) : (u.agility / 5)) /* XXX combat.c data and funcs */ -extern Action_cost throw_flask(int obj, Offset step); extern Action_cost player_attack(Offset step); extern Action_cost player_power_attack(Offset step); -extern void resolve_player_melee(int mon, int damage); -extern int mhitu(int mon, Damtyp dtyp); -extern int uhitm(int mon); -extern int mshootu(int mon); +extern void resolve_player_melee(Mon_handle mon, int damage); +extern int mhitu(Mon_handle mon, Damtyp dtyp); +extern int uhitm(Mon_handle mon); +extern int mshootu(Mon_handle mon); extern int ushootm(Offset step); class Combo_spec diff --git a/coord.hh b/coord.hh index 1a2016a..c69dda2 100644 --- a/coord.hh +++ b/coord.hh @@ -30,6 +30,7 @@ #define COORD_HH #include +#include template T myabs(T val); template T mysign(T val); @@ -48,8 +49,8 @@ template inline T mysign(T val) { return (val < 0) ? -1 : ((val > 0 class Offset { public: - int y; - int x; + int32_t y; + int32_t x; bool ecardinal(void) const { return ((y && !x) || (x && !y)); } bool rcardinal(void) const { return ecardinal() || (myabs(y) == myabs(x)); } int len_cheb(void) const { return std::max(myabs(y), myabs(x)); } @@ -69,7 +70,7 @@ public: bool operator <=(Offset const& right) const { return (y < right.y) || ((y == right.y) && (x <= right.x)); } bool operator >(Offset const& right) const { return (y > right.y) || ((y == right.y) && (x > right.x)); } bool operator >=(Offset const& right) const { return (y > right.y) || ((y == right.y) && (x >= right.x)); } - void clamp(int ymin, int xmin, int ymax, int xmax) + void clamp(int32_t ymin, int32_t xmin, int32_t ymax, int32_t xmax) { y = std::min(ymax, std::max(ymin, y)); x = std::min(xmax, std::max(xmin, x)); @@ -88,8 +89,8 @@ public: class Coord { public: - int y; - int x; + int32_t y; + int32_t x; int dist_cheb(Coord const& right) const { return std::max(myabs(y - right.y), myabs(x - right.x)); } int dist_taxi(Coord const& right) const { return myabs(y - right.y) + myabs(x - right.x); } int distsq_eucl(Coord const& right) const { return (y - right.y) * (y - right.y) + (x - right.x) * (x - right.x); } @@ -104,7 +105,7 @@ public: bool operator <=(Coord const& right) const { return (y < right.y) || ((y == right.y) && (x <= right.x)); } bool operator >(Coord const& right) const { return (y > right.y) || ((y == right.y) && (x > right.x)); } bool operator >=(Coord const& right) const { return (y > right.y) || ((y == right.y) && (x >= right.x)); } - void clamp(int ymin, int xmin, int ymax, int xmax) + void clamp(int32_t ymin, int32_t xmin, int32_t ymax, int32_t xmax) { y = std::min(ymax, std::max(ymin, y)); x = std::min(xmax, std::max(xmin, x)); diff --git a/core.hh b/core.hh index de1c387..3f47981 100644 --- a/core.hh +++ b/core.hh @@ -163,12 +163,14 @@ class Level_key; class Permobj; class Permon; class Obj; +typedef uint32_t Obj_handle; class Mon; +typedef uint32_t Mon_handle; #define NO_POBJ (-1) #define NO_PMON (-1) -#define NO_OBJ (-1) -#define NO_MON (-1) +extern const Obj_handle NO_OBJ; +extern const Mon_handle NO_MON; #define NO_REGION 0xffffffffu #endif diff --git a/display-nc.cc b/display-nc.cc index e3ce020..cef82a2 100644 --- a/display-nc.cc +++ b/display-nc.cc @@ -45,8 +45,8 @@ #define DISP_NC_SIDE (DISP_NC_RADIUS * 2 + 1) /* Prototypes for static funcs */ -static cchar_t const *object_char(int object_id); -static cchar_t const *monster_char(int monster_id); +static cchar_t const *object_char(int po_ref); +static cchar_t const *monster_char(int pm_ref); static cchar_t const *terrain_char(Terrain terrain_type); static void draw_status_line(void); static void draw_world(void); @@ -220,22 +220,22 @@ static cchar_t const *terrain_char(Terrain terrain_type) /*! \brief Get pointer to cchar_t object for specified permon * - * \param monster_id Specified permon + * \param pm_ref Specified permon * \return pointer to the specified permon's tile */ -static cchar_t const *monster_char(int monster_id) +static cchar_t const *monster_char(int pm_ref) { - return permon_tiles + monster_id; + return permon_tiles + pm_ref; } /*! \brief Get pointer to cchar_t object for specified permobj * - * \param object_id Specified permobj + * \param po_ref Specified permobj * \return pointer to the specified permobj's tile */ -static cchar_t const *object_char(int object_id) +static cchar_t const *object_char(int po_ref) { - return permobj_tiles + object_id; + return permobj_tiles + po_ref; } /*! \brief Repopulate the back buffer and set the hard redraw flag */ @@ -278,8 +278,8 @@ void newsym(Coord c) } else { - int obj = lvl.obj_at(c); - int mon = lvl.mon_at(c); + Obj_handle obj = lvl.obj_at(c); + Mon_handle mon = lvl.mon_at(c); Terrain terr = lvl.terrain_at(c); uint32_t flags = lvl.flags_at(c); if (c == u.pos) @@ -288,13 +288,13 @@ void newsym(Coord c) } else if ((!show_terrain) && (mon != NO_MON) && occupant_visible(c)) { - back_buffer[camoff.y][camoff.x] = monster_char(monsters[mon].mon_id); + back_buffer[camoff.y][camoff.x] = monster_char(monsters[mon].pm_ref); } else if (flags & MAPFLAG_EXPLORED) { if ((!show_terrain) && (obj != NO_OBJ)) { - back_buffer[camoff.y][camoff.x] = object_char(objects[obj].obj_id); + back_buffer[camoff.y][camoff.x] = object_char(objects[obj].po_ref); } else { @@ -760,7 +760,7 @@ static void update_inv(enum poclass_num filter) else { if ((filter == POCLASS_NONE) || - (permobjs[objects[u.inventory[i]].obj_id].poclass == filter)) + (permobjs[objects[u.inventory[i]].po_ref].poclass == filter)) { wattr_set(inventory_window, colour_data[Gcol_l_grey].attr, colour_data[Gcol_l_grey].cpair, nullptr); } @@ -800,7 +800,7 @@ static int inv_select(enum poclass_num filter, char const *action, int accept_bl for (i = 0; i < 19; i++) { - if ((u.inventory[i] != NO_OBJ) && ((filter == POCLASS_NONE) || (permobjs[objects[u.inventory[i]].obj_id].poclass == filter))) + if ((u.inventory[i] != NO_OBJ) && ((filter == POCLASS_NONE) || (permobjs[objects[u.inventory[i]].po_ref].poclass == filter))) { items++; } @@ -859,7 +859,7 @@ tryagain: * a strict superset of ASCII. IF we're not, the following code may * break. */ selection = ch - 'a'; - if ((u.inventory[selection] != NO_OBJ) && ((filter == POCLASS_NONE) || (permobjs[objects[u.inventory[selection]].obj_id].poclass == filter))) + if ((u.inventory[selection] != NO_OBJ) && ((filter == POCLASS_NONE) || (permobjs[objects[u.inventory[selection]].po_ref].poclass == filter))) { hide_inv(); return selection; @@ -1608,8 +1608,8 @@ static void examine_square(Offset o) { Coord c = u.pos + o; uint32_t flags; - int mon; - int obj; + Mon_handle mon; + Obj_handle obj; Terrain terr; if ((c.y < 0) || (c.x < 0) || (c.y >= (lvl.chunks_high << CHUNK_SHIFT)) || (c.x >= (lvl.chunks_wide << CHUNK_SHIFT))) @@ -1629,11 +1629,11 @@ static void examine_square(Offset o) print_msg("%s\n", terrain_props[terr]); if ((mon != NO_MON) && mon_visible(mon)) { - print_msg("%s\n%s\n", permons[monsters[mon].mon_id].name, permons[monsters[mon].mon_id].description); + print_msg("%s\n%s\n", permons[monsters[mon].pm_ref].name, permons[monsters[mon].pm_ref].description); } if (obj != NO_OBJ) { - print_msg("%s\n%s\n", permobjs[objects[obj].obj_id].name, permobjs[objects[obj].obj_id].description); + print_msg("%s\n%s\n", permobjs[objects[obj].po_ref].name, permobjs[objects[obj].po_ref].description); } } @@ -1690,27 +1690,23 @@ void welcome(void) print_msg("Press '?' for help.\n"); } -void describe_object(int obj) +void describe_object(Obj_handle obj) { - Obj *optr; - Permobj *poptr; + Obj const *optr = obj_snap(obj); + Permobj const *poptr = permobjs + optr->po_ref; print_obj_name(obj); - optr = objects + obj; - poptr = permobjs + optr->obj_id; print_msg("\n%s\n", poptr->description); } -void print_obj_name(int obj) +void print_obj_name(Obj_handle obj) { - Obj *optr; - Permobj *poptr; - optr = objects + obj; - poptr = permobjs + optr->obj_id; + Obj const *optr = obj_snap(obj); + Permobj const *poptr = permobjs + optr->po_ref; if (optr->quan > 1) { print_msg("%d %s", optr->quan, poptr->plural); } - else if (po_is_stackable(optr->obj_id)) + else if (po_is_stackable(optr->po_ref)) { print_msg("1 %s", poptr->name); } @@ -1725,26 +1721,26 @@ void print_obj_name(int obj) } } -void print_mon_name(int mon, int article) +void print_mon_name(Mon_handle mon, int article) { - if (permons[monsters[mon].mon_id].name[0] == '\0') + if (permons[monsters[mon].pm_ref].name[0] == '\0') { - print_msg("GROB THE VOID (%d)", monsters[mon].mon_id); + print_msg("GROB THE VOID (%d)", monsters[mon].pm_ref); return; } switch (article) { case 0: /* a */ - print_msg("a%s %s", is_vowel(permons[monsters[mon].mon_id].name[0]) ? "n" : "", permons[monsters[mon].mon_id].name); + print_msg("a%s %s", is_vowel(permons[monsters[mon].pm_ref].name[0]) ? "n" : "", permons[monsters[mon].pm_ref].name); break; case 1: /* the */ - print_msg("the %s", permons[monsters[mon].mon_id].name); + print_msg("the %s", permons[monsters[mon].pm_ref].name); break; case 2: /* A */ - print_msg("A%s %s", is_vowel(permons[monsters[mon].mon_id].name[0]) ? "n" : "", permons[monsters[mon].mon_id].name); + print_msg("A%s %s", is_vowel(permons[monsters[mon].pm_ref].name[0]) ? "n" : "", permons[monsters[mon].pm_ref].name); break; case 3: /* The */ - print_msg("The %s", permons[monsters[mon].mon_id].name); + print_msg("The %s", permons[monsters[mon].pm_ref].name); break; } } diff --git a/display.hh b/display.hh index 0a92378..b524572 100644 --- a/display.hh +++ b/display.hh @@ -56,6 +56,7 @@ extern void pressanykey(void); extern void show_discoveries(void); extern void touch_one_screen(Coord c); extern void welcome(void); +extern void print_obj_name(Obj_handle obj); /* "I've changed things that need to be redisplayed" flags. */ extern bool hard_redraw; diff --git a/log.cc b/log.cc index b2bc2c0..6aa7b0f 100644 --- a/log.cc +++ b/log.cc @@ -154,6 +154,136 @@ void wrapped_fread(void *buf, size_t size, size_t nmemb, FILE *fp) } } +static inline void deserialize_uint32(FILE *fp, uint32_t *i) +{ + wrapped_fread(&i, 1, sizeof i, fp); + *i = ntohl(*i); +} + +static inline void deserialize_int32(FILE *fp, int32_t *i) +{ + int32_t tmp; + wrapped_fread(&tmp, 1, sizeof tmp, fp); + *i = (int32_t) ntohl(tmp); +} + +static inline void deserialize_int(FILE *fp, int *i) +{ + int32_t tmp; + wrapped_fread(&tmp, 1, sizeof tmp, fp); + *i = (int32_t) ntohl(tmp); +} + +static inline void deserialize_coord(FILE *fp, Coord * c) +{ + deserialize_int32(fp, &(c->y)); + deserialize_int32(fp, &(c->x)); +} + +static inline void serialize_uint32(FILE *fp, uint32_t i) +{ + i = htonl(i); + fwrite(&i, 1, sizeof i, fp); +} + +static inline void serialize_int32(FILE *fp, int32_t i) +{ + int32_t tmp = htonl(i); + fwrite(&tmp, 1, sizeof tmp, fp); +} + +static inline void serialize_int(FILE *fp, int i) +{ + int32_t tmp = htonl(i); + fwrite(&tmp, 1, sizeof tmp, fp); +} + +static inline void serialize_coord(FILE *fp, Coord const& c) +{ + serialize_int32(fp, c.y); + serialize_int32(fp, c.x); +} + +static inline void serialize_monhandle(FILE *fp, Mon_handle m) +{ + uint32_t tmp = htonl(m); + fwrite(&tmp, 1, sizeof tmp, fp); +} + +static void serialize_monster(FILE *fp, Mon const& mon) +{ + serialize_monhandle(fp, mon.self); + serialize_int(fp, mon.pm_ref); + serialize_uint32(fp, mon.flags); + serialize_coord(fp, mon.pos); + serialize_coord(fp, mon.ai_lastpos); + serialize_int(fp, mon.hpmax); + serialize_int(fp, mon.hpcur); + serialize_int(fp, mon.mtohit); + serialize_int(fp, mon.rtohit); + serialize_int(fp, mon.defence); + serialize_int(fp, mon.mdam); + serialize_int(fp, mon.rdam); + serialize_int(fp, mon.next_summon); +} + +static inline void serialize_objhandle(FILE *fp, Obj_handle o) +{ + uint32_t tmp = htonl(o); + fwrite(&tmp, 1, sizeof tmp, fp); +} + +static inline void serialize_object(FILE *fp, Obj const& obj) +{ + serialize_objhandle(fp, obj.self); + serialize_int(fp, obj.po_ref); + serialize_uint32(fp, obj.flags); + serialize_coord(fp, obj.pos); + serialize_int(fp, obj.quan); + serialize_int(fp, obj.durability); +} + +static inline void deserialize_monhandle(FILE *fp, Mon_handle *m) +{ + uint32_t tmp; + wrapped_fread(&tmp, 1, sizeof tmp, fp); + *m = htonl(tmp); +} + +static inline void deserialize_objhandle(FILE *fp, Obj_handle *o) +{ + uint32_t tmp; + wrapped_fread(&tmp, 1, sizeof tmp, fp); + *o = htonl(tmp); +} + +static inline void deserialize_object(FILE *fp, Obj *obj) +{ + deserialize_objhandle(fp, &(obj->self)); + deserialize_int(fp, &(obj->po_ref)); + deserialize_uint32(fp, &(obj->flags)); + deserialize_coord(fp, &(obj->pos)); + deserialize_int(fp, &(obj->quan)); + deserialize_int(fp, &(obj->durability)); +} + +static void deserialize_monster(FILE *fp, Mon * mon) +{ + deserialize_monhandle(fp, &(mon->self)); + deserialize_int(fp, &(mon->pm_ref)); + deserialize_uint32(fp, &(mon->flags)); + deserialize_coord(fp, &(mon->pos)); + deserialize_coord(fp, &(mon->ai_lastpos)); + deserialize_int(fp, &(mon->hpmax)); + deserialize_int(fp, &(mon->hpcur)); + deserialize_int(fp, &(mon->mtohit)); + deserialize_int(fp, &(mon->rtohit)); + deserialize_int(fp, &(mon->defence)); + deserialize_int(fp, &(mon->mdam)); + deserialize_int(fp, &(mon->rdam)); + deserialize_int(fp, &(mon->next_summon)); +} + void save_game(void) { FILE *fp; @@ -177,8 +307,18 @@ void save_game(void) tmp = htonl(game_tick); fwrite(&tmp, 1, sizeof tmp, fp); serialize_level(fp, &lvl); - fwrite(monsters, sizeof (Mon), MONSTERS_IN_PLAY, fp); - fwrite(objects, sizeof (Obj), OBJECTS_IN_PLAY, fp); + for (auto iter = monsters.begin(); iter != monsters.end(); ++iter) + { + serialize_monhandle(fp, iter->second.self); + serialize_monster(fp, iter->second); + } + serialize_monhandle(fp, NO_MON); + for (auto iter = objects.begin(); iter != objects.end(); ++iter) + { + serialize_objhandle(fp, iter->second.self); + serialize_object(fp, iter->second); + } + serialize_objhandle(fp, NO_OBJ); /* Clean up */ fflush(fp); fsync(fd); @@ -191,12 +331,11 @@ void save_game(void) */ static void rebuild_mapmons(void) { - int i; - for (i = 0; i < 100; i++) + for (auto iter = monsters.begin(); iter != monsters.end(); ++iter) { - if (monsters[i].used) + if (iter->second.flags & MF_USED) { - lvl.set_mon_at(monsters[i].pos, i); + lvl.set_mon_at(iter->second.pos, iter->first); } } } @@ -205,12 +344,11 @@ static void rebuild_mapmons(void) */ static void rebuild_mapobjs(void) { - int i; - for (i = 0; i < 100; i++) + for (auto iter = objects.begin(); iter != objects.end(); ++iter) { - if (objects[i].used && !objects[i].with_you) + if (iter->second.flags & OF_USED) { - lvl.set_obj_at(objects[i].pos, i); + lvl.set_obj_at(iter->second.pos, iter->first); } } } @@ -235,8 +373,36 @@ int load_game(void) wrapped_fread(&game_tick, 1, sizeof game_tick, fp); game_tick = ntohl(game_tick); deserialize_level(fp, &lvl); - wrapped_fread(monsters, sizeof (Mon), MONSTERS_IN_PLAY, fp); - wrapped_fread(objects, sizeof (Obj), OBJECTS_IN_PLAY, fp); + while (1) + { + Mon_handle mon; + deserialize_monhandle(fp, &mon); + if (mon != NO_MON) + { + Mon m; + deserialize_monster(fp, &m); + monsters[mon] = m; + } + else + { + break; + } + } + while (1) + { + Obj_handle obj; + deserialize_objhandle(fp, &obj); + if (obj != NO_OBJ) + { + Obj o; + deserialize_object(fp, &o); + objects[obj] = o; + } + else + { + break; + } + } rebuild_mapobjs(); rebuild_mapmons(); fclose(fp); diff --git a/main.cc b/main.cc index 411c02d..25d305d 100644 --- a/main.cc +++ b/main.cc @@ -66,7 +66,6 @@ void new_game(char const *name) void main_loop(void) { - int i; int action_speed = 0; welcome(); while (!game_finished) @@ -99,18 +98,17 @@ void main_loop(void) } } while (cost == Cost_none); } - for (i = 0; i < 100; i++) + for (auto iter = monsters.begin(); iter != monsters.end(); ++iter) { - if (!monsters[i].used) + if (!(iter->second.flags & MF_USED)) { - /* Unused monster */ continue; } /* Update the monster's status. */ - update_mon(i); - if (action_speed <= permons[monsters[i].mon_id].speed) + update_mon(iter->first); + if (action_speed <= permons[iter->second.pm_ref].speed) { - mon_acts(i); + mon_acts(iter->first); } if (game_finished) { diff --git a/map.cc b/map.cc index ab8069d..764fa10 100644 --- a/map.cc +++ b/map.cc @@ -255,7 +255,7 @@ int Level::find_stairs(Terrain t, std::vector *dest) const int Level::find_stairs(Level_key from, std::vector *dest) const { int count = 0; - for (auto iter = lvl.stairs.begin(); iter != lvl.stairs.end(); ++iter) + for (auto iter = stairs.begin(); iter != stairs.end(); ++iter) { if (iter->destination == from) { @@ -268,16 +268,22 @@ int Level::find_stairs(Level_key from, std::vector *dest) const void leave_level(void) { - int i; - for (i = 0; i < 100; i++) + for (auto iter = monsters.begin(); iter != monsters.end(); ) { - /* Throw away each monster */ - monsters[i].used = false; - /* and each object not carried by the player */ - if (!objects[i].with_you) + auto iter2 = iter; + ++iter2; + monsters.erase(iter); + iter = iter2; + } + for (auto iter = objects.begin(); iter != objects.end(); ) + { + auto iter2 = iter; + ++iter2; + if (!(iter->second.flags & OF_WITH_YOU)) { - objects[i].used = false; + objects.erase(iter); } + iter = iter2; } depth++; } @@ -286,7 +292,7 @@ void make_new_level(void) { build_level(); populate_level(); - inject_player(lvl.self.naive_prev()); + inject_player(&lvl, lvl.self.naive_prev()); look_around_you(); notify_change_of_depth(); } @@ -296,28 +302,28 @@ void make_new_level(void) * This version of run_random_walk will extend the level boundaries instead * of rejecting out-of-bounds coordinates. */ -Coord run_random_walk(Coord oc, rwalk_mod_funcptr func, +Coord run_random_walk(Level *l, Coord oc, rwalk_mod_funcptr func, void const *priv_ptr, int cells) { int i; Coord c = oc; int bailout = 10000; - func(c, priv_ptr); + func(l, c, priv_ptr); for (i = 0; (i < cells) && (bailout > 0); --bailout) { oc = c; if (zero_die(2)) { c.y += (zero_die(2) ? -1 : 1); - c.y = std::min(lvl.max_y() - 2, std::max(c.y, lvl.min_y() + 2)); + c.y = std::min(l->max_y() - 2, std::max(c.y, l->min_y() + 2)); } else { c.x += (zero_die(2) ? -1 : 1); - c.x = std::min(lvl.max_x() - 2, std::max(c.x, lvl.min_x() + 2)); + c.x = std::min(l->max_x() - 2, std::max(c.x, l->min_x() + 2)); } - switch (func(c, priv_ptr)) + switch (func(l, c, priv_ptr)) { case 0: /* nothing changed */ @@ -344,14 +350,14 @@ Coord run_random_walk(Coord oc, rwalk_mod_funcptr func, * This version of run_random_walk will extend the level boundaries instead * of rejecting out-of-bounds coordinates. */ -Coord run_random_walk_unbounded(Coord oc, rwalk_mod_funcptr func, +Coord run_random_walk_unbounded(Level *l, Coord oc, rwalk_mod_funcptr func, void const *priv_ptr, int cells) { int i; Coord c = oc; int bailout = 10000; - func(c, priv_ptr); + func(l, c, priv_ptr); for (i = 0; (i < cells) && (bailout > 0); --bailout) { oc = c; @@ -363,23 +369,23 @@ Coord run_random_walk_unbounded(Coord oc, rwalk_mod_funcptr func, { c.x += (zero_die(2) ? -1 : 1); } - if (c.y <= lvl.min_y()) + if (c.y <= l->min_y()) { - lvl.grow(North, true); + l->grow(North, true); } - if (c.y >= lvl.max_y()) + if (c.y >= l->max_y()) { - lvl.grow(South, true); + l->grow(South, true); } - if (c.x <= lvl.min_x()) + if (c.x <= l->min_x()) { - lvl.grow(West, true); + l->grow(West, true); } - if (c.x >= lvl.max_x()) + if (c.x >= l->max_x()) { - lvl.grow(East, true); + l->grow(East, true); } - switch (func(c, priv_ptr)) + switch (func(l, c, priv_ptr)) { case 0: /* nothing changed */ @@ -444,22 +450,22 @@ void build_level(void) switch (lvl.layout) { case LAYOUT_CAVE_SHRINE: - build_level_shrine(); + build_level_shrine(&lvl); break; case LAYOUT_CAVE_INTRUSIONS: - build_level_intrusions(); + build_level_intrusions(&lvl); break; case LAYOUT_DUNGEONBASH: - build_level_dungeonbash(); + build_level_dungeonbash(&lvl); break; case LAYOUT_CLASSIC_CAVE: - build_level_cave(); + build_level_cave(&lvl); break; } } /*! \brief Build a dungeonbash-style rooms-and-corridors level */ -void build_level_dungeonbash() +void build_level_dungeonbash(Level *l) { int chy; int chx; @@ -467,9 +473,9 @@ void build_level_dungeonbash() * immediately. */ initialize_chunks(&lvl, GUIDE_EDGE_CHUNKS, GUIDE_EDGE_CHUNKS, true); /* One room per chunk. */ - for (chy = 0; chy < lvl.chunks_high; ++chy) + for (chy = 0; chy < l->chunks_high; ++chy) { - for (chx = 0; chx < lvl.chunks_wide; ++ chx) + for (chx = 0; chx < l->chunks_wide; ++ chx) { /* Smallest allowed room has a 2x2 interior. */ Offset room_size = { MIN_ROOM_EDGE + zero_die(5), MIN_ROOM_EDGE + zero_die(5) }; @@ -487,13 +493,13 @@ void build_level_dungeonbash() } /*! \brief Excavation function for use with random walks */ -int excavation_write(Coord c, void const *data) +int excavation_write(Level *l, Coord c, void const *data) { int const *data_as_ints = (int const *) data; int const *overwrite = data_as_ints + 2; int newterr = data_as_ints[1]; int j; - if (lvl.flags_at(c) & MAPFLAG_HARDWALL) + if (l->flags_at(c) & MAPFLAG_HARDWALL) { /* Don't bite into hardened walls, but don't waste a step on * them either. */ @@ -501,9 +507,9 @@ int excavation_write(Coord c, void const *data) } for (j = 0; j < data_as_ints[0]; ++j) { - if (lvl.terrain_at(c) == overwrite[j]) + if (l->terrain_at(c) == overwrite[j]) { - lvl.set_terrain_at(c, (Terrain) newterr); + l->set_terrain_at(c, (Terrain) newterr); return 1; } } @@ -511,10 +517,10 @@ int excavation_write(Coord c, void const *data) } /*! \brief "Intrusion" function for use with random walks */ -int intrusion_write(Coord c, void const *data) +int intrusion_write(Level *l, Coord c, void const *data) { Terrain const *tptr = (Terrain const *) data; - if ((lvl.terrain_at(c) != WALL) || (lvl.flags_at(c) & MAPFLAG_HARDWALL)) + if ((l->terrain_at(c) != WALL) || (l->flags_at(c) & MAPFLAG_HARDWALL)) { return 0; } @@ -529,14 +535,14 @@ int intrusion_write(Coord c, void const *data) } if (tptr) { - lvl.set_terrain_at(c, *tptr); + l->set_terrain_at(c, *tptr); } - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_flags_at(c, MAPFLAG_HARDWALL); return 1; } /*! \brief Do a random walk laying down an exclusion area */ -void place_random_intrusion(Terrain new_wall) +void place_random_intrusion(Level *l, Terrain new_wall) { Coord c; int intrusion_size = inc_flat(27, 54); @@ -544,19 +550,19 @@ void place_random_intrusion(Terrain new_wall) { c.x = zero_die(2) ? inc_flat(1, GUIDE_EDGE_SIZE / 3) : inc_flat((2 * GUIDE_EDGE_SIZE) / 3, GUIDE_EDGE_SIZE - 2); c.y = zero_die(2) ? inc_flat(1, GUIDE_EDGE_SIZE / 3) : inc_flat((2 * GUIDE_EDGE_SIZE) / 3, GUIDE_EDGE_SIZE - 2); - } while (lvl.flags_at(c) & MAPFLAG_HARDWALL); - run_random_walk(c, intrusion_write, &new_wall, intrusion_size); + } while (l->flags_at(c) & MAPFLAG_HARDWALL); + run_random_walk(l, c, intrusion_write, &new_wall, intrusion_size); } /*! \brief Get a valid square to generate a monster on */ -Pass_fail get_levgen_mon_floor(Coord *c) +Pass_fail get_levgen_mon_floor(Level *l, Coord *c) { int cell_try; Coord t; for (cell_try = 0; cell_try < 200; cell_try++) { - t = lvl.random_point(1); - if ((lvl.terrain_at(t) != FLOOR) || (lvl.mon_at(t) != NO_MON)) + t = l->random_point(1); + if ((l->terrain_at(t) != FLOOR) || (l->mon_at(t) != NO_MON)) { t = Nowhere; continue; @@ -581,7 +587,7 @@ void populate_level(void) /* Generate some random monsters */ for (i = 0; i < 10; i++) { - pf = get_levgen_mon_floor(&c); + pf = get_levgen_mon_floor(&lvl, &c); if (pf == You_fail) { continue; @@ -597,7 +603,7 @@ void populate_level(void) /* Generate some random treasure */ for (i = 0; i < ic; i++) { - pf = get_levgen_mon_floor(&c); + pf = get_levgen_mon_floor(&lvl, &c); if (pf == You_fail) { continue; @@ -607,12 +613,12 @@ void populate_level(void) } /*! \brief Inject the player into the level based on where they arrived from */ -void inject_player(Level_key from) +void inject_player(Level *l, Level_key from) { /* For now we are allowing only one linkage between levels */ Coord c; std::vector stair_list; - int i = lvl.find_stairs(from, &stair_list); + int i = l->find_stairs(from, &stair_list); if (i != 0) { c = stair_list[0].pos; @@ -818,16 +824,8 @@ uint32_t rotate_connection_mask(uint32_t val, int clockwise_steps) void level_cleanup(void) { - int i; - for (i = 0; i < MONSTERS_IN_PLAY; ++i) - { - monsters[i].used = false; - } - for (i = 0; i < OBJECTS_IN_PLAY; ++i) - { - objects[i].used = false; - objects[i].with_you = false; - } + monsters.clear(); + objects.clear(); drop_all_chunks(&lvl); } diff --git a/map.hh b/map.hh index 3f5bbcf..532bb03 100644 --- a/map.hh +++ b/map.hh @@ -105,8 +105,8 @@ extern Terrain_props terrain_props[NUM_TERRAINS]; class Chunk { public: - int objs[CHUNK_EDGE][CHUNK_EDGE]; - int mons[CHUNK_EDGE][CHUNK_EDGE]; + Obj_handle objs[CHUNK_EDGE][CHUNK_EDGE]; + Mon_handle mons[CHUNK_EDGE][CHUNK_EDGE]; Terrain terrain[CHUNK_EDGE][CHUNK_EDGE]; uint32_t flags[CHUNK_EDGE][CHUNK_EDGE]; uint32_t region_number[CHUNK_EDGE][CHUNK_EDGE]; @@ -217,14 +217,14 @@ public: ch->clear_flags_at(c2, to_clear); } } - int mon_at(Coord c) const + Mon_handle mon_at(Coord c) const { Coord rc = c + origin_off; Coord c2 = { rc.y & CHUNK_MASK, rc.x & CHUNK_MASK }; Chunk const *ch = chunks[rc.y >> CHUNK_SHIFT][rc.x >> CHUNK_SHIFT]; return ch ? ch->mon_at(c2) : NO_MON; } - void set_mon_at(Coord c, int mon) + void set_mon_at(Coord c, Mon_handle mon) { Coord rc = c + origin_off; Coord c2 = { rc.y & CHUNK_MASK, rc.x & CHUNK_MASK }; @@ -234,14 +234,14 @@ public: ch->set_mon_at(c2, mon); } } - int obj_at(Coord c) const + Obj_handle obj_at(Coord c) const { Coord rc = c + origin_off; Coord c2 = { rc.y & CHUNK_MASK, rc.x & CHUNK_MASK }; Chunk const *ch = chunks[rc.y >> CHUNK_SHIFT][rc.x >> CHUNK_SHIFT]; return ch ? ch->obj_at(c2) : NO_OBJ; } - void set_obj_at(Coord c, int obj) + void set_obj_at(Coord c, Obj_handle obj) { Coord rc = c + origin_off; Coord c2 = { rc.y & CHUNK_MASK, rc.x & CHUNK_MASK }; @@ -293,7 +293,7 @@ void leave_level(void); void make_new_level(void); void build_level(void); void populate_level(void); -void inject_player(Level_key from); +void inject_player(Level *l, Level_key from); void look_around_you(void); bool terrain_is_opaque(Terrain terr); bool terrain_blocks_beings(Terrain terr); diff --git a/mapgen.hh b/mapgen.hh index 4936e8e..4f16841 100644 --- a/mapgen.hh +++ b/mapgen.hh @@ -42,18 +42,18 @@ extern int depth; extern enum level_theme current_theme; extern enum level_layout current_layout; -void build_level_shrine(void); -void build_level_intrusions(void); -void build_level_cave(void); -void build_level_dungeonbash(void); -Pass_fail get_levgen_mon_floor(Coord *c); -int excavation_write(Coord c, void const *data); -int intrusion_write(Coord c, void const *data); +void build_level_shrine(Level *l); +void build_level_intrusions(Level *l); +void build_level_cave(Level *l); +void build_level_dungeonbash(Level *l); +Pass_fail get_levgen_mon_floor(Level *l, Coord *c); +int excavation_write(Level *l, Coord c, void const *data); +int intrusion_write(Level *l, Coord c, void const *data); void initialize_chunks(Level *l, int height, int width, bool dense); void drop_all_chunks(Level *l); -void place_shrine(Coord topleft, shrine const *sh, uint32_t accept_conns = 0, Terrain shwall = MASONRY_WALL, Terrain shfloor = FLOOR, bool margin_is_wall = false); -void place_random_intrusion(Terrain new_wall = WALL); -void place_cave_stairs(void); +void place_shrine(Level *l, Coord topleft, shrine const *sh, uint32_t accept_conns = 0, Terrain shwall = MASONRY_WALL, Terrain shfloor = FLOOR, bool margin_is_wall = false); +void place_random_intrusion(Level *l, Terrain new_wall = WALL); +void place_cave_stairs(Level *l); #define ROOMCONN_NORTH 0x00000001u #define ROOMCONN_EAST 0x00000002u @@ -61,10 +61,10 @@ void place_cave_stairs(void); #define ROOMCONN_WEST 0x00000008u uint32_t rotate_connection_mask(uint32_t val, int clockwise_steps); -typedef int (*rwalk_mod_funcptr)(Coord c, void const *data); -Coord run_random_walk(Coord oc, rwalk_mod_funcptr func, +typedef int (*rwalk_mod_funcptr)(Level *l, Coord c, void const *data); +Coord run_random_walk(Level *l, Coord oc, rwalk_mod_funcptr func, void const *priv_ptr, int cells); -Coord run_random_walk_unbounded(Coord oc, rwalk_mod_funcptr func, +Coord run_random_walk_unbounded(Level *l, Coord oc, rwalk_mod_funcptr func, void const *priv_ptr, int cells); #endif diff --git a/mon2.cc b/mon2.cc index 9f216bf..7c6c716 100644 --- a/mon2.cc +++ b/mon2.cc @@ -48,7 +48,7 @@ static void get_drunk_prefs(Coord loc, Offset delta, Coord *pref_pos); static void build_ai_cells(struct ai_cell *cells, Coord loc); static Comparison ai_cell_compare(struct ai_cell *cell, Offset delta); static void get_dodger_prefs(Coord loc, Offset delta, Coord *pref_pos); -static void get_chase_prefs(int mon, Coord *pref_pos); +static void get_chase_prefs(Mon_handle mon, Coord *pref_pos); /* get_drunk_prefs() * @@ -105,9 +105,9 @@ static void get_drunk_prefs(Coord loc, Offset delta, Coord *pref_pos) * details. */ -static void get_chase_prefs(int mon, Coord *pref_pos) +static void get_chase_prefs(Mon_handle mon, Coord *pref_pos) { - Mon const *mptr = monsters + mon; + Mon const *mptr = mon_snapv(mon); Offset delta = mptr->ai_lastpos.delta(mptr->pos); Offset step = mysign(delta); Offset absdelta = myabs(delta); @@ -192,7 +192,7 @@ static void get_seeking_prefs(Coord loc, Offset delta, Coord *pref_pos) int i; int highest_score = AI_REALLY_HATE; int tryct; - Mon *mptr = monsters + lvl.mon_at(loc); + Mon *mptr = mon_snapv(lvl.mon_at(loc)); *pref_pos = loc; build_ai_cells(ai_cells, loc); for (i = 0; i < 8; i++) @@ -367,7 +367,7 @@ static void get_dodger_prefs(Coord loc, Offset delta, Coord *pref_pos) Offset absdelta = myabs(delta); int highest_score = AI_REALLY_HATE; int tryct; - Mon *mptr = monsters + lvl.mon_at(loc); + Mon *mptr = mon_snapv(lvl.mon_at(loc)); *pref_pos = loc; build_ai_cells(ai_cells, loc); /* Build the local dx/dy arrays. */ @@ -444,7 +444,7 @@ void select_space(Coord *pc, Offset delta, int selection_mode) Offset absdelta = myabs(delta); Coord c; Offset step = mysign(delta); - Mon *mptr = monsters + lvl.mon_at(*pc); + Mon *mptr = mon_snapv(lvl.mon_at(*pc)); switch (selection_mode) { case AI_charger: @@ -566,14 +566,14 @@ void select_space(Coord *pc, Offset delta, int selection_mode) break; case AI_chaser: /* "chase" AI i.e. pursue your last known position. */ - get_chase_prefs(mptr - monsters, ai_pos); + get_chase_prefs(mptr->self, ai_pos); c = ai_pos[0]; break; } *pc = c; } -void mon_acts(int mon) +void mon_acts(Mon_handle mon) { Mon *mptr; Offset delta; @@ -582,7 +582,7 @@ void mon_acts(int mon) bool meleerange; bool oncardinal; bool special_used = false; - mptr = monsters + mon; + mptr = mon_snapv(mon); /* dy,dx == direction monster must go to reach you. */ c = mptr->pos; delta = u.pos.delta(c); @@ -592,17 +592,17 @@ void mon_acts(int mon) if (delta.len_cheb() == 0) { debug_misplaced_monster(); - mptr->used = false; + mptr->flags &= ~MF_USED; lvl.set_mon_at(c, NO_MON); return; } if (lvl.mon_at(c) != mon) { debug_misplaced_monster(); - mptr->used = false; + mptr->flags &= ~MF_USED; if (lvl.mon_at(c) != NO_MON) { - monsters[lvl.mon_at(c)].used = false; + monsters[lvl.mon_at(c)].flags &= ~MF_USED; lvl.set_mon_at(c, NO_MON); } return; @@ -620,14 +620,14 @@ void mon_acts(int mon) /* Adjacent! Attack you. Demons have a 1 in 10 chance of attempting to * summon another demon instead of attacking you, if that individual * demon has not summoned in the last 100 ticks. */ - if ((mptr->mon_id == PM_DEMON) && (mptr->next_summon < game_tick) && + if ((mptr->pm_ref == PM_DEMON) && (mptr->next_summon < game_tick) && !zero_die(10)) { summon_demon_near(c); mptr->next_summon = game_tick + 100; special_used = true; } - else if (pmon_is_magician(mptr->mon_id)) + else if (pmon_is_magician(mptr->pm_ref)) { special_used = mon_use_sorcery(mon); } @@ -639,7 +639,7 @@ void mon_acts(int mon) else if (mon_visible(mon)) { /* In sight. */ - if (pmon_is_magician(mptr->mon_id)) + if (pmon_is_magician(mptr->pm_ref)) { /* Two-thirds of the time, try to use sorcery. */ if (zero_die(6) < 4) @@ -654,7 +654,7 @@ void mon_acts(int mon) * as if an archer. */ select_space(&c, delta, AI_archer); } - else if (pmon_is_archer(mptr->mon_id)) + else if (pmon_is_archer(mptr->pm_ref)) { if (oncardinal && (zero_die(6) < 3)) { @@ -667,7 +667,7 @@ void mon_acts(int mon) } select_space(&c, delta, AI_archer); } - else if (pmon_is_smart(mptr->mon_id)) + else if (pmon_is_smart(mptr->pm_ref)) { select_space(&c, delta, AI_dodger); } @@ -685,7 +685,7 @@ void mon_acts(int mon) { /* Out of LOS, but awake. Stupid monsters move "drunkenly"; smart * monsters (may) seek you out. */ - if (pmon_is_magician(mptr->mon_id)) + if (pmon_is_magician(mptr->pm_ref)) { /* Magicians may have spells that are used when * you are out of sight. For example, some magicians @@ -696,11 +696,11 @@ void mon_acts(int mon) { return; } - if (pmon_is_smart(mptr->mon_id)) + if (pmon_is_smart(mptr->pm_ref)) { select_space(&c, delta, AI_seeker); } - else if (pmon_is_stupid(mptr->mon_id) || (mptr->ai_lastpos == Nowhere)) + else if (pmon_is_stupid(mptr->pm_ref) || (mptr->ai_lastpos == Nowhere)) { select_space(&c, delta, AI_drunk); } diff --git a/monsters.cc b/monsters.cc index a3d8ed4..55fee7c 100644 --- a/monsters.cc +++ b/monsters.cc @@ -31,8 +31,10 @@ #include "monsters.hh" #include "objects.hh" -Mon monsters[100]; -static int reject_mon(int pm); +const Mon_handle NO_MON = 0u; + +std::map monsters; +static bool reject_mon(int pm); /*! \brief Summon some monsters * @@ -45,7 +47,7 @@ int summoning(Coord c, int how_many) Offset delta; Coord testpos; int tryct; - int mon; + Mon_handle mon; int created = 0; int pmon; for (i = 0; i < how_many; i++) @@ -98,9 +100,19 @@ int get_random_pmon(void) return pm; } -int create_mon(int pm_idx, Coord c) +Mon_handle first_free_mon_handle = 1u; +static Mon_handle get_first_free_mon(void) { - int mon; + if (first_free_mon_handle == NO_MON) + { + return NO_MON; + } + return first_free_mon_handle++; +} + +Mon_handle create_mon(int pm_idx, Coord c) +{ + Mon_handle mon; if (lvl.mon_at(c) != NO_MON) { debug_create_mon_occupied(c); @@ -115,45 +127,44 @@ int create_mon(int pm_idx, Coord c) return NO_MON; } } - for (mon = 0; mon < 100; mon++) - { - if (!monsters[mon].used) - { - monsters[mon].mon_id = pm_idx; - monsters[mon].used = true; - monsters[mon].pos = c; - monsters[mon].ai_lastpos = Nowhere; - monsters[mon].hpmax = permons[pm_idx].hp + ood(permons[pm_idx].power, 1); - monsters[mon].hpcur = monsters[mon].hpmax; - monsters[mon].mtohit = permons[pm_idx].mtohit + ood(permons[pm_idx].power, 3); - monsters[mon].defence = permons[pm_idx].defence + ood(permons[pm_idx].power, 3); - monsters[mon].mdam = permons[pm_idx].mdam + ood(permons[pm_idx].power, 5); - if (permons[pm_idx].rdam != NO_ATK) - { - monsters[mon].rtohit = permons[pm_idx].rtohit + ood(permons[pm_idx].power, 3); - monsters[mon].rdam = permons[pm_idx].rdam + ood(permons[pm_idx].power, 5); - } - else - { - monsters[mon].rtohit = NO_ATK; - monsters[mon].rdam = NO_ATK; - } - monsters[mon].awake = false; - lvl.set_mon_at(c, mon); - if (mon_visible(mon)) - { - notify_new_mon_at(c, mon); - } - return mon; - } + mon = get_first_free_mon(); + if (mon != NO_MON) + { + Mon m; + m.pm_ref = pm_idx; + m.flags = MF_USED | MF_ALIVE; + m.pos = c; + m.ai_lastpos = Nowhere; + m.hpmax = permons[pm_idx].hp + ood(permons[pm_idx].power, 1); + m.hpcur = m.hpmax; + m.mtohit = permons[pm_idx].mtohit + ood(permons[pm_idx].power, 3); + m.defence = permons[pm_idx].defence + ood(permons[pm_idx].power, 3); + m.mdam = permons[pm_idx].mdam + ood(permons[pm_idx].power, 5); + if (permons[pm_idx].rdam != NO_ATK) + { + m.rtohit = permons[pm_idx].rtohit + ood(permons[pm_idx].power, 3); + m.rdam = permons[pm_idx].rdam + ood(permons[pm_idx].power, 5); + } + else + { + m.rtohit = NO_ATK; + m.rdam = NO_ATK; + } + monsters[mon] = m; + lvl.set_mon_at(c, mon); + if (mon_visible(mon)) + { + notify_new_mon_at(c, mon); + } + return mon; } return NO_MON; } -void death_drop(int mon) +void death_drop(Mon_handle mon) { - Mon *mptr = monsters + mon; - int pm = mptr->mon_id; + Mon *mptr = mon_snapv(mon); + int pm = mptr->pm_ref; Coord c = mptr->pos; Offset delta; int tryct = 0; @@ -279,7 +290,7 @@ bool Mon::can_pass(Coord c) const return true; } -void heal_mon(int mon, int amount, int cansee) +void heal_mon(Mon_handle mon, int amount, int cansee) { if (amount > (monsters[mon].hpmax - monsters[mon].hpcur)) { @@ -295,17 +306,17 @@ void heal_mon(int mon, int amount, int cansee) } } -void unplace_mon(int mon) +void unplace_mon(Mon_handle mon) { lvl.set_mon_at(monsters[mon].pos, NO_MON); - monsters[mon].used = false; + monsters[mon].flags &= ~MF_USED; } /*! \brief Handle the death of a monster * * \todo Support special effects on monster death */ -void kill_mon(int mon, bool by_you) +void kill_mon(Mon_handle mon, bool by_you) { death_drop(mon); // phat lewt! monsters[mon].hpcur = -1; // Set HP to -1 so nothing will think it's alive @@ -313,7 +324,7 @@ void kill_mon(int mon, bool by_you) if (by_you) { notify_player_killed_mon(mon); - gain_experience(permons[monsters[mon].mon_id].exp); + gain_experience(permons[monsters[mon].pm_ref].exp); } else if (mon_visible(mon)) { @@ -321,10 +332,10 @@ void kill_mon(int mon, bool by_you) } } -void damage_mon(int mon, int amount, bool by_you) +void damage_mon(Mon_handle mon, int amount, bool by_you) { Mon *mptr; - mptr = monsters + mon; + mptr = mon_snapv(mon); if (amount >= mptr->hpcur) { kill_mon(mon, by_you); @@ -335,22 +346,22 @@ void damage_mon(int mon, int amount, bool by_you) } } -int reject_mon(int pm) +bool reject_mon(int pm) { if ((permons[pm].power > depth) || (zero_die(100) < permons[pm].rarity)) { - return 1; + return true; } - return 0; + return false; } -Pass_fail teleport_mon_to_you(int mon) +Pass_fail teleport_mon_to_you(Mon_handle mon) { int tryct; Offset delta; Coord c; int success = 0; - Mon *mptr = monsters + mon; + Mon *mptr = mon_snapv(mon); Coord oldpos = mptr->pos; for (tryct = 0; tryct < 40; tryct++) { @@ -371,7 +382,7 @@ Pass_fail teleport_mon_to_you(int mon) return You_fail; } -Pass_fail teleport_mon(int mon) +Pass_fail teleport_mon(Mon_handle mon) { Pass_fail rval = You_fail; int cell_try; @@ -389,10 +400,10 @@ Pass_fail teleport_mon(int mon) return rval; } -int knockback_mon(int mon, Offset step, bool cansee, bool by_you) +int knockback_mon(Mon_handle mon, Offset step, bool cansee, bool by_you) { /* 0 = blocked, 1 = knocked, 2 = killed */ - Mon *mptr = monsters + mon; + Mon *mptr = mon_snapv(mon); Coord c = mptr->pos + step; Coord savedpos = mptr->pos; Terrain terr = lvl.terrain_at(c); @@ -472,9 +483,9 @@ int knockback_mon(int mon, Offset step, bool cansee, bool by_you) return 1; } -void reloc_mon(int mon, Coord newpos) +void reloc_mon(Mon_handle mon, Coord newpos) { - Mon *mptr = monsters + mon; + Mon *mptr = mon_snapv(mon); lvl.set_mon_at(mptr->pos, NO_MON); notify_new_mon_at(mptr->pos, NO_MON); mptr->pos = newpos; @@ -482,10 +493,10 @@ void reloc_mon(int mon, Coord newpos) notify_new_mon_at(mptr->pos, mon); } -void move_mon(int mon, Coord c) +void move_mon(Mon_handle mon, Coord c) { Mon *mptr; - mptr = monsters + mon; + mptr = mon_snapv(mon); if (!mptr->can_pass(c)) { debug_mon_invalid_move(mon, c); @@ -502,7 +513,7 @@ void move_mon(int mon, Coord c) void summon_demon_near(Coord c) { Coord c2 = c + random_step(); - int mon; + Mon_handle mon; if ((lvl.terrain_at(c2) == FLOOR) && (lvl.mon_at(c2) == NO_MON) && (c2 != u.pos)) { @@ -511,14 +522,15 @@ void summon_demon_near(Coord c) } } -bool mon_visible(int mon) +bool mon_visible(Mon_handle mon) { Offset delta; - if (monsters[mon].used == 0) + Mon const *mptr = mon_snap(mon); + if (!(mptr->flags & MF_USED)) { return false; } - delta = monsters[mon].pos.delta(u.pos); + delta = mptr->pos.delta(u.pos); if (delta.len_cheb() <= MAX_FOV_RADIUS) { return (player_fov.affected[MAX_FOV_RADIUS + delta.y][MAX_FOV_RADIUS + delta.x]) & Visflag_central; @@ -529,14 +541,15 @@ bool mon_visible(int mon) } } -void update_mon(int mon) +void update_mon(Mon_handle mon) { int cansee; - if (monsters[mon].hpcur < monsters[mon].hpmax) + Mon *mptr = mon_snapv(mon); + if (mptr->hpcur < mptr->hpmax) { cansee = mon_visible(mon); - // TODO modify regen handling to use flags/fields instead of switching on mon_id - switch (monsters[mon].mon_id) + // TODO modify regen handling to use flags/fields instead of switching on pm_ref + switch (mptr->pm_ref) { case PM_TROLL: if (!(game_tick % 10)) @@ -568,19 +581,19 @@ bool Mon::resists(Damtyp dt) const switch (dt) { case DT_COLD: - return pmon_resists_cold(mon_id); + return pmon_resists_cold(pm_ref); case DT_FIRE: - return pmon_resists_fire(mon_id); + return pmon_resists_fire(pm_ref); case DT_POISON: - return pmon_resists_poison(mon_id); + return pmon_resists_poison(pm_ref); case DT_NECRO: - return pmon_resists_necro(mon_id); + return pmon_resists_necro(pm_ref); case DT_ELEC: - return pmon_resists_elec(mon_id); + return pmon_resists_elec(pm_ref); case DT_KNOCKBACK: - return pmon_resists_knockback(mon_id); + return pmon_resists_knockback(pm_ref); case DT_DROWNING: - return pmon_resists_drowning(mon_id); + return pmon_resists_drowning(pm_ref); default: return false; } @@ -588,12 +601,12 @@ bool Mon::resists(Damtyp dt) const bool Mon::is_ethereal(void) const { - return pmon_is_ethereal(mon_id); + return pmon_is_ethereal(pm_ref); } bool Mon::can_fly(void) const { - return pmon_can_fly(mon_id); + return pmon_can_fly(pm_ref); } /* monsters.c */ diff --git a/monsters.hh b/monsters.hh index fc8fd38..a845ca0 100644 --- a/monsters.hh +++ b/monsters.hh @@ -38,13 +38,18 @@ #endif /* XXX struct mon */ -#define MONSTERS_IN_PLAY 100 + +#define MF_AWAKE 0x00000001u // gets turns +#define MF_ALIVE 0x00000002u // gets displayed +#define MF_USED 0x00000004u // legacy cruft + class Mon { public: - int mon_id; + Mon_handle self; + int pm_ref; Coord pos; Coord ai_lastpos; - bool used; + uint32_t flags; int hpmax; /* Improved by OOD rating at 1:1. */ int hpcur; /* <= 0 is dead. */ int mtohit; /* Improved by OOD rating at 1:3. */ @@ -54,39 +59,52 @@ public: int rdam; /* Improved by OOD rating at 1:5. */ bool awake; int next_summon; + /* member functions only past this point please */ bool resists(Damtyp dt) const; bool can_pass(Coord c) const; bool can_fly(void) const; bool is_ethereal(void) const; }; -extern Mon monsters[MONSTERS_IN_PLAY]; +#include +extern std::map monsters; + +inline Mon *mon_snapv(Mon_handle mon) +{ + auto iter = monsters.find(mon); + return ((iter == monsters.end()) ? &(iter->second) : nullptr); +} + +inline Mon const *mon_snap(Mon_handle mon) +{ + auto iter = monsters.find(mon); + return ((iter == monsters.end()) ? &(iter->second) : nullptr); +} -#define NO_MON (-1) #define PLAYER_MON (-2) /* XXX monsters.c data and funcs */ -extern void update_mon(int mon); -extern void mon_acts(int mon); -extern void death_drop(int mon); -extern void print_mon_name(int mon, int article); -extern void summon_demon_near(Coord c); -extern int create_mon(int pm_idx, Coord c); -extern int summoning(Coord c, int how_many); -extern int ood(int power, int ratio); -extern int get_random_pmon(void); -extern void damage_mon(int mon, int amount, bool by_you); -extern bool mon_visible(int mon); -extern int knockback_mon(int mon, Offset step, bool cansee, bool by_you); -extern void move_mon(int mon, Coord c); -extern void reloc_mon(int mon, Coord c); -extern Pass_fail teleport_mon(int mon); /* Randomly relocate monster. */ -extern Pass_fail teleport_mon_to_you(int mon); /* Relocate monster to your vicinity. */ -extern void heal_mon(int mon, int amount, int cansee); -extern void kill_mon(int mon, bool by_you); -extern void unplace_mon(int mon); +void update_mon(Mon_handle mon); +void mon_acts(Mon_handle mon); +void death_drop(Mon_handle mon); +void print_mon_name(Mon_handle mon, int article); +void summon_demon_near(Coord c); +Mon_handle create_mon(int pm_idx, Coord c); +int summoning(Coord c, int how_many); +int ood(int power, int ratio); +int get_random_pmon(void); +void damage_mon(Mon_handle mon, int amount, bool by_you); +bool mon_visible(Mon_handle mon); +int knockback_mon(Mon_handle mon, Offset step, bool cansee, bool by_you); +void move_mon(Mon_handle mon, Coord c); +void reloc_mon(Mon_handle mon, Coord c); +Pass_fail teleport_mon(Mon_handle mon); /* Randomly relocate monster. */ +Pass_fail teleport_mon_to_you(Mon_handle mon); /* Relocate monster to your vicinity. */ +void heal_mon(Mon_handle mon, int amount, int cansee); +void kill_mon(Mon_handle mon, bool by_you); +void unplace_mon(Mon_handle mon); /* XXX mon2.c data and funcs */ -extern void select_space(int *py, int *px, int dy, int dx, int selection_mode); +void select_space(Coord *pc, Offset delta, int selection_mode); #endif diff --git a/notify-local-tty.cc b/notify-local-tty.cc index 0497681..c976ca3 100644 --- a/notify-local-tty.cc +++ b/notify-local-tty.cc @@ -274,7 +274,7 @@ void notify_wasted_gain(void) print_msg("You feel disappointed.\n"); } -void notify_summon_help(int mon, bool success) +void notify_summon_help(Mon_handle mon, bool success) { /* Do the summoning... */ print_mon_name(mon, 3); @@ -289,7 +289,7 @@ void notify_summon_help(int mon, bool success) } } -void notify_summon_demon(int mon) +void notify_summon_demon(Mon_handle mon) { if (mon != NO_MON) { @@ -301,7 +301,7 @@ void notify_summon_demon(int mon) } } -void notify_mon_disappear(int mon) +void notify_mon_disappear(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" vanishes in a puff of smoke.\n"); @@ -345,7 +345,7 @@ void notify_hellfire_hit(bool resisted) print_msg("The fires of hell %s\n", resisted ? "lightly singe you." : "burn you!"); } -void notify_monster_cursing(int mon) +void notify_monster_cursing(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" points at you and curses horribly.\n"); @@ -361,21 +361,21 @@ void notify_knockback_mon_pass(void) print_msg("Your foe is knocked backwards by the force of the shot.\n"); } -void notify_player_miss(int mon) +void notify_player_miss(Mon_handle mon) { print_msg("You miss "); print_mon_name(mon, 1); print_msg(".\n"); } -void notify_player_hit_mon(int mon) +void notify_player_hit_mon(Mon_handle mon) { print_msg("You hit "); print_mon_name(mon, 1); print_msg(".\n"); } -void notify_player_combo_powatk(int mon) +void notify_player_combo_powatk(Mon_handle mon) { print_msg("You deal a powerful blow to "); print_mon_name(mon, 1); @@ -387,12 +387,12 @@ void notify_point_blank_warning(void) print_msg(Msg_prio::Alert, "Using a bow at such close quarters is awkward, and you are unlikely to hit your target.\n"); } -void notify_player_shot_terrain(int obj, Coord c) +void notify_player_shot_terrain(Obj_handle obj, Coord c) { - print_msg("Your %s hits the %s.\n", (objects[obj].obj_id == PO_CROSSBOW) ? "bolt" : "arrow", terrain_props[lvl.terrain_at(c)].name); + print_msg("Your %s hits the %s.\n", (objects[obj].po_ref == PO_CROSSBOW) ? "bolt" : "arrow", terrain_props[lvl.terrain_at(c)].name); } -void notify_ring_boost(int mon, int pobj) +void notify_ring_boost(Mon_handle mon, int pobj) { switch (pobj) { @@ -414,12 +414,12 @@ void notify_ring_boost(int mon, int pobj) } } -void notify_player_hurt_mon(int mon, int damage) +void notify_player_hurt_mon(Mon_handle mon, int damage) { print_msg("You do %d damage.\n", damage); } -void notify_player_killed_mon(int mon) +void notify_player_killed_mon(Mon_handle mon) { newsym(monsters[mon].pos); print_msg("You kill "); @@ -434,7 +434,7 @@ void notify_player_killed_mon(int mon) print_msg("!\n"); } -void notify_mon_dies(int mon) +void notify_mon_dies(Mon_handle mon) { newsym(monsters[mon].pos); if (occupant_visible(monsters[mon].pos)) @@ -444,37 +444,37 @@ void notify_mon_dies(int mon) } } -void notify_knockback_mon_resisted(int mon) +void notify_knockback_mon_resisted(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" wobbles slightly.\n"); } -void notify_knockback_mon_blocked(int mon) +void notify_knockback_mon_blocked(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" is slammed against the wall.\n"); } -void notify_knockback_mon_hover_lava(int mon) +void notify_knockback_mon_hover_lava(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" is hurled out over the lava.\n"); } -void notify_knockback_mon_hover_water(int mon) +void notify_knockback_mon_hover_water(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" is hurled out over the water.\n"); } -void notify_knockback_mon_immersed_lava(int mon) +void notify_knockback_mon_immersed_lava(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" tumbles into a pool of molten rock.\n"); } -void notify_knockback_mon_immersed_water(int mon) +void notify_knockback_mon_immersed_water(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" tumbles into the water.\n"); @@ -490,38 +490,38 @@ void notify_knockback_mon_water_offscreen(void) print_msg("Splash!\n"); } -void notify_mon_disappears(int mon, Coord oldpos) +void notify_mon_disappears(Mon_handle mon, Coord oldpos) { } -void notify_mon_appears(int mon) +void notify_mon_appears(Mon_handle mon) { print_mon_name(mon, 2); print_msg(" appears in a puff of smoke.\n"); } -void notify_mon_hit_armour(int mon) +void notify_mon_hit_armour(Mon_handle mon) { print_msg("Your armour deflects "); print_mon_name(mon, 1); print_msg("'s blow.\n"); } -void notify_mon_missed_player(int mon) +void notify_mon_missed_player(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" misses you.\n"); } -void notify_mon_hit_player(int mon) +void notify_mon_hit_player(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" hits you.\n"); } -void notify_mon_ranged_attack(int mon) +void notify_mon_ranged_attack(Mon_handle mon) { - int pm = monsters[mon].mon_id; + int pm = monsters[mon].pm_ref; Damtyp dt = permons[pm].rdtyp; print_mon_name(mon, 3); if (dt == DT_PHYS) @@ -540,12 +540,12 @@ void notify_mon_ranged_hit_mon(int er, int ee) print_msg("It hits a bystander.\n"); } -void notify_mon_ranged_missed_player(int mon) +void notify_mon_ranged_missed_player(Mon_handle mon) { print_msg("It misses you.\n"); } -void notify_mon_ranged_hit_player(int mon) +void notify_mon_ranged_hit_player(Mon_handle mon) { print_msg("It hits you!\n"); } @@ -586,12 +586,12 @@ void notify_zap_powerless_weapon(void) print_msg("Your current weapon seems to have no magic powers to activate.\n"); } -void notify_armour_equip(int obj) +void notify_armour_equip(Obj_handle obj) { - Permobj *pobj = permobjs + objects[obj].obj_id; + Permobj *pobj = permobjs + objects[obj].po_ref; if (pobj->flags[0] & POF_NOTIFY_EQUIP) { - switch (objects[u.armour].obj_id) + switch (objects[u.armour].po_ref) { case PO_FOETID_VESTMENTS: if (u.rotten()) @@ -622,13 +622,13 @@ void notify_armour_equip(int obj) } } -void notify_armour_unequip(int obj) +void notify_armour_unequip(Obj_handle obj) { - Permobj *pobj = permobjs + objects[obj].obj_id; + Permobj *pobj = permobjs + objects[obj].po_ref; // TODO add unequip messages for NOTIFY_EQUIP armours. if (pobj->flags[0] & POF_NOTIFY_EQUIP) { - switch (objects[obj].obj_id) + switch (objects[obj].po_ref) { case PO_LICHS_ROBE: print_msg("The supernatural chill of the robes lingers in your bones even after you put them aside.\n"); @@ -657,14 +657,14 @@ void notify_armour_unequip(int obj) } } -void notify_ring_equip(int obj) +void notify_ring_equip(Obj_handle obj) { print_msg("You put on "); print_obj_name(obj); print_msg(".\n"); } -void notify_ring_unequip(int obj) +void notify_ring_unequip(Obj_handle obj) { print_msg("You remove your ring.\n"); } @@ -735,9 +735,9 @@ void notify_player_ignore_damage(Damtyp dt) } } -void notify_item_explodes_flames(int obj) +void notify_item_explodes_flames(Obj_handle obj) { - print_msg("The %s explodes in flames!\n", permobjs[objects[obj].obj_id].name); + print_msg("The %s explodes in flames!\n", permobjs[objects[obj].po_ref].name); } void notify_read_scroll_protection(void) @@ -789,7 +789,7 @@ void notify_firestaff_activation(int specific) } } -void notify_fireitem_hit(int mon) +void notify_fireitem_hit(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" is engulfed in roaring flames.\n"); @@ -866,19 +866,19 @@ void notify_nothing_to_get(void) print_msg("Nothing to get.\n"); } -void notify_mon_healed(int mon) +void notify_mon_healed(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" looks healthier.\n"); } -void notify_mon_regenerates(int mon) +void notify_mon_regenerates(Mon_handle mon) { // TODO allow things that aren't trolls to be regenerators print_msg("The troll regenerates.\n"); } -void notify_unwield(int obj, Noisiness noisy) +void notify_unwield(Obj_handle obj, Noisiness noisy) { if (noisy == Noise_std) { @@ -886,24 +886,24 @@ void notify_unwield(int obj, Noisiness noisy) } } -void notify_wield_weapon(int obj) +void notify_wield_weapon(Obj_handle obj) { print_msg("Wielding "); print_obj_name(obj); print_msg(".\n"); } -void notify_weapon_broke(int obj) +void notify_weapon_broke(Obj_handle obj) { print_msg(Msg_prio::Warn, "Your weapon breaks!\n"); } -void notify_armour_broke(int obj) +void notify_armour_broke(Obj_handle obj) { print_msg(Msg_prio::Warn, "Your armour is ruined!\n"); } -void notify_drop_item(int obj) +void notify_drop_item(Obj_handle obj) { print_msg("You drop "); print_obj_name(obj); @@ -915,7 +915,7 @@ void notify_drop_blocked(void) print_msg(Msg_prio::Alert, "There is no room to drop that here.\n"); } -void notify_get_item(int from, int slot) +void notify_get_item(Obj_handle from, int slot) { if (from != NO_OBJ) { @@ -948,7 +948,7 @@ void notify_pack_full(void) * \param c Affected location * \param mon Monster at that location. */ -void notify_new_mon_at(Coord c, int mon) +void notify_new_mon_at(Coord c, Mon_handle mon) { newsym(c); display_update(); @@ -1052,9 +1052,9 @@ void debug_read_non_scroll(void) print_msg(Msg_prio::Bug, "BUG: reading non-scroll\n"); } -void debug_eat_non_food(int obj) +void debug_eat_non_food(Obj_handle obj) { - print_msg(Msg_prio::Bug, "BUG: attempt to eat non-food (%d)!\n", objects[obj].obj_id); + print_msg(Msg_prio::Bug, "BUG: attempt to eat non-food (%d)!\n", objects[obj].po_ref); } void debug_quaff_non_potion(void) @@ -1137,7 +1137,7 @@ void debug_unimplemented_break_reaction(int po) print_msg(Msg_prio::Bug, "BUG: permobj %d should react to hitting durability 0 but has no break reaction handler.\n"); } -void debug_mon_invalid_move(int mon, Coord c) +void debug_mon_invalid_move(Mon_handle mon, Coord c) { print_msg(Msg_prio::Bug, "BUG: monster %d attempted move to impassable location y=%d x=%d\n", mon, c.y, c.x); } diff --git a/notify.hh b/notify.hh index c6778f5..a90d738 100644 --- a/notify.hh +++ b/notify.hh @@ -64,10 +64,10 @@ void notify_cant_go(void); // Unsorted notifications void notify_obj_at(Coord c); void notify_dress_shredded(void); -void notify_mon_healed(int mon); -void notify_mon_regenerates(int mon); -void notify_mon_disappears(int mon, Coord oldpos); -void notify_mon_appears(int mon); +void notify_mon_healed(Mon_handle mon); +void notify_mon_regenerates(Mon_handle mon); +void notify_mon_disappears(Mon_handle mon, Coord oldpos); +void notify_mon_appears(Mon_handle mon); // Item manipulation notifications void notify_magic_no_ring(void); @@ -76,20 +76,20 @@ void notify_zap_no_weapon(void); void notify_magic_powerless_ring(void); void notify_emanate_powerless_armour(void); void notify_zap_powerless_weapon(void); -void notify_ring_equip(int obj); -void notify_ring_unequip(int obj); -void notify_armour_equip(int obj); -void notify_armour_unequip(int obj); +void notify_ring_equip(Obj_handle obj); +void notify_ring_unequip(Obj_handle obj); +void notify_armour_equip(Obj_handle obj); +void notify_armour_unequip(Obj_handle obj); void notify_lava_blocks_unequip(void); void notify_water_blocks_unequip(void); void notify_nothing_to_get(void); -void notify_unwield(int obj, Noisiness noisy); -void notify_wield_weapon(int obj); -void notify_weapon_broke(int obj); -void notify_armour_broke(int obj); -void notify_drop_item(int obj); +void notify_unwield(Obj_handle obj, Noisiness noisy); +void notify_wield_weapon(Obj_handle obj); +void notify_weapon_broke(Obj_handle obj); +void notify_armour_broke(Obj_handle obj); +void notify_drop_item(Obj_handle obj); void notify_drop_blocked(void); -void notify_get_item(int from, int slot); +void notify_get_item(Obj_handle from, int slot); void notify_pack_full(void); // Magic item use releated notifications @@ -100,10 +100,10 @@ void notify_quaff_potion_restoration(void); void notify_ribbon_activation(int specific); void notify_lash_activation(int specific); void notify_firestaff_activation(int specific); -void notify_fireitem_hit(int mon); +void notify_fireitem_hit(Mon_handle mon); void notify_telering_activation(int specific); -void notify_item_explodes_flames(int obj); +void notify_item_explodes_flames(Obj_handle obj); void notify_eat_food(bool ravenous); void notify_ingest_spleen(void); @@ -111,43 +111,43 @@ void notify_ingest_spleen(void); void notify_swing_bow(void); void notify_no_attackee(void); void notify_no_flask_target(void); -void notify_player_miss(int mon); -void notify_ring_boost(int mon, int pobj); -void notify_player_hit_mon(int mon); -void notify_player_hurt_mon(int mon, int damage); -void notify_player_killed_mon(int mon); -void notify_player_combo_powatk(int mon); -void notify_knockback_mon_resisted(int mon); -void notify_knockback_mon_blocked(int mon); -void notify_knockback_mon_hover_lava(int mon); -void notify_knockback_mon_hover_water(int mon); -void notify_knockback_mon_immersed_lava(int mon); -void notify_knockback_mon_immersed_water(int mon); +void notify_player_miss(Mon_handle mon); +void notify_ring_boost(Mon_handle mon, int pobj); +void notify_player_hit_mon(Mon_handle mon); +void notify_player_hurt_mon(Mon_handle mon, int damage); +void notify_player_killed_mon(Mon_handle mon); +void notify_player_combo_powatk(Mon_handle mon); +void notify_knockback_mon_resisted(Mon_handle mon); +void notify_knockback_mon_blocked(Mon_handle mon); +void notify_knockback_mon_hover_lava(Mon_handle mon); +void notify_knockback_mon_hover_water(Mon_handle mon); +void notify_knockback_mon_immersed_lava(Mon_handle mon); +void notify_knockback_mon_immersed_water(Mon_handle mon); void notify_knockback_mon_water_offscreen(void); void notify_knockback_mon_lava_offscreen(void); void notify_point_blank_warning(void); -void notify_player_shot_terrain(int obj, Coord c); - -void notify_mon_hit_armour(int mon); -void notify_mon_missed_player(int mon); -void notify_mon_hit_player(int mon); -void notify_mon_ranged_attack(int mon); -void notify_mon_ranged_hit_player(int mon); -void notify_mon_ranged_missed_player(int mon); +void notify_player_shot_terrain(Obj_handle obj, Coord c); + +void notify_mon_hit_armour(Mon_handle mon); +void notify_mon_missed_player(Mon_handle mon); +void notify_mon_hit_player(Mon_handle mon); +void notify_mon_ranged_attack(Mon_handle mon); +void notify_mon_ranged_hit_player(Mon_handle mon); +void notify_mon_ranged_missed_player(Mon_handle mon); void notify_mon_ranged_hit_mon(int er, int ee); -void notify_mon_dies(int mon); -void notify_new_mon_at(Coord c, int mon); +void notify_mon_dies(Mon_handle mon); +void notify_new_mon_at(Coord c, Mon_handle mon); void notify_player_damage_taken(int amount); void notify_player_touch_effect(Damtyp dt); void notify_player_ignore_damage(Damtyp dt); // Sorcery notifications -void notify_summon_help(int mon, bool success); -void notify_summon_demon(int mon); -void notify_monster_cursing(int mon); -void notify_mon_disappear(int mon); +void notify_summon_help(Mon_handle mon, bool success); +void notify_summon_demon(Mon_handle mon); +void notify_monster_cursing(Mon_handle mon); +void notify_mon_disappear(Mon_handle mon); void notify_moncurse_fail(void); void notify_start_armourmelt(void); void notify_start_withering(void); @@ -178,7 +178,7 @@ void debug_take_off_no_armour(void); void debug_remove_no_ring(void); void debug_put_on_second_ring(void); void debug_put_on_uncarried_ring(void); -void debug_eat_non_food(int obj); +void debug_eat_non_food(Obj_handle obj); void debug_read_non_scroll(void); void debug_quaff_non_potion(void); void debug_ascend_non_stairs(void); @@ -190,7 +190,7 @@ void debug_pobj_select_failed(void); void debug_misplaced_monster(void); void debug_create_mon_occupied(Coord c); void debug_monster_pool_exhausted(void); -void debug_mon_invalid_move(int mon, Coord c); +void debug_mon_invalid_move(Mon_handle mon, Coord c); void debug_pmon_select_failed(void); void debug_dump_write_failed(void); void debug_unimplemented_activation(int po); @@ -210,7 +210,7 @@ bool query_wizmode_death(void); class Notify_uattkm { public: - int mon; + Mon_handle mon; bool hit; int dmg; bool ringflag; diff --git a/objects.cc b/objects.cc index 46788d3..bd1c47e 100644 --- a/objects.cc +++ b/objects.cc @@ -31,7 +31,9 @@ #include "objects.hh" #include "monsters.hh" -Obj objects[100]; +std::map objects; +const Obj_handle NO_OBJ = 0u; + int get_random_pobj(void); char const ring_colours[20][16] = { @@ -55,11 +57,10 @@ char const potion_colours[20][16] = { "navy blue", "bottle green", "amber", "lilac", "ivory" }; -Action_cost read_scroll(int obj) +Action_cost read_scroll(Obj_handle obj) { - Obj *optr = objects + obj; - int i; - switch (optr->obj_id) + Obj *optr = obj_snapv(obj); + switch (optr->po_ref) { case PO_TELEPORT_SCROLL: teleport_u(); @@ -74,17 +75,20 @@ Action_cost read_scroll(int obj) { damage_u(dice(4, 10), DEATH_KILLED, "searing flames"); } +#if 0 + // TODO iterate over visible monsters for (i = 0; i < MONSTERS_IN_PLAY; ++i) { if (mon_visible(i)) { - if (!pmon_resists_fire(monsters[i].mon_id)) + if (!pmon_resists_fire(monsters[i].pm_ref)) { notify_fireitem_hit(i); damage_mon(i, dice(4, 10), true); } } } +#endif break; case PO_PROTECTION_SCROLL: notify_read_scroll_protection(); @@ -119,14 +123,15 @@ Action_cost read_scroll(int obj) return Cost_std; } -bool consume_obj(int obj) +bool consume_obj(Obj_handle obj) { int i; - objects[obj].quan--; - if (objects[obj].quan == 0) + Obj *optr = obj_snapv(obj); + optr->quan--; + if (optr->quan == 0) { - objects[obj].used = false; - if (objects[obj].with_you) + optr->flags &= ~OF_USED; + if (optr->flags & OF_WITH_YOU) { if (obj == u.armour) { @@ -145,34 +150,31 @@ bool consume_obj(int obj) u.ring = NO_OBJ; recalc_defence(); } - if (!objects[obj].used) - { - for (i = 0; i < 19; i++) - { - if (u.inventory[i] == obj) - { - u.inventory[i] = NO_OBJ; - break; - } - } - } + for (i = 0; i < 19; i++) + { + if (u.inventory[i] == obj) + { + u.inventory[i] = NO_OBJ; + break; + } + } } return true; } return false; } -Action_cost eat_food(int obj) +Action_cost eat_food(Obj_handle obj) { - Obj *optr = objects + obj; + Obj *optr = obj_snapv(obj); bool ravenous = (u.food < 0); u.food += 1500; - if (permobjs[optr->obj_id].poclass != POCLASS_FOOD) + if (permobjs[optr->po_ref].poclass != POCLASS_FOOD) { debug_eat_non_food(obj); return Cost_none; } - if (optr->obj_id == PO_DEVIL_SPLEEN) + if (optr->po_ref == PO_DEVIL_SPLEEN) { notify_ingest_spleen(); if (zero_die(2)) @@ -194,10 +196,10 @@ Action_cost eat_food(int obj) return Cost_std; } -Action_cost quaff_potion(int obj) +Action_cost quaff_potion(Obj_handle obj) { - Obj *optr = objects + obj; - switch (optr->obj_id) + Obj *optr = obj_snapv(obj); + switch (optr->po_ref) { case PO_BODY_POTION: gain_body(1); @@ -307,29 +309,21 @@ void flavours_init(void) permobjs[PO_RESTORATION_POTION].power = colour_choices[3]; } -int get_first_free_obj(void) +Obj_handle first_free_obj_handle = 1u; + +Obj_handle get_first_free_obj(void) { - int obj; - for (obj = 0; obj < 100; obj++) + if (first_free_obj_handle == 0u) { - if (!objects[obj].used) - { - break; - } + return NO_OBJ; } - return (obj == 100) ? NO_OBJ : obj; + return first_free_obj_handle++; } -int create_obj_class(enum poclass_num po_class, int quantity, bool with_you, Coord c) +Obj_handle create_obj_class(enum poclass_num po_class, int quantity, bool with_you, Coord c) { int po_idx; int tryct; - int obj = get_first_free_obj(); - if (obj == 100) - { - debug_object_pool_exhausted(); - return NO_OBJ; - } for (tryct = 0; tryct < 200; tryct++) { switch (po_class) @@ -353,9 +347,7 @@ int create_obj_class(enum poclass_num po_class, int quantity, bool with_you, Coo } break; } - objects[obj].obj_id = po_idx; - objects[obj].quan = quantity; - return obj; + return create_obj(po_idx, quantity, with_you, c); } int get_random_pobj(void) @@ -370,9 +362,6 @@ int get_random_pobj(void) po_idx = NO_POBJ; continue; } - /* v1.3: Do not permit generation of particularly powerful - * items (runeswords, mage armour, etc.) at shallow depths. - * (game balance fix) */ if (depth < permobjs[po_idx].depth) { po_idx = NO_POBJ; @@ -383,10 +372,10 @@ int get_random_pobj(void) return po_idx; } -int create_obj(int po_idx, int quantity, bool with_you, Coord c) +Obj_handle create_obj(int po_idx, int quantity, bool with_you, Coord c) { - int obj = get_first_free_obj(); - if (obj == 100) + Obj_handle obj = get_first_free_obj(); + if (obj == NO_OBJ) { debug_object_pool_exhausted(); return NO_OBJ; @@ -400,11 +389,11 @@ int create_obj(int po_idx, int quantity, bool with_you, Coord c) return NO_OBJ; } } - objects[obj].obj_id = po_idx; - objects[obj].with_you = with_you; - objects[obj].used = true; - objects[obj].pos = c; - objects[obj].quan = quantity; + Obj o; + o.po_ref = po_idx; + o.flags = OF_USED | (with_you ? OF_WITH_YOU : 0); + o.pos = c; + o.quan = quantity; switch (permobjs[po_idx].poclass) { case POCLASS_WEAPON: @@ -412,29 +401,29 @@ int create_obj(int po_idx, int quantity, bool with_you, Coord c) /* Set durability of weapons and armour to a suitable value. * 100 has been chosen for the moment, but this may need * tuning. */ - objects[obj].durability = OBJ_MAX_DUR; + o.durability = OBJ_MAX_DUR; break; default: break; } - if (!objects[obj].with_you) + if (!(o.flags & OF_WITH_YOU)) { lvl.set_obj_at(c, obj); } return obj; } -void sprint_obj_name(char *buf, int obj, int len) +void sprint_obj_name(char *buf, Obj_handle obj, int len) { Obj *optr; Permobj *poptr; - optr = objects + obj; - poptr = permobjs + optr->obj_id; + optr = obj_snapv(obj); + poptr = permobjs + optr->po_ref; if (optr->quan > 1) { snprintf(buf, len, "%d %s", optr->quan, poptr->plural); } - else if (po_is_stackable(optr->obj_id)) + else if (po_is_stackable(optr->po_ref)) { snprintf(buf, len, "1 %s", poptr->name); } @@ -449,17 +438,17 @@ void sprint_obj_name(char *buf, int obj, int len) } } -void fprint_obj_name(FILE *fp, int obj) +void fprint_obj_name(FILE *fp, Obj_handle obj) { Obj *optr; Permobj *poptr; - optr = objects + obj; - poptr = permobjs + optr->obj_id; + optr = obj_snapv(obj); + poptr = permobjs + optr->po_ref; if (optr->quan > 1) { fprintf(fp, "%d %s", optr->quan, poptr->plural); } - else if (po_is_stackable(optr->obj_id)) + else if (po_is_stackable(optr->po_ref)) { fprintf(fp, "1 %s", poptr->name); } @@ -477,7 +466,7 @@ void fprint_obj_name(FILE *fp, int obj) Action_cost drop_obj(int inv_idx) { Obj *optr; - optr = objects + u.inventory[inv_idx]; + optr = obj_snapv(u.inventory[inv_idx]); if (lvl.obj_at(u.pos) == NO_OBJ) { optr->pos = u.pos; @@ -487,7 +476,7 @@ Action_cost drop_obj(int inv_idx) u.weapon = NO_OBJ; } u.inventory[inv_idx] = NO_OBJ; - optr->with_you = false; + optr->flags &= ~OF_WITH_YOU; notify_drop_item(lvl.obj_at(u.pos)); return Cost_std; } @@ -515,16 +504,16 @@ void attempt_pickup(void) { int i; int stackable; - stackable = po_is_stackable(objects[lvl.obj_at(u.pos)].obj_id); + stackable = po_is_stackable(objects[lvl.obj_at(u.pos)].po_ref); if (stackable) { for (i = 0; i < 19; i++) { - if ((objects[u.inventory[i]].obj_id == objects[lvl.obj_at(u.pos)].obj_id)) + 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].used = false; + objects[stale_obj].flags &= ~OF_USED; lvl.set_obj_at(u.pos, NO_OBJ); notify_get_item(stale_obj, i); return; @@ -545,14 +534,14 @@ void attempt_pickup(void) } u.inventory[i] = lvl.obj_at(u.pos); lvl.set_obj_at(u.pos, NO_OBJ); - objects[u.inventory[i]].with_you = true; + objects[u.inventory[i]].flags |= OF_WITH_YOU; objects[u.inventory[i]].pos = Nowhere; notify_get_item(NO_OBJ, i); } -void break_reaction(int obj) +void break_reaction(Obj_handle obj) { - switch (objects[obj].obj_id) + switch (objects[obj].po_ref) { case PO_TORMENTORS_LASH: if (u.food < 500) @@ -572,22 +561,22 @@ void break_reaction(int obj) break; default: - if (permobjs[objects[obj].obj_id].flags[0] & POF_DRESS) + if (permobjs[objects[obj].po_ref].flags[0] & POF_DRESS) { objects[obj].durability = 50 + zero_die(51); - objects[obj].obj_id = PO_RAGGED_SHIFT; + objects[obj].po_ref = PO_RAGGED_SHIFT; notify_dress_shredded(); recalc_defence(); } else { - debug_unimplemented_break_reaction(objects[obj].obj_id); + debug_unimplemented_break_reaction(objects[obj].po_ref); } break; } } -void damage_obj(int obj) +void damage_obj(Obj_handle obj) { /* Only weapons and armour have non-zero durability. */ if (objects[obj].durability == 0) @@ -598,26 +587,26 @@ void damage_obj(int obj) else { objects[obj].durability--; - if ((objects[obj].durability == 0) && (permobjs[objects[obj].obj_id].flags[0] & POF_BREAK_REACT)) + if ((objects[obj].durability == 0) && (permobjs[objects[obj].po_ref].flags[0] & POF_BREAK_REACT)) { break_reaction(obj); } } } -int evasion_penalty(int obj) +int evasion_penalty(Obj_handle obj) { - if (permobjs[objects[obj].obj_id].poclass == POCLASS_ARMOUR) + if (permobjs[objects[obj].po_ref].poclass == POCLASS_ARMOUR) { - return permobjs[objects[obj].obj_id].power2; + return permobjs[objects[obj].po_ref].power2; } return 100; } Action_cost magic_ring(void) { - Obj *optr = objects + u.ring; - switch (optr->obj_id) + Obj *optr = obj_snapv(u.ring); + switch (optr->po_ref) { case PO_TELEPORT_RING: if (u.food >= 50) @@ -633,9 +622,9 @@ Action_cost magic_ring(void) } return Cost_none; default: - if (permobjs[optr->obj_id].flags[0] & POF_ACTIVATABLE) + if (permobjs[optr->po_ref].flags[0] & POF_ACTIVATABLE) { - debug_unimplemented_activation(optr->obj_id); + debug_unimplemented_activation(optr->po_ref); } else { @@ -647,13 +636,13 @@ Action_cost magic_ring(void) Action_cost emanate_armour(void) { - Obj *optr = objects + u.armour; - switch (optr->obj_id) + Obj *optr = obj_snapv(u.armour); + switch (optr->po_ref) { default: - if (permobjs[optr->obj_id].flags[0] & POF_ACTIVATABLE) + if (permobjs[optr->po_ref].flags[0] & POF_ACTIVATABLE) { - debug_unimplemented_activation(optr->obj_id); + debug_unimplemented_activation(optr->po_ref); } else { @@ -666,8 +655,8 @@ Action_cost emanate_armour(void) Action_cost zap_weapon(void) { - Obj *optr = objects + u.weapon; - switch (optr->obj_id) + Obj *optr = obj_snapv(u.weapon); + switch (optr->po_ref) { case PO_STAFF_OF_FIRE: if (u.food > 150) @@ -683,7 +672,7 @@ Action_cost zap_weapon(void) } for (c.x = u.pos.x - 1; c.x <= u.pos.x + 1; ++c.x) { - int mon; + Mon_handle mon; if ((c.x < lvl.min_x()) || (c.x >= lvl.max_x())) { continue; @@ -691,8 +680,8 @@ Action_cost zap_weapon(void) mon = lvl.mon_at(c); if (mon != NO_MON) { - Mon *mptr = monsters + mon; - if (!pmon_resists_fire(mptr->mon_id)) + Mon *mptr = mon_snapv(mon); + if (!pmon_resists_fire(mptr->pm_ref)) { notify_fireitem_hit(mon); damage_mon(mon, dice(4, 10), true); @@ -709,9 +698,9 @@ Action_cost zap_weapon(void) } return Cost_std; default: - if (permobjs[optr->obj_id].flags[0] & POF_ACTIVATABLE) + if (permobjs[optr->po_ref].flags[0] & POF_ACTIVATABLE) { - debug_unimplemented_activation(optr->obj_id); + debug_unimplemented_activation(optr->po_ref); } else { @@ -740,28 +729,26 @@ Action_cost player_unwield(Noisiness noisy) return Cost_std; } -Action_cost player_wield(int slot, Noisiness noisy) +Action_cost player_wield(Obj_handle obj, Noisiness noisy) { if (u.weapon != NO_OBJ) { player_unwield(Noise_low); } - u.weapon = u.inventory[slot]; + u.weapon = obj; notify_wield_weapon(u.weapon); recalc_defence(); return Cost_std; } -Action_cost wear_armour(int slot) +Action_cost wear_armour(Obj_handle obj) { - int obj; if (u.armour != NO_OBJ) { debug_wear_while_wearing(); return Cost_none; } - obj = u.inventory[slot]; - if (!objects[obj].with_you) + if (!(objects[obj].flags & OF_WITH_YOU)) { debug_wear_uncarried_armour(); return Cost_none; @@ -772,14 +759,14 @@ Action_cost wear_armour(int slot) return Cost_std; } -Action_cost put_on_ring(int obj) +Action_cost put_on_ring(Obj_handle obj) { if (u.ring != NO_OBJ) { debug_put_on_second_ring(); return Cost_none; } - if (!objects[obj].with_you) + if (!(objects[obj].flags & OF_WITH_YOU)) { debug_put_on_uncarried_ring(); return Cost_none; @@ -814,7 +801,7 @@ Pass_fail ring_removal_unsafe(Noisiness noisy) } return You_fail; } - else if ((objects[u.ring].obj_id == PO_FROST_RING) && (lvl.terrain_at(u.pos) == WATER)) + else if ((objects[u.ring].po_ref == PO_FROST_RING) && (lvl.terrain_at(u.pos) == WATER)) { if (noisy != Noise_silent) { diff --git a/objects.hh b/objects.hh index 719c9e1..689a992 100644 --- a/objects.hh +++ b/objects.hh @@ -37,51 +37,62 @@ #include "permobj.hh" #endif +#include /* XXX Obj */ #define OBJ_MAX_DUR 100 #define OBJECTS_IN_PLAY 100 +#define OF_USED 0x00000001u +#define OF_WITH_YOU 0x00000002u class Obj { public: - int obj_id; - bool used; /* Entry is occupied. */ - bool with_you; /* Preserved when item DB is reaped on level change. */ + Obj_handle self; + int po_ref; + uint32_t flags; int quan; Coord pos; int durability; /* Weapons and armour degrade with use. */ }; -extern Obj objects[OBJECTS_IN_PLAY]; +extern std::map objects; -#define NO_OBJ (-1) +/* XXX objects.cc data and funcs */ +void sprint_obj_name(char *s, Obj_handle obj, int len); +void fprint_obj_name(FILE *fp, Obj_handle obj); +void describe_object(Obj_handle obj); +Obj_handle create_obj(int po_idx, int quantity, bool with_you, Coord c); +bool consume_obj(Obj_handle obj); +Obj_handle create_obj_class(enum poclass_num pocl, int quantity, bool with_you, Coord c); +void damage_obj(Obj_handle obj); +int evasion_penalty(Obj_handle obj); -/* XXX objects.c data and funcs */ -extern void flavours_init(void); -extern void sprint_obj_name(char *s, int obj, int len); -extern void fprint_obj_name(FILE *fp, int obj); -extern void print_obj_name(int obj); -extern void describe_object(int obj); -extern int create_obj(int po_idx, int quantity, bool with_you, Coord c); -extern bool consume_obj(int obj); -extern int create_obj_class(enum poclass_num pocl, int quantity, bool with_you, Coord c); -extern void damage_obj(int obj); -extern int evasion_penalty(int obj); +inline Obj *obj_snapv(Obj_handle obj) +{ + auto iter = objects.find(obj); + return ((iter == objects.end()) ? &(iter->second) : nullptr); +} -extern Action_cost drop_obj(int inv_idx); -extern Action_cost put_on_ring(int obj); -extern Action_cost remove_ring(void); -extern Action_cost wear_armour(int obj); -extern Action_cost take_off_armour(void); -extern Action_cost read_scroll(int obj); -extern Action_cost quaff_potion(int obj); -extern Action_cost eat_food(int obj); -extern Action_cost magic_ring(void); -extern Action_cost emanate_armour(void); -extern Action_cost zap_weapon(void); -extern Action_cost player_unwield(Noisiness noisy = Noise_std); -extern Action_cost player_wield(int slot, Noisiness noisy = Noise_std); -extern void attempt_pickup(void); +inline Obj const *obj_snap(Obj_handle obj) +{ + auto iter = objects.find(obj); + return ((iter == objects.end()) ? &(iter->second) : nullptr); +} -extern Pass_fail ring_removal_unsafe(Noisiness noisy = Noise_std); -extern Pass_fail armour_removal_unsafe(Noisiness noisy = Noise_std); +Action_cost drop_obj(int inv_idx); +Action_cost put_on_ring(Obj_handle obj); +Action_cost remove_ring(void); +Action_cost wear_armour(Obj_handle obj); +Action_cost take_off_armour(void); +Action_cost read_scroll(Obj_handle obj); +Action_cost quaff_potion(Obj_handle obj); +Action_cost eat_food(Obj_handle obj); +Action_cost magic_ring(void); +Action_cost emanate_armour(void); +Action_cost zap_weapon(void); +Action_cost player_unwield(Noisiness noisy = Noise_std); +Action_cost player_wield(Obj_handle obj, Noisiness noisy = Noise_std); +void attempt_pickup(void); + +Pass_fail ring_removal_unsafe(Noisiness noisy = Noise_std); +Pass_fail armour_removal_unsafe(Noisiness noisy = Noise_std); #endif diff --git a/player.hh b/player.hh index 6913afe..b7fb924 100644 --- a/player.hh +++ b/player.hh @@ -53,10 +53,10 @@ public: int speed; //!< Controls how often you act. uint32_t resistances[DT_COUNT]; //!< Resistance masks per damage type int level; //!< Current experience level. - int inventory[19]; //!< Object handles of currently carried items. - int weapon; //!< Object handle of currently equipped weapon. - int armour; //!< Object handle of currently equipped armour. - int ring; //!< Object handle of currently equipped ring. + Obj_handle inventory[19]; //!< currently carried items. + Obj_handle weapon; //!< currently equipped weapon. + Obj_handle armour; //!< currently equipped armour. + Obj_handle ring; //!< currently equipped ring. int sympathy[TOTAL_FELL_POWERS]; //!< Level of alignment with fell powers /* Methods only after here plzkthx */ bool resists(Damtyp dtype) const; //!< Does player resist this Damtyp? diff --git a/shrine.cc b/shrine.cc index 1f00063..573ed0a 100644 --- a/shrine.cc +++ b/shrine.cc @@ -106,7 +106,7 @@ struct shrine shrines[4] = }; /*! \brief Construction helper for shrines */ -void place_shrine(Coord topleft, shrine const *sh, uint32_t accept_conns, Terrain shwall, Terrain shfloor, bool margin_is_wall) +void place_shrine(Level *l, Coord topleft, shrine const *sh, uint32_t accept_conns, Terrain shwall, Terrain shfloor, bool margin_is_wall) { Coord c; Coord start; @@ -165,38 +165,38 @@ void place_shrine(Coord topleft, shrine const *sh, uint32_t accept_conns, Terrai switch (sh->grid[shy][shx]) { case '0': - lvl.set_terrain_at(c, shfloor); + l->set_terrain_at(c, shfloor); /* We want to be able to slap this down as a room, which means * that at least one square on the connectable edges must not * be HARDWALL. Those squares are marked '0'. */ break; case '1': - lvl.set_terrain_at(c, margin_is_wall ? shwall : shfloor); - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_terrain_at(c, margin_is_wall ? shwall : shfloor); + l->set_flags_at(c, MAPFLAG_HARDWALL); break; case '.': - lvl.set_terrain_at(c, shfloor); - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_terrain_at(c, shfloor); + l->set_flags_at(c, MAPFLAG_HARDWALL); break; case '#': - lvl.set_terrain_at(c, shwall); - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_terrain_at(c, shwall); + l->set_flags_at(c, MAPFLAG_HARDWALL); break; case '+': - lvl.set_terrain_at(c, DOOR); - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_terrain_at(c, DOOR); + l->set_flags_at(c, MAPFLAG_HARDWALL); break; case '_': - lvl.set_terrain_at(c, ALTAR); - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_terrain_at(c, ALTAR); + l->set_flags_at(c, MAPFLAG_HARDWALL); break; case 'L': - lvl.set_terrain_at(c, LAVA); - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_terrain_at(c, LAVA); + l->set_flags_at(c, MAPFLAG_HARDWALL); break; case 'W': - lvl.set_terrain_at(c, WATER); - lvl.set_flags_at(c, MAPFLAG_HARDWALL); + l->set_terrain_at(c, WATER); + l->set_flags_at(c, MAPFLAG_HARDWALL); break; } } @@ -205,7 +205,7 @@ void place_shrine(Coord topleft, shrine const *sh, uint32_t accept_conns, Terrai } /*! \brief Excavate a cave-with-shrine level. */ -void build_level_shrine(void) +void build_level_shrine(Level *l) { Coord shrinepos = { inc_flat(GUIDE_EDGE_SIZE / 4, GUIDE_EDGE_SIZE / 2), inc_flat(GUIDE_EDGE_SIZE / 4, GUIDE_EDGE_SIZE / 2) }; Coord c; @@ -217,11 +217,11 @@ void build_level_shrine(void) int intrusions; int i; - initialize_chunks(&lvl, GUIDE_EDGE_CHUNKS, GUIDE_EDGE_CHUNKS, true); + initialize_chunks(l, GUIDE_EDGE_CHUNKS, GUIDE_EDGE_CHUNKS, true); intrusions = dice(2, 4) - 1; for (i = 0; i < 6; ++i) { - place_random_intrusion(WALL); + place_random_intrusion(l, WALL); } switch (zero_die(4)) { @@ -253,12 +253,12 @@ void build_level_shrine(void) c3 = c + North; mask = ROOMCONN_EAST; } - place_shrine(shrinepos, shrines + shrine_num, mask); - lvl.set_terrain_at(c, FLOOR); - lvl.set_terrain_at(c2, FLOOR); - lvl.set_terrain_at(c3, FLOOR); - run_random_walk_unbounded(c, excavation_write, walk_data, LEVGEN_WALK_CELLS); - place_cave_stairs(); + place_shrine(l, shrinepos, shrines + shrine_num, mask); + l->set_terrain_at(c, FLOOR); + l->set_terrain_at(c2, FLOOR); + l->set_terrain_at(c3, FLOOR); + run_random_walk_unbounded(l, c, excavation_write, walk_data, LEVGEN_WALK_CELLS); + place_cave_stairs(l); } /* shrine.cc */ diff --git a/sorcery.cc b/sorcery.cc index e6b03b3..021be67 100644 --- a/sorcery.cc +++ b/sorcery.cc @@ -68,7 +68,7 @@ int mon_use_sorcery(int mon) { /* Returns zero for no spell selected, -1 for unsupported spell * selected, 1 for supported spell selected. */ - Mon *mptr = monsters + mon; + Mon *mptr = mon_snapv(mon); Offset delta = u.pos.delta(mptr->pos); Offset step = mysign(delta); enum monspell to_cast = MS_REJECT; @@ -81,7 +81,7 @@ int mon_use_sorcery(int mon) bool cansee = mon_visible(mon); int i; - switch (monsters[mon].mon_id) + switch (monsters[mon].pm_ref) { case PM_ARCHMAGE: if (cansee) @@ -434,7 +434,7 @@ int mon_use_sorcery(int mon) } else { - damage_u(dice(1, 20), DEATH_KILLED_MON, permons[monsters[mon].mon_id].name); + damage_u(dice(1, 20), DEATH_KILLED_MON, permons[monsters[mon].pm_ref].name); } break; @@ -443,11 +443,11 @@ int mon_use_sorcery(int mon) notify_hellfire_hit(u.resists(DT_FIRE)); if (u.resists(DT_FIRE)) { - damage_u(dice(1, 5), DEATH_KILLED_MON, permons[monsters[mon].mon_id].name); + damage_u(dice(1, 5), DEATH_KILLED_MON, permons[monsters[mon].pm_ref].name); } else { - damage_u(dice(1, 20), DEATH_KILLED_MON, permons[monsters[mon].mon_id].name); + damage_u(dice(1, 20), DEATH_KILLED_MON, permons[monsters[mon].pm_ref].name); } break; } diff --git a/u.cc b/u.cc index ce957bf..e0bce27 100644 --- a/u.cc +++ b/u.cc @@ -40,12 +40,12 @@ struct Player u; bool wielding_ranged_weapon(void) { - return permobjs[objects[u.weapon].obj_id].flags[0] & POF_RANGED_WEAPON; + return permobjs[objects[u.weapon].po_ref].flags[0] & POF_RANGED_WEAPON; } bool wielding_melee_weapon(void) { - return permobjs[objects[u.weapon].obj_id].flags[0] & POF_MELEE_WEAPON; + return permobjs[objects[u.weapon].po_ref].flags[0] & POF_MELEE_WEAPON; } void recalc_defence(void) @@ -58,9 +58,9 @@ void recalc_defence(void) u.speed = (u.leadfoot ? 0 : 1); if (u.armour != NO_OBJ) { - u.defence = u.armourmelt ? 0 : permobjs[objects[u.armour].obj_id].power; + u.defence = u.armourmelt ? 0 : permobjs[objects[u.armour].po_ref].power; u.defence += u.withering ? (u.agility / 10) : (u.agility / 5); - switch (objects[u.armour].obj_id) + switch (objects[u.armour].po_ref) { case PO_DRAGONHIDE_ARMOUR: case PO_METEORIC_PLATE_ARMOUR: @@ -79,7 +79,7 @@ void recalc_defence(void) } if (u.ring != NO_OBJ) { - switch (objects[u.ring].obj_id) + switch (objects[u.ring].po_ref) { case PO_FIRE_RING: u.resistances[DT_FIRE] |= RESIST_RING; @@ -107,9 +107,9 @@ Action_cost move_player(Offset delta) { if (u.weapon != NO_OBJ) { - if ((objects[u.weapon].obj_id == PO_BOW) || - (objects[u.weapon].obj_id == PO_CROSSBOW) || - (objects[u.weapon].obj_id == PO_THUNDERBOW)) + if ((objects[u.weapon].po_ref == PO_BOW) || + (objects[u.weapon].po_ref == PO_CROSSBOW) || + (objects[u.weapon].po_ref == PO_THUNDERBOW)) { notify_swing_bow(); return Cost_none; @@ -154,7 +154,7 @@ Action_cost move_player(Offset delta) return Cost_none; } case WATER: - if ((u.ring != NO_OBJ) && (objects[u.ring].obj_id == PO_FROST_RING)) + if ((u.ring != NO_OBJ) && (objects[u.ring].po_ref == PO_FROST_RING)) { if (lvl.terrain_at(u.pos) != WATER) { @@ -447,7 +447,7 @@ void update_player(void) * 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].obj_id == PO_REGENERATION_RING) && + (objects[u.ring].po_ref == PO_REGENERATION_RING) && (u.hpcur < ((u.food >= 0) ? u.hpmax : ((u.hpmax * 3) / 4))) && (u.food > MIN_FOOD)) { @@ -460,7 +460,7 @@ void update_player(void) { int food_use = 1; int squeal = 0; - if ((objects[u.ring].obj_id == PO_REGENERATION_RING) && !(game_tick % 2) && (u.food > MIN_FOOD)) + if ((objects[u.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 @@ -547,7 +547,7 @@ enum Combo_phase bool action_rewrite(Action const *act, Action *revised_act) { Coord c = u.pos; - int mon = NO_MON; + Mon_handle mon = NO_MON; Offset o; Action tmp_act = *act; Combo_phase p;