diff --git a/complex.cpp b/complex.cpp index 7a6cd233..c57ed10a 100644 --- a/complex.cpp +++ b/complex.cpp @@ -1056,6 +1056,33 @@ namespace whirlpool { namespace mirror { + bool build(cell *c) { + if(gp::on) { + if(c == c->master->c7) { + c->wall = ((gp::param.second == 0 || gp::param.first == gp::param.second) && hrand(2)) ? waMirror : waCloud; + return true; + } + return false; + } + if(archimedean) { + c->wall = hrand(2) ? waMirror : waCloud; + return true; + } + if(binarytiling || irr::on) { + // mirrors not supported + if(is_mirrorland(c)) { + c->item = itShard; + return true; + } + return false; + } + if(nonbitrunc?pseudohept(c):!ishept(c)) { + c->wall = hrand(2) ? waMirror : waCloud; + return true; + } + return false; + } + vector> mirrors; static const int LIGHTNING = -1; // passed instead of cpid @@ -1110,11 +1137,60 @@ namespace mirror { mirrors.emplace_back(cpid, cw); } } + + // we go by heptagons in Archimedean, + bool equal(heptspin h1, heptspin h2, int lev) { + if(h1.at->degree() != h2.at->degree()) return false; + if(lev) for(int i=0; idegree(); i++) { + heptspin h11 = h1 + i + wstep; + heptspin h21 = h2 + i + wstep; + if(!equal(h11, h21, lev-1)) return false; + } + return true; + } + + int create_archimedean_rec(heptspin hs, int cpid, heptspin hs0, int lev) { + int result = 0; + for(int i=0; idegree(); i++) { + heptspin hs1 = hs + i; + if(lev == 0) { + if(hs1.at != hs0.at && equal(hs1, hs0, 3)) { + createMirror(cellwalker(hs1.at->c7, hs1.spin, hs1.mirrored), cpid); + result++; + } + } + else result += create_archimedean_rec(hs1 + wstep, cpid, hs0, lev-1); + } + return result; + } + + void create_archimedean(cellwalker cw, int cpid, bool mirrored) { + heptspin hs(cw.at->master, cw.spin, cw.mirrored); + heptspin hsx = hs; + if(mirrored) hsx += wmirror; + if(create_archimedean_rec(hsx, cpid, hs, 2)) return; + if(create_archimedean_rec(hsx, cpid, hs, 3)) return; + if(create_archimedean_rec(hsx, cpid, hs, 4)) return; + } void createMirrors(cellwalker cw, int cpid) { + + if(archimedean) { + create_archimedean(cw, cpid, true); + return; + } + cw.mirrored = !cw.mirrored; cell *c = cw.at; + if(gp::on) { + for(int i=0; itype; i++) { + heptspin hs(cw.at->master, cw.spin, cw.mirrored); + hs = hs + i + wstep + i - (gp::param.first == gp::param.second ? 1 : 0); + createMirror(cellwalker(hs.at->c7, hs.spin, hs.mirrored), cpid); + } + return; + } for(int i=0; itype; i++) { auto cws = cw + wstep; if(cws.at->type == c->type) @@ -1124,9 +1200,39 @@ namespace mirror { } void createMirages(cellwalker cw, int cpid) { - if(nonbitrunc) { + if(archimedean) { + create_archimedean(cw, cpid, false); + return; + } + if(gp::on && !(S7 & 1)) { + for(int i=0; itype; i++) { + heptspin hs(cw.at->master, cw.spin, cw.mirrored); + hs = hs + i + wstep + 1 + wstep + 1 + (S7/2) - i + 1; + createMirror(cellwalker(hs.at->c7, hs.spin, hs.mirrored), cpid); + } + return; + } + if(gp::on && (S7 & 1)) { + for(int i=0; itype; i++) { + heptspin hs(cw.at->master, cw.spin, cw.mirrored); + hs = hs + i + wstep + (S7/2) + wstep - 2 + wstep + (S7/2) - i; + createMirror(cellwalker(hs.at->c7, hs.spin, hs.mirrored), cpid); + } + return; + } + if(nonbitrunc && !(S7 & 1)) { for(int i=0; itype; i++) - createMirror(cw + i + wstep + 3 + wstep + 5 + wstep + 3 - i, cpid); + createMirror(cw + i + wstep + 1 + wstep + 1 + (S7/2) - i, cpid); + return; + } + if(nonbitrunc && (S7 & 1) && (S3 == 4)) { + for(int i=0; itype; i++) + createMirror(cw + i + wstep + 1 + wstep - (S7/2) + wstep - (S7/2) - i, cpid); + return; + } + if(nonbitrunc && (S7 & 1)) { + for(int i=0; itype; i++) + createMirror(cw + i + wstep + (S7/2) + wstep - 2 + wstep + (S7/2) - i, cpid); return; } for(int i=0; iland, laMirror, laMirrorOld); + } + } diff --git a/game.cpp b/game.cpp index fd0dec43..0bbf729c 100644 --- a/game.cpp +++ b/game.cpp @@ -3320,7 +3320,7 @@ string itemcounter(int qty) { void gainShard(cell *c2, const char *msg) { invismove = false; string s = XLAT(msg); - if(among(c2->land, laMirror, laMirrorOld) && !peace::on) { + if(is_mirrorland(c2) && !peace::on) { gainItem(itShard); s += itemcounter(items[itShard]); collectMessage(c2, itShard); diff --git a/graph.cpp b/graph.cpp index bd98b250..2678a2e9 100644 --- a/graph.cpp +++ b/graph.cpp @@ -2052,24 +2052,24 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) { if(d>=4) cw += 2; transmatrix Vs = Vparam; bool mirr = cw.mirrored; - Vs = Vs * ddspin(c, cw.spin-cwt.spin, masterless ? 0 : M_PI); - nospins = applyAnimation(cwt.at, Vs, footphase, LAYER_SMALL); - if(!nospins) Vs = Vs * ddspin(c, cwt.spin); + transmatrix T = Id; + nospins = applyAnimation(cwt.at, T, footphase, LAYER_SMALL); + if(nospins) + Vs = Vs * ddspin(c, cw.spin, 0) * iddspin(cwt.at, cwt.spin, 0) * T; + else + Vs = Vs * ddspin(c, cw.spin, 0); if(mirr) Vs = Vs * Mirror; if(inmirrorcount&1) mirr = !mirr; col = mirrorcolor(geometry == gElliptic ? det(Vs) < 0 : mirr); + if(!mouseout() && !nospins) { + hyperpoint P2 = Vs * inverse(cwtV) * mouseh; + queuechr(P2, 10, 'x', 0xFF00); + } if(!nospins && flipplayer) Vs = Vs * pispin; if(mmmon) { drawMonsterType(moMimic, c, Vs, col, footphase); drawPlayerEffects(Vs, c, false); } - if(!mouseout() && !nospins) { - transmatrix invxy = Id; - if(flipplayer) invxy[0][0] = invxy[1][1] = -1; - - hyperpoint P2 = Vs * inverse(cwtV) * invxy * mouseh; - queuechr(P2, 10, 'x', 0xFF00); - } } return !mmmon; } diff --git a/landgen.cpp b/landgen.cpp index b96b96c7..86a4ed95 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -533,8 +533,7 @@ void giantLandSwitch(cell *c, int d, cell *from) { itOrbFlash, itOrbSpeed, itOrbFire, itOrbWinter, itOrbAether, itOrbLife}; c->item = powerorbs[hrand(6)]; } - else if(!ctof(c) && hrand(5000) < 10) - c->wall = hrand(2) ? waMirror : waCloud; + else if(hrand(5000) < 10 && mirror::build(c)) ; else if(hrand(1000) < 10 + (items[itPower] ? 10:0) + (items[itPower] + yendor::hardness())) c->monst = eMonster(moWitch + hrand(NUMWITCH)); } @@ -1993,8 +1992,7 @@ void giantLandSwitch(cell *c, int d, cell *from) { case laMirrorOld: ONEMPTY { - if((nonbitrunc?pseudohept(c):!ishept(c)) && hrand(5000) < 120 && (peace::on || notDippingFor(itShard))) - c->wall = hrand(2) ? waMirror : waCloud; + if(hrand(5000) < 120 && (peace::on || notDippingFor(itShard)) && mirror::build(c)); else if(ishept(c) && hrand(5000) < 10 * PRIZEMUL) placePrizeOrb(c); else if(hrand(12000) < 8 + items[itShard] + yendor::hardness()) @@ -2006,8 +2004,7 @@ void giantLandSwitch(cell *c, int d, cell *from) { case laMirror: ONEMPTY { - if((nonbitrunc?pseudohept(c):!ishept(c)) && hrand(1250) < 120 && (peace::on || notDippingFor(itShard))) - c->wall = hrand(2) ? waMirror : waCloud; + if(hrand(1250) < 120 && (peace::on || notDippingFor(itShard)) && mirror::build(c)) ; else if(ishept(c) && hrand(5000) < 10 * PRIZEMUL) placePrizeOrb(c); else if(hrand(cwt.at->land == laMirror ? 600 : 2400) < 8 + items[itShard] + yendor::hardness()) { @@ -2205,12 +2202,9 @@ void giantLandSwitch(cell *c, int d, cell *from) { ONEMPTY { if(nonbitrunc && c->land == laCrossroads5 && hrand(100) < 60) c->wall = waBarrier; - else if(!ctof(c) && !inv::on && items[itShard] >= 10 && hrand(8000) < 120*orbcrossfun(items[itShard]) && !gp::on) - c->wall = hrand(2) ? waMirror : waCloud; - else if(!ctof(c) && hyperstonesUnlocked() && hrand(8000) < 100 && !gp::on) - c->wall = hrand(2) ? waMirror : waCloud; - else if(!ctof(c) && tactic::on && isCrossroads(specialland) && hrand(8000) < 120 && !gp::on) - c->wall = hrand(2) ? waMirror : waCloud; + else if(!inv::on && items[itShard] >= 10 && hrand(8000) < 120*orbcrossfun(items[itShard]) && mirror::build(c)) ; + else if(hyperstonesUnlocked() && hrand(8000) < 100 && mirror::build(c)) ; + else if(tactic::on && isCrossroads(specialland) && hrand(8000) < 120 && mirror::build(c)) ; else if(c->land == laCrossroads4 && hrand(24000) < 10 && tactic::on) c->wall = waRose; else { diff --git a/landlock.cpp b/landlock.cpp index 7c77537a..637a58fb 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -1138,9 +1138,12 @@ land_validity_t& land_validity(eLand l) { return not_enough_space; // mirrors do not work in gp - if(among(l, laMirror, laMirrorOld) && gp::on) + if(among(l, laMirror, laMirrorOld) && (gp::on && old_daily_id < 33)) return dont_work; + if(binarytiling && among(l, laMirror, laMirrorOld)) + return dont_work; + if(l == laWhirlwind && hyperbolic_not37) return pattern_incompatibility; diff --git a/monstergen.cpp b/monstergen.cpp index 339d6995..f2848818 100644 --- a/monstergen.cpp +++ b/monstergen.cpp @@ -354,7 +354,8 @@ void wandering() { placeLocalOrbs(c); if(!c->item) c->item = wanderingTreasure(c); if(c->item == itShard) { - c->item = itNone, c->wall = hrand(2) ? waMirror : waCloud; + c->item = itNone; + mirror::build(c); } if(c->item == itFulgurite) { c->item = itNone, c->wall = waSandstone; diff --git a/orbgen.cpp b/orbgen.cpp index d818c97f..c59ddd59 100644 --- a/orbgen.cpp +++ b/orbgen.cpp @@ -369,13 +369,10 @@ ld orbcrossfun(int tr) { bool buildPrizeMirror(cell *c, int freq) { if(inv::on) return false; - if(gp::on) return false; - if(c->type == 7 && !nonbitrunc) return false; if(items[itShard] < 25) return false; if(freq && hrand(freq * 100 / orbprizefun(items[itShard])) >= 100) return false; - c->wall = hrand(2) ? waCloud : waMirror; - return true; + return mirror::build(c); } eLand getPrizeLand(cell *c = cwt.at) {