From 4f3558feb5639ff93e46a0795d94d638ef0c89fc Mon Sep 17 00:00:00 2001 From: haranp Date: Tue, 8 Apr 2008 12:12:19 +0000 Subject: Added Water card. Might need some rebalancing. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4127 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/decks.cc | 105 ++++++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/decks.h | 1 + crawl-ref/source/dungeon.cc | 6 +-- crawl-ref/source/dungeon.h | 1 + crawl-ref/source/stuff.cc | 100 +++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/stuff.h | 26 +++++++++++ crawl-ref/source/traps.cc | 14 ++++++ crawl-ref/source/traps.h | 18 +------- crawl-ref/source/view.cc | 2 +- 9 files changed, 252 insertions(+), 21 deletions(-) (limited to 'crawl-ref/source') diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index e2f8e50bc1..db0f42a7ca 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -146,6 +146,7 @@ const deck_archetype deck_of_wonders[] = { }; const deck_archetype deck_of_dungeons[] = { + { CARD_WATER, {5, 5, 5} }, { CARD_GLASS, {5, 5, 5} }, { CARD_MAP, {5, 5, 5} }, { CARD_DOWSING, {5, 5, 5} }, @@ -278,6 +279,7 @@ const char* card_name(card_type card) case CARD_MINEFIELD: return "the Minefield"; case CARD_GENIE: return "the Genie"; case CARD_TOMB: return "the Tomb"; + case CARD_WATER: return "Water"; case CARD_GLASS: return "Vitrification"; case CARD_MAP: return "the Map"; case CARD_BANSHEE: return "the Banshee"; @@ -2089,6 +2091,108 @@ static void _sage_card(int power, deck_rarity_type rarity) } } +static void _create_pond(const coord_def& center, int radius, bool allow_deep) +{ + radius_iterator ri(center, radius, false); + for ( ; ri; ++ri ) + { + const coord_def p = *ri; + if ( p != you.pos() && coinflip() ) + { + destroy_trap(p); + if ( grd(p) == DNGN_FLOOR ) + { + if ( allow_deep ) + grd(p) = coinflip() ? DNGN_SHALLOW_WATER : DNGN_DEEP_WATER; + else + grd(p) = DNGN_SHALLOW_WATER; + } + } + } +} + +static void _deepen_water(const coord_def& center, int radius) +{ + radius_iterator ri(center, radius, false); + for ( ; ri; ++ri ) + { + // FIXME The iteration shouldn't affect the later squares in the + // same iteration, i.e., a newly-flooded square shouldn't count + // in the decision as to whether to make the next square flooded. + const coord_def p = *ri; + if ( grd(p) == DNGN_SHALLOW_WATER && + p != you.pos() && + random2(8) < 1 + count_neighbours(p.x, p.y, DNGN_DEEP_WATER) ) + { + grd(p) = DNGN_DEEP_WATER; + } + if (grd(p) == DNGN_FLOOR && + random2(3) < random2(count_neighbours(p.x,p.y,DNGN_DEEP_WATER) + + count_neighbours(p.x,p.y,DNGN_SHALLOW_WATER))) + { + grd(p) = DNGN_SHALLOW_WATER; + } + } +} + +static void _pond_creature_effect( const coord_def& center, int radius ) +{ + radius_iterator ri(center, radius, false); + bool you_affected = false; + for ( ; ri; ++ri ) + { + const coord_def p = *ri; + if ( p == you.pos() ) + you_affected = true; + else if ( mgrd(p) != NON_MONSTER ) + mons_check_pool( &menv[mgrd(p)], KILL_YOU ); + } + if ( you_affected ) + move_player_to_grid( you.x_pos, you.y_pos, false, true, true ); +} + +static void _water_card(int power, deck_rarity_type rarity) +{ + const int power_level = get_power_level(power, rarity); + if ( power_level == 0 ) + { + mpr("You create a pond!"); + _create_pond(you.pos(), 4, false); + _pond_creature_effect(you.pos(), 4); + } + else if ( power_level == 1 ) + { + mpr("You feel the tide rushing in!"); + _create_pond(you.pos(), 6, true); + for ( int i = 0; i < 2; ++i ) + _deepen_water(you.pos(), 6); + _pond_creature_effect(you.pos(), 5); + } + else + { + mpr("Water floods your area!"); + // Flood all visible squares + radius_iterator ri( you.pos(), LOS_RADIUS, false ); + for ( ; ri; ++ri ) + { + coord_def p = *ri; + destroy_trap(p); + if ( grd(p) == DNGN_FLOOR ) + { + dungeon_feature_type new_feature = DNGN_SHALLOW_WATER; + if ( p != you.pos() && coinflip() ) + new_feature = DNGN_DEEP_WATER; + grd(p) = new_feature; + // In the future we might want to place all the water first, + // if monsters can scramble out. + if ( mgrd(p) != NON_MONSTER ) + mons_check_pool( &menv[mgrd(p)], KILL_YOU ); + } + } + move_player_to_grid( you.x_pos, you.y_pos, false, true, true ); + } +} + static void _glass_card(int power, deck_rarity_type rarity) { const int power_level = get_power_level(power, rarity); @@ -2560,6 +2664,7 @@ bool card_effect(card_type which_card, deck_rarity_type rarity, case CARD_EXPERIENCE: _experience_card(power, rarity); break; case CARD_HELIX: _helix_card(power, rarity); break; case CARD_SAGE: _sage_card(power, rarity); break; + case CARD_WATER: _water_card(power, rarity); break; case CARD_GLASS: _glass_card(power, rarity); break; case CARD_DOWSING: _dowsing_card(power, rarity); break; case CARD_MINEFIELD: _minefield_card(power, rarity); break; diff --git a/crawl-ref/source/decks.h b/crawl-ref/source/decks.h index 2245a60d79..a080723d81 100644 --- a/crawl-ref/source/decks.h +++ b/crawl-ref/source/decks.h @@ -101,6 +101,7 @@ enum card_type CARD_SAGE, // skill training CARD_HELIX, // remove one *bad* mutation + CARD_WATER, // flood squares CARD_GLASS, // make walls transparent CARD_MAP, // magic mapping CARD_DOWSING, // detect SD/traps/items/monsters diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 3e7668874f..ea4e30f654 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -1293,7 +1293,7 @@ static int _count_antifeature_in_box(int x0, int y0, int x1, int y1, } // count how many neighbours of grd[x][y] are the feature feat. -static int _count_neighbours(int x, int y, dungeon_feature_type feat) +int count_neighbours(int x, int y, dungeon_feature_type feat) { return _count_feature_in_box(x-1, y-1, x+2, y+2, feat); } @@ -1431,7 +1431,7 @@ static void _prepare_shoals(int level_number) for ( int i = margin; i < GXM - margin; ++i) for ( int j = margin; j < GYM - margin; ++j) if (grd[i][j] == DNGN_DEEP_WATER - && _count_neighbours(i, j, DNGN_FLOOR) > random2(random2(3)+1)) + && count_neighbours(i, j, DNGN_FLOOR) > random2(random2(3)+1)) { grd[i][j] = DNGN_SHALLOW_WATER; } @@ -1477,7 +1477,7 @@ static void _prepare_shoals(int level_number) for ( int y = margin; y < GYM - margin; ++y ) if ( grd[x][y] == DNGN_DEEP_WATER ) { - int badness = _count_neighbours(x, y, DNGN_WATER_STUCK); + int badness = count_neighbours(x, y, DNGN_WATER_STUCK); if ( random2(badness) >= 2 && coinflip() ) grd[x][y] = DNGN_LAVA; } diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 0ed5275ecc..7edc1acf49 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -321,6 +321,7 @@ void replace_area_wrapper(dungeon_feature_type old_feat, bool unforbidden(const coord_def &c, unsigned mask); coord_def dgn_find_nearby_stair(dungeon_feature_type stair_to_find, coord_def base_pos, bool find_closest); +int count_neighbours(int x, int y, dungeon_feature_type feat); class mons_spec; bool dgn_place_monster(mons_spec &mspec, diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index b43efaa035..49f5b4f214 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -75,6 +75,106 @@ #include "tutorial.h" #include "view.h" +radius_iterator::radius_iterator( const coord_def& _center, int _radius, + bool _roguelike_metric, bool _require_los, + bool _exclude_center ) + : center(_center), radius(_radius), roguelike_metric(_roguelike_metric), + require_los(_require_los), exclude_center(_exclude_center), + iter_done(false) +{ + location.x = center.x - radius; + location.y = center.y - radius; + + if ( !this->on_valid_square() ) + ++(*this); +} + +bool radius_iterator::done() const +{ + return iter_done; +} + +coord_def radius_iterator::operator *() const +{ + return location; +} + +void radius_iterator::step() +{ + const int minx = std::max(X_BOUND_1+1, center.x - radius); + const int maxx = std::min(X_BOUND_2-1, center.x + radius); + const int maxy = std::min(Y_BOUND_2-1, center.y + radius); + + // Sweep L-R, U-D + location.x++; + if ( location.x > maxx ) + { + location.x = minx; + location.y++; + if ( location.y > maxy ) + iter_done = true; + } +} + +void radius_iterator::step_back() +{ + const int minx = std::max(X_BOUND_1+1, center.x - radius); + const int maxx = std::min(X_BOUND_2-1, center.x + radius); + const int miny = std::max(Y_BOUND_1+1, center.y - radius); + + location.x--; + if ( location.x < minx ) + { + location.x = maxx; + location.y--; + if ( location.y < miny ) + iter_done = true; // hmm + } +} + +bool radius_iterator::on_valid_square() const +{ + if ( !in_bounds(location) ) + return false; + if ( !roguelike_metric && (location - center).abs() > radius*radius ) + return false; + if ( require_los && !see_grid(location) ) + return false; + if ( exclude_center && location == center ) + return false; + return true; +} + +const radius_iterator& radius_iterator::operator++() +{ + do { + this->step(); + } while ( !this->done() && !this->on_valid_square() ); + return *this; +} + +const radius_iterator& radius_iterator::operator--() +{ + do { + this->step_back(); + } while ( !this->done() && !this->on_valid_square() ); + return *this; +} + +radius_iterator radius_iterator::operator++(int dummy) +{ + const radius_iterator copy = *this; + ++(*this); + return copy; +} + +radius_iterator radius_iterator::operator--(int dummy) +{ + const radius_iterator copy = *this; + --(*this); + return copy; +} + // Crude, but functional. std::string make_time_string( time_t abs_time, bool terse ) { diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h index 42d0006c8b..d7b59c6cb4 100644 --- a/crawl-ref/source/stuff.h +++ b/crawl-ref/source/stuff.h @@ -48,6 +48,32 @@ int roll_dice( int num, int size ); int roll_dice( const struct dice_def &dice ); void scale_dice( dice_def &dice, int threshold = 24 ); +class radius_iterator : public std::iterator +{ +public: + radius_iterator( const coord_def& center, int radius, + bool roguelike_metric = true, + bool require_los = true, + bool exclude_center = false ); + bool done() const; + operator bool() const { return !done(); } + coord_def operator *() const; + + const radius_iterator& operator ++ (); + const radius_iterator& operator -- (); + radius_iterator operator ++ (int); + radius_iterator operator -- (int); +private: + void step(); + void step_back(); + bool on_valid_square() const; + + coord_def location, center; + int radius; + bool roguelike_metric, require_los, exclude_center; + bool iter_done; +}; int random2limit(int max, int limit); int stepdown_value(int base_value, int stepping, int first_step, diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index d2d2d30dbf..50473e468b 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -471,6 +471,20 @@ void handle_traps(trap_type trt, int i, bool trap_known) exercise(SK_TRAPS_DOORS, ((coinflip()) ? 2 : 1)); } // end handle_traps() +void destroy_trap( const coord_def& pos ) +{ + for ( int i = 0; i < MAX_TRAPS; ++i ) + { + if ( env.trap[i].x == pos.x && env.trap[i].y == pos.y && + env.trap[i].type != TRAP_UNASSIGNED ) + { + grd(pos) = DNGN_FLOOR; + env.trap[i].type = TRAP_UNASSIGNED; + return; + } + } +} + void disarm_trap( struct dist &disa ) { if (you.duration[DUR_BERSERKER]) diff --git a/crawl-ref/source/traps.h b/crawl-ref/source/traps.h index 793789a935..935ad72629 100644 --- a/crawl-ref/source/traps.h +++ b/crawl-ref/source/traps.h @@ -42,25 +42,9 @@ void monster_caught_in_net(monsters *mon, bolt &pbolt); void player_caught_in_net(void); void clear_trapping_net(void); -// last updated 12may2000 {dlb} -/* *********************************************************************** - * called from: misc - mstuff2 - * *********************************************************************** */ void itrap(struct bolt &pbolt, int trapped); - -// last updated 3jun2000 {dlb} -/* *********************************************************************** - * called from: acr - misc - mstuff2 - spells3 - * *********************************************************************** */ -int trap_at_xy(int which_x, int which_y); - - -// last updated 3jun2000 {dlb} -/* *********************************************************************** - * called from: acr - misc - mstuff2 - spells2 - spells3 - * *********************************************************************** */ +void destroy_trap( const coord_def& pos ); dungeon_feature_type trap_category(trap_type type); - int trap_at_xy(int x, int y); trap_type trap_type_at_xy(int x, int y); diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 81deece2d1..a638506992 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -2466,7 +2466,7 @@ bool find_ray( int sourcex, int sourcey, int targetx, int targety, // Count the number of matching features between two points along // a beam-like path; the path will pass through solid features. -// By default, it exludes enpoints from the count. +// By default, it excludes enpoints from the count. int num_feats_between(int sourcex, int sourcey, int targetx, int targety, dungeon_feature_type min_feat, dungeon_feature_type max_feat, -- cgit v1.2.3-54-g00ecf