/// <summary> /// Returns an action that moves towards an enemy as fast as possible. /// </summary> public static UctAction FastMoveTowardsEnemy(GameInstance state, CachedMob mob, CachedMob target) { var pathfinder = state.Pathfinder; var moveTarget = pathfinder.FurthestPointToTarget(mob, target); if (moveTarget != null && pathfinder.Distance(mob.MobInstance.Coord, moveTarget.Value) <= mob.MobInstance.Ap) { return(UctAction.MoveAction(mob.MobId, moveTarget.Value)); } else if (moveTarget == null) { // Intentionally doing nothing return(UctAction.EndTurnAction()); } else { Utils.Log(LogSeverity.Debug, nameof(AiRuleBasedController), $"Move failed since target is too close, source {mob.MobInstance.Coord}, target {target.MobInstance.Coord}"); return(UctAction.EndTurnAction()); } }
/// <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); } } } }