Skip to content

Commit

Permalink
generating items
Browse files Browse the repository at this point in the history
  • Loading branch information
malytomas committed Aug 1, 2023
1 parent d1d3dc1 commit 2adf0ff
Show file tree
Hide file tree
Showing 6 changed files with 398 additions and 175 deletions.
28 changes: 28 additions & 0 deletions sources/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,41 @@ String Thing::makeName(const String &basicName, Real relevance) const
{
if (a.name.empty())
continue;
if (a.relevance < 0.4)
continue;
if (!r.empty())
r += " ";
r += a.name;
}
if (r.empty())
r = t.affixes[(uint32)AffixEnum::Infix].name;
return r;
}

Generate::Generate(uint32 level, sint32 difficultyOffset) : level(level), difficultyOffset(difficultyOffset)
{
randomize();
}

Generate::Generate(SlotEnum slot, uint32 level, sint32 difficultyOffset) : slot(slot), level(level), difficultyOffset(difficultyOffset)
{
randomize();
}

void Generate::randomize()
{
magic = randomChance();
ranged = randomChance();
support = randomChance();
}

uint32 Generate::ll() const
{
const sint32 l = (sint32)level + difficultyOffset;
CAGE_ASSERT(l >= 1);
return l;
}

void removeLastComma(std::string &json)
{
auto c = json.find_last_of(',');
Expand Down
53 changes: 34 additions & 19 deletions sources/dnt.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

#include <array>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <variant>
#include <vector>

using namespace cage;

struct Skill;
struct Item;
struct Monster;

using Variant = std::variant<std::string, Skill, Item, Monster>;

enum class AffixEnum : uint8
{
Prefix,
Expand All @@ -20,7 +24,7 @@ enum class AffixEnum : uint8

struct Affix
{
String name;
detail::StringBase<120> name;
Real relevance;
};

Expand All @@ -31,7 +35,7 @@ struct Thing : private Noncopyable
uint32 powersCount = 0;
Real powerWeight; // sum of weights
Real powerTotal; // sum of weighted rolls
Real goldCost;
Real goldCost = 1;

Real addPower(Real weight);
Real addPower(Real roll, Real weight);
Expand Down Expand Up @@ -87,9 +91,9 @@ enum class SkillTargetEnum : uint8

struct SkillCost
{
uint16 life = 0;
uint16 mana = 0;
uint16 stamina = 0;
uint32 life = 0;
uint32 mana = 0;
uint32 stamina = 0;
};

using SkillAttributesEffects = std::map<AttributeEnum, AttributesValueMappingFloat>;
Expand Down Expand Up @@ -127,16 +131,12 @@ struct Item : public Thing
uint32 buyPrice = 0;
};

struct Monster;

using OnDeathEffect = std::variant<std::unique_ptr<Skill>, std::unique_ptr<Item>, std::unique_ptr<Monster>>;

struct Monster : public Thing
{
String name = "<unnamed monster>";
AttributesValueMappingInt attributes;
std::vector<Item> equippedItems;
std::vector<OnDeathEffect> onDeath;
std::vector<Variant> onDeath;
};

enum class TileEnum : uint8
Expand All @@ -163,7 +163,7 @@ enum class OccupancyEnum : uint8
Block, // walls, non-walkable decorations
};

using TileExtra = std::variant<std::monostate, std::string, std::vector<Item>, std::unique_ptr<Monster>>;
using TileExtra = std::vector<Variant>;

struct Floor : private Noncopyable
{
Expand Down Expand Up @@ -213,20 +213,35 @@ struct FloorExport
std::string json;
};

struct Generate
{
Real magic = Real::Nan(); // 0 = warrior, 1 = sorcerer
Real ranged = Real::Nan(); // 0 = melee, 1 = ranged
Real support = Real::Nan(); // 0 = combat, 1 = support
uint32 level = 0;
sint32 difficultyOffset = 0;
SlotEnum slot = SlotEnum::None;

Generate() = default;
explicit Generate(uint32 level, sint32 difficultyOffset = 0);
explicit Generate(SlotEnum slot, uint32 level, sint32 difficultyOffset = 0);
void randomize();
uint32 ll() const;
};

void removeLastComma(std::string &json);
OccupancyEnum occupancy(TileEnum tile);
bool isLevelBoss(uint32 level);
uint32 levelToBossIndex(uint32 level);
uint32 bossIndexToLevel(uint32 index);

Skill generateMagicSpell(uint32 level, SlotEnum slot);
Item generateEquippedItem(uint32 level, SlotEnum slot);
Item generateDroppedItem(uint32 level);
Monster generateMonster(uint32 level, sint32 difficultyOffset);
Monster generateSummonedMinion(uint32 level);
Monster generateChest(uint32 level);
Skill generateSkill(const Generate &generate);
Item generateItem(const Generate &generate);
Monster generateMonster(const Generate &generate);
Monster generateChest(const Generate &generate);
Floor generateFloor(uint32 level, uint32 maxLevel);

std::string exportVariant(const Variant &variant);
std::string exportSkill(const Skill &skill);
std::string exportItem(const Item &item);
std::string exportMonster(const Monster &monster);
Expand Down
38 changes: 12 additions & 26 deletions sources/exportFloor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,30 +151,16 @@ namespace
json += (Stringizer() + "\"x\":" + position[0] + ",\n").value.c_str();
json += (Stringizer() + "\"y\":" + position[1] + ",\n").value.c_str();
json += (Stringizer() + "\"type\":\"" + tileName(type) + "\",\n").value.c_str();
std::visit(
[&](const auto &arg)
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::monostate>)
{
// nothing
}
else if constexpr (std::is_same_v<T, std::string>)
json += "\"data\":" + arg + ",\n";
else if constexpr (std::is_same_v<T, std::vector<Item>>)
{
json += "\"data\":[\n";
for (const Item &item : arg)
json += exportItem(item) + ",\n";
removeLastComma(json);
json += "],\n";
}
else if constexpr (std::is_same_v<T, std::unique_ptr<Monster>>)
json += "\"data\":" + exportMonster(*arg) + ",\n";
else
static_assert(always_false<T>, "non-exhaustive visitor");
},
extra);

if (!extra.empty())
{
json += "\"data\":[\n";
for (const auto &it : extra)
json += exportVariant(it) + ",\n";
removeLastComma(json);
json += "],\n"; // data
}

removeLastComma(json);
json += "}"; // /root
return json;
Expand Down Expand Up @@ -261,7 +247,7 @@ void exportExamples(uint32 maxLevel)
Holder<File> json = writeFile("items.json");
for (uint32 i = 1; i < maxLevel; i++)
{
json->write(exportItem(generateDroppedItem(i)));
json->write(exportItem(generateItem(Generate(i))));
json->writeLine("");
json->writeLine("");
}
Expand All @@ -271,7 +257,7 @@ void exportExamples(uint32 maxLevel)
Holder<File> json = writeFile("monsters.json");
for (uint32 i = 1; i < maxLevel; i++)
{
json->write(exportMonster(generateMonster(i, 0)));
json->write(exportMonster(generateMonster(Generate(i))));
json->writeLine("");
json->writeLine("");
}
Expand Down
39 changes: 22 additions & 17 deletions sources/exportThing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,26 @@ namespace
}
}

std::string exportVariant(const Variant &variant)
{
return std::visit(
[](const auto &arg) -> std::string
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::string>)
return arg;
else if constexpr (std::is_same_v<T, Skill>)
return exportSkill(arg) + "\n";
else if constexpr (std::is_same_v<T, Item>)
return exportItem(arg) + "\n";
else if constexpr (std::is_same_v<T, Monster>)
return exportMonster(arg) + "\n";
else
static_assert(always_false<T>, "non-exhaustive visitor");
},
variant);
}

std::string exportSkill(const Skill &skill)
{
std::string json;
Expand Down Expand Up @@ -239,24 +259,9 @@ std::string exportMonster(const Monster &monster)

json += "\"onDeath\":[\n";
for (const auto &it : monster.onDeath)
{
std::visit(
[&](const auto &arg)
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::unique_ptr<Skill>>)
json += exportSkill(*arg) + ",\n";
else if constexpr (std::is_same_v<T, std::unique_ptr<Item>>)
json += exportItem(*arg) + ",\n";
else if constexpr (std::is_same_v<T, std::unique_ptr<Monster>>)
json += exportMonster(*arg) + ",\n";
else
static_assert(always_false<T>, "non-exhaustive visitor");
},
it);
}
json += exportVariant(it) + ",\n";
removeLastComma(json);
json += "],\n"; // /onDeath
json += "],\n"; // onDeath

json += "\"_debug\":" + thingJson(monster) + "\n";
json += "}"; // /root
Expand Down
27 changes: 13 additions & 14 deletions sources/generateFloor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,17 +228,16 @@ namespace
}
}

std::vector<Item> makeShopItems(uint32 maxLevel)
void makeShopItems(TileExtra &extra, uint32 maxLevel)
{
std::vector<Item> r;
// todo increase number of generated items
for (uint32 i = 0; i < 1; i++)
{
Item item = generateDroppedItem(randomRange(1u, maxLevel));
Generate gen;
Item item = generateItem(Generate(randomRange(1u, maxLevel)));
item.buyPrice = numeric_cast<uint32>(item.goldCost);
r.push_back(std::move(item));
extra.push_back(std::move(item));
}
return r;
}

void generateShopFloor(Floor &f, uint32 maxLevel)
Expand All @@ -258,7 +257,7 @@ namespace
else if (isDecoration(x, y))
{
f.tile(x, y) = TileEnum::Decoration;
f.extra(x, y) = makeShopItems(maxLevel);
makeShopItems(f.extra(x, y), maxLevel);
}
else
f.tile(x, y) = TileEnum::Empty;
Expand All @@ -270,7 +269,7 @@ namespace
for (uint32 i = 0; i < portals; i++)
{
f.tile(8 + i * 2, h / 2) = TileEnum::Waypoint;
f.extra(8 + i * 2, h / 2) = std::string() + (Stringizer() + "{\"class\":\"waypoint\",\"destinationFloor\":" + bossIndexToLevel(i + 1) + "}").value.c_str();
f.extra(8 + i * 2, h / 2).push_back(std::string() + (Stringizer() + "{\"class\":\"waypoint\",\"destinationFloor\":" + bossIndexToLevel(i + 1) + "}").value.c_str());
}
}

Expand Down Expand Up @@ -305,9 +304,9 @@ namespace

Monster generateBossMonster(const Floor &f)
{
Monster mr = generateMonster(f.level, levelToBossIndex(f.level));
Monster mr = generateMonster(Generate(f.level, levelToBossIndex(f.level)));
mr.name = Stringizer() + "Guardian of " + f.level + "th floor";
mr.onDeath.push_back(std::make_unique<Item>(generateKeyToAllDoors(f)));
mr.onDeath.push_back(generateKeyToAllDoors(f));
return mr;
}

Expand Down Expand Up @@ -386,7 +385,7 @@ namespace
w = f.width;

f.tile(w / 2, w / 2) = TileEnum::Monster; // the boss
f.extra(w / 2, w / 2) = std::make_unique<Monster>(generateBossMonster(f));
f.extra(w / 2, w / 2).push_back(generateBossMonster(f));

{ // additional monsters
const uint32 cnt = bossIndex * 2;
Expand Down Expand Up @@ -528,14 +527,14 @@ namespace
{
case TileEnum::Monster:
{
if (f.extras[i].index() == 0)
f.extras[i] = std::make_unique<Monster>(generateMonster(f.level, 0));
if (f.extras[i].empty())
f.extras[i].push_back(generateMonster(Generate(f.level)));
break;
}
case TileEnum::Chest:
{
if (f.extras[i].index() == 0)
f.extras[i] = std::make_unique<Monster>(generateChest(f.level));
if (f.extras[i].empty())
f.extras[i].push_back(generateChest(Generate(f.level)));
break;
}
}
Expand Down
Loading

0 comments on commit 2adf0ff

Please sign in to comment.