From a14cced41dec4364375660dd87e5c2ea8b36833d Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 6 Nov 2017 19:24:02 +0100 Subject: [PATCH] Hypersian Rug for the torus --- cell.cpp | 9 ++- changelog.txt | 49 +++++++++++--- graph.cpp | 6 +- rug.cpp | 181 +++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 214 insertions(+), 31 deletions(-) diff --git a/cell.cpp b/cell.cpp index 2723e413..2a72d937 100644 --- a/cell.cpp +++ b/cell.cpp @@ -214,8 +214,13 @@ namespace torusconfig { // the configuration of the torus topology. // torus cells are indexed [0..qty), // where the cell to the right from i is indexed i+dx, - // and the cell to the down-rightis numbered i+dy - // changed with command line option: -tpar ,, + // and the cell to the down-right is numbered i+dy + + // Changed with command line option: -tpar ,, + // Ideally, qty, dx, and dy should have the same "modulo 3" + // values as the default -- otherwise the three-color + // pattern breaks. Also, they should have no common + // prime divisor. int qty = 127*3, dx = -1, dy = 11*2; } diff --git a/changelog.txt b/changelog.txt index 33c62327..69eba18d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1910,7 +1910,7 @@ - fixed the checkmate rule not taking the mirrored mimics into account - fixed some bugs with the activation of Orb of Yendor -2019.10.14 19:50 version 10.1 +2017.10.14 19:50 version 10.1 * four new lands - Terracotta Army @@ -1954,12 +1954,12 @@ - some new command line options - 'shame to cheat' is no longer displayed when autocheating is on -2019.10.14 19:50 version 10.1a +2017.10.14 19:50 version 10.1a - fixed the missing leaderboards - fixed the typos in the description of Lava Wolf - fixed the ordering of lands in the Overview -2019.10.15 01:06 version 10.1b +2017.10.15 01:06 version 10.1b - added wandering monsters to the new lands - no longer highlight blizzard particles - flash/lightning destroys terracotta warriors @@ -1968,7 +1968,7 @@ - slime visible in Volcanic Wasteland (but destroyed by lava) - living monsters awaken Terracotta Warriors -2019.10.16 00:43 version 10.1c +2017.10.16 00:43 version 10.1c - changes to the Hunting Ground: - - a new pattern at 0 treasures - - guards now always appear in pairs (not larger groups) @@ -1987,14 +1987,14 @@ - fixed two more graphical glitches in Halloween - fixed the joystick support -2019.10.17 01:50 version 10.1d +2017.10.17 01:50 version 10.1d - updated the translations - made the dogs give up to 'regroup' when you have escaped - you can now melt ice through great wall into the Blizzard - if the sight range option is lowered below 7, ambushes temporarily increase it (as the land makes no sense otherwise) - ancient weapon icon in the inventory -2019.10.17 23:41 version 10.1e +2017.10.17 23:41 version 10.1e - added an option to disable background particles (for lower end platforms and for easier reading) - added an option to change the font size on desktop - the wind icon in Windy Plains is clickable now @@ -2008,21 +2008,21 @@ - warriors awakening takes Orb of Speed into account now - land connection likelihoods adjusted for the new lands -2019.10.25 23:17 version 10.1f +2017.10.25 23:17 version 10.1f - fixed the Halloween in main menu - fixed Zebra unlocking -2019.10.26 22:00 version 10.1g +2017.10.26 22:00 version 10.1g - fixed floating-point values sometimes saving incorrectly on Windows - fixed 's'ave the config also toggling the 's'team leaderboards - fixed the 'wm' and 'mm' commandline options - added the Octagonal geometry (work in progress) -2019.10.26 22:39 version 10.1h +2017.10.26 22:39 version 10.1h - fixed some graphical glitches introduced by 10.1g - fixed some graphical glitches in Halloween -2019.10.31 00:31 version 10.2 +2017.10.31 00:31 version 10.2 - added Crystal World - reworked the geometry experiment menu - changed the Hunting Ground music to Graveyard @@ -2035,7 +2035,7 @@ - fontscale is now saved - fixed CR4 appearing inside mirror reflections -2019.11.01 00:48 version 10.2a +2017.11.01 00:48 version 10.2a - improved the texts in geometry experiment menu - translation updates (to Polish) - the "expansion" screen has moved to the geometry experiment menu (click world size) @@ -2045,3 +2045,30 @@ - added 'alpha' commandline parameter - fixed some polygons which did not end in the start point - Hunting Ground no longer hangs in some geometries + +2017.11.03 22:56 version 10.2b +General: +- marked Orb of Earth as useful in Hunting Ground +- Rose Garden needs 90 treasure now +- the order of lands is now the same in all listings +- translations updated +- Glowing Crystals no longer required for the Hyperstone Quest + +Geometry experiment improvements: +- Crystal World now generated in weird hyperbolic chaos mode +- no Dead Orb generation in the smallworld Graveyard +- Power works correctly on big spheres (randomly on other weird geometries) +- adjusted the hive radii in weird hyperbolic geometries +- fixed the Field Quotient Prairie +- improved the Land of Storms +- made ambushes work on the sphere +- added Mercury Rivers to Euclidean and spherical Terracotta Army +- improved Windy Plains on smaller spheres +- Zebra patterns for some of the new geometries +- Halloween on a Torus +- 'strong wind' was not allowed in Euclidean for some reason + some fixes in validity + validity appears in better place, lands colored + don't display 'bad end' + translations updated + unified the land lists diff --git a/graph.cpp b/graph.cpp index cbda4ce7..f2311d52 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3065,6 +3065,8 @@ bool dodrawcell(cell *c) { if(!buggyGeneration && !debugmode && c->land != laCanvas && sightrange < 10) { // not yet created if(c->mpdist > 7 && !cheater) return false; + // always show on the torus rug + if(rug::rugged && torus) return true; // in the Yendor Challenge, scrolling back is forbidden if(c->cpdist > 7 && (yendor::on && !cheater)) return false; // (incorrect comment) too far, no bugs nearby @@ -5138,9 +5140,6 @@ void drawfullmap() { else drawmovestar(0, 0); } -#if CAP_RUG - if(rug::rugged && !rug::renderonce) queueline(C0, mouseh, 0xFF00FFFF, 5); -#endif #if CAP_EDIT if(cmode & sm::DRAW) mapeditor::drawGrid(); #endif @@ -5238,6 +5237,7 @@ void drawscreen() { DEBB(DF_GRAPH, (debugfile,"drawscreen\n")); calcparam(); + // rug::setVidParam(); #if CAP_ROGUEVIZ rogueviz::fixparam(); #endif diff --git a/rug.cpp b/rug.cpp index a3ac19bf..825f6356 100644 --- a/rug.cpp +++ b/rug.cpp @@ -3,6 +3,7 @@ // implementation of the Hypersian Rug mode + #if CAP_RUG #define TEXTURESIZE (texturesize) @@ -32,6 +33,8 @@ GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers) namespace rug { +double rugzoom = .3; + // hypersian rug datatypes and globals //------------------------------------- @@ -134,8 +137,131 @@ void calcLengths() { points[i]->edges[j].len = hdist(points[i]->h, points[i]->edges[j].target->h); } +void setVidParam() { + vid.xres = vid.yres = TEXTURESIZE; vid.scale = 1; + vid.radius = HTEXTURESIZE; vid.xcenter = HTEXTURESIZE; vid.ycenter = HTEXTURESIZE; + vid.beta = 2; vid.alphax = 1; vid.eye = 0; vid.goteyes = false; + if(torus) vid.radius *= rugzoom; + } + +void buildTorusRug() { + using namespace torusconfig; + + dynamicval d(vid, vid); + rugzoom = 1; + setVidParam(); + + struct toruspoint { + int x,y; + toruspoint() { x=qty; y=qty; } + toruspoint(int _x, int _y) : x(_x), y(_y) {} + int d2() { + return x*x+x*y+y*y; + } + }; + + vector zeropoints; + vector tps(qty); + + for(int ax=-qty; ax tp.d2()) tps[v] = tp; + if(v == 0) + zeropoints.emplace_back(ax, ay); + } + + pair solution; + ld bestsol = 1e12; + + for(auto p1: zeropoints) + for(auto p2: zeropoints) { + int det = p1.x * p2.y - p2.x * p1.y; + if(det < 0) continue; + if(det != qty && det != -qty) continue; + ld quality = ld(p1.d2()) * p2.d2(); + if(quality < bestsol * 3) + if(quality < bestsol) + bestsol = quality, solution.first = p1, solution.second = p2; + } + + if(solution.first.d2() > solution.second.d2()) + swap(solution.first, solution.second); + + ld factor = sqrt(ld(solution.second.d2()) / solution.first.d2()); + + printf("factor = %lf\n", factor); + if(factor < 2) factor = 2.2; + factor -= 1; + + // 22,1 + // 7,-17 + + // transmatrix z1 = {{{22,7,0}, {1,-17,0}, {0,0,1}}}; + transmatrix z1 = {{{(ld)solution.first.x,(ld)solution.second.x,0}, {(ld)solution.first.y,(ld)solution.second.y,0}, {0,0,1}}}; + transmatrix z2 = inverse(z1); + printf("h1 = %s\n", display(z2 * hyperpoint {22,1,0})); + + auto addToruspoint = [&] (int x, int y) { + auto r = addRugpoint(C0, 0); + hyperpoint onscreen; + applymodel(tC0(eumove(x, y)), onscreen); + // take point (1,0) + // apply eumove(1,0) + // divide by EUCSCALE + // multiply by vid.radius (= HTEXTURESIZE * rugzoom) + // add 1, divide by texturesize + r->x1 = onscreen[0]; + r->y1 = onscreen[1]; + // r->y1 = (1 + onscreen[1] * rugzoom / EUCSCALE)/2; + hyperpoint h1 = hpxyz(x, y, 0); + hyperpoint h2 = z2 * h1; + double alpha = -h2[0] * 2 * M_PI; + double beta = -h2[1] * 2 * M_PI; + // r->flat = {alpha, beta, 0}; + double sc = (factor+1)/4; + r->flat = {(factor+cos(alpha)) * cos(beta) * sc, (factor+cos(alpha)) * sin(beta) * sc, -sin(alpha) * sc}; + r->valid = true; + return r; + }; + + for(int i=0; ix1), abs(p->y1))); + + // maxz * rugzoom * vid.radius == vid.radius + + rugzoom = 1 / maxz; + printf("rugzoom = %lf\n", rugzoom); + + for(auto p: points) + p->x1 = (vid.xcenter + vid.radius * rugzoom * p->x1)/ vid.xres, + p->y1 = (vid.ycenter - vid.radius * rugzoom * p->y1)/ vid.yres; + + return; + } + void buildRug() { + if(torus) { + buildTorusRug(); + return; + } + + map vptr; for(int i=0; iflat[0] - r0->flat[0]; + double dy1 = r1->flat[1] - r0->flat[1]; + double dx2 = r2->flat[0] - r0->flat[0]; + double dy2 = r2->flat[1] - r0->flat[1]; + double dxm = mx - r0->flat[0]; + double dym = my - r0->flat[1]; + // A (dx1,dy1) = (1,0) + // B (dx2,dy2) = (0,1) + double det = dx1*dy2 - dy1*dx2; + double tx = dxm * dy2 - dym * dx2; + double ty = -(dxm * dy1 - dym * dx1); + tx /= det; ty /= det; + if(tx >= 0 && ty >= 0 && tx+ty <= 1) { + double rz1 = r0->flat[2] * (1-tx-ty) + r1->flat[2] * tx + r2->flat[2] * ty; + rz1 = -rz1; + if(rz1 < bdist) { + bdist = rz1; + rx1 = r0->x1 + (r1->x1 - r0->x1) * tx + (r2->x1 - r0->x1) * ty; + ry1 = r0->y1 + (r1->y1 - r0->y1) * tx + (r2->y1 - r0->y1) * ty; + } + found = true; + } } - double px = points[besti]->x1 * TEXTURESIZE, py = (1-points[besti]->y1) * TEXTURESIZE; + if(!found) return hpxy(0,0); + + double px = rx1 * TEXTURESIZE, py = (1-ry1) * TEXTURESIZE; videopar svid = vid; setVidParam(); @@ -660,7 +811,7 @@ hyperpoint gethyper(ld x, ld y) { void show() { dialog::init(XLAT("hypersian rug mode"), iinf[itPalace].color, 150, 100); - if(euclid || sphere) { + if((euclid || sphere) && !torus) { dialog::addInfo("This makes sense only in hyperbolic geometry."); dialog::addBreak(50); } @@ -690,7 +841,7 @@ void show() { "Use arrow keys to rotate, Page Up/Down to zoom." ); else if(uni == 'u') { - if(euclid || sphere) + if((euclid || sphere) && !torus) addMessage("This makes sense only in hyperbolic geometry."); else { rug::init();