From 314f10d9b0b40d927a2e64f9a0c29275e23c95a0 Mon Sep 17 00:00:00 2001 From: Martin Read Date: Mon, 10 Mar 2014 19:16:22 +0000 Subject: [PATCH] More switch-slaying. --- core.hh | 9 ++++ deeds.cc | 23 +++++++-- fov.cc | 62 +++++++++-------------- fov.hh | 25 +++++----- log.cc | 2 + notify-local-tty.cc | 2 +- notify.hh | 2 +- obj1.cc | 139 +++++++++++----------------------------------------- obj2.cc | 129 ++++++++++++++++++++++++++++++++++++++++++++++-- objects.hh | 14 +++++- 10 files changed, 236 insertions(+), 171 deletions(-) diff --git a/core.hh b/core.hh index 4117e36..46bd0c2 100644 --- a/core.hh +++ b/core.hh @@ -186,6 +186,15 @@ extern const Obj_handle NO_OBJ; extern const Mon_handle NO_MON; #define NO_REGION 0xffffffffu +struct Inferno_detail +{ + bool by_you; + Mon_handle caster; + int dice_count; + int dice_sides; + int dice_bonus; +}; + #endif /* core.hh */ diff --git a/deeds.cc b/deeds.cc index a144801..95a166a 100644 --- a/deeds.cc +++ b/deeds.cc @@ -79,14 +79,29 @@ static Action_cost deed_ascend(Action const *act) static Action_cost deed_descend(Action const *act) { Terrain t = lvl.terrain_at(u.pos); - if (terrain_props[t].flags & TFLAG_descend) + if (terrain_props[t].flags & TFLAG_portal) { - leave_level(); - make_new_level(); + if (terrain_props[t].flags & TFLAG_ascend) + { + notify_inert_portal(); + } + else + { + leave_level(); + make_new_level(); + } } else { - debug_descend_non_stairs(); + if (terrain_props[t].flags & TFLAG_descend) + { + leave_level(); + make_new_level(); + } + else + { + debug_descend_non_stairs(); + } } return Cost_none; } diff --git a/fov.cc b/fov.cc index f1d6d68..53e4a12 100644 --- a/fov.cc +++ b/fov.cc @@ -65,7 +65,7 @@ static void compute_row(Radiance *rad, int octant, int radius, double inmost_slo * This function returns true if the specified coordinates are out of bounds * or the terrain at the specified position is opaque. */ -static bool dflt_blk(Coord c) +bool dflt_blk(Coord c) { return ((c.y <= lvl.min_y()) || (c.x <= lvl.min_x()) || (c.y >= lvl.max_y()) || (c.x >= lvl.max_x()) || (terrain_is_opaque(lvl.terrain_at(c)))); } @@ -116,13 +116,6 @@ static inline double centre_slope(int rdl, int trn) return ((double) trn) / ((double) rdl); } -/*! \brief Reset the affected flags of a Radiance object - */ -void clear_radiance(Radiance *rad) -{ - memset(&(rad->affected), '\0', sizeof rad->affected); -} - /*! \brief Start computing one octant of a Radiance */ static inline void compute_octant(Radiance *rad, int octant) @@ -241,54 +234,47 @@ static void compute_row(Radiance *rad, int octant, int radius, double inmost_slo } } -void compute_radiance(Radiance *rad) +void Radiance::compute(void) { int oct; /* Compute the eight octants in order. */ for (oct = 0; oct < 8; ++oct) { - compute_octant(rad, oct); + compute_octant(this, oct); } /* Mark the centre as (un)affected according to the Radiance's setup. */ - if (rad->exclude_centre) - { - rad->affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = false; - } - else - { - rad->affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = true; - } + affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = !exclude_centre; } -void resolve_radiance(Radiance *rad) +void Radiance::resolve(void) { Coord c; int i; int j; int k; - switch (rad->order) + switch (order) { case Reo_ascending: - for ((i = MAX_FOV_RADIUS - rad->radius), (c.y = rad->centre.y - rad->radius); c.y <= rad->centre.y + rad->radius; ++c.y, ++i) + for ((i = MAX_FOV_RADIUS - radius), (c.y = centre.y - radius); c.y <= centre.y + radius; ++c.y, ++i) { - for ((j = MAX_FOV_RADIUS - rad->radius), (c.x = rad->centre.x - rad->radius); c.x <= rad->centre.x + rad->radius; ++c.x, ++j) + for ((j = MAX_FOV_RADIUS - radius), (c.x = centre.x - radius); c.x <= centre.x + radius; ++c.x, ++j) { - if (rad->affected[i][j]) + if (affected[i][j]) { - rad->effect_fun(c, rad->pvt); + effect_fun(c, pvt); } } } break; case Reo_spiral_out: - for (i = 0, j = 0, k = 0; i >= -(rad->radius); ) + for (i = 0, j = 0, k = 0; i >= -(radius); ) { - c.y = rad->centre.y + i; - c.x = rad->centre.x + j; - if (rad->affected[MAX_FOV_RADIUS + i][MAX_FOV_RADIUS + j]) + c.y = centre.y + i; + c.x = centre.x + j; + if (affected[MAX_FOV_RADIUS + i][MAX_FOV_RADIUS + j]) { - rad->effect_fun(c, rad->pvt); + effect_fun(c, pvt); } if ((i == 0) && (j == 0)) { @@ -344,13 +330,13 @@ void resolve_radiance(Radiance *rad) } break; case Reo_spiral_in: - for (i = -(rad->radius), j = -(rad->radius), k = rad->radius; k >= 0; ) + for (i = -(radius), j = -(radius), k = radius; k >= 0; ) { - c.y = rad->centre.y + i; - c.x = rad->centre.x + j; - if (rad->affected[MAX_FOV_RADIUS + i][MAX_FOV_RADIUS + j]) + c.y = centre.y + i; + c.x = centre.x + j; + if (affected[MAX_FOV_RADIUS + i][MAX_FOV_RADIUS + j]) { - rad->effect_fun(c, rad->pvt); + effect_fun(c, pvt); } if ((i == 0) && (j == 0)) { @@ -406,7 +392,7 @@ void resolve_radiance(Radiance *rad) break; default: - debug_unimplemented_radiance_order(rad->order); + debug_unimplemented_radiance_order(order); abort(); } } @@ -415,7 +401,7 @@ Radiance player_fov; void compute_fov(void) { - clear_radiance(&player_fov); + player_fov.clear(); player_fov.centre = u.pos; player_fov.radius = MAX_FOV_RADIUS; player_fov.order = Reo_ascending; @@ -423,8 +409,8 @@ void compute_fov(void) player_fov.opaque_fun = dflt_blk; player_fov.effect_fun = mark_explored; player_fov.pvt = nullptr; - compute_radiance(&player_fov); - resolve_radiance(&player_fov); + player_fov.compute(); + player_fov.resolve(); } bool tile_visible(Coord c) diff --git a/fov.hh b/fov.hh index 15f40ad..a8d096f 100644 --- a/fov.hh +++ b/fov.hh @@ -2,7 +2,7 @@ * \brief field-of-view header */ -/* Copyright 2013 Martin Read +/* Copyright © 2013-2014 Martin Read * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,6 +29,8 @@ #ifndef FOV_HH #define FOV_HH +#include + #define MAX_FOV_RADIUS 10 #define FOV_SIDE (2 * MAX_FOV_RADIUS + 1) @@ -52,7 +54,7 @@ typedef enum rad_eval_order Rad_eval_order; #define Visflag_central 0x02u typedef uint8_t Vision_flags; /* 8 bits should do for now */ -class radiance_data +class Radiance { public: Vision_flags affected[FOV_SIDE][FOV_SIDE]; @@ -63,6 +65,8 @@ public: void *pvt; bool (*opaque_fun)(Coord c); bool (*effect_fun)(Coord c, void *pvt); + /* member functions only past this point please */ + void clear(void) { memset(affected, '\0', sizeof affected); } bool test(Coord c) const { if ((c.y >= 0) && (c.x >= 0) && (c.y < FOV_SIDE) && (c.x < FOV_SIDE)) { @@ -70,19 +74,18 @@ public: } return false; } + void compute(void); + void resolve(void); }; -typedef struct radiance_data Radiance; - -extern void clear_radiance(Radiance *rad); -extern void compute_radiance(Radiance *rad); -extern void resolve_radiance(Radiance *rad); -extern void compute_fov(void); -extern bool tile_visible(Coord c); -extern bool occupant_visible(Coord c); extern Radiance player_fov; +void compute_fov(void); +bool tile_visible(Coord c); +bool occupant_visible(Coord c); +bool dflt_blk(Coord c); + #endif -/* fov.h */ +/* fov.hh */ // vim:cindent diff --git a/log.cc b/log.cc index e8f28f1..c4cf754 100644 --- a/log.cc +++ b/log.cc @@ -290,6 +290,7 @@ static void deserialize_player(FILE *fp, Player *player) deserialize_int(fp, &(player->hpcur)); deserialize_int(fp, &(player->food)); deserialize_int(fp, &(player->experience)); + deserialize_int(fp, &(player->level)); deserialize_int(fp, &(player->defence)); deserialize_int(fp, &(player->protection)); deserialize_int(fp, &(player->leadfoot)); @@ -327,6 +328,7 @@ static void serialize_player(FILE *fp, Player const& player) serialize_int(fp, player.hpcur); serialize_int(fp, player.food); serialize_int(fp, player.experience); + serialize_int(fp, player.level); serialize_int(fp, player.defence); serialize_int(fp, player.protection); serialize_int(fp, player.leadfoot); diff --git a/notify-local-tty.cc b/notify-local-tty.cc index 2a9585a..4c909f7 100644 --- a/notify-local-tty.cc +++ b/notify-local-tty.cc @@ -800,7 +800,7 @@ void notify_firestaff_activation(int specific) } } -void notify_fireitem_hit(Mon_handle mon) +void notify_inferno_hit(Mon_handle mon) { print_mon_name(mon, 3); print_msg(" is engulfed in roaring flames.\n"); diff --git a/notify.hh b/notify.hh index 157aa98..bbd835f 100644 --- a/notify.hh +++ b/notify.hh @@ -101,7 +101,7 @@ 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(Mon_handle mon); +void notify_inferno_hit(Mon_handle mon); void notify_telering_activation(int specific); void notify_item_explodes_flames(Obj_handle obj); diff --git a/obj1.cc b/obj1.cc index c1fc9ca..f240047 100644 --- a/obj1.cc +++ b/obj1.cc @@ -63,67 +63,18 @@ char const potion_colours[20][16] = { Action_cost read_scroll(Obj_handle obj) { Obj *optr = obj_snapv(obj); - switch (optr->po_ref) + int i; + for (i = 0; scroll_table[i].read_func != nullptr; ++i) { - case PO_TELEPORT_SCROLL: - teleport_u(); - break; - case PO_FIRE_SCROLL: - notify_item_explodes_flames(obj); - if (u.resistances[DT_FIRE]) - { - notify_player_ignore_damage(DT_FIRE); - } - else - { - 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].pm_ref)) - { - notify_fireitem_hit(i); - damage_mon(i, dice(4, 10), true); - } - } - } -#endif - break; - case PO_PROTECTION_SCROLL: - notify_read_scroll_protection(); - if (!u.protection) - { - /* Do not prolong existing protection, only grant - * protection to the unprotected. */ - u.protection = 100; - } - if (u.withering) - { - u.withering = 0; - notify_wither_recovered(); - } - if (u.armourmelt) - { - u.armourmelt = 0; - notify_armourmelt_recovered(); - } - if (u.leadfoot) - { - u.leadfoot = 0; - notify_leadfoot_recovered(); - } - recalc_defence(); - break; - default: - debug_read_non_scroll(); - return Cost_none; + if (scroll_table[i].pobj == optr->po_ref) + { + scroll_table[i].read_func(obj); + consume_obj(obj); + return Cost_std; + } } - consume_obj(obj); - return Cost_std; + debug_read_non_scroll(); + return Cost_none; } bool consume_obj(Obj_handle obj) @@ -209,7 +160,7 @@ Action_cost quaff_potion(Obj_handle obj) { if (potion_table[i].pobj == optr->po_ref) { - potion_table[i].quaff_func(); + potion_table[i].quaff_func(obj); consume_obj(obj); return Cost_std; } @@ -704,58 +655,26 @@ Action_cost emanate_armour(void) Action_cost zap_weapon(void) { Obj *optr = obj_snapv(u.weapon); - switch (optr->po_ref) + int i; + for (i = 0; weapon_table[i].pobj != NO_POBJ; ++i) { - case PO_STAFF_OF_FIRE: - if (u.food > 150) - { - Coord c; - u.food -= 150; - notify_firestaff_activation(1); - for (c.y = u.pos.y - 1; c.y <= u.pos.y + 1; ++c.y) - { - if ((c.y < lvl.min_y()) || (c.y >= lvl.max_y())) - { - continue; - } - for (c.x = u.pos.x - 1; c.x <= u.pos.x + 1; ++c.x) - { - Mon_handle mon; - if ((c.x < lvl.min_x()) || (c.x >= lvl.max_x())) - { - continue; - } - mon = lvl.mon_at(c); - if (mon != NO_MON) - { - Mon *mptr = mon_snapv(mon); - if (!pmon_resists_fire(mptr->pm_ref)) - { - notify_fireitem_hit(mon); - damage_mon(mon, dice(4, 10), true); - } - } - } - } - damage_obj(u.weapon); - } - else - { - notify_firestaff_activation(0); - return Cost_none; - } - return Cost_std; - default: - if (permobjs[optr->po_ref].flags[0] & POF_ACTIVATABLE) - { - debug_unimplemented_activation(optr->po_ref); - } - else - { - notify_zap_powerless_weapon(); - } - return Cost_none; + if (weapon_table[i].pobj == optr->po_ref) + { + if (weapon_table[i].zap_func != nullptr) + { + weapon_table[i].zap_func(u.weapon); + return Cost_std; + } + else if (permobjs[optr->po_ref].flags[0] & POF_ACTIVATABLE) + { + debug_unimplemented_activation(optr->po_ref); + return Cost_none; + } + break; + } } + notify_zap_powerless_weapon(); + return Cost_none; } /*! \brief Unwield the player's currently equipped weapon diff --git a/obj2.cc b/obj2.cc index 382f08b..ea98956 100644 --- a/obj2.cc +++ b/obj2.cc @@ -30,23 +30,24 @@ #include "obumbrata.hh" #include "objects.hh" #include "monsters.hh" +#include "fov.hh" #include /*! \brief Effect of quaffing a body potion */ -static void body_potion_quaff(void) +static void body_potion_quaff(Obj_handle obj) { gain_body(1); } /*! \brief Effect of quaffing a agility potion */ -static void agility_potion_quaff(void) +static void agility_potion_quaff(Obj_handle obj) { gain_agility(1); } /*! \brief Effect of quaffing a healing potion */ -static void healing_potion_quaff(void) +static void healing_potion_quaff(Obj_handle obj) { int healpercent = inc_flat(30, 50); int healamount = (healpercent * ((u.hpmax > 60) ? u.hpmax : 60)) / 100; @@ -54,7 +55,7 @@ static void healing_potion_quaff(void) } /*! \brief Effect of quaffing a restoration potion */ -static void restoration_potion_quaff(void) +static void restoration_potion_quaff(Obj_handle obj) { notify_quaff_potion_restoration(); if (u.bdam && ((!u.adam) || zero_die(2))) @@ -79,11 +80,131 @@ Potion_table_entry potion_table[] = { NO_POBJ, nullptr } }; +static Inferno_detail fire_scroll_inferno = { true, NO_MON, 4, 10, 0 }; + +bool inferno_effector(Coord c, void *pvt) +{ + Inferno_detail *inf = (Inferno_detail *) pvt; + Mon_handle mon = lvl.mon_at(c); + if (mon != NO_MON) + { + Mon const *mptr = mon_snap(mon); + if (!pmon_resists_fire(mptr->pm_ref)) + { + notify_inferno_hit(mon); + damage_mon(mon, inf->dice_bonus + dice(inf->dice_count, inf->dice_sides), inf->by_you); + } + } + return true; +} + +static Radiance fire_scroll_explosion = +{ + {}, + Nowhere, + MAX_FOV_RADIUS, + Reo_spiral_out, + true, + &fire_scroll_inferno, + dflt_blk, + inferno_effector +}; + +static void fire_scroll_read(Obj_handle obj) +{ + notify_item_explodes_flames(obj); + if (u.resistances[DT_FIRE]) + { + notify_player_ignore_damage(DT_FIRE); + } + else + { + damage_u(dice(4, 10), DEATH_KILLED, "searing flames"); + } + fire_scroll_explosion.clear(); + fire_scroll_explosion.centre = u.pos; + fire_scroll_explosion.compute(); + fire_scroll_explosion.resolve(); +} + +static void teleport_scroll_read(Obj_handle obj) +{ + teleport_u(); +} + +static void protection_scroll_read(Obj_handle obj) +{ + notify_read_scroll_protection(); + if (!u.protection) + { + /* Do not prolong existing protection, only grant + * protection to the unprotected. */ + u.protection = 100; + } + if (u.withering) + { + u.withering = 0; + notify_wither_recovered(); + } + if (u.armourmelt) + { + u.armourmelt = 0; + notify_armourmelt_recovered(); + } + if (u.leadfoot) + { + u.leadfoot = 0; + notify_leadfoot_recovered(); + } + recalc_defence(); +} + /*! \brief Lookup table for effects of reading scrolls */ Scroll_table_entry scroll_table[] = { + { PO_FIRE_SCROLL, fire_scroll_read }, + { PO_TELEPORT_SCROLL, teleport_scroll_read }, + { PO_PROTECTION_SCROLL, protection_scroll_read }, { NO_POBJ, nullptr } }; +static Inferno_detail fire_staff_inferno = { true, NO_MON, 4, 10, 0 }; + +static Radiance fire_staff_explosion = +{ + {}, + Nowhere, + MAX_FOV_RADIUS, + Reo_spiral_out, + true, + &fire_staff_inferno, + dflt_blk, + inferno_effector +}; + +static void fire_staff_zap(Obj_handle obj) +{ + if (u.food > 150) + { + u.food -= 150; + notify_firestaff_activation(1); + fire_staff_explosion.clear(); + fire_staff_explosion.centre = u.pos; + fire_staff_explosion.compute(); + fire_staff_explosion.resolve(); + damage_obj(obj); + } + else + { + notify_firestaff_activation(0); + } +} + +Weapon_table_entry weapon_table[] = +{ + { PO_STAFF_OF_FIRE, fire_staff_zap, nullptr, nullptr }, + { NO_POBJ, nullptr, nullptr, nullptr }, +}; + /* obj2.cc */ // vim:cindent diff --git a/objects.hh b/objects.hh index eb4c65f..0844e2d 100644 --- a/objects.hh +++ b/objects.hh @@ -59,18 +59,28 @@ extern Obj_handle first_free_obj_handle; struct Potion_table_entry { int pobj; - void (*quaff_func)(void); + void (*quaff_func)(Obj_handle obj); }; extern Potion_table_entry potion_table[]; struct Scroll_table_entry { int pobj; - void (*read_func)(void); + void (*read_func)(Obj_handle obj); }; extern Scroll_table_entry scroll_table[]; +struct Weapon_table_entry +{ + int pobj; + void (*zap_func)(Obj_handle obj); + void (*on_wield)(Obj_handle obj); + void (*on_unwield)(Obj_handle obj); +}; + +extern Weapon_table_entry weapon_table[]; + /* XXX objects.cc data and funcs */ void asprint_obj_name(char **s, Obj_handle obj); void sprint_obj_name(char *s, Obj_handle obj, int len); -- 2.11.0