game_generation.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. #ifndef __GAME_GENERATION_H
  2. #define __GAME_GENERATION_H
  3. inline std::string make_mapname(int worldx, int worldy, int worldz) {
  4. std::ostringstream cached_map;
  5. cached_map << "_level_" << worldx << "_" << worldy << "_" << worldz << ".dat";
  6. return cached_map.str();
  7. }
  8. inline uint64_t make_fixedseed(int worldx, int worldy, int worldz) {
  9. uint64_t ret = (((uint64_t)worldx) ^
  10. ((uint64_t)worldy << 16) ^
  11. ((uint64_t)worldz << 32)) + 1;
  12. return ret;
  13. }
  14. template <typename FUNC>
  15. void make_map(int worldx, int worldy, int worldz, GameState& state, const Levelskin& lev, FUNC progressbar) {
  16. auto genparams = lev.genparams;
  17. if (genparams.nflatten_walk < 0) {
  18. genparams.nflatten_walk = std::max(0, 5 - 2*(worldx + worldy));
  19. }
  20. if (genparams.nflatten_water < 0) {
  21. genparams.nflatten_water = std::max(0, 3 - 2*(worldx + worldy));
  22. }
  23. if (genparams.nunflow < 0) {
  24. genparams.nunflow = std::min(std::max(0, worldz), 8);
  25. }
  26. state.grid.generate(state.neigh, state.rng, genparams, progressbar);
  27. }
  28. inline void generate_vaults(GameState& state, grid::Map::genmaps_t& ptsource,
  29. unsigned int vaults_level, unsigned int number_vaults, Vault::type_t type,
  30. vault_state_t& vaultstate) {
  31. std::set<grid::pt> affected;
  32. counters::Counts vaults_counts;
  33. switch (type) {
  34. case Vault::type_t::FIXED:
  35. vaults_counts = vaults().fixed_counts;
  36. break;
  37. case Vault::type_t::SEMIRANDOM:
  38. vaults_counts = vaults().semirandom_counts;
  39. break;
  40. case Vault::type_t::RANDOM:
  41. vaults_counts = vaults().random_counts;
  42. break;
  43. }
  44. std::map<tag_t, unsigned int> vc = vaults_counts.take(state.rng, vaults_level, number_vaults, true);
  45. std::map< unsigned int, std::map<tag_t, unsigned int> > s_vc;
  46. for (const auto& vi : vc) {
  47. const Vault& v = vaults().get(vi.first);
  48. s_vc[v.priority].insert(vi);
  49. }
  50. for (const auto& tmp : s_vc) {
  51. for (const auto vi : tmp.second) {
  52. const Vault& v = vaults().get(vi.first);
  53. for (unsigned int ci = 0; ci < vi.second; ++ci) {
  54. generate_vault(v, state, ptsource, vaultstate);
  55. }
  56. }
  57. vault_generation_cleanup(state, vaultstate.affected);
  58. ptsource.swap(grid::Map::genmaps_t(ptsource, state.grid));
  59. }
  60. }
  61. template <typename FUNC>
  62. inline grid::Map::genmaps_t
  63. generate_or_read_cached(const std::string& filename, GameState& state, const Levelskin& lev,
  64. int worldx, int worldy, int worldz, unsigned int vaults_level,
  65. FUNC progressbar, vault_state_t& vaultstate) {
  66. try {
  67. serialize::Source source(filename);
  68. serialize::read(source, state.grid);
  69. serialize::read(source, state.features);
  70. serialize::read(source, vaultstate.summons);
  71. serialize::read(source, vaultstate.itemplace);
  72. serialize::read(source, vaultstate.player_positions);
  73. serialize::read(source, vaultstate.packed);
  74. return grid::Map::genmaps_t(state.grid);
  75. } catch (std::exception& e) {
  76. state.features.init();
  77. vaultstate = vault_state_t();
  78. }
  79. make_map(worldx, worldy, worldz, state, lev, progressbar);
  80. grid::Map::genmaps_t maps(state.grid);
  81. // Place some dungeon features on the same spots every time.
  82. {
  83. progressbar("Placing features..."_m);
  84. counters::Counts terrain_counts = terrain().counts;
  85. unsigned int featscount = ::fabs(state.rng.gauss(lev.number_features.mean, lev.number_features.deviation));
  86. for (unsigned int i = 0; i < featscount; ++i) {
  87. std::map<tag_t, unsigned int> t = terrain_counts.take(state.rng, 0, 1);
  88. for (const auto& j : t) {
  89. state.features.generate(state.rng, state.grid, maps, j.first, j.second);
  90. }
  91. }
  92. }
  93. {
  94. progressbar("Placing vaults..."_m);
  95. generate_vaults(state, maps, vaults_level, lev.number_fixed_vaults, Vault::type_t::FIXED, vaultstate);
  96. }
  97. {
  98. // Having two threads generate the same level at the same time is very rare,
  99. // but let's put a lock in place just in case anyways.
  100. static std::mutex m;
  101. std::unique_lock<std::mutex> l(m);
  102. serialize::Sink sink(filename);
  103. serialize::write(sink, state.grid);
  104. serialize::write(sink, state.features);
  105. serialize::write(sink, vaultstate.summons);
  106. serialize::write(sink, vaultstate.itemplace);
  107. serialize::write(sink, vaultstate.player_positions);
  108. serialize::write(sink, vaultstate.packed);
  109. }
  110. return maps;
  111. }
  112. template <typename FUNC>
  113. void Game::generate(GameState& state, FUNC progressbar) {
  114. // Read or generate cached map.
  115. const Levelskin& lev = levelskins().get(p.worldz);
  116. uint64_t fixedseed = make_fixedseed(p.worldx, p.worldy, p.worldz);
  117. std::string filename = make_mapname(p.worldx, p.worldy, p.worldz);
  118. progressbar("Generating dungeon..."_m);
  119. unsigned int species_level = lev.get_species_level(p.worldz);
  120. unsigned int designs_level = lev.get_designs_level(p.worldz);
  121. unsigned int vaults_level = lev.get_vaults_level(p.worldz);
  122. vault_state_t vaultstate;
  123. // Level-specific random seed that's always the same.
  124. state.rng.init(fixedseed);
  125. grid::Map::genmaps_t maps = generate_or_read_cached(filename, state, lev,
  126. p.worldx, p.worldy, p.worldz,
  127. vaults_level, progressbar, vaultstate);
  128. // //
  129. for (const auto& xy : state.grid.cornermap) {
  130. if (state.grid.walkmap.count(xy) == 0)
  131. throw std::runtime_error("Sanity error 1.1");
  132. }
  133. for (const auto& xy : state.grid.lakemap) {
  134. if (state.grid.walkmap.count(xy) == 0)
  135. throw std::runtime_error("Sanity error 1.2.1");
  136. if (state.grid.watermap.count(xy) == 0)
  137. throw std::runtime_error("Sanity error 1.2.2");
  138. }
  139. for (const auto& xy : state.grid.shoremap) {
  140. if (state.grid.walkmap.count(xy) == 0)
  141. throw std::runtime_error("Sanity error 1.3");
  142. }
  143. for (const auto& xy : state.grid.floormap) {
  144. if (state.grid.watermap.count(xy) != 0)
  145. throw std::runtime_error("Sanity error 1.4");
  146. if (state.grid.walkmap.count(xy) == 0)
  147. throw std::runtime_error("Sanity error 1.5");
  148. }
  149. // A known random seed for the randomized dungeon parts.
  150. size_t& num_visits = state.dungeon_visits_count[worldkey::key_t(p.worldx, p.worldy, p.worldz)];
  151. uint64_t semirandomseed = ((fixedseed + (int)state.moon.pi.phase) & 0xFFFFFFFF);
  152. uint64_t randomseed = ((game_seed + fixedseed + num_visits) & 0xFFFFFFFF);
  153. num_visits++;
  154. //
  155. // Place some vaults. Some are randomized, some are always on the same spots every time.
  156. {
  157. progressbar("Placing vaults..."_m);
  158. state.rng.init(semirandomseed);
  159. generate_vaults(state, maps, vaults_level, lev.number_semirandom_vaults, Vault::type_t::SEMIRANDOM,
  160. vaultstate);
  161. // Initialize a known random sequence here!!
  162. state.rng.init(randomseed);
  163. generate_vaults(state, maps, vaults_level, lev.number_random_vaults, Vault::type_t::RANDOM,
  164. vaultstate);
  165. }
  166. for (const auto& xy : state.grid.cornermap) {
  167. if (state.grid.walkmap.count(xy) == 0)
  168. throw std::runtime_error("Sanity error 2.1");
  169. }
  170. for (const auto& xy : state.grid.lakemap) {
  171. if (state.grid.walkmap.count(xy) == 0)
  172. throw std::runtime_error("Sanity error 2.2.1");
  173. if (state.grid.watermap.count(xy) == 0)
  174. throw std::runtime_error("Sanity error 2.2.2");
  175. }
  176. for (const auto& xy : state.grid.shoremap) {
  177. if (state.grid.walkmap.count(xy) == 0)
  178. throw std::runtime_error("Sanity error 2.3");
  179. }
  180. for (const auto& xy : state.grid.floormap) {
  181. if (state.grid.walkmap.count(xy) == 0)
  182. throw std::runtime_error("Sanity error 2.4");
  183. }
  184. for (const auto& xy : state.grid.floormap) {
  185. if (state.grid.watermap.count(xy) != 0)
  186. throw std::runtime_error("Sanity error 2.5");
  187. }
  188. for (const auto& mv : state.monsters.mgrid) {
  189. if (state.grid.walkmap.count(mv.first) == 0)
  190. throw std::runtime_error("Sanity error 3");
  191. }
  192. //
  193. //
  194. // Place bones.
  195. {
  196. progressbar("Scattering bones..."_m);
  197. std::vector< std::pair<bones::pt, double> > bxy;
  198. bones::bones().get_marks(p.worldx, p.worldy, p.worldz, bxy);
  199. tag_t grave = constants().grave;
  200. for (const auto& marks : bxy) {
  201. const bones::pt& xy = marks.first;
  202. features::Feature feat;
  203. if (state.features.get(xy.first, xy.second, feat)) {
  204. const Terrain& t = terrain().get(feat.tag);
  205. if (t.preserve)
  206. continue;
  207. }
  208. if (!state.grid.is_walk(xy.first, xy.second))
  209. continue;
  210. state.features.set(xy.first, xy.second, grave, state.render);
  211. }
  212. }
  213. // Place saved features.
  214. {
  215. auto feats = permafeats::features().get(p);
  216. for (const auto& i : feats) {
  217. unsigned int x = i.first.first;
  218. unsigned int y = i.first.second;
  219. features::Feature feat;
  220. if (state.features.get(x, y, feat)) {
  221. const Terrain& t = terrain().get(feat.tag);
  222. if (t.preserve)
  223. continue;
  224. }
  225. const auto& spec = i.second;
  226. if (spec.walk.set() && spec.water.set()) {
  227. state.grid.set_walk_water(state.neigh, x, y, spec.walk.is(true), spec.water.is(true));
  228. }
  229. if (!state.grid.is_walk(x, y))
  230. continue;
  231. if (!spec.feat.null()) {
  232. state.features.set(x, y, spec.feat, state.render);
  233. }
  234. if (spec.label.set()) {
  235. state.features.label(x, y, spec.text);
  236. }
  237. }
  238. }
  239. maps.swap(grid::Map::genmaps_t(maps, state.grid));
  240. // Place player.
  241. if (vaultstate.player_positions.empty()) {
  242. grid::pt xy;
  243. if (!maps.one_of_lowlands(state.rng, xy))
  244. throw std::runtime_error("Failed to generate grid");
  245. p.px = xy.first;
  246. p.py = xy.second;
  247. maps.add_nogen_expand(state.neigh, p.px, p.py, 3);
  248. } else {
  249. std::vector<grid::pt> pp;
  250. for (const auto& xy : vaultstate.player_positions) {
  251. if (state.grid.is_walk(xy.first, xy.second)) {
  252. pp.push_back(xy);
  253. }
  254. }
  255. if (pp.empty())
  256. throw std::runtime_error("Failed to generate grid (placement packed)");
  257. const grid::pt& xy = pp[state.rng.n(pp.size())];
  258. p.px = xy.first;
  259. p.py = xy.second;
  260. }
  261. // Place the victory item
  262. if (!p.uniques_disabled) {
  263. size_t unique_series = p.dungeon_unique_series;
  264. if (p.worldx == 0 && p.worldy == 0 && p.worldz == 0 &&
  265. uniques::uniques().generate(constants().uniques_timeout, unique_series)) {
  266. grid::pt xy;
  267. if (maps.one_of_lowlands(state.rng, xy)) {
  268. items::Item vi(constants().unique_item, xy, 1);
  269. state.items.place(xy.first, xy.second, vi, state.render);
  270. }
  271. } else {
  272. std::vector<items::Item> vic = uniques::uniques().get(p.worldx, p.worldy, p.worldz, unique_series);
  273. for (const auto& i : vic) {
  274. state.items.place(i.xy.first, i.xy.second, i, state.render);
  275. }
  276. }
  277. p.dungeon_unique_series = unique_series;
  278. }
  279. // Place saved items.
  280. {
  281. size_t tmp;
  282. std::vector<items::Item> perms = uniques::items().get(p.worldx, p.worldy, p.worldz, tmp);
  283. for (const auto& i : perms) {
  284. if (!state.grid.is_walk(i.xy.first, i.xy.second))
  285. continue;
  286. state.items.place(i.xy.first, i.xy.second, i, state.render);
  287. }
  288. }
  289. // Place some random items.
  290. {
  291. progressbar("Placing items..."_m);
  292. unsigned int items = std::max(0.0, state.rng.gauss(lev.number_items.mean, lev.number_items.deviation));
  293. state.items.generate(state.neigh, state.rng, state.grid, maps,
  294. state.designs_counts, designs_level, items, lev.exclusive_items);
  295. if (p.worldx != 0 || p.worldy != 0) {
  296. if (p.worldx == 0 || p.worldy == 0) {
  297. const auto& bac = constants().bonus_a_items;
  298. unsigned int bonusa = std::max(0.0, state.rng.gauss(bac.mean, bac.deviation));
  299. state.items.generate(state.neigh, state.rng, state.grid, maps,
  300. state.bonus_designs_a_counts, designs_level, bonusa, lev.exclusive_items);
  301. } else {
  302. const auto& bbc = constants().bonus_b_items;
  303. unsigned int bonusb = std::max(0.0, state.rng.gauss(bbc.mean, bbc.deviation));
  304. state.items.generate(state.neigh, state.rng, state.grid, maps,
  305. state.bonus_designs_b_counts, designs_level, bonusb, lev.exclusive_items);
  306. }
  307. }
  308. }
  309. // Place non-random items.
  310. {
  311. for (const auto& s : vaultstate.itemplace) {
  312. tag_t item;
  313. switch (s.type) {
  314. case itemplace_t::type_t::SPECIFIC:
  315. item = s.tag;
  316. break;
  317. case itemplace_t::type_t::LEVEL:
  318. {
  319. auto is = state.designs_counts.take(state.rng, s.level);
  320. if (is.size() > 0) {
  321. item = is.begin()->first;
  322. }
  323. break;
  324. }
  325. case itemplace_t::type_t::LEVEL_ANY:
  326. item = state.designs_counts.find(state.rng, s.level);
  327. break;
  328. }
  329. if (!item.null()) {
  330. if (!state.grid.is_walk(s.x, s.y))
  331. continue;
  332. state.items.place(s.x, s.y,
  333. state.items.make_item(item, items::pt(s.x, s.y), state.rng),
  334. state.render);
  335. }
  336. }
  337. }
  338. // Place some random monsters.
  339. {
  340. progressbar("Placing monsters..."_m);
  341. for (const auto& s : vaultstate.summons) {
  342. switch (s.type) {
  343. case summons_t::type_t::SPECIFIC:
  344. state.monsters.summon(state.neigh, state.rng, state.grid, state.species_counts, state.render,
  345. s.x, s.y, p.px, p.py, s.summontag, s.count, false, s.ally);
  346. break;
  347. case summons_t::type_t::LEVEL:
  348. state.monsters.summon_any(state.neigh, state.rng, state.grid, state.species_counts, state.render,
  349. s.x, s.y, p.px, p.py, s.level, s.count, s.ally);
  350. break;
  351. case summons_t::type_t::GENUS:
  352. state.monsters.summon_genus(state.neigh, state.rng, state.grid, state.species_counts, state.render,
  353. s.x, s.y, p.px, p.py, s.summontag, s.level, s.count, s.ally);
  354. break;
  355. }
  356. }
  357. unsigned int mongroups = ::fabs(state.rng.gauss(lev.number_monsters.mean, lev.number_monsters.deviation));
  358. for (unsigned int i = 0; i < mongroups; ++i) {
  359. state.monsters.generate(state.neigh, state.rng, state.grid, maps,
  360. state.species_counts, species_level, lev.exclusive_monsters);
  361. }
  362. }
  363. state.monsters.replace(state.neigh, state.grid, p.px, p.py, p.followers);
  364. p.followers.clear();
  365. for (const auto& mv : state.monsters.mgrid) {
  366. if (state.grid.walkmap.count(mv.first) == 0) {
  367. throw std::runtime_error("Sanity error 4");
  368. }
  369. }
  370. p.current_wx = p.worldx;
  371. p.current_wy = p.worldy;
  372. p.current_wz = p.worldz;
  373. progressbar("Done!"_m);
  374. }
  375. #endif