It looks like you're new here. If you want to get involved, click one of these buttons!
<<set $m to [
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,+1,+1,+1,+1,+1,+1,-1,+1,+1,+1,+1,-1,-1,+1,-1,+1,+1,-1],
[-1,-1,+1,-1,-1,-1,-1,-1,-1,-1,-1,+1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,+1,-1,-1,-1,-1,-1,+1,+1,+1,+1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,+1,+1,+1,-1,+1,+1,+1,+1,+1,+1,+1,+1,+1,-1,+1,+1,+1,+1,-1],
[-1,+1,+1,+1,+1,+1,-1,+1,+1,+1,+1,+1,+1,+1,+1,-1,+1,+1,-1,-1],
[-1,+1,-1,-1,-1,+1,-1,-1,+1,+1,+1,+1,+1,-1,+1,+1,-1,+1,-1,-1],
[-1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,-1,-1,+1,-1,+1,+1,-1],
[-1,-1,-1,-1,-1,-1,-1,+1,+1,+1,+1,+1,+1,-1,-1,-1,-1,-1,-1,-1],
[-1,+1,+1,+1,-1,+1,+1,+1,+1,+1,+1,+1,+1,+1,-1,+1,+1,+1,+1,-1],
[-1,+1,+1,+1,-1,+1,-1,+1,+1,+1,+1,+1,+1,+1,+1,-1,+1,+1,-1,-1],
[-1,+1,-1,-1,-1,-1,-1,-1,-1,+1,+1,+1,+1,-1,+1,+1,-1,+1,-1,-1],
[-1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,-1,-1,+1,-1,+1,+1,-1],
[-1,-1,-1,-1,-1,-1,-1,+1,-1,-1,-1,-1,-1,-1,-1,+1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,+1,-1,-1,-1,-1,-1,-1,-1,+1,-1,-1,-1,-1],
[-1,+1,+1,+1,-1,+1,+1,+1,-1,+1,+1,+1,+1,+1,-1,+1,+1,+1,+1,-1],
[-1,+1,+1,+1,-1,+1,-1,+1,-1,+1,+1,-1,+1,+1,+1,-1,+1,+1,-1,-1],
[-1,+1,-1,-1,+1,-1,-1,+1,-1,-1,-1,-1,+1,-1,+1,+1,+1,+1,-1,-1],
[-1,+1,+1,+1,+1,+1,+1,+1,-1,+1,+1,+1,+1,-1,-1,+1,-1,+1,+1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]]>>
<<pathfind [11,1] [1,12] $m>>
The first two arguments of the macro are the start and the end points, after this there are only 2 for-loops on the page that print the contents of $m and of $pf_map, which is the internal map of the macro. Even though, beside the initial declaration there is no other operation which modifies $m, $m and $pf_map come out the same when the page is rendered. It seems as if at some point the script flows backwards.<<widget "pathfind">>
/%input of arguments. 1. start coordinates (x.y) 2. end coordinates (x.y) 3. map%/
<<set $pf_start = $args[0]>>
<<set $pf_end = $args[1]>>
<<set $pf_map = $args[2]>>
/%convert map to collision map. positive numbers are converted to open nodes, negative numbers to not closed nodes (not passable)%/
<<for $pf_i_x to 0, $pf_i_y to 0; $pf_i_y lt $pf_map.length;>>
<<if $pf_map[$pf_i_y][$pf_i_x] gt 0>>
<<set $pf_map[$pf_i_y][$pf_i_x] to "O">>
<<else>>
<<set $pf_map[$pf_i_y][$pf_i_x] to "N">>
<<endif>>
<<if $pf_i_x lt $pf_map[$pf_i_y].length -1>>
<<set $pf_i_x++>>
<<else>>
<<set $pf_i_y++>>
<<set $pf_i_x to 0>>
<<endif>>
<</for>>
/%calculates optimal number of steps necessary to reach each node%/
<<for $pf_smallest to [], $pf_list to [[$pf_start[0],$pf_start[1]]], $pf_path to [$pf_start]; def $pf_list[0]; $pf_smallest to []>>
<<if $pf_map[$pf_list[0][1]+1][$pf_list[0][0]] eq "O">>
<<set $pf_map[$pf_list[0][1]+1][$pf_list[0][0]] to "Li">>
<<set $pf_list.push([$pf_list[0][0],$pf_list[0][1]+1])>>
<<elseif $pf_map[$pf_list[0][1]+1][$pf_list[0][0]] gte 0>>
<<set $pf_smallest.push($pf_map[$pf_list[0][1]+1][$pf_list[0][0]])>>
<<endif>>
<<if $pf_map[$pf_list[0][1]-1][$pf_list[0][0]] eq "O">>
<<set $pf_map[$pf_list[0][1]-1][$pf_list[0][0]] to "Li">>
<<set $pf_list.push([$pf_list[0][0],$pf_list[0][1]-1]) >>
<<elseif $pf_map[$pf_list[0][1]-1][$pf_list[0][0]] gte 0>>
<<set $pf_smallest.push($pf_map[$pf_list[0][1]-1][$pf_list[0][0]])>>
<<endif>>
<<if $pf_map[$pf_list[0][1]][$pf_list[0][0]+1] eq "O">>
<<set $pf_map[$pf_list[0][1]][$pf_list[0][0]+1] to "Li">>
<<set $pf_list.push([$pf_list[0][0]+1,$pf_list[0][1]]) >>
<<elseif $pf_map[$pf_list[0][1]][$pf_list[0][0]+1] gte 0>>
<<set $pf_smallest.push($pf_map[$pf_list[0][1]][$pf_list[0][0]+1])>>
<<endif>>
<<if $pf_map[$pf_list[0][1]][$pf_list[0][0]-1] eq "O">>
<<set $pf_map[$pf_list[0][1]][$pf_list[0][0]-1] to "Li">>
<<set $pf_list.push([$pf_list[0][0]-1,$pf_list[0][1]]) >>
<<elseif $pf_map[$pf_list[0][1]][$pf_list[0][0]-1] gte 0>>
<<set $pf_smallest.push($pf_map[$pf_list[0][1]][$pf_list[0][0]-1])>>
<<endif>>
<<if def $pf_smallest[0]>>
<<set $pf_smallest.sort(function(a, b){return a-b})>>
<<set $pf_map[$pf_list[0][1]][$pf_list[0][0]] to $pf_smallest[0] +1>>
<<else>>
<<set $pf_map[$pf_list[0][1]][$pf_list[0][0]] to 0>>
<<endif>>
<<set $pf_list.shift()>>
/%saves optimal path to the final note to a path (a list of coordinates) and ends loop%/
<<if $pf_map[$pf_end[1]][$pf_end[0]] gte 0>>
<<for $pf_steps to $pf_map[$pf_end[1]][$pf_end[0]], $pf_pointer to $pf_end, $pf_select to [], $pf_path to [$pf_end]; $pf_steps gt 1; $pf_steps--, $pf_select to []>>
<<if $pf_map[$pf_pointer[1]][$pf_pointer[0]-1] eq $pf_steps -1>>
<<set $pf_select.push([$pf_pointer[0]-1,$pf_pointer[1]])>>
<<endif>>
<<if $pf_map[$pf_pointer[1]][$pf_pointer[0]+1] eq $pf_steps -1>>
<<set $pf_select.push([$pf_pointer[0]+1,$pf_pointer[1]])>>
<<endif>>
<<if $pf_map[$pf_pointer[1]+1][$pf_pointer[0]] eq $pf_steps -1>>
<<set $pf_select.push([$pf_pointer[0],$pf_pointer[1]+1])>>
<<endif>>
<<if $pf_map[$pf_pointer[1]-1][$pf_pointer[0]] eq $pf_steps -1>>
<<set $pf_select.push([$pf_pointer[0],$pf_pointer[1]-1])>>
<<endif>>
<<set $pf_path.unshift($pf_select.random())>>
<<set $pf_pointer to $pf_path[0]>>
<</for>>
<<break>>
<<endif>>
<</for>>
<</widget>>
I am not sure, if that's the most elegant way to do a pathfinding macro, but it works. By the way, is it of any use to unset the variables (exept $pf_path) at the end of the widget?
Comments
What you want to do is make a Copy/Clone of the array, which you would normally do using the following code but this wont work correctly in your case because you have an array of arrays: Instead you will need to do a Deep Copy using one of the following two methods, they both work.
How can I tell, if a parameter is passed by reference? Or does it only happen when I pass data to a widget?
The actual value in an array variable is NOT the array itself but an object reference (kinda like a number) to where the array is stored and you are passing this reference by value. The same behavior happens when passing any object as a parameter, and is standard in Javascript which is the programming language behind all the marcos and code you use in a Twine story format.
I hope, doing all that twine stuff will make it easier for me to eventually learn JS.