public bool Move(Cell cell, ISimplePathFinder pathFinder = null, int minDistance = 0, bool cautious = false, bool cancelMove = true) { if (cell == null) { throw new ArgumentNullException("cell"); } if (!CanMove()) { return(false); } if (pathFinder == null) { pathFinder = new BiM.Behaviors.Game.World.Pathfinding.FFPathFinding.PathFinder(Map, false); } Path path = null; if (pathFinder is IAdvancedPathFinder) { path = (pathFinder as IAdvancedPathFinder).FindPath(Cell, cell, true, -1, minDistance, cautious); } else { path = pathFinder.FindPath(Cell, cell, true, -1); } return(Move(path, cell)); }
public bool ChangeMap(MapNeighbour neighbour, Predicate<CellInfo> cellSelector) { try { m_nextMap = null; PathFinder pathFinder = new PathFinder(Map, false); // Select a random cell in the set of all reachable cells that allow map change in the right direction. Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0 && cellSelector(cell)).GetRandom(); if (destCell == null) return false; neighbour = Map.GetDirectionOfTransitionCell(destCell); if (neighbour == MapNeighbour.None) return false; if (Move(destCell, pathFinder, 0, true)) { m_nextMap = GetNeighbourId(neighbour); m_previousMap = Map.Id; return true; } return false; } finally { if (m_nextMap == null) SendMessage(String.Format("Can't find any linked map from {0}", this), Color.Red); else SendMessage(String.Format("Moving at the {2} of map {0} to map {1}", this, m_nextMap, neighbour), Color.Pink); } }
public MapNeighbour ChangeMap(MapNeighbour neighbour = MapNeighbour.Any) { m_nextMap = null; PathFinder pathFinder = new PathFinder(Map, false); // Select a random cell in the set of all reachable cells that allow map change in the right direction. Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0).GetRandom(); if (destCell == null) return MapNeighbour.None; neighbour = Map.GetDirectionOfTransitionCell(destCell); if (neighbour == MapNeighbour.None) { SendMessage(String.Format("Can't find any linked map from {0}", this), Color.Red); return MapNeighbour.None; } if (destCell.Id != Cell.Id) { if (Move(destCell, pathFinder, 0, true)) { m_nextMap = GetNeighbourId(neighbour); SendMessage(String.Format("Moving at the {2} of map {0} to map {1}", this, m_nextMap, neighbour), Color.Pink); return neighbour; } else return MapNeighbour.None; } else { Bot.AddMessage(() => Bot.SendToServer(new ChangeMapMessage(GetNeighbourId(neighbour)))); m_previousMap = Map.Id; SendMessage(String.Format("Moving at the {2} of map {0} to map {1} (direct)", this, m_nextMap, neighbour), Color.Pink); } return neighbour; }
private void InternalChangeMap() { _changingMap = true; if (IsFighting()) { SendWarning("InternalChangeMap : I'm fighting => stop it !"); _changingMap = false; return; } if (_srcLeaderMap != Map.Id) { SendWarning("I'm not on the proper map to follow leader on the next map"); _changingMap = false; return; } if (_pivotLeaderCell != Cell.Id) { PathFinder pathFinder = new PathFinder(Map, false); if (!Move(_pivotLeaderCell, pathFinder, 0, true)) { if (_nbTryLeft > 0) { SendWarning("InternalChangeMap : Can't join the leader yet, try later"); _nbTryLeft--; Bot.CallDelayed(6000, InternalChangeMap); } else if (_nbTryLeft > -6) { MapNeighbour neighbour = Map.GetDirectionOfTransitionCell(Map.Cells[_pivotLeaderCell]); Cell destCell = pathFinder.FindConnectedCells(Cell, false, true, cell => (cell.Cell.MapChangeData & Map.MapChangeDatas[neighbour]) != 0).GetRandom(); if (destCell == null) SendWarning("InternalChangeMap : Can't join the leader, no try left. Can't even find any alternate path to go {0}", neighbour); else { SendWarning("InternalChangeMap : Can't join the leader, no try left. Trying alternative path to go {0} : cell {1}", neighbour, destCell); _pivotLeaderCell = destCell.Id; } _nbTryLeft--; Bot.CallDelayed(2000, InternalChangeMap); } else { SendError("InternalChangeMap : Can't find any path to join the leader. Trying again later. "); _changingMap = false; } return; } SendWarning("InternalChangeMap : Move from {0} to {1} succeeded. When move is complete, should go from map {2} to map {3}. ", Cell, Map.Cells[_pivotLeaderCell], Map.ToString(), new Map(_dstLeaderMap)); _changingMap = false; m_nextMap = _dstLeaderMap; return; } SendError("I'm already on the good Cell, just try to jump to the other map."); Bot.CallDelayed(400, () => Bot.AddMessage(() => Bot.SendToServer(new ChangeMapMessage(_dstLeaderMap)))); m_previousMap = Map.Id; _changingMap = false; return; }
public bool Move(Cell cell, ISimplePathFinder pathFinder = null, int minDistance = 0, bool cautious = false, bool cancelMove = true) { if (cell == null) throw new ArgumentNullException("cell"); if (!CanMove()) return false; if (pathFinder == null) pathFinder = new BiM.Behaviors.Game.World.Pathfinding.FFPathFinding.PathFinder(Map, false); Path path = null; if (pathFinder is IAdvancedPathFinder) path = (pathFinder as IAdvancedPathFinder).FindPath(Cell, cell, true, -1, minDistance, cautious); else path = pathFinder.FindPath(Cell, cell, true, -1); return Move(path, cell); }
/// <summary> /// Gives walkable cells where the character may walk within the turn. /// Note : it's now supposed to be reliable, using PathFinder /// </summary> /// <returns></returns> public IEnumerable<Cell> GetPossibleMoves(bool cautious, bool ForceIncludeStartingCell = true, PathFinder pathFinder = null) { if (pathFinder == null) pathFinder = new PathFinder(Fight, true); List<Cell> cells = pathFinder.FindConnectedCells( Cell, true, cautious, cell => cell.DistanceSteps <= Stats.CurrentMP, null, Stats.CurrentMP).ToList(); if (ForceIncludeStartingCell && !cells.Contains(Cell)) cells.Add(Cell); return cells; }
public SpellTarget FindBestUsage(PlayedFighter pc, Spell.SpellCategory category, bool withWeapon, IEnumerable<Cell> possiblePlacement = null) { SpellTarget spellTarget = new SpellTarget(); if (pc.PCStats.CurrentAP <= 0) return spellTarget; Stopwatch timer = new Stopwatch(); timer.Start(); PathFinder pathFinder = new PathFinder(pc.Fight, true); IEnumerable<Cell> sourceCells = possiblePlacement == null ? pc.GetPossibleMoves(true, true, pathFinder) : possiblePlacement; IEnumerable<Fighter> actorsWithoutPC = pc.Fight.AliveActors.Where(actor => actor != pc); List<Spell> spells = m_spells.ToList(); if (withWeapon && ((category & (Spell.SpellCategory.Damages | Spell.SpellCategory.Healing)) != 0)) spells.Add(WeaponSpellLike()); //logger.Debug("***FindBestUsage {0}, {1} spells in book. {2} PA. {3}/{4} HP ***", category, spells.Count, pc.PCStats.CurrentAP, pc.PCStats.Health, pc.PCStats.MaxHealth); Object thisLock = new Object(); //foreach(Spell spell in spells) int NbSpellsChecked = 0; Parallel.ForEach(spells, spell => { NbSpellsChecked++; if (spell != null && !IgnoredSpells.Contains(spell.Template.id)) { int spellId = spell.Template.id; if (spell.IsAvailable(null) && ((spellId != 0 && pc.CanCastSpells) || (spellId == 0 && pc.CanFight)) && spell.LevelTemplate.apCost <= pc.Stats.CurrentAP && pc.CanCastSpell(spellId)) { if ((spell.Categories & category) > 0) { SpellTarget lastSpellTarget = spell.FindBestTarget(pc, sourceCells, actorsWithoutPC, category); if (lastSpellTarget != null && lastSpellTarget.Efficiency > spellTarget.Efficiency) //lock (thisLock) spellTarget = lastSpellTarget; //if (lastSpellTarget != null) // logger.Debug("efficiency {0} = {1} ({2})", lastSpellTarget.Spell, lastSpellTarget.Efficiency, lastSpellTarget.Comment); //lock (thisLock) // logger.Debug("efficiency {0} = ???", spell); // else //lock (thisLock) // logger.Debug("efficiency {0} = {1} ({2})", lastSpellTarget.Spell, lastSpellTarget.Efficiency, lastSpellTarget.Comment); } } else { // lock (thisLock) // logger.Info("{0} skipped : available={1} ({6}), canUse={2}, ApCost={3}, CanCast({4})={5}", spell, spell.IsAvailable(null), ((spellId != 0 && pc.CanCastSpells) || (spellId == 0 && pc.CanFight)), spell.LevelTemplate.apCost <= pc.Stats.CurrentAP, spellId, pc.CanCastSpell(spellId), spell.AvailabilityExplainString(null)); } } } ); //Debug.Assert(NbSpellsChecked == spells.Count); timer.Stop(); spellTarget.TimeSpan = timer.Elapsed; //pc.Character.SendInformation("Spell {0} selected - efficientcy : {1} - comment = {2}", spellTarget.Spell, spellTarget.Efficiency, spellTarget.Comment); return spellTarget; }
/*public bool IsProperTarget(PlayedFighter caster, Fighter target, Spell spell) { // SpellTargetType if (target == null) return spell.LevelTemplate.needFreeCell && spell.IsAvailable(null, null); foreach (var spellEffect in spell.GetEffects()) if (EffectBase.canAffectTarget(spellEffect, spell, caster, target)) return true; return false; }*/ #endregion Availability management #region Spell selection /*public IEnumerable<Spell> GetOrderListOfSimpleBoostSpells(PlayedFighter caster, Fighter target, Spell.SpellCategory category) { return m_spells.Where(spell => (caster.Stats.CurrentAP >= spell.LevelTemplate.apCost) && spell.IsAvailable(caster.Id, category) && IsProperTarget(caster, target, spell)).OrderByDescending(spell => spell.Level).ThenByDescending(spell => spell.LevelTemplate.minPlayerLevel); } public IEnumerable<Spell> GetOrderedAttackSpells(PlayedFighter caster, Fighter target, Spell.SpellCategory category = Spell.SpellCategory.Damages) { Debug.Assert(((category & Spell.SpellCategory.Damages) > 0), "category do not include Damage effects"); return m_spells.Where(spell => (caster.Stats.CurrentAP >= spell.LevelTemplate.apCost) && spell.IsAvailable(target.Id, category) && IsProperTarget(caster, target, spell)) .OrderByDescending(spell => (int)(spell.GetSpellDamages(caster, target, Spell.SpellCategory.Damages).Damage) * (caster.Stats.CurrentAP / (int)spell.LevelTemplate.apCost)); }*/ public SpellTarget FindBestUsage(PlayedFighter pc, List<int> spellIds, IEnumerable<Cell> possiblePlacement = null) { Stopwatch timer = new Stopwatch(); timer.Start(); PathFinder pathFinder = new PathFinder(pc.Fight, true); IEnumerable<Cell> sourceCells = possiblePlacement == null ? pc.GetPossibleMoves(true, true, pathFinder) : possiblePlacement; IEnumerable<Fighter> actorsWithoutPC = pc.Fight.AliveActors.Where(actor => actor != pc); SpellTarget spellTarget = new SpellTarget(); foreach (int spellId in spellIds) { Spell spell = m_spells.FirstOrDefault(sp => sp.Template.id == spellId); if (spell == null && spellId == 0) spell = WeaponSpellLike(); if (spell != null) { if (spell.IsAvailable(null) && ((spellId != 0 && pc.CanCastSpells) || (spellId == 0 && pc.CanFight)) && spell.LevelTemplate.apCost <= pc.Stats.CurrentAP && pc.CanCastSpell(spellId)) if (spell != null && spell.IsAvailable(null) && spell.LevelTemplate.apCost <= pc.Stats.CurrentAP) { SpellTarget lastSpellTarget = spell.FindBestTarget(pc, sourceCells, actorsWithoutPC, Spell.SpellCategory.All); if (lastSpellTarget != null && lastSpellTarget.Efficiency > spellTarget.Efficiency) { spellTarget = lastSpellTarget; break; // Stop on the first spell with positive efficiency } } } } timer.Stop(); spellTarget.TimeSpan = timer.Elapsed; return spellTarget; }