spacepaste

  1.  
  2. local util = require("util")
  3. local robot = require("robot")
  4. local config_file = "state.cfg"
  5. local libnav = {
  6. str = "",
  7. _navlog = "",
  8. retry = true,
  9. breaking = false,
  10. }
  11. function libnav.get_location()
  12. return util.config_get(config_file, "location", "")..libnav.str
  13. end
  14. local function log_flush()
  15. local state = util.config(config_file)
  16. local place = state:get("location", "")
  17. place = place .. libnav._navlog
  18. libnav._navlog = ""
  19. state:set("location", place)
  20. state:close()
  21. end
  22. local function log_assert(cond)
  23. if not cond then log_flush() end
  24. assert(cond)
  25. end
  26. local function record(str)
  27. libnav._navlog = libnav._navlog .. str
  28. end
  29. function retry_loop(fn, swingfn, msg)
  30. while true do
  31. if fn() then break end
  32. if libnav.breaking and swingfn then
  33. swingfn()
  34. end
  35. if fn() then break end
  36. if libnav.retry then
  37. os.sleep(1)
  38. else
  39. log_assert(false, msg)
  40. end
  41. end
  42. end
  43. local function _up()
  44. retry_loop(robot.up, robot.swingUp, "can't move up")
  45. record("u")
  46. end
  47. local function _down()
  48. retry_loop(robot.down, robot.swingDown, "can't move down")
  49. record("d")
  50. end
  51. local function _turnLeft()
  52. retry_loop(robot.turnLeft, nil, "can't turn left")
  53. record("l")
  54. end
  55. local function _turnRight()
  56. retry_loop(robot.turnRight, nil, "can't turn right")
  57. record("r")
  58. end
  59. local function _forward()
  60. retry_loop(robot.forward, robot.swing, "can't move forward")
  61. record("f")
  62. end
  63. local function _back()
  64. retry_loop(robot.back, nil, "can't move back")
  65. record("b")
  66. end
  67. local function _brk()
  68. libnav.breaking = true
  69. record("X")
  70. end
  71. local function _unbrk()
  72. libnav.breaking = false
  73. record("x")
  74. end
  75. function libnav.add(str)
  76. libnav.str = libnav.str .. str
  77. end
  78. function libnav.up() libnav.add("u")
  79. end
  80. function libnav.down() libnav.add("d")
  81. end
  82. function libnav.left() libnav.add("l")
  83. end
  84. function libnav.right() libnav.add("r")
  85. end
  86. function libnav.fwd() libnav.add("f")
  87. end
  88. function libnav.back() libnav.add("b")
  89. end
  90. function libnav.brk() libnav.add("X")
  91. end
  92. function libnav.unbrk() libnav.add("x")
  93. end
  94. function libnav.opt(str)
  95. -- todo optimize
  96. local bak = str
  97. while true do
  98. local prev = str
  99. str = str
  100. :gsub("ud", ""):gsub("du", "")
  101. :gsub("fb", ""):gsub("bf", "")
  102. :gsub("rl", ""):gsub("lr", "")
  103. :gsub("llll", ""):gsub("rrrr", "")
  104. :gsub("fllf", "ll"):gsub("frrf", "rr")
  105. :gsub("bllb", "ll"):gsub("brrb", "rr")
  106. :gsub("dllu", "ll"):gsub("drru", "rr")
  107. :gsub("ulld", "ll"):gsub("urrd", "rr")
  108. :gsub("dlu", "l"):gsub("dru", "r")
  109. :gsub("uld", "l"):gsub("urd", "r")
  110. :gsub("dfu", "f"):gsub("dbu", "b")
  111. :gsub("ufd", "f"):gsub("ubd", "b")
  112. :gsub("lll", "r"):gsub("rrr", "l")
  113. -- move all rotations down so they can cancel
  114. :gsub("ul", "lu"):gsub("ur", "ru")
  115. :gsub("ld", "dl"):gsub("rd", "dr")
  116. :gsub("frfrf", "rfr"):gsub("flflf", "lfl")
  117. :gsub("frflb", "rfl"):gsub("flfrb", "lfr")
  118. if prev == str then break end
  119. end
  120. -- print("opt "..bak.." => "..str)
  121. return str;
  122. end
  123. function libnav.flush()
  124. local actions = {
  125. u = _up,
  126. d = _down,
  127. l = _turnLeft,
  128. r = _turnRight,
  129. f = _forward,
  130. b = _back,
  131. X = _brk,
  132. x = _unbrk,
  133. }
  134. local str = libnav.opt(libnav.str)
  135. libnav.str = ""
  136. for i = 1, str:len() do
  137. local ch = str:sub(i, i)
  138. local action = actions[ch]
  139. assert(action)
  140. action()
  141. end
  142. log_flush()
  143. -- optimize location
  144. local state = util.config(config_file)
  145. local location = state:get("location", "")
  146. location = libnav.opt(location)
  147. state:set("location", location)
  148. state:close()
  149. end
  150. function libnav.estimate_and_discard()
  151. local str = libnav.opt(libnav.str)
  152. libnav.str = ""
  153. return str:len()
  154. end
  155. function libnav.invert(movestr)
  156. local res = ""
  157. local flips = {
  158. u = "d",
  159. d = "u",
  160. l = "r",
  161. r = "l",
  162. f = "f",
  163. b = "b",
  164. x = "X",
  165. X = "x",
  166. }
  167. for i = movestr:len(), 1, -1 do
  168. local ch = movestr:sub(i, i)
  169. local flip = flips[ch]
  170. assert(flip)
  171. res = res .. flip
  172. end
  173. return "rr" .. res .. "rr"
  174. end
  175. -- go to where 'libnav.get_location()' was 'loc'
  176. function libnav.go_to(loc)
  177. libnav.add(libnav.invert(libnav.get_location()))
  178. libnav.add(loc)
  179. end
  180. return libnav
  181.