bug修复

This commit is contained in:
wuwenbo 2025-07-07 14:12:57 +08:00
parent b1f436c113
commit be0b509e24
7 changed files with 125 additions and 52 deletions

View File

@ -27,7 +27,7 @@ MonoBehaviour:
_version: 3.33
_category:
_comments:
_translation: {x: 215.61038, y: 443.87662}
_translation: {x: 443, y: 169}
_zoomFactor: 1
_haltSerialization: 0
_externalSerializationFile: {fileID: 0}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,38 @@ using Vector2 = System.Numerics.Vector2;
namespace Logic.AI
{
public enum CountryAttackType
{
CounterattackInvasions,
BullyWeak,
ForcedExpansion,
None,
}
public enum LegionStrategyType
{
SelfDefend,
SelfAttack,
CountryDefendMatch,
CountryDefendMax,
CountryAttackMatch,
CountryAttackMax,
None,
}
public enum FreeUnitStrategyType
{
EmergencyAvoidance1,
EmergencyAvoidance2,
FreeDevelopment1,
Retreat,
FreeDevelopment2,
None,
}
public enum Strategy
{
Attack,
@ -89,11 +121,15 @@ namespace Logic.AI
public PlayerData Player;
public Strategy CountryStrategy;
public PlayerData AttackPlayer;
public CountryAttackType AttackType;
public PlayerData DefendTarget;
// 策略集合
public Dictionary<CityData, Strategy> CityStrategy;
public Dictionary<UnitData, Strategy> FreeUnitStrategy;
public Dictionary<uint, Strategy> LegionStrategy;
public Dictionary<uint, LegionStrategyType> LegionStrategyTypes;
public Dictionary<uint, FreeUnitStrategyType> FreeUnitStrategyTypes;
// 玩家的军事分
public Dictionary<uint, float> MilitaryScore;
@ -172,6 +208,8 @@ namespace Logic.AI
CityStrategy = new Dictionary<CityData, Strategy>();
FreeUnitStrategy = new Dictionary<UnitData, Strategy>();
LegionStrategy = new Dictionary<uint, Strategy>();
LegionStrategyTypes = new Dictionary<uint, LegionStrategyType>();
FreeUnitStrategyTypes = new Dictionary<uint, FreeUnitStrategyType>();
AIActions = new List<AIActionBase>();
TargetParam = new CommonActionParams();
Marks = new HashSet<string>();
@ -218,6 +256,10 @@ namespace Logic.AI
{
Map = map;
Player = player;
CountryStrategy = Strategy.None;
AttackPlayer = null;
AttackType = CountryAttackType.None;
DefendTarget = null;
IsFinish = false;
AIActions.Clear();
@ -230,6 +272,9 @@ namespace Logic.AI
CityStrategy.Clear();
FreeUnitStrategy.Clear();
LegionStrategy.Clear();
LegionStrategyTypes.Clear();
FreeUnitStrategyTypes.Clear();
MilitaryScore.Clear();
DevelopmentScore.Clear();
ThreatScore.Clear();
@ -552,6 +597,8 @@ namespace Logic.AI
public bool CalculateLegionStrategy()
{
LegionStrategy.Clear();
LegionStrategyTypes.Clear();
FreeUnitStrategyTypes.Clear();
LegionUnits.Clear();
FreeUnits.Clear();
LegionScore.Clear();
@ -652,6 +699,7 @@ namespace Logic.AI
if (!LegionCanMoveCities[kv.Key].Contains(cityPair.Key.Id)) continue;
LegionTargetCity[kv.Key] = cityPair.Key.Id;
LegionStrategy[kv.Key] = Strategy.Defend;
LegionStrategyTypes[kv.Key] = LegionStrategyType.SelfDefend;
isFinish = true;
break;
}
@ -677,6 +725,7 @@ namespace Logic.AI
{
LegionTargetCity[kv.Key] = targetCity.Id;
LegionStrategy[kv.Key] = Strategy.Attack;
LegionStrategyTypes[kv.Key] = LegionStrategyType.SelfAttack;
break;
}
}
@ -712,18 +761,13 @@ namespace Logic.AI
if (LegionTargetCity.ContainsKey(result.LegionId)) continue;
LegionTargetCity[result.LegionId] = result.CityId;
LegionStrategy[result.LegionId] = Strategy.Defend;
LegionStrategyTypes[result.LegionId] = LegionStrategyType.CountryDefendMatch;
}
if (LegionTargetCity.Count == LegionUnits.Count) return true;
uint targetId = 0;
foreach (var city in selfCity)
{
if (targetId == 0 || CityDangerScore[city.Id] > CityDangerScore[targetId]) targetId = city.Id;
}
foreach (var legionId in waitLegions)
{
if (!LegionTargetCity.TryAdd(legionId, targetId)) continue;
LegionStrategy[legionId] = Strategy.Defend;
if (LegionTargetCity.ContainsKey(legionId)) continue;
LogSystem.LogError($"军团防守存在未匹配到目标的军团 {legionId},请检查逻辑");
}
}
// 国家进攻
@ -733,12 +777,11 @@ namespace Logic.AI
{
foreach (var cityId in CityBorder)
{
if (!Map.CityMap.GetCityById(cityId, out var city)) continue;
if (!LegionCanMoveCities[legionId].Contains(city.Id)) continue;
if (!Map.GetGridDataByCityId(city.Id, out var cityGrid)) continue;
var score = (2 * LegionScore[legionId] - CityDefendScore[city.Id] - CityRescueScore[city.Id]) /
if (!LegionCanMoveCities[legionId].Contains(cityId)) continue;
if (!Map.GetGridDataByCityId(cityId, out var cityGrid)) continue;
var score = (2 * LegionScore[legionId] - CityDefendScore[cityId] - CityRescueScore[cityId]) /
(Map.GridMap.CalcDistance(cityGrid, LegionGrid[legionId]) + 1);
results.Add(new MatchResult(legionId, city.Id, score));
results.Add(new MatchResult(legionId, cityId, score));
}
}
results = results.OrderByDescending(r => r.Score).ToList();
@ -747,20 +790,13 @@ namespace Logic.AI
if (LegionTargetCity.ContainsKey(result.LegionId)) continue;
LegionTargetCity[result.LegionId] = result.CityId;
LegionStrategy[result.LegionId] = Strategy.Attack;
LegionStrategyTypes[result.LegionId] = LegionStrategyType.CountryAttackMatch;
}
if (LegionTargetCity.Count == LegionUnits.Count) return true;
uint targetId = 0;
foreach (var city in Map.CityMap.CityList)
{
if (selfCity.Contains(city)) continue;
if (targetId == 0 || CityDefendScore[city.Id] + CityRescueScore[city.Id] <
CityDefendScore[targetId] + CityRescueScore[targetId]) targetId = city.Id;
}
foreach (var legionId in waitLegions)
{
if (!LegionTargetCity.TryAdd(legionId, targetId)) continue;
LegionStrategy[legionId] = Strategy.Attack;
if (LegionTargetCity.ContainsKey(legionId)) continue;
LogSystem.LogError($"军团进攻存在未匹配到目标的军团 {legionId},请检查逻辑");
}
}
@ -852,6 +888,7 @@ namespace Logic.AI
if (action.CheckCan(param))
{
FreeUnitStrategy[unit] = Strategy.Defend;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.EmergencyAvoidance1;
isFinish = true;
}
}
@ -868,6 +905,7 @@ namespace Logic.AI
if (!Map.GetUnitDataByGid(aroundGrid.Id, out var cityUnit)) continue;
if (selfUnit.Contains(cityUnit)) continue;
FreeUnitStrategy[unit] = Strategy.Defend;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.EmergencyAvoidance2;
isFinish = true;
break;
}
@ -876,7 +914,8 @@ namespace Logic.AI
if (unitGrid.Resource == ResourceType.Treasure)
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Defend;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
}
if (unitGrid.Resource == ResourceType.CityCenter)
{
@ -884,6 +923,7 @@ namespace Logic.AI
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
}
else
{
@ -891,6 +931,7 @@ namespace Logic.AI
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
}
}
}
@ -898,6 +939,7 @@ namespace Logic.AI
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
}
if (isFinish) continue;
@ -956,6 +998,7 @@ namespace Logic.AI
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Retreat;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.Retreat;
UnitTargetGrid[unit.Id] = targetGrid;
UnitTargetCity[unit.Id] = target.Id;
}
@ -974,6 +1017,7 @@ namespace Logic.AI
return false;
}
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment2;
}
return true;
}
@ -1294,6 +1338,7 @@ namespace Logic.AI
if (ThreatScore[target.Id] < 10) continue;
if (MilitaryGapScore[target.Id] > -5) continue;
CountryStrategy = Strategy.Defend;
DefendTarget = target;
return;
}
@ -1341,6 +1386,7 @@ namespace Logic.AI
CountryStrategy = Strategy.Attack;
AttackPlayer = target;
AttackType = CountryAttackType.CounterattackInvasions;
return;
}
@ -1351,6 +1397,7 @@ namespace Logic.AI
if (AttackDistance[target.Id] > 5) continue;
CountryStrategy = Strategy.Attack;
AttackPlayer = target;
AttackType = CountryAttackType.BullyWeak;
return;
}
@ -1381,6 +1428,7 @@ namespace Logic.AI
if (!hasCityCenter) continue;
CountryStrategy = Strategy.Attack;
AttackPlayer = target;
AttackType = CountryAttackType.ForcedExpansion;
return;
}

View File

@ -622,12 +622,22 @@ namespace Logic.AI
if (type == CalculateType.UnitAttackSelfCityEnemy)
{
if (aiAction.Param.UnitData == null || aiAction.Param.TargetUnitData == null) return false;
if (!aiAction.Param.MapData.GetGridDataByUnitId(aiAction.Param.UnitData.Id, out var unitGrid)) return false;
if (!aiAction.Param.MapData.GetGridDataByUnitId(aiAction.Param.TargetUnitData.Id, out var unitGrid)) return false;
if (!aiAction.Param.MapData.GetCityDataByGid(unitGrid.Id, out var city)) return false;
if (!aiAction.Param.MapData.GetPlayerIdByCityId(city.Id, out var playerId)) return false;
if (playerId != aiAction.Param.PlayerData.Id) return false;
return true;
}
if (type == CalculateType.UnitAttackCityCenter)
{
if (aiAction.Param.UnitData == null || aiAction.Param.TargetUnitData == null) return false;
if (!aiAction.Param.MapData.GetGridDataByUnitId(aiAction.Param.TargetUnitData.Id, out var unitGrid)) return false;
if (!aiAction.Param.MapData.GetCityDataByGid(unitGrid.Id, out var city)) return false;
if (!aiAction.Param.MapData.GetPlayerIdByCityId(city.Id, out var playerId)) return false;
if (playerId == aiAction.Param.PlayerData.Id) return false;
return true;
}
if (type == CalculateType.UnitAuto)
{
@ -706,7 +716,6 @@ namespace Logic.AI
if (type == CalculateType.UnitMoveForTrain) CalculateLegionDefendMoveForTrain(data, param, result);
if (type == CalculateType.UnitRecovery) CalculateUnitRecovery(data, param, result);
if (type == CalculateType.UnitAttackCityCenter) CalculateUnitAttackCityCenter(data, param, result);
if (type == CalculateType.UnitExplore) CalculateExplore(data, param, result);
if (type == CalculateType.UnitRetreat) CalculateUnitRetreat(data, param, result);
if (type == CalculateType.UnitMoveToTargetGrid) CalculateUnitMoveToTargetGrid(data, param, result);
@ -725,17 +734,6 @@ namespace Logic.AI
return result;
}
private static void CalculateUnitAttackCityCenter(AICalculatorData data, CommonActionParams param, CalculateResult result)
{
if (param.UnitData == null || param.TargetUnitData == null) return;
if (!param.MapData.GetGridDataByUnitId(param.TargetUnitData.Id, out var unitGrid)) return;
if (!param.MapData.GetCityDataByGid(unitGrid.Id, out var cityData)) return;
var selfCities = param.MapData.GetCityDataSetByPlayerId(param.PlayerData.Id);
if (!selfCities.Contains(cityData)) return;
result.Score[CalculateType.UnitAttackCityCenter] = 1f;
}
private static void CalculateLegionDevelopmentMoveToOtherCity(AICalculatorData data, CommonActionParams param, CalculateResult result)
{
if (param.UnitData == null || param.TargetGridData == null) return;

View File

@ -113,9 +113,15 @@ namespace Logic.Editor
{
if (_main?.MapData == null || _player == null) return;
MainEditor.Instance.GetPlayerStrategy(_player.Id, out var playerStrategy);
MainEditor.Instance.GetPlayerStrategy(_player.Id, out var playerStrategy, out var targetId, out var attackType);
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}</b>");
if (playerStrategy != Strategy.Attack)
InspectorUtils.InspectorTextWidthRich($"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}</b>");
else
{
InspectorUtils.InspectorTextWidthRich(
$"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}, 目标:{targetId}, 类型:{attackType}</b>");
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginVertical(_redBoxStyle);
@ -139,10 +145,10 @@ namespace Logic.Editor
_main.MapData.GetUnitDataListByPlayerId(_player.Id, selfUnits);
foreach (var unit in selfUnits)
{
MainEditor.Instance.GetUnitStrategy(unit.Id, unit.LegionId, _player.Id, out var strategy, out var target);
MainEditor.Instance.GetUnitStrategy(unit.Id, unit.LegionId, _player.Id, out var strategy, out var target, out var type);
InspectorUtils.InspectorTextWidthRich(unit.LegionId == 0
? $"<b>ID: {unit.Id}, 自由人, 策略: {strategy}, 目标城市: {target}</b>"
: $"<b>ID: {unit.Id}, 军团ID:{unit.LegionId}, 策略: {strategy}, 目标城市: {target}</b>");
: $"<b>ID: {unit.Id}, 军团ID:{unit.LegionId}, 策略: {strategy}, 类型:{type}, 目标城市: {target}</b>");
}
EditorGUILayout.EndVertical();

View File

@ -17,20 +17,28 @@ namespace Logic
public bool IsGo = false;
public AICalculatorData Data;
private Dictionary<uint, Strategy> _playerStrategy;
private Dictionary<uint, CountryAttackType> _playerAttackType;
private Dictionary<uint, uint> _playerAttackTarget;
private Dictionary<uint, Strategy> _cityStrategy;
private Dictionary<uint, Strategy> _unitStrategy;
private Dictionary<uint, Strategy> _legionStrategy;
private Dictionary<uint, LegionStrategyType> _legionStrategyTypes;
private Dictionary<uint, FreeUnitStrategyType> _freeUnitStrategyTypes;
private Dictionary<uint, uint> _unitTarget;
private Dictionary<uint, List<AIActionBase>> _actionRecord;
public static MainEditor Instance = new MainEditor();
public MainEditor()
{
_playerStrategy = new Dictionary<uint, Strategy>();
_playerAttackType = new Dictionary<uint, CountryAttackType>();
_playerAttackTarget = new Dictionary<uint, uint>();
_cityStrategy = new Dictionary<uint, Strategy>();
_unitStrategy = new Dictionary<uint, Strategy>();
_legionStrategy = new Dictionary<uint, Strategy>();
_legionStrategyTypes = new Dictionary<uint, LegionStrategyType>();
_unitTarget = new Dictionary<uint, uint>();
_actionRecord = new Dictionary<uint, List<AIActionBase>>();
}
@ -53,19 +61,28 @@ namespace Logic
return _actionRecord.GetValueOrDefault(cid);
}
public void GetPlayerStrategy(uint pid, out Strategy strategy)
public void GetPlayerStrategy(uint pid, out Strategy strategy, out uint target, out CountryAttackType attackType)
{
strategy = Strategy.None;
target = 0;
attackType = CountryAttackType.None;
_playerStrategy.TryGetValue(pid, out strategy);
_playerAttackTarget.TryGetValue(pid, out target);
_playerAttackType.TryGetValue(pid, out attackType);
}
public void GetUnitStrategy(uint uid, uint legion, uint playerId, out Strategy strategy, out uint cityId)
public void GetUnitStrategy(uint uid, uint legion, uint playerId, out Strategy strategy, out uint cityId, out LegionStrategyType type)
{
cityId = 0;
strategy = Strategy.None;
type = LegionStrategyType.None;
_unitTarget.TryGetValue(uid, out cityId);
if (legion == 0 && !_unitStrategy.TryGetValue(uid, out strategy))return;
if (legion != 0 && !_legionStrategy.TryGetValue(legion * 10000 + playerId, out strategy))return;
if (legion == 0) _unitStrategy.TryGetValue(uid, out strategy);
else
{
_legionStrategy.TryGetValue(legion * 10000 + playerId, out strategy);
_legionStrategyTypes.TryGetValue(legion * 10000 + playerId, out type);
}
}
public void GetCityStrategy(uint cid, out Strategy strategy)
@ -95,9 +112,13 @@ namespace Logic
if (Data == null) return;
if (Data.Player == null) return;
_playerStrategy[Data.Player.Id] = Data.CountryStrategy;
_playerAttackType[Data.Player.Id] = Data.AttackType;
_playerAttackTarget[Data.Player.Id] = Data.AttackPlayer.Id;
foreach (var kv in Data.CityStrategy) _cityStrategy[kv.Key.Id] = kv.Value;
foreach (var kv in Data.FreeUnitStrategy) _unitStrategy[kv.Key.Id] = kv.Value;
foreach (var kv in Data.LegionStrategy) _legionStrategy[kv.Key * 10000 + Data.Player.Id] = kv.Value;
foreach (var kv in Data.LegionStrategyTypes) _legionStrategyTypes[kv.Key * 10000 + Data.Player.Id] = kv.Value;
foreach (var kv in Data.FreeUnitStrategyTypes) _freeUnitStrategyTypes[kv.Key] = kv.Value;
foreach (var kv in Data.UnitTargetCity) _unitTarget[kv.Key] = kv.Value;
}
}