mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 22:12:59 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/zenorogue/hyperrogue
This commit is contained in:
		
							
								
								
									
										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; | ||||
|   | ||||
							
								
								
									
										47
									
								
								graph.cpp
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								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,7 +4435,8 @@ EX void drawMarkers() { | ||||
|     ignore(ok); | ||||
|       | ||||
|     #if CAP_QUEUE | ||||
|     if(haveMount()) ADC(V, dragon::target) { | ||||
|     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)); | ||||
|         } | ||||
| @@ -4536,15 +4554,19 @@ EX void drawMarkers() { | ||||
|  | ||||
|       int adj = 1 - ((sword_angles/cwt.at->type)&1); | ||||
|        | ||||
|       if(items[itOrbSword]) ADC(V, cwt.at) | ||||
|       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]) ADC(V, cwt.at) | ||||
|       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) | ||||
|       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]) ADC(V, cwt.at) | ||||
|       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,11 +4625,18 @@ 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) { | ||||
|     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) | ||||
|     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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue