patrol_system_test.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "core/component.h"
  2. #include "core/entity.h"
  3. #include "core/world.h"
  4. #include "systems/patrol_system.h"
  5. #include <gtest/gtest.h>
  6. using namespace Engine::Core;
  7. using namespace Game::Systems;
  8. // Detection range from patrol_system.cpp (line 66: if (dist_sq < 25.0F))
  9. constexpr float kPatrolDetectionRangeSq = 25.0F;
  10. class PatrolSystemTest : public ::testing::Test {
  11. protected:
  12. void SetUp() override {
  13. world = std::make_unique<World>();
  14. patrol_system = std::make_unique<PatrolSystem>();
  15. }
  16. void TearDown() override {
  17. patrol_system.reset();
  18. world.reset();
  19. }
  20. std::unique_ptr<World> world;
  21. std::unique_ptr<PatrolSystem> patrol_system;
  22. };
  23. TEST_F(PatrolSystemTest, PatrollingUnitIgnoresEnemyBuildings) {
  24. // Create a patrolling unit
  25. auto *unit = world->create_entity();
  26. auto *transform = unit->add_component<TransformComponent>(0.0F, 0.0F, 0.0F);
  27. // UnitComponent(health, max_health, speed, vision_range)
  28. auto *unit_comp = unit->add_component<UnitComponent>(100, 100, 1.0F, 12.0F);
  29. unit_comp->owner_id = 1;
  30. auto *movement = unit->add_component<MovementComponent>();
  31. auto *patrol = unit->add_component<PatrolComponent>();
  32. // Setup patrol waypoints
  33. patrol->waypoints.push_back({10.0F, 0.0F});
  34. patrol->waypoints.push_back({10.0F, 10.0F});
  35. patrol->patrolling = true;
  36. patrol->current_waypoint = 0;
  37. // Create an enemy building nearby (within detection range of 25.0F dist_sq)
  38. // Distance of 3.0F units from origin results in dist_sq = 9.0F, which is
  39. // < 25.0F
  40. auto *enemy_building = world->create_entity();
  41. auto *enemy_transform =
  42. enemy_building->add_component<TransformComponent>(3.0F, 0.0F, 0.0F);
  43. // UnitComponent(health, max_health, speed, vision_range)
  44. auto *enemy_unit_comp =
  45. enemy_building->add_component<UnitComponent>(100, 100, 0.0F, 10.0F);
  46. enemy_unit_comp->owner_id = 2; // Different owner
  47. enemy_building->add_component<BuildingComponent>(); // Mark as building
  48. // Run the patrol system
  49. patrol_system->update(world.get(), 0.1F);
  50. // Verify that the unit did NOT auto-attack the building
  51. auto *attack_target = unit->get_component<AttackTargetComponent>();
  52. EXPECT_EQ(attack_target, nullptr)
  53. << "Patrolling unit should not auto-attack enemy buildings";
  54. }
  55. TEST_F(PatrolSystemTest, PatrollingUnitAttacksEnemyTroops) {
  56. // Create a patrolling unit
  57. auto *unit = world->create_entity();
  58. auto *transform = unit->add_component<TransformComponent>(0.0F, 0.0F, 0.0F);
  59. // UnitComponent(health, max_health, speed, vision_range)
  60. auto *unit_comp = unit->add_component<UnitComponent>(100, 100, 1.0F, 12.0F);
  61. unit_comp->owner_id = 1;
  62. auto *movement = unit->add_component<MovementComponent>();
  63. auto *patrol = unit->add_component<PatrolComponent>();
  64. // Setup patrol waypoints
  65. patrol->waypoints.push_back({10.0F, 0.0F});
  66. patrol->waypoints.push_back({10.0F, 10.0F});
  67. patrol->patrolling = true;
  68. patrol->current_waypoint = 0;
  69. // Create an enemy troop nearby (within detection range)
  70. auto *enemy_troop = world->create_entity();
  71. auto *enemy_transform =
  72. enemy_troop->add_component<TransformComponent>(3.0F, 0.0F, 0.0F);
  73. // UnitComponent(health, max_health, speed, vision_range)
  74. auto *enemy_unit_comp =
  75. enemy_troop->add_component<UnitComponent>(100, 100, 1.0F, 10.0F);
  76. enemy_unit_comp->owner_id = 2; // Different owner
  77. // No BuildingComponent - this is a regular troop
  78. // Run the patrol system
  79. patrol_system->update(world.get(), 0.1F);
  80. // Verify that the unit DID auto-attack the enemy troop
  81. auto *attack_target = unit->get_component<AttackTargetComponent>();
  82. ASSERT_NE(attack_target, nullptr)
  83. << "Patrolling unit should auto-attack enemy troops";
  84. EXPECT_EQ(attack_target->target_id, enemy_troop->get_id());
  85. EXPECT_FALSE(attack_target->should_chase) << "Patrol attack should not chase";
  86. }
  87. TEST_F(PatrolSystemTest, PatrollingUnitIgnoresFriendlyUnits) {
  88. // Create a patrolling unit
  89. auto *unit = world->create_entity();
  90. auto *transform = unit->add_component<TransformComponent>(0.0F, 0.0F, 0.0F);
  91. // UnitComponent(health, max_health, speed, vision_range)
  92. auto *unit_comp = unit->add_component<UnitComponent>(100, 100, 1.0F, 12.0F);
  93. unit_comp->owner_id = 1;
  94. auto *movement = unit->add_component<MovementComponent>();
  95. auto *patrol = unit->add_component<PatrolComponent>();
  96. // Setup patrol waypoints
  97. patrol->waypoints.push_back({10.0F, 0.0F});
  98. patrol->waypoints.push_back({10.0F, 10.0F});
  99. patrol->patrolling = true;
  100. patrol->current_waypoint = 0;
  101. // Create a friendly unit nearby
  102. auto *friendly_unit = world->create_entity();
  103. auto *friendly_transform =
  104. friendly_unit->add_component<TransformComponent>(3.0F, 0.0F, 0.0F);
  105. // UnitComponent(health, max_health, speed, vision_range)
  106. auto *friendly_unit_comp =
  107. friendly_unit->add_component<UnitComponent>(100, 100, 1.0F, 10.0F);
  108. friendly_unit_comp->owner_id = 1; // Same owner
  109. // Run the patrol system
  110. patrol_system->update(world.get(), 0.1F);
  111. // Verify that the unit did NOT attack the friendly unit
  112. auto *attack_target = unit->get_component<AttackTargetComponent>();
  113. EXPECT_EQ(attack_target, nullptr)
  114. << "Patrolling unit should not attack friendly units";
  115. }
  116. TEST_F(PatrolSystemTest, PatrollingUnitIgnoresDeadEnemies) {
  117. // Create a patrolling unit
  118. auto *unit = world->create_entity();
  119. auto *transform = unit->add_component<TransformComponent>(0.0F, 0.0F, 0.0F);
  120. // UnitComponent(health, max_health, speed, vision_range)
  121. auto *unit_comp = unit->add_component<UnitComponent>(100, 100, 1.0F, 12.0F);
  122. unit_comp->owner_id = 1;
  123. auto *movement = unit->add_component<MovementComponent>();
  124. auto *patrol = unit->add_component<PatrolComponent>();
  125. // Setup patrol waypoints
  126. patrol->waypoints.push_back({10.0F, 0.0F});
  127. patrol->waypoints.push_back({10.0F, 10.0F});
  128. patrol->patrolling = true;
  129. patrol->current_waypoint = 0;
  130. // Create a dead enemy troop nearby
  131. auto *dead_enemy = world->create_entity();
  132. auto *enemy_transform =
  133. dead_enemy->add_component<TransformComponent>(3.0F, 0.0F, 0.0F);
  134. // UnitComponent(health=0, max_health, speed, vision_range)
  135. auto *enemy_unit_comp =
  136. dead_enemy->add_component<UnitComponent>(0, 100, 1.0F, 10.0F); // 0 health
  137. enemy_unit_comp->owner_id = 2; // Different owner
  138. // Run the patrol system
  139. patrol_system->update(world.get(), 0.1F);
  140. // Verify that the unit did NOT attack the dead enemy
  141. auto *attack_target = unit->get_component<AttackTargetComponent>();
  142. EXPECT_EQ(attack_target, nullptr)
  143. << "Patrolling unit should not attack dead enemies";
  144. }