// // Created by postaron on 23/02/24. // #include "billy_objects.hpp" #include #include "characteristic/characteristic.hpp" #include "character_sheet.hpp" std::uint32_t constexpr const_hash(const char *input) { return *input ? static_cast(*input) + 33 * const_hash(input + 1) : 5381; } constexpr std::uint32_t weaponsHash = const_hash("weapons"); constexpr std::uint32_t equipmentHash = const_hash("equipments"); constexpr std::uint32_t toolsHash = const_hash("tools"); namespace character { using characteristic::Characteristic; bool BillyObjects::push_object(const billyObject &object, CharacterSheet &sheet) noexcept { if (sheet.objects.size() < 3) { sheet.objects.emplace_back(object); sheet.available_objects.erase(object); auto &local_habilete = static_cast(sheet.habilete); auto &local_adresse = static_cast(sheet.adresse); auto &local_endurance = static_cast(sheet.endurance); auto &local_chance = static_cast(sheet.chance); std::visit(overloaded{ [&](const weapons &arg) { ++sheet.nb_weapons; change_carac_weapon(arg, sheet, local_habilete, local_adresse, local_endurance, plus); }, [&](const equipments &arg) { ++sheet.nb_equipments; change_carac_equipment(arg, sheet, local_habilete, local_adresse, local_endurance, local_chance, plus, minus); }, [&](const tools &arg) { ++sheet.nb_tools; change_carac_tools(arg, sheet, local_habilete, local_adresse, local_endurance, local_chance, plus); }, }, object); return true; } return false; } void BillyObjects::pop_object(CharacterSheet &sheet) noexcept { if (!sheet.objects.empty()) { const billyObject obj = sheet.objects.back(); sheet.objects.pop_back(); sheet.available_objects.insert(obj); auto &local_habilete = static_cast(sheet.habilete); auto &local_adresse = static_cast(sheet.adresse); auto &local_endurance = static_cast(sheet.endurance); auto &local_chance = static_cast(sheet.chance); std::visit(overloaded{ [&](const weapons &arg) { --sheet.nb_weapons; change_carac_weapon(arg, sheet, local_habilete, local_adresse, local_endurance, minus); }, [&](const equipments &arg) { --sheet.nb_equipments; change_carac_equipment(arg, sheet, local_habilete, local_adresse, local_endurance, local_chance, minus, plus); }, [&](const tools &arg) { --sheet.nb_tools; change_carac_tools(arg, sheet, local_habilete, local_adresse, local_endurance, local_chance, minus); } }, obj); } } void BillyObjects::change_carac_tools(const tools &arg, CharacterSheet &sheet, Characteristic &localHabilete, Characteristic &localAdresse, Characteristic &localEndurance, Characteristic &localChance, const std::function &operation) noexcept { switch (arg) { case tools::Fourche: localHabilete.materiel = operation(localHabilete.materiel, 1); localEndurance.materiel = operation(localEndurance.materiel, 3); break; case tools::Dagger: sheet.critique = operation(sheet.critique, 6); break; case tools::RockClimbingKit: localAdresse.materiel = operation(localAdresse.materiel, 1); break; case tools::SackOfGrain: localEndurance.materiel = operation(localEndurance.materiel, 2); localChance.materiel = operation(localChance.materiel, 2); break; } } void BillyObjects::change_carac_equipment(const equipments &arg, CharacterSheet &sheet, Characteristic &localHabilete, Characteristic &localAdresse, Characteristic &localEndurance, Characteristic &localChance, const std::function &primary, const std::function &complement) noexcept { switch (arg) { case equipments::Chainmail: localHabilete.materiel = complement(localHabilete.materiel, 1); localAdresse.materiel = complement(localAdresse.materiel, 1); localEndurance.materiel = primary(localEndurance.materiel, 1); sheet.armor = primary(sheet.armor, 2); break; case equipments::CookingPot: localEndurance.materiel = primary(localEndurance.materiel, 2); sheet.armor = primary(sheet.armor, 1); break; case equipments::PamphletTourist: localChance.materiel = primary(localChance.materiel, 4); break; case equipments::MedicKit: localChance.materiel = primary(localChance.materiel, 1); break; } } void BillyObjects::change_carac_weapon(const weapons &arg, CharacterSheet &sheet, Characteristic &localHabilete, Characteristic &localAdresse, Characteristic &localEndurance, const std::function &operation) noexcept { switch (arg) { case weapons::Sword: localHabilete.materiel = operation(localHabilete.materiel, 4); break; case weapons::Lance: localHabilete.materiel = operation(localHabilete.materiel, 3); localAdresse.materiel = operation(localAdresse.materiel, 1); break; case weapons::Morgenstern: localHabilete.materiel = operation(localHabilete.materiel, 1); localEndurance.materiel = operation(localEndurance.materiel, 1); sheet.damage = operation(sheet.damage, 1); break; case weapons::Bow: localHabilete.materiel = operation(localHabilete.materiel, 3); localAdresse.materiel = operation(localAdresse.materiel, 1); break; } } void BillyObjects::check_dagger_conditions(const CharacterSheet &sheet, Characteristic &localHabilete, const std::function &operation) { int count_weapons = 0; bool is_there_bow = false; std::for_each(sheet.objects.cbegin(), sheet.objects.cend(), [&](const billyObject &object) -> void { if (const weapons *p = std::get_if(std::addressof(object)); p != nullptr) { ++count_weapons; if (*p == weapons::Bow) { is_there_bow = true; } } }); if (count_weapons < 2 && !is_there_bow) { localHabilete.materiel = operation(localHabilete.materiel, 1); } } std::string_view BillyObjects::billy_object_to_string(const billyObject &object) noexcept { return std::visit(overloaded{ [](const weapons &arg) { switch (arg) { case weapons::Sword: return sword; case weapons::Lance: return lance; case weapons::Morgenstern: return morgenstern; case weapons::Bow: return bow; } }, [](const equipments &arg) { switch (arg) { case equipments::Chainmail: return chainmail; case equipments::CookingPot: return cooking_pot; case equipments::MedicKit: return medic_kit; case equipments::PamphletTourist: return pamphlet_tourist; } }, [](const tools &arg) { switch (arg) { case tools::Fourche: return fourche; case tools::Dagger: return dagger; case tools::RockClimbingKit: return rock_climbing_kit; case tools::SackOfGrain: return sack_of_grain; } } }, object); } void BillyObjects::from_json(const json &j, BillyObjects::container &billy) { for (const auto &element: j) { const std::uint32_t key = element[0].get(); const std::uint8_t value = element[1].get(); switch (key) { case weaponsHash: billy.push_back(static_cast(value)); break; case equipmentHash: billy.push_back(static_cast(value)); break; case toolsHash: billy.push_back(static_cast(value)); break; } } } void BillyObjects::to_json(json &j, const BillyObjects::container &billy) { for (const auto &object: billy) { std::visit(overloaded{ [&j](const weapons weapon) { j.emplace_back(std::pair{ weaponsHash, static_cast(weapon) }); }, [&j](const equipments equipment) { j.emplace_back(std::pair{ equipmentHash, static_cast(equipment) }); }, [&j](const tools tool) { j.emplace_back(std::pair{ toolsHash, static_cast(tool) }); } }, object); } } ankerl::svector BillyObjects::check_conformity(const CharacterSheet &sheet) noexcept { ankerl::svector output; std::transform(sheet.get_objects().cbegin(), sheet.get_objects().cend(), std::back_inserter(output), [&sheet](const billyObject &object) -> bool { return std::visit(overloaded{ [](const weapons weapon) { return false; }, [](const equipments equipment) { return false; }, [](const tools tool) { return false; }, }, object); }); const int total = std::accumulate(sheet.get_objects().cbegin(), sheet.get_objects().cend(), 0, [](const int a, const billyObject &object) -> int { return 0; }); return output; } }