This commit is contained in:
daixiawu 2025-07-09 17:23:22 +08:00
commit 504ade8c9c
13 changed files with 302 additions and 207 deletions

View File

@ -18,7 +18,7 @@ MonoBehaviour:
_version: 3.33
_category:
_comments:
_translation: {x: -84, y: 97}
_zoomFactor: 0.7500899
_translation: {x: -356, y: -54}
_zoomFactor: 1
_haltSerialization: 0
_externalSerializationFile: {fileID: 0}

View File

@ -10,7 +10,7 @@ MonoBehaviour:
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7a686a47eee2fa44cb0a34b5d86e4d5e, type: 3}
m_Name: 'CommonTech '
m_Name: CommonTech
m_EditorClassIdentifier:
_serializedGraph: '{"type":"NodeCanvas.BehaviourTrees.BehaviourTree","nodes":[{"_position":{"x":497.1322,"y":549.8659},"$type":"NodeCanvas.BehaviourTrees.Sequencer","$id":"0"},{"_action":{"MarkStr":"DevelopmentTechFinal","CheckNotHave":true,"$type":"NodeCanvas.Tasks.Actions.MarkAction"},"_position":{"x":113.4,"y":687.2},"$type":"NodeCanvas.BehaviourTrees.ActionNode","$id":"1"},{"_position":{"x":695.4,"y":644.2},"$type":"NodeCanvas.BehaviourTrees.Selector","$id":"2"},{"_position":{"x":554.0001,"y":759.6},"$type":"NodeCanvas.BehaviourTrees.Sequencer","$id":"3"},{"_action":{"ActionTypes":[9],"$type":"NodeCanvas.Tasks.Actions.AIGeneratorAction"},"_tag":"","_position":{"x":349.4702,"y":902.9698},"$type":"NodeCanvas.BehaviourTrees.ActionNode","$id":"4"},{"_action":{"CalculateTypes":[34],"$type":"NodeCanvas.Tasks.Actions.AICalculateAction"},"_tag":"","_position":{"x":522.9526,"y":905.599},"$type":"NodeCanvas.BehaviourTrees.ActionNode","$id":"5"},{"_action":{"$type":"NodeCanvas.Tasks.Actions.AIExecuteAction"},"_tag":"","_position":{"x":710.7076,"y":910.691},"$type":"NodeCanvas.BehaviourTrees.ActionNode","$id":"6"},{"_action":{"MarkStr":"DevelopmentTechFinal","$type":"NodeCanvas.Tasks.Actions.MarkAction"},"_position":{"x":800.4,"y":754.0},"$type":"NodeCanvas.BehaviourTrees.ActionNode","$id":"7"}],"connections":[{"_sourceNode":{"$ref":"0"},"_targetNode":{"$ref":"1"},"$type":"NodeCanvas.BehaviourTrees.BTConnection"},{"_sourceNode":{"$ref":"0"},"_targetNode":{"$ref":"2"},"$type":"NodeCanvas.BehaviourTrees.BTConnection"},{"_sourceNode":{"$ref":"2"},"_targetNode":{"$ref":"3"},"$type":"NodeCanvas.BehaviourTrees.BTConnection"},{"_sourceNode":{"$ref":"2"},"_targetNode":{"$ref":"7"},"$type":"NodeCanvas.BehaviourTrees.BTConnection"},{"_sourceNode":{"$ref":"3"},"_targetNode":{"$ref":"4"},"$type":"NodeCanvas.BehaviourTrees.BTConnection"},{"_sourceNode":{"$ref":"3"},"_targetNode":{"$ref":"5"},"$type":"NodeCanvas.BehaviourTrees.BTConnection"},{"_sourceNode":{"$ref":"3"},"_targetNode":{"$ref":"6"},"$type":"NodeCanvas.BehaviourTrees.BTConnection"}],"canvasGroups":[],"localBlackboard":{"_variables":{}},"derivedData":{"repeat":true,"$type":"NodeCanvas.BehaviourTrees.BehaviourTree+DerivedSerializationData"}}'
_objectReferences: []
@ -18,7 +18,7 @@ MonoBehaviour:
_version: 3.33
_category:
_comments:
_translation: {x: 73, y: -257}
_zoomFactor: 0.99983007
_translation: {x: 226.22678, y: -51.781044}
_zoomFactor: 0.7499281
_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

@ -0,0 +1,59 @@
/*
* @Author:
* @Description:
* @Date: 20250606 19:06:16
* @Modify:
*/
using System;
using System.Collections.Generic;
using Logic.Action;
using Logic.AI;
using NodeCanvas.Framework;
using ParadoxNotion.Design;
namespace NodeCanvas.Tasks.Actions
{
[Category("AIAction")]
[Serializable]
public class AIActionRecoveryAndNoMove : ActionTask
{
protected override string info => "回血并且原地不动";
protected override void OnExecute()
{
// 直接从Blackboard获取AICalculatorData
var data = blackboard.GetVariable<AICalculatorData>("Data");
if (data?.value == null)
{
EndAction(false);
return;
}
var actionId = new CommonActionId();
actionId.ActionType = CommonActionType.UnitAction;
actionId.UnitActionType = UnitActionType.Recover;
var action = ActionLogicFactory.GetActionLogic(actionId);
if (action.CheckCan(data.value.TargetParam))
{
action.Execute(data.value.TargetParam);
EndAction(true);
return;
}
if (data.value.TargetParam.UnitData.MP > 0)
{
data.value.TargetParam.UnitData.CP = 0;
data.value.TargetParam.UnitData.MP = 0;
data.value.TargetParam.UnitData.AP = 0;
EndAction(true);
return;
}
EndAction(false);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6d788bec02c644e39f2b8caa88fce3c8
timeCreated: 1751947052

View File

@ -82,16 +82,16 @@ namespace NodeCanvas.Tasks.Actions
new (unitGrid.Pos.X, unitGrid.Pos.Y), new (target.Pos.X, target.Pos.Y), param.MapData, param.PlayerData);
if (!path.found) continue;
aroundGrids = param.MapData.GridMap.GetAroundGridData(Offset, Offset, target);
var selfScore = 0;
var enemyScore = 0;
aroundGrids = param.MapData.GridMap.GetAroundGridData(3, 3, target);
var selfScore = 0f;
var enemyScore = 0f;
foreach (var grid in aroundGrids)
{
if (unitGrid.Id == grid.Id) continue;
if (!param.MapData.GetUnitDataByGid(grid.Id, out var unit)) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
if (selfUnits.Contains(unit)) selfScore += info.Cost;
else enemyScore += info.Cost;
var dis = param.MapData.GridMap.CalcDistance(grid, target);
if (selfUnits.Contains(unit)) selfScore += unit.GetCost() / (dis + 1f);
else enemyScore += unit.GetCost() / (dis + 1f);
}
var targetScore = (selfScore - enemyScore) / path.length;

View File

@ -0,0 +1,62 @@
/*
* @Author:
* @Description:
* @Date: 20250606 19:06:16
* @Modify:
*/
using System;
using System.Collections.Generic;
using Logic.AI;
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using RuntimeData;
namespace NodeCanvas.Tasks.Actions
{
[Category("AIAction")]
[Serializable]
public class AIParamMustGarrison : ActionTask
{
protected override string info => "必须驻守城市";
protected override void OnExecute()
{
// 直接从Blackboard获取AICalculatorData
var data = blackboard.GetVariable<AICalculatorData>("Data");
if (data?.value?.TargetParam.UnitData == null)
{
EndAction(false);
return;
}
var map = data.value.TargetParam.MapData;
var unit = data.value.TargetParam.UnitData;
var selfCity = new List<CityData>();
map.GetCityDataListByPlayerId(data.value.TargetParam.PlayerData.Id, selfCity);
var selfUnit = new HashSet<UnitData>();
map.GetUnitDataListByPlayerId(data.value.TargetParam.PlayerData.Id, selfUnit);
if (!map.GetGridDataByUnitId(unit.Id, out var unitGrid) ||
!map.GetCityDataByGid(unitGrid.Id, out var city) ||
!selfCity.Contains(city) || !map.CheckIfCityFullPopulation(city))
{
EndAction(false);
return;
}
var around = map.GridMap.GetAroundGridData(1, 1, unitGrid);
foreach (var grid in around)
{
if (!map.GetUnitDataByGid(grid.Id, out var attacker)) continue;
if (selfUnit.Contains(attacker)) continue;
EndAction(true);
return;
}
EndAction(false);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 90daa9731e684789bd4e9e4a615e5fce
timeCreated: 1751946383

View File

@ -200,6 +200,21 @@ namespace RuntimeData
return unitTypeInfo.MaxHealth + (Veteran?5:0);
}
// 获取血量百分比
public float GetHealthRatio()
{
return (float)Health / GetMaxHealth();
}
// 获取造价
public float GetCost()
{
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType, GiantType, out var info))
return 0;
if (GetHealthRatio() <= 0.5f) return info.Cost * 0.5f;
return info.Cost;
}
public UnitData()
{
InitData();

View File

@ -42,8 +42,6 @@ namespace Logic.AI
public enum FreeUnitStrategyType
{
EmergencyAvoidance1,
EmergencyAvoidance2,
FreeDevelopment1,
Retreat,
FreeDevelopment2,
@ -141,7 +139,7 @@ namespace Logic.AI
public Dictionary<uint, float> MilitaryGapScore;
// 玩家对我的地缘距离
public Dictionary<uint, int> GeographicalDistance;
// 我的领土到对方城市的最近距离
// 我的城市到对方城市的最近距离
public Dictionary<uint, int> AttackDistance;
// 城市3格内我方单位
@ -158,9 +156,9 @@ namespace Logic.AI
public Dictionary<uint, float> CityDangerScore;
// 城市加权危险分
public Dictionary<uint, float> CityRatioDangerScore;
// 别国对我任意城市的最近边境距离
// 别国任意城市对我城市的最近距离
public Dictionary<uint, int> PlayerBorderDistance;
// 别国城市对我任意城市的最近边境距离小于5的城市
// 别国城市对我任意城市的最近距离小于8的城市
public List<uint> CityBorder;
// 军团单位
@ -182,7 +180,7 @@ namespace Logic.AI
// 小兵目标城市
public Dictionary<uint, uint> UnitTargetCity;
// 小兵攻击系数
public Dictionary<uint, int> UnitAttackRatio;
public Dictionary<uint, float> UnitAttackRatio;
// 军团可达城市
public Dictionary<uint, HashSet<uint>> LegionCanMoveCities;
@ -243,7 +241,7 @@ namespace Logic.AI
LegionTargetCity = new Dictionary<uint, uint>();
UnitTargetGrid = new Dictionary<uint, GridData>();
UnitTargetCity = new Dictionary<uint, uint>();
UnitAttackRatio = new Dictionary<uint, int>();
UnitAttackRatio = new Dictionary<uint, float>();
LegionCanMoveCities = new Dictionary<uint, HashSet<uint>>();
TechGapScore = new Dictionary<TechType, float>();
@ -624,12 +622,10 @@ namespace Logic.AI
foreach (var kv in LegionUnits)
{
var score = 0;
var score = 0f;
foreach (var unit in kv.Value)
{
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
score += info.Cost;
score += unit.GetCost();
}
LegionScore[kv.Key] = score;
}
@ -640,10 +636,8 @@ namespace Logic.AI
var vec = new Vector2();
foreach (var unit in kv.Value)
{
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
if (!Map.GetGridDataByUnitId(unit.Id, out var grid)) continue;
var ratio = info.Cost / (float)score;
var ratio = unit.GetCost() / score;
vec += new Vector2(grid.Pos.X, grid.Pos.Y) * ratio;
}
var center = new Vector2Int((int)Math.Round(vec.X), (int)Math.Round(vec.Y));
@ -684,7 +678,7 @@ namespace Logic.AI
{
var citySet = new HashSet<CityData>();
var centerGrid = LegionGrid[kv.Key];
var aroundGrids = Map.GridMap.GetAroundGridData(3, 3, centerGrid);
var aroundGrids = Map.GridMap.GetAroundGridData(4, 4, centerGrid);
foreach (var grid in aroundGrids)
{
if (!Map.GetCityDataByGid(grid.Id, out var cityData)) continue;
@ -692,18 +686,25 @@ namespace Logic.AI
}
// 防守-城市协防
bool isFinish = false;
var minDis = int.MaxValue;
CityData defendCity = null;
foreach (var cityPair in CityStrategy)
{
if (cityPair.Value != Strategy.EmergencyDefend) continue;
if (!LegionCanMoveCities[kv.Key].Contains(cityPair.Key.Id)) continue;
LegionTargetCity[kv.Key] = cityPair.Key.Id;
if (!Map.GetGridDataByCityId(cityPair.Key.Id, out var grid)) continue;
var dis = Map.GridMap.CalcDistance(grid, centerGrid);
if (dis >= minDis) continue;
minDis = dis;
defendCity = cityPair.Key;
}
if (defendCity != null)
{
LegionTargetCity[kv.Key] = defendCity.Id;
LegionStrategy[kv.Key] = Strategy.Defend;
LegionStrategyTypes[kv.Key] = LegionStrategyType.SelfDefend;
isFinish = true;
break;
continue;
}
if (isFinish) continue;
// 进攻-城市进攻
foreach (var targetCity in citySet)
@ -818,8 +819,6 @@ namespace Logic.AI
if (LegionUnits[legionId].Count == 1)
{
LegionUnits[legionId][0].LegionId = 0;
FreeUnits.Add(LegionUnits[legionId][0]);
LegionUnits.Remove(legionId);
Debug.Log($"解散军团{legionId}");
return false;
}
@ -840,13 +839,13 @@ namespace Logic.AI
}
}
maxUnit.LegionId = 0;
FreeUnits.Add(maxUnit);
LegionUnits[legionId].Remove(maxUnit);
Debug.Log($"{legionId} 军团抛弃小兵 {maxUnit.Id}");
return false;
}
}
}
foreach (var kv in LegionUnits) LegionStrategy.TryAdd(kv.Key, Strategy.Development);
return true;
}
@ -859,79 +858,37 @@ namespace Logic.AI
Map.GetUnitDataListByPlayerId(Player.Id, selfUnit);
Map.GetCityDataListByPlayerId(Player.Id, selfCity);
var actionId = new CommonActionId();
actionId.ActionType = CommonActionType.UnitAction;
actionId.UnitActionType = UnitActionType.Upgrade;
var action = ActionLogicFactory.GetActionLogic(actionId);
var param = new CommonActionParams();
param.MapData = Map;
param.PlayerData = Player;
param.MainObjectType = MainObjectType.Unit;
foreach (var unit in FreeUnits)
{
bool isFinish = false;
if (action != null)
{
param.UnitData = unit;
if (action.CheckCan(param))
{
FreeUnitStrategy[unit] = Strategy.Defend;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.EmergencyAvoidance1;
isFinish = true;
}
}
if (isFinish) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
// 如果当前在遗迹/村庄/敌方城市中心/可采集的海星上,则确定自由发展战略
if (!Map.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
var aroundGrids = Map.GridMap.GetAroundGridData(info.AttackRange, info.AttackRange, unitGrid);
foreach (var aroundGrid in aroundGrids)
if (unitGrid.Resource == ResourceType.Treasure || unitGrid.Resource == ResourceType.Starfish)
{
if (!Map.GetCityDataByGid(aroundGrid.Id, out var city)) continue;
if (!selfCity.Contains(city)) continue;
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;
}
if (isFinish) continue;
if (unitGrid.Resource == ResourceType.Treasure)
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
continue;
}
if (unitGrid.Resource == ResourceType.CityCenter)
{
if (!Map.GetCityDataByGid(unitGrid.Id, out var city))
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
continue;
}
else
if (city != null && !selfCity.Contains(city))
{
if (!selfCity.Contains(city))
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
continue;
}
}
}
if (unitGrid.Resource == ResourceType.Starfish)
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment1;
}
if (isFinish) continue;
// 如果3寻路距离内存在一个军团有战力缺口则加入该军团
uint legion = 0;
int dis = int.MaxValue;
foreach (var kv in LegionGapScore)
@ -949,25 +906,22 @@ namespace Logic.AI
dis = path.length;
}
}
if (legion != 0)
{
Debug.Log($"加入军团{legion}");
unit.LegionId = legion;
return false;
}
aroundGrids = Map.GridMap.GetAroundGridData(2, 2, unitGrid);
var score = 0;
// 如果2直线距离内交战国的敌军总分-友军总分>=6且自由人距离最近的我方城市中心距离>2则执行撤退战略
var aroundGrids = Map.GridMap.GetAroundGridData(2, 2, unitGrid);
var score = 0f;
foreach (var aroundGrid in aroundGrids)
{
if (!Map.GetUnitDataByGid(aroundGrid.Id, out var attacker)) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(attacker.UnitType, attacker.GiantType, out var attackInfo))
continue;
if (!selfUnit.Contains(attacker)) score += attackInfo.Cost;
else score -= attackInfo.Cost;
if (!selfUnit.Contains(attacker)) score += attacker.GetCost();
else score -= attacker.GetCost();
}
if (score > 6)
if (score > 6f)
{
CityData target = null;
int minDis = int.MaxValue;
@ -984,14 +938,13 @@ namespace Logic.AI
if (target != null)
{
isFinish = true;
FreeUnitStrategy[unit] = Strategy.Retreat;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.Retreat;
UnitTargetGrid[unit.Id] = targetGrid;
UnitTargetCity[unit.Id] = target.Id;
continue;
}
}
if (isFinish) continue;
if (CountryStrategy == Strategy.Attack || CountryStrategy == Strategy.Defend)
{
@ -1004,9 +957,32 @@ namespace Logic.AI
Debug.Log($"成立");
return false;
}
// 防守-城市协防
foreach (var cityPair in CityStrategy)
{
if (cityPair.Value != Strategy.EmergencyDefend) continue;
if (!Map.GetGridDataByCityId(cityPair.Key.Id, out var grid)) continue;
var defendDis = Map.GridMap.CalcDistance(grid, unitGrid);
if (defendDis > 4) continue;
var path = PathFinder.FindPath((int)Map.MapConfig.Width, (int)Map.MapConfig.Height,
new (unitGrid.Pos.X, unitGrid.Pos.Y), new (grid.Pos.X, grid.Pos.Y), Map, Player);
if (!path.found) continue;
if (path.length > 4) continue;
uint legionId = 1;
foreach (var kv in LegionUnits)
{
if (legionId <= kv.Key) legionId = kv.Key + 1;
}
unit.LegionId = legionId;
Debug.Log($"成立");
return false;
}
FreeUnitStrategy[unit] = Strategy.Development;
FreeUnitStrategyTypes[unit.Id] = FreeUnitStrategyType.FreeDevelopment2;
}
return true;
}
@ -1063,9 +1039,11 @@ namespace Logic.AI
// 刷新小兵攻击系数
public void CalculateUnitAttackRatio()
{
var selfCity = new List<CityData>();
Map.GetCityDataListByPlayerId(Player.Id, selfCity);
foreach (var unit in Map.UnitMap.UnitList)
{
var ratio = 1;
var ratio = 1f;
if (unit.LegionId != 0)
{
if (LegionStrategy.TryGetValue(unit.LegionId, out var value))
@ -1082,23 +1060,21 @@ namespace Logic.AI
else ratio = 2;
}
}
if (Map.GetGridDataByUnitId(unit.Id, out var unitGrid) &&
Map.GetCityDataByGid(unitGrid.Id, out var city) &&
selfCity.Contains(city)) ratio = 0.5f;
UnitAttackRatio[unit.Id] = ratio;
}
}
// 计算玩家的军事分
private int CalMilitaryScore(PlayerData player)
private float CalMilitaryScore(PlayerData player)
{
int score = 0;
var score = 0f;
var unitList = new List<UnitData>();
Map.GetUnitDataListByPlayerId(player.Id, unitList);
foreach (var unit in unitList)
{
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
score += info.Cost;
}
foreach (var unit in unitList) score += unit.GetCost();
return score;
}
@ -1160,6 +1136,7 @@ namespace Logic.AI
// 计算两个小兵的克制分
public float CalUnitCounterScore(UnitData self, UnitData target)
{
if (self.GetHealthRatio() <= 0.5) return CalUnitCounterScore(self.UnitType, target.UnitType) * 0.5f;
return CalUnitCounterScore(self.UnitType, target.UnitType);
}
@ -1342,21 +1319,23 @@ namespace Logic.AI
// 我的领土到对方城市的最近距离
private int CalAttackDistance(PlayerData target)
{
var selfGridSet = Map.GetPlayerTerritoryGridIdSet(Player.Id);
var targetCity = new HashSet<CityData>();
Map.GetCityDataListByPlayerId(target.Id, targetCity);
var selfCityList = new List<CityData>();
Map.GetCityDataListByPlayerId(Player.Id, selfCityList);
var targetCityList = new HashSet<CityData>();
Map.GetCityDataListByPlayerId(target.Id, targetCityList);
var minDistance = int.MaxValue;
foreach (var selfGridId in selfGridSet)
foreach (var selfCity in selfCityList)
{
if (!Map.GridMap.GetGridDataByGid(selfGridId, out var selfGrid)) continue;
foreach (var city in targetCity)
if (!Map.GetGridDataByCityId(selfCity.Id, out var selfGrid)) continue;
foreach (var targetCity in targetCityList)
{
if (!Map.GetGridDataByCityId(city.Id, out var cityGrid)) continue;
var distance = Map.GridMap.CalcDistance(selfGrid, cityGrid);
if (!Map.GetGridDataByCityId(targetCity.Id, out var targetGrid)) continue;
var distance = Map.GridMap.CalcDistance(selfGrid, targetGrid);
if (distance < minDistance)
{
var path = PathFinder.FindPath((int)Map.MapConfig.Width, (int)Map.MapConfig.Height,
new (selfGrid.Pos.X, selfGrid.Pos.Y), new (cityGrid.Pos.X, cityGrid.Pos.Y), Map, Player);
new (selfGrid.Pos.X, selfGrid.Pos.Y), new (targetGrid.Pos.X, targetGrid.Pos.Y), Map, Player);
if (!path.found) continue;
if (path.length > minDistance) continue;
minDistance = path.length;
@ -1420,7 +1399,7 @@ namespace Logic.AI
if (target == Player) continue;
if (ThreatScore[target.Id] < 10) continue;
if (MilitaryGapScore[target.Id] < 3) continue;
if (AttackDistance[target.Id] > 5) continue;
if (AttackDistance[target.Id] > 7) continue;
CountryStrategy = Strategy.Attack;
AttackPlayer = target;
@ -1432,7 +1411,7 @@ namespace Logic.AI
{
if (target == Player) continue;
if (MilitaryGapScore[target.Id] < 0) continue;
if (AttackDistance[target.Id] > 5) continue;
if (AttackDistance[target.Id] > 7) continue;
CountryStrategy = Strategy.Attack;
AttackPlayer = target;
AttackType = CountryAttackType.BullyWeak;
@ -1494,24 +1473,18 @@ namespace Logic.AI
}
// 计算城市守备分
private int CalCityDefendScore(CityData city)
private float CalCityDefendScore(CityData city)
{
var score = 0;
foreach (var unit in CityDefendUnits[city.Id])
{
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
score += info.Cost;
}
var score = 0f;
foreach (var unit in CityDefendUnits[city.Id]) score += unit.GetCost();
if (city.CityWall) score += 2;
return score;
}
// 计算城市救援分
private int CalCityRescueScore(CityData city)
private float CalCityRescueScore(CityData city)
{
var score = 0;
var score = 0f;
var selfUnits = new HashSet<UnitData>();
Map.GetPlayerDataByCityId(city.Id, out var player);
Map.GetUnitDataListByPlayerId(player.Id, selfUnits);
@ -1519,25 +1492,18 @@ namespace Logic.AI
foreach (var unit in selfUnits)
{
if (!Map.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
var distance = Map.GridMap.CalcDistance(cityGrid, unitGrid);
score += info.Cost / (distance + 1);
score += unit.GetCost() / (distance + 1);
}
return score;
}
// 计算城市敌军分
private int CalCityEnemyScore(CityData city)
private float CalCityEnemyScore(CityData city)
{
var score = 0;
foreach (var unit in CityEnemyUnits[city.Id])
{
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
score += info.Cost;
}
var score = 0f;
foreach (var unit in CityEnemyUnits[city.Id]) score += unit.GetCost();
return score;
}
@ -1562,11 +1528,9 @@ namespace Logic.AI
{
if (!Map.GetGridDataByCityId(city.Id, out var cityGrid)) return 0;
var score = 0;
var score = 0f;
foreach (var unit in CityEnemyUnits[city.Id])
{
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
if (!Map.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
var ratio = 1;
var dis = Map.GridMap.CalcDistance(unitGrid, cityGrid);
@ -1578,7 +1542,7 @@ namespace Logic.AI
3 => 0,
_ => ratio
};
score += info.Cost * ratio;
score += unit.GetCost() * ratio;
}
foreach (var unit in CityDefendUnits[city.Id])
{
@ -1595,7 +1559,7 @@ namespace Logic.AI
3 => 0,
_ => ratio
};
score -= info.Cost * ratio;
score -= unit.GetCost() * ratio;
}
return score;
}
@ -1656,53 +1620,48 @@ namespace Logic.AI
// 计算城市最近的别国边境距离
private int CalPlayerBorderDistance(CityData city)
{
if (!Map.GetGridDataByCityId(city.Id, out var selfGrid)) return 0;
var selfCity = new HashSet<CityData>();
Map.GetPlayerDataByCityId(city.Id, out var player);
Map.GetCityDataListByPlayerId(player.Id, selfCity);
var targetGridList = new List<GridData>();
foreach (var target in Map.CityMap.CityList)
{
if (selfCity.Contains(target)) continue;
foreach (var gridId in target.Territory.TerritoryArea)
{
if (!Map.GridMap.GetGridDataByGid(gridId, out var targetGrid)) continue;
targetGridList.Add(targetGrid);
}
}
if (!Map.GetGridDataByCityId(city.Id, out var selfGrid)) return int.MaxValue;
var selfCityList = new List<CityData>();
Map.GetCityDataListByPlayerId(Player.Id, selfCityList);
var minDistance = int.MaxValue;
foreach (var target in targetGridList)
foreach (var targetCity in Map.CityMap.CityList)
{
var distance = Map.GridMap.CalcDistance(selfGrid, target);
if (distance < minDistance) minDistance = distance;
if (selfCityList.Contains(targetCity)) continue;
if (!Map.GetGridDataByCityId(targetCity.Id, out var targetGrid)) continue;
var distance = Map.GridMap.CalcDistance(selfGrid, targetGrid);
if (distance < minDistance)
{
var path = PathFinder.FindPath((int)Map.MapConfig.Width, (int)Map.MapConfig.Height,
new (selfGrid.Pos.X, selfGrid.Pos.Y), new (targetGrid.Pos.X, targetGrid.Pos.Y), Map, Player);
if (!path.found) continue;
if (path.length > minDistance) continue;
minDistance = path.length;
}
}
return minDistance;
}
// 计算城市与其他城市的距离
private void CalCityBorderDistance()
{
var selfCity = new HashSet<CityData>();
Map.GetCityDataListByPlayerId(Map.PlayerMap.SelfPlayerId, selfCity);
var selfCityList = new List<CityData>();
Map.GetCityDataListByPlayerId(Player.Id, selfCityList);
var selfSet = new HashSet<uint>();
foreach (var city in selfCity)
foreach (var selfCity in selfCityList)
{
if (!Map.GetGridDataByCityId(city.Id, out var grid)) continue;
var around = Map.GridMap.GetAroundGridData(5, 5, grid);
foreach (var aroundGrid in around) selfSet.Add(aroundGrid.Id);
}
foreach (var city in Map.CityMap.CityList)
if (!Map.GetGridDataByCityId(selfCity.Id, out var selfGrid)) continue;
foreach (var targetCity in Map.CityMap.CityList)
{
if (selfCity.Contains(city)) continue;
foreach (var id in city.Territory.TerritoryArea)
{
if (!selfSet.Contains(id)) continue;
CityBorder.Add(city.Id);
break;
if (selfCityList.Contains(targetCity)) continue;
if (!Map.GetGridDataByCityId(targetCity.Id, out var targetGrid)) continue;
var distance = Map.GridMap.CalcDistance(selfGrid, targetGrid);
if (distance > 7) continue;
var path = PathFinder.FindPath((int)Map.MapConfig.Width, (int)Map.MapConfig.Height,
new (selfGrid.Pos.X, selfGrid.Pos.Y), new (targetGrid.Pos.X, targetGrid.Pos.Y), Map, Player);
if (!path.found) continue;
if (path.length > 7) continue;
CityBorder.Add(targetCity.Id);
}
}
}

View File

@ -800,14 +800,13 @@ namespace Logic.AI
private static void CalculateLegionDevelopmentKill(AICalculatorData data, CommonActionParams param, CalculateResult result)
{
var score = 0;
var score = 0f;
var selfUnits = new HashSet<UnitData>();
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
foreach (var unit in param.MapData.UnitMap.UnitList)
{
if (selfUnits.Contains(unit)) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info)) continue;
score += info.Cost;
score += unit.GetCost();
}
result.Score[CalculateType.LegionDevelopmentKill] = 1f / (score + 1);
}
@ -885,13 +884,12 @@ namespace Logic.AI
var selfUnits = new HashSet<UnitData>();
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
var around = param.MapData.GridMap.GetAroundGridData(1, 1, unitGrid);
var score = 0;
var score = 0f;
foreach (var aroundGrid in around)
{
if (!param.MapData.GetUnitDataByGid(aroundGrid.Id, out var aroundUnit)) continue;
if (!selfUnits.Contains(aroundUnit)) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(aroundUnit.UnitType, aroundUnit.GiantType, out var info)) continue;
score += info.Cost;
score += aroundUnit.GetCost();
}
result.Score[CalculateType.LegionDefendMove] = 1 / ((float)path.length + 1) * 1000 + score / 1000f;
}
@ -934,22 +932,20 @@ namespace Logic.AI
var units = new HashSet<UnitData>();
var targets = new HashSet<UnitData>();
var selfScore = 0;
var targetScore = 0;
var selfScore = 0f;
var targetScore = 0f;
foreach (var unit in param.MapData.UnitMap.UnitList)
{
if (!selfUnits.Contains(unit)) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
if (selfUnits.Contains(unit))
{
units.Add(unit);
selfScore += info.Cost;
selfScore += unit.GetCost();
}
else
{
targets.Add(unit);
targetScore += info.Cost;
targetScore += unit.GetCost();
}
}
@ -975,24 +971,22 @@ namespace Logic.AI
var units = new HashSet<UnitData>();
var targets = new HashSet<UnitData>();
var selfScore = 0;
var targetScore = 0;
var selfScore = 0f;
var targetScore = 0f;
foreach (var unit in param.MapData.UnitMap.UnitList)
{
if (!param.MapData.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
var dis = param.MapData.GridMap.CalcDistance(cityGrid, unitGrid);
if (dis > 6) continue;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, out var info))
continue;
if (selfUnits.Contains(unit))
{
units.Add(unit);
selfScore += info.Cost;
selfScore += unit.GetCost();
}
else
{
targets.Add(unit);
targetScore += info.Cost;
targetScore += unit.GetCost();
}
}