1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-06-24 22:23:18 +00:00

Merge branch 'master' into misc-windows

This commit is contained in:
Zeno Rogue 2018-06-28 15:13:42 +02:00 committed by GitHub
commit 0d0eb06886
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 400 additions and 330 deletions

View File

@ -970,15 +970,6 @@ int wallchance(cell *c, bool deepOcean) {
50;
}
bool mouse_reachability_test(cell *c) {
if(c->pathdist != PINFD)
return true;
forCellEx(c2, c)
if(passable(c, c2, 0) && c2->mpdist < c->mpdist)
return mouse_reachability_test(c2);
return false;
}
bool horo_ok() {
// do the horocycles work in the current geometry?
// (they work in ALL hyperbolic geometries currently!)
@ -1139,7 +1130,7 @@ void buildBigStuff(cell *c, cell *from) {
createAlternateMap(c, 2, hsA);
if(c->land == laPalace && ctof(c) && !princess::generating && !shmup::on && multi::players == 1 && horo_ok() && !weirdhyperbolic &&
(princess::forceMouse ? mouse_reachability_test(from) :
(princess::forceMouse ? canReachPlayer(from, moMouse) :
(hrand(2000) < (peace::on ? 100 : 20))) &&
!c->master->alt &&
(princess::challenge || kills[moVizier] || peace::on) && !tactic::on && !yendor::on) {

View File

@ -59,7 +59,7 @@ vector<blizzardcell*> bcells;
int N;
blizzardcell* getbcell(cell *c) {
int i = c->aitmp;
int i = c->listindex;
if(i<0 || i >= N) return NULL;
if(bcells[i]->c != c) return NULL;
return bcells[i];
@ -80,8 +80,8 @@ void drawBlizzards() {
N = isize(bcells);
for(int i=0; i<N; i++) {
auto& bc = *bcells[i];
bc.tmp = bc.c->aitmp,
bc.c->aitmp = i;
bc.tmp = bc.c->listindex,
bc.c->listindex = i;
bc.gm = &gmatrix[bc.c];
bc.wmap = windmap::at(bc.c);
}
@ -223,7 +223,7 @@ void drawBlizzards() {
}
for(auto bc: bcells)
bc->c->aitmp = bc->tmp;
bc->c->listindex = bc->tmp;
}
vector<cell*> arrowtraps;

View File

@ -2513,3 +2513,15 @@ non-game:
2018.06.24 01:19 Update 10.4g
- fixed Arrow Traps not killing anything (and possibly other similar cases)
- fixed the 'skip start menu' option
2018.06.28 14:14 Update 10.4h
- fixed the map not being generated far enough in non-std geometries after Teleport (and other orbs)
- fixed the missing message when picking up orbs from a boat
- rewritten various pathfinding (and similar) algorithms in a more robust way
- Orb of Freedom is now checked after the Terracotta Warriors, and it consider active arrow traps as impassable
- kills-at-once achievements now also count the 'original' kill; it no longer counts if a monster performs the killing
- in quotient geometries, the whole world is now generated from the start (otherwise e.g. Blizzard breaks down); also the windmap (used in Blizzard/Volcanic) is now generated correctly in field quotient
- an option to display all floors as 'full', i.e., without spaces between them ('r' in map/graphics editor)
- new commandline options: -fsh (floor shape display) and -noshadow (disable shadows)
- fixed a bug with Orb of Mirror display in OSM

File diff suppressed because one or more lines are too long

View File

@ -823,24 +823,28 @@ namespace conformal {
else if(doexiton(sym, uni)) popScreen();
}
set<cell*> inmovehistory, inkillhistory, infindhistory;
void restore() {
sval++;
inmovehistory.clear();
inkillhistory.clear();
infindhistory.clear();
for(int i=0; i<isize(movehistory); i++)
movehistory[i]->aitmp = sval;
inmovehistory.insert(movehistory[i]);
sval++;
int sk = isize(killhistory);
for(int i=0; i<sk; i++) {
eMonster m = killhistory[i].second;
killhistory[i].second = killhistory[i].first->monst;
killhistory[i].first->monst = m;
killhistory[i].first->aitmp = sval;
inkillhistory.insert(killhistory[i].first);
}
int si = isize(findhistory);
for(int i=0; i<si; i++) {
eItem m = findhistory[i].second;
findhistory[i].second = findhistory[i].first->item;
findhistory[i].first->item = m;
findhistory[i].first->aitmp = sval;
infindhistory.insert(findhistory[i].first);
}
}

View File

@ -333,7 +333,7 @@ void debugScreen() {
dialog::addSelItem("celldist", its(celldist(mouseover)), 0);
dialog::addSelItem("pathdist", its(mouseover->pathdist), 0);
dialog::addSelItem("celldistAlt", mouseover->master->alt ? its(celldistAlt(mouseover)) : "--", 0);
dialog::addSelItem("temporary", its(mouseover->aitmp), 0);
dialog::addSelItem("temporary", its(mouseover->listindex), 0);
if(gp::on)
dialog::addSelItem("whirl", gp::disp(gp::get_local_info(mouseover).relative), 0);
dialog::addBreak(50);

155
game.cpp
View File

@ -170,7 +170,7 @@ void initcell(cell *c) {
c->cpdist = INFD; // current distance from the player
c->pathdist = PINFD;// current distance from the player, along paths (used by yetis)
c->landparam = 0; c->landflags = 0; c->wparam = 0;
c->aitmp = 0;
c->listindex = -1;
c->wall = waNone;
c->item = itNone;
c->monst = moNone;
@ -2747,12 +2747,32 @@ bool nogoSlow(cell *to, cell *from) {
cell *pd_from;
int pd_range;
void onpath(cell *c, int d) {
c->pathdist = d;
pathq.push_back(c);
}
void onpath(cell *c, int d, int sp) {
c->pathdist = d;
pathq.push_back(c);
reachedfrom.push_back(sp);
}
void clear_pathdata() {
for(auto c: pathq) c->pathdist = PINFD;
pathq.clear();
pathqm.clear();
reachedfrom.clear();
}
int pathlock = 0;
void compute_graphical_distance() {
if(pathlock) { printf("path error: compute_graphical_distance\n"); }
cell *c1 = centerover.c ? centerover.c : pd_from ? pd_from : cwt.c;
int sr = get_sightrange_ambush();
if(pd_from == c1 && pd_range == sr) return;
for(auto c: pathq) c->pathdist = PINFD;
pathq.clear();
clear_pathdata();
pd_from = c1;
pd_range = sr;
@ -2765,23 +2785,14 @@ void compute_graphical_distance() {
if(qb == 0) forCellCM(c1, c) ;
forCellEx(c1, c)
if(c1->pathdist == PINFD)
c1->pathdist = c->pathdist + 1,
pathq.push_back(c1);
onpath(c1, c->pathdist + 1);
}
}
}
void computePathdist(eMonster param) {
pd_from = NULL;
for(auto c: pathq) c->pathdist = PINFD;
pathq.clear();
pathqm.clear();
reachedfrom.clear();
for(int i=0; i<isize(targets); i++) {
pathq.push_back(targets[i]);
targets[i]->pathdist = isPlayerOn(targets[i]) ? 0 : 1;
reachedfrom.push_back(hrand(targets[i]->type));
}
for(cell *c: targets)
onpath(c, isPlayerOn(c) ? 0 : 1, hrand(c->type));
int qtarg = isize(targets);
@ -2818,8 +2829,7 @@ void computePathdist(eMonster param) {
continue;
}
c2->pathdist = d+1;
pathq.push_back(c2); reachedfrom.push_back(c->spn(i));
onpath(c2, d+1, c->spn(i));
}
}
}
@ -3770,6 +3780,8 @@ int moveval(cell *c1, cell *c2, int d, flagtype mf) {
// actually they just run away
if(m == moHunterChanging && c2->pathdist > c1->pathdist) return 1600;
if((mf & MF_PATHDIST) && !pathlock) printf("using MF_PATHDIST without path\n");
if(hunt && (mf & MF_PATHDIST) && c2->pathdist < c1->pathdist && !peace::on) return 1500; // good move
// prefer straight direction when wandering
@ -3941,7 +3953,7 @@ void beastAttack(cell *c, bool player) {
if(c2->monst && c2->stuntime) {
cellwalker bull (c, d);
int subdir = determinizeBullPush(bull);
int pushdir = 0;
int pushdir = NOHINT;
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return passable(c, c2, P_BLOW); }, pushdir);
if(c3 && c3 != c2)
pushMonster(c3, c2, pushdir);
@ -3954,7 +3966,7 @@ void beastAttack(cell *c, bool player) {
if(c2->wall == waThumperOn) {
cellwalker bull (c, d);
int subdir = determinizeBullPush(bull);
int pushdir = 0;
int pushdir = NOHINT;
cell *c3 = determinePush(bull, c2, subdir, [c2] (cell *c) { return canPushThumperOn(c, c2, c); }, pushdir);
if(c3 && c3 != c2)
pushThumper(c2, c3);
@ -4379,7 +4391,7 @@ void removeIvy(cell *c) {
void moveivy() {
if(isize(ivies) == 0) return;
computePathdist(moIvyRoot);
pathdata pd(moIvyRoot);
for(int i=0; i<isize(ivies); i++) {
cell *c = ivies[i];
cell *co = c;
@ -4461,7 +4473,7 @@ bool isTargetOrAdjacent(cell *c) {
void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
if(!c) return;
if(eq(c->aitmp, sval)) return;
if(c->pathdist == 0) return;
if(movtype == moKrakenH && isTargetOrAdjacent(from)) ;
/* else if(passable_for(movtype, from, c, P_ONPLAYER | P_CHAIN | P_MONSTER)) ;
@ -4518,7 +4530,8 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
return;
// in the gravity lands, eagles cannot ascend in their second move
if((mf & MF_ONLYEAGLE) && gravityLevel(c) < gravityLevel(from)) {
c->aitmp = sval; return;
onpath(c, 0);
return;
}
if((mf & MF_NOFRIEND) && isFriendly(c)) return;
if((mf & MF_MOUNT) && !isMounted(c)) return;
@ -4532,12 +4545,12 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
if(c->mov[j] && canAttack(c, c->monst, c->mov[j], c->mov[j]->monst, af)) {
attackMonster(c->mov[j], AF_NORMAL | AF_GETPLAYER | AF_MSG, c->monst);
animateAttack(c, c->mov[j], LAYER_SMALL, j);
c->aitmp = sval;
onpath(c, 0);
// XLATC eagle
return;
}
if(from->cpdist == 0 || from->monst) { c->aitmp = sval; return; }
if(from->cpdist == 0 || from->monst) { onpath(c, 0); return; }
if(movtype == moDragonHead) {
dragon::move(from, c);
@ -4545,15 +4558,15 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
}
moveMonster(from, c, revhint(from, d));
from->aitmp = sval;
onpath(from, 0);
}
c->aitmp = sval;
onpath(c, 0);
// MAXGCELL
if(isize(gendfs) < 1000 || c->cpdist <= 6) gendfs.push_back(c);
}
void groupmove(eMonster movtype, flagtype mf) {
sval++;
pathdata pd(0);
gendfs.clear();
if(mf & MF_MOUNT) {
@ -4602,9 +4615,9 @@ void groupmove(eMonster movtype, flagtype mf) {
if(movtype != moDragonHead) for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
if((mf & MF_ONLYEAGLE) && c->monst != moEagle && c->monst != moBat) return;
if(movegroup(c->monst) == movtype && !eq(c->aitmp, sval)) {
if(movegroup(c->monst) == movtype && c->pathdist != 0) {
cell *c2 = moveNormal(c, mf);
if(c2) c2->aitmp = sval;
onpath(c2, 0);
}
}
}
@ -4665,7 +4678,7 @@ int snake_pair(cell *c) {
void hexvisit(cell *c, cell *from, int d, bool mounted, int colorpair) {
if(!c) return;
if(cellUnstable(c) || cellEdgeUnstable(c)) return;
if(eq(c->aitmp, sval)) return;
if(c->pathdist == 0) return;
if(cellUnstableOrChasm(c) || cellUnstableOrChasm(from)) return;
@ -4690,7 +4703,7 @@ void hexvisit(cell *c, cell *from, int d, bool mounted, int colorpair) {
moveHexSnake(from, c, d, mounted);
}
c->aitmp = sval;
onpath(c, 0);
// MAXGCELL
if(isize(hexdfs) < 2000 || c->cpdist <= 6)
@ -4698,18 +4711,18 @@ void hexvisit(cell *c, cell *from, int d, bool mounted, int colorpair) {
}
void movehex(bool mounted, int colorpair) {
sval++;
pathdata pd(3);
hexdfs.clear();
if(mounted) {
if(dragon::target && dragon::target->monst != moHexSnake) {
hexdfs.push_back(dragon::target);
dragon::target->aitmp = sval;
onpath(dragon::target, 0);
}
}
else for(int i=0; i<isize(targets); i++) {
hexdfs.push_back(targets[i]);
targets[i]->aitmp = sval;
else for(cell *c: targets) {
hexdfs.push_back(c);
onpath(c, 0);
}
//hexdfs.push_back(cwt.c);
@ -4977,8 +4990,10 @@ void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) {
sideAttack(mf, dir, who, 2, itOrbSide2);
sideAttack(mf, dir, who, 3, itOrbSide3);
int kills = tkills() - k + bonuskill;
if(kills >= 5) achievement_gain("MELEE5");
if(who == moPlayer) {
int kills = tkills() - k + bonuskill;
if(kills >= 5) achievement_gain("MELEE5");
}
}
void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill) {
@ -5067,15 +5082,17 @@ void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill) {
}
}
if(numsh) achievement_count("STAB", numsh, 0);
if(who == moPlayer) {
if(numsh) achievement_count("STAB", numsh, 0);
if(numlance && numflail && numsh) achievement_gain("MELEE3");
if(numlance && numflail && numsh) achievement_gain("MELEE3");
if(numlance + numflail + numsh + numslash + bonuskill >= 5) achievement_gain("MELEE5");
if(numsh == 2) {
if(lastdouble == turncount-1) achievement_count("STAB", 4, 0);
lastdouble = turncount;
if(numlance + numflail + numsh + numslash + bonuskill >= 5) achievement_gain("MELEE5");
if(numsh == 2) {
if(lastdouble == turncount-1) achievement_count("STAB", 4, 0);
lastdouble = turncount;
}
}
}
@ -5198,7 +5215,7 @@ int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) {
void movegolems(flagtype flags) {
if(items[itOrbEmpathy] && items[itOrbSlaying])
flags |= AF_CRUSH;
computePathdist(moMouse);
pathdata pd(moMouse);
int qg = 0;
for(int i=0; i<isize(golems); i++) {
cell *c = golems[i];
@ -5363,7 +5380,7 @@ void specialMoves() {
}
if(m == moNecromancer) {
computePathdist(moNecromancer);
pathdata pd(moNecromancer);
int gravenum = 0, zombienum = 0;
cell *gtab[8], *ztab[8];
for(int j=0; j<c->type; j++) if(c->mov[j]) {
@ -5465,7 +5482,7 @@ void specialMoves() {
void moveworms() {
if(!isize(worms)) return;
computePathdist(moWorm);
pathdata pd(moWorm);
int wrm = isize(worms);
for(int i=0; i<wrm; i++) {
moveWorm(worms[i]);
@ -5728,7 +5745,7 @@ void consMove(cell *c, eMonster param) {
}
void moveNormals(eMonster param) {
computePathdist(param);
pathdata pd(param);
for(int d=0; d<8; d++) movesofgood[d].clear();
@ -5749,12 +5766,11 @@ void moveNormals(eMonster param) {
}
}
void markAmbush(cell *c) {
if(eq(c->aitmp, sval)) return;
c->aitmp = sval;
void markAmbush(cell *c, manual_celllister& cl) {
if(!cl.add(c)) return;
forCellEx(c2, c)
if(c2->cpdist < c->cpdist)
markAmbush(c2);
markAmbush(c2, cl);
}
int ambush_distance;
@ -5762,30 +5778,30 @@ bool ambushed;
void checkAmbushState() {
if(havewhat & HF_HUNTER) {
sval++;
manual_celllister cl;
for(cell *c: dcal) {
if(c->monst == moHunterDog) {
if(c->cpdist > ambush_distance)
ambush_distance = c->cpdist;
markAmbush(c);
markAmbush(c, cl);
}
if(c->monst == moHunterGuard && c->cpdist <= 4)
markAmbush(c);
markAmbush(c, cl);
}
if(items[itHunting] > 5 && items[itHunting] <= 22) {
int q = 0;
for(int i=0; i<numplayers(); i++)
forCellEx(c2, playerpos(i))
if(eq(c2->aitmp, sval))
q++;
if(cl.listed(c2))
q++;
if(q == 1) havewhat |= HF_FAILED_AMBUSH;
if(q == 2) {
for(int i=0; i<numplayers(); i++)
forCellEx(c2, playerpos(i))
if(eq(c2->aitmp, sval))
if(cl.listed(c2))
forCellEx(c3, playerpos(i))
if(c3 != c2 && isNeighbor(c2,c3))
if(eq(c3->aitmp, sval))
if(cl.listed(c3))
havewhat |= HF_FAILED_AMBUSH;
}
if(havewhat & HF_FAILED_AMBUSH && ambushed) {
@ -6330,7 +6346,7 @@ void collectMessage(cell *c2, eItem which) {
else if(which == itGreenStone)
addMessage(XLAT("Another Dead Orb."));
else if(itemclass(which) != IC_TREASURE) {
if(c2->wall != waBoat && !inv::activating)
if(!inv::activating)
addMessage(XLAT("You have found %the1!", which));
}
else if(which == itBabyTortoise) {
@ -6509,7 +6525,6 @@ int ambush(cell *c, eItem what) {
celllister cl(c, maxdist, 1000000, NULL);
cell *c0 = c;
int d = 0;
cl.prepare();
int dogs0 = 0;
for(cell *cx: cl.lst) {
int dh = cl.getdist(cx);
@ -7191,15 +7206,15 @@ void monstersTurn() {
heat::processheat();
// if(elec::havecharge) elec::drawcharges();
orbbull::check();
if(!phase1) terracotta();
if(items[itOrbFreedom])
for(int i=0; i<numplayers(); i++)
if(multi::playerActive(i))
checkFreedom(playerpos(i));
orbbull::check();
if(!phase1) terracotta();
DEBT("check");
checkmove();
if(canmove) elec::checklightningfast();
@ -7643,6 +7658,8 @@ bool movepcto(int d, int subdir, bool checkonly) {
} */
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK);
int tk = tkills();
if(goodTortoise) {
items[itBabyTortoise] += 4;
@ -7672,7 +7689,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
}
}
sideAttack(cwt.c, d, moPlayer, 0);
sideAttack(cwt.c, d, moPlayer, tkills() - tk);
lastmovetype = lmAttack; lastmove = c2;
swordAttackStatic();
}

View File

@ -586,7 +586,7 @@ bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks,
poly_outline = OUTLINE_OTHER;
}
if(c && conformal::includeHistory && eq(c->aitmp, sval)) poly_outline = OUTLINE_DEAD;
if(c && conformal::includeHistory && conformal::infindhistory.count(c)) poly_outline = OUTLINE_DEAD;
if(!mmitem && it) return true;
@ -1809,7 +1809,7 @@ bool dont_face_pc = false;
bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
bool darkhistory = conformal::includeHistory && eq(c->aitmp, sval);
bool darkhistory = conformal::includeHistory && conformal::inkillhistory.count(c);
if(doHighlight())
poly_outline =
@ -2981,7 +2981,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
}
case waFloorA: case waFloorB: // isAlch
if(c->item && !(conformal::includeHistory && eq(c->aitmp, sval)))
if(c->item && !(conformal::includeHistory && conformal::infindhistory.count(c)))
fcol = wcol = iinf[c->item].color;
else
fcol = wcol;
@ -3648,7 +3648,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
bool hidden = itemHidden(c);
bool hiddens = itemHiddenFromSight(c);
if(conformal::includeHistory && eq(c->aitmp, sval)) {
if(conformal::includeHistory && conformal::infindhistory.count(c)) {
hidden = true;
hiddens = false;
}
@ -4211,7 +4211,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
queuepoly((*Vdp), shHeptaMarker, wmblack ? 0x80808080 : 0x00000080);
}
if(conformal::includeHistory && eq(c->aitmp, sval-1))
if(conformal::includeHistory && conformal::inmovehistory.count(c))
queuepoly((*Vdp), shHeptaMarker, 0x000000C0);
char xch = winf[c->wall].glyph;

90
hyper.h
View File

@ -2,9 +2,9 @@
// It is quite chaotic.
// version numbers
#define VER "10.4g"
#define VERNUM 10407
#define VERNUM_HEX 0xA0B7
#define VER "10.4h"
#define VERNUM 10408
#define VERNUM_HEX 0xA0B8
#include <stdarg.h>
@ -369,10 +369,7 @@ struct cell : gcell {
// wall parameter, used for remaining power of Bonfires and Thumpers
char wparam;
// 'tmp' is used for:
// pathfinding algorithm used by monsters with atypical movement (which do not use pathdist)
// bugs' pathfinding algorithm
short aitmp;
int listindex;
uint32_t spintable;
int spin(int d) { return tspin(spintable, d); }
@ -1064,6 +1061,7 @@ namespace conformal {
extern vector<pair<cell*, eMonster> > killhistory;
extern vector<pair<cell*, eItem> > findhistory;
extern vector<cell*> movehistory;
extern set<cell*> inmovehistory, inkillhistory, infindhistory;
extern bool includeHistory;
extern ld rotation;
extern int do_rotate;
@ -1199,7 +1197,6 @@ bool isAlchAny(cell *c);
#define MODECODES 255
extern cellwalker cwt; // player character position
extern int sval;
extern array<int, ittypes> items;
extern array<int, motypes> kills;
@ -2546,34 +2543,42 @@ extern vector<hrmap*> allmaps;
// list all cells in distance at most maxdist, or until when maxcount cells are reached
struct celllister {
struct manual_celllister {
vector<cell*> lst;
vector<int> tmps;
vector<int> dists;
void add(cell *c, int d) {
if(eq(c->aitmp, sval)) return;
c->aitmp = sval;
tmps.push_back(c->aitmp);
lst.push_back(c);
dists.push_back(d);
bool listed(cell *c) {
return c->listindex >= 0 && c->listindex < isize(lst) && lst[c->listindex] == c;
}
~celllister() {
for(int i=0; i<isize(lst); i++) lst[i]->aitmp = tmps[i];
bool add(cell *c) {
if(listed(c)) return false;
tmps.push_back(c->listindex);
c->listindex = isize(lst);
lst.push_back(c);
return true;
}
~manual_celllister() {
for(int i=0; i<isize(lst); i++) lst[i]->listindex = tmps[i];
}
};
struct celllister : manual_celllister {
vector<int> dists;
void add_at(cell *c, int d) {
if(add(c)) dists.push_back(d);
}
celllister(cell *orig, int maxdist, int maxcount, cell *breakon) {
lst.clear();
tmps.clear();
dists.clear();
sval++;
add(orig, 0);
add_at(orig, 0);
cell *last = orig;
for(int i=0; i<isize(lst); i++) {
cell *c = lst[i];
if(maxdist) forCellCM(c2, c) {
add(c2, dists[i]+1);
add_at(c2, dists[i]+1);
if(c2 == breakon) return;
}
if(c == last) {
@ -2583,16 +2588,7 @@ struct celllister {
}
}
void prepare() {
for(int i=0; i<isize(lst); i++) lst[i]->aitmp = i;
}
int getdist(cell *c) { return dists[c->aitmp]; }
bool listed(cell *c) {
return c->aitmp >= 0 && c->aitmp < isize(lst) && lst[c->aitmp] == c;
}
int getdist(cell *c) { return dists[c->listindex]; }
};
hrmap *newAltMap(heptagon *o);
@ -3569,4 +3565,28 @@ bool confusingGeometry();
int revhint(cell *c, int hint);
extern int pathlock;
extern void computePathdist(eMonster m);
extern void onpath(cell *c, int d);
extern void clear_pathdata();
struct pathdata {
void checklock() {
if(pd_from) pd_from = NULL, clear_pathdata();
if(pathlock) printf("path error\n");
pathlock++;
}
~pathdata() {
pathlock--;
clear_pathdata();
}
pathdata(eMonster m) {
checklock();
computePathdist(m);
}
pathdata(int i) {
checklock();
}
};
}

View File

@ -60,12 +60,8 @@ bool reptilecheat = false;
#define ONEMPTY if(d == 7 && passable(c, NULL, 0) && !safety)
vector<cell*> noescape_list;
bool blizzard_no_escape1(cell *c) {
if(c->aitmp >= 0 && c->aitmp < isize(noescape_list) && noescape_list[c->aitmp] == c)
return true;
c->aitmp = isize(noescape_list); noescape_list.push_back(c);
bool blizzard_no_escape1(cell *c, manual_celllister &cl) {
if(!cl.add(c)) return true;
if(c->item == itOrbSafety)
return false;
forCellEx(c2, c) {
@ -73,16 +69,15 @@ bool blizzard_no_escape1(cell *c) {
continue;
if(c2->land != laBlizzard && passable(c2, NULL, 0))
return false;
if(!againstWind(c2, c) && !blizzard_no_escape1(c2))
if(!againstWind(c2, c) && !blizzard_no_escape1(c2, cl))
return false;
}
return true;
}
bool blizzard_no_escape(cell *c) {
sval++;
noescape_list.resize(0);
return blizzard_no_escape1(c);
manual_celllister cl;
return blizzard_no_escape1(c, cl);
}
bool out_ruin(cell *c) {
@ -383,7 +378,7 @@ void giantLandSwitch(cell *c, int d, cell *from) {
c->monst = moVizier;
c->hitpoints = palaceHP();
}
else if(princess::forceVizier && from->pathdist != PINFD) {
else if(princess::forceVizier && hrand(100) < 10 && canReachPlayer(c, moVizier)) {
c->monst = moVizier;
c->hitpoints = palaceHP();
princess::forceVizier = false;

View File

@ -267,8 +267,9 @@ namespace mapstream {
c->bardir = NOBARRIERS;
// fixspin(rspin, loadChar(), c->type);
if(vernum < 7400) {
load(c->aitmp);
c->wparam = c->aitmp;
short z;
load(z);
c->wparam = z;
}
else load(c->wparam);
load(c->landparam);
@ -620,7 +621,7 @@ namespace mapeditor {
vector<pair<cellwalker, cellwalker> > spill_list;
void list_spill(cellwalker tgt, cellwalker src) {
void list_spill(cellwalker tgt, cellwalker src, manual_celllister& cl) {
spill_list.clear(); sval++;
spill_list.emplace_back(tgt, src);
int crad = 0, nextstepat = 0;
@ -633,8 +634,7 @@ namespace mapeditor {
for(int i=0; i<sd.first.c->type; i++) {
auto sd2 = sd;
sd2.first = sd2.first + i + wstep;
if(eq(sd2.first.c->aitmp, sval)) continue;
sd2.first.c->aitmp = sval;
if(!cl.add(sd2.first.c)) continue;
if(sd2.second.c) {
sd2.second = sd2.second + i + wstep;
if(sd2.second.c->land == laNone) continue;
@ -668,7 +668,7 @@ namespace mapeditor {
}
#endif
void editAt(cellwalker where) {
void editAt(cellwalker where, manual_celllister& cl) {
if(painttype == 4 && radius) {
if(where.c->type != copysource.c->type) return;
@ -677,7 +677,7 @@ namespace mapeditor {
where += 1;
}
if(painttype != 4) copysource.c = NULL;
list_spill(where, copysource);
list_spill(where, copysource, cl);
for(auto& st: spill_list)
editCell(st);
@ -685,34 +685,30 @@ namespace mapeditor {
void allInPattern(cellwalker where) {
manual_celllister cl;
if(!patterns::whichPattern) {
editAt(where);
editAt(where, cl);
return;
}
vector<cell*> v;
v.push_back(where.c);
sval++;
where.c->aitmp = sval;
cl.add(where.c);
int at = 0;
while(at < isize(v)) {
cell *c2 = v[at];
while(at < isize(cl.lst)) {
cell *c2 = cl.lst[at];
at++;
forCellEx(c3, c2)
if(!eq(c3->aitmp, sval))
c3->aitmp = sval, v.push_back(c3);
forCellEx(c3, c2) cl.add(c3);
}
auto si = patterns::getpatterninfo0(where.c);
int cdir = where.spin;
if(cdir >= 0) cdir = cdir - si.dir;
for(cell* c2: v) {
for(cell* c2: cl.lst) {
auto si2 = patterns::getpatterninfo0(c2);
if(si2.id == si.id) {
editAt(cellwalker(c2, cdir>=0 ? fixdir(cdir + si2.dir, c2) : -1));
editAt(cellwalker(c2, cdir>=0 ? fixdir(cdir + si2.dir, c2) : -1), cl);
modelcell[si2.id] = c2;
}
}

View File

@ -242,18 +242,17 @@ int getSeepcount() {
}
bool canReachPlayer(cell *cf, eMonster m) {
vector<cell*> v;
sval++;
v.push_back(cf); cf->aitmp = sval;
for(int i=0; i<isize(v); i++) {
cell *c = v[i];
manual_celllister cl;
cl.add(cf);
for(int i=0; i<isize(cl.lst) && i < 10000; i++) {
cell *c = cl.lst[i];
for(int j=0; j<c->type; j++) {
cell *c2 = c->mov[j];
if(!c2) continue;
if(eq(c2->aitmp, sval)) continue;
if(cl.listed(c2)) continue;
if(!passable_for(m, c2, c, P_MONSTER | P_ONPLAYER | P_CHAIN)) continue;
if(isPlayerOn(c2)) return true;
c2->aitmp = sval; v.push_back(c2);
cl.add(c2);
}
}
return false;
@ -304,6 +303,7 @@ eItem wanderingTreasure(cell *c) {
void wandering() {
if(!canmove) return;
pathdata pd(moYeti);
int seepcount = getSeepcount();
int ghostcount = getGhostcount();
if(cwt.c->land == laCA) ghostcount = 0;

View File

@ -247,29 +247,24 @@ bool distanceBound(cell *c1, cell *c2, int d) {
}
void checkFreedom(cell *cf) {
sval++;
static vector<cell*> avcells;
avcells.clear();
avcells.push_back(cf);
cf->aitmp = sval;
for(int i=0; i<isize(avcells); i++) {
cell *c = avcells[i];
manual_celllister cl;
cl.add(cf);
for(int i=0; i<isize(cl.lst); i++) {
cell *c = cl.lst[i];
if(c->cpdist >= 5) return;
for(int i=0; i<c->type; i++) {
cell *c2 = c->mov[i];
// todo leader
if(cl.listed(c2)) continue;
if(!passable(c2, c, P_ISPLAYER | P_MIRROR | P_LEADER)) continue;
if(eq(c2->aitmp, sval)) continue;
if(c2->wall == waArrowTrap && c2->wparam == 2) continue;
bool monsterhere = false;
for(int j=0; j<c2->type; j++) {
cell *c3 = c2->mov[j];
if(c3 && c3->monst && !isFriendly(c3))
monsterhere = true;
}
if(!monsterhere) {
c2->aitmp = sval;
avcells.push_back(c2);
}
if(!monsterhere) cl.add(c2);
}
}
addMessage(XLAT("Your %1 activates!", itOrbFreedom));
@ -541,8 +536,7 @@ void teleportTo(cell *dest) {
drainOrb(itOrbTeleport);
movecost(cwt.c, dest);
playerMoveEffects(cwt.c, dest);
for(int i=9; i>=0; i--)
setdist(dest, i, NULL);
afterplayermoved();
bfs();
}
return;
@ -557,9 +551,7 @@ void teleportTo(cell *dest) {
addMessage(XLAT("You teleport to a new location!"));
mirror::destroyAll();
for(int i=9; i>=0; i--)
setdist(cwt.c, i, NULL);
afterplayermoved();
bfs();
sword::reset();
@ -1179,11 +1171,13 @@ eItem targetRangedOrb(cell *c, orbAction a) {
}
// (4a) colt
if(!shmup::on && items[itRevolver] && c->monst && canAttack(cwt.c, moPlayer, c, c->monst, AF_GUN)
&& c->pathdist <= GUNRANGE && !monstersnearO(a, cwt.c, c, moPlayer, NULL, cwt.c)) {
if(!isCheck(a)) gun_attack(c);
return itRevolver;
}
if(!shmup::on && items[itRevolver] && c->monst && canAttack(cwt.c, moPlayer, c, c->monst, AF_GUN)) {
pathdata pd(moEagle);
if(c->pathdist <= GUNRANGE && !monstersnearO(a, cwt.c, c, moPlayer, NULL, cwt.c)) {
if(!isCheck(a)) gun_attack(c);
return itRevolver;
}
}
// (5) psi blast (non-shmup variant)
if(!shmup::on && items[itOrbPsi] && c->monst && (isDragon(c->monst) || !isWorm(c)) && c->monst != moShadow && c->monst != moKrakenH) {

View File

@ -388,6 +388,8 @@ void bantar_frame() {
case 4:
xdst = .5, ydst = 0;
break;
default:
xdst = ydst = 0;
}
/* ld xpos = (!(i&2)) ? xdst : -xdst;

View File

@ -287,15 +287,15 @@ struct cellcrawler {
vector<cellcrawlerdata> data;
void store(const cellwalker& o, int from, int spin) {
if(eq(o.c->aitmp, sval)) return;
o.c->aitmp = sval;
void store(const cellwalker& o, int from, int spin, manual_celllister& cl) {
if(!add(o.c)) return;
data.emplace_back(o, from, spin);
}
void build(const cellwalker& start) {
sval++;
data.clear();
manual_celllister cl;
store(start, 0, 0);
for(int i=0; i<isize(data); i++) {
cellwalker cw0 = data[i].orig;
@ -593,6 +593,8 @@ void showbestsamples() {
if(whowon[i])
whowon[i]->samples++;
}
int kohrestrict = 1000000;
void sominit(int initto) {
@ -614,6 +616,11 @@ void sominit(int initto) {
allcells = cl.lst;
}
else allcells = currentmap->allcells();
if(isize(allcells) > kohrestrict) {
sort(allcells.begin(), allcells.end(), [] (cell *c1, cell *c2) { return hdist0(tC0(shmup::ggmatrix(c1))) < hdist0(tC0(shmup::ggmatrix(c2))); });
allcells.resize(kohrestrict);
}
cells = isize(allcells);
net.resize(cells);
@ -1177,6 +1184,9 @@ int readArgs() {
start_game();
verify_crawlers();
}
else if(argis("-somrestrict")) {
shift(); kohrestrict = argi();
}
else return 1;
return 0;

View File

@ -706,6 +706,7 @@ namespace sag {
forgetedges(i);
}
shmup::fixStorage();
}
vector<edgeinfo> sagedges;
@ -815,6 +816,8 @@ namespace sag {
printf("loglikelihood = %lf\n", (double) loglik);
}
ld min_visible_weight = .1;
void readsag(const char *fname) {
maxweight = 0;
FILE *f = fopen(fname, "rt");
@ -869,7 +872,7 @@ namespace sag {
} */
for(int i=0; i<isize(sagedges); i++) {
edgeinfo& ei = sagedges[i];
ei.visible = ei.weight >= 0.1;
ei.visible = ei.weight >= min_visible_weight;
// (ei.weight >= maxwei[ei.i] / 5 || ei.weight >= maxwei[ei.j] / 5);
ei.weight2 = pow((double) ei.weight, (double) edgepower) * edgemul;
@ -1410,6 +1413,9 @@ int readArgs() {
shift(); sag::hightemp = argf();
shift(); sag::lowtemp = argf();
}
else if(argis("-sagmin")) {
shift(); sag::min_visible_weight = argf();
}
// (2) read the edge data
else if(argis("-sagpar")) {
PHASE(3);

View File

@ -2937,19 +2937,12 @@ void turn(int delta) {
for(int t=1; t<motypes; t++) if(exists[t]) {
pd_from = NULL;
pathdata pd(1);
// build the path data
int pqs = isize(pathq);
for(int i=0; i<pqs; i++) {
pathq[i]->pathdist = PINFD;
}
pathq.clear();
for(int i=0; i<isize(targets); i++) {
targets[i]->pathdist = isPlayerOn(targets[i]) ? 0 : 1;
pathq.push_back(targets[i]);
}
for(cell *c: targets)
onpath(c, isPlayerOn(c) ? 0 : 1);
int qb = 0;
for(qb=0; qb < isize(pathq); qb++) {
@ -2961,8 +2954,7 @@ void turn(int delta) {
// printf("i=%d cd=%d\n", i, c->mov[i]->cpdist);
if(c2 && c2->pathdist == PINFD && gmatrix.count(c2) &&
(passable_for(eMonster(t), c, c2, P_CHAIN | P_ONPLAYER) || c->wall == waThumperOn)) {
c2->pathdist = d+1;
pathq.push_back(c2);
onpath(c2, d+1);
}
}
}

View File

@ -291,6 +291,9 @@ void initgame() {
bfs();
checkmove();
playermoved = true;
if(quotient || sphere)
for(cell *c: currentmap->allcells()) setdist(c, 8, NULL);
if(!cheater) gamerange_bonus = genrange_bonus = 0;
}

View File

@ -1011,14 +1011,14 @@ namespace peace {
clister.emplace_back(cp, cp);
int id = 0;
sval++;
manual_celllister cl;
while(id < isize(clister)) {
cell *c = clister[id].first;
cell *fr = clister[id].second;
setdist(c, 5, NULL);
forCellEx(c2,c)
if(!eq(c2->aitmp, sval) && passable(c2, c, 0) && (c2->land == specialland || c2->land == laTemple) && !c2->item) {
if(!cl.listed(c2) && passable(c2, c, 0) && (c2->land == specialland || c2->land == laTemple) && !c2->item) {
if(!id) fr = c2;
bool next;
if(specialland == laRlyeh)
@ -1031,7 +1031,7 @@ namespace peace {
goto again;
}
clister.emplace_back(c2, fr);
c2->aitmp = sval;
cl.add(c2);
}
id++;
}