public override void Pick(PlanOfAttack plan) { int index = Random.Range(0, pickers.Count); BaseAbilityPicker p = pickers[index]; p.Pick(plan); }
public override void Pick(PlanOfAttack plan) { plan.ability = Find(card); plan.target = target; bool noNeedToHeal = true; if (plan.ability != null) { List <Tile> targets = new List <Tile>(GetComponentInParent <BattleController>().board.tiles.Values); foreach (Tile t in targets) { if (t.content != null && t.content.GetComponent <Alliance>().IsMatch(owner.GetComponent <Alliance>(), target) && plan.ability.GetComponent <AbilityEffectTarget>().IsTarget(t)) { if (!t.content.GetComponent <Health>().FullHP || t.content.GetComponent <Unit>().beingHealed) { noNeedToHeal = false; } } } } if (noNeedToHeal) { plan.ability = null; } }
public PlanOfAttack Evaluate() { PlanOfAttack poa = new PlanOfAttack(); AttackPattern pattern = actor.GetComponentInChildren <AttackPattern>(); if (pattern) { pattern.Pick(poa); } else { DefaultAttackPattern(poa); } if (IsPositionIndependent(poa)) { PlanPositionIndependent(poa); } else if (IsDirectionIndependent(poa)) { PlanDirectionIndependent(poa); } else { PlanDirectionDependent(poa); } if (poa.ability == null) { MoveTowardOpponent(poa); } return(poa); }
//position and facing angle matter. checks every facing for best option void PlanDirectionDependent(PlanOfAttack poa) { Tile startTile = actor.tile; Directions startDirection = actor.dir; List <AttackOption> list = new List <AttackOption>(); List <Tile> moveOptions = GetMoveOptions(); for (int i = 0; i < moveOptions.Count; ++i) { Tile moveTile = moveOptions[i]; actor.Place(moveTile); for (int j = 0; j < 4; ++j) { actor.dir = (Directions)j; AttackOption ao = new AttackOption(); ao.target = moveTile; ao.direction = actor.dir; RateFireLocation(poa, ao); ao.AddMoveTarget(moveTile); list.Add(ao); } } actor.Place(startTile); actor.dir = startDirection; PickBestOption(poa, list); }
private void PlanDirectionDependent(PlanOfAttack poa) { Tile startTile = actor.tile; Directions startDirection = actor.dir; var list = new List <AttackOption>(); List <Tile> moveOptions = GetMoveOptions(); // Loop on the move options (movement range) for (int i = 0; i < moveOptions.Count; ++i) { Tile moveTile = moveOptions[i]; actor.Place(moveTile); // Loop on the directions. for (int j = 0; j < 4; ++j) { actor.dir = (Directions)j; var actionOption = new AttackOption(); actionOption.target = moveTile; actionOption.direction = actor.dir; RateFireLocation(poa, actionOption); actionOption.AddMoveTarget(moveTile); list.Add(actionOption); } } // Place the actor back to the initial tile. If we didn't do this, the // AI would be out of sync with the visuals. actor.Place(startTile); actor.dir = startDirection; PickBestOption(poa, list); }
void RateFireLocation(PlanOfAttack poa, AttackOption option) { if (poa.ability != null) { AbilityRange range = poa.ability.GetComponent <AbilityRange>(); List <Tile> tiles = range.GetTilesInRange(owner.board); option.targets = tiles; for (int i = 0; i < tiles.Count; ++i) { Tile tile = tiles[i]; if (!poa.ability.GetComponent <AbilityEffectTarget>().IsTarget(tile)) { continue; } bool isMatch = IsAbilityTargetMatch(poa, tile); if (isMatch && poa.ability.GetComponent <BaseAbilityEffect>() is HealAbilityEffect) { if (tile.content.GetComponent <Health>().FullHP) { option.AddMark(tile, false); option.AddMark(tile, false); } else { option.AddMark(tile, isMatch); } } option.AddMark(tile, isMatch); } } }
/// <summary> /// Sets the plan of attack's move location and fire location to /// a random position (within the possible move options). /// </summary> /// /// <param name="poa">The plan of attack.</param> private void PlanPositionIndependent(PlanOfAttack poa) { List <Tile> moveOptions = GetMoveOptions(); Tile tile = moveOptions[Random.Range(0, moveOptions.Count)]; poa.moveLocation = poa.fireLocation = tile.pos; }
public void Pick(PlanOfAttack plan) { pickers[index].Pick(plan); index++; if (index >= pickers.Count) { index = 0; } }
public PlanOfAttack Evaluate() { string state; PlanOfAttack poa = new PlanOfAttack(); poa.complete = false; state = EvaluateState(); if (actor.lastState != state) { actor.lastState = state; if (state == "Default") { bc.GetComponentInChildren <BattleMessageController>().Display(actor.name + " feels normal"); } else if (state == "Shaken") { bc.GetComponentInChildren <BattleMessageController>().Display(actor.name + " feels shaken"); } else if (state == "Emboldened") { bc.GetComponentInChildren <BattleMessageController>().Display(actor.name + " feels emboldened"); } actor.transform.Find(state + " " + actor.GetComponentInChildren <Job>().name + " Attack Pattern").GetComponent <AttackPattern>().index = 0; } AttackPattern pattern = actor.transform.Find(state + " " + actor.GetComponentInChildren <Job>().name + " Attack Pattern").GetComponent <AttackPattern>(); if (pattern) { pattern.Pick(poa); } else { DefaultAttackPattern(poa); } if (poa.complete == false) { if (IsPositionIndependent(poa)) { PlanPositionIndependent(poa); } else if (IsDirectionIndependent(poa)) { PlanDirectionIndependent(poa); } else { PlanDirectionDependent(poa); } if (poa.ability == null) { MoveTowardOpponent(poa); } } return(poa); }
public override void Pick(PlanOfAttack finalPlan) { PlanOfAttack optionalPlan = new PlanOfAttack(); PlanOfAttack plan = new PlanOfAttack(); for (int i = 0; i < pickers.Count; i++) { BaseAbilityPicker p = pickers[i]; p.Pick(plan); cp.Evaluate(plan); if (plan.ability == null) { optionalPlan = plan; continue; } Debug.Log(plan.ability.name); Debug.Log(plan.unit.name); string unit = plan.unit.name; string ability = plan.ability.name; Unit.Pair pair = new Unit.Pair(unit, ability); if (owner.pairings.Contains(pair)) { pair = (Unit.Pair)owner.pairings[owner.pairings.IndexOf(pair)]; } else { owner.pairings.Add(pair); max = pair.damage; abilityName = pair.ability; } if (pair.damage >= max) { max = pair.damage; abilityName = pair.ability; finalPlan.ability = plan.ability; finalPlan.target = plan.target; finalPlan.moveLocation = plan.moveLocation; finalPlan.fireLocation = plan.fireLocation; finalPlan.attackDirection = plan.attackDirection; finalPlan.unit = plan.unit; } bmc.Display("Current max: " + max + " by " + abilityName); StartCoroutine(Wait()); } max = 0; if (finalPlan.ability == null) { finalPlan.ability = optionalPlan.ability; finalPlan.target = optionalPlan.target; finalPlan.moveLocation = optionalPlan.moveLocation; finalPlan.fireLocation = optionalPlan.fireLocation; finalPlan.attackDirection = optionalPlan.attackDirection; finalPlan.unit = optionalPlan.unit; } finalPlan.complete = true; }
public override void Pick(PlanOfAttack plan) { plan.target = target; plan.ability = Find(ability); if (plan.ability == null) { plan.ability = Default(); plan.target = Targets.Foe; } }
public void Change(Unit current) { actor = current; hasUnitMoved = false; hasUnitActed = false; lockMove = false; startTile = actor.tile; startDir = actor.dir; plan = null; }
void PickBestOption(PlanOfAttack poa, List <AttackOption> list) { int bestScore = 1; List <AttackOption> bestOptions = new List <AttackOption>(); for (int i = 0; i < list.Count; ++i) { AttackOption option = list[i]; int score = option.GetScore(actor, poa.ability); if (score > bestScore) { bestScore = score; bestOptions.Clear(); bestOptions.Add(option); } else if (score == bestScore) { bestOptions.Add(option); } } if (bestOptions.Count == 0) { poa.ability = null; // Clear ability as a sign not to perform it return; } List <AttackOption> finalPicks = new List <AttackOption>(); bestScore = 0; for (int i = 0; i < bestOptions.Count; ++i) { AttackOption option = bestOptions[i]; int score = option.bestAngleBasedScore; if (score > bestScore) { bestScore = score; finalPicks.Clear(); finalPicks.Add(option); } else if (score == bestScore) { finalPicks.Add(option); } } AttackOption choice = finalPicks[UnityEngine.Random.Range(0, finalPicks.Count)]; poa.fireLocation = choice.target.pos; Debug.Log(choice.target.pos); poa.unit = choice.target.content; poa.attackDirection = choice.direction; poa.moveLocation = choice.bestMoveTile.pos; }
public override void Pick(PlanOfAttack plan) { for (int i = 0; i < pickers.Count; i++) { BaseCardPicker p = pickers[i]; p.Pick(plan); if (plan.ability != null) { break; } } }
public IEnumerator AIMoveSequence(PlanOfAttack attack) { Tile location = owner.board.GetTile(attack.moveLocation); if (location != null) { actor.acting = true; yield return(StartCoroutine(actor.GetComponent <Movement>().Traverse(location))); actor.acting = false; } }
public IEnumerator AIAttackSequence(PlanOfAttack attack) { actor.acting = true; if (attack.ability.GetComponent <AbilityManaCost>().amount <= actor.GetComponent <Mana>().MP) { List <Tile> targets = attack.fireLocations; attack.ability.Perform(targets); yield return(StartCoroutine(AIReloadCardSequence(attack.ability))); } yield return(new WaitForSeconds(1 - (actor.GetComponent <Stats>()[StatTypes.DEX] * .02f))); yield return(new WaitForSeconds(AIThoughtLatency)); actor.acting = false; }
bool IsAbilityTargetMatch(PlanOfAttack poa, Tile tile) { bool isMatch = false; if (poa.target == Targets.Tile) { isMatch = true; } else if (poa.target != Targets.None) { Alliance other = tile.content.GetComponentInChildren <Alliance>(); if (other != null && alliance.IsMatch(other, poa.target)) { isMatch = true; } } return(isMatch); }
private void PlanDirectionIndependent(PlanOfAttack poa) { Tile startTile = actor.tile; var map = new Dictionary <Tile, AttackOption>(); AbilityRange abilityRange = poa.ability.GetComponent <AbilityRange>(); List <Tile> moveOptions = GetMoveOptions(); // Loop on the move options (movement range). for (int i = 0; i < moveOptions.Count; ++i) { Tile moveTile = moveOptions[i]; actor.Place(moveTile); List <Tile> fireOptions = abilityRange.GetTilesInRange(bc.board); // Loop on the fire options (ability range). for (int j = 0; j < fireOptions.Count; ++j) { Tile fireTile = fireOptions[j]; AttackOption attackOption = null; if (map.ContainsKey(fireTile)) { attackOption = map[fireTile]; } else { attackOption = new AttackOption(); attackOption.target = fireTile; attackOption.direction = actor.dir; map[fireTile] = attackOption; RateFireLocation(poa, attackOption); } attackOption.AddMoveTarget(moveTile); } } // Place the actor back to the initial tile. If we didn't do this, the // AI would be out of sync with the visuals. actor.Place(startTile); var list = new List <AttackOption>(map.Values); PickBestOption(poa, list); }
void Update() { if (!AssessHand()) { if (!actor.acting && !actor.beingHealed) { AIThoughtLatency = 1 / actor.GetComponent <Stats>()[StatTypes.WIS]; PlanOfAttack plan = Evaluate(); if (plan.fireLocations.Count > 0 && plan.ability != null && plan.moveLocation == actor.tile.pos) { StartCoroutine(AIAttackSequence(plan)); } else { StartCoroutine(AIMoveSequence(plan)); } } } }
private void RateFireLocation(PlanOfAttack poa, AttackOption attackOption) { AbilityArea area = poa.ability.GetComponent <AbilityArea>(); List <Tile> tiles = area.GetTilesInArea(bc.board, attackOption.target.pos); attackOption.areaTargets = tiles; attackOption.isCasterMatch = IsAbilityTargetMatch(poa, actor.tile); for (int i = 0; i < tiles.Count; ++i) { Tile tile = tiles[i]; if (actor.tile == tiles[i] || !poa.ability.IsTarget(tile)) { continue; } bool isMatch = IsAbilityTargetMatch(poa, tile); attackOption.AddMark(tile, isMatch); } }
void MoveTowardOpponent(PlanOfAttack poa) { List <Tile> moveOptions = GetMoveOptions(); FindNearestFoe(); if (nearestFoe != null) { Tile toCheck = nearestFoe.tile; while (toCheck != null) { if (moveOptions.Contains(toCheck)) { poa.moveLocation = toCheck.pos; return; } toCheck = toCheck.prev; } } poa.moveLocation = actor.tile.pos; }
public PlanOfAttack Evaluate(PlanOfAttack poa) { if (IsPositionIndependent(poa)) { PlanPositionIndependent(poa); } else if (IsDirectionIndependent(poa)) { PlanDirectionIndependent(poa); } else { PlanDirectionDependent(poa); } if (poa.ability == null) { MoveTowardOpponent(poa); } return(poa); }
/// <summary> /// Determines if the ability target's is a match (should use ability). /// </summary> /// /// <param name="poa">The plan of attack.</param> /// <param name="tile">The tile to check.</param> /// /// <returns>True if the ability target's is a match , False otherwise.</returns> private bool IsAbilityTargetMatch(PlanOfAttack poa, Tile tile) { bool isMatch = false; // If the target is a Tile, it's automatically a match. if (poa.target == Targets.Tile) { isMatch = true; } // If the target is a Unit (Ally, Foe, Self), use the unit's alliance // to determine if it's a match. else if (poa.target != Targets.None) { Alliance other = tile.content.GetComponentInChildren <Alliance>(); if (other != null && alliance.IsMatch(other, poa.target)) { isMatch = true; } } return(isMatch); }
void PlanDirectionIndependent(PlanOfAttack poa) { Tile startTile = actor.tile; Dictionary <Tile, AttackOption> map = new Dictionary <Tile, AttackOption>(); AbilityRange ar = poa.ability.GetComponent <AbilityRange>(); List <Tile> moveOptions = GetMoveOptions(); for (int i = 0; i < moveOptions.Count; ++i) { Tile moveTile = moveOptions[i]; actor.Place(moveTile); List <Tile> fireOptions = ar.GetTilesInRange(bc.board); for (int j = 0; j < fireOptions.Count; ++j) { Tile fireTile = fireOptions[j]; AttackOption ao = null; if (map.ContainsKey(fireTile)) { ao = map[fireTile]; } else { ao = new AttackOption(); map[fireTile] = ao; ao.target = fireTile; ao.direction = actor.dir; RateFireLocation(poa, ao); } ao.AddMoveTarget(moveTile); } } actor.Place(startTile); List <AttackOption> list = new List <AttackOption>(map.Values); PickBestOption(poa, list); }
public PlanOfAttack Evaluate() { // create and fill out a plan of attack PlanOfAttack poa = new PlanOfAttack(); // step 1: what ability to use AttackPattern pattern = actor.GetComponentInChildren <AttackPattern>(); if (pattern) { pattern.Pick(poa); } else { DefaultAttackPattern(poa); } // step 2: where to move and aim to best use if (IsPositionIndependent(poa)) { PlanPositionIndependent(poa); } else if (IsDirectionIndependent(poa)) { PlanDirectionIndependent(poa); } else { PlanDirectionDependent(poa); } if (poa.ability == null) { MoveTowardOpponent(poa); } // return plan return(poa); }
// Create and fill out a plan of attack public PlanOfAttack Evaluate() { PlanOfAttack poa = new PlanOfAttack(); // Step 1: Decide what ability to use AttackPattern pattern = actor.GetComponentInChildren <AttackPattern>(); if (pattern) { pattern.Pick(poa); } else { DefaultAttackPattern(poa); } // Step 2: Determine where to move and aim to best use the ability if (IsPositionIndependent(poa)) { PlanPositionIndependent(poa); } else if (IsDirectionIndependent(poa)) { PlanDirectionIndependent(poa); } else { PlanDirectionDependent(poa); } if (poa.ability == null) { MoveTowardOpponent(poa); } // Return the completed plan return(poa); }
public PlanOfAttack Evaluate() { var poa = new PlanOfAttack(); AttackPattern pattern = actor.GetComponentInChildren <AttackPattern>(); if (pattern) { pattern.Pick(poa); } else { // TODO: Remove default pattern and throw instead? DefaultAttackPattern(poa); } if (IsPositionIndependent(poa)) { PlanPositionIndependent(poa); } else if (IsDirectionIndependent(poa)) { PlanDirectionIndependent(poa); } else { PlanDirectionDependent(poa); } if (poa.ability == null) { // TODO: Flee if low HP. MoveTowardOpponent(poa); } return(poa); }
public abstract void Pick(PlanOfAttack plan);
/// <summary> /// Sets the default attack pattern on the plan of attack. /// /// @todo What if the the actor has no ability? /// </summary> /// /// <param name="poa">The plan of attack.</param> private void DefaultAttackPattern(PlanOfAttack poa) { poa.ability = actor.GetComponentInChildren <Ability>(); poa.target = Targets.Foe; }
/// <summary> /// Determines if the plan of attack's ability is direction independent. /// </summary> /// /// <param name="poa">The plan of attack.</param> /// /// <returns>True if the ability is direction independent, False otherwise.</returns> private bool IsDirectionIndependent(PlanOfAttack poa) { var range = poa.ability.GetComponent <AbilityRange>(); return(!range.directionOriented); }