Ниже приведен код по реализации Ходилки с обходом препятствий по алгоритму "Надежная трассировка" с соединенем алгорима "Трассировка вокруг препятствия".
Суть алгоритмов можно почерпнуть http://dev.dtf.ru/articles/read.php?id=46 внизу страницы.
Для алгорима необходим Стек. Вот он
Code: Select all
#(c)SerrouS
Sub InitStack()
UO.SetGlobal('STACK', '0')
endsub
Sub Push( param )
var chk = val(UO.GetGlobal('STACK')) ; количество элементов в стеке
UO.SetGlobal('STACK',str(chk + 1))
UO.SetGlobal('STACK_'+str(chk), param)
endsub
Sub Pop ()
var chk = val(UO.GetGlobal('STACK')) ; количество элементов в стеке
if chk then
UO.SetGlobal('STACK',str(chk - 1))
return UO.GetGlobal('STACK_'+str(chk - 1))
else
return ''
endif
endsub
Кто не знает что такое стек - ищет что-нить типа программирование для чайников и руками не лезет.
Кто знает и хочет его использовать у себя - иметь в виду стек существо капризное. Кто не верит - Assembler опять же для чайников, ищем и смотрим, что если похерить стек - то всему кранты.
Далее
Code: Select all
SUB GoToXY(x,y,prec)
#original (c) ...
#modification 2.00 (c) SerrouS
dim turn[8] ; индекс - ГетДир, значение поворот направо под 45 градусов
turn[0] = 39
turn[1] = 34
turn[2] = 40
turn[3] = 35
turn[4] = 37
turn[5] = 36
turn[6] = 38
turn[7] = 33
dim deltax[8]; индекс - аналогично, значение - изменение координаты при проходе стенки
dim deltay[8]
deltax[0] = 1
deltax[1] = 1
deltax[2] = 1
deltax[3] = 0
deltax[4] = -1
deltax[5] = -1
deltax[6] = -1
deltax[7] = 0
deltay[0] = -1
deltay[1] = 0
deltay[2] = 1
deltay[3] = 1
deltay[4] = 1
deltay[5] = 0
deltay[6] = -1
deltay[7] = -1
var dx,dy
var mx,my ; current coords
var lx = 0, ly = 0, ld = -1 ; last move coords
var pathFind = 0 ; as logical 0 - norm, 1 - block
var ind
var recursInd = 0
var fout = 0
var stepdelay = 1000
InitStack()
repeat
mx=UO.GetX()
my=UO.GetY()
; calculating for precision coming
dx = mx - x
If dx < 0 Then
dx = 0 - dx
EndIf ;get ABS diff
dy = my - y
If dy < 0 Then
dy = 0 - dy
EndIf
If dy > dx Then
dx = dy
EndIf
If dx <= prec Then
Return
EndIf
if mx == x and my == y then
return
endif
lx = mx
ly = my
ld = UO.GetDir() ; cause once pressing can only change the direcction
if mx == x and my > y then
UO.Press(33)
endif
if mx == x and my < y then
UO.Press(35)
endif
if mx < x and my == y then
UO.Press(34)
endif
if mx < x and my > y then
UO.Press(39)
endif
if mx < x and my < y then
UO.Press(40)
endif
if mx > x and my == y then
UO.Press(36)
endif
if mx > x and my > y then
UO.Press(38)
endif
if mx > x and my < y then
UO.Press(37)
endif
UO.Print('KeyPressed')
wait( stepdelay )
if lx == UO.GetX() and ly == UO.GetY() and ld == UO.GetDir() then
; now there is a stop situation
UO.Print('PathFind')
recursInd = 0
repeat
#################################################
ind = ld
UO.Print(str(ind))
fout = 0
repeat ; идем в обход пока не упремся снова или не кончится стена
UO.Print('Iteration')
mx = UO.GetX()
my = UO.GetY()
ld = UO.GetDir()
UO.Press( turn[ ind ] )
wait( stepdelay )
if (UO.GetX() == mx and UO.GetY() == my and ld == UO.GetDir()) then
fout = 1 ; уперлись
else
dx = UO.GetX() - mx
dy = UO.GetY() - my
UO.Print('deltas '+str(dx)+' '+str(dy))
if deltax[ ind ] == dx and deltay[ ind ] == dy then
fout = 2 ; препятствие пройдено
endif
endif
until fout
UO.Print('fout '+ str(fout))
if fout == 1 then ; уходим на следующий поворот
recursInd = recursInd + 1
Push( str( ind ) )
;ld = ind
else ; fout == 2
; надо попытаться восстановить контекст из стека, или выйти из обхода
UO.Print('Iter '+ str(recursInd))
pathFind = 0
if recursInd then ; восстановление
pathFind = 1
recursInd = recursInd - 1
ld = val(Pop()) - 1
if ld == -1 then
ld = 7
endif
UO.Press( turn[ld] )
wait ( stepdelay ) ; в сиду того, что ондо нажатие меняет напрваление
endif
endif
#################################################
until not recursInd and not pathFind
UO.Print('PathFind END')
endif
until 0
endsub
Просьба протестировать, кому интересно. Если глюки будут - скидываем суда лог + пишем о поведении.
Пробный пуск показал, что принципиальная схема работает. Точность - один тайл ( для непонявших поясняю - в проход шириной в один тайл при обходе чар не пройдет - делаем по старинке - прописываем ару лишних координат, чтоб чар пользовался дверью по порямому назначению а не как обходом)
Выслушаю любые предложения по усовершенствованию и облагораживанию.
Чей исходный был копирайт - незнаю, но уважаю (напишите чей, тока имейте в виду название не суть скрипта, просто может кто код узнает).