Source File: ex63.cpp

#include <fmt/core.h>
#include <chrono>
#include <thread>
#include <string>
#include "dinkyecs.hpp"
#include <fuc2/testing.hpp>
#include <fuc2/run.hpp>

using namespace fuc2;
using namespace DinkyECS;

struct Player {
  std::string name;
};

struct Combat {
  int damage = 0;
  int hp = 0;
};

struct Enemy {
  std::string name;
};

void spawn_enemies(World& world, Entity player_id, Entity rat_id) {
  // create the player
  world.set<Player>(player_id, {"Zed the Destroyer"});
  world.set<Combat>(player_id, {10, 100});

  // add a rat enemy
  world.set<Enemy>(rat_id, {"Rat the Disgusting"});
  world.set<Combat>(rat_id, {3, 30});
}

void test_crud_ops() {
  World world;
  auto player_id = world.entity();
  auto rat_id = world.entity();

  spawn_enemies(world, player_id, rat_id);

  // confirm the player exists
  CHECK(world.has<Player>(player_id), "should have player");
  CHECK(world.has<Combat>(player_id), "no player combat?");

  // check for the rat
  CHECK(world.has<Enemy>(rat_id), "missing rat Enemy");

  // confirm get_if works
  auto player_combat = world.get_if<Combat>(player_id);
  CHECK(player_combat != nullptr, "get_if should find player");

  CHECK(world.get_if<Enemy>(player_id) == nullptr, "there should _not_ be an enemy at player_id");

  // normal get operation
  auto& rat_combat = world.get<Combat>(rat_id);
  CHECK(rat_combat.hp == 30, "rat is corrupted?");

  // confirm remove works
  world.remove<Combat>(rat_id);
  CHECK(!world.has<Combat>(rat_id));

  world.remove<Enemy>(rat_id);
  CHECK(!world.has<Enemy>(rat_id));

  // make sure player still exists
  CHECK(world.has<Combat>(player_id));
  CHECK(world.has<Player>(player_id));
}

void test_queries() {
  World world;
  auto player_id = world.entity();
  auto rat_id = world.entity();

  spawn_enemies(world, player_id, rat_id);
  bool found_player = false;
  bool found_rat = false;

  world.query<Combat>([&](auto id, auto& combat) {
      if(id == player_id) {
        found_player = true;
      } else if(id == rat_id) {
        found_rat = true;
      }

      CHECK(id == player_id || id == rat_id, "invalid id, not player or rat");
  });

  world.query<Combat, Player>([&](auto id, auto& combat, auto& player) {
      CHECK(id == player_id);
      CHECK(player.name == "Zed the Destroyer");
      CHECK(combat.hp == 100);
  });
}

int main(int argc, char* argv[]) {
  return run({
    .name="DinkyECS",
    .tests={
      TEST(test_crud_ops),
      TEST(test_queries),
    }
  }, {}, false);
}