1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-11-13 04:13:03 +00:00
This commit is contained in:
Zeno Rogue
2021-07-21 10:51:40 +02:00
10 changed files with 110 additions and 46 deletions

View File

@@ -1051,7 +1051,7 @@ EX namespace dice {
c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie; c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie;
generate_specific(c, &d6, 1, 2); generate_specific(c, &d6, 1, 2);
} }
if(pct2 < 40 + hard) { else if(pct2 < 40 + hard) {
c->monst = moAnimatedDie; c->monst = moAnimatedDie;
generate_specific(c, &d6, 0, 99); generate_specific(c, &d6, 0, 99);
} }
@@ -1062,7 +1062,7 @@ EX namespace dice {
c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie; c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie;
generate_specific(c, &d12, 2, 3); generate_specific(c, &d12, 2, 3);
} }
if(pct2 < 40 + hard) { else if(pct2 < 40 + hard) {
c->monst = moAnimatedDie; c->monst = moAnimatedDie;
generate_specific(c, &d12, 0, 99); generate_specific(c, &d12, 0, 99);
} }
@@ -1153,6 +1153,12 @@ EX namespace dice {
return isDie(c->wall) || isDie(c->monst); return isDie(c->wall) || isDie(c->monst);
} }
EX string describe(cell *c) {
if (!data.count(c)) return "BUG: die data missing";
else if (!data[c].which) return "BUG: die data default-initialized";
else return XLAT("d%1 rolled %2", its(data[c].which->faces), its(data[c].val + 1));
}
EX void roll(movei mi) { EX void roll(movei mi) {
auto &cto = mi.t; auto &cto = mi.t;
auto &th = mi.s; auto &th = mi.s;

View File

@@ -45,7 +45,23 @@ EX bool hide_player() {
; ;
} }
#define ADC(V,c) IF_KEY_EXISTS(it, current_display->all_drawn_copies, c) for(const shiftmatrix& V: it->second) template<class T>
class span {
T *begin_ = nullptr;
T *end_ = nullptr;
public:
explicit span() = default;
explicit span(T *p, int n) : begin_(p), end_(p + n) {}
T *begin() const { return begin_; }
T *end() const { return end_; }
};
template<class Map, class Key>
hr::span<const shiftmatrix> span_at(const Map& map, const Key& key) {
auto it = map.find(key);
return (it == map.end()) ? hr::span<const shiftmatrix>() : hr::span<const shiftmatrix>(it->second.data(), it->second.size());
}
EX hookset<bool(int sym, int uni)> hooks_handleKey; EX hookset<bool(int sym, int uni)> hooks_handleKey;
EX hookset<bool(cell *c, const shiftmatrix& V)> hooks_drawcell; EX hookset<bool(cell *c, const shiftmatrix& V)> hooks_drawcell;
@@ -4361,7 +4377,8 @@ EX void queuecircleat1(cell *c, const shiftmatrix& V, double rad, color_t col) {
EX void queuecircleat(cell *c, double rad, color_t col) { EX void queuecircleat(cell *c, double rad, color_t col) {
if(!c) return; if(!c) return;
ADC(V, c) queuecircleat1(c, V, rad, col); for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, c))
queuecircleat1(c, V, rad, col);
} }
#endif #endif
@@ -4418,10 +4435,11 @@ EX void drawMarkers() {
ignore(ok); ignore(ok);
#if CAP_QUEUE #if CAP_QUEUE
if(haveMount()) ADC(V, dragon::target) { if(haveMount())
queuestr(V, 1, "X", for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, dragon::target)) {
gradient(0, iinf[itOrbDomination].color, -1, sintick(dragon::whichturn == turncount ? 75 : 150), 1)); queuestr(V, 1, "X",
} gradient(0, iinf[itOrbDomination].color, -1, sintick(dragon::whichturn == turncount ? 75 : 150), 1));
}
#endif #endif
/* for(int i=0; i<12; i++) if(c->type == 5 && c->master == &dodecahedron[i]) /* for(int i=0; i<12; i++) if(c->type == 5 && c->master == &dodecahedron[i])
@@ -4536,16 +4554,20 @@ EX void drawMarkers() {
int adj = 1 - ((sword_angles/cwt.at->type)&1); int adj = 1 - ((sword_angles/cwt.at->type)&1);
if(items[itOrbSword]) ADC(V, cwt.at) if(items[itOrbSword])
queuestr(V * spin(M_PI+(-adj-2*ang)*M_PI/sword_angles) * xpush0(cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword].color); for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, cwt.at))
if(items[itOrbSword2]) ADC(V, cwt.at) queuestr(V * spin(M_PI+(-adj-2*ang)*M_PI/sword_angles) * xpush0(cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword].color);
queuestr(V * spin((-adj-2*ang)*M_PI/sword_angles) * xpush0(-cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword2].color); if(items[itOrbSword2])
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, cwt.at))
queuestr(V * spin((-adj-2*ang)*M_PI/sword_angles) * xpush0(-cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword2].color);
} }
if(SWORDDIM == 3 && !shmup::on) { if(SWORDDIM == 3 && !shmup::on) {
if(items[itOrbSword]) ADC(V, cwt.at) if(items[itOrbSword])
queuestr(V * sword::dir[multi::cpid].T * xpush0(cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword].color); for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, cwt.at))
if(items[itOrbSword2]) ADC(V, cwt.at) queuestr(V * sword::dir[multi::cpid].T * xpush0(cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword].color);
queuestr(V * sword::dir[multi::cpid].T * xpush0(-cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword2].color); if(items[itOrbSword2])
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, cwt.at))
queuestr(V * sword::dir[multi::cpid].T * xpush0(-cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword2].color);
} }
} }
@@ -4603,10 +4625,17 @@ void drawFlashes() {
bool kill = true; bool kill = true;
flashdata& f = flashes[k]; flashdata& f = flashes[k];
bool copies = false; bool copies = false;
ADC(V, f.where) copies = true, draw_flash(f, V, kill); for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, f.where)) {
forCellIdEx(c2, id, f.where) if(!copies) ADC(V, c2) {
draw_flash(f, V * currentmap->iadj(f.where, id), kill);
copies = true; copies = true;
draw_flash(f, V, kill);
}
forCellIdEx(c2, id, f.where) {
if(!copies) {
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, c2)) {
draw_flash(f, V * currentmap->iadj(f.where, id), kill);
copies = true;
}
}
} }
if(f.t > ticks - 800 && !copies) { if(f.t > ticks - 800 && !copies) {
kill = false; kill = false;

View File

@@ -945,6 +945,9 @@ EX void describeMouseover() {
if(c->wall == waRose) out += " (" + its(7-rosephase) + ")"; if(c->wall == waRose) out += " (" + its(7-rosephase) + ")";
if(c->wall == waTerraWarrior) out += " (" + its(c->landparam) + ")"; if(c->wall == waTerraWarrior) out += " (" + its(c->landparam) + ")";
#if CAP_COMPLEX2
if(isDie(c->wall)) out += " (" + dice::describe(c) + ")";
#endif
if((c->wall == waBigTree || c->wall == waSmallTree) && c->land != laDryForest) if((c->wall == waBigTree || c->wall == waSmallTree) && c->land != laDryForest)
help = help =
@@ -972,6 +975,10 @@ EX void describeMouseover() {
else if(c->monst) { else if(c->monst) {
out += ", "; out += XLAT1(minf[c->monst].name); out += ", "; out += XLAT1(minf[c->monst].name);
#if CAP_COMPLEX2
if(isDie(c->monst))
out += " (" + dice::describe(c) + ")";
#endif
if(hasHitpoints(c->monst)) if(hasHitpoints(c->monst))
out += " (" + its(c->hitpoints)+" HP)"; out += " (" + its(c->hitpoints)+" HP)";
if(isMutantIvy(c)) if(isMutantIvy(c))

12
hyper.h
View File

@@ -575,11 +575,6 @@ typedef function<int(struct cell*)> cellfunction;
#define forCellCM(ct, cf) forCellIdCM(ct,forCellCM ## __LINE__,cf) #define forCellCM(ct, cf) forCellIdCM(ct,forCellCM ## __LINE__,cf)
#define forCellAll(ct, cf) forCellIdCM(ct,forCellAll ## __LINE__,cf) #define forCellAll(ct, cf) forCellIdCM(ct,forCellAll ## __LINE__,cf)
/* conditions */
/** `IF_KEY_EXISTS(it, map, key) statement` checks whether the map 'map' contain key 'key', and if so, executes statement with it set to the relevant iterator */
#define IF_KEY_EXISTS(it, map, key) for(auto it: {map.find(key)}) if(it != map.end())
// canAttack/moveval flags // canAttack/moveval flags
#define AF_NORMAL 0 // nothing special about this attack #define AF_NORMAL 0 // nothing special about this attack
@@ -851,6 +846,13 @@ template<class T> array<T, 4> make_array(T a, T b, T c, T d) { array<T,4> x; x[0
template<class T> array<T, 3> make_array(T a, T b, T c) { array<T,3> x; x[0] = a; x[1] = b; x[2] = c; return x; } template<class T> array<T, 3> make_array(T a, T b, T c) { array<T,3> x; x[0] = a; x[1] = b; x[2] = c; return x; }
template<class T> array<T, 2> make_array(T a, T b) { array<T,2> x; x[0] = a; x[1] = b; return x; } template<class T> array<T, 2> make_array(T a, T b) { array<T,2> x; x[0] = a; x[1] = b; return x; }
// Find in a std::map or std::unordered_map, or return null.
template<class Map, class Key>
const typename Map::mapped_type *at_or_null(const Map& map, const Key& key) {
auto it = map.find(key);
return (it == map.end()) ? nullptr : &it->second;
}
namespace daily { namespace daily {
extern bool on; extern bool on;
extern int daily_id; extern int daily_id;

View File

@@ -537,8 +537,8 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
c->item = hrand(100) < 80 ? itOrbFrog : itOrbDiscord; c->item = hrand(100) < 80 ? itOrbFrog : itOrbDiscord;
if(hrand(5000) < 20*PRIZEMUL && c->wall != waOpenGate) if(hrand(5000) < 20*PRIZEMUL && c->wall != waOpenGate)
placePrizeOrb(c); placePrizeOrb(c);
if(c->wall == waNone) buildPrizeMirror(c, 250); if(c->wall == waNone && buildPrizeMirror(c, 250)) {}
if(c->land == laPalace && (eubinary || c->master->alt) && celldistAlt(c) <= 150 && !(havewhat&HF_MOUSE) && !princess::generating && else if(c->land == laPalace && (eubinary || c->master->alt) && celldistAlt(c) <= 150 && !(havewhat&HF_MOUSE) && !princess::generating &&
princess::getPrisonInfo(c) && princess::getPrisonInfo(c) &&
(eubinary || (princess::getPrisonInfo(c)->bestdist < 6 && princess::getPrisonInfo(c)->princess))) { (eubinary || (princess::getPrisonInfo(c)->bestdist < 6 && princess::getPrisonInfo(c)->princess))) {
c->monst = moMouse; c->monst = moMouse;
@@ -2345,7 +2345,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
} }
if(d == 7 && c->landparam == 2) forCellEx(c2, c) if(c2->land == laRuins && out_ruin(c2)) c->landparam = 1; if(d == 7 && c->landparam == 2) forCellEx(c2, c) if(c2->land == laRuins && out_ruin(c2)) c->landparam = 1;
ONEMPTY { ONEMPTY {
if(hrand(1500) < PT(30 + kills[moHexDemon] + kills[moSkeleton] + kills[moMonk] + kills[moPair], 100) && notDippingFor(itRuins)) { if(hrand(1500) < PT(30 + kills[moHexDemon] + kills[moAltDemon] + kills[moMonk] + kills[moPair] + kills[moCrusher], 100) && notDippingFor(itRuins)) {
c->item = itRuins; c->item = itRuins;
forCellEx(c2, c) if(c2->monst == moMonk) forCellEx(c2, c) if(c2->monst == moMonk)
c->item = itNone; c->item = itNone;
@@ -2587,8 +2587,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
case laDice: { case laDice: {
#if CAP_COMPLEX2 #if CAP_COMPLEX2
if(fargen) if(fargen && !c->monst && !c->wall) {
dice::generate_full(c, items[itDice] + yendor::hardness()); dice::generate_full(c, items[itDice] + yendor::hardness());
}
#endif #endif
break; break;
} }
@@ -2632,6 +2633,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
c->monst = moHexer; c->monst = moHexer;
c->item = pick(itCurseWeakness, itCurseDraining, itCurseWater, itCurseFatigue, itCurseRepulsion, itCurseGluttony); c->item = pick(itCurseWeakness, itCurseDraining, itCurseWater, itCurseFatigue, itCurseRepulsion, itCurseGluttony);
} }
break;
} }
} }

View File

@@ -7270,10 +7270,23 @@ S("A brown gem.", "Коричневый камень.")
Orb("Choice", "Выбора") Orb("Choice", "Выбора")
N("Free Fall", GEN_O, "Свободное падение", "Свободные падения", "Свободное падение", "в Свободном падении") N("Free Fall", GEN_O, "Свободное падение", "Свободные падения", "Свободное падение", "в Свободном падении")
S("What on one side looks to be a normal (well, infinite) horizontal wall, on the other side turns out to be the vertical wall"
" of an infinitely high tower. Jump from the window, and let the magical gravity carry you...",
"То, что на одной стороне похоже на обычную (хотя и бесконечную) горизонтальную стену, "
"на другой стороне оказывается вертикальной стеной бесконечно высокой башни. "
"Выпрыгайте через окно, и пусть сила волшебной тяжести везёт Вас...")
N("Falling Dog", GEN_F, "Падающая собака", "Падающие собаки", "Падающую собаку", "Падающей собакой") N("Falling Dog", GEN_F, "Падающая собака", "Падающие собаки", "Падающую собаку", "Падающей собакой")
S("Distant relatives of the Running Dogs.", "Дальние родственники Бегущих собак.") S("Distant relatives of the Running Dogs.", "Дальние родственники Бегущих собак.")
N("Western Hawk", GEN_M, "Западный ястреб", "Западные ястреба", "Западного ястреба", "Западным ястребом") N("Western Hawk", GEN_M, "Западный ястреб", "Западные ястреба", "Западного ястреба", "Западным ястребом")
N("Meteorite", GEN_O, "Метеорит", "Метеориты", "Метеорит", "Метеоритом") N("Meteorite", GEN_O, "Метеорит", "Метеориты", "Метеорит", "Метеоритом")
S("These rocks falling from the sky have been captured to fall forever in the artificial gravity. Meteorite iron is believed to be a valuable material for magical weapons.",
"Эти падающие с неба камни захвачены, чтобы вечно падать под силой исскуственной тяжести. "
"Верят, что метеоритное железо - ценный материал для ковки волшебных орудий.")
Orb("Gravity", "Гравитации") Orb("Gravity", "Гравитации")
N("Irradiated Field", GEN_N, "Облучённое поле", "Облучённые поля", "Облучённое поле", "в Облучённом поле") N("Irradiated Field", GEN_N, "Облучённое поле", "Облучённые поля", "Облучённое поле", "в Облучённом поле")

View File

@@ -232,7 +232,7 @@ void parrep(string& x, string w, stringpar p) {
rep(x, "%a"+w, N->n[3].acc); rep(x, "%a"+w, N->n[3].acc);
rep(x, "%abl"+w, N->n[3].abl); rep(x, "%abl"+w, N->n[3].abl);
rep(x, "%E"+w, choose3(N->n[3].genus, "", "а", "о")); rep(x, "%E"+w, choose3(N->n[3].genus, "", "а", "о"));
rep(x, "%A"+w, choose3(N->n[3].genus, "ый", "ая", "ое")); rep(x, "%A"+w, choose3(N->n[3].genus, "ый", "ую", "ое"));
rep(x, "%c"+w, choose3(N->n[3].genus, "ся", "ась", "")); rep(x, "%c"+w, choose3(N->n[3].genus, "ся", "ась", ""));
rep(x, "%y"+w, choose3(N->n[3].genus, "ый", "ая", "ое")); rep(x, "%y"+w, choose3(N->n[3].genus, "ый", "ая", "ое"));
} }

View File

@@ -1796,8 +1796,13 @@ EX void specialMoves() {
if(m == moHunterGuard && items[itHunting] >= 10) if(m == moHunterGuard && items[itHunting] >= 10)
c->monst = moHunterChanging; c->monst = moHunterChanging;
if(m == moHunterDog && (havewhat & HF_FAILED_AMBUSH) && hyperbolic && !quotient) if ((havewhat & HF_FAILED_AMBUSH) && hyperbolic && !quotient) {
c->monst = moHunterChanging; if(m == moHunterDog)
c->monst = moHunterChanging;
forCellEx(c2, c)
if(c2->monst == moHunterDog)
c2->monst = moHunterChanging;
}
if(m == moSleepBull && !peace::on) { if(m == moSleepBull && !peace::on) {
bool wakeup = false; bool wakeup = false;

View File

@@ -297,7 +297,7 @@ EX eOrbLandRelation getOLR(eItem it, eLand l) {
if(it == itOrbSlaying && !among(l, if(it == itOrbSlaying && !among(l,
laMirror, laHell, laEmerald, laDryForest, laCamelot, laPalace, laStorms, laRose, laTortoise, laBurial, laDungeon, laReptile, laMirror, laHell, laEmerald, laDryForest, laCamelot, laPalace, laStorms, laRose, laTortoise, laBurial, laDungeon, laReptile,
laPrairie, laBull, laVolcano, laTerracotta, laRuins, laVariant, laEclectic, laBrownian)) laPrairie, laBull, laVolcano, laTerracotta, laRuins, laVariant, laEclectic, laBrownian, laCursed))
return olrUseless; return olrUseless;
if(l == laCocytus) if(l == laCocytus)

View File

@@ -207,10 +207,10 @@ cld exp_parser::parse(int prio) {
cld c = rparse(0); cld c = rparse(0);
force_eat(")"); force_eat(")");
IF_KEY_EXISTS(it, extra_params, "angleunit") { if (auto *angleunit = hr::at_or_null(extra_params, "angleunit")) {
a *= it->second; a *= *angleunit;
b *= it->second; b *= *angleunit;
c *= it->second; c *= *angleunit;
} }
return edge_of_triangle_with_angles(real(a), real(b), real(c)); return edge_of_triangle_with_angles(real(a), real(b), real(c));
@@ -237,14 +237,14 @@ cld exp_parser::parse(int prio) {
test.compute_sum(); test.compute_sum();
test.compute_geometry(); test.compute_geometry();
res = test.edgelength; res = test.edgelength;
IF_KEY_EXISTS(it, extra_params, "distunit") if (auto *distunit = hr::at_or_null(extra_params, "distunit"))
res /= it->second; res /= *distunit;
} }
#endif #endif
else if(eat("regangle(")) { else if(eat("regangle(")) {
cld edgelen = parse(0); cld edgelen = parse(0);
IF_KEY_EXISTS(it, extra_params, "distunit") { if (auto *distunit = hr::at_or_null(extra_params, "distunit")) {
edgelen = edgelen * it->second; edgelen *= *distunit;
} }
force_eat(","); force_eat(",");
@@ -260,14 +260,14 @@ cld exp_parser::parse(int prio) {
if(arb::legacy) { if(arb::legacy) {
res = M_PI - result; res = M_PI - result;
IF_KEY_EXISTS(it, extra_params, "angleofs") if (auto *angleofs = hr::at_or_null(extra_params, "angleofs"))
res -= it->second; res -= *angleofs;
} }
else else
res = result; res = result;
IF_KEY_EXISTS(it, extra_params, "angleunit") if (auto *angleunit = hr::at_or_null(extra_params, "angleunit"))
res /= it->second; res /= *angleunit;
} }
else if(eat("test(")) { else if(eat("test(")) {
res = parsepar(); res = parsepar();
@@ -318,8 +318,8 @@ cld exp_parser::parse(int prio) {
else if(next() == '(') at++, res = parsepar(); else if(next() == '(') at++, res = parsepar();
else { else {
string number = next_token(); string number = next_token();
IF_KEY_EXISTS(it, extra_params, number) res = it->second; if (auto *p = hr::at_or_null(extra_params, number)) res = *p;
else IF_KEY_EXISTS(it, params, number) res = it->second->get_cld(); else if (auto *p = hr::at_or_null(params, number)) res = (*p)->get_cld();
else if(number == "e") res = exp(1); else if(number == "e") res = exp(1);
else if(number == "i") res = cld(0, 1); else if(number == "i") res = cld(0, 1);
else if(number == "p" || number == "pi") res = M_PI; else if(number == "p" || number == "pi") res = M_PI;