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);
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 {
cell *gamestart() {
@ -322,19 +392,33 @@ struct hrmap_euclidean : hrmap {
union heptacoder {
heptagon *h;
struct { eucoord x; eucoord y; } c;
int id;
};
void decodeMaster(heptagon *h, eucoord& x, eucoord& y) {
if(torus) { printf("decodeMaster on torus\n"); exit(1); }
heptacoder u;
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) {
if(torus) { printf("encodeMaster on torus\n"); exit(1); }
heptacoder u;
u.c.x = x; u.c.y = y;
return u.h;
}
heptagon* encodeId(int id) {
heptacoder u;
u.id = id;
return u.h;
}
// --- quotient geometry ---
namespace quotientspace {
@ -591,6 +675,7 @@ void eumerge(cell* c1, cell *c2, int s1, int s2) {
// map<pair<eucoord, eucoord>, cell*> euclidean;
cell*& euclideanAt(eucoord x, eucoord y) {
if(torus) { printf("euclideanAt called\n"); exit(1); }
hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap);
return euc->at(x, y);
}
@ -615,7 +700,8 @@ cell*& euclideanAtCreate(eucoord x, eucoord y) {
void initcells() {
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(quotient) currentmap = new quotientspace::hrmap_quotient;
else currentmap = new hrmap_hyperbolic;
@ -705,6 +791,7 @@ void verifycells(heptagon *at) {
}
int eupattern(cell *c) {
if(torus) return decodeId(c->master) % 3;
eucoord x, y;
decodeMaster(c->master, x, y);
short z = (short(y+2*x))%3;
@ -760,6 +847,8 @@ int compdist(int dx[3]) {
int celldist(cell *c) {
if(euclid) {
if(torus)
return torusmap()->dists[decodeId(c->master)];
eucoord x, y;
decodeMaster(c->master, x, y);
return eudist(x, y);
@ -782,6 +871,7 @@ int euclidAlt(short x, short y);
int celldistAlt(cell *c) {
if(euclid) {
if(torus) return celldist(c);
eucoord x, y;
decodeMaster(c->master, x, y);
return euclidAlt(x, y);
@ -817,6 +907,10 @@ unsigned bitmajority(unsigned a, unsigned b, unsigned c) {
int eufifty(cell *c) {
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);
int ix = short(x) + 99999 + short(y);
int iy = short(y) + 99999;
@ -1196,9 +1290,16 @@ cdata *getHeptagonCdata(heptagon *h) {
}
cdata *getEuclidCdata(heptagon *h) {
if(torus) {
static cdata xx;
return &xx;
}
eucoord x, y;
hrmap_euclidean* euc = dynamic_cast<hrmap_euclidean*> (currentmap);
if(euc->eucdata.count(h)) return &(euc->eucdata[h]);
decodeMaster(h, x, y);
if(x == 0 && y == 0) {
@ -1314,6 +1415,8 @@ int celldistance(cell *c1, cell *c2) {
int d = 0;
if(euclid) {
if(torus)
return torusmap()->dists[toridMod(decodeId(c1->master)-decodeId(c2->master))];
eucoord x1, y1, x2, y2;
decodeMaster(c1->master, x1, y1);
decodeMaster(c2->master, x2, y2);
@ -1404,6 +1507,7 @@ void clearMemory() {
}
int getHemisphere(cell *c, int which) {
if(torus) return 0;
if(c->type != 6) {
int id = c->master->fiftyval;
int hemitable[3][12] = {

View File

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

View File

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

View File

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

View File

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

120
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) {
char xch = iinf[it].glyph;
int ct6 = c ? c->type-6 : 0;
int ct6 = c ? c->type-6 : 1;
hpcshape *xsh =
(it == itPirate || it == itKraken) ? &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 == itDodeca ? &shDodeca :
xch == '*' ? &shGem[ct6] :
it == itShard ? &shMFloor[0] :
it == itTreat ? &shTreat :
it == itSlime ? &shEgg :
xch == '%' ? &shDaisy : xch == '$' ? &shStar : xch == ';' ? &shTriangle :
@ -7086,38 +7087,38 @@ void showGameover() {
if(intour) {
#ifdef TOUR
if(canmove) {
dialog::addItem("spherical geometry", '1');
dialog::addItem("Euclidean geometry", '2');
dialog::addItem("more curved hyperbolic geometry", '3');
dialog::addItem(XLAT("spherical geometry"), '1');
dialog::addItem(XLAT("Euclidean geometry"), '2');
dialog::addItem(XLAT("more curved hyperbolic geometry"), '3');
}
if(!items[itOrbTeleport])
dialog::addItem("teleport away", '4');
dialog::addItem(XLAT("teleport away"), '4');
else if(!items[itOrbAether])
dialog::addItem("move through walls", '4');
dialog::addItem(XLAT("move through walls"), '4');
else
dialog::addItem("flash", '4');
dialog::addItem(XLAT("flash"), '4');
if(canmove) {
if(tour::slidecommand != "")
dialog::addItem(tour::slidecommand, '5');
dialog::addItem("static mode", '6');
dialog::addItem("enable/disable texts", '7');
dialog::addItem("next slide", SDLK_RETURN);
dialog::addItem("previous slide", SDLK_BACKSPACE);
dialog::addItem(XLAT("static mode"), '6');
dialog::addItem(XLAT("enable/disable texts"), '7');
dialog::addItem(XLAT("next slide"), SDLK_RETURN);
dialog::addItem(XLAT("previous slide"), SDLK_BACKSPACE);
}
else
dialog::addBreak(200);
dialog::addItem("main menu", 'v');
dialog::addItem(XLAT("main menu"), 'v');
#endif
}
else {
dialog::addItem(canmove ? "continue" : "see how it ended", SDLK_ESCAPE);
dialog::addItem("main menu", 'v');
dialog::addItem("restart", SDLK_F5);
dialog::addItem(XLAT(canmove ? "continue" : "see how it ended"), SDLK_ESCAPE);
dialog::addItem(XLAT("main menu"), 'v');
dialog::addItem(XLAT("restart"), SDLK_F5);
#ifndef MOBILE
dialog::addItem(quitsaves() ? "save" : "quit", SDLK_F10);
dialog::addItem(XLAT(quitsaves() ? "save" : "quit"), SDLK_F10);
#endif
#ifdef ANDROIDSHARE
dialog::addItem("SHARE", 's'-96);
dialog::addItem(XLAT("SHARE"), 's'-96);
#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_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5;
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();
else if(uni == 'o') setAppropriateOverview();
else if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
#ifndef NOSAVE
else if(uni == 't') {
if(!canmove) restartGame();
@ -8669,49 +8670,50 @@ void handleKeyNormal(int sym, int uni, extra& ev) {
}
#endif
if(DEFAULTCONTROL) {
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(sym == '.' || sym == 's') movepcto(-1, 1);
if(uni == '%' && sym == '5') {
if(vid.wallmode == 0) vid.wallmode = 6;
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)
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(playermoved && items[itStrongWind]) {
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;
}
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();
/* if(sym == SDLK_F6) {
@ -8774,7 +8776,7 @@ void handleKeyNormal(int sym, int uni, extra& ev) {
cmode = emDraw;
} */
if(sym == 'v') {
if(sym == 'v' && DEFAULTNOR(sym)) {
cmode = emMenu;
}
@ -8826,7 +8828,7 @@ void handlekey(int sym, int uni, extra& ev) {
if(tour::on && tour::handleKeyTour(sym, uni)) return;
#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
if(sym == SDLK_RIGHT) {
if(conformal::on)

View File

@ -70,6 +70,15 @@ eItem readItem(const char *s) {
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() {
printf("HyperRogue by Zeno Rogue <zeno@attnam.com>, version " VER "\n");
@ -121,6 +130,13 @@ int arg::readCommon() {
shift(); eItem i = readItem(args());
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")) {
printf("Treasures:\n");
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;
fp43.init(p);
}
else if(argis("-tpar")) {
shift(); sscanf(args(), "%d,%d,%d",
&torusconfig::qty,
&torusconfig::dx,
&torusconfig::dy
);
}
else if(argis("-cs")) {
shift();
fieldpattern::matrix M = fp43.strtomatrix(args());

View File

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

View File

@ -1,12 +1,17 @@
// Hyperbolic Rogue
// 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;
#define euclid (geometry == gEuclid)
#define euclid (geometry == gEuclid || geometry == gTorus)
#define sphere (geometry == gSphere || geometry == gElliptic)
#define elliptic (geometry == gElliptic)
#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
bool purehepta = false;

View File

@ -1,6 +1,6 @@
#define VER "9.4k"
#define VERNUM 9411
#define VERNUM_HEX 0x9411
#define VER "9.4l"
#define VERNUM 9412
#define VERNUM_HEX 0x9412
#define GEN_M 0
#define GEN_F 1
@ -186,6 +186,7 @@ typedef int SDL_Event;
#undef TOUR
#else
#include <functional>
#include <memory>
#endif
#include <cmath>
@ -199,6 +200,8 @@ typedef int SDL_Event;
#include <map>
#include <queue>
#include <array>
#ifdef USE_UNORDERED_MAP
#include <unordered_map>
#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)) {
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;
@ -484,7 +487,7 @@ void mobile_draw(MOBPAR_FORMAL) {
safety = false;
vid.fsize = (min(vid.xres, vid.yres) * fontscale + 50) / 3200;
hyperpoint mouseoh = mouseh;
mouseoh = mouseh;
gtouched = mousepressed = clicked;
longclick = lclicked && ticks > touchedAt + 500;
@ -592,7 +595,7 @@ void mobile_draw(MOBPAR_FORMAL) {
if((cmode != emVisual1 && cmode != emScores)) {
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);
}
}

View File

@ -98,7 +98,7 @@ int isNative(eLand l, eMonster m) {
case laDeadCaves:
return (m == moEarthElemental || m == moDarkTroll) ? 2 :
m == moGoblin ? 1 : 0;
(m == moGoblin || m == moSeep) ? 1 : 0;
case laPower:
return (isWitch(m) || m == moEvilGolem) ? 1 : 0;
@ -319,7 +319,7 @@ struct orbinfo {
eItem orb;
};
orbinfo orbinfos[ORBLINES] = {
const orbinfo orbinfos[ORBLINES] = {
{laGraveyard, 200, 200,itGreenStone}, // must be first so that it does not reduce
// chance of other orbs
{laJungle, 1200, 1500,itOrbLightning},
@ -546,6 +546,9 @@ eOrbLandRelation getOLR(eItem it, eLand l) {
l == laMountain || l == laReptile || l == laDungeon)
return olrUseless;
if(it == itOrbWinter && l == laMinefield)
return olrForbidden;
if(it == itOrbWinter && l != laRlyeh && l != laTemple)
return olrUseless;
@ -1017,7 +1020,7 @@ void placePrizeOrb(cell *c) {
if(l == laPalace && princess::dist(c) < OUT_OF_PRISON)
l = laPrincessQuest;
for(int i=0; i<ORBLINES; i++) {
orbinfo& oi(orbinfos[i]);
const orbinfo& oi(orbinfos[i]);
eOrbLandRelation olr = getOLR(oi.orb, l);
if(olr != olrPrize25 && olr != olrPrize3) continue;
int treas = items[treasureType(oi.l)];
@ -1050,7 +1053,7 @@ void placeLocalOrbs(cell *c) {
if(isElemental(l)) l = laElementalWall;
for(int i=0; i<ORBLINES; i++) {
orbinfo& oi(orbinfos[i]);
const orbinfo& oi(orbinfos[i]);
if(oi.l != l) continue;
if(yendor::on && (oi.orb == itOrbSafety || oi.orb == itOrbYendor))
continue;
@ -1072,7 +1075,7 @@ void placeLocalOrbs(cell *c) {
void placeCrossroadOrbs(cell *c) {
for(int i=0; i<ORBLINES; i++) {
orbinfo& oi(orbinfos[i]);
const orbinfo& oi(orbinfos[i]);
if(!oi.gchance) continue;
int treas = items[treasureType(oi.l)] * landMultiplier(oi.l);
if(tactic::on && isCrossroads(tactic::lasttactic)) {
@ -1095,7 +1098,7 @@ void placeCrossroadOrbs(cell *c) {
void placeOceanOrbs(cell *c) {
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(!oi.gchance) continue;
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 == laCamelot && !tactic::on) setland(c, laCrossroads);
if(euclid) setLandEuclid(c);
if(sphere) setLandSphere(c);
if(sphere || torus) setLandSphere(c);
else if(euclid) setLandEuclid(c);
if(quotient) { setland(c, euclidland); setLandQuotient(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(randomPatternsMode)
c->wall = RANDPAT3(0) ? waCavewall : waCavefloor;
else if(torus) ;
else if(euclid) {
eucoord x, y;
decodeMaster(c->master, x, y);
@ -3483,6 +3487,7 @@ void setdist(cell *c, int d, cell *from) {
int v;
if(randomPatternsMode)
v = RANDPAT ? 24 : 0;
else if(torus) ;
else if(euclid) {
eucoord 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(euclid) {
if(torus) ;
else if(euclid) {
eucoord x, y;
decodeMaster(c->master, x, y);
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(euclid) {
if(torus) ;
else if(euclid) {
eucoord x, y;
decodeMaster(c->master, x, y);
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(euclid) {
if(torus) ;
else if(euclid) {
eucoord x, y;
decodeMaster(c->master, x, y);
if(short(x+1)%3 == 0 && short(y)%3 == 0) {
@ -4628,8 +4636,24 @@ void setdist(cell *c, int d, cell *from) {
cw.c->monst = moMouse;
}
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) {
@ -4936,22 +4960,6 @@ void setdist(cell *c, int d, cell *from) {
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(hrand(4500) < items[itWindstone] + hard)
c->monst = moWindCrow;
@ -5280,8 +5288,8 @@ void wandering() {
if(cwt.c->land == laZebra && cwt.c->wall == waNone && wchance(items[itZebra], 20))
wanderingZebra(cwt.c);
if(sphere || quotient == 1) {
if(smallbounded) {
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-1) { first7 = i; break; }
@ -5295,7 +5303,7 @@ void wandering() {
int i = first7 + hrand(size(dcal) - first7);
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(!haveOrbPower() && euclidland != laHell) for(int it=0; it<1000 && !c->item; it++)
placeLocalOrbs(c);
@ -5314,7 +5322,7 @@ void wandering() {
if(!c->monst) c->stuntime = 0;
if(timerghost && !sphere && quotient != 1) {
if(timerghost && !smallbounded) {
// wandering seeps & ghosts
if(seepcount && c->wall == waCavewall && !c->monst && canReachPlayer(c, moSlime)) {
c->monst = moSeep;

View File

@ -1231,7 +1231,7 @@ namespace mapeditor {
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;
@ -1368,7 +1368,7 @@ namespace mapeditor {
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);
if(!outofmap(mouseh)) {
if(!mouseout()) {
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*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] = {
"hyperbolic", "Euclidean", "spherical", "elliptic",
"Zebra quotient", "field quotient"
"Zebra quotient", "field quotient", "torus"
};
void showEuclideanMenu() {

View File

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

View File

@ -1008,7 +1008,7 @@ struct monster {
fixmatrix(at); pat = at;
return;
}
if(geometry == gQuotient) {
if(geometry == gQuotient || geometry == gTorus) {
at = inverse(gmatrix[base]) * new_pat;
virtualRebase(this, true);
fixmatrix(at);
@ -1514,10 +1514,14 @@ void movePlayer(monster *m, int delta) {
playerturn[cpid] = mturn * delta / 150.0;
double mdd = hypot(mdx, mdy);
if(mdd > 1e-6) {
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]);
mgo += mdd;
@ -1526,7 +1530,7 @@ void movePlayer(monster *m, int delta) {
#ifndef NOSDL
Uint8 *keystate = SDL_GetKeyState(NULL);
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;
hyperpoint h = inverse(m->pat) * mouseh;
playerturn[cpid] = -atan2(h[1], h[0]);
@ -1843,7 +1847,7 @@ monster *getPlayer() {
}
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->pat = m->at;
return;
@ -1879,7 +1883,7 @@ void moveMimic(monster *m) {
c2->wall = waNone;
}
if(!quotient && c2->cpdist >= 6)
if(!doall && c2->cpdist >= 6)
m->dead = true;
}
@ -2077,7 +2081,7 @@ void moveBullet(monster *m, int delta) {
m->rebasePat(nat);
// 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]))
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) {
lmousetarget = NULL;
@ -2733,7 +2747,7 @@ void turn(int delta) {
invismove = (curtime >= visibleAt) && markOrb(itOrbInvis);
// detect active monsters
if(quotient)
if(doall)
for(cell *c: currentmap->allcells()) activateMonstersAt(c);
else
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;
transmatrix view = V * m->at;
if(!outofmap(mouseh)) {
if(!mouseout()) {
#ifdef ROGUEVIZ
if(rogueviz::virt(m)) ; else
#endif
@ -3039,6 +3053,7 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
hyperpoint h = keytarget(cpid);
queuechr(h, vid.fsize, '+', iinf[keyresult[cpid]].color);
}
break;
case moBullet: {
int col;
@ -3172,8 +3187,6 @@ transmatrix calc_relative_matrix(cell *c, heptagon *h1) {
return gm * where;
}
transmatrix ztmp;
transmatrix &ggmatrix(cell *c) {
transmatrix& t = gmatrix[c];
if(t[2][2] == 0) {
@ -3183,6 +3196,11 @@ transmatrix &ggmatrix(cell *c) {
printf("error: gmatrix0 not known\n");
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) {
eucoord xh, yh, xc, yc;
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) {
if(euclid || sphere) {
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;
if(hypot(tC0(newat)[0], tC0(newat)[1])
< hypot(tC0(at)[0], tC0(at)[1])) {