// Hyperbolic Rogue pattern generator // Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details namespace hr { void spill50(cell *c, eWall w, int r) { c->wall = w; if(r) for(int i=0; itype; i++) spill50(createMov(c, i), w, r-1); } int style = 3; struct state50 { bool polarity1; bool polarity2; color_t color, color2, wc2; }; void progress(cell *c, state50 s); #include map map50; void initPatternFifty(cell *c) { state50 s; s.polarity1 = 0; s.polarity2 = 0; s.color = 0; s.color2 = 1; s.wc2 = 0; map50[c] = s; } int par; int haverule[1<<24][8]; void saveCode(heptagon *H1, int d, heptagon *H2) { /* if(!H1 || !H2) return; if(H1->move[d] != H2) exit(1); int h1 = H1->fiftyval; int h2 = H2->fiftyval; if(!h1 || !h2) return; if(haverule[h1][d] && haverule[h1][d] != h2) { printf("rule conflict: %06x, %d, %06x/%06x\n", h1, d, h2, haverule[h1][d]); // exit(1); } if(!haverule[h1][d]) { haverule[h1][d] = h2; printf("RULE50(0x%06x, %d, 0x%06x)\n", h1, d, h2); } */ fflush(stdout); } void saveCode(cell *c) { /* heptagon *hept = c->master; if(hept != &origin) saveCode(hept->move[0], hept->spin[0], hept); */ bool allcodes = c->master->fiftyval >= 0; for(int i=0; i<7; i++) if(c->master->move[i] && c->master->move[i]->fiftyval >= 0) ; else allcodes = false; if(allcodes) { printf("RULE50(0x%03x", c->master->fiftyval); int rulebase = 0; for(int i=0; i<7; i++) if(c->master->move[i]->fiftyval < c->master->move[rulebase]->fiftyval) rulebase = i; for(int i=0; i<7; i++) printf(", 0x%03x", c->master->move[(rulebase+i)%7]->fiftyval); printf(")\n"); } // hept->fiftyused = true; } void encode(cell *c, state50 s, int mod, int spn) { /*int i = 0; i *= 16; i += s.color; i *= 16; i += s.color2; i *= 16; i += s.polarity1; i *= 16; i += s.polarity2; i *= 16; i += mod; i *= 16; i += spn; if(c->master->fiftyval) { printf("multiply 50val\n"); exit(1); } c->master->fiftyval = i; c->master->fiftyused = false; */ c->master->fiftyval = s.color + s.polarity1 * 8 + s.polarity2 * 16 + mod * 32; // s.color * 16 + (s.polarity1 ? 128 : 0) + (s.polarity2 ? 256 :0) + mod; saveCode(c); for(int i=0; i<7; i++) saveCode(createStep(c->master, i)->c7); /* for(int i=0; i<7; i++) if(c->master->move[i]) { saveCode(c->master, i, c->master->move[i]); saveCode(c->master->move[i], c->master->spin[i], c->master); } */ } eWall colorwalls[4] = {waCIsland, waCIsland2, waMineOpen, waDeadfloor }; void patternFiftyAt(cell *c) { if(!map50.count(c)) return; state50 s = map50[c]; // c->wall = waCIsland; // if(c->heat > ii) return; // printf("pfifty %p\n", c); if(style == 1 && s.polarity2) { spill50(c, waCamelot, 3); spill50(c, waNone, 2); for(int i=0; itype; i++) { cellwalker cw(c, i); cellwalker cw1 = cw + wstep + 4 + wstep; (cw1+3+wstep).at->wall = waFloorA; (cw1+4+wstep).at->wall = waFloorA; } } /*switch(ii) { case 0: spill50(c, waNone, 3); break; case 1: spill50(c, waNone, 3); break; case 2: spill50(c, waNone, 3); break; case 3: spill50(c, waNone, 3); break; } */ if(style == 2) { spill50(c, waCavefloor, 2); spill50(c, waFloorA, 1); } if(style == 3) { spill50(c, colorwalls[s.color], 3); // c->item = itGold; // if(s.polarity2) return; } encode(c, s, 0, 0); int sgn = s.polarity2 ? 1 : -1; int sgn1 = s.polarity1 ? 1 : -1; color_t col2 = s.color2, sw = s.wc2; while(col2 != 7-s.color) { sw += (s.polarity1?1:-1); sw %= 7; while(true) { col2++; col2 &= 7; if(col2 != s.color) break; } } for(int i=0; itype; i++) { auto cw = cellwalker(c, sw) + (sgn1 * i) + wstep + (sgn * 4) + wstep; if(cw.spin < 0 || cw.spin >= 7 || cw.at->type != 7) exit(1); encode(cw.c, s, 1+i, cw.spin); } for(int i=0; itype; i++) { auto cw = cellwalker(c, sw) + (sgn1 * i) + wstep + 3 + wstep + 3 + wstep; if(cw.spin < 0 || cw.spin >= 7 || cw.at->type != 7) exit(1); encode(cw.c, s, 8+i, cw.spin); } // c->heat = s.color + for(int i=0; itype; i++) { cellwalker cw(c, s.wc2); cw += (sgn1 * i); cw += wstep; if(style == 0) cw.at->wall = waCamelot; // cw.at->item = itSilver; cw += (sgn*4); //6 cw += wstep; if(style == 0) cw.at->wall = waFloorA; // cw.at->item = itSilver; cw += (sgn*4); //7 cw += wstep; if(style == 0) cw.at->wall = waFloorA; // cw.at->item = itSilver; cw += (3); //6 cw += wstep; if(style == 0) cw.at->wall = waFloorA; // cw.at->item = itSilver; cw += (3); //6 cw += wstep; if(style == 0) cw.at->wall = waFloorA; // cw.at->item = itSilver; cw += (sgn*3); //7 cw += wstep; if(style == 0) cw.at->wall = waCamelot; // cw.at->item = itSilver; cw += (sgn*2); //6 cw += wstep; // cw.at->item = itGold; // setdist(cw.c, 8, NULL); state50 s2 = s; s2.polarity1 = !s.polarity1; s2.wc2 = (cw.spin + sgn1 * i + sgn + 42) % 7; progress(cw.c, s2); // printf("heat set %f\n", cw.at->heat); } int newcol = s.color2; // if(s.polarity2) return; for(int i=0; itype; i++) { cellwalker cw(c, s.wc2); cw += (sgn1 * i); cw += wstep; // cw.at->item = itSilver; // cw.at->item = itDiamond; cw += (3); // 6 cw += wstep; // cw.at->item = itSilver; // cw.at->item = itDiamond; cw += (sgn*4); // 6 cw += wstep; // cw.at->item = itSilver; // cw.at->item = itDiamond; cw += (sgn*2); // 6 cw += wstep; // cw.at->item = itSilver; // cw.at->item = itDiamond; cw += (3); // 6 cw += wstep; // cw.at->item = itSilver; // cw.at->item = itDiamond; cw += (sgn*3); // 7 cw += wstep; // cw.at->item = itSilver; // cw.at->item = itDiamond; cw += (sgn*4); // 6 cw += wstep; // cw.at->item = itSilver; // setdist(cw.c, 8, NULL); state50 s2 = s; s2.polarity2 = !s.polarity2; if(s.polarity2) s2.polarity1 = !s.polarity1; s2.color2 = s2.color; s2.color = newcol; s2.wc2 = cw.spin; progress(cw.c, s2); while(true) { newcol++; newcol &= 7; if(newcol != s2.color && newcol != s.color) break; } // printf("heat set %f\n", cw.at->heat); } } void progress(cell *c, state50 s) { while(s.wc2) { s.wc2 += (s.polarity1?1:-1); s.wc2 %= 7; while(true) { s.color2++; s.color2 &= 7; if(s.color2 != s.color) break; } } if(map50.count(c)) { state50 s2 = map50[c]; if(s2.polarity1 != s.polarity1 || s2.polarity2 != s.polarity2) { printf("Polarity mismatch!\n"); exit(1); } else { if(s2.color != s.color || s2.color2 != s.color2 || s2.wc2 != s.wc2) printf("%d:%d color= %dv%d color2= %dv%d wc2= %dv%d\n", s.polarity1, s.polarity2, s.color, s2.color, s.color2, s2.color2, s.wc2, s2.wc2); } return; } map50[c] = s; if(c->mpdist <= 7) patternFiftyAt(c); } long long Q; int qconflict; string allconflict; void setzebra(cellwalker cwb, int it, int type, string pathcode, int xmods) { // printf("spin=%d type=%d\n", cwb.spin, type); if(cwb.spin != 1 && cwb.spin != 3 && cwb.spin != 5) { printf("S WRONG SPIN %d\n", cwb.spin); exit(1); } if(type < 0 || type > 3) { printf("S WRONG TYPE %d\n", type); exit(1); } cwb.at->tmp = cwb.spin + 16 * type; } void zebra(cellwalker cwb, int it, int type, string pathcode, int xmods) { if(!it) return; if(cwb.spin != 1 && cwb.spin != 3 && cwb.spin != 5) { printf("WRONG SPIN %d\n", cwb.spin); exit(1); } if(type < 0 || type > 3) { printf("WRONG TYPE %d\n", type); exit(1); } // printf("%p+%d = 0%s\n", cwb.c, cwb.spin, pathcode.c_str()); bool redraw = false; // int qval = Q + 99; // redraw = cwb.at->heat == qval; // cwb.at->heat = qval; eWall w = colorwalls[type]; cwb.at->wall = w; for(int i=0; i<6; i+=2) { cellwalker cw = cwb; cw += (i); cw.at->heat = 4 + type + 4 * 9; cw += wstep; cw += (3); cw.at->wall = w; int i0 = i; if(type&2 && i0) i0 = 6-i0; i0 /= 2; cw.at->heat = 4 + type + 4 * (3+i0); cw += wstep; cw += (3); cw.at->wall = w; cw.at->heat = 4 + type + 4 * i0; cw += wstep; cw += (3); cw.at->wall = w; cw.at->heat = 4 + type + 4 * (6+i0); cw += wstep; cw += (-3); cw += wstep; cw += (-3); cw += wstep; cw += (-3); cw += wstep; cw += (-i); cw += (0); setzebra(cw, it-1, type ^ 1, pathcode +'+'+char('A'+i)+char('0'+type), xmods*2); } for(int i=0; i<6; i+=2) { cellwalker cw = cwb; cw += ((type&2)?-i:i); cw += wstep; cw += (3); cw += wstep; cw += (5); if(xmods < 2) { if(cw.at->item && cw.at->item != (1+i) && redraw && i==0) { qconflict++; // allconflict += pathcode; allconflict += "-"; // cwb.at->item = itPalace; // printf("Conflict at %p\n", cwb.at); } // cw.at->item = eItem(1 + i); // cw.at->heat = 4 + type + 4 * (i/2); } cw += wstep; cw += (1); if(type < 2) { // cw += (i); cw += (i); } else { cw += (-i); } // cw += (((Q >> (4*type)) & 12)); setzebra(cw, it-1, 2^type, pathcode + '+'+char('a'+i)+char('0'+type), xmods+1); } } void zebraPattern() { // int bqc = 99; /* for(Q=0; Q<65536; Q++) { if((Q & (Q>>1)) & 0x5555) continue; qconflict = false; cellwalker cw(cwt); cw += wstep; cw += (1); qconflict = 0; allconflict = ""; zebra(cw, 3, 0, ""); if(qconflict < bqc) bqc = qconflict; // if(qconflict == bqc) printf("%X - X-%sX\n", Q, allconflict.c_str()); } Q = 0xFFFB; */ cellwalker cw(cwt); cw += wstep; cw += (1); setzebra(cw, 7, 0, "", -999); // cw.at-> // printf("Conflicts: %d\n", qconflict); } int bspin(heptagon *h) { vector xv; xv.push_back(999); int besti = -1; for(int i=0; i<7; i++) { vector yv; for(int j=0; j<7; j++) yv.push_back(int(h->move[(i+j)%7]->c7->heat+.1)); if(yv < xv) xv = yv, besti = i; } return besti; } void buildAutomatonRule(heptagon *h) { if(!h->c7->heat) return; for(int i=0; i<7; i++) if(!h->move[i]) return; for(int i=0; i<7; i++) for(int j=0; j<7; j++) if(!h->move[i]->move[j] || !h->move[i]->move[j]->c7->heat) return; int bi = bspin(h); printf("RULEZEBRA(%2d", int(h->c7->heat+.1)); for(int j=0; j<7; j++) { heptagon *h2 = h->move[(bi+j)%7]; int bi2 = bspin(h2); printf(", %2d%d", int(h2->c7->heat+.1), fix7(bi2 - h->spin[(bi+j)%7])); } printf(")\n"); } void buildAutomatonRule(cell *c) { if(c->type == 7) buildAutomatonRule(c->master); else { int ii[3]; for(int i=0; i<6; i+=2) if(!c->move(i) || !c->move(i)->heat || c->move(i)->type != 7) return; for(int i=0; i<6; i+=2) ii[i/2] = int(c->move(i)->heat); int z; for(int r=0; r<2; r++) if(ii[1] < ii[0] || ii[2] < ii[0]) z = ii[0], ii[0] = ii[1], ii[1] = ii[2], ii[2] = z; printf("RULEZEBRA6(%d,%d,%d,%d)\n", int(c->heat), int(ii[0]), int(ii[1]), int(ii[2])); } } /* to drawcell: if(c->type == 6 && c->tmp > 0) { int i = c->tmp; zebra(cellwalker(c, i&15), 1, i>>4, "", 0); } c->item = eItem(c->heat / 4); buildAutomatonRule(c); #endif */ // #define BUILDZEBRA }