· 6 years ago · Nov 11, 2019, 12:00 AM
1-- Author: Xoandbit
2--
3-- Read data from file
4-- Saved data in file must be in textutils.serialize
5function readData(file)
6 if (fs.exists(file) == false) then
7 return nil
8 end
9
10 local f=fs.open(file, "r")
11 local s=f.readAll()
12 f.close()
13 return textutils.unserialize(s)
14end
15
16-- Save data in file
17function writeData(file, data)
18 if (fs.exists(file)) then
19 fs.delete(file)
20 end
21
22 local f=fs.open(file, "w")
23 f.write(textutils.serialize(data))
24 f.close()
25end
26
27-- Clear screen and draw border around it
28function Decorate(screen,border)
29 if (screen==nil) then
30 return
31 end
32 if (border==nil) then
33 border=" "
34 end
35
36 local w,h,i
37 w,h=screen.getSize()
38
39 screen.clear()
40
41 for i=1,w do
42 screen.setCursorPos(i,1);
43 screen.write(border)
44 screen.setCursorPos(i,h);
45 screen.write(border)
46 end
47
48 for i=1,h do
49 screen.setCursorPos(1,i)
50 screen.write(border);
51 screen.setCursorPos(w,i)
52 screen.write(border);
53 end
54end
55
56
57-- Write text at specific cordinates on screen
58-- clearLine - clear all line
59-- hidden - replaces characters with "*"
60function WriteText(screen,x,y,text,clearLine,hidden)
61 if (text==nil) then
62 text=""
63 end
64
65 if (screen==nil) then
66 screen=term
67 end
68
69 screen.setCursorPos(x,y)
70 if (clearLine==true) then
71 screen.clearLine()
72 end
73
74 cnt = string.len(text)
75
76 if (hidden==true) then
77 for i=1,cnt do
78 screen.write("*")
79 end
80 else
81 for i=1,cnt do
82 screen.write(string.sub(text,i,i))
83 end
84 end
85
86end
87
88-- Write multiple values on screen from data table
89-- example data definition data={a,b,c,d}
90function WriteInLine(screen, x,y, data)
91 screen.setCursorPos(x,y)
92 if (data==nil) then return 0 end
93 for i=1,#data do
94 screen.write(data[i])
95 screen.write(" ")
96 end
97end
98
99-- Read user input, opens new screen on top of parent screen
100-- number - if user need to input integer
101-- password - user input in screen output is replaced with "*"
102function ReadUserInput(parentscreen, question, number, password, x, y, x2, y2)
103 if (parentscreen==nil) then
104 parentscreen=term.current();
105 end
106
107 if (number==nil) then
108 number=false
109 end
110
111 if (password==nil) then
112 password=false
113 end
114
115 if (y2==nil) then
116 x,y=3,3
117 x2,y2=parentscreen.getSize()
118 x2,y2= x2 -5, y + 7
119
120 end
121
122 local screen, ev, text, txtlen, cursorpos
123 screen=window.create(parentscreen, x, y, x2-x+1, y2-y+1, true)
124
125 ev={}
126 text=""
127 txtlen=0
128 cursorpos=1
129 term.setCursorBlink(true)
130
131 while (true) do
132
133 if (ev[1]=="char") and (number~=true or tonumber(ev[2])~=nil) then
134 if (cursorpos>txtlen) then
135 text=text..ev[2]
136 cursorpos=cursorpos+1
137 txtlen = txtlen + 1
138 else
139
140 tmp=string.sub(text,1,cursorpos-1)..ev[2]..string.sub(text,cursorpos)
141 text=tmp;
142 cursorpos=cursorpos+1
143 txtlen = txtlen + 1
144 end
145
146
147 elseif (ev[1]=="key") then
148 if (ev[2]==keys.left)then
149 cursorpos=math.max(1,cursorpos-1)
150
151 elseif (ev[2]==keys.right) then
152 cursorpos=math.min(txtlen+1,cursorpos+1)
153
154 elseif (ev[2]==28) then -- 28 ENTER key
155 break; -- return text
156 elseif (ev[2]==14 and cursorpos>1) then --backspace
157
158 tmp=string.sub(text,1,cursorpos-2)
159
160 if (tmp==nil)then
161 tmp=""
162 end
163
164 text=string.sub(text,cursorpos)
165 if (text==nil) then
166 text=""
167 end
168
169 text=tmp .. text
170 txtlen=txtlen-1
171
172 cursorpos=math.max(1,cursorpos-1)
173 end
174 end
175
176 Decorate(screen, "#")
177 WriteText(screen,3,3,question,false)
178 WriteText(screen,5,5,text,false,password)
179 screen.setCursorPos(5+cursorpos-1,5)
180
181 ev = {os.pullEventRaw()}
182
183 end
184
185
186 screen.setCursorBlink(false)
187 if (number) then
188 return tonumber(text)
189 end
190
191 return text;
192end
193
194
195
196
197-- os.pullEvent loger
198-- Writes log to screen
199function DisplayEvents(parentscreen)
200 if (parentscreen==nil) then
201 parentscreen=term.current()
202 end
203
204 local w,h,screen, data, ev, tmp
205
206 w,h=parentscreen.getSize()
207 screen=window.create(parentscreen,1,1,w,h)
208
209 data = readData("event.log")
210 if (data==nil) then
211 data = {}
212 end
213
214 ev={}
215
216 while (true) do
217 local message=""
218 i=1
219 while (ev[i]~=nil) do
220
221 message= message.." "..tostring(ev[i])
222 i=i+1
223 end
224
225 local w,h=screen.getSize()
226
227 table.insert(data, 1, message)
228 table.remove(data, h+1)
229 Decorate(screen);
230 for i=1,h do
231 WriteText(screen,1,i,data[i],true)
232 end
233
234 writeData("event.log", data)
235
236 ev = {os.pullEventRaw()}
237 end
238end
239
240-- Return value of table - data[x] | data[x][y] etc
241function Tget(data,x,y,z,f)
242
243 if (x==nil) or (data==nil) then
244 return data
245 else
246 if (data[x]==nil) then
247 return nil
248 else
249 return Tget(data[x],y,z,f)
250 end
251 end
252end
253
254-- Set value to table - data[x]=value | data[x][y]=value etc
255function Tset(data,value,x,y,z,f)
256
257 if (x==nil) then
258 return value
259 else
260 if (data==nil) then
261 data={}
262 end
263 if (data[x]==nil) then
264 data[x]={}
265 end
266
267 data[x]= Tset(data[x], value, y, z, f)
268 return data
269 end
270end
271
272-- Move turtle forward
273function tforward()
274 if (turtle.forward()) then
275 if (robot["f"]==0) then robot["z"]=robot["z"]+1
276 elseif (robot["f"]==1) then robot["x"]=robot["x"]-1
277 elseif (robot["f"]==2) then robot["z"]=robot["z"]-1
278 elseif (robot["f"]==3) then robot["x"]=robot["x"]+1
279 end
280
281 robot["o"]=true
282 writeData("robot.log",robot)
283 return true
284 else
285 robot["o"]=false
286 return false
287 end
288end
289
290-- Move turtle back
291function tback()
292 if (turtle.back()) then
293 if (robot["f"]==0) then robot["z"]=robot["z"]-1
294 elseif (robot["f"]==1) then robot["x"]=robot["x"]+1
295 elseif (robot["f"]==2) then robot["z"]=robot["z"]+1
296 elseif (robot["f"]==3) then robot["x"]=robot["x"]-1
297 end
298
299 robot["o"]=true
300 writeData("robot.log",robot)
301 return true
302 else
303 robot["o"]=false
304 return false
305 end
306end
307
308-- Move turtle up
309function tup()
310 if (turtle.up()) then
311 robot["y"]=robot["y"]+1
312
313 robot["o"]=true
314 writeData("robot.log",robot)
315 return true
316 else
317 robot["o"]=false
318 return false
319 end
320end
321
322--Move turtle down
323function tdown()
324 if (turtle.down()) then
325 robot["y"]=robot["y"]-1
326 robot["o"]=true
327 writeData("robot.log",robot)
328 return true
329 else
330 robot["o"]=false
331 return false
332 end
333end
334
335--Turn turtle anti-clockwise
336function tturnLeft()
337 if (turtle.turnLeft()) then
338 robot["f"]=robot["f"]+4-1
339 while (robot["f"]>3) do
340 robot["f"]=robot["f"]-4
341 end
342
343 robot["o"]=true
344 writeData("robot.log",robot)
345 return true
346 else
347 robot["o"]=false
348 return false
349 end
350end
351
352--turn turtle clockwise
353function tturnRight()
354 if (turtle.turnRight()) then
355 robot["f"]=robot["f"]+4+1
356 while (robot["f"]>3) do
357 robot["f"]=robot["f"]-4
358 end
359
360 robot["o"]=true
361 writeData("robot.log",robot)
362 return true
363 else
364 robot["o"]=false
365 return false
366 end
367end
368
369-- turn turtle to specific direction f=[0;4]
370function tturn(direction)
371 if (direction<0 or direction>3) then
372 return true
373 end
374
375 local cf=robot.f
376 if (direction==cf) then
377 return true
378 end
379
380 r = direction + 4 - cf
381 while (r>3) do
382 r=r-4
383 end
384 l = cf + 4 - direction
385 while (l>3) do
386 l = l-4
387 end
388
389 if (r<l) then
390 while (robot.f~=direction) do
391 tturnRight()
392 end
393
394 else
395 while (robot.f~=direction) do
396 tturnLeft()
397 end
398 end
399
400 return true
401end
402
403-- Calculates cordinate of block next to turtle
404-- Possible direction - UP DOWN FORWARD RIGHT BACK LEFT
405function calculateBlockCordfromRobotCord(wdirection)
406 local cc = {
407 x=robot.x,
408 y=robot.y,
409 z=robot.z
410 }
411
412 tf=robot.f
413 if (tf==nil) then tf=0 end
414
415 if (wdirection=="UP") then tf=-4
416 elseif (wdirection=="DOWN") then tf=-5
417 elseif (wdirection=="FORWARD") then tf=tf+0
418 elseif (wdirection=="RIGHT") then tf=tf+1
419 elseif (wdirection=="BACK") then tf=tf+2
420 elseif (wdirection=="LEFT") then tf=tf+3 end
421
422
423 while (tf>3) do --tf=[0;3]
424 tf=tf-4
425 end
426
427 if (tf<0) then tf=-tf end -- for UP and DOWN
428
429
430 if (tf==0) then cc.z=cc.z+1
431 elseif (tf==1) then cc.x=cc.x-1
432 elseif (tf==2) then cc.z=cc.z-1
433 elseif (tf==3) then cc.x=cc.x+1
434 elseif (tf==4) then cc.y=cc.y+1
435 elseif (tf==5) then cc.y=cc.y-1 end
436
437 return cc
438end
439
440-- Move turtle to one possible direction
441-- UP DOWN FORWARD
442function _MOVE(movefunction,direction) -- direction UP DOWN FORWARD
443
444 local try, maxtry = 0, 5
445
446 while (true) do
447 try= try+1
448 local success, blockdataT , blockdata= nil, nil, nil
449 if (direction=="UP") then
450 success, blockdataT= turtle.inspectUp()
451 elseif (direction=="DOWN") then
452 success, blockdataT= turtle.inspectDown()
453 elseif (direction=="FORWARD") then
454 success, blockdataT= turtle.inspect()
455 else
456 print(" ERROR - _MOVE ")
457 exit()
458 end
459
460 if (success == false) then -- air - can move
461
462 if (movefunction()) then
463 return true
464 else
465 if (turtle.getFuelLevel()==0) then
466 turtle.select(16)
467 if (turtle.refuel(1)) then
468 print("REFUEL")
469 else
470 print("NO MORE FUEL AT SLOT 16")
471 end
472 end
473 -- if not try again
474 -- ???????????????
475 end
476 else
477
478 blockdata=blockdataT.name
479 -- 1. BlockLaunchTest
480 -- 2. TryToBreak
481 -- 3. TryToGoAroundIt
482 --
483 local continue, allowtobreak, returnval = true, false, nil
484 blockcord = calculateBlockCordfromRobotCord(direction)
485
486 -- Lets check if we have to call a function
487 if (BlockLaunchTest[blockdata]) then
488 print("Block launch test ",blockdata)
489 continue, allowtobreak, returnval=BlockLaunchTest[blockdata](blockcord)
490 if (returnval~=nil) then
491 return returnval
492 end
493 end
494
495 if (continue) then
496 if (AllowedToBreak[blockdata] or allowtobreak) then
497 print("BREAK BLOCK")
498 if (direction=="UP") then
499 turtle.digUp()
500 elseif (direction=="DOWN") then
501 turtle.digDown()
502 elseif (direction=="FORWARD") then
503 turtle.dig()
504 end
505 else -- Add to nonbreakable block list
506 print("Adding to NO BREAK")
507 if string.find(blockdata, "Turtle") then
508 addNonBreakableBlock(blockcord, 4)
509 else
510 addNonBreakableBlock(blockcord, NonBreakableBlockTimer)
511 end
512 return false
513 end
514 end
515 end
516
517 end
518
519 return false -- failed to move
520end
521
522-- Turtle execute a move array,,, array consists of integer
523-- [0;3] f 4 - up 5 - down
524function tmove(movelist)
525 while (robot.to.go and robot.to.calculated) do
526 sleep(0)
527 if (turtle.detect()==false) then
528 turtle.suck() -- Try to pick items from ground
529 end
530
531 if (turtle.detectDown()==false) then
532 turtle.suckDown() -- Try to pick items from ground
533 end
534
535 local try=0 -- How many times will try
536 local f=table.remove(movelist)
537 if (f==nil or f>5 or f<0) then
538 break
539 end
540 tturn(f)
541 if (f==4) then
542 if (_MOVE(tup,"UP")==false) then
543 return false
544 end
545 elseif (f==5) then
546 if (_MOVE(tdown,"DOWN")==false) then
547 return false
548 end
549 else
550 if (_MOVE(tforward,"FORWARD")==false) then
551 return false
552 end
553 end
554 end
555
556 return true
557
558end
559
560-- Compare if cordinates are equal
561function tcomparecord(a,b)
562 if (a.x==b.x and a.y==b.y and a.z==b.z) then
563 return true
564 else
565 return false
566 end
567end
568
569-- Add cordinate b to a, and checking a facing direction and expecting that
570-- Function rotates b cordinates to match with a direction
571function taddCord(a, b) -- a cordinates with face b normal cordinates
572 local aplusb = {}
573 aplusb.x=b.x
574 aplusb.y=b.y
575 aplusb.z=b.z
576 if (a.f==nil) then -- Maybe normal cordinate addition
577 a.f=0
578 end
579
580 local tf=a.f
581 while (tf>0) do -- ROTATE CORDINATES
582 local tmp = aplusb.x
583 aplusb.x = - aplusb.z
584 aplusb.z = tmp
585 tf=tf-1
586 end
587
588 aplusb.x=aplusb.x + a.x
589 aplusb.y=aplusb.y + a.y
590 aplusb.z=aplusb.z + a.z
591
592 return aplusb
593end
594
595-- Pytagorean distance between a and b cordinates
596function distance(a,b)
597 local x,y,z
598 x=a.x-b.x
599 y=a.y-b.y
600 z=a.z-b.z
601 return math.sqrt((x*x)+(y*y)+(z*z))
602end
603
604-- Manhetens distance between a and b cordinates
605function tdistance(a,b)
606 if (a==nil or b==nil) then
607 return 100000000 -- infinity
608 end
609 return (math.abs(a.x-b.x)+math.abs(a.y-b.y)+math.abs(a.z-b.z))
610end
611
612-- Moves turtle to target cordinates
613-- Target cordinates need to be set at robot.to
614-- Variable robot.to.go = true needs to be set
615-- When target is reached robot.to.go is set to false
616--
617-- This functions is written to run in parrallel api with the main program
618-- which sets (robot.to) in this api for robot to move
619function RobotMoveTo()
620 print("Robot move to listener started")
621 while (true) do
622 sleep(1)
623 if (robot==nil) then
624 robot={to={}}
625 elseif (robot.to==nil) then
626 robot.to={}
627 end
628
629 if (robot.to.go==true) then
630 print("Starting to move")
631 while (tcomparecord(robot,robot.to)==false and robot.to.go) do
632 local movelist=Apath(robot, robot.to, true)
633 robot.to.calculated=true
634 recalc=tmove(movelist)
635 if (recalc~=true or #movelist==0) then
636 sleep(3)
637 end
638 end
639 robot.to.go=false
640 -- FINISHED
641 end
642 end
643end
644
645-- Startuo function for turtle
646-- Ask user to input robot cordinates
647function RunRobot(parentscreen)
648 local robot = readData("robot.log")
649 if robot == nil then
650 robot = {}
651 end
652 robot.id=os.getComputerID()
653 robot.ID=robot.id
654 if (robot["installed"]==nil) then
655 if (parentscreen==nil) then
656 parentscreen=term.current()
657 end
658
659 local w,h=parentscreen.getSize()
660 local screen=window.create(parentscreen,3,2,w-2,h-2,true)
661 Decorate(screen)
662 robot["x"]=ReadUserInput(screen,"Turtle x position",true)
663 robot["y"]=ReadUserInput(screen,"Trutle y position",true)
664 robot["z"]=ReadUserInput(screen,"Turtle z position",true)
665 while (robot["f"]==nil) do
666 robot["f"]=ReadUserInput(screen,"Turtle direction f [0;3]",true)
667 if (robot["f"]<0 or robot["f"]>3) then
668 robot["f"]=nil;
669 end
670 end
671 robot["installed"]=true
672 robot.to={}
673 robot.to.go=false
674 robot.to.calculated=false
675 screen.setVisible(false)
676 end
677
678 writeData("robot.log", robot)
679 return robot
680end
681
682-- Add block what is allowed to break when robot is moving around
683function addAllowedToBreak(block)
684 AllowedToBreak[block]=true;
685end
686
687-- Remove allowed to break block
688function removeAllowedToBreak(block)
689 AllowedToBreak[block]=nil;
690end
691
692-- Add function to be runned when turtle path is blocked by a block
693-- For specific callFunction expected return variables check _MOVE function
694function addBlockTest(block,callFunction)
695 BlockLaunchTest[block]=callFunction
696end
697
698-- Remove in addBlockTest(block,callFunction) setted callFunction
699function removeBlockTest(block)
700 BlockLaunchTest[block]=nil
701end
702
703-- Function is called when turtle path is blocked by a block
704-- function saves block position for timeoutsec / A* pathfinding uses this
705-- cordinate to check if position is empty
706function addNonBreakableBlock(blockcord, timeoutsec)
707 local timer=nil
708 if (timeout~=nil) then
709 timer = os.startTimer(timeoutsec)
710 end
711 blockcord.timer=timer
712
713 table.insert(NonBreakableBlock,blockcord)
714end
715
716-- USE THIS IF using built in navigation functions
717-- Delete NonBreakableBlock after some time ( timeoutsec )
718function turtleUpdate()
719 -- Updating breakable block database - maybe turtle or tree ?
720 while (true) do
721 ev = { os.pullEventRaw() }
722 -- Check something
723 if (ev[1]=="timer")then
724 for i=1,#NonBreakableBlock do
725 if (NonBreakableBlock[i].timer==ev[2]) then
726 print("REMOVED NonBreakableBlock")
727 table.remove(NonBreakableBlock,i)
728 break
729 end
730 end
731 end
732 end
733end
734
735-- Setting api global variables
736--
737robot = {}
738if turtle then
739
740 AllowedToBreak = {}
741
742 NonBreakableBlockTimer = 30
743
744 NonBreakableBlock = {}
745 BlockLaunchTest = {}
746 --[[
747 {x,y,z,timer}
748 ]]--
749 turtle.select(1)
750end
751
752function initRobot(screen)
753 local k = next(robot)
754 while k do
755 robot[k] = nil
756 k = next(robot)
757 end
758 for k,v in pairs(RunRobot(screen)) do
759 robot[k] = v
760 end
761end
762
763-- COROUTINE CONTAINER - FOR SIMPLER EVENT FILTERING
764
765CoroutineControl = {}
766function CoroutineControl.new(self)
767 local new = {}
768 setmetatable(new, {__index = self})
769 new.idcnt=1 --Coroutine id cnter
770 new.coroutines={} -- coroutine list
771 new.run=true
772 return new
773end
774
775function CoroutineControl.addCoroutine(self,func,Arg)
776
777 local id=self.idcnt
778
779 self.idcnt = self.idcnt + 1
780
781 self.coroutines[id]={}
782 self.coroutines[id].funcID=func
783 self.coroutines[id].id=id
784 self.coroutines[id].run=true
785 self.coroutines[id].cID=coroutine.create(func)
786 if (Arg) then -- ADD ARG
787 self.coroutines[id].ok, self.coroutines[id].requestedEvent =
788 coroutine.resume(self.coroutines[id].cID, unpack( Arg ))
789 else
790 self.coroutines[id].ok, self.coroutines[id].requestedEvent =
791 coroutine.resume(self.coroutines[id].cID)
792 end
793 return id
794end
795
796function CoroutineControl.loop(self)
797 while (self.run) do
798 ev = {os.pullEventRaw()}
799 -- coroutine id and coroutines table
800 for id,coro in pairs(self.coroutines) do
801 if (coro.run) then
802 if (ev[1]==coro.requestedEvent or coro.requestedEvent==nil) then
803 coro.ok, coro.requestedEvent =
804 coroutine.resume(coro.cID,unpack( ev ))
805 end
806 end
807 end
808 end
809end
810
811
812-- PASTE CORDINATES
813function tpasteCord(from,to)
814 to.x=from.x
815 to.y=from.y
816 to.z=from.z
817end
818
819-- HEAP FUNCTIONS
820
821
822function pushHeap(heap,data)
823 if (heap==nil) then
824 heap={}
825 end
826 if (heap.cnt==nil or heap.cnt<0) then
827 heap.cnt=0
828 end
829
830 heap.cnt = heap.cnt+1
831 heap[heap.cnt]=data
832
833 local act=heap.cnt
834 while (math.floor(act/2)>=1) do
835 local div = math.floor(act/2)
836 if (heap[div].V>heap[act].V) then
837 local tmp=heap[div]
838 heap[div]=heap[act]
839 heap[act]=tmp
840 act=div
841 else
842 break
843 end
844 end
845end
846
847function popHeap(heap)
848 if (heap.cnt==nil or heap.cnt==0) then
849 return nil
850 else
851 local retval = heap[1]
852 heap[1]=heap[heap.cnt]
853 heap[heap.cnt]=nil
854 heap.cnt=heap.cnt-1
855
856 local act, lc, rc, ch
857 local act=1
858 while (act*2 <= heap.cnt) do
859 lc=act*2
860 rc=lc+1
861 if (rc<=heap.cnt and heap[rc].V<heap[lc].V) then
862 ch=rc
863 else
864 ch=lc
865 end
866
867 if (heap[ch].V<heap[act].V) then
868 local tmp=heap[ch]
869 heap[ch]=heap[act]
870 heap[act]=tmp
871 act=ch
872 else
873 break
874 end
875 end
876
877 return retval
878 end
879end
880
881-- A* pathfinding
882-- returns movelist (directions [0;5] 4 - UP 5 - DOWN)
883function Apath(from, to, vertical)
884
885 print(" A* recalculating ")
886
887 local directions = {
888 [ 0 ] = {x=0, z=1,y=0},
889 [ 1 ] = {x=-1, z=0,y=0},
890 [ 2 ] = {x=0, z=-1,y=0},
891 [ 3 ] = {x=1, z=0,y=0},
892 [ 4 ] = {x=0, z=0,y=1}, -- UP
893 [ 5 ] = {x=0, z=0,y=-1}, --DOWN
894 }
895
896 local searchingDistance=25
897 local heap,dist,cnt,elem,answ,answdist
898
899 answdist = 10000000
900
901 heap={}
902 heap.cnt=0
903 dist={}
904 cnt=0
905
906 elem={}
907 tpasteCord(from,elem)
908 elem.sD=0
909 elem.eD=tdistance(elem,to)
910 elem.V=elem.sD+elem.eD
911 Tset(dist,-1,elem.x,elem.y,elem.z)
912 pushHeap(heap,elem)
913
914 while (cnt<searchingDistance and heap.cnt>0) do
915
916 cnt = cnt + 1
917
918 local act, desc, continue
919 continue=true
920
921 act = popHeap(heap)
922
923 --CHECK IF CAN MOVE THROUGHT
924 for i=1,#NonBreakableBlock do
925 if (tcomparecord(NonBreakableBlock[i],act)) then
926 continue=false
927 cnt=cnt-1
928 break
929 end
930 end
931
932 if (continue==true) then --IF CAN MOVE THROUGHT THEN OK
933
934 local face = Tget(dist, act.x,act.y,act.z)
935 local distan = tdistance(act,to)
936 if (distan < answdist) then
937 answdist = distan
938 answ = {}
939 tpasteCord(act, answ)
940 if (answdist==0) then
941 break
942 end
943 end
944
945 for f=0,5 do
946 local actf={}
947 actf.x = act.x + directions[f].x
948 actf.y = act.y + directions[f].y
949 actf.z = act.z + directions[f].z
950
951 actf.sD = act.sD + 1
952 actf.eD = tdistance(actf,to)
953 actf.V=actf.eD + actf.sD
954
955 if (face~=f) then actf.V = actf.V+0.5 end
956
957 local parb = Tget(dist, actf.x, actf.y, actf.z)
958 if (parb==nil) then
959 pushHeap(heap,actf)
960 Tset(dist,f,actf.x,actf.y,actf.z)
961 end
962 end
963 end
964 end
965
966 heap=nil
967 local movelist={}
968 local f=Tget(dist,answ.x,answ.y,answ.z)
969 while (f~=-1) do
970 table.insert(movelist,f)
971 if (f==0) then answ.z = answ.z -1
972 elseif (f==1) then answ.x = answ.x +1
973 elseif (f==2) then answ.z = answ.z +1
974 elseif (f==3) then answ.x = answ.x -1
975 elseif (f==4) then answ.y = answ.y -1
976 elseif (f==5) then answ.y = answ.y +1
977 end
978 f = Tget(dist, answ.x,answ.y,answ.z)
979 end
980
981 return movelist
982end