From 5f5c86e529142a1b0d60545b599e6f97131b7c2f Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Fri, 29 Dec 2017 01:10:47 +0100 Subject: [PATCH] new land: Docks --- classes.cpp | 11 ++++++++++- classes.h | 14 ++++++++------ commandline.cpp | 4 ++++ complex.cpp | 5 +++-- flags.cpp | 10 ++++++---- game.cpp | 17 +++++++++++++++-- graph.cpp | 12 +++++++++++- hyper.h | 1 + landgen.cpp | 28 ++++++++++++++++++++++++++++ landlock.cpp | 11 ++++++++++- monstergen.cpp | 5 +++++ orbgen.cpp | 7 +++++-- orbs.cpp | 1 + pattern2.cpp | 17 +++++++++++++++-- patterns.cpp | 20 ++++++++++++++------ 15 files changed, 136 insertions(+), 27 deletions(-) diff --git a/classes.cpp b/classes.cpp index 557f5509..0fec7182 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1203,6 +1203,8 @@ itemtype iinf[ittypes] = { "Does not affect multi-tile monsters."}, { '!', 0x80FF00, "Glowing Crystal", crystaldesc}, { '!', 0x80FF80, "Snake Oil", NODESCYET}, + { '*', 0x80FF80, "Dock Treasure", NODESCYET}, + { '*', 0x80FF80, "Invix Treasure", NODESCYET}, }; // --- wall types --- @@ -1380,6 +1382,8 @@ walltype winf[walltypes] = { { '^', 0xD00000, "arrow trap", arrowtrapdesc}, { '=', 0xE2E2E2, "mercury river", "A river of mercury."}, { '&', 0xD00000, "lava", lavadesc}, + { '=', 0x804000, "dock", "A dock."}, + { '^', 0xFF8000, "burning dock", "A burning dock."}, }; // --- land types --- @@ -1566,6 +1570,8 @@ const landtype linf[landtypes] = { { 0xE2725B, "Terracotta Army", terraldesc}, { 0x80FF00, "Crystal World", crystaldesc}, { 0x306030, "Snake Nest", NODESCYET}, + { 0x80FF00, "Docks", NODESCYET}, + { 0x306030, "Invisible", NODESCYET}, }; struct landtacinfo { eLand l; int tries, multiplier; }; @@ -1597,7 +1603,10 @@ vector land_tac = { {laCrossroads, 10, 1}, {laCrossroads2, 10, 1}, {laCrossroads3, 10, 1}, {laCrossroads4, 10, 1}, {laCamelot, 1, 100}, - {laWildWest, 10, 1} + {laWildWest, 10, 1}, + {laDual, 10, 1}, + {laSnakeNest, 10, 1}, + {laDocks, 10, 1} }; vector randlands = { diff --git a/classes.h b/classes.h index 52ae8d0c..0d8592a4 100644 --- a/classes.h +++ b/classes.h @@ -68,7 +68,7 @@ struct genderswitch_t { #define NUM_GS 6 -static const int ittypes = 123; +static const int ittypes = 125; struct itemtype { char glyph; @@ -112,10 +112,11 @@ enum eItem { itInventory, itLavaLily, itHunting, itBlizzard, itTerra, itOrbSide1, itOrbSide2, itOrbSide3, - itOrbLava, itOrbMorph, itGlowCrystal, itSnake + itOrbLava, itOrbMorph, itGlowCrystal, itSnake, + itDock, itInvix }; -static const int walltypes = 105; +static const int walltypes = 107; struct walltype { char glyph; @@ -155,10 +156,11 @@ enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCav waPetrifiedBridge, waTempBridgeBlocked, waTerraWarrior, waBubble, - waArrowTrap, waMercury, waMagma + waArrowTrap, waMercury, waMagma, + waDock, waBurningDock }; -static const int landtypes = 79; +static const int landtypes = 81; struct landtype { int color; @@ -184,7 +186,7 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle laMirrorWall, laMirrored, laMirrorWall2, laMirrored2, laMirrorOld, laVolcano, laBlizzard, laHunting, laTerracotta, laMercuryRiver, - laDual, laSnakeNest + laDual, laSnakeNest, laDocks, laInvincible }; enum eGeometry {gNormal, gEuclid, gSphere, gElliptic, gQuotient, gQuotient2, gTorus, gOctagon, g45, g46, g47, gSmallSphere, gTinySphere, gEuclidSquare, gGUARD}; diff --git a/commandline.cpp b/commandline.cpp index 5cda7f84..7ee3c91b 100644 --- a/commandline.cpp +++ b/commandline.cpp @@ -84,8 +84,12 @@ int arg::readCommon() { char *c = args(); using namespace patterns; subpattern_flags = 0; + whichPattern = 0; while(*c) { if(*c >= '0' && *c <= '9') subpattern_flags ^= 1 << (*c - '0'); + else if(*c == '@') subpattern_flags ^= 1 << 10; + else if(*c == '-') subpattern_flags ^= 1 << 11; + else if(*c == '~') subpattern_flags ^= 1 << 12; else whichPattern = *c; c++; } diff --git a/complex.cpp b/complex.cpp index 9166b0af..12eb099c 100644 --- a/complex.cpp +++ b/complex.cpp @@ -1994,7 +1994,8 @@ namespace heat { } else if(c2->wall == waVinePlant || c2->wall == waRose || c2->wall == waSaloon || c2->wall == waWeakBranch || c2->wall == waCanopy || c2->wall == waTrunk || c2->wall == waSolidBranch || - c2->wall == waBigBush || c2->wall == waSmallBush || c2->wall == waBonfireOff || c2->wall == waSmallTree) + c2->wall == waBigBush || c2->wall == waSmallBush || c2->wall == waBonfireOff || c2->wall == waSmallTree || + c2->wall == waDock) newfires.emplace_back(c2, 12); else if(cellHalfvine(c2) && last && last->wall == c2->wall) newfires.emplace_back(c2, 12); @@ -2005,7 +2006,7 @@ namespace heat { } if(hasTimeout(c)) { - if(c->mpdist == 8 && (c->land == laWineyard || c->land == laEndorian)) { + if(c->mpdist == 8 && (c->land == laWineyard || c->land == laEndorian || c->land == laDocks)) { // do not expire, do not store in 'offscreen', do not generate more land } else { diff --git a/flags.cpp b/flags.cpp index 41cbdf2c..3c50f4c4 100644 --- a/flags.cpp +++ b/flags.cpp @@ -46,7 +46,7 @@ bool boatStrandable(cell *c) { // monster/wall types bool isFire(cell *w) { - return w->wall == waFire || w->wall == waPartialFire || w->wall == waEternalFire; + return w->wall == waFire || w->wall == waPartialFire || w->wall == waEternalFire || w->wall == waBurningDock; } bool isFireOrMagma(cell *w) { @@ -68,7 +68,7 @@ bool isActivable(cell *c) { bool hasTimeout(cell *c) { return c->wall == waThumperOn || c->wall == waFire || c->wall == waPartialFire || c->wall == waTempWall || c->wall == waTempFloor || c->wall == waTempBridge || - c->wall == waTempBridgeBlocked; + c->wall == waTempBridgeBlocked || c->wall == waBurningDock; } bool isMimic(eMonster m) { @@ -275,7 +275,8 @@ int itemclass(eItem i) { i == itSlime || i == itAmethyst || i == itDodeca || i == itGreenGrass || i == itBull || i == itLavaLily || i == itHunting || - i == itBlizzard || i == itTerra || i == itGlowCrystal || i == itSnake + i == itBlizzard || i == itTerra || i == itGlowCrystal || i == itSnake || + i == itDock || i == itInvix ) return IC_TREASURE; if(i == itSavedPrincess || i == itStrongWind || i == itWarning) @@ -338,7 +339,8 @@ bool isWall(cell *w) { w->wall == waWeakBranch || w->wall == waCanopy || w->wall == waTower || w->wall == waSmallBush || w->wall == waBigBush || w->wall == waReptile || w->wall == waReptileBridge || w->wall == waInvisibleFloor || - w->wall == waSlime1 || w->wall == waSlime2 || w->wall == waArrowTrap || w->wall == waMagma) + w->wall == waSlime1 || w->wall == waSlime2 || w->wall == waArrowTrap || w->wall == waMagma || + w->wall == waDock) return false; if(isWatery(w) || isChasmy(w) || isFire(w)) return false; return true; diff --git a/game.cpp b/game.cpp index 59df83f8..4099fdf0 100644 --- a/game.cpp +++ b/game.cpp @@ -825,7 +825,7 @@ void useup(cell *c) { drawParticles(c, c->wall == waFire ? 0xC00000 : winf[c->wall].color, 10, 50); if(c->wall == waTempFloor) c->wall = waChasm; - else if(c->wall == waTempBridge || c->wall == waTempBridgeBlocked) + else if(c->wall == waTempBridge || c->wall == waTempBridgeBlocked || c->wall == waBurningDock) placeWater(c, c); else c->wall = c->land == laCaribbean ? waCIsland2 : waNone; @@ -1640,6 +1640,12 @@ bool makeflame(cell *c, int timeout, bool checkonly) { c->wall != waSaloon && c->wall != waRose) return false; // reptiles are able to use the water to put the fire off else if(c->wall == waReptileBridge) return false; + else if(c->wall == waDock) { + if(checkonly) return true; + c->wall = waBurningDock; + c->wparam = 3; + return false; + } else { eWall w = eternalFire(c) ? waEternalFire : waFire; if(!checkonly) drawFireParticles(c, 10); @@ -2909,6 +2915,10 @@ bool makeEmpty(cell *c) { ; else if(c->wall == waGiantRug) ; + else if(c->wall == waDock) + ; + else if(c->land == laDocks) + c->wall = waBoat; else if(c->wall == waFreshGrave && bounded) ; else if(isReptile(c->wall)) @@ -3264,7 +3274,10 @@ void moveMonster(cell *ct, cell *cf) { } else if(isFire(c2) && c2->wall != waEternalFire) { addMessage(XLAT("%The1 is extinguished!", c2->wall, moWaterElemental)); - c2->wall = waNone; + if(c2->wall == waBurningDock) + c2->wall = waDock; + else + c2->wall = waNone; } if(shmup::on && isWatery(c2)) shmup::destroyBoats(c2); } diff --git a/graph.cpp b/graph.cpp index 8a947ead..0e15504a 100644 --- a/graph.cpp +++ b/graph.cpp @@ -2443,6 +2443,9 @@ void setcolors(cell *c, int& wcol, int &fcol) { if(nearshore) mafcol += 30; */ fcol = fcol + mafcol * (4+sin(ticks / 500. + ((euclid||c->master->alt) ? celldistAlt(c) : 0)*1.5))/5; } + else if(c->land == laDocks) { + fcol = 0x0000A0; + } else if(c->land == laAlchemist) fcol = 0x900090; else if(c->land == laWhirlpool) @@ -2471,6 +2474,7 @@ void setcolors(cell *c, int& wcol, int &fcol) { case laDesert: fcol = 0xEDC9AF; break; case laKraken: fcol = 0x20A020; break; + case laDocks: fcol = 0x202020; break; case laCA: fcol = 0x404040; break; case laMotion: fcol = 0xF0F000; break; case laGraveyard: fcol = 0x107010; break; @@ -2757,7 +2761,7 @@ void setcolors(cell *c, int& wcol, int &fcol) { fcol = wcol = winf[c->wall].color; */ // floors become fcol - if(c->wall == waSulphur || c->wall == waSulphurC || c->wall == waPlatform || c->wall == waMercury) + if(c->wall == waSulphur || c->wall == waSulphurC || c->wall == waPlatform || c->wall == waMercury || c->wall == waDock) fcol = wcol; if(isAlch(c)) { @@ -3142,6 +3146,7 @@ int getfd(cell *c) { return (c->wall == waMercury && wmspatial) ? 0 : 1; case laKraken: + case laDocks: case laBurial: case laIvoryTower: case laDungeon: @@ -3873,6 +3878,9 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { else if(c->land == laKraken) qfloor(c, Vf, FULLFLOOR, darkena(fcol, fd, 0xFF)); + else if(c->land == laDocks) + qfloor(c, Vf, FULLFLOOR, darkena(fcol, fd, 0xFF)); + else if(c->land == laLivefjord) qfloor(c, Vf, CAVEFLOOR, darkena(fcol, fd, 0xFF)); @@ -4263,6 +4271,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { queuepoly(V, shBigCarpet2, darkena(0x600000, 0, 0xFF)); queuepoly(V, shBigCarpet3, darkena(0xC09F00, 0, 0xFF)); } + + else if(c->wall == waDock) ; else if(xch != '.' && xch != '+' && xch != '>' && xch != ':'&& xch != '-' && xch != ';' && c->wall != waSulphur && c->wall != waMercury && xch != ',' && xch != '&') error = true; diff --git a/hyper.h b/hyper.h index 06ad88e5..90f94185 100644 --- a/hyper.h +++ b/hyper.h @@ -690,6 +690,7 @@ namespace patterns { static const int SPF_ALTERNATE = 128; static const int SPF_FOOTBALL = 256; static const int SPF_FULLSYM = 512; + static const int SPF_DOCKS = 1024; static const int SPF_SYM0123 = SPF_SYM01 | SPF_SYM02 | SPF_SYM03; diff --git a/landgen.cpp b/landgen.cpp index cdad857b..e7b605c5 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -1876,6 +1876,34 @@ void giantLandSwitch(cell *c, int d, cell *from) { } break; + case laDocks: { + if(d == 8) { + patterns::patterninfo si; + patterns::val38(c, si, patterns::SPF_DOCKS, patterns::PAT_COLORING); + c->wall = waSea; + if(among(si.id, 0, 4, 16, nontruncated ? -1 : 24)) + c->wall = waDock; + if(si.id == 8 && hrand(100) < 75) { + c->wall = waBoat; + for(int i=0; itype; i++) { + patterns::val38(createMov(c, i), si, patterns::SPF_DOCKS, patterns::PAT_COLORING); + if(si.id == 0) c->mondir = i; + } + } + } + if(d == 7 && !safety) { + patterns::patterninfo si; + patterns::val38(c, si, patterns::SPF_DOCKS, patterns::PAT_COLORING); + if(si.id == 16 && hrand(250) < PT(30 + kills[moRatling] + kills[moCShark] + kills[moAlbatross] + kills[moPirate] + kills[moFireFairy], 100)) + c->item = itDock; + if(c->wall == waDock && hrand(6000) < 25 + items[itDock] + yendor::hardness()) + c->monst = pick(moPirate, moRatling, moFireFairy); + if(c->wall == waSea && hrand(6000) < 25 + items[itDock] + yendor::hardness()) + c->monst = pick(moCShark, moAlbatross); + } + break; + } + case laEAir: case laEWater: case laEEarth: diff --git a/landlock.cpp b/landlock.cpp index 84e7f860..2081314f 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -205,6 +205,9 @@ int isNative(eLand l, eMonster m) { return m == moHexSnake ? 2 : 0; case laCA: return 0; + + case laDocks: + return among(m, moRatling, moPirate, moCShark, moAlbatross, moFireFairy) ? 2 : 0; } return false; } @@ -298,6 +301,8 @@ eItem treasureType(eLand l) { case laHunting: return itHunting; case laDual: return itGlowCrystal; case laSnakeNest: return itSnake; + case laDocks: return itDock; + case laInvincible: return itInvix; case laCA: return itNone; } @@ -412,6 +417,7 @@ bool landUnlocked(eLand l) { case laMirror: case laMinefield: case laPalace: case laOcean: case laLivefjord: case laMirrored: case laMirrorWall: case laMirrorWall2: + case laDocks: case laMirrored2: return gold() >= R30; @@ -945,7 +951,7 @@ vector land_over = { laHell, laCrossroads3, laCocytus, laPower, laCrossroads4, laCrossroads5, // EXTRA - laWildWest, laHalloween, laDual, laSnakeNest, laCA + laWildWest, laHalloween, laDual, laSnakeNest, laDocks, laInvincible, laCA }; vector landlist; @@ -1196,6 +1202,9 @@ int isLandValid(eLand l) { if(l == laSnakeNest) return geosupport_threecolor() ? 3 : 0; + if(l == laDocks) + return a38 ? 2 : 0; + if(l == laStorms && torus) return 3; diff --git a/monstergen.cpp b/monstergen.cpp index 0753c596..716c9ec6 100644 --- a/monstergen.cpp +++ b/monstergen.cpp @@ -408,6 +408,11 @@ void wandering() { playSeenSound(c); continue; } + if(c->land == laDocks && wchance(items[itDock], 25) && canReachPlayer(c, moEagle)) { + c->monst = moAlbatross; + playSeenSound(c); + continue; + } if(!peace::on && c->land == laLivefjord && wchance(items[itFjord], 80) && items[itFjord] >= 10 && canReachPlayer(c, moWaterElemental)) { c->monst = moWaterElemental; playSeenSound(c); diff --git a/orbgen.cpp b/orbgen.cpp index ae2bf313..3c270061 100644 --- a/orbgen.cpp +++ b/orbgen.cpp @@ -1,4 +1,4 @@ -#define ORBLINES 63 +#define ORBLINES 66 // orbgen flags @@ -81,7 +81,7 @@ const orbinfo orbinfos[ORBLINES] = { {orbgenflags::S_NAT_NT, laLivefjord, 0, 1800, itOrbFish}, {orbgenflags::S_NAT_NT, laPrincessQuest, 0, 200, itOrbLove}, {orbgenflags::S_NATIVE, laIvoryTower, 500, 4000, itOrbMatter}, - {orbgenflags::S_NAT_NT , laElementalWall, 1500, 4000, itOrbSummon}, + {orbgenflags::S_NAT_NT, laElementalWall, 1500, 4000, itOrbSummon}, {orbgenflags::S_NATIVE, laStorms, 1000, 2500, itOrbStunning}, {orbgenflags::S_NAT_NT, laOvergrown, 1000, 800, itOrbLuck}, {orbgenflags::S_NATIVE, laWhirlwind, 1250, 3000, itOrbAir}, @@ -108,6 +108,9 @@ const orbinfo orbinfos[ORBLINES] = { {orbgenflags::S_NATIVE, laTerracotta, 800, 2500, itOrbSide1}, {orbgenflags::S_NATIVE, laDual, 600, 2500, itOrbSide2}, {orbgenflags::S_GUEST, laSnakeNest, 2000, 0, itOrbDomination}, + {orbgenflags::S_GUEST, laDocks, 3000, 0, itOrbFish}, + {orbgenflags::S_GUEST, laDocks, 3000, 0, itOrbDragon}, + {orbgenflags::S_GUEST, laDocks, 3000, 0, itOrbDash}, {orbgenflags::S_NATIVE, laWhirlpool, 0, 2000, itOrbWater}, // needs to be last }; diff --git a/orbs.cpp b/orbs.cpp index 9696fcfc..7befe526 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -423,6 +423,7 @@ void castLightningBolt(cellwalker lig) { makeflame(c, 4, false); brk = true; } + if(c->wall == waDock) makeflame(c, 5, false); if(c->wall == waCTree) makeflame(c, 12, false); if(c->wall == waRose) makeflame(c, 60, false); if(cellHalfvine(c) && c->mov[lig.spin] && c->wall == c->mov[lig.spin]->wall) { diff --git a/pattern2.cpp b/pattern2.cpp index b745037b..14ef9373 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -549,17 +549,25 @@ namespace patterns { si.id += 8; si.id %= 12; applyAlt(si, sub, pat); + if((sub & SPF_DOCKS) && (c->master->fiftyval & 32)) + si.id += 16, si.symmetries = 4; } else { si.id = 8 * ((c->master->fiftyval & 1) ^ (c->spin(0) & 1)); + bool dock = false; for(int i=0; itype; i+=2) { - int fv = (createMov(c, i)->master->fiftyval >> 1) & 3; - if(fv == 0) si.dir = (si.id == 8 && pat == PAT_COLORING ? 1 : 0) + i; + int fiv = createMov(c, i)->master->fiftyval; + int fv = (fiv >> 1) & 3; + if(fv == 0) { + si.dir = (si.id == 8 && pat == PAT_COLORING ? 1 : 0) + i; + if(fiv & 32) dock = true; + } } if(symRotation) si.symmetries = 2; si.id += 8; si.id %= 12; applyAlt(si, sub, pat); + if(dock && (sub & SPF_DOCKS)) si.id += 16; } } @@ -829,6 +837,11 @@ namespace patterns { si.symmetries = 6; } + else if(pat == PAT_PALACE) { + val_nopattern(c, si, sub); + si.id = c->master->fiftyval; + } + else if(pat == PAT_DOWN) { si.id = towerval(c); si.dir = downdir(c); diff --git a/patterns.cpp b/patterns.cpp index 4834d6cd..41f71ed6 100644 --- a/patterns.cpp +++ b/patterns.cpp @@ -1118,18 +1118,26 @@ int zebra_heptagon(int parent, int dir) { int fifty_38(int f, int d) { // This creates the 'p' pattern for the a38 geometry. - // Hexagons have codes 4 and 5, while octagons have 0, 1, 2. + // Hexagons have codes 4 and 8, while octagons have 0, 1, 2. + // Heptagons also have a 'dock flag' which is flipped + // for almost-adjacent octagons of the same code // f&1 is which direction is the hexagon with code '4' // c=((f>>1)&3) is 0, 1, or 2 int c = ((f>>1)&3); - // f&8: in which direction is c increasing by one - int step = (f&8) ? 1 : 2; if(d&1) step ^= 3; - + // (f>>3)&3: in which direction is c increasing by one (keeping the dock flag) + int ssub = (f>>3) & 3; + + // f&32: dock flags + int dockflip[2][4] = {{1+24, 2+0, 1+32+8, 2+32+0}, {1+8, 2+32+16, 1+32+24, 2+16}}; + + int d2 = (d-ssub) & 3; + int dock = (f>>5) & 1; + return ((f ^ d ^ 1) & 1) -+ (((c + step) % 3) << 1) - + (step==2?8:0); + + (((c + (dockflip[dock][d2]&3)) % 3) << 1) + + (dockflip[dock][d2]&~3); }