Ce dépôt a été archivé le 2020-03-15. Vous pouvez voir ses fichiers ou le cloner, mais pas ouvrir de ticket ou de demandes d'ajout, ni soumettre de changements.
Routing.Route=Route-- Make it available as a member
-- This should pass on all routes. If it does not, *things need to be fixed*. No, commenting tests out is not an adequate response - this *must* pass. Eventually this will get rolled into the unsucky Route class.
localsanityfixed=nil-- If we've done something to improve the sanity of the overall path, i.e. force the path into a situation where it's no longer trying to turn in quests before the quest has been completed, then we definitely want to accept this path overall. Before, this wasn't a problem, since this function was so unstable that it would randomly change the path anyway, and it doesn't *break* things once they're fixed. Now that we have a check that this function actually *improves* the path, we need a slightly more complicated definition of "improve". Ideally, that shouldn't be necessary, but for now it is (until, at least, this function actually puts things in the best location, and that will have to wait until the get-optimal-path functions actually get optimal paths.)
localbest_index,best_delta,best_d1,best_d2,best_p
localno_cache,prev_pos,prev_len
localmn,mx=self:findObjectiveRange(obj)
ifold_indexandmn<=old_indexandold_index<=mxthen
-- We're trying to re-evaluate it, and it could remain in the same place.
-- So that place is our starting best known place.
-- if we didn't have an old index, or our old index was out of bounds and our best index is in bounds, then we've done something Majorly Good and we should be using this path even if the old one was faster
-- Record info for the 'Player Position' objective, so we don't mess it up later
seen[self[0].obj]=self[0].pos
-- Record the objective that we chose to put first
localobj=info.obj
indexes[obj]=1
seen[obj]=info.pos-- Save its position, because we don't want to clobber any of the info objects yet
prev_pos=info.pos
last=links[obj]
links[obj]=nil
-- Scan the rest of the places in the route, and pick objectives to go there
forindex=2,lendo
info=nil
localc=1
-- Scan the list of scores from the prior objective
fori,weightinpairs(last)do
iflinks[i.obj]then
-- Only consider an item if we have scores for that item
localw
localpos=i.pos
ifprev_pos[1].c==pos[1].cthen
localu,v=prev_pos[3]-pos[3],prev_pos[4]-pos[4]
w=math.sqrt(u*u+v*v)
else
w=500
end
w=weight*math.random()/w
ifnotinfoorw>rthen
info,r=i,w
end
end
c=c+1
end
-- In case we had no valid scores, scan the remaining objectives and score by distance
ifnotinfothen
forobjinpairs(links)do
localpos=obj.pos
localw
ifprev_pos[1]==pos[1]then
-- Same zone
localu,v=prev_pos[3]-pos[3],prev_pos[4]-pos[4]
w=math.sqrt(u*u+v*v)
elseifprev_pos[1].c==pos[1].cthen
-- Same continent. -- Assume twices as long.
localu,v=prev_pos[3]-pos[3],prev_pos[4]-pos[4]
w=2*math.sqrt(u*u+v*v)
else
-- Different continent. Assume fixed value of 5 minutes.
w=300
end
w=math.random()/w
ifnotinfoorw>rthen
localroute=next(route_map)
info,r=route[route.index[obj]],w
end
end
--[[ assert(info) ]]
end
-- Add the selected item to the route
obj=info.obj
indexes[obj]=index
prev_pos=info.pos
seen[obj]=prev_pos
--[[ assert(info.obj == obj) ]]
-- Get the scores table for this objective, clear it out, discard the scores from the prior objective, and save these scores for next time around
locallink=links[obj]
links[obj]=nil
QuestHelper:ReleaseTable(last)
last=link
QH_Timeslice_Yield()
end
-- Clean up the last table
QuestHelper:ReleaseTable(last)
-- Now that we've got our objectives lined up, fill in the info objects with the positions we saved
forobj,iinpairs(indexes)do
--[[ assert(seen[obj]) ]]
localinfo=self[i]
info.obj,info.pos=obj,seen[obj]
seen[obj]=nil
end
-- Now randomly randomize some of the route (aka mutation)
whilemath.random()>0.3do
locall=math.floor(math.random()^1.6*(len-1))+1
locali=math.random(1,len-l)
localj=i+l
-- Reverse a chunk of the route
fork=0,j-i-1do
self[i+k],self[j-k]=self[j-k],self[i+k]
end
end
-- But wait, after all that some objectives might violate the rules. Make sure the route follows
-- the rules.
-- There's some horrifying ugly here. The "before" and "after" links are not properly updated simultaneously. This means that X can be flagged as after Y without Y being flagged as before X. Making things worse (because, oh man, things had to be made worse!) this means that X might have a lower priority than Y despite needing to happen before it. Urgh.
-- Since the entire thing is internally inconsistent anyway, we're just gonna try to consistentize it.
localvalid_items={}
fork,vinipairs(self)do
valid_items[v.obj]=true
end
fork,vinipairs(self)do
forbinpairs(v.obj.before)do
ifvalid_items[b]then
b.after[v.obj]=true
end
end
forainpairs(v.obj.after)do
ifvalid_items[a]then
a.before[v.obj]=true
end
end
end
-- Because priorities might have been changed in here, we next make absolutely sure we have up-to-date priorities.
fork,vinipairs(self)do
CalcObjectivePriority(v.obj)
end
-- Have I mentioned I hate this codebase yet?
-- Because I do.
-- Just, you know.
-- FYI.
localinvalid=true
localinvalid_passes=0
--local output_strings = {}
whileinvaliddo
invalid_passes=invalid_passes+1
--[[if invalid_passes >= 100 then
fork,vinpairs(output_strings)do
QuestHelper:TextOut(v)
end
end]]
ifinvalid_passes>=100then
-- ugh
QuestHelper.mutation_passes_exceeded=true
break
end
QuestHelper:Assert(invalid_passes<=100,"Too many mutation passes needed to preserve sanity, something has gone Horribly Wrong, please report this as a bug (you will probably need to restart WoW for QH to continue working, sorry about that)")-- space is so it works in the real code
-- Objective was probably made to depend on an objective that we don't know about yet.
-- We add it to both lists, because although we need to remove it, we need it added again when we can.
-- This creates an inconsistancy, but it'll get fixed in the removal loop before anything has a chance to
-- explode from it.
to_remove[o]=true
to_add[o]=true
else
ifo.swap_beforethen
qh:ReleaseTable(o.before)
o.before=o.swap_before
o.swap_before=nil
end
ifo.swap_afterthen
qh:ReleaseTable(o.after)
o.after=o.swap_after
o.swap_after=nil
end
ifo.is_sharing~=o.want_sharethen
o.is_sharing=o.want_share
ifo.want_sharethen
qh:DoShareObjective(o)
else
qh:DoUnshareObjective(o)
end
end
CalcObjectivePriority(o)
-- Make sure the objective in best_route is still in a valid position.
-- Won't worry about other routes, they should forced into valid configurations by breeding.
-- This is a temporary, horrible hack - we want to do a "best" test without actually clobbering our old route, so we're making a new temporary one to jam our route in for now. In theory, AddObjectiveBest should, I don't know, add it in the *best place*, but at the moment it does not necessarily, thus this nastiness.
localaobt={}
setmetatable(aobt,getmetatable(best_route))
fork,vinpairs(best_route)do
aobt[k]=v
end
aobt.index={}
fork,vinipairs(best_route)do
-- arglbargl
aobt[k]=QuestHelper:CreateTable("AOBT idiocy")
fort,qinpairs(v)do
aobt[k][t]=q
end
aobt.index[aobt[k].obj]=k
end
ifaobt[0]then
aobt[0]=QuestHelper:CreateTable("AOBT idiocy")
fort,qinpairs(best_route[0])do
aobt[0][t]=q
end
end
-- Actually duplicating a route is irritatingly hard (this is another thing which will be fixed eventually dammit)
localnew_real_distance=(best_route.distanceor0)+(best_route[1]andqh:ComputeTravelTime(pos,best_route[1].pos)or0)-- part of hack
-- not sure if best_route.distance can ever be nil or not, I was just getting errors I couldn't find for a while and ended up with that test included when I fixed the real error
ifnew_real_distance<old_real_distanceorsanityfixedthen-- More of the temporary hack
-- this chunk of code used to live up by old_index ~= new_index, but it obviously no longer does. should probably be moved back once Best works again
-- Maybe the bug he's referring to is the one I'm fighting with in this chunk of code? Hey dude, if you find a bug, *fix the damn bug don't work around it*
--if old_index == new_index then
-- We don't advance recheck_position unless the node doesn't get moved.
-- TODO: As the this code is apparently bugged, it's gotten into an infinite loop of constantly swapping
-- and hence never advancing. As a work around for now, we'll always advance.