Skip to content

Commit

Permalink
templars
Browse files Browse the repository at this point in the history
  • Loading branch information
malytomas committed Aug 9, 2023
1 parent 9b24fe5 commit f9d608b
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 66 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
shell: bash
run: |
cd build/result/${{ matrix.build-config }}
./dntgenerator.exe
./dntgenerator.exe -s 20 -e 22 -m 30
- name: Upload Artifact
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -106,7 +106,7 @@ jobs:
shell: bash
run: |
cd build/result/${{ matrix.build-config }}
./dntgenerator
./dntgenerator -s 20 -e 22 -m 30
- name: Upload Artifact
uses: actions/upload-artifact@v3
Expand Down
3 changes: 3 additions & 0 deletions sources/dnt.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ Item generateItem(const Generate &generate);
Monster generateMonster(const Generate &generate);
Monster generateMinion(const Generate &generate);
Monster generateChest(const Generate &generate);
Monster generateButcher(uint32 level);
Monster generateWitch(uint32 level);
Monster generateTemplar(uint32 level);
Floor generateFloor(uint32 level, uint32 maxLevel);

std::string exportVariant(const Variant &variant);
Expand Down
70 changes: 48 additions & 22 deletions sources/generateFloor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,18 +624,9 @@ namespace
f.tile(c) = TileEnum::Decoration;
f.extra(c).push_back(std::string() + "{\"class\":\"decoration\",\"type\":\"cauldron\"}");

// occultists
// witches
for (uint32 i = 0; i < 4; i++)
{
Generate g = Generate(f.level, f.level / 10);
g.magic = 1;
g.ranged = 1;
g.defensive = 0;
g.support = 0;
Monster mr = generateMonster(g);
mr.name = "Witch";
mr.icon = "witch";
mr.algorithm = "boss";
const Vec2i ps[4] = {
c + Vec2i(0, -1),
c + Vec2i(0, +1),
Expand All @@ -644,7 +635,7 @@ namespace
};
Vec2i p = ps[i];
f.tile(p) = TileEnum::Monster;
f.extra(p).push_back(std::move(mr));
f.extra(p).push_back(generateWitch(f.level));
}
}

Expand Down Expand Up @@ -812,6 +803,7 @@ namespace
cutoutFloor(f);
placeSpawnAndStairs(f);

// lava river
if (f.level > 50 && randomChance() < 0.05)
placeLavaRiver(f);

Expand All @@ -835,22 +827,18 @@ namespace
// the butcher
if (f.level > 40 && randomChance() < 0.05)
{
Generate g = Generate(f.level, f.level / 3);
g.magic = 0;
g.ranged = 0;
g.defensive = 0;
g.support = 0;
Monster mr = generateMonster(g);
mr.name = "The Butcher";
mr.icon = "butcher";
mr.algorithm = "boss";
const Vec2i p = findAny(f, TileEnum::Empty);
f.tile(p) = TileEnum::Monster;
f.extra(p).push_back(std::move(mr));
const Vec2i ps[4] = {
f.extra(p).push_back(generateButcher(f.level));

const Vec2i ps[] = {
p + Vec2i(-1, -1),
p + Vec2i(-1, +0),
p + Vec2i(-1, +1),
p + Vec2i(+0, -1),
p + Vec2i(+0, +1),
p + Vec2i(+1, -1),
p + Vec2i(+1, +0),
p + Vec2i(+1, +1),
};
for (Vec2i i : ps)
Expand All @@ -863,6 +851,44 @@ namespace
}
}

// templars
if (f.level > 70 && randomChance() < 0.05)
{
const Vec2i spawn = findAny(f, TileEnum::Spawn);
const uint32 cnt = randomRange(3u, 7u);
for (uint32 i = 0; i < cnt; i++)
{
Vec2i p;
for (uint32 a = 0; a < 100; a++)
{
p = findAny(f, TileEnum::Empty);
if (distance(p, spawn) < 20)
break;
}

f.tile(p) = TileEnum::Monster;
f.extra(p).push_back(generateTemplar(f.level));

Vec2i ps[4] = {
p + Vec2i(-1, +0),
p + Vec2i(+0, -1),
p + Vec2i(+1, +0),
p + Vec2i(+0, +1),
};
for (uint32 a = 0; a < 3; a++)
std::swap(ps[randomRange(0, 4)], ps[randomRange(0, 4)]);
for (Vec2i n : ps)
{
if (f.tile(n) == TileEnum::Empty)
{
f.tile(n) = TileEnum::Decoration;
f.extra(n).push_back(std::string() + "{\"class\":\"decoration\",\"type\":\"cross\"}");
break;
}
}
}
}

// random chest
if (f.level > 15 && randomChance() < 0.4)
{
Expand Down
141 changes: 99 additions & 42 deletions sources/generateMonsters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,15 @@ namespace

namespace
{
Monster generateOutlawBase(const Generate &generate)
{
return generateRandomMonster(generate);
}

// mundane melee offensive combat
Monster generateBarbarian(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Barbarian";
mr.icon = "barbarian";
mr.faction = "outlaw";
Expand All @@ -277,7 +282,7 @@ namespace
// mundane ranged offensive combat
Monster generateAssassin(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Assassin";
mr.icon = "assassin";
mr.faction = "outlaw";
Expand All @@ -287,7 +292,7 @@ namespace
// mundane --- defensive combat
Monster generateBandit(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Bandit";
mr.icon = "bandit";
mr.faction = "outlaw";
Expand All @@ -297,7 +302,7 @@ namespace
// mundane melee --- support
Monster generateRogue(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Rogue";
mr.icon = "rogue";
mr.faction = "outlaw";
Expand All @@ -307,7 +312,7 @@ namespace
// mundane ranged --- support
Monster generateSaboteur(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Saboteur";
mr.icon = "saboteur";
mr.faction = "outlaw";
Expand All @@ -317,7 +322,7 @@ namespace
// magic melee --- combat
Monster generateDruid(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Druid";
mr.icon = "druid";
mr.faction = "outlaw";
Expand All @@ -327,7 +332,7 @@ namespace
// magic ranged offensive combat
Monster generateWarlock(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Warlock";
mr.icon = "warlock";
mr.faction = "outlaw";
Expand All @@ -337,7 +342,7 @@ namespace
// magic ranged offensive support
Monster generateOccultist(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Occultist";
mr.icon = "occultist";
mr.faction = "outlaw";
Expand All @@ -347,7 +352,7 @@ namespace
// magic ranged defensive support
Monster generateShaman(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Shaman";
mr.icon = "shaman";
mr.faction = "outlaw";
Expand All @@ -357,7 +362,7 @@ namespace
// magic --- --- support
Monster generateNecromancer(const Generate &generate)
{
Monster mr = generateRandomMonster(generate);
Monster mr = generateOutlawBase(generate);
mr.name = "Necromancer";
mr.icon = "necromancer";
mr.faction = "outlaw";
Expand Down Expand Up @@ -424,42 +429,45 @@ namespace
}
}
}
}

Monster generateMonster(const Generate &generate_)
{
CAGE_ASSERT(generate_.valid());
CAGE_ASSERT(generate_.slot == SlotEnum::None);

const auto generator = isHellFloor(generate_.level) > 0.5 ? &generateHell : &generateOutlaw;

// additional empower
// https://www.wolframalpha.com/input?i=plot+exp%28%28x+-+100%29+%2F+200%29%3B+x+%3D+100+..+1000
const Real empower = max(pow((Real(generate_.power) - 100) / 200), 1);
Generate generate = generate_;
generate.power = numeric_cast<uint32>(generate_.power * empower);

// generate several monsters and pick the strongest
// 0 .. 39 -> 1 attempt
// 40 .. 59 -> 2 attempts
// 60 .. 79 -> 3 attempts
// 80 .. 99 -> 4 attempts
// 100 and more -> 5 attempts
Monster mr = generator(generate);
const uint32 attempts = min(generate_.power / 20, 5u); // use the original power
for (uint32 i = 1; i < attempts; i++) // starting from one -> one attempt has already been generated above
Monster generateMonsterImpl(const Generate &generate_, Monster (*generator)(const Generate &))
{
Monster mr2 = generator(generate);
if (mr2.goldCost > mr.goldCost)
std::swap(mr, mr2);
}
CAGE_ASSERT(generate_.valid());
CAGE_ASSERT(generate_.slot == SlotEnum::None);

// additional empower
// https://www.wolframalpha.com/input?i=plot+exp%28%28x+-+100%29+%2F+200%29%3B+x+%3D+100+..+1000
const Real empower = max(pow((Real(generate_.power) - 100) / 200), 1);
Generate generate = generate_;
generate.power = numeric_cast<uint32>(generate_.power * empower);

// generate several monsters and pick the strongest
// 0 .. 39 -> 1 attempt
// 40 .. 59 -> 2 attempts
// 60 .. 79 -> 3 attempts
// 80 .. 99 -> 4 attempts
// 100 and more -> 5 attempts
Monster mr = generator(generate);
const uint32 attempts = min(generate_.power / 20, 5u); // use the original power
for (uint32 i = 1; i < attempts; i++) // starting from one -> one attempt has already been generated above
{
Monster mr2 = generator(generate);
if (mr2.goldCost > mr.goldCost)
std::swap(mr, mr2);
}

// loot
if (randomChance() < 0.4)
mr.onDeath.push_back(generateItem(Generate(generate.level, generate_.powerOffset()))); // use the original power
mr.score = numeric_cast<uint32>(mr.goldCost / empower);
// loot
if (randomChance() < 0.4)
mr.onDeath.push_back(generateItem(Generate(generate_.level, generate_.powerOffset()))); // use the original power
mr.score = numeric_cast<uint32>(mr.goldCost / empower);

return mr;
return mr;
}
}

Monster generateMonster(const Generate &generate)
{
return generateMonsterImpl(generate, isHellFloor(generate.level) > 0.5 ? &generateHell : &generateOutlaw);
}

Monster generateMinion(const Generate &generate)
Expand Down Expand Up @@ -498,3 +506,52 @@ Monster generateChest(const Generate &generate)

return mr;
}

Monster generateButcher(uint32 level)
{
Generate g = Generate(level, level / 3);
g.magic = 0;
g.ranged = 0;
g.defensive = 0;
g.support = 0;

Monster mr = generateMonsterImpl(g, &generateBarbarian);
mr.name = "Butcher";
mr.icon = "butcher";
mr.algorithm = "boss";
mr.faction = "butcher";
return mr;
}

Monster generateWitch(uint32 level)
{
Generate g = Generate(level, level / 10);
g.magic = 1;
g.ranged = 1;
g.defensive = 0;
g.support = randomChance();

Monster mr = generateMonsterImpl(g, g.support < 0.5 ? &generateWarlock : &generateOccultist);
mr.name = "Witch";
mr.icon = "witch";
mr.algorithm = "boss";
mr.faction = "witch";
return mr;
}

Monster generateTemplar(uint32 level)
{
Generate g = Generate(level, level / 10);
g.magic = 0;
g.ranged = 0;
g.defensive = 1;
g.support = randomChance();

Monster mr = generateMonsterImpl(g, &generateOutlawBase);
mr.name = "Templar";
mr.icon = "templar";
mr.algorithm = "boss";
mr.faction = "templar";
mr.score = 0;
return mr;
}

0 comments on commit f9d608b

Please sign in to comment.