mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-20 15:40:26 +00:00
Merge branch 'master' of https://github.com/zenorogue/hyperrogue
This commit is contained in:
commit
1769ec6b69
10
complex2.cpp
10
complex2.cpp
@ -1051,7 +1051,7 @@ EX namespace dice {
|
||||
c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie;
|
||||
generate_specific(c, &d6, 1, 2);
|
||||
}
|
||||
if(pct2 < 40 + hard) {
|
||||
else if(pct2 < 40 + hard) {
|
||||
c->monst = moAnimatedDie;
|
||||
generate_specific(c, &d6, 0, 99);
|
||||
}
|
||||
@ -1062,7 +1062,7 @@ EX namespace dice {
|
||||
c->wall = (pct < (items[itOrbLuck] ? 9 : 11)) ? waRichDie : waHappyDie;
|
||||
generate_specific(c, &d12, 2, 3);
|
||||
}
|
||||
if(pct2 < 40 + hard) {
|
||||
else if(pct2 < 40 + hard) {
|
||||
c->monst = moAnimatedDie;
|
||||
generate_specific(c, &d12, 0, 99);
|
||||
}
|
||||
@ -1153,6 +1153,12 @@ EX namespace dice {
|
||||
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) {
|
||||
auto &cto = mi.t;
|
||||
auto &th = mi.s;
|
||||
|
63
graph.cpp
63
graph.cpp
@ -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(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) {
|
||||
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
|
||||
|
||||
@ -4418,10 +4435,11 @@ EX void drawMarkers() {
|
||||
ignore(ok);
|
||||
|
||||
#if CAP_QUEUE
|
||||
if(haveMount()) ADC(V, dragon::target) {
|
||||
queuestr(V, 1, "X",
|
||||
gradient(0, iinf[itOrbDomination].color, -1, sintick(dragon::whichturn == turncount ? 75 : 150), 1));
|
||||
}
|
||||
if(haveMount())
|
||||
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, dragon::target)) {
|
||||
queuestr(V, 1, "X",
|
||||
gradient(0, iinf[itOrbDomination].color, -1, sintick(dragon::whichturn == turncount ? 75 : 150), 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
|
||||
if(items[itOrbSword]) 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);
|
||||
if(items[itOrbSword2]) ADC(V, cwt.at)
|
||||
queuestr(V * spin((-adj-2*ang)*M_PI/sword_angles) * xpush0(-cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword2].color);
|
||||
if(items[itOrbSword])
|
||||
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, cwt.at))
|
||||
queuestr(V * spin(M_PI+(-adj-2*ang)*M_PI/sword_angles) * xpush0(cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword].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(items[itOrbSword]) ADC(V, cwt.at)
|
||||
queuestr(V * sword::dir[multi::cpid].T * xpush0(cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword].color);
|
||||
if(items[itOrbSword2]) ADC(V, cwt.at)
|
||||
queuestr(V * sword::dir[multi::cpid].T * xpush0(-cgi.sword_size), vid.fsize*2, "+", iinf[itOrbSword2].color);
|
||||
if(items[itOrbSword])
|
||||
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[itOrbSword].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;
|
||||
flashdata& f = flashes[k];
|
||||
bool copies = false;
|
||||
ADC(V, f.where) copies = true, draw_flash(f, V, kill);
|
||||
forCellIdEx(c2, id, f.where) if(!copies) ADC(V, c2) {
|
||||
draw_flash(f, V * currentmap->iadj(f.where, id), kill);
|
||||
for (const shiftmatrix& V : hr::span_at(current_display->all_drawn_copies, f.where)) {
|
||||
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) {
|
||||
kill = false;
|
||||
|
7
help.cpp
7
help.cpp
@ -945,6 +945,9 @@ EX void describeMouseover() {
|
||||
|
||||
if(c->wall == waRose) out += " (" + its(7-rosephase) + ")";
|
||||
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)
|
||||
help =
|
||||
@ -972,6 +975,10 @@ EX void describeMouseover() {
|
||||
|
||||
else if(c->monst) {
|
||||
out += ", "; out += XLAT1(minf[c->monst].name);
|
||||
#if CAP_COMPLEX2
|
||||
if(isDie(c->monst))
|
||||
out += " (" + dice::describe(c) + ")";
|
||||
#endif
|
||||
if(hasHitpoints(c->monst))
|
||||
out += " (" + its(c->hitpoints)+" HP)";
|
||||
if(isMutantIvy(c))
|
||||
|
12
hyper.h
12
hyper.h
@ -575,11 +575,6 @@ typedef function<int(struct cell*)> cellfunction;
|
||||
#define forCellCM(ct, cf) forCellIdCM(ct,forCellCM ## __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
|
||||
|
||||
#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, 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 {
|
||||
extern bool on;
|
||||
extern int daily_id;
|
||||
|
10
landgen.cpp
10
landgen.cpp
@ -537,8 +537,8 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
c->item = hrand(100) < 80 ? itOrbFrog : itOrbDiscord;
|
||||
if(hrand(5000) < 20*PRIZEMUL && c->wall != waOpenGate)
|
||||
placePrizeOrb(c);
|
||||
if(c->wall == waNone) buildPrizeMirror(c, 250);
|
||||
if(c->land == laPalace && (eubinary || c->master->alt) && celldistAlt(c) <= 150 && !(havewhat&HF_MOUSE) && !princess::generating &&
|
||||
if(c->wall == waNone && buildPrizeMirror(c, 250)) {}
|
||||
else if(c->land == laPalace && (eubinary || c->master->alt) && celldistAlt(c) <= 150 && !(havewhat&HF_MOUSE) && !princess::generating &&
|
||||
princess::getPrisonInfo(c) &&
|
||||
(eubinary || (princess::getPrisonInfo(c)->bestdist < 6 && princess::getPrisonInfo(c)->princess))) {
|
||||
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;
|
||||
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;
|
||||
forCellEx(c2, c) if(c2->monst == moMonk)
|
||||
c->item = itNone;
|
||||
@ -2587,8 +2587,9 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
|
||||
case laDice: {
|
||||
#if CAP_COMPLEX2
|
||||
if(fargen)
|
||||
if(fargen && !c->monst && !c->wall) {
|
||||
dice::generate_full(c, items[itDice] + yendor::hardness());
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -2632,6 +2633,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) {
|
||||
c->monst = moHexer;
|
||||
c->item = pick(itCurseWeakness, itCurseDraining, itCurseWater, itCurseFatigue, itCurseRepulsion, itCurseGluttony);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7270,10 +7270,23 @@ S("A brown gem.", "Коричневый камень.")
|
||||
Orb("Choice", "Выбора")
|
||||
|
||||
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, "Падающая собака", "Падающие собаки", "Падающую собаку", "Падающей собакой")
|
||||
S("Distant relatives of the Running Dogs.", "Дальние родственники Бегущих собак.")
|
||||
N("Western Hawk", GEN_M, "Западный ястреб", "Западные ястреба", "Западного ястреба", "Западным ястребом")
|
||||
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", "Гравитации")
|
||||
|
||||
N("Irradiated Field", GEN_N, "Облучённое поле", "Облучённые поля", "Облучённое поле", "в Облучённом поле")
|
||||
|
@ -232,7 +232,7 @@ void parrep(string& x, string w, stringpar p) {
|
||||
rep(x, "%a"+w, N->n[3].acc);
|
||||
rep(x, "%abl"+w, N->n[3].abl);
|
||||
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, "%y"+w, choose3(N->n[3].genus, "ый", "ая", "ое"));
|
||||
}
|
||||
|
@ -1796,8 +1796,13 @@ EX void specialMoves() {
|
||||
if(m == moHunterGuard && items[itHunting] >= 10)
|
||||
c->monst = moHunterChanging;
|
||||
|
||||
if(m == moHunterDog && (havewhat & HF_FAILED_AMBUSH) && hyperbolic && !quotient)
|
||||
c->monst = moHunterChanging;
|
||||
if ((havewhat & HF_FAILED_AMBUSH) && hyperbolic && !quotient) {
|
||||
if(m == moHunterDog)
|
||||
c->monst = moHunterChanging;
|
||||
forCellEx(c2, c)
|
||||
if(c2->monst == moHunterDog)
|
||||
c2->monst = moHunterChanging;
|
||||
}
|
||||
|
||||
if(m == moSleepBull && !peace::on) {
|
||||
bool wakeup = false;
|
||||
|
@ -297,7 +297,7 @@ EX eOrbLandRelation getOLR(eItem it, eLand l) {
|
||||
|
||||
if(it == itOrbSlaying && !among(l,
|
||||
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;
|
||||
|
||||
if(l == laCocytus)
|
||||
|
28
util.cpp
28
util.cpp
@ -207,10 +207,10 @@ cld exp_parser::parse(int prio) {
|
||||
cld c = rparse(0);
|
||||
force_eat(")");
|
||||
|
||||
IF_KEY_EXISTS(it, extra_params, "angleunit") {
|
||||
a *= it->second;
|
||||
b *= it->second;
|
||||
c *= it->second;
|
||||
if (auto *angleunit = hr::at_or_null(extra_params, "angleunit")) {
|
||||
a *= *angleunit;
|
||||
b *= *angleunit;
|
||||
c *= *angleunit;
|
||||
}
|
||||
|
||||
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_geometry();
|
||||
res = test.edgelength;
|
||||
IF_KEY_EXISTS(it, extra_params, "distunit")
|
||||
res /= it->second;
|
||||
if (auto *distunit = hr::at_or_null(extra_params, "distunit"))
|
||||
res /= *distunit;
|
||||
}
|
||||
#endif
|
||||
else if(eat("regangle(")) {
|
||||
cld edgelen = parse(0);
|
||||
IF_KEY_EXISTS(it, extra_params, "distunit") {
|
||||
edgelen = edgelen * it->second;
|
||||
if (auto *distunit = hr::at_or_null(extra_params, "distunit")) {
|
||||
edgelen *= *distunit;
|
||||
}
|
||||
|
||||
force_eat(",");
|
||||
@ -260,14 +260,14 @@ cld exp_parser::parse(int prio) {
|
||||
|
||||
if(arb::legacy) {
|
||||
res = M_PI - result;
|
||||
IF_KEY_EXISTS(it, extra_params, "angleofs")
|
||||
res -= it->second;
|
||||
if (auto *angleofs = hr::at_or_null(extra_params, "angleofs"))
|
||||
res -= *angleofs;
|
||||
}
|
||||
else
|
||||
res = result;
|
||||
|
||||
IF_KEY_EXISTS(it, extra_params, "angleunit")
|
||||
res /= it->second;
|
||||
if (auto *angleunit = hr::at_or_null(extra_params, "angleunit"))
|
||||
res /= *angleunit;
|
||||
}
|
||||
else if(eat("test(")) {
|
||||
res = parsepar();
|
||||
@ -318,8 +318,8 @@ cld exp_parser::parse(int prio) {
|
||||
else if(next() == '(') at++, res = parsepar();
|
||||
else {
|
||||
string number = next_token();
|
||||
IF_KEY_EXISTS(it, extra_params, number) res = it->second;
|
||||
else IF_KEY_EXISTS(it, params, number) res = it->second->get_cld();
|
||||
if (auto *p = hr::at_or_null(extra_params, number)) res = *p;
|
||||
else if (auto *p = hr::at_or_null(params, number)) res = (*p)->get_cld();
|
||||
else if(number == "e") res = exp(1);
|
||||
else if(number == "i") res = cld(0, 1);
|
||||
else if(number == "p" || number == "pi") res = M_PI;
|
||||
|
Loading…
Reference in New Issue
Block a user