I miss FORTH. Once you wrapped your head around the reverse polish notation and got a handle on how much you could/should factor your code, it was simple, elegant, and perfect for automating machinery. It's also about half a step above raw assembly, which made it very very fast provided you were using compiled words and not interpreting off a disk like most people seemed to think they needed to.
Anyway, controlling that monster with LUA will work much the same as with FORTH:
Basically it boils down to creating a function for each action and then sequencing them together. For movement that means turning on the output for a given direction, waiting some amount of time, turning it back of, then waiting again for whatever delay it takes for the machine to be able to take another movement. Keep those delay amounts in variables so you can use them everywhere but tweak them easily. From my work making FORTH-operated tunnel bores I would recommend having a short delay (0.05 or 0.1) between activating the redstone and shutting it off, and a longer delay between motions (the four seconds you mentioned).
You said you got the timing down in FORTH, so here's how to translate that: each TICK in forth is a sleep(0.05) in LUA, so if you were waiting 3 TICKS between redstone toggles you'll want to sleep(0.15) and so on.
Basically, your program will look something like this:
delayRedstone = ## -- you have this data in your existing FORTH program; it's how long each output stays on for
delayMove = ## -- if it takes four seconds to settle out, then stick a 4 here
function dig()
redstone.setBundledOutput(number) -- in this case "number" really means "colors.colorname" for the line to your breakers
sleep(delayRedstone)
redstone.setBundledOutput(0) -- shuts off the output
end
function forward()
redstone.setBundledOutput(number) -- first color to move forward
sleep(delayMove) -- give it time for first motor to finish moving
redstone.setBundledOutput(number) -- second color to move forward
sleep(delayMove)
redstone.setBundledOutput(0)
end
--back() left() right() up() and down() are just variations of the above with the appropriate colors substituted.
--You can always use compass directions for names if you prefer. You may want to include dig() as part of the direction it digs in,
--but that is up to you. You will then need to sequence the desired actions, with loops as needed.
--The following will tell it to dig 10 blocks forward, come back, shift sideways 10 blocks to the next location, and repeat.
while true do
for i=1,10 do
dig()
forward()
end
for i=1,10 do back() end
for i=1,10 do left() end
end
Once the basic functions are built for the actions it can perform, you can make things as complex or simple as you please. If you want to write less code overall, you can include the for loops int he move functions themselves so it takes an argument. If you do this, make sure your "forward" also digs. That would look something like this:
function forward(times)
if times == nil then times = 1 end -- if you just call forward() with no argument, it will still move one time, but forward(10) moves 10 times
for i=1,times do
--movement code, same as above; make sure you dig if it is appropriate
end
end
-- the sequenced action from above now looks like this
while true do
forward(10)
back(10)
left(10)
end
If you want to track where it is, have variables for X Y and Z that are altered when it moves. So if forward moves along the X axis then you just add X = X+1 inside your forward() function, X=X-1 in back(), etc. There are tutorials elsewhere on the forum for how to save and load this data to a file so you could make it load it's current position at startup and use where it is to determine what it should do next.
Note, however, that unlike a turtle you cannot tell if a motion was successful; if your machine gets blocked and cannot actually move it will still THINK it has moved and change it's internal position unless you build some kind of feedback into it. I'm sure you can think of a way to do that, but your engine will be larger. This was a problem on my tunnel bore; it would encounter gravel and get stuck int he same place for a few attempts. I had to check in on it now and then and calibrate it to it's actual position. A possible way to thwart this, at the expense of mining speed, would be to dig multiple times before moving.
Assuming your tracked position is accurate however, you can move to a specific location by subtracting your position on an axis from the desired position, then moving the appropriate direction that many times. If forward is +X, you are at location 10 and you want to go to location 5….
goto(XDesired,YDesired,ZDesired)
XDiff = XDesired-X
if XDiff > 0 then -- current 10, want 15, XDiff = 5
forward(XDiff)
elseif XDiff < 0 then -- current 10, want 5, XDiff = -5
back(-XDiff) --you can also make the move functions ensure the argument is positive instead of inverting it here
end
--Y and Z follow the same; just make sure the directions are correct
end
I hope this helps. I had a lot of fun programming my tunnel bore back in the day.