forked from zenorogue/hyperrogue
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hyper.h
1538 lines (1217 loc) · 40.9 KB
/
hyper.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// scale the Euclidean
#define EUCSCALE 2.3
#define NUMWITCH 7
// achievements
#define LB_YENDOR_CHALLENGE 40
#define LB_PURE_TACTICS 41
#define NUMLEADER 72
#define LB_PURE_TACTICS_SHMUP 49
#define LB_PURE_TACTICS_COOP 50
extern int currentscore[NUMLEADER];
extern int syncstate;
// initialize the achievement system.
void achievement_init();
// close the achievement system.
void achievement_close();
// 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
vector<string> achievementsReceived;
// game forward declarations
typedef int flagtype;
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);
bool cellEdgeUnstable(cell *c, flagtype flags = 0);
int coastvalEdge(cell *c);
typedef int cellfunction(cell*);
int towerval(cell *c, cellfunction* cf = &coastvalEdge);
#define HRANDMAX 0x7FFFFFFF
int hrandpos(); // 0 to HRANDMAX
void restartGame(char switchWhat = 0, bool push = false);
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);
bool buildBarrier6(struct cellwalker cw, int type);
bool makeEmpty(cell *c);
bool isCrossroads(eLand l);
enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce, roMultiCheck, roMultiGo };
void moveItem (cell *from, cell *to, bool activateYendor);
void uncoverMines(cell *c, int lev, int dist);
bool survivesMine(eMonster m);
void killMonster(cell *c, eMonster who_killed, flagtype flags = 0);
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 generateAlts(heptagon *h);
void setdist(cell *c, int d, cell *from);
void checkOnYendorPath();
void killThePlayerAt(eMonster m, cell *c, flagtype flags);
bool notDippingFor(eItem i);
bool collectItem(cell *c2, bool telekinesis = false);
void castLightningBolt(struct cellwalker lig);
bool movepcto(int d, int subdir = 1, bool checkonly = false);
void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill = 0);
bool earthMove(cell *from, int dir);
void messageKill(eMonster killer, eMonster victim);
void moveMonster(cell *ct, cell *cf);
int palaceHP();
void placeLocalOrbs(cell *c);
int elementalKills();
bool elementalUnlocked();
bool trollUnlocked();
bool isMultitile(eMonster m);
void checkFreedom(cell *cf);
int rosedist(cell *c);
bool canPushStatueOn(cell *c);
namespace hive { void createBugArmy(cell *c); }
namespace whirlpool { void generate(cell *wto); }
namespace whirlwind { void generate(cell *wto); }
namespace mirror {
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);
}
int neighborId(cell *c1, cell *c2);
struct movedir {
int d; // 0 to 6, or one of the following -- warning: not used consistently
#define MD_WAIT (-1)
#define MD_DROP (-2)
#define MD_UNDECIDED (-3)
#define MD_USE_ORB (-4)
int subdir; // for normal movement (0-6): turn left or right
cell *tgt; // for MD_USE_ORB: target cell
};
inline bool movepcto(const movedir& md) { return movepcto(md.d, md.subdir); }
void activateActiv(cell *c, bool msg);
// shmup
struct charstyle {
int charid;
unsigned skincolor, haircolor, dresscolor, swordcolor, dresscolor2, uicolor;
};
string csname(charstyle& cs);
void initcs(charstyle& cs);
void savecs(FILE *f, charstyle& cs, int vernum);
void loadcs(FILE *f, charstyle& cs, int vernum);
#define MAXPLAYER 7
#define MAXJOY 8
#define MAXBUTTON 64
#define MAXAXE 16
#define MAXHAT 4
namespace multi {
extern bool shmupcfg;
extern bool alwaysuse;
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 {
int players;
int subconfig;
int setwhat;
char keyaction[512];
char joyaction[MAXJOY][MAXBUTTON];
char axeaction[MAXJOY][MAXAXE];
char hataction[MAXJOY][MAXHAT][4];
int deadzoneval[MAXJOY][MAXAXE];
};
void saveConfig(FILE *f);
void loadConfig(FILE *f);
void initConfig();
charstyle scs[MAXPLAYER];
bool playerActive(int p);
int activePlayers();
cell *multiPlayerTarget(int i);
void checklastmove();
void leaveGame(int i);
void showShmupConfig();
}
namespace shmup {
using namespace multi;
void recall();
extern bool on;
extern bool safety;
extern int curtime;
void clearMonsters();
void clearMemory();
void init();
void teleported();
extern struct monster* mousetarget;
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);
void destroyBoats(cell *c);
bool boatAt(cell *c);
void virtualRebase(cell*& base, transmatrix& at, bool tohex);
void virtualRebase(shmup::monster *m, bool tohex);
void fixStorage();
void addShmupHelp(string& out);
}
// graph
extern int msgscroll;
void showMissionScreen();
void restartGraph();
void resetmusic();
void drawFlash(cell* c);
void drawBigFlash(cell* c);
void drawParticle(cell *c, int col, int maxspeed = 100);
void drawParticles(cell *c, int col, int qty, int maxspeed = 100);
void drawFireParticles(cell *c, int qty, int maxspeed = 100);
int firecolor(int phase);
void drawLightning();
void drawSafety();
void restartGraph();
void movepckeydir(int);
void centerpc(ld aspd);
void displayButton(int x, int y, const string& name, int key, int align, int rad = 0);
void displayColorButton(int x, int y, const string& name, int key, int align, int rad, int color, int color2 = 0);
inline string ONOFF(bool b) { return XLAT(b ? "ON" : "OFF"); }
int darkened(int c);
extern int getcstat;
bool displaychr(int x, int y, int shift, int size, char chr, int col);
bool displayfr(int x, int y, int b, int size, const string &s, int color, int align);
bool displayfrSP(int x, int y, int sh, int b, int size, const string &s, int color, int align, int p);
bool outofmap(hyperpoint h);
void applymodel(hyperpoint H, hyperpoint& Hscr);
void drawCircle(int x, int y, int size, int color);
void fixcolor(int& col);
int displaydir(cell *c, int d);
hyperpoint gethyper(ld x, ld y);
void resetview(); extern heptspin viewctr; extern cell *centerover;
void drawthemap();
void drawfullmap();
bool displaystr(int x, int y, int shift, int size, const char *str, int color, int align);
bool displaystr(int x, int y, int shift, int size, const string& str, int color, int align);
extern int darken, inmirrorcount;
void calcparam();
#if CAP_SDL
int& qpixel(SDL_Surface *surf, int x, int y);
void setvideomode();
void saveHighQualityShot(const char *fname = NULL, const char *caption = NULL, int fade = 255);
#endif
#if CAP_CONFIG
void saveConfig();
#endif
extern hyperpoint mouseh;
extern hyperpoint ccenter;
extern ld crad;
extern bool mousepressed, anyshiftclick;
extern string help;
extern function<void()> help_delegate;
#define HELPFUN(x) (help_delegate = x, "HELPFUN")
struct videopar {
ld scale, eye, alpha, sspeed, mspeed, yshift, camera_angle;
ld ballangle, ballproj;
int mobilecompasssize;
int aurastr, aurasmoothen;
bool full;
bool goteyes; // for rendering
bool goteyes2; // for choosing colors
int graphglyph; // graphical glyphs
bool darkhepta;
int shifttarget;
int xres, yres, framelimit;
int xscr, yscr;
// paramaters calculated from the above
int xcenter, ycenter;
int radius;
ld alphax, beta;
bool grid;
int particles;
int fsize;
int flashtime;
int wallmode, monmode, axes;
bool revcontrol;
// for OpenGL
float scrdist;
bool usingGL;
int antialias;
#define AA_NOGL 1
#define AA_VERSION 2
#define AA_LINES 4
#define AA_POLY 8
#define AA_LINEWIDTH 16
#define AA_FONT 32
#define AA_MULTI 64
#define AA_MULTI16 128 // not configurable
ld linewidth;
int joyvalue, joyvalue2, joypanthreshold;
ld joypanspeed;
charstyle cs;
bool samegender; // same gender for the Princess?
int language;
int killreduction, itemreduction, portreduction;
multi::config scfg;
int steamscore;
bool drawmousecircle; // draw the circle around the mouse
bool skipstart; // skip the start menu
int quickmouse; // quick mouse on the map
};
extern videopar vid;
extern vector< function<void()> > screens;
template<class T> void pushScreen(T& x) { screens.push_back(x); }
inline void popScreen() { screens.pop_back(); }
inline void popScreenAll() { while(size(screens)>1) popScreen(); }
extern transmatrix View; // current rotation, relative to viewctr
extern transmatrix cwtV; // player-relative view
extern cell *mouseover, *mouseover2;
extern string mouseovers;
extern struct SDL_Surface *s;
namespace mapeditor {
extern bool drawplayer;
extern char whichPattern, whichShape;
extern char whichCanvas;
extern int displaycodes;
int generateCanvas(cell *c);
void applyModelcell(cell *c);
int realpattern(cell *c);
int patterndir(cell *c, char w = whichPattern);
int subpattern(cell *c);
extern cell *drawcell;
void initdraw(cell *c);
void showMapEditor();
void showDrawEditor();
}
namespace rug {
extern bool rugged;
extern bool renderonce;
extern bool rendernogl;
extern int texturesize;
extern ld scale;
#if CAP_RUG
void show();
void init();
void close();
void actDraw();
void select();
void buildVertexInfo(cell *c, transmatrix V);
#endif
}
#define HASLINEVIEW
namespace conformal {
extern bool on;
extern vector<pair<cell*, eMonster> > killhistory;
extern vector<pair<cell*, eItem> > findhistory;
extern vector<cell*> movehistory;
extern bool includeHistory;
extern int rotation;
extern bool autoband;
extern bool autobandhistory;
extern bool dospiral;
extern ld lvspeed;
extern int bandsegment;
extern int bandhalf;
void create();
void clear();
void show();
void apply();
void movetophase();
void renderAutoband();
extern vector<shmup::monster*> v;
extern double phase;
void applyIB();
}
namespace polygonal {
static const int MSI = 120;
extern int SI;
extern ld STAR;
extern int deg;
extern ld coefr[MSI], coefi[MSI];
extern int maxcoef, coefid;
void solve();
pair<ld, ld> compute(ld x, ld y);
}
void selectEyeGL(int ed);
void selectEyeMask(int ed);
extern int ticks;
void setGLProjection();
// passable flags
#define P_MONSTER (1<<0) // can move through monsters
#define P_MIRROR (1<<1) // can move through mirrors
#define P_REVDIR (1<<2) // reverse direction movement
#define P_WIND (1<<3) // can move against the wind
#define P_GRAVITY (1<<4) // can move against the gravity
#define P_ISPLAYER (1<<5) // player-only moves (like the Round Table jump)
#define P_ONPLAYER (1<<6) // always can step on the player
#define P_FLYING (1<<7) // is flying
#define P_BULLET (1<<8) // bullet can fly through more things
#define P_MIRRORWALL (1<<9) // mirror images go through mirror walls
#define P_JUMP1 (1<<10) // first part of a jump
#define P_JUMP2 (1<<11) // second part of a jump
#define P_TELE (1<<12) // teleport onto
#define P_BLOW (1<<13) // Orb of Air -- blow, or push
#define P_AETHER (1<<14) // aethereal
#define P_FISH (1<<15) // swimming
#define P_WINTER (1<<16) // fire resistant
#define P_USEBOAT (1<<17) // can use boat
#define P_NOAETHER (1<<18) // disable AETHER
#define P_FRIENDSWAP (1<<19) // can move on friends (to swap with tem)
#define P_ISFRIEND (1<<20) // is a friend (can use Empathy + Winter/Aether/Fish combo)
#define P_LEADER (1<<21) // can push statues and use boats
#define P_MARKWATER (1<<22) // mark Orb of Water as used
#define P_EARTHELEM (1<<23) // Earth Elemental
#define P_WATERELEM (1<<24) // Water Elemental
#define P_IGNORE37 (1<<25) // ignore the triheptagonal board
#define P_CHAIN (1<<26) // for chaining moves with boats
#define P_DEADLY (1<<27) // suicide moves allowed
#define P_ROSE (1<<28) // rose smell
#define P_CLIMBUP (1<<29) // allow climbing up
#define P_CLIMBDOWN (1<<30) // allow climbing down
#define P_REPTILE (1<<31) // is reptile
bool passable(cell *w, cell *from, flagtype flags);
bool isElemental(eLand l);
int coastval(cell *c, eLand base);
int getHauntedDepth(cell *c);
eLand randomElementalLand();
extern eLand euland[65536];
bool notDippingForExtra(eItem i, eItem x);
void placePrizeOrb(cell *c);
int hivehard();
eMonster randomHyperbug();
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);
cell *chosenDown(cell *c, int which, int bonus, cellfunction* cf = &coastvalEdge);
eLand pickLandRPM(eLand old);
bool bearsCamelot(eLand l);
extern bool safety;
#define SAGEMELT .1
#define TEMPLE_EACH 6
#define PT(x, y) ((tactic::on || quotient == 2) ? (y) : inv::on ? min(2*(y),x) : (x))
#define ROCKSNAKELENGTH 50
#define WORMLENGTH 15
#define PUREHARDCORE_LEVEL 10
#define PRIZEMUL 7
#define INF 9999
#define INFD 20
#define PINFD 125
#define BARLEV ((ISANDROID||ISIOS||ISFAKEMOBILE||purehepta)?9:10)
#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
#define MODECODES 255
extern cellwalker cwt; // player character position
extern int sval;
extern int items[ittypes], kills[motypes], explore[10], exploreland[10][landtypes], landcount[landtypes];
typedef int modecode_t;
extern map<modecode_t, array<int, ittypes> > hiitems;
extern eLand firstland, specialland;
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?
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);
int tkills();
bool hellUnlocked();
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
bool markEmpathy2(eItem it); // as above, but next turn
bool isMimic(eMonster m);
bool isMimic(cell *c);
void fallMonster(cell *c, flagtype flags = 0); // kill monster due to terrain
bool attackMonster(cell *c, flagtype flags, eMonster killer);
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
// 0 = basic treasure, 1 = other item, 2 = power orb, 3 = not an item
#define IC_TREASURE 0
#define IC_OTHER 1
#define IC_ORB 2
#define IC_NAI 3
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);
void killOrStunMonster(cell *c2, eMonster who_killed);
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);
bool isPlayerInBoatOn(cell *c, int i);
void destroyBoats(cell *c, cell *cf, bool strandedToo);
extern bool showoff;
extern int lastexplore;
extern int truelotus;
extern eLand lastland;
extern time_t timerstart;
extern bool timerstopped;
bool againstRose(cell *cfrom, cell *cto);
bool withRose(cell *cfrom, cell *cto);
// loops
#define fakecellloop(ct) for(cell *ct = (cell*)1; ct; ct=NULL)
#define forCellIdAll(ct, i, cf) fakecellloop(ct) for(int i=0; i<(cf)->type && (ct=(cf)->mov[i],true); i++)
#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
#define AF_TOUGH (1<<0) // tough attacks: Hyperbugs
#define AF_MAGIC (1<<1) // magical attacks: Flash
#define AF_STAB (1<<2) // stabbing attacks (usually ignored except Hedgehogs)
#define AF_LANCE (1<<3) // lance attacks (used by Lancers)
#define AF_ONLY_ENEMY (1<<4) // only say YES if it is an enemy
#define AF_ONLY_FRIEND (1<<5) // only say YES if it is a friend
#define AF_ONLY_FBUG (1<<6) // only say YES if it is a bug_or friend
#define AF_BACK (1<<7) // backward attacks (ignored except Viziers and Flailers)
#define AF_APPROACH (1<<8) // approach attacks (ignored except Lancers)
#define AF_IGNORE_UNARMED (1<<9) // ignore the UNARMED flag
#define AF_NOSHIELD (1<<10) // ignore the shielded status
#define AF_GETPLAYER (1<<11) // check for player (replace m2 with moPlayer for player position)
#define AF_GUN (1<<12) // revolver attack
#define AF_FAST (1<<13) // fast attack
#define AF_EAT (1<<17) // eating attacks from Worm-likes
#define MF_NOATTACKS (1<<14) // don't do any attacks
#define MF_PATHDIST (1<<15) // consider pathdist for moveval
#define MF_ONLYEAGLE (1<<16) // do this only for Eagles
#define MF_MOUNT (1<<18) // don't do
#define MF_NOFRIEND (1<<19) // don't do it for friends
#define AF_SWORD (1<<20) // big sword
#define AF_SWORD_INTO (1<<21) // moving into big sword
#define AF_MSG (1<<22) // produce a message
#define AF_ORSTUN (1<<23) // attackMonster: allow stunning
#define AF_NEXTTURN (1<<24) // next turn -- don't count shield at power 1
#define AF_FALL (1<<25) // death by falling
#define MF_STUNNED (1<<26) // edgeunstable: ignore ladders (as stunned monsters do)
#define MF_IVY (1<<27) // edgeunstable: ignore ivy (ivy cannot climb ivy)
#define AF_HORNS (1<<28) // spear attack (always has APPROACH too)
#define AF_BULL (1<<29) // bull attack
bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags);
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);
#if CAP_SDL
#if CAP_PNG
#include "savepng.h"
#define IMAGEEXT ".png"
void IMAGESAVE(SDL_Surface *s, const char *fname);
#else
#define IMAGEEXT ".bmp"
#define IMAGESAVE SDL_SaveBMP
#endif
#endif
void drawscreen();
void buildAirmap();
// currently works for worms only
bool sameMonster(cell *c1, cell *c2);
cell *wormhead(cell *c);
eMonster getMount(int player_id);
eMonster haveMount();
bool isDragon(eMonster m);
// for some reason I need this to compile under OSX
#if ISMAC
extern "C" { void *_Unwind_Resume = 0; }
#endif
extern bool autocheat;
extern bool inHighQual;
void mountmove(cell *c, int spin, bool fp);
void mountmove(cell *c, int spin, bool fp, cell *ppos);
void mountswap(cell *c1, int spin1, bool fp1, cell *c2, int spin2, bool fp2);
template<class T> struct dynamicval {
T& where;
T backup;
dynamicval(T& wh, T val) : where(wh) { backup = wh; wh = val; }
dynamicval(T& wh) : where(wh) { backup = wh; }
~dynamicval() { where = backup; }
};
struct stalemate1 {
eMonster who;
cell *moveto;
cell *killed;
cell *pushto;
cell *comefrom;
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 {
vector<stalemate1> moves;
bool nextturn;
bool isKilled(cell *c);
bool anyKilled();
bool isMoveto(cell *c);
bool isKilledDirectlyAt(cell *c);
bool isPushto(cell *c);
};
extern int turncount;
bool reduceOrbPower(eItem it, int cap);
bool checkOrb(eMonster m1, eItem orb);
movedir vectodir(const hyperpoint& P);
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);
bool attackJustStuns(cell *c2);
bool isTargetOrAdjacent(cell *c);
bool warningprotection();
bool mineMarked(cell *c);
bool minesafe();
bool hasSafeOrb(cell *c);
void placeWater(cell *c, cell *c2);
bool againstCurrent(cell *w, cell *from);
#define DEFAULTCONTROL (multi::players == 1 && !shmup::on && !multi::alwaysuse)
#define DEFAULTNOR(sym) (DEFAULTCONTROL || multi::notremapped(sym))
extern bool timerghost;
#define CAP_MENUSCALING (ISPANDORA || ISMOBILE)
#if CAP_MENUSCALING
#define displayfrZ dialog::displayzoom
#else
#define displayfrZ displayfr
#endif
namespace dialog {
enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diSlider, diBigItem};
struct item {
tDialogItem type;
string body;
string value;
string keycaption;
int key;
int color, colorv, colork, colors, colorc;
int scale;
double param;
int position;
};
extern vector<item> items;
item& lastItem();
extern unsigned int *palette;
void addSelItem(string body, string value, int key);
void addBoolItem(string body, bool value, int key);
void addColorItem(string body, int value, int key);
void openColorDialog(unsigned int& col, unsigned int *pal = palette);
void addHelp(string body);
void addInfo(string body, int color = 0xC0C0C0);
void addItem(string body, int key);
int addBreak(int val);
void addTitle(string body, int color, int scale);
void init();
void init(string title, int color = 0xE8E8E8, int scale = 150, int brk = 60);
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);
void scaleLog();
void scaleSinh();
void handleNavigation(int &sym, int &uni);
bool displayzoom(int x, int y, int b, int size, const string &s, int color, int align);
bool editingDetail();
int handlePage(int& nl, int& nlm, int perpage);
void displayPageButtons(int i, bool pages);
bool handlePageButtons(int uni);
extern bool sidedialog;
}
void checkStunKill(cell *dest);
void clearMessages();
void resetGeometry();
namespace svg {
void circle(int x, int y, int size, int col);
void polygon(int *polyx, int *polyy, int polyi, int col, int outline);
void text(int x, int y, int size, const string& str, bool frame, int col, int align);
extern bool in;
extern string *info;
void render(const char *fname = NULL);
}
extern int sightrange;
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
bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, double footphase);
void drawPlayerEffects(const transmatrix& V, cell *c, bool onPlayer);
// monster movement animations
struct animation {
int ltick;
double footphase;
transmatrix wherenow;
};
// 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];
extern unordered_map<cell*, transmatrix> gmatrix, gmatrix0;
void animateMovement(cell *src, cell *tgt, int layer);
// for animations which might use the same locations,
// such as replacements or multi-tile monsters
void indAnimateMovement(cell *src, cell *tgt, int layer);
void commitAnimations(int layer);
void animateReplacement(cell *a, cell *b, int layer);
void fallingFloorAnimation(cell *c, eWall w = waNone, eMonster m = moNone);
void fallingMonsterAnimation(cell *c, eMonster m, int id = multi::cpid);
// ranks:
enum PPR {
PPR_ZERO, PPR_OUTCIRCLE, PPR_MOVESTAR,
PPR_MINUSINF,
PPR_BELOWBOTTOMm,
PPR_BELOWBOTTOM,
PPR_BELOWBOTTOMp,
PPR_LAKEBOTTOM, PPR_HELLSPIKE,
PPR_INLAKEWALLm, PPR_INLAKEWALL, PPR_INLAKEWALLp,
PPR_SUBLAKELEV, PPR_LAKELEV, PPR_BOATLEV, PPR_BOATLEV2, PPR_BOATLEV3,
PPR_LAKEWALLm, PPR_LAKEWALL, PPR_LAKEWALLp,
PPR_FLOOR_TOWER,
PPR_FLOOR,
PPR_FLOOR_DRAGON,
PPR_FLOORa, PPR_FLOORb, PPR_FLOORc, PPR_FLOORd,
PPR_LIZEYE,
PPR_BFLOOR,
PPR_GFLOORa, PPR_GFLOORb, PPR_GFLOORc,
PPR_WALLSHADOW,
PPR_STRUCT0, PPR_STRUCT1, PPR_STRUCT2, PPR_STRUCT3,
PPR_THORNS, PPR_WALL,
PPR_REDWALLm, PPR_REDWALLs, PPR_REDWALLp, PPR_REDWALL,
PPR_REDWALLm2, PPR_REDWALLs2, PPR_REDWALLp2, PPR_REDWALLt2,
PPR_REDWALLm3, PPR_REDWALLs3, PPR_REDWALLp3, PPR_REDWALLt3,
PPR_HEPTAMARK,
PPR_ITEM, PPR_ITEMa, PPR_ITEMb,
PPR_BIGSTATUE,
PPR_GLASSm, PPR_GLASSs, PPR_GLASSp, PPR_GLASS,
PPR_WALL3m, PPR_WALL3s, PPR_WALL3p, PPR_WALL3, PPR_WALL3A,
PPR_HIDDEN, PPR_GIANTSHADOW,
PPR_TENTACLE0, PPR_TENTACLE1,
PPR_ONTENTACLE, PPR_ONTENTACLE_EYES, PPR_ONTENTACLE_EYES2,
PPR_MONSTER_SHADOW,
PPR_MONSTER_FOOT, PPR_MONSTER_LEG, PPR_MONSTER_GROIN,
PPR_MONSTER_SUBWPN, PPR_MONSTER_WPN,
PPR_MONSTER_BODY, PPR_MONSTER_ARMOR0, PPR_MONSTER_ARMOR1,
PPR_MONSTER_CLOAK, PPR_MONSTER_NECK,
PPR_MONSTER_HEAD, PPR_MONSTER_FACE, PPR_MONSTER_EYE0, PPR_MONSTER_EYE1,
PPR_MONSTER_HAIR, PPR_MONSTER_HAT0, PPR_MONSTER_HAT1,
PPR_MONSTER_HOODCLOAK1, PPR_MONSTER_HOODCLOAK2,
PPR_STUNSTARS,
PPR_CARRIED, PPR_CARRIEDa, PPR_CARRIEDb,
PPR_PARTICLE, PPR_SWORDMARK, PPR_MAGICSWORD, PPR_MISSILE,
PPR_MINEMARK, PPR_ARROW,
PPR_LINE, PPR_TEXT, PPR_CIRCLE,
PPR_MAX
};
void ShadowV(const transmatrix& V, const struct hpcshape& bp, int prio = PPR_MONSTER_SHADOW);
#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
#define OUTLINE_DEFAULT ((bordcolor << 8) + 0xFF)
#define OUTLINE_FORE ((forecolor << 8) + 0xFF)
#define OUTLINE_BACK ((backcolor << 8) + 0xFF)
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;
extern int maxreclevel, reclevel;
string explain3D(ld *param);