Snakes Nest v1

This commit is contained in:
Zeno Rogue 2017-12-05 19:43:45 +01:00
parent 9b2f9ecc14
commit 87b6b8b372
11 changed files with 145 additions and 71 deletions

View File

@ -1202,6 +1202,7 @@ itemtype iinf[ittypes] = {
"This ranged Orb will transform the target monster into one without any special powers. It also stuns them for one turn. "
"Does not affect multi-tile monsters."},
{ '!', 0x80FF00, "Glowing Crystal", crystaldesc},
{ '!', 0x80FF80, "Snake Oil", NODESCYET},
};
// --- wall types ---
@ -1563,7 +1564,8 @@ const landtype linf[landtypes] = {
{ 0x207068, "Hunting Ground", huntingdesc},
{ 0xE2725B, "Terracotta Army", terraldesc},
{ 0xE2725B, "Terracotta Army", terraldesc},
{ 0x80FF00, "Crystal World", crystaldesc}
{ 0x80FF00, "Crystal World", crystaldesc},
{ 0x306030, "Snake Nest", NODESCYET},
};
struct landtacinfo { eLand l; int tries, multiplier; };

View File

@ -68,7 +68,7 @@ struct genderswitch_t {
#define NUM_GS 6
static const int ittypes = 122;
static const int ittypes = 123;
struct itemtype {
char glyph;
@ -112,7 +112,7 @@ enum eItem {
itInventory,
itLavaLily, itHunting, itBlizzard, itTerra,
itOrbSide1, itOrbSide2, itOrbSide3,
itOrbLava, itOrbMorph, itGlowCrystal
itOrbLava, itOrbMorph, itGlowCrystal, itSnake
};
static const int walltypes = 105;
@ -158,7 +158,7 @@ enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCav
waArrowTrap, waMercury, waMagma
};
static const int landtypes = 78;
static const int landtypes = 79;
struct landtype {
int color;
@ -184,7 +184,7 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle
laMirrorWall, laMirrored, laMirrorWall2, laMirrored2,
laMirrorOld,
laVolcano, laBlizzard, laHunting, laTerracotta, laMercuryRiver,
laDual
laDual, laSnakeNest
};
enum eGeometry {gNormal, gEuclid, gSphere, gElliptic, gQuotient, gQuotient2, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gGUARD};

View File

@ -21,6 +21,8 @@ bool survivalist;
bool hardcore = false;
int hardcoreAt;
set<int> snaketypes;
flagtype havewhat, hadwhat;
#define HF_BUG Flag(0)
@ -2656,6 +2658,7 @@ void bfs() {
hadwhat = havewhat;
havewhat = 0;
snaketypes.clear();
if(!(hadwhat & HF_WARP)) { avengers = 0; }
if(!(hadwhat & HF_MIRROR)) { mirrorspirits = 0; }
@ -2793,6 +2796,8 @@ void bfs() {
survivalist = false;
if(c2->monst == moHexSnake || c2->monst == moHexSnakeTail) {
havewhat |= HF_HEX;
if(c2->mondir != NODIR)
snaketypes.insert(snake_pair(c2));
if(c2->monst == moHexSnake) hexsnakes.push_back(c2);
else findWormIvy(c2);
}
@ -4374,8 +4379,16 @@ bool goodmount(cell *c, bool mounted) {
else return !isMounted(c);
}
int inpair(cell *c, int colorpair) {
return (colorpair >> pattern_threecolor(c)) & 1;
}
int snake_pair(cell *c) {
return (1 << pattern_threecolor(c)) | (1 << pattern_threecolor(c->mov[c->mondir]));
}
// note: move from 'c' to 'from'!
void hexvisit(cell *c, cell *from, int d, bool mounted) {
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;
@ -4387,10 +4400,10 @@ void hexvisit(cell *c, cell *from, int d, bool mounted) {
if(from->cpdist && (!passable(from, c, P_MONSTER|P_WIND|P_FISH))) return;
if(c->monst == moHexSnake) {
if(c->monst == moHexSnake && snake_pair(c) == colorpair) {
// printf("got snake\n");
if(pseudohept(from)) return;
if(!inpair(from, colorpair)) return;
if(!goodmount(c, mounted)) return;
if(canAttack(c, moHexSnake, from, from->monst, AF_EAT | (mounted ? AF_ONLY_ENEMY : AF_ONLY_FBUG | AF_GETPLAYER))) {
@ -4410,7 +4423,7 @@ void hexvisit(cell *c, cell *from, int d, bool mounted) {
hexdfs.push_back(c);
}
void movehex(bool mounted) {
void movehex(bool mounted, int colorpair) {
sval++;
hexdfs.clear();
@ -4429,29 +4442,29 @@ void movehex(bool mounted) {
for(int i=0; i<size(hexdfs); i++) {
cell *c = hexdfs[i];
int dirtable[10], qdirtable=0;
for(int t=0; t<c->type; t++) if(c->mov[t] && !pseudohept(c->mov[t]))
for(int t=0; t<c->type; t++) if(c->mov[t] && inpair(c->mov[t], colorpair))
dirtable[qdirtable++] = t;
random_shuffle(dirtable, dirtable+qdirtable);
while(qdirtable--) {
int t = dirtable[qdirtable];
hexvisit(c->mov[t], c, t, mounted);
hexvisit(c->mov[t], c, t, mounted, colorpair);
}
}
for(int i=0; i<size(hexsnakes); i++) {
cell *c = hexsnakes[i];
if(c->monst == moHexSnake) {
if(c->monst == moHexSnake && snake_pair(c) == colorpair) {
if(!goodmount(c, mounted)) continue;
int t[MAX_EDGE];
for(int i=0; i<c->type; i++) t[i] = i;
for(int j=1; j<c->type; j++) swap(t[j], t[hrand(j+1)]);
for(int u=0; u<c->type; u++) {
createMov(c, t[u]);
if(!pseudohept(c->mov[t[u]]))
hexvisit(c, c->mov[t[u]], c->spn(t[u]), mounted);
if(inpair(c->mov[t[u]], colorpair))
hexvisit(c, c->mov[t[u]], c->spn(t[u]), mounted, colorpair);
}
}
if(c->monst == moHexSnake) {
if(c->monst == moHexSnake && snake_pair(c) == colorpair) {
snakeAttack(c, mounted);
kills[moHexSnake]++;
playSound(c, "die-troll");
@ -5479,6 +5492,13 @@ void checkAmbushState() {
}
}
void movehex_all() {
for(int i: snaketypes) {
movehex(false, i);
if(!shmup::on && haveMount()) movehex(true, i);
}
}
void movemonsters() {
ambush_distance = 0;
@ -5550,10 +5570,8 @@ void movemonsters() {
savepos[i] = playerpos(i);
moveworms();
if(havewhat & HF_HEX) {
movehex(false);
if(haveMount()) movehex(true);
}
if(havewhat & HF_HEX)
movehex_all();
if(havewhat & HF_KRAKEN) kraken::attacks(), groupmove(moKrakenH, 0);
if(havewhat & HF_DRAGON) groupmove(moDragonHead, MF_NOFRIEND);

View File

@ -1717,6 +1717,12 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
if(isIvy(c) || isWorm(c) || isMutantIvy(c) || c->monst == moFriendlyIvy) {
if((m == moHexSnake || m == moHexSnakeTail) && c->land == laSnakeNest && c->mondir != NODIR) {
int c1 = nestcolors[pattern_threecolor(c)];
int c2 = nestcolors[pattern_threecolor(c->mov[c->mondir])];
col = (c1 + c2); // sum works because they are dark and should be brightened
}
if(isDragon(c->monst) && c->stuntime == 0) col = 0xFF6000;
transmatrix Vb0 = Vb;
@ -1835,8 +1841,10 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
queuepoly(Vbb, shDragonWings, darkena(col, c->hitpoints?0:1, 0xFF));
}
}
else if(!(c->mondir == NODIR && (c->monst == moTentacletail || (c->monst == moWormtail && wormpos(c) < WORMLENGTH))))
queuepoly(Vb, shJoint, darkena(col, 0, 0xFF));
else {
if(!(c->mondir == NODIR && (c->monst == moTentacletail || (c->monst == moWormtail && wormpos(c) < WORMLENGTH))))
queuepoly(Vb, shJoint, darkena(col, 0, 0xFF));
}
}
if(!mmmon) return true;
@ -2407,6 +2415,8 @@ ld wavefun(ld x) {
else return 0; */
}
const unsigned int nestcolors[8] = { 0x800000, 0x008000, 0x000080, 0x404040, 0x700070, 0x007070, 0x707000, 0x606060 };
void setcolors(cell *c, int& wcol, int &fcol) {
wcol = fcol = winf[c->wall].color;
@ -2707,6 +2717,14 @@ void setcolors(cell *c, int& wcol, int &fcol) {
else
fcol = gradient(0xD0D090, 0xD0D020, -1, sin((double) c->landparam), 1);
break;
case laSnakeNest: {
int fv = pattern_threecolor(c);
fcol = nestcolors[fv&7];
if(realred(c->wall))
wcol = fcol * (4 + snakelevel(c)) / 4;
break;
}
default:
if(isElemental(c->land)) fcol = linf[c->land].color;
@ -3133,6 +3151,9 @@ int getfd(cell *c) {
case laReptile:
case laCanvas:
return 0;
case laSnakeNest:
return realred(c->wall) ? 0 : 1;
case laTerracotta:
case laMercuryRiver:
@ -3173,6 +3194,19 @@ int getfd(cell *c) {
return 2;
}
}
int getSnakelevColor(cell *c, int i, int last, int fd, int wcol) {
int col;
if(c->wall == waTower)
col = 0xD0D0D0-i*0x101010;
else if(c->land == laSnakeNest)
return darkena(nestcolors[pattern_threecolor(c)] * (5 + i) / 4, 0, 0xFF);
else if(i == last-1)
col = wcol;
else
col = winf[waRed1+i].color;
return darkena(col, fd, 0xFF);
}
void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
@ -3843,7 +3877,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
else if(c->land == laLivefjord)
qfloor(c, Vf, CAVEFLOOR, darkena(fcol, fd, 0xFF));
else if(c->land == laRedRock)
else if(c->land == laRedRock || c->land == laSnakeNest)
qfloor_eswap(c, Vf, DESERTFLOOR, darkena(fcol, fd, 0xFF));
else if(c->land == laPalace || c->land == laTerracotta)
@ -3917,11 +3951,11 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
if(realred(c->wall) && !wmspatial) {
int s = snakelevel(c);
if(s >= 1)
qfloor(c, V, shRedRockFloor[0][ct6], darkena(winf[waRed1].color, 0, 0xFF));
qfloor(c, V, shRedRockFloor[0][ct6], getSnakelevColor(c, 0, 7, fd, wcol));
if(s >= 2)
queuepoly(V, shRedRockFloor[1][ct6], darkena(winf[waRed2].color, 0, 0xFF));
queuepoly(V, shRedRockFloor[1][ct6], getSnakelevColor(c, 1, 7, fd, wcol));
if(s >= 3)
queuepoly(V, shRedRockFloor[2][ct6], darkena(winf[waRed3].color, 0, 0xFF));
queuepoly(V, shRedRockFloor[2][ct6], getSnakelevColor(c, 2, 7, fd, wcol));
}
if(c->wall == waTower && !wmspatial) {
@ -4076,13 +4110,11 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
bool w = isWarped(c);
warpfloor(c, (*Vdp), darkena(wcol, fd, 0xFF), PPR_REDWALL-4+4*sl, w);
floorShadow(c, V, SHADOW_SL * sl, w);
bool tower = c->wall == waTower;
for(int s=0; s<sl; s++)
forCellIdEx(c2, i, c) {
int sl2 = snakelevel(c2);
if(s >= sl2)
placeSidewallX(c, i, SIDE_SLEV+s, V, w, false,
darkena(tower?0xD0D0D0-i*0x101010 : s==sl-1?wcol:winf[waRed1+s].color, fd, 0xFF));
placeSidewallX(c, i, SIDE_SLEV+s, V, w, false, getSnakelevColor(c, s, sl, fd, wcol));
}
}

View File

@ -2295,3 +2295,8 @@ namespace fieldpattern {
}
int emeraldval(cell *c);
int inpair(cell *c, int colorpair);
int snake_pair(cell *c);
extern const unsigned int nestcolors[8];

View File

@ -1477,30 +1477,8 @@ void giantLandSwitch(cell *c, int d, cell *from) {
int i = -1;
for(int t=0; t<c->type; t++) if(c->mov[t]->mpdist > c->mpdist && !pseudohept(c->mov[t]))
i = t;
if(i != -1 && !peace::on) {
c->monst = moHexSnake;
preventbarriers(c);
int len = nontruncated ? 2 : ROCKSNAKELENGTH;
cell *c2 = c;
vector<cell*> rocksnake;
while(--len) {
rocksnake.push_back(c2);
preventbarriers(c2);
c2->mondir = i;
createMov(c2, i);
int j = c2->spn(i);
cell *c3 = c2->mov[i];
if(c3->monst || c3->bardir != NODIR || c3->wall) break;
c2 = c3;
c2->monst = moHexSnakeTail;
i = (j + (S6==8 ? 4 : (len%2 ? 2 : 4))) % S6;
}
if(size(rocksnake) < ROCKSNAKELENGTH/2 && !nontruncated) {
for(int i=0; i<size(rocksnake); i++)
rocksnake[i]->monst = moNone;
}
else c2->mondir = NODIR;
}
if(i != -1 && !peace::on)
generateSnake(c, i);
}
else if(hrand(16000) < 50+items[itRedGem]+yendor::hardness() && (nontruncated?hrand(10)<3:!ishept(c)) && !c->monst)
c->monst = moRedTroll,
@ -1508,6 +1486,20 @@ void giantLandSwitch(cell *c, int d, cell *from) {
}
break;
case laSnakeNest:
ONEMPTY {
if(hrand(30000) < 30+items[itRedGem]+yendor::hardness() && !c->monst && !c->wall && !peace::on) {
vector<int> gooddir;
for(int t=0; t<c->type; t++) if(c->mov[t]->mpdist > c->mpdist && !pseudohept(c->mov[t]))
gooddir.push_back(t);
if(size(gooddir))
generateSnake(c, gooddir[hrand(size(gooddir))]);
}
else if(hrand(16000) < kills[moHexSnake] * 100 && c->wall == waNone)
c->item = itSnake, c->wall = waRed3;
}
break;
case laWarpSea:
case laWarpCoast:
if(d == 9 && randomPatternsMode)
@ -2055,7 +2047,7 @@ void repairLandgen(cell *c) {
if(c->wall == waIcewall && c->land != laIce && c->land != laCocytus && c->land != laBlizzard)
c->wall = waNone;
if(c->wall == waRed3 && c->land != laRedRock)
if(c->wall == waRed3 && c->land != laRedRock && c->land != laSnakeNest)
c->wall = waNone;
if(c->item == itRedGem && c->land != laRedRock)

View File

@ -200,6 +200,9 @@ int isNative(eLand l, eMonster m) {
case laDual:
return m == moRatling ? 2 : 0;
case laSnakeNest:
return m == moHexSnake ? 2 : 0;
case laCA: return 0;
}
@ -294,6 +297,7 @@ eItem treasureType(eLand l) {
case laBlizzard: return itBlizzard;
case laHunting: return itHunting;
case laDual: return itGlowCrystal;
case laSnakeNest: return itSnake;
case laCA: return itNone;
}
@ -399,7 +403,7 @@ bool landUnlocked(eLand l) {
case laStorms: case laWhirlwind:
return gold() >= R60;
case laWildWest: case laHalloween: case laDual:
case laWildWest: case laHalloween: case laDual: case laSnakeNest:
return false;
case laIce: case laJungle: case laCaves: case laDesert:

View File

@ -1820,10 +1820,8 @@ namespace mapeditor {
return pseudohept(c) ? 0x202020 : 0xC0C0C0;
}
if(whichCanvas == 'T') {
static unsigned int fcol[8] = { 0x800000, 0x008000, 0x000080, 0x404040,
0x800080, 0x008080, 0x808000, 0xD0D0D0 };
int fv = pattern_threecolor(c);
return fcol[fv&7];
return nestcolors[fv&7];
}
return canvasback;
}

View File

@ -626,3 +626,37 @@ void wandering() {
}
}
void generateSnake(cell *c, int i) {
c->monst = moHexSnake;
int cpair = (1<<pattern_threecolor(c)) | (1<<pattern_threecolor(c->mov[i]));
preventbarriers(c);
int len = nontruncated ? 2 : ROCKSNAKELENGTH;
cell *c2 = c;
vector<cell*> rocksnake;
while(--len) {
rocksnake.push_back(c2);
preventbarriers(c2);
c2->mondir = i;
createMov(c2, i);
int j = c2->spn(i);
cell *c3 = c2->mov[i];
if(c3->monst || c3->bardir != NODIR || c3->wall) break;
c2 = c3;
c2->monst = moHexSnakeTail;
i = (j + (c2->type%4 == 0 ? c2->type/2 : (len%2 ? 2 : c2->type - 2))) % S6;
createMov(c2, i);
if(!inpair(c2->mov[i], cpair)) {
vector<int> goodsteps;
for(int i=0; i<c2->type; i++)
if(inpair(c2->mov[i], cpair))
goodsteps.push_back(i);
if(!size(goodsteps)) break;
i = goodsteps[hrand(size(goodsteps))];
}
}
if(size(rocksnake) < ROCKSNAKELENGTH/2 && !nontruncated) {
for(int i=0; i<size(rocksnake); i++)
rocksnake[i]->monst = moNone;
}
else c2->mondir = NODIR;
}

View File

@ -677,24 +677,13 @@ int pattern_threecolor(cell *c) {
if(S7 == 3 && nontruncated)
return c->master->fiftyval;
if(euclid) return eupattern(c);
return 3;
return ishept(c);
}
// returns ishept in the normal tiling;
// in the 'pure heptagonal' tiling, returns true for a set of cells
// which roughly corresponds to the heptagons in the normal tiling
bool pseudohept(cell *c) {
if(nontruncated) {
if(bigsphere)
return
c->master == getDodecahedron(3) ||
c->master == getDodecahedron(5) ||
c->master == getDodecahedron(6);
if(S7 == 3)
return c->master == getDodecahedron(0);
else
return pattern_threecolor(c) == 0;
}
else return ishept(c);
return pattern_threecolor(c) == 0;
}

View File

@ -2961,7 +2961,7 @@ void turn(int delta) {
moveworms();
moveivy();
movemutant();
if(havewhat&HF_HEX) movehex(false);
if(havewhat&HF_HEX) movehex_all();
wandering();
livecaves();
terracotta();