Compare commits
2 Commits
4bd7723e6f
...
1a37eed852
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a37eed852 | |||
| cf72dfcc12 |
@ -14,76 +14,193 @@ namespace Logic.AI
|
||||
{
|
||||
public class AIActionGenerator
|
||||
{
|
||||
private MapData _mapData;
|
||||
private PlayerData _player;
|
||||
private List<UnitData> _waitUnits;
|
||||
private List<GridData> _waitGrids;
|
||||
private List<CityData> _waitCity;
|
||||
private uint _actionRecord;
|
||||
private uint _recordCount;
|
||||
|
||||
public AIActionType ActionType => (AIActionType)(_actionRecord % (int)AIActionType.Max);
|
||||
|
||||
|
||||
public void Init(MapData map, PlayerData player)
|
||||
{
|
||||
_mapData = map;
|
||||
_player = player;
|
||||
_waitUnits ??= new List<UnitData>();
|
||||
_waitGrids ??= new List<GridData>();
|
||||
_waitCity ??= new List<CityData>();
|
||||
|
||||
var gridSet = map.GetPlayerTerritoryGridIdSet(player.Id);
|
||||
var unitList = new List<UnitData>();
|
||||
map.GetUnitDataListByPlayerId(player.Id, unitList);
|
||||
var cityList = new List<CityData>();
|
||||
map.GetCityDataListByPlayerId(player.Id, cityList);
|
||||
foreach (var unit in unitList) _waitUnits.Add(unit);
|
||||
foreach (var city in cityList) _waitCity.Add(city);
|
||||
foreach (var grid in _mapData.GridMap.GridList)
|
||||
if(gridSet.Contains(grid.Id)) _waitGrids.Add(grid);
|
||||
|
||||
_actionRecord = 0;
|
||||
_recordCount = 0;
|
||||
}
|
||||
|
||||
public void GeneratorOneStepActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
|
||||
{
|
||||
if (aiActions == null) aiActions = new List<AIActionBase>();
|
||||
for (int i = 0; i < (int)AIActionType.Max; i++)
|
||||
{
|
||||
if (_recordCount > 100) break;
|
||||
_recordCount++;
|
||||
_actionRecord++;
|
||||
var actionType = (AIActionType)(_actionRecord % (int)AIActionType.Max);
|
||||
if (actionType == AIActionType.Unit) GeneratorUnitActions(aiActions);
|
||||
else if (actionType == AIActionType.Grid) GeneratorGridActions(aiActions);
|
||||
else if (actionType == AIActionType.City) GeneratorCityActions(aiActions);
|
||||
if (aiActions.Count != 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
private void GeneratorUnitActions(List<AIActionBase> aiActions)
|
||||
{
|
||||
if (_waitUnits.Count == 0 || aiActions == null) return;
|
||||
for (int i = _waitUnits.Count - 1; i >= 0; i--)
|
||||
{
|
||||
GeneratorOneUnitActions(_waitUnits[i], aiActions);
|
||||
if (aiActions.Count != 0) break;
|
||||
_waitUnits.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void GeneratorOneUnitActions(UnitData unit, List<AIActionBase> aiActions)
|
||||
{
|
||||
if (ActionLogicFactory.UnitHasMoveAndAttackAction(_mapData, unit, out var aiActionList))
|
||||
{
|
||||
foreach (var aiAction in aiActionList) aiActions.Add(aiAction);
|
||||
}
|
||||
|
||||
var param = new CommonActionParams(_mapData, playerData:_player, unitData:unit);
|
||||
param.RefreshParams();
|
||||
if (!ActionLogicFactory.UnitHasAction(param, out var actions)) return;
|
||||
foreach (var action in actions)
|
||||
{
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
}
|
||||
|
||||
private void GeneratorGridActions(List<AIActionBase> aiActions)
|
||||
{
|
||||
if (_waitUnits.Count == 0 || aiActions == null) return;
|
||||
for (int i = _waitGrids.Count - 1; i >= 0; i--)
|
||||
{
|
||||
GeneratorOneGridActions(_waitGrids[i], aiActions);
|
||||
if (aiActions.Count != 0) break;
|
||||
_waitGrids.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void GeneratorOneGridActions(GridData grid, List<AIActionBase> aiActions)
|
||||
{
|
||||
var gridParam = new CommonActionParams(_mapData, playerData:_player, gridData:grid, mainObjectType:MainObjectType.Grid);
|
||||
var actionList = new List<ActionLogicBase>();
|
||||
if (!ActionLogicFactory.GridHasAction(gridParam, actionList)) return;
|
||||
foreach (var action in actionList)
|
||||
{
|
||||
if (gridParam.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(gridParam, action));
|
||||
}
|
||||
}
|
||||
|
||||
private void GeneratorCityActions(List<AIActionBase> aiActions)
|
||||
{
|
||||
if (_waitCity.Count == 0 || aiActions == null) return;
|
||||
|
||||
for (int i = _waitCity.Count - 1; i >= 0; i--)
|
||||
{
|
||||
GeneratorOneCityActions(_waitCity[i], aiActions);
|
||||
if (aiActions.Count != 0) break;
|
||||
_waitCity.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void GeneratorOneCityActions(CityData city, List<AIActionBase> aiActions)
|
||||
{
|
||||
var param = new CommonActionParams(_mapData, playerData:_player, cityData:city);
|
||||
param.RefreshParams();
|
||||
if (!ActionLogicFactory.CityHasAction(param, out var actions)) return;
|
||||
foreach (var action in actions)
|
||||
{
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
}
|
||||
|
||||
// 穷举式生成所有可能的行动
|
||||
public static void GeneratorActions(MapData map, PlayerData player, AIActionType actionType, List<AIActionBase> aiActions = null)
|
||||
public void GeneratorActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
|
||||
{
|
||||
if (aiActions == null) aiActions = new List<AIActionBase>();
|
||||
|
||||
// 小兵行为
|
||||
if (actionType == AIActionType.Unit)
|
||||
var unitList = new List<UnitData>();
|
||||
map.GetUnitDataListByPlayerId(player.Id, unitList);
|
||||
foreach (var unit in unitList)
|
||||
{
|
||||
var unitList = new List<UnitData>();
|
||||
map.GetUnitDataListByPlayerId(player.Id, unitList);
|
||||
foreach (var unit in unitList)
|
||||
if (ActionLogicFactory.UnitHasMoveAndAttackAction(map, unit, out var aiActionList))
|
||||
{
|
||||
if (ActionLogicFactory.UnitHasMoveAndAttackAction(map, unit, out var aiActionList))
|
||||
{
|
||||
foreach (var aiAction in aiActionList) aiActions.Add(aiAction);
|
||||
}
|
||||
|
||||
var param = new CommonActionParams(map, playerData:player, unitData:unit);
|
||||
param.RefreshParams();
|
||||
if (!ActionLogicFactory.UnitHasAction(param, out var actions)) continue;
|
||||
foreach (var action in actions)
|
||||
{
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
foreach (var aiAction in aiActionList) aiActions.Add(aiAction);
|
||||
}
|
||||
|
||||
var param = new CommonActionParams(map, playerData: player, unitData: unit);
|
||||
param.RefreshParams();
|
||||
if (!ActionLogicFactory.UnitHasAction(param, out var actions)) continue;
|
||||
foreach (var action in actions)
|
||||
{
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
}
|
||||
|
||||
if (actionType == AIActionType.Grid)
|
||||
// 地块行为
|
||||
var gridSet = map.GetPlayerTerritoryGridIdSet(player.Id);
|
||||
var gridParam = new CommonActionParams(map, playerData: player, gridData: null,
|
||||
mainObjectType: MainObjectType.Grid);
|
||||
var actionList = new List<ActionLogicBase>();
|
||||
foreach (var gird in map.GridMap.GridList)
|
||||
{
|
||||
// 地块行为
|
||||
var gridSet = map.GetPlayerTerritoryGridIdSet(player.Id);
|
||||
var gridParam = new CommonActionParams(map, playerData:player, gridData:null, mainObjectType:MainObjectType.Grid);
|
||||
var actionList = new List<ActionLogicBase>();
|
||||
foreach (var gird in map.GridMap.GridList)
|
||||
if (!gridSet.Contains(gird.Id)) continue;
|
||||
gridParam.GridData = gird;
|
||||
gridParam.RefreshParams();
|
||||
if (!ActionLogicFactory.GridHasAction(gridParam, actionList)) continue;
|
||||
var param = new CommonActionParams(map, playerData: player, gridData: gird,
|
||||
mainObjectType: MainObjectType.Grid);
|
||||
foreach (var action in actionList)
|
||||
{
|
||||
if (!gridSet.Contains(gird.Id)) continue;
|
||||
gridParam.GridData = gird;
|
||||
gridParam.RefreshParams();
|
||||
if (!ActionLogicFactory.GridHasAction(gridParam, actionList)) continue;
|
||||
var param = new CommonActionParams(map, playerData:player, gridData:gird, mainObjectType:MainObjectType.Grid);
|
||||
foreach (var action in actionList)
|
||||
{
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
}
|
||||
|
||||
if (actionType == AIActionType.City)
|
||||
|
||||
// 城市行为
|
||||
var cityList = new List<CityData>();
|
||||
map.GetCityDataListByPlayerId(player.Id, cityList);
|
||||
foreach (var city in cityList)
|
||||
{
|
||||
// 城市行为
|
||||
var cityList = new List<CityData>();
|
||||
map.GetCityDataListByPlayerId(player.Id, cityList);
|
||||
foreach (var city in cityList)
|
||||
var param = new CommonActionParams(map, playerData: player, cityData: city);
|
||||
param.RefreshParams();
|
||||
if (!ActionLogicFactory.CityHasAction(param, out var actions)) continue;
|
||||
foreach (var action in actions)
|
||||
{
|
||||
var param = new CommonActionParams(map, playerData:player, cityData:city);
|
||||
param.RefreshParams();
|
||||
if (!ActionLogicFactory.CityHasAction(param, out var actions)) continue;
|
||||
foreach (var action in actions)
|
||||
{
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
|
||||
aiActions.Add(new AIActionBase(param, action));
|
||||
}
|
||||
}
|
||||
|
||||
if (actionType == AIActionType.Tech) GeneratorTechActions(map, player, aiActions);
|
||||
|
||||
GeneratorTechActions(map, player, aiActions);
|
||||
}
|
||||
|
||||
|
||||
// 穷举科技树行动
|
||||
public static void GeneratorTechActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
|
||||
{
|
||||
@ -105,9 +222,7 @@ namespace Logic.AI
|
||||
public static void GeneratorFutureActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
|
||||
{
|
||||
if (aiActions == null) aiActions = new List<AIActionBase>();
|
||||
GeneratorActions(map, player, AIActionType.Grid, aiActions);
|
||||
GeneratorActions(map, player, AIActionType.City, aiActions);
|
||||
GeneratorActions(map, player, AIActionType.Unit, aiActions);
|
||||
GeneratorTechActions(map, player, aiActions);
|
||||
|
||||
for (int i = aiActions.Count - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
@ -79,6 +79,7 @@ namespace Logic.AI
|
||||
private Dictionary<UnitData, float> _unitScore;
|
||||
private Dictionary<CityData, float> _cityScore;
|
||||
private Dictionary<CityData, float> _cityDefendScore;
|
||||
public HashSet<UnitData> _unitOnCity;
|
||||
private UnitTargetMap _unitTargetMap;
|
||||
private List<CommonActionId> _actionList;
|
||||
|
||||
@ -86,6 +87,7 @@ namespace Logic.AI
|
||||
public Dictionary<UnitData, float> UnitScore => _unitScore;
|
||||
public Dictionary<CityData, float> CityScore => _cityScore;
|
||||
public Dictionary<CityData, float> CityDefendScore => _cityDefendScore;
|
||||
public HashSet<UnitData> UnitOnCity => _unitOnCity;
|
||||
public UnitTargetMap UnitTargetMap => _unitTargetMap;
|
||||
|
||||
|
||||
@ -95,10 +97,12 @@ namespace Logic.AI
|
||||
if (aiAction.ActionLogic.ActionId.UnitActionType == UnitActionType.Capture) return true;
|
||||
if (aiAction.ActionLogic.ActionId.UnitActionType == UnitActionType.Gather) return true;
|
||||
if (aiAction.ActionLogic.ActionId.UnitActionType == UnitActionType.Examine) return true;
|
||||
if (aiAction.ActionLogic is UnitAttackAction && UnitOnCity.Contains(aiAction.Param.TargetUnitData)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public AIActionBase CalculateMaxScoreAIAction(MapData mapData, PlayerData player, List<AIActionBase> actions, AIConfigAsset cfg, AIActionType actionType)
|
||||
public AIActionBase CalculateMaxScoreAIAction(MapData mapData, PlayerData player, List<AIActionBase> actions, AIConfigAsset cfg)
|
||||
{
|
||||
_cfg = cfg;
|
||||
AIActionBase maxAction = null;
|
||||
@ -107,40 +111,39 @@ namespace Logic.AI
|
||||
var maxScoreOffset = 0f;
|
||||
|
||||
var futureActions = new List<AIActionBase>();
|
||||
if (actionType == AIActionType.Tech)
|
||||
// if (actionType == AIActionType.Tech)
|
||||
// {
|
||||
// AIActionGenerator.GeneratorFutureActions(mapData, player, futureActions);
|
||||
// foreach (var aiAction in actions)
|
||||
// {
|
||||
// calMap.DeepCopy(mapData);
|
||||
// aiAction.Param.MapData = calMap;
|
||||
// aiAction.Param.RefreshParams();
|
||||
// aiAction.ActionLogic.Execute(aiAction.Param);
|
||||
// if (aiAction.ActionLogic.ActionId == null)continue;
|
||||
// aiAction.Result = CalculateFutureScore(aiAction.Param.MapData, player);
|
||||
// if (maxAction == null || aiAction.Result.GetAllScore() > 0) maxAction = aiAction;
|
||||
// }
|
||||
// }
|
||||
|
||||
foreach (var aiAction in actions)
|
||||
{
|
||||
AIActionGenerator.GeneratorFutureActions(mapData, player, futureActions);
|
||||
foreach (var aiAction in actions)
|
||||
{
|
||||
calMap.DeepCopy(mapData);
|
||||
aiAction.Param.MapData = calMap;
|
||||
aiAction.Param.RefreshParams();
|
||||
aiAction.ActionLogic.Execute(aiAction.Param);
|
||||
if (aiAction.ActionLogic.ActionId == null)continue;
|
||||
aiAction.Result = CalculateFutureScore(aiAction.Param.MapData, player);
|
||||
if (maxAction == null || aiAction.Result.GetAllScore() > 0) maxAction = aiAction;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var aiAction in actions)
|
||||
{
|
||||
calMap.DeepCopy(mapData);
|
||||
aiAction.Param.MapData = calMap;
|
||||
aiAction.Param.RefreshParams();
|
||||
aiAction.ActionLogic.Execute(aiAction.Param);
|
||||
aiAction.Result = CalculateScore(aiAction.Param.MapData, player, cfg);
|
||||
calMap.DeepCopy(mapData);
|
||||
aiAction.Param.MapData = calMap;
|
||||
aiAction.Param.RefreshParams();
|
||||
aiAction.ActionLogic.Execute(aiAction.Param);
|
||||
aiAction.Result = CalculateScore(aiAction.Param.MapData, player, cfg);
|
||||
|
||||
if (IsTrueAction(aiAction)) return aiAction;
|
||||
var scoreOffset = aiAction.Result.GetAllScore() - startResult.GetAllScore();
|
||||
if (scoreOffset < 0) continue;
|
||||
if (maxAction == null || scoreOffset > maxScoreOffset)
|
||||
{
|
||||
maxAction = aiAction;
|
||||
maxScoreOffset = scoreOffset;
|
||||
}
|
||||
if (IsTrueAction(aiAction)) return aiAction;
|
||||
var scoreOffset = aiAction.Result.GetAllScore() - startResult.GetAllScore();
|
||||
if (scoreOffset < 0) continue;
|
||||
if (maxAction == null || scoreOffset > maxScoreOffset)
|
||||
{
|
||||
maxAction = aiAction;
|
||||
maxScoreOffset = scoreOffset;
|
||||
}
|
||||
}
|
||||
|
||||
return maxAction;
|
||||
}
|
||||
|
||||
@ -150,17 +153,19 @@ namespace Logic.AI
|
||||
_unitScore ??= new Dictionary<UnitData, float>();
|
||||
_cityScore ??= new Dictionary<CityData, float>();
|
||||
_cityDefendScore ??= new Dictionary<CityData, float>();
|
||||
_unitOnCity ??= new HashSet<UnitData>();
|
||||
_canMoveGrid ??= new HashSet<GridData>();
|
||||
_unitTargetMap ??= new UnitTargetMap();
|
||||
_unitScore.Clear();
|
||||
_cityScore.Clear();
|
||||
_cityDefendScore.Clear();
|
||||
_unitOnCity.Clear();
|
||||
_canMoveGrid.Clear();
|
||||
UnitTargetMap.Clear();
|
||||
|
||||
var result = new CalculateResult();
|
||||
for (int i = 0; i < (int)AICalculatorType.Max; i++)
|
||||
{
|
||||
RefreshUnitPos(mapData, player, result);
|
||||
if (i == (int)AICalculatorType.Sight) CalculatePlayerSightScore(mapData, player, result);
|
||||
if (i == (int)AICalculatorType.UnitCanMove) CalculateUnitCanMoveScore(mapData, player, result);
|
||||
if (i == (int)AICalculatorType.MoneyScore) CalculateMoneyScore(mapData, player, result);
|
||||
@ -301,6 +306,30 @@ namespace Logic.AI
|
||||
result.ScoreDict[AICalculatorType.CityDefendScore] = cityDefendScore;
|
||||
}
|
||||
|
||||
// 刷新小兵位置
|
||||
private void RefreshUnitPos(MapData mapData, PlayerData playerData, CalculateResult result)
|
||||
{
|
||||
var selfCities = mapData.GetCityDataSetByPlayerId(playerData.Id);
|
||||
var cityGridSet = new HashSet<GridData>();
|
||||
foreach (var city in mapData.CityMap.CityList)
|
||||
{
|
||||
if (selfCities.Contains(city)) continue;
|
||||
if (!mapData.GetGridDataByCityId(city.Id, out var gridData)) continue;
|
||||
cityGridSet.Add(gridData);
|
||||
}
|
||||
|
||||
var selfUnits = new HashSet<UnitData>();
|
||||
mapData.GetUnitDataListByPlayerId(playerData.Id, selfUnits);
|
||||
foreach (var unit in mapData.UnitMap.UnitList)
|
||||
{
|
||||
if (selfUnits.Contains(unit)) continue;
|
||||
if (!mapData.GetGridDataByUnitId(unit.Id, out var gridData)) continue;
|
||||
if (!cityGridSet.Contains(gridData)) continue;
|
||||
_unitOnCity.Add(unit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 刷新小兵攻击评分
|
||||
private void RefreshUnitAttackScore(MapData mapData, PlayerData playerData, CalculateResult result)
|
||||
{
|
||||
@ -520,7 +549,6 @@ namespace Logic.AI
|
||||
var actions = new List<AIActionBase>();
|
||||
AIActionGenerator.GeneratorFutureActions(mapData, player, actions);
|
||||
|
||||
|
||||
if (actions.Count == 0) return result;
|
||||
var calMap = mapData.GetDeepCopyMapData();
|
||||
float score = 0;
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
@ -32,21 +33,33 @@ namespace Logic.AI
|
||||
public float UnitExploreStarfishScore;
|
||||
|
||||
public float FutureScoreTransformValue;
|
||||
|
||||
public List<AICalculatorTechInfo> TechInfoList = new List<AICalculatorTechInfo>();
|
||||
|
||||
|
||||
public AICalculatorTechInfo GetTechInfo(TechType techType)
|
||||
{
|
||||
foreach (var techInfo in TechInfoList)
|
||||
{
|
||||
if (techInfo.TechType != techType) continue;
|
||||
return techInfo;
|
||||
}
|
||||
|
||||
var newTechInfo = new AICalculatorTechInfo()
|
||||
{
|
||||
TechType = techType,
|
||||
Ratio = 1
|
||||
};
|
||||
TechInfoList.Add(newTechInfo);
|
||||
return newTechInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class AICalculatorConfig
|
||||
public class AICalculatorTechInfo
|
||||
{
|
||||
public AICalculatorType CalType;
|
||||
public float CalScore;
|
||||
|
||||
public float FutureScoreTransformValue;
|
||||
|
||||
public AICalculatorConfig(AICalculatorType type, float score)
|
||||
{
|
||||
CalType = type;
|
||||
CalScore = score;
|
||||
}
|
||||
public TechType TechType;
|
||||
public float Ratio;
|
||||
}
|
||||
}
|
||||
@ -7,9 +7,11 @@
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Logic.Action;
|
||||
using UnityEngine;
|
||||
using RuntimeData;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
|
||||
namespace Logic.AI
|
||||
@ -38,6 +40,7 @@ namespace Logic.AI
|
||||
|
||||
private float _recordTime;
|
||||
private AIActionScoreCalculator _scoreCalculator;
|
||||
private AIActionGenerator _generator;
|
||||
|
||||
private List<AIActionBase> RecordActions;
|
||||
private AIActionBase MaxScoreAction;
|
||||
@ -45,10 +48,6 @@ namespace Logic.AI
|
||||
private MapData _mapData;
|
||||
private PlayerData _playerData;
|
||||
private AIConfigAsset _cfg;
|
||||
|
||||
private Dictionary<AIActionType, bool> _actionFinishState;
|
||||
private uint _curActionState;
|
||||
private uint _actionLimit;
|
||||
|
||||
|
||||
public AILogic()
|
||||
@ -57,9 +56,8 @@ namespace Logic.AI
|
||||
RecordActions = new List<AIActionBase>();
|
||||
_scoreCalculator = new AIActionScoreCalculator();
|
||||
_cfg = Resources.Load<AIConfigAsset>("DataAssets/AiConfig");
|
||||
|
||||
_actionFinishState = new Dictionary<AIActionType, bool>();
|
||||
for (int i = 0; i < (int)AIActionType.Max; i++) _actionFinishState[(AIActionType)i] = false;
|
||||
|
||||
_generator = new AIActionGenerator();
|
||||
}
|
||||
|
||||
// 开始 AI 逻辑
|
||||
@ -68,10 +66,7 @@ namespace Logic.AI
|
||||
AILogicState = AILogicState.Playing;
|
||||
_mapData = mapData;
|
||||
_playerData = playerData;
|
||||
|
||||
for (int i = 0; i < (int)AIActionType.Max; i++) _actionFinishState[(AIActionType)i] = false;
|
||||
_curActionState = 0;
|
||||
_actionLimit = 0;
|
||||
_generator.Init(_mapData, _playerData);
|
||||
}
|
||||
|
||||
// 结束 AI 逻辑
|
||||
@ -91,18 +86,12 @@ namespace Logic.AI
|
||||
|
||||
if (AILogicState == AILogicState.Playing)
|
||||
{
|
||||
for (int i = 0; i < (int)AIActionType.Max; i++)
|
||||
{
|
||||
if (_actionFinishState[(AIActionType)i]) continue;
|
||||
var actionType = (AIActionType)(_curActionState % (int)AIActionType.Max);
|
||||
AIActionGenerator.GeneratorActions(_mapData, _playerData, actionType, RecordActions);
|
||||
CalculateMaxScoreAction(actionType);
|
||||
_curActionState++;
|
||||
if (MaxScoreAction != null) break;
|
||||
_actionFinishState[(AIActionType)i] = true;
|
||||
}
|
||||
|
||||
if (_actionLimit >= 20) MaxScoreAction = null;
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
RecordActions.Clear();
|
||||
_generator.GeneratorOneStepActions(_mapData, _playerData, RecordActions);
|
||||
CalculateMaxScoreAction();
|
||||
if (sw.Elapsed.TotalMilliseconds > 20) Debug.Log($"{_generator.ActionType} 耗时:{sw.Elapsed.TotalMilliseconds} ms");
|
||||
|
||||
// AI 执行已结束
|
||||
if (!GetAILogicPermission())
|
||||
@ -121,12 +110,10 @@ namespace Logic.AI
|
||||
MaxScoreAction.Param.MapData = _mapData;
|
||||
MaxScoreAction.Param.RefreshParams();
|
||||
MaxScoreAction.ActionLogic.Execute(MaxScoreAction.Param);
|
||||
_actionLimit++;
|
||||
MaxScoreAction = null;
|
||||
AILogicState = AILogicState.Pausing;
|
||||
_recordTime = Time.time;
|
||||
}
|
||||
|
||||
RecordActions.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,9 +124,10 @@ namespace Logic.AI
|
||||
}
|
||||
|
||||
// 选取最高得分行动
|
||||
private void CalculateMaxScoreAction(AIActionType actionType)
|
||||
private void CalculateMaxScoreAction()
|
||||
{
|
||||
MaxScoreAction = _scoreCalculator.CalculateMaxScoreAIAction(_mapData, _playerData, RecordActions, _cfg, actionType);
|
||||
if (RecordActions.Count == 0) return;
|
||||
MaxScoreAction = _scoreCalculator.CalculateMaxScoreAIAction(_mapData, _playerData, RecordActions, _cfg);
|
||||
if (MaxScoreAction != null && MaxScoreAction.ActionLogic.ActionId != null &&
|
||||
MaxScoreAction.ActionLogic.ActionId.ActionType == CommonActionType.LearnTech)
|
||||
{
|
||||
|
||||
60
My project/Assets/Scripts/Logic/AI/AITechScoreCalculator.cs
Normal file
60
My project/Assets/Scripts/Logic/AI/AITechScoreCalculator.cs
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* @Author: 白哉
|
||||
* @Description:
|
||||
* @Date: 2025年05月12日 星期一 20:05:44
|
||||
* @Modify:
|
||||
*/
|
||||
|
||||
|
||||
using RuntimeData;
|
||||
|
||||
|
||||
namespace Logic.AI
|
||||
{
|
||||
public class AITechScoreCalculator
|
||||
{
|
||||
public float CalculateTechScore(MapData map, PlayerData player, TechType tech, AIConfigAsset cfg)
|
||||
{
|
||||
if (tech == TechType.Climbing)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var gridId in player.Sight.SightGidSet)
|
||||
{
|
||||
if (!map.GridMap.GetGridDataByGid(gridId, out var gridData)) continue;
|
||||
if (gridData.Feature != TerrainFeature.Mountain) continue;
|
||||
count++;
|
||||
}
|
||||
|
||||
return cfg.GetTechInfo(TechType.Climbing).Ratio * count;
|
||||
}
|
||||
|
||||
if (tech == TechType.Fishing)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var gridId in player.Sight.SightGidSet)
|
||||
{
|
||||
if (!map.GridMap.GetGridDataByGid(gridId, out var gridData)) continue;
|
||||
if (gridData.Terrain != TerrainType.ShallowSea) continue;
|
||||
count++;
|
||||
}
|
||||
|
||||
return cfg.GetTechInfo(TechType.Climbing).Ratio * count;
|
||||
}
|
||||
|
||||
if (tech == TechType.Sailing)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var gridId in player.Sight.SightGidSet)
|
||||
{
|
||||
if (!map.GridMap.GetGridDataByGid(gridId, out var gridData)) continue;
|
||||
if (gridData.Terrain != TerrainType.DeepSea) continue;
|
||||
count++;
|
||||
}
|
||||
|
||||
return cfg.GetTechInfo(TechType.Climbing).Ratio * count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e604e03efac4414e9511f983bcbe8611
|
||||
timeCreated: 1747053040
|
||||
Loading…
x
Reference in New Issue
Block a user