public void SelectAbility(int index) { var currentMob = _game.CurrentMob; if (currentMob == null) { return; } var mobInfo = _game.MobManager.MobInfos[currentMob.Value]; if (index >= mobInfo.Abilities.Count) { Utils.Log(LogSeverity.Info, nameof(GameBoardController), "Trying to select an ability index higher than the number of abilities."); return; } var ability = mobInfo.Abilities[index]; if (SelectedAbilityIndex.HasValue) { if (SelectedAbilityIndex.Value == index) { SelectedAbilityIndex = null; } else if (GameInvariants.IsAbilityUsableNoTarget(_game, currentMob.Value, ability)) { SelectedAbilityIndex = index; } } else if (GameInvariants.IsAbilityUsableNoTarget(_game, currentMob.Value, ability)) { SelectedAbilityIndex = index; } }
/// <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); }
public void Render(Entity entity, SpriteBatch batch, AssetManager assetManager) { var effect = assetManager.LoadEffect(AssetManager.ShaderAbility); batch.Begin(effect: effect, samplerState: Camera2D.SamplerState); var mob = _mobFunc(); if (mob != null) { var abilityId = mob.MobInfo.Abilities[_abilityIndex]; var isActive = _gameBoardController.SelectedAbilityIndex == _abilityIndex; if (GameInvariants.IsAbilityUsableNoTarget(_game, mob.MobId, abilityId)) { isActive = true; } var ability = _game.MobManager.Abilities[abilityId]; batch.Draw(assetManager[AssetManager.SpellBg], entity.RenderPosition); if (entity.AABB.Contains(InputManager.Instance.MousePosition)) { batch.Draw(assetManager[AssetManager.SpellHighlight], entity.RenderPosition); } } else { Debug.WriteLine("ERROR - Rendering abilities, but no mob is currently active."); batch.Draw(assetManager[AssetManager.NoTexture], entity.RenderPosition); } batch.End(); }
private void UnselectAbilityIfNeeded() { var mobId = _game.CurrentMob; if (mobId == null || !SelectedAbilityIndex.HasValue) { return; } var mobInfo = _game.MobManager.MobInfos[mobId.Value]; var selectedAbility = mobInfo.Abilities[SelectedAbilityIndex.Value]; if (!GameInvariants.IsAbilityUsableNoTarget(_game, mobId.Value, selectedAbility)) { SelectedAbilityIndex = null; } }
/// <summary> /// Calculates an action according to a simple default policy. Used mainly /// in MCTS playouts. /// </summary> public static UctAction DefaultPolicyAction(GameInstance state) { var mobId = state.CurrentMob; if (mobId == null) { throw new InvalidOperationException("Requesting mob action when there is no current mob."); } Debug.Assert(state.State.MobInstances[mobId.Value].Hp > 0, "Current mob is dead"); var mob = state.CachedMob(mobId.Value); if (mob.MobInstance.Ap == 0) { return(UctAction.EndTurnAction()); } var abilityIds = new List <int>(); foreach (var possibleAbilityId in mob.MobInfo.Abilities) { if (GameInvariants.IsAbilityUsableNoTarget(state, mobId.Value, possibleAbilityId)) { abilityIds.Add(possibleAbilityId); } } int moveTargetId = MobInstance.InvalidId; var actions = new List <UctAction>(); foreach (var possibleTargetId in state.MobManager.Mobs) { var possibleTarget = state.CachedMob(possibleTargetId); moveTargetId = possibleTargetId; if (!GameInvariants.IsTargetable(state, mob, possibleTarget)) { continue; } if (abilityIds.Count == 0) { continue; } foreach (var abilityId in abilityIds) { if (GameInvariants.IsAbilityUsableApRangeCheck(state, mob, possibleTarget, abilityId)) { actions.Add(UctAction.AbilityUseAction(abilityId, mob.MobId, possibleTargetId)); } } } if (actions.Count > 0) { return(MaxAbilityRatio(state, actions)); } if (moveTargetId != MobInstance.InvalidId) { return(PickMoveTowardsEnemyAction(state, state.CachedMob(mobId.Value), state.CachedMob(moveTargetId))); } else { Utils.Log(LogSeverity.Error, nameof(ActionGenerator), "No targets, game should be over"); throw new InvalidOperationException("No targets, game should be over."); } }