忍者ブログ

cc-memo

Computer Craft のメモ

kyoten/採掘・移動に失敗する場合の考慮

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

コメント

ただいまコメントを受けつけておりません。

kyoten/採掘・移動に失敗する場合の考慮

kyoten
地下深くに拠点(と称した適当な大きさの部屋)を作るプログラム。
ブランチマイニングの拠点として使用する場合は、高度80以下の場所から開始する必要有り。

lib_turtle_0.2.1
毎度の俺々フレームワーク
以下は、lib_turtle_0.2.0からの更新点

[採掘時に砂とか砂利が落ちてくる場合を考慮して処理を追加した]
上を掘る場合
砂や砂利が崩れてくる場合があるので、掘った方向のブロックがなくなるまで、採掘を繰り返す。

正面を掘る場合
砂や砂利が崩れてくる場合があるので、掘った方向のブロックがなくなるまで、採掘を繰り返す。

①はsleep(0)の間隔で目の前のブロックがなくなるまでdig()することでクリア出来るが、、、


 砂
 砂
 砂
亀石
石石石

②はsleep(0)の間隔ではうまくいかないので、sleep(0.5)の間隔でdig()する処理も追加した。


 砂
 砂
 砂
亀石
石 石
石 石
石石石
※という対策を入れたがまだテストしてない。⇒うまく出来ていない。時々停まってる。

「採掘を繰り返す」わけですが、岩盤を採掘しようとして失敗している場合もありうるので、適当なところで切り上げる。
岩盤が正面にあるような場所で正確に作業しようとすること自体に無理があるので、適当。

下を掘る場合
下に掘る場合は特に問題はないと思うので、1回だけ掘る。

[移動時]
ブロックにぶつかって移動できない場合は、エラーとはしない。
MOBに引っかかって、移動しようとした方向に移動できない場合は、移動が成功するまで同じ方向への移動を繰り返す。mobを排除する為に、攻撃(turtle.attack())も行う。とはいえ、所定の回数繰り返しても解決しない場合は、プレイヤーに継続するかあきらめるか決めてもらうようにする。
※書くだけ書いたがまだテストしてない。

[他①]
「ミニ言語」にturtle.suck()とturtle.attack()を追加。
k = suc[k]
a = [a]ttack

[他②]
「ミニ言語」に[v]という命令を追加。
ミニ言語で書いたスクリプトの途中で、Luaで書いた処理を呼び出すための仕組み。
v = user e[v]ent

「lib_turtle_x.x.x」を利用するプログラムに”イベントハンドラ”的な関数を書き、
「lib_turtle_x.x.x」の「userEventHandler」という変数にその関数の”ポインタ”を指定しておけば、vが処理されるタイミングで、その「”イベントハンドラ”」が呼ばれるという仕組み。


以下ソース
lib_turtle_0.2.1
dofile("lib_log");
userEventHandler = nil;
local function myPlace(para1)
  if para1 == 0 then
    turtle.placeUp();
  elseif para1 == 1 then
    turtle.place();
  elseif para1 == 2 then
    turtle.placeDown();
  end
end
local function myThrow(para1, para2)
  if para1 == 0 then
    turtle.dropUp(para2);
  elseif para1 == 1 then
    turtle.drop(para2);
  elseif para1 == 2 then
    turtle.dropDown(para2);
  end
end
local function myExcavate(para1)
  if para1 == 0 then
    if turtle.detectUp() then
      repeat
        turtle.digUp();
        sleep(0.5);
      until not turtle.detectUp()
    end
  elseif para1 == 1 then
    if turtle.detect() then
      for i = 0, 9 do
        turtle.dig();
        sleep(0);
        if false == turtle.detect() then
          return;
        end
      end
      for i = 0, 9 do
        turtle.dig();
        sleep(0.5);
        if false == turtle.detect() then
          return;
        end
      end
end
  elseif para1 == 2 then
    turtle.digDown();
  end
end
local function myZzz(para1)
  sleep(para1 / 1000);
end
local function myOutput(para1, para2)
  local dir = { [0] = "top",  [1] = "front", [2] = "bottom",
                [3] = "left", [4] = "back",  [5] = "right" };
  if para2 == 1 then
    rs.setOutput(dir[para1], true);
  else
    rs.setOutput(dir[para1], false);
  end
end
local function mySuck(para1)
  if para1 == 0 then
    turtle.suckUp();
  elseif para1 == 1 then
    turtle.suck();
  elseif para1 == 2 then
    turtle.suckDown();
  end
end
local function myAttack(para1)
  if para1 == 0 then
    turtle.attackUp();
  elseif para1 == 1 then
    turtle.attack();
  elseif para1 == 2 then
    turtle.attackDown();
  end
end
local function myMove(dirName, moveFunc, detectFunc, attackFunc)
  local rslt, msg;
  while true do
    rslt, msg = moveFunc();
    if rslt then
      return;
    else
      if moveFunc == turtle.back then
        turtle.turnRight();
        turtle.turnRight();
      end
      if detectFunc() then
        if moveFunc == turtle.back then
          turtle.turnLeft();
          turtle.turnLeft();
        end
        return;
      else
        for i = 0, 9 do
          attackFunc();
          attackFunc();
          attackFunc();
          if moveFunc == turtle.back then
            if true == turtle.forward() then
              turtle.turnLeft();
              turtle.turnLeft();
              return;
            end
          else
            if true == moveFunc() then
              return;
            end
          end
        end
        if moveFunc == turtle.back then
          turtle.turnLeft();
          turtle.turnLeft();
        end
        while true do
          print("move [" .. dirName .. "] failed. retry? (y/n)");
          local input = read();
          if "y" == input then
            break;
          elseif "n" == input then
            error("program stopped by user request.");
          else
            print("wrong input. type y or n.");
          end
        end
      end
    end
  end
end
local function myForward()
  myMove("forward", turtle.forward, turtle.detect, turtle.attack);
end
local function myBack()
  myMove("back", turtle.back, turtle.detect, turtle.attack);
end
local function myUp()
  myMove("up", turtle.up, turtle.detectUp, turtle.attackUp);
end
local function myDown()
  myMove("down", turtle.down, turtle.detectDown, turtle.attackDown);
end
local function myUserEvent(para1)
  if nil ~= userEventHandler then
    userEventHandler(para1);
  end
end
local cmdInfo =
{
  f = { paraCnt = 0, func = myForward;        }, -- [f]orward
  b = { paraCnt = 0, func = myBack;           }, -- [b]ack
  l = { paraCnt = 0, func = turtle.turnLeft;  }, -- turn [l]eft
  r = { paraCnt = 0, func = turtle.turnRight; }, -- turn [r]ight
  u = { paraCnt = 0, func = myUp;             }, -- [u]p
  d = { paraCnt = 0, func = myDown;           }, -- [d]own
  s = { paraCnt = 1, func = turtle.select;    }, -- [s]elect
  p = { paraCnt = 1, func = myPlace;          }, -- [p]lace
  t = { paraCnt = 2, func = myThrow;          }, -- [t]hrow = drop
  e = { paraCnt = 1, func = myExcavate;       }, -- [e]xcavate = dig
  z = { paraCnt = 1, func = myZzz;            }, -- [z]zz = sleep
  o = { paraCnt = 2, func = myOutput;         }, -- set [o]utput (redstone) 
  k = { paraCnt = 1, func = mySuck;           }, -- suc[k]
  a = { paraCnt = 1, func = myAttack;         }, -- [a]ttack
  v = { paraCnt = 1, func = myUserEvent;      }, -- user e[v]ent
};
local function getParam(command, idx)
  local buff = "";
  local ch = "";
  for i = idx, command:len() do
    ch = command:sub(i, i);
    --log("getParam i = " .. i .. " / ch =[" .. ch .. "]");
    if ch == "," then
      if buff == "" then
        return nil, i + 1;
      else
        return tonumber(buff), i + 1;
      end
    elseif nil ~= string.find("0123456789", ch, 1, true) then
      buff = buff .. ch;
    else
      if buff ~= "" then
        return tonumber(buff), i;
      end
    end
  end
  if buff == "" then
    return nil, command:len() + 1;
  else
    return tonumber(buff), command:len() + 1;
  end
end
local function get1Cmd(command, idx)
  local cmd = string.sub(command, idx, idx);
  local para1, para2, nextIdx, paraCnt;
  --log(idx .. " / " .. cmd);
  if nil ~= cmdInfo[cmd] then
    paraCnt = cmdInfo[cmd].paraCnt;
  else
    --log("unknown command [" .. cmd .. "]");
    error("unknown command [" .. cmd .. "]");
  end
  if -1 == paraCnt then
    return nil, nil, nil, idx + 1;
  elseif paraCnt == 0 then
    return cmd, nil, nil, idx + 1;
  elseif paraCnt == 1 then
    para1, nextIdx = getParam(command, idx + 1);
    return cmd, para1, nil, nextIdx;
  elseif paraCnt == 2 then
    para1, nextIdx = getParam(command, idx + 1);
    para2, nextIdx = getParam(command, nextIdx);
    return cmd, para1, para2, nextIdx;
  end
end
local function checkLoop(command)
  local kBgn = {""};
  local loopInfo = {};
  local ch, repeatCnt, nextIdx, kBgnIdx;
  for i = 1, command:len() do
    ch = command:sub(i, i);
    if "(" == ch then
      table.insert(kBgn, i);
    elseif ")" == ch then
      repeatCnt, nextIdx = getParam(command, i + 1);
      loopInfo[i] = { beginIdx   = table.remove(kBgn),
                      endIdx     = i,
                      nextIdx    = nextIdx,
                      repeatCnt  = repeatCnt,
                      currentCnt = 0 };
      --log("loopInfo[" .. i .. "]");
      --log("  beginIdx   = " .. loopInfo[i].beginIdx);
      --log("  endIdx     = " .. loopInfo[i].endIdx);
      --log("  nextIdx    = " .. loopInfo[i].nextIdx);
      --log("  repeatCnt  = " .. loopInfo[i].repeatCnt);
      --log("  currentCnt = " .. loopInfo[i].currentCnt);
      i = nextIdx;
    end
  end
  return loopInfo;
end
function doCommand(command)
  
  command = command .. " ";
  local loopInfo = checkLoop(command);
  --for i, dat in pairs(loopInfo) do
    --log("check loopInfo")
    --log("  i = " .. i);
    --log("  " .. dat.beginIdx .. " / " .. dat.endIdx .. " / " .. dat.repeatCnt);
  --end
  local cmd, para1, para2, nextIdx, ch;
  local i = 1;
  while true do
    ch = command:sub(i, i);
    --log("doCommand idx = " .. i .. " [" .. ch .. "]");
    if ")" == ch then
      --log("i = " .. i);
      --log(   loopInfo[i].beginIdx .. " / " .. loopInfo[i].endIdx .. " / "
      --    .. loopInfo[i].nextIdx  .. " / " .. loopInfo[i].repeatCnt);
      loopInfo[i].currentCnt = loopInfo[i].currentCnt + 1;
      if loopInfo[i].repeatCnt <= loopInfo[i].currentCnt then
        loopInfo[i].currentCnt = 0;
        i = loopInfo[i].nextIdx;
      else
        i = loopInfo[i].beginIdx;
      end
    elseif " " == ch then
      i = i + 1;
    elseif "\n" == ch then
      i = i + 1;
    elseif "(" == ch then
      i = i + 1;
    else
      cmd, para1, para2, nextIdx = get1Cmd(command, i);
      --log("  nextIdx = " .. nextIdx);
      i = nextIdx;
      if cmd ~= nil then
        cmdInfo[cmd].func(para1, para2);
      end
    end
    if command:len() <= i then
      break;
    end
  end
end

kyoten
dofile("lib_turtle_0.2.1");
torchCnt = 0;
levelCnt = 0;
local function myUserEvent(para1)
  if 0 == para1 then
    torchCnt = 1;
  elseif 1 == para1 then
    torchCnt = torchCnt + 1;
    if torchCnt == 2 or torchCnt == 7 or torchCnt == 9 or torchCnt == 14 then
      doCommand("le1le1 rr ");
    end
  elseif 2 == para1 then
    if torchCnt == 2 or torchCnt == 7 or torchCnt == 9 or torchCnt == 14 then
      doCommand("s4 p0 s1 ");
    end
  elseif 3 == para1 then
    doCommand("s2 t2,64 s3 t2,64 s5 t2,64 s6 t2,64 s7 t2,64 s8 t2,64 s9 t2,64"
           .. "s10t2,64 s11t2,64 s12t2,64 s13t2,64 s14t2,64 s15t2,64 s16t2,64 ");
  elseif 4 == para1 then
    if 0 < levelCnt then
      doCommand(string.rep("e2d e2d ", levelCnt));
    end
  elseif 5 == para1 then
    doCommand(string.rep("e0u e0u ", levelCnt) .. " r s1p1 e0u p1p0 e2dl ");
  elseif 6 == para1 then
    if levelCnt == 0 then
      doCommand("p2 ");
    end
  elseif 7 == para1 then
    levelCnt = levelCnt + 1;
  end
end
userEventHandler = myUserEvent;
print("slot1 : cobblestone x 64");
print("slot2 : ladder x 64");
print("slot3 : ladder x 16");
print("slot4 : torch x 64");
print("slot5 : chest x 2");
-- print("required fuel level : "); -- TODO
print("hit any key when ready.");
read();
doCommand("e2d (s1(p1l)4 s2e2d p0)64 (s1(p1l)4 s3 e2d p0)16 (e0u)6 s1p2 ");
doCommand("s1 (e1f)2 rp2p1e0up1p0ld ");
doCommand("e2d e2s1p2(p1l)4 u s5p2 le1fe2de2dus1p2(p1l)4us5p2lle1fl v3 ");
doCommand("("
       .. "  s1(v0 (e1f r v6 p1 e0u p1p0 v1 d v2 l)14 v6 p1 u p1p0 d l)4 rre1ll v4 v3 v5 "
       .. "  l e1fr s1 ("
       .. "              (e1fv6 e0up0d)13 e1fle1fl " 
       .. "              (e1fv6 e0up0d)13 e1fre1fr "
       .. "            )6"
       .. "              (e1fv6 e0up0d)13 "
       .. "            ll (e1f)13 l (e1f)13 l v4 v3 v7 v5 "
       .. "  "
       .. ")2 ");



PR

コメント

プロフィール

HN:
kssr
性別:
非公開

Twitter

最古記事

(04/25)
(04/26)
(04/27)
(04/28)
(04/29)

アンテナ・ランキング