1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-06-17 22:04:07 +00:00

update to 9.4l

This commit is contained in:
Zeno Rogue 2017-06-09 03:41:33 +02:00
parent 627658d00d
commit 4addcaa71f
15 changed files with 383 additions and 156 deletions

106
cell.cpp
View File

@ -276,6 +276,76 @@ heptagon *getDodecahedron(int i) {
cell*& euclideanAtCreate(eucoord x, eucoord y); cell*& euclideanAtCreate(eucoord x, eucoord y);
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 <qty>,<dx>,<dy>
int qty = 127*3, dx = -1, dy = 11*2;
}
int decodeId(heptagon* h);
heptagon* encodeId(int id);
struct hrmap_torus : hrmap {
vector<cell*> all;
vector<int> dists;
virtual vector<cell*>& allcells() { return all; }
cell *gamestart() {
return all[0];
}
hrmap_torus() {
using namespace torusconfig;
all.resize(qty);
for(int i=0; i<qty; i++) {
all[i] = newCell(6, NULL);
all[i]->master = encodeId(i);
}
dx %= qty;
dy %= qty;
for(int i=0; i<qty; i++) {
all[i]->mov[0] = all[(i+dx+2*qty)%qty];
all[i]->mov[1] = all[(i+dy+2*qty)%qty];
all[i]->mov[2] = all[(i+dy-dx+2*qty)%qty];
all[i]->mov[3] = all[(i-dx+2*qty)%qty];
all[i]->mov[4] = all[(i-dy+2*qty)%qty];
all[i]->mov[5] = all[(i-dy+dx+2*qty)%qty];
for(int j=0; j<6; j++)
tsetspin(all[i]->spintable, j, (j+3) % 6);
}
celllister cl(gamestart(), 100, 100000000, NULL);
dists.resize(qty);
for(int i=0; i<size(cl.lst); i++)
dists[decodeId(cl.lst[i]->master)] = cl.dists[i];
}
~hrmap_torus() {
for(cell *c: all) delete c;
}
};
int toridMod(int id) {
using namespace torusconfig;
id %= qty; if(id < 0) id += qty;
return id;
}
hrmap_torus *torusmap() {
return dynamic_cast<hrmap_torus*> (currentmap);
}
cell *getTorusId(int id) {
hrmap_torus *cur = torusmap();
if(!cur) return NULL;
return cur->all[toridMod(id)];
}
struct hrmap_euclidean : hrmap { struct hrmap_euclidean : hrmap {
cell *gamestart() { cell *gamestart() {
@ -322,19 +392,33 @@ struct hrmap_euclidean : hrmap {
union heptacoder { union heptacoder {
heptagon *h; heptagon *h;
struct { eucoord x; eucoord y; } c; struct { eucoord x; eucoord y; } c;
int id;
}; };
void decodeMaster(heptagon *h, eucoord& x, eucoord& y) { void decodeMaster(heptagon *h, eucoord& x, eucoord& y) {
if(torus) { printf("decodeMaster on torus\n"); exit(1); }
heptacoder u; heptacoder u;
u.h = h; x = u.c.x; y = u.c.y; u.h = h; x = u.c.x; y = u.c.y;
} }
int decodeId(heptagon* h) {
heptacoder u;
u.h = h; return u.id;
}
heptagon* encodeMaster(eucoord x, eucoord y) { heptagon* encodeMaster(eucoord x, eucoord y) {
if(torus) { printf("encodeMaster on torus\n"); exit(1); }
heptacoder u; heptacoder u;
u.c.x = x; u.c.y = y; u.c.x = x; u.c.y = y;
return u.h; return u.h;
} }
heptagon* encodeId(int id) {
heptacoder u;
u.id = id;
return u.h;
}
// --- quotient geometry --- // --- quotient geometry ---
namespace quotientspace { namespace quotientspace {
@ -591,6 +675,7 @@ void eumerge(cell* c1, cell *c2, int s1, int s2) {
// map<pair<eucoord, eucoord>, cell*> euclidean; // map<pair<eucoord, eucoord>, cell*> euclidean;
cell*& euclideanAt(eucoord x, eucoord y) { cell*& euclideanAt(eucoord x, eucoord y) {
if(torus) { printf("euclideanAt called\n"); exit(1); }
hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap); hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap);
return euc->at(x, y); return euc->at(x, y);
} }
@ -615,7 +700,8 @@ cell*& euclideanAtCreate(eucoord x, eucoord y) {
void initcells() { void initcells() {
DEBB(DF_INIT, (debugfile,"initcells\n")); DEBB(DF_INIT, (debugfile,"initcells\n"));
if(euclid) currentmap = new hrmap_euclidean; if(torus) currentmap = new hrmap_torus;
else if(euclid) currentmap = new hrmap_euclidean;
else if(sphere) currentmap = new hrmap_spherical; else if(sphere) currentmap = new hrmap_spherical;
else if(quotient) currentmap = new quotientspace::hrmap_quotient; else if(quotient) currentmap = new quotientspace::hrmap_quotient;
else currentmap = new hrmap_hyperbolic; else currentmap = new hrmap_hyperbolic;
@ -705,6 +791,7 @@ void verifycells(heptagon *at) {
} }
int eupattern(cell *c) { int eupattern(cell *c) {
if(torus) return decodeId(c->master) % 3;
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
short z = (short(y+2*x))%3; short z = (short(y+2*x))%3;
@ -760,6 +847,8 @@ int compdist(int dx[3]) {
int celldist(cell *c) { int celldist(cell *c) {
if(euclid) { if(euclid) {
if(torus)
return torusmap()->dists[decodeId(c->master)];
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
return eudist(x, y); return eudist(x, y);
@ -782,6 +871,7 @@ int euclidAlt(short x, short y);
int celldistAlt(cell *c) { int celldistAlt(cell *c) {
if(euclid) { if(euclid) {
if(torus) return celldist(c);
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
return euclidAlt(x, y); return euclidAlt(x, y);
@ -817,6 +907,10 @@ unsigned bitmajority(unsigned a, unsigned b, unsigned c) {
int eufifty(cell *c) { int eufifty(cell *c) {
eucoord x, y; eucoord x, y;
if(torus) {
if(c->land == laWildWest) return decodeId(c->master) % 37;
else return decodeId(c->master) % 27;
}
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
int ix = short(x) + 99999 + short(y); int ix = short(x) + 99999 + short(y);
int iy = short(y) + 99999; int iy = short(y) + 99999;
@ -1196,9 +1290,16 @@ cdata *getHeptagonCdata(heptagon *h) {
} }
cdata *getEuclidCdata(heptagon *h) { cdata *getEuclidCdata(heptagon *h) {
if(torus) {
static cdata xx;
return &xx;
}
eucoord x, y; eucoord x, y;
hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap); hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap);
if(euc->eucdata.count(h)) return &(euc->eucdata[h]); if(euc->eucdata.count(h)) return &(euc->eucdata[h]);
decodeMaster(h, x, y); decodeMaster(h, x, y);
if(x == 0 && y == 0) { if(x == 0 && y == 0) {
@ -1314,6 +1415,8 @@ int celldistance(cell *c1, cell *c2) {
int d = 0; int d = 0;
if(euclid) { if(euclid) {
if(torus)
return torusmap()->dists[toridMod(decodeId(c1->master)-decodeId(c2->master))];
eucoord x1, y1, x2, y2; eucoord x1, y1, x2, y2;
decodeMaster(c1->master, x1, y1); decodeMaster(c1->master, x1, y1);
decodeMaster(c2->master, x2, y2); decodeMaster(c2->master, x2, y2);
@ -1404,6 +1507,7 @@ void clearMemory() {
} }
int getHemisphere(cell *c, int which) { int getHemisphere(cell *c, int which) {
if(torus) return 0;
if(c->type != 6) { if(c->type != 6) {
int id = c->master->fiftyval; int id = c->master->fiftyval;
int hemitable[3][12] = { int hemitable[3][12] = {

View File

@ -1415,7 +1415,7 @@ struct landtype {
const char *help; const char *help;
}; };
landtype linf[landtypes] = { const landtype linf[landtypes] = {
{ 0xFF00FF, "???" , ""}, { 0xFF00FF, "???" , ""},
{ 0xC06000, "Great Wall" , ""}, { 0xC06000, "Great Wall" , ""},
{ 0xFF0000, "Crossroads" , { 0xFF0000, "Crossroads" ,

View File

@ -11,6 +11,7 @@ namespace whirlwind {
int fzebra3(cell *c) { int fzebra3(cell *c) {
if(euclid) { if(euclid) {
if(torus) return 0;
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
return 1+((((signed short)(y)+int(50000))/3)%3); return 1+((((signed short)(y)+int(50000))/3)%3);
@ -543,9 +544,9 @@ namespace princess {
int dist(cell *c) { int dist(cell *c) {
if(c->land != laPalace) return OUT_OF_PALACE; if(c->land != laPalace) return OUT_OF_PALACE;
else if(quotient || sphere || torus) return OUT_OF_PRISON;
else if(euclid) return celldistAlt(c); else if(euclid) return celldistAlt(c);
else if(!c->master->alt) return OUT_OF_PRISON; else if(!c->master->alt) return OUT_OF_PRISON;
else if(quotient || sphere) return OUT_OF_PRISON;
else return celldistAlt(c); else return celldistAlt(c);
} }
@ -778,6 +779,7 @@ namespace clearing {
if(buggyplant) return; if(buggyplant) return;
if(euclid) { if(euclid) {
if(torus) return;
if(pseudohept(c)) return; if(pseudohept(c)) return;
c->monst = moMutant; c->monst = moMutant;
@ -1101,7 +1103,7 @@ namespace mirror {
} }
void destroyStray() { void destroyStray() {
if(geometry == gQuotient2) return; if(doall) return;
for(int i=0; i<size(mirrors2); i++) { for(int i=0; i<size(mirrors2); i++) {
cell *c = mirrors2[i]; cell *c = mirrors2[i];
if(c->cpdist > 7 && isMimic(c)) { if(c->cpdist > 7 && isMimic(c)) {
@ -1402,12 +1404,13 @@ namespace hive {
if(!q) { if(c->land == laHive) c->landparam += 3; continue; } if(!q) { if(c->land == laHive) c->landparam += 3; continue; }
int d = gmoves[hrand(q)]; int d = gmoves[hrand(q)];
cell *c2 = c->mov[d]; cell *c2 = c->mov[d];
if(c2->monst) { if(c2->monst || isPlayerOn(c2)) {
eMonster killed = c2->monst; eMonster killed = c2->monst;
if(isPlayerOn(c2)) killed = moPlayer;
if(isBug(killed)) battlecount++; if(isBug(killed)) battlecount++;
else if(!fightspam(c2)) else if(killed != moPlayer && !fightspam(c2))
addMessage(XLAT("%The1 fights with %the2!", c->monst, c2->monst)); addMessage(XLAT("%The1 fights with %the2!", c->monst, killed));
attackMonster(c2, AF_ORSTUN, c->monst); attackMonster(c2, AF_ORSTUN | AF_GETPLAYER, c->monst);
// killMonster(c); // killMonster(c);
if(isBug(killed)) { if(isBug(killed)) {
c2->monst = moDeadBug, deadbug.push_back(c2); c2->monst = moDeadBug, deadbug.push_back(c2);
@ -1613,7 +1616,7 @@ namespace heat {
double xrate = (c->land == laCocytus && shmup::on) ? 1/3. : 1; double xrate = (c->land == laCocytus && shmup::on) ? 1/3. : 1;
if(purehepta) xrate *= 1.7; if(purehepta) xrate *= 1.7;
if(!shmup::on) xrate /= FIX94; if(!shmup::on) xrate /= FIX94;
if(c->cpdist > 7 && !quotient) break; if(c->cpdist > 7 && !doall) break;
if(hasTimeout(c)) { if(hasTimeout(c)) {
if(tick) useup(c); if(tick) useup(c);
@ -1623,24 +1626,36 @@ namespace heat {
if(isFire(c) && tick) { if(isFire(c) && tick) {
if(c->wall != waPartialFire) for(int i=0; i<c->type; i++) { if(c->wall != waPartialFire) for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i]; cell *c2 = c->mov[i];
if(c2 && c2->wall == waNone && c2->land == laRose && c->wparam >= 10) if(!c2) continue;
if(c2->wall == waNone && c2->land == laRose && c->wparam >= 10)
rosefires.push_back(make_pair(c2, c->wparam)); rosefires.push_back(make_pair(c2, c->wparam));
if(c2 && c2->wall == waFire && c2->land == laRose && c->wparam >= 10 && c2->wparam < c->wparam/2) if(c2->wall == waFire && c2->land == laRose && c->wparam >= 10 && c2->wparam < c->wparam/2)
rosefires.push_back(make_pair(c2, c->wparam)); rosefires.push_back(make_pair(c2, c->wparam));
if(c2 && c2->wall == waVinePlant) if(againstWind(c, c2) && c->wall != waEternalFire && c->wparam >= 10) {
if(isFire(c2)) {
if(c2->wparam < c->wparam/2) {
rosefires.push_back(make_pair(c2, c->wparam));
}
}
else {
rosefires.push_back(make_pair(c2, c->wparam));
useup(c);
}
}
if(c2->wall == waVinePlant)
vinefires.push_back(c2); vinefires.push_back(c2);
if(c2 && c2->wall == waRose) if(c2->wall == waRose)
vinefires.push_back(c2); vinefires.push_back(c2);
if(c2 && c2->wall == waSaloon) if(c2->wall == waSaloon)
vinefires.push_back(c2); vinefires.push_back(c2);
if(c2 && c2->wall == waSmallTree && c2->land != laDryForest) if(c2->wall == waSmallTree && c2->land != laDryForest)
vinefires.push_back(c2); vinefires.push_back(c2);
if(c2 && (c2->wall == waWeakBranch || c2->wall == waCanopy || c2->wall == waTrunk || c2->wall == waSolidBranch || if((c2->wall == waWeakBranch || c2->wall == waCanopy || c2->wall == waTrunk || c2->wall == waSolidBranch ||
c2->wall == waBigBush || c2->wall == waSmallBush)) c2->wall == waBigBush || c2->wall == waSmallBush))
vinefires.push_back(c2); vinefires.push_back(c2);
if(c2 && c2->wall == waBonfireOff) activateActiv(c2, false); if(c2->wall == waBonfireOff) activateActiv(c2, false);
// both halfvines have to be near fire at once // both halfvines have to be near fire at once
if(c2 && cellHalfvine(c2) && c->mov[(i+1)%c->type]->wall == c2->wall) if(cellHalfvine(c2) && c->mov[(i+1)%c->type]->wall == c2->wall)
vinefires.push_back(c2); vinefires.push_back(c2);
} }
@ -1704,7 +1719,7 @@ namespace heat {
hmods[i] = hmod; hmods[i] = hmod;
} }
if((readd || HEAT(c)) && !quotient) if((readd || HEAT(c)) && !doall)
offscreen.push_back(c); offscreen.push_back(c);
} }
@ -1752,7 +1767,7 @@ namespace heat {
cell* c = rosefires[i].first; cell* c = rosefires[i].first;
int qty = rosefires[i].second; int qty = rosefires[i].second;
qty /= 2; qty /= 2;
if(c->wall == waNone && c->land == laRose) // if(c->wall == waNone && c->land == laRose)
makeflame(c, qty, false); makeflame(c, qty, false);
if(c->wparam < qty) c->wparam = qty; if(c->wparam < qty) c->wparam = qty;
} }
@ -1763,21 +1778,30 @@ namespace heat {
void dryforest() { void dryforest() {
vector<cell*>& allcells = currentmap->allcells(); vector<cell*>& allcells = currentmap->allcells();
int dcs = size(allcells); int dcs = size(allcells);
for(int i=0; i<dcs; i++) { for(int i=0; i<dcs; i++) {
cell *c = allcells[i]; cell *c = allcells[i];
if(!quotient && c->cpdist > 8) break; if(!doall && c->cpdist > 8) break;
if(c->land != laDryForest) continue; if(c->land != laDryForest) continue;
for(int j=0; j<c->type; j++) if(c->mov[j]) { forCellEx(c2, c) {
if(isFire(c->mov[j])) c->landparam++; if(isFire(c2)) {
if(!againstWind(c, c2)) c->landparam++;
if(againstWind(c2, c)) c->landparam++;
} }
}
}
for(int i=0; i<dcs; i++) {
cell *c = allcells[i];
if(c->land != laDryForest) continue;
if(c->landparam >= 10) makeflame(c, 10, false), c->landparam = 0; if(c->landparam >= 10) makeflame(c, 10, false), c->landparam = 0;
} }
for(int i=0; i<dcs; i++) { for(int i=0; i<dcs; i++) {
cell *c = allcells[i]; cell *c = allcells[i];
if(!quotient && c->cpdist > 8) break; if(!doall && c->cpdist > 8) break;
if(c->land != laDryForest) continue; if(c->land != laDryForest) continue;
if((c->wall == waBigTree || c->wall == waSmallTree || isFire(c)) && c->landparam >= 1) if((c->wall == waBigTree || c->wall == waSmallTree || isFire(c)) && c->landparam >= 1)
c->wall = waEternalFire; c->wall = waEternalFire;
@ -1797,7 +1821,7 @@ void livecaves() {
for(int i=0; i<dcs; i++) { for(int i=0; i<dcs; i++) {
cell *c = allcells[i]; cell *c = allcells[i];
if(!quotient && c->cpdist > 8) break; if(!doall && c->cpdist > 8) break;
if(c->wall == waCavefloor || c->wall == waCavewall || c->wall == waDeadTroll) { if(c->wall == waCavefloor || c->wall == waCavewall || c->wall == waDeadTroll) {
c->aitmp = 0; c->aitmp = 0;
@ -1899,7 +1923,7 @@ void livecaves() {
for(int i=0; i<dcs; i++) { for(int i=0; i<dcs; i++) {
cell *c = allcells[i]; cell *c = allcells[i];
if(!quotient && c->cpdist > 8) break; if(!doall && c->cpdist > 8) break;
if(c->wall == waCavefloor || c->wall == waCavewall) { if(c->wall == waCavefloor || c->wall == waCavewall) {
// if(c->land != laCaves) continue; // if(c->land != laCaves) continue;
@ -2429,7 +2453,10 @@ namespace prairie {
c->LHU.fi.walldist = 8; c->LHU.fi.walldist = 8;
c->LHU.fi.walldist2 = 8; c->LHU.fi.walldist2 = 8;
if(euclid) { if(torus) {
c->LHU.fi.rval = 0;
}
else if(euclid) {
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
c->LHU.fi.rval = (y&15); c->LHU.fi.rval = (y&15);

View File

@ -706,7 +706,7 @@ namespace conformal {
void renderAutoband() { void renderAutoband() {
#ifndef NOSDL #ifndef NOSDL
if(celldist(cwt.c) <= 7) return; if(!cwt.c || celldist(cwt.c) <= 7) return;
if(!autoband) return; if(!autoband) return;
eModel spm = pmodel; eModel spm = pmodel;
bool ih = includeHistory; bool ih = includeHistory;

View File

@ -379,8 +379,6 @@ bool thruVine(cell *c, cell *c2) {
// === MOVEMENT FUNCTIONS === // === MOVEMENT FUNCTIONS ===
bool againstWind(cell *c2, cell *c1); // to, from
// w = from->mov[d] // w = from->mov[d]
bool againstCurrent(cell *w, cell *from) { bool againstCurrent(cell *w, cell *from) {
if(from->land != laWhirlpool) return false; if(from->land != laWhirlpool) return false;
@ -4280,7 +4278,7 @@ bool swordAttack(cell *mt, eMonster who, cell *c, int bb) {
eMonster m = c->monst; eMonster m = c->monst;
if(c->wall == waCavewall) markOrb(bb ? itOrbSword2: itOrbSword); if(c->wall == waCavewall) markOrb(bb ? itOrbSword2: itOrbSword);
if(c->wall == waSmallTree || c->wall == waBigTree || c->wall == waRose || c->wall == waCTree || c->wall == waVinePlant || if(c->wall == waSmallTree || c->wall == waBigTree || c->wall == waRose || c->wall == waCTree || c->wall == waVinePlant ||
thruVine(mt, c)) { thruVine(mt, c) || c->wall == waBigBush || c->wall == waSmallBush || c->wall == waSolidBranch || c->wall == waWeakBranch) {
playSound(NULL, "hit-axe"+pick123()); playSound(NULL, "hit-axe"+pick123());
markOrb(bb ? itOrbSword2: itOrbSword); markOrb(bb ? itOrbSword2: itOrbSword);
drawParticles(c, winf[c->wall].color, 16); drawParticles(c, winf[c->wall].color, 16);
@ -7075,6 +7073,9 @@ bool mightBeMine(cell *c) {
} }
void performMarkCommand(cell *c) { void performMarkCommand(cell *c) {
#ifdef ROGUEVIZ
rogueviz::mark(c);
#endif
if(c->land == laCA && c->wall == waNone) if(c->land == laCA && c->wall == waNone)
c->wall = waFloorA; c->wall = waFloorA;
else if(c->land == laCA && c->wall == waFloorA) else if(c->land == laCA && c->wall == waFloorA)

118
graph.cpp
View File

@ -1699,7 +1699,7 @@ bool drawstar(cell *c) {
bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks, bool hidden) { bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks, bool hidden) {
char xch = iinf[it].glyph; char xch = iinf[it].glyph;
int ct6 = c ? c->type-6 : 0; int ct6 = c ? c->type-6 : 1;
hpcshape *xsh = hpcshape *xsh =
(it == itPirate || it == itKraken) ? &shPirateX : (it == itPirate || it == itKraken) ? &shPirateX :
(it == itBuggy || it == itBuggy2) ? &shPirateX : (it == itBuggy || it == itBuggy2) ? &shPirateX :
@ -1708,6 +1708,7 @@ bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks,
(it == itBombEgg || it == itTrollEgg) ? &shEgg : (it == itBombEgg || it == itTrollEgg) ? &shEgg :
it == itDodeca ? &shDodeca : it == itDodeca ? &shDodeca :
xch == '*' ? &shGem[ct6] : xch == '*' ? &shGem[ct6] :
it == itShard ? &shMFloor[0] :
it == itTreat ? &shTreat : it == itTreat ? &shTreat :
it == itSlime ? &shEgg : it == itSlime ? &shEgg :
xch == '%' ? &shDaisy : xch == '$' ? &shStar : xch == ';' ? &shTriangle : xch == '%' ? &shDaisy : xch == '$' ? &shStar : xch == ';' ? &shTriangle :
@ -7086,38 +7087,38 @@ void showGameover() {
if(intour) { if(intour) {
#ifdef TOUR #ifdef TOUR
if(canmove) { if(canmove) {
dialog::addItem("spherical geometry", '1'); dialog::addItem(XLAT("spherical geometry"), '1');
dialog::addItem("Euclidean geometry", '2'); dialog::addItem(XLAT("Euclidean geometry"), '2');
dialog::addItem("more curved hyperbolic geometry", '3'); dialog::addItem(XLAT("more curved hyperbolic geometry"), '3');
} }
if(!items[itOrbTeleport]) if(!items[itOrbTeleport])
dialog::addItem("teleport away", '4'); dialog::addItem(XLAT("teleport away"), '4');
else if(!items[itOrbAether]) else if(!items[itOrbAether])
dialog::addItem("move through walls", '4'); dialog::addItem(XLAT("move through walls"), '4');
else else
dialog::addItem("flash", '4'); dialog::addItem(XLAT("flash"), '4');
if(canmove) { if(canmove) {
if(tour::slidecommand != "") if(tour::slidecommand != "")
dialog::addItem(tour::slidecommand, '5'); dialog::addItem(tour::slidecommand, '5');
dialog::addItem("static mode", '6'); dialog::addItem(XLAT("static mode"), '6');
dialog::addItem("enable/disable texts", '7'); dialog::addItem(XLAT("enable/disable texts"), '7');
dialog::addItem("next slide", SDLK_RETURN); dialog::addItem(XLAT("next slide"), SDLK_RETURN);
dialog::addItem("previous slide", SDLK_BACKSPACE); dialog::addItem(XLAT("previous slide"), SDLK_BACKSPACE);
} }
else else
dialog::addBreak(200); dialog::addBreak(200);
dialog::addItem("main menu", 'v'); dialog::addItem(XLAT("main menu"), 'v');
#endif #endif
} }
else { else {
dialog::addItem(canmove ? "continue" : "see how it ended", SDLK_ESCAPE); dialog::addItem(XLAT(canmove ? "continue" : "see how it ended"), SDLK_ESCAPE);
dialog::addItem("main menu", 'v'); dialog::addItem(XLAT("main menu"), 'v');
dialog::addItem("restart", SDLK_F5); dialog::addItem(XLAT("restart"), SDLK_F5);
#ifndef MOBILE #ifndef MOBILE
dialog::addItem(quitsaves() ? "save" : "quit", SDLK_F10); dialog::addItem(XLAT(quitsaves() ? "save" : "quit"), SDLK_F10);
#endif #endif
#ifdef ANDROIDSHARE #ifdef ANDROIDSHARE
dialog::addItem("SHARE", 's'-96); dialog::addItem(XLAT("SHARE"), 's'-96);
#endif #endif
} }
@ -8618,9 +8619,9 @@ void handleKeyQuit(int sym, int uni) {
else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5; else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5;
else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5; else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5;
else if(uni == 'v') cmode = emMenu; else if(uni == 'v') cmode = emMenu;
else if(sym == SDLK_HOME || sym == SDLK_F3 || (sym == ' ' && DEFAULTCONTROL)) else if(sym == SDLK_F3 || (sym == ' ' || sym == SDLK_HOME))
fullcenter(); fullcenter();
else if(uni == 'o') setAppropriateOverview(); else if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
#ifndef NOSAVE #ifndef NOSAVE
else if(uni == 't') { else if(uni == 't') {
if(!canmove) restartGame(); if(!canmove) restartGame();
@ -8669,49 +8670,50 @@ void handleKeyNormal(int sym, int uni, extra& ev) {
} }
#endif #endif
if(uni == sym && DEFAULTNOR(sym)) {
if(sym == '1') {
vid.alpha = 999; vid.scale = 998;
}
if(sym == '2') {
vid.alpha = 1; vid.scale = 0.4;
}
if(sym == '3') {
vid.alpha = 1; vid.scale = 1;
}
if(sym == '4') {
vid.alpha = 0; vid.scale = 1;
}
if(sym == '5') {
vid.wallmode++;
if(vid.wallmode == 6) vid.wallmode = 0;
}
if(sym == '6') {
vid.grid = !vid.grid;
}
if(sym == '7') {
vid.darkhepta = !vid.darkhepta;
}
if(sym == '8') {
backcolor = backcolor ^ 0xFFFFFF;
printf("back = %x\n", backcolor);
}
if(sym == '9') {
pmodel = eModel(8 - pmodel);
// vid.yshift = 1 - vid.yshift;
// vid.drawmousecircle = true;
}
if(sym == 'm' && canmove && cmode == emNormal && (centerover == cwt.c ? mouseover : centerover))
performMarkCommand(mouseover);
}
if(DEFAULTCONTROL) { if(DEFAULTCONTROL) {
if(sym == '.' || sym == 's') movepcto(-1, 1); if(sym == '.' || sym == 's') movepcto(-1, 1);
if(uni == '%' && sym == '5') { if(uni == '%' && sym == '5') {
if(vid.wallmode == 0) vid.wallmode = 6; if(vid.wallmode == 0) vid.wallmode = 6;
vid.wallmode--; vid.wallmode--;
} }
if(uni == sym) {
if(uni == '1') {
vid.alpha = 999; vid.scale = 998;
}
if(uni == '2') {
vid.alpha = 1; vid.scale = 0.4;
}
if(uni == '3') {
vid.alpha = 1; vid.scale = 1;
}
if(uni == '4') {
vid.alpha = 0; vid.scale = 1;
}
if(uni == '5') {
vid.wallmode++;
if(vid.wallmode == 6) vid.wallmode = 0;
}
if(uni == '6') {
vid.grid = !vid.grid;
}
if(uni == '7') {
vid.darkhepta = !vid.darkhepta;
}
if(uni == '8') {
backcolor = backcolor ^ 0xFFFFFF;
printf("back = %x\n", backcolor);
}
if(uni == '9') {
pmodel = eModel(8 - pmodel);
// vid.yshift = 1 - vid.yshift;
// vid.drawmousecircle = true;
}
}
if((sym == SDLK_DELETE || sym == SDLK_KP_PERIOD || sym == 'g') && uni != 'G' && uni != 'G'-64) if((sym == SDLK_DELETE || sym == SDLK_KP_PERIOD || sym == 'g') && uni != 'G' && uni != 'G'-64)
movepcto(MD_DROP, 1); movepcto(MD_DROP, 1);
if(sym == 'm' && canmove && cmode == emNormal && (centerover == cwt.c ? mouseover : centerover))
performMarkCommand(mouseover);
if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove && cmode == emNormal) { if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove && cmode == emNormal) {
if(playermoved && items[itStrongWind]) { if(playermoved && items[itStrongWind]) {
cell *c = whirlwind::jumpDestination(cwt.c); cell *c = whirlwind::jumpDestination(cwt.c);
@ -8763,9 +8765,9 @@ void handleKeyNormal(int sym, int uni, extra& ev) {
else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5; else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5;
} }
if(uni == 'o') setAppropriateOverview(); if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
if(sym == SDLK_HOME || sym == SDLK_F3 || (sym == ' ' && DEFAULTCONTROL)) if((sym == SDLK_HOME || sym == SDLK_F3 || sym == ' ') && DEFAULTNOR(sym))
fullcenter(); fullcenter();
/* if(sym == SDLK_F6) { /* if(sym == SDLK_F6) {
@ -8774,7 +8776,7 @@ void handleKeyNormal(int sym, int uni, extra& ev) {
cmode = emDraw; cmode = emDraw;
} */ } */
if(sym == 'v') { if(sym == 'v' && DEFAULTNOR(sym)) {
cmode = emMenu; cmode = emMenu;
} }
@ -8826,7 +8828,7 @@ void handlekey(int sym, int uni, extra& ev) {
if(tour::on && tour::handleKeyTour(sym, uni)) return; if(tour::on && tour::handleKeyTour(sym, uni)) return;
#endif #endif
if(((cmode == emNormal && canmove) || (cmode == emQuit && !canmove) || cmode == emDraw || (cmode == emMapEditor && !mapeditor::subscreen)) && DEFAULTCONTROL && !rug::rugged) { if(((cmode == emNormal && canmove) || (cmode == emQuit && !canmove) || cmode == emDraw || (cmode == emMapEditor && !mapeditor::subscreen)) && DEFAULTNOR(sym) && !rug::rugged) {
#ifndef PANDORA #ifndef PANDORA
if(sym == SDLK_RIGHT) { if(sym == SDLK_RIGHT) {
if(conformal::on) if(conformal::on)

View File

@ -70,6 +70,15 @@ eItem readItem(const char *s) {
return itNone; return itNone;
} }
eMonster readMonster(const char *s) {
string ss = s;
for(int i=0; i<motypes; i++) if(strstr(minf[i].name, s) != NULL) {
return eMonster(i);
break;
}
return moNone;
}
void initializeCLI() { void initializeCLI() {
printf("HyperRogue by Zeno Rogue <zeno@attnam.com>, version " VER "\n"); printf("HyperRogue by Zeno Rogue <zeno@attnam.com>, version " VER "\n");
@ -121,6 +130,13 @@ int arg::readCommon() {
shift(); eItem i = readItem(args()); shift(); eItem i = readItem(args());
shift(); items[i] = argi(); shift(); items[i] = argi();
} }
else if(argis("-M")) {
PHASE(3) cheater++; timerghost = false;
shift(); eMonster m = readMonster(args());
shift(); int q = argi();
printf("m = %s q = %d\n", dnameof(m), q);
restoreGolems(q, m, 7);
}
else if(argis("-L")) { else if(argis("-L")) {
printf("Treasures:\n"); printf("Treasures:\n");
for(int i=1; i<ittypes; i++) for(int i=1; i<ittypes; i++)
@ -193,6 +209,13 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase ==
autocheat = true; autocheat = true;
fp43.init(p); fp43.init(p);
} }
else if(argis("-tpar")) {
shift(); sscanf(args(), "%d,%d,%d",
&torusconfig::qty,
&torusconfig::dx,
&torusconfig::dy
);
}
else if(argis("-cs")) { else if(argis("-cs")) {
shift(); shift();
fieldpattern::matrix M = fp43.strtomatrix(args()); fieldpattern::matrix M = fp43.strtomatrix(args());

View File

@ -1,8 +1,8 @@
id ICON "hr-icon.ico" id ICON "hr-icon.ico"
1 VERSIONINFO 1 VERSIONINFO
FILEVERSION 9,4,0,11 FILEVERSION 9,4,0,12
PRODUCTVERSION 9,4,0,11 PRODUCTVERSION 9,4,0,12
BEGIN BEGIN
BLOCK "StringFileInfo" BLOCK "StringFileInfo"
BEGIN BEGIN
@ -15,7 +15,7 @@ BEGIN
VALUE "LegalCopyright", "Zeno Rogue" VALUE "LegalCopyright", "Zeno Rogue"
VALUE "OriginalFilename", "hyper.exe" VALUE "OriginalFilename", "hyper.exe"
VALUE "ProductName", "HyperRogue" VALUE "ProductName", "HyperRogue"
VALUE "ProductVersion", "9.4k" VALUE "ProductVersion", "9.4l"
END END
END END

View File

@ -1,12 +1,17 @@
// Hyperbolic Rogue // Hyperbolic Rogue
// Copyright (C) 2011-2012 Zeno Rogue, see 'hyper.cpp' for details // Copyright (C) 2011-2012 Zeno Rogue, see 'hyper.cpp' for details
enum eGeometry {gNormal, gEuclid, gSphere, gElliptic, gQuotient, gQuotient2, gGUARD}; enum eGeometry {gNormal, gEuclid, gSphere, gElliptic, gQuotient, gQuotient2, gTorus, gGUARD};
eGeometry geometry, targetgeometry = gEuclid; eGeometry geometry, targetgeometry = gEuclid;
#define euclid (geometry == gEuclid) #define euclid (geometry == gEuclid || geometry == gTorus)
#define sphere (geometry == gSphere || geometry == gElliptic) #define sphere (geometry == gSphere || geometry == gElliptic)
#define elliptic (geometry == gElliptic) #define elliptic (geometry == gElliptic)
#define quotient (geometry == gQuotient ? 1 : geometry == gQuotient2 ? 2 : 0) #define quotient (geometry == gQuotient ? 1 : geometry == gQuotient2 ? 2 : 0)
#define torus (geometry == gTorus)
#define doall (quotient || torus)
#define smallbounded (sphere || quotient == 1 || torus)
// for the pure heptagonal grid // for the pure heptagonal grid
bool purehepta = false; bool purehepta = false;

View File

@ -1,6 +1,6 @@
#define VER "9.4k" #define VER "9.4l"
#define VERNUM 9411 #define VERNUM 9412
#define VERNUM_HEX 0x9411 #define VERNUM_HEX 0x9412
#define GEN_M 0 #define GEN_M 0
#define GEN_F 1 #define GEN_F 1
@ -186,6 +186,7 @@ typedef int SDL_Event;
#undef TOUR #undef TOUR
#else #else
#include <functional> #include <functional>
#include <memory>
#endif #endif
#include <cmath> #include <cmath>
@ -199,6 +200,8 @@ typedef int SDL_Event;
#include <map> #include <map>
#include <queue> #include <queue>
#include <array>
#ifdef USE_UNORDERED_MAP #ifdef USE_UNORDERED_MAP
#include <unordered_map> #include <unordered_map>
#else #else
@ -392,7 +395,7 @@ void handleclick(MOBPAR_FORMAL) {
} }
} }
if(buttonclicked || outofmap(mouseh)) { if(buttonclicked || mouseout()) {
if(andmode == 0 && getcstat == 'g' && !shmup::on && (cmode == emNormal || cmode == emQuit)) { if(andmode == 0 && getcstat == 'g' && !shmup::on && (cmode == emNormal || cmode == emQuit)) {
movepcto(MD_DROP); movepcto(MD_DROP);
@ -435,7 +438,7 @@ void handleclick(MOBPAR_FORMAL) {
} }
} }
if(andmode == 0 && cmode == (canmove ? emNormal : emQuit) && !outofmap(mouseh)) { if(andmode == 0 && cmode == (canmove ? emNormal : emQuit) && !mouseout()) {
bool forcetarget = longclick; bool forcetarget = longclick;
@ -484,7 +487,7 @@ void mobile_draw(MOBPAR_FORMAL) {
safety = false; safety = false;
vid.fsize = (min(vid.xres, vid.yres) * fontscale + 50) / 3200; vid.fsize = (min(vid.xres, vid.yres) * fontscale + 50) / 3200;
hyperpoint mouseoh = mouseh; mouseoh = mouseh;
gtouched = mousepressed = clicked; gtouched = mousepressed = clicked;
longclick = lclicked && ticks > touchedAt + 500; longclick = lclicked && ticks > touchedAt + 500;
@ -592,7 +595,7 @@ void mobile_draw(MOBPAR_FORMAL) {
if((cmode != emVisual1 && cmode != emScores)) { if((cmode != emVisual1 && cmode != emScores)) {
if(clicked && lclicked && andmode == 1 && !inmenu) { if(clicked && lclicked && andmode == 1 && !inmenu) {
if(!outofmap(mouseoh) && !outofmap(mouseh) && mouseoh[2] < 50 && mouseh[2] < 50) { if(!mouseout2() && mouseoh[2] < 50 && mouseh[2] < 50) {
panning(mouseoh, mouseh); panning(mouseoh, mouseh);
} }
} }

View File

@ -98,7 +98,7 @@ int isNative(eLand l, eMonster m) {
case laDeadCaves: case laDeadCaves:
return (m == moEarthElemental || m == moDarkTroll) ? 2 : return (m == moEarthElemental || m == moDarkTroll) ? 2 :
m == moGoblin ? 1 : 0; (m == moGoblin || m == moSeep) ? 1 : 0;
case laPower: case laPower:
return (isWitch(m) || m == moEvilGolem) ? 1 : 0; return (isWitch(m) || m == moEvilGolem) ? 1 : 0;
@ -319,7 +319,7 @@ struct orbinfo {
eItem orb; eItem orb;
}; };
orbinfo orbinfos[ORBLINES] = { const orbinfo orbinfos[ORBLINES] = {
{laGraveyard, 200, 200,itGreenStone}, // must be first so that it does not reduce {laGraveyard, 200, 200,itGreenStone}, // must be first so that it does not reduce
// chance of other orbs // chance of other orbs
{laJungle, 1200, 1500,itOrbLightning}, {laJungle, 1200, 1500,itOrbLightning},
@ -546,6 +546,9 @@ eOrbLandRelation getOLR(eItem it, eLand l) {
l == laMountain || l == laReptile || l == laDungeon) l == laMountain || l == laReptile || l == laDungeon)
return olrUseless; return olrUseless;
if(it == itOrbWinter && l == laMinefield)
return olrForbidden;
if(it == itOrbWinter && l != laRlyeh && l != laTemple) if(it == itOrbWinter && l != laRlyeh && l != laTemple)
return olrUseless; return olrUseless;
@ -1017,7 +1020,7 @@ void placePrizeOrb(cell *c) {
if(l == laPalace && princess::dist(c) < OUT_OF_PRISON) if(l == laPalace && princess::dist(c) < OUT_OF_PRISON)
l = laPrincessQuest; l = laPrincessQuest;
for(int i=0; i<ORBLINES; i++) { for(int i=0; i<ORBLINES; i++) {
orbinfo& oi(orbinfos[i]); const orbinfo& oi(orbinfos[i]);
eOrbLandRelation olr = getOLR(oi.orb, l); eOrbLandRelation olr = getOLR(oi.orb, l);
if(olr != olrPrize25 && olr != olrPrize3) continue; if(olr != olrPrize25 && olr != olrPrize3) continue;
int treas = items[treasureType(oi.l)]; int treas = items[treasureType(oi.l)];
@ -1050,7 +1053,7 @@ void placeLocalOrbs(cell *c) {
if(isElemental(l)) l = laElementalWall; if(isElemental(l)) l = laElementalWall;
for(int i=0; i<ORBLINES; i++) { for(int i=0; i<ORBLINES; i++) {
orbinfo& oi(orbinfos[i]); const orbinfo& oi(orbinfos[i]);
if(oi.l != l) continue; if(oi.l != l) continue;
if(yendor::on && (oi.orb == itOrbSafety || oi.orb == itOrbYendor)) if(yendor::on && (oi.orb == itOrbSafety || oi.orb == itOrbYendor))
continue; continue;
@ -1072,7 +1075,7 @@ void placeLocalOrbs(cell *c) {
void placeCrossroadOrbs(cell *c) { void placeCrossroadOrbs(cell *c) {
for(int i=0; i<ORBLINES; i++) { for(int i=0; i<ORBLINES; i++) {
orbinfo& oi(orbinfos[i]); const orbinfo& oi(orbinfos[i]);
if(!oi.gchance) continue; if(!oi.gchance) continue;
int treas = items[treasureType(oi.l)] * landMultiplier(oi.l); int treas = items[treasureType(oi.l)] * landMultiplier(oi.l);
if(tactic::on && isCrossroads(tactic::lasttactic)) { if(tactic::on && isCrossroads(tactic::lasttactic)) {
@ -1095,7 +1098,7 @@ void placeCrossroadOrbs(cell *c) {
void placeOceanOrbs(cell *c) { void placeOceanOrbs(cell *c) {
for(int i=0; i<ORBLINES; i++) { for(int i=0; i<ORBLINES; i++) {
orbinfo& oi(orbinfos[i]); const orbinfo& oi(orbinfos[i]);
if(items[treasureType(oi.l)] * landMultiplier(oi.l) < 10) continue; if(items[treasureType(oi.l)] * landMultiplier(oi.l) < 10) continue;
if(!oi.gchance) continue; if(!oi.gchance) continue;
if(oi.orb == itOrbLife) continue; // useless if(oi.orb == itOrbLife) continue; // useless
@ -3289,8 +3292,8 @@ void setdist(cell *c, int d, cell *from) {
if(c->land == laWhirlpool && !tactic::on && !yendor::on) setland(c, laOcean); if(c->land == laWhirlpool && !tactic::on && !yendor::on) setland(c, laOcean);
if(c->land == laCamelot && !tactic::on) setland(c, laCrossroads); if(c->land == laCamelot && !tactic::on) setland(c, laCrossroads);
if(euclid) setLandEuclid(c); if(sphere || torus) setLandSphere(c);
if(sphere) setLandSphere(c); else if(euclid) setLandEuclid(c);
if(quotient) { setland(c, euclidland); setLandQuotient(c); } if(quotient) { setland(c, euclidland); setLandQuotient(c); }
// if(chaosmode) setland(c, getCLand(c)); // if(chaosmode) setland(c, getCLand(c));
@ -3452,6 +3455,7 @@ void setdist(cell *c, int d, cell *from) {
if(d==8 && c->land == laEmerald) { if(d==8 && c->land == laEmerald) {
if(randomPatternsMode) if(randomPatternsMode)
c->wall = RANDPAT3(0) ? waCavewall : waCavefloor; c->wall = RANDPAT3(0) ? waCavewall : waCavefloor;
else if(torus) ;
else if(euclid) { else if(euclid) {
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
@ -3483,6 +3487,7 @@ void setdist(cell *c, int d, cell *from) {
int v; int v;
if(randomPatternsMode) if(randomPatternsMode)
v = RANDPAT ? 24 : 0; v = RANDPAT ? 24 : 0;
else if(torus) ;
else if(euclid) { else if(euclid) {
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
@ -3508,7 +3513,8 @@ void setdist(cell *c, int d, cell *from) {
} }
if(d==8 && c->land == laZebra) { if(d==8 && c->land == laZebra) {
if(euclid) { if(torus) ;
else if(euclid) {
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
if(y&1) c->wall = waTrapdoor; if(y&1) c->wall = waTrapdoor;
@ -3528,7 +3534,8 @@ void setdist(cell *c, int d, cell *from) {
} }
if(d==8 && c->land == laWineyard) { if(d==8 && c->land == laWineyard) {
if(euclid) { if(torus) ;
else if(euclid) {
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
int dy = ((short)y)%3; if(dy<0) dy += 3; int dy = ((short)y)%3; if(dy<0) dy += 3;
@ -3794,7 +3801,8 @@ void setdist(cell *c, int d, cell *from) {
if(c->land == laStorms) { if(c->land == laStorms) {
if(euclid) { if(torus) ;
else if(euclid) {
eucoord x, y; eucoord x, y;
decodeMaster(c->master, x, y); decodeMaster(c->master, x, y);
if(short(x+1)%3 == 0 && short(y)%3 == 0) { if(short(x+1)%3 == 0 && short(y)%3 == 0) {
@ -4629,7 +4637,23 @@ void setdist(cell *c, int d, cell *from) {
} }
c2->wall = waOpenPlate; c2->wall = waOpenPlate;
} }
}
if(d == 7 && c->land == laMountain) {
if(hrand(50000) < 100)
buildIvy(c, 0, 3);
else if(hrand(125000) < 100 - celldistAlt(c))
c->monst = moMonkey;
else if(hrand(200000) < min(100, -10*celldistAlt(c)) - celldistAlt(c))
c->monst = moEagle;
else if(hrand(100) < 5)
c->wall = waPlatform;
else if(hrand(100) < 20)
c->wall = waBigBush;
else if(hrand(100) < 12)
c->wall = waSmallBush;
else if(hrand(500) < -celldistAlt(c) / 5 - items[itAmethyst])
c->item = itAmethyst;
} }
if(d == 7 && passable(c, NULL, 0) && !safety) { if(d == 7 && passable(c, NULL, 0) && !safety) {
@ -4936,22 +4960,6 @@ void setdist(cell *c, int d, cell *from) {
c->item = itRuby; c->item = itRuby;
} }
} }
if(c->land == laMountain) {
if(hrand(50000) < 100)
buildIvy(c, 0, 3);
else if(hrand(125000) < 100 - celldistAlt(c))
c->monst = moMonkey;
else if(hrand(200000) < min(100, -10*celldistAlt(c)) - celldistAlt(c))
c->monst = moEagle;
else if(hrand(100) < 5)
c->wall = waPlatform;
else if(hrand(100) < 20)
c->wall = waBigBush;
else if(hrand(100) < 12)
c->wall = waSmallBush;
else if(hrand(500) < -celldistAlt(c) / 5 - items[itAmethyst])
c->item = itAmethyst;
}
if(c->land == laWhirlwind) { if(c->land == laWhirlwind) {
if(hrand(4500) < items[itWindstone] + hard) if(hrand(4500) < items[itWindstone] + hard)
c->monst = moWindCrow; c->monst = moWindCrow;
@ -5281,7 +5289,7 @@ void wandering() {
if(cwt.c->land == laZebra && cwt.c->wall == waNone && wchance(items[itZebra], 20)) if(cwt.c->land == laZebra && cwt.c->wall == waNone && wchance(items[itZebra], 20))
wanderingZebra(cwt.c); wanderingZebra(cwt.c);
if(sphere || quotient == 1) { if(smallbounded) {
int maxdist = 0; int maxdist = 0;
for(int i=0; i<size(dcal); i++) if(dcal[i]->cpdist > maxdist) maxdist = dcal[i]->cpdist; for(int i=0; i<size(dcal); i++) if(dcal[i]->cpdist > maxdist) maxdist = dcal[i]->cpdist;
for(int i=0; i<size(dcal); i++) if(dcal[i]->cpdist >= maxdist-1) { first7 = i; break; } for(int i=0; i<size(dcal); i++) if(dcal[i]->cpdist >= maxdist-1) { first7 = i; break; }
@ -5295,7 +5303,7 @@ void wandering() {
int i = first7 + hrand(size(dcal) - first7); int i = first7 + hrand(size(dcal) - first7);
cell *c = dcal[i]; cell *c = dcal[i];
if((sphere || quotient == 1) && !c->item && hrand(5) == 0 && c->land != laHalloween) { if(smallbounded && !c->item && hrand(5) == 0 && c->land != laHalloween) {
if(passable(c, NULL, 0) || euclidland == laKraken) { if(passable(c, NULL, 0) || euclidland == laKraken) {
if(!haveOrbPower() && euclidland != laHell) for(int it=0; it<1000 && !c->item; it++) if(!haveOrbPower() && euclidland != laHell) for(int it=0; it<1000 && !c->item; it++)
placeLocalOrbs(c); placeLocalOrbs(c);
@ -5314,7 +5322,7 @@ void wandering() {
if(!c->monst) c->stuntime = 0; if(!c->monst) c->stuntime = 0;
if(timerghost && !sphere && quotient != 1) { if(timerghost && !smallbounded) {
// wandering seeps & ghosts // wandering seeps & ghosts
if(seepcount && c->wall == waCavewall && !c->monst && canReachPlayer(c, moSlime)) { if(seepcount && c->wall == waCavewall && !c->monst && canReachPlayer(c, moSlime)) {
c->monst = moSeep; c->monst = moSeep;

View File

@ -1231,7 +1231,7 @@ namespace mapeditor {
transmatrix V2 = V * spin(M_PI + 2*M_PI*a/dsCur->rots); transmatrix V2 = V * spin(M_PI + 2*M_PI*a/dsCur->rots);
if(outofmap(mouseh)) break; if(mouseout()) break;
hyperpoint P2 = V2 * inverse(cwtV) * mouseh; hyperpoint P2 = V2 * inverse(cwtV) * mouseh;
@ -1368,7 +1368,7 @@ namespace mapeditor {
displayButton(vid.xres-8, 8+fs*2, XLAT("o = zoom out"), 'o', 16); displayButton(vid.xres-8, 8+fs*2, XLAT("o = zoom out"), 'o', 16);
displayfr(vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 0xC0C0C0, 16); displayfr(vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 0xC0C0C0, 16);
if(!outofmap(mouseh)) { if(!mouseout()) {
hyperpoint mh = inverse(drawtrans * rgpushxto0(ccenter)) * mouseh; hyperpoint mh = inverse(drawtrans * rgpushxto0(ccenter)) * mouseh;
displayfr(vid.xres-8, vid.yres-8-fs*6, 2, vid.fsize, XLAT("x: %1", fts4(mh[0])), 0xC0C0C0, 16); displayfr(vid.xres-8, vid.yres-8-fs*6, 2, vid.fsize, XLAT("x: %1", fts4(mh[0])), 0xC0C0C0, 16);
displayfr(vid.xres-8, vid.yres-8-fs*5, 2, vid.fsize, XLAT("y: %1", fts4(mh[1])), 0xC0C0C0, 16); displayfr(vid.xres-8, vid.yres-8-fs*5, 2, vid.fsize, XLAT("y: %1", fts4(mh[1])), 0xC0C0C0, 16);

View File

@ -1137,7 +1137,7 @@ int euperpage = 21;
const char* geometrynames[gGUARD] = { const char* geometrynames[gGUARD] = {
"hyperbolic", "Euclidean", "spherical", "elliptic", "hyperbolic", "Euclidean", "spherical", "elliptic",
"Zebra quotient", "field quotient" "Zebra quotient", "field quotient", "torus"
}; };
void showEuclideanMenu() { void showEuclideanMenu() {

View File

@ -34,7 +34,7 @@ string fname;
// const char *fname; // const char *fname;
// const char *cfname; // const char *cfname;
enum eVizkind { kNONE, kAnyGraph, kTree, kSpiral, kSAG, kCollatz, kFullNet }; enum eVizkind { kNONE, kAnyGraph, kTree, kSpiral, kSAG, kCollatz, kFullNet, kKohonen };
eVizkind kind; eVizkind kind;
bool on; bool on;
@ -889,6 +889,12 @@ bool edgecmp(edgeinfo *e1, edgeinfo *e2) {
return e1->weight > e2->weight; return e1->weight > e2->weight;
} }
#include "kohonen.cpp"
void describe(cell *c) {
if(kind == kKohonen) return kohonen::describe(c);
}
string describe(shmup::monster *m) { string describe(shmup::monster *m) {
int i = m->pid; int i = m->pid;
vertexdata& vd = vdata[i]; vertexdata& vd = vdata[i];
@ -1244,9 +1250,10 @@ void readcolor(const char *cfname) {
if(size(lab) && lab[0] == '*') { if(size(lab) && lab[0] == '*') {
lab = lab.substr(1); lab = lab.substr(1);
for(int i=0; i<size(vdata); i++) for(int i=0; i<size(vdata); i++)
if(vdata[i].name.find(lab) != string::npos) if(vdata[i].name.find(lab) != string::npos) {
vdata[i].cp = x; vdata[i].cp = x;
} }
}
else { else {
int i = getid(lab); int i = getid(lab);
again: vdata[i].cp = x; again: vdata[i].cp = x;
@ -1296,6 +1303,7 @@ void close() {
void turn(int delta) { void turn(int delta) {
if(!on) return; if(!on) return;
if(kind == kSAG) sag::iterate(); if(kind == kSAG) sag::iterate();
if(kind == kKohonen) kohonen::steps();
// shmup::pc[0]->rebase(); // shmup::pc[0]->rebase();
} }
@ -1601,6 +1609,21 @@ int readArgs() {
else if(argis("-ggamma")) { else if(argis("-ggamma")) {
shift(); ggamma = argf(); shift(); ggamma = argf();
} }
else if(argis("-som")) {
PHASE(3);
shift(); const char *fname = args();
shift(); int percount = argi();
shift(); kohonen::run(fname, percount, argf());
}
else if(argis("-somsave")) {
PHASE(3);
while(!kohonen::finished()) kohonen::step();
shift(); kohonen::ksave(args());
}
else if(argis("-somload")) {
PHASE(3);
shift(); kohonen::kload(args());
}
else if(argis("-nolegend")) { else if(argis("-nolegend")) {
legend.clear(); legend.clear();
} }
@ -1623,12 +1646,16 @@ void showMenu() {
dialog::init(XLAT("rogueviz configuration")); dialog::init(XLAT("rogueviz configuration"));
dialog::addSelItem(XLAT("temperature"), fts(sag::temperature), 't'); dialog::addSelItem(XLAT("temperature"), fts(sag::temperature), 't');
if(kind == kSAG)
dialog::addSelItem(XLAT("SAG mode"), sag::sagmodes[sag::sagmode], 'm'); dialog::addSelItem(XLAT("SAG mode"), sag::sagmodes[sag::sagmode], 'm');
dialog::addBoolItem(XLAT("show labels"), showlabels, 'l'); dialog::addBoolItem(XLAT("show labels"), showlabels, 'l');
dialog::addBoolItem(XLAT("mark special vertices"), specialmark, 'x'); dialog::addBoolItem(XLAT("mark special vertices"), specialmark, 'x');
dialog::addSelItem(XLAT("background color"), itsh(backcolor), 'b'); dialog::addSelItem(XLAT("background color"), itsh(backcolor), 'b');
dialog::addSelItem(XLAT("gamma value for edges"), fts(ggamma), 'g'); dialog::addSelItem(XLAT("gamma value for edges"), fts(ggamma), 'g');
dialog::addBoolItem(XLAT("vertices in 3D"), rog3, '3'); dialog::addBoolItem(XLAT("vertices in 3D"), rog3, 'v');
if(kind == kKohonen)
kohonen::showMenu();
dialog::addBreak(50); dialog::addBreak(50);
dialog::addItem(XLAT("exit menu"), 'v'); dialog::addItem(XLAT("exit menu"), 'v');
@ -1644,7 +1671,7 @@ void handleMenu(int sym, int uni) {
sag::sagmode = sag::eSagmode( (1+sag::sagmode) % 3 ); sag::sagmode = sag::eSagmode( (1+sag::sagmode) % 3 );
} }
else if(uni == 'l') showlabels = !showlabels; else if(uni == 'l') showlabels = !showlabels;
else if(uni == '3') rog3 = !rog3; else if(uni == 'v') rog3 = !rog3;
else if(uni == 'x') specialmark = !specialmark; else if(uni == 'x') specialmark = !specialmark;
else if(uni == 'b') backcolor ^= 0xFFFFFF; else if(uni == 'b') backcolor ^= 0xFFFFFF;
else if(uni == 'g') { else if(uni == 'g') {
@ -1658,6 +1685,7 @@ void handleMenu(int sym, int uni) {
printf("named = %d\n", size(named)); printf("named = %d\n", size(named));
cmode = emNormal; cmode = emNormal;
} }
else if(kind == kKohonen && kohonen::handleMenu(sym, uni)) ;
else if(doexiton(sym, uni)) cmode = emNormal; else if(doexiton(sym, uni)) cmode = emNormal;
} }

View File

@ -1008,7 +1008,7 @@ struct monster {
fixmatrix(at); pat = at; fixmatrix(at); pat = at;
return; return;
} }
if(geometry == gQuotient) { if(geometry == gQuotient || geometry == gTorus) {
at = inverse(gmatrix[base]) * new_pat; at = inverse(gmatrix[base]) * new_pat;
virtualRebase(this, true); virtualRebase(this, true);
fixmatrix(at); fixmatrix(at);
@ -1514,10 +1514,14 @@ void movePlayer(monster *m, int delta) {
playerturn[cpid] = mturn * delta / 150.0; playerturn[cpid] = mturn * delta / 150.0;
double mdd = hypot(mdx, mdy); double mdd = hypot(mdx, mdy);
if(mdd > 1e-6) { if(mdd > 1e-6) {
hyperpoint jh = hpxy(mdx/100.0, mdy/100.0); hyperpoint jh = hpxy(mdx/100.0, mdy/100.0);
hyperpoint ctr = m->pat * C0;
hyperpoint h = inverse(m->pat) * rgpushxto0(m->pat * C0) * jh; if(sphere && vid.alphax > 1.001) for(int i=0; i<3; i++) ctr[i] = -ctr[i];
hyperpoint h = inverse(m->pat) * rgpushxto0(ctr) * jh;
playerturn[cpid] = -atan2(h[1], h[0]); playerturn[cpid] = -atan2(h[1], h[0]);
mgo += mdd; mgo += mdd;
@ -1526,7 +1530,7 @@ void movePlayer(monster *m, int delta) {
#ifndef NOSDL #ifndef NOSDL
Uint8 *keystate = SDL_GetKeyState(NULL); Uint8 *keystate = SDL_GetKeyState(NULL);
bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]); bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]);
if(((mousepressed && !forcetarget) || facemouse) && delta > 0 && !outofmap(mouseh)) { if(((mousepressed && !forcetarget) || facemouse) && delta > 0 && !mouseout()) {
// playermoved = true; // playermoved = true;
hyperpoint h = inverse(m->pat) * mouseh; hyperpoint h = inverse(m->pat) * mouseh;
playerturn[cpid] = -atan2(h[1], h[0]); playerturn[cpid] = -atan2(h[1], h[0]);
@ -1843,7 +1847,7 @@ monster *getPlayer() {
} }
void virtualize(monster *m) { void virtualize(monster *m) {
if(quotient) forCellCM(c2, m->base) if(!gmatrix.count(c2)) { if(doall) forCellCM(c2, m->base) if(!gmatrix.count(c2)) {
m->isVirtual = true; m->isVirtual = true;
m->pat = m->at; m->pat = m->at;
return; return;
@ -1879,7 +1883,7 @@ void moveMimic(monster *m) {
c2->wall = waNone; c2->wall = waNone;
} }
if(!quotient && c2->cpdist >= 6) if(!doall && c2->cpdist >= 6)
m->dead = true; m->dead = true;
} }
@ -2077,7 +2081,7 @@ void moveBullet(monster *m, int delta) {
m->rebasePat(nat); m->rebasePat(nat);
// destroy stray bullets // destroy stray bullets
if(!quotient) for(int i=0; i<m->base->type; i++) if(!doall) for(int i=0; i<m->base->type; i++)
if(!m->base->mov[i] || !gmatrix.count(m->base->mov[i])) if(!m->base->mov[i] || !gmatrix.count(m->base->mov[i]))
m->dead = true; m->dead = true;
@ -2716,6 +2720,16 @@ void activateMonstersAt(cell *c) {
} }
} }
void fixStorage() {
vector<monster*> restore;
for(auto it = monstersAt.begin(); it != monstersAt.end(); it++)
if(it->second->base != it->first) {
restore.push_back(it->second);
monstersAt.erase(it++);
}
for(monster *m: restore) m->store();
}
void turn(int delta) { void turn(int delta) {
lmousetarget = NULL; lmousetarget = NULL;
@ -2733,7 +2747,7 @@ void turn(int delta) {
invismove = (curtime >= visibleAt) && markOrb(itOrbInvis); invismove = (curtime >= visibleAt) && markOrb(itOrbInvis);
// detect active monsters // detect active monsters
if(quotient) if(doall)
for(cell *c: currentmap->allcells()) activateMonstersAt(c); for(cell *c: currentmap->allcells()) activateMonstersAt(c);
else else
for(unordered_map<cell*, transmatrix>::iterator it = gmatrix.begin(); it != gmatrix.end(); it++) for(unordered_map<cell*, transmatrix>::iterator it = gmatrix.begin(); it != gmatrix.end(); it++)
@ -2998,7 +3012,7 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
m->pat = ggmatrix(m->base) * m->at; m->pat = ggmatrix(m->base) * m->at;
transmatrix view = V * m->at; transmatrix view = V * m->at;
if(!outofmap(mouseh)) { if(!mouseout()) {
#ifdef ROGUEVIZ #ifdef ROGUEVIZ
if(rogueviz::virt(m)) ; else if(rogueviz::virt(m)) ; else
#endif #endif
@ -3039,6 +3053,7 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
hyperpoint h = keytarget(cpid); hyperpoint h = keytarget(cpid);
queuechr(h, vid.fsize, '+', iinf[keyresult[cpid]].color); queuechr(h, vid.fsize, '+', iinf[keyresult[cpid]].color);
} }
break; break;
case moBullet: { case moBullet: {
int col; int col;
@ -3172,8 +3187,6 @@ transmatrix calc_relative_matrix(cell *c, heptagon *h1) {
return gm * where; return gm * where;
} }
transmatrix ztmp;
transmatrix &ggmatrix(cell *c) { transmatrix &ggmatrix(cell *c) {
transmatrix& t = gmatrix[c]; transmatrix& t = gmatrix[c];
if(t[2][2] == 0) { if(t[2][2] == 0) {
@ -3183,6 +3196,11 @@ transmatrix &ggmatrix(cell *c) {
printf("error: gmatrix0 not known\n"); printf("error: gmatrix0 not known\n");
exit(1); exit(1);
} }
else if(torus) {
forCellIdEx(c2, i, c)
if(celldistance(c2, centerover) < celldistance(c, centerover))
t = ggmatrix(c2) * eumovedir(3+i);
}
else if(euclid) { else if(euclid) {
eucoord xh, yh, xc, yc; eucoord xh, yh, xc, yc;
decodeMaster(c->master, xh, yh); decodeMaster(c->master, xh, yh);
@ -3233,7 +3251,15 @@ transmatrix calc_relative_matrix_help(cell *c, heptagon *h1) {
void virtualRebase(cell*& base, transmatrix& at, bool tohex) { void virtualRebase(cell*& base, transmatrix& at, bool tohex) {
if(euclid || sphere) { if(euclid || sphere) {
again: again:
forCellCM(c2, base) { if(torus) for(int i=0; i<6; i++) {
transmatrix newat = eumovedir(3+i) * at;
if(hdist0(tC0(newat)) < hdist0(tC0(at))) {
at = newat;
base = createMov(base, i);
goto again;
}
}
else forCellCM(c2, base) {
transmatrix newat = inverse(ggmatrix(c2)) * ggmatrix(base) * at; transmatrix newat = inverse(ggmatrix(c2)) * ggmatrix(base) * at;
if(hypot(tC0(newat)[0], tC0(newat)[1]) if(hypot(tC0(newat)[0], tC0(newat)[1])
< hypot(tC0(at)[0], tC0(at)[1])) { < hypot(tC0(at)[0], tC0(at)[1])) {