/// <summary> /// Generates possible direct ability use actions. /// </summary> public static bool GenerateDirectAbilityUse(GameInstance state, CachedMob mob, List <UctAction> result) { bool foundAbilityUse = false; var mobInfo = mob.MobInfo; var mobId = mob.MobId; foreach (var abilityId in mobInfo.Abilities) { if (!GameInvariants.IsAbilityUsableNoTarget(state, mobId, abilityId)) { continue; } foreach (var targetId in state.MobManager.Mobs) { if (GameInvariants.IsAbilityUsable(state, mob, state.CachedMob(targetId), abilityId)) { foundAbilityUse = true; var action = UctAction.AbilityUseAction(abilityId, mobId, targetId); GameInvariants.AssertValidAction(state, action); result.Add(action); } } } return(foundAbilityUse); }
/// <summary> /// Generates a number of defensive move actions based on a heatmap. /// </summary> public static void GenerateDefensiveMoveActions(GameInstance state, CachedMob mob, List <UctAction> result) { var heatmap = Heatmap.BuildHeatmap(state, null, false); var coords = new List <AxialCoord>(); var mobInstance = mob.MobInstance; var mobId = mob.MobId; foreach (var coord in heatmap.Map.AllCoords) { if (heatmap.Map[coord] != heatmap.MinValue) { continue; } if (state.Map[coord] == HexType.Wall) { continue; } if (state.State.AtCoord(coord, true).HasValue) { continue; } bool canMoveTo = state.Pathfinder.Distance(mobInstance.Coord, coord) <= mobInstance.Ap; if (!canMoveTo) { continue; } coords.Add(coord); } coords.Shuffle(); int maximumMoveActions = Math.Max(0, 3 - result.Count); for (int i = 0; i < Math.Min(coords.Count, maximumMoveActions); i++) { var action = UctAction.DefensiveMoveAction(mobId, coords[i]); GameInvariants.AssertValidAction(state, action); result.Add(action); } }
/// <summary> /// Generates possible attack move actions. /// </summary> public static void GenerateAttackMoveActions(GameInstance state, CachedMob mob, List <UctAction> result) { var mobInfo = mob.MobInfo; var mobInstance = mob.MobInstance; foreach (var enemyId in state.MobManager.Mobs) { var target = state.CachedMob(enemyId); if (!GameInvariants.IsTargetableNoSource(state, mob, target)) { continue; } AxialCoord myCoord = mobInstance.Coord; AxialCoord?closestCoord = null; int? distance = null; int? chosenAbilityId = null; foreach (var coord in state.Map.EmptyCoords) { if (!state.Map.IsVisible(coord, target.MobInstance.Coord)) { continue; } var possibleMoveAction = GameInvariants.CanMoveTo(state, mob, coord); if (possibleMoveAction.Type == UctActionType.Null) { continue; } Debug.Assert(possibleMoveAction.Type == UctActionType.Move); foreach (var abilityId in mobInfo.Abilities) { if (!GameInvariants.IsAbilityUsableFrom(state, mob, coord, target, abilityId)) { continue; } int myDistance = state.Pathfinder.Distance(myCoord, coord); if (!closestCoord.HasValue) { chosenAbilityId = abilityId; closestCoord = coord; distance = myDistance; } else if (distance.Value > myDistance) { chosenAbilityId = abilityId; closestCoord = coord; distance = myDistance; } } } if (closestCoord.HasValue) { if (Constants.AttackMoveEnabled) { var action = UctAction.AttackMoveAction(mob.MobId, closestCoord.Value, chosenAbilityId.Value, target.MobId); var after = ActionEvaluator.F(state, action.ToPureMove()); GameInvariants.AssertValidAbilityUseAction(after, action.ToPureAbilityUse()); GameInvariants.AssertValidAction(state, action); result.Add(action); } else { var action = UctAction.MoveAction(mob.MobId, closestCoord.Value); GameInvariants.AssertValidAction(state, action); result.Add(action); } } } }