TH1/My project/Assets/Scripts/Logic/AI/AIActionGenerator.cs
2025-05-13 11:44:59 +08:00

242 lines
10 KiB
C#

/*
* @Author: 白哉
* @Description: AI Action 生成器
* @Date: 2025年04月30日 星期三 11:04:38
* @Modify:
*/
using System.Collections.Generic;
using Logic.Action;
using RuntimeData;
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 void GeneratorActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
// 小兵行为
var unitList = new List<UnitData>();
map.GetUnitDataListByPlayerId(player.Id, unitList);
foreach (var unit in unitList)
{
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));
}
}
// 地块行为
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 (param.PlayerData.PlayerWealth < action.GetCost()) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
// 城市行为
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)
{
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
GeneratorTechActions(map, player, aiActions);
}
// 穷举科技树行动
public static void GeneratorTechActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
// 玩家行为
var param = new CommonActionParams(map, playerData:player, mainObjectType:MainObjectType.Player);
param.RefreshParams();
if (!ActionLogicFactory.PlayerHasAction(param, out var actions)) return;
foreach (var action in actions)
{
if (action.ActionId.ActionType != CommonActionType.LearnTech) continue;
if (param.PlayerData.PlayerWealth < action.GetCost()) continue;
aiActions.Add(new AIActionBase(param, action));
}
}
// 穷举地图预期收益行动
public static void GeneratorFutureActions(MapData map, PlayerData player, List<AIActionBase> aiActions = null)
{
if (aiActions == null) aiActions = new List<AIActionBase>();
GeneratorTechActions(map, player, aiActions);
for (int i = aiActions.Count - 1; i >= 0; i--)
{
if (aiActions[i].ActionLogic.ActionId == null)
{
aiActions.RemoveAt(i);
continue;
}
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.Gain) continue;
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.BuildWonder) continue;
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.Build) continue;
if (aiActions[i].ActionLogic.ActionId.ActionType == CommonActionType.TrainUnit) continue;
aiActions.RemoveAt(i);
}
}
}
}