2019-08-10 11:43:24 +00:00
|
|
|
// Hyperbolic Rogue -- Heptagon
|
2018-02-08 23:40:26 +00:00
|
|
|
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
|
2015-08-08 13:57:52 +00:00
|
|
|
|
2019-08-10 11:43:24 +00:00
|
|
|
/** \file heptagon.cpp
|
|
|
|
* \brief implementation of Heptagons
|
|
|
|
*
|
|
|
|
* Start with locations.cpp
|
|
|
|
*/
|
2015-08-08 13:57:52 +00:00
|
|
|
|
2019-09-05 07:15:40 +00:00
|
|
|
#include "hyper.h"
|
2018-06-10 23:58:31 +00:00
|
|
|
namespace hr {
|
|
|
|
|
2017-10-29 09:52:02 +00:00
|
|
|
#define MIRR(x) x.mirrored
|
|
|
|
|
2017-12-01 23:31:44 +00:00
|
|
|
int heptacount = 0;
|
|
|
|
|
2015-08-08 13:57:52 +00:00
|
|
|
struct cell;
|
|
|
|
cell *newCell(int type, heptagon *master);
|
|
|
|
|
2019-08-10 11:43:24 +00:00
|
|
|
/** the automaton is used to generate each heptagon in an unique way.
|
|
|
|
* See http://roguetemple.com/z/dev.php for more help.
|
|
|
|
* From the origin we can go further in any direction, and from other heptagons
|
|
|
|
* we can go in directions 3 and 4 (0 is back to origin, so 3 and 4 go forward),
|
|
|
|
* and sometimes in direction 5
|
|
|
|
*/
|
2015-08-08 13:57:52 +00:00
|
|
|
|
2019-09-06 06:17:02 +00:00
|
|
|
EX hstate transition(hstate s, int dir) {
|
2017-03-23 10:53:57 +00:00
|
|
|
if(sphere) {
|
|
|
|
if(S7 == 4) {
|
|
|
|
if(s == hsOrigin) return dir == 0 ? hsB0 : hsB1;
|
|
|
|
}
|
2019-01-11 01:22:19 +00:00
|
|
|
if(S7 == 3 && S3 == 3) {
|
2017-03-23 10:53:57 +00:00
|
|
|
if(s == hsOrigin) return hsB1;
|
|
|
|
}
|
2019-01-11 01:22:19 +00:00
|
|
|
if(S7 == 3 && S3 == 4) {
|
|
|
|
if(s == hsOrigin) return dir == 0 ? hsA0 : hsA1;
|
|
|
|
if(s == hsA0 && dir == 1) return hsB0;
|
|
|
|
if(s == hsA1 && dir == 1) return hsB1;
|
|
|
|
if(s == hsB0 && dir == 2) return hsC;
|
|
|
|
return hsError;
|
|
|
|
}
|
2017-03-23 10:53:57 +00:00
|
|
|
if(s == hsOrigin) return dir == 0 ? hsA0 : hsA1;
|
|
|
|
if(s == hsA0 && dir == 2) return hsB0;
|
|
|
|
if(s == hsA1 && dir == 2) return hsB1;
|
|
|
|
if(s == hsB0 && dir == S7-2) return hsC;
|
|
|
|
return hsError;
|
|
|
|
}
|
2017-10-28 23:57:34 +00:00
|
|
|
else if(S6 == 8) {
|
2017-10-28 08:04:28 +00:00
|
|
|
if(s == hsOrigin) return hsA;
|
|
|
|
if(s == hsA && (dir >= 2 && dir < S7-1)) return hsA;
|
|
|
|
if(s == hsA && (dir == S7-1)) return hsB;
|
|
|
|
if(s == hsB && (dir >= 2 && dir < S7-2)) return hsA;
|
|
|
|
if(s == hsB && (dir == S7-2)) return hsB;
|
|
|
|
}
|
2017-03-23 10:53:57 +00:00
|
|
|
else {
|
|
|
|
if(s == hsOrigin) return hsA;
|
2017-10-27 18:07:58 +00:00
|
|
|
if(s == hsA && dir >= 3 && dir <= S7-3) return hsA;
|
|
|
|
if(s == hsA && dir == S7-2) return hsB;
|
2017-10-28 23:57:34 +00:00
|
|
|
if(s == hsB && dir >= 3 && dir <= S7-4) return hsA;
|
2017-10-27 18:07:58 +00:00
|
|
|
if(s == hsB && dir == S7-3) return hsB;
|
2017-03-23 10:53:57 +00:00
|
|
|
}
|
2015-08-08 13:57:52 +00:00
|
|
|
return hsError;
|
|
|
|
}
|
|
|
|
|
2017-10-28 23:57:34 +00:00
|
|
|
#define COMPUTE -1000000
|
|
|
|
|
2015-08-08 13:57:52 +00:00
|
|
|
// create a new heptagon
|
2019-09-05 10:00:55 +00:00
|
|
|
EX heptagon *buildHeptagon1(heptagon *h, heptagon *parent, int d, hstate s, int pard IS(0)) {
|
2015-08-08 13:57:52 +00:00
|
|
|
h->alt = NULL;
|
|
|
|
h->s = s;
|
2018-08-17 22:46:45 +00:00
|
|
|
h->c.connect(pard, parent, d, false);
|
2018-08-17 19:43:29 +00:00
|
|
|
h->cdata = NULL;
|
2018-08-18 15:43:54 +00:00
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
|
|
|
heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0, int fixdistance = COMPUTE) {
|
2019-05-05 15:34:46 +00:00
|
|
|
heptagon *h = buildHeptagon1(tailored_alloc<heptagon> (S7), parent, d, s, pard);
|
2018-08-19 21:06:32 +00:00
|
|
|
if(binarytiling || archimedean) return h;
|
2015-08-08 13:57:52 +00:00
|
|
|
if(parent->c7) {
|
2019-02-17 17:28:20 +00:00
|
|
|
#if CAP_IRR
|
2018-08-28 15:17:34 +00:00
|
|
|
if(IRREGULAR)
|
2018-07-16 18:05:23 +00:00
|
|
|
irr::link_next(parent, d);
|
|
|
|
else
|
2019-02-17 17:28:20 +00:00
|
|
|
#endif
|
2018-07-16 18:05:23 +00:00
|
|
|
h->c7 = newCell(S7, h);
|
2018-08-17 19:43:29 +00:00
|
|
|
h->rval0 = h->rval1 = 0;
|
2017-10-29 09:52:02 +00:00
|
|
|
h->emeraldval = emerald_heptagon(parent->emeraldval, d);
|
|
|
|
h->zebraval = zebra_heptagon(parent->zebraval, d);
|
2019-02-17 17:28:20 +00:00
|
|
|
#if CAP_FIELD
|
2018-11-30 13:39:23 +00:00
|
|
|
if(&currfp != &fieldpattern::fp_invalid)
|
|
|
|
h->fieldval = currfp.connections[fieldpattern::btspin(parent->fieldval, d)];
|
2019-02-17 17:28:20 +00:00
|
|
|
#endif
|
2017-12-05 15:19:22 +00:00
|
|
|
if(a38)
|
|
|
|
h->fiftyval = fifty_38(parent->fiftyval, d);
|
2017-12-03 15:13:17 +00:00
|
|
|
else if(parent->s == hsOrigin)
|
2017-10-29 09:52:02 +00:00
|
|
|
h->fiftyval = firstfiftyval(d);
|
|
|
|
else
|
2018-08-17 22:46:45 +00:00
|
|
|
h->fiftyval = nextfiftyval(parent->fiftyval, parent->move(0)->fiftyval, d);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
h->c7 = NULL;
|
2016-01-02 10:09:13 +00:00
|
|
|
h->emeraldval = 0;
|
|
|
|
h->fiftyval = 0;
|
2018-01-25 18:49:19 +00:00
|
|
|
h->cdata = NULL;
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
2016-01-02 10:09:13 +00:00
|
|
|
//generateEmeraldval(parent);
|
|
|
|
//generateEmeraldval(h);
|
2015-08-08 13:57:52 +00:00
|
|
|
if(pard == 0) {
|
2017-07-04 13:38:33 +00:00
|
|
|
h->dm4 = parent->dm4+1;
|
2017-10-28 23:57:34 +00:00
|
|
|
if(fixdistance != COMPUTE) h->distance = fixdistance;
|
2018-08-28 15:17:34 +00:00
|
|
|
else if(S3 == 4 && BITRUNCATED) {
|
2017-10-28 23:57:34 +00:00
|
|
|
h->distance = parent->distance + 2;
|
2018-08-17 22:46:45 +00:00
|
|
|
if(h->c.spin(0) == 2 || (h->c.spin(0) == 3 && S7 <= 5))
|
|
|
|
h->distance = min<short>(h->distance, createStep(h->move(0), 0)->distance + 3);
|
|
|
|
if(h->c.spin(0) == 2 && h->move(0)) {
|
|
|
|
int d = h->c.spin(0);
|
2017-10-28 23:57:34 +00:00
|
|
|
int d1 = (d+S7-1)%S7;
|
2018-08-17 22:46:45 +00:00
|
|
|
heptagon* h1 = createStep(h->move(0), d1);
|
|
|
|
if(h1->distance <= h->move(0)->distance)
|
|
|
|
h->distance = h->move(0)->distance+1;
|
2017-10-28 23:57:34 +00:00
|
|
|
}
|
2018-08-17 22:46:45 +00:00
|
|
|
if((h->s == hsB && h->move(0)->s == hsB) || h->move(0)->s == hsA) {
|
|
|
|
int d = h->c.spin(0);
|
|
|
|
heptagon* h1 = createStep(h->move(0), (d+1)%S7);
|
|
|
|
if(h1->distance <= h->move(0)->distance)
|
|
|
|
h->distance = h->move(0)->distance+1;
|
2017-10-28 23:57:34 +00:00
|
|
|
}
|
2018-08-17 22:46:45 +00:00
|
|
|
if(h->c.spin(0) == S7-1 && h->move(0)->distance != 0)
|
2017-10-28 23:57:34 +00:00
|
|
|
h->distance = min(
|
2018-08-17 22:46:45 +00:00
|
|
|
h->move(0)->move(0)->distance + 2,
|
2017-10-28 23:57:34 +00:00
|
|
|
createStep(h, S7-1)->distance + 1
|
|
|
|
);
|
|
|
|
}
|
2018-04-10 15:06:04 +00:00
|
|
|
else if(parent->s == hsOrigin) h->distance = parent->distance + gp::dist_2();
|
2019-02-17 17:28:20 +00:00
|
|
|
#if CAP_GP
|
2018-08-28 15:17:34 +00:00
|
|
|
else if(S3 == 4 && GOLDBERG && h->c.spin(0) == S7-2 && h->move(0)->c.spin(0) >= S7-2 && h->move(0)->move(0)->s != hsOrigin) {
|
2018-07-10 16:03:41 +00:00
|
|
|
heptspin hs(h, 0);
|
|
|
|
hs += wstep;
|
2018-08-17 22:46:45 +00:00
|
|
|
int d1 = hs.at->distance;
|
2018-07-10 16:03:41 +00:00
|
|
|
hs += 1; hs += wstep;
|
2018-08-17 22:46:45 +00:00
|
|
|
int dm = hs.at->distance;
|
2018-07-10 16:03:41 +00:00
|
|
|
hs += -1; hs += wstep;
|
2018-08-17 22:46:45 +00:00
|
|
|
int d0 = hs.at->distance;
|
2018-07-10 16:03:41 +00:00
|
|
|
h->distance = gp::solve_triangle(dm, d0, d1, gp::operator* (gp::param, gp::loc(-1,1)));
|
|
|
|
}
|
2018-08-28 15:17:34 +00:00
|
|
|
else if(S3 == 4 && GOLDBERG && h->c.spin(0) == S7-1 && among(h->move(0)->c.spin(0), S7-2, S7-3) && h->move(0)->move(0)->s != hsOrigin) {
|
2018-07-10 16:03:41 +00:00
|
|
|
heptspin hs(h, 0);
|
|
|
|
hs += wstep;
|
2018-08-17 22:46:45 +00:00
|
|
|
int d0 = hs.at->distance;
|
2018-07-10 16:03:41 +00:00
|
|
|
hs += 1; hs += wstep;
|
2018-08-17 22:46:45 +00:00
|
|
|
int dm = hs.at->distance;
|
2018-07-10 16:03:41 +00:00
|
|
|
hs += 1; hs += wstep;
|
2018-08-17 22:46:45 +00:00
|
|
|
int d1 = hs.at->distance;
|
2018-07-10 16:03:41 +00:00
|
|
|
h->distance = gp::solve_triangle(dm, d0, d1, gp::operator* (gp::param, gp::loc(1,1)));
|
|
|
|
}
|
2018-08-28 15:17:34 +00:00
|
|
|
else if(S3 == 4 && GOLDBERG && h->c.spin(0) >= 2 && h->c.spin(0) <= S7-2) {
|
2018-07-10 16:03:41 +00:00
|
|
|
h->distance = parent->distance + gp::dist_2();
|
|
|
|
}
|
2019-02-17 17:28:20 +00:00
|
|
|
#endif
|
2018-08-17 22:46:45 +00:00
|
|
|
else if(h->c.spin(0) == S7-2) {
|
2019-02-17 17:28:20 +00:00
|
|
|
#if CAP_GP
|
|
|
|
if(GOLDBERG) {
|
2018-04-10 15:06:04 +00:00
|
|
|
int d0 = parent->distance;
|
|
|
|
int d1 = createStep(parent, S7-1)->distance;
|
|
|
|
int dm = createStep(parent, 0)->distance;
|
|
|
|
h->distance = gp::solve_triangle(dm, d0, d1, gp::operator* (gp::param, gp::loc(1,1)));
|
2019-02-17 17:28:20 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
h->distance = parent->distance + gp::dist_1();
|
2018-04-10 15:06:04 +00:00
|
|
|
}
|
2018-08-17 22:46:45 +00:00
|
|
|
else if(h->c.spin(0) == S7-3 && h->move(0)->s == hsB) {
|
2019-02-17 17:28:20 +00:00
|
|
|
#if CAP_GP
|
|
|
|
if(GOLDBERG) {
|
2018-04-10 15:06:04 +00:00
|
|
|
int d0 = parent->distance;
|
|
|
|
int d1 = createStep(parent, S7-2)->distance;
|
|
|
|
int dm = createStep(parent, S7-1)->distance;
|
|
|
|
h->distance = gp::solve_triangle(dm, d0, d1, gp::operator* (gp::param, gp::loc(1,1)));
|
2019-02-17 17:28:20 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
h->distance = createStep(h->move(0), (h->c.spin(0)+2)%S7)->distance + gp::dist_3();
|
2018-04-10 15:06:04 +00:00
|
|
|
}
|
2018-08-28 15:17:34 +00:00
|
|
|
else if(h->c.spin(0) == S7-1 && S3 == 4 && GOLDBERG) {
|
2018-07-10 16:03:41 +00:00
|
|
|
h->distance = parent->distance + gp::dist_1();
|
|
|
|
}
|
2018-04-10 15:06:04 +00:00
|
|
|
else h->distance = parent->distance + gp::dist_2();
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
2017-07-04 13:38:33 +00:00
|
|
|
else {
|
2018-04-10 15:06:04 +00:00
|
|
|
h->distance = parent->distance - gp::dist_2();
|
2017-10-28 23:57:34 +00:00
|
|
|
if(S3 == 4 && S7 == 5) {
|
|
|
|
if(h->s == hsOrigin) {
|
|
|
|
printf("had to cheat!\n");
|
|
|
|
h->distance = parent->distance - 2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
h->distance = parent->distance - 1;
|
|
|
|
buildHeptagon(h, 2, hsA, 0, h->distance + 2);
|
|
|
|
buildHeptagon(h, 4, hsB, 0, h->distance);
|
|
|
|
}
|
|
|
|
}
|
2017-07-04 13:38:33 +00:00
|
|
|
h->dm4 = parent->dm4-1;
|
|
|
|
}
|
2015-08-08 13:57:52 +00:00
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2017-10-28 23:57:34 +00:00
|
|
|
int recsteps;
|
|
|
|
|
2015-08-08 13:57:52 +00:00
|
|
|
void addSpin(heptagon *h, int d, heptagon *from, int rot, int spin) {
|
2018-08-17 22:46:45 +00:00
|
|
|
rot = h->c.fix(rot);
|
|
|
|
auto h1 = createStep(from, rot);
|
|
|
|
int fr = h1->c.fix(from->c.spin(rot) + spin);
|
|
|
|
h->c.connect(d, from->move(rot), fr, false);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
|
|
|
|
2016-08-26 09:58:03 +00:00
|
|
|
extern int hrand(int);
|
|
|
|
|
2019-08-10 11:43:24 +00:00
|
|
|
EX hookset<void(heptagon*, int)> *hooks_createStep;
|
2018-11-30 13:37:59 +00:00
|
|
|
|
2019-08-10 11:43:24 +00:00
|
|
|
// create h->move(d) if not created yet
|
2015-08-08 13:57:52 +00:00
|
|
|
heptagon *createStep(heptagon *h, int d) {
|
2018-08-17 22:46:45 +00:00
|
|
|
d = h->c.fix(d);
|
2019-03-08 21:38:44 +00:00
|
|
|
if(h->move(d)) return h->move(d);
|
|
|
|
callhooks(hooks_createStep, h, d);
|
|
|
|
return currentmap->create_step(h, d);
|
|
|
|
}
|
|
|
|
|
|
|
|
heptagon *hrmap_standard::create_step(heptagon *h, int d) {
|
2019-08-22 10:14:39 +00:00
|
|
|
if(!h->move(0) && h->s != hsOrigin && !binarytiling && !cryst) {
|
2017-10-28 23:57:34 +00:00
|
|
|
// cheating:
|
2017-10-30 21:47:40 +00:00
|
|
|
int pard=0;
|
2017-10-28 23:57:34 +00:00
|
|
|
if(S3 == 3)
|
|
|
|
pard = 3 + hrand(2);
|
|
|
|
else if(S3 == 4 && S7 == 5)
|
|
|
|
pard = 3; // to do: randomize
|
|
|
|
else if(S3 == 4)
|
|
|
|
pard = 3;
|
2017-10-30 21:47:40 +00:00
|
|
|
buildHeptagon(h, 0, h->distance < -10000 ? hsOrigin : hsA, pard);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
2018-08-17 22:46:45 +00:00
|
|
|
if(h->move(d)) return h->move(d);
|
2015-08-08 13:57:52 +00:00
|
|
|
if(h->s == hsOrigin) {
|
|
|
|
buildHeptagon(h, d, hsA);
|
|
|
|
}
|
2017-10-28 23:57:34 +00:00
|
|
|
else if(S3 == 4) {
|
2017-10-28 08:04:28 +00:00
|
|
|
if(d == 1) {
|
2018-08-17 22:46:45 +00:00
|
|
|
heptspin hs(h, 0, false);
|
2018-03-24 11:59:01 +00:00
|
|
|
hs = hs + wstep - 1 + wstep - 1 + wstep - 1;
|
2018-08-17 22:46:45 +00:00
|
|
|
h->c.connect(d, hs);
|
2017-10-28 08:04:28 +00:00
|
|
|
}
|
|
|
|
else if(h->s == hsB && d == S7-1) {
|
2018-08-17 22:46:45 +00:00
|
|
|
heptspin hs(h, 0, false);
|
2018-03-24 11:59:01 +00:00
|
|
|
hs = hs + wstep + 1 + wstep + 1 + wstep + 1;
|
2018-08-17 22:46:45 +00:00
|
|
|
h->c.connect(d, hs);
|
2017-10-28 08:04:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
buildHeptagon(h, d, transition(h->s, d));
|
|
|
|
}
|
2015-08-08 13:57:52 +00:00
|
|
|
else if(d == 1) {
|
2018-08-17 22:46:45 +00:00
|
|
|
addSpin(h, d, h->move(0), h->c.spin(0)-1, -1);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
2017-10-27 18:07:58 +00:00
|
|
|
else if(d == S7-1) {
|
2018-08-17 22:46:45 +00:00
|
|
|
addSpin(h, d, h->move(0), h->c.spin(0)+1, +1);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
|
|
|
else if(d == 2) {
|
2018-08-17 22:46:45 +00:00
|
|
|
createStep(h->move(0), h->c.spin(0)-1);
|
|
|
|
addSpin(h, d, h->move(0)->modmove(h->c.spin(0)-1), S7-2 + h->move(0)->c.modspin(h->c.spin(0)-1), -1);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
2017-10-27 18:07:58 +00:00
|
|
|
else if(d == S7-2 && h->s == hsB) {
|
2018-08-17 22:46:45 +00:00
|
|
|
createStep(h->move(0), h->c.spin(0)+1);
|
|
|
|
addSpin(h, d, h->move(0)->modmove(h->c.spin(0)+1), 2 + h->move(0)->c.modspin(h->c.spin(0)+1), +1);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
|
|
|
else
|
2017-10-27 18:07:58 +00:00
|
|
|
buildHeptagon(h, d, (d == S7-2 || (h->s == hsB && d == S7-3)) ? hsB : hsA);
|
2018-08-17 22:46:45 +00:00
|
|
|
return h->move(d);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// display the coordinates of the heptagon
|
|
|
|
void backtrace(heptagon *pos) {
|
2017-04-04 09:13:15 +00:00
|
|
|
if(pos->s == hsOrigin) return;
|
2018-08-17 22:46:45 +00:00
|
|
|
backtrace(pos->move(0));
|
|
|
|
printf(" %d", pos->c.spin(0));
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void hsshow(const heptspin& t) {
|
2018-08-17 22:46:45 +00:00
|
|
|
printf("ORIGIN"); backtrace(t.at); printf(" (spin %d)\n", t.spin);
|
2015-08-08 13:57:52 +00:00
|
|
|
}
|
|
|
|
|
2018-06-10 23:58:31 +00:00
|
|
|
}
|