mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 05:52:59 +00:00 
			
		
		
		
	improved the great walls in pure octagonal
This commit is contained in:
		| @@ -85,6 +85,7 @@ bool wrongMode(char flags) { | ||||
|   if(cheater) return true; | ||||
|   if(flags == 'x') return false; | ||||
|   if(nonbitrunc != (flags == '7')) return true; | ||||
|   if(whirl::whirl) return true; | ||||
|  | ||||
|   switch(flags) { | ||||
|     case 'e': | ||||
| @@ -621,6 +622,7 @@ void achievement_final(bool really_final) { | ||||
|   if(shmup::on) specials++; | ||||
|   if(chaosmode) specials++; | ||||
|   if(nonbitrunc) specials++; | ||||
|   if(whirl::whirl) specials++; | ||||
|   if(inv::on) specials++; | ||||
|   if(specials > 1) return; | ||||
|    | ||||
|   | ||||
| @@ -88,7 +88,7 @@ bool checkBarriersNowall(cellwalker bb, int q, int dir, eLand l1=laNone, eLand l | ||||
|     bb = bb + dir + wstep + dir; | ||||
|     } | ||||
|   else if(nonbitrunc) { | ||||
|     bb = bb + (3*dir) + wstep - (3*dir); | ||||
|     bb = bb + (dir>0?3:4) + wstep - (dir>0?3:4); | ||||
|     } | ||||
|   else { | ||||
|     bb = bb + wstep + (2*dir) + wstep + dir; | ||||
| @@ -261,7 +261,8 @@ void extendNowall(cell *c) { | ||||
|       cw0 = cw + i + wstep + i;  | ||||
|       } | ||||
|     else if(nonbitrunc) { | ||||
|       cw0 = cw + (3*i) + wstep - (3*i); | ||||
|       cw0 = cw + (i>0?3:4) + wstep - (i>0?3:4); | ||||
|       //cw0 = cw + (3*i) + wstep - (3*i); | ||||
|       } | ||||
|     else { | ||||
|       cw0 = cw + (2*i) + wstep; | ||||
|   | ||||
							
								
								
									
										388
									
								
								whirl.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										388
									
								
								whirl.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,388 @@ | ||||
| namespace whirl { | ||||
|   bool whirl; | ||||
|   typedef pair<int, int> loc; | ||||
|   loc param(1, 0); | ||||
|  | ||||
|   hyperpoint next; | ||||
|   ld scale; | ||||
|   ld alpha; | ||||
|   int area; | ||||
|    | ||||
|   loc operator+(loc e1, loc e2) { | ||||
|     return make_pair(e1.first+e2.first, e1.second+e2.second); | ||||
|     } | ||||
|    | ||||
|   loc operator-(loc e1, loc e2) { | ||||
|     return make_pair(e1.first-e2.first, e1.second-e2.second); | ||||
|     } | ||||
|    | ||||
|   loc operator*(loc e1, loc e2) { | ||||
|     return make_pair(e1.first*e2.first-e1.second*e2.second,  | ||||
|       e1.first*e2.second + e2.first*e1.second + e1.second*e2.second); | ||||
|     } | ||||
|    | ||||
|   struct whirlmap_t { | ||||
|     cell *c; | ||||
|     char rdir; | ||||
|     int rspin; | ||||
|     }; | ||||
|  | ||||
|   loc eudir(int d) { | ||||
|     d %= 6; if (d < 0) d += 6; | ||||
|     switch(d) { | ||||
|       case 0: return make_pair(1, 0); | ||||
|       case 1: return make_pair(0, 1); | ||||
|       case 2: return make_pair(-1, 1); | ||||
|       case 3: return make_pair(-1, 0); | ||||
|       case 4: return make_pair(0, -1); | ||||
|       case 5: return make_pair(1, -1); | ||||
|       default: return make_pair(0, 0); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   loc get_coord(cell *c) { | ||||
|     if(c == c->master->c7) return loc(0,0); | ||||
|     vector<int> dirs; | ||||
|     while(c != c->master->c7) { | ||||
|       dirs.push_back(c->spin(0)); | ||||
|       c = c->mov[0]; | ||||
|       } | ||||
|     loc at(0,0); | ||||
|     int dir = 0; | ||||
|     at = at + eudir(dir); | ||||
|     dirs.pop_back(); | ||||
|     while(dirs.size()) { | ||||
|       dir += dirs.back() + 3; | ||||
|       dirs.pop_back(); | ||||
|       at = at + eudir(dir); | ||||
|       } | ||||
|     return at; | ||||
|     } | ||||
|    | ||||
|   bool pseudohept(cell *c) { | ||||
|     loc v = get_coord(c); | ||||
|     return (v.first - v.second)%3 == 0; | ||||
|     } | ||||
|    | ||||
|   whirlmap_t whirlmap[20][20]; | ||||
|   void whirl_clear() { | ||||
|     for(int y=0; y<20; y++) for(int x=0; x<20; x++) { | ||||
|       whirlmap[y][x].c = NULL; | ||||
|       whirlmap[y][x].rdir = -1; | ||||
|       } | ||||
|     } | ||||
|    | ||||
|   whirlmap_t& whirl_get(loc c) { | ||||
|     return whirlmap[c.second + 10][c.first + 10]; | ||||
|     } | ||||
|  | ||||
|   const char *disp(loc at) {  | ||||
|     static char bufs[16][16]; | ||||
|     static int bufid; | ||||
|     bufid++; bufid %= 16; | ||||
|     snprintf(bufs[bufid], 16, "[%d,%d]", at.first, at.second); | ||||
|     return bufs[bufid]; | ||||
|     } | ||||
|  | ||||
|   int spawn; | ||||
|    | ||||
| #define WHD(x) // x | ||||
|  | ||||
|   void conn1(loc at, int dir, int dir1) { | ||||
|     auto& wc = whirl_get(at); | ||||
|     auto& wc1 = whirl_get(at + eudir(dir)); | ||||
|     int cdir = fixdir(dir + wc.rspin, wc.c); | ||||
|     WHD( printf("  connection %s/%d %p/%d ", disp(at), dir, wc.c, cdir); ) | ||||
|     if(!wc1.c) { | ||||
|       wc1.c = wc.c->mov[cdir]; | ||||
|       if(wc1.c) { | ||||
|         // wc1.c/wc.c->spin(cdir) == dir1 | ||||
|         wc1.rspin = fixdir(wc.c->spin(cdir) - dir1, wc1.c); | ||||
|         WHD( printf("(pulled) "); ) | ||||
|         } | ||||
|       if(!wc1.c) { | ||||
|         wc1.c = newCell(6, wc.c->master); | ||||
|         spawn++; | ||||
|         // 0 for wc1.c should be dir1 | ||||
|         wc1.rspin = fix6(-dir1); | ||||
|         WHD( printf("(created) "); ) | ||||
|         } | ||||
|       } | ||||
|     int cdir1 = fixdir(dir1 + wc1.rspin, wc1.c); | ||||
|     WHD( printf("(%p/%d) ", wc1.c, cdir1); ) | ||||
|     if(wc.c->mov[cdir] && wc.c->mov[cdir] != wc1.c) { | ||||
|       WHD( printf("FAIL: %p\n", wc.c->mov[cdir]); exit(1); ) | ||||
|       } | ||||
|     if(wc.c->mov[cdir]) { | ||||
|       if(wc.c->spin(cdir) != cdir1) { | ||||
|         printf("warning: wrong spin\n"); | ||||
|         exit(1); | ||||
|         } | ||||
|       } | ||||
|     WHD( else printf("ok\n"); ) | ||||
|     wc.c->mov[cdir] = wc1.c; | ||||
|     tsetspin(wc.c->spintable, cdir, cdir1); | ||||
|     } | ||||
|  | ||||
|   void conn(loc at, int dir) { | ||||
|     conn1(at, fix6(dir), fix6(dir+3)); | ||||
|     conn1(at + eudir(dir), fix6(dir+3), fix6(dir)); | ||||
|     } | ||||
|    | ||||
|   void extend_map(cell *c, int d) { | ||||
|     WHD( printf("EXTEND %p %d\n", c, d); ) | ||||
|     if(c->master->c7 != c) { | ||||
|       while(c->master->c7 != c) { | ||||
|         d = c->spin(0); | ||||
|         c = c->mov[0]; | ||||
|         } | ||||
|       // c move 0 equals c' move spin(0) | ||||
|       extend_map(c, d); | ||||
|       extend_map(c, fixdir(d-1, c)); | ||||
|       extend_map(c, fixdir(d+1, c)); | ||||
|       return; | ||||
|       } | ||||
|  | ||||
|     whirl_clear(); | ||||
|  | ||||
|     // we generate a local map from an Euclidean grid to the | ||||
|     // hyperbolic grid we build. | ||||
|      | ||||
|     // we fill the equilateral triangle with the following vertices: | ||||
|  | ||||
|     loc vc[3]; | ||||
|     vc[0] = loc(0,0); | ||||
|     vc[1] = param; | ||||
|     vc[2] = param * loc(0,1); | ||||
|      | ||||
|     // whirl_get(loc) gives our local map. We set the vertices first | ||||
|     { | ||||
|     auto h = c->master; | ||||
|     auto& ac0 = whirl_get(vc[0]); | ||||
|     ac0.c = h->c7; | ||||
|     ac0.rspin = d; | ||||
|      | ||||
|     auto& ac1 = whirl_get(vc[1]); | ||||
|     ac1.c = createStep(h, d)->c7; | ||||
|     WHD( printf("%s : %p\n", disp(vc[1]), ac1.c); ) | ||||
|   | ||||
|     // 3 ~ h->spin(d) | ||||
|     ac1.rspin = h->spin(d) - 3; | ||||
|      | ||||
|     auto& ac2 = whirl_get(vc[2]); | ||||
|     ac2.c = createStep(h, (d+1)%S7)->c7; | ||||
|     WHD( printf("%s : %p\n", disp(vc[2]), ac2.c); ) | ||||
|     // 4 ~ h->spin(d+1) | ||||
|     ac2.rspin = h->spin((d+1)%S7) - 4; | ||||
|     } | ||||
|  | ||||
|     // then we set the edges of our big equilateral triangle (in a symmetric way) | ||||
|     for(int i=0; i<3; i++) { | ||||
|       loc start = vc[i]; | ||||
|       loc end = vc[(i+1)%3]; | ||||
|       WHD( printf("from %s to %s\n", disp(start), disp(end)); ) | ||||
|       loc rel = param; | ||||
|       auto build = [&] (loc& at, int dx, bool forward) { | ||||
|         int dx1 = dx + 2*i; | ||||
|         WHD( printf("%s %d\n", disp(at), dx1); ) | ||||
|         conn(at, dx1);         | ||||
|         if(forward) whirl_get(at).rdir = fix6(dx1); | ||||
|         else whirl_get(at+eudir(dx1)).rdir = fix6(dx1+3); | ||||
|         at = at + eudir(dx1); | ||||
|         }; | ||||
|       while(rel.first >= 2) { | ||||
|         build(start, 0, true); | ||||
|         build(end, 3, false); | ||||
|         rel.first -= 2; | ||||
|         } | ||||
|       while(rel.second >= 2) { | ||||
|         build(start, 1, true); | ||||
|         build(end, 4, false); | ||||
|         rel.second -= 2; | ||||
|         } | ||||
|       while(rel.first>0 && rel.second) { | ||||
|         build(start, 0, true); | ||||
|         build(end, 3, false); | ||||
|         rel.first -= 2; | ||||
|         } | ||||
|       for(int k=0; k<6; k++) | ||||
|         if(start + eudir(k+2*i) == end) | ||||
|           build(start, k, true);                          | ||||
|       if(start != end) { printf("assertion failed: start %s == end %s\n", disp(start), disp(end)); exit(1); } | ||||
|       } | ||||
|  | ||||
|     // now we can fill the interior of our big equilateral triangle | ||||
|     loc at = vc[0]; | ||||
|     while(true) { | ||||
|       auto& wc = whirl_get(at); | ||||
|       int dx = wc.rdir; | ||||
|       auto at1 = at + eudir(dx); | ||||
|       auto& wc1 = whirl_get(at1); | ||||
|       WHD( printf("%s (%d) %s (%d)\n", disp(at), dx, disp(at1), wc1.rdir); ) | ||||
|       int df = wc1.rdir - dx; | ||||
|       if(df < 0) df += 6; | ||||
|       if(df == 3) break; | ||||
|       switch(df) { | ||||
|         case 0: | ||||
|         case 4: | ||||
|         case 5: | ||||
|           at = at1; | ||||
|           continue; | ||||
|         case 2: { | ||||
|           conn(at, dx+1); | ||||
|           wc.rdir = (dx+1) % 6; | ||||
|           break; | ||||
|           } | ||||
|         case 1: { | ||||
|           auto at2 = at + eudir(dx+1); | ||||
|           auto& wc2 = whirl_get(at2); | ||||
|           if(wc2.c) { at = at1; continue; } | ||||
|           wc.rdir = (dx+1) % 6; | ||||
|           conn(at, (dx+1) % 6); | ||||
|           conn(at1, (dx+2) % 6); | ||||
|           conn(at2, (dx+0) % 6); | ||||
|           wc1.rdir = -1; | ||||
|           wc2.rdir = dx;  | ||||
|           break; | ||||
|           } | ||||
|         default: | ||||
|           printf("case unhandled %d\n", df); | ||||
|           exit(1); | ||||
|         } | ||||
|       } | ||||
|     WHD( printf("DONE\n\n"); ) | ||||
|     } | ||||
|    | ||||
|   void compute_geometry() { | ||||
|     if(whirl) { | ||||
|       int x = param.first; | ||||
|       int y = param.second; | ||||
|       area = ((2*x+y) * (2*x+y) + y*y*3) / 4; | ||||
|       next = hpxyz(x+y/2., -y * sqrt(3) / 2, 0); | ||||
|       scale = 1 / hypot2(next); | ||||
|       crossf *= scale; | ||||
|       hepvdist *= scale; | ||||
|       rhexf *= scale; | ||||
| //    spin = spintox(next); | ||||
| //    ispin = rspintox(next); | ||||
|       alpha = -atan2(next[1], next[0]); | ||||
|       base_distlimit = (base_distlimit + log(scale) / log(2.618)) / scale; | ||||
|       } | ||||
|     else { | ||||
|       scale = 1; | ||||
|       alpha = 0; | ||||
|       } | ||||
|     } | ||||
|    | ||||
|   string operation_name() { | ||||
|     if(!whirl::whirl) { | ||||
|       if(nonbitrunc) return XLAT("OFF"); | ||||
|       else return XLAT("bitruncated"); | ||||
|       } | ||||
|     else if(param == loc(1, 0)) | ||||
|       return XLAT("OFF"); | ||||
|     else if(param == loc(1, 1)) | ||||
|       return XLAT("bitruncated"); | ||||
|     else if(param == loc(2, 0)) | ||||
|       return XLAT("chamfered"); | ||||
|     else if(param == loc(3, 0)) | ||||
|       return XLAT("2x bitruncated"); | ||||
|     else | ||||
|       return "(" + its(param.first) + "," + its(param.second) + ")"; | ||||
|     } | ||||
|    | ||||
|   int config_x, config_y; | ||||
|    | ||||
|   void whirl_set(int x, int y) { | ||||
|     if(y < 0) { y = -y; x -= y; } | ||||
|     if(x < 0) { x = -x; y = -y; } | ||||
|     if(x < y) swap(x, y); | ||||
|     if(x > 8) x = 8; | ||||
|     if(y > 8) y = 8; | ||||
|     config_x = x; config_y = y; | ||||
|     param = loc(x, y); | ||||
|     auto g = screens; | ||||
|     if(x == 1 && y == 0) { | ||||
|       if(whirl::whirl) restartGame('7'); | ||||
|       if(!nonbitrunc) restartGame('7'); | ||||
|       } | ||||
|     else if(x == 1 && y == 1) { | ||||
|       if(whirl::whirl) restartGame('7'); | ||||
|       if(nonbitrunc) restartGame('7'); | ||||
|       } | ||||
|     else { | ||||
|       if(nonbitrunc) restartGame('7'); | ||||
|       param = loc(x, y); | ||||
|       restartGame('w'); | ||||
|       } | ||||
|     screens = g; | ||||
|     } | ||||
|  | ||||
|   string helptext() { | ||||
|     return  | ||||
|       "HyperRogue's map is obtained by applying an operator to the basic regular tesselation. " | ||||
|       "Operator (x,y) means that, to get to a nearest non-hex from any non-hex, you should move x " | ||||
|       "cells in any direction, turn right 60 degrees, and move y cells. " | ||||
|       "By default HyperRogue uses bitruncation, which corresponds to (1,1)."; | ||||
|     }   | ||||
|  | ||||
|   void show() { | ||||
|     cmode = sm::SIDE; | ||||
|     gamescreen(0);   | ||||
|     dialog::init(XLAT("operators")); | ||||
|      | ||||
|     dialog::addBoolItem(XLAT("OFF"), param == loc(1,0), 'a'); | ||||
|     dialog::lastItem().value = "(1,0)"; | ||||
|  | ||||
|     dialog::addBoolItem(XLAT("bitruncated"), param == loc(1,1), 'b'); | ||||
|     dialog::lastItem().value = "(1,1)"; | ||||
|  | ||||
|     dialog::addBoolItem(XLAT("chamfered"), param == loc(2,0), 'c'); | ||||
|     dialog::lastItem().value = "(2,0)"; | ||||
|  | ||||
|     dialog::addBoolItem(XLAT("2x bitruncated"), param == loc(3,0), 'd'); | ||||
|     dialog::lastItem().value = "(3,0)"; | ||||
|  | ||||
|     dialog::addBreak(100); | ||||
|     dialog::addSelItem("x", its(config_x), 0); | ||||
|     dialog::addSelItem("y", its(config_y), 0); | ||||
|     dialog::addBoolItem(XLAT("tuned"), param == loc(config_x, config_y), 'f'); | ||||
|  | ||||
|     dialog::addBreak(100); | ||||
|     dialog::addItem(XLAT("help"), SDLK_F1);   | ||||
|     dialog::addItem(XLAT("back"), '0');   | ||||
|     dialog::display(); | ||||
|  | ||||
|     keyhandler = [] (int sym, int uni) { | ||||
|       dialog::handleNavigation(sym, uni); | ||||
|       if(uni == 'a')  | ||||
|         whirl_set(1, 0); | ||||
|       else if(uni == 'b') | ||||
|         whirl_set(1, 1); | ||||
|       else if(uni == 'c') | ||||
|         whirl_set(2, 0); | ||||
|       else if(uni == 'd') | ||||
|         whirl_set(3, 0); | ||||
|       else if(uni == 'f') | ||||
|         whirl_set(config_x, config_y); | ||||
|       else if(uni == 'x') | ||||
|         dialog::editNumber(config_x, 1, 10, 1, 1, "x", helptext()); | ||||
|       else if(uni == 'y') | ||||
|         dialog::editNumber(config_y, 1, 10, 1, 1, "y", helptext()); | ||||
|       else if(doexiton(sym, uni)) | ||||
|         popScreen(); | ||||
|       }; | ||||
|     } | ||||
|    | ||||
|   void configure() { | ||||
|     if(whirl::whirl) | ||||
|       config_x = param.first, config_y = param.second; | ||||
|     else if(nonbitrunc) | ||||
|       config_x = 1, config_y = 0; | ||||
|     else | ||||
|       config_x = 1, config_y = 1; | ||||
|     param = loc(config_x, config_y); | ||||
|     pushScreen(whirl::show); | ||||
|     } | ||||
|   } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue