mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-04 21:26:17 +00:00
dae6b9e3d3
The "pop this menu" option's *text* is still highly variable among all the different menus, which could make it hard to navigate, but at least if you're using the keyboard it's now easy to "go back". Plus, the rogueviz menu incorrectly reported "(v) exit menu" when actually `v` was already in use by an earlier option. This is now fixed.
736 lines
20 KiB
C++
736 lines
20 KiB
C++
// Hyperbolic Rogue -- the conformal/history mode
|
|
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
|
|
|
#include <complex>
|
|
|
|
#if ISMOBWEB
|
|
typedef double precise;
|
|
#else
|
|
typedef long double precise;
|
|
#endif
|
|
|
|
namespace polygonal {
|
|
|
|
typedef complex<ld> cld;
|
|
|
|
int SI = 4;
|
|
ld STAR = 0;
|
|
|
|
int deg = ISMOBWEB ? 2 : 20;
|
|
|
|
precise matrix[MSI][MSI];
|
|
precise ans[MSI];
|
|
|
|
cld coef[MSI];
|
|
ld coefr[MSI], coefi[MSI];
|
|
int maxcoef, coefid;
|
|
|
|
void solve() {
|
|
if(pmodel == mdPolynomial) {
|
|
for(int i=0; i<MSI; i++) coef[i] = cld(coefr[i], coefi[i]);
|
|
return;
|
|
}
|
|
if(pmodel != mdPolygonal) return;
|
|
if(SI < 3) SI = 3;
|
|
for(int i=0; i<MSI; i++) ans[i] = cos(M_PI / SI);
|
|
for(int i=0; i<MSI; i++)
|
|
for(int j=0; j<MSI; j++) {
|
|
precise i0 = (i+0.) / (MSI-1);
|
|
// i0 *= i0;
|
|
// i0 = 1 - i0;
|
|
i0 *= M_PI;
|
|
matrix[i][j] =
|
|
cos(i0 * (j + 1./SI)) * (STAR > 0 ? (1+STAR) : 1)
|
|
- sin(i0 * (j + 1./SI)) * (STAR > 0 ? STAR : STAR/(1+STAR));
|
|
}
|
|
|
|
for(int i=0; i<MSI; i++) {
|
|
precise dby = matrix[i][i];
|
|
for(int k=0; k<MSI; k++) matrix[i][k] /= dby;
|
|
ans[i] /= dby;
|
|
for(int j=i+1; j<MSI; j++) {
|
|
precise sub = matrix[j][i];
|
|
ans[j] -= ans[i] * sub;
|
|
for(int k=0; k<MSI; k++)
|
|
matrix[j][k] -= sub * matrix[i][k];
|
|
}
|
|
}
|
|
for(int i=MSI-1; i>=0; i--) {
|
|
for(int j=0; j<i; j++) {
|
|
precise sub = matrix[j][i];
|
|
ans[j] -= ans[i] * sub;
|
|
for(int k=0; k<MSI; k++)
|
|
matrix[j][k] -= sub * matrix[i][k];
|
|
}
|
|
}
|
|
}
|
|
|
|
pair<ld, ld> compute(ld x, ld y, int prec) {
|
|
if(pmodel == mdPolynomial) {
|
|
cld z(x,y);
|
|
cld res (0,0);
|
|
for(int i=maxcoef; i>=0; i--) { res += coef[i]; if(i) res *= z; }
|
|
return make_pair(real(res), imag(res));
|
|
}
|
|
|
|
cld z(x, y);
|
|
cld res (0,0);
|
|
cld zp = 1; for(int i=0; i<SI; i++) zp *= z;
|
|
|
|
for(int i=prec; i>0; i--) {
|
|
res += ans[i];
|
|
res *= zp;
|
|
}
|
|
res += ans[0]; res *= z;
|
|
return make_pair(real(res), imag(res));
|
|
}
|
|
|
|
pair<ld, ld> compute(ld x, ld y) { return compute(x,y,deg); }
|
|
|
|
void drawBoundary(int color) {
|
|
queuereset(mdDisk, PPR_CIRCLE);
|
|
|
|
for(int r=0; r<=2000; r++) {
|
|
cld z = exp(cld(0, 2*M_PI * r / 2000.0));
|
|
pair<ld,ld> z2 = compute(real(z), imag(z), deg);
|
|
hyperpoint h;
|
|
h[0] = z2.first * vid.radius;
|
|
h[1] = z2.second * vid.radius;
|
|
h[2] = vid.scrdist;
|
|
curvepoint(h);
|
|
}
|
|
|
|
queuecurve(color, 0, PPR_CIRCLE);
|
|
queuereset(pmodel, PPR_CIRCLE);
|
|
}
|
|
|
|
}
|
|
|
|
#if CAP_SDL
|
|
namespace spiral {
|
|
|
|
typedef long double ld;
|
|
typedef complex<long double> cld;
|
|
|
|
int shiftx, shifty, velx, vely;
|
|
|
|
vector<pair<short, short> > quickmap;
|
|
|
|
int CX, CY, SX, SY, Yshift;
|
|
|
|
vector<SDL_Surface*> band;
|
|
SDL_Surface *out;
|
|
|
|
bool displayhelp = true;
|
|
|
|
int& bandpixel(int x, int y) {
|
|
int i = 0;
|
|
while(i < size(band) && x >= band[i]->w)
|
|
x -= band[i]->w, i++;
|
|
return qpixel(band[i], x, y);
|
|
}
|
|
|
|
void precompute() {
|
|
|
|
CX = 0;
|
|
for(int i=0; i<size(band); i++) CX += band[i]->w;
|
|
if(CX == 0) { printf("ERROR: no CX\n"); return; }
|
|
CY = band[0]->h;
|
|
SX = out->w;
|
|
SY = out->h;
|
|
|
|
ld k = -2*M_PI*M_PI / log(2.6180339);
|
|
|
|
// cld mnoznik = cld(0, M_PI) / cld(k, M_PI);
|
|
|
|
cld factor = cld(0, -CY/2/M_PI/M_PI) * cld(k, M_PI);
|
|
|
|
Yshift = CY * k / M_PI;
|
|
|
|
quickmap.clear();
|
|
|
|
double xc = ((SX | 1) - 2) / 2.;
|
|
double yc = ((SY | 1) - 2) / 2.;
|
|
|
|
for(int y=0; y<SY; y++)
|
|
for(int x=0; x<SX; x++) {
|
|
cld z(x-xc, y-yc);
|
|
cld z1 = log(z);
|
|
|
|
z1 = z1 * factor;
|
|
|
|
quickmap.push_back(make_pair(int(real(z1)) % CX, int(imag(z1))));
|
|
}
|
|
}
|
|
|
|
void draw() {
|
|
int c = 0;
|
|
for(int y=0; y<SY; y++) for(int x=0; x<SX; x++) {
|
|
pair<short,short> p = quickmap[c++];
|
|
int cx = p.first + shiftx;
|
|
int cy = p.second + + shifty;
|
|
int d = cy / CY;
|
|
cy -= d * CY; cx -= d * Yshift;
|
|
if(cy<0) cy += CY, cx += Yshift;
|
|
cx %= CX; if(cx<0) cx += CX;
|
|
qpixel(out, x, y) = bandpixel(cx, cy);
|
|
}
|
|
}
|
|
|
|
void loop(vector<SDL_Surface*> _band) {
|
|
|
|
bool saveGL = vid.usingGL;
|
|
if(saveGL) { vid.usingGL = false; setvideomode(); }
|
|
|
|
band = _band;
|
|
out = s;
|
|
precompute();
|
|
if(CX == 0) return;
|
|
shiftx = shifty = 0;
|
|
velx=1; vely=1;
|
|
bool dosave = false;
|
|
while(true) {
|
|
|
|
time_t timer;
|
|
timer = time(NULL);
|
|
char buf[128];
|
|
strftime(buf, 128, "spiral-%y%m%d-%H%M%S" IMAGEEXT, localtime(&timer));
|
|
|
|
SDL_LockSurface(s);
|
|
draw();
|
|
if(dosave) { dosave = false; IMAGESAVE(s, buf); }
|
|
SDL_UnlockSurface(s);
|
|
if(displayhelp) {
|
|
displaystr(SX/2, vid.fsize*2, 0, vid.fsize, "arrows = navigate, ESC = return, h = hide help", forecolor, 8);
|
|
displaystr(SX/2, SY - vid.fsize*2, 0, vid.fsize, XLAT("s = save to " IMAGEEXT, buf), forecolor, 8);
|
|
}
|
|
SDL_UpdateRect(s, 0, 0, 0, 0);
|
|
shiftx += velx; shifty += vely;
|
|
|
|
SDL_Event event;
|
|
while(SDL_PollEvent(&event)) switch (event.type) {
|
|
case SDL_QUIT: case SDL_MOUSEBUTTONDOWN:
|
|
goto breakloop;
|
|
|
|
case SDL_KEYDOWN: {
|
|
int key = event.key.keysym.sym;
|
|
// int uni = event.key.keysym.unicode;
|
|
if(key == SDLK_RIGHT) velx++;
|
|
if(key == SDLK_LEFT) velx--;
|
|
if(key == SDLK_UP) vely++;
|
|
if(key == SDLK_DOWN) vely--;
|
|
if(key == SDLK_ESCAPE) goto breakloop;
|
|
if(key == 'h') displayhelp = !displayhelp;
|
|
if(key == 's') dosave = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
breakloop:
|
|
quickmap.clear();
|
|
if(saveGL) { vid.usingGL = true; setvideomode(); }
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
bool isbad(ld z) { return !isfinite(z) || fabs(z) > 1e6; }
|
|
|
|
namespace conformal {
|
|
|
|
void handleKeyC(int sym, int uni);
|
|
|
|
int lastprogress;
|
|
|
|
void progress_screen() {
|
|
gamescreen(0);
|
|
mouseovers = "";
|
|
}
|
|
|
|
void progress(string str) {
|
|
#if CAP_SDL
|
|
int tick = SDL_GetTicks();
|
|
if(tick > lastprogress + 250) {
|
|
lastprogress = tick;
|
|
msgs.clear();
|
|
addMessage(str);
|
|
drawscreen();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool on;
|
|
vector<shmup::monster*> v;
|
|
int llv;
|
|
double phase;
|
|
|
|
vector<pair<cell*, eMonster> > killhistory;
|
|
vector<pair<cell*, eItem> > findhistory;
|
|
vector<cell*> movehistory;
|
|
|
|
bool includeHistory;
|
|
ld lvspeed = 1;
|
|
int bandhalf = 200;
|
|
int bandsegment = 16000;
|
|
int rotation = 0;
|
|
bool autoband = false;
|
|
bool autobandhistory = false;
|
|
bool dospiral = true;
|
|
|
|
void clear() {
|
|
on = false;
|
|
int N = size(v);
|
|
for(int i=0; i<N; i++) delete v[i];
|
|
v.resize(0);
|
|
}
|
|
|
|
void create() {
|
|
if(celldist(cwt.c) <= 7) {
|
|
addMessage("Must go a distance from the starting point");
|
|
return;
|
|
}
|
|
|
|
on = true;
|
|
cell *c = cwt.c;
|
|
|
|
for(int q=0; q<5; q++) {
|
|
for(int i=0; i<c->type; i++)
|
|
if(celldist(c->mov[i]) > celldist(c)) {
|
|
c = c->mov[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
while(true) {
|
|
shmup::monster *m = new shmup::monster;
|
|
m->at = Id;
|
|
m->base = c;
|
|
v.push_back(m);
|
|
if(c == currentmap->gamestart()) break;
|
|
for(int i=0; i<c->type; i++)
|
|
if(celldist(c->mov[i]) < celldist(c)) {
|
|
c = c->mov[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
reverse(v.begin(), v.end());
|
|
|
|
int Q = size(v)-1;
|
|
|
|
for(int i=0; i<1000; i++) {
|
|
progress(XLAT("Preparing the line (%1/1000)...", its(i+1)));
|
|
|
|
/*for(int j=1; j<Q; j++) {
|
|
hyperpoint cur = v[j]->at * C0;
|
|
printf("%4d/%3d. %p [%3d] %Lf %Lf %Lf\n", i, j, v[j]->base, celldist(v[j]->base), cur[0], cur[1], cur[2]);
|
|
} */
|
|
|
|
for(int j=1; j<Q; j++) if((j^i)&1) {
|
|
|
|
virtualRebase(v[j], false);
|
|
|
|
hyperpoint prev = shmup::calc_relative_matrix(v[j-1]->base, v[j]->base->master) *
|
|
v[j-1]->at * C0;
|
|
|
|
hyperpoint next = shmup::calc_relative_matrix(v[j+1]->base, v[j]->base->master) *
|
|
v[j+1]->at * C0;
|
|
|
|
hyperpoint hmid = mid(prev, next);
|
|
|
|
v[j]->at = rgpushxto0(hmid);
|
|
|
|
v[j]->at = v[j]->at * rspintox(inverse(v[j]->at) * next);
|
|
fixmatrix(v[j]->at);
|
|
}
|
|
}
|
|
llv = ticks;
|
|
phase = 0;
|
|
}
|
|
|
|
void movetophase() {
|
|
|
|
int ph = int(phase);
|
|
int siz = size(v);
|
|
if(ph<0 || ph >= siz-1) return;
|
|
|
|
viewctr.h = v[ph]->base->master;
|
|
viewctr.spin = 0;
|
|
|
|
View = inverse(v[ph]->at);
|
|
|
|
int j = ph;
|
|
|
|
hyperpoint now = v[j]->at * C0;
|
|
|
|
hyperpoint next = shmup::calc_relative_matrix(v[j+1]->base, v[j]->base->master) *
|
|
v[j+1]->at * C0;
|
|
|
|
View = spin(M_PI/2 * rotation) * xpush(-(phase-ph) * hdist(now, next)) * View;
|
|
playermoved = false;
|
|
}
|
|
|
|
void apply() {
|
|
int t = ticks;
|
|
phase += (t-llv) * lvspeed / 400.;
|
|
llv = t;
|
|
|
|
int siz = size(v);
|
|
|
|
while(phase < 1) phase += siz - 2;
|
|
while(phase >= siz-1) phase -= siz - 2;
|
|
|
|
movetophase();
|
|
}
|
|
|
|
int measureLength() {
|
|
int rad = vid.radius;
|
|
vid.radius = bandhalf;
|
|
|
|
int tpixels = 0;
|
|
int siz = size(v);
|
|
|
|
for(int j=1; j<siz-1; j++) {
|
|
hyperpoint next =
|
|
inverse(v[j]->at) *
|
|
shmup::calc_relative_matrix(v[j+1]->base, v[j]->base->master) *
|
|
v[j+1]->at * C0;
|
|
|
|
hyperpoint nextscr;
|
|
applymodel(next, nextscr);
|
|
tpixels += nextscr[0] * vid.radius;
|
|
}
|
|
|
|
vid.radius = rad;
|
|
return tpixels;
|
|
}
|
|
|
|
void restore();
|
|
void restoreBack();
|
|
|
|
#if CAP_SDL
|
|
void createImage(bool dospiral) {
|
|
int segid = 1;
|
|
inHighQual = true;
|
|
if(includeHistory) restore();
|
|
|
|
int bandfull = 2*bandhalf;
|
|
int len = measureLength();
|
|
|
|
time_t timer;
|
|
timer = time(NULL);
|
|
char timebuf[128];
|
|
strftime(timebuf, 128, "%y%m%d-%H%M%S", localtime(&timer));
|
|
|
|
rotation = 0;
|
|
|
|
SDL_Surface *sav = s;
|
|
|
|
SDL_Surface *bbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,bandfull,bandfull,32,0,0,0,0);
|
|
s = bbuf;
|
|
int ssr = sightrange; sightrange = 10; int sch = cheater; cheater = 0;
|
|
videopar vid2 = vid; vid.xres = vid.yres = bandfull; vid.scale = 1;
|
|
calcparam();
|
|
vid.radius = bandhalf;
|
|
|
|
int xpos = 0;
|
|
|
|
vector<SDL_Surface*> bands;
|
|
|
|
SDL_Surface *band = SDL_CreateRGBSurface(SDL_SWSURFACE, min(len, bandsegment), bandfull,32,0,0,0,0);
|
|
|
|
if(!band) {
|
|
addMessage("Could not create an image of that size.");
|
|
}
|
|
else {
|
|
|
|
int siz = size(v);
|
|
for(int j=1; j<siz-1; j++) {
|
|
SDL_Surface *buffer = s;
|
|
s = sav;
|
|
|
|
pushScreen(progress_screen);
|
|
|
|
char buf[128];
|
|
sprintf(buf, "#%03d", segid);
|
|
|
|
progress(s0 + buf + " ("+its(j)+"/"+its(siz-2)+")");
|
|
calcparam();
|
|
vid.radius = bandhalf;
|
|
|
|
s = buffer;
|
|
viewctr.h = v[j]->base->master;
|
|
viewctr.spin = 0;
|
|
View = inverse(v[j]->at);
|
|
|
|
SDL_FillRect(s, NULL, 0);
|
|
bool ugl = vid.usingGL;
|
|
vid.usingGL = false;
|
|
drawfullmap();
|
|
vid.usingGL = ugl;
|
|
|
|
hyperpoint next =
|
|
inverse(v[j]->at) *
|
|
shmup::calc_relative_matrix(v[j+1]->base, v[j]->base->master) *
|
|
v[j+1]->at * C0;
|
|
|
|
int x, y, shift;
|
|
getcoord0(next, x, y, shift);
|
|
|
|
int bwidth = x-bandhalf;
|
|
|
|
popScreen();
|
|
|
|
drawsegment:
|
|
|
|
for(int cy=0; cy<bandfull; cy++) for(int cx=0; cx<bwidth; cx++)
|
|
qpixel(band, xpos+cx, cy) = qpixel(s, bandhalf+cx, cy);
|
|
|
|
if(xpos+bwidth > bandsegment) {
|
|
char buf[128];
|
|
sprintf(buf, "bandmodel-%s-%03d" IMAGEEXT, timebuf, segid++);
|
|
|
|
IMAGESAVE(band, buf);
|
|
|
|
if(dospiral)
|
|
bands.push_back(band);
|
|
else
|
|
SDL_FreeSurface(band);
|
|
|
|
len -= bandsegment; xpos -= bandsegment;
|
|
band = SDL_CreateRGBSurface(SDL_SWSURFACE, min(len, bandsegment), bandfull,32,0,0,0,0);
|
|
goto drawsegment;
|
|
}
|
|
xpos += bwidth;
|
|
}
|
|
}
|
|
|
|
char buf[128];
|
|
sprintf(buf, "bandmodel-%s-%03d" IMAGEEXT, timebuf, segid++);
|
|
IMAGESAVE(band, buf);
|
|
addMessage(XLAT("Saved the band image as: ") + buf);
|
|
|
|
if(dospiral)
|
|
bands.push_back(band);
|
|
else
|
|
SDL_FreeSurface(band);
|
|
|
|
SDL_FreeSurface(sav);
|
|
s = sav; vid = vid2; sightrange = ssr; cheater = sch;
|
|
if(includeHistory) restoreBack();
|
|
|
|
if(dospiral) {
|
|
spiral::loop(bands);
|
|
for(int i=0; i<size(bands); i++) SDL_FreeSurface(bands[i]);
|
|
}
|
|
|
|
inHighQual = false;
|
|
}
|
|
#endif
|
|
|
|
const char* directions[MODELCOUNT][4] = {
|
|
{ "right", "up", "left", "down" },
|
|
{ "counterclockwise", "zoom out", "clockwise", "zoom in" },
|
|
{ "left to right", "spin down", "right to left", "spin up" },
|
|
{ "right", "up", "left", "down" },
|
|
{ "right", "up", "left", "down" },
|
|
{ "right", "up", "left", "down" },
|
|
{ "right", "up", "left", "down" },
|
|
{ "right", "up", "left", "down" },
|
|
{ "right", "up", "left", "down" }
|
|
};
|
|
|
|
const char *modelnames[MODELCOUNT] = {
|
|
"disk", "half-plane", "band", "polygonal", "polynomial",
|
|
"azimuthal equidistant", "azimuthal equi-area",
|
|
"ball model", "hyperboloid"
|
|
};
|
|
|
|
void show() {
|
|
cmode = sm::SIDE;
|
|
gamescreen(0);
|
|
|
|
dialog::init(XLAT("conformal/history mode"));
|
|
|
|
dialog::addBoolItem(XLAT("include history"), (includeHistory), 'i');
|
|
|
|
bool notconformal = (pmodel >= 5 && pmodel <= 6) || abs(vid.alpha-1) > 1e-3;
|
|
|
|
dialog::addSelItem(notconformal ? XLAT("model used (not conformal!)") : XLAT("model used"), XLAT(modelnames[pmodel]), 'm');
|
|
dialog::addSelItem(XLAT("rotation"), directions[pmodel][rotation&3], 'r');
|
|
|
|
if(pmodel == 4) {
|
|
dialog::addSelItem(XLAT("coefficient"),
|
|
fts4(polygonal::coefr[polygonal::coefid]), 'x');
|
|
dialog::addSelItem(XLAT("coefficient (imaginary)"),
|
|
fts4(polygonal::coefi[polygonal::coefid]), 'y');
|
|
dialog::addSelItem(XLAT("which coefficient"), its(polygonal::coefid), 'n');
|
|
}
|
|
|
|
if(pmodel == 3) {
|
|
dialog::addSelItem(XLAT("polygon sides"), its(polygonal::SI), 'x');
|
|
dialog::addSelItem(XLAT("star factor"), fts(polygonal::STAR), 'y');
|
|
dialog::addSelItem(XLAT("degree of the approximation"), its(polygonal::deg), 'n');
|
|
}
|
|
|
|
dialog::addBoolItem(XLAT("prepare the line animation"), (on), 'e');
|
|
if(on) dialog::addSelItem(XLAT("animation speed"), fts(lvspeed), 'a');
|
|
|
|
#if CAP_SDL
|
|
dialog::addBoolItem(XLAT("render bands automatically"), (autoband), 'o');
|
|
if(autoband)
|
|
dialog::addBoolItem(XLAT("include history when auto-rendering"), (autobandhistory), 'j');
|
|
|
|
bool renderable = on && pmodel == 2;
|
|
if(renderable || autoband) {
|
|
dialog::addSelItem(XLAT("band width"), "2*"+its(bandhalf), 'd');
|
|
dialog::addSelItem(XLAT("length of a segment"), its(bandsegment), 's');
|
|
dialog::addBoolItem(XLAT("spiral on rendering"), (dospiral), 'g');
|
|
if(renderable)
|
|
dialog::addItem(XLAT("render now (length: %1)", its(measureLength())), 'f');
|
|
}
|
|
#endif
|
|
|
|
dialog::addItem(XLAT("exit this menu"), ' ');
|
|
dialog::display();
|
|
mouseovers = XLAT("see http://www.roguetemple.com/z/hyper/conformal.php");
|
|
keyhandler = handleKeyC;
|
|
}
|
|
|
|
void handleKeyC(int sym, int uni) {
|
|
dialog::handleNavigation(sym, uni);
|
|
|
|
if(uni == 'e') {
|
|
if(on) clear();
|
|
else {
|
|
if(canmove && !cheater) {
|
|
addMessage("Enable cheat mode or GAME OVER to use this");
|
|
return;
|
|
}
|
|
if(canmove && cheater) cheater++;
|
|
create();
|
|
}
|
|
}
|
|
else if(uni == 'o')
|
|
autoband = !autoband;
|
|
else if(uni == 'm' || uni == 'M') {
|
|
|
|
switchagain: {
|
|
pmodel = eModel((pmodel + (shiftmul > 0 ? 1 : -1) + MODELCOUNT) % MODELCOUNT);
|
|
if(sphere)
|
|
if(pmodel == mdHalfplane || pmodel == mdBand || pmodel == mdEquidistant || pmodel == mdEquiarea)
|
|
goto switchagain;
|
|
}
|
|
polygonal::solve();
|
|
/* if(pmodel && vid.usingGL) {
|
|
addMessage(XLAT("openGL mode disabled"));
|
|
vid.usingGL = false;
|
|
setvideomode();
|
|
} */
|
|
}
|
|
else if(sym == 'x' && pmodel == mdPolygonal)
|
|
dialog::editNumber(polygonal::SI, 3, 10, 1, 4, XLAT("polygon sides"), "");
|
|
else if(sym == 'y' && pmodel == mdPolygonal)
|
|
dialog::editNumber(polygonal::STAR, -1, 1, .1, 0, XLAT("star factor"), "");
|
|
else if(sym == 'n' && pmodel == mdPolygonal)
|
|
dialog::editNumber(polygonal::deg, 2, polygonal::MSI-1, 1, 2, XLAT("degree of the approximation"), "");
|
|
else if(sym == 'x' && pmodel == mdPolynomial) {
|
|
polygonal::maxcoef = max(polygonal::maxcoef, polygonal::coefid);
|
|
int ci = polygonal::coefid + 1;
|
|
dialog::editNumber(polygonal::coefr[polygonal::coefid], -10, 10, .01/ci/ci, 0, XLAT("coefficient"), "");
|
|
}
|
|
else if(sym == 'y' && pmodel == mdPolynomial) {
|
|
polygonal::maxcoef = max(polygonal::maxcoef, polygonal::coefid);
|
|
int ci = polygonal::coefid + 1;
|
|
dialog::editNumber(polygonal::coefi[polygonal::coefid], -10, 10, .01/ci/ci, 0, XLAT("coefficient (imaginary)"), "");
|
|
}
|
|
else if(sym == 'n' && pmodel == mdPolynomial)
|
|
dialog::editNumber(polygonal::coefid, 0, polygonal::MSI-1, 1, 0, XLAT("which coefficient"), "");
|
|
else if(sym == 'r') rotation += (shiftmul > 0 ? 1:3);
|
|
else if(sym == 'a')
|
|
dialog::editNumber(lvspeed, -5, 5, .1, 1, XLAT("animation speed"), "");
|
|
else if(sym == 'd')
|
|
dialog::editNumber(bandhalf, 5, 1000, 5, 200, XLAT("band width"), "");
|
|
else if(sym == 's')
|
|
dialog::editNumber(bandsegment, 500, 32000, 500, 16000, XLAT("band segment"), "");
|
|
else if(sym == 'g') { dospiral = !dospiral; }
|
|
#if CAP_SDL
|
|
else if(uni == 'f' && pmodel == mdBand && on) createImage(dospiral);
|
|
#endif
|
|
else if(sym == 'i') {
|
|
if(canmove && !cheater) {
|
|
addMessage("Enable cheat mode or GAME OVER to use this");
|
|
return;
|
|
}
|
|
if(canmove && cheater) cheater++;
|
|
includeHistory = !includeHistory;
|
|
}
|
|
else if(sym == 'j') {
|
|
autobandhistory = !autobandhistory;
|
|
}
|
|
else if(doexiton(sym, uni)) popScreen();
|
|
}
|
|
|
|
void restore() {
|
|
sval++;
|
|
for(int i=0; i<size(movehistory); i++)
|
|
movehistory[i]->aitmp = sval;
|
|
sval++;
|
|
int sk = size(killhistory);
|
|
for(int i=0; i<sk; i++) {
|
|
eMonster m = killhistory[i].second;
|
|
killhistory[i].second = killhistory[i].first->monst;
|
|
killhistory[i].first->monst = m;
|
|
killhistory[i].first->aitmp = sval;
|
|
}
|
|
int si = size(findhistory);
|
|
for(int i=0; i<si; i++) {
|
|
eItem m = findhistory[i].second;
|
|
findhistory[i].second = findhistory[i].first->item;
|
|
findhistory[i].first->item = m;
|
|
findhistory[i].first->aitmp = sval;
|
|
}
|
|
}
|
|
|
|
void restoreBack() {
|
|
int sk = size(killhistory);
|
|
for(int i=sk-1; i>=0; i--) {
|
|
eMonster m = killhistory[i].second;
|
|
killhistory[i].second = killhistory[i].first->monst;
|
|
killhistory[i].first->monst = m;
|
|
}
|
|
int si = size(findhistory);
|
|
for(int i=si-1; i>=0; i--) {
|
|
eItem m = findhistory[i].second;
|
|
findhistory[i].second = findhistory[i].first->item;
|
|
findhistory[i].first->item = m;
|
|
}
|
|
}
|
|
|
|
void renderAutoband() {
|
|
#if CAP_SDL
|
|
if(!cwt.c || celldist(cwt.c) <= 7) return;
|
|
if(!autoband) return;
|
|
eModel spm = pmodel;
|
|
bool ih = includeHistory;
|
|
includeHistory = autobandhistory;
|
|
pmodel = mdBand;
|
|
create();
|
|
createImage(dospiral);
|
|
clear();
|
|
pmodel = spm;
|
|
includeHistory = ih;
|
|
#endif
|
|
}
|
|
|
|
auto hooks = addHook(clearmemory, 0, [] () {
|
|
conformal::renderAutoband();
|
|
conformal::on = false;
|
|
conformal::killhistory.clear();
|
|
conformal::findhistory.clear();
|
|
conformal::movehistory.clear();
|
|
conformal::includeHistory = false;
|
|
});
|
|
|
|
}
|