Advertisement
Tag365

FlutterFile

Apr 13th, 2017
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 161.04 KB | None | 0 0
  1. {
  2. [ "Flutter/Programs/find" ] = "textutils.pagedTabulate(index.searchFileNames(... or \"\"))",
  3. [ "Flutter/Programs/levels/12" ] = "6\
  4. 77 777 77\
  5. 72888888897\
  6. 8 8 8\
  7. 8 8b888 8\
  8. 78 e8888 87\
  9. 78888788887\
  10. 78 8888e 87\
  11. 8 888b8 8\
  12. 8 8 8\
  13. 75888888807\
  14. 77 777 77",
  15. [ "Flutter/Apis/index" ] = "local indexedFiles = {} -- This table is used to store indexed file contents.\
  16. local fileContentIndex = {} -- This table is used to store file content matches.\
  17. local fileNameIndex = {} -- This table is used to store file name matches.\
  18. \
  19. -- This is an internal function called by updateIndex to initalize the search index.\
  20. function updateIndexFile(path)\
  21. indexedFiles[path] = \"\"\
  22. local file = fs.open(path, \"r\")\
  23. if file then\
  24. local line = file.readAll()\
  25. file.close()\
  26. indexedFiles[path] = line\
  27. else\
  28. indexedFiles[path] = \"\"\
  29. end\
  30. end\
  31. \
  32. -- This is an internal function called by rebuildIndex to initalize the search index.\
  33. -- It loops through the directory list and calls itself if it finds a directory.\
  34. function updateIndex(path)\
  35. if fs.isDir(path) then\
  36. for k, v in pairs(fs.list(path)) do\
  37. if fs.isDir(path..\"/\"..v) then\
  38. updateIndex(path..\"/\"..v)\
  39. else\
  40. updateIndexFile(path..\"/\"..v)\
  41. end\
  42. end\
  43. elseif fs.exists(path) then\
  44. updateIndexFile(path)\
  45. end\
  46. end\
  47. \
  48. -- This is an internal function run by Lua Script System to initalize the search index.\
  49. -- It is run on startup to initalize the index. If you are not using LuaSS then you need to run this before the\
  50. -- first time you search files using the searchFiles or searchFileName functions given by this API.\
  51. -- Currently it just calls updateIndex to index the root directory.\
  52. function rebuildIndex()\
  53. updateIndex(\"\")\
  54. end\
  55. \
  56. -- This is an internal function used to check if a file should be included in the table returned by searchFiles.\
  57. function findStringInIndexSearchFiles(path, sSearch)\
  58. local contents = indexedFiles[path]\
  59. local startHere = 0\
  60. while true do\
  61. local nextSlash = string.find(string.sub(contents, startHere, -1), sSearch)\
  62. if not nextSlash then\
  63. return\
  64. else\
  65. fileContentIndex[sSearch][#fileContentIndex[sSearch] + 1] = path\
  66. return true\
  67. end\
  68. nextSlash = nextSlash + startHere\
  69. tab = tab + 1\
  70. startHere = nextSlash\
  71. end\
  72. end\
  73. \
  74. -- This is an internal function used to check if a file should be included in the table returned by searchFileNames.\
  75. function findStringInIndexSearchFileNames(path, sSearch)\
  76. local match = string.find(path, sSearch)\
  77. if match then\
  78. fileNameIndex[sSearch][#fileNameIndex[sSearch] + 1] = path\
  79. return true\
  80. end\
  81. end\
  82. \
  83. -- This function searches inside files for the searchstring sSearch.\
  84. function searchFiles(sSearch)\
  85. local tab = fileContentIndex[sSearch]\
  86. if tab then\
  87. return tab\
  88. else\
  89. fileContentIndex[sSearch] = {}\
  90. for k, v in pairs(indexedFiles) do\
  91. findStringInIndexSearchFiles(k, sSearch)\
  92. end\
  93. return fileContentIndex[sSearch]\
  94. end\
  95. end\
  96. \
  97. -- This function searches for files with names that include the string sSearch.\
  98. function searchFileNames(sSearch)\
  99. local tab = fileNameIndex[sSearch]\
  100. if tab then\
  101. return tab\
  102. else\
  103. fileNameIndex[sSearch] = {}\
  104. for k, v in pairs(indexedFiles) do\
  105. findStringInIndexSearchFileNames(k, sSearch)\
  106. end\
  107. return fileNameIndex[sSearch]\
  108. end\
  109. end",
  110. [ "Flutter/Programs/edit" ] = "-- Get file to edit\
  111. local tArgs = { ... }\
  112. _G.EditSplashStatus = (_G.EditSplashStatus or 0) + 1\
  113. if #tArgs == 0 then\
  114. print( \"Usage: edit <path> [line number]\" )\
  115. return\
  116. end\
  117. \
  118. -- Error checking\
  119. local sPath = shell.resolve( tArgs[1] )\
  120. local bReadOnly = fs.isReadOnly( sPath )\
  121. if fs.exists( sPath ) and fs.isDir( sPath ) then\
  122. print( sPath..\" is a directory, not a file. Please type in an actual file name.\" )\
  123. return\
  124. end\
  125. \
  126. local showLineNumberSidebar = true\
  127. local x,y = 1,1\
  128. local shiftX = 0\
  129. if type(tonumber(tArgs[2])) == \"number\" then\
  130. y = math.floor(math.max(tArgs[2], 1))\
  131. end\
  132. local w,h = term.getSize()\
  133. local scrollX, scrollY = 0,y - 1\
  134. \
  135. local tLines = {}\
  136. local bRunning = true\
  137. \
  138. -- Code Highlighting Colors\
  139. local highlightColor, keywordColor, commentColor, textColor, bgColor, menuBgColor\
  140. if term.isColor() then\
  141. menuBgColor = colors.gray\
  142. bgColor = colors.black\
  143. textColor = colors.white\
  144. highlightColor = colors.yellow\
  145. keywordColor = colors.blue\
  146. commentColor = colors.green\
  147. stringColor = colors.red\
  148. else\
  149. menuBgColor = colors.black\
  150. bgColor = colors.black\
  151. textColor = colors.white\
  152. highlightColor = colors.white\
  153. keywordColor = colors.white\
  154. commentColor = colors.white\
  155. stringColor = colors.white\
  156. end\
  157. \
  158. -- Menus\
  159. local bMenu = false\
  160. local nMenuItem = 1\
  161. local tMenuItems = { \"Exit\", \"Go To\", \"Test\", \"Find\", \"Replace\", \"Add Bookmark\", \"Bookmarks\" }\
  162. if not bReadOnly then\
  163. table.insert( tMenuItems, 1, \"Save\" )\
  164. else\
  165. table.insert( tMenuItems, 1, \"Save As...\" )\
  166. end\
  167. if peripheral.find( \"printer\" ) then\
  168. table.insert( tMenuItems, \"Print\" )\
  169. end\
  170. \
  171. local tSplashStatus = {\
  172. \"Press Ctrl to access menu.\",\
  173. \"Press Ctrl to access the extended menu, with more options than the default Editor included with ComputerCraft.\",\
  174. \"The status bar shows the results of an action you made.\",\
  175. \"When attempting to edit a read-only file, use the Save As... function to start editing a new file.\",\
  176. \"Adding an Editor Bookmark will cause the built in Autocomplete feature to automatically include that line in the list of lines to show.\",\
  177. \"Bookmarks can be accessed by clicking on the Bookmark button.\",\
  178. }\
  179. \
  180. local sStatus = tSplashStatus[1 + ((_G.EditSplashStatus - 1)%#tSplashStatus)]\
  181. local nStatusScroll = -1\
  182. \
  183. local function updateSidebar()\
  184. -- If line numbers are enabled then fix the shiftX variable\
  185. if showLineNumberSidebar then\
  186. local curPower = #tLines\
  187. local power = 1\
  188. while curPower >= 10 do\
  189. curPower = curPower/10\
  190. power = power + 1\
  191. end\
  192. shiftX = power + 2\
  193. else\
  194. shiftX = 0\
  195. end\
  196. end\
  197. \
  198. local function load( _sPath )\
  199. tLines = {}\
  200. if fs.exists( _sPath ) then\
  201. local file = io.open( _sPath, \"r\" )\
  202. local sLine = file:read()\
  203. while sLine do\
  204. table.insert( tLines, sLine )\
  205. sLine = file:read()\
  206. end\
  207. file:close()\
  208. end\
  209. \
  210. if #tLines == 0 then\
  211. table.insert( tLines, \"\" )\
  212. end\
  213. end\
  214. \
  215. local function save( _sPath )\
  216. -- Create intervening folder\
  217. local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )\
  218. if not fs.exists( sDir ) then\
  219. fs.makeDir( sDir )\
  220. end\
  221. \
  222. -- Save\
  223. local file = nil\
  224. local function innerSave()\
  225. file = fs.open( _sPath, \"w\" )\
  226. if file then\
  227. for n, sLine in ipairs( tLines ) do\
  228. file.write( sLine .. \"\\n\" )\
  229. end\
  230. else\
  231. error( \"Failed to open \".._sPath )\
  232. end\
  233. end\
  234. \
  235. local ok = pcall( innerSave )\
  236. if file then \
  237. file.close()\
  238. end\
  239. return ok\
  240. end\
  241. \
  242. -- Lua keywords\
  243. local tKeywords = {\
  244. [\"and\"] = true,\
  245. [\"break\"] = true,\
  246. [\"do\"] = true,\
  247. [\"else\"] = true,\
  248. [\"elseif\"] = true,\
  249. [\"end\"] = true,\
  250. [\"false\"] = true,\
  251. [\"for\"] = true,\
  252. [\"function\"] = true,\
  253. [\"if\"] = true,\
  254. [\"in\"] = true,\
  255. [\"local\"] = true,\
  256. [\"nil\"] = true,\
  257. [\"not\"] = true,\
  258. [\"or\"] = true,\
  259. [\"repeat\"] = true,\
  260. [\"return\"] = true,\
  261. [\"then\"] = true,\
  262. [\"true\"] = true,\
  263. [\"until\"] = true,\
  264. [\"while\"] = true,\
  265. }\
  266. \
  267. local function tryWrite( sLine, regex, color )\
  268. local match = string.match( sLine, regex )\
  269. if match then\
  270. if type(color) == \"number\" then\
  271. term.setTextColor( color )\
  272. else\
  273. term.setTextColor( color(match) )\
  274. end\
  275. term.write( match )\
  276. term.setTextColor( textColor )\
  277. return string.sub( sLine, string.len(match) + 1 )\
  278. end\
  279. return nil\
  280. end\
  281. \
  282. local function writeHighlighted( sLine )\
  283. while string.len(sLine) > 0 do \
  284. sLine = \
  285. tryWrite( sLine, \"^%-%-%[%[.-%]%]\", commentColor ) or\
  286. tryWrite( sLine, \"^%-%-.*\", commentColor ) or\
  287. tryWrite( sLine, \"^\\\".-[^\\\\]\\\"\", stringColor ) or\
  288. tryWrite( sLine, \"^\\'.-[^\\\\]\\'\", stringColor ) or\
  289. tryWrite( sLine, \"^%[%[.-%]%]\", stringColor ) or\
  290. tryWrite( sLine, \"^[%w_]+\", function( match )\
  291. if tKeywords[ match ] then\
  292. return keywordColor\
  293. end\
  294. return textColor\
  295. end ) or\
  296. tryWrite( sLine, \"^[^%w_]\", textColor )\
  297. end\
  298. end\
  299. \
  300. local tCompletions\
  301. local nCompletion\
  302. \
  303. local tCompleteEnv = _ENV\
  304. local function complete( sLine )\
  305. local nStartPos = string.find( sLine, \"[a-zA-Z0-9_%.]+$\" )\
  306. if nStartPos then\
  307. sLine = string.sub( sLine, nStartPos )\
  308. end\
  309. if #sLine > 0 then\
  310. return textutils.complete( sLine, tCompleteEnv )\
  311. end\
  312. return nil\
  313. end\
  314. \
  315. local function recomplete()\
  316. local sLine = tLines[y]\
  317. if not bMenu and not bReadOnly and x == string.len(sLine) + 1 then\
  318. tCompletions = complete( sLine )\
  319. if tCompletions and #tCompletions > 0 then\
  320. nCompletion = 1\
  321. else\
  322. nCompletion = nil\
  323. end\
  324. else\
  325. tCompletions = nil\
  326. nCompletion = nil\
  327. end\
  328. end\
  329. \
  330. local function eliminatePoint(num)\
  331. local str = tostring(num)\
  332. if str:find(\".\") then\
  333. return str:sub(1, -1)\
  334. end\
  335. return str\
  336. end\
  337. \
  338. local function writeCompletion( sLine )\
  339. if nCompletion then\
  340. local sCompletion = tCompletions[ nCompletion ]\
  341. term.setTextColor( colors.white )\
  342. term.setBackgroundColor( colors.gray )\
  343. term.write( sCompletion )\
  344. term.setTextColor( textColor )\
  345. term.setBackgroundColor( bgColor )\
  346. end\
  347. end\
  348. \
  349. local function redrawText()\
  350. updateSidebar()\
  351. local cursorX, cursorY = x, y\
  352. for y=1,h-1 do\
  353. term.setCursorPos( 1 + (shiftX) - scrollX, y )\
  354. term.clearLine()\
  355. \
  356. local sLine = tLines[ y + scrollY ]\
  357. if sLine ~= nil then\
  358. writeHighlighted( sLine )\
  359. if cursorY == y and cursorX == #sLine + 1 then\
  360. writeCompletion()\
  361. end\
  362. end\
  363. term.setCursorPos( 1, y )\
  364. term.setBackgroundColor( menuBgColor )\
  365. term.write(string.rep(\" \", shiftX - 1))\
  366. term.setCursorPos( shiftX - (1 + #eliminatePoint(y + scrollY)), y )\
  367. if y + scrollY <= #tLines then\
  368. term.write( eliminatePoint(y + scrollY ))\
  369. end\
  370. term.setBackgroundColor( bgColor )\
  371. end\
  372. term.setCursorPos( x + (shiftX) - scrollX, y - scrollY )\
  373. end\
  374. \
  375. local function redrawLine(_nY)\
  376. updateSidebar()\
  377. local sLine = tLines[_nY]\
  378. if sLine then\
  379. local y = _nY - scrollY\
  380. term.setCursorPos( 1 + (shiftX) - scrollX, y )\
  381. term.clearLine()\
  382. writeHighlighted( sLine )\
  383. if _nY == y and x == #sLine + 1 then\
  384. writeCompletion()\
  385. end\
  386. term.setCursorPos( 1, y )\
  387. term.setBackgroundColor( menuBgColor )\
  388. term.write(string.rep(\" \", shiftX - 1))\
  389. term.setCursorPos( shiftX - 1 - #eliminatePoint(y + scrollY), y )\
  390. if y + scrollY <= #tLines then\
  391. term.write( eliminatePoint(y + scrollY) )\
  392. end\
  393. term.setCursorPos( 1 + (shiftX + #sLine) - scrollX, y )\
  394. writeCompletion()\
  395. term.setBackgroundColor( bgColor )\
  396. term.setCursorPos( x + (shiftX) - scrollX, _nY - scrollY )\
  397. end\
  398. end\
  399. \
  400. local function getScroll(value)\
  401. if value%4 < 1 then\
  402. return value%4\
  403. elseif value%4 >= 1 and value%4 <= 2 then\
  404. return 1\
  405. elseif value%4 <= 3 then\
  406. return math.max(3-(value%4), 0)\
  407. elseif value%4 > 3 then\
  408. return 0.01\
  409. end\
  410. end\
  411. \
  412. local function redrawMenu()\
  413. updateSidebar()\
  414. \
  415. -- Clear line\
  416. term.setCursorPos( 1, h )\
  417. term.setBackgroundColor(menuBgColor)\
  418. term.clearLine()\
  419. \
  420. term.setCursorPos( 1, h )\
  421. if bMenu then\
  422. local startingXPos = 1\
  423. local totalWidthOfOptions = 0\
  424. for nItem, sItem in pairs( tMenuItems ) do\
  425. if nItem >= nMenuItem - ((w > 33 and 1) or 0) then\
  426. if startingXPos < 1 then\
  427. startingXPos = startingXPos + 1\
  428. end\
  429. break\
  430. end\
  431. startingXPos = startingXPos - (#sItem + 2)\
  432. end\
  433. term.setCursorPos( startingXPos, h )\
  434. -- Draw menu\
  435. term.setTextColor( textColor )\
  436. for nItem, sItem in pairs( tMenuItems ) do\
  437. if nItem == nMenuItem then\
  438. term.setTextColor( highlightColor )\
  439. term.write( \"[\" )\
  440. term.setTextColor( textColor )\
  441. term.write( sItem )\
  442. term.setTextColor( highlightColor )\
  443. term.write( \"]\" )\
  444. term.setTextColor( textColor )\
  445. else\
  446. term.write( \" \"..sItem..\" \" )\
  447. end\
  448. totalWidthOfOptions = totalWidthOfOptions + (#sItem + 2)\
  449. end\
  450. \
  451. -- Draw indicators that there are more options available.\
  452. if startingXPos < 1 then\
  453. term.setCursorPos( 1, h )\
  454. term.write(\"<\")\
  455. end\
  456. \
  457. w,h = term.getSize()\
  458. if -startingXPos + w < totalWidthOfOptions then\
  459. term.setCursorPos( w, h )\
  460. term.write(\">\")\
  461. end\
  462. else\
  463. local scrollWidth = math.max(#sStatus - (w - 2) + string.len( \"Ln \"..y ), 0)\
  464. nStatusScroll = nStatusScroll + (w/math.max(scrollWidth, 1))/100\
  465. local statusScroll = getScroll(nStatusScroll)\
  466. term.setCursorPos( 1, h )\
  467. -- Draw status\
  468. term.setTextColor( highlightColor )\
  469. term.write( sStatus:sub(statusScroll*scrollWidth) )\
  470. term.setTextColor( textColor )\
  471. -- Draw line numbers\
  472. term.setCursorPos( w - string.len( \"Ln \"..y ), h )\
  473. term.setTextColor( highlightColor )\
  474. term.write( \" Ln \" )\
  475. term.setTextColor( textColor )\
  476. term.write( y )\
  477. end\
  478. \
  479. term.setBackgroundColor(bgColor)\
  480. -- Reset cursor\
  481. term.setCursorPos( x + (shiftX) - scrollX, y - scrollY )\
  482. end\
  483. \
  484. local tMenuFuncs = { \
  485. Save=function()\
  486. if bReadOnly then\
  487. sStatus = \"That location is read only.\"\
  488. else\
  489. local ok, err = save( sPath )\
  490. if ok then\
  491. sStatus=\"Saved to \"..sPath\
  492. else\
  493. sStatus=\"Error saving to \"..sPath\
  494. end\
  495. end\
  496. redrawMenu()\
  497. end,\
  498. Test=function()\
  499. -- Convert the table into a string that we can load\
  500. local scriptCode = tLines[1] or \"\"\
  501. for k, v in ipairs(tLines) do\
  502. if k > 1 then\
  503. scriptCode = scriptCode..\"\\n\"..v\
  504. end\
  505. end\
  506. -- Run the script\
  507. local fScript, err = loadstring(scriptCode, \"Script\")\
  508. if fScript then\
  509. term.setTextColor(colors.white)\
  510. term.setCursorPos(1, 1)\
  511. term.clear()\
  512. local ok, msg = pcall(fScript)\
  513. sStatus = tostring(msg)\
  514. -- Print the error\
  515. if sStatus == \"nil\" then\
  516. sStatus = \"Script ran successfully.\"\
  517. else\
  518. local c1 = (sStatus:find(']:', 0, true) or 0) + 1\
  519. sStatus = sStatus:sub(c1)\
  520. end\
  521. term.setBackgroundColor(colors.black)\
  522. term.setTextColor(colors.white)\
  523. redrawText()\
  524. redrawMenu()\
  525. else\
  526. if err then\
  527. local c1 = err:find(']:', 0, true) + 1\
  528. sStatus = \"Script\"..err:sub(c1)\
  529. else\
  530. sStatus = \"Error compiling script.\"\
  531. end\
  532. end\
  533. end,\
  534. Find=function()\
  535. term.setCursorPos(1, h)\
  536. term.setBackgroundColor(menuBgColor)\
  537. term.clearLine()\
  538. term.write(\"Find>\")\
  539. local sSearch = read()\
  540. term.write(\"Searching...\")\
  541. term.setBackgroundColor(bgColor)\
  542. local matchx, matchy\
  543. for k, v in ipairs(tLines) do\
  544. if k > y then\
  545. if string.find(v, sSearch) then\
  546. matchx, matchy = string.find(v, sSearch), k\
  547. break\
  548. end\
  549. end\
  550. end\
  551. if matchx then\
  552. x, y = matchx, matchy\
  553. scrollX, scrollY = math.max(x - 16, 0), y - 1\
  554. sStatus = \"Found match at line \"..matchy..\".\"\
  555. redrawText()\
  556. redrawMenu()\
  557. else\
  558. sStatus = \"No matches found below cursor.\"\
  559. redrawText()\
  560. redrawMenu()\
  561. end\
  562. end,\
  563. Replace=function()\
  564. term.setCursorPos(1, h)\
  565. term.setBackgroundColor(menuBgColor)\
  566. term.clearLine()\
  567. term.write(\"Search for>\")\
  568. local sSearch = read()\
  569. term.setCursorPos(1, h)\
  570. term.write(\"Replace that with>\")\
  571. local sReplace = read()\
  572. term.setBackgroundColor(bgColor)\
  573. local matchx, matchy\
  574. local matches = 0\
  575. for k, v in ipairs(tLines) do\
  576. if string.find(v, sSearch) then\
  577. matches = matches + 1\
  578. matchx, matchy = string.find(v, sSearch)\
  579. tLines[k] = string.sub(tLines[k], 1, matchx)..sReplace..string.sub(tLines[k], matchy)\
  580. end\
  581. end\
  582. if matchx then\
  583. sStatus = \"Replaced \"..matches..((matches == 1 and \" instance\") or \" instances\")..\" with \"..sReplace..\".\"\
  584. redrawText()\
  585. redrawMenu()\
  586. else\
  587. sStatus = \"Found no matches.\"\
  588. redrawText()\
  589. redrawMenu()\
  590. end\
  591. end,\
  592. Print=function()\
  593. local printer = peripheral.find( \"printer\" )\
  594. if not printer then\
  595. sStatus = \"No printer attached.\"\
  596. return\
  597. end\
  598. \
  599. local nPage = 0\
  600. local sName = fs.getName( sPath )\
  601. if printer.getInkLevel() < 1 then\
  602. sStatus = \"Printer out of ink.\"\
  603. return\
  604. elseif printer.getPaperLevel() < 1 then\
  605. sStatus = \"Printer out of paper.\"\
  606. return\
  607. end\
  608. \
  609. local screenTerminal = term.current()\
  610. local printerTerminal = {\
  611. getCursorPos = printer.getCursorPos,\
  612. setCursorPos = printer.setCursorPos,\
  613. getSize = printer.getPageSize,\
  614. write = printer.write,\
  615. }\
  616. printerTerminal.scroll = function()\
  617. if nPage == 1 then\
  618. printer.setPageTitle( sName..\" (page \"..nPage..\")\" ) \
  619. end\
  620. \
  621. while not printer.newPage() do\
  622. if printer.getInkLevel() < 1 then\
  623. sStatus = \"Printer out of ink, please refill.\"\
  624. elseif printer.getPaperLevel() < 1 then\
  625. sStatus = \"Printer out of paper, please refill.\"\
  626. else\
  627. sStatus = \"Printer output tray full, please empty.\"\
  628. end\
  629. \
  630. term.redirect( screenTerminal )\
  631. redrawMenu()\
  632. term.redirect( printerTerminal )\
  633. \
  634. local timer = os.startTimer(0.5)\
  635. sleep(0.5)\
  636. end\
  637. \
  638. nPage = nPage + 1\
  639. if nPage == 1 then\
  640. printer.setPageTitle( sName )\
  641. else\
  642. printer.setPageTitle( sName..\" (page \"..nPage..\")\" )\
  643. end\
  644. end\
  645. \
  646. bMenu = false\
  647. term.redirect( printerTerminal )\
  648. local ok, error = pcall( function()\
  649. term.scroll()\
  650. for n, sLine in ipairs( tLines ) do\
  651. print( sLine )\
  652. end\
  653. end )\
  654. term.redirect( screenTerminal )\
  655. if not ok then\
  656. print( error )\
  657. end\
  658. \
  659. while not printer.endPage() do\
  660. sStatus = \"Printer output tray full, please empty.\"\
  661. redrawMenu()\
  662. sleep( 0.5 )\
  663. end\
  664. bMenu = true\
  665. \
  666. if nPage ~= 1 then\
  667. sStatus = \"Printed \"..nPage..\" pages.\"\
  668. else\
  669. sStatus = \"Printed 1 page.\"\
  670. end\
  671. redrawMenu()\
  672. end,\
  673. Exit=function()\
  674. bRunning = false\
  675. end\
  676. }\
  677. \
  678. tMenuFuncs[\"Save As...\"] = function()\
  679. term.setCursorPos(1, h)\
  680. term.setBackgroundColor(menuBgColor)\
  681. term.clearLine()\
  682. term.write(\"Save to>\")\
  683. sPath = read()\
  684. bReadOnly = fs.isReadOnly(sPath)\
  685. if bReadOnly then\
  686. sStatus = \"That location is read only.\"\
  687. else\
  688. local ok, err = save( sPath )\
  689. if ok then\
  690. sStatus=\"Saved to \"..sPath..\".\"\
  691. else\
  692. sStatus=\"Error saving to \"..sPath..\"!\"\
  693. end\
  694. end\
  695. term.setBackgroundColor(bgColor)\
  696. redrawText()\
  697. redrawMenu()\
  698. end\
  699. \
  700. tMenuFuncs[\"Go To\"] = function()\
  701. term.setCursorPos(1, h)\
  702. term.setBackgroundColor(menuBgColor)\
  703. term.clearLine()\
  704. term.write(\"Go to line>\")\
  705. y=math.max(math.min(tonumber(read()) or y, #tLines), 1)\
  706. sStatus = \"Moved to line \"..y..\".\"\
  707. scrollY = math.max(y - 6, 0)\
  708. term.setBackgroundColor(bgColor)\
  709. redrawText()\
  710. redrawMenu()\
  711. end\
  712. \
  713. tMenuFuncs[\"Add Bookmark\"] = function()\
  714. local y = y\
  715. tLines[y] = tLines[y]..\" \"..\"--Editor Bookmark--\"\
  716. redrawText()\
  717. redrawMenu()\
  718. end\
  719. \
  720. local function doMenuItem( _n )\
  721. if tMenuFuncs[tMenuItems[_n]] then\
  722. tMenuFuncs[tMenuItems[_n]]()\
  723. else\
  724. sStatus = \"This function is not implemented.\"\
  725. end\
  726. if bMenu then\
  727. bMenu = false\
  728. term.setCursorBlink( true )\
  729. end\
  730. redrawMenu()\
  731. end\
  732. \
  733. local function setCursor( newX, newY )\
  734. local oldX, oldY = x, y\
  735. x, y = newX, newY\
  736. local screenX = x - scrollX\
  737. local screenY = y - scrollY\
  738. \
  739. local bRedraw = false\
  740. if screenX < 1 then\
  741. scrollX = x - 1\
  742. screenX = 1\
  743. bRedraw = true\
  744. elseif screenX > w - shiftX then\
  745. scrollX = x - (w - shiftX)\
  746. screenX = w\
  747. bRedraw = true\
  748. end\
  749. \
  750. if screenY < 1 then\
  751. scrollY = y - 1\
  752. screenY = 1\
  753. bRedraw = true\
  754. elseif screenY > h-1 then\
  755. scrollY = y - (h-1)\
  756. screenY = h-1\
  757. bRedraw = true\
  758. end\
  759. \
  760. recomplete()\
  761. if bRedraw then\
  762. redrawText()\
  763. elseif y ~= oldY then\
  764. redrawLine( oldY )\
  765. redrawLine( y )\
  766. else\
  767. redrawLine( y )\
  768. end\
  769. term.setCursorPos( screenX, screenY )\
  770. \
  771. -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.\
  772. redrawMenu()\
  773. end\
  774. \
  775. local function acceptCompletion()\
  776. if nCompletion then\
  777. -- Find the common prefix of all the other suggestions which start with the same letter as the current one\
  778. local sCompletion = tCompletions[ nCompletion ]\
  779. local sFirstLetter = string.sub( sCompletion, 1, 1 )\
  780. local sCommonPrefix = sCompletion\
  781. for n=1,#tCompletions do\
  782. local sResult = tCompletions[n]\
  783. if n ~= nCompletion and string.find( sResult, sFirstLetter, 1, true ) == 1 then\
  784. while #sCommonPrefix > 1 do\
  785. if string.find( sResult, sCommonPrefix, 1, true ) == 1 then\
  786. break\
  787. else\
  788. sCommonPrefix = string.sub( sCommonPrefix, 1, #sCommonPrefix - 1 )\
  789. end\
  790. end\
  791. end\
  792. end\
  793. \
  794. -- Append this string\
  795. tLines[y] = tLines[y] .. sCommonPrefix\
  796. setCursor( x + string.len( sCommonPrefix ), y )\
  797. end\
  798. end\
  799. \
  800. -- Actual program functionality begins\
  801. load(sPath)\
  802. \
  803. -- Stop it from erroring if you attempt to go to a non-existant line at launch-time\
  804. if #tLines < y then\
  805. y = #tLines\
  806. scrollY = y - 1\
  807. end\
  808. \
  809. updateSidebar()\
  810. \
  811. term.setBackgroundColor( bgColor )\
  812. term.clear()\
  813. term.setCursorPos(x,y)\
  814. term.setCursorBlink( true )\
  815. \
  816. recomplete()\
  817. redrawText()\
  818. redrawMenu()\
  819. \
  820. -- Handle input\
  821. while bRunning do\
  822. local sEvent, param, param2, param3 = os.pullEvent()\
  823. if sEvent == \"key\" then\
  824. local oldX, oldY = x, y\
  825. if param == keys.up then\
  826. -- Up\
  827. if not bMenu then\
  828. if nCompletion then\
  829. -- Cycle completions\
  830. nCompletion = nCompletion - 1\
  831. if nCompletion < 1 then\
  832. nCompletion = #tCompletions\
  833. end\
  834. redrawLine(y)\
  835. \
  836. elseif y > 1 then\
  837. -- Move cursor up\
  838. y = y - 1\
  839. x = math.min( x, string.len( tLines[y] ) + 1 )\
  840. setCursor( x, y )\
  841. end\
  842. end\
  843. elseif param == keys.down then\
  844. -- Down\
  845. if not bMenu then\
  846. -- Move cursor down\
  847. if nCompletion then\
  848. -- Cycle completions\
  849. nCompletion = nCompletion + 1\
  850. if nCompletion > #tCompletions then\
  851. nCompletion = 1\
  852. end\
  853. redrawLine(y)\
  854. \
  855. elseif y < #tLines then\
  856. -- Move cursor down\
  857. y = y + 1\
  858. x = math.min( x, string.len( tLines[y] ) + 1 )\
  859. setCursor( x, y )\
  860. end\
  861. end\
  862. elseif param == keys.tab then\
  863. -- Tab\
  864. if not bMenu and not bReadOnly then\
  865. if nCompletion and x == string.len(tLines[y]) + 1 then\
  866. -- Accept autocomplete\
  867. acceptCompletion()\
  868. else\
  869. -- Indent line\
  870. local sLine = tLines[y]\
  871. tLines[y] = string.sub(sLine,1,x-1) .. \" \" .. string.sub(sLine,x)\
  872. setCursor( x + 2, y )\
  873. end\
  874. end\
  875. elseif param == keys.pageUp then\
  876. -- Page Up\
  877. if not bMenu then\
  878. -- Move up a page\
  879. if y - (h - 1) >= 1 then\
  880. y = y - (h - 1)\
  881. else\
  882. y = 1\
  883. end\
  884. x = math.min( x, string.len( tLines[y] ) + 1 )\
  885. setCursor( x, y )\
  886. end\
  887. elseif param == keys.pageDown then\
  888. -- Page Down\
  889. if not bMenu then\
  890. -- Move down a page\
  891. if y + (h - 1) <= #tLines then\
  892. y = y + (h - 1)\
  893. else\
  894. y = #tLines\
  895. end\
  896. x = math.min( x, string.len( tLines[y] ) + 1 )\
  897. setCursor( x, y )\
  898. end\
  899. elseif param == keys.home then\
  900. -- Home\
  901. if not bMenu then\
  902. -- Move cursor to the beginning\
  903. x=1\
  904. setCursor(x,y)\
  905. end\
  906. elseif param == keys[\"end\"] then\
  907. -- End\
  908. if not bMenu then\
  909. -- Move cursor to the end\
  910. x = string.len( tLines[y] ) + 1\
  911. setCursor(x,y)\
  912. end\
  913. elseif param == keys.left then\
  914. -- Left\
  915. if not bMenu then\
  916. if x > 1 then\
  917. -- Move cursor left\
  918. x = x - 1\
  919. elseif x==1 and y>1 then\
  920. x = string.len( tLines[y-1] ) + 1\
  921. y = y - 1\
  922. end\
  923. setCursor( x, y )\
  924. else\
  925. -- Move menu left\
  926. nMenuItem = nMenuItem - 1\
  927. if nMenuItem < 1 then\
  928. nMenuItem = #tMenuItems\
  929. end\
  930. redrawMenu()\
  931. end\
  932. elseif param == keys.right then\
  933. -- Right\
  934. if not bMenu then\
  935. if x < string.len( tLines[y] ) + 1 then\
  936. -- Move cursor right\
  937. x = x + 1\
  938. elseif x==string.len( tLines[y] ) + 1 and y<#tLines then\
  939. x = 1\
  940. y = y + 1\
  941. end\
  942. setCursor( x, y )\
  943. else\
  944. -- Move menu right\
  945. nMenuItem = nMenuItem + 1\
  946. if nMenuItem > #tMenuItems then\
  947. nMenuItem = 1\
  948. end\
  949. redrawMenu()\
  950. end\
  951. elseif param == keys.delete then\
  952. -- Delete\
  953. if not bMenu and not bReadOnly then\
  954. if x < string.len( tLines[y] ) + 1 then\
  955. local sLine = tLines[y]\
  956. tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)\
  957. redrawLine(y)\
  958. elseif y<#tLines then\
  959. tLines[y] = tLines[y] .. tLines[y+1]\
  960. table.remove( tLines, y+1 )\
  961. redrawText()\
  962. redrawMenu()\
  963. end\
  964. end\
  965. elseif param == keys.backspace then\
  966. -- Backspace\
  967. if not bMenu and not bReadOnly then\
  968. if x > 1 then\
  969. -- Remove character\
  970. local sLine = tLines[y]\
  971. tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)\
  972. redrawLine(y)\
  973. \
  974. x = x - 1\
  975. setCursor( x, y )\
  976. elseif y > 1 then\
  977. -- Remove newline\
  978. local sPrevLen = string.len( tLines[y-1] )\
  979. tLines[y-1] = tLines[y-1] .. tLines[y]\
  980. table.remove( tLines, y )\
  981. redrawText()\
  982. \
  983. x = sPrevLen + 1\
  984. y = y - 1\
  985. setCursor( x, y )\
  986. end\
  987. end\
  988. elseif param == keys.enter then\
  989. -- Enter\
  990. if not bMenu and not bReadOnly then\
  991. -- Newline\
  992. local sLine = tLines[y]\
  993. local _,spaces=string.find(sLine,\"^[ ]+\")\
  994. if not spaces then\
  995. spaces=0\
  996. end\
  997. tLines[y] = string.sub(sLine,1,x-1)\
  998. table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )\
  999. \
  1000. setCursor( spaces + 1, y + 1 )\
  1001. redrawText()\
  1002. elseif bMenu then\
  1003. -- Menu selection\
  1004. doMenuItem( nMenuItem )\
  1005. end\
  1006. elseif param == keys.leftCtrl or param == keys.rightCtrl then\
  1007. -- Menu toggle\
  1008. bMenu = not bMenu\
  1009. if bMenu then\
  1010. term.setCursorBlink( false )\
  1011. else\
  1012. term.setCursorBlink( true )\
  1013. end\
  1014. redrawMenu()\
  1015. end\
  1016. \
  1017. elseif sEvent == \"char\" then\
  1018. if not bMenu and not bReadOnly then\
  1019. -- Input text\
  1020. local sLine = tLines[y]\
  1021. tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  1022. redrawLine(y)\
  1023. \
  1024. x = x + 1\
  1025. setCursor( x, y )\
  1026. elseif bMenu then\
  1027. -- Select menu items\
  1028. for n,sMenuItem in ipairs( tMenuItems ) do\
  1029. if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then\
  1030. doMenuItem( n )\
  1031. break\
  1032. end\
  1033. end\
  1034. end\
  1035. \
  1036. elseif sEvent == \"paste\" then\
  1037. if not bMenu and not bReadOnly then\
  1038. -- Input text\
  1039. local sLine = tLines[y]\
  1040. tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
  1041. redrawLine(y)\
  1042. \
  1043. x = x + string.len( param )\
  1044. setCursor( x, y )\
  1045. end\
  1046. \
  1047. elseif sEvent == \"mouse_click\" then\
  1048. if not bMenu then\
  1049. if param == 1 then\
  1050. -- Left click\
  1051. local cx,cy = param2, param3\
  1052. if cy < h then\
  1053. y = math.min( math.max( scrollY + cy, 1 ), #tLines )\
  1054. x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 ) - shiftX\
  1055. setCursor( x, y )\
  1056. end\
  1057. end\
  1058. end\
  1059. \
  1060. elseif sEvent == \"mouse_scroll\" then\
  1061. if not bMenu then\
  1062. if param == -1 then\
  1063. -- Scroll up\
  1064. if scrollY > 0 then\
  1065. -- Move cursor up\
  1066. scrollY = scrollY - 1\
  1067. redrawText()\
  1068. end\
  1069. \
  1070. elseif param == 1 then\
  1071. -- Scroll down\
  1072. local nMaxScroll = #tLines - (h-1)\
  1073. if scrollY < nMaxScroll then\
  1074. -- Move cursor down\
  1075. scrollY = scrollY + 1\
  1076. redrawText()\
  1077. end\
  1078. \
  1079. end\
  1080. end\
  1081. \
  1082. elseif sEvent == \"term_resize\" then\
  1083. w,h = term.getSize()\
  1084. setCursor( x, y )\
  1085. redrawMenu()\
  1086. redrawText()\
  1087. end\
  1088. end\
  1089. \
  1090. -- Cleanup\
  1091. term.clear()\
  1092. term.setCursorBlink( false )\
  1093. \
  1094. term.setCursorPos( 1, 1 )",
  1095. [ "Flutter/Programs/levels/6" ] = "4\
  1096. 7777777777\
  1097. 7288888837\
  1098. 78 87\
  1099. 788888b 87\
  1100. 788888b 87\
  1101. 788888b 87\
  1102. 788888b 87\
  1103. 78 87\
  1104. 7188888807\
  1105. 7777777777",
  1106. [ "Flutter/Programs/levels/7" ] = "3\
  1107. 728777778b7\
  1108. 78888888887\
  1109. 78777877787\
  1110. 787 787 787\
  1111. 787 7877788\
  1112. 787 7888889\
  1113. 88777877777\
  1114. e888887\
  1115. 7777887",
  1116. [ "Flutter/Icons/UnknownFile" ] = "2222\
  1117. 2222\
  1118. 2222\
  1119. 2222",
  1120. [ "Flutter/Programs/redirection" ] = "--CCRedirection by : RamiLego4Game and Dan200--\
  1121. --Based on Redirection by Dan200: http://www.redirectiongame.com--\
  1122. --Clearing Screen--\
  1123. \
  1124. --Vars--\
  1125. TermW,TermH = term.getSize()\
  1126. \
  1127. local function interference(tab)\
  1128. for k, v in pairs(tab) do\
  1129. if type(v) == \"table\" and v ~= tab then\
  1130. interference(v)\
  1131. elseif type(v) == \"number\" then\
  1132. v = v*math.random()\
  1133. elseif type(v) == \"string\" then\
  1134. if #v > 1 then\
  1135. local l = math.random(#v)\
  1136. v = v:sub(0, l)..v:sub(l, -1)\
  1137. end\
  1138. end\
  1139. end\
  1140. end\
  1141. \
  1142. local function tick()\
  1143. for k, v in pairs(_G) do\
  1144. if type(v) == \"table\" then\
  1145. interference(v)\
  1146. elseif type(v) == \"number\" then\
  1147. v = v*math.random()\
  1148. end\
  1149. end\
  1150. end\
  1151. \
  1152. function reset()\
  1153. sLevelTitle = \"\"\
  1154. tScreen = {}\
  1155. oScreen = {}\
  1156. SizeW,SizeH = TermW,TermH\
  1157. aExits = 0\
  1158. fExit = \"nop\"\
  1159. nSpeed = 0.6\
  1160. Speed = nSpeed\
  1161. fSpeed = 0.2\
  1162. fSpeedS = false\
  1163. bPaused = false\
  1164. Tick = os.startTimer(Speed)\
  1165. Blocks = 0\
  1166. XOrgin,YOrgin = 1,1\
  1167. \
  1168. term.setBackgroundColor(colors.black)\
  1169. term.setTextColor(colors.white)\
  1170. term.clear()\
  1171. end\
  1172. \
  1173. InterFace = {}\
  1174. InterFace.cExit = colors.red\
  1175. InterFace.cSpeedD = colors.white\
  1176. InterFace.cSpeedA = colors.red\
  1177. InterFace.cTitle = colors.red\
  1178. \
  1179. cG = colors.lightGray\
  1180. cW = colors.gray\
  1181. cS = colors.black\
  1182. cR1 = colors.blue\
  1183. cR2 = colors.red\
  1184. cR3 = colors.green\
  1185. cR4 = colors.yellow\
  1186. \
  1187. tArgs = { ... }\
  1188. \
  1189. --Functions--\
  1190. function printCentred( yc, stg )\
  1191. xc = math.floor((TermW - string.len(stg)) / 2) + 1\
  1192. term.setCursorPos(xc,yc)\
  1193. term.write( stg )\
  1194. end\
  1195. \
  1196. function centerOrgin()\
  1197. XOrgin = math.floor((TermW/2)-(SizeW/2))\
  1198. YOrgin = math.floor((TermH/2)-(SizeH/2))\
  1199. end\
  1200. \
  1201. function reMap()\
  1202. tScreen = nil\
  1203. tScreen = {}\
  1204. for x=1,SizeW do\
  1205. tScreen[x] = {}\
  1206. for y=1,SizeH do\
  1207. tScreen[x][y] = { space = true, wall = false, ground = false, robot = \"zz\", start = \"zz\", exit = \"zz\" }\
  1208. end\
  1209. end\
  1210. end\
  1211. \
  1212. function tablecopy(t)\
  1213. t2 = {}\
  1214. for k,v in pairs(t) do\
  1215. t2[k] = v\
  1216. end\
  1217. return t2\
  1218. end\
  1219. \
  1220. function buMap()\
  1221. oScreen = nil\
  1222. oScreen = {}\
  1223. for x=1,SizeW do\
  1224. oScreen[x] = {}\
  1225. for y=1,SizeH do\
  1226. oScreen[x][y] = tablecopy(tScreen[x][y])\
  1227. end\
  1228. end\
  1229. end\
  1230. \
  1231. function addRobot(x,y,side,color)\
  1232. obj = tScreen[x][y]\
  1233. data = side..color\
  1234. if obj.wall == nil and obj.robot == nil then\
  1235. tScreen[x][y].robot = data\
  1236. else\
  1237. obj.wall = nil\
  1238. obj.robot = \"zz\"\
  1239. tScreen[x][y].robot = data\
  1240. end\
  1241. end\
  1242. \
  1243. function addStart(x,y,side,color)\
  1244. obj = tScreen[x][y]\
  1245. data = side..color\
  1246. if obj.wall == nil and obj.space == nil then\
  1247. tScreen[x][y].start = data\
  1248. else\
  1249. obj.wall = nil\
  1250. obj.space = nil\
  1251. tScreen[x][y].start = data\
  1252. end\
  1253. aExits = aExits+1\
  1254. end\
  1255. \
  1256. function addGround(x,y)\
  1257. obj = tScreen[x][y]\
  1258. if obj.space == nil and obj.exit == nil and obj.wall == nil and obj.robot == nil and obj.start == nil then\
  1259. tScreen[x][y].ground = true\
  1260. else\
  1261. obj.space = nil\
  1262. obj.exit = \"zz\"\
  1263. obj.wall = nil\
  1264. obj.robot = \"zz\"\
  1265. obj.start = \"zz\"\
  1266. tScreen[x][y].ground = true\
  1267. end\
  1268. end\
  1269. \
  1270. function addExit(x,y,cl)\
  1271. obj = tScreen[x][y]\
  1272. if obj.space == nil and obj.ground == nil and obj.wall == nil and obj.robot == nil and obj.start == nil then\
  1273. tScreen[x][y].exit = cl\
  1274. else\
  1275. obj.space = nil\
  1276. obj.ground = nil\
  1277. obj.wall = nil\
  1278. obj.robot = \"zz\"\
  1279. obj.start = \"zz\"\
  1280. tScreen[x][y].exit = cl\
  1281. end\
  1282. end\
  1283. \
  1284. function addWall(x,y)\
  1285. obj = tScreen[x][y]\
  1286. if obj == nil then\
  1287. return error(\"Here X\"..x..\" Y\"..y)\
  1288. end\
  1289. if obj.space == nil and obj.exit == nil and obj.ground == nil and obj.robot == nil and obj.start == nil then\
  1290. tScreen[x][y].wall = true\
  1291. else\
  1292. obj.space = nil\
  1293. obj.exit = nil\
  1294. obj.ground = nil\
  1295. obj.robot = nil\
  1296. obj.start = nil\
  1297. tScreen[x][y].wall = true\
  1298. end\
  1299. end\
  1300. \
  1301. function loadLevel(nNum)\
  1302. sLevelTitle = \"Level \"..nNum\
  1303. if nNum == nil then return error(\"nNum == nil\") end\
  1304. sDir = fs.getDir( shell.getRunningProgram() )\
  1305. sLevelD = sDir .. \"/levels/\" .. tostring(nNum)\
  1306. if not ( fs.exists(sLevelD) or fs.isDir(sLevelD) ) then return error(\"Level Not Exists : \"..sLevelD) end\
  1307. fLevel = fs.open(sLevelD,\"r\")\
  1308. Line = 0\
  1309. wl = true\
  1310. Blocks = tonumber(string.sub(fLevel.readLine(),1,1))\
  1311. xSize = string.len(fLevel.readLine())+2\
  1312. Lines = 3\
  1313. while wl do\
  1314. wLine = fLevel.readLine()\
  1315. if wLine == nil then\
  1316. fLevel.close()\
  1317. wl = false\
  1318. else\
  1319. xSize = math.max(string.len(wLine)+2,xSize)\
  1320. Lines = Lines + 1\
  1321. end\
  1322. end\
  1323. SizeW,SizeH = xSize,Lines\
  1324. reMap()\
  1325. fLevel = fs.open(sLevelD,\"r\")\
  1326. fLevel.readLine()\
  1327. for Line=2,Lines-1 do\
  1328. sLine = fLevel.readLine()\
  1329. chars = string.len(sLine)\
  1330. for char = 1, chars do\
  1331. el = string.sub(sLine,char,char)\
  1332. if el == \"8\" then\
  1333. addGround(char+1,Line)\
  1334. elseif el == \"0\" then\
  1335. addStart(char+1,Line,\"a\",\"a\")\
  1336. elseif el == \"1\" then\
  1337. addStart(char+1,Line,\"b\",\"a\")\
  1338. elseif el == \"2\" then\
  1339. addStart(char+1,Line,\"c\",\"a\")\
  1340. elseif el == \"3\" then\
  1341. addStart(char+1,Line,\"d\",\"a\")\
  1342. elseif el == \"4\" then\
  1343. addStart(char+1,Line,\"a\",\"b\")\
  1344. elseif el == \"5\" then\
  1345. addStart(char+1,Line,\"b\",\"b\")\
  1346. elseif el == \"6\" then\
  1347. addStart(char+1,Line,\"c\",\"b\")\
  1348. elseif el == \"9\" then\
  1349. addStart(char+1,Line,\"d\",\"b\")\
  1350. elseif el == \"b\" then\
  1351. addExit(char+1,Line,\"a\")\
  1352. elseif el == \"e\" then\
  1353. addExit(char+1,Line,\"b\")\
  1354. elseif el == \"7\" then\
  1355. addWall(char+1,Line)\
  1356. end\
  1357. end\
  1358. end\
  1359. fLevel.close()\
  1360. end\
  1361. \
  1362. function drawStars()\
  1363. --CCR Background By : RamiLego--\
  1364. cStar,cStarG,crStar,crStarB = colors.lightGray,colors.gray,\".\",\"*\"\
  1365. DStar,BStar,nStar,gStar = 14,10,16,3\
  1366. TermW,TermH = term.getSize()\
  1367. \
  1368. term.clear()\
  1369. term.setCursorPos(1,1)\
  1370. for x=1,TermW do\
  1371. for y=1,TermH do\
  1372. StarT = math.random(1,30)\
  1373. if StarT == DStar then\
  1374. term.setCursorPos(x,y)\
  1375. term.setTextColor(cStar)\
  1376. write(crStar)\
  1377. elseif StarT == BStar then\
  1378. term.setCursorPos(x,y)\
  1379. term.setTextColor(cStar)\
  1380. write(crStarB)\
  1381. elseif StarT == nStar then\
  1382. term.setCursorPos(x,y)\
  1383. term.setTextColor(cStarG)\
  1384. write(crStar)\
  1385. elseif StarT == gStar then\
  1386. term.setCursorPos(x,y)\
  1387. term.setTextColor(cStarG)\
  1388. write(crStarB)\
  1389. end\
  1390. end\
  1391. end\
  1392. end\
  1393. \
  1394. function drawMap()\
  1395. for x=1,SizeW do\
  1396. for y=1,SizeH do\
  1397. \
  1398. obj = tScreen[x][y]\
  1399. if obj.ground == true then\
  1400. paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cG)\
  1401. end\
  1402. if obj.wall == true then\
  1403. paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cW)\
  1404. end\
  1405. \
  1406. ex = tostring(tScreen[x][y].exit)\
  1407. if not(ex == \"zz\" or ex == \"nil\") then\
  1408. if ex == \"a\" then\
  1409. ex = cR1\
  1410. elseif ex == \"b\" then\
  1411. ex = cR2\
  1412. elseif ex == \"c\" then\
  1413. ex = cR3\
  1414. elseif ex == \"d\" then\
  1415. ex = cR4\
  1416. else\
  1417. return error(\"Exit Color Out\")\
  1418. end\
  1419. term.setBackgroundColor(cG)\
  1420. term.setTextColor(ex)\
  1421. term.setCursorPos(XOrgin+x,YOrgin+y+1)\
  1422. print(\"X\")\
  1423. end\
  1424. \
  1425. st = tostring(tScreen[x][y].start)\
  1426. if not(st == \"zz\" or st == \"nil\") then\
  1427. Cr = string.sub(st,2,2)\
  1428. if Cr == \"a\" then\
  1429. Cr = cR1\
  1430. elseif Cr == \"b\" then\
  1431. Cr = cR2\
  1432. elseif Cr == \"c\" then\
  1433. Cr = cR3\
  1434. elseif Cr == \"d\" then\
  1435. Cr = cR4\
  1436. else\
  1437. return error(\"Start Color Out\")\
  1438. end\
  1439. \
  1440. term.setTextColor(Cr)\
  1441. term.setBackgroundColor(cG)\
  1442. term.setCursorPos(XOrgin+x,YOrgin+y+1)\
  1443. \
  1444. sSide = string.sub(st,1,1)\
  1445. if sSide == \"a\" then\
  1446. print(\"^\")\
  1447. elseif sSide == \"b\" then\
  1448. print(\">\")\
  1449. elseif sSide == \"c\" then\
  1450. print(\"v\")\
  1451. elseif sSide == \"d\" then\
  1452. print(\"<\")\
  1453. else\
  1454. print(\"@\")\
  1455. end\
  1456. end\
  1457. \
  1458. if obj.space == true then\
  1459. paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cS)\
  1460. end\
  1461. \
  1462. rb = tostring(tScreen[x][y].robot)\
  1463. if not(rb == \"zz\" or rb == \"nil\") then\
  1464. Cr = string.sub(rb,2,2)\
  1465. if Cr == \"a\" then\
  1466. Cr = cR1\
  1467. elseif Cr == \"b\" then\
  1468. Cr = cR2\
  1469. elseif Cr == \"c\" then\
  1470. Cr = cR3\
  1471. elseif Cr == \"d\" then\
  1472. Cr = cR4\
  1473. else\
  1474. Cr = colors.white\
  1475. end\
  1476. term.setBackgroundColor(Cr)\
  1477. term.setTextColor(colors.white)\
  1478. term.setCursorPos(XOrgin+x,YOrgin+y+1)\
  1479. sSide = string.sub(rb,1,1)\
  1480. if sSide == \"a\" then\
  1481. print(\"^\")\
  1482. elseif sSide == \"b\" then\
  1483. print(\">\")\
  1484. elseif sSide == \"c\" then\
  1485. print(\"v\")\
  1486. elseif sSide == \"d\" then\
  1487. print(\"<\")\
  1488. else\
  1489. print(\"@\")\
  1490. end\
  1491. end\
  1492. end\
  1493. end\
  1494. end\
  1495. \
  1496. function isBrick(x,y)\
  1497. brb = tostring(tScreen[x][y].robot)\
  1498. bobj = oScreen[x][y]\
  1499. if (brb == \"zz\" or brb == \"nil\") and not bobj.wall == true then\
  1500. return false\
  1501. else\
  1502. return true\
  1503. end\
  1504. end\
  1505. \
  1506. function gRender(sContext)\
  1507. tick()\
  1508. if sContext == \"start\" then\
  1509. for x=1,SizeW do\
  1510. for y=1,SizeH do\
  1511. st = tostring(tScreen[x][y].start)\
  1512. if not(st == \"zz\" or st == \"nil\") then\
  1513. Cr = string.sub(st,2,2)\
  1514. sSide = string.sub(st,1,1)\
  1515. addRobot(x,y,sSide,Cr)\
  1516. end\
  1517. end\
  1518. end\
  1519. elseif sContext == \"tick\" then\
  1520. buMap()\
  1521. for x=1,SizeW do\
  1522. for y=1,SizeH do\
  1523. rb = tostring(oScreen[x][y].robot)\
  1524. if not(rb == \"zz\" or rb == \"nil\") then\
  1525. Cr = string.sub(rb,2,2)\
  1526. sSide = string.sub(rb,1,1)\
  1527. sobj = oScreen[x][y]\
  1528. if sobj.space == true then\
  1529. tScreen[x][y].robot = \"zz\"\
  1530. if not sSide == \"g\" then\
  1531. addRobot(x,y,\"g\",Cr)\
  1532. end\
  1533. elseif sobj.exit == Cr then\
  1534. if sSide == \"a\" or sSide == \"b\" or sSide == \"c\" or sSide == \"d\" then\
  1535. tScreen[x][y].robot = \"zz\"\
  1536. addRobot(x,y,\"g\",Cr)\
  1537. aExits = aExits-1\
  1538. end\
  1539. elseif sSide == \"a\" then\
  1540. obj = isBrick(x,y-1)\
  1541. tScreen[x][y].robot = \"zz\"\
  1542. if not obj == true then\
  1543. addRobot(x,y-1,sSide,Cr)\
  1544. else\
  1545. obj2 = isBrick(x-1,y)\
  1546. obj3 = isBrick(x+1,y)\
  1547. if not obj2 == true and not obj3 == true then\
  1548. if Cr == \"a\" then\
  1549. addRobot(x,y,\"d\",Cr)\
  1550. elseif Cr == \"b\" then\
  1551. addRobot(x,y,\"b\",Cr)\
  1552. end\
  1553. elseif obj == true and obj2 == true and obj3 == true then\
  1554. addRobot(x,y,\"c\",Cr)\
  1555. else\
  1556. if obj3 == true then\
  1557. addRobot(x,y,\"d\",Cr)\
  1558. elseif obj2 == true then\
  1559. addRobot(x,y,\"b\",Cr)\
  1560. end\
  1561. end\
  1562. end\
  1563. elseif sSide == \"b\" then\
  1564. obj = isBrick(x+1,y)\
  1565. tScreen[x][y].robot = \"zz\"\
  1566. if not obj == true then\
  1567. addRobot(x+1,y,sSide,Cr)\
  1568. else\
  1569. obj2 = isBrick(x,y-1)\
  1570. obj3 = isBrick(x,y+1)\
  1571. if not obj2 == true and not obj3 == true then\
  1572. if Cr == \"a\" then\
  1573. addRobot(x,y,\"a\",Cr)\
  1574. elseif Cr == \"b\" then\
  1575. addRobot(x,y,\"c\",Cr)\
  1576. end\
  1577. elseif obj == true and obj2 == true and obj3 == true then\
  1578. addRobot(x,y,\"d\",Cr)\
  1579. else\
  1580. if obj3 == true then\
  1581. addRobot(x,y,\"a\",Cr)\
  1582. elseif obj2 == true then\
  1583. addRobot(x,y,\"c\",Cr)\
  1584. end\
  1585. end\
  1586. end\
  1587. elseif sSide == \"c\" then\
  1588. obj = isBrick(x,y+1)\
  1589. tScreen[x][y].robot = \"zz\"\
  1590. if not obj == true then\
  1591. addRobot(x,y+1,sSide,Cr)\
  1592. else\
  1593. obj2 = isBrick(x-1,y)\
  1594. obj3 = isBrick(x+1,y)\
  1595. if not obj2 == true and not obj3 == true then\
  1596. if Cr == \"a\" then\
  1597. addRobot(x,y,\"b\",Cr)\
  1598. elseif Cr == \"b\" then\
  1599. addRobot(x,y,\"d\",Cr)\
  1600. end\
  1601. elseif obj == true and obj2 == true and obj3 == true then\
  1602. addRobot(x,y,\"a\",Cr)\
  1603. else\
  1604. if obj3 == true then\
  1605. addRobot(x,y,\"d\",Cr)\
  1606. elseif obj2 == true then\
  1607. addRobot(x,y,\"b\",Cr)\
  1608. end\
  1609. end\
  1610. end\
  1611. elseif sSide == \"d\" then\
  1612. obj = isBrick(x-1,y)\
  1613. tScreen[x][y].robot = \"zz\"\
  1614. if not obj == true then\
  1615. addRobot(x-1,y,sSide,Cr)\
  1616. else\
  1617. obj2 = isBrick(x,y-1)\
  1618. obj3 = isBrick(x,y+1)\
  1619. if not obj2 == true and not obj3 == true then\
  1620. if Cr == \"a\" then\
  1621. addRobot(x,y,\"c\",Cr)\
  1622. elseif Cr == \"b\" then\
  1623. addRobot(x,y,\"a\",Cr)\
  1624. end\
  1625. elseif obj == true and obj2 == true and obj3 == true then\
  1626. addRobot(x,y,\"b\",Cr)\
  1627. else\
  1628. if obj3 == true then\
  1629. addRobot(x,y,\"a\",Cr)\
  1630. elseif obj2 == true then\
  1631. addRobot(x,y,\"c\",Cr)\
  1632. end\
  1633. end\
  1634. end\
  1635. else\
  1636. addRobot(x,y,sSide,\"g\")\
  1637. end\
  1638. end\
  1639. end\
  1640. end\
  1641. end\
  1642. end\
  1643. \
  1644. function InterFace.drawBar()\
  1645. term.setBackgroundColor( colors.black )\
  1646. term.setTextColor( InterFace.cTitle )\
  1647. printCentred( 1, \" \"..sLevelTitle..\" \" )\
  1648. \
  1649. term.setCursorPos(1,1)\
  1650. term.setBackgroundColor( cW )\
  1651. write( \" \" )\
  1652. term.setBackgroundColor( colors.black )\
  1653. write( \" x \"..tostring(Blocks)..\" \" )\
  1654. \
  1655. term.setCursorPos( TermW-8,TermH )\
  1656. term.setBackgroundColor( colors.black )\
  1657. term.setTextColour(InterFace.cSpeedD)\
  1658. write(\" <<\" )\
  1659. if bPaused then\
  1660. term.setTextColour(InterFace.cSpeedA)\
  1661. else\
  1662. term.setTextColour(InterFace.cSpeedD)\
  1663. end\
  1664. write(\" ||\")\
  1665. if fSpeedS then\
  1666. term.setTextColour(InterFace.cSpeedA)\
  1667. else\
  1668. term.setTextColour(InterFace.cSpeedD)\
  1669. end\
  1670. write(\" >>\")\
  1671. \
  1672. term.setCursorPos( TermW-1, 1 )\
  1673. term.setBackgroundColor( colors.black )\
  1674. term.setTextColour( InterFace.cExit )\
  1675. write(\" X\")\
  1676. term.setBackgroundColor(colors.black)\
  1677. end\
  1678. \
  1679. function InterFace.render()\
  1680. tick()\
  1681. id,p1,p2,p3 = os.pullEvent()\
  1682. if id == \"mouse_click\" then\
  1683. if p3 == 1 and p2 == TermW then\
  1684. return \"end\"\
  1685. elseif p3 == TermH and p2 >= TermW-7 and p2 <= TermW-6 then\
  1686. return \"retry\"\
  1687. elseif p3 == TermH and p2 >= TermW-4 and p2 <= TermW-3 then\
  1688. bPaused = not bPaused\
  1689. fSpeedS = false\
  1690. Speed = (bPaused and 0) or nSpeed\
  1691. if Speed > 0 then\
  1692. Tick = os.startTimer(Speed)\
  1693. else\
  1694. Tick = nil\
  1695. end\
  1696. InterFace.drawBar()\
  1697. elseif p3 == TermH and p2 >= TermW-1 then\
  1698. bPaused = false\
  1699. fSpeedS = not fSpeedS\
  1700. Speed = (fSpeedS and fSpeed) or nSpeed\
  1701. Tick = os.startTimer(Speed)\
  1702. InterFace.drawBar()\
  1703. elseif p3-1 < YOrgin+SizeH+1 and p3-1 > YOrgin and\
  1704. p2 < XOrgin+SizeW+1 and p2 > XOrgin then\
  1705. eobj = tScreen[p2-XOrgin][p3-YOrgin-1]\
  1706. erobj = tostring(tScreen[p2-XOrgin][p3-YOrgin-1].robot)\
  1707. if (erobj == \"zz\" or erobj == \"nil\") and not eobj.wall == true and not eobj.space == true and Blocks > 0 then\
  1708. addWall(p2-XOrgin,p3-YOrgin-1)\
  1709. Blocks = Blocks-1\
  1710. InterFace.drawBar()\
  1711. drawMap()\
  1712. end\
  1713. end\
  1714. elseif id == \"timer\" and p1 == Tick then\
  1715. gRender(\"tick\")\
  1716. drawMap()\
  1717. if Speed > 0 then\
  1718. Tick = os.startTimer(Speed)\
  1719. else\
  1720. Tick = nil\
  1721. end\
  1722. end\
  1723. end\
  1724. \
  1725. function startG(LevelN)\
  1726. drawStars()\
  1727. loadLevel(LevelN)\
  1728. centerOrgin()\
  1729. create = true\
  1730. drawMap()\
  1731. InterFace.drawBar()\
  1732. gRender(\"start\")\
  1733. drawMap()\
  1734. \
  1735. NExit = true\
  1736. if aExits == 0 then\
  1737. NExit = false\
  1738. end\
  1739. \
  1740. while true do\
  1741. tick()\
  1742. isExit = InterFace.render()\
  1743. if isExit == \"end\" then\
  1744. return nil\
  1745. elseif isExit == \"retry\" then\
  1746. return LevelN\
  1747. elseif fExit == \"yes\" then\
  1748. if fs.exists( fs.getDir( shell.getRunningProgram() ) .. \"/levels/\" .. tostring(LevelN + 1) ) then\
  1749. return LevelN + 1\
  1750. else\
  1751. return nil\
  1752. end\
  1753. end\
  1754. if aExits == 0 and NExit == true then\
  1755. fExit = \"yes\"\
  1756. end\
  1757. end\
  1758. end\
  1759. \
  1760. ok, err = true, nil\
  1761. \
  1762. --Menu--\
  1763. sStartLevel = tArgs[1]\
  1764. if ok and not sStartLevel then\
  1765. ok, err = pcall( function()\
  1766. term.setTextColor(colors.white)\
  1767. term.setBackgroundColor( colors.black )\
  1768. term.clear()\
  1769. drawStars()\
  1770. term.setTextColor( colors.red )\
  1771. printCentred( TermH/2 - 1, \" REDIRECTION \" )\
  1772. printCentred( TermH/2 - 0, \" ComputerCraft Edition \" )\
  1773. term.setTextColor( colors.yellow )\
  1774. printCentred( TermH/2 + 2, \" Click to Begin \" )\
  1775. os.pullEvent( \"mouse_click\" )\
  1776. end )\
  1777. end\
  1778. \
  1779. \
  1780. \
  1781. --Game--\
  1782. if ok then\
  1783. ok,err = pcall( function()\
  1784. if sStartLevel then\
  1785. nLevel = tonumber( sStartLevel )\
  1786. else\
  1787. nLevel = 1\
  1788. end\
  1789. while nLevel do\
  1790. reset()\
  1791. nLevel = startG(nLevel)\
  1792. end\
  1793. end )\
  1794. end\
  1795. \
  1796. --Upsell screen--\
  1797. if ok then\
  1798. ok, err = pcall( function()\
  1799. term.setTextColor(colors.white)\
  1800. term.setBackgroundColor( colors.black )\
  1801. term.clear()\
  1802. drawStars()\
  1803. term.setTextColor( colors.red )\
  1804. if TermW >= 40 then\
  1805. printCentred( TermH/2 - 1, \" Thank you for playing Redirection \" )\
  1806. printCentred( TermH/2 - 0, \" ComputerCraft Edition \" )\
  1807. printCentred( TermH/2 + 2, \" Check out the full game: \" )\
  1808. term.setTextColor( colors.yellow )\
  1809. printCentred( TermH/2 + 3, \" http://www.redirectiongame.com \" )\
  1810. else\
  1811. printCentred( TermH/2 - 2, \" Thank you for \" )\
  1812. printCentred( TermH/2 - 1, \" playing Redirection \" )\
  1813. printCentred( TermH/2 - 0, \" ComputerCraft Edition \" )\
  1814. printCentred( TermH/2 + 2, \" Check out the full game: \" )\
  1815. term.setTextColor( colors.yellow )\
  1816. printCentred( TermH/2 + 3, \" www.redirectiongame.com \" )\
  1817. end\
  1818. parallel.waitForAll(\
  1819. function() sleep(2) end,\
  1820. function() os.pullEvent( \"mouse_click\" ) end\
  1821. )\
  1822. end )\
  1823. end\
  1824. \
  1825. --Clear and exit--\
  1826. term.setCursorPos(1,1)\
  1827. term.setTextColor(colors.white)\
  1828. term.setBackgroundColor(colors.black)\
  1829. term.clear()\
  1830. if not ok then\
  1831. if err == \"Terminated\" then\
  1832. print( \"Check out the full version of Redirection:\" )\
  1833. print( \"http://www.redirectiongame.com\" )\
  1834. else\
  1835. printError( err )\
  1836. end\
  1837. end",
  1838. [ "Flutter/Programs/levels/3" ] = "2\
  1839. 77777777\
  1840. 777888188777\
  1841. 7b78777787b7\
  1842. 78787 78787\
  1843. 78787 78787\
  1844. 78887 78887\
  1845. 777877778777\
  1846. 78838887\
  1847. 77777777",
  1848. [ "Flutter/Programs/tag" ] = "",
  1849. [ "Flutter/publish" ] = "print(\"Please wait!\")\
  1850. local savetable = {}\
  1851. function compact(path)\
  1852. local file\
  1853. for k, v in ipairs(fs.list(path)) do\
  1854. if fs.isDir(path..\"/\"..v) then\
  1855. compact(path..\"/\"..v)\
  1856. elseif fs.exists(path..\"/\"..v) then\
  1857. file = fs.open(path..\"/\"..v, \"r\")\
  1858. if file then\
  1859. savetable[path..\"/\"..v] = file.readAll()\
  1860. file.close()\
  1861. end\
  1862. end\
  1863. end\
  1864. end\
  1865. \
  1866. compact(\"Flutter\")\
  1867. local file = fs.open(\"FlutterFile\", \"w\")\
  1868. file.write(textutils.serialize(savetable))\
  1869. file.close()\
  1870. print(\"Done serializing!\")",
  1871. [ "Flutter/Programs/levels/5" ] = "3\
  1872. 777777777\
  1873. 788888887\
  1874. 787787787\
  1875. 787787787\
  1876. 788888887\
  1877. 787787787\
  1878. 787787787\
  1879. 78e748887\
  1880. 777777777",
  1881. [ "Flutter/Programs/levels/0" ] = "0\
  1882. 77 77\
  1883. 718888887\
  1884. 8 8\
  1885. 8 8\
  1886. 8 8\
  1887. 788888897\
  1888. 77 77",
  1889. [ "Flutter/Apis/flu" ] = "local mood = nil\
  1890. local name = \"Flutter\"\
  1891. local unknownQuestionReply = \"I don't know the answer to that question.\"\
  1892. local runningCoroutines = {}\
  1893. local memorizedReplies = {}\
  1894. local defaultReplies = {}\
  1895. local menuOptions = {}\
  1896. \
  1897. -- Returns the name of the assistant.\
  1898. function getName()\
  1899. return name\
  1900. end\
  1901. \
  1902. function getQuestion(question)\
  1903. question = string.lower(question)\
  1904. if defaultReplies[question] then\
  1905. return defaultReplies[question][1]\
  1906. elseif memorizedReplies[question] then\
  1907. return memorizedReplies[question][1]\
  1908. else\
  1909. for key, value in pairs(defaultReplies) do\
  1910. if string.find(key, \"repLACE\", 1, true) then\
  1911. local wordNum, chars = 0, 0\
  1912. local lastWord = \"\"\
  1913. local continue = true\
  1914. for word in string.gmatch(key, \"%a+\") do\
  1915. if continue then\
  1916. wordNum = wordNum + 1\
  1917. --print(word)\
  1918. if string.find(word, \"repLACE\", 1, true) then\
  1919. local pos1, pos2 = string.find(string.lower(question), string.lower(lastWord))\
  1920. local str, str2 = key, string.sub(question, pos2 + 2)\
  1921. --print(str..\", \"..str2)\
  1922. return defaultReplies[str][str2]\
  1923. end\
  1924. chars = chars + #word + 1\
  1925. lastWord = tostring(word)\
  1926. if not string.find(string.lower(question), string.lower(lastWord)) then\
  1927. -- This isn't the same question as the key we looked at, cancel the operation\
  1928. continue = false\
  1929. end\
  1930. end\
  1931. end\
  1932. else\
  1933. if string.find(question, key, 1, true) then\
  1934. return defaultReplies[key][1]\
  1935. end\
  1936. end\
  1937. end\
  1938. end\
  1939. end\
  1940. \
  1941. -- Asks the assistant to reply to this question.\
  1942. function getReply(question)\
  1943. question = string.lower(question)\
  1944. local questionTag = getQuestion(question)\
  1945. if type(questionTag) == \"function\" then\
  1946. return questionTag()\
  1947. elseif type(questionTag) == \"string\" then\
  1948. return questionTag\
  1949. else\
  1950. return unknownQuestionReply\
  1951. end\
  1952. end\
  1953. \
  1954. -- \
  1955. function getOptions(menu)\
  1956. \
  1957. end\
  1958. \
  1959. function cloneQuestion(question, question2)\
  1960. defaultReplies[question2] = setmetatable({}, {__index = defaultReplies[question]})\
  1961. end\
  1962. \
  1963. -- Default questions and answers --\
  1964. local function tellName(tab, path)\
  1965. return \"My name is \"..getName()..\". I am a personal assistant and I am here to help you.\"\
  1966. end\
  1967. \
  1968. local function runApplication(tab, path)\
  1969. local ok, err = pcall(shell.openTab, tostring(path))\
  1970. if ok then\
  1971. return \"I opened \"..path..\" for you.\"\
  1972. else\
  1973. return \"I could not run that program successfuly.\"..err\
  1974. end\
  1975. end\
  1976. \
  1977. defaultReplies[\"please open repLACE\"] = setmetatable({}, {__index = runApplication})\
  1978. cloneQuestion(\"please open repLACE\", \"please run repLACE\")\
  1979. cloneQuestion(\"please open repLACE\", \"open repLACE\")\
  1980. cloneQuestion(\"please open repLACE\", \"run repLACE\")\
  1981. defaultReplies[\"what is your name\"] = setmetatable({}, {__index = tellName})\
  1982. cloneQuestion(\"what is your name\", \"who are you\")\
  1983. cloneQuestion(\"what is your name\", \"what is this\")\
  1984. cloneQuestion(\"what is your name\", \"what do you do\")\
  1985. defaultReplies[\"starttext\"] = {\"Ask me anything. Type in the given box below.\"}",
  1986. [ "Flutter/background" ] = "",
  1987. [ "Flutter/Autocomplete/edit" ] = "completeEdit",
  1988. [ "Flutter/Programs/levels/8" ] = "4\
  1989. 777777 7777\
  1990. 7287b7 7867\
  1991. 788787 7887\
  1992. 77878777877\
  1993. 7888eb8887\
  1994. 77877787877\
  1995. 7887 787887\
  1996. 7487 7e7807\
  1997. 7777 777777",
  1998. [ "Flutter/startup" ] = "-- Set the label if one does not exist --\
  1999. local computerLabel = os.getComputerLabel()\
  2000. if not computerLabel then\
  2001. os.setComputerLabel(\"Computer #\" .. os.getComputerID())\
  2002. end\
  2003. \
  2004. -- Set up Flutter API --\
  2005. multishell = nil\
  2006. local Flutter = {}\
  2007. Flutter.Dir = string.sub(shell.getRunningProgram(), 1, -(#fs.getName(shell.getRunningProgram())) - 1)\
  2008. Flutter.Dir = \"Flutter/\"\
  2009. _G.Flutter = Flutter\
  2010. \
  2011. local function overrideFile(path, str)\
  2012. local file = fs.open(path, \"w\")\
  2013. if file then\
  2014. file.write(str)\
  2015. file.close()\
  2016. return true\
  2017. end\
  2018. return false\
  2019. end\
  2020. \
  2021. local function readFile(path)\
  2022. local file = fs.open(path, \"r\")\
  2023. if file then\
  2024. local str = file.readAll()\
  2025. file.close()\
  2026. return str\
  2027. end\
  2028. return false\
  2029. end\
  2030. \
  2031. local function loadTable(path)\
  2032. local str = readFile(path)\
  2033. if str then\
  2034. return textutils.unserialize(str)\
  2035. end\
  2036. return false\
  2037. end\
  2038. \
  2039. local function saveTable(path, tab)\
  2040. local ok, str = pcall(textutils.serialize, tab)\
  2041. if ok then\
  2042. return overrideFile(path, str)\
  2043. end\
  2044. return false, str\
  2045. end\
  2046. \
  2047. Flutter.overrideFile = overrideFile\
  2048. Flutter.readFile = readFile\
  2049. Flutter.loadTable = loadTable\
  2050. Flutter.saveTable = saveTable\
  2051. Flutter.startInWindowShellMode = (readFile(Flutter.Dir..\"Configuration/MultishellMode\") or \"\") ~= \"true\"\
  2052. \
  2053. _G.Clipboard = \"\"\
  2054. _G.ReadColors = {}\
  2055. _G.ReadHistory = loadTable(Flutter.Dir..\"Configuration/ReadHistory\") or {}\
  2056. \
  2057. local rawPullEvent = os.pullEventRaw\
  2058. local rawOsRun = os.run\
  2059. local rawSetTextColor = term.setTextColor\
  2060. local rawSetBgColor = term.setBackgroundColor\
  2061. local lastKeyPressed\
  2062. \
  2063. -- Set up test quick menu\
  2064. Flutter.QuickMenu = {}\
  2065. Flutter.QuickMenu.ProgramsList = loadTable(Flutter.Dir..\"Configuration/ProgramsList\") or {}\
  2066. \
  2067. -- Override default ComputerCraft functions --\
  2068. \
  2069. -- Override term.setTextColor\
  2070. function term.setTextColor(color)\
  2071. rawSetTextColor(color)\
  2072. Flutter.currentTextColor = color\
  2073. end\
  2074. \
  2075. -- Override term.setBackgroundColor\
  2076. function term.setBackgroundColor(color)\
  2077. rawSetBgColor(color)\
  2078. Flutter.currentBgColor = color\
  2079. end\
  2080. \
  2081. -- Override os.run\
  2082. function rawOsRun( _tEnv, _sPath, ... )\
  2083. local tArgs = { ... }\
  2084. local fnFile, err = loadfile( _sPath )\
  2085. if fnFile then\
  2086. local tEnv = _tEnv\
  2087. --setmetatable( tEnv, { __index = function(t,k) return _G[k] end } )\
  2088. setmetatable( tEnv, { __index = _G } )\
  2089. setfenv( fnFile, tEnv )\
  2090. local ok, err = pcall( function()\
  2091. fnFile( unpack( tArgs ) )\
  2092. end )\
  2093. if not ok then\
  2094. if err and err ~= \"\" then\
  2095. printError( err )\
  2096. end\
  2097. return false\
  2098. end\
  2099. return true\
  2100. end\
  2101. if err and err ~= \"\" then\
  2102. if err == \"File not found\" then\
  2103. printError( \"File \".._sPath..\" could not be found. It most likely does not exist.\" )\
  2104. else\
  2105. printError( err )\
  2106. end\
  2107. end\
  2108. return false\
  2109. end\
  2110. \
  2111. function _G.os.run(envVars, path, ...)\
  2112. if fs.exists(path) then\
  2113. local matched = path:find(\"setupAutocomplete\")\
  2114. local name = string.sub(path, -(#fs.getName(path)), -1)\
  2115. name = string.upper(string.sub(name, 0, 1))..string.sub(name, 2)\
  2116. for k, v in ipairs(Flutter.QuickMenu.ProgramsList) do\
  2117. if v[2] == path then\
  2118. matched = k\
  2119. break\
  2120. end\
  2121. end\
  2122. if not matched then\
  2123. if #Flutter.QuickMenu.ProgramsList > 14 then\
  2124. table.remove(Flutter.QuickMenu.ProgramsList, 2)\
  2125. end\
  2126. table.insert(Flutter.QuickMenu.ProgramsList, {name, path, false})\
  2127. saveTable(Flutter.Dir..\"Configuration/ProgramsList\", Flutter.QuickMenu.ProgramsList)\
  2128. end\
  2129. end\
  2130. return rawOsRun(envVars, path, ...)\
  2131. end\
  2132. \
  2133. -- Override os.pullEventRaw\
  2134. function _G.os.pullEventRaw( sFilter )\
  2135. local eventData = { rawPullEvent( sFilter ) }\
  2136. if eventData[1] == \"key\" then\
  2137. if lastKeyPressed == keys.leftCtrl then\
  2138. if eventData[2] == keys.p then\
  2139. skipCharInput = true\
  2140. pasteMode = true\
  2141. for k=1, #_G.Clipboard do\
  2142. os.queueEvent(\"char\", string.sub(_G.Clipboard, k, k))\
  2143. end\
  2144. os.queueEvent(\"clipboard_paste_done\", #_G.Clipboard)\
  2145. end\
  2146. end\
  2147. lastKeyPressed = eventData[2]\
  2148. end\
  2149. return unpack( eventData )\
  2150. end\
  2151. \
  2152. -- Override os.pullEvent\
  2153. function _G.os.pullEvent( sFilter )\
  2154. local eventData = { rawPullEvent( sFilter ) }\
  2155. if eventData[1] == \"terminate\" then\
  2156. error( \"Terminated by user\", 0 )\
  2157. elseif eventData[1] == \"key\" then\
  2158. if lastKeyPressed == keys.leftCtrl then\
  2159. if eventData[2] == keys.p then\
  2160. skipCharInput = true\
  2161. pasteMode = true\
  2162. for k=1, #_G.Clipboard do\
  2163. os.queueEvent(\"char\", string.sub(_G.Clipboard, k, k))\
  2164. end\
  2165. os.queueEvent(\"clipboard_paste_done\", #_G.Clipboard)\
  2166. end\
  2167. end\
  2168. lastKeyPressed = eventData[2]\
  2169. end\
  2170. return unpack( eventData )\
  2171. end\
  2172. \
  2173. function showTextBox(x, y, width, height, text, history, color, backcolor, _fnComplete )\
  2174. local cursorpos, scrollx = math.min(x or 0, #text), 0\
  2175. scrollx = cursorpos\
  2176. local strClr = string.rep(\" \", width + 1)\
  2177. if #text == 0 then \
  2178. term.write(strClr)\
  2179. end\
  2180. local selectColor, ctrlColor = colors.blue, colors.red\
  2181. local currentEntryInHistory = #history + 1\
  2182. local toggleSelect = false\
  2183. local selectLeft, selectRight, selectStart = nil, nil, nil\
  2184. local lastKeyPressed\
  2185. \
  2186. local tCompletions\
  2187. local nCompletion\
  2188. local function recomplete()\
  2189. if _fnComplete and cursorpos == string.len(text) then\
  2190. tCompletions = _fnComplete( text )\
  2191. if tCompletions and #tCompletions > 0 then\
  2192. nCompletion = 1\
  2193. else\
  2194. nCompletion = nil\
  2195. end\
  2196. else\
  2197. tCompletions = nil\
  2198. nCompletion = nil\
  2199. end\
  2200. end\
  2201. \
  2202. local function uncomplete()\
  2203. tCompletions = nil\
  2204. nCompletion = nil\
  2205. end\
  2206. \
  2207. recomplete()\
  2208. \
  2209. local function acceptCompletion()\
  2210. if nCompletion then\
  2211. -- Find the common prefix of all the other suggestions which start with the same letter as the current one\
  2212. local sCompletion = tCompletions[ nCompletion ]\
  2213. local sFirstLetter = string.sub( sCompletion, 1, 1 )\
  2214. local sCommonPrefix = sCompletion\
  2215. for n=1,#tCompletions do\
  2216. local sResult = tCompletions[n]\
  2217. if n ~= nCompletion and string.find( sResult, sFirstLetter, 1, true ) == 1 then\
  2218. while #sCommonPrefix > 1 do\
  2219. if string.find( sResult, sCommonPrefix, 1, true ) == 1 then\
  2220. break\
  2221. else\
  2222. sCommonPrefix = string.sub( sCommonPrefix, 1, #sCommonPrefix - 1 )\
  2223. end\
  2224. end\
  2225. end\
  2226. end\
  2227. \
  2228. -- Append this string\
  2229. text = text .. sCommonPrefix\
  2230. cursorpos = string.len( text )\
  2231. end\
  2232. \
  2233. recomplete()\
  2234. --redraw()\
  2235. end\
  2236. \
  2237. term.setCursorBlink(true)\
  2238. while true do\
  2239. if #text > width then\
  2240. scrollx = math.min(math.max(cursorpos - width*.5, 0), #text - width)\
  2241. else\
  2242. scrollx = 0\
  2243. end\
  2244. term.setCursorPos(x + cursorpos - scrollx, y)\
  2245. skipCharInput = false\
  2246. local event, p1, p2, p3, p4 = os.pullEvent()\
  2247. if(event == \"key\") then\
  2248. if(p1 == keys.left) then\
  2249. cursorpos = math.max(cursorpos - 1, 0)\
  2250. if toggleSelect and selectLeft then\
  2251. if cursorpos + 1 < selectStart then\
  2252. selectLeft = cursorpos + 1\
  2253. else\
  2254. selectLeft = math.min(selectLeft, cursorpos + 1)\
  2255. selectRight = math.min(selectRight, selectStart)\
  2256. end\
  2257. else\
  2258. selectLeft, selectRight = nil, nil\
  2259. end\
  2260. elseif(p1 == keys.right) then\
  2261. if cursorpos < string.len(text) then\
  2262. -- Move right\
  2263. cursorpos = math.min(cursorpos + 1, #text)\
  2264. else\
  2265. -- Accept autocomplete\
  2266. acceptCompletion()\
  2267. end\
  2268. if toggleSelect and selectLeft then\
  2269. if cursorpos + 1 > selectStart then\
  2270. selectRight = math.max(selectRight, selectStart, cursorpos + 1)\
  2271. else\
  2272. selectLeft = math.max(selectLeft, cursorpos + 1)\
  2273. end\
  2274. else\
  2275. selectLeft, selectRight = nil, nil\
  2276. end\
  2277. elseif(p1 == keys.up or p1 == keys.down) then\
  2278. -- Cycle completions\
  2279. if p1 == keys.up then\
  2280. if nCompletion then\
  2281. nCompletion = nCompletion - 1\
  2282. if nCompletion < 1 then\
  2283. nCompletion = #tCompletions\
  2284. end\
  2285. elseif #history > 0 then\
  2286. currentEntryInHistory = math.max(1, currentEntryInHistory - 1)\
  2287. text = history[currentEntryInHistory] or \"\"\
  2288. cursorpos = #text\
  2289. end\
  2290. elseif p1 == keys.down then\
  2291. if nCompletion then\
  2292. nCompletion = nCompletion + 1\
  2293. if nCompletion > #tCompletions then\
  2294. nCompletion = 1\
  2295. end\
  2296. elseif #history > 0 then\
  2297. currentEntryInHistory = math.min(#history + 1, currentEntryInHistory + 1)\
  2298. text = history[currentEntryInHistory] or \"\"\
  2299. cursorpos = #text\
  2300. end\
  2301. end\
  2302. elseif(p1 == keys.enter) then\
  2303. term.setCursorPos(x + cursorpos - scrollx, y)\
  2304. term.setCursorPos(x, y)\
  2305. term.setTextColor(color)\
  2306. term.write(strClr)\
  2307. term.setCursorPos(x, y)\
  2308. term.write(string.sub(text, scrollx, scrollx + width))\
  2309. term.setTextColor(color)\
  2310. term.setBackgroundColor(backcolor)\
  2311. term.setCursorBlink(false)\
  2312. return text\
  2313. elseif(p1 == keys.rightShift) then\
  2314. toggleSelect = not toggleSelect\
  2315. if toggleSelect and not selectLeft then\
  2316. selectStart = cursorpos + 1\
  2317. selectLeft, selectRight = cursorpos + 1, cursorpos + 1\
  2318. end\
  2319. elseif(p1 == keys.backspace) then\
  2320. if cursorpos > 0 or selectLeft then\
  2321. text = string.sub(text, 1, (selectLeft) or cursorpos - 1) .. string.sub(text, (selectRight) or cursorpos + 1, -1)\
  2322. cursorpos = math.max(cursorpos - 1, 0)\
  2323. end\
  2324. elseif(p1 == keys.delete) then\
  2325. if cursorpos < #text then\
  2326. text = string.sub(text, 1, cursorpos) .. string.sub(text, cursorpos + 2, -1)\
  2327. end\
  2328. elseif(p1 == keys.home) then\
  2329. cursorpos = 0\
  2330. elseif(keys.getName(p1) == \"end\") then\
  2331. cursorpos = #text\
  2332. elseif(p1 == keys.tab) then\
  2333. -- Tab (accept autocomplete)\
  2334. acceptCompletion()\
  2335. elseif(lastKeyPressed == keys.leftCtrl) and (p1 == keys.c) and selectLeft then\
  2336. local clipboardText = string.sub(text, selectLeft, selectRight)\
  2337. _G.Clipboard = clipboardText\
  2338. os.queueEvent(\"clipboard_copy\", string.sub(text, selectLeft, selectRight))\
  2339. skipCharInput = true\
  2340. elseif(lastKeyPressed == keys.leftCtrl) and (p1 == keys.a) then\
  2341. selectLeft, selectRight = 1, #text\
  2342. skipCharInput = true\
  2343. end\
  2344. lastKeyPressed = p1\
  2345. end\
  2346. if(event == \"char\") and ((not skipCharInput and not (lastKeyPressed == keys.leftCtrl)) or pasteMode) then\
  2347. text = string.sub(text, 1, cursorpos) .. p1 .. string.sub(text, cursorpos + 1, -1)\
  2348. cursorpos = cursorpos + 1\
  2349. end\
  2350. if(event == \"clipboard_paste_done\") then\
  2351. skipCharInput = false\
  2352. pasteMode = false\
  2353. end\
  2354. if(event == \"mouse_click\") then\
  2355. cursorpos = math.min(p2 - (x) + scrollx, #text)\
  2356. end\
  2357. if(event == \"paste\") then\
  2358. text = string.sub(text, 1, cursorpos) .. p1 .. string.sub(text, cursorpos + 1, -1)\
  2359. cursorpos = cursorpos + #p1\
  2360. end\
  2361. if #text > width then\
  2362. scrollx = math.min(math.max(cursorpos - width*.5, 0), #text - width)\
  2363. else\
  2364. scrollx = 0\
  2365. end\
  2366. if p1 ~= keys.up and p1 ~= keys.down then\
  2367. recomplete()\
  2368. end\
  2369. -- Redraw window\
  2370. term.setCursorPos(x + cursorpos - scrollx, y)\
  2371. term.setCursorPos(x, y)\
  2372. term.setTextColor(color)\
  2373. term.write(strClr)\
  2374. term.setCursorPos(x, y)\
  2375. term.write(string.sub(text, scrollx, scrollx + width))\
  2376. if selectLeft then\
  2377. term.setBackgroundColor(selectColor)\
  2378. term.setTextColor(color)\
  2379. term.setCursorPos((x + selectLeft - scrollx) - 1, y)\
  2380. term.write(string.sub(text, selectLeft, selectRight))\
  2381. term.setTextColor(selectColor)\
  2382. end\
  2383. if lastKeyPressed == keys.leftCtrl then\
  2384. term.setTextColor(ctrlColor)\
  2385. elseif not toggleSelect then\
  2386. term.setTextColor(color)\
  2387. else\
  2388. term.setTextColor(selectColor)\
  2389. end\
  2390. if nCompletion then\
  2391. local sCompletion = tCompletions[ nCompletion ]\
  2392. local oldText, oldBg\
  2393. if not _bClear then\
  2394. oldText = term.getTextColor()\
  2395. oldBg = term.getBackgroundColor()\
  2396. term.setTextColor( colors.white )\
  2397. term.setBackgroundColor( colors.gray )\
  2398. end\
  2399. local curX, curY = term.getCursorPos()\
  2400. if sReplace then\
  2401. term.write( string.rep( sReplace, string.len( sCompletion ) ) )\
  2402. else\
  2403. term.write( sCompletion )\
  2404. end\
  2405. if not _bClear then\
  2406. term.setTextColor( oldText )\
  2407. term.setBackgroundColor( oldBg )\
  2408. end\
  2409. end\
  2410. term.setBackgroundColor(backcolor)\
  2411. end\
  2412. end\
  2413. \
  2414. \
  2415. -- Override global read\
  2416. function _G.read( _sReplaceChar, _tHistory, _fnComplete )\
  2417. local bgColor, textColor = colors.black, colors.white\
  2418. local x, y = term.getCursorPos()\
  2419. local width, height = term.getSize()\
  2420. local isUsingGlobalHistory = type(_tHistory) ~= \"table\"\
  2421. width = width - x, 0\
  2422. if type(_tHistory) == \"table\" then\
  2423. if #_tHistory < 1 then\
  2424. isUsingGlobalHistory = true\
  2425. end\
  2426. end\
  2427. if isUsingGlobalHistory then\
  2428. _tHistory = _G.ReadHistory\
  2429. end\
  2430. local text = showTextBox(x, y, width, height, \"\", _tHistory, Flutter.currentTextColor, Flutter.currentBgColor, _fnComplete )\
  2431. if isUsingGlobalHistory then\
  2432. if text ~= \"\" then\
  2433. table.insert(_G.ReadHistory, text)\
  2434. saveTable(Flutter.Dir..\"Configuration/ReadHistory\", _G.ReadHistory)\
  2435. end\
  2436. end\
  2437. print(\"\")\
  2438. return text\
  2439. end\
  2440. \
  2441. -- Load the default programs list\
  2442. for k, v in ipairs(fs.list(Flutter.Dir..\"Programs\")) do\
  2443. shell.clearAlias(v)\
  2444. shell.setAlias(v, Flutter.Dir..\"Programs/\"..v)\
  2445. end\
  2446. \
  2447. -- Load the default APIs\
  2448. for k, v in ipairs(fs.list(Flutter.Dir..\"APIs\")) do\
  2449. os.unloadAPI(Flutter.Dir..\"APIs/\"..v)\
  2450. os.loadAPI(Flutter.Dir..\"APIs/\"..v)\
  2451. end\
  2452. \
  2453. index.rebuildIndex()\
  2454. \
  2455. shell.run(Flutter.Dir..\"setupAutocomplete\")\
  2456. local errorMessage\
  2457. while true do\
  2458. if Flutter.startInWindowShellMode then\
  2459. --term.redirect(term.native())\
  2460. local ok, err = pcall(shell.run, Flutter.Dir..\"windowshell\")\
  2461. if not ok then\
  2462. errorMessage = err\
  2463. end\
  2464. else -- The windowshell crashed and we opened the regular multishell\
  2465. _G.windowShell = nil\
  2466. shell.setAlias(\"windowshell\", Flutter.Dir..\"windowshell\")\
  2467. local oldOsRun = os.run\
  2468. function os.run(...)\
  2469. local args = {...}\
  2470. if args[2] == \"/rom/programs/shell\" then\
  2471. args[2] = Flutter.Dir..\"Programs/shell\"\
  2472. end\
  2473. oldOsRun(unpack(args))\
  2474. end\
  2475. multishell = nil\
  2476. _G.multishell = nil\
  2477. term.redirect(term.native())\
  2478. term.setBackgroundColor(colors.black)\
  2479. term.setTextColor(colors.white)\
  2480. term.setCursorPos(1, 1)\
  2481. term.setCursorBlink(false)\
  2482. term.clear()\
  2483. local ok, err = pcall(shell.run, \"rom/programs/advanced/multishell\")\
  2484. if not ok then\
  2485. errorMessage = err\
  2486. end\
  2487. os.run = oldOsRun\
  2488. end\
  2489. \
  2490. -- An error occured --\
  2491. term.redirect(term.native())\
  2492. if term.isColor() then\
  2493. term.setTextColor(colors.red)\
  2494. else\
  2495. term.setTextColor(colors.white)\
  2496. end\
  2497. term.setBackgroundColor(colors.black)\
  2498. term.clear()\
  2499. term.setCursorPos(1, 1)\
  2500. term.write(errorMessage or \"You terminated the shell.\")\
  2501. \
  2502. term.setCursorPos(1, 2)\
  2503. term.setTextColor(colors.white)\
  2504. print(\"Press Enter to continue.\")\
  2505. print(\"Press Shift to reboot.\")\
  2506. print(\"Press Space to shut down.\")\
  2507. local e, key = os.pullEvent(\"key\")\
  2508. if key == keys.leftShift or key == keys.rightShift then\
  2509. os.reboot()\
  2510. elseif key == keys.space then\
  2511. os.shutdown()\
  2512. end\
  2513. Flutter.startInWindowShellMode = false\
  2514. end",
  2515. [ "Flutter/Programs/levels/1" ] = "1\
  2516. 777\
  2517. 7b7\
  2518. 787\
  2519. 7777778777\
  2520. 7188888887\
  2521. 7777777777",
  2522. [ "Flutter/tabshell" ] = "",
  2523. [ "Flutter/Programs/levels/9" ] = "2\
  2524. 777 777\
  2525. 777877778777\
  2526. 788838888887\
  2527. 7778bbbbbbbb8777\
  2528. 7888b888888b8897\
  2529. 7878be8888eb8787\
  2530. 7588b888888b8887\
  2531. 7778bbbbbbbb8777\
  2532. 788888818887\
  2533. 777877778777\
  2534. 777 777",
  2535. [ "Flutter/Programs/adventure" ] = "local tCommandHistory = {}\
  2536. local tBiomes = {\
  2537. \"in a forest\",\
  2538. \"in a pine forest\",\
  2539. \"knee deep in a swamp\",\
  2540. \"in a mountain range\",\
  2541. \"in a desert\",\
  2542. \"in a grassy plain\",\
  2543. \"in frozen tundra\",\
  2544. \"in a jungle\",\
  2545. }\
  2546. \
  2547. local function hasTrees( _nBiome )\
  2548. return _nBiome <= 3 or _nBiome == 8\
  2549. end\
  2550. \
  2551. local function hasStone( _nBiome )\
  2552. return _nBiome == 4\
  2553. end\
  2554. \
  2555. local function hasRivers( _nBiome )\
  2556. return _nBiome ~= 3 and _nBiome ~= 5\
  2557. end\
  2558. \
  2559. local items = {\
  2560. [\"no tea\"] = {\
  2561. droppable = false,\
  2562. desc = \"Pull yourself together man.\",\
  2563. },\
  2564. [\"a pig\"] = {\
  2565. heavy = true,\
  2566. creature = true,\
  2567. drops = { \"some pork\" },\
  2568. aliases = { \"pig\" },\
  2569. desc = \"The pig has a square nose.\",\
  2570. },\
  2571. [\"a cow\"] = {\
  2572. heavy = true,\
  2573. creature = true,\
  2574. aliases = { \"cow\" },\
  2575. desc = \"The cow stares at you blankly.\",\
  2576. },\
  2577. [\"a sheep\"] = {\
  2578. heavy = true,\
  2579. creature = true,\
  2580. hitDrops = { \"some wool\" },\
  2581. aliases = { \"sheep\" },\
  2582. desc = \"The sheep is fluffy.\",\
  2583. },\
  2584. [\"a chicken\"] = {\
  2585. heavy = true,\
  2586. creature = true,\
  2587. drops = { \"some chicken\" },\
  2588. aliases = { \"chicken\" },\
  2589. desc = \"The chicken looks delicious.\",\
  2590. },\
  2591. [\"a creeper\"] = {\
  2592. heavy = true,\
  2593. creature = true,\
  2594. monster = true,\
  2595. aliases = { \"creeper\" },\
  2596. desc = \"The creeper needs a hug.\",\
  2597. },\
  2598. [\"a skeleton\"] = {\
  2599. heavy = true,\
  2600. creature = true,\
  2601. monster = true,\
  2602. aliases = { \"skeleton\" },\
  2603. nocturnal = true,\
  2604. desc = \"The head bone's connected to the neck bone, the neck bone's connected to the chest bone, the chest bone's connected to the arm bone, the arm bone's connected to the bow, and the bow is pointed at you.\",\
  2605. },\
  2606. [\"a zombie\"] = {\
  2607. heavy = true,\
  2608. creature = true,\
  2609. monster = true,\
  2610. aliases = { \"zombie\" },\
  2611. nocturnal = true,\
  2612. desc = \"All he wants to do is eat your brains.\",\
  2613. },\
  2614. [\"a spider\"] = {\
  2615. heavy = true,\
  2616. creature = true,\
  2617. monster = true,\
  2618. aliases = { \"spider\" },\
  2619. desc = \"Dozens of eyes stare back at you.\",\
  2620. },\
  2621. [\"a cave entrance\"] = {\
  2622. heavy = true,\
  2623. aliases = { \"cave entance\", \"cave\", \"entrance\" },\
  2624. desc = \"The entrance to the cave is dark, but it looks like you can climb down.\",\
  2625. },\
  2626. [\"an exit to the surface\"] = {\
  2627. heavy = true,\
  2628. aliases = { \"exit to the surface\", \"exit\", \"opening\" },\
  2629. desc = \"You can just see the sky through the opening.\",\
  2630. },\
  2631. [\"a river\"] = {\
  2632. heavy = true,\
  2633. aliases = { \"river\" },\
  2634. desc = \"The river flows majestically towards the horizon. It doesn't do anything else.\",\
  2635. },\
  2636. [\"some sunflowers\"] = {\
  2637. aliases = { \"sunflower\", \"a sunflower\", \"sunflowers\" },\
  2638. desc = \"The sunflower is pointing towards the sun. It of course doesn't do anything, but it is pretty.\",\
  2639. },\
  2640. [\"some wood\"] = {\
  2641. aliases = { \"wood\" },\
  2642. material = true,\
  2643. desc = \"You could easilly craft this wood into planks.\",\
  2644. },\
  2645. [\"some planks\"] = {\
  2646. aliases = { \"planks\", \"wooden planks\", \"wood planks\" },\
  2647. desc = \"You could easilly craft these planks into sticks.\",\
  2648. },\
  2649. [\"some sticks\"] = {\
  2650. aliases = { \"sticks\", \"wooden sticks\", \"wood sticks\" },\
  2651. desc = \"A perfect handle for torches or a pickaxe.\",\
  2652. },\
  2653. [\"a crafting table\"] = {\
  2654. aliases = { \"crafting table\", \"craft table\", \"work bench\", \"workbench\", \"crafting bench\", \"table\", },\
  2655. desc = \"It's a crafting table. I shouldn't tell you this, but these don't actually do anything in this game, you can craft tools whenever you like.\",\
  2656. },\
  2657. [\"a furnace\"] = {\
  2658. aliases = { \"furnace\" },\
  2659. desc = \"It's a furnace. Between you and me, these don't actually do anything in this game.\",\
  2660. },\
  2661. [\"a wooden pickaxe\"] = {\
  2662. aliases = { \"pickaxe\", \"pick\", \"wooden pick\", \"wooden pickaxe\", \"wood pick\", \"wood pickaxe\" },\
  2663. tool = true,\
  2664. toolLevel = 1,\
  2665. toolType = \"pick\",\
  2666. desc = \"The pickaxe looks good for breaking stone and coal.\",\
  2667. },\
  2668. [\"a stone pickaxe\"] = {\
  2669. aliases = { \"pickaxe\", \"pick\", \"stone pick\", \"stone pickaxe\" },\
  2670. tool = true,\
  2671. toolLevel = 2,\
  2672. toolType = \"pick\",\
  2673. desc = \"The pickaxe looks good for breaking iron.\",\
  2674. },\
  2675. [\"an iron pickaxe\"] = {\
  2676. aliases = { \"pickaxe\", \"pick\", \"iron pick\", \"iron pickaxe\" },\
  2677. tool = true,\
  2678. toolLevel = 3,\
  2679. toolType = \"pick\",\
  2680. desc = \"The pickaxe looks strong enough to break diamond.\",\
  2681. },\
  2682. [\"a diamond pickaxe\"] = {\
  2683. aliases = { \"pickaxe\", \"pick\", \"diamond pick\", \"diamond pickaxe\" },\
  2684. tool = true,\
  2685. toolLevel = 4,\
  2686. toolType = \"pick\",\
  2687. desc = \"Best. Pickaxe. Ever.\",\
  2688. },\
  2689. [\"a wooden sword\"] = {\
  2690. aliases = { \"sword\", \"wooden sword\", \"wood sword\" },\
  2691. tool = true,\
  2692. toolLevel = 1,\
  2693. toolType = \"sword\",\
  2694. desc = \"Flimsy, but better than nothing.\",\
  2695. },\
  2696. [\"a stone sword\"] = {\
  2697. aliases = { \"sword\", \"stone sword\" },\
  2698. tool = true,\
  2699. toolLevel = 2,\
  2700. toolType = \"sword\",\
  2701. desc = \"A pretty good sword.\",\
  2702. },\
  2703. [\"an iron sword\"] = {\
  2704. aliases = { \"sword\", \"iron sword\" },\
  2705. tool = true,\
  2706. toolLevel = 3,\
  2707. toolType = \"sword\",\
  2708. desc = \"This sword can slay any enemy.\",\
  2709. },\
  2710. [\"a diamond sword\"] = {\
  2711. aliases = { \"sword\", \"diamond sword\" },\
  2712. tool = true,\
  2713. toolLevel = 4,\
  2714. toolType = \"sword\",\
  2715. desc = \"Best. Sword. Ever.\",\
  2716. },\
  2717. [\"a wooden shovel\"] = {\
  2718. aliases = { \"shovel\", \"wooden shovel\", \"wood shovel\" },\
  2719. tool = true,\
  2720. toolLevel = 1,\
  2721. toolType = \"shovel\",\
  2722. desc = \"Good for digging holes.\",\
  2723. },\
  2724. [\"a stone shovel\"] = {\
  2725. aliases = { \"shovel\", \"stone shovel\" },\
  2726. tool = true,\
  2727. toolLevel = 2,\
  2728. toolType = \"shovel\",\
  2729. desc = \"Good for digging holes.\",\
  2730. },\
  2731. [\"an iron shovel\"] = {\
  2732. aliases = { \"shovel\", \"iron shovel\" },\
  2733. tool = true,\
  2734. toolLevel = 3,\
  2735. toolType = \"shovel\",\
  2736. desc = \"Good for digging holes.\",\
  2737. },\
  2738. [\"a diamond shovel\"] = {\
  2739. aliases = { \"shovel\", \"diamond shovel\" },\
  2740. tool = true,\
  2741. toolLevel = 4,\
  2742. toolType = \"shovel\",\
  2743. desc = \"Good for digging holes.\",\
  2744. },\
  2745. [\"some coal\"] = {\
  2746. aliases = { \"coal\" },\
  2747. ore = true,\
  2748. toolLevel = 1,\
  2749. toolType = \"pick\",\
  2750. desc = \"That coal looks useful for building torches, if only you had a pickaxe to mine it.\",\
  2751. },\
  2752. [\"some dirt\"] = {\
  2753. aliases = { \"dirt\" },\
  2754. material = true,\
  2755. desc = \"Why not build a mud hut?\",\
  2756. },\
  2757. [\"some stone\"] = {\
  2758. aliases = { \"stone\", \"cobblestone\" },\
  2759. material = true,\
  2760. ore = true,\
  2761. infinite = true,\
  2762. toolLevel = 1,\
  2763. toolType = \"pick\",\
  2764. desc = \"Stone is useful for building things, and making stone pickaxes.\",\
  2765. },\
  2766. [\"some iron\"] = {\
  2767. aliases = { \"iron\" },\
  2768. material = true,\
  2769. ore = true,\
  2770. toolLevel = 2,\
  2771. toolType = \"pick\",\
  2772. desc = \"That iron looks mighty strong, you'll need a stone pickaxe to mine it.\",\
  2773. },\
  2774. [\"some diamond\"] = {\
  2775. aliases = { \"diamond\", \"diamonds\" },\
  2776. material = true,\
  2777. ore = true,\
  2778. toolLevel = 3,\
  2779. toolType = \"pick\",\
  2780. desc = \"Sparkly, rare, and impossible to mine without an iron pickaxe.\",\
  2781. },\
  2782. [\"some torches\"] = {\
  2783. aliases = { \"torches\", \"torch\" },\
  2784. desc = \"These won't run out for a while.\",\
  2785. },\
  2786. [\"a torch\"] = {\
  2787. aliases = { \"torch\" },\
  2788. desc = \"Fire, fire, burn so bright, won't you light my cave tonight?\",\
  2789. },\
  2790. [\"some wool\"] = {\
  2791. aliases = { \"wool\" },\
  2792. material = true,\
  2793. desc = \"Soft and good for building.\",\
  2794. },\
  2795. [\"some pork\"] = {\
  2796. aliases = { \"pork\", \"porkchops\" },\
  2797. food = true,\
  2798. desc = \"Delicious and nutricious.\",\
  2799. },\
  2800. [\"some chicken\"] = {\
  2801. aliases = { \"chicken\" },\
  2802. food = true,\
  2803. desc = \"Finger licking good.\",\
  2804. },\
  2805. }\
  2806. \
  2807. local tAnimals = {\
  2808. \"a pig\", \"a cow\", \"a sheep\", \"a chicken\",\
  2809. }\
  2810. \
  2811. local tMonsters = {\
  2812. \"a creeper\", \"a skeleton\", \"a zombie\", \"a spider\"\
  2813. }\
  2814. \
  2815. local tRecipes = {\
  2816. [\"some planks\"] = { \"some wood\" },\
  2817. [\"some sticks\"] = { \"some planks\" },\
  2818. [\"some sticks\"] = { \"some planks\" },\
  2819. [\"a crafting table\"] = { \"some planks\" },\
  2820. [\"a furnace\"] = { \"some stone\" },\
  2821. [\"some torches\"] = { \"some sticks\", \"some coal\" },\
  2822. \
  2823. [\"a wooden pickaxe\"] = { \"some planks\", \"some sticks\" },\
  2824. [\"a stone pickaxe\"] = { \"some stone\", \"some sticks\" },\
  2825. [\"an iron pickaxe\"] = { \"some iron\", \"some sticks\" },\
  2826. [\"a diamond pickaxe\"] = { \"some diamond\", \"some sticks\" },\
  2827. \
  2828. [\"a wooden sword\"] = { \"some planks\", \"some sticks\" },\
  2829. [\"a stone sword\"] = { \"some stone\", \"some sticks\" },\
  2830. [\"an iron sword\"] = { \"some iron\", \"some sticks\" },\
  2831. [\"a diamond sword\"] = { \"some diamond\", \"some sticks\" },\
  2832. \
  2833. [\"a wooden shovel\"] = { \"some planks\", \"some sticks\" },\
  2834. [\"a stone shovel\"] = { \"some stone\", \"some sticks\" },\
  2835. [\"an iron shovel\"] = { \"some iron\", \"some sticks\" },\
  2836. [\"a diamond shovel\"] = { \"some diamond\", \"some sticks\" },\
  2837. }\
  2838. \
  2839. local tGoWest = {\
  2840. \"(life is peaceful there)\",\
  2841. \"(lots of open air)\",\
  2842. \"(to begin life anew)\",\
  2843. \"(this is what we'll do)\",\
  2844. \"(sun in winter time)\",\
  2845. \"(we will do just fine)\",\
  2846. \"(where the skies are blue)\",\
  2847. \"(this and more we'll do)\",\
  2848. }\
  2849. local nGoWest = 0\
  2850. \
  2851. local bRunning = true\
  2852. local tMap = { { {}, }, }\
  2853. local x,y,z = 0,0,0\
  2854. local inventory = {\
  2855. [\"no tea\"] = items[\"no tea\"],\
  2856. }\
  2857. \
  2858. local nTurn = 0\
  2859. local nTimeInRoom = 0\
  2860. local nRandomSeed = 2000\
  2861. local nMapSeed = math.random()*900000\
  2862. local bHardcore = true\
  2863. local bInjured = false\
  2864. local bJustLoaded = true\
  2865. \
  2866. local tDayCycle = {\
  2867. \"It is daytime.\",\
  2868. \"It is daytime.\",\
  2869. \"It is daytime.\",\
  2870. \"It is daytime.\",\
  2871. \"It is daytime.\",\
  2872. \"It is daytime.\",\
  2873. \"It is daytime.\",\
  2874. \"It is daytime.\",\
  2875. \"The sun is setting.\",\
  2876. \"It is night.\",\
  2877. \"It is night.\",\
  2878. \"It is night.\",\
  2879. \"It is night.\",\
  2880. \"It is night.\",\
  2881. \"The sun is rising.\",\
  2882. }\
  2883. \
  2884. local function getTimeOfDay()\
  2885. return math.fmod( math.floor(nTurn/3), #tDayCycle ) + 1\
  2886. end\
  2887. \
  2888. local function isSunny()\
  2889. return (getTimeOfDay() < 10)\
  2890. end\
  2891. \
  2892. local resetGame\
  2893. \
  2894. local function getRoom( x, y, z, dontCreate )\
  2895. tMap[x] = tMap[x] or {}\
  2896. tMap[x][y] = tMap[x][y] or {}\
  2897. if not tMap[x][y][z] and dontCreate ~= true then\
  2898. math.randomseed(nMapSeed + (x*12) + (y*13) + (z*91))\
  2899. local room = {\
  2900. items = {},\
  2901. exits = {},\
  2902. nMonsters = 0,\
  2903. }\
  2904. tMap[x][y][z] = room\
  2905. \
  2906. if y == 0 then\
  2907. -- Room is above ground\
  2908. \
  2909. -- Pick biome\
  2910. room.nBiome = math.random( 1, #tBiomes )\
  2911. room.trees = hasTrees( room.nBiome )\
  2912. \
  2913. -- Add animals\
  2914. if math.random(1,3) == 1 then\
  2915. for n = 1,math.random(1,2) do\
  2916. local sAnimal = tAnimals[ math.random( 1, #tAnimals ) ]\
  2917. room.items[ sAnimal ] = items[ sAnimal ]\
  2918. end\
  2919. end\
  2920. \
  2921. -- Add surface ore\
  2922. if math.random(1,5) == 1 or hasStone( room.nBiome ) then\
  2923. room.items[ \"some stone\" ] = items[ \"some stone\" ]\
  2924. end\
  2925. if math.random(1,8) == 1 then\
  2926. room.items[ \"some coal\" ] = items[ \"some coal\" ]\
  2927. end\
  2928. if math.random(1,8) == 1 and hasRivers( room.nBiome ) then\
  2929. room.items[ \"a river\" ] = items[ \"a river\" ]\
  2930. end\
  2931. \
  2932. -- Add exits\
  2933. room.exits = {\
  2934. [\"north\"] = true,\
  2935. [\"south\"] = true,\
  2936. [\"east\"] = true,\
  2937. [\"west\"] = true,\
  2938. }\
  2939. if math.random(1,8) == 1 then\
  2940. room.exits[\"down\"] = true\
  2941. room.items[\"a cave entrance\"] = items[\"a cave entrance\"]\
  2942. end\
  2943. \
  2944. else\
  2945. -- Room is underground\
  2946. -- Add exits\
  2947. local function tryExit( sDir, sOpp, x, y, z )\
  2948. local adj = getRoom( x, y, z, true )\
  2949. if adj then\
  2950. if adj.exits[sOpp] then\
  2951. room.exits[sDir] = true\
  2952. end\
  2953. else\
  2954. if math.random(1,3) == 1 then\
  2955. room.exits[sDir] = true\
  2956. end\
  2957. end\
  2958. end\
  2959. \
  2960. if y == -1 then\
  2961. local above = getRoom( x, y + 1, z )\
  2962. if above.exits[\"down\"] then\
  2963. room.exits[\"up\"] = true\
  2964. room.items[\"an exit to the surface\"] = items[\"an exit to the surface\"]\
  2965. end\
  2966. else\
  2967. tryExit( \"up\", \"down\", x, y + 1, z )\
  2968. end\
  2969. \
  2970. if y > -3 then\
  2971. tryExit( \"down\", \"up\", x, y - 1, z )\
  2972. end \
  2973. tryExit( \"east\", \"west\", x - 1, y, z )\
  2974. tryExit( \"west\", \"east\", x + 1, y, z )\
  2975. tryExit( \"north\", \"south\", x, y, z + 1 )\
  2976. tryExit( \"south\", \"north\", x, y, z - 1 ) \
  2977. \
  2978. -- Add ores\
  2979. room.items[ \"some stone\" ] = items[ \"some stone\" ]\
  2980. if math.random(1,3) == 1 then\
  2981. room.items[ \"some coal\" ] = items[ \"some coal\" ]\
  2982. end\
  2983. if math.random(1,8) == 1 then\
  2984. room.items[ \"some iron\" ] = items[ \"some iron\" ]\
  2985. end\
  2986. if y == -3 and math.random(1,15) == 1 then\
  2987. room.items[ \"some diamond\" ] = items[ \"some diamond\" ]\
  2988. end\
  2989. \
  2990. -- Turn out the lights\
  2991. room.dark = true\
  2992. end\
  2993. end\
  2994. math.randomseed(nRandomSeed)\
  2995. return tMap[x][y][z]\
  2996. end\
  2997. \
  2998. local function itemize( t )\
  2999. local item = next( t )\
  3000. if item == nil then\
  3001. return \"nothing\"\
  3002. end\
  3003. \
  3004. local text = \"\"\
  3005. while item do\
  3006. text = text .. item\
  3007. \
  3008. local nextItem = next( t, item )\
  3009. if nextItem ~= nil then\
  3010. local nextNextItem = next( t, nextItem )\
  3011. if nextNextItem == nil then\
  3012. text = text .. \" and \"\
  3013. else\
  3014. text = text .. \", \"\
  3015. end\
  3016. end\
  3017. item = nextItem\
  3018. end\
  3019. return text\
  3020. end\
  3021. \
  3022. function findItem( _tList, _sQuery )\
  3023. for sItem, tItem in pairs( _tList ) do\
  3024. if sItem == _sQuery then\
  3025. return sItem\
  3026. end\
  3027. if tItem.aliases ~= nil then\
  3028. for n, sAlias in pairs( tItem.aliases ) do\
  3029. if sAlias == _sQuery then\
  3030. return sItem\
  3031. end\
  3032. end\
  3033. end\
  3034. end\
  3035. return nil\
  3036. end\
  3037. \
  3038. local tMatches = {\
  3039. [\"wait\"] = {\
  3040. \"wait\",\
  3041. },\
  3042. [\"look\"] = {\
  3043. \"look at the ([%a ]+)\",\
  3044. \"look at ([%a ]+)\",\
  3045. \"look\",\
  3046. \"inspect ([%a ]+)\",\
  3047. \"inspect the ([%a ]+)\",\
  3048. \"inspect\",\
  3049. },\
  3050. [\"inventory\"] = {\
  3051. \"check self\",\
  3052. \"check inventory\",\
  3053. \"inventory\",\
  3054. \"i\",\
  3055. },\
  3056. [\"go\"] = {\
  3057. \"go (%a+)\",\
  3058. \"travel (%a+)\",\
  3059. \"walk (%a+)\",\
  3060. \"run (%a+)\",\
  3061. \"move (%a+)\",\
  3062. \"go\",\
  3063. },\
  3064. [\"dig\"] = {\
  3065. \"dig (%a+) using ([%a ]+)\",\
  3066. \"dig (%a+) with ([%a ]+)\",\
  3067. \"dig (%a+)\",\
  3068. \"dig\",\
  3069. },\
  3070. [\"take\"] = {\
  3071. \"pick up the ([%a ]+)\",\
  3072. \"pick up ([%a ]+)\",\
  3073. \"pickup ([%a ]+)\",\
  3074. \"take the ([%a ]+)\",\
  3075. \"take ([%a ]+)\",\
  3076. \"take\",\
  3077. },\
  3078. [\"drop\"] = {\
  3079. \"put down the ([%a ]+)\",\
  3080. \"put down ([%a ]+)\",\
  3081. \"drop the ([%a ]+)\",\
  3082. \"drop ([%a ]+)\",\
  3083. \"drop\",\
  3084. },\
  3085. [\"place\"] = {\
  3086. \"place the ([%a ]+)\",\
  3087. \"place ([%a ]+)\",\
  3088. \"place\",\
  3089. },\
  3090. [\"cbreak\"] = {\
  3091. \"punch the ([%a ]+)\",\
  3092. \"punch ([%a ]+)\",\
  3093. \"punch\",\
  3094. \"break the ([%a ]+) with the ([%a ]+)\",\
  3095. \"break ([%a ]+) with ([%a ]+) \",\
  3096. \"break the ([%a ]+)\",\
  3097. \"break ([%a ]+)\",\
  3098. \"break\",\
  3099. },\
  3100. [\"mine\"] = {\
  3101. \"mine the ([%a ]+) with the ([%a ]+)\",\
  3102. \"mine ([%a ]+) with ([%a ]+)\",\
  3103. \"mine ([%a ]+)\",\
  3104. \"mine\",\
  3105. },\
  3106. [\"attack\"] = {\
  3107. \"attack the ([%a ]+) with the ([%a ]+)\",\
  3108. \"attack ([%a ]+) with ([%a ]+)\",\
  3109. \"attack ([%a ]+)\",\
  3110. \"attack\",\
  3111. \"kill the ([%a ]+) with the ([%a ]+)\",\
  3112. \"kill ([%a ]+) with ([%a ]+)\",\
  3113. \"kill ([%a ]+)\",\
  3114. \"kill\",\
  3115. \"hit the ([%a ]+) with the ([%a ]+)\",\
  3116. \"hit ([%a ]+) with ([%a ]+)\",\
  3117. \"hit ([%a ]+)\",\
  3118. \"hit\",\
  3119. },\
  3120. [\"craft\"] = {\
  3121. \"craft a ([%a ]+)\",\
  3122. \"craft some ([%a ]+)\",\
  3123. \"craft ([%a ]+)\",\
  3124. \"craft\",\
  3125. \"make a ([%a ]+)\",\
  3126. \"make some ([%a ]+)\",\
  3127. \"make ([%a ]+)\",\
  3128. \"make\",\
  3129. },\
  3130. [\"build\"] = {\
  3131. \"build ([%a ]+) out of ([%a ]+)\",\
  3132. \"build ([%a ]+) from ([%a ]+)\",\
  3133. \"build ([%a ]+)\",\
  3134. \"build\",\
  3135. },\
  3136. [\"eat\"] = {\
  3137. \"eat a ([%a ]+)\",\
  3138. \"eat the ([%a ]+)\",\
  3139. \"eat ([%a ]+)\",\
  3140. \"eat\",\
  3141. },\
  3142. [\"help\"] = {\
  3143. \"help me\",\
  3144. \"help\",\
  3145. },\
  3146. [\"exit\"] = {\
  3147. \"exit\",\
  3148. \"quit\",\
  3149. \"goodbye\",\
  3150. \"good bye\",\
  3151. \"bye\",\
  3152. \"farewell\",\
  3153. },\
  3154. [\"reset\"] = {\
  3155. \"reset\",\
  3156. \"start over\",\
  3157. \"new game\",\
  3158. \"start new game\",\
  3159. \"restart\",\
  3160. }\
  3161. }\
  3162. \
  3163. local commands = {}\
  3164. function doCommand( text )\
  3165. if text == \"\" then\
  3166. commands[ \"noinput\" ]()\
  3167. return\
  3168. end\
  3169. \
  3170. for sCommand, t in pairs( tMatches ) do\
  3171. for n, sMatch in pairs( t ) do\
  3172. local tCaptures = { string.match( text, \"^\" .. sMatch .. \"$\" ) }\
  3173. if #tCaptures ~= 0 then\
  3174. local fnCommand = commands[ sCommand ]\
  3175. if #tCaptures == 1 and tCaptures[1] == sMatch then\
  3176. fnCommand()\
  3177. else\
  3178. fnCommand( table.unpack( tCaptures ) )\
  3179. end\
  3180. return\
  3181. end\
  3182. end\
  3183. end\
  3184. commands[ \"badinput\" ]()\
  3185. end\
  3186. \
  3187. function commands.wait()\
  3188. print( \"Time passes...\" )\
  3189. end\
  3190. \
  3191. function commands.look( _sTarget )\
  3192. local room = getRoom( x,y,z )\
  3193. if room.dark then\
  3194. print( \"It is pitch dark.\" )\
  3195. return\
  3196. end\
  3197. \
  3198. if _sTarget == nil then\
  3199. -- Look at the world\
  3200. if y == 0 then\
  3201. io.write( \"You are standing \" .. tBiomes[room.nBiome] .. \". \" )\
  3202. print( tDayCycle[ getTimeOfDay() ] )\
  3203. else\
  3204. io.write( \"You are underground. \" )\
  3205. if next( room.exits ) ~= nil then\
  3206. print( \"You can travel \"..itemize( room.exits )..\".\" )\
  3207. else\
  3208. print()\
  3209. end\
  3210. end\
  3211. if next( room.items ) ~= nil then\
  3212. print( \"There is \" .. itemize( room.items ) .. \" here.\" )\
  3213. end\
  3214. if room.trees then\
  3215. print( \"There are trees here.\" )\
  3216. end\
  3217. \
  3218. else\
  3219. -- Look at stuff\
  3220. if room.trees and (_sTarget == \"tree\" or _sTarget == \"trees\") then\
  3221. print( \"The trees look easy to break.\" )\
  3222. elseif _sTarget == \"self\" or _sTarget == \"myself\" then\
  3223. print( \"Very handsome.\" )\
  3224. else\
  3225. local tItem = nil\
  3226. local sItem = findItem( room.items, _sTarget )\
  3227. if sItem then\
  3228. tItem = room.items[sItem]\
  3229. else\
  3230. sItem = findItem( inventory, _sTarget )\
  3231. if sItem then\
  3232. tItem = inventory[sItem]\
  3233. end\
  3234. end\
  3235. \
  3236. if tItem then\
  3237. print( tItem.desc or (\"You see nothing special about \"..sItem..\".\") )\
  3238. else\
  3239. print( \"You don't see any \".._sTarget..\" here.\" )\
  3240. end\
  3241. end\
  3242. end\
  3243. end\
  3244. \
  3245. function commands.go( _sDir )\
  3246. local room = getRoom( x,y,z )\
  3247. if _sDir == nil then\
  3248. print( \"Go where?\" )\
  3249. return\
  3250. end\
  3251. \
  3252. if nGoWest ~= nil then\
  3253. if _sDir == \"west\" then\
  3254. nGoWest = nGoWest + 1\
  3255. if nGoWest > #tGoWest then\
  3256. nGoWest = 1\
  3257. end\
  3258. print( tGoWest[ nGoWest ] )\
  3259. else\
  3260. if nGoWest > 0 or nTurn > 6 then\
  3261. nGoWest = nil\
  3262. end\
  3263. end\
  3264. end\
  3265. \
  3266. if room.exits[_sDir] == nil then\
  3267. print( \"You can't go that way.\" )\
  3268. return\
  3269. end\
  3270. \
  3271. if _sDir == \"north\" then\
  3272. z = z + 1\
  3273. elseif _sDir == \"south\" then\
  3274. z = z - 1\
  3275. elseif _sDir == \"east\" then\
  3276. x = x - 1\
  3277. elseif _sDir == \"west\" then\
  3278. x = x + 1\
  3279. elseif _sDir == \"up\" then\
  3280. y = y + 1\
  3281. elseif _sDir == \"down\" then\
  3282. y = y - 1\
  3283. else\
  3284. print( \"I don't understand that direction.\" )\
  3285. return\
  3286. end\
  3287. \
  3288. nTimeInRoom = 0\
  3289. doCommand( \"look\" )\
  3290. end\
  3291. \
  3292. function commands.dig( _sDir, _sTool )\
  3293. local room = getRoom( x,y,z )\
  3294. if _sDir == nil then\
  3295. print( \"Dig where?\" )\
  3296. return\
  3297. end\
  3298. \
  3299. local sTool = nil\
  3300. local tTool = nil\
  3301. if _sTool ~= nil then\
  3302. sTool = findItem( inventory, _sTool )\
  3303. if not sTool then\
  3304. print( \"You're not carrying a \".._sTool..\".\" )\
  3305. return\
  3306. end\
  3307. tTool = inventory[ sTool ]\
  3308. end\
  3309. \
  3310. local room = getRoom( x, y, z )\
  3311. local bActuallyDigging = (room.exits[ _sDir ] ~= true)\
  3312. if bActuallyDigging then\
  3313. if sTool == nil or tTool.toolType ~= \"pick\" then\
  3314. print( \"You need to use a pickaxe to dig through stone.\" )\
  3315. return\
  3316. end\
  3317. end\
  3318. \
  3319. if _sDir == \"north\" then\
  3320. room.exits[\"north\"] = true\
  3321. z = z + 1\
  3322. getRoom( x, y, z ).exits[\"south\"] = true\
  3323. \
  3324. elseif _sDir == \"south\" then\
  3325. room.exits[\"south\"] = true\
  3326. z = z - 1\
  3327. getRoom( x, y, z ).exits[\"north\"] = true\
  3328. \
  3329. elseif _sDir == \"east\" then\
  3330. room.exits[\"east\"] = true\
  3331. x = x - 1\
  3332. getRoom( x, y, z ).exits[\"west\"] = true\
  3333. \
  3334. elseif _sDir == \"west\" then\
  3335. room.exits[\"west\"] = true\
  3336. x = x + 1\
  3337. getRoom( x, y, z ).exits[\"east\"] = true\
  3338. \
  3339. elseif _sDir == \"up\" then\
  3340. if y == 0 then\
  3341. print( \"You can't dig that way.\" )\
  3342. return\
  3343. end\
  3344. \
  3345. room.exits[\"up\"] = true\
  3346. if y == -1 then\
  3347. room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]\
  3348. end\
  3349. y = y + 1\
  3350. \
  3351. room = getRoom( x, y, z )\
  3352. room.exits[\"down\"] = true\
  3353. if y == 0 then\
  3354. room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]\
  3355. end\
  3356. \
  3357. elseif _sDir == \"down\" then\
  3358. if y <= -3 then\
  3359. print( \"You hit bedrock.\" )\
  3360. return\
  3361. end\
  3362. \
  3363. room.exits[\"down\"] = true\
  3364. if y == 0 then\
  3365. room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]\
  3366. end\
  3367. y = y - 1\
  3368. \
  3369. room = getRoom( x, y, z )\
  3370. room.exits[\"up\"] = true\
  3371. if y == -1 then\
  3372. room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]\
  3373. end\
  3374. \
  3375. else\
  3376. print( \"I don't understand that direction.\" )\
  3377. return\
  3378. end\
  3379. \
  3380. --\
  3381. if bActuallyDigging then\
  3382. if _sDir == \"down\" and y == -1 or\
  3383. _sDir == \"up\" and y == 0 then\
  3384. inventory[ \"some dirt\" ] = items[ \"some dirt\" ]\
  3385. inventory[ \"some stone\" ] = items[ \"some stone\" ]\
  3386. print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some dirt and stone.\" )\
  3387. else\
  3388. inventory[ \"some stone\" ] = items[ \"some stone\" ]\
  3389. print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some stone.\" )\
  3390. end\
  3391. end\
  3392. \
  3393. nTimeInRoom = 0\
  3394. doCommand( \"look\" )\
  3395. end\
  3396. \
  3397. function commands.inventory()\
  3398. print( \"You are carrying \" .. itemize( inventory ) .. \".\" )\
  3399. end\
  3400. \
  3401. function commands.drop( _sItem )\
  3402. if _sItem == nil then\
  3403. print( \"Drop what?\" )\
  3404. return\
  3405. end\
  3406. \
  3407. local room = getRoom( x,y,z )\
  3408. local sItem = findItem( inventory, _sItem )\
  3409. if sItem then\
  3410. local tItem = inventory[ sItem ]\
  3411. if tItem.droppable == false then\
  3412. print( \"You can't drop that.\" )\
  3413. else\
  3414. room.items[ sItem ] = tItem\
  3415. inventory[ sItem ] = nil\
  3416. print( \"Dropped.\" )\
  3417. end\
  3418. else\
  3419. print( \"You don't have a \".._sItem..\".\" )\
  3420. end\
  3421. end\
  3422. \
  3423. function commands.place( _sItem )\
  3424. if _sItem == nil then\
  3425. print( \"Place what?\" )\
  3426. return\
  3427. end\
  3428. \
  3429. if _sItem == \"torch\" or _sItem == \"a torch\" then\
  3430. local room = getRoom( x,y,z )\
  3431. if inventory[\"some torches\"] or inventory[\"a torch\"] then\
  3432. inventory[\"a torch\"] = nil\
  3433. room.items[\"a torch\"] = items[\"a torch\"]\
  3434. if room.dark then\
  3435. print( \"The cave lights up under the torchflame.\" )\
  3436. room.dark = false\
  3437. elseif y == 0 and not isSunny() then\
  3438. print( \"The night gets a little brighter.\" )\
  3439. else\
  3440. print( \"Placed.\" )\
  3441. end\
  3442. else\
  3443. print( \"You don't have torches.\" )\
  3444. end\
  3445. return\
  3446. end\
  3447. \
  3448. commands.drop( _sItem )\
  3449. end\
  3450. \
  3451. function commands.take( _sItem )\
  3452. if _sItem == nil then\
  3453. print( \"Take what?\" )\
  3454. return\
  3455. end\
  3456. \
  3457. local room = getRoom( x,y,z )\
  3458. local sItem = findItem( room.items, _sItem )\
  3459. if sItem then\
  3460. local tItem = room.items[ sItem ]\
  3461. if tItem.heavy == true then\
  3462. print( \"You can't carry \"..sItem..\".\" )\
  3463. elseif tItem.ore == true then\
  3464. print( \"You need to mine this ore.\" )\
  3465. else\
  3466. if tItem.infinite ~= true then\
  3467. room.items[ sItem ] = nil\
  3468. end\
  3469. inventory[ sItem ] = tItem\
  3470. \
  3471. if inventory[\"some torches\"] and inventory[\"a torch\"] then\
  3472. inventory[\"a torch\"] = nil\
  3473. end\
  3474. if sItem == \"a torch\" and y < 0 then\
  3475. room.dark = true\
  3476. print( \"The cave plunges into darkness.\" )\
  3477. else\
  3478. print( \"Taken.\" )\
  3479. end\
  3480. end\
  3481. else\
  3482. print( \"You don't see a \".._sItem..\" here.\" )\
  3483. end\
  3484. end\
  3485. \
  3486. function commands.mine( _sItem, _sTool )\
  3487. if _sItem == nil then\
  3488. print( \"Mine what?\" )\
  3489. return\
  3490. end\
  3491. if _sTool == nil then\
  3492. print( \"Mine \".._sItem..\" with what?\" )\
  3493. return\
  3494. end \
  3495. commands.cbreak( _sItem, _sTool )\
  3496. end\
  3497. \
  3498. function commands.attack( _sItem, _sTool )\
  3499. if _sItem == nil then\
  3500. print( \"Attack what?\" )\
  3501. return\
  3502. end\
  3503. commands.cbreak( _sItem, _sTool )\
  3504. end\
  3505. \
  3506. function commands.cbreak( _sItem, _sTool )\
  3507. if _sItem == nil then\
  3508. print( \"Break what?\" )\
  3509. return\
  3510. end\
  3511. \
  3512. local sTool = nil\
  3513. if _sTool ~= nil then\
  3514. sTool = findItem( inventory, _sTool )\
  3515. if sTool == nil then\
  3516. print( \"You're not carrying a \".._sTool..\".\" )\
  3517. return\
  3518. end\
  3519. end\
  3520. \
  3521. local room = getRoom( x,y,z )\
  3522. if _sItem == \"tree\" or _sItem == \"trees\" or _sItem == \"a tree\" then\
  3523. print( \"The tree breaks into blocks of wood, which you pick up.\" )\
  3524. inventory[ \"some wood\" ] = items[ \"some wood\" ]\
  3525. return\
  3526. elseif _sItem == \"self\" or _sItem == \"myself\" then\
  3527. if term.isColour() then\
  3528. term.setTextColour( colours.red )\
  3529. end\
  3530. print( \"You have died.\" )\
  3531. print( \"Score: &e0\" )\
  3532. term.setTextColour( colours.white )\
  3533. bRunning = false\
  3534. bDied = true\
  3535. return\
  3536. end\
  3537. \
  3538. local sItem = findItem( room.items, _sItem )\
  3539. if sItem then\
  3540. local tItem = room.items[ sItem ]\
  3541. if tItem.ore == true then\
  3542. -- Breaking ore\
  3543. if not sTool then\
  3544. print( \"You need a tool to break this ore.\" )\
  3545. return\
  3546. end\
  3547. local tTool = inventory[ sTool ]\
  3548. if tTool.tool then\
  3549. if tTool.toolLevel < tItem.toolLevel then\
  3550. print( sTool ..\" is not strong enough to break this ore.\" )\
  3551. elseif tTool.toolType ~= tItem.toolType then\
  3552. print( \"You need a different kind of tool to break this ore.\" )\
  3553. else\
  3554. print( \"The ore breaks, dropping \"..sItem..\", which you pick up.\" )\
  3555. inventory[ sItem ] = items[ sItem ]\
  3556. if tItem.infinite ~= true then\
  3557. room.items[ sItem ] = nil\
  3558. end\
  3559. end\
  3560. else\
  3561. print( \"You can't break \"..sItem..\" with \"..sTool..\".\")\
  3562. end\
  3563. \
  3564. elseif tItem.creature == true then\
  3565. -- Fighting monsters (or pigs)\
  3566. local toolLevel = 0\
  3567. local tTool = nil\
  3568. if sTool then\
  3569. tTool = inventory[ sTool ]\
  3570. if tTool.toolType == \"sword\" then\
  3571. toolLevel = tTool.toolLevel\
  3572. end\
  3573. end\
  3574. \
  3575. local tChances = { 0.2, 0.4, 0.55, 0.8, 1 }\
  3576. if math.random() <= tChances[ toolLevel + 1 ] then\
  3577. room.items[ sItem ] = nil\
  3578. print( \"The \"..tItem.aliases[1]..\" dies.\" )\
  3579. \
  3580. if tItem.drops then\
  3581. for n, sDrop in pairs( tItem.drops ) do\
  3582. if not room.items[sDrop] then\
  3583. print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )\
  3584. room.items[sDrop] = items[sDrop]\
  3585. end\
  3586. end\
  3587. end\
  3588. \
  3589. if tItem.monster then\
  3590. room.nMonsters = room.nMonsters - 1\
  3591. end\
  3592. else\
  3593. print( \"The \"..tItem.aliases[1]..\" is injured by your blow.\" )\
  3594. end\
  3595. \
  3596. if tItem.hitDrops then\
  3597. for n, sDrop in pairs( tItem.hitDrops ) do\
  3598. if not room.items[sDrop] then\
  3599. print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )\
  3600. room.items[sDrop] = items[sDrop]\
  3601. end\
  3602. end\
  3603. end\
  3604. \
  3605. else\
  3606. print( \"You can't break \"..sItem..\".\" )\
  3607. end\
  3608. else\
  3609. print( \"You don't see a \".._sItem..\" here.\" )\
  3610. end\
  3611. end\
  3612. \
  3613. function commands.craft( _sItem )\
  3614. if _sItem == nil then\
  3615. print( \"Craft what?\" )\
  3616. return\
  3617. end\
  3618. \
  3619. if _sItem == \"computer\" or _sItem == \"a computer\" then\
  3620. print( \"By creating a computer in a computer in a computer, you tear a hole in the spacetime continuum from which no mortal being can escape.\" )\
  3621. if term.isColour() then\
  3622. term.setTextColour( colours.red )\
  3623. end\
  3624. print( \"You have died.\" )\
  3625. print( \"Score: &e0\" )\
  3626. term.setTextColour( colours.white )\
  3627. bRunning = false\
  3628. bDied = true\
  3629. return\
  3630. end\
  3631. \
  3632. local room = getRoom( x,y,z )\
  3633. local sItem = findItem( items, _sItem )\
  3634. local tRecipe = (sItem and tRecipes[ sItem ]) or nil\
  3635. if tRecipe then\
  3636. for n,sReq in ipairs( tRecipe ) do\
  3637. if inventory[sReq] == nil then\
  3638. print( \"You don't have the items you need to craft \"..sItem..\".\" )\
  3639. return\
  3640. end\
  3641. end\
  3642. \
  3643. for n,sReq in ipairs( tRecipe ) do\
  3644. inventory[sReq] = nil\
  3645. end\
  3646. inventory[ sItem ] = items[ sItem ]\
  3647. if inventory[\"some torches\"] and inventory[\"a torch\"] then\
  3648. inventory[\"a torch\"] = nil\
  3649. end\
  3650. print( \"Crafted.\" )\
  3651. else\
  3652. print( \"You don't know how to make \"..(sItem or _sItem)..\".\" )\
  3653. end \
  3654. end\
  3655. \
  3656. function commands.build( _sThing, _sMaterial )\
  3657. if _sThing == nil then\
  3658. print( \"Build what?\" )\
  3659. return\
  3660. end\
  3661. \
  3662. local sMaterial = nil\
  3663. if _sMaterial == nil then\
  3664. for sItem, tItem in pairs( inventory ) do\
  3665. if tItem.material then\
  3666. sMaterial = sItem\
  3667. break\
  3668. end\
  3669. end\
  3670. if sMaterial == nil then\
  3671. print( \"You don't have any building materials.\" )\
  3672. return\
  3673. end\
  3674. else\
  3675. sMaterial = findItem( inventory, _sMaterial )\
  3676. if not sMaterial then\
  3677. print( \"You don't have any \".._sMaterial )\
  3678. return\
  3679. end\
  3680. \
  3681. if inventory[sMaterial].material ~= true then\
  3682. print( sMaterial..\" is not a good building material.\" )\
  3683. return\
  3684. end\
  3685. end\
  3686. \
  3687. local alias = nil\
  3688. if string.sub(_sThing, 1, 1) == \"a\" then\
  3689. alias = string.match( _sThing, \"a ([%a ]+)\" )\
  3690. end\
  3691. \
  3692. local room = getRoom( x,y,z )\
  3693. inventory[sMaterial] = nil\
  3694. room.items[ _sThing ] = {\
  3695. heavy = true,\
  3696. aliases = { alias },\
  3697. desc = \"As you look at your creation (made from \"..sMaterial..\"), you feel a swelling sense of pride.\",\
  3698. }\
  3699. \
  3700. print( \"Your construction is complete.\" )\
  3701. end\
  3702. \
  3703. function commands.help()\
  3704. local sText = \
  3705. \"Welcome to adventure, the greatest text adventure game on CraftOS. \" ..\
  3706. \"To get around the world, type actions, and the adventure will \" ..\
  3707. \"be read back to you. The actions availiable to you are go, look, inspect, inventory, \" ..\
  3708. \"take, drop, place, punch, attack, mine, dig, craft, build, eat and exit.\"\
  3709. print( sText )\
  3710. end\
  3711. \
  3712. function commands.eat( _sItem )\
  3713. if _sItem == nil then\
  3714. print( \"Eat what?\" )\
  3715. return\
  3716. end\
  3717. \
  3718. local sItem = findItem( inventory, _sItem )\
  3719. if not sItem then\
  3720. print( \"You don't have any \".._sItem..\".\" )\
  3721. return\
  3722. end\
  3723. \
  3724. local tItem = inventory[sItem]\
  3725. if tItem.food then\
  3726. print( \"That was delicious!\" )\
  3727. inventory[sItem] = nil\
  3728. \
  3729. if bInjured then\
  3730. print( \"You are no longer injured.\" )\
  3731. bInjured = false\
  3732. end\
  3733. else\
  3734. print( \"You can't eat \"..sItem..\".\" )\
  3735. end\
  3736. end\
  3737. \
  3738. function commands.exit()\
  3739. bRunning = false\
  3740. end\
  3741. \
  3742. function commands.reset()\
  3743. print(\"You have requested to reset your game.\")\
  3744. if term.isColour() then\
  3745. term.setTextColour( colours.red )\
  3746. end\
  3747. print(\"Are you sure you want to reset? You will lose all progress in this adventure!\")\
  3748. print(\"Type in reset again to reset the game.\")\
  3749. if string.lower(read()) == \"reset\" then\
  3750. resetGame()\
  3751. else\
  3752. skipSimulationForThisFrame = true\
  3753. end\
  3754. end\
  3755. \
  3756. function commands.badinput()\
  3757. local tResponses = {\
  3758. \"I don't understand.\",\
  3759. \"I don't understand you.\",\
  3760. \"You can't do that.\",\
  3761. \"Nope.\",\
  3762. \"Huh?\",\
  3763. \"Say again?\",\
  3764. \"That's crazy talk.\",\
  3765. \"Speak clearly.\",\
  3766. \"I'll think about it.\",\
  3767. \"Let me get back to you on that one.\",\
  3768. \"That doesn't make any sense.\",\
  3769. \"What? Try again with a different phrase, or use help.\",\
  3770. }\
  3771. print( tResponses[ math.random(1,#tResponses) ] )\
  3772. end\
  3773. \
  3774. function commands.noinput()\
  3775. local tResponses = {\
  3776. \"Speak up.\",\
  3777. \"Enunciate.\",\
  3778. \"Project your voice.\",\
  3779. \"Don't be shy.\",\
  3780. \"Use your words.\",\
  3781. }\
  3782. print( tResponses[ math.random(1,#tResponses) ] )\
  3783. end\
  3784. \
  3785. local function simulate()\
  3786. local bNewMonstersThisRoom = false\
  3787. math.randomseed(nRandomSeed)\
  3788. \
  3789. -- Spawn monsters in nearby rooms\
  3790. for sx = -2,2 do\
  3791. for sy = -1,1 do\
  3792. for sz = -2,2 do\
  3793. local h = y + sy\
  3794. if h >= -3 and h <= 0 then\
  3795. local room = getRoom( x + sx, h, z + sz )\
  3796. \
  3797. -- Spawn monsters\
  3798. if room.nMonsters < 2 and\
  3799. ((h == 0 and not isSunny() and not room.items[\"a torch\"]) or room.dark) and\
  3800. math.random(1,6) == 1 then\
  3801. \
  3802. local sMonster = tMonsters[ math.random(1,#tMonsters) ]\
  3803. if room.items[ sMonster ] == nil then\
  3804. room.items[ sMonster ] = items[ sMonster ]\
  3805. room.nMonsters = room.nMonsters + 1\
  3806. \
  3807. if sx == 0 and sy == 0 and sz == 0 and not room.dark then\
  3808. print( \"From the shadows, \"..sMonster..\" appears.\" )\
  3809. bNewMonstersThisRoom = true\
  3810. end\
  3811. end \
  3812. end\
  3813. \
  3814. -- Burn monsters\
  3815. if h == 0 and isSunny() then\
  3816. for n,sMonster in ipairs( tMonsters ) do\
  3817. if room.items[sMonster] and items[sMonster].nocturnal then\
  3818. room.items[sMonster] = nil\
  3819. if sx == 0 and sy == 0 and sz == 0 and not room.dark then\
  3820. print( \"With the sun high in the sky, the \"..items[sMonster].aliases[1]..\" bursts into flame and dies.\" )\
  3821. end\
  3822. room.nMonsters = room.nMonsters - 1\
  3823. end\
  3824. end\
  3825. end \
  3826. end\
  3827. end\
  3828. end\
  3829. end\
  3830. \
  3831. -- Make monsters attack\
  3832. local room = getRoom( x, y, z )\
  3833. if nTimeInRoom >= 2 and not bNewMonstersThisRoom and not bJustLoaded then\
  3834. for n,sMonster in ipairs( tMonsters ) do\
  3835. if room.items[sMonster] then\
  3836. if math.random(1,4) == 1 and\
  3837. not (y == 0 and isSunny() and (sMonster == \"a spider\")) then\
  3838. if sMonster == \"a creeper\" then\
  3839. if room.dark then\
  3840. print( \"A creeper explodes.\" )\
  3841. else\
  3842. print( \"The creeper explodes.\" )\
  3843. end\
  3844. room.items[sMonster] = nil\
  3845. room.nMonsters = room.nMonsters - 1\
  3846. else\
  3847. if room.dark then\
  3848. print( \"A \"..items[sMonster].aliases[1]..\" attacks you.\" )\
  3849. else\
  3850. print( \"The \"..items[sMonster].aliases[1]..\" attacks you.\" )\
  3851. end\
  3852. end\
  3853. \
  3854. if bInjured then\
  3855. if term.isColour() then\
  3856. term.setTextColour( colours.red )\
  3857. end\
  3858. print( \"You have died.\" )\
  3859. print( \"Score: &e0\" )\
  3860. term.setTextColour( colours.white )\
  3861. bRunning = false\
  3862. bDied = true\
  3863. return\
  3864. else\
  3865. bInjured = true\
  3866. end\
  3867. \
  3868. break\
  3869. end\
  3870. end\
  3871. end\
  3872. end\
  3873. \
  3874. -- Always print this\
  3875. if bInjured then\
  3876. if term.isColour() then\
  3877. term.setTextColour( colours.red )\
  3878. end\
  3879. print( \"You are injured.\" )\
  3880. term.setTextColour( colours.white )\
  3881. end\
  3882. \
  3883. -- Advance time\
  3884. if not bJustLoaded then\
  3885. nTurn = nTurn + 1\
  3886. nTimeInRoom = nTimeInRoom + 1\
  3887. nRandomSeed = math.random()*9000 + (os.clock())\
  3888. else\
  3889. bJustLoaded = false\
  3890. end\
  3891. end\
  3892. \
  3893. -- Add autocompletion stuff --\
  3894. local tActions = {\
  3895. \"go\",\
  3896. \"craft\",\
  3897. \"drop\",\
  3898. \"place\",\
  3899. \"build\",\
  3900. \"inspect\",\
  3901. \"inventory\",\
  3902. \"take\",\
  3903. \"look\",\
  3904. \"mine\",\
  3905. \"eat\",\
  3906. \"attack\",\
  3907. \"dig\",\
  3908. \"help\",\
  3909. \"exit\",\
  3910. }\
  3911. function autoTab(tab)\
  3912. local ret = {}\
  3913. for k, v in pairs(tab) do\
  3914. if type(v) == \"string\" then\
  3915. ret[v] = true\
  3916. elseif type(k) == \"string\" then\
  3917. ret[k] = true\
  3918. end\
  3919. end\
  3920. return ret\
  3921. end\
  3922. local tActions2 = autoTab(tActions)\
  3923. \
  3924. local function autoComplete( sLine )\
  3925. if string.find(sLine, \" \") == nil then\
  3926. return textutils.complete( sLine, tActions2 )\
  3927. end\
  3928. end\
  3929. \
  3930. -- Save game stuff --\
  3931. function resetGame()\
  3932. nGoWest = 0\
  3933. \
  3934. bRunning = true\
  3935. tMap = { { {}, }, }\
  3936. x,y,z = 0,0,0\
  3937. inventory = {\
  3938. [\"no tea\"] = items[\"no tea\"],\
  3939. }\
  3940. \
  3941. nTurn = 0\
  3942. nTimeInRoom = 0\
  3943. nRandomSeed = math.random()*9000\
  3944. nMapSeed = math.random()*900000\
  3945. bInjured = false\
  3946. bJustLoaded = true\
  3947. \
  3948. doCommand( \"look\" )\
  3949. simulate()\
  3950. tCommandHistory = {}\
  3951. end\
  3952. \
  3953. function saveGame()\
  3954. local recursive = {}\
  3955. local map = {}\
  3956. for x, xTable in pairs(tMap) do\
  3957. map[x] = {}\
  3958. for y, yTable in pairs(xTable) do\
  3959. map[x][y] = {}\
  3960. for z, zTable in pairs(yTable) do\
  3961. local matched = false\
  3962. for k, v in ipairs(recursive) do\
  3963. if v == zTable then\
  3964. matched = true\
  3965. break\
  3966. end\
  3967. end\
  3968. if not matched then\
  3969. local tab = {}\
  3970. local items = {}\
  3971. for k, v in pairs(zTable.items) do\
  3972. items[k] = true\
  3973. end\
  3974. tab.dark = zTable.dark\
  3975. tab.exits = zTable.exits\
  3976. tab.nBiome = tonumber(zTable.nBiome)\
  3977. tab.nMonsters = zTable.nMonsters\
  3978. tab.items = items\
  3979. map[x][y][z] = tab\
  3980. table.insert(recursive, tab)\
  3981. end\
  3982. end\
  3983. end\
  3984. end\
  3985. local file = fs.open(\"save.Adventure\", \"w\")\
  3986. if file then\
  3987. file.writeLine(\"Success\")\
  3988. file.writeLine(textutils.serialize(map))\
  3989. file.writeLine(\"--Inventory--\")\
  3990. file.writeLine(textutils.serialize(inventory))\
  3991. file.writeLine(\"--Other--\")\
  3992. file.writeLine(tostring(bInjured))\
  3993. file.writeLine(nTurn)\
  3994. file.writeLine(nTimeInRoom)\
  3995. file.writeLine(nRandomSeed)\
  3996. file.writeLine(nMapSeed)\
  3997. file.writeLine(x)\
  3998. file.writeLine(y)\
  3999. file.writeLine(z)\
  4000. file.close()\
  4001. end\
  4002. end\
  4003. \
  4004. function loadGame()\
  4005. local file = fs.open(\"save.Adventure\", \"r\")\
  4006. if file then\
  4007. if file.readLine() ~= \"Success\" then\
  4008. file.close()\
  4009. return false\
  4010. end\
  4011. \
  4012. if term.isColour() then\
  4013. term.setTextColour( colours.yellow )\
  4014. end\
  4015. print(\"Your game is being loaded.\")\
  4016. if term.isColour() then\
  4017. term.setTextColour( colours.white )\
  4018. end\
  4019. \
  4020. bJustLoaded = true\
  4021. local mapStr = \"\"\
  4022. local loops = 0\
  4023. while true do\
  4024. loops = loops + 1\
  4025. local str = file.readLine()\
  4026. if str == \"--Inventory--\" then\
  4027. break\
  4028. end\
  4029. if loops > 1 then\
  4030. mapStr = mapStr..\"\\n\"..str\
  4031. else\
  4032. mapStr = str\
  4033. end\
  4034. end\
  4035. tMap = textutils.unserialize(mapStr)\
  4036. local invStr = \"\"\
  4037. loops = 0\
  4038. while true do\
  4039. loops = loops + 1\
  4040. local str = file.readLine()\
  4041. if str == \"--Other--\" then\
  4042. break\
  4043. end\
  4044. if loops > 1 then\
  4045. invStr = invStr..\"\\n\"..str\
  4046. else\
  4047. invStr = str\
  4048. end\
  4049. end\
  4050. inventory = textutils.unserialize(invStr)\
  4051. bInjured = file.readLine() == \"true\"\
  4052. nTurn = tonumber(file.readLine()) or 0\
  4053. nTimeInRoom = tonumber(file.readLine()) or 0\
  4054. nRandomSeed = tonumber(file.readLine()) or 0\
  4055. nMapSeed = tonumber(file.readLine()) or 0\
  4056. x = tonumber(file.readLine()) or 0\
  4057. y = tonumber(file.readLine()) or 0\
  4058. z = tonumber(file.readLine()) or 0\
  4059. file.close()\
  4060. end\
  4061. for x, xTable in pairs(tMap) do\
  4062. for y, yTable in pairs(xTable) do\
  4063. for z, zTable in pairs(yTable) do\
  4064. local Myitems = {}\
  4065. for k, v in pairs(zTable.items) do\
  4066. Myitems[k] = items[k]\
  4067. end\
  4068. zTable.items = Myitems\
  4069. end\
  4070. end\
  4071. end\
  4072. return true\
  4073. end\
  4074. \
  4075. local ok = pcall(loadGame)\
  4076. if not ok then\
  4077. if term.isColour() then\
  4078. term.setTextColour( colours.yellow )\
  4079. end\
  4080. print(\"The save could not be loaded.\")\
  4081. if term.isColour() then\
  4082. term.setTextColour( colours.white )\
  4083. end\
  4084. end\
  4085. \
  4086. doCommand( \"look\" )\
  4087. simulate()\
  4088. \
  4089. local bLoop = true\
  4090. \
  4091. while bLoop do\
  4092. while bRunning do\
  4093. if term.isColour() then\
  4094. term.setTextColour( colours.yellow )\
  4095. end\
  4096. write( \"? \" )\
  4097. term.setTextColour( colours.white )\
  4098. \
  4099. local sRawLine \
  4100. if #tCommandHistory > 1 then\
  4101. sRawLine = read( nil, tCommandHistory )\
  4102. else\
  4103. sRawLine = read( nil, tCommandHistory, autoComplete )\
  4104. end\
  4105. if #sRawLine < 1 and #tCommandHistory > 0 then\
  4106. sRawLine = tCommandHistory[#tCommandHistory]\
  4107. end\
  4108. table.insert( tCommandHistory, sRawLine )\
  4109. \
  4110. local sLine = nil\
  4111. for match in string.gmatch(sRawLine, \"%a+\") do\
  4112. if sLine then\
  4113. sLine = sLine .. \" \" .. string.lower(match)\
  4114. else\
  4115. sLine = string.lower(match)\
  4116. end\
  4117. end\
  4118. \
  4119. doCommand( sLine or \"\" )\
  4120. if bRunning and not skipSimulationForThisFrame then\
  4121. simulate()\
  4122. end\
  4123. if bRunning and not skipSimulationForThisFrame then\
  4124. saveGame()\
  4125. end\
  4126. skipSimulationForThisFrame = false\
  4127. end\
  4128. if bDied then\
  4129. if bHardcore then\
  4130. fs.delete(\"save.Adventure\")\
  4131. end\
  4132. bLoop = false\
  4133. print(\"Would you like to play again?\")\
  4134. if term.isColour() then\
  4135. term.setTextColour( colours.yellow )\
  4136. end\
  4137. write( \"? \" )\
  4138. term.setTextColour( colours.white )\
  4139. if string.lower(read()):find(\"y\") == 1 then\
  4140. bLoop = true\
  4141. resetGame()\
  4142. end\
  4143. else\
  4144. break\
  4145. end\
  4146. end",
  4147. [ "Flutter/windowshell" ] = "local tArgs = {...}\
  4148. local tDesktop = {}\
  4149. if _G.windowShell then\
  4150. tArgs[1] = tArgs[1] or \"shell\"\
  4151. os.run({}, \"fg\", unpack(tArgs))\
  4152. return\
  4153. end\
  4154. \
  4155. -- Local color setup\
  4156. local backColor, windowBorderColor, windowTitleColor, windowCloseColor\
  4157. if term.isColor() then\
  4158. backColor, windowBorderColor = colors.gray, colors.blue\
  4159. windowTitleColor, windowCloseColor = colors.white, colors.red\
  4160. else\
  4161. backColor, windowBorderColor = colors.black, colors.white\
  4162. windowTitleColor, windowCloseColor = colors.black, colors.white\
  4163. end\
  4164. term.setBackgroundColor(backColor)\
  4165. term.clear()\
  4166. term.redirect(term.native())\
  4167. \
  4168. -- Window API --\
  4169. local window = {}\
  4170. function window.create( parent, nX, nY, nWidth, nHeight, bStartVisible, sExpectedTitle )\
  4171. \
  4172. if type( parent ) ~= \"table\" or\
  4173. type( nX ) ~= \"number\" or\
  4174. type( nY ) ~= \"number\" or\
  4175. type( nWidth ) ~= \"number\" or\
  4176. type( nHeight ) ~= \"number\" or\
  4177. (bStartVisible ~= nil and type( bStartVisible ) ~= \"boolean\") then\
  4178. error( \"Expected object, number, number, number, number, [boolean]\", 2 )\
  4179. end\
  4180. \
  4181. if parent == term then\
  4182. error( \"term is not a recommended window parent, try term.current() instead\", 2 )\
  4183. end\
  4184. \
  4185. -- Setup\
  4186. local bVisible = (bStartVisible ~= false)\
  4187. local sTitle = sExpectedTitle or \"\"\
  4188. local nCursorX = 1\
  4189. local nCursorY = 1\
  4190. local nOldWidth, nOldHeight = nWidth, nHeight\
  4191. local bCursorBlink = false\
  4192. local nTextColor = colors.white\
  4193. local nBackgroundColor = colors.black\
  4194. local sEmpty = string.rep( \" \", nWidth - 2 )\
  4195. local tLines = {}\
  4196. do\
  4197. local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  4198. for y=1,nHeight do\
  4199. tLines[y] = tEmpty\
  4200. end\
  4201. end\
  4202. \
  4203. -- Helper functions\
  4204. local function updateCursorPos()\
  4205. if nCursorX >= 1 and nCursorY >= 1 and\
  4206. nCursorX <= nWidth and nCursorY <= nHeight then\
  4207. parent.setCursorPos( nX + nCursorX, nY + nCursorY)\
  4208. else\
  4209. parent.setCursorPos( 0, 0 )\
  4210. end\
  4211. end\
  4212. \
  4213. local function updateCursorBlink()\
  4214. parent.setCursorBlink( bCursorBlink )\
  4215. end\
  4216. \
  4217. local function updateCursorColor()\
  4218. parent.setTextColor( nTextColor )\
  4219. end\
  4220. \
  4221. local function redrawLine( n, drawBorder )\
  4222. if n < nHeight - 1 then\
  4223. parent.setCursorPos( nX + 1, nY + n )\
  4224. local tLine = tLines[ n ]\
  4225. local length = 0\
  4226. for m=1,#tLine do\
  4227. local tBit = tLine[ m ]\
  4228. parent.setTextColor( tBit[2] )\
  4229. parent.setBackgroundColor( tBit[3] )\
  4230. parent.write( tBit[1]:sub(0, (nWidth - 2) - length) )\
  4231. length = length + #tBit[1]\
  4232. end\
  4233. if drawBorder then\
  4234. parent.setBackgroundColor(windowBorderColor)\
  4235. parent.setCursorPos( nX + (nWidth - 1), nY + nCursorY )\
  4236. parent.write(\" \")\
  4237. end\
  4238. end\
  4239. end\
  4240. \
  4241. local function lineLen( tLine )\
  4242. local nLength = 0\
  4243. for n=1,#tLine do\
  4244. nLength = nLength + string.len( tLine[n][1] )\
  4245. end\
  4246. return nLength\
  4247. end\
  4248. \
  4249. local function lineSub( tLine, nStart, nEnd )\
  4250. --assert( math.floor(nStart) == nStart )\
  4251. --assert( math.floor(nEnd) == nEnd )\
  4252. --assert( nStart >= 1 )\
  4253. --assert( nEnd >= nStart )\
  4254. --assert( nEnd <= lineLen( tLine ) )\
  4255. local tSubLine = {}\
  4256. local nBitStart = 1\
  4257. for n=1,#tLine do\
  4258. local tBit = tLine[n]\
  4259. local sBit = tBit[1]\
  4260. local nBitEnd = math.min(nBitStart + string.len( sBit ) - 1)\
  4261. if nBitEnd >= nStart and nBitStart <= nEnd then\
  4262. if nBitStart >= nStart and nBitEnd <= nEnd then\
  4263. -- Include bit wholesale\
  4264. table.insert( tSubLine, tBit )\
  4265. --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  4266. elseif nBitStart < nStart and nBitEnd <= nEnd then\
  4267. -- Include end of bit\
  4268. table.insert( tSubLine, {\
  4269. string.sub( sBit, nStart - nBitStart + 1 ),\
  4270. tBit[2], tBit[3]\
  4271. } )\
  4272. --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  4273. elseif nBitStart >= nStart and nBitEnd > nEnd then\
  4274. -- Include beginning of bit\
  4275. table.insert( tSubLine, {\
  4276. string.sub( sBit, 1, nEnd - nBitStart + 1 ),\
  4277. tBit[2], tBit[3]\
  4278. } )\
  4279. --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  4280. else\
  4281. -- Include middle of bit\
  4282. table.insert( tSubLine, {\
  4283. string.sub( sBit, nStart - nBitStart + 1, nEnd - nBitStart + 1 ),\
  4284. tBit[2], tBit[3]\
  4285. } )\
  4286. --assert( lineLen( tSubLine ) == (math.min(nEnd, nBitEnd) - nStart + 1) )\
  4287. end\
  4288. end\
  4289. nBitStart = nBitEnd + 1\
  4290. end\
  4291. --assert( lineLen( tSubLine ) == (nEnd - nStart + 1) )\
  4292. return tSubLine\
  4293. end\
  4294. \
  4295. local function lineJoin( tLine1, tLine2 )\
  4296. local tNewLine = {}\
  4297. if tLine1[#tLine1][2] == tLine2[1][2] and\
  4298. tLine1[#tLine1][3] == tLine2[1][3] then\
  4299. -- Merge middle bits\
  4300. for n=1,#tLine1-1 do\
  4301. table.insert( tNewLine, tLine1[n] )\
  4302. end\
  4303. table.insert( tNewLine, {\
  4304. tLine1[#tLine1][1] .. tLine2[1][1],\
  4305. tLine2[1][2], tLine2[1][3]\
  4306. } )\
  4307. for n=2,#tLine2 do\
  4308. table.insert( tNewLine, tLine2[n] )\
  4309. end\
  4310. --assert( lineLen( tNewLine ) == lineLen(tLine1) + lineLen(tLine2) )\
  4311. else\
  4312. -- Just concatenate\
  4313. for n=1,#tLine1 do\
  4314. table.insert( tNewLine, tLine1[n] )\
  4315. end\
  4316. for n=1,#tLine2 do\
  4317. table.insert( tNewLine, tLine2[n] )\
  4318. end\
  4319. --assert( lineLen( tNewLine ) == lineLen(tLine1) + lineLen(tLine2) )\
  4320. end\
  4321. return tNewLine\
  4322. end\
  4323. \
  4324. local function redraw()\
  4325. -- Draw window contents.\
  4326. for n=1, nHeight - 2 do\
  4327. redrawLine( n, false )\
  4328. end\
  4329. \
  4330. -- Draw top and bottom borders.\
  4331. local lineStr = string.rep(\" \", nWidth)\
  4332. parent.setBackgroundColor(windowBorderColor)\
  4333. parent.setTextColor(windowTitleColor)\
  4334. parent.setCursorPos( nX, nY )\
  4335. parent.write(lineStr)\
  4336. \
  4337. -- Draw title bar.\
  4338. parent.setCursorPos( nX, nY )\
  4339. parent.write(sTitle or \"New Window\")\
  4340. parent.setCursorPos( nX + (nWidth - 3), nY)\
  4341. parent.write(\"_M\")\
  4342. parent.setBackgroundColor(windowCloseColor)\
  4343. parent.setCursorPos( nX + (nWidth - 1), nY)\
  4344. parent.write(\"X\")\
  4345. parent.setBackgroundColor(windowBorderColor)\
  4346. parent.setCursorPos( nX, nY + nHeight - 1 )\
  4347. parent.write(lineStr)\
  4348. \
  4349. -- Draw left and right borders.\
  4350. for y=1, nHeight - 2 do\
  4351. parent.setCursorPos( nX, nY + y )\
  4352. parent.write(\" \")\
  4353. parent.setCursorPos( nX + (nWidth - 1), nY + y )\
  4354. parent.write(\" \")\
  4355. end\
  4356. parent.setCursorPos( nX + (nWidth - 1), nY + nHeight - 1 )\
  4357. parent.write(\"/\")\
  4358. end\
  4359. \
  4360. local window = {}\
  4361. \
  4362. -- Terminal implementation\
  4363. function window.write( sText )\
  4364. local nLen = string.len( string.sub(sText, 0, nWidth - 2) )\
  4365. local nStart = nCursorX\
  4366. local nEnd = nStart + nLen - 1\
  4367. if nCursorY >= 1 and nCursorY <= nHeight - 2 then\
  4368. -- Work out where to put new line\
  4369. --assert( math.floor(nStart) == nStart )\
  4370. --assert( math.floor(nEnd) == nEnd )\
  4371. if nStart <= (nWidth - 2) and nEnd >= 1 then\
  4372. -- Construct new line\
  4373. local tLine = tLines[ nCursorY ]\
  4374. if nStart == 1 and nEnd == (nWidth - 2) then\
  4375. -- Exactly replace line\
  4376. tLine = {\
  4377. { sText, nTextColor, nBackgroundColor }\
  4378. }\
  4379. --assert( lineLen( tLine ) == nWidth )\
  4380. elseif nStart <= 1 and nEnd >= (nWidth - 2) then\
  4381. -- Overwrite line with subset\
  4382. tLine = {\
  4383. { string.sub( sText, 1 - nStart + 1, (nWidth - 2) - nStart + 1 ), nTextColor, nBackgroundColor }\
  4384. }\
  4385. --assert( lineLen( tLine ) == nWidth )\
  4386. elseif nStart <= 1 then\
  4387. -- Overwrite beginning of line\
  4388. tLine = lineJoin(\
  4389. { { string.sub( sText, 1 - nStart + 1 ), nTextColor, nBackgroundColor } },\
  4390. lineSub( tLine, nEnd + 1, (nWidth - 2) )\
  4391. )\
  4392. --assert( lineLen( tLine ) == nWidth )\
  4393. elseif nEnd >= nWidth - 2 then\
  4394. -- Overwrite end of line\
  4395. tLine = lineJoin(\
  4396. lineSub( tLine, 1, nStart - 1 ),\
  4397. { { string.sub( sText, 1, (nWidth - 2) - nStart + 1 ), nTextColor, nBackgroundColor } }\
  4398. )\
  4399. --assert( lineLen( tLine ) == nWidth )\
  4400. else\
  4401. -- Overwrite middle of line\
  4402. tLine = lineJoin(\
  4403. lineJoin(\
  4404. lineSub( tLine, 1, nStart - 1 ),\
  4405. { { sText, nTextColor, nBackgroundColor } }\
  4406. ),\
  4407. lineSub( tLine, nEnd + 1, (nWidth - 2) )\
  4408. )\
  4409. --assert( lineLen( tLine ) == nWidth )\
  4410. end\
  4411. \
  4412. -- Destroy text outside the window region that should not be there\
  4413. for k=nWidth - 2, #tLine do\
  4414. table.remove(tLine, nWidth)\
  4415. end\
  4416. \
  4417. -- Store and redraw new line\
  4418. tLines[ nCursorY ] = tLine\
  4419. if bVisible then\
  4420. redrawLine( nCursorY, true )\
  4421. end\
  4422. end\
  4423. end\
  4424. \
  4425. -- Move and redraw cursor\
  4426. nCursorX = nEnd + 1\
  4427. if bVisible then\
  4428. updateCursorColor()\
  4429. updateCursorPos()\
  4430. end\
  4431. end\
  4432. \
  4433. function window.clear()\
  4434. local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  4435. for y=1,nHeight do\
  4436. tLines[y] = tEmpty\
  4437. end\
  4438. if bVisible then\
  4439. redraw()\
  4440. updateCursorColor()\
  4441. updateCursorPos()\
  4442. end\
  4443. end\
  4444. \
  4445. function window.clearLine()\
  4446. if nCursorY >= 1 and nCursorY <= nHeight then\
  4447. tLines[ nCursorY ] = { { sEmpty, nTextColor, nBackgroundColor } }\
  4448. if bVisible then\
  4449. redrawLine( nCursorY )\
  4450. updateCursorColor()\
  4451. updateCursorPos()\
  4452. end\
  4453. end\
  4454. end\
  4455. \
  4456. function window.getCursorPos()\
  4457. return nCursorX, nCursorY\
  4458. end\
  4459. \
  4460. function window.setCursorPos( x, y )\
  4461. nCursorX = math.floor( x )\
  4462. nCursorY = math.floor( y )\
  4463. if bVisible then\
  4464. updateCursorPos()\
  4465. end\
  4466. end\
  4467. \
  4468. function window.setCursorBlink( blink )\
  4469. bCursorBlink = blink\
  4470. if bVisible then\
  4471. updateCursorBlink()\
  4472. end\
  4473. end\
  4474. \
  4475. function window.isColor()\
  4476. return parent.isColor()\
  4477. end\
  4478. \
  4479. function window.isColour()\
  4480. return parent.isColor()\
  4481. end\
  4482. \
  4483. local function setTextColor( color )\
  4484. if not parent.isColor() then\
  4485. if (color ~= colors.white and color ~= colors.black) and ((color ~= colors.gray and color ~= colors.lightGray) and not _CC_VERSION) then\
  4486. error( \"Color not supported\", 3 )\
  4487. end\
  4488. end\
  4489. nTextColor = color\
  4490. if bVisible then\
  4491. updateCursorColor()\
  4492. end\
  4493. end\
  4494. \
  4495. function window.setTextColor( color )\
  4496. setTextColor( color )\
  4497. end\
  4498. \
  4499. function window.setTextColour( color )\
  4500. setTextColor( color )\
  4501. end\
  4502. \
  4503. function window.getTextColor()\
  4504. return nTextColor\
  4505. end\
  4506. \
  4507. window.getTextColour = window.getTextColor\
  4508. \
  4509. local function setBackgroundColor( color )\
  4510. if not parent.isColor() then\
  4511. if color ~= colors.white and color ~= colors.black then\
  4512. error( \"Color not supported\", 3 )\
  4513. end\
  4514. end\
  4515. nBackgroundColor = color\
  4516. end\
  4517. \
  4518. function window.setBackgroundColor( color )\
  4519. setBackgroundColor( color )\
  4520. end\
  4521. \
  4522. function window.setBackgroundColour( color )\
  4523. setBackgroundColor( color )\
  4524. end\
  4525. \
  4526. function window.getBackgroundColor()\
  4527. return nBackgroundColor\
  4528. end\
  4529. \
  4530. window.getBackgroundColour = window.getBackgroundColor\
  4531. \
  4532. function window.getSize()\
  4533. return nWidth - 2, nHeight - 2\
  4534. end\
  4535. \
  4536. function window.scroll( n )\
  4537. if n ~= 0 then\
  4538. local tNewLines = {}\
  4539. local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  4540. for newY=1,nHeight do\
  4541. local y = newY + n\
  4542. if y >= 1 and y <= nHeight then\
  4543. tNewLines[newY] = tLines[y]\
  4544. else\
  4545. tNewLines[newY] = tEmpty\
  4546. end\
  4547. end\
  4548. tLines = tNewLines\
  4549. if bVisible then\
  4550. redraw()\
  4551. updateCursorColor()\
  4552. updateCursorPos()\
  4553. end\
  4554. end\
  4555. end\
  4556. \
  4557. -- Other functions\
  4558. function window.setVisible( bVis )\
  4559. if bVisible ~= bVis then\
  4560. bVisible = bVis\
  4561. if bVisible then\
  4562. window.redraw()\
  4563. end\
  4564. end\
  4565. end\
  4566. \
  4567. function window.redraw()\
  4568. if bVisible then\
  4569. redraw()\
  4570. updateCursorBlink()\
  4571. updateCursorColor()\
  4572. updateCursorPos()\
  4573. end\
  4574. end\
  4575. \
  4576. function window.restoreCursor()\
  4577. if bVisible then\
  4578. updateCursorBlink()\
  4579. updateCursorColor()\
  4580. updateCursorPos()\
  4581. end\
  4582. end\
  4583. \
  4584. function window.getPosition()\
  4585. return nX, nY\
  4586. end\
  4587. \
  4588. function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight )\
  4589. nX = nNewX\
  4590. nY = nNewY\
  4591. if nNewWidth and nNewHeight then\
  4592. sEmpty = string.rep( \" \", nNewWidth )\
  4593. local tNewLines = {}\
  4594. local tEmpty = { { sEmpty, nTextColor, nBackgroundColor } }\
  4595. for y=1,nNewHeight do\
  4596. if y > nHeight then\
  4597. tNewLines[y] = tEmpty\
  4598. else\
  4599. if nNewWidth == nWidth then\
  4600. tNewLines[y] = tLines[y]\
  4601. elseif nNewWidth < nWidth then\
  4602. tNewLines[y] = lineSub( tLines[y], 1, nNewWidth )\
  4603. else\
  4604. tNewLines[y] = lineJoin( tLines[y], { { string.sub( sEmpty, nWidth + 1, nNewWidth ), nTextColor, nBackgroundColor } } )\
  4605. end\
  4606. end\
  4607. end\
  4608. nWidth = nNewWidth\
  4609. nHeight = nNewHeight\
  4610. tLines = tNewLines\
  4611. end\
  4612. if bVisible then\
  4613. window.redraw()\
  4614. end\
  4615. end\
  4616. \
  4617. -- Priviate functions not actually available.\
  4618. function window.getTitle()\
  4619. return sTitle\
  4620. end\
  4621. \
  4622. function window.setTitle(sNewTitle)\
  4623. sTitle = sNewTitle\
  4624. end\
  4625. \
  4626. if bVisible then\
  4627. window.redraw()\
  4628. end\
  4629. return window\
  4630. end\
  4631. \
  4632. -- Set up the WindowShell --\
  4633. _G.windowShell = true\
  4634. local sMenu = \" Menu \"\
  4635. local sPopupMenu = \"Programs\"\
  4636. \
  4637. -- Setup process switching\
  4638. local parentTerm = term.current()\
  4639. local w,h = parentTerm.getSize()\
  4640. local background = paintutils.loadImage((Flutter.Dir or \"\")..\"background\")\
  4641. \
  4642. local tProcesses = {}\
  4643. local nCurrentProcess = nil\
  4644. local nRunningProcess = nil\
  4645. local nMenuScroll = 0\
  4646. local nCurTabEnd = 0\
  4647. local bWindowsResized = false\
  4648. \
  4649. -- Stubbed Paintutils API --\
  4650. \
  4651. local function drawPixelInternal( xPos, yPos )\
  4652. parentTerm.setCursorPos( xPos, yPos )\
  4653. parentTerm.write(\" \")\
  4654. end\
  4655. \
  4656. local tColourLookup = {}\
  4657. for n=1,16 do\
  4658. tColourLookup[ string.byte( \"0123456789abcdef\",n,n ) ] = 2^(n-1)\
  4659. end\
  4660. \
  4661. function drawImage( tImage, xPos, yPos )\
  4662. if type( tImage ) ~= \"table\" or type( xPos ) ~= \"number\" or type( yPos ) ~= \"number\" then\
  4663. error( \"Expected image, x, y\", 2 )\
  4664. end\
  4665. for y=1,#tImage do\
  4666. local tLine = tImage[y]\
  4667. for x=1,#tLine do\
  4668. if tLine[x] > 0 then\
  4669. parentTerm.setBackgroundColor( tLine[x] )\
  4670. drawPixelInternal( x + xPos - 1, y + yPos - 1 )\
  4671. end\
  4672. end\
  4673. end\
  4674. end\
  4675. \
  4676. -- Continue setting up colors\
  4677. local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor\
  4678. if parentTerm.isColor() then\
  4679. menuMainTextColor, menuMainBgColor = colors.black, colors.white\
  4680. menuOtherTextColor, menuOtherBgColor = colors.black, colors.lightGray\
  4681. else\
  4682. menuMainTextColor, menuMainBgColor = colors.white, colors.black\
  4683. menuOtherTextColor, menuOtherBgColor = colors.black, colors.white\
  4684. end\
  4685. \
  4686. --[[tDesktop[1] = {\
  4687. Name = \"Script\",\
  4688. Icon = paintutils.loadImage(Flutter.Dir..\"Icons/\"..\"UnknownFile\")\
  4689. }]]\
  4690. \
  4691. local function redrawScreen()\
  4692. parentTerm.setBackgroundColor(backColor)\
  4693. parentTerm.clear()\
  4694. if background then\
  4695. drawImage(background, 1, 1)\
  4696. end\
  4697. \
  4698. local iconHeight = 5\
  4699. local iconWidth = 7\
  4700. local width, height = parentTerm.getSize()\
  4701. local iconsPerRow = width/iconWidth\
  4702. \
  4703. for nIcon, tIcon in pairs(tDesktop) do\
  4704. local x, y = (((nIcon - 1)%iconsPerRow)*iconWidth) + 1, 0\
  4705. parentTerm.setCursorPos(x, y + 4)\
  4706. parentTerm.write(tIcon.Name)\
  4707. drawImage( tIcon.Icon, x, y )\
  4708. end\
  4709. \
  4710. parentTerm.setCursorPos(1, h)\
  4711. parentTerm.setBackgroundColor(menuOtherBgColor)\
  4712. parentTerm.clearLine()\
  4713. for k, tProcess in pairs(tProcesses) do\
  4714. if k ~= nCurrentProcess then\
  4715. tProcess.window.redraw()\
  4716. end\
  4717. end\
  4718. if tProcesses[ nCurrentProcess ] then\
  4719. tProcesses[ nCurrentProcess ].window.redraw()\
  4720. end\
  4721. redrawMenu()\
  4722. end\
  4723. \
  4724. local function selectProcess( n )\
  4725. if nCurrentProcess ~= n then\
  4726. if nCurrentProcess then\
  4727. local tOldProcess = tProcesses[ nCurrentProcess ]\
  4728. end\
  4729. nCurrentProcess = n\
  4730. if nCurrentProcess then\
  4731. local tNewProcess = tProcesses[ nCurrentProcess ]\
  4732. tNewProcess.bInteracted = true\
  4733. tNewProcess.window.setVisible(true)\
  4734. end\
  4735. else\
  4736. if nCurrentProcess then\
  4737. local tNewProcess = tProcesses[ nCurrentProcess ]\
  4738. tNewProcess.window.setVisible(true)\
  4739. end\
  4740. end\
  4741. end\
  4742. \
  4743. local function setProcessTitle( n, sTitle )\
  4744. tProcesses[ n ].sTitle = sTitle\
  4745. tProcesses[ n ].window.setTitle(sTitle)\
  4746. end\
  4747. \
  4748. local function resumeProcess( nProcess, sEvent, ... )\
  4749. local tProcess = tProcesses[ nProcess ]\
  4750. if tProcess then\
  4751. local sFilter = tProcess.sFilter\
  4752. if sFilter == nil or sFilter == sEvent or sEvent == \"terminate\" then\
  4753. local nPreviousProcess = nRunningProcess\
  4754. nRunningProcess = nProcess\
  4755. term.redirect( tProcess.terminal )\
  4756. local ok, result = coroutine.resume( tProcess.co, sEvent, ... )\
  4757. tProcess.terminal = term.current()\
  4758. if ok then\
  4759. tProcess.sFilter = result\
  4760. else\
  4761. printError( result )\
  4762. end\
  4763. nRunningProcess = nPreviousProcess\
  4764. end\
  4765. end\
  4766. end\
  4767. \
  4768. local function launchProcess( tProgramEnv, sProgramPath, ... )\
  4769. local tProgramArgs = { ... }\
  4770. local nProcess = #tProcesses + 1\
  4771. local tProcess = {}\
  4772. tProcess.sTitle = fs.getName( sProgramPath )\
  4773. tProcess.window = window.create( parentTerm, math.min((#tProcesses + 1)*2 - 1, w), math.min((#tProcesses + 1)*2 - 1, h - 12), 32, 12, false, tProcess.sTitle )\
  4774. tProcess.co = coroutine.create( function()\
  4775. os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) )\
  4776. if not tProcess.bInteracted then\
  4777. term.setCursorBlink( false )\
  4778. print( \"Press any key to continue\" )\
  4779. sleep(.1)\
  4780. os.pullEvent( \"char\" )\
  4781. end\
  4782. end )\
  4783. tProcess.sFilter = nil\
  4784. tProcess.terminal = tProcess.window\
  4785. tProcess.bInteracted = false\
  4786. tProcesses[ nProcess ] = tProcess\
  4787. resumeProcess( nProcess )\
  4788. redrawScreen()\
  4789. return nProcess\
  4790. end\
  4791. \
  4792. local function cullProcess( nProcess )\
  4793. local tProcess = tProcesses[ nProcess ]\
  4794. if tProcess then\
  4795. if coroutine.status( tProcess.co ) == \"dead\" then\
  4796. if nCurrentProcess == nProcess then\
  4797. selectProcess( nil )\
  4798. end\
  4799. table.remove( tProcesses, nProcess )\
  4800. if nCurrentProcess == nil then\
  4801. if nProcess > 1 then\
  4802. selectProcess( nProcess - 1 )\
  4803. elseif #tProcesses > 0 then\
  4804. selectProcess( 1 )\
  4805. end\
  4806. end\
  4807. return true\
  4808. end\
  4809. return false\
  4810. end\
  4811. end\
  4812. \
  4813. local function killProcess( nProcess )\
  4814. if nCurrentProcess == nProcess then\
  4815. selectProcess( nil )\
  4816. end\
  4817. table.remove( tProcesses, nProcess )\
  4818. if nCurrentProcess == nil then\
  4819. if nProcess > 1 then\
  4820. selectProcess( nProcess - 1 )\
  4821. elseif #tProcesses > 0 then\
  4822. selectProcess( 1 )\
  4823. end\
  4824. end\
  4825. redrawScreen()\
  4826. return true\
  4827. end\
  4828. \
  4829. local function cullProcesses()\
  4830. local culled = false\
  4831. for n=#tProcesses,1,-1 do\
  4832. culled = culled or cullProcess( n )\
  4833. end\
  4834. return culled\
  4835. end\
  4836. \
  4837. -- Setup the main menu\
  4838. \
  4839. function redrawMenu()\
  4840. -- Draw menu\
  4841. parentTerm.setCursorPos( 1, h )\
  4842. parentTerm.setBackgroundColor( menuOtherBgColor )\
  4843. parentTerm.clearLine()\
  4844. \
  4845. -- Draw process list\
  4846. parentTerm.setCursorPos( (#sMenu + 2) - nMenuScroll, h )\
  4847. \
  4848. local totalTabsLength = 0\
  4849. for n=1,#tProcesses do\
  4850. totalTabsLength = totalTabsLength + string.len( tProcesses[n].sTitle ) + 2\
  4851. if n == nCurrentProcess then\
  4852. parentTerm.setTextColor( menuMainTextColor )\
  4853. parentTerm.setBackgroundColor( menuMainBgColor )\
  4854. else\
  4855. parentTerm.setTextColor( menuOtherTextColor )\
  4856. parentTerm.setBackgroundColor( menuOtherBgColor )\
  4857. end\
  4858. parentTerm.write( \" \" .. tProcesses[n].sTitle .. \" \" )\
  4859. end\
  4860. nCurTabsLength = totalTabsLength\
  4861. \
  4862. -- Draw arrow buttons\
  4863. parentTerm.setTextColor( menuMainTextColor )\
  4864. parentTerm.setBackgroundColor( menuMainBgColor )\
  4865. \
  4866. parentTerm.setCursorPos( #sMenu + 1, h )\
  4867. parentTerm.write(\"<\")\
  4868. \
  4869. parentTerm.setCursorPos( w, h )\
  4870. parentTerm.write(\">\")\
  4871. \
  4872. -- Draw menu button\
  4873. parentTerm.setCursorPos( 1, h )\
  4874. parentTerm.setTextColor( windowTitleColor )\
  4875. parentTerm.setBackgroundColor( windowBorderColor )\
  4876. parentTerm.write(sMenu)\
  4877. \
  4878. -- Put the cursor back where it should be\
  4879. local tProcess = tProcesses[ nCurrentProcess ]\
  4880. if tProcess then\
  4881. tProcess.window.restoreCursor()\
  4882. end\
  4883. end\
  4884. local redrawMenu = redrawMenu\
  4885. \
  4886. local function resizeWindows()\
  4887. local windowY, windowHeight\
  4888. windowY = 2\
  4889. windowHeight = h-2\
  4890. for n=1,#tProcesses do\
  4891. local tProcess = tProcesses[n]\
  4892. local window = tProcess.window\
  4893. local x,y = tProcess.window.getCursorPos()\
  4894. if y > windowHeight then\
  4895. tProcess.window.scroll( y - windowHeight )\
  4896. tProcess.window.setCursorPos( x, windowHeight )\
  4897. end\
  4898. --tProcess.window.reposition( 4, windowY, w - 4, windowHeight )\
  4899. end\
  4900. bWindowsResized = true\
  4901. end\
  4902. \
  4903. local function setMenuVisible( bVis )\
  4904. if bShowMenu ~= bVis then\
  4905. bShowMenu = bVis\
  4906. resizeWindows()\
  4907. redrawMenu()\
  4908. end\
  4909. end\
  4910. \
  4911. local function drawQuickMenu(y)\
  4912. local width = 15\
  4913. parentTerm.setTextColor(windowTitleColor)\
  4914. parentTerm.setBackgroundColor(windowBorderColor)\
  4915. parentTerm.setCursorPos(1, y)\
  4916. parentTerm.write(tostring(sPopupMenu)..string.rep(\" \", width - #sPopupMenu))\
  4917. parentTerm.setCursorPos(1, y + 1)\
  4918. parentTerm.write(string.rep(\"=\", width))\
  4919. for k, v in ipairs(Flutter.QuickMenu.ProgramsList) do\
  4920. if k + y + 1 <= h then\
  4921. parentTerm.setCursorPos(1, k + y + 1)\
  4922. if #v[1] < width + 1 then\
  4923. parentTerm.write(tostring(v[1])..string.rep(\" \", width - #v[1]))\
  4924. else\
  4925. parentTerm.write(string.sub(v[1], 0, width - 3)..\"...\")\
  4926. end\
  4927. end\
  4928. end\
  4929. redrawMenu()\
  4930. end\
  4931. \
  4932. local function showQuickMenu()\
  4933. local slideAnimationLength = 23\
  4934. for k=1, slideAnimationLength do\
  4935. drawQuickMenu(h - 1 - math.floor((k/slideAnimationLength)*(#Flutter.QuickMenu.ProgramsList + 1)))\
  4936. for k2=1, 11 do\
  4937. os.queueEvent(\"yield\")\
  4938. os.pullEvent(\"yield\")\
  4939. end\
  4940. end\
  4941. drawQuickMenu(h)\
  4942. local event, button, x, y, p4, p5 = os.pullEvent()\
  4943. if event == \"mouse_click\" then\
  4944. if x > 12 then\
  4945. return false\
  4946. elseif y > (h - 1 - (#Flutter.QuickMenu.ProgramsList)) and y < h then\
  4947. local clicked = y - (h - 1 -(#Flutter.QuickMenu.ProgramsList))\
  4948. selectProcess(launchProcess( {[\"shell\"] = shell, [\"multishell\"] = multishell,}, \
  4949. Flutter.QuickMenu.ProgramsList[clicked][2] ))\
  4950. end\
  4951. else\
  4952. os.queueEvent(event, button, x, y, p4, p5)\
  4953. end\
  4954. redrawScreen()\
  4955. end\
  4956. \
  4957. local multishell = {}\
  4958. \
  4959. function multishell.getFocus()\
  4960. return nCurrentProcess\
  4961. end\
  4962. \
  4963. function multishell.setFocus( n )\
  4964. if n >= 1 and n <= #tProcesses then\
  4965. selectProcess( n )\
  4966. redrawMenu()\
  4967. return true\
  4968. end\
  4969. return false\
  4970. end\
  4971. \
  4972. function multishell.getTitle( n )\
  4973. if n >= 1 and n <= #tProcesses then\
  4974. return tProcesses[n].sTitle\
  4975. end\
  4976. return nil\
  4977. end\
  4978. \
  4979. function multishell.setTitle( n, sTitle )\
  4980. n = n or 0\
  4981. if n >= 1 and n <= #(tProcesses or {}) then\
  4982. setProcessTitle( n, \"#\"..n..\" \"..sTitle )\
  4983. redrawMenu()\
  4984. end\
  4985. end\
  4986. \
  4987. function multishell.getCurrent()\
  4988. return nRunningProcess\
  4989. end\
  4990. \
  4991. function multishell.launch( tProgramEnv, sProgramPath, ... )\
  4992. local previousTerm = term.current()\
  4993. local nResult = launchProcess( tProgramEnv, sProgramPath, ... )\
  4994. redrawMenu()\
  4995. term.redirect( previousTerm )\
  4996. return nResult\
  4997. end\
  4998. \
  4999. function multishell.getCount()\
  5000. return #tProcesses\
  5001. end\
  5002. \
  5003. function shell.openTab(...)\
  5004. local tArgs = {...}\
  5005. launchProcess( {\
  5006. [\"shell\"] = shell,\
  5007. [\"multishell\"] = multishell,\
  5008. [\"_G\"] = _G,\
  5009. [\"_ENV\"] = _ENV,\
  5010. }, unpack(tArgs) or \"/rom/programs/shell\" )\
  5011. end\
  5012. \
  5013. _G.multishell = multishell\
  5014. \
  5015. -- Begin\
  5016. parentTerm.clear()\
  5017. selectProcess( launchProcess( {\
  5018. [\"shell\"] = shell,\
  5019. [\"multishell\"] = multishell,\
  5020. [\"_G\"] = _G,\
  5021. [\"_ENV\"] = _ENV,\
  5022. }, unpack(tArgs) or unpack({Flutter.Dir..\"Programs/shell\"}) ) )\
  5023. -- Since the native terminal is bugged we must trigger a term_resize event.\
  5024. os.queueEvent(\"term_resize\")\
  5025. _G.shell = shell\
  5026. \
  5027. -- Run processes\
  5028. while true do\
  5029. while #tProcesses > 0 do\
  5030. -- Get the event\
  5031. local tEventData = { os.pullEventRaw() }\
  5032. local sEvent = tEventData[1]\
  5033. if sEvent == \"term_resize\" then\
  5034. -- Resize event\
  5035. w,h = parentTerm.getSize()\
  5036. resizeWindows()\
  5037. redrawScreen()\
  5038. \
  5039. elseif sEvent == \"char\" or sEvent == \"key\" or sEvent == \"paste\" or sEvent == \"terminate\" then\
  5040. -- Keyboard event\
  5041. -- Passthrough to current process\
  5042. resumeProcess( nCurrentProcess, unpack( tEventData ) )\
  5043. if cullProcess( nCurrentProcess ) then\
  5044. redrawScreen()\
  5045. end\
  5046. if tProcesses[nCurrentProcess] then\
  5047. if tProcesses[nCurrentProcess].rsX or tProcesses[nCurrentProcess].dragX then\
  5048. if tProcesses[nCurrentProcess].rsX then resumeProcess( nCurrentProcess, \"term_resize\") end\
  5049. tProcesses[nCurrentProcess].dragX, tProcesses[nCurrentProcess].dragY = nil, nil\
  5050. tProcesses[nCurrentProcess].rsX, tProcesses[nCurrentProcess].rsY = nil, nil\
  5051. redrawScreen()\
  5052. end\
  5053. end\
  5054. \
  5055. elseif sEvent == \"mouse_click\" then\
  5056. -- Click event\
  5057. local button, x, y = tEventData[2], tEventData[3], tEventData[4]\
  5058. if tProcesses[nCurrentProcess].rsX or tProcesses[nCurrentProcess].dragX then\
  5059. if tProcesses[nCurrentProcess].rsX then resumeProcess( nCurrentProcess, \"term_resize\") end\
  5060. tProcesses[nCurrentProcess].dragX, tProcesses[nCurrentProcess].dragY = nil, nil\
  5061. tProcesses[nCurrentProcess].rsX, tProcesses[nCurrentProcess].rsY = nil, nil\
  5062. end\
  5063. if y == h then\
  5064. if x <= #sMenu then\
  5065. -- Open menu\
  5066. showQuickMenu()\
  5067. elseif x == #sMenu + 1 then\
  5068. -- Scroll left\
  5069. nMenuScroll = math.max(nMenuScroll - 4, 0)\
  5070. redrawMenu()\
  5071. elseif x == w then\
  5072. -- Scroll right\
  5073. nMenuScroll = math.min(nMenuScroll + 4, math.max(nCurTabsLength - (w - (#sMenu + 2)), 0))\
  5074. redrawMenu()\
  5075. else\
  5076. -- Switch process\
  5077. local tabStart = (#sMenu + 2) - nMenuScroll\
  5078. for n=1,#tProcesses do\
  5079. tabEnd = tabStart + string.len( tProcesses[n].sTitle ) + 1\
  5080. if x >= tabStart and x <= tabEnd then\
  5081. selectProcess( n )\
  5082. redrawScreen()\
  5083. break\
  5084. end\
  5085. tabStart = tabEnd + 1\
  5086. end\
  5087. end\
  5088. else\
  5089. -- Passthrough to current process\
  5090. local nX, nY = tProcesses[nCurrentProcess].window.getPosition()\
  5091. local nWidth, nHeight = tProcesses[nCurrentProcess].window.getSize()\
  5092. if x >= nX and x <= nX + nWidth + 1 and y >= nY and y <= nY + nHeight + 1 then\
  5093. if y == nY then\
  5094. if x == nX + nWidth + 1 then\
  5095. killProcess( nCurrentProcess )\
  5096. elseif x == nX + nWidth - 1 then\
  5097. tProcesses[nCurrentProcess].window.setVisible( false )\
  5098. tProcesses[nCurrentProcess].hidden = true\
  5099. redrawScreen()\
  5100. for k, tProcess in pairs(tProcesses) do\
  5101. if not tProcesses[nCurrentProcess].hidden then\
  5102. selectProcess( k )\
  5103. end\
  5104. end\
  5105. elseif x == nX + nWidth then\
  5106. tProcesses[nCurrentProcess].window.reposition( 1, 1, w, h - 1 )\
  5107. redrawScreen()\
  5108. else\
  5109. tProcesses[nCurrentProcess].dragX, tProcesses[nCurrentProcess].dragY = x - nX, y - nY\
  5110. end\
  5111. else\
  5112. tProcesses[nCurrentProcess].dragX, tProcesses[nCurrentProcess].dragY = nil, nil\
  5113. end\
  5114. if x > nX + nWidth and x < nX + nWidth + 2 and y > nY + nHeight and y < nY + nHeight + 2 then\
  5115. tProcesses[nCurrentProcess].oldWidth, tProcesses[nCurrentProcess].oldHeight = nWidth, nHeight \
  5116. tProcesses[nCurrentProcess].rsX, tProcesses[nCurrentProcess].rsY = x - nX - 1, y - nY - 1\
  5117. elseif tProcesses[nCurrentProcess] then\
  5118. if tProcesses[nCurrentProcess].rsX then\
  5119. if tProcesses[nCurrentProcess].rsX then resumeProcess( nCurrentProcess, \"term_resize\") end\
  5120. tProcesses[nCurrentProcess].dragX, tProcesses[nCurrentProcess].dragY = nil, nil\
  5121. tProcesses[nCurrentProcess].rsX, tProcesses[nCurrentProcess].rsY = nil, nil\
  5122. redrawScreen()\
  5123. end\
  5124. end\
  5125. else\
  5126. for k, tProcess in pairs(tProcesses) do\
  5127. local nX, nY = tProcess.window.getPosition()\
  5128. local nWidth, nHeight = tProcess.window.getSize()\
  5129. if x >= nX and x <= nX + nWidth + 2 and y > nY and y < nY + nHeight then\
  5130. selectProcess( k )\
  5131. redrawScreen()\
  5132. end\
  5133. end\
  5134. end\
  5135. resumeProcess( nCurrentProcess, sEvent, button, x - nX or 0, y - nY or 0 )\
  5136. if cullProcess( nCurrentProcess ) then\
  5137. redrawMenu()\
  5138. end\
  5139. end\
  5140. \
  5141. elseif sEvent == \"mouse_drag\" or sEvent == \"mouse_scroll\" then\
  5142. -- Other mouse event\
  5143. local p1, x, y = tEventData[2], tEventData[3], tEventData[4]\
  5144. if not (y == h) then\
  5145. -- Passthrough to current process\
  5146. local nX, nY = tProcesses[nCurrentProcess].window.getPosition()\
  5147. if tProcesses[nCurrentProcess].dragX then\
  5148. -- Drag the window\
  5149. local dragX, dragY = tProcesses[nCurrentProcess].dragX, tProcesses[nCurrentProcess].dragY\
  5150. local nWidth, nHeight = tProcesses[nCurrentProcess].window.getSize()\
  5151. tProcesses[nCurrentProcess].window.reposition( x - dragX, y - dragY, nWidth + 2, nHeight + 2 )\
  5152. if #tProcesses < 8 then\
  5153. if tProcesses[nCurrentProcess].rsX then resumeProcess( nCurrentProcess, \"term_resize\") end\
  5154. redrawScreen()\
  5155. end\
  5156. redrawMenu()\
  5157. elseif tProcesses[nCurrentProcess] then\
  5158. if tProcesses[nCurrentProcess].rsX then\
  5159. -- Resize the window\
  5160. local dragX, dragY = tProcesses[nCurrentProcess].rsX, tProcesses[nCurrentProcess].rsY\
  5161. local nWidth, nHeight = tProcesses[nCurrentProcess].window.getSize()\
  5162. local oldWidth, oldHeight = tProcesses[nCurrentProcess].oldWidth, tProcesses[nCurrentProcess].oldHeight\
  5163. tProcesses[nCurrentProcess].window.reposition( nX, nY, math.max(oldWidth + 1 + (x - dragX) - nX, 8), math.max(oldHeight + 1 + (y - dragY) - nY, 4))\
  5164. redrawMenu()\
  5165. if #tProcesses < 8 then\
  5166. if tProcesses[nCurrentProcess].rsX then resumeProcess( nCurrentProcess, \"term_resize\") end\
  5167. redrawScreen()\
  5168. end\
  5169. else\
  5170. resumeProcess( nCurrentProcess, sEvent, p1, (x - nX) or 0, (y - nY) or 0 )\
  5171. end\
  5172. end\
  5173. if cullProcess( nCurrentProcess ) then\
  5174. redrawMenu()\
  5175. end\
  5176. end\
  5177. \
  5178. else\
  5179. if tProcesses[nCurrentProcess].rsX or tProcesses[nCurrentProcess].dragX then\
  5180. resumeProcess( nCurrentProcess, \"term_resize\")\
  5181. tProcesses[nCurrentProcess].dragX, tProcesses[nCurrentProcess].dragY = nil, nil\
  5182. tProcesses[nCurrentProcess].rsX, tProcesses[nCurrentProcess].rsY = nil, nil\
  5183. redrawScreen()\
  5184. end\
  5185. -- Other event\
  5186. -- Passthrough to all processes\
  5187. local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event\
  5188. for n=1,nLimit do\
  5189. resumeProcess( n, unpack( tEventData ) )\
  5190. end\
  5191. if cullProcesses() then\
  5192. redrawScreen()\
  5193. end\
  5194. end\
  5195. \
  5196. if bWindowsResized then\
  5197. -- Pass term_resize to all processes\
  5198. local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event\
  5199. for n=1,nLimit do\
  5200. resumeProcess( n, \"term_resize\" )\
  5201. end\
  5202. bWindowsResized = false\
  5203. if cullProcesses() then\
  5204. redrawScreen()\
  5205. end\
  5206. end\
  5207. end\
  5208. redrawScreen()\
  5209. showQuickMenu()\
  5210. redrawScreen()\
  5211. end\
  5212. \
  5213. -- Shutdown\
  5214. term.redirect( parentTerm )\
  5215. term.setBackgroundColor(colors.black)\
  5216. term.setTextColor(colors.white)\
  5217. term.clear()\
  5218. term.setCursorPos(1, 1)",
  5219. [ "Flutter/Apis/Compress" ] = "",
  5220. [ "Flutter/setupAutocomplete" ] = "-- Setup completion functions\
  5221. local tAutocomplete = {}\
  5222. local tFileLines = {}\
  5223. local lastFile\
  5224. function tAutocomplete.completeMultipleChoice( sText, tOptions, bAddSpaces )\
  5225. local tResults = {}\
  5226. for n=1,#tOptions do\
  5227. local sOption = tOptions[n]\
  5228. if #sOption + (bAddSpaces and 1 or 0) > #sText and string.sub( sOption, 1, #sText ) == sText then\
  5229. local sResult = string.sub( sOption, #sText + 1 )\
  5230. if bAddSpaces then\
  5231. table.insert( tResults, sResult .. \" \" )\
  5232. else\
  5233. table.insert( tResults, sResult )\
  5234. end\
  5235. end\
  5236. end\
  5237. return tResults\
  5238. end\
  5239. function tAutocomplete.completePeripheralName( sText, bAddSpaces )\
  5240. return tAutocomplete.completeMultipleChoice( sText, peripheral.getNames(), bAddSpaces )\
  5241. end\
  5242. local tRedstoneSides = redstone.getSides()\
  5243. function tAutocomplete.completeSide( sText, bAddSpaces )\
  5244. return tAutocomplete.completeMultipleChoice( sText, tRedstoneSides, bAddSpaces )\
  5245. end\
  5246. function tAutocomplete.completeFile( shell, nIndex, sText, tPreviousText )\
  5247. if nIndex == 1 then\
  5248. return fs.complete( sText, shell.dir(), true, false )\
  5249. end\
  5250. end\
  5251. function tAutocomplete.completeEdit( shell, nIndex, sText, tPreviousText )\
  5252. if nIndex == 1 then\
  5253. lastFile = sText\
  5254. return fs.complete( sText, shell.dir(), true, false )\
  5255. elseif nIndex == 2 then\
  5256. local lineTable = {}\
  5257. if not tFileLines[lastFile] then\
  5258. local file = fs.open(lastFile, \"r\")\
  5259. local markers = {}\
  5260. local functions = {}\
  5261. local lines = {}\
  5262. if file then\
  5263. while true do\
  5264. local curLine = file.readLine()\
  5265. if not curLine then break end\
  5266. table.insert(lines, curLine)\
  5267. end\
  5268. file.close()\
  5269. end\
  5270. for k, v in ipairs(lines) do\
  5271. if string.find(v, \"--Editor Bookmark--\") then\
  5272. table.insert(markers, tostring(k))\
  5273. elseif string.find(v, \"function\") then\
  5274. table.insert(functions, tostring(k))\
  5275. end\
  5276. end\
  5277. -- First check if the user has added a line Bookmark to the script.\
  5278. if #markers > 0 then -- If so, then return the table of bookmarks.\
  5279. tFileLines[lastFile] = markers\
  5280. elseif #functions > 0 then -- If no bookmarks have been added, then return the table of functions.\
  5281. tFileLines[lastFile] = functions\
  5282. else -- This script has no bookmarks or functions, return a generic line table.\
  5283. local fileLines = {}\
  5284. local markedLines = {}\
  5285. for k=1, 100 do\
  5286. local lineNumber = math.ceil((k/100)*#lines)\
  5287. if not markedLines[lineNumber] then\
  5288. table.insert(fileLines, tostring(lineNumber))\
  5289. markedLines[lineNumber] = true\
  5290. end\
  5291. end\
  5292. tFileLines[lastFile] = fileLines\
  5293. end\
  5294. end\
  5295. local lineTable\
  5296. if tFileLines[lastFile] then\
  5297. lineTable = tFileLines[lastFile]\
  5298. end\
  5299. return tAutocomplete.completeMultipleChoice( sText, lineTable, bAddSpaces )\
  5300. end\
  5301. end\
  5302. function tAutocomplete.completeDir( shell, nIndex, sText, tPreviousText )\
  5303. if nIndex == 1 then\
  5304. return fs.complete( sText, shell.dir(), false, true )\
  5305. end\
  5306. end\
  5307. function tAutocomplete.completeEither( shell, nIndex, sText, tPreviousText )\
  5308. if nIndex == 1 then\
  5309. return fs.complete( sText, shell.dir(), true, true )\
  5310. end\
  5311. end\
  5312. function tAutocomplete.completeEitherEither( shell, nIndex, sText, tPreviousText )\
  5313. if nIndex == 1 then\
  5314. local tResults = fs.complete( sText, shell.dir(), true, true )\
  5315. for n=1,#tResults do\
  5316. local sResult = tResults[n]\
  5317. if string.sub( sResult, #sResult, #sResult ) ~= \"/\" then\
  5318. tResults[n] = sResult .. \" \"\
  5319. end\
  5320. end\
  5321. return tResults\
  5322. elseif nIndex == 2 then\
  5323. return fs.complete( sText, shell.dir(), true, true )\
  5324. end\
  5325. end\
  5326. function tAutocomplete.completeProgram( shell, nIndex, sText, tPreviousText )\
  5327. if nIndex == 1 then\
  5328. return shell.completeProgram( sText )\
  5329. end\
  5330. end\
  5331. function tAutocomplete.completeHelp( shell, nIndex, sText, tPreviousText )\
  5332. if nIndex == 1 then\
  5333. return help.completeTopic( sText )\
  5334. end\
  5335. end\
  5336. function tAutocomplete.completeAlias( shell, nIndex, sText, tPreviousText )\
  5337. if nIndex == 2 then\
  5338. return shell.completeProgram( sText )\
  5339. end\
  5340. end\
  5341. function tAutocomplete.completePeripheral( shell, nIndex, sText, tPreviousText )\
  5342. if nIndex == 1 then\
  5343. return tAutocomplete.completePeripheralName( sText )\
  5344. end\
  5345. end\
  5346. local tGPSOptions = { \"host\", \"host \", \"locate\" }\
  5347. function tAutocomplete.completeGPS( shell, nIndex, sText, tPreviousText )\
  5348. if nIndex == 1 then\
  5349. return tAutocomplete.completeMultipleChoice( sText, tGPSOptions )\
  5350. end\
  5351. end\
  5352. local tLabelOptions = { \"get\", \"get \", \"set \", \"clear\", \"clear \" }\
  5353. function tAutocomplete.completeLabel( shell, nIndex, sText, tPreviousText )\
  5354. if nIndex == 1 then\
  5355. return tAutocomplete.completeMultipleChoice( sText, tLabelOptions )\
  5356. elseif nIndex == 2 then\
  5357. return tAutocomplete.completePeripheralName( sText )\
  5358. end\
  5359. end\
  5360. function tAutocomplete.completeMonitor( shell, nIndex, sText, tPreviousText )\
  5361. if nIndex == 1 then\
  5362. return tAutocomplete.completePeripheralName( sText, true )\
  5363. elseif nIndex == 2 then\
  5364. return shell.completeProgram( sText )\
  5365. end\
  5366. end\
  5367. local tRedstoneOptions = { \"probe\", \"set \", \"pulse \" }\
  5368. function tAutocomplete.completeRedstone( shell, nIndex, sText, tPreviousText )\
  5369. if nIndex == 1 then\
  5370. return tAutocomplete.completeMultipleChoice( sText, tRedstoneOptions )\
  5371. elseif nIndex == 2 then\
  5372. return tAutocomplete.completeSide( sText )\
  5373. end\
  5374. end\
  5375. local tDJOptions = { \"play\", \"play \", \"stop \" }\
  5376. function tAutocomplete.completeDJ( shell, nIndex, sText, tPreviousText )\
  5377. if nIndex == 1 then\
  5378. return tAutocomplete.completeMultipleChoice( sText, tDJOptions )\
  5379. elseif nIndex == 2 then\
  5380. return tAutocomplete.completePeripheralName( sText )\
  5381. end\
  5382. end\
  5383. local tPastebinOptions = { \"put \", \"get \", \"run \" }\
  5384. function tAutocomplete.completePastebin( shell, nIndex, sText, tPreviousText )\
  5385. if nIndex == 1 then\
  5386. return tAutocomplete.completeMultipleChoice( sText, tPastebinOptions )\
  5387. elseif nIndex == 2 then\
  5388. if tPreviousText[2] == \"put\" then\
  5389. return fs.complete( sText, shell.dir(), true, false )\
  5390. end\
  5391. end\
  5392. end\
  5393. local tChatOptions = { \"host \", \"join \" }\
  5394. function tAutocomplete.completeChat( shell, nIndex, sText, tPreviousText )\
  5395. if nIndex == 1 then\
  5396. return tAutocomplete.completeMultipleChoice( sText, tChatOptions )\
  5397. end\
  5398. end\
  5399. \
  5400. for k, v in pairs(fs.list(Flutter.Dir..\"Autocomplete\")) do\
  5401. local file = fs.open(Flutter.Dir..\"Autocomplete/\"..v, \"r\")\
  5402. if file then\
  5403. local autoCompleteType = file.readLine()\
  5404. --print(\"Program \"..v..\" is using \"..autoCompleteType..\"...\")\
  5405. if tAutocomplete[autoCompleteType] then\
  5406. shell.setCompletionFunction( Flutter.Dir..\"Programs/\"..v, tAutocomplete[autoCompleteType] )\
  5407. elseif autoCompleteType == \"Custom\" then\
  5408. shell.setCompletionFunction( Flutter.Dir..\"Programs/\"..v, loadstring(file.readAll()) )\
  5409. else\
  5410. print(\"Unknown auto complete function.\")\
  5411. end\
  5412. file.close()\
  5413. end\
  5414. end",
  5415. [ "Flutter/Programs/levels/4" ] = "2\
  5416. 77777777\
  5417. 777778888887\
  5418. 788888777787\
  5419. 7b77787 787\
  5420. 787 787 787\
  5421. 7b77787 787\
  5422. 7888887 787\
  5423. 7777707 707\
  5424. 777 777",
  5425. [ "Flutter/Programs/shell" ] = "\
  5426. local multishell = multishell\
  5427. local parentShell = shell\
  5428. local parentTerm = term.current()\
  5429. \
  5430. if multishell then\
  5431. multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  5432. end\
  5433. \
  5434. local bExit = false\
  5435. local sDir = (parentShell and parentShell.dir()) or \"\"\
  5436. local sPath = (parentShell and parentShell.path()) or \".:/rom/programs\"\
  5437. local tAliases = (parentShell and parentShell.aliases()) or {}\
  5438. local tCompletionInfo = (parentShell and parentShell.getCompletionInfo()) or {}\
  5439. local tProgramStack = {}\
  5440. \
  5441. local shell = {}\
  5442. local tEnv = {\
  5443. [ \"shell\" ] = shell,\
  5444. [ \"multishell\" ] = multishell,\
  5445. [\"_G\"] = _G,\
  5446. [\"_ENV\"] = _ENV,\
  5447. }\
  5448. \
  5449. -- Colours\
  5450. local promptColour, textColour, bgColour\
  5451. if term.isColour() then\
  5452. promptColour = colours.yellow\
  5453. textColour = colours.white\
  5454. bgColour = colors.black\
  5455. else\
  5456. promptColour = colours.white\
  5457. textColour = colours.white\
  5458. bgColour = colours.black\
  5459. end\
  5460. \
  5461. local function run( _sCommand, ... )\
  5462. local sPath = shell.resolveProgram( _sCommand )\
  5463. if sPath ~= nil then\
  5464. tProgramStack[#tProgramStack + 1] = sPath\
  5465. if multishell then\
  5466. multishell.setTitle( multishell.getCurrent(), fs.getName( sPath ) )\
  5467. end\
  5468. local result = os.run( tEnv, sPath, ... )\
  5469. tProgramStack[#tProgramStack] = nil\
  5470. if multishell then\
  5471. if #tProgramStack > 0 then\
  5472. multishell.setTitle( multishell.getCurrent(), fs.getName( tProgramStack[#tProgramStack] ) )\
  5473. else\
  5474. multishell.setTitle( multishell.getCurrent(), \"shell\" )\
  5475. end\
  5476. end\
  5477. return result\
  5478. else\
  5479. printError(_sCommand..\" is not a valid program or file name.\" )\
  5480. return false\
  5481. end\
  5482. end\
  5483. \
  5484. local function tokenise( ... )\
  5485. local sLine = table.concat( { ... }, \" \" )\
  5486. local tWords = {}\
  5487. local bQuoted = false\
  5488. for match in string.gmatch( sLine .. \"\\\"\", \"(.-)\\\"\" ) do\
  5489. if bQuoted then\
  5490. table.insert( tWords, match )\
  5491. else\
  5492. for m in string.gmatch( match, \"[^ \\t]+\" ) do\
  5493. table.insert( tWords, m )\
  5494. end\
  5495. end\
  5496. bQuoted = not bQuoted\
  5497. end\
  5498. return tWords\
  5499. end\
  5500. \
  5501. -- Install shell API\
  5502. function shell.run( ... )\
  5503. local tWords = tokenise( ... )\
  5504. local sCommand = tWords[1]\
  5505. if sCommand then\
  5506. return run( sCommand, unpack( tWords, 2 ) )\
  5507. end\
  5508. return false\
  5509. end\
  5510. \
  5511. function shell.exit()\
  5512. bExit = true\
  5513. end\
  5514. \
  5515. function shell.dir()\
  5516. return sDir\
  5517. end\
  5518. \
  5519. function shell.setDir( _sDir )\
  5520. sDir = _sDir\
  5521. end\
  5522. \
  5523. function shell.path()\
  5524. return sPath\
  5525. end\
  5526. \
  5527. function shell.setPath( _sPath )\
  5528. sPath = _sPath\
  5529. end\
  5530. \
  5531. function shell.resolve( _sPath )\
  5532. local sStartChar = string.sub( _sPath, 1, 1 )\
  5533. if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  5534. return fs.combine( \"\", _sPath )\
  5535. else\
  5536. return fs.combine( sDir, _sPath )\
  5537. end\
  5538. end\
  5539. \
  5540. function shell.resolveProgram( _sCommand )\
  5541. -- Substitute aliases firsts\
  5542. if tAliases[ _sCommand ] ~= nil then\
  5543. _sCommand = tAliases[ _sCommand ]\
  5544. end\
  5545. \
  5546. -- If the path is a global path, use it directly\
  5547. local sStartChar = string.sub( _sCommand, 1, 1 )\
  5548. if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
  5549. local sPath = fs.combine( \"\", _sCommand )\
  5550. if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  5551. return sPath\
  5552. end\
  5553. return nil\
  5554. end\
  5555. \
  5556. -- Otherwise, look on the path variable\
  5557. for sPath in string.gmatch(sPath, \"[^:]+\") do\
  5558. sPath = fs.combine( shell.resolve( sPath ), _sCommand )\
  5559. if fs.exists( sPath ) and not fs.isDir( sPath ) then\
  5560. return sPath\
  5561. end\
  5562. end\
  5563. \
  5564. -- Not found\
  5565. return nil\
  5566. end\
  5567. \
  5568. function shell.programs( _bIncludeHidden )\
  5569. local tItems = {}\
  5570. \
  5571. -- Add programs from the path\
  5572. for sPath in string.gmatch(sPath, \"[^:]+\") do\
  5573. sPath = shell.resolve( sPath )\
  5574. if fs.isDir( sPath ) then\
  5575. local tList = fs.list( sPath )\
  5576. for n,sFile in pairs( tList ) do\
  5577. if not fs.isDir( fs.combine( sPath, sFile ) ) and\
  5578. (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \".\") then\
  5579. tItems[ sFile ] = true\
  5580. end\
  5581. end\
  5582. end\
  5583. end \
  5584. \
  5585. -- Sort and return\
  5586. local tItemList = {}\
  5587. for sItem, b in pairs( tItems ) do\
  5588. table.insert( tItemList, sItem )\
  5589. end\
  5590. table.sort( tItemList )\
  5591. return tItemList\
  5592. end\
  5593. \
  5594. local function completeProgram( sLine )\
  5595. if #sLine > 0 and string.sub( sLine, 1, 1 ) == \"/\" then\
  5596. -- Add programs from the root\
  5597. return fs.complete( sLine, \"\", true, false )\
  5598. \
  5599. else\
  5600. local tResults = {}\
  5601. local tSeen = {}\
  5602. \
  5603. -- Add aliases\
  5604. for sAlias, sCommand in pairs( tAliases ) do\
  5605. if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then\
  5606. local sResult = string.sub( sAlias, #sLine + 1 )\
  5607. if not tSeen[ sResult ] then\
  5608. table.insert( tResults, sResult )\
  5609. tSeen[ sResult ] = true\
  5610. end\
  5611. end\
  5612. end\
  5613. \
  5614. -- Add programs from the path\
  5615. local tPrograms = shell.programs()\
  5616. for n=1,#tPrograms do\
  5617. local sProgram = tPrograms[n]\
  5618. if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then\
  5619. local sResult = string.sub( sProgram, #sLine + 1 )\
  5620. if not tSeen[ sResult ] then\
  5621. table.insert( tResults, sResult )\
  5622. tSeen[ sResult ] = true\
  5623. end\
  5624. end\
  5625. end\
  5626. \
  5627. -- Sort and return\
  5628. table.sort( tResults )\
  5629. return tResults\
  5630. end\
  5631. end\
  5632. \
  5633. local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts )\
  5634. local tInfo = tCompletionInfo[ sProgram ]\
  5635. if tInfo then\
  5636. return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts )\
  5637. end\
  5638. return nil\
  5639. end\
  5640. \
  5641. function shell.complete( sLine )\
  5642. if #sLine > 0 then\
  5643. local tWords = tokenise( sLine )\
  5644. local nIndex = #tWords\
  5645. if string.sub( sLine, #sLine, #sLine ) == \" \" then\
  5646. nIndex = nIndex + 1\
  5647. end\
  5648. if nIndex == 1 then\
  5649. local sBit = tWords[1] or \"\"\
  5650. local sPath = shell.resolveProgram( sBit )\
  5651. if tCompletionInfo[ sPath ] then\
  5652. return { \" \" }\
  5653. else\
  5654. local tResults = completeProgram( sBit )\
  5655. for n=1,#tResults do\
  5656. local sResult = tResults[n]\
  5657. local sPath = shell.resolveProgram( sBit .. sResult )\
  5658. if tCompletionInfo[ sPath ] then\
  5659. tResults[n] = sResult .. \" \"\
  5660. end\
  5661. end\
  5662. return tResults\
  5663. end\
  5664. \
  5665. elseif nIndex > 1 then\
  5666. local sPath = shell.resolveProgram( tWords[1] )\
  5667. local sPart = tWords[nIndex] or \"\"\
  5668. local tPreviousParts = tWords\
  5669. tPreviousParts[nIndex] = nil\
  5670. return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts )\
  5671. \
  5672. end\
  5673. end\
  5674. return nil\
  5675. end\
  5676. \
  5677. function shell.completeProgram( sProgram )\
  5678. return completeProgram( sProgram )\
  5679. end\
  5680. \
  5681. function shell.setCompletionFunction( sProgram, fnComplete )\
  5682. tCompletionInfo[ sProgram ] = {\
  5683. fnComplete = fnComplete\
  5684. }\
  5685. end\
  5686. \
  5687. function shell.getCompletionInfo()\
  5688. return tCompletionInfo\
  5689. end\
  5690. \
  5691. function shell.getRunningProgram()\
  5692. if #tProgramStack > 0 then\
  5693. return tProgramStack[#tProgramStack]\
  5694. end\
  5695. return nil\
  5696. end\
  5697. \
  5698. function shell.setAlias( _sCommand, _sProgram )\
  5699. tAliases[ _sCommand ] = _sProgram\
  5700. end\
  5701. \
  5702. function shell.clearAlias( _sCommand )\
  5703. tAliases[ _sCommand ] = nil\
  5704. end\
  5705. \
  5706. function shell.aliases()\
  5707. -- Add aliases\
  5708. local tCopy = {}\
  5709. for sAlias, sCommand in pairs( tAliases ) do\
  5710. tCopy[sAlias] = sCommand\
  5711. end\
  5712. return tCopy\
  5713. end\
  5714. \
  5715. if multishell then\
  5716. function shell.openTab( ... )\
  5717. local tWords = tokenise( ... )\
  5718. local sCommand = tWords[1]\
  5719. if sCommand then\
  5720. local sPath = shell.resolveProgram( sCommand )\
  5721. if sPath == \"rom/programs/shell\" then\
  5722. return multishell.launch( tEnv, sPath, unpack( tWords, 2 ) )\
  5723. elseif sPath ~= nil then\
  5724. return multishell.launch( tEnv, \"rom/programs/shell\", sPath, unpack( tWords, 2 ) )\
  5725. else\
  5726. printError(_sCommand..\" is not a valid program or file name.\" )\
  5727. end\
  5728. end\
  5729. end\
  5730. \
  5731. function shell.switchTab( nID )\
  5732. multishell.setFocus( nID )\
  5733. end\
  5734. end\
  5735. \
  5736. local tArgs = { ... }\
  5737. if #tArgs > 0 then\
  5738. -- \"shell x y z\"\
  5739. -- Run the program specified on the commandline\
  5740. shell.run( ... )\
  5741. \
  5742. else\
  5743. -- \"shell\"\
  5744. -- Print the header\
  5745. term.setBackgroundColor( bgColour )\
  5746. term.setTextColor( promptColour )\
  5747. print( os.version() )\
  5748. term.setTextColor( textColour )\
  5749. \
  5750. -- Read commands and execute them\
  5751. local tCommandHistory = Flutter.loadTable(Flutter.Dir..\"Configuration/ShellHistory\") or {}\
  5752. while not bExit do\
  5753. term.setBackgroundColor( bgColour )\
  5754. term.setTextColour( promptColour )\
  5755. write( shell.dir() .. \"> \" )\
  5756. term.setTextColor( textColour )\
  5757. \
  5758. local sLine = read( nil, tCommandHistory, shell.complete )\
  5759. if sLine ~= \"\" then\
  5760. table.insert( tCommandHistory, sLine )\
  5761. Flutter.saveTable(Flutter.Dir..\"Configuration/ShellHistory\", tCommandHistory)\
  5762. end\
  5763. shell.run( sLine )\
  5764. end\
  5765. end",
  5766. [ "Flutter/Programs/levels/10" ] = "5\
  5767. 777 77777\
  5768. 727777778837\
  5769. 788888878787\
  5770. 787777888887\
  5771. 77877778777777\
  5772. 7e8b7888b888e7\
  5773. 7787787b777877\
  5774. 777887887887\
  5775. 7487807487\
  5776. 7777777777",
  5777. [ "Flutter/Programs/flutter" ] = "os.unloadAPI(Flutter.Dir..\"APIs/flu\")\
  5778. os.loadAPI(Flutter.Dir..\"APIs/flu\")\
  5779. print(flu.getReply(\"starttext\"))\
  5780. while true do\
  5781. sleep()\
  5782. print(flu.getReply(read()))\
  5783. end",
  5784. [ "Flutter/Configuration/ShellHistory" ] = "{\
  5785. \"select\",\
  5786. \"select\",\
  5787. \"select\",\
  5788. \"p\",\
  5789. \"p\",\
  5790. \"clipboard_copyclipboard_copyclipboard_copyclipboard_copycedit \",\
  5791. \"clipboard_copy\",\
  5792. \"pedit pedit pedit pedit edit \",\
  5793. \"pedit pedit edit edit pedit \",\
  5794. \"edit edit pedit pedit edit edit pedit pppppedit edit \",\
  5795. \"ads\\\\\",\
  5796. \"arfwrarw\",\
  5797. \"sdfafs\",\
  5798. \"ts\",\
  5799. \"ad\",\
  5800. \"sa\",\
  5801. \"rw\",\
  5802. \"a\",\
  5803. \"wrf\",\
  5804. \"a\",\
  5805. \"es\",\
  5806. \"ddir\",\
  5807. \"21\",\
  5808. \"amp;\",\
  5809. \"dir\",\
  5810. \"label set \\\"Computer\\\"\",\
  5811. \"lua\",\
  5812. \"edit\",\
  5813. \"edit a\",\
  5814. \"publish\",\
  5815. \"Flutter/publish\",\
  5816. \"Flutter/publish\",\
  5817. }",
  5818. [ "Flutter/Programs/scriptScrambler" ] = "local function interference(tab)\
  5819. for k, v in pairs(tab) do\
  5820. if type(v) == \"table\" and v ~= tab then\
  5821. interference(v)\
  5822. elseif type(v) == \"number\" then\
  5823. v = v*math.random()\
  5824. elseif type(v) == \"string\" then\
  5825. if #v > 1 then\
  5826. local l = math.random(#v)\
  5827. v = v:sub(0, l)..v:sub(l, -1)\
  5828. end\
  5829. end\
  5830. end\
  5831. end\
  5832. \
  5833. local function tick()\
  5834. for k, v in pairs(_G) do\
  5835. if type(v) == \"table\" then\
  5836. interference(v)\
  5837. elseif type(v) == \"number\" then\
  5838. v = v*math.random()\
  5839. end\
  5840. end\
  5841. end\
  5842. \
  5843. while true do\
  5844. tick()\
  5845. sleep()\
  5846. end",
  5847. [ "Flutter/Programs/levels/2" ] = "1\
  5848. 777777777\
  5849. 7888888b7\
  5850. 787778887\
  5851. 787 78777\
  5852. 7877787\
  5853. 7888887\
  5854. 7777787\
  5855. 707\
  5856. 777",
  5857. [ "Flutter/Programs/levels/11" ] = "4\
  5858. 777777777\
  5859. 727872787\
  5860. 787878787\
  5861. 777787878787777\
  5862. 7be888888888be7\
  5863. 777787878787777\
  5864. 787878787\
  5865. 787478747\
  5866. 777777777",
  5867. [ "Flutter/Applications/Flutter" ] = "",
  5868. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement