Advertisement
kssr3951

tinyTr2

Jun 22nd, 2014
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.59 KB | None | 0 0
  1. local function fileReadAll(filePath)
  2.   local hFile = fs.open(filePath, "r")
  3.   local txt = hFile.readAll()
  4.   hFile.close()
  5.   return txt
  6. end
  7.  
  8. local function fileOverwrite(fileName, text)
  9.   local hFile = fs.open(fileName, "w")
  10.   hFile.writeLine(text)
  11.   hFile.close()
  12. end
  13.  
  14. LOG_FILE_NAME = "debug.log";
  15. local function log(txt)
  16.   local hFile;
  17.   if fs.exists(LOG_FILE_NAME) then
  18.     hFile = fs.open(LOG_FILE_NAME, "a");
  19.   else
  20.     hFile = fs.open(LOG_FILE_NAME, "w");
  21.   end
  22.   hFile.writeLine(txt);
  23.   hFile.close();
  24. end
  25.  
  26. function split(src, sepalator)
  27.   local ret = { }
  28.   local tmp = ""
  29.   for i = 1, #src do
  30.     if sepalator == src:sub(i, i) then
  31.       table.insert(ret, tmp)
  32.       tmp = ""
  33.     else
  34.       tmp = tmp .. src:sub(i, i)
  35.     end
  36.   end
  37.   if "" ~= tmp then
  38.     table.insert(ret, tmp)
  39.   end
  40.   return ret;
  41. end
  42.  
  43. local function loopHead()
  44.   -- do nothing
  45. end
  46.  
  47. local function loopTail(args, status)
  48.   local loopCnt = tonumber(args[2])
  49.   local headIdx = args[3]
  50.   local tailIdx = args[4]
  51.   local loopData = status.loopInfo[tailIdx]
  52.   if nil == loopData then
  53.     status.loopInfo[tailIdx] = { currentIteration = 1 }
  54.     loopData = status.loopInfo[tailIdx]
  55.   end
  56.   local currIter = loopData.currentIteration
  57.   if loopCnt <= currIter then
  58.     status.loopInfo[tailIdx].currentIteration = 1
  59.     status.currentStep = tailIdx + 1
  60.   else
  61.     status.loopInfo[tailIdx].currentIteration = currIter + 1
  62.     status.currentStep = headIdx
  63.   end
  64.   return status
  65. end
  66.  
  67. local function myReboot()
  68.   print("reboot!")
  69. end
  70.  
  71. local function mySleep(millisec)
  72.   sleep(millisec / 1000)
  73. end
  74.  
  75. local function createMySetRedStoneOutputFunc(side)
  76.   return function(value)
  77.       local dirName = { [0] = "up"  , [1] = "front", [2] = "down",
  78.                         [3] = "left", [4] = "back" , [5] = "right" }
  79.       local onOff = { [0] = false, [1] = true }
  80.       rs.setOutput(dirName[side], onOff[value])
  81.       -- TODO status
  82.     end
  83. end
  84.  
  85. local function vacuum(slotNo)
  86.   turtle.select(slotNo)
  87.   for i = 1, 16 do
  88.     if slotNo ~= i and turtle.compareTo(i) then
  89.       turtle.select(i)
  90.       turtle.transferTo(slotNo, turtle.getItemSpace(slotNo))
  91.       if 0 == turtle.getItemSpace(slotNo) then
  92.         break
  93.       end
  94.       turtle.select(slotNo)
  95.     end
  96.   end
  97.   turtle.select(slotNo)
  98. end
  99.  
  100. local doAllCurrentSelectIdx
  101.  
  102. local function createMyDrop(dropFunc)
  103.   return function()
  104.            if 0 == turtle.getItemCount(doAllCurrentSelectIdx) then
  105.              return true
  106.            else
  107.              return dropFunc()
  108.            end
  109.          end
  110. end
  111.  
  112. local function createDoAllFunc(func, needSelect)
  113.   return function()
  114.            for i = 1, 16 do
  115.              if needSelect then
  116.                turtle.select(i)
  117.                doAllCurrentSelectIdx = i
  118.              end
  119.              func(i)
  120.            end
  121.          end
  122. end
  123.  
  124. local function createRetryFunc(func, sleepSec, sleepMsg)
  125.   return function()
  126.            while true do
  127.              if not func() then
  128.                print(sleepMsg)
  129.                term.write("(sleep " .. tostring(sleepSec) .. ")")
  130.                local cnt = math.floor(sleepSec)
  131.                local fraction = sleepSec - cnt
  132.                for i = 1, cnt do
  133.                  term.write(".")
  134.                  sleep(1)
  135.                end
  136.                if 0 < fraction then
  137.                  term.write(".")
  138.                  sleep(fraction)
  139.                end
  140.              else
  141.                break
  142.              end
  143.            end
  144.          end
  145. end
  146.  
  147. local commands = {
  148.   _fuel     = { numArgs = 1, func = turtle.refuel },
  149.   _reboot   = { numArgs = 0, func = myReboot },
  150.   _loopHead = { numArgs = 0, func = loopHead },
  151.   _loopTail = { numArgs = 1, func = loopTail },
  152.   l  = { numArgs = 0, func = turtle.turnLeft },
  153.   r  = { numArgs = 0, func = turtle.turnRight },
  154.   f  = { numArgs = 0, func = createRetryFunc(turtle.forward, 1, "cannot move forward") },
  155.   b  = { numArgs = 0, func = createRetryFunc(turtle.back   , 1, "cannot move back"   ) },
  156.   u  = { numArgs = 0, func = createRetryFunc(turtle.up     , 1, "cannot move up"     ) },
  157.   d  = { numArgs = 0, func = createRetryFunc(turtle.down   , 1, "cannot move down"   ) },
  158.   s  = { numArgs = 1, func = turtle.select },
  159.   p0 = { numArgs = 0, func = turtle.placeUp },
  160.   p1 = { numArgs = 0, func = turtle.place },
  161.   p2 = { numArgs = 0, func = turtle.placeDown },
  162.   t0 = { numArgs = 0, func = turtle.dropUp },
  163.   t1 = { numArgs = 0, func = turtle.drop },
  164.   t2 = { numArgs = 0, func = turtle.dropDown },
  165.   e0 = { numArgs = 0, func = turtle.digUp },
  166.   e1 = { numArgs = 0, func = turtle.dig },
  167.   e2 = { numArgs = 0, func = turtle.digDown },
  168.   z  = { numArgs = 1, func = mySleep },
  169.   o1 = { numArgs = 1, func = createMySetRedStoneOutputFunc(1) },
  170.   o2 = { numArgs = 1, func = createMySetRedStoneOutputFunc(2) },
  171.   o3 = { numArgs = 1, func = createMySetRedStoneOutputFunc(3) },
  172.   o4 = { numArgs = 1, func = createMySetRedStoneOutputFunc(4) },
  173.   o5 = { numArgs = 1, func = createMySetRedStoneOutputFunc(5) },
  174.   o6 = { numArgs = 1, func = createMySetRedStoneOutputFunc(6) },
  175.   v =  { numArgs = 1, func = vacuum },
  176.   k0 = { numArgs = 0, func = turtle.suckUp },
  177.   k1 = { numArgs = 0, func = turtle.suck },
  178.   k2 = { numArgs = 0, func = turtle.suckDown },
  179.   a0 = { numArgs = 0, func = turtle.attackUp },
  180.   a1 = { numArgs = 0, func = turtle.attack },
  181.   a2 = { numArgs = 0, func = turtle.attackDown },
  182.   T0 = { numArgs = 0, func = createDoAllFunc(createRetryFunc(createMyDrop(turtle.dropUp  ), 10, "cannot drop up")     , true) },
  183.   T1 = { numArgs = 0, func = createDoAllFunc(createRetryFunc(createMyDrop(turtle.drop    ), 10, "cannot drop forward"), true) },
  184.   T2 = { numArgs = 0, func = createDoAllFunc(createRetryFunc(createMyDrop(turtle.dropDown), 10, "cannot drop down")   , true) },
  185.   K0 = { numArgs = 0, func = createDoAllFunc(turtle.suckUp  , false) },
  186.   K1 = { numArgs = 0, func = createDoAllFunc(turtle.suck    , false) },
  187.   K2 = { numArgs = 0, func = createDoAllFunc(turtle.suckDown, false) },
  188. }
  189.  
  190. local function findLoopHead(cmdList)
  191.   local closeCnt = 1
  192.   for i = #cmdList, 1, -1 do
  193.     local cmdName = cmdList[i][1]
  194.     local tmp = 0
  195.     if "_loopHead" == cmdName then
  196.       tmp = -1
  197.     elseif "_loopTail" == cmdName then
  198.       tmp = 1
  199.     end
  200.     if 0 ~= tmp then
  201.       closeCnt = closeCnt + tmp
  202.       if 0 == closeCnt then
  203.         return i
  204.       end
  205.     end
  206.   end
  207.   error("Correspondence of a parenthesis is inaccurate. (cmdIdx = " .. #cmdList .. ")")
  208. end
  209.  
  210. local function parse(script)
  211.   local replTmp = { }
  212.   local tmp = script .. "\n"
  213.   tmp = tmp:gsub("%-%-%[%[[^]]*%-%-%]%]", "")
  214.   tmp = tmp:gsub("%-%-[^\n]*\n", "")
  215.   tmp = tmp:gsub("%(", "{loopHead} ")
  216.   tmp = tmp:gsub("%)%s*(%d+)", "{loopTail}%1")
  217.   local j = 0
  218.   for i = 1, 2 do
  219.     for key, v in pairs(commands) do
  220.       if  (1 == i and "_" == key:sub(1, 1)) or
  221.           (2 == i and "_" ~= key:sub(1, 1)) then
  222.         local tempLabel = "{" .. tostring(j) .. "}"
  223.         j = j + 1
  224.         local keyPtrn
  225.         if "_" == key:sub(1, 1) then
  226.           keyPtrn = "({[^}]*" .. key:sub(2) .. "[^{]*})"
  227.         else
  228.           keyPtrn = "(" .. key .. ")"
  229.         end
  230.         if 0 == v.numArgs then
  231.           tmp = tmp:gsub(keyPtrn, tempLabel .. " ")
  232.           replTmp[tempLabel] = key
  233.         elseif 1 == v.numArgs then
  234.           tmp = tmp:gsub(keyPtrn .. "%s*(%d+)", tempLabel .. ",%2 ")
  235.           replTmp[tempLabel] = key
  236.         elseif 2 == v.numArgs then
  237.           tmp = tmp:gsub(keyPtrn .. "%s*(%d+)%s*,%s(%d+)", tempLabel .. ",%2,%3 ")
  238.           replTmp[tempLabel] = key
  239.         end
  240.       end
  241.     end
  242.   end
  243.   for key, v in pairs(replTmp) do
  244.     tmp = tmp:gsub(key, v)
  245.   end
  246.   tmp = tmp:gsub("^%s+", "")
  247.   tmp = tmp:gsub("%s*$", " ")
  248.   tmp = tmp:gsub("%s+" , " ")
  249.  
  250.   local stIdx = 1
  251.   local idx
  252.   local params
  253.   rslt = { }
  254.   while true do
  255.     idx = tmp:find(" ", stIdx, true)
  256.     if nil == idx then
  257.       break
  258.     end
  259.     params = split(tmp:sub(stIdx, idx - 1), ",")
  260.     if "_loopTail" == params[1] then
  261.       table.insert(params, findLoopHead(rslt))
  262.       table.insert(params, #rslt + 1)
  263.     end
  264.     table.insert(rslt, params)
  265.     stIdx = idx + 1
  266.   end
  267.   return rslt
  268. end
  269.  
  270. local function createInitialStatus()
  271.   return {
  272.            currentStep = 1,
  273.            loopInfo = { }
  274.          }
  275. end
  276.  
  277. local function doCommand(v, status)
  278.   if "_loopTail" ~= v[1] then
  279.     if 1 == #v then
  280.       commands[v[1]].func()
  281.     elseif 2 == #v then
  282.       commands[v[1]].func(tonumber(v[2]))
  283.     elseif 3 == #v then
  284.       commands[v[1]].func(tonumber(v[2]), tonumber(v[3]))
  285.     end
  286.     status.currentStep = status.currentStep + 1
  287.     if "_reboot" == v[1] then
  288.       return status, true
  289.     else
  290.       return status
  291.     end
  292.   else
  293.     status = commands[v[1]].func(v, status)
  294.     return status
  295.   end
  296. end
  297.  
  298. local TINY_TR_SCRIPT = "tiny_tr.script"
  299. local TINY_TR_CONFIG = "tiny_tr.config"
  300. local TINY_TR_STATUS = "tiny_tr.status"
  301.  
  302. local function runScript(scriptTbl, status, saveStatusFlg)
  303.   local rebootFlg = false
  304.   while true do
  305.     if status.currentStep <= #scriptTbl then
  306.       local v = scriptTbl[math.floor(status.currentStep)]
  307.       status, rebootFlg = doCommand(v, status)
  308.       if saveStatusFlg then
  309.         fileOverwrite(TINY_TR_STATUS, textutils.serialize(status))
  310.       end
  311.       if rebootFlg then
  312.         os.reboot()
  313.       end
  314.     else
  315.       status.currentStep = 1
  316.       break
  317.     end
  318.   end
  319.   return status
  320. end
  321.  
  322. local CONFIG_TEMPLATE =[[
  323. INFINITE_LOOP = false
  324. ]]
  325.  
  326. -- ------------------------------------
  327. -- main
  328. -- ------------------------------------
  329. local args = { ... }
  330. local scriptTbl
  331. if 1 <= #args then
  332.   local makeOnly = false
  333.   local srcFile
  334.   if 2 <= #args then
  335.     if "-c" == args[1] then
  336.       makeOnly = true
  337.       srcFile = args[2]
  338.     else
  339.       print("bad argument.")
  340.       return
  341.     end
  342.   else
  343.     srcFile = args[1]
  344.   end
  345.  
  346.   scriptTbl = parse(fileReadAll(srcFile))
  347.   fileOverwrite(TINY_TR_SCRIPT, textutils.serialize(scriptTbl))
  348.   if not fs.exists(TINY_TR_CONFIG) then
  349.     fileOverwrite(TINY_TR_CONFIG, CONFIG_TEMPLATE)
  350.   end
  351.   fs.delete(TINY_TR_STATUS)
  352.   fileOverwrite(TINY_TR_STATUS, createInitialStatus())
  353.   if not makeOnly then
  354.     runScript(scriptTbl, createInitialStatus(), false)
  355.   end
  356.   print("tinyTr2 was completed.")
  357. else
  358.   scriptTbl = textutils.unserialize(fileReadAll(TINY_TR_SCRIPT))
  359.   local status = textutils.unserialize(fileReadAll(TINY_TR_STATUS))
  360.   dofile(TINY_TR_CONFIG)
  361.   while true do
  362.     status = runScript(scriptTbl, status, true)
  363.     if not INFINITE_LOOP then
  364.       print("tinyTr2 was completed.")
  365.       break
  366.     else
  367.       print("infinite loop.")
  368.     end
  369.   end
  370. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement