mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-06-21 07:44:07 +00:00
merge
This commit is contained in:
commit
6c61162392
@ -26,7 +26,7 @@ language-data.cpp: langen
|
|||||||
./langen > language-data.cpp
|
./langen > language-data.cpp
|
||||||
|
|
||||||
autohdr.h: makeh language-data.cpp *.cpp
|
autohdr.h: makeh language-data.cpp *.cpp
|
||||||
./makeh classes.cpp locations.cpp hyperpoint.cpp geometry.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp *.cpp > autohdr.h
|
./makeh classes.cpp locations.cpp hyperpoint.cpp geometry.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp util.cpp complex.cpp *.cpp > autohdr.h
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
# Platform specific setup
|
# Platform specific setup
|
||||||
|
@ -159,7 +159,7 @@ makeh$(EXE_EXTENSION): makeh.cpp
|
|||||||
$(CXX) makeh.cpp -o $@
|
$(CXX) makeh.cpp -o $@
|
||||||
|
|
||||||
autohdr.h: makeh$(EXE_EXTENSION) *.cpp
|
autohdr.h: makeh$(EXE_EXTENSION) *.cpp
|
||||||
./makeh classes.cpp locations.cpp hyperpoint.cpp geometry.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp complex.cpp *.cpp > autohdr.h
|
./makeh classes.cpp locations.cpp hyperpoint.cpp geometry.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp util.cpp complex.cpp *.cpp > autohdr.h
|
||||||
|
|
||||||
language-data.cpp: langen$(EXE_EXTENSION)
|
language-data.cpp: langen$(EXE_EXTENSION)
|
||||||
./langen > language-data.cpp
|
./langen > language-data.cpp
|
||||||
|
41
attack.cpp
41
attack.cpp
@ -216,7 +216,7 @@ EX void killIvy(cell *c, eMonster who) {
|
|||||||
c->monst = moIvyDead; // NEWYEARFIX
|
c->monst = moIvyDead; // NEWYEARFIX
|
||||||
for(int i=0; i<c->type; i++) if(c->move(i))
|
for(int i=0; i<c->type; i++) if(c->move(i))
|
||||||
if(isIvy(c->move(i)) && c->move(i)->mondir == c->c.spin(i))
|
if(isIvy(c->move(i)) && c->move(i)->mondir == c->c.spin(i))
|
||||||
killIvy(c->move(i), who);
|
killIvy(c->move(i), who), kills[moIvyDead]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void prespill(cell* c, eWall t, int rad, cell *from) {
|
EX void prespill(cell* c, eWall t, int rad, cell *from) {
|
||||||
@ -293,14 +293,14 @@ EX void prespill(cell* c, eWall t, int rad, cell *from) {
|
|||||||
// block spill
|
// block spill
|
||||||
if(t == waTemporary) return;
|
if(t == waTemporary) return;
|
||||||
// cwt.at->item = itNone;
|
// cwt.at->item = itNone;
|
||||||
if(rad) for(int i=0; i<c->type; i++) if(c->move(i))
|
if(rad) for(cell *c2: adj_minefield_cells(c))
|
||||||
prespill(c->move(i), t, rad-1, c);
|
prespill(c2, t, rad-1, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void spillfix(cell* c, eWall t, int rad) {
|
EX void spillfix(cell* c, eWall t, int rad) {
|
||||||
if(c->wall == waTemporary) c->wall = t;
|
if(c->wall == waTemporary) c->wall = t;
|
||||||
if(rad) for(int i=0; i<c->type; i++) if(c->move(i))
|
if(rad) for(cell *c2: adj_minefield_cells(c))
|
||||||
spillfix(c->move(i), t, rad-1);
|
spillfix(c2, t, rad-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void spill(cell* c, eWall t, int rad) {
|
EX void spill(cell* c, eWall t, int rad) {
|
||||||
@ -391,7 +391,14 @@ EX void killMutantIvy(cell *c, eMonster who) {
|
|||||||
removeIvy(c);
|
removeIvy(c);
|
||||||
for(int i=0; i<c->type; i++)
|
for(int i=0; i<c->type; i++)
|
||||||
if(c->move(i)->mondir == c->c.spin(i) && (isMutantIvy(c->move(i)) || c->move(i)->monst == moFriendlyIvy))
|
if(c->move(i)->mondir == c->c.spin(i) && (isMutantIvy(c->move(i)) || c->move(i)->monst == moFriendlyIvy))
|
||||||
killMutantIvy(c->move(i), who);
|
kills[c->move(i)->monst]++, killMutantIvy(c->move(i), who);
|
||||||
|
if(c->land == laClearing) clearing::imput(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
EX bignum ivy_total() {
|
||||||
|
return kills[moMutant] + kills[moFriendlyIvy] +
|
||||||
|
kills[moIvyRoot] + kills[moIvyHead] + kills[moIvyBranch] + kills[moIvyWait] + kills[moIvyDead]
|
||||||
|
+ clearing::imputed;
|
||||||
}
|
}
|
||||||
|
|
||||||
EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
||||||
@ -441,7 +448,7 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
|||||||
if(m == moHunterGuard) m = moHunterDog;
|
if(m == moHunterGuard) m = moHunterDog;
|
||||||
if(m == moHunterChanging) m = moHunterDog;
|
if(m == moHunterChanging) m = moHunterDog;
|
||||||
if(m == moWolfMoved) m = moWolf;
|
if(m == moWolfMoved) m = moWolf;
|
||||||
if(!isBulletType(m)) kills[m]++;
|
if(!isBulletType(m) && m != moIvyDead) kills[m]++;
|
||||||
|
|
||||||
if(saved_tortoise_on(c)) c->item = itNone;
|
if(saved_tortoise_on(c)) c->item = itNone;
|
||||||
|
|
||||||
@ -462,7 +469,12 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
|||||||
|
|
||||||
if(isMutantIvy(m) || m == moFriendlyIvy) {
|
if(isMutantIvy(m) || m == moFriendlyIvy) {
|
||||||
pcount = 0;
|
pcount = 0;
|
||||||
|
if(isMutantIvy(m)) clearing::direct++;
|
||||||
|
bignum s = ivy_total() - 1;
|
||||||
killMutantIvy(c, who);
|
killMutantIvy(c, who);
|
||||||
|
s = ivy_total() - s;
|
||||||
|
if(vid.bubbles_special && s > bignum(1))
|
||||||
|
drawBubble(c, 0xFFFF00, s.get_str(100), .5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m == moPrincess) {
|
if(m == moPrincess) {
|
||||||
@ -680,12 +692,27 @@ EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) {
|
|||||||
}
|
}
|
||||||
if(m == moLesser && !(kills[m] % 10))
|
if(m == moLesser && !(kills[m] % 10))
|
||||||
degradeDemons();
|
degradeDemons();
|
||||||
|
if(m == moLesser) {
|
||||||
|
if(kills[m] % 10) {
|
||||||
|
if(vid.bubbles_special)
|
||||||
|
drawBubble(c, 0xFF0000, its(kills[m]%10), 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(vid.bubbles_special)
|
||||||
|
drawBubble(c, 0xFF8000, "+1 XP", .8);
|
||||||
|
degradeDemons();
|
||||||
|
}
|
||||||
|
}
|
||||||
if(isIvy(c)) {
|
if(isIvy(c)) {
|
||||||
pcount = 0;
|
pcount = 0;
|
||||||
eMonster m = c->monst;
|
eMonster m = c->monst;
|
||||||
|
bignum s = ivy_total() - 1;
|
||||||
/*if((m == moIvyBranch || m == moIvyHead) && c->move(c->mondir)->monst == moIvyRoot)
|
/*if((m == moIvyBranch || m == moIvyHead) && c->move(c->mondir)->monst == moIvyRoot)
|
||||||
ivynext(c, moIvyNext); */
|
ivynext(c, moIvyNext); */
|
||||||
killIvy(c, who);
|
killIvy(c, who);
|
||||||
|
s = ivy_total() - s;
|
||||||
|
if(s > bignum(1) && vid.bubbles_special)
|
||||||
|
drawBubble(c, 0xFFFF00, s.get_str(100), .5);
|
||||||
if(m == moIvyBranch || m == moIvyHead || m == moIvyNext) {
|
if(m == moIvyBranch || m == moIvyHead || m == moIvyNext) {
|
||||||
int qty = 0;
|
int qty = 0;
|
||||||
cell *c2 = c->move(c->mondir);
|
cell *c2 = c->move(c->mondir);
|
||||||
|
@ -1782,7 +1782,7 @@ EX void moreBigStuff(cell *c) {
|
|||||||
c->land = laClearing, c->wall = waNone; // , c->monst = moNone, c->item = itNone;
|
c->land = laClearing, c->wall = waNone; // , c->monst = moNone, c->item = itNone;
|
||||||
}
|
}
|
||||||
else if(d == 1 && !tactic::on && !eubinary)
|
else if(d == 1 && !tactic::on && !eubinary)
|
||||||
c->wall = waSmallTree, c->monst = moNone, c->item = itNone;
|
c->wall = waSmallTree, c->monst = moNone, c->item = itNone, c->landparam = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2242,9 +2242,20 @@ void celldrawer::add_map_effects() {
|
|||||||
int tim = ticks - lightat;
|
int tim = ticks - lightat;
|
||||||
if(tim > 1000) tim = 800;
|
if(tim > 1000) tim = 800;
|
||||||
if(elec::havecharge && tim > 400) tim = 400;
|
if(elec::havecharge && tim > 400) tim = 400;
|
||||||
for(int t=0; t<c->type; t++) if(c->move(t) && c->move(t)->ligon) {
|
for(int t=0; t<c->type; t++) if(c->move(t)) {
|
||||||
int lcol = darkena(gradient(iinf[itOrbLightning].color, 0, 0, tim, 1100), 0, 0xFF);
|
if(c->move(t)->ligon) {
|
||||||
queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
|
int lcol = darkena(gradient(iinf[itOrbLightning].color, 0, 0, tim, 1100), 0, 0xFF);
|
||||||
|
queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
|
||||||
|
}
|
||||||
|
for(int u: {-1, 1}) {
|
||||||
|
cellwalker cw = cellwalker(c, t) + wstep + u;
|
||||||
|
if(u == -1 && VALENCE == 4) continue;
|
||||||
|
cell *c2 = cw.peek();
|
||||||
|
if(c2 && c2->ligon) {
|
||||||
|
int lcol = darkena(gradient(iinf[itOrbLightning].color, 0, 0, tim, 1100), 0, 0xFF);
|
||||||
|
queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t)*currentmap->adj(cw.at, cw.spin), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,7 +722,7 @@ enum eGeometry {
|
|||||||
gBinary4, gSol,
|
gBinary4, gSol,
|
||||||
gKiteDart2, gKiteDart3, gNil, gProduct, gRotSpace,
|
gKiteDart2, gKiteDart3, gNil, gProduct, gRotSpace,
|
||||||
gTernary, gNIH, gSolN, gInfOrder, gSpace336, gSpace344, gCrystal344,
|
gTernary, gNIH, gSolN, gInfOrder, gSpace336, gSpace344, gCrystal344,
|
||||||
gArnoldCat, gArbitrary,
|
gArnoldCat, gArbitrary, gInfOrder4,
|
||||||
gGUARD};
|
gGUARD};
|
||||||
|
|
||||||
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSolNIH, gcNil, gcProduct, gcSL2 };
|
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSolNIH, gcNil, gcProduct, gcSL2 };
|
||||||
@ -887,6 +887,7 @@ EX vector<geometryinfo> ginf = {
|
|||||||
{"{3,4,4}","Crystal", "4D crystal in H3", "Cryst3" , 8, 4, qIDEAL | qANYQ | qCRYSTAL, giHyperb3, 0x52000, {{7, 3}}, eVariation::pure},
|
{"{3,4,4}","Crystal", "4D crystal in H3", "Cryst3" , 8, 4, qIDEAL | qANYQ | qCRYSTAL, giHyperb3, 0x52000, {{7, 3}}, eVariation::pure},
|
||||||
{"cat", "cat", "Arnold's cat mapping torus", "cat", 12, 3, qBINARY | qSOL | qsBQ | qOPTQ, giSolNIH, 0x52200, {{6, 4}}, eVariation::pure},
|
{"cat", "cat", "Arnold's cat mapping torus", "cat", 12, 3, qBINARY | qSOL | qsBQ | qOPTQ, giSolNIH, 0x52200, {{6, 4}}, eVariation::pure},
|
||||||
{"arb", "arb", "arbitrary", "arb", 7, 3, qEXPERIMENTAL, giEuclid2, 0, {{7, 5}}, eVariation::pure},
|
{"arb", "arb", "arbitrary", "arb", 7, 3, qEXPERIMENTAL, giEuclid2, 0, {{7, 5}}, eVariation::pure},
|
||||||
|
{"{4,oo}", "none", "{4,∞} (infinite squares)", "oox4", 4, 100, qIDEAL, giHyperb2, 0x49400, {{5, 5}}, eVariation::pure},
|
||||||
};
|
};
|
||||||
// bits: 9, 10, 15, 16, (reserved for later) 17, 18
|
// bits: 9, 10, 15, 16, (reserved for later) 17, 18
|
||||||
|
|
||||||
|
55
complex.cpp
55
complex.cpp
@ -306,9 +306,7 @@ EX namespace elec {
|
|||||||
if(from != 1) charges[id].lowlink = 1;
|
if(from != 1) charges[id].lowlink = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<c->type; i++) {
|
for(cell *c2: adj_minefield_cells(c)) {
|
||||||
cell *c2 = c->move(i);
|
|
||||||
if(!c2) continue;
|
|
||||||
if(c2->listindex == from) continue;
|
if(c2->listindex == from) continue;
|
||||||
eCharge ct = getCharge(c2);
|
eCharge ct = getCharge(c2);
|
||||||
if(conduct(chh, ct))
|
if(conduct(chh, ct))
|
||||||
@ -956,6 +954,46 @@ EX namespace clearing {
|
|||||||
steps--; ds++;
|
steps--; ds++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef tuple<int, int, int, int> celltype;
|
||||||
|
|
||||||
|
map<celltype, pair<bignum, int> > stats;
|
||||||
|
|
||||||
|
EX bignum imputed;
|
||||||
|
EX int direct;
|
||||||
|
|
||||||
|
map<cell*, pair<bignum, int> > score;
|
||||||
|
|
||||||
|
celltype get_celltype(cell *c) {
|
||||||
|
cell *c1 = c;
|
||||||
|
if(c->mondir < c->type)
|
||||||
|
c1 = c->move(c->mondir);
|
||||||
|
return make_tuple(
|
||||||
|
celldistAlt(c), type_in(expansion, c, celldistAlt),
|
||||||
|
celldistAlt(c1), type_in(expansion, c1, celldistAlt)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void imput(cell *c) {
|
||||||
|
if(bounded) return;
|
||||||
|
if(score.count(c)) return;
|
||||||
|
auto& is = score[c];
|
||||||
|
celltype t = get_celltype(c);
|
||||||
|
auto& stat = stats[t];
|
||||||
|
is.second = c->mondir;
|
||||||
|
if(c->mpdist <= 6) {
|
||||||
|
is.first = 1;
|
||||||
|
forCellEx(c2, c) if(score.count(c2) && c2->move(score[c2].second) == c)
|
||||||
|
is.first += score[c2].first;
|
||||||
|
stat.first += is.first;
|
||||||
|
stat.second++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is.first = stat.second ? stat.first.randomized_div(stat.second) : bignum(1);
|
||||||
|
imputed += is.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EX }
|
EX }
|
||||||
|
|
||||||
EX namespace whirlpool {
|
EX namespace whirlpool {
|
||||||
@ -2047,14 +2085,16 @@ EX namespace heat {
|
|||||||
if(isFire(c)) hmod += 4 * xrate;
|
if(isFire(c)) hmod += 4 * xrate;
|
||||||
if(isPrincess(c->monst)) hmod += (markEmpathy(itOrbWinter) ? -1.2 : 1.2) * xrate;
|
if(isPrincess(c->monst)) hmod += (markEmpathy(itOrbWinter) ? -1.2 : 1.2) * xrate;
|
||||||
|
|
||||||
forCellEx(ct, c) {
|
auto ls = adj_minefield_cells(c);
|
||||||
|
|
||||||
|
for(cell* ct: ls) {
|
||||||
if(!isIcyLand(ct) && isFire(ct))
|
if(!isIcyLand(ct) && isFire(ct))
|
||||||
hmod += xrate*.1;
|
hmod += xrate*.1;
|
||||||
if(ct->land == laVolcano)
|
if(ct->land == laVolcano)
|
||||||
hmod += xrate * (ct->wall == waMagma ? .4 : .2);
|
hmod += xrate * (ct->wall == waMagma ? .4 : .2);
|
||||||
}
|
}
|
||||||
|
|
||||||
forCellEx(ct, c) {
|
for(cell* ct: ls) {
|
||||||
if(!isIcyLand(ct)) {
|
if(!isIcyLand(ct)) {
|
||||||
// make sure that we can still enter Cocytus,
|
// make sure that we can still enter Cocytus,
|
||||||
// it won't heat up right away even without Orb of Winter or Orb of Speed
|
// it won't heat up right away even without Orb of Winter or Orb of Speed
|
||||||
@ -2139,7 +2179,8 @@ EX namespace heat {
|
|||||||
|
|
||||||
cell *last = c->move(c->type-1);
|
cell *last = c->move(c->type-1);
|
||||||
|
|
||||||
forCellEx(c2, c) {
|
auto ls = adj_minefield_cells(c);
|
||||||
|
for(cell* c2: ls) {
|
||||||
|
|
||||||
if(c->wall == waPartialFire) {
|
if(c->wall == waPartialFire) {
|
||||||
// two partial fires adjacent are necessary to spread
|
// two partial fires adjacent are necessary to spread
|
||||||
@ -2260,7 +2301,7 @@ EX void livecaves() {
|
|||||||
hv = 0;
|
hv = 0;
|
||||||
if(c->monst == moDarkTroll) c->monst = moTroll;
|
if(c->monst == moDarkTroll) c->monst = moTroll;
|
||||||
if(c->item || c->monst || c->cpdist == 0) continue;
|
if(c->item || c->monst || c->cpdist == 0) continue;
|
||||||
forCellEx(c2, c) {
|
for(cell *c2: adj_minefield_cells(c)) {
|
||||||
eWall w = c2->wall;
|
eWall w = c2->wall;
|
||||||
if(w == waDeadfloor) hv++, bringlife.push_back(c2);
|
if(w == waDeadfloor) hv++, bringlife.push_back(c2);
|
||||||
else if(w == waDeadwall || (w == waDeadfloor2 && !c2->monst))
|
else if(w == waDeadwall || (w == waDeadfloor2 && !c2->monst))
|
||||||
|
25
config.cpp
25
config.cpp
@ -619,6 +619,10 @@ EX void initConfig() {
|
|||||||
addsaver(s2xe::qrings, "s2xe-rings");
|
addsaver(s2xe::qrings, "s2xe-rings");
|
||||||
addsaver(rots::underlying_scale, "rots-underlying-scale");
|
addsaver(rots::underlying_scale, "rots-underlying-scale");
|
||||||
|
|
||||||
|
addsaver(vid.bubbles_special, "bubbles-special", 1);
|
||||||
|
addsaver(vid.bubbles_threshold, "bubbles-special", 1);
|
||||||
|
addsaver(vid.bubbles_all, "bubbles-special", 0);
|
||||||
|
|
||||||
#if CAP_SHMUP
|
#if CAP_SHMUP
|
||||||
multi::initConfig();
|
multi::initConfig();
|
||||||
#endif
|
#endif
|
||||||
@ -996,6 +1000,22 @@ EX void menuitem_sightrange(char c IS('c')) {
|
|||||||
dialog::add_action(edit_sightrange);
|
dialog::add_action(edit_sightrange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EX void showSpecialEffects() {
|
||||||
|
cmode = vid.xres > vid.yres * 1.4 ? sm::SIDE : sm::MAYDARK;
|
||||||
|
gamescreen(0);
|
||||||
|
dialog::init(XLAT("extra graphical effects"));
|
||||||
|
|
||||||
|
dialog::addBoolItem_action(XLAT("particles on attack"), (vid.particles), 'p');
|
||||||
|
dialog::addBoolItem_action(XLAT("floating bubbles: special"), vid.bubbles_special, 's');
|
||||||
|
dialog::addBoolItem_action(XLAT("floating bubbles: treasure thresholds"), vid.bubbles_threshold, 't');
|
||||||
|
dialog::addBoolItem_action(XLAT("floating bubbles: all treasures"), vid.bubbles_all, 'a');
|
||||||
|
dialog::addBoolItem_action(XLAT("background particle effects"), (vid.backeffects), 'b');
|
||||||
|
|
||||||
|
dialog::addBreak(50);
|
||||||
|
dialog::addBack();
|
||||||
|
dialog::display();
|
||||||
|
}
|
||||||
|
|
||||||
EX void showGraphConfig() {
|
EX void showGraphConfig() {
|
||||||
cmode = vid.xres > vid.yres * 1.4 ? sm::SIDE : sm::MAYDARK;
|
cmode = vid.xres > vid.yres * 1.4 ? sm::SIDE : sm::MAYDARK;
|
||||||
gamescreen(0);
|
gamescreen(0);
|
||||||
@ -1039,8 +1059,7 @@ EX void showGraphConfig() {
|
|||||||
|
|
||||||
dialog::addSelItem(XLAT("movement animation speed"), fts(vid.mspeed), 'm');
|
dialog::addSelItem(XLAT("movement animation speed"), fts(vid.mspeed), 'm');
|
||||||
|
|
||||||
dialog::addBoolItem(XLAT("extra graphical effects"), (vid.particles), 'u');
|
dialog::addItem(XLAT("extra graphical effects"), 'u');
|
||||||
dialog::addBoolItem(XLAT("background particle effects"), (vid.backeffects), 'p');
|
|
||||||
|
|
||||||
dialog::addBreak(50);
|
dialog::addBreak(50);
|
||||||
dialog::addBack();
|
dialog::addBack();
|
||||||
@ -1055,7 +1074,7 @@ EX void showGraphConfig() {
|
|||||||
|
|
||||||
if((uni >= 32 && uni < 64) || uni == 'L' || uni == 'C') xuni = uni;
|
if((uni >= 32 && uni < 64) || uni == 'L' || uni == 'C') xuni = uni;
|
||||||
|
|
||||||
if(xuni == 'u') vid.particles = !vid.particles;
|
if(xuni == 'u') pushScreen(showSpecialEffects);
|
||||||
|
|
||||||
else if(xuni == 'a') dialog::editNumber(vid.sspeed, -5, 5, 1, 0,
|
else if(xuni == 'a') dialog::editNumber(vid.sspeed, -5, 5, 1, 0,
|
||||||
XLAT("scrolling speed"),
|
XLAT("scrolling speed"),
|
||||||
|
18
control.cpp
18
control.cpp
@ -1027,7 +1027,23 @@ EX bool gmodekeys(int sym, int uni) {
|
|||||||
if(NUMBERKEY == '7') { vid.darkhepta = !vid.darkhepta; return true; }
|
if(NUMBERKEY == '7') { vid.darkhepta = !vid.darkhepta; return true; }
|
||||||
|
|
||||||
if(GDIM == 2) {
|
if(GDIM == 2) {
|
||||||
if(NUMBERKEY == '1' && !rug::rugged) { vid.alpha = 999; vid.scale = 998; vid.xposition = vid.yposition = 0; }
|
if(among(NUMBERKEY, '1', '2', '3') && !rug::rugged && euclid && WDIM == 2) {
|
||||||
|
vid.xposition = vid.yposition = 0;
|
||||||
|
ld maxs = 0;
|
||||||
|
auto& cd = current_display;
|
||||||
|
for(auto& p: gmatrix) for(int i=0; i<p.first->type; i++) {
|
||||||
|
hyperpoint h = tC0(p.second * currentmap->adj(p.first, i));
|
||||||
|
hyperpoint onscreen;
|
||||||
|
applymodel(h, onscreen);
|
||||||
|
maxs = max(maxs, onscreen[0] / cd->xsize);
|
||||||
|
maxs = max(maxs, onscreen[1] / cd->ysize);
|
||||||
|
}
|
||||||
|
vid.alpha = 1;
|
||||||
|
vid.scale = vid.scale / 2 / maxs / cd->radius;
|
||||||
|
if(NUMBERKEY == '3') vid.scale *= 2;
|
||||||
|
if(NUMBERKEY == '1') vid.scale /= 2;
|
||||||
|
}
|
||||||
|
else if(NUMBERKEY == '1' && !rug::rugged) { vid.alpha = 999; vid.scale = 998; vid.xposition = vid.yposition = 0; }
|
||||||
else if(NUMBERKEY == '2' && !rug::rugged) { vid.alpha = 1; vid.scale = 0.4; vid.xposition = vid.yposition = 0; }
|
else if(NUMBERKEY == '2' && !rug::rugged) { vid.alpha = 1; vid.scale = 0.4; vid.xposition = vid.yposition = 0; }
|
||||||
else if(NUMBERKEY == '3' && !rug::rugged) { vid.alpha = 1; vid.scale = 1; vid.xposition = vid.yposition = 0; }
|
else if(NUMBERKEY == '3' && !rug::rugged) { vid.alpha = 1; vid.scale = 1; vid.xposition = vid.yposition = 0; }
|
||||||
else if(NUMBERKEY == '4' && !rug::rugged) { vid.alpha = 0; vid.scale = 1; vid.xposition = vid.yposition = 0; }
|
else if(NUMBERKEY == '4' && !rug::rugged) { vid.alpha = 0; vid.scale = 1; vid.xposition = vid.yposition = 0; }
|
||||||
|
@ -348,6 +348,7 @@ EX void bfs() {
|
|||||||
if(c2->land == laWhirlwind) havewhat |= HF_WHIRLWIND;
|
if(c2->land == laWhirlwind) havewhat |= HF_WHIRLWIND;
|
||||||
if(c2->land == laWestWall) havewhat |= HF_WESTWALL;
|
if(c2->land == laWestWall) havewhat |= HF_WESTWALL;
|
||||||
if(c2->land == laPrairie) havewhat |= HF_RIVER;
|
if(c2->land == laPrairie) havewhat |= HF_RIVER;
|
||||||
|
if(c2->land == laClearing) havewhat |= HF_MUTANT;
|
||||||
|
|
||||||
if(c2->wall == waRose) havewhat |= HF_ROSE;
|
if(c2->wall == waRose) havewhat |= HF_ROSE;
|
||||||
|
|
||||||
|
158
expansion.cpp
158
expansion.cpp
@ -15,164 +15,6 @@ int subtype(cell *c) {
|
|||||||
return patterns::getpatterninfo(c, patterns::PAT_NONE, 0).id;
|
return patterns::getpatterninfo(c, patterns::PAT_NONE, 0).id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HDR
|
|
||||||
struct bignum {
|
|
||||||
static const int BASE = 1000000000;
|
|
||||||
static const long long BASE2 = BASE * (long long)BASE;
|
|
||||||
vector<int> digits;
|
|
||||||
bignum() {}
|
|
||||||
bignum(int i) : digits() { digits.push_back(i); }
|
|
||||||
void be(int i) { digits.resize(1); digits[0] = i; }
|
|
||||||
bignum& operator +=(const bignum& b);
|
|
||||||
void addmul(const bignum& b, int factor);
|
|
||||||
string get_str(int max_length);
|
|
||||||
|
|
||||||
bool operator < (const bignum&) const;
|
|
||||||
|
|
||||||
ld leading() const {
|
|
||||||
switch(isize(digits)) {
|
|
||||||
case 0:
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
return digits.back();
|
|
||||||
default:
|
|
||||||
return digits.back() + ld(digits[isize(digits)-2]) / BASE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ld approx() const {
|
|
||||||
return leading() * pow(BASE, isize(digits) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ld log_approx() const {
|
|
||||||
return log(leading()) * log(BASE) * (isize(digits) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ld operator / (const bignum& b) const {
|
|
||||||
return leading() / b.leading() * pow(BASE, isize(digits) - isize(b.digits));
|
|
||||||
}
|
|
||||||
|
|
||||||
int approx_int() const {
|
|
||||||
if(isize(digits) > 1) return BASE;
|
|
||||||
if(digits.empty()) return 0;
|
|
||||||
return digits[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
long long approx_ll() const {
|
|
||||||
if(isize(digits) > 2) return BASE2;
|
|
||||||
if(digits.empty()) return 0;
|
|
||||||
if(isize(digits) == 1) return digits[0];
|
|
||||||
return digits[0] + digits[1] * (long long) BASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend inline bignum operator +(bignum a, const bignum& b) { a.addmul(b, 1); return a; }
|
|
||||||
friend inline bignum operator -(bignum a, const bignum& b) { a.addmul(b, -1); return a; }
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bignum& bignum::operator +=(const bignum& b) {
|
|
||||||
int K = isize(b.digits);
|
|
||||||
if(K > isize(digits)) digits.resize(K);
|
|
||||||
int carry = 0;
|
|
||||||
for(int i=0; i<K || carry; i++) {
|
|
||||||
if(i >= isize(digits)) digits.push_back(0);
|
|
||||||
digits[i] += carry;
|
|
||||||
if(i < K) digits[i] += b.digits[i];
|
|
||||||
if(digits[i] >= BASE) {
|
|
||||||
digits[i] -= BASE;
|
|
||||||
carry = 1;
|
|
||||||
}
|
|
||||||
else carry = 0;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bignum::operator < (const bignum& b) const {
|
|
||||||
if(isize(digits) != isize(b.digits))
|
|
||||||
return isize(digits) < isize(b.digits);
|
|
||||||
for(int i = isize(digits)-1; i>=0; i--)
|
|
||||||
if(digits[i] != b.digits[i])
|
|
||||||
return digits[i] < b.digits[i];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bignum::addmul(const bignum& b, int factor) {
|
|
||||||
int K = isize(b.digits);
|
|
||||||
if(K > isize(digits)) digits.resize(K);
|
|
||||||
int carry = 0;
|
|
||||||
for(int i=0; i<K || (carry > 0 || carry < -1) || (carry == -1 && i < isize(digits)); i++) {
|
|
||||||
if(i >= isize(digits)) digits.push_back(0);
|
|
||||||
long long l = digits[i];
|
|
||||||
l += carry;
|
|
||||||
if(i < K) l += b.digits[i] * factor;
|
|
||||||
carry = 0;
|
|
||||||
if(l >= BASE) carry = l / BASE;
|
|
||||||
if(l < 0) carry = -(BASE-1-l) / BASE;
|
|
||||||
l -= carry * BASE;
|
|
||||||
digits[i] = l;
|
|
||||||
}
|
|
||||||
if(carry < 0) digits.back() -= BASE;
|
|
||||||
while(isize(digits) && digits.back() == 0) digits.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
EX bignum hrand(bignum b) {
|
|
||||||
bignum res;
|
|
||||||
int d = isize(b.digits);
|
|
||||||
while(true) {
|
|
||||||
res.digits.resize(d);
|
|
||||||
for(int i=0; i<d-1; i++) res.digits[i] = hrand(bignum::BASE);
|
|
||||||
res.digits.back() = hrand(b.digits.back() + 1);
|
|
||||||
if(res < b) return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EX void operator ++(bignum &b, int) {
|
|
||||||
int i = 0;
|
|
||||||
while(true) {
|
|
||||||
if(isize(b.digits) == i) { b.digits.push_back(1); break; }
|
|
||||||
else if(b.digits[i] == bignum::BASE-1) {
|
|
||||||
b.digits[i] = 0;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
b.digits[i]++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EX void operator --(bignum &b, int) {
|
|
||||||
int i = 0;
|
|
||||||
while(true) {
|
|
||||||
if(isize(b.digits) == i) { b.digits.push_back(bignum::BASE-1); break; }
|
|
||||||
else if(b.digits[i] == 0) {
|
|
||||||
b.digits[i] = bignum::BASE-1;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
b.digits[i]--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string bignum::get_str(int max_length) {
|
|
||||||
if(digits.empty()) return "0";
|
|
||||||
string ret = its(digits.back());
|
|
||||||
for(int i=isize(digits)-2; i>=0; i--) {
|
|
||||||
if(isize(ret) > max_length && i) {
|
|
||||||
ret += XLAT(" (%1 more digits)", its(9 * (i+1)));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret += " ";
|
|
||||||
string val = its(digits[i]);
|
|
||||||
while(isize(val) < 9) val = "0" + val;
|
|
||||||
ret += val;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void canonicize(vector<int>& t) {
|
void canonicize(vector<int>& t) {
|
||||||
for(int i=2; i<isize(t); i++)
|
for(int i=2; i<isize(t); i++)
|
||||||
if((t[i] & 3) == 1 && (t[i-1] & 3) != 1)
|
if((t[i] & 3) == 1 && (t[i-1] & 3) != 1)
|
||||||
|
@ -751,12 +751,13 @@ EX void showEuclideanMenu() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(among(specialland, laMinefield, laCA) && geometry_has_alt_mine_rule()) {
|
if(geometry_has_alt_mine_rule()) {
|
||||||
dialog::addSelItem(XLAT("mine adjacency rule"), XLAT(mine_adjacency_rule ? "vertex" : WDIM == 3 ? "face" : "edge"), 'M');
|
dialog::addSelItem(XLAT("adjacency rule"), XLAT(mine_adjacency_rule ? "vertex" : WDIM == 3 ? "face" : "edge"), 'M');
|
||||||
dialog::add_action([] {
|
dialog::add_action([] {
|
||||||
stop_game();
|
stop_game();
|
||||||
mine_adjacency_rule = !mine_adjacency_rule;
|
mine_adjacency_rule = !mine_adjacency_rule;
|
||||||
start_game();
|
start_game();
|
||||||
|
addMessage(XLAT("Note: adjacency rule affects environmental effects, but not movement."));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
graph.cpp
28
graph.cpp
@ -3762,6 +3762,7 @@ struct flashdata {
|
|||||||
double angle2;
|
double angle2;
|
||||||
int spd; // 0 for flashes, >0 for particles
|
int spd; // 0 for flashes, >0 for particles
|
||||||
color_t color;
|
color_t color;
|
||||||
|
string text;
|
||||||
flashdata(int _t, int _s, cell *_w, color_t col, int sped) {
|
flashdata(int _t, int _s, cell *_w, color_t col, int sped) {
|
||||||
t=_t; size=_s; where=_w; color = col;
|
t=_t; size=_s; where=_w; color = col;
|
||||||
angle = rand() % 1000; spd = sped;
|
angle = rand() % 1000; spd = sped;
|
||||||
@ -3771,6 +3772,13 @@ struct flashdata {
|
|||||||
|
|
||||||
vector<flashdata> flashes;
|
vector<flashdata> flashes;
|
||||||
|
|
||||||
|
EX void drawBubble(cell *c, color_t col, string s, ld size) {
|
||||||
|
auto fd = flashdata(ticks, 1000, c, col, 0);
|
||||||
|
fd.text = s;
|
||||||
|
fd.angle = size;
|
||||||
|
flashes.push_back(fd);
|
||||||
|
}
|
||||||
|
|
||||||
EX void drawFlash(cell *c) {
|
EX void drawFlash(cell *c) {
|
||||||
flashes.push_back(flashdata(ticks, 1000, c, iinf[itOrbFlash].color, 0));
|
flashes.push_back(flashdata(ticks, 1000, c, iinf[itOrbFlash].color, 0));
|
||||||
}
|
}
|
||||||
@ -3990,8 +3998,8 @@ EX void drawMarkers() {
|
|||||||
queuecircleat(lmouseover, .8, darkena(lmouseover->cpdist > 1 ? 0x00FFFF : 0xFF0000, 0, 0xFF));
|
queuecircleat(lmouseover, .8, darkena(lmouseover->cpdist > 1 ? 0x00FFFF : 0xFF0000, 0, 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pcm.mip.t && vid.drawmousecircle && ok && DEFAULTCONTROL && MOBON && WDIM == 2) {
|
if(global_pushto && vid.drawmousecircle && ok && DEFAULTCONTROL && MOBON && WDIM == 2) {
|
||||||
queuecircleat(pcm.mip.t, .6, darkena(0xFFD500, 0, 0xFF));
|
queuecircleat(global_pushto, .6, darkena(0xFFD500, 0, 0xFF));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -4138,7 +4146,19 @@ EX void draw_flash(struct flashdata& f, const transmatrix& V, bool& kill) {
|
|||||||
|
|
||||||
if(tim <= f.size && !f.spd) kill = false;
|
if(tim <= f.size && !f.spd) kill = false;
|
||||||
|
|
||||||
if(f.spd) {
|
if(f.text != "") {
|
||||||
|
if(GDIM == 3 || sphere)
|
||||||
|
queuestr(V, (1 - tim * 1. / f.size) * f.angle, f.text, f.color);
|
||||||
|
else if(!kill) {
|
||||||
|
hyperpoint h = tC0(V);
|
||||||
|
if(hdist0(h) > .1) {
|
||||||
|
transmatrix V2 = rspintox(h) * xpush(hdist0(h) * (1 / (1 - tim * 1. / f.size)));
|
||||||
|
queuestr(V2, f.angle, f.text, f.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(f.spd) {
|
||||||
#if CAP_SHAPES
|
#if CAP_SHAPES
|
||||||
if(tim <= 300) kill = false;
|
if(tim <= 300) kill = false;
|
||||||
int partcol = darkena(f.color, 0, GDIM == 3 ? 255 : max(255 - tim*255/300, 0));
|
int partcol = darkena(f.color, 0, GDIM == 3 ? 255 : max(255 - tim*255/300, 0));
|
||||||
@ -4786,7 +4806,7 @@ EX bool nohelp;
|
|||||||
EX void normalscreen() {
|
EX void normalscreen() {
|
||||||
help = "@";
|
help = "@";
|
||||||
|
|
||||||
mouseovers = XLAT("Press F1 or right click for help");
|
mouseovers = standard_help();
|
||||||
|
|
||||||
#if CAP_TOUR
|
#if CAP_TOUR
|
||||||
if(tour::on) mouseovers = tour::tourhelp;
|
if(tour::on) mouseovers = tour::tourhelp;
|
||||||
|
14
help.cpp
14
help.cpp
@ -178,6 +178,10 @@ void buildHelpText() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EX string standard_help() {
|
||||||
|
return XLAT("Press F1 or right click for help");
|
||||||
|
}
|
||||||
|
|
||||||
EX void buildCredits() {
|
EX void buildCredits() {
|
||||||
help = "";
|
help = "";
|
||||||
help += XLAT("game design, programming, texts and graphics by Zeno Rogue <zeno@attnam.com>\n\n");
|
help += XLAT("game design, programming, texts and graphics by Zeno Rogue <zeno@attnam.com>\n\n");
|
||||||
@ -576,6 +580,16 @@ EX string generateHelpForMonster(eMonster m) {
|
|||||||
if(isGhost(m))
|
if(isGhost(m))
|
||||||
s += XLAT("\n\nA Ghost never moves to a cell which is adjacent to another Ghost of the same kind.", m);
|
s += XLAT("\n\nA Ghost never moves to a cell which is adjacent to another Ghost of the same kind.", m);
|
||||||
|
|
||||||
|
if(m == moMutant) {
|
||||||
|
using namespace clearing;
|
||||||
|
if(direct)
|
||||||
|
s += XLAT("\n\nLeaves cut directly: %1", its(direct));
|
||||||
|
if(kills[moMutant])
|
||||||
|
s += XLAT("\n\nLeaves cut onscreen: %1", its(kills[moMutant]));
|
||||||
|
if(imputed.nonzero())
|
||||||
|
s += XLAT("\n\nLeaves cut offscreen (approximately): %1", imputed.get_str(10000));
|
||||||
|
}
|
||||||
|
|
||||||
if(m == moBat || m == moEagle)
|
if(m == moBat || m == moEagle)
|
||||||
s += XLAT("\n\nFast flying creatures may attack or go against gravity only in their first move.", m);
|
s += XLAT("\n\nFast flying creatures may attack or go against gravity only in their first move.", m);
|
||||||
|
|
||||||
|
59
hud.cpp
59
hud.cpp
@ -253,8 +253,25 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, color_t color, int
|
|||||||
(qty < 10 && (flags & (GLYPH_MARKTODO | GLYPH_RUNOUT))) ? buttonsize*3/4 :
|
(qty < 10 && (flags & (GLYPH_MARKTODO | GLYPH_RUNOUT))) ? buttonsize*3/4 :
|
||||||
qty < 100 ? buttonsize / 2 :
|
qty < 100 ? buttonsize / 2 :
|
||||||
buttonsize / 3;
|
buttonsize / 3;
|
||||||
if(str != "")
|
|
||||||
displayfr(cx + buttonsize, cy + buttonsize/2 - bsize/2, 1, bsize, str, color, 16);
|
if(id == moMutant + ittypes && clearing::imputed.nonzero()) {
|
||||||
|
ld d = qty + clearing::imputed.approx_ld();
|
||||||
|
if(d < 100000) str = its(int(d));
|
||||||
|
else {
|
||||||
|
int digits = 0;
|
||||||
|
while(d >= 10) digits++, d /= 10;
|
||||||
|
str = its(int(d*100)) + "E" + its(digits);
|
||||||
|
str.insert(1, ".");
|
||||||
|
}
|
||||||
|
bsize = buttonsize / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(str != "") {
|
||||||
|
if(textwidth(bsize, str) < buttonsize)
|
||||||
|
displayfr(cx + buttonsize, cy + buttonsize/2 - bsize/2, 1, bsize, str, color, 16);
|
||||||
|
else
|
||||||
|
displayfr(cx, cy + buttonsize/2 - bsize/2, 1, bsize, str, color, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
@ -365,6 +382,8 @@ EX bool nofps = false;
|
|||||||
EX color_t crosshair_color = 0xFFFFFFC0;
|
EX color_t crosshair_color = 0xFFFFFFC0;
|
||||||
EX ld crosshair_size = 0;
|
EX ld crosshair_size = 0;
|
||||||
|
|
||||||
|
EX bool long_kills;
|
||||||
|
|
||||||
EX void drawStats() {
|
EX void drawStats() {
|
||||||
if(nohud || vid.stereo_mode == sLR) return;
|
if(nohud || vid.stereo_mode == sLR) return;
|
||||||
if(callhandlers(false, hooks_prestats)) return;
|
if(callhandlers(false, hooks_prestats)) return;
|
||||||
@ -577,7 +596,8 @@ EX void drawStats() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if(!peace::on) {
|
else if(!peace::on) {
|
||||||
if(displayButtonS(vid.xres - 8, vid.fsize, XLAT("score: %1", its(gold())), forecolor, 16, vid.fsize)) {
|
string scoreline = XLAT("score: %1", its(gold()));
|
||||||
|
if(displayButtonS(vid.xres - 8, vid.fsize, scoreline, forecolor, 16, vid.fsize)) {
|
||||||
mouseovers = XLAT("Your total wealth"),
|
mouseovers = XLAT("Your total wealth"),
|
||||||
instat = true,
|
instat = true,
|
||||||
getcstat = SDLK_F1,
|
getcstat = SDLK_F1,
|
||||||
@ -590,16 +610,29 @@ EX void drawStats() {
|
|||||||
"Orbs of Yendor are worth 50 $$$ each.\n\n"
|
"Orbs of Yendor are worth 50 $$$ each.\n\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if(displayButtonS(8, vid.fsize, XLAT("kills: %1", its(tkills())), forecolor, 0, vid.fsize)) {
|
string s = XLAT("kills: %1", its(tkills()));
|
||||||
instat = true,
|
long_kills = false;
|
||||||
getcstat = SDLK_F1,
|
int siz = vid.fsize;
|
||||||
mouseovers = XLAT("Your total kills")+": " + its(tkills()),
|
if(cwt.at->land == laClearing && clearing::imputed.approx_ld() >= 100000) {
|
||||||
help = helptitle(XLAT("Your total kills") + ": " + its(tkills()), 0x404040) +
|
long_kills = true;
|
||||||
XLAT(
|
s = XLAT("leaves cut: " + (bignum(kills[moMutant]) + clearing::imputed).get_str(200));
|
||||||
"In most lands, more treasures are generated with each enemy native to this land you kill. "
|
if(mouseovers == standard_help()) mouseovers = " ";
|
||||||
"Moreover, 100 kills is a requirement to enter the Graveyard and the Hive.\n\n"
|
while(siz > 4 && textwidth(siz, s) > vid.xres - textwidth(vid.fsize, scoreline)) siz--;
|
||||||
"Friendly creatures and parts of monsters (such as the Ivy) do appear in the list, "
|
}
|
||||||
"but are not counted in the total kill count.");
|
|
||||||
|
if(displayButtonS(8, vid.fsize, s, forecolor, 0, siz)) {
|
||||||
|
instat = true;
|
||||||
|
getcstat = SDLK_F1;
|
||||||
|
if(long_kills) { mouseovers = " "; help = generateHelpForMonster(moMutant); }
|
||||||
|
else {
|
||||||
|
mouseovers = XLAT("Your total kills")+": " + its(tkills()),
|
||||||
|
help = helptitle(XLAT("Your total kills") + ": " + its(tkills()), 0x404040) +
|
||||||
|
XLAT(
|
||||||
|
"In most lands, more treasures are generated with each enemy native to this land you kill. "
|
||||||
|
"Moreover, 100 kills is a requirement to enter the Graveyard and the Hive.\n\n"
|
||||||
|
"Friendly creatures and parts of monsters (such as the Ivy) do appear in the list, "
|
||||||
|
"but are not counted in the total kill count.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
string vers = VER;
|
string vers = VER;
|
||||||
|
3
hyper.h
3
hyper.h
@ -246,7 +246,7 @@ struct videopar {
|
|||||||
ld xposition, yposition;
|
ld xposition, yposition;
|
||||||
|
|
||||||
bool grid;
|
bool grid;
|
||||||
int particles;
|
bool particles;
|
||||||
|
|
||||||
int fsize;
|
int fsize;
|
||||||
int flashtime;
|
int flashtime;
|
||||||
@ -325,6 +325,7 @@ struct videopar {
|
|||||||
|
|
||||||
ld collignon_parameter; bool collignon_reflected;
|
ld collignon_parameter; bool collignon_reflected;
|
||||||
ld plevel_factor;
|
ld plevel_factor;
|
||||||
|
bool bubbles_special, bubbles_threshold, bubbles_all;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern videopar vid;
|
extern videopar vid;
|
||||||
|
@ -1157,7 +1157,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||||||
(hrand(50+items[itMutant]/2+yendor::hardness()) < 30) ? (hrand(100) < 50 ? waBigTree : waSmallTree) : waNone;
|
(hrand(50+items[itMutant]/2+yendor::hardness()) < 30) ? (hrand(100) < 50 ? waBigTree : waSmallTree) : waNone;
|
||||||
}
|
}
|
||||||
if(d == 8) {
|
if(d == 8) {
|
||||||
if(hrand(doCross ?450:15000) < 20 + (2 * items[itMutant] + yendor::hardness()) && !safety) {
|
bool ok = c->landparam == 0;
|
||||||
|
forCellEx(c2, c) if(c2->landparam) ok = false;
|
||||||
|
if(ok && hrand(doCross ?450:15000) < 20 + (2 * items[itMutant] + yendor::hardness()) && !safety) {
|
||||||
if(!peace::on) c->item = itMutant;
|
if(!peace::on) c->item = itMutant;
|
||||||
c->landparam = items[itMutant] + 5 + hrand(11);
|
c->landparam = items[itMutant] + 5 + hrand(11);
|
||||||
c->wall = waNone;
|
c->wall = waNone;
|
||||||
@ -1165,7 +1167,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
|||||||
if(c->move(i) && (c->move(i)->wall == waBigTree || c->move(i)->wall == waSmallTree))
|
if(c->move(i) && (c->move(i)->wall == waBigTree || c->move(i)->wall == waSmallTree))
|
||||||
c->move(i)->wall = waNone;
|
c->move(i)->wall = waNone;
|
||||||
}
|
}
|
||||||
else if(hrand_monster(15000) < 20 + (2 * items[itMutant] + yendor::hardness()) && !safety) {
|
else if(hrand_monster(15000) < 20 + (2 * items[itMutant] + yendor::hardness()) && ok && !safety) {
|
||||||
// for the Yendor Challenge, use only Mutants
|
// for the Yendor Challenge, use only Mutants
|
||||||
if(!(yendor::on && yendor::clev().l == laMirror)) {
|
if(!(yendor::on && yendor::clev().l == laMirror)) {
|
||||||
c->monst = moForestTroll;
|
c->monst = moForestTroll;
|
||||||
|
@ -38,6 +38,7 @@ EX int buildIvy(cell *c, int children, int minleaf) {
|
|||||||
leaf += leafchild;
|
leaf += leafchild;
|
||||||
if(leaf < minleaf) {
|
if(leaf < minleaf) {
|
||||||
if(child) killIvy(child, moNone);
|
if(child) killIvy(child, moNone);
|
||||||
|
dynamicval<int> k(kills[moIvyDead]);
|
||||||
killIvy(c, moNone);
|
killIvy(c, moNone);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1333,8 +1333,18 @@ EX void movehex_rest(bool mounted) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EX void movemutant() {
|
EX void movemutant() {
|
||||||
|
manual_celllister mcells;
|
||||||
|
for(cell *c: currentmap->allcells()) mcells.add(c);
|
||||||
|
if(!bounded)
|
||||||
|
for(int i=0; i<isize(mcells.lst); i++) {
|
||||||
|
cell *c = mcells.lst[i];
|
||||||
|
if(c->land == laClearing && c->monst != moMutant && !pseudohept(c))
|
||||||
|
forCellEx(c2, c) forCellEx(c3, c2) if(celldistAlt(c3) < celldistAlt(c))
|
||||||
|
mcells.add(c3);
|
||||||
|
}
|
||||||
|
|
||||||
vector<cell*> young;
|
vector<cell*> young;
|
||||||
for(cell *c: currentmap->allcells())
|
for(cell *c: mcells.lst)
|
||||||
if(c->monst == moMutant && c->stuntime == mutantphase)
|
if(c->monst == moMutant && c->stuntime == mutantphase)
|
||||||
young.push_back(c);
|
young.push_back(c);
|
||||||
|
|
||||||
|
@ -958,6 +958,11 @@ EX void handleInput(int delta) {
|
|||||||
cdir = d;
|
cdir = d;
|
||||||
if(multi::multiPlayerTarget(i) == c) break;
|
if(multi::multiPlayerTarget(i) == c) break;
|
||||||
cdir = scdir;
|
cdir = scdir;
|
||||||
|
cwt = multi::player[i];
|
||||||
|
calcMousedest();
|
||||||
|
auto& sd = multi::whereto[i].subdir;
|
||||||
|
sd = mousedest.subdir;
|
||||||
|
if(sd == 0) sd = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,12 +224,15 @@ struct pcmove {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EX pcmove pcm;
|
EX cell *global_pushto;
|
||||||
|
|
||||||
EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) {
|
||||||
|
pcmove pcm;
|
||||||
pcm.checkonly = checkonly;
|
pcm.checkonly = checkonly;
|
||||||
pcm.d = d; pcm.subdir = subdir;
|
pcm.d = d; pcm.subdir = subdir;
|
||||||
return pcm.movepcto();
|
auto b = pcm.movepcto();
|
||||||
|
global_pushto = pcm.mip.t;
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pcmove::movepcto() {
|
bool pcmove::movepcto() {
|
||||||
|
15
system.cpp
15
system.cpp
@ -394,7 +394,7 @@ bool havesave = true;
|
|||||||
|
|
||||||
#if HDR
|
#if HDR
|
||||||
#define MAXBOX 500
|
#define MAXBOX 500
|
||||||
#define POSSCORE 371 // update this when new boxes are added!
|
#define POSSCORE 373 // update this when new boxes are added!
|
||||||
struct score {
|
struct score {
|
||||||
string ver;
|
string ver;
|
||||||
int box[MAXBOX];
|
int box[MAXBOX];
|
||||||
@ -414,6 +414,16 @@ void applyBox(int& t) {
|
|||||||
else boxid++;
|
else boxid++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void applyBoxBignum(bignum& tb) {
|
||||||
|
float tf;
|
||||||
|
int ti;
|
||||||
|
if(saving) tf = tb.approx_ld();
|
||||||
|
if(saving) memcpy(&ti, &tf, 4);
|
||||||
|
applyBox(ti);
|
||||||
|
if(loading) memcpy(&tf, &ti, 4);
|
||||||
|
if(loading) tb = bignum(tf);
|
||||||
|
}
|
||||||
|
|
||||||
EX void applyBoxNum(int& i, string name IS("")) {
|
EX void applyBoxNum(int& i, string name IS("")) {
|
||||||
fakebox[boxid] = (name == "");
|
fakebox[boxid] = (name == "");
|
||||||
boxname[boxid] = name;
|
boxname[boxid] = name;
|
||||||
@ -815,6 +825,9 @@ EX void applyBoxes() {
|
|||||||
applyBoxM(moNarciss);
|
applyBoxM(moNarciss);
|
||||||
applyBoxM(moMirrorSpirit);
|
applyBoxM(moMirrorSpirit);
|
||||||
|
|
||||||
|
applyBox(clearing::direct);
|
||||||
|
applyBoxBignum(clearing::imputed);
|
||||||
|
|
||||||
if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid);
|
if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
194
util.cpp
194
util.cpp
@ -325,4 +325,198 @@ EX string parser_help() {
|
|||||||
"(a)sin(h), (a)cos(h), (a)tan(h), exp, log, abs, re, im, conj, let(t=...,...t...), floor, frac, e, i, pi, s, ms, mousex, mousey, mousez, shot [1 if taking screenshot/animation], sqrt, to01, random, edge(7,3), regradius(7,3), ifp(a,v,w) [if positive]");
|
"(a)sin(h), (a)cos(h), (a)tan(h), exp, log, abs, re, im, conj, let(t=...,...t...), floor, frac, e, i, pi, s, ms, mousex, mousey, mousez, shot [1 if taking screenshot/animation], sqrt, to01, random, edge(7,3), regradius(7,3), ifp(a,v,w) [if positive]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HDR
|
||||||
|
struct bignum {
|
||||||
|
static const int BASE = 1000000000;
|
||||||
|
static const long long BASE2 = BASE * (long long)BASE;
|
||||||
|
vector<int> digits;
|
||||||
|
bignum() {}
|
||||||
|
bignum(int i) : digits() { digits.push_back(i); }
|
||||||
|
void be(int i) { digits.resize(1); digits[0] = i; }
|
||||||
|
bignum& operator +=(const bignum& b);
|
||||||
|
void addmul(const bignum& b, int factor);
|
||||||
|
string get_str(int max_length) const;
|
||||||
|
bignum(ld d);
|
||||||
|
|
||||||
|
bool operator < (const bignum&) const;
|
||||||
|
bool operator > (const bignum& b) const { return b < self; }
|
||||||
|
|
||||||
|
ld leading() const {
|
||||||
|
switch(isize(digits)) {
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
return digits.back();
|
||||||
|
default:
|
||||||
|
return digits.back() + ld(digits[isize(digits)-2]) / BASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ld approx() const {
|
||||||
|
return leading() * pow(BASE, isize(digits) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld log_approx() const {
|
||||||
|
return log(leading()) * log(BASE) * (isize(digits) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld approx_div(const bignum& b) const {
|
||||||
|
return leading() / b.leading() * pow(BASE, isize(digits) - isize(b.digits));
|
||||||
|
}
|
||||||
|
|
||||||
|
int approx_int() const {
|
||||||
|
if(isize(digits) > 1) return BASE;
|
||||||
|
if(digits.empty()) return 0;
|
||||||
|
return digits[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nonzero() { return approx_ld() != 0; }
|
||||||
|
|
||||||
|
bignum randomized_div(int x) const;
|
||||||
|
|
||||||
|
ld approx_ld() const {
|
||||||
|
ld res = 0;
|
||||||
|
for(int i=0; i<isize(digits); i++) res += digits[i] * pow(BASE, i);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long approx_ll() const {
|
||||||
|
if(isize(digits) > 2) return BASE2;
|
||||||
|
if(digits.empty()) return 0;
|
||||||
|
if(isize(digits) == 1) return digits[0];
|
||||||
|
return digits[0] + digits[1] * (long long) BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bignum operator +(bignum a, const bignum& b) { a.addmul(b, 1); return a; }
|
||||||
|
friend inline bignum operator -(bignum a, const bignum& b) { a.addmul(b, -1); return a; }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bignum& bignum::operator +=(const bignum& b) {
|
||||||
|
int K = isize(b.digits);
|
||||||
|
if(K > isize(digits)) digits.resize(K);
|
||||||
|
int carry = 0;
|
||||||
|
for(int i=0; i<K || carry; i++) {
|
||||||
|
if(i >= isize(digits)) digits.push_back(0);
|
||||||
|
digits[i] += carry;
|
||||||
|
if(i < K) digits[i] += b.digits[i];
|
||||||
|
if(digits[i] >= BASE) {
|
||||||
|
digits[i] -= BASE;
|
||||||
|
carry = 1;
|
||||||
|
}
|
||||||
|
else carry = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bignum::operator < (const bignum& b) const {
|
||||||
|
if(isize(digits) != isize(b.digits))
|
||||||
|
return isize(digits) < isize(b.digits);
|
||||||
|
for(int i = isize(digits)-1; i>=0; i--)
|
||||||
|
if(digits[i] != b.digits[i])
|
||||||
|
return digits[i] < b.digits[i];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum bignum::randomized_div(int x) const {
|
||||||
|
bignum res = self;
|
||||||
|
long long carry = 0;
|
||||||
|
int K = isize(res.digits);
|
||||||
|
for(int i=K-1; i>=0; i--) {
|
||||||
|
carry *= BASE;
|
||||||
|
carry += digits[i];
|
||||||
|
tie(carry, res.digits[i]) = make_pair(carry % x, carry / x);
|
||||||
|
}
|
||||||
|
while(isize(res.digits) && res.digits.back() == 0) res.digits.pop_back();
|
||||||
|
if(rand() % x < carry) res += 1;
|
||||||
|
println(hlog, get_str(100), " / ", x, " = ", res.get_str(100));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bignum::addmul(const bignum& b, int factor) {
|
||||||
|
int K = isize(b.digits);
|
||||||
|
if(K > isize(digits)) digits.resize(K);
|
||||||
|
int carry = 0;
|
||||||
|
for(int i=0; i<K || (carry > 0 || carry < -1) || (carry == -1 && i < isize(digits)); i++) {
|
||||||
|
if(i >= isize(digits)) digits.push_back(0);
|
||||||
|
long long l = digits[i];
|
||||||
|
l += carry;
|
||||||
|
if(i < K) l += b.digits[i] * factor;
|
||||||
|
carry = 0;
|
||||||
|
if(l >= BASE) carry = l / BASE;
|
||||||
|
if(l < 0) carry = -(BASE-1-l) / BASE;
|
||||||
|
l -= carry * BASE;
|
||||||
|
digits[i] = l;
|
||||||
|
}
|
||||||
|
if(carry < 0) digits.back() -= BASE;
|
||||||
|
while(isize(digits) && digits.back() == 0) digits.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
EX bignum hrand(bignum b) {
|
||||||
|
bignum res;
|
||||||
|
int d = isize(b.digits);
|
||||||
|
while(true) {
|
||||||
|
res.digits.resize(d);
|
||||||
|
for(int i=0; i<d-1; i++) res.digits[i] = hrand(bignum::BASE);
|
||||||
|
res.digits.back() = hrand(b.digits.back() + 1);
|
||||||
|
if(res < b) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void operator ++(bignum &b, int) {
|
||||||
|
int i = 0;
|
||||||
|
while(true) {
|
||||||
|
if(isize(b.digits) == i) { b.digits.push_back(1); break; }
|
||||||
|
else if(b.digits[i] == bignum::BASE-1) {
|
||||||
|
b.digits[i] = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b.digits[i]++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EX void operator --(bignum &b, int) {
|
||||||
|
int i = 0;
|
||||||
|
while(true) {
|
||||||
|
if(isize(b.digits) == i) { b.digits.push_back(bignum::BASE-1); break; }
|
||||||
|
else if(b.digits[i] == 0) {
|
||||||
|
b.digits[i] = bignum::BASE-1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b.digits[i]--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string bignum::get_str(int max_length) const {
|
||||||
|
if(digits.empty()) return "0";
|
||||||
|
string ret = its(digits.back());
|
||||||
|
for(int i=isize(digits)-2; i>=0; i--) {
|
||||||
|
if(isize(ret) > max_length && i) {
|
||||||
|
ret += XLAT(" (%1 more digits)", its(9 * (i+1)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += " ";
|
||||||
|
string val = its(digits[i]);
|
||||||
|
while(isize(val) < 9) val = "0" + val;
|
||||||
|
ret += val;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bignum::bignum(ld d) {
|
||||||
|
if(d == 0) return;
|
||||||
|
int n = 1;
|
||||||
|
while(d > BASE) d /= BASE, n++;
|
||||||
|
digits.resize(n);
|
||||||
|
n--;
|
||||||
|
while(n >= 0) { digits[n] = int(d); d -= digits[n]; d *= BASE; n--; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user