diff --git a/cell.cpp b/cell.cpp index 334e554d..3032e195 100644 --- a/cell.cpp +++ b/cell.cpp @@ -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 ,, + int qty = 127*3, dx = -1, dy = 11*2; + } + +int decodeId(heptagon* h); +heptagon* encodeId(int id); + +struct hrmap_torus : hrmap { + + vector all; + vector dists; + + virtual vector& allcells() { return all; } + + cell *gamestart() { + return all[0]; + } + + hrmap_torus() { + using namespace torusconfig; + all.resize(qty); + for(int i=0; imaster = encodeId(i); + } + dx %= qty; + dy %= qty; + for(int i=0; imov[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; imaster)] = 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 (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, cell*> euclidean; cell*& euclideanAt(eucoord x, eucoord y) { + if(torus) { printf("euclideanAt called\n"); exit(1); } hrmap_euclidean* euc = dynamic_cast (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 (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] = { diff --git a/classes.cpp b/classes.cpp index 7d0d167f..c5bf6df4 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1415,7 +1415,7 @@ struct landtype { const char *help; }; -landtype linf[landtypes] = { +const landtype linf[landtypes] = { { 0xFF00FF, "???" , ""}, { 0xC06000, "Great Wall" , ""}, { 0xFF0000, "Crossroads" , diff --git a/complex.cpp b/complex.cpp index 8bb67366..ef45df5f 100644 --- a/complex.cpp +++ b/complex.cpp @@ -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; icpdist > 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; itype; 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& allcells = currentmap->allcells(); int dcs = size(allcells); + for(int i=0; icpdist > 8) break; + if(!doall && c->cpdist > 8) break; if(c->land != laDryForest) continue; - for(int j=0; jtype; 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; iland != laDryForest) continue; if(c->landparam >= 10) makeflame(c, 10, false), c->landparam = 0; } for(int i=0; icpdist > 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; icpdist > 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; icpdist > 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); diff --git a/conformal.cpp b/conformal.cpp index ca12aec9..9e8a10bf 100644 --- a/conformal.cpp +++ b/conformal.cpp @@ -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; diff --git a/game.cpp b/game.cpp index eaaaaee7..77de4beb 100644 --- a/game.cpp +++ b/game.cpp @@ -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) diff --git a/graph.cpp b/graph.cpp index a56d41a2..ae2aef4d 100644 --- a/graph.cpp +++ b/graph.cpp @@ -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) diff --git a/hyper.cpp b/hyper.cpp index aa7cda72..432df068 100644 --- a/hyper.cpp +++ b/hyper.cpp @@ -70,6 +70,15 @@ eItem readItem(const char *s) { return itNone; } +eMonster readMonster(const char *s) { + string ss = s; + for(int i=0; i, 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 +#include #endif #include @@ -199,6 +200,8 @@ typedef int SDL_Event; #include #include +#include + #ifdef USE_UNORDERED_MAP #include #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); } } diff --git a/landgen.cpp b/landgen.cpp index d8acc98d..6b34c49a 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -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; iland == 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; icpdist > maxdist) maxdist = dcal[i]->cpdist; for(int i=0; icpdist >= 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; diff --git a/mapeditor.cpp b/mapeditor.cpp index f752a84b..e71e831d 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -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); diff --git a/menus.cpp b/menus.cpp index 8e0bd55c..553b9719 100644 --- a/menus.cpp +++ b/menus.cpp @@ -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() { diff --git a/rogueviz.cpp b/rogueviz.cpp index 03d09a63..e3152331 100644 --- a/rogueviz.cpp +++ b/rogueviz.cpp @@ -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; irebase(); } @@ -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; } diff --git a/shmup.cpp b/shmup.cpp index b07de5a5..089452e3 100644 --- a/shmup.cpp +++ b/shmup.cpp @@ -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; ibase->type; i++) + if(!doall) for(int i=0; ibase->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 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::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])) {