2019-08-10 11:43:24 +00:00
|
|
|
// Hyperbolic Rogue -- main header file
|
|
|
|
// Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
|
|
|
|
|
2019-08-10 17:30:21 +00:00
|
|
|
/** \file hyper.h
|
2019-08-10 11:43:24 +00:00
|
|
|
* \brief The main header file of HyperRogue
|
|
|
|
*
|
|
|
|
* Contains general utility macros, various value macros, using clauses for standard library functions,
|
|
|
|
* implementation of the basic connection_table, walker, cell and heptagon classes,
|
|
|
|
* and general routines which did not fit elsewhere
|
|
|
|
*/
|
2017-10-29 13:19:51 +00:00
|
|
|
|
2019-09-05 07:07:04 +00:00
|
|
|
#ifndef _HYPER_H_
|
|
|
|
#define _HYPER_H_
|
|
|
|
|
2018-06-10 23:58:31 +00:00
|
|
|
// version numbers
|
2020-05-31 15:22:18 +00:00
|
|
|
#define VER "11.3o"
|
|
|
|
#define VERNUM_HEX 0xA82F
|
2018-06-10 23:58:31 +00:00
|
|
|
|
2019-09-05 07:07:04 +00:00
|
|
|
#include "sysconfig.h"
|
|
|
|
|
2018-06-17 03:32:09 +00:00
|
|
|
#include <stdarg.h>
|
2019-01-06 01:47:51 +00:00
|
|
|
#include "hyper_function.h"
|
2018-06-17 03:32:09 +00:00
|
|
|
|
2020-03-27 20:48:31 +00:00
|
|
|
/** \brief the main namespace of HyperRogue */
|
2018-06-10 23:58:31 +00:00
|
|
|
namespace hr {
|
|
|
|
|
2020-03-27 20:48:31 +00:00
|
|
|
/** \brief A helper structure that acts as a boolean which is always false. Helpful when disabling stuff with compiler flags. */
|
2019-02-17 17:50:56 +00:00
|
|
|
struct always_false {
|
|
|
|
operator bool() const { return false; };
|
2019-09-13 01:10:26 +00:00
|
|
|
bool operator = (bool b) const { return b; };
|
2019-02-17 17:50:56 +00:00
|
|
|
};
|
|
|
|
|
2020-03-27 20:48:31 +00:00
|
|
|
/** \brief placate GCC's overzealous -Wunused-result */
|
2018-07-14 06:45:14 +00:00
|
|
|
template<class T>
|
|
|
|
void ignore(T&&) {
|
|
|
|
}
|
|
|
|
|
2020-03-27 20:48:31 +00:00
|
|
|
/** \brief a simple static_cast<void*> for use with printf("%p") */
|
2020-03-27 18:39:33 +00:00
|
|
|
inline const void *voidp(const void *p) {
|
2020-02-23 02:48:46 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2020-03-27 20:48:31 +00:00
|
|
|
/** \brief Is the value of first parameter equal to one of the remaining parameters? */
|
2019-03-30 16:52:51 +00:00
|
|
|
template<class T, class V, class... U> bool among(T x, V y) { return x == y; }
|
|
|
|
template<class T, class V, class... U> bool among(T x, V y, U... u) { return x==y || among(x,u...); }
|
|
|
|
|
2018-06-17 16:32:06 +00:00
|
|
|
// functions and types used from the standard library
|
|
|
|
using std::vector;
|
|
|
|
using std::map;
|
|
|
|
using std::array;
|
|
|
|
using std::unordered_map;
|
|
|
|
using std::sort;
|
|
|
|
using std::multimap;
|
|
|
|
using std::set;
|
|
|
|
using std::string;
|
|
|
|
using std::pair;
|
|
|
|
using std::tuple;
|
|
|
|
using std::shared_ptr;
|
|
|
|
using std::make_shared;
|
|
|
|
using std::min;
|
|
|
|
using std::max;
|
|
|
|
using std::make_pair;
|
|
|
|
using std::tie;
|
|
|
|
using std::queue;
|
|
|
|
using std::swap;
|
|
|
|
using std::complex;
|
|
|
|
using std::reverse;
|
|
|
|
using std::real;
|
|
|
|
using std::imag;
|
|
|
|
using std::stable_sort;
|
|
|
|
using std::out_of_range;
|
|
|
|
using std::get;
|
2018-06-22 00:00:26 +00:00
|
|
|
using std::move;
|
|
|
|
using std::make_tuple;
|
2018-09-04 17:53:42 +00:00
|
|
|
using std::unique_ptr;
|
2018-06-18 01:53:39 +00:00
|
|
|
|
2018-06-18 01:43:23 +00:00
|
|
|
using std::abs;
|
2018-06-18 01:53:39 +00:00
|
|
|
using std::isfinite;
|
|
|
|
using std::isnan;
|
2018-10-23 15:03:58 +00:00
|
|
|
using std::isinf;
|
2018-06-18 01:53:39 +00:00
|
|
|
using std::log;
|
|
|
|
using std::exp;
|
|
|
|
using std::sin;
|
|
|
|
using std::cos;
|
|
|
|
using std::sinh;
|
|
|
|
using std::asin;
|
|
|
|
using std::acos;
|
|
|
|
using std::tan;
|
|
|
|
using std::atan;
|
|
|
|
using std::atan2;
|
|
|
|
using std::tanh;
|
|
|
|
using std::sqrt;
|
|
|
|
using std::pow;
|
|
|
|
using std::floor;
|
|
|
|
using std::ceil;
|
2018-07-23 12:07:18 +00:00
|
|
|
#ifndef NO_STD_HYPOT
|
2018-07-23 03:18:03 +00:00
|
|
|
using std::hypot;
|
|
|
|
using std::asinh;
|
|
|
|
using std::acosh;
|
|
|
|
#endif
|
2018-06-10 23:58:31 +00:00
|
|
|
|
2019-04-03 18:24:15 +00:00
|
|
|
struct hr_exception: std::exception { hr_exception() {} };
|
|
|
|
struct hr_shortest_path_exception: hr_exception { };
|
|
|
|
|
2018-06-10 23:58:31 +00:00
|
|
|
// genus (in grammar)
|
|
|
|
#define GEN_M 0
|
|
|
|
#define GEN_F 1
|
|
|
|
#define GEN_N 2
|
|
|
|
#define GEN_O 3
|
|
|
|
|
2019-04-29 09:17:06 +00:00
|
|
|
// Add a message to the GUI.
|
|
|
|
// If multiple messages appear with the same spamtype != 0, the older ones disappear quickly
|
2018-06-10 23:58:31 +00:00
|
|
|
void addMessage(string s, char spamtype = 0);
|
|
|
|
|
|
|
|
// geometry-dependent constants
|
|
|
|
|
2019-10-10 11:13:37 +00:00
|
|
|
#define cginf ginf[geometry]
|
|
|
|
|
|
|
|
#define S7 cginf.sides
|
|
|
|
#define S3 cginf.vertex
|
2019-12-14 11:05:01 +00:00
|
|
|
#define hyperbolic_37 (S7 == 7 && S3 == 3 && !bt::in() && !arcm::in())
|
|
|
|
#define hyperbolic_not37 ((S7 > 7 || S3 > 3 || bt::in() || arcm::in()) && hyperbolic)
|
|
|
|
#define weirdhyperbolic ((S7 > 7 || S3 > 3 || !STDVAR || bt::in() || arcm::in()) && hyperbolic)
|
|
|
|
#define stdhyperbolic (S7 == 7 && S3 == 3 && STDVAR && !bt::in() && !arcm::in())
|
2018-08-09 17:28:53 +00:00
|
|
|
|
2019-10-10 11:13:37 +00:00
|
|
|
#define cgflags cginf.flags
|
|
|
|
|
|
|
|
#define cryst (cgflags & qCRYSTAL)
|
2019-04-29 09:17:06 +00:00
|
|
|
|
2019-08-10 17:34:12 +00:00
|
|
|
/** convenience flag for geometries with major aspects missing */
|
2019-10-10 11:13:37 +00:00
|
|
|
#define experimental (cgflags & qEXPERIMENTAL)
|
2019-08-10 17:34:12 +00:00
|
|
|
|
2019-04-29 09:17:06 +00:00
|
|
|
// these geometries do not feature alternate structures for horocycles
|
2019-12-14 11:05:01 +00:00
|
|
|
#define eubinary (euclid || bt::in() || cryst || nil)
|
2018-06-10 23:58:31 +00:00
|
|
|
|
2019-10-10 11:13:37 +00:00
|
|
|
#define cgclass (cginf.cclass)
|
2018-06-10 23:58:31 +00:00
|
|
|
#define euclid (cgclass == gcEuclid)
|
|
|
|
#define sphere (cgclass == gcSphere)
|
2019-10-10 11:13:37 +00:00
|
|
|
#define sol (cgflags & qSOL)
|
|
|
|
#define nih (cgflags & qNIH)
|
2019-08-06 10:00:46 +00:00
|
|
|
#define nil (cgclass == gcNil)
|
2019-08-24 09:55:45 +00:00
|
|
|
#define sl2 (cgclass == gcSL2)
|
2019-08-17 21:28:41 +00:00
|
|
|
#define prod (cgclass == gcProduct)
|
2019-10-10 11:13:37 +00:00
|
|
|
#define hybri (cgflags & qHYBRID)
|
2020-05-08 18:26:30 +00:00
|
|
|
#define rotspace (geometry == gRotSpace)
|
2018-06-10 23:58:31 +00:00
|
|
|
#define hyperbolic (cgclass == gcHyperbolic)
|
2019-12-14 11:28:45 +00:00
|
|
|
#define nonisotropic (among(cgclass, gcSolNIH, gcNil, gcSL2))
|
2019-08-06 10:00:46 +00:00
|
|
|
#define translatable (euclid || nonisotropic)
|
2019-10-10 11:13:37 +00:00
|
|
|
#define nonorientable (cgflags & qNONORIENTABLE)
|
|
|
|
#define elliptic (cgflags & qELLIPTIC)
|
|
|
|
#define quotient (cgflags & qANYQ)
|
|
|
|
#define smallbounded (cgflags & qSMALL)
|
|
|
|
#define bounded (cgflags & qBOUNDED)
|
2018-06-10 23:58:31 +00:00
|
|
|
|
2019-04-29 09:17:06 +00:00
|
|
|
// Dry Forest burning, heat transfer, etc. are performed on the whole universe
|
|
|
|
#define doall (bounded)
|
|
|
|
|
2019-12-14 10:42:16 +00:00
|
|
|
#define sphere_narcm (sphere && !arcm::in())
|
2018-08-17 11:29:00 +00:00
|
|
|
|
2018-06-10 23:58:31 +00:00
|
|
|
#define a4 (S3 == 4)
|
|
|
|
#define a45 (S3 == 4 && S7 == 5)
|
|
|
|
#define a46 (S3 == 4 && S7 == 6)
|
|
|
|
#define a47 (S3 == 4 && S7 == 7)
|
|
|
|
#define a457 (S3 == 4 && S7 != 6)
|
|
|
|
#define a467 (S3 == 4 && S7 >= 6)
|
2018-11-30 13:45:19 +00:00
|
|
|
#define a38 (S3 == 3 && S7 == 8)
|
2018-06-10 23:58:31 +00:00
|
|
|
#define sphere4 (sphere && S7 == 4)
|
|
|
|
#define stdeuc (geometry == gNormal || geometry == gEuclid || geometry == gEuclidSquare)
|
2018-11-30 14:26:50 +00:00
|
|
|
#define smallsphere (sphere_narcm && S7 < 5)
|
|
|
|
#define bigsphere (sphere_narcm && S7 == 5)
|
2018-06-10 23:58:31 +00:00
|
|
|
|
|
|
|
#define S6 (S3*2)
|
|
|
|
#define MAX_S3 4
|
|
|
|
|
2018-11-27 15:17:20 +00:00
|
|
|
#define SG6 (S3==3?6:4)
|
|
|
|
#define SG3 (S3==3?3:2)
|
|
|
|
#define SG2 (S3==3?2:1)
|
|
|
|
|
2018-08-28 15:17:34 +00:00
|
|
|
#define GOLDBERG (variation == eVariation::goldberg)
|
|
|
|
#define IRREGULAR (variation == eVariation::irregular)
|
|
|
|
#define PURE (variation == eVariation::pure)
|
|
|
|
#define BITRUNCATED (variation == eVariation::bitruncated)
|
2018-08-30 00:11:43 +00:00
|
|
|
#define DUAL (variation == eVariation::dual)
|
2018-08-30 14:05:24 +00:00
|
|
|
#define DUALMUL (DUAL ? 2 : 1)
|
2018-08-28 15:17:34 +00:00
|
|
|
|
2019-10-10 11:13:37 +00:00
|
|
|
#define CHANGED_VARIATION (variation != cginf.default_variation)
|
2018-08-28 15:17:34 +00:00
|
|
|
|
|
|
|
#define STDVAR (PURE || BITRUNCATED)
|
|
|
|
#define NONSTDVAR (!STDVAR)
|
|
|
|
|
2019-02-17 17:28:20 +00:00
|
|
|
#if CAP_ARCM
|
2019-12-14 10:42:16 +00:00
|
|
|
#define VALENCE (BITRUNCATED ? 3 : arcm::in() ? arcm::valence() : S3)
|
2019-02-17 17:28:20 +00:00
|
|
|
#else
|
|
|
|
#define VALENCE (BITRUNCATED ? 3 : S3)
|
|
|
|
#endif
|
2018-08-28 15:17:34 +00:00
|
|
|
|
2016-08-26 09:58:03 +00:00
|
|
|
#define NUMWITCH 7
|
|
|
|
|
|
|
|
// achievements
|
|
|
|
|
|
|
|
#define LB_YENDOR_CHALLENGE 40
|
|
|
|
#define LB_PURE_TACTICS 41
|
2020-02-28 23:09:02 +00:00
|
|
|
#define NUMLEADER 85
|
2016-08-26 09:58:03 +00:00
|
|
|
#define LB_PURE_TACTICS_SHMUP 49
|
|
|
|
#define LB_PURE_TACTICS_COOP 50
|
2019-01-11 01:19:28 +00:00
|
|
|
#define LB_RACING 81
|
2016-08-26 09:58:03 +00:00
|
|
|
|
2017-10-29 11:19:33 +00:00
|
|
|
#if ISMOBILE || ISWEB || ISPANDORA || 1
|
|
|
|
typedef double ld;
|
|
|
|
#define LDF "%lf"
|
|
|
|
#define PLDF "lf"
|
|
|
|
#else
|
|
|
|
typedef long double ld;
|
|
|
|
#define LDF "%Lf"
|
|
|
|
#define PLDF "Lf"
|
|
|
|
#endif
|
|
|
|
|
2018-11-06 23:51:41 +00:00
|
|
|
typedef complex<ld> cld;
|
|
|
|
|
2019-12-23 21:21:04 +00:00
|
|
|
typedef unsigned color_t;
|
|
|
|
|
2019-05-29 14:27:24 +00:00
|
|
|
struct charstyle {
|
|
|
|
int charid;
|
|
|
|
color_t skincolor, haircolor, dresscolor, swordcolor, dresscolor2, uicolor, eyecolor;
|
|
|
|
bool lefthanded;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum eStereo { sOFF, sAnaglyph, sLR, sODS };
|
|
|
|
|
2019-12-23 21:21:04 +00:00
|
|
|
enum eModel : int;
|
|
|
|
|
2020-04-16 22:53:58 +00:00
|
|
|
/** configuration of the projection */
|
|
|
|
struct projection_configuration {
|
|
|
|
eModel model; /**< which projection, see classes.cpp */
|
|
|
|
ld xposition, yposition; /**< move the center to another position */
|
|
|
|
ld scale, alpha, camera_angle, fisheye_param, twopoint_param, stretch, ballangle, ballproj, euclid_to_sphere;
|
|
|
|
ld clip_min, clip_max;
|
|
|
|
ld model_orientation, halfplane_scale, model_orientation_yz;
|
|
|
|
ld collignon_parameter;
|
|
|
|
bool collignon_reflected;
|
|
|
|
string formula;
|
|
|
|
eModel basic_model;
|
|
|
|
ld top_z;
|
|
|
|
ld model_transition;
|
|
|
|
ld spiral_angle;
|
|
|
|
ld spiral_x;
|
|
|
|
ld spiral_y;
|
|
|
|
bool use_atan;
|
|
|
|
ld right_spiral_multiplier;
|
|
|
|
ld any_spiral_multiplier;
|
|
|
|
ld sphere_spiral_multiplier;
|
|
|
|
ld spiral_cone;
|
|
|
|
ld skiprope;
|
|
|
|
ld product_z_scale;
|
|
|
|
|
|
|
|
projection_configuration() {
|
|
|
|
formula = "z^2"; top_z = 5; model_transition = 1; spiral_angle = 70; spiral_x = 10; spiral_y = 7;
|
|
|
|
right_spiral_multiplier = 1;
|
|
|
|
any_spiral_multiplier = 1;
|
|
|
|
sphere_spiral_multiplier = 2;
|
|
|
|
spiral_cone = 360;
|
|
|
|
use_atan = false;
|
|
|
|
product_z_scale = 1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-29 14:27:24 +00:00
|
|
|
struct videopar {
|
2020-04-16 22:53:58 +00:00
|
|
|
projection_configuration projection_config, rug_config;
|
|
|
|
ld yshift;
|
|
|
|
ld sspeed, mspeed;
|
|
|
|
ld binary_width, fixed_facing_dir;
|
2019-05-29 14:27:24 +00:00
|
|
|
int mobilecompasssize;
|
|
|
|
int radarsize; // radar for 3D geometries
|
2019-07-31 15:32:44 +00:00
|
|
|
ld radarrange;
|
2019-05-29 14:27:24 +00:00
|
|
|
int aurastr, aurasmoothen;
|
|
|
|
bool fixed_facing;
|
|
|
|
bool fixed_yz;
|
|
|
|
bool use_wall_radar;
|
|
|
|
|
|
|
|
int linequality;
|
|
|
|
|
|
|
|
bool full;
|
|
|
|
|
|
|
|
int graphglyph; // graphical glyphs
|
|
|
|
bool darkhepta;
|
|
|
|
int shifttarget;
|
|
|
|
|
|
|
|
int xres, yres, framelimit;
|
|
|
|
|
|
|
|
int xscr, yscr;
|
|
|
|
|
|
|
|
bool grid;
|
2019-12-25 22:04:07 +00:00
|
|
|
bool particles;
|
2019-05-29 14:27:24 +00:00
|
|
|
|
|
|
|
int fsize;
|
|
|
|
int flashtime;
|
|
|
|
|
|
|
|
int wallmode, monmode, axes;
|
2019-06-25 08:30:31 +00:00
|
|
|
bool axes3;
|
2019-05-29 14:27:24 +00:00
|
|
|
bool revcontrol;
|
|
|
|
|
|
|
|
int msgleft, msglimit;
|
|
|
|
|
|
|
|
bool usingGL;
|
|
|
|
int antialias;
|
|
|
|
#define AA_NOGL 1
|
|
|
|
#define AA_VERSION 2
|
|
|
|
#define AA_LINES 4
|
|
|
|
#define AA_POLY 8
|
|
|
|
#define AA_LINEWIDTH 16
|
|
|
|
#define AA_FONT 32
|
|
|
|
#define AA_MULTI 64
|
|
|
|
#define AA_MULTI16 128 // not configurable
|
|
|
|
ld linewidth;
|
2019-07-13 12:37:30 +00:00
|
|
|
|
|
|
|
ld multiplier_grid, multiplier_ring;
|
2019-05-29 14:27:24 +00:00
|
|
|
|
|
|
|
int joyvalue, joyvalue2, joypanthreshold;
|
|
|
|
ld joypanspeed;
|
|
|
|
|
|
|
|
charstyle cs;
|
|
|
|
|
|
|
|
bool samegender; // same gender for the Princess?
|
|
|
|
int language;
|
|
|
|
|
|
|
|
bool backeffects; // background particle effects
|
|
|
|
|
|
|
|
int killreduction, itemreduction, portreduction;
|
|
|
|
|
|
|
|
int steamscore;
|
|
|
|
bool drawmousecircle; // draw the circle around the mouse
|
|
|
|
bool skipstart; // skip the start menu
|
|
|
|
bool quickmouse; // quick mouse on the map
|
|
|
|
bool sloppy_3d; // make 3D faster but ugly
|
|
|
|
int timeformat; // time format used in the message log
|
|
|
|
|
|
|
|
int use_smart_range; // 0 = distance-based, 1 = model-based, 2 = model-based and generate
|
|
|
|
ld smart_range_detail;// minimum visible cell for modes 1 and 2
|
|
|
|
ld smart_range_detail_3;// minimum visible cell in 3D (for mode 2, there is no mode 1)
|
|
|
|
int cells_drawn_limit;
|
|
|
|
int cells_generated_limit; // limit on cells generated per frame
|
|
|
|
|
|
|
|
eStereo stereo_mode;
|
|
|
|
ld ipd;
|
|
|
|
ld lr_eyewidth, anaglyph_eyewidth;
|
|
|
|
ld fov;
|
|
|
|
bool consider_shader_projection;
|
|
|
|
int desaturate;
|
|
|
|
int texture_step;
|
|
|
|
|
|
|
|
|
|
|
|
bool always3; // always use the 3D engine
|
|
|
|
ld depth; // world level below the plane
|
|
|
|
ld camera; // camera level above the plane
|
|
|
|
ld wall_height, creature_scale, height_width;
|
|
|
|
ld lake_top, lake_bottom;
|
|
|
|
ld rock_wall_ratio;
|
|
|
|
ld human_wall_ratio;
|
|
|
|
|
|
|
|
int tc_alpha, tc_depth, tc_camera;
|
|
|
|
ld highdetail, middetail;
|
|
|
|
bool gp_autoscale_heights;
|
2019-06-01 17:58:07 +00:00
|
|
|
|
|
|
|
ld eye;
|
|
|
|
bool auto_eye;
|
2019-08-14 16:58:42 +00:00
|
|
|
|
2019-08-18 19:16:27 +00:00
|
|
|
ld plevel_factor;
|
2019-12-25 22:04:07 +00:00
|
|
|
bool bubbles_special, bubbles_threshold, bubbles_all;
|
2019-12-27 10:57:08 +00:00
|
|
|
int joysmooth;
|
2019-05-29 14:27:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
extern videopar vid;
|
|
|
|
|
2019-10-10 11:13:37 +00:00
|
|
|
#define WDIM cginf.g.gameplay_dimension
|
|
|
|
#define GDIM cginf.g.graphical_dimension
|
2020-04-17 13:37:31 +00:00
|
|
|
#define MDIM (MAXMDIM == 3 ? 3 : cginf.g.homogeneous_dimension)
|
2019-08-17 21:28:41 +00:00
|
|
|
#define LDIM (MDIM-1)
|
2019-08-22 09:24:25 +00:00
|
|
|
#define cclass g.kind
|
2019-02-17 17:47:19 +00:00
|
|
|
|
2019-08-09 12:03:43 +00:00
|
|
|
#define self (*this)
|
|
|
|
|
2020-01-18 15:59:16 +00:00
|
|
|
// #define MODFIXER (2*10090080*17)
|
2017-10-29 11:19:33 +00:00
|
|
|
|
|
|
|
#define BUGCOLORS 3
|
|
|
|
|
2019-06-17 08:13:08 +00:00
|
|
|
#define big_unlock (inv::on && !chaosmode)
|
|
|
|
|
2017-10-29 11:19:33 +00:00
|
|
|
// land completion for shared unlocking
|
2019-06-17 08:13:08 +00:00
|
|
|
#define U5 (big_unlock ? 10 : 5)
|
2017-10-29 11:19:33 +00:00
|
|
|
// land completion for advanced unlocking
|
2019-06-17 08:13:08 +00:00
|
|
|
#define U10 (big_unlock ? 25 : 10)
|
2017-10-29 11:19:33 +00:00
|
|
|
|
|
|
|
// land completion
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R10 (big_unlock ? 50 : 10)
|
2017-10-29 11:19:33 +00:00
|
|
|
// intermediate lands
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R30 (big_unlock ? 100 : 30)
|
2017-10-29 11:19:33 +00:00
|
|
|
// advanced lands
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R60 (big_unlock ? 200 : 60)
|
2017-10-29 11:19:33 +00:00
|
|
|
// advanced lands II
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R90 (big_unlock ? 300 : 90)
|
2017-10-29 11:19:33 +00:00
|
|
|
// Crossroads IV
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R200 (big_unlock ? 800 : 200)
|
2017-10-29 11:19:33 +00:00
|
|
|
// Crossroads V
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R300 (big_unlock ? 1200 : 300)
|
2017-10-29 11:19:33 +00:00
|
|
|
// kill types for Dragon Chasms
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R20 (big_unlock ? 30 : 20)
|
2017-10-29 11:19:33 +00:00
|
|
|
// kill count for Graveyard/Hive
|
2019-06-17 08:13:08 +00:00
|
|
|
#define R100 (big_unlock ? 500 : 100)
|
2017-10-29 11:19:33 +00:00
|
|
|
|
2018-06-22 12:47:24 +00:00
|
|
|
// size casted to int, to prevent warnings and actual errors caused by the unsignedness of x.size()
|
|
|
|
template<class T> int isize(const T& x) {return x.size(); }
|
2017-10-29 11:19:33 +00:00
|
|
|
|
2020-01-18 15:59:16 +00:00
|
|
|
// automatically growing vector
|
|
|
|
template<class T> struct grow_vector : public vector<T> {
|
|
|
|
T& grow(size_t index) {
|
|
|
|
if(index >= this->size()) {
|
|
|
|
this->resize(index + 1);
|
|
|
|
}
|
|
|
|
return (vector<T>::operator[]) (index);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-08-26 09:58:03 +00:00
|
|
|
// game forward declarations
|
|
|
|
|
|
|
|
namespace anticheat { extern bool tampered; }
|
|
|
|
#define HRANDMAX 0x7FFFFFFF
|
2018-04-09 16:05:23 +00:00
|
|
|
|
2017-03-23 10:53:57 +00:00
|
|
|
struct movedir {
|
2019-04-29 11:41:24 +00:00
|
|
|
int d;
|
|
|
|
// non-negative numbers denote 'rotate +d steps and act in this direction
|
|
|
|
// negative numbers have the following meanings (warning: not used consistently):
|
2017-03-23 10:53:57 +00:00
|
|
|
#define MD_WAIT (-1)
|
|
|
|
#define MD_DROP (-2)
|
|
|
|
#define MD_UNDECIDED (-3)
|
|
|
|
#define MD_USE_ORB (-4)
|
2019-04-29 11:41:24 +00:00
|
|
|
int subdir; // for normal movement (0+): turn left or right
|
2019-08-10 11:43:24 +00:00
|
|
|
struct cell *tgt; // for MD_USE_ORB: target cell
|
2017-03-23 10:53:57 +00:00
|
|
|
};
|
|
|
|
|
2016-08-26 09:58:03 +00:00
|
|
|
// shmup
|
|
|
|
|
2020-04-12 00:44:31 +00:00
|
|
|
template<class T>
|
|
|
|
class hookset {
|
|
|
|
std::map<int, std::function<T>> *map_ = nullptr;
|
|
|
|
|
|
|
|
public:
|
|
|
|
template<class U>
|
|
|
|
int add(int prio, U&& hook) {
|
|
|
|
if (map_ == nullptr) map_ = new std::map<int, std::function<T>>();
|
|
|
|
while (map_->count(prio)) {
|
|
|
|
prio++;
|
|
|
|
}
|
|
|
|
map_->emplace(prio, static_cast<U&&>(hook));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class... U>
|
|
|
|
void callhooks(U&&... args) const {
|
|
|
|
if (map_ == nullptr) return;
|
|
|
|
for (const auto& p : *map_) {
|
|
|
|
p.second(static_cast<U&&>(args)...);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class V, class... U>
|
|
|
|
V callhandlers(V zero, U&&... args) const {
|
|
|
|
if (map_ == nullptr) return zero;
|
|
|
|
for (const auto& p : *map_) {
|
|
|
|
auto z = p.second(static_cast<U&&>(args)...);
|
|
|
|
if (z != zero) return z;
|
|
|
|
}
|
|
|
|
return zero;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
using purehookset = hookset<void()>;
|
2018-07-09 17:32:34 +00:00
|
|
|
|
2018-06-17 15:51:26 +00:00
|
|
|
static const int NOHINT = -1;
|
2016-08-26 09:58:03 +00:00
|
|
|
|
2017-10-08 22:21:39 +00:00
|
|
|
typedef function<void()> reaction_t;
|
2017-12-14 11:10:40 +00:00
|
|
|
typedef function<bool()> bool_reaction_t;
|
2017-10-08 22:21:39 +00:00
|
|
|
|
2017-05-27 19:40:40 +00:00
|
|
|
#define HELPFUN(x) (help_delegate = x, "HELPFUN")
|
|
|
|
|
2019-08-10 11:43:24 +00:00
|
|
|
typedef function<int(struct cell*)> cellfunction;
|
2018-09-27 19:52:13 +00:00
|
|
|
|
2016-08-26 09:58:03 +00:00
|
|
|
// passable flags
|
|
|
|
|
|
|
|
#define SAGEMELT .1
|
2018-05-15 21:26:04 +00:00
|
|
|
#define PT(x, y) ((tactic::on || quotient == 2 || daily::on) ? (y) : inv::on ? min(2*(y),x) : (x))
|
2016-08-26 09:58:03 +00:00
|
|
|
#define ROCKSNAKELENGTH 50
|
2017-03-23 10:53:57 +00:00
|
|
|
#define WORMLENGTH 15
|
2016-08-26 09:58:03 +00:00
|
|
|
#define PRIZEMUL 7
|
|
|
|
|
|
|
|
#define INF 9999
|
2018-04-03 21:34:47 +00:00
|
|
|
#define INFD 60
|
2017-03-23 10:53:57 +00:00
|
|
|
#define PINFD 125
|
2018-01-25 22:52:57 +00:00
|
|
|
#ifndef BARLEV
|
2019-03-02 23:45:40 +00:00
|
|
|
#define BARLEV ((ISANDROID||ISIOS||ISFAKEMOBILE||getDistLimit()<7)?(getDistLimit()<4?8:9):10)
|
2018-01-25 22:52:57 +00:00
|
|
|
#endif
|
2016-08-26 09:58:03 +00:00
|
|
|
#define BUGLEV 15
|
|
|
|
// #define BARLEV 9
|
|
|
|
|
|
|
|
#define YDIST 101
|
2018-12-14 18:24:27 +00:00
|
|
|
#define MODECODES (1ll<<61)
|
2016-08-26 09:58:03 +00:00
|
|
|
|
|
|
|
#define GUNRANGE 3
|
|
|
|
|
|
|
|
// loops
|
|
|
|
|
|
|
|
#define fakecellloop(ct) for(cell *ct = (cell*)1; ct; ct=NULL)
|
|
|
|
|
2018-08-17 22:46:45 +00:00
|
|
|
#define forCellIdAll(ct, i, cf) fakecellloop(ct) for(int i=0; i<(cf)->type && (ct=(cf)->move(i),true); i++)
|
2016-08-26 09:58:03 +00:00
|
|
|
#define forCellIdCM(ct, i, cf) fakecellloop(ct) for(int i=0; i<(cf)->type && (ct=createMov((cf),i),true); i++)
|
|
|
|
#define forCellIdEx(ct, i, cf) forCellIdAll(ct,i,cf) if(ct)
|
|
|
|
|
|
|
|
#define forCellEx(ct, cf) forCellIdEx(ct,forCellEx ## __LINE__,cf)
|
|
|
|
#define forCellCM(ct, cf) forCellIdCM(ct,forCellCM ## __LINE__,cf)
|
|
|
|
#define forCellAll(ct, cf) forCellIdCM(ct,forCellAll ## __LINE__,cf)
|
|
|
|
|
|
|
|
// canAttack/moveval flags
|
|
|
|
|
2018-01-03 20:49:14 +00:00
|
|
|
#define AF_NORMAL 0 // nothing special about this attack
|
|
|
|
|
2017-09-30 09:46:41 +00:00
|
|
|
#define AF_TOUGH Flag(0) // tough attacks: Hyperbugs
|
|
|
|
#define AF_MAGIC Flag(1) // magical attacks: Flash
|
|
|
|
#define AF_STAB Flag(2) // stabbing attacks (usually ignored except Hedgehogs)
|
|
|
|
#define AF_LANCE Flag(3) // lance attacks (used by Lancers)
|
|
|
|
#define AF_ONLY_ENEMY Flag(4) // only say YES if it is an enemy
|
|
|
|
#define AF_ONLY_FRIEND Flag(5) // only say YES if it is a friend
|
|
|
|
#define AF_ONLY_FBUG Flag(6) // only say YES if it is a bug_or friend
|
|
|
|
#define AF_BACK Flag(7) // backward attacks (ignored except Viziers and Flailers)
|
|
|
|
#define AF_APPROACH Flag(8) // approach attacks (ignored except Lancers)
|
|
|
|
#define AF_IGNORE_UNARMED Flag(9) // ignore the UNARMED flag
|
|
|
|
#define AF_NOSHIELD Flag(10) // ignore the shielded status
|
|
|
|
#define AF_GETPLAYER Flag(11) // check for player (replace m2 with moPlayer for player position)
|
|
|
|
#define AF_GUN Flag(12) // revolver attack
|
|
|
|
#define AF_FAST Flag(13) // fast attack
|
|
|
|
#define AF_EAT Flag(17) // eating attacks from Worm-likes
|
|
|
|
|
|
|
|
#define MF_NOATTACKS Flag(14) // don't do any attacks
|
|
|
|
#define MF_PATHDIST Flag(15) // consider pathdist for moveval
|
|
|
|
#define MF_ONLYEAGLE Flag(16) // do this only for Eagles
|
|
|
|
#define MF_MOUNT Flag(18) // don't do
|
|
|
|
#define MF_NOFRIEND Flag(19) // don't do it for friends
|
|
|
|
|
|
|
|
#define AF_SWORD Flag(20) // big sword
|
|
|
|
#define AF_SWORD_INTO Flag(21) // moving into big sword
|
|
|
|
#define AF_MSG Flag(22) // produce a message
|
2018-01-03 20:49:14 +00:00
|
|
|
#define AF_MUSTKILL Flag(23) // when TRUE, stunning attacks are not accepted by canAttack
|
2017-09-30 09:46:41 +00:00
|
|
|
#define AF_NEXTTURN Flag(24) // next turn -- don't count shield at power 1
|
|
|
|
#define AF_FALL Flag(25) // death by falling
|
|
|
|
#define MF_STUNNED Flag(26) // edgeunstable: ignore ladders (as stunned monsters do)
|
|
|
|
#define MF_IVY Flag(27) // edgeunstable: ignore ivy (ivy cannot climb ivy)
|
|
|
|
#define AF_HORNS Flag(28) // spear attack (always has APPROACH too)
|
|
|
|
#define AF_BULL Flag(29) // bull attack
|
|
|
|
#define AF_SIDE Flag(30) // side attack
|
2018-01-02 10:15:42 +00:00
|
|
|
#define AF_CRUSH Flag(31) // Crusher's delayed attack
|
2020-02-26 01:49:35 +00:00
|
|
|
#define AF_PLAGUE Flag(32) // Orb of Plague (do not check adjacency)
|
2020-03-02 19:35:15 +00:00
|
|
|
#define AF_PSI Flag(33) // Orb of the Mind
|
2017-03-23 10:53:57 +00:00
|
|
|
|
2017-07-22 23:33:27 +00:00
|
|
|
#if CAP_SDL
|
2016-08-26 09:58:03 +00:00
|
|
|
|
2017-07-22 23:33:27 +00:00
|
|
|
#if CAP_PNG
|
2016-08-26 09:58:03 +00:00
|
|
|
#include "savepng.h"
|
|
|
|
#define IMAGEEXT ".png"
|
|
|
|
void IMAGESAVE(SDL_Surface *s, const char *fname);
|
2017-07-22 23:33:27 +00:00
|
|
|
#else
|
|
|
|
#define IMAGEEXT ".bmp"
|
|
|
|
#define IMAGESAVE SDL_SaveBMP
|
|
|
|
#endif
|
|
|
|
|
2016-08-26 09:58:03 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
template<class T> struct dynamicval {
|
|
|
|
T& where;
|
|
|
|
T backup;
|
|
|
|
dynamicval(T& wh, T val) : where(wh) { backup = wh; wh = val; }
|
2017-07-04 13:38:33 +00:00
|
|
|
dynamicval(T& wh) : where(wh) { backup = wh; }
|
2016-08-26 09:58:03 +00:00
|
|
|
~dynamicval() { where = backup; }
|
|
|
|
};
|
|
|
|
|
2019-08-09 21:48:28 +00:00
|
|
|
static const int MAXPLAYER = 7;
|
|
|
|
|
2018-03-02 12:05:31 +00:00
|
|
|
#define DEFAULTCONTROL (multi::players == 1 && !shmup::on && !multi::alwaysuse && !(rug::rugged && rug::renderonce))
|
2017-05-31 16:33:50 +00:00
|
|
|
#define DEFAULTNOR(sym) (DEFAULTCONTROL || multi::notremapped(sym))
|
2017-03-23 10:53:57 +00:00
|
|
|
|
2017-07-22 23:33:27 +00:00
|
|
|
#define CAP_MENUSCALING (ISPANDORA || ISMOBILE)
|
2017-03-23 10:53:57 +00:00
|
|
|
|
2017-07-22 23:33:27 +00:00
|
|
|
#if CAP_MENUSCALING
|
2018-07-22 10:54:05 +00:00
|
|
|
#define displayfrZ dialog::zoom::displayfr
|
|
|
|
#define displayfrZH dialog::zoom::displayfr_highlight
|
2017-03-23 10:53:57 +00:00
|
|
|
#else
|
|
|
|
#define displayfrZ displayfr
|
2018-07-22 13:54:44 +00:00
|
|
|
#define displayfrZH dialog::zoom::displayfr_highlight
|
2017-03-23 10:53:57 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// just in case if I change my mind about when Orbs lose their power
|
|
|
|
#define ORBBASE 0
|
|
|
|
|
|
|
|
#define mmscale(V, x) (mmspatial ? (ivoryz ? mzscale(V,x) : mscale(V, x)) : (V))
|
|
|
|
|
|
|
|
#define SHADOW_WALL 0x60
|
|
|
|
#define SHADOW_SL 0x18
|
|
|
|
#define SHADOW_MON 0x30
|
|
|
|
|
|
|
|
// ranks:
|
2018-08-28 12:27:23 +00:00
|
|
|
enum class PPR {
|
2019-05-28 23:06:01 +00:00
|
|
|
ZERO, EUCLIDEAN_SKY, OUTCIRCLE, MOVESTAR,
|
2018-08-28 12:27:23 +00:00
|
|
|
MINUSINF,
|
|
|
|
BELOWBOTTOMm,
|
|
|
|
BELOWBOTTOM,
|
|
|
|
BELOWBOTTOMp,
|
|
|
|
BELOWBOTTOM_FALLANIM,
|
|
|
|
LAKEBOTTOM, HELLSPIKE,
|
|
|
|
INLAKEWALLm, INLAKEWALL, INLAKEWALLp,
|
|
|
|
INLAKEWALL_FALLANIM,
|
2020-02-26 00:15:30 +00:00
|
|
|
BSHALLOW, SHALLOW, ASHALLOW,
|
2018-08-28 12:27:23 +00:00
|
|
|
SUBLAKELEV, LAKELEV, BOATLEV, BOATLEV2, BOATLEV3,
|
|
|
|
LAKEWALLm, LAKEWALL, LAKEWALLp,
|
|
|
|
LAKEWALL_FALLANIM,
|
|
|
|
FLOOR_TOWER,
|
|
|
|
FLOOR,
|
|
|
|
FLOOR_DRAGON,
|
|
|
|
FLOORa, FLOORb, FLOORc, FLOORd,
|
|
|
|
LIZEYE,
|
|
|
|
BFLOOR,
|
|
|
|
GFLOORa, GFLOORb, GFLOORc,
|
|
|
|
WALLSHADOW,
|
|
|
|
STRUCT0, STRUCT1, STRUCT2, STRUCT3,
|
|
|
|
THORNS, WALL,
|
|
|
|
REDWALLm, REDWALLs, REDWALLp, REDWALL,
|
|
|
|
REDWALLm2, REDWALLs2, REDWALLp2, REDWALLt2,
|
|
|
|
REDWALLm3, REDWALLs3, REDWALLp3, REDWALLt3,
|
|
|
|
HEPTAMARK,
|
|
|
|
ITEM_BELOW,
|
|
|
|
ITEM, ITEMa, ITEMb,
|
|
|
|
BIGSTATUE,
|
|
|
|
|
|
|
|
WALL3m, WALL3s, WALL3p, WALL3, WALL3A,
|
|
|
|
|
|
|
|
// WALL3m, WALL3s, WALL3p, WALL3, WALL3A,
|
|
|
|
HIDDEN, GIANTSHADOW,
|
|
|
|
TENTACLE0, TENTACLE1,
|
|
|
|
ONTENTACLE, ONTENTACLE_EYES, ONTENTACLE_EYES2,
|
|
|
|
MONSTER_SHADOW,
|
|
|
|
MONSTER_FOOT, MONSTER_LEG, MONSTER_GROIN,
|
|
|
|
MONSTER_SUBWPN, MONSTER_WPN,
|
|
|
|
MONSTER_BODY, MONSTER_ARMOR0, MONSTER_ARMOR1,
|
|
|
|
MONSTER_CLOAK, MONSTER_NECK,
|
|
|
|
MONSTER_HEAD, MONSTER_FACE, MONSTER_EYE0, MONSTER_EYE1,
|
|
|
|
MONSTER_HAIR, MONSTER_HAT0, MONSTER_HAT1,
|
|
|
|
MONSTER_HOODCLOAK1, MONSTER_HOODCLOAK2,
|
|
|
|
STUNSTARS,
|
|
|
|
CARRIED, CARRIEDa, CARRIEDb,
|
2019-05-20 11:40:56 +00:00
|
|
|
PARTICLE, SWORDMARK, MAGICSWORD, MISSILE, SKY,
|
2018-08-28 12:27:23 +00:00
|
|
|
MINEMARK, ARROW,
|
|
|
|
MOBILE_ARROW,
|
2019-02-27 00:16:07 +00:00
|
|
|
LINE,
|
2019-03-04 17:00:51 +00:00
|
|
|
// in depth tested models transparent surfaces need to be depth sorted by HyperRogue
|
2019-05-13 11:18:55 +00:00
|
|
|
// and set to PPR::TRANSPARENT_* to draw them after all the opaque ones
|
|
|
|
TRANSPARENT_LAKE, TRANSPARENT_SHADOW, TRANSPARENT_WALL,
|
2019-02-27 00:16:07 +00:00
|
|
|
// no depth testing for SUPERLINE and above
|
|
|
|
SUPERLINE, TEXT, CIRCLE,
|
2018-08-28 12:27:23 +00:00
|
|
|
MAX,
|
|
|
|
DEFAULT = -1
|
2017-03-23 10:53:57 +00:00
|
|
|
};
|
2018-08-28 11:45:11 +00:00
|
|
|
|
2018-09-01 11:50:56 +00:00
|
|
|
inline PPR operator + (PPR x, int y) { return PPR(int(x) + y); }
|
|
|
|
inline PPR operator - (PPR x, int y) { return PPR(int(x) - y); }
|
|
|
|
inline int operator - (PPR x, PPR y) { return int(x) - int(y); }
|
2018-08-28 12:27:23 +00:00
|
|
|
|
2017-03-23 10:53:57 +00:00
|
|
|
#define OUTLINE_NONE 0x000000FF
|
|
|
|
#define OUTLINE_FRIEND 0x00FF00FF
|
|
|
|
#define OUTLINE_ENEMY 0xFF0000FF
|
|
|
|
#define OUTLINE_TREASURE 0xFFFF00FF
|
|
|
|
#define OUTLINE_ORB 0xFF8000FF
|
|
|
|
#define OUTLINE_OTHER 0xFFFFFFFF
|
|
|
|
#define OUTLINE_DEAD 0x800000FF
|
|
|
|
#define OUTLINE_TRANS 0
|
2017-07-04 13:38:33 +00:00
|
|
|
#define OUTLINE_DEFAULT ((bordcolor << 8) + 0xFF)
|
|
|
|
#define OUTLINE_FORE ((forecolor << 8) + 0xFF)
|
|
|
|
#define OUTLINE_BACK ((backcolor << 8) + 0xFF)
|
2017-03-23 10:53:57 +00:00
|
|
|
|
2019-08-10 00:16:48 +00:00
|
|
|
enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce, roMultiCheck, roMultiGo };
|
2017-03-23 10:53:57 +00:00
|
|
|
|
|
|
|
#define MODELCOUNT ((int) mdGUARD)
|
|
|
|
|
2020-04-16 22:53:58 +00:00
|
|
|
#define pconf vid.projection_config
|
|
|
|
#define vpconf (rug::rugged ? vid.rug_config : vid.projection_config)
|
|
|
|
#define pmodel (pconf.model)
|
2017-11-13 10:26:21 +00:00
|
|
|
|
2019-03-09 02:32:24 +00:00
|
|
|
color_t darkena(color_t c, int lev, int a);
|
2017-03-23 10:53:57 +00:00
|
|
|
|
2019-08-02 20:09:19 +00:00
|
|
|
static const int DISTANCE_UNKNOWN = 127;
|
2017-06-18 16:51:46 +00:00
|
|
|
|
2020-04-12 00:44:31 +00:00
|
|
|
template<class T, class U> int addHook(hookset<T>& m, int prio, U&& hook) {
|
|
|
|
return m.add(prio, static_cast<U&&>(hook));
|
2017-07-10 18:47:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-12 00:44:31 +00:00
|
|
|
template<class T, class... U> void callhooks(const hookset<T>& h, U&&... args) {
|
|
|
|
return h.callhooks(static_cast<U&&>(args)...);
|
2017-07-10 18:47:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-12 00:44:31 +00:00
|
|
|
template<class T, class V, class... U> V callhandlers(V zero, const hookset<T>& h, U&&... args) {
|
|
|
|
return h.callhandlers(zero, static_cast<U&&>(args)...);
|
2017-07-10 18:47:38 +00:00
|
|
|
}
|
|
|
|
|
2019-08-10 00:16:48 +00:00
|
|
|
string XLAT(string);
|
2017-10-29 11:46:57 +00:00
|
|
|
|
2017-07-10 18:47:38 +00:00
|
|
|
#define GLERR(call) glError(call, __FILE__, __LINE__)
|
|
|
|
|
2018-11-08 15:21:33 +00:00
|
|
|
struct colortable: vector<color_t> {
|
|
|
|
color_t& operator [] (int i) { i %= size(); if(i<0) i += size(); return ((vector<color_t>&)(*this)) [i]; }
|
|
|
|
const color_t& operator [] (int i) const { i %= size(); if(i<0) i += size(); return ((vector<color_t>&)(*this)) [i]; }
|
|
|
|
colortable(std::initializer_list<color_t> v) : vector(v) {}
|
|
|
|
colortable() : vector({0}) {}
|
|
|
|
};
|
|
|
|
|
2017-07-10 18:47:38 +00:00
|
|
|
#define SHMUPTITLE "shoot'em up mode"
|
|
|
|
|
2018-12-06 10:43:10 +00:00
|
|
|
// check for a plain number key
|
2018-12-06 11:31:51 +00:00
|
|
|
#define NUMBERKEY (interpret_as_direction(sym, uni) ? 0 : uni)
|
|
|
|
#define DKEY (get_direction_key(sym, uni))
|
|
|
|
#define DIRECTIONKEY (interpret_as_direction(sym, uni) ? uni : 0)
|
|
|
|
|
2017-07-12 16:03:53 +00:00
|
|
|
namespace scores { void load(); }
|
|
|
|
|
2020-05-03 18:56:41 +00:00
|
|
|
#if ISMOBILE
|
2017-07-12 16:03:53 +00:00
|
|
|
namespace leader { void showMenu(); void handleKey(int sym, int uni); }
|
|
|
|
#endif
|
|
|
|
|
2017-07-22 23:33:27 +00:00
|
|
|
int textwidth(int siz, const string &str);
|
|
|
|
#if CAP_GL
|
|
|
|
int gl_width(int size, const char *s);
|
|
|
|
#endif
|
|
|
|
|
2020-05-03 18:56:41 +00:00
|
|
|
#if ISMOBILE
|
2017-07-22 23:33:27 +00:00
|
|
|
extern int andmode;
|
2018-07-22 13:54:44 +00:00
|
|
|
extern bool longclick;
|
|
|
|
extern bool useRangedOrb;
|
2017-07-22 23:33:27 +00:00
|
|
|
#endif
|
2017-08-06 12:50:16 +00:00
|
|
|
|
2017-10-29 11:46:57 +00:00
|
|
|
#ifndef GL
|
|
|
|
typedef float GLfloat;
|
|
|
|
#endif
|
|
|
|
|
2019-02-22 19:58:40 +00:00
|
|
|
typedef array<GLfloat, 2> glvec2;
|
2018-02-11 18:08:17 +00:00
|
|
|
typedef array<GLfloat, 3> glvec3;
|
|
|
|
typedef array<GLfloat, 4> glvec4;
|
2019-02-24 18:40:01 +00:00
|
|
|
|
2019-02-27 22:30:26 +00:00
|
|
|
#if MAXMDIM == 4
|
2019-02-24 18:40:01 +00:00
|
|
|
#define SHDIM 4
|
2019-02-22 19:58:40 +00:00
|
|
|
typedef glvec4 glvertex;
|
2019-02-24 18:40:01 +00:00
|
|
|
#else
|
|
|
|
#define SHDIM 3
|
|
|
|
typedef glvec3 glvertex;
|
|
|
|
#endif
|
2018-02-11 18:08:17 +00:00
|
|
|
|
2017-10-29 13:19:51 +00:00
|
|
|
extern int emeraldtable[100][7];
|
|
|
|
|
2018-03-24 11:59:01 +00:00
|
|
|
// extern cell *cwpeek(cellwalker cw, int dir);
|
2017-10-29 13:19:51 +00:00
|
|
|
|
|
|
|
#define HAUNTED_RADIUS getDistLimit()
|
|
|
|
#define UNKNOWN 65535
|
|
|
|
|
|
|
|
#define GRAIL_FOUND 0x4000
|
|
|
|
#define GRAIL_RADIUS_MASK 0x3FFF
|
|
|
|
|
2019-08-09 21:24:33 +00:00
|
|
|
extern vector<cell*> dcal;
|
|
|
|
|
2017-11-03 18:20:54 +00:00
|
|
|
// z to close to this limit => do not draw
|
|
|
|
|
|
|
|
#define BEHIND_LIMIT 1e-6
|
2017-11-03 18:31:42 +00:00
|
|
|
|
2018-01-26 00:45:49 +00:00
|
|
|
template<class T, class U> void eliminate_if(vector<T>& data, U pred) {
|
2018-06-22 12:47:24 +00:00
|
|
|
for(int i=0; i<isize(data); i++)
|
2018-01-26 00:45:49 +00:00
|
|
|
if(pred(data[i]))
|
|
|
|
data[i] = data.back(), data.pop_back(), i--;
|
|
|
|
}
|
|
|
|
|
2019-03-01 17:53:32 +00:00
|
|
|
template<class T> array<T, 4> make_array(T a, T b, T c, T d) { array<T,4> x; x[0] = a; x[1] = b; x[2] = c; x[3] = d; return x; }
|
2018-02-11 18:08:17 +00:00
|
|
|
template<class T> array<T, 3> make_array(T a, T b, T c) { array<T,3> x; x[0] = a; x[1] = b; x[2] = c; return x; }
|
|
|
|
template<class T> array<T, 2> make_array(T a, T b) { array<T,2> x; x[0] = a; x[1] = b; return x; }
|
|
|
|
|
2018-04-30 22:21:18 +00:00
|
|
|
namespace daily {
|
|
|
|
extern bool on;
|
|
|
|
extern int daily_id;
|
|
|
|
void setup();
|
|
|
|
void split();
|
|
|
|
void gifts();
|
2018-05-15 21:26:04 +00:00
|
|
|
void turnoff();
|
|
|
|
void showMenu();
|
|
|
|
int find_daily_lbid(int id);
|
2018-05-20 13:16:21 +00:00
|
|
|
bool prevent_spawn_treasure_on(cell *c);
|
2018-05-26 23:06:12 +00:00
|
|
|
void handleQuit(int sev);
|
|
|
|
void uploadscore(bool really_final);
|
2018-04-30 22:21:18 +00:00
|
|
|
}
|
|
|
|
|
2019-05-26 16:04:02 +00:00
|
|
|
#define RING(i) for(double i=0; i<=cgi.S84+1e-6; i+=SD3 * pow(.5, vid.linequality))
|
|
|
|
#define REVRING(i) for(double i=cgi.S84; i>=-1e-6; i-=SD3 * pow(.5, vid.linequality))
|
|
|
|
#define PRING(i) for(double i=0; i<=cgi.S84+1e-6; i+= pow(.5, vid.linequality))
|
|
|
|
#define REVPRING(i) for(double i=cgi.S84; i>=-1e-6; i-=pow(.5, vid.linequality))
|
2018-08-09 17:28:53 +00:00
|
|
|
|
2018-12-21 13:43:38 +00:00
|
|
|
#define ONEMPTY if(d == 7 && passable(c, NULL, 0) && !safety && !reptilecheat)
|
|
|
|
|
2019-05-09 15:20:31 +00:00
|
|
|
template <class T> void texture_order(const T& f) {
|
|
|
|
const int STEP = vid.texture_step;
|
|
|
|
const ld STEP2 = STEP;
|
|
|
|
for(int y=0; y<STEP; y++)
|
|
|
|
for(int x=0; x<STEP; x++) {
|
|
|
|
ld x0 = x / STEP2;
|
|
|
|
ld y0 = y / STEP2;
|
|
|
|
ld b = 1 / STEP2;
|
|
|
|
|
|
|
|
if(x+y < STEP) {
|
|
|
|
f(x0, y0); f(x0+b, y0); f(x0, y0+b);
|
|
|
|
}
|
|
|
|
if(x+y <= STEP && x && y) {
|
|
|
|
f(x0, y0); f(x0-b, y0); f(x0, y0-b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-11 17:46:34 +00:00
|
|
|
|
2020-03-31 18:06:18 +00:00
|
|
|
/** find the smallest value of x in range [dmin..dmax] such that f(x) returns true */
|
|
|
|
|
|
|
|
template<class T> ld binsearch(ld dmin, ld dmax, const T& f) {
|
|
|
|
for(int i=0; i<200; i++) {
|
|
|
|
ld d = (dmin + dmax) / 2;
|
|
|
|
if(dmin == d || dmax == d) break;
|
|
|
|
if(f(d)) dmax = d;
|
|
|
|
else dmin = d;
|
|
|
|
}
|
|
|
|
return dmin;
|
|
|
|
}
|
|
|
|
|
2019-06-24 10:57:00 +00:00
|
|
|
static const color_t NOCOLOR = 0;
|
|
|
|
|
2019-08-09 19:00:52 +00:00
|
|
|
static const int max_vec = (1<<14);
|
|
|
|
extern bool needConfirmationEvenIfSaved();
|
2019-07-31 11:21:41 +00:00
|
|
|
|
2019-12-23 21:21:04 +00:00
|
|
|
typedef unsigned long long flagtype;
|
|
|
|
#define Flag(i) (flagtype(1ull<<i))
|
|
|
|
static inline void set_flag(flagtype& f, flagtype which, bool b) {
|
|
|
|
if(b) f |= which;
|
|
|
|
else f &= ~which;
|
|
|
|
}
|
|
|
|
|
2019-08-09 13:07:43 +00:00
|
|
|
}
|
|
|
|
|
2020-02-29 16:58:59 +00:00
|
|
|
/** this macro is used to delay performing the action in case if everything is rolled back */
|
|
|
|
#define LATE(x) \
|
|
|
|
if(changes.on) { changes.at_commit([=] { x; }); return; }
|
|
|
|
|
2019-12-14 10:53:55 +00:00
|
|
|
// assert macro
|
|
|
|
#ifdef NDEBUG
|
|
|
|
#define hassert(condition) if(!condition) __builtin_unreachable()
|
|
|
|
#else
|
|
|
|
#define hassert(condition) if(condition) println(hlog, __FILE__, ":", __LINE__, ":", __func__, ": assertion failed: ", condition)
|
|
|
|
#endif
|
|
|
|
|
2019-08-09 19:00:52 +00:00
|
|
|
#define IS(z) = z
|
2019-08-09 13:07:43 +00:00
|
|
|
#include "autohdr.h"
|
2019-08-09 19:00:52 +00:00
|
|
|
#undef IS
|
|
|
|
#define IS(z)
|
2019-08-09 23:15:41 +00:00
|
|
|
#define EX
|
2019-08-09 19:00:52 +00:00
|
|
|
|
2019-09-05 07:07:04 +00:00
|
|
|
#endif
|