{deck}
version:1
card:0
size:[512,342]
name:"path module"
patterns:"%%IMG2AAgA5gBAAUEABwEBAAcBAQAHAQgABAEBAAcBAQAHAQEAAwEIAAIBAQAGAQEABgEBAAcBAgAFAQEAAgEBAAMBAQAEAQMABgEBAAYBAQAEAQEAEwEBAAsBAQATAQEACwEIAAEBAwABAQ0AAQEDAAEBCQABAQMAAQENAAEBAwABAQEAAQEDAAMBAQACAQEAAwEBAAQBAQABAQQAAwEEAAEBAQADAQMAAgEBAAMBAQACAQMAAQEBAAIBBQADAQEAAwEBAAQBAQABAQEABgEBAAsBAQAGAQEAAQECAAMBAQADAQEAAwEBAAMBAQADAQEAAwEBAAMBAQANAQEAAwEBAAkBAQADAQEADQEBAAMBAQAKAQMAAQEFAAEBAwABAQEAAQEDAAEBBQABAQMAAQEBAAEBAwABAQUAAQEDAAEBAQABAQMAAQEFAAEBAwABAQEAAQEBAAYBAQATAQEACAEBAAgBAQALAQEADAEBAAcBAQAGAQMABAEBAAMBAQACAQEABQECAAgBAgAIAQEAAQEBAAMBAQAFAQEAAwEBAAEBAQADAQEABQEBAAMBAQABAQEAAwEBAAUBAQADAQEAAQEBAAMBAQAFAQEAAwEBAAEBAQABAQEAAQEBAAEBAQACAQEAAQEBAAEBAQABAQIAAQEBAAEBAQABAQEAAgEBAAEBAQABAQEAAQECAAEBAQABAQEAAQEBAAIBAQABAQEAAQEBAAEBAgABAQEAAQEBAAEBAQACAQEAAQEBAAEBAQABAQIADAEBAAMBAQAKAQEACgEBAAIBAQALAQEABAEBAAQBAgAKAQIAAgEBAAMBAgABAQIAAQECAAMBAQACAQIACgECAAMBAgABAQQAAQECAAMBAQABAQEAAQEBAAEBAQAJAQEAAQEBAAEBAQABAQEACQEBAAEBAQABAQEAAQEBAAkBAQABAQEAAQEBAAEBAQAJAQgAAQEBAAEBAQABAQEAAQEJAAEBAQABAQEAAQEBAAEBCQABAQEAAQEBAAEBAQABAQkAAQEBAAEBAQABAQEAAQEJAAgBCAAIAQgACAEIAAgBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAQEBAAEBAQABAQEAAgEBAAMBAQACAQEAAwEBAAYBAQADAQEAAgEBAAMBAQACAQEAAwEBAAIBAQADAQEABgEBAAMBAQACAQEAAwEBAAEBAgABAQMAAQECAAEBAwABAQIAAQEDAAEBBgABAQMAAQECAAEBAwABAQIAAQEDAAEBAgABAQMAAQEGAAEBAwACAQEABgEBAA4BAQAGAQEABgEBAAYBAQAGAQEABgEBAAUBAQABAQYAAQEOAAEBBgABAQYAAQEGAAEBBgABAQYAAQEFAAQBAQALAQEAAQEBAAEBAQABAQEADQEBAAsBAQADAQEACwEBAAMBBQADAQQAAQEDAAEBBAACAQIAAwEFAAMBBQAEAQMAAQEEAAMBAQACAQIAAQEBAAEBAQABAQEACQEBAAMBAQAGAQEAAQEBAAQBAQADAQEAAgEBAAUBAgADAQEACwEBAAEBAgAEAQEAAQECAAQBAQABAQIABAEBAAEBBgAIAQEAAQEHAAEBBwABAQIABP8FAATcAQAC/wEAAZcBNgEAAZcBAALKAQABlwH/AQABqAEAAmUBAAFlATYBAAGXAWUBNgG5A4YDRQMAAw=="

{card:Index}
image:"%%[encoded data, 14196 characters]"
script:"Index.0"
{widgets}
field1:{"type":"field","size":[154,17],"pos":[342,136],"locked":1,"font":"menu","border":0,"align":"center","value":"Pathfinding for Decker"}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
field2:{"type":"field","size":[248,55],"pos":[14,142],"locked":1,"show":"transparent","border":0,"value":{"text":["The \"path\" module provides flexible grid-based pathfinding routines.\n\n\n","Index:"],"font":["","menu"],"arg":["",""]}}
index:{"type":"field","size":[243,117],"pos":[16,197],"locked":1,"volatile":1,"script":"Index.2","scrollbar":1}
version:{"type":"field","size":[42,14],"pos":[16,318],"locked":1,"volatile":1,"border":0}

{script:Index.0}
on view do
 bullet:image["%%IMG0AAYADQAAAAB49Pz8/HgAAAA="]
 i:select c:key t:value..widgets.title.text where value..widgets.title from deck.cards
 index.value:raze each row in rows i
  rtext.make["" "" bullet],
  rtext.make["  "],
  rtext.make[("%s\n" format row.t) "mono" row.c]
 end
 version.text:"v%0.1f" format deck.modules.path.version
end
{end}

{script:Index.1}
on click do
 t.Prev:"SlideRight"
 t.Next:"SlideLeft"
 t.Index:"BoxOut"
 go[me.text t[me.text] 15]
end
{end}

{script:Index.2}
on link val do
 go[val "BoxIn" 15]
end
{end}

{card:overview}
image:"%%[encoded data, 5932 characters]"
script:"overview.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Overview"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":{"text":["The \"path\" module performs pathfinding. Given a grid, it computes a list of moves which define a route from a start point to an end point, avoiding impassable cells.\n\nThe module exposes several functions which operate on pixel-based coordinates, automatically discretized to some grid cell size:\n\n","- path.find[start goal grid etc]\n- path.test[pos grid etc]\n- path.closest[pos t grid etc]","\n\nAs well as equivalents which operate on grid-cell based coordinates, otherwise taking the same arguments:\n\n","- path.find_cell[start goal grid etc]\n- path.test_cell[pos grid etc]\n- path.closest_cell[pos t grid etc]","\n\nFinally, this deck includes a contraption called the ","Follower ","which can automatically interpolate along a supplied path with configurable animation."],"font":["","mono","","mono","","menu",""],"arg":["","","","","","",""]}}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
field5:{"type":"field","size":[74,14],"pos":[61,72],"locked":1,"border":0,"style":"plain","align":"center","value":"grid cell"}
field1:{"type":"field","size":[117,14],"pos":[103,263],"locked":1,"border":0,"style":"plain","align":"center","value":"impassable cells"}
field3:{"type":"field","size":[27,14],"pos":[23,160],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}

{script:overview.0}
on view do
 
end
{end}

{card:find}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.find[]"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":{"text":["In its simplest form, path.find[] computes a route from a start point to an end point along a grid.\n\n","path.find[start goal grid etc]","\n\n- START: a pair of coordinates or a widget.\n- GOAL: a pair of coordinates or a widget.\n- GRID: an Image, Canvas, or Card.\n- ETC: a dictionary of optional parameters.\n\nBy default, the grid uses 16x16 pixel cells, and cells within the grid which contain any black pixels (pattern 1) are considered impassable.\n\nIn this case, the start and goal are specified in pixels relative to the top-left corner of the grid, and the result is a list of coordinate pairs of grid centerpoints in the same coordinate system.\n\nIf path.find[] is unable to find a passable route, it will return 0."],"font":["","mono",""],"arg":["","",""]}}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"grid"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,0]},"scr":{"size":[246,99]}}}
grid:{"type":"canvas","size":[128,128],"pos":[46,54],"locked":1,"script":"find.0","image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDQcjAw0GABANEAAQDRAAEA0QABANBiMFDQUAEA0QABANEAAQDRAAEA0FIwcNBAAQDRAAEA0QABANEAAQDQUjCA0DABANEAAQDRAAEA0QABANBSMJDQIAEA0QABANEAAQDRAAEA0GIwkNAQAQDRAAEA0QABANEAAQDQcjCQAQDRAAEA0QABANEAAQDQgjCQAPDRAAEA0QABANEAAQDQkjCQAODRAAEA0QABANEAAQDQojCQANDRAAEA0QABANEAAQDQsjCQAMDRAAEA0QABANEAAcIwkNCwAQDRAAEA0QABANEAANIwkNCgAQDRAAEA0QABANEAAOIwkNCQAQDRAAEA0QABANEAAPIwkNCAAQDRAAEA0QABANEAAQIwkNBwAQDRAAEA0QABANEAAQDQEjCQ0GABANEAAQDRAAEA0QABANAiMJDQUAEA0QABANEAAQDRAAEA0DIwkNBAAQDRAAEA0QABANEAAQDQQjCA0EABANEAAQDRAAEA0QABANBSMHDQQAEA0QABANEAAQDRAAEA0FIwcNBAAQDRAAEA0QABANEAAQDQUjBw0EABANEAAQDRAAEA0QABANBSMHDQQAEA0QABANEAAQDRAAEA0FIwcNBAAQDRAAEA0QABANEAAQDQUjBw0EABANEAAQDRAAEA0QABANBSMHDQQAEA0QABANEAAQDSAABSMHAAQBEAAQDRAAEA0QABANEAAFIwcABAEBAA4BAQAQDRAAEA0QABANEAAFIwcABAEBAAEBDAABAQEAEA0QABANEAAQDRAABSMHAAQBAQABAQwAAQEBABANEAAQDRAAEA0QAAUjBwAEAQEAAQEMAAEBAQAQDRAAEA0QABANEAAFIwcABAEBAAEBDAABAQEAEA0QABANEAAQDRAABSMHAAQBAQABAQwAAQEBABANEAAQDRAAEA0QAAUjBwAEAQEAAQEMAAEBAQAQDRAAEA0QABANEAAFIwcABAEBAAEBDAABAQEAEA0QABANEAAQDRAABSMHAAQBAQABAQwAAQEBABANEAAQDRAAEA0QAAUjBwAEAQEAAQEMAAEBAQAQDRAAEA0QABANEAAFIwcABAEBAAEBDAABAQEAEA0QABANEAAQDRAABSMHAAQBAQABAQwAAQEBABANEAAQDRAAEA0QAAUjBwAEAQEAAQEMAAEBAQAQDRAAEA0QABANEAAFIwcABAEBAAEBDAABAQEAEA0QABANEAAQDRAABSMHAAQBAQABAQwAAQEBABANEAAQDRAAIA0FIwcNBAEBAAEBDAABAQENEAAQDRAAEA0QABANBSMHDQQBAQABAQwAAQEBDRAAEA0QABANEAAQDQUjBw0EAQEAAQEMAAEBAQ0QABANEAAQDRAAEA0FIwcNBAEBAAEBDAABAQENEAAQDRAAEA0QABANBSMHDQQBAQABAQwAAQEBDRAAEA0QABANEAAQDQUjBw0EAQEAAQEMAAEBAQ0QABANEAAQDRAAEA0FIwcNBAEBAAEBDAABAQENEAAQDRAAEA0QABANBSMHDQQBAQABAQwAAQEBDRAAEA0QABANEAAQDQUjCA0DAQEAAQEMAAEBAQ0QABANEAAQDRAAEA0FIwkNAgEBAAEBDAABAQENEAAQDRAAEA0QABANBiMJDQEBAQABAQwAAQEBDRAAEA0QABANEAAQDQcjCQEBAAEBDAABAQENEAAQDRAAEA0QABANCCMJAAEBDAABAQENEAAQDRAAEA0QABANCSMJAQwAAQEBDRAAEA0QABANEAAQDQojCQAMAQENEAAQDRAAEA0QABANCyMJAQwNEAAQDRAAEA0gAAwjCQ0LABANEAEQDRAAEA0QAA0jCQ0KABANEAEBAA4BAQ0QABANEAAOIwkNCQAQDRABAQABAQwAAQEBDRAAEA0QAA8jCQ0IABANEAEBAAEBDAABAQENEAAQDRAAECMJDQcAEA0QAQEAAQEMAAEBAQ0QABANEAAQDQEjCQ0GABANEAEBAAEBDAABAQENEAAQDRAAEA0CIwkNBQAQDRABAQABAQwAAQEBDRAAEA0QABANAyMJDQQAEA0QAQEAAQEMAAEBAQ0QABANEAAQDQQjCQ0DABANEAEBAAEBDAABAQENEAAQDRAAEA0FIwkNAgAQDRABAQABAQwAAQEBDRAAEA0QABANBiMJDQEAEA0QAQEAAQEMAAEBAQ0QABANEAAQDQcjCQAQDRABAQABAQwAAQEBDRAAEA0QABANCCMJAA8NEAEBAAEBDAABAQENEAAQDRAAEA0JIwkADg0QAQEAAQEMAAEBAQ0QABANEAAQDQojCQANDRABAQABAQwAAQEBDRAAEA0QABANCyMJAAwNEAEBAAEBDAABAQENEAAgDRAADCMJDQsBEQABAQwAAQEBABANEAAQDRAADSMJDQoBAQARAQwAAQEBABANEAAQDRAADiMJDQkBAQABARwAAQEBABANEAAQDRAADyMJDQgBAQABARwAAQEBABANEAAQDRAAECMJDQcBAQABARwAAQEBABANEAAQDRAAEA0BIwkNBgEBAAEBHAABAQEAEA0QABANEAAQDQIjCQ0FAQEAAQEcAAEBAQAQDRAAEA0QABANAyMJDQQBAQABARwAAQEBABANEAAQDRAAEA0EIwkNAwEBAAEBHAABAQEAEA0QABANEAAQDQUjCQ0CAQEAAQEcAAEBAQAQDRAAEA0QABANBiMJDQEBAQABARwAAQEBABANEAAQDRAAEA0HIwkBAQABARwAAQEBABANEAAQDRAAEA0IIwkAAQEcAAEBAQAQDRAAEA0QABANCSMJARwAAQEBABANEAAQDRAAEA0KIwkAHAEBABANEAAQDRAAEA0LIwkBHAAQDSAAEA0QAAwjCQ0LABANEAAQDRAAEA0QAA0jCQ0KABANEAAQDRAAEA0QAA4jCQ0JABANEAAQDRAAEA0QAA8jCQ0IABANEAAQDRAAEA0QABAjCQ0HABANEAAQDRAAEA0QABANASMJDQYAEA0QABANEAAQDRAAEA0CIwkNBQAQDRAAEA0QABANEAAQDQMjCQ0EABANEAAQDRAAEA0QABANBCMIDQQAEA0QABANEAAQDRAAEA0FIwcNBAAQDRAAEA0QABANEAAQDQYjBQ0FABANEAAQDRAAEA0QABANByMDDQYAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAgDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRA=","brush":4,"pattern":35,"scale":1}
ref:{"type":"canvas","size":[32,32],"pos":[188,97],"locked":1,"image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":0.25}
field5:{"type":"field","size":[74,14],"pos":[71,38],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
field1:{"type":"field","size":[43,14],"pos":[182,83],"locked":1,"border":0,"style":"plain","align":"center","value":"ref"}

{script:find.0}
on click pos do
 g:ref.copy[]
 p:path.find[0,0 pos g]
 grid.pattern:colors.red
 grid.brush:4
 grid.paste[g]
 grid.line[p]
end
{end}

{card:coordinates}
image:"%%IMG2AgABVgD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AHUBAQB6AQEA/wCFAQEAegEBAP8AhQEBAHoBAQD/AIUBAQB6AQEA/wCFAQEAegEBAP8AhQEBAHoBAQD/AIUBAQB6AQEA/wCFAQEAegEBAP8AhQEBAHoBAQD/AIUBAQB6AQEA/wCFAQEAegEBAP8AhQEBAHoBAQD/AIUBAQB6AQEA/wCFAQEAegEBAP8AhQEBAHoBAQD/AIUBAQB6AQEA/wCFAQEAegEBAP8AhQEBAHoBAQD/AIUBAQB6AQEA/wCFAQEAegEBAP8AgwEFAHYBBQD/AIEBBQB2AQUA/wCBAQUAdgEFAP8AggEDAHgBAwD/AIMBAwB4AQMA/wCDAQMAeAEDAP8AhAEBAHoBAQD/AIUBAQB6AQEA/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8Ahg=="
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.find[]: coordinates"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":"The START and GOAL arguments to path.find[] can be specified as pairs or references to widgets. The GRID argument can be given as an image, a card, or a canvas. \n\nIf START or GOAL are given as pairs, they will be interpreted as positions in pixels relative to the origin of the GRID.\n\nIf START or GOAL are given as a widget reference, the centerpoint of that widget is converted to a position in pixels relative to the position of the GRID: (0,0) for a card or image or the .pos attribute of a canvas.\n\nSTART and GOAL don't need to be of the same type.\n\nThe resulting route will always be given in a coordinate system which matches the START. Thus, if you provide START as a pair, you'll get back route coordinates which can be directly used to draw on a canvas, whereas if you provide START as a widget you'll get back path coordinates which can be used as the centerpoint for positioning widgets on the card."}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
field5:{"type":"field","size":[107,14],"pos":[19,135],"locked":1,"border":0,"style":"plain","align":"center","value":"position on canvas"}
field1:{"type":"field","size":[107,14],"pos":[19,180],"locked":1,"border":0,"style":"plain","align":"center","value":"positions on canvas"}
field3:{"type":"field","size":[107,14],"pos":[141,135],"locked":1,"border":0,"style":"plain","align":"center","value":"widget on card"}
field4:{"type":"field","size":[107,14],"pos":[141,180],"locked":1,"border":0,"style":"plain","align":"center","value":"widget centers on card"}

{card:etcparams}
image:"%%IMG2AgABVgD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/ANMNzQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0DQEAyw0BAP8ANA0BAMsNAQD/ADQNAQDLDQEA/wA0Dc0A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wB4"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.find[]: etc"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":"The fourth \"etc\" parameter to path.find[] (as well as other functions in the path module) is a dictionary which accepts a variety of optional keys:\n\n- etc.cell: a pair giving the width and height of grid cells in pixels. defaults to (16,16).\n\n- etc.block: a list of impassable patterns. If any pixels within a cell contain an impassable pattern, the entire cell is considered impassable. defaults to (list 1).\n\n- etc.shuffle: if truthy, produce random results of equal cost when several are available, instead of a consistent arbitrary result.\n\n- etc.move: a list of relative offsets (in grid cells) to consider for each step on a route. may also be specified as one of the strings:\n\n\"ortho\" (orthogonal movement)\n\"diag\" (diagonal movement)\n\"orthodiag\" (ortho and diag, the default)."}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
grid:{"type":"canvas","size":[128,128],"pos":[49,70],"locked":1,"script":"etcparams.0","image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDQcjEwAGDRAAEA0QABANEAAQDQYjFQAFDRAAEA0QABANEAAQDQUjFwAEDRAAEA0QABANEAAQDQUjFwAEDRAAEA0QABANEAAQDQUjFwAEDRAAEA0QABANEAAQDQYjFgAEDRAAEA0QABANEAAQDQcjFQAEDRAAEA0QABANEAAQDRAABSMHAAQNEAAQDRAAEA0QABANEAAFIwcABA0QABANEAAQDRAAEA0QAAUjBwAEDRAAEA0QABANEAAQDRAABSMHAAQNEAAQDRAAEA0QACANBSMHDQQAEA0QABANEAAQDRAAEA0FIwcNBAAQDRAAEA0QABANEAAQDQUjBw0EABANEAAQDRAAEA0QABANBSMHDQQAEA0QABANEAAQDRAAEA0FIwcNBAAQDRAAEA0QABANEAAQDQUjJQ0GABANEAAQDRAAEA0FIyYNBQAQDRAAEA0QABANBSMnDQQAEA0QABANEAAQDQUjJw0EABANEAAQDRAAEA0FIycNBAAQDRAAEA0QABANBiMmDQQAEA0QABANEAAQDQcjJQ0EABANEAAQDRAAEA0QABANBSMHDQQAEA0QABANEAAQDRAAEA0FIwcNBAAQDRAAEA0QABANEAAQDQUjBw0EABANEAAQDRAAEA0QABANBSMHDQQAEA0QABANIAAQARAABSMHAAQNEAAQDRAAEA0QABABAQAOAQEABSMHAAQNEAAQDRAAEA0QABABAQABAQwAAQEBAAUjBwAEDRAAEA0QABANEAAQAQEAAQEMAAEBAQAFIwcABA0QABANEAAQDRAAEAEBAAEBDAABAQEABSMHAAQNEAAQDRAAEA0QABABAQABAQwAAQEBAAUjBwAEDRAAEA0QABANEAAQAQEAAQEMAAEBAQAFIwcABA0QABANEAAQDRAAEAEBAAEBDAABAQEABSMHAAQNEAAQDRAAEA0QABABAQABAQwAAQEBAAUjBwAEDRAAEA0QABANEAAQAQEAAQEMAAEBAQAFIwcABA0QABANEAAQDRAAEAEBAAEBDAABAQEABSMHAAQNEAAQDRAAEA0QABABAQABAQwAAQEBAAUjBwAEDRAAEA0QABANEAAQAQEAAQEMAAEBAQAFIwcABA0QABANEAAQDRAAEAEBAAEBDAABAQEABSMHAAQNEAAQDRAAEA0QABABAQABAQwAAQEBAAUjBwAEDRAAEA0QABANEAAQAQEAAQEMAAEBAQAFIwcABA0QABANEAAgDRABAQABAQwAAQEBDQUjBw0EABANEAAQDRAAEA0QAQEAAQEMAAEBAQ0FIwcNBAAQDRAAEA0QABANEAEBAAEBDAABAQENBSMHDQQAEA0QABANEAAQDRABAQABAQwAAQEBDQUjBw0EABANEAAQDRAAEA0QAQEAAQEMAAEBAQ0FIwcNBAAQDRAAEA0QABANEAEBAAEBDAABAQENBSMHDQQAEA0QABANEAAQDRABAQABAQwAAQEBDQUjBw0EABANEAAQDRAAEA0QAQEAAQEMAAEBAQ0FIwcNBAAQDRAAEA0QABANEAEBAAEBDAABAQENBSMHDQQAEA0QABANEAAQDRABAQABAQwAAQEBDQUjBw0EABANEAAQDRAAEA0QAQEAAQEMAAEBAQ0FIwcNBAAQDRAAEA0QABANEAEBAAEBDAABAQENBSMHDQQAEA0QABANEAAQDRABAQABAQwAAQEBDQUjBw0EABANEAAQDRAAEA0QAQEAAQEMAAEBAQ0FIwcNBAAQDRAAEA0QABANEAEBAA4BAQ0FIwcNBAAQDRAAEA0QABANEAEQDQUjBw0EABANEAAQDSAAEA0QAAUjBwAEDRABEA0QABANEAAQDRAABSMHAAQNEAEBAA4BAQ0QABANEAAQDRAABSMHAAQNEAEBAAEBDAABAQENEAAQDRAAEA0QAAUjBwAEDRABAQABAQwAAQEBDRAAEA0QABANEAAFIwcABA0QAQEAAQEMAAEBAQ0QABANEAAQDRAABSMHAAQNEAEBAAEBDAABAQENEAAQDRAAEA0QAAUjBwAEDRABAQABAQwAAQEBDRAAEA0QABANEAAFIwcABA0QAQEAAQEMAAEBAQ0QABANEAAQDRAABSMHAAQNEAEBAAEBDAABAQENEAAQDRAAEA0QAAUjBwAEDRABAQABAQwAAQEBDRAAEA0QABANEAAFIwcABA0QAQEAAQEMAAEBAQ0QABANEAAQDRAABSMHAAQNEAEBAAEBDAABAQENEAAQDRAAEA0QAAUjBwAEDRABAQABAQwAAQEBDRAAEA0QABANEAAFIwcABA0QAQEAAQEMAAEBAQ0QABANEAAQDRAABSMHAAQNEAEBAAEBDAABAQENEAAQDRAAEA0QAAUjBwAEDRABAQABAQwAAQEBDRAAIA0QABANBSMHDQQBEQABAQwAAQEBABANEAAQDRAAEA0FIwcNBAEBABEBDAABAQEAEA0QABANEAAQDQUjBw0EAQEAAQEcAAEBAQAQDRAAEA0QABANBSMHDQQBAQABARwAAQEBABANEAAQDRAAEA0FIwcNBAEBAAEBHAABAQEAEA0QABANEAAQDQUjBw0EAQEAAQEcAAEBAQAQDRAAEA0QABANBSMHDQQBAQABARwAAQEBABANEAAQDRAAEA0FIwcNBAEBAAEBHAABAQEAEA0QABANEAAQDQUjBw0EAQEAAQEcAAEBAQAQDRAAEA0QABANBSMHDQQBAQABARwAAQEBABANEAAQDRAAEA0FIwcNBAEBAAEBHAABAQEAEA0QABANEAAQDQUjBw0EAQEAAQEcAAEBAQAQDRAAEA0QABANBSMHDQQBAQABARwAAQEBABANEAAQDRAAEA0FIwcNBAEBAAEBHAABAQEAEA0QABANEAAQDQUjBw0EAQEAHgEBABANEAAQDRAAEA0FIwcNBAEgABANIAAQDRAABSMHAAQNEAAQDRAAEA0QABANEAAFIwcABA0QABANEAAQDRAAEA0QAAUjBwAEDRAAEA0QABANEAAQDRAABSMHAAQNEAAQDRAAEA0QABANEAAFIwcABA0QABANEAAQDRAAEA0QAAUjFQ0GABANEAAQDRAAEA0QAAUjFg0FABANEAAQDRAAEA0QAAUjFw0EABANEAAQDRAAEA0QAAUjFw0EABANEAAQDRAAEA0QAAUjFw0EABANEAAQDRAAEA0QAAYjFQ0FABANEAAQDRAAEA0QAAcjEw0GABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAIA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0Q","brush":4,"pattern":35,"scale":1}
ref:{"type":"canvas","size":[32,32],"pos":[191,113],"locked":1,"image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":0.25}
field5:{"type":"field","size":[74,14],"pos":[74,54],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
field1:{"type":"field","size":[43,14],"pos":[185,99],"locked":1,"border":0,"style":"plain","align":"center","value":"ref"}
shuffle:{"type":"button","size":[75,20],"pos":[48,246],"font":"body","text":"etc.shuffle","style":"check","value":1}
move:{"type":"grid","size":[83,67],"pos":[144,221],"scrollbar":0,"headers":1,"lines":0,"widths":[0],"format":"sJ","value":{"val":["ortho","diag","orthodiag",[[-2,-1],[-1,-2],[1,-2],[2,-1],[-2,1],[-1,2],[1,2],[2,1]]],"etc.move":["ortho","diag","orthodiag","knight"]},"row":0}

{script:etcparams.0}
on click pos do
 g:ref.copy[]
 etc.shuffle:shuffle.value
 etc.move:first move.rowvalue
 p:path.find[0,0 pos g etc]
 grid.pattern:colors.red
 grid.brush:4
 grid.paste[g]
 grid.line[p]
end
{end}

{card:findmulti}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.find[]: multiple starts"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":"The path.find[] function may optionally be given a list of widgets or pairs as the START parameter. In this case, it will return a list of routes (or 0) from every provided start point to the GOAL (which may not be \"listy\" in the same manner).\n\nExtracting multiple routes at once in this fashion is much more efficient than performing separate calls to path.find[]; prefer it when possible."}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"grid"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,0]},"scr":{"size":[246,99]}}}
grid:{"type":"canvas","size":[128,128],"pos":[46,54],"locked":1,"script":"findmulti.0","image":"%%[encoded data, 4316 characters]","brush":4,"pattern":38,"scale":1}
ref:{"type":"canvas","size":[32,32],"pos":[188,97],"locked":1,"image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":0.25}
field5:{"type":"field","size":[74,14],"pos":[71,38],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
field1:{"type":"field","size":[43,14],"pos":[182,83],"locked":1,"border":0,"style":"plain","align":"center","value":"ref"}

{script:findmulti.0}
on click pos do
 o:"[[0,0],[0,7],[7,0],[7,7]]"
 s:16*"%j" parse o
 g:ref.copy[]
 grid.brush:4
 grid.paste[g]
 each r i in path.find[s pos g]
  grid.pattern:colors.red+i
  grid.line[r]
 end
end
{end}

{card:limits}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.find[]: limits"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":"There are some limitations to path.find[] that you should be aware of:\n\n- The maximum path length is 255 steps. If a route cannot be found within this limit, it will be treated as unreachable.\n\n- Calculating paths can be time-consuming. Avoid recomputing paths unnecessarily, and use the coarsest grid size and smallest grid that can suit your application."}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}

{card:testblocked}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.test[], path.testall[]"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":{"text":["In some situations you may want to directly consult the passability of cells within a grid, using the same approach as path.find[]. The path module exposes two approaches:\n\n","path.test[start grid etc]","\n\nreturn truthy if the specified START position is passable. coordinates outside the grid are considered non-passable.\n\n","path.testall[grid etc]","\n\nreturn an image interface filled with patterns 0 or 1, where 1 indicates a cell is passable. This is much more efficient than path.test[] if you need to query many cells at a time.\n\nboth of the above functions accept the same variations of widget/pair and card/image/canvas parameters as path.find[]."],"font":["","mono","","mono",""],"arg":["","","","",""]}}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
grid:{"type":"canvas","size":[128,128],"pos":[40,54],"locked":1,"script":"testblocked.0","image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":1}
field5:{"type":"field","size":[74,14],"pos":[67,39],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"grid"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,0]},"scr":{"size":[246,99]}}}
field1:{"type":"field","size":[71,35],"pos":[178,99],"locked":1,"border":0,"style":"plain","align":"center","value":"click on the grid to test passability!"}

{script:testblocked.0}
on click pos do
 p:path.test[pos grid]
 alert["passable: %b" format p]
end
{end}

{card:conversion}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.to_cell[], path.to_pix[]"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":{"text":["You may also occasionally want to explicitly convert canvas drawing coordinates to grid cell coordinates, or vice versa:\n\n","path.to_cell[x grid etc]","\n\nconvert a pair or the centerpoint of a widget x (or a list of either) into cell coordinates with respect to a grid.\n\n","path.to_pix[x etc]","\n\nconvert a pair in cell coordinates (or a list of such pairs) to a pair giving the drawing coordinates of the center of the cell (or a list of such pairs).\n\nTry clicking on the grid to the left to see these coordinate transforms in action!"],"font":["","mono","","mono",""],"arg":["","","","",""]}}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
grid:{"type":"canvas","size":[128,128],"pos":[16,54],"locked":1,"script":"conversion.0","image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":1}
field5:{"type":"field","size":[74,14],"pos":[37,39],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"grid"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,0]},"scr":{"size":[246,99]}}}
orig:{"type":"field","size":[100,14],"pos":[153,69],"locked":1,"volatile":1,"style":"plain","align":"center"}
field3:{"type":"field","size":[74,14],"pos":[165,54],"locked":1,"border":0,"style":"plain","align":"center","value":"orig"}
cell:{"type":"field","size":[100,14],"pos":[153,108],"locked":1,"volatile":1,"style":"plain","align":"center"}
field4:{"type":"field","size":[74,14],"pos":[165,93],"locked":1,"border":0,"style":"plain","align":"center","value":"cell"}
center:{"type":"field","size":[100,14],"pos":[153,147],"locked":1,"volatile":1,"style":"plain","align":"center"}
field6:{"type":"field","size":[74,14],"pos":[165,132],"locked":1,"border":0,"style":"plain","align":"center","value":"center"}

{script:conversion.0}
on click pos do
 c:path.to_cell[pos grid]
 p:path.to_pix[c]
 orig  .data:pos
 cell  .data:c
 center.data:p
end
{end}

{card:closest}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"path.closest[]"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":{"text":["Sometimes you may want to add some flexibility to START or GOAL positions when calculating a route. The path.closest[] function attempts to locate the nearest passable position on a grid to a provided position.\n\n","path.closest[start tol grid etc]","\n\n- START: a pair of coordinates or a widget.\n- TOL: the maximum distance to search, in grid cells.\n- GRID: an Image, Canvas, or Card.\n- ETC: a dictionary of optional parameters.\n\nIf path.closest[] is unable to find a passable route, it will return 0.\n\nIf etc.shuffle is truthy, this function will choose randomly among equally close cells.\n\nTry clicking on impassable tiles on the example to the left, and observe the \"best guess\" path."],"font":["","mono",""],"arg":["","",""]}}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"grid"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,0]},"scr":{"size":[246,99]}}}
grid:{"type":"canvas","size":[128,128],"pos":[46,54],"locked":1,"script":"closest.0","image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDQcjIw0GABANEAAQDRAAEA0GIyUNBQAQDRAAEA0QABANBSMnDQQAEA0QABANEAAQDQUjKA0DABANEAAQDRAAEA0FIykNAgAQDRAAEA0QABANBiMpDQEAEA0QABANEAAQDQcjKQAQDRAAEA0QABANEAAQDQgjCQAPDRAAEA0QABANEAAQDQkjCQAODRAAEA0QABANEAAQDQojCQANDRAAEA0QABANEAAQDQsjCQAMDRAAEA0QACANEAAMIwkNCwAQDRAAEA0QABANEAANIwkNCgAQDRAAEA0QABANEAAOIwkNCQAQDRAAEA0QABANEAAPIwkNCAAQDRAAEA0QABANEAAQIwkNBwAQDRAAEA0QABANEAAQDQEjCQ0GABANEAAQDRAAEA0QABANAiMJDQUAEA0QABANEAAQDRAAEA0DIwkNBAAQDRAAEA0QABANEAAQDQQjCQ0DABANEAAQDRAAEA0QABANBSMJDQIAEA0QABANEAAQDRAAEA0GIwkNAQAQDRAAEA0QABANEAAQDQcjCQAQDRAAEA0QABANEAAQDQgjCQAPDRAAEA0QABANEAAQDQkjCQAODRAAEA0QABANEAAQDQojCQANDRAAEA0QABANEAAQDQsjCQAMDRAAEA0gABABEAAMIwkNCwAQDRAAEA0QABABAQAOAQEADSMJDQoAEA0QABANEAAQAQEAAQEMAAEBAQAOIwkNCQAQDRAAEA0QABABAQABAQwAAQEBAA8jCQ0IABANEAAQDRAAEAEBAAEBDAABAQEAECMJDQcAEA0QABANEAAQAQEAAQEMAAEBAQAQDQEjCQ0GABANEAAQDRAAEAEBAAEBDAABAQEAEA0CIwkNBQAQDRAAEA0QABABAQABAQwAAQEBABANAyMJDQQAEA0QABANEAAQAQEAAQEMAAEBAQAQDQQjCQ0DABANEAAQDRAAEAEBAAEBDAABAQEAEA0FIwkNAgAQDRAAEA0QABABAQABAQwAAQEBABANBiMJDQEAEA0QABANEAAQAQEAAQEMAAEBAQAQDQcjCQAQDRAAEA0QABABAQABAQwAAQEBABANCCMJAA8NEAAQDRAAEAEBAAEBDAABAQEAEA0JIwkADg0QABANEAAQAQEAAQEMAAEBAQAQDQojCQANDRAAEA0QABABAQABAQwAAQEBABANCyMJAAwNEAAgDRABAQABAQwAAQEBDRAADCMJDQsAEA0QABANEAEBAAEBDAABAQENEAANIwkNCgAQDRAAEA0QAQEAAQEMAAEBAQ0QAA4jCQ0JABANEAAQDRABAQABAQwAAQEBDRAADyMJDQgAEA0QABANEAEBAAEBDAABAQENEAAQIwkNBwAQDRAAEA0QAQEAAQEMAAEBAQ0QABANASMJDQYAEA0QABANEAEBAAEBDAABAQENEAAQDQIjCQ0FABANEAAQDRABAQABAQwAAQEBDRAAEA0DIwkNBAAQDRAAEA0QAQEAAQEMAAEBAQ0QABANBCMIDQQAEA0QABANEAEBAAEBDAABAQENEAAQDQUjBw0EABANEAAQDRABAQABAQwAAQEBDRAAEA0GIwUNBQAQDRAAEA0QAQEAAQEMAAEBAQ0QABANByMDDQYAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","brush":4,"pattern":35,"scale":1}
ref:{"type":"canvas","size":[32,32],"pos":[188,97],"locked":1,"image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":0.25}
field5:{"type":"field","size":[74,14],"pos":[71,38],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
field1:{"type":"field","size":[43,14],"pos":[182,83],"locked":1,"border":0,"style":"plain","align":"center","value":"ref"}

{script:closest.0}
on click pos do
 g:ref.copy[]
 c:path.closest[pos 2 g ().shuffle:1]
 p:path.find[0,0 c g]
 grid.pattern:colors.red
 grid.brush:4
 grid.paste[g]
 grid.line[p]
end
{end}

{card:followerContraption}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"the Follower contraption"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":"The Follower contraption is a handy companion to the \"path\" module, offering a self-animating entity that can move along computed routes.\n\n-follower.path: a list of screen-space coordinates upon which to center the follower in sequence. Writing a 0 cancels movement.\n\n- follower.done: has movement completed? (read-only).\n\n- follower.speed: how many frames of animation does it take to carry out one step in a path? (A higher number means slower movement.)\n\n- follower.aux: auxiliary storage for any lil data\n\n- follower.image: the visual appearance of the follower, drawn centered within its bounding box.\n\n- follower.show: control transparency or hide the contraption.\n\n- follower.animate[]: an alternative to the follower's internal animation pump, if you want it to move during a \"synchronous\" blocking script."}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
grid:{"type":"canvas","size":[128,128],"pos":[33,54],"locked":1,"script":"followerContraption.0","image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":1}
f:{"type":"contraption","size":[16,16],"pos":[81,134],"show":"transparent","def":"follower","widgets":{"c":{"size":[16,16],"show":"transparent"},"si":{"pos":[52,-38]},"ss":{"size":[100,12],"pos":[52,-11]},"sd":{"size":[100,3],"pos":[52,3]},"sp":{"size":[100,3],"pos":[52,7],"value":"{}"},"sa":{"size":[100,3],"pos":[52,11]}}}
field5:{"type":"field","size":[74,14],"pos":[60,39],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"grid"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,0]},"scr":{"size":[246,99]}}}
field1:{"type":"field","size":[79,36],"pos":[172,99],"locked":1,"border":0,"style":"plain","align":"center","value":"click anywhere on the board to move the pawn!"}

{script:followerContraption.0}
on click pos do
 f.path:path.find[f pos grid]
end
{end}

{card:followermovement}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Follower movement events"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":"The Follower contraption emits several events while it travels along an assigned route:\n\n- step[]: called each time a step on the route is completed.\n\n- finish[]: called once when an entire route is completed. Not called if a route is canceled!\n\n- tween[t a b]: called multiple times over the course of each step in the route. \"a\" and \"b\" are pairs in screen coordinates and \"t\" is a tweening value that ranges from 0 to 1. If this event handler is defined and returns a coordinate pair, the follower will center itself on those screen coordinates for that frame of the animation; otherwise it will linearly interpolate itself from \"a\" to \"b\".\n\nAny of these event handlers can offer good opportunities for driving animation by redefining follower.sprite!"}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
grid:{"type":"canvas","size":[128,128],"pos":[10,54],"locked":1,"script":"followermovement.0","image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":1}
f:{"type":"contraption","size":[16,16],"pos":[74,118],"script":"followermovement.1","show":"transparent","def":"follower","widgets":{"c":{"size":[16,16],"show":"transparent"},"si":{"pos":[52,-38]},"ss":{"size":[100,12],"pos":[52,-11],"value":"20"},"sd":{"size":[100,3],"pos":[52,3]},"sp":{"size":[100,3],"pos":[52,7],"value":"{}"},"sa":{"size":[100,3],"pos":[52,11]}}}
field5:{"type":"field","size":[74,14],"pos":[37,39],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"grid\nf"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,1],"value":1},"scr":{"size":[246,99]}}}
log:{"type":"field","size":[116,129],"pos":[144,53],"volatile":1,"scrollbar":1,"style":"plain"}
field11:{"type":"field","size":[74,14],"pos":[162,38],"locked":1,"border":0,"style":"plain","align":"center","value":"log"}

{script:followermovement.0}
on click pos do
 log.text:""
 p:path.find[f pos grid]
 if p~0 log.text:"thud."
 else f.path:p
 end
end
{end}

{script:followermovement.1}
on tween t a b do
 ((1,-4)*sin t*pi)+ # bounce
 a+(b-a)*t^2        # quad ease-in
end

on finish do
 record["finish!"]
end

on step do
 record["step %i,%i" format me.pos]
end

on record x do
 log.text:log.text,"\n",x
 log.scroll:999999
end
{end}

{card:followerinteraction}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Follower interaction events"}
field2:{"type":"field","size":[236,269],"pos":[266,41],"locked":1,"border":0,"value":"The Follower contraption also supports direct interaction:\n\n- follower.draggable: if truthy, the user can click and drag to reposition this contraption.\n\n- follower.locked: if truthy, disable clicks/dragging and pause movement.\n\n- click[]: fired when the user clicks this contraption.\n\n- release[]: fired when the user completes a drag operation (if draggable)."}
button5:{"type":"button","size":[60,20],"pos":[78,316],"script":"Index.1","text":"Index","style":"rect"}
grid:{"type":"canvas","size":[128,128],"pos":[37,53],"locked":1,"image":"%%IMG2AIAAgA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANIAAQARAAEA0QABANEAAQDRAAEAEBAA4BAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QABANEAAQAQEAAQEMAAEBAQAQDRAAEA0QACANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAAEBDAABAQENEAAQDRAAEA0QABANEAEBAA4BAQ0QABANEAAQDRAAEA0QARANEAAQDRAAEA0gABANEAAQDRABEA0QABANEAAQDRAAEA0QAQEADgEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAEA0QABANEAAQDRABAQABAQwAAQEBDRAAIA0QABANEAERAAEBDAABAQEAEA0QABANEAAQDRABAQARAQwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAAQEcAAEBAQAQDRAAEA0QABANEAEBAAEBHAABAQEAEA0QABANEAAQDRABAQABARwAAQEBABANEAAQDRAAEA0QAQEAHgEBABANEAAQDRAAEA0QASAAEA0gABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QACANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEAAQDRAAEA0QABANEA==","scale":1}
f:{"type":"contraption","size":[16,16],"pos":[53,69],"script":"followerinteraction.0","show":"transparent","def":"follower","widgets":{"c":{"size":[16,16],"show":"transparent","draggable":1},"si":{"pos":[52,-38]},"ss":{"size":[100,12],"pos":[52,-11]},"sd":{"size":[100,3],"pos":[52,3],"value":1},"sp":{"size":[100,3],"pos":[52,7],"value":"{}"},"sa":{"size":[100,3],"pos":[52,11]}}}
field5:{"type":"field","size":[74,14],"pos":[64,38],"locked":1,"border":0,"style":"plain","align":"center","value":"grid"}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"f"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,0]},"scr":{"size":[246,99]}}}
field1:{"type":"field","size":[70,45],"pos":[177,96],"locked":1,"border":0,"style":"plain","align":"center","value":"drag the pawn somewhere else on the board!"}

{script:followerinteraction.0}
on release do
 f.path:path.find[f 16,16 grid]
end
{end}

{card:followeranim}
image:"%%[encoded data, 20680 characters]"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,316],"script":"Index.1","text":"Index","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,316],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,19],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Follower animation demo"}
field2:{"type":"field","size":[236,105],"pos":[266,205],"locked":1,"border":0,"value":"This demo uses the card background as the grid, with an orange color as the impassable marker. By manipulating Decker's palette it can be made visually indistinguishable from black pixels. Alternatively, you could store the passability mask on a separate card from the visible graphics.\n\nThis also demonstrates dynamically altering a Follower's \".sprite\" attribute to animate it."}
f:{"type":"contraption","size":[16,16],"pos":[160,96],"script":"followeranim.0","show":"transparent","def":"follower","widgets":{"c":{"size":[16,16],"show":"transparent"},"si":{"pos":[52,-38],"value":{"text":["i"],"font":[""],"arg":["%%IMG2ABAAEAAUAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBASACAQIgAgECIAIBAQAFAQEgCAEBAAcBCAAJAQIAAgECAAoBAgACAQIACgECAAIBAgALAQEAAgEBAAsBAgACAQIACQECAAQBAgAE"]}},"ss":{"size":[100,12],"pos":[52,-11],"value":"7"},"sd":{"size":[100,3],"pos":[52,3]},"sp":{"size":[100,3],"pos":[52,7],"value":"{\"path\":0}"},"sa":{"size":[100,3],"pos":[52,11],"value":"\"dn\""}}}
viewer:{"type":"contraption","size":[250,120],"pos":[10,190],"def":"scriptViewer","widgets":{"o":{"size":[100,24],"pos":[273,1],"value":"f\npump"},"c":{"size":[250,18]},"i":{"size":[100,30],"pos":[273,38],"interval":[0,1],"value":1},"scr":{"size":[246,99]}}}
pump:{"type":"button","size":[16,15],"pos":[418,319],"locked":1,"animated":1,"script":"followeranim.1","style":"invisible"}
anims:{"type":"field","size":[26,18],"pos":[382,318],"show":"none","value":"{\"dn\":[%%IMG2ABAAEAAUAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBASACAQIgAgECIAIBAQAFAQEgCAEBAAcBCAAJAQIAAgECAAoBAgACAQIACgECAAIBAgALAQEAAgEBAAsBAgACAQIACQECAAQBAgAE,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBASACAQIgAgECIAIBAQAFAQEgCAEBAAcBCAAJAQIAAgECAAgBBAACAQIACQEDAAIBAgAKAQEAAgECAA4BAgANAQIAEAEBAAY=,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBASACAQIgAgECIAIBAQAFAQEgCAEBAAcBCAAJAQIAAgECAAoBAgACAQQACAECAAIBAwAKAQIAAgEBAAsBAgAPAQIADQEBAAk=],\"lf\":[%%IMG2ABAAEAAUAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBAyAGAQIABgEBIAYBAwAHAQgACgECAAEBAgALAQIAAQECAAwBAgABAQEADAEBAAEBAQAMAQEAAQECAAoBAgABAQIABw==,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBAyAGAQIABgEBIAYBAwAHAQgACgEEAAkBAwABAQQABwEBAAEBBwAHAQEABgECAA8BAgAOAQIADQECAAU=,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBAyAGAQIABgEBIAYBAwAHAQgACQEFAAwBBAALAQUACQEDAAIBAgAIAQMAAwEDAAYBAQAIAQEADwECAAQ=],\"rt\":[%%IMG2ABAAEAAUAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAUBAiAGAQMABQEDIAYBAQAHAQgACQECAAEBAgALAQIAAQECAAsBAQABAQIADQEBAAEBAQANAQIAAQEBAA0BAgABAQIABA==,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAUBAiAGAQMABQEDIAYBAQAHAQgACgEEAAsBBAABAQMACAEHAAEBAQAHAQIABgEBAAYBAgAOAQIADwECAAk=,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAUBAiAGAQMABQEDIAYBAQAHAQgACgEFAAsBBAAMAQUACwECAAIBAwAIAQMAAwEDAAcBAQAIAQEABQECAAo=],\"up\":[%%IMG2ABAAEAAUAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBASAEAQIgBAEBAAUBASABAQYgAQEBAAcBCAAJAQIAAgECAAoBAgACAQIACgECAAIBAgALAQEAAgEBAAsBAgACAQIACQECAAQBAgAE,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBASAEAQIgBAEBAAUBASABAQYgAQEBAAcBCAAJAQIAAgECAAgBBAACAQIACQEDAAIBAgAKAQEAAgECAA4BAgANAQIAEAEBAAY=,%%IMG2ABAAEAAEAQgABwEBIAgBAQAFAQEgCgEBAAQBASAKAQEABAEBIAoBAQAEAQEgCgEBAAQBASAEAQIgBAEBAAUBASABAQYgAQEBAAcBCAAJAQIAAgECAAoBAgACAQQACAECAAIBAwAKAQIAAgEBAAsBAgAPAQIADQEBAAk=]}"}
field1:{"type":"field","size":[100,26],"pos":[228,150],"locked":1,"border":0,"style":"plain","align":"center","value":"click anywhere to move the little fella!"}
button3:{"type":"button","size":[179,20],"pos":[170,316],"script":"followeranim.2","text":"Show Impassable Regions","style":"check","value":0}

{script:followeranim.0}
on tween t a b do
 dir:b-a
 face:if dir[0]<0 "lf"
 elseif  dir[0]>0 "rt"
 elseif  dir[1]<0 "up"
 else             "dn" end
 ix:(0,1,0,2)[4%sys.frame/4]
 me.sprite:anims.data[face][ix]
 me.aux:face
 0 # use default tweening
end

on finish do
 me.sprite:anims.data[me.aux][0]
end
{end}

{script:followeranim.1}
on view do
 if pointer.down
  etc.move:"ortho"
  etc.block:list colors.orange
  g:pointer.pos
  f.path:path.find[f g card etc]
 end
end
{end}

{script:followeranim.2}
on click do
 patterns[colors.orange]:me.value * 16737536
end
{end}

{card:card1}
image:"%%IMG2AgABVgD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wBFAQgACAEIAP8A2QEIAAcBASAIAQEABgEBIAgBAQD/ANcBASAIAQEABQEBIAoBAQAEAQEgCgEBAP8A1QEBIAoBAQAEAQEgCgEBAAQBASAKAQEA/wDVAQEgCgEBAAQBASAKAQEABAEBIAoBAQD/ANUBASAKAQEABAEBIAoBAQAEAQEgCgEBAP8A1QEBIAoBAQAEAQEgAgECIAIBAiACAQEABAEBIAIBAiACAQIgAgEBAP8A1QEBIAIBAiACAQIgAgEBAAUBASAIAQEABgEBIAgBAQD/ANcBASAIAQEABwEIAAgBCAD/ANkBCAAJAQIAAgECAAoBAgACAQIA/wDbAQIAAgECAAgBBAACAQIACgECAAIBBAD/ANkBAgACAQIACQEDAAIBAgAKAQIAAgEDAP8A2gECAAIBAgAKAQEAAgECAAwBAgACAQEA/wDcAQEAAgEBAA4BAgAMAQIA/wDeAQIAAgECAAwBAgAOAQIA/wDcAQIABAECAA0BAQAMAQEA/wDuAQgACAEIAP8A2QEIAAcBASAIAQEABgEBIAgBAQD/ANcBASAIAQEABQEBIAoBAQAEAQEgCgEBAP8A1QEBIAoBAQAEAQEgCgEBAAQBASAKAQEA/wDVAQEgCgEBAAQBASAKAQEABAEBIAoBAQD/ANUBASAKAQEABAEBIAoBAQAEAQEgCgEBAP8A1QEBIAoBAQAEAQMgBgECAAUBAyAGAQIA/wDWAQMgBgECAAYBASAGAQMABgEBIAYBAwD/ANcBASAGAQMABwEIAAgBCAD/ANkBCAAKAQQACwEFAP8A3QECAAEBAgAIAQMAAQEEAAsBBAD/AN0BAgABAQIABwEBAAEBBwAKAQUA/wDeAQIAAQEBAAcBAQAGAQIACAEDAAIBAgD/AN4BAQABAQEAEAECAAYBAwADAQMA/wDcAQEAAQECABABAgAFAQEACAEBAP8A2gECAAEBAgAQAQIADwECAP8A6QEIAAgBCAD/ANkBCAAHAQEgCAEBAAYBASAIAQEA/wDXAQEgCAEBAAUBASAKAQEABAEBIAoBAQD/ANUBASAKAQEABAEBIAoBAQAEAQEgCgEBAP8A1QEBIAoBAQAEAQEgCgEBAAQBASAKAQEA/wDVAQEgCgEBAAQBASAKAQEABAEBIAoBAQD/ANUBASAKAQEABAEBIAQBAiAEAQEABAEBIAQBAiAEAQEA/wDVAQEgBAECIAQBAQAFAQEgAQEGIAEBAQAGAQEgAQEGIAEBAQD/ANcBASABAQYgAQEBAAcBCAAIAQgA/wDZAQgACQECAAIBAgAKAQIAAgECAP8A2wECAAIBAgAIAQQAAgECAAoBAgACAQQA/wDZAQIAAgECAAkBAwACAQIACgECAAIBAwD/ANoBAgACAQIACgEBAAIBAgAMAQIAAgEBAP8A3AEBAAIBAQAOAQIADAECAP8A3gECAAIBAgAMAQIADgECAP8A3AECAAQBAgANAQEADAEBAP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/APc="
{widgets}
sprites:{"type":"button","size":[48,48],"pos":[80,112],"show":"none"}
field1:{"type":"field","size":[112,48],"pos":[80,48],"locked":1,"value":"This is how the sprites for the follower animation demo were prepared:"}
data:{"type":"field","size":[144,112],"pos":[80,176],"volatile":1,"scrollbar":1}
button1:{"type":"button","size":[60,20],"pos":[144,128],"script":"card1.0","text":"Export"}

{script:card1.0}
on click do
 s:16,16
 i:card.image.copy[sprites.pos sprites.size]
 frames:each pos in flip s*flip 3 cross 3 i.copy[pos s] end
 
 anim.dn: frames @ 0,1,2
 anim.lf: frames @ 3,4,5
 anim.rt:(frames @ 3,4,5)..copy[].transform.horiz
 anim.up: frames @ 6,7,8
 
 data.data:anim
end
{end}

{module:path}
description:"generic grid-based pathfinding routines"
version:1.1
{script}
local default_cell:16,16
local minusone:0|-1+range 256
local rects:"|"split"field|button|canvas|grid|slider|contraption|dict"
local deltas:"%j" parse "{l}
 'ortho'    :[[-1,0],[0,-1],[1,0],[0,1]],
 'diag'     :[[-1,-1],[1,-1],[1,1],[-1,1]],
 'orthodiag':[[-1,0],[0,-1],[1,0],[0,1],[-1,-1],[1,-1],[1,1],[-1,1]],
{r}"
on is_rect x do (typeof x) in rects     end
on is_pair x do "number"~typeof first x end

module.to_cell:on to_cell x mask etc do
 local off:(0,0) unless mask.pos
 local cell:default_cell unless etc.cell
 on scr_to_cell x do floor ((-off)+x.pos+.5*x.size)/cell end # rect
 on rel_to_cell x do floor x                       /cell end # pair
 # pos can be a pair, rect, or list of pairs/rects
 if     is_rect[x]  scr_to_cell[x]
 elseif is_pair[x]  rel_to_cell[x]
 else
  each v in x
   if is_rect[v] scr_to_cell[v] else rel_to_cell[v] end
  end
 end
end
module.to_pix:on to_pix x etc do
 local cell:default_cell unless etc.cell
 if x
  if is_pair[x] (.5*cell)+cell*x   # single pair
  else flip (.5*cell)+cell*flip x  # list of pairs
  end
 end
end

module.test_cell:on test_cell pos mask etc do
 if "card"~typeof mask  mask:mask.image end       # card | canvas | image
 local cell :default_cell unless etc.cell         # pair
 local block:(list 1) unless etc.block            # list
 local s:floor mask.size/cell
 (min(pos>-1)&(pos<s))&!sum mask.copy[pos*cell cell].hist @ block
end
module.test:on test pos mask etc do
 test_cell[to_cell[pos] mask etc]
end
module.testall:on testall mask etc do
 if "card"~typeof mask  mask:mask.image end       # card | canvas | image
 local cell :default_cell unless etc.cell         # pair
 local block:(list 1) unless etc.block            # list
 local s:floor mask.size/cell
 local r:image[s]
 r.pixels:each pos in s[0] cross s[1]
  !sum mask.copy[pos*cell cell].hist @ block
 end
 r
end

module.find_cell:on find_cell start goal mask etc do
 start:floor start                                # pair | list-of-pair
 goal :floor goal                                 # pair
 local tmove:deltas["orthodiag" unless etc.move]  # str | list-of-pair
 if tmove~0 tmove:etc.move end
 local move :flip tmove                           # str
 local p:testall[mask etc]
 # parallel flood-fill maximum scent:
 local changed:1
 local v:image[p.size]
 v[goal]:255*p[goal]
 while changed
  local t:v.copy[].map[minusone]
  local n:v.copy[]
  each delta in tmove
   n.merge["|" t.copy[].translate[delta]]
  end
  n.merge["*" p]
  changed:!n.pixels~v.pixels
  v:n
 end
 # walk the flood-filled matrix to extract a max-scent path
 # if the goal is unreachable, return 0:
 on getpath here do
  if (max v @ flip move + here)&p[here]
   local r:list here
   if etc.shuffle # choose randomly from among equal-scent trails
    while (255>count r)&!here~goal
     here:first extract orderby v @ value desc from flip random[move (-count move)]+here
     r:r,list here
    end
   else # choose first-visited from among equal-scent trails
    while (255>count r)&!here~goal
     here:first extract orderby v @ value desc from flip move+here
     r:r,list here
    end
   end
   r
  end
 end
 # accept a single start or a list of starts:
 if is_pair[start] getpath[start] else getpath@start end
end
module.find:on find start goal mask etc do
 local off:(0,0) unless mask.pos
 local cell:default_cell unless etc.cell
 on cell_to_scr x do if x flip off+(.5*cell)+cell*flip x end end # 0 | list-of-pair
 on cell_to_rel x do if x flip     (.5*cell)+cell*flip x end end # 0 | list-of-pair
 local sc:to_cell[start mask etc] # rect | pair | list of either
 local gc:to_cell[ goal mask etc] # rect | pair
 r:find_cell[sc gc mask etc]
 # result(s) will be in the same coordinate system as start(s):
 if     is_rect[start]  cell_to_scr[r]
 elseif is_pair[start]  cell_to_rel[r]
 else
  each v i in start
   if is_rect[v] cell_to_scr[r[i]] else cell_to_rel[r[i]] end
  end
 end
end

module.closest_cell:on closest_cell x tolerance mask etc do
 # find the closest passable cell on the mask to x,
 # using a search radius of 'tolerance', or return 0
 local cell :default_cell unless etc.cell # pair
 local block:(list 1) unless etc.block    # list
 local s:floor mask.size/cell
 on passable x do
  if (min x>-1)&(min x<s)
   !sum mask.copy[x*cell cell].hist @ block
  end
 end
 if passable[x] x else
  cells:((2*tolerance) cross (2*tolerance))-tolerance
  if etc.shuffle cells:random[cells (-count cells)] end
  grid:extract orderby mag@value asc from cells
  first extract where passable@value from flip x+flip grid
 end
end
module.closest:on closest start tolerance mask etc do
 local off:(0,0) unless mask.pos
 local cell:default_cell unless etc.cell
 on cell_to_scr x do if x off+(.5*cell)+cell*x end end # 0 | pair
 on cell_to_rel x do if x     (.5*cell)+cell*x end end # 0 | pair
 local sc:to_cell[start mask etc] # rect | pair
 local r:closest_cell[sc tolerance mask etc]
 # result will be in the same coordinate system as start:
 if is_rect[start] cell_to_scr[r] else cell_to_rel[r] end
end
{end}

{contraption:follower}
size:[100,100]
resizable:1
margin:[1,1,1,1]
description:"A semi-autonomous \"agent\" that can animate itself along a provided path of waypoints."
version:1.1
script:"follower.0p"
template:"on finish do end\non step do end\non tween t a b do end\non click do end\non release do end"
attributes:{"name":["sprite","speed","draggable"],"label":["Sprite","Frames per step","Draggable"],"type":["rich","number","bool"]}
{widgets}
c:{"type":"canvas","size":[100,100],"pos":[0,0],"locked":1,"volatile":1,"border":0,"scale":1}
si:{"type":"field","size":[100,20],"pos":[136,-38],"locked":1,"show":"none","value":{"text":["","i"],"font":["",""],"arg":["","%%IMG2ABAAEAAFIAUACiABAQUgAQAIIAEBAyADAQEgAQAHIAEBBSABAQEgAQAHIAEBByABAAggAQEFIAEACiABAQMgAQALIAEBAyABAAsgAQEDIAEACiABAQUgAQAIIAIBAyABAQIgAQAGIAEBBiABAQIgAQAEIAEBCCABAQIgAQADIAEBCSABAQIgAQADIAEBCiABAAUgCgAD"]}}
ss:{"type":"field","size":[100,20],"pos":[136,-11],"locked":1,"show":"none","style":"plain","value":"10"}
sd:{"type":"button","size":[100,20],"pos":[136,16],"locked":1,"show":"none","style":"check"}
sp:{"type":"field","size":[100,20],"pos":[136,43],"locked":1,"show":"none","style":"plain"}
sa:{"type":"field","size":[100,20],"pos":[136,69],"locked":1,"show":"none","border":0,"style":"plain"}

{script:follower.0p}
on get_animate do view end
on get_speed do 0+ss.text end
on set_speed x do ss.text:1|x end
on get_draggable do sd.value end
on set_draggable x do sd.value:x end
on get_sprite do si.value end
on set_sprite x do si.value:x update_view[] end
on get_aux do sa.data end
on set_aux x do sa.data:x end
on get_done do c.animated~0 end
on get_path do () unless sp.data.path end
on set_path x do
 if !x~() # animate along path
  sp.data:().path:x
  c.animated:x
 end
end
on click do
 if !card.locked
  card.event.click
  if get_draggable[] set_path[0] end
 end
end
on drag pos do
 if get_draggable[]&!card.locked
  card.pos:pointer.pos-c.size/2
  c.pos:0,0
 end
end
on release do
 if get_draggable[]&!card.locked
  card.event.release
 end
end
on update_view do
 i:first si.images
 c.clear[]
 c.paste[i .5*c.size-i.size]
 c.show:card.show
 c.draggable:get_draggable[]
end
on view do
 if c.animated&!card.locked
  fin:0
  stp:0
  s:sp.data
  if 1~count s.path # direct warp; no tween
   card.pos:(first s.path)-.5*card.size
   sp.data:().path:()
   c.animated:0
   fin:1
  elseif s.i>get_speed[]-1
   stp:1
   if s.s>(count s.path)-3
    c.animated:0
    s:()dict()
    fin:1
   else
    s.s:s.s+1
    s.i:0
   end
   sp.data:s
  else
   tt:s.i/get_speed[]-1
   ta:s.path[s.s]
   tb:s.path[s.s+1]
   s.i:s.i+1
   sp.data:s
   t:(ta+tt*tb-ta) unless card.event["tween" tt ta tb]
   card.pos:t-.5*card.size
  end
  if stp card.event.step   end
  if fin card.event.finish end
 end
 update_view[]
end
{end}

{contraption:scriptViewer}
size:[100,100]
resizable:1
margin:[3,20,3,3]
description:"a tabbed editor for viewing and editing the scripts of one or more widgets on the current card."
version:1
image:"%%IMG2AGQAZAD/AP8A/wD/AP8A/wCqAWUgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAWU="
script:"scriptViewer.0p"
attributes:{"name":["options_text"],"label":["Sources"],"type":["code"]}
{widgets}
o:{"type":"field","size":[100,20],"pos":[123,1],"show":"none","style":"plain","value":"card"}
c:{"type":"canvas","size":[100,18],"pos":[0,0],"locked":1,"volatile":1,"show":"transparent","border":0,"pattern":32,"scale":1}
i:{"type":"slider","size":[100,25],"pos":[123,32],"show":"none","interval":[0,2]}
scr:{"type":"field","size":[96,79],"pos":[2,19],"volatile":1,"border":0,"scrollbar":1,"style":"code"}

{script:scriptViewer.0p}
on get_options_text do o.text end
on set_options_text x do
 o.text:x
 i.interval:0,(count "\n" split o.text)-1
 view[]
end
on get_options do "\n" split o.text end
on set_options x do set_options_text["\n" fuse x] x end
on get_value do get_options[][i.value] end
on set_value x do v:get_options[] i.value:sum (range count v)*v=x x view[] end

bf:image["%%IMG2AAsABwADAQUABQEBIAUBAQADAQEgBwEBAAEBASAJAQIgCQECIAkBDA=="] bb:image["%%IMG2AAsABwADAQUABQEBIAUBAQADAQEgAQEFIAEBAQABAQEgAQEHIAEBAiABAQcgAQECIAEBByABAQIgAQEHIAEBAQ=="]

on target do
 val:get_value[]
 if val~"deck" deck elseif val~"card" deck.card else deck.card.widgets[val] end
end
on change do
 target[].script:scr.text
end

on view do
 c.font:card.font
 c.clear[]
 v:get_options[]
 w:(.7*c.size[0])/count v
 each x ix in v
  sel:ix~i.value
  b:(ix*w),0,(w+ix<-1+count v),c.size[1]
  c.segment[(bf,bb)[sel] b 5,4,5,2]
  c.pattern:(1,32)[sel]
  c.text[x b+(0,1,0,0) "center"]
 end
 scr.text:target[].script
 scr.locked:card.locked
end

on click pos do
 v:get_options[]
 w:(.7*c.size[0])/count v
 set_value[v[floor(first pos)/w]]
end
{end}

