From c72f09adfa6f776ff5cabd0b8e4b4e0a2e752703 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Fri, 30 Oct 2009 15:59:29 +0100 Subject: Splitting up stuff.cc. New: colour.cc, coord.cc, coordit.cc, random.cc, rng.cc. --- crawl-ref/source/stuff.cc | 849 +--------------------------------------------- 1 file changed, 1 insertion(+), 848 deletions(-) (limited to 'crawl-ref/source/stuff.cc') diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 1654202916..ed29feb547 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -8,6 +8,7 @@ #include "beam.h" #include "cio.h" +#include "coordit.h" #include "database.h" #include "directn.h" #include "los.h" @@ -32,21 +33,6 @@ #include -#ifdef USE_MORE_SECURE_SEED - -// for times() -#include - -// for getpid() -#include -#include - -#endif - -#ifdef MORE_HARDENED_PRNG -#include "sha256.h" -#endif - #ifdef TARGET_OS_DOS #include #endif @@ -66,7 +52,6 @@ #include "misc.h" #include "monstuff.h" #include "mon-util.h" -#include "mt19937ar.h" #include "notes.h" #include "output.h" #include "player.h" @@ -129,183 +114,6 @@ stack_iterator stack_iterator::operator++(int dummy) return copy; } -rectangle_iterator::rectangle_iterator( const coord_def& corner1, - const coord_def& corner2 ) -{ - topleft.x = std::min(corner1.x, corner2.x); - topleft.y = std::min(corner1.y, corner2.y); // not really necessary - bottomright.x = std::max(corner1.x, corner2.x); - bottomright.y = std::max(corner1.y, corner2.y); - current = topleft; -} - -rectangle_iterator::rectangle_iterator( int x_border_dist, int y_border_dist ) -{ - if (y_border_dist < 0) - y_border_dist = x_border_dist; - - topleft.set(x_border_dist, y_border_dist); - bottomright.set(GXM - x_border_dist - 1, GYM - y_border_dist - 1); - current = topleft; -} - -rectangle_iterator::operator bool() const -{ - return (current.y <= bottomright.y); -} - -coord_def rectangle_iterator::operator *() const -{ - return current; -} - -const coord_def* rectangle_iterator::operator->() const -{ - return ¤t; -} - -rectangle_iterator& rectangle_iterator::operator ++() -{ - if (current.x == bottomright.x) - { - current.x = topleft.x; - current.y++; - } - else - { - current.x++; - } - return *this; -} - -rectangle_iterator rectangle_iterator::operator++( int dummy ) -{ - const rectangle_iterator copy = *this; - ++(*this); - return (copy); -} - -radius_iterator::radius_iterator(const coord_def& _center, int _radius, - bool _roguelike_metric, bool _require_los, - bool _exclude_center, - const env_show_grid* _losgrid) - : center(_center), radius(_radius), roguelike_metric(_roguelike_metric), - require_los(_require_los), exclude_center(_exclude_center), - losgrid(_losgrid), iter_done(false) -{ - reset(); -} - -void radius_iterator::reset() -{ - 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; -} - -const 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; - } -} - -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) - { - if (!losgrid && !see_cell(location)) - return (false); - if (losgrid && !see_cell(*losgrid, center, 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) { @@ -471,276 +279,6 @@ unsigned char get_ch() return gotched; } -void seed_rng(unsigned long* seed_key, size_t num_keys) -{ - // MT19937 -- see mt19937ar.cc for details/licence - init_by_array(seed_key, num_keys); -} - -void seed_rng(long seed) -{ - // MT19937 -- see mt19937ar.cc for details/licence - init_genrand(seed); -} - -void seed_rng() -{ - unsigned long seed = time( NULL ); -#ifdef USE_MORE_SECURE_SEED - - /* (at least) 256-bit wide seed */ - unsigned long seed_key[8]; - - struct tms buf; - seed += times( &buf ) + getpid(); - seed_key[0] = seed; - - /* Try opening from various system provided (hopefully) CSPRNGs */ - FILE* seed_f = fopen("/dev/urandom", "rb"); - if (!seed_f) - seed_f = fopen("/dev/random", "rb"); - if (!seed_f) - seed_f = fopen("/dev/srandom", "rb"); - if (!seed_f) - seed_f = fopen("/dev/arandom", "rb"); - if (seed_f) - { - fread(&seed_key[1], sizeof(unsigned long), 7, seed_f); - fclose(seed_f); - } - - seed_rng(seed_key, 8); - -#else - seed_rng(seed); -#endif -} - -// MT19937 -- see mt19937ar.cc for details -unsigned long random_int( void ) -{ -#ifndef MORE_HARDENED_PRNG - return (genrand_int32()); -#else - return (sha256_genrand()); -#endif -} - -int random_range(int low, int high) -{ - ASSERT(low <= high); - return (low + random2(high - low + 1)); -} - -int random_range(int low, int high, int nrolls) -{ - ASSERT(nrolls > 0); - int sum = 0; - for (int i = 0; i < nrolls; ++i) - sum += random_range(low, high); - return (sum / nrolls); -} - -// Chooses one of the numbers passed in at random. The list of numbers -// must be terminated with -1. -int random_choose(int first, ...) -{ - va_list args; - va_start(args, first); - - int chosen = first, count = 1, nargs = 100; - - while (nargs-- > 0) - { - const int pick = va_arg(args, int); - if (pick == -1) - break; - if (one_chance_in(++count)) - chosen = pick; - } - - ASSERT(nargs > 0); - - va_end(args); - return (chosen); -} - -// Chooses one of the strings passed in at random. The list of strings -// must be terminated with NULL. -const char* random_choose_string(const char* first, ...) -{ - va_list args; - va_start(args, first); - - const char* chosen = first; - int count = 1, nargs = 100; - - while (nargs-- > 0) - { - char* pick = va_arg(args, char*); - if (pick == NULL) - break; - if (one_chance_in(++count)) - chosen = pick; - } - - ASSERT(nargs > 0); - - va_end(args); - return (chosen); -} - -int random_choose_weighted(int weight, int first, ...) -{ - va_list args; - va_start(args, first); - - int chosen = first, cweight = weight, nargs = 100; - - while (nargs-- > 0) - { - const int nweight = va_arg(args, int); - if (!nweight) - break; - - const int choice = va_arg(args, int); - if (random2(cweight += nweight) < nweight) - chosen = choice; - } - - ASSERT(nargs > 0); - - va_end(args); - return (chosen); -} - -int random2(int max) -{ - if (max <= 1) - return (0); - - #ifdef MORE_HARDENED_PRNG - return (static_cast(sha256_genrand() / (0xFFFFFFFFUL / max + 1))); - #else - return (static_cast(genrand_int32() / (0xFFFFFFFFUL / max + 1))); - #endif -} - -bool coinflip(void) -{ - return (static_cast(random2(2))); -} - -// Returns random2(x) if random_factor is true, otherwise the mean. -int maybe_random2(int x, bool random_factor) -{ - if (random_factor) - return (random2(x)); - else - return (x / 2); -} - -void push_rng_state() -{ - push_mt_state(); -} - -void pop_rng_state() -{ - pop_mt_state(); -} - -// Attempts to make missile weapons nicer to the player by reducing the -// extreme variance in damage done. -void scale_dice(dice_def &dice, int threshold) -{ - while (dice.size > threshold) - { - dice.num *= 2; - // If it's an odd number, lose one; this is more than - // compensated by the increase in number of dice. - dice.size /= 2; - } -} - -int bestroll(int max, int rolls) -{ - int best = 0; - - for (int i = 0; i < rolls; i++) - { - int curr = random2(max); - if (curr > best) - best = curr; - } - - return (best); -} - -// random2avg() returns same mean value as random2() but with a lower variance -// never use with rolls < 2 as that would be silly - use random2() instead {dlb} -int random2avg(int max, int rolls) -{ - int sum = random2(max); - - for (int i = 0; i < (rolls - 1); i++) - sum += random2(max + 1); - - return (sum / rolls); -} - -int roll_dice(int num, int size) -{ - int ret = 0; - int i; - - // If num <= 0 or size <= 0, then we'll just return the default - // value of zero. This is good behaviour in that it will be - // appropriate for calculated values that might be passed in. - if (num > 0 && size > 0) - { - ret += num; // since random2() is zero based - - for (i = 0; i < num; i++) - ret += random2(size); - } - - return (ret); -} - -// originally designed to randomise evasion - -// values are slightly lowered near (max) and -// approach an upper limit somewhere near (limit/2) -int random2limit(int max, int limit) -{ - int i; - int sum = 0; - - if (max < 1) - return (0); - - for (i = 0; i < max; i++) - if (random2(limit) >= i) - sum++; - - return (sum); -} - -// Generate samples from a binomial distribution with n_trials and trial_prob -// probability of success per trial. trial_prob is a integer less than 100 -// representing the % chancee of success. -// This just evaluates all n trials, there is probably an efficient way of -// doing this but I'm not much of a statistician. -CAO -int binomial_generator(unsigned n_trials, unsigned trial_prob) -{ - int count = 0; - for (unsigned i = 0; i < n_trials; ++i) - if (::x_chance_in_y(trial_prob, 100)) - count++; - - return count; -} - void cio_init() { crawl_state.io_inited = true; @@ -968,33 +506,11 @@ int stat_div( int stat_level, int value, int mult, int shift ) return ((mult * value) / div); } -// Calculates num/den and randomly adds one based on the remainder. -int div_rand_round(int num, int den) -{ - return (num / den + (random2(den) < num % den)); -} - int div_round_up(int num, int den) { return (num / den + (num % den != 0)); } -bool one_chance_in(int a_million) -{ - return (random2(a_million) == 0); -} - -bool x_chance_in_y(int x, int y) -{ - if (x <= 0) - return (false); - - if (x >= y) - return (true); - - return (random2(y) < x); -} - // Simple little function to quickly modify all three stats // at once - does check for '0' modifiers to prevent needless // adding .. could use checking for sums less than zero, I guess. @@ -1269,41 +785,6 @@ int yesnoquit( const char* str, bool safe, int safeanswer, bool allow_all, } } -int grid_distance( const coord_def& p1, const coord_def& p2 ) -{ - return grid_distance(p1.x, p1.y, p2.x, p2.y); -} - -// More accurate than distance() given the actual movement geometry -- bwr -int grid_distance( int x, int y, int x2, int y2 ) -{ - const int dx = abs( x - x2 ); - const int dy = abs( y - y2 ); - - // returns distance in terms of moves: - return ((dx > dy) ? dx : dy); -} - -int distance( const coord_def& p1, const coord_def& p2 ) -{ - return distance(p1.x, p1.y, p2.x, p2.y); -} - -int distance( int x, int y, int x2, int y2 ) -{ - //jmf: now accurate, but remember to only compare vs. pre-squared distances - // thus, next to == (distance(m1.x,m1.y, m2.x,m2.y) <= 2) - const int dx = x - x2; - const int dy = y - y2; - - return ((dx * dx) + (dy * dy)); -} - -bool adjacent( const coord_def& p1, const coord_def& p2 ) -{ - return grid_distance(p1, p2) <= 1; -} - bool silenced(const coord_def& p) { // FIXME: implement for monsters @@ -1315,315 +796,6 @@ bool player_can_hear(const coord_def& p) return (!silenced(p) && !silenced(you.pos())); } -bool in_bounds_x(int x) -{ - return (x > X_BOUND_1 && x < X_BOUND_2); -} - -bool in_bounds_y(int y) -{ - return (y > Y_BOUND_1 && y < Y_BOUND_2); -} - -// Returns true if inside the area the player can move and dig (ie exclusive). -bool in_bounds(int x, int y) -{ - return (in_bounds_x(x) && in_bounds_y(y)); -} - -bool map_bounds_x(int x) -{ - return (x >= X_BOUND_1 && x <= X_BOUND_2); -} - -bool map_bounds_y(int y) -{ - return (y >= Y_BOUND_1 && y <= Y_BOUND_2); -} - -// Returns true if inside the area the player can map (ie inclusive). -// Note that terrain features should be in_bounds() leaving an outer -// ring of rock to frame the level. -bool map_bounds(int x, int y) -{ - return (map_bounds_x(x) && map_bounds_y(y)); -} - -coord_def random_in_bounds() -{ - if (crawl_state.arena) - { - const coord_def &ul = crawl_view.glos1; // Upper left - const coord_def &lr = crawl_view.glos2; // Lower right - - return coord_def(random_range(ul.x, lr.x - 1), - random_range(ul.y, lr.y - 1)); - } - else - return coord_def(random_range(MAPGEN_BORDER, GXM - MAPGEN_BORDER - 1), - random_range(MAPGEN_BORDER, GYM - MAPGEN_BORDER - 1)); -} - -unsigned char random_colour(void) -{ - return (1 + random2(15)); -} - -unsigned char random_uncommon_colour() -{ - unsigned char result; - - do - result = random_colour(); - while (result == LIGHTCYAN || result == CYAN || result == BROWN); - - return (result); -} - -unsigned char make_low_colour(unsigned char colour) -{ - if (colour >= 8 && colour <= 15) - return (colour - 8); - - return (colour); -} - -unsigned char make_high_colour(unsigned char colour) -{ - if (colour <= 7) - return (colour + 8); - - return (colour); -} - -// returns if a colour is one of the special element colours (ie not regular) -bool is_element_colour( int col ) -{ - // stripping any COLFLAGS (just in case) - return ((col & 0x007f) >= ETC_FIRE); -} - -int element_colour( int element, bool no_random ) -{ - // Doing this so that we don't have to do recursion here at all - // (these were the only cases which had possible double evaluation): - if (element == ETC_FLOOR) - element = env.floor_colour; - else if (element == ETC_ROCK) - element = env.rock_colour; - - // pass regular colours through for safety. - if (!is_element_colour( element )) - return (element); - - int ret = BLACK; - - // Setting no_random to true will get the first colour in the cases - // below. This is potentially useful for calls to this function - // which might want a consistent result. - int tmp_rand = (no_random ? 0 : random2(120)); - - switch (element & 0x007f) // strip COLFLAGs just in case - { - case ETC_FIRE: - ret = (tmp_rand < 40) ? RED : - (tmp_rand < 80) ? YELLOW - : LIGHTRED; - break; - - case ETC_ICE: - ret = (tmp_rand < 40) ? LIGHTBLUE : - (tmp_rand < 80) ? BLUE - : WHITE; - break; - - case ETC_EARTH: - ret = (tmp_rand < 60) ? BROWN : LIGHTRED; - break; - - case ETC_AIR: - ret = (tmp_rand < 60) ? LIGHTGREY : WHITE; - break; - - case ETC_ELECTRICITY: - ret = (tmp_rand < 40) ? LIGHTCYAN : - (tmp_rand < 80) ? LIGHTBLUE - : CYAN; - break; - - case ETC_POISON: - ret = (tmp_rand < 60) ? LIGHTGREEN : GREEN; - break; - - case ETC_WATER: - ret = (tmp_rand < 60) ? BLUE : CYAN; - break; - - case ETC_MAGIC: - ret = (tmp_rand < 30) ? LIGHTMAGENTA : - (tmp_rand < 60) ? LIGHTBLUE : - (tmp_rand < 90) ? MAGENTA - : BLUE; - break; - - case ETC_MUTAGENIC: - case ETC_WARP: - ret = (tmp_rand < 60) ? LIGHTMAGENTA : MAGENTA; - break; - - case ETC_ENCHANT: - ret = (tmp_rand < 60) ? LIGHTBLUE : BLUE; - break; - - case ETC_HEAL: - ret = (tmp_rand < 60) ? LIGHTBLUE : YELLOW; - break; - - case ETC_BLOOD: - ret = (tmp_rand < 60) ? RED : DARKGREY; - break; - - case ETC_DEATH: // assassin - case ETC_NECRO: // necromancer - ret = (tmp_rand < 80) ? DARKGREY : MAGENTA; - break; - - case ETC_UNHOLY: // ie demonology - ret = (tmp_rand < 80) ? DARKGREY : RED; - break; - - case ETC_DARK: - ret = (tmp_rand < 80) ? DARKGREY : LIGHTGREY; - break; - - case ETC_HOLY: - ret = (tmp_rand < 60) ? YELLOW : WHITE; - break; - - case ETC_VEHUMET: - ret = (tmp_rand < 40) ? LIGHTRED : - (tmp_rand < 80) ? LIGHTMAGENTA - : LIGHTBLUE; - break; - - case ETC_BEOGH: - ret = (tmp_rand < 60) ? LIGHTRED // plain Orc colour - : BROWN; // Orcish mines wall/idol colour - break; - - case ETC_CRYSTAL: - ret = (tmp_rand < 40) ? LIGHTGREY : - (tmp_rand < 80) ? GREEN - : LIGHTRED; - break; - - case ETC_SLIME: - ret = (tmp_rand < 40) ? GREEN : - (tmp_rand < 80) ? BROWN - : LIGHTGREEN; - break; - - case ETC_SMOKE: - ret = (tmp_rand < 30) ? LIGHTGREY : - (tmp_rand < 60) ? DARKGREY : - (tmp_rand < 90) ? LIGHTBLUE - : MAGENTA; - break; - - case ETC_JEWEL: - ret = (tmp_rand < 12) ? WHITE : - (tmp_rand < 24) ? YELLOW : - (tmp_rand < 36) ? LIGHTMAGENTA : - (tmp_rand < 48) ? LIGHTRED : - (tmp_rand < 60) ? LIGHTGREEN : - (tmp_rand < 72) ? LIGHTBLUE : - (tmp_rand < 84) ? MAGENTA : - (tmp_rand < 96) ? RED : - (tmp_rand < 108) ? GREEN - : BLUE; - break; - - case ETC_ELVEN: - ret = (tmp_rand < 40) ? LIGHTGREEN : - (tmp_rand < 80) ? GREEN : - (tmp_rand < 100) ? LIGHTBLUE - : BLUE; - break; - - case ETC_DWARVEN: - ret = (tmp_rand < 40) ? BROWN : - (tmp_rand < 80) ? LIGHTRED : - (tmp_rand < 100) ? LIGHTGREY - : CYAN; - break; - - case ETC_ORCISH: - ret = (tmp_rand < 40) ? DARKGREY : - (tmp_rand < 80) ? RED : - (tmp_rand < 100) ? BROWN - : MAGENTA; - break; - - case ETC_GILA: - ret = (tmp_rand < 30) ? LIGHTMAGENTA : - (tmp_rand < 60) ? MAGENTA : - (tmp_rand < 90) ? YELLOW : - (tmp_rand < 105) ? LIGHTRED - : RED; - break; - - case ETC_STONE: - if (player_in_branch( BRANCH_HALL_OF_ZOT )) - ret = env.rock_colour; - else - ret = LIGHTGREY; - break; - - case ETC_MIST: - ret = tmp_rand < 100? CYAN : BLUE; - break; - - case ETC_SHIMMER_BLUE: - ret = random_choose_weighted(80, BLUE, 20, LIGHTBLUE, 5, CYAN, 0); - break; - - case ETC_DECAY: - ret = (tmp_rand < 60) ? BROWN : GREEN; - break; - - case ETC_SILVER: - ret = (tmp_rand < 90) ? LIGHTGREY : WHITE; - break; - - case ETC_GOLD: - ret = (tmp_rand < 60) ? YELLOW : BROWN; - break; - - case ETC_IRON: - ret = (tmp_rand < 40) ? CYAN : - (tmp_rand < 80) ? LIGHTGREY : - DARKGREY; - break; - - case ETC_BONE: - ret = (tmp_rand < 90) ? WHITE : LIGHTGREY; - break; - - case ETC_RANDOM: - ret = 1 + random2(15); // always random - break; - - case ETC_FLOOR: // should already be handled - case ETC_ROCK: // should already be handled - default: - break; - } - - ASSERT( !is_element_colour( ret ) ); - - return ((ret == BLACK) ? GREEN : ret); -} - char index_to_letter(int the_index) { return (the_index + ((the_index < 26) ? 'a' : ('A' - 26))); @@ -1641,13 +813,6 @@ int letter_to_index(int the_letter) return (the_letter); } -int fuzz_value(int val, int lowfuzz, int highfuzz, int naverage) -{ - const int lfuzz = lowfuzz * val / 100, - hfuzz = highfuzz * val / 100; - return val + random2avg(lfuzz + hfuzz + 1, naverage) - lfuzz; -} - // Returns 0 if the point is not near stairs. // Returns 1 if the point is near unoccupied stairs. // Returns 2 if the point is near player-occupied stairs. @@ -1740,13 +905,6 @@ void zap_los_monsters() } } -////////////////////////////////////////////////////////////////////////// -// coord_def -int coord_def::distance_from(const coord_def &other) const -{ - return (grid_distance(*this, other)); -} - int integer_sqrt(int value) { if (value <= 0) @@ -1772,8 +930,3 @@ int random_rod_subtype() { return STAFF_FIRST_ROD + random2(NUM_STAVES - STAFF_FIRST_ROD); } - -int dice_def::roll() const -{ - return roll_dice(this->num, this->size); -} -- cgit v1.2.3-54-g00ecf