mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-29 00:35:41 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b2cf908d1 | ||
|
|
496545b006 |
@@ -20,6 +20,9 @@
|
||||
#include <sstream>
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "AIAttackerStrategySelector.hpp"
|
||||
#include "AIConfig.hpp"
|
||||
#include "AIDefenderStrategySelector.hpp"
|
||||
@@ -197,13 +200,85 @@ auto ShardokAIClient::StandardChooseCommandIndex(
|
||||
: -1;
|
||||
const int guessedActor =
|
||||
i < commandCount ? (*guessedCommands)[i]->GetActorUnitId() : -1;
|
||||
const int realRow = i < realAvailableCommands->size()
|
||||
? (*realAvailableCommands)[i]->GetTargetRow()
|
||||
: -1;
|
||||
const int realCol = i < realAvailableCommands->size()
|
||||
? (*realAvailableCommands)[i]->GetTargetColumn()
|
||||
: -1;
|
||||
const int guessedRow = i < commandCount ? (*guessedCommands)[i]->GetTargetRow() : -1;
|
||||
const int guessedCol = i < commandCount ? (*guessedCommands)[i]->GetTargetColumn() : -1;
|
||||
fprintf(stderr,
|
||||
" [%zu] real: %s unit=%d guessed: %s unit=%d\n",
|
||||
" [%zu] real: %s unit=%d (%d,%d) guessed: %s unit=%d (%d,%d)\n",
|
||||
i,
|
||||
realName,
|
||||
realActor,
|
||||
realRow,
|
||||
realCol,
|
||||
guessedName,
|
||||
guessedActor);
|
||||
guessedActor,
|
||||
guessedRow,
|
||||
guessedCol);
|
||||
}
|
||||
|
||||
// Find positions in real commands that are missing from guessed commands
|
||||
// Group by unit to find the missing position per unit
|
||||
std::unordered_map<int, std::set<std::pair<int, int>>> realPositions;
|
||||
std::unordered_map<int, std::set<std::pair<int, int>>> guessedPositions;
|
||||
for (size_t i = 0; i < realAvailableCommands->size(); i++) {
|
||||
const auto &cmd = (*realAvailableCommands)[i];
|
||||
realPositions[cmd->GetActorUnitId()].emplace(
|
||||
cmd->GetTargetRow(),
|
||||
cmd->GetTargetColumn());
|
||||
}
|
||||
for (size_t i = 0; i < commandCount; i++) {
|
||||
const auto &cmd = (*guessedCommands)[i];
|
||||
guessedPositions[cmd->GetActorUnitId()].emplace(
|
||||
cmd->GetTargetRow(),
|
||||
cmd->GetTargetColumn());
|
||||
}
|
||||
for (const auto &[unitId, positions] : realPositions) {
|
||||
for (const auto &[row, col] : positions) {
|
||||
if (!guessedPositions[unitId].contains({row, col})) {
|
||||
fprintf(stderr,
|
||||
" Missing from guessed: unit=%d pos=(%d,%d)",
|
||||
unitId,
|
||||
row,
|
||||
col);
|
||||
const Coords missingCoords(row, col);
|
||||
const auto *occupant = guessedState.GetOccupant(missingCoords);
|
||||
if (occupant) {
|
||||
fprintf(stderr,
|
||||
" -> guessed occupant: unit_id=%d player=%d status=%d "
|
||||
"loc=(%d,%d) hidden=%d battalion_size=%d\n",
|
||||
occupant->unit_id(),
|
||||
occupant->player_id(),
|
||||
static_cast<int>(occupant->status()),
|
||||
occupant->location().row(),
|
||||
occupant->location().column(),
|
||||
occupant->hidden(),
|
||||
occupant->battalion().size());
|
||||
} else {
|
||||
fprintf(stderr, " -> no occupant in guessed state\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dump all guessed state units for full picture
|
||||
fprintf(stderr, " Guessed state units (%u total):\n", guessedState->units()->size());
|
||||
for (size_t i = 0; i < guessedState->units()->size(); i++) {
|
||||
const auto *u = guessedState->units()->Get(static_cast<unsigned int>(i));
|
||||
fprintf(stderr,
|
||||
" unit_id=%d player=%d status=%d loc=(%d,%d) hidden=%d "
|
||||
"starting_pos_idx=%d\n",
|
||||
u->unit_id(),
|
||||
u->player_id(),
|
||||
static_cast<int>(u->status()),
|
||||
u->location().row(),
|
||||
u->location().column(),
|
||||
u->hidden(),
|
||||
u->starting_position_index());
|
||||
}
|
||||
|
||||
throw ShardokInternalErrorException(
|
||||
|
||||
@@ -580,45 +580,45 @@
|
||||
"attackerStartingPositions": [
|
||||
{
|
||||
"positions": [
|
||||
{
|
||||
"row": 0,
|
||||
"column": 0
|
||||
},
|
||||
{
|
||||
"row": 0,
|
||||
"column": 1
|
||||
},
|
||||
{
|
||||
"row": 0,
|
||||
"column": 2
|
||||
},
|
||||
{
|
||||
"row": 1,
|
||||
"column": 0
|
||||
},
|
||||
{
|
||||
"row": 1,
|
||||
"column": 1
|
||||
},
|
||||
{
|
||||
"row": 1,
|
||||
"column": 2
|
||||
},
|
||||
{
|
||||
"row": 2,
|
||||
"column": 0
|
||||
},
|
||||
{
|
||||
"row": 2,
|
||||
"column": 1
|
||||
},
|
||||
{
|
||||
"row": 0,
|
||||
"column": 3
|
||||
},
|
||||
{
|
||||
"row": 0,
|
||||
"column": 4
|
||||
},
|
||||
{
|
||||
"row": 0,
|
||||
"column": 5
|
||||
},
|
||||
{
|
||||
"row": 1,
|
||||
"column": 3
|
||||
},
|
||||
{
|
||||
"row": 1,
|
||||
"column": 4
|
||||
},
|
||||
{
|
||||
"row": 1,
|
||||
"column": 5
|
||||
},
|
||||
{
|
||||
"row": 2,
|
||||
"column": 3
|
||||
},
|
||||
{
|
||||
"row": 2,
|
||||
"column": 4
|
||||
},
|
||||
{
|
||||
"row": 3,
|
||||
"column": 0
|
||||
"column": 2
|
||||
},
|
||||
{
|
||||
"row": 3,
|
||||
"column": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <set>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/util/MapLoader.hpp"
|
||||
#include "src/test/cpp/net/eagle0/shardok/library/GameSettings_test_utils.hpp"
|
||||
|
||||
using std::vector;
|
||||
@@ -74,4 +76,26 @@ TEST_F(MapInfoCalculatorTest, yuetia_checkStartingPositions) {
|
||||
{{0, 0}, {1, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}});
|
||||
|
||||
EXPECT_EQ(expectedRequirements, yuetiaInfo.positionsRequiringCrossing);
|
||||
}
|
||||
|
||||
TEST_F(MapInfoCalculatorTest, noAttackerDefenderStartingPositionOverlap) {
|
||||
for (const auto& mapName : GetMapNames()) {
|
||||
const auto mapProto = LoadMap(mapName);
|
||||
|
||||
// Collect defender starting positions
|
||||
std::set<std::pair<int, int>> defenderPositions;
|
||||
for (const auto& pos : mapProto.defender_starting_positions().positions()) {
|
||||
defenderPositions.emplace(pos.row(), pos.column());
|
||||
}
|
||||
|
||||
// Check each attacker starting position list for overlap
|
||||
for (int idx = 0; idx < mapProto.attacker_starting_positions_size(); idx++) {
|
||||
const auto& attackerList = mapProto.attacker_starting_positions(idx);
|
||||
for (const auto& pos : attackerList.positions()) {
|
||||
EXPECT_FALSE(defenderPositions.contains({pos.row(), pos.column()}))
|
||||
<< mapName << ": attacker index " << idx << " position (" << pos.row()
|
||||
<< "," << pos.column() << ") overlaps with a defender starting position";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user