wesnoth/src/util.hpp
Ali El Gariani 125f186aaa Allow to have attack with damage=0...
(rounding of other attacks continue to be >0)

This also fix round_damage() which was supposed to round towards
base_damage, but was incorrect for 2 cases: when dividing by 1 (D/1
give D-1, but currently not used) and when base_damage was 0.
2009-05-11 20:04:00 +00:00

183 lines
4.5 KiB
C++

/* $Id$ */
/*
Copyright (C) 2003 - 2009 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
or at your option any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file util.hpp
* Templates and utility-routines for strings and numbers.
*/
#ifndef UTIL_H_INCLUDED
#define UTIL_H_INCLUDED
#include "global.hpp"
#include "wesconfig.h"
#include <cmath>
#include <vector>
#include <sstream>
template<typename T>
inline bool is_odd(T num) {
int n = static_cast< int >(num);
return static_cast< unsigned int >(n >= 0 ? n : -n) & 1;
}
template<typename T>
inline bool is_even(T num) { return !is_odd(num); }
/** Guarantees portable results for division by 100; round towards 0 */
inline int div100rounded(int num) {
return (num < 0) ? -(((-num) + 49) / 100) : (num + 49) / 100;
}
/**
* round (base_damage * bonus / divisor) to the closest integer,
* but up or down towards base_damage
*/
inline int round_damage(int base_damage, int bonus, int divisor) {
if (base_damage==0) return 0;
const int rounding = divisor / 2 - (bonus < divisor || divisor==1 ? 0 : 1);
return std::max<int>(1, (base_damage * bonus + rounding) / divisor);
}
// not guaranteed to have exactly the same result on different platforms
inline int round_double(double d) {
#ifdef HAVE_ROUND
return static_cast<int>(round(d)); //surprisingly, not implemented everywhere
#else
return static_cast<int>((d >= 0.0)? std::floor(d + 0.5) : std::ceil(d - 0.5));
#endif
}
// Guaranteed to have portable results across different platforms
inline double round_portable(double d) {
return (d >= 0.0) ? std::floor(d + 0.5) : std::ceil(d - 0.5);
}
struct bad_lexical_cast {};
template<typename To, typename From>
To lexical_cast(From a)
{
To res;
std::stringstream str;
if(!(str << a && str >> res)) {
throw bad_lexical_cast();
} else {
return res;
}
}
template<typename To, typename From>
To lexical_cast_default(From a, To def=To())
{
To res;
std::stringstream str;
if(!(str << a && str >> res)) {
return def;
} else {
return res;
}
}
template<>
int lexical_cast<int, const std::string&>(const std::string& a);
template<>
int lexical_cast<int, const char*>(const char* a);
template<>
int lexical_cast_default<int, const std::string&>(const std::string& a, int def);
template<>
int lexical_cast_default<int, const char*>(const char* a, int def);
template<typename From>
std::string str_cast(From a)
{
return lexical_cast<std::string,From>(a);
}
template<typename To, typename From>
To lexical_cast_in_range(From a, To def, To min, To max)
{
To res;
std::stringstream str;
if(!(str << a && str >> res)) {
return def;
} else {
if(res < min) {
return min;
}
if(res > max) {
return max;
}
return res;
}
}
template<typename Cmp>
bool in_ranges(const Cmp c, const std::vector<std::pair<Cmp, Cmp> >&ranges) {
typename std::vector<std::pair<Cmp,Cmp> >::const_iterator range,
range_end = ranges.end();
for (range = ranges.begin(); range != range_end; ++range) {
if(range->first <= c && c <= range->second) {
return true;
}
}
return false;
}
inline bool chars_equal_insensitive(char a, char b) { return tolower(a) == tolower(b); }
inline bool chars_less_insensitive(char a, char b) { return tolower(a) < tolower(b); }
#ifdef __GNUC__
#define LIKELY(a) __builtin_expect((a),1) // Tells GCC to optimize code so that if is likely to happen
#define UNLIKELY(a) __builtin_expect((a),0) // Tells GCC to optimize code so that if is unlikely to happen
#else
#define LIKELY(a) a
#define UNLIKELY(a) a
#endif
#if 1
# include <SDL_types.h>
typedef Sint32 fixed_t;
# define fxp_shift 8
# define fxp_base (1 << fxp_shift)
/** IN: float or int - OUT: fixed_t */
# define ftofxp(x) (fixed_t((x) * fxp_base))
/** IN: unsigned and fixed_t - OUT: unsigned */
# define fxpmult(x,y) (((x)*(y)) >> fxp_shift)
/** IN: unsigned and int - OUT: fixed_t */
# define fxpdiv(x,y) (((x) << fxp_shift) / (y))
/** IN: fixed_t - OUT: int */
# define fxptoi(x) ( ((x)>0) ? ((x) >> fxp_shift) : (-((-(x)) >> fxp_shift)) )
#else
typedef float fixed_t;
# define ftofxp(x) (x)
# define fxpmult(x,y) ((x)*(y))
# define fxpdiv(x,y) (static_cast<float>(x) / static_cast<float>(y))
# define fxptoi(x) ( static_cast<int>(x) )
#endif
#endif