Merge branch 'main' of http://10.27.16.144:3000/kawagiri/TH1
This commit is contained in:
commit
504ade8c9c
@ -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}
|
||||
|
||||
@ -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
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description:
|
||||
* @Date: 2025年06月06日 星期五 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d788bec02c644e39f2b8caa88fce3c8
|
||||
timeCreated: 1751947052
|
||||
@ -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;
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description:
|
||||
* @Date: 2025年06月06日 星期五 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90daa9731e684789bd4e9e4a615e5fce
|
||||
timeCreated: 1751946383
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user