You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
5.7 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Mapper
{
public class PathFinder_VisitAll : Pathfinder
{
public PathFinder_VisitAll(Mapper mapper, params Room[] roomId)
: base()
{
map = mapper;
foreach(Room u in roomId)
{
if(!AllRooms.Contains(u))
AllRooms.Add(u);
}
if(_grid[0] == null)
{
for(int i = 0; i < _grid.Length; i++)
_grid[i] = new List<uint[]>(512);
}
for(int i = 0; i < _grid.Length; i++)
_grid[i].Clear();
}
private readonly Mapper map;
private readonly List<Room> AllRooms = new List<Room>();
private readonly Dictionary<uint, Dictionary<uint, uint>> Costs = new Dictionary<uint, Dictionary<uint, uint>>();
private static List<uint[]>[] _grid = new List<uint[]>[1024];
public override bool IsTargetRoom(Room r)
{
return true;
}
public override void OnStartedPathfind()
{
base.OnStartedPathfind();
foreach(Room x in StartRooms)
AllRooms.Remove(x);
}
public override void OnEndedPathFind(PathfindResult pr)
{
base.OnEndedPathFind(pr);
foreach(Room x in StartRooms)
AllRooms.Add(x);
foreach(Room u in AllRooms)
{
_Internal_PathFinder_VisitAll pf = new _Internal_PathFinder_VisitAll((from val in AllRooms where val != u select val).ToArray());
pf.CanUsePortals = CanUsePortals;
pf.CanUseRecalls = CanUseRecalls;
pf.CharacterLevel = CharacterLevel;
pf.CharacterTier = CharacterTier;
pf.IsGlobalQuest = IsGlobalQuest;
pf.IsSingleClassTier0 = IsSingleClassTier0;
pf.OverridePortals = OverridePortals;
pf.SkipExits = SkipExits;
pf.SkipPortals = SkipPortals;
pf.SkipRooms = SkipRooms;
pf.StartRooms = new[] { u };
PathfindResult p = map.Get(pf);
if(!p.Success)
{
pr.Success = false;
return;
}
Costs[u.Entry] = new Dictionary<uint, uint>();
foreach(Room x in AllRooms)
{
if(x == u)
continue;
if(x.Mapper_OpenBy != null)
Costs[u.Entry][x.Entry] = x.Mapper_OpenCost;
else
{
pr.Success = false;
return;
}
}
}
OpenRoom(new[] { StartRooms[0].Entry }, 0);
uint[] Finish = null;
int itr1 = 0, itr2 = 0;
while(itr1 < _grid.Length)
{
if(itr2 >= _grid[itr1].Count)
{
itr2 = 0;
_grid[itr1].Clear();
itr1++;
continue;
}
if(OpenRoom(_grid[itr1][itr2], (uint)itr1))
{
Finish = _grid[itr1][itr2];
break;
}
itr2++;
}
if(Finish == null)
pr.Success = false;
else
{
pr.Cost = itr1;
pr.Path.Clear();
pr.Target = map.GetRoom(Finish[Finish.Length - 1]);
Room u = map.GetRoom(Finish[0]);
int j = 1;
while(u != null && j < Finish.Length)
{
Pathfinder_Entry pf = new Pathfinder_Entry(Finish[j]);
pf.StartRooms = new[] { u };
pf.CanUsePortals = CanUsePortals;
pf.CanUseRecalls = CanUseRecalls;
pf.CharacterLevel = CharacterLevel;
pf.CharacterTier = CharacterTier;
pf.IsGlobalQuest = IsGlobalQuest;
pf.IsSingleClassTier0 = IsSingleClassTier0;
pf.OverridePortals = OverridePortals;
pf.SkipExits = SkipExits;
pf.SkipPortals = SkipPortals;
pf.SkipRooms = SkipRooms;
PathfindResult p = map.Get(pf);
if(!p.Success)
{
pr.Success = false;
return;
}
pr.Path.AddRange(p.Path);
u = map.GetRoom(Finish[j]);
j++;
}
}
}
private bool OpenRoom(uint[] r, uint cost)
{
if(r.Length == AllRooms.Count)
return true;
foreach(KeyValuePair<uint, uint> x in Costs[r[r.Length - 1]])
{
if(r.Contains(x.Key))
continue;
uint[] z = r.Concat(new[] { x.Key }).ToArray();
uint c = cost + x.Value;
if(c < _grid.Length)
_grid[(int)c].Add(z);
}
return false;
}
}
public class _Internal_PathFinder_VisitAll : Pathfinder
{
public _Internal_PathFinder_VisitAll(params Room[] roomId)
{
AllRooms.AddRange(roomId);
}
private readonly List<Room> AllRooms = new List<Room>();
public override bool IsTargetRoom(Room r)
{
AllRooms.Remove(r);
return AllRooms.Count == 0;
}
}
}