1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-16 02:04:48 +00:00
hyperrogue/rogueviz/magmahep.cpp

250 lines
5.3 KiB
C++
Raw Normal View History

2020-06-07 23:31:21 +00:00
#include "../hyper.h"
// usage: -viz -geo 1 -canvas i -zoom .2 -shot-1000 -magmashape N
// where N = 1, 2, 3, 4
namespace hr {
int magmav = 7;
2020-06-07 23:59:34 +00:00
/* vertices of the Magma's heptagon */
vector<hyperpoint> vertices;
hyperpoint hcenter;
2020-06-07 23:31:21 +00:00
2020-06-07 23:59:34 +00:00
/* how are all Magma's heptagons transformed and colored */
vector<pair<transmatrix, color_t>> heps;
2020-06-07 23:31:21 +00:00
int magmashape = 0;
int magmacount = 1000;
int magmalong = 10;
bool magmadebug = false;
2020-06-07 23:59:34 +00:00
/* transformation from the original to the next heptagon;
edge a of the original heptagon matches edge b of the next heptagon */
2020-06-07 23:31:21 +00:00
EX transmatrix get_adj(int a, int b) {
hyperpoint vl = vertices[a];
hyperpoint vr = vertices[a+1];
hyperpoint vm = mid(vl, vr);
transmatrix rm = gpushxto0(vm);
hyperpoint xvl = vertices[b];
hyperpoint xvr = vertices[b+1];
hyperpoint xvm = mid(xvl, xvr);
transmatrix xrm = gpushxto0(xvm);
transmatrix Res = rgpushxto0(vm) * rspintox(rm*vr);
Res = Res * spintox(xrm*xvl) * xrm;
return Res;
}
pair<int, int> hash(hyperpoint h) {
return {int(h[0] * 1000000 + .5), int(h[1] * 1000000 + .5)};
}
2020-06-07 23:31:21 +00:00
void make() {
2020-06-07 23:59:34 +00:00
int& v = magmav;
2020-06-07 23:59:34 +00:00
/* compute the vertices */
vertices.resize(magmav+1);
for(int i=0; i<=magmav; i++)
vertices[i] = spin(2*M_PI*(i+(v-7)/4.)/v) * xpush0(1);
2020-06-07 23:31:21 +00:00
ld xx = vertices[2][0];
int down = v/2 + 2;
for(int k=3; k<down; k++)
vertices[k][0] = 2 * xx - vertices[k][0];
hcenter = Hypc;
for(int i=0; i<magmav; i++) hcenter += vertices[i];
hcenter = normalize(hcenter);
2020-06-07 23:31:21 +00:00
vertices.resize(magmav);
for(int i=0; i<magmav; i++) vertices.push_back(vertices[i]);
for(int i=0; i<magmav; i++) vertices.push_back(vertices[i]);
Remove USE_UNORDERED_MAP because it has bit-rotted. Trying to compile with `-DUSE_UNORDERED_MAP` produces lots of compiler errors like these, because of missing `std::hash` specializations. Also, `#define unordered_map map` is just evil! ``` ./nonisotropic.cpp:875:36: note: in instantiation of template class 'std::__1::unordered_map<hr::nilv::mvec, hr::heptagon *, std::__1::hash<hr::nilv::mvec>, std::__1::equal_to<hr::nilv::mvec>, std::__1::allocator<std::__1::pair<const hr::nilv::mvec, hr::heptagon *> > >' requested here unordered_map<mvec, heptagon*> at; ^ ./nonisotropic.cpp:239:58: note: in instantiation of template class 'std::__1::unordered_map<std::__1::pair<hr::heptagon *, hr::heptagon *>, hr::heptagon *, std::__1::hash<std::__1::pair<hr::heptagon *, hr::heptagon *> >, std::__1::equal_to<std::__1::pair<hr::heptagon *, hr::heptagon *> >, std::__1::allocator<std::__1::pair<const std::__1::pair<hr::heptagon *, hr::heptagon *>, hr::heptagon *> > >' requested here unordered_map<pair<heptagon*, heptagon*>, heptagon*> at; ^ ./nonisotropic.cpp:457:49: error: no matching member function for call to 'iadj' while(h1->distance < h2->distance) back = iadj(h2, down) * back, h2 = h2->cmove(down); ^~~~ cell.cpp:42:15: note: candidate function not viable: no known conversion from 'hr::sn::hrmap_solnih' to 'hr::hrmap' for object argument transmatrix iadj(heptagon *h, int d) { ^ cell.cpp:41:22: note: candidate function not viable: no known conversion from 'hr::sn::hrmap_solnih' to 'hr::hrmap' for object argument struct transmatrix iadj(cell *c, int i) { cell *c1 = c->cmove(i); return adj(c1, c->c.spin(i)); } ^ ```
2020-09-25 03:15:19 +00:00
map<pair<int, int>, int> counts;
int big = v - 2;
auto rehash = [&] (const transmatrix& T) {
for(int a=0; a<v; a++) {
auto hashval = hash(T * vertices[a]);
if(a == 2 || a == down)
counts[hashval]++;
else if(a > 2 && a < down)
counts[hashval] += 2*v - big;
else
counts[hashval] += big;
}
};
2020-06-07 23:54:55 +00:00
heps.emplace_back(Id, 0xFFFFFFFF);
2020-06-07 23:31:21 +00:00
2020-06-07 23:56:53 +00:00
auto advance = [&] (int i, int j, bool mirror = false) {
transmatrix T = heps.back().first * get_adj(i, j);
if(mirror) T = T * MirrorY;
heps.emplace_back(T, heps.back().second ^ 0xFFFF00);
};
2020-06-07 23:59:34 +00:00
/* create the core */
int last = v-1;
int t = 3;
2020-06-07 23:59:34 +00:00
2020-06-07 23:52:37 +00:00
switch(magmashape) {
2020-06-07 23:31:21 +00:00
2020-06-07 23:52:37 +00:00
case 1:
for(int i=1; i<2*v; i++)
advance(0, t);
2020-06-07 23:52:37 +00:00
break;
2020-06-07 23:31:21 +00:00
2020-06-07 23:52:37 +00:00
case 2:
for(int i=0; i<t+1; i++)
advance(t, 0);
2020-06-07 23:52:37 +00:00
break;
case 3:
for(int a=0; a<2; a++) {
advance(t-1, 0);
for(int i=a; i<v+1; i++)
advance(t, 0);
2020-06-07 23:52:37 +00:00
}
break;
case 4: {
advance(t, 1);
for(int a=0; a<v-3; a++)
advance(t, 0);
advance(t, 1);
for(int a=0; a<v-4; a++)
advance(t, 0);
2020-06-07 23:52:37 +00:00
break;
}
2020-06-07 23:52:37 +00:00
case 5:
for(int a=0; a<v-1; a++) {
advance(t, 0);
2020-06-07 23:52:37 +00:00
}
for(int b=0; b<magmalong; b++) {
advance(t, last);
advance(t, 0);
2020-06-07 23:52:37 +00:00
}
2020-06-07 23:31:21 +00:00
for(int a=0; a<v; a++) {
advance(t, 0);
2020-06-07 23:52:37 +00:00
}
2020-06-07 23:31:21 +00:00
2020-06-07 23:52:37 +00:00
for(int b=0; b<magmalong; b++) {
advance(t, last);
advance(t, 0);
2020-06-07 23:52:37 +00:00
}
break;
2020-06-07 23:31:21 +00:00
}
2020-06-07 23:54:55 +00:00
2020-06-07 23:59:34 +00:00
/* center the core */
2020-06-07 23:54:55 +00:00
hyperpoint center = Hypc;
for(auto& h: heps) for(int i=0; i<v; i++)
2020-06-07 23:54:55 +00:00
center += h.first * vertices[i];
center = normalize(center);
for(auto& h: heps) h.first = gpushxto0(center) * h.first;
2020-06-07 23:31:21 +00:00
counts.clear();
for(auto& h: heps) rehash(h.first);
2020-06-07 23:59:34 +00:00
/* grow */
for(int a=0; a<magmacount; a++) {
hyperpoint p = heps.back().first * vertices[2];
int total = counts[hash(p)];
println(hlog, "total ", total);
if(total == 2*v)
advance(down, down, true);
else if(total == 2 * v - big)
advance(t, last);
else if(total < 2 * v)
advance(t, 0);
else
break;
rehash(heps.back().first);
2020-06-07 23:31:21 +00:00
}
}
void draw_at(transmatrix T, color_t col, int id) {
for(int i=0; i<=magmav; i++)
2020-06-07 23:31:21 +00:00
curvepoint(T * vertices[i]);
queuecurve(0xFF, col, PPR::LINE);
if(magmadebug) {
for(int i=0; i<magmav; i++) {
hyperpoint h = mid(vertices[i], vertices[i+1]);
h += spin(M_PI/2) * (vertices[i+1] - vertices[i]) * .05;
queuestr(T * rgpushxto0(h), 0.4, its(i), 0x80);
}
queuestr(T * rgpushxto0(hcenter), 0.4, "#"+its(id), 0x80);
2020-06-07 23:31:21 +00:00
}
}
void draw_magma() {
2020-06-07 23:52:27 +00:00
if(heps.empty()) make();
transmatrix V = ggmatrix(currentmap->gamestart());
int id = 0;
2020-06-07 23:52:27 +00:00
for(auto h: heps)
draw_at(V * h.first, h.second, id++);
2020-06-07 23:31:21 +00:00
}
int readArgs() {
using namespace arg;
if(0) ;
else if(argis("-magmashape")) {
shift(); magmashape = argi();
}
else if(argis("-magmav")) {
shift(); magmav = argi();
}
2020-06-07 23:31:21 +00:00
else if(argis("-magmacount")) {
shift(); magmacount = argi();
}
else if(argis("-magmalong")) {
shift(); magmalong = argi();
}
else if(argis("-magmadebug")) {
shift(); magmadebug = argi();
}
2020-06-07 23:31:21 +00:00
else return 1;
return 0;
}
auto msc = addHook(hooks_frame, 100, draw_magma)
2020-06-07 23:31:21 +00:00
+ addHook(hooks_args, 100, readArgs);
}