💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

552 lines
22 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "game/ecoregion.hpp"
  20. #include <engine/resources/resource-loader.hpp>
  21. #include <engine/resources/resource-manager.hpp>
  22. #include <engine/utility/json.hpp>
  23. #include <engine/math/angles.hpp>
  24. #include <stdexcept>
  25. template <>
  26. std::unique_ptr<ecoregion> resource_loader<ecoregion>::load(::resource_manager& resource_manager, deserialize_context& ctx)
  27. {
  28. // Load JSON data
  29. auto json_data = resource_loader<nlohmann::json>::load(resource_manager, ctx);
  30. // Validate ecoregion file
  31. auto ecoregion_element = json_data->find("ecoregion");
  32. if (ecoregion_element == json_data->end())
  33. throw std::runtime_error("Invalid ecoregion file.");
  34. // Allocate and init ecoregion
  35. std::unique_ptr<::ecoregion> ecoregion = std::make_unique<::ecoregion>();
  36. ecoregion->elevation = 0.0f;
  37. ecoregion->latitude = 0.0f;
  38. ecoregion->longitude = 0.0f;
  39. ecoregion->terrain_material = nullptr;
  40. ecoregion->horizon_material = nullptr;
  41. if (auto element = ecoregion_element->find("name"); element != ecoregion_element->end())
  42. ecoregion->name = element->get<std::string>();
  43. if (auto location_element = ecoregion_element->find("location"); location_element != ecoregion_element->end())
  44. {
  45. if (auto element = location_element->find("elevation"); element != location_element->end())
  46. ecoregion->elevation = element->get<float>();
  47. if (auto element = location_element->find("latitude"); element != location_element->end())
  48. ecoregion->latitude = math::radians(element->get<float>());
  49. if (auto element = location_element->find("longitude"); element != location_element->end())
  50. ecoregion->longitude = math::radians(element->get<float>());
  51. }
  52. if (auto terrain_element = ecoregion_element->find("terrain"); terrain_element != ecoregion_element->end())
  53. {
  54. if (auto element = terrain_element->find("material"); element != terrain_element->end())
  55. ecoregion->terrain_material = resource_manager.load<render::material>(element->get<std::string>());
  56. if (auto element = terrain_element->find("albedo"); element != terrain_element->end())
  57. ecoregion->terrain_albedo = {(*element)[0].get<float>(), (*element)[1].get<float>(), (*element)[2].get<float>()};
  58. if (auto element = terrain_element->find("horizon_material"); element != terrain_element->end())
  59. ecoregion->horizon_material = resource_manager.load<render::material>(element->get<std::string>());
  60. }
  61. // Load gene pools
  62. if (auto gene_pools_element = ecoregion_element->find("gene_pools"); gene_pools_element != ecoregion_element->end())
  63. {
  64. // For each gene pool
  65. for (auto gene_pool_element = gene_pools_element->begin(); gene_pool_element != gene_pools_element->end(); ++gene_pool_element)
  66. {
  67. // Allocate gene pool
  68. ecoregion->gene_pools.resize(ecoregion->gene_pools.size() + 1);
  69. ant_gene_pool& gene_pool = ecoregion->gene_pools.back();
  70. // Read gene pool name
  71. if (auto name_element = gene_pool_element->find("name"); name_element != gene_pool_element->end())
  72. gene_pool.name = name_element->get<std::string>();
  73. // Load genes
  74. if (auto genes_element = gene_pool_element->find("genes"); genes_element != gene_pool_element->end())
  75. {
  76. // Load antennae genes
  77. if (auto antennae_elements = genes_element->find("antennae"); antennae_elements != genes_element->end())
  78. {
  79. for (auto antennae_element = antennae_elements->begin(); antennae_element != antennae_elements->end(); ++antennae_element)
  80. {
  81. float weight = 0.0f;
  82. std::shared_ptr<ant_antennae_gene> gene;
  83. if (auto weight_element = antennae_element->find("weight"); weight_element != antennae_element->end())
  84. weight = weight_element->get<float>();
  85. if (auto gene_element = antennae_element->find("gene"); gene_element != antennae_element->end())
  86. gene = resource_manager.load<ant_antennae_gene>(gene_element->get<std::string>());
  87. if (gene)
  88. {
  89. gene_pool.antennae.weights.push_back(weight);
  90. gene_pool.antennae.genes.push_back(gene);
  91. }
  92. }
  93. }
  94. // Load body size genes
  95. if (auto body_size_elements = genes_element->find("body_size"); body_size_elements != genes_element->end())
  96. {
  97. for (auto body_size_element = body_size_elements->begin(); body_size_element != body_size_elements->end(); ++body_size_element)
  98. {
  99. float weight = 0.0f;
  100. std::shared_ptr<ant_body_size_gene> gene;
  101. if (auto weight_element = body_size_element->find("weight"); weight_element != body_size_element->end())
  102. weight = weight_element->get<float>();
  103. if (auto gene_element = body_size_element->find("gene"); gene_element != body_size_element->end())
  104. gene = resource_manager.load<ant_body_size_gene>(gene_element->get<std::string>());
  105. if (gene)
  106. {
  107. gene_pool.body_size.weights.push_back(weight);
  108. gene_pool.body_size.genes.push_back(gene);
  109. }
  110. }
  111. }
  112. // Load pupa genes
  113. if (auto pupa_elements = genes_element->find("pupa"); pupa_elements != genes_element->end())
  114. {
  115. for (auto pupa_element = pupa_elements->begin(); pupa_element != pupa_elements->end(); ++pupa_element)
  116. {
  117. float weight = 0.0f;
  118. std::shared_ptr<ant_pupa_gene> gene;
  119. if (auto weight_element = pupa_element->find("weight"); weight_element != pupa_element->end())
  120. weight = weight_element->get<float>();
  121. if (auto gene_element = pupa_element->find("gene"); gene_element != pupa_element->end())
  122. gene = resource_manager.load<ant_pupa_gene>(gene_element->get<std::string>());
  123. if (gene)
  124. {
  125. gene_pool.pupa.weights.push_back(weight);
  126. gene_pool.pupa.genes.push_back(gene);
  127. }
  128. }
  129. }
  130. // Load diet genes
  131. if (auto diet_elements = genes_element->find("diet"); diet_elements != genes_element->end())
  132. {
  133. for (auto diet_element = diet_elements->begin(); diet_element != diet_elements->end(); ++diet_element)
  134. {
  135. float weight = 0.0f;
  136. std::shared_ptr<ant_diet_gene> gene;
  137. if (auto weight_element = diet_element->find("weight"); weight_element != diet_element->end())
  138. weight = weight_element->get<float>();
  139. if (auto gene_element = diet_element->find("gene"); gene_element != diet_element->end())
  140. gene = resource_manager.load<ant_diet_gene>(gene_element->get<std::string>());
  141. if (gene)
  142. {
  143. gene_pool.diet.weights.push_back(weight);
  144. gene_pool.diet.genes.push_back(gene);
  145. }
  146. }
  147. }
  148. // Load egg genes
  149. if (auto egg_elements = genes_element->find("egg"); egg_elements != genes_element->end())
  150. {
  151. for (auto egg_element = egg_elements->begin(); egg_element != egg_elements->end(); ++egg_element)
  152. {
  153. float weight = 0.0f;
  154. std::shared_ptr<ant_egg_gene> gene;
  155. if (auto weight_element = egg_element->find("weight"); weight_element != egg_element->end())
  156. weight = weight_element->get<float>();
  157. if (auto gene_element = egg_element->find("gene"); gene_element != egg_element->end())
  158. gene = resource_manager.load<ant_egg_gene>(gene_element->get<std::string>());
  159. if (gene)
  160. {
  161. gene_pool.egg.weights.push_back(weight);
  162. gene_pool.egg.genes.push_back(gene);
  163. }
  164. }
  165. }
  166. // Load eyes genes
  167. if (auto eyes_elements = genes_element->find("eyes"); eyes_elements != genes_element->end())
  168. {
  169. for (auto eyes_element = eyes_elements->begin(); eyes_element != eyes_elements->end(); ++eyes_element)
  170. {
  171. float weight = 0.0f;
  172. std::shared_ptr<ant_eyes_gene> gene;
  173. if (auto weight_element = eyes_element->find("weight"); weight_element != eyes_element->end())
  174. weight = weight_element->get<float>();
  175. if (auto gene_element = eyes_element->find("gene"); gene_element != eyes_element->end())
  176. gene = resource_manager.load<ant_eyes_gene>(gene_element->get<std::string>());
  177. if (gene)
  178. {
  179. gene_pool.eyes.weights.push_back(weight);
  180. gene_pool.eyes.genes.push_back(gene);
  181. }
  182. }
  183. }
  184. // Load foraging time genes
  185. if (auto foraging_time_elements = genes_element->find("foraging_time"); foraging_time_elements != genes_element->end())
  186. {
  187. for (auto foraging_time_element = foraging_time_elements->begin(); foraging_time_element != foraging_time_elements->end(); ++foraging_time_element)
  188. {
  189. float weight = 0.0f;
  190. std::shared_ptr<ant_foraging_time_gene> gene;
  191. if (auto weight_element = foraging_time_element->find("weight"); weight_element != foraging_time_element->end())
  192. weight = weight_element->get<float>();
  193. if (auto gene_element = foraging_time_element->find("gene"); gene_element != foraging_time_element->end())
  194. gene = resource_manager.load<ant_foraging_time_gene>(gene_element->get<std::string>());
  195. if (gene)
  196. {
  197. gene_pool.foraging_time.weights.push_back(weight);
  198. gene_pool.foraging_time.genes.push_back(gene);
  199. }
  200. }
  201. }
  202. // Load founding mode genes
  203. if (auto founding_mode_elements = genes_element->find("founding_mode"); founding_mode_elements != genes_element->end())
  204. {
  205. for (auto founding_mode_element = founding_mode_elements->begin(); founding_mode_element != founding_mode_elements->end(); ++founding_mode_element)
  206. {
  207. float weight = 0.0f;
  208. std::shared_ptr<ant_founding_mode_gene> gene;
  209. if (auto weight_element = founding_mode_element->find("weight"); weight_element != founding_mode_element->end())
  210. weight = weight_element->get<float>();
  211. if (auto gene_element = founding_mode_element->find("gene"); gene_element != founding_mode_element->end())
  212. gene = resource_manager.load<ant_founding_mode_gene>(gene_element->get<std::string>());
  213. if (gene)
  214. {
  215. gene_pool.founding_mode.weights.push_back(weight);
  216. gene_pool.founding_mode.genes.push_back(gene);
  217. }
  218. }
  219. }
  220. // Load gaster genes
  221. if (auto gaster_elements = genes_element->find("gaster"); gaster_elements != genes_element->end())
  222. {
  223. for (auto gaster_element = gaster_elements->begin(); gaster_element != gaster_elements->end(); ++gaster_element)
  224. {
  225. float weight = 0.0f;
  226. std::shared_ptr<ant_gaster_gene> gene;
  227. if (auto weight_element = gaster_element->find("weight"); weight_element != gaster_element->end())
  228. weight = weight_element->get<float>();
  229. if (auto gene_element = gaster_element->find("gene"); gene_element != gaster_element->end())
  230. gene = resource_manager.load<ant_gaster_gene>(gene_element->get<std::string>());
  231. if (gene)
  232. {
  233. gene_pool.gaster.weights.push_back(weight);
  234. gene_pool.gaster.genes.push_back(gene);
  235. }
  236. }
  237. }
  238. // Load head genes
  239. if (auto head_elements = genes_element->find("head"); head_elements != genes_element->end())
  240. {
  241. for (auto head_element = head_elements->begin(); head_element != head_elements->end(); ++head_element)
  242. {
  243. float weight = 0.0f;
  244. std::shared_ptr<ant_head_gene> gene;
  245. if (auto weight_element = head_element->find("weight"); weight_element != head_element->end())
  246. weight = weight_element->get<float>();
  247. if (auto gene_element = head_element->find("gene"); gene_element != head_element->end())
  248. gene = resource_manager.load<ant_head_gene>(gene_element->get<std::string>());
  249. if (gene)
  250. {
  251. gene_pool.head.weights.push_back(weight);
  252. gene_pool.head.genes.push_back(gene);
  253. }
  254. }
  255. }
  256. // Load larva genes
  257. if (auto larva_elements = genes_element->find("larva"); larva_elements != genes_element->end())
  258. {
  259. for (auto larva_element = larva_elements->begin(); larva_element != larva_elements->end(); ++larva_element)
  260. {
  261. float weight = 0.0f;
  262. std::shared_ptr<ant_larva_gene> gene;
  263. if (auto weight_element = larva_element->find("weight"); weight_element != larva_element->end())
  264. weight = weight_element->get<float>();
  265. if (auto gene_element = larva_element->find("gene"); gene_element != larva_element->end())
  266. gene = resource_manager.load<ant_larva_gene>(gene_element->get<std::string>());
  267. if (gene)
  268. {
  269. gene_pool.larva.weights.push_back(weight);
  270. gene_pool.larva.genes.push_back(gene);
  271. }
  272. }
  273. }
  274. // Load legs genes
  275. if (auto legs_elements = genes_element->find("legs"); legs_elements != genes_element->end())
  276. {
  277. for (auto legs_element = legs_elements->begin(); legs_element != legs_elements->end(); ++legs_element)
  278. {
  279. float weight = 0.0f;
  280. std::shared_ptr<ant_legs_gene> gene;
  281. if (auto weight_element = legs_element->find("weight"); weight_element != legs_element->end())
  282. weight = weight_element->get<float>();
  283. if (auto gene_element = legs_element->find("gene"); gene_element != legs_element->end())
  284. gene = resource_manager.load<ant_legs_gene>(gene_element->get<std::string>());
  285. if (gene)
  286. {
  287. gene_pool.legs.weights.push_back(weight);
  288. gene_pool.legs.genes.push_back(gene);
  289. }
  290. }
  291. }
  292. // Load mandibles genes
  293. if (auto mandibles_elements = genes_element->find("mandibles"); mandibles_elements != genes_element->end())
  294. {
  295. for (auto mandibles_element = mandibles_elements->begin(); mandibles_element != mandibles_elements->end(); ++mandibles_element)
  296. {
  297. float weight = 0.0f;
  298. std::shared_ptr<ant_mandibles_gene> gene;
  299. if (auto weight_element = mandibles_element->find("weight"); weight_element != mandibles_element->end())
  300. weight = weight_element->get<float>();
  301. if (auto gene_element = mandibles_element->find("gene"); gene_element != mandibles_element->end())
  302. gene = resource_manager.load<ant_mandibles_gene>(gene_element->get<std::string>());
  303. if (gene)
  304. {
  305. gene_pool.mandibles.weights.push_back(weight);
  306. gene_pool.mandibles.genes.push_back(gene);
  307. }
  308. }
  309. }
  310. // Load mesosoma genes
  311. if (auto mesosoma_elements = genes_element->find("mesosoma"); mesosoma_elements != genes_element->end())
  312. {
  313. for (auto mesosoma_element = mesosoma_elements->begin(); mesosoma_element != mesosoma_elements->end(); ++mesosoma_element)
  314. {
  315. float weight = 0.0f;
  316. std::shared_ptr<ant_mesosoma_gene> gene;
  317. if (auto weight_element = mesosoma_element->find("weight"); weight_element != mesosoma_element->end())
  318. weight = weight_element->get<float>();
  319. if (auto gene_element = mesosoma_element->find("gene"); gene_element != mesosoma_element->end())
  320. gene = resource_manager.load<ant_mesosoma_gene>(gene_element->get<std::string>());
  321. if (gene)
  322. {
  323. gene_pool.mesosoma.weights.push_back(weight);
  324. gene_pool.mesosoma.genes.push_back(gene);
  325. }
  326. }
  327. }
  328. // Load nest site genes
  329. if (auto nest_site_elements = genes_element->find("nest_site"); nest_site_elements != genes_element->end())
  330. {
  331. for (auto nest_site_element = nest_site_elements->begin(); nest_site_element != nest_site_elements->end(); ++nest_site_element)
  332. {
  333. float weight = 0.0f;
  334. std::shared_ptr<ant_nest_site_gene> gene;
  335. if (auto weight_element = nest_site_element->find("weight"); weight_element != nest_site_element->end())
  336. weight = weight_element->get<float>();
  337. if (auto gene_element = nest_site_element->find("gene"); gene_element != nest_site_element->end())
  338. gene = resource_manager.load<ant_nest_site_gene>(gene_element->get<std::string>());
  339. if (gene)
  340. {
  341. gene_pool.nest_site.weights.push_back(weight);
  342. gene_pool.nest_site.genes.push_back(gene);
  343. }
  344. }
  345. }
  346. // Load ocelli genes
  347. if (auto ocelli_elements = genes_element->find("ocelli"); ocelli_elements != genes_element->end())
  348. {
  349. for (auto ocelli_element = ocelli_elements->begin(); ocelli_element != ocelli_elements->end(); ++ocelli_element)
  350. {
  351. float weight = 0.0f;
  352. std::shared_ptr<ant_ocelli_gene> gene;
  353. if (auto weight_element = ocelli_element->find("weight"); weight_element != ocelli_element->end())
  354. weight = weight_element->get<float>();
  355. if (auto gene_element = ocelli_element->find("gene"); gene_element != ocelli_element->end())
  356. gene = resource_manager.load<ant_ocelli_gene>(gene_element->get<std::string>());
  357. if (gene)
  358. {
  359. gene_pool.ocelli.weights.push_back(weight);
  360. gene_pool.ocelli.genes.push_back(gene);
  361. }
  362. }
  363. }
  364. // Load pigmentation genes
  365. if (auto pigmentation_elements = genes_element->find("pigmentation"); pigmentation_elements != genes_element->end())
  366. {
  367. for (auto pigmentation_element = pigmentation_elements->begin(); pigmentation_element != pigmentation_elements->end(); ++pigmentation_element)
  368. {
  369. float weight = 0.0f;
  370. std::shared_ptr<ant_pigmentation_gene> gene;
  371. if (auto weight_element = pigmentation_element->find("weight"); weight_element != pigmentation_element->end())
  372. weight = weight_element->get<float>();
  373. if (auto gene_element = pigmentation_element->find("gene"); gene_element != pigmentation_element->end())
  374. gene = resource_manager.load<ant_pigmentation_gene>(gene_element->get<std::string>());
  375. if (gene)
  376. {
  377. gene_pool.pigmentation.weights.push_back(weight);
  378. gene_pool.pigmentation.genes.push_back(gene);
  379. }
  380. }
  381. }
  382. // Load pilosity genes
  383. if (auto pilosity_elements = genes_element->find("pilosity"); pilosity_elements != genes_element->end())
  384. {
  385. for (auto pilosity_element = pilosity_elements->begin(); pilosity_element != pilosity_elements->end(); ++pilosity_element)
  386. {
  387. float weight = 0.0f;
  388. std::shared_ptr<ant_pilosity_gene> gene;
  389. if (auto weight_element = pilosity_element->find("weight"); weight_element != pilosity_element->end())
  390. weight = weight_element->get<float>();
  391. if (auto gene_element = pilosity_element->find("gene"); gene_element != pilosity_element->end())
  392. gene = resource_manager.load<ant_pilosity_gene>(gene_element->get<std::string>());
  393. if (gene)
  394. {
  395. gene_pool.pilosity.weights.push_back(weight);
  396. gene_pool.pilosity.genes.push_back(gene);
  397. }
  398. }
  399. }
  400. // Load sculpturing genes
  401. if (auto sculpturing_elements = genes_element->find("sculpturing"); sculpturing_elements != genes_element->end())
  402. {
  403. for (auto sculpturing_element = sculpturing_elements->begin(); sculpturing_element != sculpturing_elements->end(); ++sculpturing_element)
  404. {
  405. float weight = 0.0f;
  406. std::shared_ptr<ant_sculpturing_gene> gene;
  407. if (auto weight_element = sculpturing_element->find("weight"); weight_element != sculpturing_element->end())
  408. weight = weight_element->get<float>();
  409. if (auto gene_element = sculpturing_element->find("gene"); gene_element != sculpturing_element->end())
  410. gene = resource_manager.load<ant_sculpturing_gene>(gene_element->get<std::string>());
  411. if (gene)
  412. {
  413. gene_pool.sculpturing.weights.push_back(weight);
  414. gene_pool.sculpturing.genes.push_back(gene);
  415. }
  416. }
  417. }
  418. // Load sting genes
  419. if (auto sting_elements = genes_element->find("sting"); sting_elements != genes_element->end())
  420. {
  421. for (auto sting_element = sting_elements->begin(); sting_element != sting_elements->end(); ++sting_element)
  422. {
  423. float weight = 0.0f;
  424. std::shared_ptr<ant_sting_gene> gene;
  425. if (auto weight_element = sting_element->find("weight"); weight_element != sting_element->end())
  426. weight = weight_element->get<float>();
  427. if (auto gene_element = sting_element->find("gene"); gene_element != sting_element->end())
  428. gene = resource_manager.load<ant_sting_gene>(gene_element->get<std::string>());
  429. if (gene)
  430. {
  431. gene_pool.sting.weights.push_back(weight);
  432. gene_pool.sting.genes.push_back(gene);
  433. }
  434. }
  435. }
  436. // Load waist genes
  437. if (auto waist_elements = genes_element->find("waist"); waist_elements != genes_element->end())
  438. {
  439. for (auto waist_element = waist_elements->begin(); waist_element != waist_elements->end(); ++waist_element)
  440. {
  441. float weight = 0.0f;
  442. std::shared_ptr<ant_waist_gene> gene;
  443. if (auto weight_element = waist_element->find("weight"); weight_element != waist_element->end())
  444. weight = weight_element->get<float>();
  445. if (auto gene_element = waist_element->find("gene"); gene_element != waist_element->end())
  446. gene = resource_manager.load<ant_waist_gene>(gene_element->get<std::string>());
  447. if (gene)
  448. {
  449. gene_pool.waist.weights.push_back(weight);
  450. gene_pool.waist.genes.push_back(gene);
  451. }
  452. }
  453. }
  454. // Load wings genes
  455. if (auto wings_elements = genes_element->find("wings"); wings_elements != genes_element->end())
  456. {
  457. for (auto wings_element = wings_elements->begin(); wings_element != wings_elements->end(); ++wings_element)
  458. {
  459. float weight = 0.0f;
  460. std::shared_ptr<ant_wings_gene> gene;
  461. if (auto weight_element = wings_element->find("weight"); weight_element != wings_element->end())
  462. weight = weight_element->get<float>();
  463. if (auto gene_element = wings_element->find("gene"); gene_element != wings_element->end())
  464. gene = resource_manager.load<ant_wings_gene>(gene_element->get<std::string>());
  465. if (gene)
  466. {
  467. gene_pool.wings.weights.push_back(weight);
  468. gene_pool.wings.genes.push_back(gene);
  469. }
  470. }
  471. }
  472. }
  473. }
  474. }
  475. return ecoregion;
  476. }