2017-10-29 13:19:51 +00:00
// This is the main header file of HyperRogue. Mostly everything is dumped here.
// It is quite chaotic.
2018-06-10 23:58:31 +00:00
// version numbers
2019-04-29 11:41:41 +00:00
# define VER "11.0r"
# define VERNUM 11018
# define VERNUM_HEX 0xA612
2018-06-10 23:58:31 +00:00
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
2018-06-10 23:58:31 +00:00
namespace hr {
2019-02-17 17:50:56 +00:00
struct always_false {
operator bool ( ) const { return false ; } ;
void operator = ( bool b ) const { } ;
} ;
2018-07-14 06:45:14 +00:00
template < class T >
void ignore ( T & & ) {
// placate GCC's overzealous -Wunused-result
}
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
# define ALPHA (M_PI*2 / S7)
# define S7 ginf[geometry].sides
# define S3 ginf[geometry].vertex
2018-08-30 14:08:05 +00:00
# define hyperbolic_37 (S7 == 7 && S3 == 3 && !binarytiling && !archimedean)
# define hyperbolic_not37 ((S7 > 7 || S3 > 3 || binarytiling || archimedean) && hyperbolic)
2018-08-28 15:17:34 +00:00
# define weirdhyperbolic ((S7 > 7 || S3 > 3 || !STDVAR || binarytiling || archimedean) && hyperbolic)
# define stdhyperbolic (S7 == 7 && S3 == 3 && STDVAR && !binarytiling && !archimedean)
2018-08-09 17:28:53 +00:00
2019-03-12 01:40:15 +00:00
# define binarytiling (ginf[geometry].flags & qBINARY)
2018-08-19 21:06:32 +00:00
# define archimedean (geometry == gArchimedean)
2019-04-29 09:17:06 +00:00
// these geometries do not feature alternate structures for horocycles
2019-03-09 00:00:46 +00:00
# define eubinary (euclid || binarytiling || geometry == gCrystal)
2018-06-10 23:58:31 +00:00
# define cgclass (ginf[geometry].cclass)
# define euclid (cgclass == gcEuclid)
# define sphere (cgclass == gcSphere)
# define hyperbolic (cgclass == gcHyperbolic)
2018-11-30 14:26:50 +00:00
# define nonorientable (ginf[geometry].flags & qNONORIENTABLE)
2019-02-25 17:13:09 +00:00
# define elliptic (ginf[geometry].flags & qELLIPTIC)
2018-11-30 14:26:50 +00:00
# define quotient (ginf[geometry].flags & qANYQ)
# define euwrap (quotient && euclid)
# define fulltorus (bounded && euclid)
# define smallbounded (ginf[geometry].flags & qSMALL)
# define bounded (ginf[geometry].flags & 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)
// These geometries are generated without the heptagon structure.
// 'master' holds the coordinates
2018-08-18 15:35:39 +00:00
# define masterless among(geometry, gEuclid, gEuclidSquare, gTorus)
2019-04-29 09:17:06 +00:00
2018-08-19 21:06:32 +00:00
# define sphere_narcm (sphere && !archimedean)
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-08-18 15:35:39 +00:00
# define euclid4 (masterless && a4)
# define euclid6 (masterless && !a4)
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
2018-08-29 19:19:52 +00:00
# define CHANGED_VARIATION (variation != ginf[geometry].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
2018-08-30 14:05:24 +00:00
# define VALENCE (BITRUNCATED ? 3 : archimedean ? 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
2019-01-03 00:59:12 +00:00
# define NUMLEADER 82
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 ;
2017-12-01 23:31:36 +00:00
# define DEBMEM(x) // { x fflush(stdout); }
2018-01-26 00:45:49 +00:00
# define DEBSM(x)
2019-02-27 22:30:26 +00:00
# if MAXMDIM == 3
2019-02-24 18:40:01 +00:00
# define DIM 2
# else
2019-03-01 17:53:20 +00:00
# define DIM ((geometry >= gBinary3) ? 3 : 2)
2019-02-24 18:40:01 +00:00
# endif
2019-02-17 17:47:19 +00:00
# define MDIM (DIM+1)
2019-02-25 16:21:53 +00:00
extern array < ld , gGUARD > sightranges ;
2019-02-27 22:30:26 +00:00
struct hyperpoint : array < ld , MAXMDIM > {
2018-05-20 13:30:43 +00:00
hyperpoint ( ) { }
2019-02-24 18:40:01 +00:00
2019-02-22 19:58:40 +00:00
hyperpoint ( ld x , ld y , ld z , ld w ) {
( * this ) [ 0 ] = x ; ( * this ) [ 1 ] = y ; ( * this ) [ 2 ] = z ;
2019-02-27 22:30:26 +00:00
if ( MAXMDIM = = 4 ) ( * this ) [ 3 ] = w ;
2019-02-22 19:58:40 +00:00
}
2017-10-29 11:19:33 +00:00
} ;
struct transmatrix {
2019-02-27 22:30:26 +00:00
ld tab [ MAXMDIM ] [ MAXMDIM ] ;
2017-10-29 11:19:33 +00:00
ld * operator [ ] ( int i ) { return tab [ i ] ; }
const ld * operator [ ] ( int i ) const { return tab [ i ] ; }
} ;
2017-12-01 23:31:36 +00:00
inline hyperpoint operator * ( const transmatrix & T , const hyperpoint & H ) {
hyperpoint z ;
2019-02-17 17:47:19 +00:00
for ( int i = 0 ; i < MDIM ; i + + ) {
2017-12-01 23:31:36 +00:00
z [ i ] = 0 ;
2019-02-17 17:47:19 +00:00
for ( int j = 0 ; j < MDIM ; j + + ) z [ i ] + = T [ i ] [ j ] * H [ j ] ;
2017-12-01 23:31:36 +00:00
}
return z ;
}
inline transmatrix operator * ( const transmatrix & T , const transmatrix & U ) {
transmatrix R ;
2019-02-22 19:58:40 +00:00
for ( int i = 0 ; i < MDIM ; i + + ) for ( int j = 0 ; j < MDIM ; j + + ) {
R [ i ] [ j ] = 0 ;
for ( int k = 0 ; k < MDIM ; k + + )
R [ i ] [ j ] + = T [ i ] [ k ] * U [ k ] [ j ] ;
}
2017-12-01 23:31:36 +00:00
return R ;
}
2019-02-17 17:47:19 +00:00
constexpr transmatrix diag ( ld a , ld b , ld c , ld d ) {
2019-02-27 22:30:26 +00:00
# if MAXMDIM==3
2019-02-17 17:47:19 +00:00
return transmatrix { { { a , 0 , 0 } , { 0 , b , 0 } , { 0 , 0 , c } } } ;
# else
return transmatrix { { { a , 0 , 0 , 0 } , { 0 , b , 0 , 0 } , { 0 , 0 , c , 0 } , { 0 , 0 , 0 , d } } } ;
# endif
}
2019-03-30 16:51:37 +00:00
const static hyperpoint Hypc = hyperpoint ( 0 , 0 , 0 , 0 ) ;
2019-02-17 17:47:19 +00:00
2018-09-10 15:26:27 +00:00
// identity matrix
2019-02-17 17:47:19 +00:00
const static transmatrix Id = diag ( 1 , 1 , 1 , 1 ) ;
2018-09-10 15:26:27 +00:00
2019-02-22 19:58:40 +00:00
// zero matrix
const static transmatrix Zero = diag ( 0 , 0 , 0 , 0 ) ;
2018-09-10 15:26:27 +00:00
// mirror image
2019-02-17 17:47:19 +00:00
const static transmatrix Mirror = diag ( 1 , - 1 , 1 , 1 ) ;
2019-04-16 01:22:52 +00:00
const static transmatrix MirrorY = diag ( 1 , - 1 , 1 , 1 ) ;
2018-09-10 15:26:27 +00:00
// mirror image
2019-02-17 17:47:19 +00:00
const static transmatrix MirrorX = diag ( - 1 , 1 , 1 , 1 ) ;
2018-09-10 15:26:27 +00:00
// mirror image
2019-02-17 17:47:19 +00:00
const static transmatrix MirrorZ = diag ( 1 , 1 , - 1 , 1 ) ;
2018-09-10 15:26:27 +00:00
// rotate by PI
2019-02-17 17:47:19 +00:00
const static transmatrix pispin = diag ( - 1 , - 1 , 1 , 1 ) ;
2018-09-10 15:26:27 +00:00
// central symmetry
2019-02-17 17:47:19 +00:00
const static transmatrix centralsym = diag ( - 1 , - 1 , - 1 , - 1 ) ;
2018-09-10 15:26:27 +00:00
2019-02-24 18:40:01 +00:00
inline hyperpoint hpxyz ( ld x , ld y , ld z ) { return DIM = = 2 ? hyperpoint ( x , y , z , 0 ) : hyperpoint ( x , y , 0 , z ) ; }
inline hyperpoint hpxyz3 ( ld x , ld y , ld z , ld w ) { return DIM = = 2 ? hyperpoint ( x , y , w , 0 ) : hyperpoint ( x , y , z , w ) ; }
2019-02-22 19:58:40 +00:00
inline hyperpoint point3 ( ld x , ld y , ld z ) { return hyperpoint ( x , y , z , 0 ) ; }
inline hyperpoint point2 ( ld x , ld y ) { return hyperpoint ( x , y , 0 , 0 ) ; }
2019-02-17 17:47:19 +00:00
2018-03-24 11:59:01 +00:00
namespace hyperpoint_vec {
inline hyperpoint & operator * = ( hyperpoint & h , ld d ) {
2019-02-17 17:47:19 +00:00
for ( int i = 0 ; i < MDIM ; i + + ) h [ i ] * = d ;
2018-03-24 11:59:01 +00:00
return h ;
}
inline hyperpoint & operator / = ( hyperpoint & h , ld d ) {
2019-02-17 17:47:19 +00:00
for ( int i = 0 ; i < MDIM ; i + + ) h [ i ] / = d ;
2018-03-24 11:59:01 +00:00
return h ;
}
inline hyperpoint operator + = ( hyperpoint & h , hyperpoint h2 ) {
2019-02-17 17:47:19 +00:00
for ( int i = 0 ; i < MDIM ; i + + ) h [ i ] + = h2 [ i ] ;
2018-03-24 11:59:01 +00:00
return h ;
}
inline hyperpoint operator - = ( hyperpoint & h , hyperpoint h2 ) {
2019-02-17 17:47:19 +00:00
for ( int i = 0 ; i < MDIM ; i + + ) h [ i ] - = h2 [ i ] ;
2018-03-24 11:59:01 +00:00
return h ;
}
inline hyperpoint operator * ( ld d , hyperpoint h ) { return h * = d ; }
inline hyperpoint operator * ( hyperpoint h , ld d ) { return h * = d ; }
inline hyperpoint operator / ( hyperpoint h , ld d ) { return h / = d ; }
inline hyperpoint operator + ( hyperpoint h , hyperpoint h2 ) { return h + = h2 ; }
inline hyperpoint operator - ( hyperpoint h , hyperpoint h2 ) { return h - = h2 ; }
// cross product
inline hyperpoint operator ^ ( hyperpoint h1 , hyperpoint h2 ) {
return hpxyz (
h1 [ 1 ] * h2 [ 2 ] - h1 [ 2 ] * h2 [ 1 ] ,
h1 [ 2 ] * h2 [ 0 ] - h1 [ 0 ] * h2 [ 2 ] ,
h1 [ 0 ] * h2 [ 1 ] - h1 [ 1 ] * h2 [ 0 ]
) ;
}
2018-07-16 18:06:21 +00:00
// inner product (in R^3)
2018-03-24 11:59:01 +00:00
inline ld operator | ( hyperpoint h1 , hyperpoint h2 ) {
2019-02-22 19:58:40 +00:00
ld sum = 0 ;
for ( int i = 0 ; i < MDIM ; i + + ) sum + = h1 [ i ] * h2 [ i ] ;
return sum ;
2018-03-24 11:59:01 +00:00
}
}
2017-12-14 01:50:52 +00:00
extern int cellcount , heptacount ;
2017-10-29 11:19:33 +00:00
// cell information for the game
struct gcell {
2018-02-10 17:21:46 +00:00
# if CAP_BITFIELD
2017-10-29 11:19:33 +00:00
// main fields
eLand land : 8 ;
eWall wall : 8 ;
eMonster monst : 8 ;
eItem item : 8 ;
// if this is a barrier, what lands on are on the sides?
eLand barleft : 8 , barright : 8 ;
unsigned ligon : 1 ; // is it sparkling with lightning?
2018-04-03 21:34:47 +00:00
signed
mpdist : 7 ,
pathdist : 8 , // player distance wrt usual movement
cpdist : 8 ; // current/minimum player distance
2017-10-29 11:19:33 +00:00
unsigned
2019-04-29 01:36:28 +00:00
mondir : 8 , // monster direction, for multi-tile monsters and graphics
bardir : 8 , // barrier direction
stuntime : 8 , // stun time left (for Palace Guards and Skeletons)
hitpoints : 8 ; // hitpoints left (for Palace Guards, also reused as cpid for mirrors)
2017-10-29 11:19:33 +00:00
unsigned landflags : 8 ; // extra flags for land
2018-02-10 17:21:46 +00:00
# else
eLand land ;
eWall wall ;
eMonster monst ;
eItem item ;
eLand barleft , barright ;
bool ligon ;
2018-09-02 13:08:51 +00:00
signed char pathdist , cpdist , mpdist ;
2018-02-10 17:21:46 +00:00
unsigned char mondir , bardir , stuntime , hitpoints ;
unsigned char landflags ;
# endif
2017-10-29 11:19:33 +00:00
// 'landparam' is used for:
// heat in Icy/Cocytus;
// heat in Dry (0..10);
// CR2 structure;
// hive Weird Rock color / pheromones;
// Ocean/coast depth;
// Bomberbird Egg hatch time / mine marking;
// number of Ancient Jewelry;
// improved tracking in Trollheim
union {
int32_t landpar ;
2018-09-04 17:53:42 +00:00
unsigned int landpar_color ;
2017-10-29 11:19:33 +00:00
float heat ;
char bytes [ 4 ] ;
struct fieldinfo {
uint16_t fieldval ;
unsigned rval : 4 ;
unsigned flowerdist : 4 ;
unsigned walldist : 4 ;
unsigned walldist2 : 4 ;
} fi ;
} LHU ;
2017-12-14 01:50:52 +00:00
2018-01-13 18:23:02 +00:00
# ifdef CELLID
int cellid ;
# endif
gcell ( ) { cellcount + + ;
# ifdef CELLID
cellid = cellcount ;
# endif
}
2017-12-14 01:50:52 +00:00
~ gcell ( ) { cellcount - - ; }
2017-10-29 11:19:33 +00:00
} ;
# define landparam LHU.landpar
2018-09-04 17:53:42 +00:00
# define landparam_color LHU.landpar_color
2017-10-29 11:19:33 +00:00
# define fval LHU.fi.fieldval
2019-04-29 01:36:28 +00:00
# define NODIR 126
# define NOBARRIERS 127
# define MODFIXER (2*10090080*17)
2017-10-29 11:19:33 +00:00
2019-04-29 01:36:28 +00:00
# define MAX_EDGE 18
2018-08-18 15:40:54 +00:00
2018-08-17 22:46:45 +00:00
template < class T > struct walker ;
2017-10-29 11:46:57 +00:00
2018-08-17 22:46:45 +00:00
template < class T > struct connection_table {
2018-08-21 22:00:59 +00:00
// Assumption: class T has a field c of type connection_table<T>.
// NOTE: since aconnection_table may be allocated with
// less than MAX_EDGE neighbors (see tailored_alloc),
// the order of fields matters.
2019-04-29 01:36:28 +00:00
T * move_table [ MAX_EDGE + ( MAX_EDGE + sizeof ( char * ) - 1 ) / sizeof ( char * ) ] ;
2018-08-21 22:00:59 +00:00
2019-04-29 01:36:28 +00:00
unsigned char * spintable ( ) { return ( unsigned char * ) ( & move_table [ full ( ) - > degree ( ) ] ) ; }
2018-08-22 07:52:24 +00:00
T * full ( ) { T * x = ( T * ) this ; return ( T * ) ( ( char * ) this - ( ( char * ) ( & ( x - > c ) ) - ( char * ) x ) ) ; }
2018-08-18 15:40:54 +00:00
void setspin ( int d , int spin , bool mirror ) {
2019-04-29 01:36:28 +00:00
unsigned char & c = spintable ( ) [ d ] ;
c = spin ;
if ( mirror ) c | = 128 ;
2018-08-18 15:40:54 +00:00
}
2018-08-17 22:46:45 +00:00
// we are spin(i)-th neighbor of move[i]
2019-04-29 01:36:28 +00:00
int spin ( int d ) { return spintable ( ) [ d ] & 127 ; }
bool mirror ( int d ) { return spintable ( ) [ d ] & 128 ; }
2018-08-17 22:46:45 +00:00
int fix ( int d ) { return ( d + MODFIXER ) % full ( ) - > degree ( ) ; }
T * & modmove ( int i ) { return move ( fix ( i ) ) ; }
T * & move ( int i ) { return move_table [ i ] ; }
unsigned char modspin ( int i ) { return spin ( fix ( i ) ) ; }
2018-08-21 22:00:59 +00:00
void fullclear ( ) {
2019-01-28 20:41:53 +00:00
for ( int i = 0 ; i < full ( ) - > degree ( ) ; i + + ) move_table [ i ] = NULL ;
2018-08-17 22:46:45 +00:00
}
void connect ( int d0 , T * c1 , int d1 , bool m ) {
move ( d0 ) = c1 ;
c1 - > move ( d1 ) = full ( ) ;
setspin ( d0 , d1 , m ) ;
c1 - > c . setspin ( d1 , d0 , m ) ;
}
void connect ( int d0 , walker < T > hs ) {
connect ( d0 , hs . at , hs . spin , hs . mirrored ) ;
}
} ;
2018-08-21 22:00:59 +00:00
// Allocate a class T with a connection_table, but
// with only `degree` connections. Also set yet
// unknown connections to NULL.
// Generating the hyperbolic world consumes lots of
// RAM, so we really need to be careful on low memory devices.
template < class T > T * tailored_alloc ( int degree ) {
const T * sample = ( T * ) & degree ;
T * result ;
# ifndef NO_TAILORED_ALLOC
2019-04-29 01:36:28 +00:00
int b = ( char * ) & sample - > c . move_table [ degree ] + degree - ( char * ) sample ;
result = ( T * ) new char [ b ] ;
new ( result ) T ( ) ;
# else
result = new T ;
2018-08-21 22:00:59 +00:00
# endif
for ( int i = 0 ; i < degree ; i + + ) result - > c . move_table [ i ] = NULL ;
return result ;
}
2019-01-18 20:04:39 +00:00
template < class T > void tailored_delete ( T * x ) {
x - > ~ T ( ) ;
2019-01-14 21:54:30 +00:00
delete [ ] ( ( char * ) ( x ) ) ;
}
2018-08-17 22:46:45 +00:00
static const struct wstep_t { wstep_t ( ) { } } wstep ;
static const struct wmirror_t { wmirror_t ( ) { } } wmirror ;
static const struct rev_t { rev_t ( ) { } } rev ;
static const struct revstep_t { revstep_t ( ) { } } revstep ;
int hrand ( int x ) ;
2019-03-10 11:06:58 +00:00
// automatically adjust monster generation for 3D geometries
int hrand_monster ( int x ) ;
2018-08-17 22:46:45 +00:00
template < class T > struct walker {
T * at ;
int spin ;
bool mirrored ;
walker < T > ( T * at = NULL , int s = 0 , bool m = false ) : at ( at ) , spin ( s ) , mirrored ( m ) { }
walker < T > & operator + = ( int i ) {
spin = at - > c . fix ( spin + ( mirrored ? - i : i ) ) ;
return ( * this ) ;
}
walker < T > & operator - = ( int i ) {
spin = at - > c . fix ( spin - ( mirrored ? - i : i ) ) ;
return ( * this ) ;
}
walker < T > & operator + = ( wmirror_t ) {
mirrored = ! mirrored ;
return ( * this ) ;
}
walker < T > & operator + = ( wstep_t ) {
at - > cmove ( spin ) ;
int nspin = at - > c . spin ( spin ) ;
if ( at - > c . mirror ( spin ) ) mirrored = ! mirrored ;
at = at - > move ( spin ) ;
spin = nspin ;
return ( * this ) ;
}
walker < T > & operator + = ( rev_t ) {
int d = at - > degree ( ) ;
2019-02-27 15:14:28 +00:00
if ( DIM = = 3 & & binarytiling ) {
if ( spin < 4 ) spin = 8 ;
else if ( spin > = 8 ) spin = 0 ;
else spin ^ = 1 ;
}
2018-08-17 22:46:45 +00:00
return ( * this ) + = d / 2 + ( ( d & 1 ) ? hrand ( 2 ) : 0 ) ;
}
walker < T > & operator + = ( revstep_t ) {
( * this ) + = rev ; return ( * this ) + = wstep ;
}
bool operator ! = ( const walker < T > & x ) const {
return at ! = x . at | | spin ! = x . spin | | mirrored ! = x . mirrored ;
}
bool operator = = ( const walker < T > & x ) const {
return at = = x . at & & spin = = x . spin & & mirrored = = x . mirrored ;
}
2018-11-06 23:52:48 +00:00
bool operator < ( const walker < T > & cw2 ) const {
return tie ( at , spin , mirrored ) < tie ( cw2 . at , cw2 . spin , cw2 . mirrored ) ;
}
2018-08-17 22:46:45 +00:00
walker < T > & operator + + ( int ) { return ( * this ) + = 1 ; }
walker < T > & operator - - ( int ) { return ( * this ) - = 1 ; }
template < class U > walker operator + ( U t ) const { walker < T > w = * this ; w + = t ; return w ; }
template < class U > walker operator - ( U t ) const { walker < T > w = * this ; w + = ( - t ) ; return w ; }
T * & peek ( ) { return at - > move ( spin ) ; }
T * cpeek ( ) { return at - > cmove ( spin ) ; }
bool creates ( ) { return ! peek ( ) ; }
walker < T > mirrorat ( int d ) { return walker < T > ( at , at - > c . fix ( d + d - spin ) , ! mirrored ) ; }
} ;
2018-08-17 11:29:00 +00:00
2017-10-29 13:19:51 +00:00
struct cell ;
// automaton state
enum hstate { hsOrigin , hsA , hsB , hsError , hsA0 , hsA1 , hsB0 , hsB1 , hsC } ;
2018-08-17 22:46:45 +00:00
struct cell * createMov ( struct cell * c , int d ) ;
struct heptagon * createStep ( struct heptagon * c , int d ) ;
2019-04-29 11:41:24 +00:00
// in bitruncated/irregular/Goldberg geometries, heptagons form the
// underlying regular tiling (not necessarily heptagonal); in pure
// geometries, they correspond 1-1 to tiles; in 'masterless' geometries
// heptagons are unused
2017-10-29 13:19:51 +00:00
struct heptagon {
// automaton state
hstate s : 6 ;
2018-07-20 00:58:47 +00:00
unsigned int dm4 : 2 ;
2017-10-29 13:19:51 +00:00
// distance from the origin
short distance ;
2019-04-29 11:41:24 +00:00
// note: all the 'val' values may have different meaning in other geometries
2017-10-29 13:19:51 +00:00
// emerald/wineyard generator
short emeraldval ;
// fifty generator
short fiftyval ;
// zebra generator (1B actually)
short zebraval ;
// field id
int fieldval ;
2019-04-29 11:41:24 +00:00
// data for fractal landscapes
2017-10-29 13:19:51 +00:00
short rval0 , rval1 ;
2019-04-29 11:41:24 +00:00
// for alternate structures, cdata contains the pointer to the original
// for the main map, it contains the fractal landscape data
struct cdata * cdata ;
// central cell of this underlying tiling
2017-10-29 13:19:51 +00:00
cell * c7 ;
// associated generator of alternate structure, for Camelot and horocycles
heptagon * alt ;
2018-08-17 22:46:45 +00:00
// connection table
connection_table < heptagon > c ;
heptagon * & move ( int d ) { return c . move ( d ) ; }
heptagon * & modmove ( int d ) { return c . modmove ( d ) ; }
2017-10-29 13:19:51 +00:00
// functions
2017-12-14 01:50:52 +00:00
heptagon ( ) { heptacount + + ; }
~ heptagon ( ) { heptacount - - ; }
2018-08-17 22:46:45 +00:00
heptagon * cmove ( int d ) { return createStep ( this , d ) ; }
2018-09-27 19:52:13 +00:00
heptagon * cmodmove ( int d ) { return createStep ( this , c . fix ( d ) ) ; }
2018-08-17 22:46:45 +00:00
inline int degree ( ) ;
2018-08-21 22:00:59 +00:00
// prevent accidental copying
heptagon ( const heptagon & ) = delete ;
heptagon & operator = ( const heptagon & ) = delete ;
// do not add any fields after connection_table (see tailored_alloc)
2017-12-01 23:31:36 +00:00
} ;
2017-10-29 13:19:51 +00:00
2017-10-29 11:46:57 +00:00
struct cell : gcell {
2019-04-29 11:41:24 +00:00
char type ; int degree ( ) { return type ; }
2017-10-29 11:46:57 +00:00
// wall parameter, used for remaining power of Bonfires and Thumpers
char wparam ;
2019-04-29 11:41:24 +00:00
// used by celllister
2018-06-28 10:59:35 +00:00
int listindex ;
2017-10-29 11:46:57 +00:00
2019-04-29 11:41:24 +00:00
// heptagon who owns us; for 'masterless' tilings it contains coordinates instead
2017-10-29 11:46:57 +00:00
heptagon * master ;
2018-08-17 22:46:45 +00:00
connection_table < cell > c ;
cell * & move ( int d ) { return c . move ( d ) ; }
cell * & modmove ( int d ) { return c . modmove ( d ) ; }
cell * cmove ( int d ) { return createMov ( this , d ) ; }
2018-09-27 19:52:13 +00:00
cell * cmodmove ( int d ) { return createMov ( this , c . fix ( d ) ) ; }
2018-08-21 22:00:59 +00:00
cell ( ) { }
// prevent accidental copying
cell ( const cell & ) = delete ;
heptagon & operator = ( const cell & ) = delete ;
// do not add any fields after connection_table (see tailored_alloc)
2017-10-29 13:19:51 +00:00
} ;
2017-10-29 11:19:33 +00:00
2018-09-27 19:52:23 +00:00
namespace arcm { int degree ( heptagon * h ) ; int valence ( ) ; }
2018-08-30 00:11:43 +00:00
2019-02-17 17:28:20 +00:00
int heptagon : : degree ( ) {
# if CAP_ARCM
if ( archimedean ) return arcm : : degree ( this ) ; else
# endif
return S7 ;
}
2018-08-17 22:46:45 +00:00
2018-08-22 09:52:35 +00:00
typedef walker < heptagon > heptspin ;
typedef walker < cell > cellwalker ;
2018-08-17 22:46:45 +00:00
2018-08-30 14:04:28 +00:00
static const struct cth_t { cth_t ( ) { } } cth ;
2018-09-01 11:50:56 +00:00
inline heptspin operator + ( cellwalker cw , cth_t ) { return heptspin ( cw . at - > master , cw . spin * DUALMUL , cw . mirrored ) ; }
inline cellwalker operator + ( heptspin hs , cth_t ) { return cellwalker ( hs . at - > c7 , hs . spin / DUALMUL , hs . mirrored ) ; }
2018-08-30 14:04:28 +00:00
2017-10-29 11:19:33 +00:00
# define BUGCOLORS 3
// land completion for shared unlocking
# define U5 (inv::on ? 10 : 5)
// land completion for advanced unlocking
# define U10 (inv::on ? 25 : 10)
// land completion
# define R10 (inv::on ? 50 : 10)
// intermediate lands
# define R30 (inv::on ? 100 : 30)
// advanced lands
# define R60 (inv::on ? 200 : 60)
// advanced lands II
# define R90 (inv::on ? 300 : 90)
// Crossroads IV
# define R200 (inv::on ? 800 : 200)
// Crossroads V
# define R300 (inv::on ? 1200 : 300)
// kill types for Dragon Chasms
# define R20 (inv::on ? 30 : 20)
// kill count for Graveyard/Hive
# define R100 (inv::on ? 500 : 100)
2019-04-29 11:41:24 +00:00
string XLAT ( string x ) ; // translate the sentence x
string XLATN ( string x ) ; // translate the sentence x
string cts ( char c ) ; // character to string
string its ( int i ) ; // int to string
// a random integer from [0..i), generated by the game's main generator
// we want the same world to be generated if the seed is the same. For this purpose,
// hrand should be used for all the game-related generation, and nowhere else
2017-10-29 11:19:33 +00:00
int hrand ( int i ) ;
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
2016-08-26 09:58:03 +00:00
// initialize the achievement system.
void achievement_init ( ) ;
// close the achievement system.
void achievement_close ( ) ;
2019-01-17 13:08:10 +00:00
// get the user name
string myname ( ) ;
2016-08-26 09:58:03 +00:00
// gain the achievement with the given name.
// flags: 'e' - for Euclidean, 's' - for Shmup, '7' - for heptagonal
// Only awarded if special modes are matched exactly.
void achievement_gain ( const char * , char flags = 0 ) ;
// gain the achievement for collecting a number of 'it'.
void achievement_collection ( eItem it , int prevgold , int newgold ) ;
// this is used for 'counting' achievements, such as kill 10
// monsters at the same time.
void achievement_count ( const string & s , int current , int prev ) ;
// scores for special challenges
void achievement_score ( int cat , int score ) ;
// gain the victory achievements. Set 'hyper' to true for
// the Hyperstone victory, and false for the Orb of Yendor victory.
void achievement_victory ( bool hyper ) ;
// gain the final achievements. Called with really=false whenever the user
// looks at their score, and really=true when the game really ends.
void achievement_final ( bool really ) ;
// display the last achievement gained.
void achievement_display ( ) ;
// call the achievement callbacks
void achievement_pump ( ) ;
// achievements received this game
2017-10-29 11:46:57 +00:00
extern vector < string > achievementsReceived ;
2016-08-26 09:58:03 +00:00
// game forward declarations
bool mirrorkill ( cell * c ) ;
bool isNeighbor ( cell * c1 , cell * c2 ) ;
void checkTide ( cell * c ) ;
namespace anticheat { extern bool tampered ; }
int numplayers ( ) ;
void removeIvy ( cell * c ) ;
2017-03-23 10:53:57 +00:00
bool cellEdgeUnstable ( cell * c , flagtype flags = 0 ) ;
2016-08-26 09:58:03 +00:00
int coastvalEdge ( cell * c ) ;
# define HRANDMAX 0x7FFFFFFF
int hrandpos ( ) ; // 0 to HRANDMAX
2018-04-09 16:05:23 +00:00
namespace rg {
2018-06-10 22:58:38 +00:00
// possible parameters e.g. for restart_game and wrongmode
2018-04-09 16:05:23 +00:00
static const char nothing = 0 ;
static const char peace = ' P ' ;
static const char inv = ' i ' ;
static const char chaos = ' C ' ;
static const char tactic = ' t ' ;
static const char tour = ' T ' ;
static const char yendor = ' y ' ;
static const char shmup = ' s ' ;
static const char randpattern = ' r ' ;
static const char princess = ' p ' ;
2018-04-30 22:21:18 +00:00
static const char daily = ' d ' ;
2018-05-15 21:26:04 +00:00
static const char daily_off = ' D ' ;
2018-11-24 22:52:13 +00:00
static const char racing = ' R ' ;
2018-04-09 16:05:23 +00:00
// wrongmode only -- marks 'global' achievements not related to the current mode
static const char global = ' x ' ;
2018-06-10 22:58:38 +00:00
// wrongmode only -- change vid.scfg.players then restart_game(rg::nothing) instead
2018-04-09 16:05:23 +00:00
static const char multi = ' m ' ;
2018-12-25 22:56:05 +00:00
// wrongmode only -- mark achievements for special geometries/variations
2018-08-28 15:17:34 +00:00
static const char special_geometry = ' g ' ;
2018-04-09 16:05:23 +00:00
}
2016-08-26 09:58:03 +00:00
int landMultiplier ( eLand l ) ;
eItem treasureType ( eLand l ) ;
void buildBarrier ( cell * c , int d , eLand l = laNone ) ;
void extendBarrier ( cell * c ) ;
bool buildBarrier4 ( cell * c , int d , int mode , eLand ll , eLand lr ) ;
2018-08-17 22:46:45 +00:00
bool buildBarrier6 ( cellwalker cw , int type ) ;
2017-03-23 10:53:57 +00:00
bool makeEmpty ( cell * c ) ;
2016-08-26 09:58:03 +00:00
bool isCrossroads ( eLand l ) ;
2017-03-23 10:53:57 +00:00
enum orbAction { roMouse , roKeyboard , roCheck , roMouseForce , roMultiCheck , roMultiGo } ;
2016-08-26 09:58:03 +00:00
void moveItem ( cell * from , cell * to , bool activateYendor ) ;
2019-01-24 13:51:24 +00:00
bool uncoverMines ( cell * c , int lev , int dist , bool just_checking ) ;
2017-03-23 10:53:57 +00:00
void killMonster ( cell * c , eMonster who_killed , flagtype flags = 0 ) ;
2016-08-26 09:58:03 +00:00
void toggleGates ( cell * ct , eWall type , int rad ) ;
bool destroyHalfvine ( cell * c , eWall newwall = waNone , int tval = 6 ) ;
void buildCrossroads2 ( cell * c ) ;
bool isHaunted ( eLand l ) ;
heptagon * createAlternateMap ( cell * c , int rad , hstate firststate , int special = 0 ) ;
void setdist ( cell * c , int d , cell * from ) ;
void checkOnYendorPath ( ) ;
2017-03-23 10:53:57 +00:00
void killThePlayerAt ( eMonster m , cell * c , flagtype flags ) ;
2016-08-26 09:58:03 +00:00
bool notDippingFor ( eItem i ) ;
bool collectItem ( cell * c2 , bool telekinesis = false ) ;
2018-08-17 22:46:45 +00:00
void castLightningBolt ( cellwalker lig ) ;
2016-08-26 09:58:03 +00:00
bool movepcto ( int d , int subdir = 1 , bool checkonly = false ) ;
2017-03-23 10:53:57 +00:00
void stabbingAttack ( cell * mf , cell * mt , eMonster who , int bonuskill = 0 ) ;
2016-08-26 09:58:03 +00:00
bool earthMove ( cell * from , int dir ) ;
void messageKill ( eMonster killer , eMonster victim ) ;
2018-06-17 15:51:26 +00:00
void moveMonster ( cell * ct , cell * cf , int direction_hint ) ;
2016-08-26 09:58:03 +00:00
int palaceHP ( ) ;
void placeLocalOrbs ( cell * c ) ;
int elementalKills ( ) ;
bool isMultitile ( eMonster m ) ;
void checkFreedom ( cell * cf ) ;
int rosedist ( cell * c ) ;
bool canPushStatueOn ( cell * c ) ;
2019-04-10 00:33:54 +00:00
void auto_teleport_charges ( ) ;
2016-08-26 09:58:03 +00:00
namespace hive { void createBugArmy ( cell * c ) ; }
namespace whirlpool { void generate ( cell * wto ) ; }
namespace whirlwind { void generate ( cell * wto ) ; }
namespace mirror {
2017-07-22 23:33:27 +00:00
static const int SPINSINGLE = 1 ;
static const int SPINMULTI = 2 ;
static const int GO = 4 ;
static const int ATTACK = 8 ;
void act ( int dir , int flags ) ;
2016-08-26 09:58:03 +00:00
}
int neighborId ( cell * c1 , cell * c2 ) ;
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
2017-03-23 10:53:57 +00:00
cell * tgt ; // for MD_USE_ORB: target cell
} ;
2016-08-26 09:58:03 +00:00
inline bool movepcto ( const movedir & md ) { return movepcto ( md . d , md . subdir ) ; }
void activateActiv ( cell * c , bool msg ) ;
// shmup
struct charstyle {
2017-07-16 21:00:55 +00:00
int charid ;
2018-09-04 17:53:42 +00:00
color_t skincolor , haircolor , dresscolor , swordcolor , dresscolor2 , uicolor ;
2018-11-10 17:32:55 +00:00
bool lefthanded ;
2016-08-26 09:58:03 +00:00
} ;
string csname ( charstyle & cs ) ;
void initcs ( charstyle & cs ) ;
2017-03-23 10:53:57 +00:00
# define MAXPLAYER 7
# define MAXJOY 8
# define MAXBUTTON 64
# define MAXAXE 16
# define MAXHAT 4
2019-03-06 15:36:10 +00:00
extern bool flipplayer ;
2017-03-23 10:53:57 +00:00
namespace multi {
2017-08-06 12:50:16 +00:00
extern bool alwaysuse ;
2017-03-23 10:53:57 +00:00
void recall ( ) ;
extern cell * origpos [ MAXPLAYER ] , * origtarget [ MAXPLAYER ] ;
extern int players ;
extern cellwalker player [ MAXPLAYER ] ;
extern bool flipped [ MAXPLAYER ] ;
cell * mplayerpos ( int i ) ;
extern vector < int > revive_queue ; // queue for revival
extern movedir whereto [ MAXPLAYER ] ; // player's target cell
extern int cpid ; // player id -- an extra parameter for player-related functions
extern int cpid_edit ; // cpid currently being edited
// treasure collection, kill, and death statistics
extern int treasures [ MAXPLAYER ] , kills [ MAXPLAYER ] , deaths [ MAXPLAYER ] ;
struct config {
char keyaction [ 512 ] ;
char joyaction [ MAXJOY ] [ MAXBUTTON ] ;
char axeaction [ MAXJOY ] [ MAXAXE ] ;
char hataction [ MAXJOY ] [ MAXHAT ] [ 4 ] ;
int deadzoneval [ MAXJOY ] [ MAXAXE ] ;
} ;
2017-07-10 18:47:38 +00:00
void saveConfig ( FILE * f ) ;
void loadConfig ( FILE * f ) ;
void initConfig ( ) ;
2017-10-29 11:46:57 +00:00
extern charstyle scs [ MAXPLAYER ] ;
2017-03-23 10:53:57 +00:00
bool playerActive ( int p ) ;
int activePlayers ( ) ;
cell * multiPlayerTarget ( int i ) ;
void checklastmove ( ) ;
void leaveGame ( int i ) ;
2018-11-18 02:18:11 +00:00
void configure ( ) ;
2019-03-30 22:45:28 +00:00
void showConfigureMultiplayer ( ) ;
2017-03-23 10:53:57 +00:00
}
2016-08-26 09:58:03 +00:00
2018-07-09 17:32:34 +00:00
template < class T > class hookset : public map < int , function < T > > { } ;
typedef hookset < void ( ) > * purehookset ;
2016-08-26 09:58:03 +00:00
namespace shmup {
2017-07-10 18:47:38 +00:00
using namespace multi ;
2017-03-23 10:53:57 +00:00
void recall ( ) ;
2016-08-26 09:58:03 +00:00
extern bool on ;
2019-04-28 10:09:57 +00:00
extern bool delayed_safety ;
2016-08-26 09:58:03 +00:00
extern int curtime ;
2017-04-14 18:12:23 +00:00
void clearMonsters ( ) ;
2016-08-26 09:58:03 +00:00
void clearMemory ( ) ;
void init ( ) ;
void teleported ( ) ;
2017-12-01 23:31:36 +00:00
struct monster {
eMonster type ;
cell * base ;
cell * torigin ;
// tortoises: origin
// butterflies: last position
transmatrix at ;
transmatrix pat ;
eMonster stk ;
bool dead ;
bool notpushed ;
bool inBoat ;
2018-07-09 17:32:34 +00:00
bool no_targetting ;
2017-12-01 23:31:36 +00:00
monster * parent ; // who shot this missile
eMonster parenttype ; // type of the parent
int nextshot ; // when will it be able to shot (players/flailers)
int pid ; // player ID
2019-03-30 16:51:37 +00:00
int hitpoints ; // hitpoints; or time elapsed in Asteroids
2017-12-01 23:31:36 +00:00
int stunoff ;
int blowoff ;
double swordangle ; // sword angle wrt at
double vel ; // velocity, for flail balls
double footphase ;
bool isVirtual ; // off the screen: gmatrix is unknown, and pat equals at
2019-03-30 16:51:37 +00:00
hyperpoint inertia ; // for frictionless lands
2017-12-01 23:31:36 +00:00
monster ( ) {
dead = false ; inBoat = false ; parent = NULL ; nextshot = 0 ;
2018-07-09 17:32:34 +00:00
stunoff = 0 ; blowoff = 0 ; footphase = 0 ; no_targetting = false ;
2019-03-30 16:51:37 +00:00
swordangle = 0 ; inertia = Hypc ;
2017-12-01 23:31:36 +00:00
}
void store ( ) ;
void findpat ( ) ;
cell * findbase ( const transmatrix & T ) ;
void rebasePat ( const transmatrix & new_pat ) ;
} ;
2016-08-26 09:58:03 +00:00
extern struct monster * mousetarget ;
2018-04-21 10:17:33 +00:00
extern monster * pc [ MAXPLAYER ] ;
2016-08-26 09:58:03 +00:00
extern eItem targetRangedOrb ( orbAction a ) ;
void degradeDemons ( ) ;
void killThePlayer ( eMonster m ) ;
void killThePlayer ( eMonster m , int i ) ;
void visibleFor ( int t ) ;
bool verifyTeleport ( ) ;
bool dragonbreath ( cell * dragon ) ;
void shmupDrownPlayers ( cell * c ) ;
cell * playerpos ( int i ) ;
bool playerInBoat ( int i ) ;
2017-03-23 10:53:57 +00:00
void destroyBoats ( cell * c ) ;
bool boatAt ( cell * c ) ;
2017-05-31 16:33:50 +00:00
2017-06-18 16:51:46 +00:00
void fixStorage ( ) ;
2017-07-10 18:47:38 +00:00
void addShmupHelp ( string & out ) ;
2017-10-12 09:33:26 +00:00
void activateArrow ( cell * c ) ;
2018-02-12 11:48:31 +00:00
void pushmonsters ( ) ;
void popmonsters ( ) ;
2018-07-09 17:32:34 +00:00
extern hookset < bool ( int ) > * hooks_turn ;
extern hookset < bool ( const transmatrix & , cell * , shmup : : monster * ) > * hooks_draw ;
extern hookset < bool ( shmup : : monster * ) > * hooks_kill ;
extern hookset < bool ( shmup : : monster * , string & ) > * hooks_describe ;
2018-07-09 19:02:23 +00:00
void turn ( int ) ;
extern monster * lmousetarget ;
2018-08-17 14:47:06 +00:00
void virtualRebase ( shmup : : monster * m , bool tohex ) ;
2018-09-10 15:26:27 +00:00
extern monster * pc [ MAXPLAYER ] ;
2018-09-23 21:55:03 +00:00
int reflect ( cell * & c2 , cell * & mbase , transmatrix & nat ) ;
2019-03-30 22:45:28 +00:00
void switch_shmup ( ) ;
2016-08-26 09:58:03 +00:00
}
2018-08-17 14:47:06 +00:00
transmatrix & ggmatrix ( cell * c ) ;
transmatrix master_relative ( cell * c , bool get_inverse = false ) ;
void virtualRebase ( cell * & base , transmatrix & at , bool tohex ) ;
void virtualRebase ( cell * & base , hyperpoint & h , bool tohex ) ;
transmatrix calc_relative_matrix ( cell * c , cell * c1 , const hyperpoint & point_hint ) ;
transmatrix calc_relative_matrix ( cell * c , cell * c1 , int direction_hint ) ;
2018-06-17 15:51:26 +00:00
static const int NOHINT = - 1 ;
2016-08-26 09:58:03 +00:00
// graph
void showMissionScreen ( ) ;
void restartGraph ( ) ;
void resetmusic ( ) ;
void drawFlash ( cell * c ) ;
void drawBigFlash ( cell * c ) ;
2019-02-26 19:19:19 +00:00
void drawParticleSpeed ( cell * c , color_t col , int speed ) ;
2018-09-04 17:53:42 +00:00
void drawParticle ( cell * c , color_t col , int maxspeed = 100 ) ;
void drawParticles ( cell * c , color_t col , int qty , int maxspeed = 100 ) ;
2017-03-23 10:53:57 +00:00
void drawFireParticles ( cell * c , int qty , int maxspeed = 100 ) ;
2018-09-10 15:56:37 +00:00
int firecolor ( int phase = 0 , int mul = 1 ) ;
2016-08-26 09:58:03 +00:00
void drawLightning ( ) ;
void drawSafety ( ) ;
void restartGraph ( ) ;
void movepckeydir ( int ) ;
void centerpc ( ld aspd ) ;
2018-09-04 17:53:42 +00:00
typedef color_t color_t ;
2016-08-26 09:58:03 +00:00
void displayButton ( int x , int y , const string & name , int key , int align , int rad = 0 ) ;
2018-09-04 17:53:42 +00:00
void displayColorButton ( int x , int y , const string & name , int key , int align , int rad , color_t color , color_t color2 = 0 ) ;
2016-08-26 09:58:03 +00:00
inline string ONOFF ( bool b ) { return XLAT ( b ? " ON " : " OFF " ) ; }
2019-03-09 02:32:24 +00:00
color_t darkened ( color_t c ) ;
2016-08-26 09:58:03 +00:00
extern int getcstat ;
2018-09-04 17:53:42 +00:00
bool displaychr ( int x , int y , int shift , int size , char chr , color_t col ) ;
bool displayfr ( int x , int y , int b , int size , const string & s , color_t color , int align ) ;
bool displayfrSP ( int x , int y , int sh , int b , int size , const string & s , color_t color , int align , int p ) ;
2016-08-26 09:58:03 +00:00
bool outofmap ( hyperpoint h ) ;
2017-03-23 10:53:57 +00:00
void applymodel ( hyperpoint H , hyperpoint & Hscr ) ;
2018-11-08 15:28:17 +00:00
void drawCircle ( int x , int y , int size , color_t color , color_t fillcolor = 0 ) ;
2019-02-26 13:56:07 +00:00
void queuecircleat ( cell * c , double rad , color_t col ) ;
2016-08-26 09:58:03 +00:00
void fixcolor ( int & col ) ;
2018-08-19 13:52:39 +00:00
ld displayspin ( cell * c , int d ) ;
2018-12-05 18:57:35 +00:00
bool non_spatial_model ( ) ;
2016-08-26 09:58:03 +00:00
hyperpoint gethyper ( ld x , ld y ) ;
2018-11-17 18:24:02 +00:00
void resetview ( ) ;
2016-08-26 09:58:03 +00:00
void drawthemap ( ) ;
void drawfullmap ( ) ;
2019-03-30 16:47:16 +00:00
void draw_boundary ( int w ) ;
void draw_model_elements ( ) ;
2018-01-25 16:22:04 +00:00
extern function < void ( ) > wrap_drawfullmap ;
2018-09-04 17:53:42 +00:00
bool displaystr ( int x , int y , int shift , int size , const char * str , color_t color , int align ) ;
bool displaystr ( int x , int y , int shift , int size , const string & str , color_t color , int align ) ;
2016-08-26 09:58:03 +00:00
2017-07-16 21:00:55 +00:00
extern int darken , inmirrorcount ;
2016-08-26 09:58:03 +00:00
void calcparam ( ) ;
2017-07-22 23:33:27 +00:00
# if CAP_SDL
2018-09-04 17:53:42 +00:00
color_t & qpixel ( SDL_Surface * surf , int x , int y ) ;
2017-05-27 19:40:40 +00:00
void setvideomode ( ) ;
# endif
2017-07-22 23:33:27 +00:00
# if CAP_CONFIG
2016-08-26 09:58:03 +00:00
void saveConfig ( ) ;
2017-03-23 10:53:57 +00:00
# endif
2016-08-26 09:58:03 +00:00
extern hyperpoint mouseh ;
extern hyperpoint ccenter ;
extern ld crad ;
2018-12-06 11:31:51 +00:00
extern bool mousepressed , anyshiftclick , numlock_on ;
2016-08-26 09:58:03 +00:00
extern string help ;
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
extern reaction_t help_delegate ;
2017-05-27 19:40:40 +00:00
# define HELPFUN(x) (help_delegate = x, "HELPFUN")
2018-11-17 18:24:02 +00:00
enum eStereo { sOFF , sAnaglyph , sLR , sODS } ;
2019-02-28 15:24:46 +00:00
struct radarpoint {
hyperpoint h ;
char glyph ;
color_t color ;
color_t line ;
} ;
extern vector < radarpoint > radarpoints ;
2016-08-26 09:58:03 +00:00
struct videopar {
2018-02-03 12:41:49 +00:00
ld scale , alpha , sspeed , mspeed , yshift , camera_angle ;
2019-01-17 13:09:00 +00:00
ld ballangle , ballproj , euclid_to_sphere , twopoint_param , stretch , binary_width , fixed_facing_dir ;
2017-03-23 10:53:57 +00:00
int mobilecompasssize ;
2019-02-28 15:24:46 +00:00
int radarsize ; // radar for 3D geometries
2017-05-27 19:40:40 +00:00
int aurastr , aurasmoothen ;
2019-01-17 13:09:00 +00:00
bool fixed_facing ;
2019-04-29 01:34:21 +00:00
bool use_wall_radar ;
2018-08-01 09:07:22 +00:00
int linequality ;
2017-03-23 10:53:57 +00:00
2016-08-26 09:58:03 +00:00
bool full ;
2018-02-03 12:41:49 +00:00
2017-05-28 22:16:17 +00:00
int graphglyph ; // graphical glyphs
2016-08-26 09:58:03 +00:00
bool darkhepta ;
2017-03-23 10:53:57 +00:00
int shifttarget ;
2016-08-26 09:58:03 +00:00
int xres , yres , framelimit ;
int xscr , yscr ;
2017-12-25 09:26:50 +00:00
ld xposition , yposition ;
2017-03-23 10:53:57 +00:00
bool grid ;
int particles ;
2016-08-26 09:58:03 +00:00
int fsize ;
int flashtime ;
int wallmode , monmode , axes ;
2017-07-10 18:47:38 +00:00
bool revcontrol ;
2017-10-08 12:49:49 +00:00
int msgleft , msglimit ;
2016-08-26 09:58:03 +00:00
bool usingGL ;
2017-07-04 13:38:33 +00:00
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
2017-07-10 18:47:38 +00:00
# define AA_MULTI 64
2017-08-06 12:50:16 +00:00
# define AA_MULTI16 128 // not configurable
2017-07-04 13:38:33 +00:00
ld linewidth ;
2016-08-26 09:58:03 +00:00
int joyvalue , joyvalue2 , joypanthreshold ;
2017-03-23 10:53:57 +00:00
ld joypanspeed ;
2016-08-26 09:58:03 +00:00
charstyle cs ;
bool samegender ; // same gender for the Princess?
int language ;
2017-10-17 19:26:21 +00:00
bool backeffects ; // background particle effects
2016-08-26 09:58:03 +00:00
int killreduction , itemreduction , portreduction ;
2017-03-23 10:53:57 +00:00
multi : : config scfg ;
2016-08-26 09:58:03 +00:00
2017-03-23 10:53:57 +00:00
int steamscore ;
bool drawmousecircle ; // draw the circle around the mouse
2017-08-06 12:50:16 +00:00
bool skipstart ; // skip the start menu
int quickmouse ; // quick mouse on the map
2017-10-09 08:51:16 +00:00
int timeformat ; // time format used in the message log
2018-11-01 17:59:25 +00:00
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
2019-03-21 18:13:45 +00:00
ld smart_range_detail_3 ; // minimum visible cell in 3D (for mode 2, there is no mode 1)
2018-11-01 17:59:25 +00:00
int cells_drawn_limit ;
2018-11-06 14:53:50 +00:00
ld skiprope ;
2018-11-17 18:24:02 +00:00
eStereo stereo_mode ;
ld ipd ;
ld lr_eyewidth , anaglyph_eyewidth ;
ld fov ;
2018-11-18 16:27:27 +00:00
bool consider_shader_projection ;
2019-03-09 02:32:24 +00:00
int desaturate ;
2016-08-26 09:58:03 +00:00
} ;
extern videopar vid ;
2017-07-10 18:47:38 +00:00
extern vector < function < void ( ) > > screens ;
2018-04-10 03:12:40 +00:00
template < class T > void pushScreen ( const T & x ) { screens . push_back ( x ) ; }
2017-07-10 18:47:38 +00:00
inline void popScreen ( ) { screens . pop_back ( ) ; }
2018-06-22 12:47:24 +00:00
inline void popScreenAll ( ) { while ( isize ( screens ) > 1 ) popScreen ( ) ; }
2016-08-26 09:58:03 +00:00
2018-11-17 18:24:02 +00:00
struct display_data {
transmatrix view_matrix ; // current rotation, relative to viewctr
transmatrix player_matrix ; // player-relative view
heptspin view_center ;
cellwalker precise_center ;
unordered_map < cell * , transmatrix > cellmatrices , old_cellmatrices ;
2018-11-17 23:35:50 +00:00
ld xmin , ymin , xmax , ymax ; // relative
ld xtop , ytop , xsize , ysize ; // in pixels
2018-11-17 18:24:02 +00:00
display_data ( ) { xmin = ymin = 0 ; xmax = ymax = 1 ; }
// paramaters calculated from the above
int xcenter , ycenter ;
ld radius ;
int scrsize ;
bool sidescreen ;
ld tanfov ;
GLfloat scrdist , scrdist_text ;
ld eyewidth ( ) ;
bool stereo_active ( ) ;
bool in_anaglyph ( ) ;
void set_viewport ( int ed ) ;
2019-04-23 13:03:17 +00:00
void set_projection ( int ed ) ;
2018-11-17 18:24:02 +00:00
void set_mask ( int ed ) ;
2019-04-23 13:03:17 +00:00
void set_all ( int ed ) ;
2018-11-17 18:24:02 +00:00
} ;
extern display_data default_display ;
extern display_data * current_display ;
# define View (current_display->view_matrix)
# define cwtV (current_display->player_matrix)
# define viewctr (current_display->view_center)
# define centerover (current_display->precise_center)
# define gmatrix (current_display->cellmatrices)
# define gmatrix0 (current_display->old_cellmatrices)
2016-08-26 09:58:03 +00:00
2017-12-18 22:42:08 +00:00
extern cell * mouseover , * mouseover2 , * lmouseover ;
2016-08-26 09:58:03 +00:00
extern string mouseovers ;
extern struct SDL_Surface * s ;
2018-09-27 19:52:13 +00:00
typedef function < int ( cell * ) > cellfunction ;
2017-12-09 02:48:30 +00:00
namespace patterns {
extern char whichShape ;
2018-04-05 22:31:25 +00:00
extern int canvasback ;
2017-12-09 07:06:41 +00:00
2018-04-05 22:31:25 +00:00
extern cpatterntype cgroup , old_cgroup ;
2017-12-09 07:06:41 +00:00
2018-12-12 01:51:14 +00:00
enum ePattern : char {
2018-08-28 02:05:32 +00:00
PAT_NONE = 0 ,
PAT_TYPES = ' T ' ,
PAT_ZEBRA = ' z ' ,
PAT_EMERALD = ' f ' ,
PAT_PALACE = ' p ' ,
PAT_FIELD = ' F ' ,
PAT_DOWN = ' H ' ,
PAT_COLORING = ' C ' ,
PAT_SIBLING = ' S ' ,
PAT_CHESS = ' c ' ,
PAT_SINGLETYPE = ' t '
} ;
extern ePattern whichPattern ;
2017-12-09 07:06:41 +00:00
extern int subpattern_flags ;
static const int SPF_ROT = 1 ;
static const int SPF_SYM01 = 2 ;
static const int SPF_SYM02 = 4 ;
static const int SPF_SYM03 = 8 ;
static const int SPF_CHANGEROT = 16 ;
static const int SPF_TWOCOL = 32 ;
2017-12-09 19:02:56 +00:00
static const int SPF_EXTRASYM = 64 ;
2017-12-19 13:35:34 +00:00
static const int SPF_ALTERNATE = 128 ;
static const int SPF_FOOTBALL = 256 ;
2017-12-21 10:36:07 +00:00
static const int SPF_FULLSYM = 512 ;
2017-12-29 00:10:47 +00:00
static const int SPF_DOCKS = 1024 ;
2018-08-30 17:14:04 +00:00
static const int SPF_NO_SUBCODES = 2048 ;
2017-12-09 07:06:41 +00:00
2017-12-19 13:35:34 +00:00
static const int SPF_SYM0123 = SPF_SYM01 | SPF_SYM02 | SPF_SYM03 ;
2017-12-09 07:06:41 +00:00
2017-12-09 02:48:30 +00:00
extern char whichCanvas ;
2017-12-19 13:35:34 +00:00
extern bool displaycodes ;
2017-12-05 15:19:22 +00:00
2017-12-09 02:48:30 +00:00
int generateCanvas ( cell * c ) ;
2017-12-09 07:06:41 +00:00
struct patterninfo {
int id ;
int dir ;
bool reflect ;
2017-12-09 19:02:56 +00:00
int symmetries ;
2017-12-09 07:06:41 +00:00
} ;
2018-08-28 02:05:32 +00:00
patterninfo getpatterninfo ( cell * c , ePattern pat , int sub ) ;
2017-12-09 07:06:41 +00:00
2017-12-09 19:02:56 +00:00
inline patterninfo getpatterninfo0 ( cell * c ) {
2017-12-09 07:06:41 +00:00
return getpatterninfo ( c , whichPattern , subpattern_flags ) ;
}
2018-04-05 22:31:25 +00:00
bool compatible ( cpatterntype oldp , cpatterntype newp ) ;
extern void pushChangeablePatterns ( ) ;
void computeCgroup ( ) ;
void showPattern ( ) ;
void val38 ( cell * c , patterninfo & si , int sub , int pat ) ;
2018-09-27 19:52:13 +00:00
int downdir ( cell * c , const cellfunction & cf = coastvalEdge ) ;
2017-12-09 02:48:30 +00:00
}
namespace mapeditor {
# if CAP_EDIT
extern map < int , cell * > modelcell ;
# endif
extern bool drawplayer ;
void applyModelcell ( cell * c ) ;
2017-12-05 15:19:22 +00:00
2016-08-26 09:58:03 +00:00
extern cell * drawcell ;
2017-06-18 16:51:46 +00:00
void initdraw ( cell * c ) ;
2017-07-10 18:47:38 +00:00
void showMapEditor ( ) ;
void showDrawEditor ( ) ;
2018-08-27 17:27:35 +00:00
2019-02-28 16:06:53 +00:00
enum eShapegroup { sgPlayer , sgMonster , sgItem , sgFloor , sgWall } ;
static const int USERSHAPEGROUPS = 5 ;
2018-08-27 17:27:35 +00:00
2019-01-03 14:12:45 +00:00
bool haveUserShape ( eShapegroup group , int id ) ;
void draw_texture_ghosts ( cell * c , const transmatrix & V ) ;
2018-12-24 14:10:52 +00:00
void map_settings ( ) ;
2016-08-26 09:58:03 +00:00
}
2018-05-18 15:34:12 +00:00
struct renderbuffer ;
2016-08-26 09:58:03 +00:00
namespace rug {
extern bool rugged ;
2018-12-05 18:57:35 +00:00
extern bool spatial_rug ;
2018-03-24 14:17:17 +00:00
extern bool computed ;
2017-07-10 18:47:38 +00:00
extern bool renderonce ;
extern bool rendernogl ;
extern int texturesize ;
2017-12-27 17:53:00 +00:00
extern ld model_distance ;
2019-03-30 16:52:27 +00:00
extern ld modelscale ;
2018-01-14 20:21:32 +00:00
extern transmatrix currentrot ;
2017-07-24 22:21:36 +00:00
# if CAP_RUG
2017-07-10 18:47:38 +00:00
void show ( ) ;
2018-03-24 14:17:17 +00:00
// initialize both the texture and the model
2016-08-26 09:58:03 +00:00
void init ( ) ;
2018-03-24 14:17:17 +00:00
// initialize only the texture (assume model already initialized)
void reopen ( ) ;
// close the rug mode, remove the texture
2016-08-26 09:58:03 +00:00
void close ( ) ;
2018-03-24 14:17:17 +00:00
// clear the model
void clear_model ( ) ;
2016-08-26 09:58:03 +00:00
void actDraw ( ) ;
2017-07-10 18:47:38 +00:00
void select ( ) ;
2016-08-26 09:58:03 +00:00
void buildVertexInfo ( cell * c , transmatrix V ) ;
2018-02-01 12:43:39 +00:00
void drawRugScene ( ) ;
void prepareTexture ( ) ;
void drawRugScene ( ) ;
void push_all_points ( int coord , ld val ) ;
void apply_rotation ( const transmatrix & t ) ;
2018-02-26 12:15:33 +00:00
string makehelp ( ) ;
2018-03-24 14:17:17 +00:00
struct edge {
struct rugpoint * target ;
double len ;
} ;
struct dexp_data {
hyperpoint params ;
hyperpoint cont ;
ld remaining_distance ;
} ;
struct rugpoint {
double x1 , y1 ;
bool valid ;
bool inqueue ;
double dist ;
hyperpoint h ; // point in the represented space
hyperpoint flat ; // point in the native space, in azeq
hyperpoint precompute ;
vector < edge > edges ;
vector < edge > anticusp_edges ;
// Find-Union algorithm
rugpoint * glue ;
rugpoint * getglue ( ) {
return glue ? ( glue = glue - > getglue ( ) ) : this ;
}
hyperpoint & glueflat ( ) {
return glue - > flat ;
}
rugpoint ( ) { glue = NULL ; }
void glueto ( rugpoint * x ) {
x = x - > getglue ( ) ;
auto y = getglue ( ) ;
if ( x ! = y ) y - > glue = x ;
}
int dexp_id ;
dexp_data surface_point ;
} ;
struct triangle {
rugpoint * m [ 3 ] ;
triangle ( rugpoint * m1 , rugpoint * m2 , rugpoint * m3 ) {
m [ 0 ] = m1 ; m [ 1 ] = m2 ; m [ 2 ] = m3 ;
}
} ;
extern vector < rugpoint * > points ;
extern vector < triangle > triangles ;
extern int qvalid ;
extern bool subdivide_further ( ) ;
extern void subdivide ( ) ;
extern bool good_shape ;
extern int vertex_limit ;
extern void enqueue ( rugpoint * p ) ;
void sort_rug_points ( ) ;
extern bool rug_perspective ;
bool handlekeys ( int sym , int uni ) ;
2018-03-29 22:20:50 +00:00
void addTriangle ( rugpoint * t1 , rugpoint * t2 , rugpoint * t3 , ld len = 1 ) ;
rugpoint * addRugpoint ( hyperpoint h , double dist ) ;
void buildRug ( ) ;
2018-05-18 15:34:12 +00:00
2018-12-01 22:53:50 +00:00
bool in_crystal ( ) ;
void physics ( ) ;
2018-05-18 15:34:12 +00:00
extern renderbuffer * glbuf ;
extern eGeometry gwhere ;
extern bool no_fog ;
extern ld lowrug , hirug , ruggospeed ;
extern GLuint alternate_texture ;
2018-09-03 14:32:11 +00:00
extern bool invert_depth ;
2018-09-10 15:26:27 +00:00
extern ld ruggo ;
2018-05-07 18:09:58 +00:00
# endif
2017-07-24 22:21:36 +00:00
}
2016-08-26 09:58:03 +00:00
# define HASLINEVIEW
2017-07-10 18:47:38 +00:00
2016-08-26 09:58:03 +00:00
namespace conformal {
extern bool on ;
extern vector < pair < cell * , eMonster > > killhistory ;
extern vector < pair < cell * , eItem > > findhistory ;
extern vector < cell * > movehistory ;
2018-06-28 10:59:35 +00:00
extern set < cell * > inmovehistory , inkillhistory , infindhistory ;
2016-08-26 09:58:03 +00:00
extern bool includeHistory ;
2018-12-24 00:10:55 +00:00
extern bool use_atan ;
2018-03-25 13:07:11 +00:00
extern ld rotation ;
2019-03-21 02:38:10 +00:00
extern ld rotation_xz ;
2018-03-25 13:07:11 +00:00
extern int do_rotate ;
2019-03-20 17:32:03 +00:00
extern ld model_orientation , model_orientation_yz ;
2018-10-23 14:58:19 +00:00
extern ld halfplane_scale ;
2019-03-20 17:32:03 +00:00
extern ld ocos , osin , ocos_yz , osin_yz ;
2018-10-25 17:58:38 +00:00
extern ld cos_ball , sin_ball ;
2019-03-20 17:32:03 +00:00
extern bool model_straight , model_straight_yz ;
2018-10-26 19:03:27 +00:00
extern ld model_transition ;
2018-10-23 18:08:57 +00:00
extern ld top_z ;
2018-11-10 16:23:43 +00:00
extern ld spiral_angle , spiral_x , spiral_y ;
2018-12-21 13:42:59 +00:00
extern ld spiral_cone ;
2019-03-20 23:25:38 +00:00
extern ld clip_min , clip_max ;
2018-10-23 14:58:19 +00:00
// screen coordinates to logical coordinates: apply_orientation(x,y)
// logical coordinates back to screen coordinates: apply_orientation(y,x)
template < class A >
void apply_orientation ( A & x , A & y ) { if ( ! model_straight ) tie ( x , y ) = make_pair ( x * ocos + y * osin , y * ocos - x * osin ) ; }
2018-10-25 17:58:38 +00:00
template < class A >
2019-03-20 17:32:03 +00:00
void apply_orientation_yz ( A & x , A & y ) { if ( ! model_straight_yz ) tie ( x , y ) = make_pair ( x * ocos_yz + y * osin_yz , y * ocos_yz - x * osin_yz ) ; }
template < class A >
2018-10-25 17:58:38 +00:00
void apply_ball ( A & x , A & y ) { tie ( x , y ) = make_pair ( x * cos_ball + y * sin_ball , y * cos_ball - x * sin_ball ) ; }
2018-10-23 14:58:19 +00:00
void configure ( ) ;
2017-07-10 18:47:38 +00:00
extern bool autoband ;
extern bool autobandhistory ;
extern bool dospiral ;
extern ld lvspeed ;
extern int bandsegment ;
extern int bandhalf ;
2018-04-21 10:12:52 +00:00
extern ld extra_line_steps ;
2016-08-26 09:58:03 +00:00
2019-04-03 18:27:45 +00:00
void create ( cell * start , cell * target ) ;
void create_playerpath ( ) ;
void create_recenter_to_view ( ) ;
2016-08-26 09:58:03 +00:00
void clear ( ) ;
2018-03-25 12:04:40 +00:00
void model_menu ( ) ;
void history_menu ( ) ;
string get_model_name ( eModel ) ;
2016-08-26 09:58:03 +00:00
void apply ( ) ;
2017-05-27 19:40:40 +00:00
void movetophase ( ) ;
2016-08-26 09:58:03 +00:00
void renderAutoband ( ) ;
2017-05-27 19:40:40 +00:00
extern vector < shmup : : monster * > v ;
extern double phase ;
2017-07-10 18:47:38 +00:00
void applyIB ( ) ;
2018-03-24 14:18:53 +00:00
void progress_screen ( ) ;
void progress ( string str ) ;
2018-10-23 14:58:19 +00:00
bool model_has_orientation ( ) ;
2018-11-06 23:52:48 +00:00
extern string formula ;
extern eModel basic_model ;
2016-08-26 09:58:03 +00:00
}
namespace polygonal {
2017-07-10 18:47:38 +00:00
static const int MSI = 120 ;
2016-08-26 09:58:03 +00:00
extern int SI ;
2017-03-23 10:53:57 +00:00
extern ld STAR ;
2017-07-10 18:47:38 +00:00
extern int deg ;
2017-07-16 21:00:55 +00:00
extern ld coefr [ MSI ] , coefi [ MSI ] ;
2017-07-10 18:47:38 +00:00
extern int maxcoef , coefid ;
2016-08-26 09:58:03 +00:00
void solve ( ) ;
pair < ld , ld > compute ( ld x , ld y ) ;
}
void selectEyeGL ( int ed ) ;
void selectEyeMask ( int ed ) ;
extern int ticks ;
2018-02-01 12:42:47 +00:00
2018-09-04 17:53:42 +00:00
extern color_t backcolor , bordcolor , forecolor ;
2018-02-01 12:42:47 +00:00
2018-09-04 17:53:42 +00:00
void setGLProjection ( color_t col = backcolor ) ;
2016-08-26 09:58:03 +00:00
// passable flags
2017-09-30 09:46:41 +00:00
# define P_MONSTER Flag(0) // can move through monsters
# define P_MIRROR Flag(1) // can move through mirrors
# define P_REVDIR Flag(2) // reverse direction movement
# define P_WIND Flag(3) // can move against the wind
# define P_GRAVITY Flag(4) // can move against the gravity
# define P_ISPLAYER Flag(5) // player-only moves (like the Round Table jump)
# define P_ONPLAYER Flag(6) // always can step on the player
# define P_FLYING Flag(7) // is flying
# define P_BULLET Flag(8) // bullet can fly through more things
# define P_MIRRORWALL Flag(9) // mirror images go through mirror walls
# define P_JUMP1 Flag(10) // first part of a jump
# define P_JUMP2 Flag(11) // second part of a jump
# define P_TELE Flag(12) // teleport onto
# define P_BLOW Flag(13) // Orb of Air -- blow, or push
# define P_AETHER Flag(14) // aethereal
# define P_FISH Flag(15) // swimming
# define P_WINTER Flag(16) // fire resistant
# define P_USEBOAT Flag(17) // can use boat
# define P_NOAETHER Flag(18) // disable AETHER
# define P_FRIENDSWAP Flag(19) // can move on friends (to swap with tem)
# define P_ISFRIEND Flag(20) // is a friend (can use Empathy + Winter/Aether/Fish combo)
# define P_LEADER Flag(21) // can push statues and use boats
# define P_MARKWATER Flag(22) // mark Orb of Water as used
# define P_EARTHELEM Flag(23) // Earth Elemental
# define P_WATERELEM Flag(24) // Water Elemental
# define P_IGNORE37 Flag(25) // ignore the triheptagonal board
# define P_CHAIN Flag(26) // for chaining moves with boats
# define P_DEADLY Flag(27) // suicide moves allowed
# define P_ROSE Flag(28) // rose smell
# define P_CLIMBUP Flag(29) // allow climbing up
# define P_CLIMBDOWN Flag(30) // allow climbing down
# define P_REPTILE Flag(31) // is reptile
# define P_VOID Flag(32) // void beast
2017-12-30 22:47:10 +00:00
# define P_PHASE Flag(33) // phasing movement
2018-01-02 10:15:42 +00:00
# define P_PULLMAGNET Flag(34) // pull the other part of the magnet
2016-08-26 09:58:03 +00:00
2017-03-23 10:53:57 +00:00
bool passable ( cell * w , cell * from , flagtype flags ) ;
2016-08-26 09:58:03 +00:00
2018-12-23 02:14:48 +00:00
bool anti_alchemy ( cell * w , cell * from ) ;
2016-08-26 09:58:03 +00:00
bool isElemental ( eLand l ) ;
int coastval ( cell * c , eLand base ) ;
int getHauntedDepth ( cell * c ) ;
eLand randomElementalLand ( ) ;
bool notDippingForExtra ( eItem i , eItem x ) ;
void placePrizeOrb ( cell * c ) ;
void wandering ( ) ;
bool isSealand ( eLand l ) ;
int newRoundTableRadius ( ) ;
bool grailWasFound ( cell * c ) ;
extern bool buggyGeneration ;
int buildIvy ( cell * c , int children , int minleaf ) ;
int celldistAltRelative ( cell * c ) ;
int roundTableRadius ( cell * c ) ;
eLand pickLandRPM ( eLand old ) ;
bool bearsCamelot ( eLand l ) ;
extern bool safety ;
# define SAGEMELT .1
2019-03-13 12:12:49 +00:00
# define TEMPLE_EACH (among(geometry, gHoroRec, gHoroHex) ? 3 : (DIM == 3 && binarytiling) ? 2 : geometry == gSpace435 ? 4 : (DIM == 3 && hyperbolic) ? 3 : 6)
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 PUREHARDCORE_LEVEL 10
# 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
bool isKillable ( cell * c ) ;
bool isKillableSomehow ( cell * c ) ;
bool isAlchAny ( eWall w ) ;
bool isAlchAny ( cell * c ) ;
# define YDIST 101
2018-12-14 18:24:27 +00:00
# define MODECODES (1ll<<61)
2016-08-26 09:58:03 +00:00
extern cellwalker cwt ; // player character position
2018-01-25 16:20:41 +00:00
extern array < int , ittypes > items ;
extern array < int , motypes > kills ;
extern int explore [ 10 ] , exploreland [ 10 ] [ landtypes ] , landcount [ landtypes ] ;
2017-08-17 23:40:07 +00:00
2018-12-14 18:24:27 +00:00
typedef flagtype modecode_t ;
2017-08-17 23:40:07 +00:00
extern map < modecode_t , array < int , ittypes > > hiitems ;
2016-08-26 09:58:03 +00:00
2017-08-06 12:50:16 +00:00
extern eLand firstland , specialland ;
2016-08-26 09:58:03 +00:00
bool pseudohept ( cell * c ) ;
bool pureHardcore ( ) ;
extern int cheater ;
int airdist ( cell * c ) ;
bool eq ( short a , short b ) ;
extern vector < cell * > dcal ; // queue for cpdist
bool isPlayerOn ( cell * c ) ;
bool isFriendly ( eMonster m ) ;
bool isFriendly ( cell * c ) ;
bool isChild ( cell * w , cell * killed ) ; // is w killed if killed is killed?
2017-07-12 16:03:53 +00:00
static const int NO_TREASURE = 1 ;
static const int NO_YENDOR = 2 ;
static const int NO_GRAIL = 4 ;
static const int NO_LOVE = 8 ;
int gold ( int no = 0 ) ;
2016-08-26 09:58:03 +00:00
int tkills ( ) ;
bool markOrb ( eItem it ) ; // mark the orb as 'used', return true if exists
bool markEmpathy ( eItem it ) ; // mark both the given orb and Empathy as 'used', return true if exists
2017-03-23 10:53:57 +00:00
bool markEmpathy2 ( eItem it ) ; // as above, but next turn
2016-08-26 09:58:03 +00:00
bool isMimic ( eMonster m ) ;
bool isMimic ( cell * c ) ;
2017-03-23 10:53:57 +00:00
void fallMonster ( cell * c , flagtype flags = 0 ) ; // kill monster due to terrain
bool attackMonster ( cell * c , flagtype flags , eMonster killer ) ;
2016-08-26 09:58:03 +00:00
bool isWorm ( eMonster m ) ;
bool isWorm ( cell * c ) ;
void empathyMove ( cell * c , cell * cto , int dir ) ;
bool isIvy ( eMonster m ) ;
bool isIvy ( cell * c ) ;
# define GUNRANGE 3
2017-03-23 10:53:57 +00:00
// 0 = basic treasure, 1 = other item, 2 = power orb, 3 = not an item
2016-08-26 09:58:03 +00:00
# define IC_TREASURE 0
# define IC_OTHER 1
# define IC_ORB 2
2017-03-23 10:53:57 +00:00
# define IC_NAI 3
2016-08-26 09:58:03 +00:00
bool playerInPower ( ) ;
void activateFlash ( ) ;
void activateLightning ( ) ;
bool markOrb ( eItem it ) ;
bool markOrb2 ( eItem it ) ;
void drainOrb ( eItem it , int target = 0 ) ;
void useupOrb ( eItem it , int qty ) ;
void initgame ( ) ;
bool haveRangedTarget ( ) ;
eItem targetRangedOrb ( cell * c , orbAction a ) ;
void reduceOrbPowers ( ) ;
int realstuntime ( cell * c ) ;
extern bool invismove , invisfish ;
bool attackingForbidden ( cell * c , cell * c2 ) ;
2017-03-23 10:53:57 +00:00
void killOrStunMonster ( cell * c2 , eMonster who_killed ) ;
2016-08-26 09:58:03 +00:00
void useup ( cell * c ) ; // useup thumpers/bonfires
cell * playerpos ( int i ) ;
bool makeflame ( cell * c , int timeout , bool checkonly ) ;
void bfs ( ) ;
bool isPlayerInBoatOn ( cell * c ) ;
2017-03-23 10:53:57 +00:00
bool isPlayerInBoatOn ( cell * c , int i ) ;
void destroyBoats ( cell * c , cell * cf , bool strandedToo ) ;
2016-08-26 09:58:03 +00:00
extern bool showoff ;
extern int lastexplore ;
extern int truelotus ;
2019-03-30 16:51:37 +00:00
extern int asteroids_generated , asteroid_orbs_generated ;
2016-08-26 09:58:03 +00:00
extern eLand lastland ;
extern time_t timerstart ;
extern bool timerstopped ;
bool againstRose ( cell * cfrom , cell * cto ) ;
bool withRose ( cell * cfrom , cell * cto ) ;
2019-04-04 12:36:45 +00:00
extern ld bounded_mine_percentage ;
extern int bounded_mine_quantity , bounded_mine_max ;
void generate_mines ( ) ;
2016-08-26 09:58:03 +00:00
// 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
2017-03-23 10:53:57 +00:00
bool canAttack ( cell * c1 , eMonster m1 , cell * c2 , eMonster m2 , flagtype flags ) ;
2016-08-26 09:58:03 +00:00
extern bool chaosmode ;
extern bool chaosUnlocked ;
extern bool chaosAchieved ;
bool isTechnicalLand ( eLand l ) ;
int getGhostcount ( ) ;
void raiseBuggyGeneration ( cell * c , const char * s ) ;
void verifyMutantAround ( cell * c ) ;
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
void drawscreen ( ) ;
void buildAirmap ( ) ;
// currently works for worms only
bool sameMonster ( cell * c1 , cell * c2 ) ;
cell * wormhead ( cell * c ) ;
2017-03-23 10:53:57 +00:00
eMonster getMount ( int player_id ) ;
eMonster haveMount ( ) ;
2016-08-26 09:58:03 +00:00
bool isDragon ( eMonster m ) ;
// for some reason I need this to compile under OSX
2017-07-22 23:33:27 +00:00
# if ISMAC
2016-08-26 09:58:03 +00:00
extern " C " { void * _Unwind_Resume = 0 ; }
# endif
extern bool autocheat ;
extern bool inHighQual ;
void mountmove ( cell * c , int spin , bool fp ) ;
2017-03-23 10:53:57 +00:00
void mountmove ( cell * c , int spin , bool fp , cell * ppos ) ;
void mountswap ( cell * c1 , int spin1 , bool fp1 , cell * c2 , int spin2 , bool fp2 ) ;
2016-08-26 09:58:03 +00:00
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 ; }
} ;
2017-03-23 10:53:57 +00:00
struct stalemate1 {
2016-08-26 09:58:03 +00:00
eMonster who ;
cell * moveto ;
cell * killed ;
cell * pushto ;
cell * comefrom ;
2017-03-23 10:53:57 +00:00
cell * swordlast [ 2 ] , * swordtransit [ 2 ] , * swordnext [ 2 ] ;
bool isKilled ( cell * c ) ;
stalemate1 ( eMonster w , cell * mt , cell * ki , cell * pt , cell * cf ) : who ( w ) , moveto ( mt ) , killed ( ki ) , pushto ( pt ) , comefrom ( cf ) { }
} ;
namespace stalemate {
2017-10-29 11:46:57 +00:00
extern vector < stalemate1 > moves ;
extern bool nextturn ;
2016-08-26 09:58:03 +00:00
bool isKilled ( cell * c ) ;
2017-03-23 10:53:57 +00:00
bool isMoveto ( cell * c ) ;
bool isKilledDirectlyAt ( cell * c ) ;
bool isPushto ( cell * c ) ;
2016-08-26 09:58:03 +00:00
} ;
extern int turncount ;
bool reduceOrbPower ( eItem it , int cap ) ;
bool checkOrb ( eMonster m1 , eItem orb ) ;
2017-03-23 10:53:57 +00:00
movedir vectodir ( const hyperpoint & P ) ;
2018-01-14 20:21:32 +00:00
namespace tortoise {
extern int seekbits ;
int getRandomBits ( ) ;
}
2019-02-26 13:10:23 +00:00
# define sword_angles (S7*S3*2)
2017-03-23 10:53:57 +00:00
namespace sword {
extern int angle [ MAXPLAYER ] ;
cell * pos ( cell * c , int s ) ;
cell * pos ( int id ) ;
bool at ( cell * where , bool noplayer = false ) ;
int shift ( cell * c1 , cell * c2 ) ;
}
void killThePlayer ( eMonster m , int id , flagtype flags ) ;
2018-12-16 23:04:59 +00:00
bool attackJustStuns ( cell * c2 , flagtype flags , eMonster attacker ) ;
2017-03-23 10:53:57 +00:00
bool isTargetOrAdjacent ( cell * c ) ;
2018-12-14 12:26:17 +00:00
bool warningprotection ( const string & s ) ;
2017-03-23 10:53:57 +00:00
bool mineMarked ( cell * c ) ;
bool minesafe ( ) ;
bool hasSafeOrb ( cell * c ) ;
void placeWater ( cell * c , cell * c2 ) ;
bool againstCurrent ( cell * w , cell * from ) ;
2018-12-14 17:21:52 +00:00
bool needConfirmation ( ) ;
bool needConfirmationEvenIfSaved ( ) ;
2017-03-23 10:53:57 +00:00
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
2019-02-25 17:39:36 +00:00
extern bool smooth_scrolling ;
2017-03-23 10:53:57 +00:00
extern bool timerghost ;
2018-12-24 14:10:52 +00:00
extern bool gen_wandering ;
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
namespace dialog {
2018-02-08 21:27:12 +00:00
extern string highlight_text ;
2018-09-05 13:18:40 +00:00
extern color_t dialogcolor ;
2019-04-15 21:29:07 +00:00
extern int dfsize , dfspace ;
2017-03-23 10:53:57 +00:00
2017-08-06 12:50:16 +00:00
enum tDialogItem { diTitle , diItem , diBreak , diHelp , diInfo , diSlider , diBigItem } ;
2017-03-23 10:53:57 +00:00
struct item {
tDialogItem type ;
string body ;
string value ;
string keycaption ;
int key ;
2018-09-04 17:53:42 +00:00
color_t color , colorv , colork , colors , colorc ;
2017-03-23 10:53:57 +00:00
int scale ;
double param ;
2017-07-04 13:38:33 +00:00
int position ;
2017-03-23 10:53:57 +00:00
} ;
2018-09-10 14:47:28 +00:00
struct scaler {
ld ( * direct ) ( ld ) ;
ld ( * inverse ) ( ld ) ;
bool positive ;
} ;
static inline ld identity_f ( ld x ) { return x ; } ;
const static scaler identity = { identity_f , identity_f , false } ;
const static scaler logarithmic = { log , exp , true } ;
const static scaler asinhic = { asinh , sinh , false } ;
2018-03-29 22:20:50 +00:00
struct numberEditor {
ld * editwhat ;
string s ;
ld vmin , vmax , step , dft ;
string title , help ;
2018-09-10 14:47:28 +00:00
scaler sc ;
2018-03-29 22:20:50 +00:00
int * intval ; ld intbuf ;
2018-11-09 19:41:55 +00:00
bool animatable ;
2018-03-29 22:20:50 +00:00
} ;
extern numberEditor ne ;
2017-03-23 10:53:57 +00:00
2017-07-10 18:47:38 +00:00
extern vector < item > items ;
2017-10-17 19:26:21 +00:00
2018-11-06 23:50:03 +00:00
extern reaction_t reaction , extra_options , reaction_final ;
2017-07-10 18:47:38 +00:00
2017-03-23 10:53:57 +00:00
item & lastItem ( ) ;
2018-09-04 17:53:42 +00:00
extern color_t * palette ;
2017-10-29 19:04:27 +00:00
string keyname ( int k ) ;
2017-03-23 10:53:57 +00:00
2018-08-01 01:59:20 +00:00
string disp ( ld x ) ;
2017-03-23 10:53:57 +00:00
void addSelItem ( string body , string value , int key ) ;
void addBoolItem ( string body , bool value , int key ) ;
2018-01-14 20:21:32 +00:00
void addBigItem ( string body , int key ) ;
2017-03-23 10:53:57 +00:00
void addColorItem ( string body , int value , int key ) ;
2018-09-04 17:53:42 +00:00
void openColorDialog ( color_t & col , color_t * pal = palette ) ;
2018-11-08 20:56:06 +00:00
extern bool colorAlpha ;
2017-03-23 10:53:57 +00:00
void addHelp ( string body ) ;
2018-09-05 13:18:40 +00:00
void addInfo ( string body , color_t color = dialogcolor ) ;
2017-03-23 10:53:57 +00:00
void addItem ( string body , int key ) ;
2017-07-04 13:38:33 +00:00
int addBreak ( int val ) ;
2018-09-04 17:53:42 +00:00
void addTitle ( string body , color_t color , int scale ) ;
2017-03-23 10:53:57 +00:00
void init ( ) ;
2018-09-04 17:53:42 +00:00
void init ( string title , color_t color = 0xE8E8E8 , int scale = 150 , int brk = 60 ) ;
2017-03-23 10:53:57 +00:00
void display ( ) ;
void editNumber ( ld & x , ld vmin , ld vmax , ld step , ld dft , string title , string help ) ;
void editNumber ( int & x , int vmin , int vmax , int step , int dft , string title , string help ) ;
2019-01-18 20:04:29 +00:00
void use_hexeditor ( ) ;
2018-09-10 14:47:28 +00:00
inline void scaleLog ( ) { ne . sc = logarithmic ; }
inline void scaleSinh ( ) { ne . sc = asinhic ; }
2018-11-09 19:41:55 +00:00
void bound_low ( ld val ) ;
void bound_up ( ld val ) ;
2017-03-23 10:53:57 +00:00
void handleNavigation ( int & sym , int & uni ) ;
2018-07-22 10:54:05 +00:00
namespace zoom {
2018-09-04 17:53:42 +00:00
bool displayfr ( int x , int y , int b , int size , const string & s , color_t color , int align ) ;
bool displayfr_highlight ( int x , int y , int b , int size , const string & s , color_t color , int align , int hicolor = 0xFFFF00 ) ;
2018-07-22 10:54:05 +00:00
}
2017-03-23 10:53:57 +00:00
bool editingDetail ( ) ;
int handlePage ( int & nl , int & nlm , int perpage ) ;
void displayPageButtons ( int i , bool pages ) ;
bool handlePageButtons ( int uni ) ;
2017-04-04 09:37:16 +00:00
extern bool sidedialog ;
2017-12-03 10:48:02 +00:00
extern int dialogflags ;
2017-12-03 17:25:31 +00:00
extern int dcenter ;
2018-09-04 17:53:42 +00:00
int displaycolor ( color_t col ) ;
2017-12-09 03:01:56 +00:00
2017-12-14 11:10:40 +00:00
void openFileDialog ( string & filename , string fcap , string ext , bool_reaction_t action ) ;
2017-12-09 03:01:56 +00:00
extern string infix ;
bool hasInfix ( const string & s ) ;
bool editInfix ( int uni ) ;
2018-09-05 13:18:40 +00:00
void vpush ( color_t , const char * name ) ;
extern vector < pair < string , color_t > > v ;
2018-06-12 22:00:01 +00:00
void addHelp ( ) ;
void addBack ( ) ;
2018-12-14 12:26:17 +00:00
void add_action ( const reaction_t & action ) ;
void add_key_action ( int key , const reaction_t & action ) ;
2019-03-30 22:45:28 +00:00
void add_action_push ( const reaction_t & action ) ;
2018-11-06 23:50:03 +00:00
string view_edited_string ( ) ;
void start_editing ( string & s ) ;
2018-11-24 21:49:45 +00:00
string editchecker ( int sym , int uni ) ;
bool handle_edit_string ( int sym , int uni , function < string ( int , int ) > checker = editchecker ) ;
2018-11-06 23:50:03 +00:00
void edit_string ( string & s , string title , string help ) ;
2018-12-14 17:21:52 +00:00
void confirm_dialog ( const string & text , const reaction_t & act ) ;
2018-12-14 17:22:21 +00:00
inline void cheat_if_confirmed ( const reaction_t & act ) {
if ( needConfirmationEvenIfSaved ( ) ) pushScreen ( [ act ] ( ) { confirm_dialog ( XLAT ( " This will enable the cheat mode, making this game ineligible for scoring. Are you sure? " ) , act ) ; } ) ;
2018-12-14 17:21:52 +00:00
else act ( ) ;
}
2018-12-14 17:22:21 +00:00
inline void do_if_confirmed ( const reaction_t & act ) {
if ( needConfirmationEvenIfSaved ( ) ) pushScreen ( [ act ] ( ) { confirm_dialog ( XLAT ( " This will end your current game and start a new one. Are you sure? " ) , act ) ; } ) ;
2018-12-14 17:21:52 +00:00
else act ( ) ;
}
2018-12-14 17:22:21 +00:00
inline reaction_t add_confirmation ( const reaction_t & act ) {
2018-12-14 17:21:52 +00:00
return [ act ] { do_if_confirmed ( act ) ; } ;
}
2017-03-23 10:53:57 +00:00
}
void checkStunKill ( cell * dest ) ;
void clearMessages ( ) ;
void resetGeometry ( ) ;
2018-12-13 12:33:08 +00:00
namespace shot {
2019-02-17 17:43:39 +00:00
# if CAP_SHOT
2018-12-13 12:33:08 +00:00
extern int shotx , shoty , shotformat ;
extern bool make_svg ;
2018-12-13 13:53:44 +00:00
extern ld gamma , fade ;
extern string caption ;
2018-12-13 16:57:26 +00:00
extern bool transparent ;
2018-12-13 12:33:08 +00:00
void menu ( ) ;
void default_screenshot_content ( ) ;
void take ( string fname , const function < void ( ) > & what = default_screenshot_content ) ;
2019-02-17 17:43:39 +00:00
# endif
2018-12-13 12:33:08 +00:00
}
2019-02-17 17:43:39 +00:00
# if CAP_SVG
2017-03-23 10:53:57 +00:00
namespace svg {
2018-12-13 16:03:39 +00:00
void circle ( int x , int y , int size , color_t col , color_t fillcolor , double linewidth ) ;
2018-09-04 19:43:43 +00:00
void polygon ( int * polyx , int * polyy , int polyi , color_t col , color_t outline , double linewidth ) ;
2018-09-04 17:53:42 +00:00
void text ( int x , int y , int size , const string & str , bool frame , color_t col , int align ) ;
2017-03-23 10:53:57 +00:00
extern bool in ;
2018-09-04 17:53:42 +00:00
extern string link ;
2019-02-17 17:43:39 +00:00
# if CAP_SHOT
2018-12-13 12:33:08 +00:00
void render ( const string & fname , const function < void ( ) > & what = shot : : default_screenshot_content ) ;
2019-02-17 17:43:39 +00:00
# endif
}
# else
namespace svg {
static const always_false in ;
2017-03-23 10:53:57 +00:00
}
2019-02-17 17:43:39 +00:00
# endif
2017-03-23 10:53:57 +00:00
2018-04-03 21:34:47 +00:00
extern int sightrange_bonus , genrange_bonus , gamerange_bonus ;
2017-03-23 10:53:57 +00:00
namespace halloween {
void getTreat ( cell * where ) ;
}
// just in case if I change my mind about when Orbs lose their power
# define ORBBASE 0
transmatrix mscale ( const transmatrix & t , double fac ) ;
transmatrix mzscale ( const transmatrix & t , double fac ) ;
extern bool ivoryz ;
# 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
2019-03-30 19:06:35 +00:00
transmatrix face_the_player ( const transmatrix V ) ;
hyperpoint makeradar ( transmatrix V ) ;
2018-09-04 17:53:42 +00:00
bool drawMonsterType ( eMonster m , cell * where , const transmatrix & V , color_t col , double footphase ) ;
2018-07-09 19:02:23 +00:00
2017-03-23 10:53:57 +00:00
void drawPlayerEffects ( const transmatrix & V , cell * c , bool onPlayer ) ;
// monster movement animations
struct animation {
int ltick ;
double footphase ;
transmatrix wherenow ;
2018-01-25 16:19:50 +00:00
int attacking ;
transmatrix attackat ;
2017-03-23 10:53:57 +00:00
} ;
// we need separate animation layers for Orb of Domination and Tentacle+Ghost,
// and also to mark Boats
# define ANIMLAYERS 3
# define LAYER_BIG 0 // for worms and krakens
# define LAYER_SMALL 1 // for others
# define LAYER_BOAT 2 // mark that a boat has moved
extern map < cell * , animation > animations [ ANIMLAYERS ] ;
2018-06-17 15:51:26 +00:00
void animateAttack ( cell * src , cell * tgt , int layer , int direction_hint ) ;
2018-01-25 16:19:50 +00:00
2018-06-17 15:51:26 +00:00
void animateMovement ( cell * src , cell * tgt , int layer , int direction_hint ) ;
2017-03-23 10:53:57 +00:00
// for animations which might use the same locations,
// such as replacements or multi-tile monsters
2018-06-17 15:51:26 +00:00
void indAnimateMovement ( cell * src , cell * tgt , int layer , int direction_hint ) ;
2017-03-23 10:53:57 +00:00
void commitAnimations ( int layer ) ;
2018-06-17 15:51:26 +00:00
void animateReplacement ( cell * a , cell * b , int layer , int direction_hinta , int direction_hintb ) ;
2017-03-23 10:53:57 +00:00
void fallingFloorAnimation ( cell * c , eWall w = waNone , eMonster m = moNone ) ;
2017-08-06 12:50:16 +00:00
void fallingMonsterAnimation ( cell * c , eMonster m , int id = multi : : cpid ) ;
2017-03-23 10:53:57 +00:00
// ranks:
2018-08-28 12:27:23 +00:00
enum class PPR {
ZERO , OUTCIRCLE , MOVESTAR ,
MINUSINF ,
BELOWBOTTOMm ,
BELOWBOTTOM ,
BELOWBOTTOMp ,
BELOWBOTTOM_FALLANIM ,
LAKEBOTTOM , HELLSPIKE ,
INLAKEWALLm , INLAKEWALL , INLAKEWALLp ,
INLAKEWALL_FALLANIM ,
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 ,
PARTICLE , SWORDMARK , MAGICSWORD , MISSILE ,
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
// and set to PPR::TRANSPARENT to draw them after all the opaque ones
TRANSPARENT ,
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
2018-08-28 11:45:11 +00:00
namespace mapeditor {
2018-09-04 17:53:42 +00:00
bool drawUserShape ( const transmatrix & V , eShapegroup group , int id , color_t color , cell * c , PPR prio = PPR : : DEFAULT ) ;
2018-08-28 11:45:11 +00:00
}
2019-02-17 18:39:44 +00:00
# if CAP_SHAPES
2018-08-28 12:27:23 +00:00
void ShadowV ( const transmatrix & V , const struct hpcshape & bp , PPR prio = PPR : : MONSTER_SHADOW ) ;
2019-02-17 18:39:44 +00:00
# endif
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
extern bool audio ;
extern string musiclicense ;
extern string musfname [ landtypes ] ;
extern int musicvolume , effvolume ;
void initAudio ( ) ;
bool loadMusicInfo ( ) ;
void handlemusic ( ) ;
void playSeenSound ( cell * c ) ;
void playSound ( cell * c , const string & fname , int vol = 100 ) ;
inline string pick123 ( ) { return cts ( ' 1 ' + rand ( ) % 3 ) ; }
inline string pick12 ( ) { return cts ( ' 1 ' + rand ( ) % 2 ) ; }
bool playerInBoat ( int i ) ;
extern int lowfar ;
extern bool wmspatial , wmescher , wmplain , wmblack , wmascii ;
extern bool mmspatial , mmhigh , mmmon , mmitem ;
2018-12-05 18:57:35 +00:00
extern bool spatial_graphics ;
2017-03-23 10:53:57 +00:00
extern int maxreclevel , reclevel ;
string explain3D ( ld * param ) ;
extern int detaillevel ;
extern bool quitmainloop ;
enum eGlyphsortorder {
gsoFirstTop , gsoFirstBottom ,
gsoLastTop , gsoLastBottom ,
gsoLand , gsoValue ,
gsoMAX
} ;
extern eGlyphsortorder glyphsortorder ;
void explodeMine ( cell * c ) ;
bool mayExplodeMine ( cell * c , eMonster who ) ;
2018-12-16 23:04:59 +00:00
void explosion ( cell * c , int power , int central ) ;
void explodeBarrel ( cell * c ) ;
2017-03-23 10:53:57 +00:00
2018-12-23 02:14:48 +00:00
enum eGravity { gsNormal , gsLevitation , gsAnti } ;
extern eGravity gravity_state , last_gravity_state ;
2017-03-23 10:53:57 +00:00
int gravityLevel ( cell * c ) ;
2018-12-21 13:41:23 +00:00
int gravityLevelDiff ( cell * c , cell * f ) ;
2017-03-23 10:53:57 +00:00
void fullcenter ( ) ;
2018-08-01 12:04:47 +00:00
void movecost ( cell * from , cell * to , int phase ) ; // 1 = pre-collect, 2 = post-collect, 3 = both
2017-03-23 10:53:57 +00:00
void checkmove ( ) ;
2017-11-07 13:39:26 +00:00
transmatrix eumove ( ld x , ld y ) ;
2017-12-28 15:46:10 +00:00
transmatrix eumove ( int vec ) ;
2017-06-18 16:51:46 +00:00
transmatrix eumovedir ( int d ) ;
2017-03-23 10:53:57 +00:00
int reptilemax ( ) ;
extern bool mousing ;
# define IFM(x) (mousing?"":x)
extern cell * recallCell ;
extern eLand cheatdest ;
void cheatMoveTo ( eLand l ) ;
void doOvergenerate ( ) ;
void collectMessage ( cell * c2 , eItem which ) ;
namespace quotientspace {
void build ( ) ;
void clear ( ) ;
extern vector < int > connections ;
}
void killFriendlyIvy ( ) ;
2019-02-17 18:39:44 +00:00
# if CAP_SHAPES
2017-03-23 10:53:57 +00:00
void pushdown ( cell * c , int & q , const transmatrix & V , double down , bool rezoom , bool repriority ) ;
2019-02-17 18:39:44 +00:00
# endif
2017-03-23 10:53:57 +00:00
extern bool viewdists ;
void preventbarriers ( cell * c ) ;
bool passable_for ( eMonster m , cell * w , cell * from , flagtype extra ) ;
void beastcrash ( cell * c , cell * beast ) ;
int angledist ( int t , int d1 , int d2 ) ;
int angledist ( cell * c , int d1 , int d2 ) ;
void setcameraangle ( bool b ) ;
# define MODELCOUNT ((int) mdGUARD)
2018-09-04 17:53:42 +00:00
void drawShape ( pair < ld , ld > * coords , int qty , color_t color ) ;
2017-03-23 10:53:57 +00:00
extern eModel pmodel ;
2019-04-04 15:23:53 +00:00
string current_proj_name ( ) ;
2017-03-23 10:53:57 +00:00
2019-03-30 16:45:56 +00:00
inline bool mdAzimuthalEqui ( ) { return among ( pmodel , mdEquidistant , mdEquiarea , mdEquivolume ) ; }
2018-03-26 17:06:47 +00:00
2019-03-30 16:45:56 +00:00
inline bool mdBandAny ( ) { return among ( pmodel , mdBand , mdBandEquidistant , mdBandEquiarea , mdSinusoidal ) ; }
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
# define SHSIZE 16
extern cell * shpos [ MAXPLAYER ] [ SHSIZE ] ;
extern int cshpos ;
2019-02-17 17:43:39 +00:00
# if CAP_ANIMATIONS
2018-11-09 19:41:55 +00:00
namespace anims {
void animate_parameter ( ld & x , string f , const reaction_t & r ) ;
void deanimate ( ld & x ) ;
void get_parameter_animation ( ld & x , string & f ) ;
2018-11-09 20:18:58 +00:00
extern ld a , b ;
2018-11-09 19:41:55 +00:00
}
2019-02-17 17:43:39 +00:00
# endif
2017-03-23 10:53:57 +00:00
namespace arg {
2017-07-22 23:33:27 +00:00
# if CAP_COMMANDLINE
2017-03-23 10:53:57 +00:00
2018-02-26 12:14:20 +00:00
void lshift ( ) ;
2019-04-23 10:02:58 +00:00
void unshift ( ) ;
2017-03-23 10:53:57 +00:00
2018-02-26 12:14:20 +00:00
void shift ( ) ;
2017-03-23 10:53:57 +00:00
2018-02-26 12:14:20 +00:00
const string & args ( ) ;
2018-04-21 10:17:22 +00:00
const char * argcs ( ) ;
2018-02-26 12:14:20 +00:00
int argi ( ) ;
ld argf ( ) ;
bool argis ( const string & s ) ;
2019-04-22 20:59:37 +00:00
bool nomore ( ) ;
2018-07-09 16:07:47 +00:00
unsigned arghex ( ) ;
2018-11-09 13:26:31 +00:00
2019-02-17 17:43:39 +00:00
inline void shift_arg_formula ( ld & x , const reaction_t & r = reaction_t ( ) ) { shift ( ) ; x = argf ( ) ;
# if CAP_ANIMATIONS
anims : : animate_parameter ( x , args ( ) , r ) ;
# endif
}
2017-03-23 10:53:57 +00:00
2018-02-26 12:14:20 +00:00
void init ( int _argc , char * * _argv ) ;
2017-03-23 10:53:57 +00:00
2018-11-11 10:06:32 +00:00
void launch_dialog ( const reaction_t & r = reaction_t ( ) ) ;
2017-10-29 11:46:57 +00:00
extern int curphase ;
2017-03-23 10:53:57 +00:00
2018-02-26 12:14:20 +00:00
void phaseerror ( int x ) ;
2017-03-23 10:53:57 +00:00
// returned values: 0 = ok, 1 = not recognized, 2 = shift phase
int readCommon ( ) ;
int readLocal ( ) ;
// an useful macro
2019-01-07 03:51:46 +00:00
# define PHASE(x) { if(arg::curphase > x) arg::phaseerror(x); else if(arg::curphase < x) return 2; }
2017-05-27 19:40:40 +00:00
# define PHASEFROM(x) { if(arg::curphase < x) return 2; }
2018-07-19 21:46:58 +00:00
2018-07-21 16:03:53 +00:00
inline void cheat ( ) { autocheat = true ; cheater + + ; timerghost = false ; }
2018-07-19 21:46:58 +00:00
# define TOGGLE(x, param, act) \
else if ( args ( ) [ 0 ] = = ' - ' & & args ( ) [ 1 ] = = x & & ! args ( ) [ 2 ] ) { PHASEFROM ( 2 ) ; showstartmenu = false ; act ; } \
else if ( args ( ) [ 0 ] = = ' - ' & & args ( ) [ 1 ] = = x & & args ( ) [ 2 ] = = ' 1 ' ) { PHASEFROM ( 2 ) ; showstartmenu = false ; if ( ! param ) act ; } \
else if ( args ( ) [ 0 ] = = ' - ' & & args ( ) [ 1 ] = = x & & args ( ) [ 2 ] = = ' 0 ' ) { PHASEFROM ( 2 ) ; showstartmenu = false ; if ( param ) act ; }
2017-03-23 10:53:57 +00:00
void read ( int phase ) ;
2018-07-19 22:04:23 +00:00
eLand readland ( const string & ss ) ;
eItem readItem ( const string & ss ) ;
eMonster readMonster ( const string & ss ) ;
2017-03-23 10:53:57 +00:00
# endif
}
extern bool generatingEquidistant ;
2017-04-04 09:37:16 +00:00
void clearfrom ( heptagon * at ) ;
void clearHexes ( heptagon * at ) ;
void verifycells ( heptagon * at ) ;
int zebra40 ( cell * c ) ;
cell * createMov ( cell * c , int d ) ;
2017-04-08 15:18:29 +00:00
2017-07-22 23:33:27 +00:00
# if CAP_TOUR
2017-04-08 15:18:29 +00:00
namespace tour {
extern bool on ;
extern string tourhelp ;
2017-05-27 19:40:40 +00:00
extern string slidecommand ;
2017-07-04 13:38:33 +00:00
extern int currentslide ;
2017-04-08 15:18:29 +00:00
2017-05-27 19:40:40 +00:00
enum presmode {
pmStartAll = 0 ,
pmStart = 1 , pmFrame = 2 , pmStop = 3 , pmKey = 4 , pmRestart = 5 ,
2017-07-10 18:47:38 +00:00
pmAfterFrame = 6 ,
2017-05-27 19:40:40 +00:00
pmGeometry = 11 , pmGeometryReset = 13 , pmGeometryStart = 15
} ;
2017-06-18 16:51:46 +00:00
void setCanvas ( presmode mode , char canv ) ;
2017-05-27 19:40:40 +00:00
void presentation ( presmode mode ) ;
2017-04-14 18:12:23 +00:00
void checkGoodLand ( eLand l ) ;
2017-04-08 15:18:29 +00:00
int getid ( ) ;
2017-05-27 19:40:40 +00:00
extern function < eLand ( eLand ) > getNext ;
extern function < bool ( eLand ) > quickfind ;
extern function < bool ( eLand ) > showland ;
2017-04-08 15:18:29 +00:00
void start ( ) ;
2017-06-18 16:51:46 +00:00
struct slide {
const char * name ; int unused_id ; int flags ; const char * help ;
function < void ( presmode mode ) > action ;
} ;
extern slide * slides ;
extern slide default_slides [ ] ;
static const int LEGAL_NONE = 0 ;
static const int LEGAL_UNLIMITED = 1 ;
static const int LEGAL_HYPERBOLIC = 2 ;
static const int LEGAL_ANY = 3 ;
static const int LEGAL_NONEUC = 4 ;
static const int QUICKSKIP = 8 ;
static const int FINALSLIDE = 16 ;
2017-07-04 13:38:33 +00:00
static const int QUICKGEO = 32 ;
static const int SIDESCREEN = 64 ;
2018-04-22 09:10:19 +00:00
static const int USE_SLIDE_NAME = 128 ;
2017-06-18 16:51:46 +00:00
extern slide slideHypersian ;
extern slide slideExpansion ;
2017-07-04 13:38:33 +00:00
namespace ss {
void showMenu ( ) ;
void list ( slide * ) ;
}
2018-07-09 17:55:56 +00:00
extern hookset < void ( int ) > * hooks_slide ;
2017-04-08 15:18:29 +00:00
} ;
2019-02-17 17:50:56 +00:00
# else
namespace tour {
static const always_false on ;
}
2017-04-08 15:18:29 +00:00
# endif
2017-05-27 19:40:40 +00:00
extern bool doCross ;
void optimizeview ( ) ;
extern bool noGUI ;
extern bool dronemode ;
extern ld whatever ;
2017-07-12 17:50:39 +00:00
namespace sm {
static const int NORMAL = 1 ;
static const int MISSION = 2 ;
static const int HELP = 4 ;
static const int MAP = 8 ;
static const int DRAW = 16 ;
static const int NUMBER = 32 ;
static const int SHMUPCONFIG = 64 ;
static const int OVERVIEW = 128 ;
static const int SIDE = 256 ;
static const int DOTOUR = 512 ;
static const int CENTER = 1024 ;
static const int A3 = 2048 ; // affects poly
2017-07-22 23:33:27 +00:00
static const int ZOOMABLE = 4096 ;
2017-11-06 20:18:40 +00:00
static const int TORUSCONFIG = 8192 ;
2017-12-03 10:48:02 +00:00
static const int MAYDARK = 16384 ;
2017-12-14 01:50:52 +00:00
static const int DIALOG_STRICT_X = 32768 ; // do not interpret dialog clicks outside of the X region
2018-09-13 18:38:06 +00:00
static const int EXPANSION = ( 1 < < 16 ) ;
2019-01-18 20:04:29 +00:00
static const int HEXEDIT = ( 1 < < 17 ) ;
2017-07-12 17:50:39 +00:00
} ;
2017-07-10 18:47:38 +00:00
2017-05-27 19:40:40 +00:00
namespace linepatterns {
enum ePattern {
patPalacelike ,
patPalace ,
patZebraTriangles ,
patZebraLines ,
2018-09-21 17:51:13 +00:00
patTriTree ,
2017-05-27 19:40:40 +00:00
patTriRings ,
patHepta ,
patRhomb ,
patTree ,
patAltTree ,
patVine ,
patPower ,
patNormal ,
patTrihepta ,
2017-07-04 13:38:33 +00:00
patBigTriangles ,
2018-04-10 15:57:33 +00:00
patBigRings ,
2018-09-21 17:51:13 +00:00
patHorocycles ,
patTriOther ,
2018-11-08 21:21:46 +00:00
patDual ,
patMeridians ,
patParallels ,
patCircles ,
patRadii
2017-05-27 19:40:40 +00:00
} ;
void clearAll ( ) ;
2018-09-04 17:53:42 +00:00
void setColor ( ePattern id , color_t col ) ;
2017-05-27 19:40:40 +00:00
void drawAll ( ) ;
2017-07-10 18:47:38 +00:00
void showMenu ( ) ;
2018-09-04 17:53:42 +00:00
void switchAlpha ( ePattern id , color_t col ) ;
2018-09-21 17:51:13 +00:00
struct linepattern {
int id ;
const char * lpname ;
color_t color ;
} ;
2018-09-21 19:31:11 +00:00
extern vector < linepattern > patterns ;
2018-11-08 21:34:23 +00:00
extern ld width ;
2017-05-27 19:40:40 +00:00
} ;
2018-08-19 13:52:39 +00:00
transmatrix ddspin ( cell * c , int d , ld bonus = 0 ) ;
transmatrix iddspin ( cell * c , int d , ld bonus = 0 ) ;
2017-05-27 19:40:40 +00:00
bool doexiton ( int sym , int uni ) ;
void switchFullscreen ( ) ;
string turnstring ( int i ) ;
int celldistance ( cell * c1 , cell * c2 ) ;
2018-09-23 11:56:00 +00:00
int hyperbolic_celldistance ( cell * c1 , cell * c2 ) ;
2017-05-27 19:40:40 +00:00
bool behindsphere ( const transmatrix & V ) ;
2017-05-28 22:16:17 +00:00
extern hyperpoint pirateCoords ;
2017-05-31 16:33:50 +00:00
2017-06-18 16:51:46 +00:00
bool mouseout ( ) ;
bool againstWind ( cell * c2 , cell * c1 ) ; // to, from
transmatrix atscreenpos ( ld x , ld y , ld size ) ;
hyperpoint mirrorif ( const hyperpoint & V , bool b ) ;
# define SETMOUSEKEY 5000
extern char mousekey ;
extern char newmousekey ;
void displaymm ( char c , int x , int y , int rad , int size , const string & title , int align ) ;
bool canPushThumperOn ( cell * tgt , cell * thumper , cell * player ) ;
void pushThumper ( cell * th , cell * cto ) ;
2017-07-04 13:38:33 +00:00
2018-01-02 10:15:42 +00:00
template < class T , class . . . U > T pick ( T x , U . . . u ) { std : : initializer_list < T > i = { x , u . . . } ; return * ( i . begin ( ) + hrand ( 1 + sizeof . . . ( u ) ) ) ; }
2017-07-04 13:38:33 +00:00
eLand getNewSealand ( eLand old ) ;
bool createOnSea ( eLand old ) ;
namespace inv {
2017-07-12 16:03:53 +00:00
extern bool on ;
2017-07-16 21:00:55 +00:00
extern bool usedForbidden ;
2018-01-25 16:20:13 +00:00
extern bool activating ;
extern array < int , ittypes > remaining ;
extern array < int , ittypes > usedup ;
2017-07-12 16:03:53 +00:00
void compute ( ) ;
2017-07-16 21:00:55 +00:00
void applyBox ( eItem it ) ;
extern int incheck ;
void check ( int delta ) ;
void show ( ) ;
2017-07-04 13:38:33 +00:00
}
2019-02-28 15:24:46 +00:00
bool drawItemType ( eItem it , cell * c , const transmatrix & V , color_t icol , int ticks , bool hidden ) ;
2017-07-04 13:38:33 +00:00
void initquickqueue ( ) ;
void quickqueue ( ) ;
int darkenedby ( int c , int lev ) ;
extern int mousex , mousey ;
2019-02-26 01:35:30 +00:00
extern ld mouseaim_x , mouseaim_y , mouseaim_sensitivity ;
2017-07-04 13:38:33 +00:00
string generateHelpForItem ( eItem it ) ;
bool graphglyph ( ) ;
extern bool hiliteclick ;
extern int antialiaslines ;
2019-03-08 21:40:34 +00:00
extern color_t ringcolor , periodcolor , modelcolor , stdgridcolor ;
2017-07-10 18:47:38 +00:00
# include <functional>
template < class T , class U > int addHook ( hookset < T > * & m , int prio , const U & hook ) {
if ( ! m ) m = new hookset < T > ( ) ;
2017-07-16 21:00:55 +00:00
while ( m - > count ( prio ) ) {
prio + + ;
}
2017-07-10 18:47:38 +00:00
( * m ) [ prio ] = hook ;
return 0 ;
}
2018-09-06 20:34:35 +00:00
extern purehookset hooks_frame , hooks_stats , clearmemory , hooks_config , hooks_tests , hooks_removecells , hooks_initgame , hooks_calcparam , hooks_mainmenu , hooks_startmenu , hooks_markers ;
2017-07-10 18:47:38 +00:00
template < class T , class . . . U > void callhooks ( hookset < T > * h , U . . . args ) {
if ( h ) for ( auto & p : * h ) p . second ( args . . . ) ;
}
2017-12-01 23:31:36 +00:00
template < class T , class V , class . . . U > V callhandlers ( V zero , hookset < T > * h , U & . . . args ) {
2017-07-10 18:47:38 +00:00
if ( h ) for ( auto & p : * h ) {
auto z = p . second ( args . . . ) ;
if ( z ! = zero ) return z ;
}
return zero ;
}
extern hookset < bool ( int sym , int uni ) > * hooks_handleKey ;
2018-05-25 23:11:19 +00:00
extern hookset < bool ( cell * c , const transmatrix & V ) > * hooks_drawcell ;
2018-02-26 12:14:20 +00:00
extern hookset < bool ( int argc , char * * argv ) > * hooks_main ;
2017-07-10 18:47:38 +00:00
extern hookset < int ( ) > * hooks_args ;
2018-07-09 16:59:12 +00:00
extern hookset < bool ( cell * ) > * hooks_mark ;
2017-07-10 18:47:38 +00:00
extern hookset < eLand ( eLand ) > * hooks_nextland ;
2018-07-09 18:09:56 +00:00
extern hookset < bool ( ) > * hooks_welcome_message , * hooks_default_help ;
extern hookset < void ( cell * ) > * hooks_mouseover ;
2019-03-15 11:45:57 +00:00
extern hookset < struct hrmap * ( ) > * hooks_newmap ;
2017-07-10 18:47:38 +00:00
extern ld shiftmul ;
void initcs ( charstyle & cs ) ;
2017-08-06 12:50:16 +00:00
charstyle & getcs ( int id = multi : : cpid ) ;
2017-07-10 18:47:38 +00:00
struct msginfo {
int stamp ;
2017-10-09 08:51:16 +00:00
time_t rtstamp ;
int gtstamp ;
int turnstamp ;
2017-07-10 18:47:38 +00:00
char flashout ;
char spamtype ;
int quantity ;
string msg ;
} ;
extern vector < msginfo > msgs ;
void flashMessages ( ) ;
extern int lightat , safetyat ;
int watercolor ( int phase ) ;
bool doHighlight ( ) ;
2018-02-26 12:15:33 +00:00
void buildHelpText ( ) ;
void buildCredits ( ) ;
2017-07-10 18:47:38 +00:00
void setAppropriateOverview ( ) ;
bool quitsaves ( ) ;
2017-10-29 11:46:57 +00:00
extern const char * COLORBAR ;
2017-07-10 18:47:38 +00:00
int textwidth ( int siz , const string & str ) ;
# define GLERR(call) glError(call, __FILE__, __LINE__)
extern bool gtouched , mousepressed , mousemoved , actonrelease ;
extern bool inslider ;
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
extern bool outoffocus ;
extern int frames ;
extern transmatrix playerV ;
extern bool didsomething ;
extern void drawStats ( ) ;
extern int calcfps ( ) ;
2018-11-08 15:21:33 +00:00
extern colortable distcolors , minecolors ;
2017-07-10 18:47:38 +00:00
extern eItem orbToTarget ;
extern eMonster monsterToSummon ;
void panning ( hyperpoint hf , hyperpoint ht ) ;
extern transmatrix sphereflip ;
void initConfig ( ) ;
void loadConfig ( ) ;
extern bool auraNOGL ;
2017-07-22 23:33:27 +00:00
# if CAP_SDLJOY
2017-07-10 18:47:38 +00:00
extern void initJoysticks ( ) ;
extern bool autojoy ;
2017-07-22 23:33:27 +00:00
extern int joyx , joyy , panjoyx , panjoyy ;
2017-07-10 18:47:38 +00:00
extern movedir joydir ;
extern SDL_Joystick * sticks [ 8 ] ;
extern int numsticks ;
void closeJoysticks ( ) ;
# endif
void preparesort ( ) ;
# define SHMUPTITLE "shoot'em up mode"
bool dodrawcell ( cell * c ) ;
void drawcell ( cell * c , transmatrix V , int spinv , bool mirrored ) ;
extern double downspin ;
extern int frameid ;
extern bool leftclick ;
void clearMemory ( ) ;
extern function < void ( int sym , int uni ) > keyhandler ;
2018-11-18 02:18:11 +00:00
# if CAP_SDL
extern function < bool ( SDL_Event & ev ) > joyhandler ;
# endif
2019-03-30 22:45:28 +00:00
bool gmodekeys ( int sym , int uni ) ;
2017-07-10 18:47:38 +00:00
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)
bool interpret_as_direction ( int sym , int uni ) ;
int get_direction_key ( int sym , int uni ) ;
2018-12-06 10:43:10 +00:00
2017-07-10 18:47:38 +00:00
void switchGL ( ) ;
void switchFullscreen ( ) ;
2017-07-12 17:50:39 +00:00
extern int cmode ;
2017-07-10 18:47:38 +00:00
2017-07-12 16:03:53 +00:00
namespace scores { void load ( ) ; }
2017-07-10 18:47:38 +00:00
void gotoHelp ( const string & h ) ;
void showCustomizeChar ( ) ;
void showCheatMenu ( ) ;
2019-03-30 22:45:28 +00:00
void showGraphQuickKeys ( ) ;
2017-07-10 18:47:38 +00:00
void showChangeMode ( ) ;
void showEuclideanMenu ( ) ;
void show3D ( ) ;
void gameoverscreen ( ) ;
void showJoyConfig ( ) ;
void gamescreen ( int darken ) ;
void showMission ( ) ;
void handleKeyQuit ( int sym , int uni ) ;
void handlePanning ( int sym , int uni ) ;
2017-07-12 16:03:53 +00:00
2017-07-22 23:33:27 +00:00
# if ISMOBILE==1
2017-07-12 16:03:53 +00:00
namespace leader { void showMenu ( ) ; void handleKey ( int sym , int uni ) ; }
# endif
2017-07-16 21:00:55 +00:00
namespace mirror {
2017-08-06 12:50:16 +00:00
cellwalker reflect ( const cellwalker & cw ) ;
2017-07-16 21:00:55 +00:00
}
bool inmirror ( eLand l ) ;
bool inmirror ( cell * c ) ;
bool inmirror ( const cellwalker & cw ) ;
2018-09-04 17:53:42 +00:00
void queuemarkerat ( const transmatrix & V , color_t col ) ;
2017-07-16 21:00:55 +00:00
void check_total_victory ( ) ;
void applyBoxNum ( int & i , string name = " " ) ;
extern int hinttoshow ;
bool isShmupLifeOrb ( eItem it ) ;
int orbcharges ( eItem it ) ;
2018-09-04 17:53:42 +00:00
color_t gradient ( color_t c0 , color_t c1 , ld v0 , ld v , ld v1 ) ;
2017-07-16 21:00:55 +00:00
struct hint {
time_t last ;
function < bool ( ) > usable ;
function < void ( ) > display ;
function < void ( ) > action ;
} ;
extern hint hints [ ] ;
int counthints ( ) ;
2017-07-22 23:33:27 +00:00
void gainShard ( cell * c2 , const char * msg ) ;
int textwidth ( int siz , const string & str ) ;
# if CAP_GL
int gl_width ( int size , const char * s ) ;
# endif
# ifdef ISMOBILE
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
2018-10-26 19:05:35 +00:00
void addaura ( hyperpoint h , color_t col , int fd ) ;
void addauraspecial ( hyperpoint h , color_t col , int dir ) ;
2018-12-17 10:33:52 +00:00
void drawaura ( ) ;
void clearaura ( ) ;
2017-08-06 12:50:16 +00:00
2018-09-04 17:53:42 +00:00
void drawBug ( const cellwalker & cw , color_t col ) ;
2017-08-06 12:50:16 +00:00
void mainloop ( ) ;
2017-09-01 20:13:41 +00:00
void mainloopiter ( ) ;
2017-08-06 12:50:16 +00:00
extern bool showstartmenu ;
void selectLanguageScreen ( ) ;
bool inscreenrange ( cell * c ) ;
2017-08-18 00:58:55 +00:00
bool allowIncreasedSight ( ) ;
2018-04-11 13:49:49 +00:00
bool allowChangeRange ( ) ;
2017-09-01 21:01:10 +00:00
2017-10-29 11:46:57 +00:00
static inline bool orbProtection ( eItem it ) { return false ; } // not implemented
2017-09-03 19:12:44 +00:00
2019-02-17 17:33:15 +00:00
# if CAP_FIELD
2017-09-03 19:12:44 +00:00
namespace windmap {
void create ( ) ;
2017-09-30 09:46:41 +00:00
static const int NOWINDBELOW = 8 ;
static const int NOWINDFROM = 120 ;
2017-12-05 15:19:22 +00:00
int getId ( cell * c ) ;
2017-09-30 09:46:41 +00:00
int at ( cell * c ) ;
2017-09-03 19:12:44 +00:00
}
2019-02-17 17:33:15 +00:00
# endif
2017-09-03 19:12:44 +00:00
extern int wavephase ;
2017-09-30 09:46:41 +00:00
void buildEquidistant ( cell * c ) ;
void produceGhost ( cell * c , eMonster victim , eMonster who ) ;
void sideAttack ( cell * mf , int dir , eMonster who , int bonus , eItem orb ) ;
void sideAttack ( cell * mf , int dir , eMonster who , int bonuskill ) ;
2017-10-08 09:12:03 +00:00
void orboflava ( int i ) ;
2017-10-08 10:10:40 +00:00
void setland ( cell * c , eLand l ) ;
eLand getNewLand ( eLand old ) ;
extern bool randomPatternsMode ;
extern int isRandland ( eLand l ) ;
extern vector < cell * > buggycells ;
extern bool landUnlocked ( eLand l ) ;
extern void describeCell ( cell * ) ;
extern bool rlyehComplete ( ) ;
2017-10-29 13:19:51 +00:00
extern int steplimit , cstep ;
template < class . . . T >
void limitgen ( T . . . args ) {
if ( steplimit ) {
cstep + + ;
printf ( " %6d " , cstep ) ;
printf ( args . . . ) ;
if ( cstep = = steplimit ) buggyGeneration = true ;
}
}
2017-10-08 10:10:40 +00:00
eLand oppositeElement ( eLand l , eLand l2 ) ;
extern int hardness_empty ( ) ;
extern eWall getElementalWall ( eLand l ) ;
void gainItem ( eItem it ) ;
2017-10-08 12:02:03 +00:00
void destroyTrapsOn ( cell * c ) ;
void destroyTrapsAround ( cell * c ) ;
2017-10-09 08:51:16 +00:00
extern int messagelogpos ;
void showMessageLog ( ) ;
int getgametime ( ) ;
string getgametime_s ( int timespent = getgametime ( ) ) ;
extern int stampbase ;
2017-10-09 09:46:49 +00:00
transmatrix cellrelmatrix ( cell * c , int i ) ;
2017-10-14 23:10:40 +00:00
void terracottaAround ( cell * c ) ;
2017-10-27 18:10:37 +00:00
double cellgfxdist ( cell * c , int i ) ;
2017-10-28 23:57:34 +00:00
int ctof ( cell * c ) ;
void modalDebug ( cell * c ) ;
2019-01-02 21:03:23 +00:00
void push_debug_screen ( ) ;
2017-10-28 23:57:34 +00:00
int getDistLimit ( ) ;
2017-10-29 11:46:57 +00:00
void drawqueue ( ) ;
# 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
2018-02-13 22:25:44 +00:00
struct texture_triangle {
array < hyperpoint , 3 > v ;
array < hyperpoint , 3 > tv ;
texture_triangle ( array < hyperpoint , 3 > _v , array < hyperpoint , 3 > _tv ) : v ( _v ) , tv ( _tv ) { }
} ;
2019-03-11 17:46:34 +00:00
struct basic_textureinfo {
2017-12-09 01:20:10 +00:00
int texture_id ;
2019-03-11 17:46:34 +00:00
vector < glvertex > tvertices ;
} ;
struct textureinfo : basic_textureinfo {
transmatrix M ;
2018-02-13 22:25:44 +00:00
vector < texture_triangle > triangles ;
2018-02-11 18:08:17 +00:00
vector < glvertex > vertices ;
2017-12-14 01:50:52 +00:00
cell * c ;
2017-12-18 23:39:11 +00:00
vector < transmatrix > matrices ;
2017-12-14 01:50:52 +00:00
// these are required to adjust to geometry changes
2017-12-19 15:40:24 +00:00
int current_type , symmetries ;
2017-12-09 01:20:10 +00:00
} ;
2018-09-04 17:53:42 +00:00
struct drawqueueitem {
PPR prio ;
color_t color ;
2019-03-04 17:00:51 +00:00
int subprio ;
2018-09-04 17:53:42 +00:00
virtual void draw ( ) = 0 ;
virtual void draw_back ( ) { }
virtual void draw_pre ( ) { }
virtual ~ drawqueueitem ( ) { }
void draw_darker ( ) ;
2018-09-04 21:27:27 +00:00
virtual color_t outline_group ( ) = 0 ;
2018-09-04 17:53:42 +00:00
} ;
2017-10-29 11:46:57 +00:00
2018-09-04 17:53:42 +00:00
struct dqi_poly : drawqueueitem {
2018-11-09 13:14:36 +00:00
ld band_shift ;
2018-09-04 17:53:42 +00:00
transmatrix V ;
const vector < glvertex > * tab ;
2019-03-20 01:16:00 +00:00
int offset , cnt , offset_texture ;
2018-09-04 19:43:43 +00:00
color_t outline ;
2018-09-04 17:53:42 +00:00
double linewidth ;
int flags ;
2019-03-11 17:46:34 +00:00
basic_textureinfo * tinf ;
2018-09-07 14:18:40 +00:00
hyperpoint intester ;
2018-09-04 17:53:42 +00:00
void draw ( ) ;
void gldraw ( ) ;
void draw_back ( ) ;
2018-09-04 21:27:27 +00:00
virtual color_t outline_group ( ) { return outline ; }
2018-09-04 17:53:42 +00:00
} ;
struct dqi_line : drawqueueitem {
2018-11-09 13:14:36 +00:00
ld band_shift ;
2018-09-04 17:53:42 +00:00
hyperpoint H1 , H2 ;
int prf ;
double width ;
void draw ( ) ;
void draw_back ( ) ;
2018-09-04 21:27:27 +00:00
virtual color_t outline_group ( ) { return color ; }
2018-09-04 17:53:42 +00:00
} ;
2017-10-29 11:46:57 +00:00
2018-09-04 17:53:42 +00:00
struct dqi_string : drawqueueitem {
string str ;
int x , y , shift , size , frame ;
int align ;
void draw ( ) ;
2018-09-04 21:27:27 +00:00
virtual color_t outline_group ( ) { return 1 ; }
2018-05-20 13:30:43 +00:00
} ;
2018-09-04 17:53:42 +00:00
struct dqi_circle : drawqueueitem {
2018-11-08 15:28:17 +00:00
int x , y , size , fillcolor ;
2018-12-13 16:03:39 +00:00
double linewidth ;
2018-09-04 17:53:42 +00:00
void draw ( ) ;
2018-09-04 21:27:27 +00:00
virtual color_t outline_group ( ) { return 2 ; }
2018-09-04 17:53:42 +00:00
} ;
struct dqi_action : drawqueueitem {
reaction_t action ;
dqi_action ( const reaction_t & a ) : action ( a ) { }
void draw ( ) { action ( ) ; }
2018-09-04 21:27:27 +00:00
virtual color_t outline_group ( ) { return 2 ; }
2018-09-04 17:53:42 +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
const eLand NOWALLSEP = laNone ;
const eLand NOWALLSEP_USED = laWhirlpool ;
bool hasbardir ( cell * c ) ;
2018-04-11 21:37:28 +00:00
bool buildBarrierNowall ( cell * c , eLand l2 , int forced_dir = NODIR ) ;
2017-10-29 13:19:51 +00:00
bool checkBarriersBack ( cellwalker bb , int q = 5 , bool cross = false ) ;
bool checkBarriersFront ( cellwalker bb , int q = 5 , bool cross = false ) ;
bool quickfind ( eLand l ) ;
void beCIsland ( cell * c ) ;
bool isOnCIsland ( cell * c ) ;
void generateTreasureIsland ( cell * c ) ;
bool openplains ( cell * c ) ;
void buildBigStuff ( cell * c , cell * from ) ;
void setLandQuotient ( cell * c ) ;
void setLandSphere ( cell * c ) ;
2017-10-30 18:12:33 +00:00
void setLandWeird ( cell * c ) ;
2017-10-29 13:19:51 +00:00
void moreBigStuff ( cell * c ) ;
void setLandEuclid ( cell * c ) ;
bool checkInTree ( cell * c , int maxv ) ;
cell * findcompass ( cell * c ) ;
int edgeDepth ( cell * c ) ;
int compassDist ( cell * c ) ;
2018-12-01 22:49:14 +00:00
void buildCamelot ( cell * c ) ;
2017-10-29 13:19:51 +00:00
# define HAUNTED_RADIUS getDistLimit()
# define UNKNOWN 65535
# if CAP_COMMANDLINE
extern const char * scorefile ;
extern string levelfile ;
extern string picfile ;
extern const char * conffile ;
extern const char * musicfile ;
# endif
extern string s0 ;
extern int anthraxBonus ;
int celldistAlt ( cell * c ) ;
int celldist ( cell * c ) ;
2019-03-09 00:00:46 +00:00
int masterAlt ( cell * c ) ;
2017-10-29 13:19:51 +00:00
int getHemisphere ( cell * c , int which ) ;
namespace tactic {
extern bool on ;
extern bool trailer ;
}
namespace yendor {
extern bool on ;
extern bool generating ;
extern eLand nexttostart ;
# define YF_DEAD 1
# define YF_WALLS 2
# define YF_END 4
# define YF_DEAD5 8
# define YF_NEAR_IVY 16
# define YF_NEAR_ELEM 32
# define YF_NEAR_OVER 64
# define YF_NEAR_RED 128
# define YF_REPEAT 512
# define YF_NEAR_TENT 1024
# define YF_START_AL 2048
# define YF_START_CR 4096
# define YF_CHAOS 8192
# define YF_RECALL 16384
# define YF_NEAR_FJORD 32768
# define YF_START_ANY (YF_START_AL|YF_START_CR)
struct yendorlevel {
eLand l ;
int flags ;
} ;
yendorlevel & clev ( ) ;
}
namespace clearing {
struct clearingdata {
cell * root ;
int dist ;
} ;
extern bool buggyplant ;
extern std : : map < heptagon * , clearingdata > bpdata ;
}
namespace peace {
extern bool on ;
}
namespace princess {
# define EPX 39
# define EPY 21
# define OUT_OF_PRISON 200
# define OUT_OF_PALACE 250
# define PRADIUS0 (141)
# define PRADIUS1 (150)
extern bool generating ;
extern bool gotoPrincess ;
extern bool forceMouse ;
extern bool challenge ;
2018-02-08 21:27:12 +00:00
extern bool squeaked ;
extern bool saved ;
extern bool nodungeon ;
extern int reviveAt ;
extern bool forceVizier ;
2017-10-29 13:19:51 +00:00
struct info {
int id ; // id of this info
cell * prison ; // where was the Princess locked
heptagon * alt ; // alt of the prison
int bestdist ; // best dist achieved
int bestnear ; // best dist achieved, by the player
int value ; // number of Rugs at 120
cell * princess ; // where is the Princess currently
} ;
int newInfo ( cell * c ) ;
}
# define GRAIL_FOUND 0x4000
# define GRAIL_RADIUS_MASK 0x3FFF
2018-11-27 15:17:20 +00:00
int eudist ( int sx , int sy ) ;
2017-10-29 13:19:51 +00:00
cell * createMovR ( cell * c , int d ) ;
bool ishept ( cell * c ) ;
int cdist50 ( cell * c ) ;
2018-09-05 13:37:07 +00:00
bool polarb50 ( cell * c ) ;
2017-10-29 13:19:51 +00:00
bool isGravityLand ( eLand l ) ;
2019-04-16 22:42:51 +00:00
bool isWarpedType ( eLand l ) ;
2017-12-05 15:19:22 +00:00
bool isWarped ( cell * c ) ;
2017-10-29 13:19:51 +00:00
2017-12-01 23:31:36 +00:00
struct hrmap {
virtual heptagon * getOrigin ( ) { return NULL ; }
virtual cell * gamestart ( ) { return getOrigin ( ) - > c7 ; }
virtual ~ hrmap ( ) { } ;
virtual vector < cell * > & allcells ( ) { return dcal ; }
virtual void verify ( ) { }
2019-03-08 21:38:44 +00:00
virtual void link_alt ( const cellwalker & hs ) { }
virtual void generateAlts ( heptagon * h , int levs = IRREGULAR ? 1 : S3 - 3 , bool link_cdata = true ) ;
heptagon * may_create_step ( heptagon * h , int direction ) {
if ( h - > move ( direction ) ) return h - > move ( direction ) ;
return create_step ( h , direction ) ;
}
virtual heptagon * create_step ( heptagon * h , int direction ) {
printf ( " create_step called unexpectedly \n " ) ; exit ( 1 ) ;
return NULL ;
}
virtual transmatrix relative_matrix ( heptagon * h2 , heptagon * h1 ) {
printf ( " relative_matrix called unexpectedly \n " ) ;
return Id ;
}
virtual transmatrix relative_matrix ( cell * c2 , cell * c1 , const hyperpoint & point_hint ) {
return relative_matrix ( c2 - > master , c1 - > master ) ;
}
virtual void draw ( ) {
printf ( " undrawable \n " ) ;
}
2019-04-08 14:16:16 +00:00
virtual vector < hyperpoint > get_vertices ( cell * ) ;
2019-03-08 21:38:44 +00:00
} ;
// hrmaps which are based on regular non-Euclidean 2D tilings, possibly quotient
struct hrmap_standard : hrmap {
void draw ( ) override ;
transmatrix relative_matrix ( cell * c2 , cell * c1 , const hyperpoint & point_hint ) override ;
heptagon * create_step ( heptagon * h , int direction ) override ;
2017-12-01 23:31:36 +00:00
} ;
2019-03-08 21:38:44 +00:00
struct hrmap_hyperbolic : hrmap_standard {
2017-12-01 23:31:36 +00:00
heptagon * origin ;
2018-08-28 15:17:34 +00:00
eVariation mvar ;
2017-12-01 23:31:36 +00:00
hrmap_hyperbolic ( ) ;
2019-03-08 21:38:44 +00:00
hrmap_hyperbolic ( heptagon * origin ) ;
heptagon * getOrigin ( ) override { return origin ; }
2017-12-01 23:31:36 +00:00
~ hrmap_hyperbolic ( ) {
DEBMEM ( verifycells ( origin ) ; )
// printf("Deleting hyperbolic map: %p\n", this);
2018-08-28 15:17:34 +00:00
dynamicval < eVariation > ph ( variation , mvar ) ;
2017-12-01 23:31:36 +00:00
clearfrom ( origin ) ;
}
2019-03-08 21:38:44 +00:00
void verify ( ) override { verifycells ( origin ) ; }
2017-12-01 23:31:36 +00:00
} ;
2018-07-16 18:05:23 +00:00
namespace irr {
2019-02-17 17:28:20 +00:00
# if CAP_IRR
2018-07-17 12:28:49 +00:00
extern ld density ;
extern ld quality ;
extern int cellcount ;
extern int place_attempts ;
extern int rearrange_max_attempts ;
extern int rearrange_less ;
2018-07-16 18:05:23 +00:00
void link_to_base ( heptagon * h , heptspin base ) ;
void link_start ( heptagon * h ) ;
void link_next ( heptagon * h , int d ) ;
void may_link_next ( heptagon * h , int d ) ;
void link_cell ( cell * c , int d ) ;
void clear_links ( heptagon * h ) ;
bool pseudohept ( cell * ) ;
array < heptagon * , 3 > get_masters ( cell * c ) ;
bool ctof ( cell * c ) ;
2018-07-17 00:29:18 +00:00
bool supports ( eGeometry g ) ;
void visual_creator ( ) ;
2018-07-17 12:18:41 +00:00
unsigned char density_code ( ) ;
2018-07-20 00:58:47 +00:00
int celldist ( cell * c , bool alts ) ;
2018-08-05 03:07:34 +00:00
extern int bitruncations_requested , bitruncations_performed ;
2019-02-17 17:28:20 +00:00
# endif
2018-07-16 18:05:23 +00:00
}
2017-10-29 13:19:51 +00:00
extern hrmap * currentmap ;
extern vector < hrmap * > allmaps ;
// list all cells in distance at most maxdist, or until when maxcount cells are reached
2018-06-28 11:35:03 +00:00
struct manual_celllister {
2017-10-29 13:19:51 +00:00
vector < cell * > lst ;
vector < int > tmps ;
2018-06-28 11:35:03 +00:00
2018-06-28 10:59:35 +00:00
bool listed ( cell * c ) {
return c - > listindex > = 0 & & c - > listindex < isize ( lst ) & & lst [ c - > listindex ] = = c ;
}
bool add ( cell * c ) {
if ( listed ( c ) ) return false ;
tmps . push_back ( c - > listindex ) ;
c - > listindex = isize ( lst ) ;
2018-06-28 11:35:03 +00:00
lst . push_back ( c ) ;
2018-06-28 10:59:35 +00:00
return true ;
}
2018-06-28 11:35:03 +00:00
~ manual_celllister ( ) {
2018-06-28 10:59:35 +00:00
for ( int i = 0 ; i < isize ( lst ) ; i + + ) lst [ i ] - > listindex = tmps [ i ] ;
2018-06-28 11:35:03 +00:00
}
} ;
2018-06-28 10:59:35 +00:00
2018-06-28 11:35:03 +00:00
struct celllister : manual_celllister {
vector < int > dists ;
void add_at ( cell * c , int d ) {
if ( add ( c ) ) dists . push_back ( d ) ;
2017-10-29 13:19:51 +00:00
}
celllister ( cell * orig , int maxdist , int maxcount , cell * breakon ) {
2018-06-28 11:35:03 +00:00
add_at ( orig , 0 ) ;
2017-10-29 13:19:51 +00:00
cell * last = orig ;
2018-06-22 12:47:24 +00:00
for ( int i = 0 ; i < isize ( lst ) ; i + + ) {
2017-10-29 13:19:51 +00:00
cell * c = lst [ i ] ;
if ( maxdist ) forCellCM ( c2 , c ) {
2018-06-28 11:35:03 +00:00
add_at ( c2 , dists [ i ] + 1 ) ;
2017-10-29 13:19:51 +00:00
if ( c2 = = breakon ) return ;
}
if ( c = = last ) {
2018-06-22 12:47:24 +00:00
if ( isize ( lst ) > = maxcount | | dists [ i ] + 1 = = maxdist ) break ;
last = lst [ isize ( lst ) - 1 ] ;
2017-10-29 13:19:51 +00:00
}
}
}
2018-06-28 10:59:35 +00:00
int getdist ( cell * c ) { return dists [ c - > listindex ] ; }
2017-10-29 13:19:51 +00:00
} ;
hrmap * newAltMap ( heptagon * o ) ;
2019-02-17 17:33:15 +00:00
# if CAP_FIELD
2017-10-29 13:19:51 +00:00
# define currfp fieldpattern::getcurrfp()
namespace fieldpattern {
struct fpattern & getcurrfp ( ) ;
}
int currfp_gmul ( int a , int b ) ;
int currfp_inverses ( int i ) ;
int currfp_distwall ( int i ) ;
2019-03-15 11:47:08 +00:00
int currfp_n ( ) ;
int currfp_get_P ( ) ;
int currfp_get_R ( ) ;
int currfp_get_X ( ) ;
2019-02-17 17:33:15 +00:00
# endif
2017-10-29 13:19:51 +00:00
const char * dnameof ( eMonster m ) ;
const char * dnameof ( eLand l ) ;
const char * dnameof ( eWall w ) ;
const char * dnameof ( eItem i ) ;
2017-10-30 11:05:36 +00:00
void runGeometryExperiments ( ) ;
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-04-13 11:08:41 +00:00
namespace lv {
static const flagtype appears_in_geom_exp = 1 ;
static const flagtype display_error_message = 2 ;
static const flagtype appears_in_full = 4 ;
static const flagtype appears_in_ptm = 8 ;
static const flagtype display_in_help = 16 ;
2018-05-01 17:34:57 +00:00
static const flagtype one_and_half = 32 ;
2018-04-13 11:08:41 +00:00
} ;
struct land_validity_t {
int quality_level ; // 0 (dont show), 1 (1/2), 2 (ok), 3(1!)
flagtype flags ;
string msg ;
} ;
2017-11-03 18:31:42 +00:00
extern vector < eLand > landlist ;
template < class T > void generateLandList ( T t ) ;
2018-04-13 11:08:41 +00:00
land_validity_t & land_validity ( eLand l ) ;
2018-01-08 22:11:29 +00:00
bool isLandIngame ( eLand l ) ;
2017-11-06 22:11:40 +00:00
bool inmirrororwall ( eLand l ) ;
2017-11-06 22:22:13 +00:00
extern bool holdmouse ;
2017-11-13 10:08:06 +00:00
// what part of the compass does 'skip turn'
static const auto SKIPFAC = .4 ;
bool haveMobileCompass ( ) ;
bool handleCompass ( ) ;
2019-02-26 21:22:21 +00:00
inline bool sphereflipped ( ) { return sphere & & vid . alpha > 1.1 & & DIM = = 3 ; }
2019-03-09 14:31:02 +00:00
bool hide_player ( ) ;
2017-11-13 10:08:06 +00:00
int cellcolor ( cell * c ) ;
transmatrix screenpos ( ld x , ld y ) ;
2017-11-13 11:23:42 +00:00
extern ld backbrightness ;
2017-12-01 23:31:36 +00:00
void initcells ( ) ;
void precalc ( ) ;
2019-02-25 13:50:39 +00:00
extern const hyperpoint C02 , C03 ;
# define C0 (DIM == 2 ? C02 : C03)
2017-12-01 23:31:36 +00:00
extern long long circlesize [ 100 ] , disksize [ 100 ] ;
extern ld circlesizeD [ 10000 ] ;
void computeSizes ( ) ;
# if CAP_FILES
extern const char * scorefile ;
extern const char * conffile ;
extern string levelfile ;
extern string picfile ;
extern const char * musicfile ;
extern const char * loadlevel ;
# endif
transmatrix spin ( ld alpha ) ;
transmatrix xpush ( ld alpha ) ;
transmatrix inverse ( const transmatrix & ) ;
ld hdist ( const hyperpoint & h1 , const hyperpoint & h2 ) ;
extern bool fixseed ;
extern eLand firstland0 ;
extern int startseed ;
extern transmatrix heptmove [ MAX_EDGE ] , hexmove [ MAX_EDGE ] ;
extern transmatrix invheptmove [ MAX_EDGE ] , invhexmove [ MAX_EDGE ] ;
2018-03-24 11:59:01 +00:00
// heptspin hsstep(const heptspin &hs, int spin);
2017-12-01 23:31:36 +00:00
extern void fixmatrix ( transmatrix & ) ;
transmatrix rgpushxto0 ( const hyperpoint & H ) ;
string its ( int i ) ;
double hdist0 ( const hyperpoint & mh ) ;
extern bool fading ;
extern ld fadeout ;
int itemclass ( eItem i ) ;
2018-09-23 22:05:05 +00:00
int monsterclass ( eMonster m ) ;
2017-12-03 17:25:31 +00:00
extern purehookset hooks_drawmap ;
extern hookset < bool ( eLand & ) > * hooks_music ;
extern hookset < bool ( ) > * hooks_prestats ;
extern purehookset hooks_fixticks ;
ld realradius ( ) ;
2017-12-03 17:44:29 +00:00
void sdltogl ( SDL_Surface * txt , struct glfont_t & f , int ch ) ;
2017-12-03 17:25:31 +00:00
2017-12-03 18:51:45 +00:00
void showStartMenu ( ) ;
2017-12-05 15:19:22 +00:00
bool polara50 ( int x ) ;
2018-09-05 13:37:07 +00:00
bool polara50 ( cell * c ) ;
2017-12-05 15:19:22 +00:00
int fiftyval049 ( cell * c ) ;
namespace fieldpattern {
pair < int , bool > fieldval ( cell * c ) ;
}
int emeraldval ( cell * c ) ;
2017-12-05 18:43:45 +00:00
int inpair ( cell * c , int colorpair ) ;
int snake_pair ( cell * c ) ;
2018-11-08 15:21:33 +00:00
extern colortable nestcolors ;
2017-12-09 01:20:10 +00:00
2017-12-21 10:36:07 +00:00
# if CAP_TEXTURE
2017-12-14 01:50:52 +00:00
namespace texture {
enum eTextureState {
tsOff , tsAdjusting , tsActive
} ;
2018-03-17 20:12:46 +00:00
struct texture_data {
2018-03-25 12:03:41 +00:00
GLuint textureid ;
2018-03-17 20:12:46 +00:00
2018-03-25 12:03:41 +00:00
int twidth ;
2019-03-12 01:42:46 +00:00
int tx , ty , origdim ;
2018-03-25 12:03:41 +00:00
texture_data ( ) { textureid = 0 ; twidth = 2048 ; }
2018-03-17 20:12:46 +00:00
2018-09-04 17:53:42 +00:00
vector < color_t > texture_pixels ;
2018-03-17 20:12:46 +00:00
2018-09-04 17:53:42 +00:00
color_t & get_texture_pixel ( int x , int y ) {
2018-03-17 20:12:46 +00:00
return texture_pixels [ ( y & ( twidth - 1 ) ) * twidth + ( x & ( twidth - 1 ) ) ] ;
}
2018-09-04 17:53:42 +00:00
vector < pair < color_t * , color_t > > undos ;
2018-03-17 20:12:46 +00:00
vector < tuple < cell * , hyperpoint , int > > pixels_to_draw ;
bool loadTextureGL ( ) ;
bool whitetexture ( ) ;
bool readtexture ( string tn ) ;
void saveRawTexture ( string tn ) ;
void undo ( ) ;
void undoLock ( ) ;
void update ( ) ;
} ;
struct texture_config {
2018-03-25 12:03:41 +00:00
string texturename ;
string configname ;
2018-09-04 17:53:42 +00:00
color_t paint_color ;
2018-03-17 20:12:46 +00:00
eTextureState tstate ;
eTextureState tstate_max ;
2018-03-25 12:03:41 +00:00
transmatrix itt ;
2018-03-17 20:12:46 +00:00
2018-09-04 17:53:42 +00:00
color_t grid_color ;
color_t mesh_color ;
color_t master_color ;
color_t slave_color ;
2018-03-17 20:12:46 +00:00
2018-03-25 12:03:41 +00:00
int color_alpha ;
2018-03-17 20:12:46 +00:00
2018-03-25 12:03:41 +00:00
int gsplits ;
2018-09-04 17:53:42 +00:00
int recolor ( color_t col ) ;
2018-03-17 20:12:46 +00:00
2018-08-28 15:17:34 +00:00
typedef tuple < eGeometry , eVariation , char , int , eModel , ld , ld > texture_parameters ;
2018-03-17 20:12:46 +00:00
texture_parameters orig_texture_parameters ;
map < int , textureinfo > texture_map , texture_map_orig ;
set < cell * > models ;
2019-04-12 13:18:16 +00:00
basic_textureinfo tinf3 ;
2018-03-17 20:12:46 +00:00
2018-03-25 12:03:41 +00:00
bool texture_tuned ;
2018-03-17 20:12:46 +00:00
string texture_tuner ;
vector < hyperpoint * > tuned_vertices ;
2018-09-04 17:53:42 +00:00
bool apply ( cell * c , const transmatrix & V , color_t col ) ;
2018-03-17 20:12:46 +00:00
void mark_triangles ( ) ;
void clear_texture_map ( ) ;
void perform_mapping ( ) ;
void mapTextureTriangle ( textureinfo & mi , const array < hyperpoint , 3 > & v , const array < hyperpoint , 3 > & tv , int splits ) ;
void mapTextureTriangle ( textureinfo & mi , const array < hyperpoint , 3 > & v , const array < hyperpoint , 3 > & tv ) { mapTextureTriangle ( mi , v , tv , gsplits ) ; }
void mapTexture2 ( textureinfo & mi ) ;
void finish_mapping ( ) ;
2018-08-20 00:04:49 +00:00
void true_remap ( ) ;
void remap ( ) ;
bool correctly_mapped ;
2018-08-14 07:15:17 +00:00
hyperpoint texture_coordinates ( hyperpoint ) ;
2018-03-17 20:12:46 +00:00
void drawRawTexture ( ) ;
void saveFullTexture ( string tn ) ;
bool save ( ) ;
bool load ( ) ;
texture_data data ;
2018-03-25 12:03:41 +00:00
texture_config ( ) {
// argh, no member initialization in some of my compilers
texturename = " textures/hyperrogue-texture.png " ;
configname = " textures/hyperrogue.txc " ;
itt = Id ;
paint_color = 0x000000FF ;
grid_color = 0 ;
mesh_color = 0 ;
master_color = 0xFFFFFF30 ;
slave_color = 0xFF000008 ;
color_alpha = 128 ;
gsplits = 1 ;
texture_tuned = false ;
}
2018-03-17 20:12:46 +00:00
} ;
extern texture_config config ;
2017-12-18 22:42:08 +00:00
extern ld penwidth ;
2017-12-21 13:05:07 +00:00
extern bool saving ;
2017-12-14 01:50:52 +00:00
void showMenu ( ) ;
2017-12-19 13:35:34 +00:00
2018-09-04 17:53:42 +00:00
void drawPixel ( cell * c , hyperpoint h , color_t col ) ;
2018-01-04 11:25:02 +00:00
extern cell * where ;
// compute 'c' automatically, based on the hint in 'where'
2018-09-04 17:53:42 +00:00
void drawPixel ( hyperpoint h , color_t col ) ;
void drawLine ( hyperpoint h1 , hyperpoint h2 , color_t col , int steps = 10 ) ;
2017-12-19 15:40:24 +00:00
2017-12-22 20:57:55 +00:00
extern bool texturesym ;
2017-12-19 13:35:34 +00:00
extern cpatterntype cgroup ;
2018-08-03 08:47:20 +00:00
extern bool texture_aura ;
bool using_aura ( ) ;
2019-01-03 14:16:12 +00:00
void start_editor ( ) ;
2017-12-14 01:50:52 +00:00
}
2017-12-21 10:36:07 +00:00
# endif
2017-12-09 02:48:30 +00:00
2018-09-04 17:53:42 +00:00
dqi_line & queueline ( const hyperpoint & H1 , const hyperpoint & H2 , color_t col , int prf = 0 , PPR prio = PPR : : LINE ) ;
dqi_action & queueaction ( PPR prio , const reaction_t & action ) ;
void queuereset ( eModel m , PPR prio ) ;
2017-12-09 02:48:30 +00:00
extern ld tessf , crossf , hexf , hcrossf , hexhexdist , hexvdist , hepvdist , rhexf ;
2019-03-09 16:36:04 +00:00
extern ld sword_size ;
2018-08-28 17:05:57 +00:00
extern ld scalefactor , orbsize , floorrad0 , floorrad1 , zhexf ;
2018-09-04 17:53:42 +00:00
unsigned char & part ( color_t & col , int i ) ;
2017-12-09 07:06:41 +00:00
transmatrix applyPatterndir ( cell * c , const patterns : : patterninfo & si ) ;
2017-12-09 19:02:56 +00:00
int pattern_threecolor ( cell * c ) ;
int fiftyval200 ( cell * c ) ;
2017-12-14 01:50:52 +00:00
// T * C0, optimized
inline hyperpoint tC0 ( const transmatrix & T ) {
hyperpoint z ;
2019-02-21 17:46:53 +00:00
for ( int i = 0 ; i < MDIM ; i + + ) z [ i ] = T [ i ] [ DIM ] ;
2017-12-14 01:50:52 +00:00
return z ;
}
2017-12-16 08:03:50 +00:00
transmatrix actualV ( const heptspin & hs , const transmatrix & V ) ;
transmatrix cview ( ) ;
2019-04-29 01:34:21 +00:00
bool isWall3 ( cell * c , color_t & wcol ) ;
extern transmatrix actual_view_transform ;
ld wall_radar ( cell * c , transmatrix T ) ;
2017-12-17 23:24:56 +00:00
2018-08-28 15:17:34 +00:00
extern string bitruncnames [ 5 ] ;
2017-12-27 13:09:39 +00:00
extern bool need_mouseh ;
2017-12-28 15:46:10 +00:00
extern int whateveri , whateveri2 ;
void clear_euland ( eLand first ) ;
2017-12-30 14:12:15 +00:00
extern eMonster passive_switch ;
2017-12-30 22:47:10 +00:00
bool cannotPickupItem ( cell * c , bool telekinesis ) ;
bool canPickupItemWithMagnetism ( cell * c , cell * from ) ;
void pickupMovedItems ( cell * c ) ;
2018-01-04 20:24:13 +00:00
eMonster genRuinMonster ( cell * c ) ;
2018-01-13 18:23:02 +00:00
template < class T > void hrandom_shuffle ( T * x , int n ) {
for ( int k = 1 ; k < n ; k + + ) swap ( x [ k ] , x [ hrand ( k + 1 ) ] ) ;
}
2018-01-14 20:21:32 +00:00
void resetModes ( char leave = ' c ' ) ;
void activateSafety ( eLand l ) ;
void showMainMenu ( ) ;
extern bool nomenukey ;
void resetConfig ( ) ;
void welcomeMessage ( ) ;
void jumpTo ( cell * dest , eItem byWhat , int bonuskill = 0 , eMonster dashmon = moNone ) ;
extern bool canmove ;
void activateSafety ( eLand l ) ;
extern bool childbug ;
void fullcenter ( ) ;
void mainloop ( ) ;
void clearAnimations ( ) ;
transmatrix rotmatrix ( double rotation , int c0 , int c1 ) ;
2018-01-25 18:49:19 +00:00
void destroycellcontents ( cell * c ) ;
extern heptagon * last_cleared ;
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 - - ;
}
bool is_cell_removed ( cell * c ) ;
void set_if_removed ( cell * & c , cell * val ) ;
2018-02-01 12:42:47 +00:00
struct renderbuffer {
2018-02-03 12:50:47 +00:00
bool valid ;
int x , y ;
# if CAP_GL
int tx , ty ;
2018-02-01 12:42:47 +00:00
GLuint FramebufferName ;
GLuint renderedTexture ;
GLuint depth_stencil_rb ;
Uint32 * expanded_data ;
2018-02-03 12:50:47 +00:00
void use_as_texture ( ) ;
# endif
# if CAP_SDL
SDL_Surface * srf ;
2018-02-01 12:42:47 +00:00
void make_surface ( ) ;
2018-02-03 12:50:47 +00:00
SDL_Surface * render ( ) ;
# endif
2018-02-01 12:42:47 +00:00
renderbuffer ( int x , int y , bool gl ) ;
~ renderbuffer ( ) ;
void enable ( ) ;
2018-09-04 17:53:42 +00:00
void clear ( color_t col ) ;
2018-02-01 12:42:47 +00:00
} ;
2018-02-03 12:41:49 +00:00
2018-02-11 01:19:49 +00:00
struct resetbuffer {
GLint drawFboId , readFboId ;
SDL_Surface * sreset ;
resetbuffer ( ) ;
void reset ( ) ;
} ;
2018-02-03 12:41:49 +00:00
double randd ( ) ;
2018-02-03 19:04:47 +00:00
# if CAP_ORIENTATION
transmatrix getOrientation ( ) ;
# endif
2018-02-08 21:27:12 +00:00
bool showHalloween ( ) ;
extern bool havesave ;
extern vector < msginfo > gamelog ;
extern time_t savetime ;
extern bool cblind ;
extern void save_memory ( ) ;
namespace inv { void init ( ) ; }
extern bool survivalist ;
extern bool hauntedWarning ;
extern bool usedSafety ;
namespace elec { extern int lightningfast ; }
extern int lastkills ;
extern map < cell * , int > rosemap ;
extern int hardcoreAt ;
extern flagtype havewhat , hadwhat ;
extern int safetyseed ;
extern int lastsafety ;
extern int knighted ;
extern int rosephase ;
extern int rosewave ;
extern eItem localTreasureType ( ) ;
extern void clearshadow ( ) ;
extern bool seenSevenMines ;
extern vector < cell * > dcal ; // queue for cpdist
extern vector < cell * > pathq ; // queue for pathdist
extern vector < pair < cell * , int > > butterflies ;
extern vector < cell * > crush_now , crush_next ;
extern void shrand ( int seed ) ;
extern eLand safetyland ;
extern int sagephase ;
extern int lastsize ;
extern int noiseuntil ;
2019-03-11 17:38:04 +00:00
hyperpoint cpush0 ( int d , ld x ) ;
inline hyperpoint xpush0 ( ld x ) { return cpush0 ( 0 , x ) ; }
inline hyperpoint ypush0 ( ld x ) { return cpush0 ( 1 , x ) ; }
2018-08-19 13:52:39 +00:00
transmatrix xspinpush ( ld alpha , ld x ) ;
2018-08-21 22:10:56 +00:00
hyperpoint xspinpush0 ( ld alpha , ld x ) ;
2018-02-08 21:27:12 +00:00
2019-03-15 11:45:57 +00:00
transmatrix cspin ( int a , int b , ld alpha ) ;
transmatrix cpush ( int cid , ld alpha ) ;
bool eqmatrix ( transmatrix A , transmatrix B , ld eps = 1e-6 ) ;
void set_column ( transmatrix & T , int i , const hyperpoint & H ) ;
2018-02-08 21:27:12 +00:00
# define DF_INIT 0 // always display these
# define DF_MSG 0 // always display these
# define DF_STEAM 1
# define DF_GRAPH 2
# define DF_TURN 4
# define DF_FIELD 8
# if ISANDROID
# define DEBB(r,x)
# else
# define DEBB(r,x) { if(debugfile && (!(r) || (debugflags & (r)))) { fprintf x; fflush(debugfile); } }
# endif
extern FILE * debugfile ;
extern int debugflags ;
int gmod ( int i , int j ) ;
2018-12-01 22:53:03 +00:00
int gdiv ( int i , int j ) ;
2018-02-08 21:27:12 +00:00
extern walltype winf [ walltypes ] ;
extern vector < landtacinfo > land_tac ;
string llts ( long long i ) ;
void clearMemoRPM ( ) ;
extern int randompattern [ landtypes ] ;
extern int pair_to_vec ( int x , int y ) ;
2018-11-27 01:32:11 +00:00
typedef pair < cell * * , bool > euc_pointer ;
euc_pointer euclideanAt ( int vec ) ;
euc_pointer euclideanAtCreate ( int vec ) ;
2018-02-08 21:27:12 +00:00
bool isCyclic ( eLand l ) ;
bool generateAll ( eLand l ) ;
void extendcheck ( cell * c ) ;
void extendNowall ( cell * c ) ;
bool isbar4 ( cell * c ) ;
void extendBarrierFront ( cell * c ) ;
void extendBarrierBack ( cell * c ) ;
void extendCR5 ( cell * c ) ;
bool mirrorwall ( cell * c ) ;
extern void setbarrier ( cell * c ) ;
extern function < void ( ) > call_initgame ;
extern void initializeCLI ( ) ;
static const int max_vec = ( 1 < < 14 ) ;
2018-09-04 17:53:42 +00:00
string helptitle ( string s , color_t col ) ;
2018-02-08 21:27:12 +00:00
pair < int , int > cell_to_pair ( cell * c ) ;
2018-07-09 16:10:28 +00:00
extern bool nohud , nofps , nomap ;
2018-02-11 01:19:49 +00:00
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-02-27 22:43:21 +00:00
extern cell * lastmountpos [ MAXPLAYER ] ;
2018-03-24 14:18:53 +00:00
extern const hyperpoint Hypc ;
ld det ( const transmatrix & T ) ;
2018-09-04 17:53:42 +00:00
void queuechr ( const hyperpoint & h , int size , char chr , color_t col , int frame = 0 ) ;
2018-03-24 14:18:53 +00:00
string fts ( float x ) ;
bool model_needs_depth ( ) ;
2019-02-22 19:58:40 +00:00
hyperpoint hpxy ( ld x , ld y ) ;
hyperpoint hpxy3 ( ld x , ld y , ld z ) ;
2019-02-27 18:33:13 +00:00
ld sqhypot_d ( int d , const hyperpoint & h ) ;
ld hypot_d ( int d , const hyperpoint & h ) ;
2018-03-24 14:18:53 +00:00
transmatrix pushxto0 ( const hyperpoint & H ) ;
transmatrix rpushxto0 ( const hyperpoint & H ) ;
transmatrix spintox ( const hyperpoint & H ) ;
2018-03-24 16:21:25 +00:00
transmatrix ypush ( ld alpha ) ;
2018-03-24 15:00:13 +00:00
2018-03-24 16:21:25 +00:00
# if CAP_SURFACE
namespace surface {
2018-11-30 19:29:14 +00:00
enum eShape { dsNone , dsTractricoid , dsDini , dsKuen , dsHyperlike , dsHyperboloid , dsHemisphere , dsCrystal } ;
2018-03-24 16:21:25 +00:00
extern eShape sh ;
void show_surfaces ( ) ;
2018-09-10 15:26:27 +00:00
void run_shape ( eShape ) ;
extern ld hyper_b , dini_b ;
2018-03-24 16:21:25 +00:00
}
# endif
2018-03-29 22:20:50 +00:00
struct stringpar {
string v ;
stringpar ( string s ) : v ( s ) { }
stringpar ( const char * s ) : v ( s ) { }
stringpar ( eMonster m ) { v = minf [ m ] . name ; }
stringpar ( eLand l ) { v = linf [ l ] . name ; }
stringpar ( eWall w ) { v = winf [ w ] . name ; }
stringpar ( eItem i ) { v = iinf [ i ] . name ; }
} ;
string XLAT ( string x ) ;
string XLAT ( string x , stringpar p1 ) ;
string XLAT ( string x , stringpar p1 , stringpar p2 ) ;
string XLAT ( string x , stringpar p1 , stringpar p2 , stringpar p3 ) ;
string XLAT ( string x , stringpar p1 , stringpar p2 , stringpar p3 , stringpar p4 ) ;
string XLAT ( string x , stringpar p1 , stringpar p2 , stringpar p3 , stringpar p4 , stringpar p5 ) ;
2018-04-03 21:39:18 +00:00
2018-04-09 15:40:12 +00:00
namespace gp {
2018-04-05 22:31:25 +00:00
typedef pair < int , int > loc ;
2019-02-17 17:28:20 +00:00
loc operator + ( loc e1 , loc e2 ) ;
loc operator - ( loc e1 , loc e2 ) ;
loc operator * ( loc e1 , loc e2 ) ;
extern loc eudir ( int dir ) ;
2019-03-10 13:35:30 +00:00
int length ( loc p ) ;
2019-02-17 17:28:20 +00:00
# if CAP_GP
2018-04-03 21:39:18 +00:00
void compute_geometry ( ) ;
void extend_map ( cell * c , int d ) ;
2018-04-05 22:31:25 +00:00
extern loc param ;
extern int area ;
extern int pseudohept_val ( cell * ) ;
extern int last_dir ( cell * c ) ;
2018-08-20 00:04:49 +00:00
extern void configure ( ) ;
2018-04-05 22:31:25 +00:00
extern ld alpha ;
2018-11-23 22:46:26 +00:00
extern transmatrix Tf [ MAX_EDGE ] [ 32 ] [ 32 ] [ 6 ] ;
2018-04-05 22:31:25 +00:00
struct local_info {
int last_dir ;
loc relative ;
int first_dir ;
int total_dir ;
} ;
2019-03-08 21:38:44 +00:00
extern local_info draw_li ;
2018-04-05 22:31:25 +00:00
local_info get_local_info ( cell * c ) ;
const char * disp ( loc at ) ;
2018-04-06 20:22:33 +00:00
2018-04-10 22:55:05 +00:00
void be_in_triangle ( local_info & li ) ;
2018-04-10 06:05:35 +00:00
2018-04-06 20:22:33 +00:00
int compute_dist ( cell * c , int master_function ( cell * ) ) ;
2018-04-10 15:06:04 +00:00
int solve_triangle ( int dmain , int d0 , int d1 , loc at ) ;
2018-04-13 11:19:45 +00:00
2018-12-03 09:40:19 +00:00
hyperpoint get_master_coordinates ( cell * c ) ;
2018-09-23 11:56:00 +00:00
loc univ_param ( ) ;
2019-02-17 17:28:20 +00:00
# endif
int dist_1 ( ) , dist_2 ( ) , dist_3 ( ) ;
array < heptagon * , 3 > get_masters ( cell * c ) ;
extern string operation_name ( ) ;
2018-04-03 21:39:18 +00:00
}
int get_sightrange ( ) ;
2018-04-11 11:16:40 +00:00
int get_sightrange_ambush ( ) ;
2018-04-03 21:39:18 +00:00
int gamerange ( ) ;
int numplayers ( ) ;
extern int base_distlimit ;
2018-04-04 11:50:21 +00:00
bool has_nice_dual ( ) ;
2018-04-05 22:31:25 +00:00
extern hyperpoint mid ( const hyperpoint & h1 , const hyperpoint & h2 ) ;
void loadNewConfig ( FILE * f ) ;
struct supersaver {
string name ;
virtual string save ( ) = 0 ;
virtual void load ( const string & s ) = 0 ;
virtual bool dosave ( ) = 0 ;
virtual void reset ( ) = 0 ;
2018-07-03 10:00:02 +00:00
virtual ~ supersaver ( ) { } ;
2018-04-05 22:31:25 +00:00
} ;
typedef vector < shared_ptr < supersaver > > saverlist ;
extern saverlist savers ;
extern string ftssmart ( ld x ) ;
string itsh ( int i ) ;
# if CAP_CONFIG
template < class T > struct dsaver : supersaver {
T & val ;
T dft ;
bool dosave ( ) { return val ! = dft ; }
void reset ( ) { val = dft ; }
dsaver ( T & val ) : val ( val ) { }
} ;
template < class T > struct saver : dsaver < T > { } ;
template < class T , class U , class V > void addsaver ( T & i , U name , V dft ) {
auto s = make_shared < saver < T > > ( i ) ;
s - > dft = dft ;
s - > name = name ;
savers . push_back ( s ) ;
}
template < class T > void addsaver ( T & i , string name ) {
addsaver ( i , name , i ) ;
}
template < class T > struct saverenum : supersaver {
T & val ;
T dft ;
bool dosave ( ) { return val ! = dft ; }
void reset ( ) { val = dft ; }
saverenum < T > ( T & v ) : val ( v ) { }
2018-08-28 15:17:34 +00:00
string save ( ) { return its ( int ( val ) ) ; }
2018-04-05 22:31:25 +00:00
void load ( const string & s ) { val = ( T ) atoi ( s . c_str ( ) ) ; }
} ;
template < class T , class U > void addsaverenum ( T & i , U name , T dft ) {
auto s = make_shared < saverenum < T > > ( i ) ;
s - > dft = dft ;
s - > name = name ;
savers . push_back ( s ) ;
}
template < class T , class U > void addsaverenum ( T & i , U name ) {
addsaverenum ( i , name , i ) ;
}
template < > struct saver < int > : dsaver < int > {
saver < int > ( int & val ) : dsaver < int > ( val ) { }
string save ( ) { return its ( val ) ; }
void load ( const string & s ) { val = atoi ( s . c_str ( ) ) ; }
} ;
template < > struct saver < char > : dsaver < char > {
saver < char > ( char & val ) : dsaver < char > ( val ) { }
string save ( ) { return its ( val ) ; }
void load ( const string & s ) { val = atoi ( s . c_str ( ) ) ; }
} ;
template < > struct saver < bool > : dsaver < bool > {
saver < bool > ( bool & val ) : dsaver < bool > ( val ) { }
string save ( ) { return val ? " yes " : " no " ; }
2018-06-22 12:47:24 +00:00
void load ( const string & s ) { val = isize ( s ) & & s [ 0 ] = = ' y ' ; }
2018-04-05 22:31:25 +00:00
} ;
template < > struct saver < unsigned > : dsaver < unsigned > {
saver < unsigned > ( unsigned & val ) : dsaver < unsigned > ( val ) { }
string save ( ) { return itsh ( val ) ; }
void load ( const string & s ) { val = ( unsigned ) strtoll ( s . c_str ( ) , NULL , 16 ) ; }
} ;
template < > struct saver < string > : dsaver < string > {
saver < string > ( string & val ) : dsaver < string > ( val ) { }
string save ( ) { return val ; }
void load ( const string & s ) { val = s ; }
} ;
template < > struct saver < ld > : dsaver < ld > {
saver < ld > ( ld & val ) : dsaver < ld > ( val ) { }
string save ( ) { return ftssmart ( val ) ; }
void load ( const string & s ) {
if ( s = = " 0.0000000000e+000 " ) ; // ignore!
else val = atof ( s . c_str ( ) ) ;
}
} ;
# endif
2018-09-04 17:53:42 +00:00
extern vector < unique_ptr < drawqueueitem > > ptds ;
2018-04-05 22:31:25 +00:00
extern ld intval ( const hyperpoint & h1 , const hyperpoint & h2 ) ;
transmatrix euscalezoom ( hyperpoint h ) ;
transmatrix euaffine ( hyperpoint h ) ;
2019-02-22 19:58:40 +00:00
transmatrix eupush ( ld x , ld y ) ;
transmatrix eupush3 ( ld x , ld y , ld z ) ;
2018-04-05 22:31:25 +00:00
transmatrix eupush ( hyperpoint h ) ;
transmatrix rspintox ( const hyperpoint & H ) ;
transmatrix gpushxto0 ( const hyperpoint & H ) ;
transmatrix build_matrix ( hyperpoint h1 , hyperpoint h2 , hyperpoint h3 ) ;
hyperpoint normalize ( hyperpoint H ) ;
2019-03-20 01:18:28 +00:00
ld signum ( ld x ) ;
2018-04-05 22:31:25 +00:00
extern ld hrandf ( ) ;
namespace glhr {
struct glmatrix {
GLfloat a [ 4 ] [ 4 ] ;
GLfloat * operator [ ] ( int i ) { return a [ i ] ; }
const GLfloat * operator [ ] ( int i ) const { return a [ i ] ; }
GLfloat * as_array ( ) { return a [ 0 ] ; }
const GLfloat * as_array ( ) const { return a [ 0 ] ; }
} ;
2019-02-25 12:17:10 +00:00
enum class shader_projection { standard , band , halfplane , standardH3 , standardR3 ,
2019-03-20 18:53:59 +00:00
standardS30 , standardS31 , standardS32 , standardS33 ,
2019-03-20 20:17:31 +00:00
ball , halfplane3 , band3 ,
2019-03-20 18:53:59 +00:00
MAX
2019-02-25 12:17:10 +00:00
} ;
2018-11-17 16:59:57 +00:00
extern shader_projection new_shader_projection ;
2018-04-05 22:31:25 +00:00
void set_depthtest ( bool b ) ;
glmatrix translate ( ld x , ld y , ld z ) ;
2019-02-06 17:39:53 +00:00
void color2 ( color_t color , ld scale = 1 ) ;
2018-11-17 16:59:57 +00:00
void be_nontextured ( shader_projection sp = new_shader_projection ) ;
void be_textured ( shader_projection sp = new_shader_projection ) ;
2019-04-29 01:37:27 +00:00
void use_projection ( shader_projection sp = new_shader_projection ) ;
2018-04-05 22:31:25 +00:00
void set_modelview ( const glmatrix & m ) ;
hyperpoint gltopoint ( const glvertex & t ) ;
glvertex pointtogl ( const hyperpoint & t ) ;
2019-02-22 19:58:40 +00:00
inline glvertex makevertex ( GLfloat x , GLfloat y , GLfloat z ) {
2019-02-24 18:40:01 +00:00
# if SHDIM == 3
2019-03-01 17:53:32 +00:00
return make_array ( x , y , z ) ;
2019-02-24 18:40:01 +00:00
# else
2019-03-01 17:53:32 +00:00
return make_array < GLfloat > ( x , y , z , 1 ) ;
2019-02-24 18:40:01 +00:00
# endif
2019-02-22 19:58:40 +00:00
}
2018-04-05 22:31:25 +00:00
struct colored_vertex {
2019-02-24 18:40:01 +00:00
glvertex coords ;
2018-04-05 22:31:25 +00:00
glvec4 color ;
colored_vertex ( GLfloat x , GLfloat y , GLfloat r , GLfloat g , GLfloat b ) {
coords [ 0 ] = x ;
coords [ 1 ] = y ;
2018-11-17 18:24:02 +00:00
coords [ 2 ] = current_display - > scrdist ;
2019-03-11 17:38:16 +00:00
coords [ 3 ] = 1 ;
2018-04-05 22:31:25 +00:00
color [ 0 ] = r ;
color [ 1 ] = g ;
color [ 2 ] = b ;
color [ 3 ] = 1 ;
}
} ;
struct textured_vertex {
2019-02-24 18:40:01 +00:00
glvertex coords ;
2019-02-22 19:58:40 +00:00
glvec2 texture ;
2018-04-05 22:31:25 +00:00
} ;
struct ct_vertex {
2019-02-24 18:40:01 +00:00
glvertex coords ;
2018-04-05 22:31:25 +00:00
glvec4 color ;
2019-02-22 19:58:40 +00:00
glvec2 texture ;
2018-04-05 22:31:25 +00:00
ct_vertex ( const hyperpoint & h , ld x1 , ld y1 , ld col ) {
coords = pointtogl ( h ) ;
texture [ 0 ] = x1 ;
texture [ 1 ] = y1 ;
color [ 0 ] = color [ 1 ] = color [ 2 ] = col ;
color [ 3 ] = 1 ;
}
} ;
void prepare ( vector < textured_vertex > & v ) ;
void prepare ( vector < colored_vertex > & v ) ;
void prepare ( vector < ct_vertex > & v ) ;
}
2018-09-04 17:53:42 +00:00
void prettypoly ( const vector < hyperpoint > & t , color_t fillcol , color_t linecol , int lev ) ;
2019-02-17 18:39:44 +00:00
# if CAP_SHAPES
2018-09-04 17:53:42 +00:00
dqi_poly & queuepolyat ( const transmatrix & V , const hpcshape & h , color_t col , PPR prio ) ;
2019-02-17 18:39:44 +00:00
# endif
2018-09-04 17:53:42 +00:00
dqi_poly & queuetable ( const transmatrix & V , const vector < glvertex > & f , int cnt , color_t linecol , color_t fillcol , PPR prio ) ;
2018-04-05 22:31:25 +00:00
2019-02-17 18:39:44 +00:00
# if CAP_SHAPES
2018-05-07 18:13:56 +00:00
struct floorshape ;
2018-04-05 22:31:25 +00:00
struct qfloorinfo {
transmatrix spin ;
const hpcshape * shape ;
2019-03-11 17:46:34 +00:00
floorshape * fshape ;
2018-04-05 22:31:25 +00:00
textureinfo * tinf ;
2018-08-27 17:27:35 +00:00
int usershape ;
2018-04-05 22:31:25 +00:00
} ;
extern qfloorinfo qfi ;
struct hpcshape {
2018-08-28 11:45:11 +00:00
int s , e ;
PPR prio ;
2018-04-05 22:31:25 +00:00
int flags ;
2018-09-07 14:18:40 +00:00
hyperpoint intester ;
2019-04-20 23:09:38 +00:00
basic_textureinfo * tinf ;
int texture_offset ;
2018-04-05 22:31:25 +00:00
} ;
2018-05-07 18:13:56 +00:00
extern hpcshape shFullCross [ 2 ] ;
2019-03-15 11:45:57 +00:00
void bshape ( hpcshape & sh , PPR prio ) ;
void hpcpush ( hyperpoint h ) ;
void finishshape ( ) ;
void extra_vertices ( ) ;
extern vector < hyperpoint > hpc ;
extern hpcshape * last ;
extern vector < hpcshape > shPlainWall3D , shWireframe3D , shWall3D , shMiniWall3D ;
2019-02-17 18:39:44 +00:00
# endif
2018-04-05 22:31:25 +00:00
int fix6 ( int a ) ;
int fix7 ( int a ) ;
int fixdir ( int a , cell * c ) ;
cell * newCell ( int type , heptagon * master ) ;
2018-09-04 17:53:42 +00:00
extern color_t qpixel_pixel_outside ;
2018-04-05 22:31:25 +00:00
2018-09-04 17:53:42 +00:00
void queuechr ( int x , int y , int shift , int size , char chr , color_t col , int frame = 0 , int align = 8 ) ;
2018-04-05 22:31:25 +00:00
int zebra3 ( cell * c ) ;
int geosupport_threecolor ( ) ;
2018-08-20 13:24:44 +00:00
int geosupport_football ( ) ;
2018-08-30 14:44:17 +00:00
bool geosupport_chessboard ( ) ;
2018-04-05 22:31:25 +00:00
bool ishex1 ( cell * c ) ;
namespace fieldpattern { int fieldval_uniq ( cell * c ) ; int fieldval_uniq_rand ( cell * c , int d ) ; }
bool warptype ( cell * c ) ;
2018-04-10 06:05:35 +00:00
bool horo_ok ( ) ;
2019-03-09 22:56:12 +00:00
bool deep_ocean_at ( cell * c , cell * from ) ;
int wallchance ( cell * c , bool deepOcean ) ;
2018-04-10 15:06:04 +00:00
ld master_to_c7_angle ( ) ;
2018-04-14 08:24:02 +00:00
extern int mutantphase ;
2018-04-21 10:14:25 +00:00
void resize_screen_to ( int x , int y ) ;
2018-04-21 15:57:30 +00:00
extern bool canvas_invisible ;
2018-04-23 11:20:36 +00:00
extern cell * pd_from ;
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
}
enum eOrbLandRelation {
olrForbidden , // never appears: forbidden
olrDangerous , // never appears: would be dangerous
olrUseless , // never appears: useless here
olrNoPrizes , // no prizes in this land
olrNoPrizeOrb , // orb not allowed as a prize
olrPrize25 , // prize for collecting 25
olrPrize3 , // prize for collecting 3
olrNative , // native orb in this land
olrNative1 , // native orb in this land (1)
olrGuest , // extra orb in this land
olrPNative , // Land of Power: native
olrPBasic , // Land of Power: basic orbs
olrPPrized , // Land of Power: prized orbs
olrPNever , // Land of Power: foreign orbs
olrHub , // hub lands
olrMonster , // available from a monster
olrAlways , // always available
olrBurns // burns
} ;
2018-05-04 00:40:46 +00:00
namespace torusconfig {
extern int sdx , sdy ;
2018-12-14 18:24:27 +00:00
enum eTorusMode : char {
2018-05-04 00:40:46 +00:00
tmSingleHex ,
tmSingle ,
tmSlantedHex ,
tmStraight ,
tmStraightHex ,
tmKlein ,
2018-11-27 01:32:11 +00:00
tmKleinHex ,
tmCylinder ,
tmCylinderHex ,
tmMobius ,
tmMobiusHex ,
2018-05-04 00:40:46 +00:00
} ;
extern eTorusMode torus_mode ;
extern void activate ( ) ;
struct torusmode_info {
string name ;
flagtype flags ;
} ;
extern vector < torusmode_info > tmodes ;
2018-07-09 19:02:23 +00:00
enum : flagtype {
TF_SINGLE = 1 ,
TF_SIMPLE = 2 ,
TF_WEIRD = 4 ,
TF_HEX = 16 ,
TF_SQUARE = 32 ,
2018-11-27 01:32:11 +00:00
TF_CYL = 64 ,
TF_KLEIN = 256 ,
2018-07-09 19:02:23 +00:00
} ;
flagtype tmflags ( ) ;
2018-05-04 00:40:46 +00:00
}
2019-02-17 17:33:15 +00:00
# if CAP_FIELD
2018-05-04 00:40:46 +00:00
namespace fieldpattern {
extern int current_extra ;
struct primeinfo {
int p ;
int cells ;
bool squared ;
} ;
struct fgeomextra {
eGeometry base ;
vector < primeinfo > primes ;
int current_prime_id ;
fgeomextra ( eGeometry b , int i ) : base ( b ) , current_prime_id ( i ) { }
} ;
extern vector < fgeomextra > fgeomextras ;
extern void enableFieldChange ( ) ;
}
2019-02-17 17:33:15 +00:00
# endif
2018-05-04 00:40:46 +00:00
bool incompatible ( eLand l1 , eLand l2 ) ;
eOrbLandRelation getOLR ( eItem it , eLand l ) ;
2018-05-04 10:20:50 +00:00
struct plainshape ;
void clear_plainshape ( plainshape & gsh ) ;
2019-02-17 17:28:20 +00:00
# if CAP_GP
2018-05-04 10:20:50 +00:00
void build_plainshape ( plainshape & gsh , gp : : local_info & li ) ;
2019-02-17 17:28:20 +00:00
# endif
2018-05-04 10:20:50 +00:00
namespace gp {
void clear_plainshapes ( ) ;
plainshape & get_plainshape ( ) ;
}
extern bool debug_geometry ;
2018-05-07 18:13:56 +00:00
2019-02-17 18:39:44 +00:00
# if CAP_SHAPES
2018-09-04 17:53:42 +00:00
dqi_poly & queuepoly ( const transmatrix & V , const hpcshape & h , color_t col ) ;
dqi_poly & queuepolyat ( const transmatrix & V , const hpcshape & h , color_t col , PPR prio ) ;
2019-02-17 18:39:44 +00:00
# endif
2018-05-07 18:13:56 +00:00
2018-09-04 17:53:42 +00:00
void queuestr ( const hyperpoint & h , int size , const string & chr , color_t col , int frame = 0 ) ;
void queuechr ( const transmatrix & V , double size , char chr , color_t col , int frame = 0 ) ;
2018-05-07 18:13:56 +00:00
extern bool just_gmatrix ;
2018-05-15 21:23:12 +00:00
bool haveLeaderboard ( int id ) ;
int get_currentscore ( int id ) ;
void set_priority_board ( int id ) ;
int get_sync_status ( ) ;
bool score_loaded ( int id ) ;
int score_default ( int id ) ;
2018-05-25 23:10:23 +00:00
void handle_event ( SDL_Event & ev ) ;
2018-06-10 22:58:38 +00:00
void pop_game ( ) ;
void push_game ( ) ;
void start_game ( ) ;
void stop_game ( ) ;
void switch_game_mode ( char switchWhat ) ;
void stop_game_and_switch_mode ( char switchWhat = rg : : nothing ) ; // stop_game + switch_game_mode
void restart_game ( char switchWhat = rg : : nothing ) ; // popAllScreens + popAllGames + stop_game + switch_game_mode + start_game
2018-06-10 23:12:18 +00:00
2018-08-28 15:17:34 +00:00
// these work as stop_game_and_switch_mode
void set_variation ( eVariation ) ;
void set_geometry ( eGeometry ) ;
2018-06-10 23:12:18 +00:00
void generate_floorshapes ( ) ;
void drawArrowTraps ( ) ;
void drawBlizzards ( ) ;
struct blizzardcell ;
extern vector < cell * > arrowtraps ;
extern map < cell * , blizzardcell > blizzardcells ;
extern vector < blizzardcell * > bcells ;
void set_blizzard_frame ( cell * c , int frameid ) ;
# define SIDE_SLEV 0
# define SIDE_WALL 3
# define SIDE_LAKE 4
# define SIDE_LTOB 5
# define SIDE_BTOI 6
# define SIDE_WTS3 7
# define SIDEPARS 8
2019-02-17 18:39:44 +00:00
# if CAP_SHAPES
2018-06-10 23:12:18 +00:00
struct floorshape {
bool is_plain ;
2018-08-28 11:45:11 +00:00
int shapeid ;
2019-03-16 21:15:48 +00:00
int pstrength ; // pattern strength in 3D
int fstrength ; // frame strength in 3D
2018-08-28 11:45:11 +00:00
PPR prio ;
2018-08-17 19:44:03 +00:00
vector < hpcshape > b , shadow , side [ SIDEPARS ] , gpside [ SIDEPARS ] [ MAX_EDGE ] ;
2019-03-11 17:46:34 +00:00
basic_textureinfo tinf3 ;
2019-03-16 21:15:48 +00:00
floorshape ( ) { prio = PPR : : FLOOR ; pstrength = fstrength = 10 ; }
2018-06-10 23:12:18 +00:00
} ;
extern vector < struct plain_floorshape * > all_plain_floorshapes ;
extern vector < struct escher_floorshape * > all_escher_floorshapes ;
struct plain_floorshape : floorshape {
ld rad0 , rad1 ;
plain_floorshape ( ) { is_plain = true ; all_plain_floorshapes . push_back ( this ) ; }
void configure ( ld r0 , ld r1 ) { rad0 = r0 ; rad1 = r1 ; }
} ;
// noftype: 0 (shapeid2 is heptagonal or just use shapeid1), 1 (shapeid2 is pure heptagonal), 2 (shapeid2 is Euclidean), 3 (shapeid2 is hexagonal)
struct escher_floorshape : floorshape {
int shapeid0 , shapeid1 , noftype , shapeid2 ;
ld scale ;
escher_floorshape ( int s0 , int s1 , int noft = 0 , int s2 = 0 ) : shapeid0 ( s0 ) , shapeid1 ( s1 ) , noftype ( noft ) , shapeid2 ( s2 ) {
all_escher_floorshapes . push_back ( this ) ; scale = 1 ; is_plain = false ;
}
} ;
extern plain_floorshape
shFloor ,
shMFloor , shMFloor2 , shMFloor3 , shMFloor4 , shFullFloor ,
shBigTriangle , shTriheptaFloor , shBigHepta ;
extern escher_floorshape shDragonFloor , shPowerFloor , shRedRockFloor [ 3 ] ;
2019-02-17 18:39:44 +00:00
# endif
2018-06-10 23:58:31 +00:00
# if ISMOBILE
bool buttonclicked ;
void gdpush ( int t ) ;
# endif
extern int fontscale ;
2018-06-17 15:51:26 +00:00
bool confusingGeometry ( ) ;
int revhint ( cell * c , int hint ) ;
2018-06-28 10:59:35 +00:00
extern int pathlock ;
extern void computePathdist ( eMonster m ) ;
extern void onpath ( cell * c , int d ) ;
extern void clear_pathdata ( ) ;
struct pathdata {
void checklock ( ) {
if ( pd_from ) pd_from = NULL , clear_pathdata ( ) ;
if ( pathlock ) printf ( " path error \n " ) ;
pathlock + + ;
}
~ pathdata ( ) {
pathlock - - ;
clear_pathdata ( ) ;
}
pathdata ( eMonster m ) {
checklock ( ) ;
computePathdist ( m ) ;
}
pathdata ( int i ) {
checklock ( ) ;
}
} ;
2018-07-09 18:38:20 +00:00
extern int timetowait ;
2018-07-09 19:02:23 +00:00
extern vector < pair < cell * , int > > airmap ;
extern void compute_graphical_distance ( ) ;
extern ld scalef ;
struct help_extension {
char key ;
string text ;
2018-09-05 13:19:51 +00:00
string subtext ;
color_t color ;
2018-07-09 19:02:23 +00:00
reaction_t action ;
2018-09-05 13:19:51 +00:00
help_extension ( ) { color = forecolor ; }
help_extension ( char k , string t , reaction_t a ) : key ( k ) , text ( t ) , action ( a ) { color = forecolor ; }
2018-07-09 19:02:23 +00:00
} ;
extern vector < help_extension > help_extensions ;
namespace gamestack {
bool pushed ( ) ;
}
namespace geom3 {
extern ld BODY ;
2019-02-28 02:41:59 +00:00
extern ld depth , camera , wall_height , creature_scale , height_width ;
2018-07-09 19:02:23 +00:00
}
2018-09-04 17:53:42 +00:00
void queuestr ( const transmatrix & V , double size , const string & chr , color_t col , int frame = 0 , int align = 8 ) ;
void queuestr ( int x , int y , int shift , int size , string str , color_t col , int frame = 0 , int align = 8 ) ;
2018-07-09 19:02:23 +00:00
ld frac ( ld x ) ;
2018-09-04 17:53:42 +00:00
extern color_t poly_outline ;
2018-07-09 19:02:23 +00:00
2019-02-17 18:39:44 +00:00
# if CAP_SHAPES
2019-01-02 21:03:23 +00:00
extern hpcshape shDisk , shTriangle , shHeptaMarker , shSnowball , shDiskT , shDiskS , shDiskSq , shDiskM , shTinyBird , shTinyShark , shAsymmetric ;
2019-02-17 18:39:44 +00:00
# endif
2018-07-09 19:02:23 +00:00
extern std : : mt19937 hrngen ;
2018-07-10 19:51:28 +00:00
bool anglestraight ( cell * c , int d1 , int d2 ) ;
2018-07-16 18:02:33 +00:00
hyperpoint randomPointIn ( int t ) ;
void buildpolys ( ) ;
bool compute_relamatrix ( cell * src , cell * tgt , int direction_hint , transmatrix & T ) ;
extern bool need_reset_geometry ;
extern ld hexshift ;
2018-07-19 22:04:23 +00:00
extern bool noshadow , bright , nohelp , dont_face_pc ;
2018-07-19 22:07:30 +00:00
extern void switchHardcore ( ) ;
2018-07-21 15:46:14 +00:00
2018-11-17 16:59:57 +00:00
extern bool shaderside_projection ;
2018-07-21 22:39:57 +00:00
2018-07-23 03:14:19 +00:00
namespace ors {
extern int mode ;
extern string choices [ ] ;
void show ( ) ;
void apply ( ) ;
void check_orientation ( ) ;
void unrotate ( transmatrix & T ) ;
void rerotate ( transmatrix & T ) ;
void reset ( ) ;
}
2018-07-23 14:08:08 +00:00
2018-07-30 07:51:57 +00:00
bool saved_tortoise_on ( cell * c ) ;
2019-02-26 13:36:37 +00:00
# define RING(i) for(double i=0; i<=S84+1e-6; i+=SD3 * pow(.5, vid.linequality))
# define REVRING(i) for(double i=S84; i>=-1e-6; i-=SD3 * pow(.5, vid.linequality))
2018-08-01 09:07:22 +00:00
# define PRING(i) for(double i=0; i<=S84+1e-6; i+= pow(.5, vid.linequality))
2018-08-01 13:03:48 +00:00
# define REVPRING(i) for(double i=S84; i>=-1e-6; i-=pow(.5, vid.linequality))
2019-02-17 17:28:20 +00:00
# if CAP_BT
2018-08-09 17:28:53 +00:00
void horopoint ( ld y , ld x ) ;
2019-02-22 19:58:40 +00:00
hyperpoint get_horopoint ( ld y , ld x ) ;
hyperpoint get_horopoint3 ( ld y , ld x , ld z ) ;
2018-08-09 17:28:53 +00:00
namespace binary {
2019-02-22 19:58:40 +00:00
transmatrix parabolic ( ld u ) ;
transmatrix parabolic3 ( ld u , ld v ) ;
extern ld btrange , btrange_cosh ;
2019-03-08 21:38:44 +00:00
hrmap * new_map ( ) ;
hrmap * new_alt_map ( heptagon * o ) ;
2018-08-09 17:28:53 +00:00
}
2019-02-17 17:28:20 +00:00
# endif
2018-08-09 17:28:53 +00:00
2019-02-27 22:30:26 +00:00
# if MAXMDIM == 4
2019-02-24 22:04:52 +00:00
namespace euclid3 {
2019-02-24 21:12:32 +00:00
hrmap * new_map ( ) ;
void draw ( ) ;
2019-04-11 22:17:50 +00:00
int dist_relative ( cell * c ) ;
2019-04-15 21:29:07 +00:00
void build_torus3 ( ) ;
void clear_torus3 ( ) ;
void show_torus3 ( ) ;
2019-02-24 21:12:32 +00:00
}
2019-03-02 23:43:31 +00:00
namespace reg3 {
void generate ( ) ;
hrmap * new_map ( ) ;
extern vector < hyperpoint > cellshape ;
int celldistance ( cell * c1 , cell * c2 ) ;
bool pseudohept ( cell * c ) ;
2019-03-09 00:00:46 +00:00
inline short & altdist ( heptagon * h ) { return h - > emeraldval ; }
2019-03-15 11:45:57 +00:00
extern transmatrix spins [ 12 ] , adjmoves [ 12 ] ;
int bucketer ( hyperpoint h ) ;
extern bool dirs_adjacent [ 16 ] [ 16 ] ;
cellwalker strafe ( cellwalker cw , int j ) ;
2019-03-02 23:43:31 +00:00
}
2019-02-24 21:12:32 +00:00
# endif
2018-08-19 21:06:32 +00:00
namespace arcm {
2019-02-17 17:28:20 +00:00
# if CAP_ARCM
2018-09-03 14:32:34 +00:00
struct archimedean_tiling {
int coloring ;
string symbol ;
vector < int > faces ;
vector < int > adj ;
vector < bool > invert ;
vector < int > nflags ;
bool have_ph , have_line , have_symmetry ;
int real_faces ;
int real_face_type ;
int repetition ;
int N ;
ld euclidean_angle_sum ;
vector < int > flags ;
vector < vector < pair < int , int > > > adjacent ;
vector < vector < pair < ld , ld > > > triangles ;
void make_match ( int a , int i , int b , int j ) ;
void prepare ( ) ;
void compute_geometry ( ) ;
void parse ( ) ;
void parse ( string s ) { symbol = s ; parse ( ) ; }
ld edgelength ;
vector < ld > inradius , circumradius , alphas ;
int matches [ 30 ] [ 30 ] ;
int periods [ 30 ] ;
int tilegroup [ 30 ] , groupoffset [ 30 ] , tilegroups ;
int errors ;
string errormsg ;
pair < int , int > & get_adj ( heptagon * h , int cid ) ;
pair < int , int > & get_adj ( heptspin hs ) { return get_adj ( hs . at , hs . spin ) ; }
pair < ld , ld > & get_triangle ( heptagon * h , int cid ) ;
pair < ld , ld > & get_triangle ( heptspin hs ) { return get_triangle ( hs . at , hs . spin ) ; }
pair < ld , ld > & get_triangle ( const pair < int , int > & p , int delta = 0 ) ;
pair < int , int > & get_adj ( const pair < int , int > & p , int delta = 0 ) ;
int support_threecolor ( ) ;
int support_threecolor_bitruncated ( ) ;
int support_football ( ) ;
bool support_chessboard ( ) ;
void regroup ( ) ;
string world_size ( ) ;
eGeometryClass get_class ( ) ;
ld scale ( ) ;
} ;
extern archimedean_tiling current ;
extern map < heptagon * , pair < heptagon * , transmatrix > > archimedean_gmatrix ;
2018-08-17 11:29:00 +00:00
void initialize ( heptagon * root ) ;
short & id_of ( heptagon * ) ;
int fix ( heptagon * h , int spin ) ;
2019-02-17 17:28:20 +00:00
# endif
2018-08-17 11:29:00 +00:00
}
2018-08-17 14:53:57 +00:00
2018-11-30 15:31:55 +00:00
namespace crystal {
2019-02-17 17:28:20 +00:00
# if CAP_CRYSTAL
2019-01-28 20:40:26 +00:00
static const int MAXDIM = 7 ;
typedef array < int , MAXDIM > coord ;
static const coord c0 = { } ;
typedef array < ld , MAXDIM > ldcoord ;
static const ldcoord ldc0 = { } ;
heptagon * get_heptagon_at ( coord c ) ;
coord get_coord ( heptagon * h ) ;
ldcoord get_ldcoord ( cell * c ) ;
2018-12-04 01:36:08 +00:00
extern colortable coordcolors ;
extern ld compass_probability ;
extern bool view_coordinates ;
2018-11-30 15:31:55 +00:00
color_t colorize ( cell * c ) ;
2018-12-01 22:53:03 +00:00
int precise_distance ( cell * c1 , cell * c2 ) ;
2018-12-04 20:16:39 +00:00
ld space_distance ( cell * c1 , cell * c2 ) ;
2018-11-30 15:31:55 +00:00
hrmap * new_map ( ) ;
2018-11-30 19:29:14 +00:00
void build_rugdata ( ) ;
void apply_rotation ( const transmatrix t ) ;
void switch_z_coordinate ( ) ;
void next_home_orientation ( ) ;
2018-12-06 10:43:10 +00:00
void flip_z ( ) ;
2018-12-01 22:53:03 +00:00
void set_land ( cell * c ) ;
int dist_alt ( cell * c ) ;
int dist_relative ( cell * c ) ;
2018-12-02 10:41:32 +00:00
void show ( ) ;
2018-12-02 19:26:58 +00:00
void init_rotation ( ) ;
2018-12-03 11:38:11 +00:00
string get_table_volume ( ) ;
string get_table_boundary ( ) ;
bool pure ( ) ;
2018-12-03 22:03:35 +00:00
ld compass_angle ( ) ;
2018-12-03 22:15:53 +00:00
string compass_help ( ) ;
2018-12-03 22:03:35 +00:00
void may_place_compass ( cell * c ) ;
2018-12-04 17:10:36 +00:00
void centerrug ( ld aspd ) ;
2018-12-04 21:35:00 +00:00
vector < cell * > build_shortest_path ( cell * c1 , cell * c2 ) ;
2019-02-17 17:28:20 +00:00
# endif
2018-11-30 15:31:55 +00:00
}
2018-08-17 14:53:57 +00:00
hyperpoint get_warp_corner ( cell * c , int cid ) ;
hyperpoint get_corner_position ( cell * c , int cid , ld cf = 3 ) ;
2018-08-18 22:25:43 +00:00
int decodeId ( heptagon * h ) ;
heptagon * encodeId ( int id ) ;
void virtualRebaseSimple ( heptagon * & base , transmatrix & at ) ;
2018-08-30 16:18:54 +00:00
extern bool game_active , playerfound ;
2018-08-20 00:04:49 +00:00
2018-09-05 13:19:51 +00:00
string bygen ( reaction_t h ) ;
2018-09-05 13:34:13 +00:00
# if CAP_URL
void open_url ( string s ) ;
# endif
2018-11-24 16:01:49 +00:00
// HyperRogue streams
struct hstream {
virtual void write_char ( char c ) = 0 ;
virtual void write_chars ( const char * c , size_t q ) { while ( q - - ) write_char ( * ( c + + ) ) ; }
virtual char read_char ( ) = 0 ;
virtual void read_chars ( char * c , size_t q ) { while ( q - - ) * ( c + + ) = read_char ( ) ; }
template < class T > void write ( const T & t ) { hwrite ( * this , t ) ; }
template < class T > void read ( T & t ) { hread ( * this , t ) ; }
template < class T > T get ( ) { T t ; hread ( * this , t ) ; return t ; }
template < class T > T get_raw ( ) { T t ; hread_raw ( * this , t ) ; return t ; }
} ;
template < class T > void hwrite_raw ( hstream & hs , const T & c ) { hs . write_chars ( ( char * ) & c , sizeof ( T ) ) ; }
template < class T > void hread_raw ( hstream & hs , T & c ) { hs . read_chars ( ( char * ) & c , sizeof ( T ) ) ; }
template < class T , typename = typename std : : enable_if < std : : is_integral < T > : : value | | std : : is_enum < T > : : value > : : type > void hwrite ( hstream & hs , const T & c ) { hwrite_raw ( hs , c ) ; }
template < class T , typename = typename std : : enable_if < std : : is_integral < T > : : value | | std : : is_enum < T > : : value > : : type > void hread ( hstream & hs , T & c ) { hread_raw ( hs , c ) ; }
inline void hwrite ( hstream & hs , const string & s ) { hs . write_char ( isize ( s ) ) ; for ( char c : s ) hs . write_char ( c ) ; }
inline void hread ( hstream & hs , string & s ) { s = " " ; int l = ( unsigned char ) hs . read_char ( ) ; for ( int i = 0 ; i < l ; i + + ) s + = hs . read_char ( ) ; }
inline void hwrite ( hstream & hs , const ld & h ) { double d = h ; hs . write_chars ( ( char * ) & d , sizeof ( double ) ) ; }
inline void hread ( hstream & hs , ld & h ) { double d ; hs . read_chars ( ( char * ) & d , sizeof ( double ) ) ; h = d ; }
template < class T , size_t X > void hwrite ( hstream & hs , const array < T , X > & a ) { for ( auto & ae : a ) hwrite ( hs , ae ) ; }
template < class T , size_t X > void hread ( hstream & hs , array < T , X > & a ) { for ( auto & ae : a ) hread ( hs , ae ) ; }
2019-04-20 23:01:02 +00:00
inline void hread ( hstream & hs , hyperpoint & h ) { for ( int i = 0 ; i < MDIM ; i + + ) hread ( hs , h [ i ] ) ; }
inline void hwrite ( hstream & hs , hyperpoint h ) { for ( int i = 0 ; i < MDIM ; i + + ) hwrite ( hs , h [ i ] ) ; }
2018-11-24 16:01:49 +00:00
template < class T > void hwrite ( hstream & hs , const vector < T > & a ) { hwrite < int > ( hs , isize ( a ) ) ; for ( auto & ae : a ) hwrite ( hs , ae ) ; }
template < class T > void hread ( hstream & hs , vector < T > & a ) { a . resize ( hs . get < int > ( ) ) ; for ( auto & ae : a ) hread ( hs , ae ) ; }
template < class T , class U > void hwrite ( hstream & hs , const map < T , U > & a ) {
hwrite < int > ( hs , isize ( a ) ) ; for ( auto & ae : a ) hwrite ( hs , ae . first , ae . second ) ;
}
template < class T , class U > void hread ( hstream & hs , map < T , U > & a ) {
a . clear ( ) ;
int N = hs . get < int > ( ) ;
for ( int i = 0 ; i < N ; i + + ) {
T key ; hread ( hs , key ) ;
hread ( hs , a [ key ] ) ;
}
}
template < class C , class C1 , class . . . CS > void hwrite ( hstream & hs , const C & c , const C1 & c1 , const CS & . . . cs ) { hwrite ( hs , c ) ; hwrite ( hs , c1 , cs . . . ) ; }
template < class C , class C1 , class . . . CS > void hread ( hstream & hs , C & c , C1 & c1 , CS & . . . cs ) { hread ( hs , c ) ; hread ( hs , c1 , cs . . . ) ; }
2019-04-03 18:24:15 +00:00
struct hstream_exception : hr_exception { hstream_exception ( ) { } } ;
2018-11-24 16:01:49 +00:00
struct fhstream : hstream {
FILE * f ;
virtual void write_char ( char c ) { write_chars ( & c , 1 ) ; }
2018-12-15 14:16:11 +00:00
virtual void write_chars ( const char * c , size_t i ) { if ( fwrite ( c , i , 1 , f ) ! = 1 ) throw hstream_exception ( ) ; }
2018-11-24 16:01:49 +00:00
virtual void read_chars ( char * c , size_t i ) { if ( fread ( c , i , 1 , f ) ! = 1 ) throw hstream_exception ( ) ; }
virtual char read_char ( ) { char c ; read_chars ( & c , 1 ) ; return c ; }
fhstream ( ) { f = NULL ; }
fhstream ( const string pathname , const char * mode ) { f = fopen ( pathname . c_str ( ) , mode ) ; }
~ fhstream ( ) { if ( f ) fclose ( f ) ; }
} ;
struct shstream : hstream {
string s ;
int pos ;
shstream ( ) { pos = 0 ; }
virtual void write_char ( char c ) { s + = c ; }
virtual char read_char ( ) { if ( pos = = isize ( s ) ) throw hstream_exception ( ) ; return s [ pos + + ] ; }
} ;
inline void print ( hstream & hs ) { }
template < class . . . CS > string sprint ( const CS & . . . cs ) { shstream hs ; print ( hs , cs . . . ) ; return hs . s ; }
template < class C , class C1 , class . . . CS > void print ( hstream & hs , const C & c , const C1 & c1 , const CS & . . . cs ) { print ( hs , c ) ; print ( hs , c1 , cs . . . ) ; }
template < class . . . CS > void println ( hstream & hs , const CS & . . . cs ) { print ( hs , cs . . . ) ; hs . write_char ( ' \n ' ) ; }
// copied from: https://stackoverflow.com/questions/16387354/template-tuple-calling-a-function-on-each-element
namespace detail
{
template < int . . . Is >
struct seq { } ;
template < int N , int . . . Is >
struct gen_seq : gen_seq < N - 1 , N - 1 , Is . . . > { } ;
template < int . . . Is >
struct gen_seq < 0 , Is . . . > : seq < Is . . . > { } ;
template < typename T , typename F , int . . . Is >
void for_each ( T & & t , F f , seq < Is . . . > )
{
auto l = { ( f ( std : : get < Is > ( t ) ) , 0 ) . . . } ; ignore ( l ) ;
}
}
template < typename . . . Ts , typename F >
void for_each_in_tuple ( std : : tuple < Ts . . . > const & t , F f )
{
detail : : for_each ( t , f , detail : : gen_seq < sizeof . . . ( Ts ) > ( ) ) ;
}
inline void print ( hstream & hs , const string & s ) { hs . write_chars ( s . c_str ( ) , isize ( s ) ) ; }
inline void print ( hstream & hs , int i ) { print ( hs , its ( i ) ) ; }
inline void print ( hstream & hs , ld x ) { print ( hs , fts ( x ) ) ; }
2018-12-13 13:54:15 +00:00
template < class T > void print ( hstream & hs , const walker < T > & w ) { print ( hs , " [ " , w . at , " / " , w . spin , " / " , w . mirrored , " ] " ) ; }
2018-11-24 16:01:49 +00:00
struct comma_printer {
bool first ;
hstream & hs ;
template < class T > void operator ( ) ( const T & t ) { if ( first ) first = false ; else print ( hs , " , " ) ; print ( hs , t ) ; }
comma_printer ( hstream & hs ) : first ( true ) , hs ( hs ) { }
} ;
template < class T , size_t X > void print ( hstream & hs , const array < T , X > & a ) { print ( hs , " ( " ) ; comma_printer c ( hs ) ; for ( const T & t : a ) c ( t ) ; print ( hs , " ) " ) ; }
template < class T > void print ( hstream & hs , const vector < T > & a ) { print ( hs , " ( " ) ; comma_printer c ( hs ) ; for ( const T & t : a ) c ( t ) ; print ( hs , " ) " ) ; }
2019-02-27 22:30:26 +00:00
inline void print ( hstream & hs , const hyperpoint h ) { print ( hs , ( const array < ld , MAXMDIM > & ) h ) ; }
2018-11-24 16:01:49 +00:00
inline void print ( hstream & hs , const transmatrix T ) {
print ( hs , " ( " ) ; comma_printer c ( hs ) ;
2019-02-21 17:46:53 +00:00
for ( int i = 0 ; i < MDIM ; i + + )
for ( int j = 0 ; j < MDIM ; j + + ) c ( T [ i ] [ j ] ) ;
2018-11-24 16:01:49 +00:00
print ( hs , " ) " ) ; }
template < class T , class U > void print ( hstream & hs , const pair < T , U > & t ) { print ( hs , " ( " , t . first , " , " , t . second , " ) " ) ; }
template < class . . . T > void print ( hstream & hs , const tuple < T . . . > & t ) {
print ( hs , " ( " ) ;
comma_printer p ( hs ) ;
for_each_in_tuple ( t , p ) ;
print ( hs , " ) " ) ;
}
# ifndef SPECIAL_LOGGER
inline void special_log ( char c ) { putchar ( c ) ; }
# endif
struct logger : hstream {
int indentation ;
2018-12-12 01:49:23 +00:00
bool doindent ;
logger ( ) { doindent = false ; }
2018-11-30 13:45:53 +00:00
virtual void write_char ( char c ) { if ( doindent ) { doindent = false ; for ( int i = 0 ; i < indentation ; i + + ) special_log ( ' ' ) ; } special_log ( c ) ; if ( c = = 10 ) doindent = true ; }
2018-11-24 16:01:49 +00:00
virtual char read_char ( ) { throw hstream_exception ( ) ; }
} ;
extern logger hlog ;
# ifdef __GNUC__
__attribute__ ( ( __format__ ( __printf__ , 1 , 2 ) ) )
# endif
inline string format ( const char * fmt , . . . ) {
char buf [ 1000 ] ;
va_list ap ;
va_start ( ap , fmt ) ;
vsnprintf ( buf , 1000 , fmt , ap ) ;
va_end ( ap ) ;
return buf ;
}
2018-09-07 13:15:00 +00:00
2018-11-24 16:01:49 +00:00
inline void print ( hstream & hs , heptagon * h ) { print ( hs , format ( " H%p " , h ) ) ; }
inline void print ( hstream & hs , cell * h ) { print ( hs , format ( " C%p " , h ) ) ; }
2018-09-07 13:15:00 +00:00
2018-11-24 16:01:49 +00:00
inline void print ( hstream & hs , cellwalker cw ) {
if ( cw . at ) print ( hs , " [ " , cw . at , " / " , cw . at - > type , " : " , cw . spin , " : " , cw . mirrored , " ] " ) ;
else print ( hs , " [NULL] " ) ;
2018-09-07 13:15:00 +00:00
}
2018-11-24 16:01:49 +00:00
struct indenter {
dynamicval < int > ind ;
indenter ( int i = 2 ) : ind ( hlog . indentation , hlog . indentation + ( i ) ) { }
} ;
2018-09-07 13:15:53 +00:00
void appendHelp ( string s ) ;
2018-09-10 15:26:27 +00:00
transmatrix rspintox ( const hyperpoint & H ) ;
extern bool playermoved ;
extern int tidalsize ;
extern void calcTidalPhase ( ) ;
void curvepoint ( const hyperpoint & H1 ) ;
dqi_poly & queuecurve ( color_t linecol , color_t fillcol , PPR prio ) ;
2018-11-18 17:13:15 +00:00
2018-09-10 15:26:27 +00:00
ld cos_auto ( ld x ) ;
2018-11-18 17:13:15 +00:00
ld sin_auto ( ld x ) ;
ld tan_auto ( ld x ) ;
ld asin_auto ( ld x ) ;
ld atan_auto ( ld x ) ;
ld atan2_auto ( ld x ) ;
ld atan2 ( hyperpoint h ) ;
2018-09-10 15:26:27 +00:00
2018-09-10 15:58:36 +00:00
namespace anims {
2019-02-17 17:43:39 +00:00
# if CAP_ANIMATIONS
2018-09-10 15:58:36 +00:00
void apply ( ) ;
void rollback ( ) ;
void show ( ) ;
bool any_on ( ) ;
bool any_animation ( ) ;
bool center_music ( ) ;
2018-09-10 17:44:01 +00:00
extern string animfile ;
extern int noframes ;
extern ld period , cycle_length , parabolic_length , rug_angle , circle_radius , circle_spins ;
2019-02-17 17:43:39 +00:00
# else
static bool any_on ( ) { return false ; }
static void rollback ( ) { }
static bool center_music ( ) { return false ; }
static bool any_animation ( ) { return false ; }
static void apply ( ) { }
# endif
2018-09-10 15:58:36 +00:00
}
2019-02-17 17:43:39 +00:00
# if CAP_STARTANIM
2018-12-17 10:33:52 +00:00
namespace startanims {
extern reaction_t current ;
void pick ( ) ;
}
2019-02-17 17:43:39 +00:00
# endif
2018-12-17 10:33:52 +00:00
2018-09-10 15:58:36 +00:00
extern int animation_lcm ;
extern ld animation_factor ;
2018-09-10 17:28:12 +00:00
ld parseld ( const string & s ) ;
2018-09-12 02:23:15 +00:00
pair < int , int > vec_to_pair ( int vec ) ;
struct bignum {
static const int BASE = 1000000000 ;
static const long long BASE2 = BASE * ( long long ) BASE ;
vector < int > digits ;
bignum ( ) { }
bignum ( int i ) : digits ( ) { digits . push_back ( i ) ; }
void be ( int i ) { digits . resize ( 1 ) ; digits [ 0 ] = i ; }
bignum & operator + = ( const bignum & b ) ;
2018-09-13 18:38:06 +00:00
void addmul ( const bignum & b , int factor ) ;
2018-09-12 02:23:15 +00:00
string get_str ( int max_length ) ;
2018-09-23 11:46:21 +00:00
bool operator < ( const bignum & ) const ;
ld leading ( ) const {
switch ( isize ( digits ) ) {
case 0 :
return 0 ;
case 1 :
return digits . back ( ) ;
default :
return digits . back ( ) + ld ( digits [ isize ( digits ) - 2 ] ) / BASE ;
}
}
ld approx ( ) const {
return leading ( ) * pow ( BASE , isize ( digits ) - 1 ) ;
}
2018-09-27 19:52:23 +00:00
ld log_approx ( ) const {
return log ( leading ( ) ) * log ( BASE ) * ( isize ( digits ) - 1 ) ;
}
2018-09-23 11:46:21 +00:00
ld operator / ( const bignum & b ) const {
return leading ( ) / b . leading ( ) * pow ( BASE , isize ( digits ) - isize ( b . digits ) ) ;
2018-09-12 02:23:15 +00:00
}
2018-09-23 11:46:21 +00:00
int approx_int ( ) const {
2018-09-12 02:23:15 +00:00
if ( isize ( digits ) > 1 ) return BASE ;
if ( digits . empty ( ) ) return 0 ;
return digits [ 0 ] ;
}
2018-09-23 11:46:21 +00:00
long long approx_ll ( ) const {
2018-09-12 02:23:15 +00:00
if ( isize ( digits ) > 2 ) return BASE2 ;
if ( digits . empty ( ) ) return 0 ;
if ( isize ( digits ) = = 1 ) return digits [ 0 ] ;
return digits [ 0 ] + digits [ 1 ] * ( long long ) BASE ;
}
2018-12-03 11:38:11 +00:00
friend inline bignum operator + ( bignum a , const bignum & b ) { a . addmul ( b , 1 ) ; return a ; }
friend inline bignum operator - ( bignum a , const bignum & b ) { a . addmul ( b , - 1 ) ; return a ; }
2018-09-12 02:23:15 +00:00
} ;
struct expansion_analyzer {
vector < int > gettype ( cell * c ) ;
int N ;
vector < cell * > samples ;
map < vector < int > , int > codeid ;
vector < vector < int > > children ;
int rootid , diskid ;
int coefficients_known ;
vector < int > coef ;
int valid_from , tested_to ;
ld growth ;
int sample_id ( cell * c ) ;
void preliminary_grouping ( ) ;
void reduce_grouping ( ) ;
vector < vector < bignum > > descendants ;
bignum & get_descendants ( int level ) ;
bignum & get_descendants ( int level , int type ) ;
void find_coefficients ( ) ;
void reset ( ) ;
expansion_analyzer ( ) { reset ( ) ; }
string approximate_descendants ( int d , int max_length ) ;
void view_distances_dialog ( ) ;
ld get_growth ( ) ;
private :
bool verify ( int id ) ;
int valid ( int v , int step ) ;
} ;
extern expansion_analyzer expansion ;
2018-09-27 19:52:13 +00:00
int towerval ( cell * c , const cellfunction & cf ) ;
int parent_id ( cell * c , int which , const cellfunction & cf ) ;
extern int sibling_limit ;
extern void set_sibling_limit ( ) ;
int type_in_reduced ( expansion_analyzer & ea , cell * c , const function < int ( cell * ) > & f ) ;
namespace ts {
cell * verified_add ( cell * c , int which , int bonus , const cellfunction & cf ) ;
cell * add ( cell * c , int which , int bonus , const cellfunction & cf ) ;
inline cell * left_parent ( cell * c , const cellfunction & cf ) { return verified_add ( c , 1 , 0 , cf ) ; }
inline cell * right_parent ( cell * c , const cellfunction & cf ) { return verified_add ( c , - 1 , 0 , cf ) ; }
cell * left_of ( cell * c , const cellfunction & cf ) ;
cell * right_of ( cell * c , const cellfunction & cf ) ;
cell * child_number ( cell * c , int id , const cellfunction & cf ) ;
}
void generate_around ( cell * c ) ;
2018-09-28 10:27:44 +00:00
int euclidAlt ( short x , short y ) ;
2018-12-04 18:13:26 +00:00
int cylinder_alt ( cell * c ) ;
2018-09-23 11:56:00 +00:00
2018-10-23 15:05:46 +00:00
struct exp_parser {
string s ;
int at ;
exp_parser ( ) { at = 0 ; }
2018-11-06 23:51:41 +00:00
map < string , cld > extra_params ;
2018-10-23 15:05:46 +00:00
bool ok ( ) { return at = = isize ( s ) ; }
2018-11-09 19:41:55 +00:00
char next ( int step = 0 ) { if ( at > = isize ( s ) - step | | at = = - 1 ) return 0 ; else return s [ at + step ] ; }
2018-10-23 15:05:46 +00:00
bool eat ( const char * c ) {
int orig_at = at ;
while ( * c & & * c = = next ( ) ) at + + , c + + ;
if ( * c = = 0 ) return true ;
else at = orig_at ;
return false ;
}
2018-11-06 23:51:41 +00:00
cld parse ( int prio = 0 ) ;
2018-10-23 15:05:46 +00:00
2018-11-06 23:51:41 +00:00
cld parsepar ( ) {
cld res = parse ( ) ;
2018-10-23 15:05:46 +00:00
if ( next ( ) ! = ' ) ' ) { at = - 1 ; return res ; }
at + + ;
return res ;
2018-11-06 23:51:41 +00:00
}
2018-10-23 15:05:46 +00:00
} ;
2018-10-25 00:43:14 +00:00
# if CAP_COMPLEX2
2018-11-01 17:59:25 +00:00
namespace brownian {
const int level = 5 ;
void init ( cell * c ) ;
void build ( cell * c , int d ) ;
void explosion ( cell * c , int x ) ;
} ;
# else
namespace brownian {
inline void dissolve_brownian ( cell * , int ) { } ;
inline void build ( cell * c , int d ) { }
inline void init ( cell * c ) { }
}
# endif
2018-12-21 13:43:38 +00:00
# define ONEMPTY if(d == 7 && passable(c, NULL, 0) && !safety && !reptilecheat)
extern bool reptilecheat ;
2018-11-01 17:59:25 +00:00
void enable_cheat ( ) ;
extern int cells_drawn ;
2018-11-01 19:54:44 +00:00
void menuitem_sightrange ( char c = ' r ' ) ;
2018-11-06 15:03:20 +00:00
2019-02-21 17:46:53 +00:00
bool invis_point ( const hyperpoint h ) ;
2018-12-04 21:40:29 +00:00
bool invalid_point ( const hyperpoint h ) ;
bool invalid_point ( const transmatrix T ) ;
2018-11-06 15:03:20 +00:00
bool in_smart_range ( const transmatrix & T ) ;
2018-11-06 23:53:10 +00:00
void curvepoint ( const hyperpoint & H1 ) ;
dqi_poly & queuecurve ( color_t linecol , color_t fillcol , PPR prio ) ;
2018-11-08 16:42:19 +00:00
bool haveaura ( ) ;
2018-11-07 00:03:27 +00:00
string parser_help ( ) ;
2018-11-08 17:18:25 +00:00
static const ld degree = M_PI / 180 ;
2018-11-08 20:56:06 +00:00
void show_color_dialog ( ) ;
2018-11-09 13:14:36 +00:00
extern ld band_shift ;
2018-12-21 13:42:59 +00:00
int cone_side ( const hyperpoint H ) ;
2018-11-09 13:14:36 +00:00
void fix_the_band ( transmatrix & T ) ;
struct bandfixer {
dynamicval < ld > bw ;
bandfixer ( transmatrix & T ) : bw ( band_shift , band_shift ) { fix_the_band ( T ) ; }
} ;
2018-11-09 19:41:55 +00:00
inline void delayed_geo_reset ( ) { need_reset_geometry = true ; }
2018-11-09 20:18:58 +00:00
extern unordered_map < string , ld & > params ;
2018-11-10 13:26:49 +00:00
namespace dq {
extern queue < tuple < heptagon * , transmatrix , ld > > drawqueue ;
2019-03-15 12:46:23 +00:00
extern set < heptagon * > visited ;
2018-11-10 13:26:49 +00:00
void enqueue ( heptagon * h , const transmatrix & T ) ;
2019-03-15 12:46:23 +00:00
extern set < int > visited_by_matrix ;
void enqueue_by_matrix ( heptagon * h , const transmatrix & T ) ;
2018-11-10 13:26:49 +00:00
}
2018-11-17 18:24:02 +00:00
typedef pair < string , reaction_t > named_functionality ;
inline named_functionality named_dialog ( string x , reaction_t dialog ) { return named_functionality ( x , [ dialog ] ( ) { pushScreen ( dialog ) ; } ) ; }
extern hookset < named_functionality ( ) > * hooks_o_key ;
named_functionality get_o_key ( ) ;
2018-11-18 17:13:15 +00:00
hyperpoint nearcorner ( cell * c , int i ) ;
extern bool showquotients ;
2018-11-10 13:26:49 +00:00
bool do_draw ( cell * c , const transmatrix & T ) ;
2018-11-24 14:35:02 +00:00
ld sintick ( int period , ld phase = 0 ) ;
2018-11-10 13:26:49 +00:00
2018-11-17 18:30:50 +00:00
# if CAP_RACING
namespace racing {
2019-01-17 00:15:28 +00:00
extern bool on , player_relative , track_ready , guiding , standard_centering ;
2019-01-11 01:24:13 +00:00
extern ld race_advance , race_angle ;
extern int ghosts_to_show , ghosts_to_save ;
2018-11-17 18:30:50 +00:00
void generate_track ( ) ;
2018-11-24 22:52:13 +00:00
void configure_race ( ) ;
2018-11-17 18:30:50 +00:00
void prepare_subscreens ( ) ;
extern vector < cell * > track ;
extern int current_player ;
2018-11-23 01:58:16 +00:00
extern vector < eLand > race_lands ;
2018-11-24 02:26:07 +00:00
extern string track_code ;
extern int race_start_tick , race_finish_tick [ MAXPLAYER ] ;
2018-11-24 14:35:02 +00:00
void race_won ( ) ;
void apply_seed ( ) ;
string racetimeformat ( int t ) ;
2018-12-23 12:10:46 +00:00
void add_debug ( cell * c ) ;
2019-01-11 01:19:28 +00:00
void displayScore ( eLand l ) ;
2018-11-17 18:30:50 +00:00
}
# else
2018-12-06 14:35:01 +00:00
// static bool on = false: emits a warning
// static const bool on = false: no warning, but does not allow assignment
namespace racing {
static const always_false on ;
}
2018-11-17 18:30:50 +00:00
inline bool subscreen_split ( reaction_t for_each_subscreen ) { return false ; }
# endif
2018-12-23 02:14:48 +00:00
bool in_gravity_zone ( cell * c ) ;
bool normal_gravity_at ( cell * c ) ;
2018-11-17 18:30:50 +00:00
2018-12-25 11:51:25 +00:00
void build_pool ( cell * c , bool with_boat ) ;
void createArrowTrapAt ( cell * c , eLand land ) ;
2019-01-02 21:01:00 +00:00
bool no_barriers_in_radius ( cell * c , int rad ) ;
2019-04-13 11:29:30 +00:00
bool in_full_game ( ) ;
2019-03-08 21:42:14 +00:00
extern ld extra_generation_distance ;
2019-03-09 15:20:06 +00:00
namespace subscreens {
void prepare ( ) ;
bool split ( reaction_t for_each_subscreen ) ;
}
2019-03-11 17:46:34 +00:00
const int TEXTURE_STEP_3D = 8 ;
2019-04-11 22:17:50 +00:00
void set_euland3 ( cell * c , int co0 , int co1 , int alt , int hash ) ;
2019-04-15 21:29:07 +00:00
extern bool first_cell_to_draw ;
2019-04-23 13:03:17 +00:00
extern int current_rbuffer ;
extern bool new_projection_needed ;
inline void reset_projection ( ) { new_projection_needed = true ; }
2018-06-17 03:32:09 +00:00
}
2018-08-17 14:53:57 +00:00