This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Sangar's profile picture

Lama - Location Aware Movement Api V1.4

Started by Sangar, 05 July 2013 - 03:35 PM
Sangar #1
Posted 05 July 2013 - 05:35 PM
Greetings. After confirming that my idea posted here for a workaround on keeping track of a turtle's movement is actually working, I decided to build a small API around it. This is it. Note that this is my first ComputerCraft API, so if I ignorantly violated some conventions, let me know. If you're interested in the code or want to contribute, I have created a repo on Github.

Important: when upgrading from version 1.0 or 1.1, please see the changelog for version 1.2 regarding a possibly breaking change and how to easily unbreak stuff.

Description
This API provides persistent position and facing awareness for turtles. You can query a turtle's position and facing at any time, and it will not 'desynchronize' if the turtle is unloaded (game quit / chunk unloaded) while it moves. To achieve this, it offers replacements for the default turtle movement functions, i.e. for turtle.forward(), turtle.back(), turtle.up(), turtle.down(), turtle.turnLeft() and turtle.turnRight(), as well as one for refueling, i.e. for turtle.refuel(). It also provides a few more high level movement functions to travel multiple blocks, as well as a waypoint system to store coordinates and refer to them by name.

This means you can write resumable programs that make decisions based on the turtle's position. For example, saving the following program as the startup file will make the turtle run in circles until it runs out of fuel (precondition: turtle starts at x = 0, y = 0). It will not leave its track even if the turtle is forcibly shut down at any point.

os.loadAPI("lama")
while true do
	local x, y, z = lama.get()
	if x == 0 and z == 0 then
		lama.turn(lama.side.north)
	elseif x == 0 and z == -2 then
		lama.turn(lama.side.east)
	elseif x == 2 and z == -2 then
		lama.turn(lama.side.south)
	elseif x == 2 and z == 0 then
		lama.turn(lama.side.west)
	end
	lama.forward(math.huge) -- Keep trying.
end

Requirements
This API only works on turtles that have a label and that use fuel. The label is required for state persistence, the fuel is used for checking whether the turtle finished a move that was interrupted by a forced shut down (game quit / chunk unloaded).

Important: when using this API, you must not use any of the original movement related functions, since that would invalidate the API's internal state (coordinates would no longer match), neither the original refuel function, which would also invalidate the state. Always use the functions of this API to move and refuel the turtle. You can use lama.hijackTurtleAPI() to have the functions in the turtle API replaced with wrappers for this API's functions. The native functions won't be touched; don't use them either way.

Recommended
SpoilerThe API will create a startup file while performing a move, to allow completion of multi-try moves after reboot. If there's an original startup file, it will be backed up and after API initialization/move completion will be restored an executed. This obviously introduces additional file i/o overhead for each move. To avoid that, it is highly recommended to use some multi-startup-script solution, such as Forairan's init-scripts startup file or my startup API. If present, LAMA will instead create a startup script for the multi-script-environment once, with no additional file i/o overhead when moving.

If you'd like to see compatibility with other multi-startup-script systems (I have not dabbled with custom OSs much, yet), let me know - or even better: implement it yourself and submit a pull request on Github. It's pretty easy to add more, as long as there's a way to detect the used script/system. Should you wish to give it a go, search for local startupHandlers in the code, which is the table containing the logic for different startup handlers.

Installation
To install the API, first run:
> pastebin get q45K18dv lama-installer
which will give you the installer. After it downloaded, run it:
> lama-installer

It will fetch the API and, if so desired the lama-conf program as well as an example program (it will interactively ask you). Note that the installer will not self-destruct, so you can use it to update your installation.

Alternatively you can install the API via cc-get:
> cc-get install lama
This includes only lama-conf, but not the example programs. Note that you will have to use os.loadAPI("/bin/lama-lib/lama") in this case (in particular, you'll have to adjust that call in the example program).

In both cases you will get a minified version, which is roughly only a third the size of the original version. Note the the custom installer will provide you with the option to download the full source version, too.

API
This list is just meant to provide a quick overview of the available functionality. Please see the actual code for full documentation. It is rather well commented. While you're at it, have a look at the lama.reason table to see how the movement functions may fail.

SpoilerConstants
  • lama.version
  • A string representing the current API version.
  • lama.side
  • A table of constants used to represent the direction a turtle is facing.
  • lama.reason
  • A table of constants used to indicate failure reasons when trying to move.
State
  • lama.get() -> x, y, z, facing
  • Get the current position and facing of the turtle.
  • lama.getX() -> number
  • Get the current X position of the turtle.
  • lama.getZ() -> number
  • Get the current Y position of the turtle.
  • lama.getY() -> number
  • Get the current Z position of the turtle.
  • lama.getPosition() -> vector
  • Get the current position of the turtle as a vector.
  • lama.getFacing() -> lama.side
  • Get the current facing of the turtle.
  • lama.set(x, y, z, facing) -> x, y, z, facing
  • Set the current position and facing of the turtle.
Movement
  • lama.forward(tries, aggressive) -> boolean, lama.reason
  • Replacement for turtle.forward().
  • lama.back(tries) -> boolean, lama.reason
  • Replacement for turtle.back().
  • lama.up(tries, aggressive) -> boolean, lama.reason
  • Replacement for turtle.up().
  • lama.down(tries, aggressive) -> boolean, lama.reason
  • Replacement for turtle.down().
  • lama.moveto(x, y, z, facing, tries, aggressive) -> boolean, lama.reason
  • Makes the turtle move to the specified coordinates or waypoint. Will continue across reboots.
  • lama.navigate(path, tries, aggressive) -> boolean, lama.reason
  • Makes the turtle move along the specified path of coordinates and/or waypoints. Will continue across reboots.
The parameters tries and aggressive for the movement functions do the following: if tries is specified, the turtle will try as many times to remove any obstruction it runs into before failing. If aggressive is true in addition to that, the turtle will not only try to dig out blocks but also attack entities that stand in its way.

Regarding lama.navigate(), note that the facing of all non-terminal path nodes will be ignored to avoid unnecessary turning along the way.

Rotation
  • lama.turnRight() -> boolean
  • Replacement for turtle.turnRight().
  • lama.turnLeft() -> boolean
  • Replacement for turtle.turnRight().
  • lama.turnAround() -> boolean
  • Turns the turtle around.
  • lama.turn(towards) -> boolean
  • Turns the turtle to face in the specified direction.
Note that all turning functions behave like the original ones in that they return immediately if they fail (they can only fail if the VM's event queue is full). Otherwise they're guaranteed to complete the operation successfully. For lama.turn() and lama.turnAround() it is possible that one of two needed turn commands has already been issued, when failing. The internal state will represent that however, i.e. lama.getFacing() will still be correct.

Refueling
  • lama.refuel(count) -> boolean
  • Replacement for turtle.refuel().
This has to be called instead of turtle.refuel() to ensure the API's state validity, since it uses the fuel level to check if it's in an unexpected state after rebooting. It is is otherwise functionally equivalent to turtle.refuel().

Waypoints
In some cases it may be easier (and more readable) to send your turtles to predefined, named locations, instead of some set of coordinates. That's what waypoints are for. They can be manipulated like so:
  • lama.waypoint.add(name, x, y, z, facing) -> boolean
  • Adds a new waypoint or updates an existing one with the same name.
  • lama.waypoint.remove(name) -> boolean
  • Removes a waypoint from the list of known waypoints.
  • lama.waypoint.exists(name) -> boolean
  • Tests if a waypoint with the specified name exists.
  • lama.waypoint.get(name) -> x, y, z, facing
  • Returns the coordinates of the specified waypoint.
  • lama.waypoint.iter() -> function
  • Returns an iterator function over all known waypoints.
  • lama.waypoint.moveto(name, tries, aggressive) -> boolean, lama.reason
  • This is like lama.moveto() except that it takes a waypoint as the target.
Note that waypoints may have a facing associated with them, but don't have to. This means that if a waypoint has a facing and the turtle is ordered to move to it, it will rotate into that direction, if it does not the turtle will remain with the orientation in which it arrived at the waypoint.

Utility
  • lama.init()
  • Can be used to ensure the API has been initialized without any side-effects. If this is the first call and the API has to be initialized because of that, this will block until any pending moves are completed.
  • lama.startupResult() -> boolean, lama.reason
  • Can be used in resumable programs to check whether a move command that was issued just before the turtle was forcibly shut down completed successfully or not. You will need this if you make decisions based on the result of the movement's success (e.g. stop the program if the turtle fails to move).
  • lama.hijackTurtleAPI(restore)
  • Replaces the original movement functions in the turtle API with wrappers for this API. Note that the wrappers have the same signature and behavior as the original movement functions. For example, calling the wrapper turtle.forward(5) will not make the turtle dig through obstructions! This is to make sure existing programs will not behave differently after injecting the wrappers. The original functions can be restored by passing true as this functions parameter. Important: the changes to the turtle API will be global.

Additional files
Spoiler
  • lama-conf can be used to query the current position and facing (lama-conf get), as well as set it (lama-conf set x y z facing) e.g. for calibrating newly placed turtles. It can also be used to manage waypoints (lama-conf add name [x y z [facing]], lama-conf remove name and lama-conf list).
  • lama-example is a small example program, demonstrating how to use the API in a resumable program. It allows ordering the turtle to move along a path of waypoints.

Limitations
If the turtle is moved by some external force (player pickaxing it and placing it somewhere else, RP2 frames, …) the coordinates will obviously be wrong, because we have no way of tracking such influences (aside from GPS, perhaps - might look into that for roughly validating coordinates in some future version).

All multiblock movement will only perform straight moves, i.e. turtles will never try to evade obstacles, only break through them, if allowed. For now, I feel that pathfinding is beyond the scope of this API, so if you need it you'll have to build it on top of the API. The main reason I don't feel like this belongs in here is because it would quickly get out of hand, since you'd then have to keep track of fuel (because usage cannot be precomputed at the time the order is given) and possibly even map out the region as you go.

Closing remarks
As far as I can tell, this is the first API using the fuel workaround. I'm quite sure this is the only truly working solution out there for properly keeping track of a turtle's position across forced shut downs (aside from GPS, which can be inaccurate). Two common methods I saw I can invalidate right away:
  • Saving the state before and after turtle.forward() can fail because that call yields, and the turtle may be shut down during that yield, so you may never know whether it was successful or not.
  • Saving after turtle.native.forward() and after successfully waiting for the result may fail if the turtle is shut down while waiting, since, again you will never know whether the move was successful, because the turtle_response event will not be sent after the reboot, see my thread on this issue.
If you know of another method, I'd be intrigued to hear about it, though!

I have tested the robustness of the API using the following method:
Spoiler
  • Have the turtle move randomly and continually in a 4x4x4 cube (it'd pick a new target when reaching one).
  • Drop sand stacks into the turtle's path.
  • Stand in the turtle's way.
  • Have some bedrock in the cube.
  • Have a mob in the cube.
  • Quit the game over and over as well as resetting the turtle manually (Ctrl+R) to interrupt the program at different code locations, hopefully having hit each one at least once.
  • Run a big JAM quarry (160x160 blocks) and quit+resume the game repeatedly.

Still, this is software, and testing is a tricky business, so it's very possible for some interesting bugs to remain. If you come across any (and are sure it's not your fault) please let me know, thanks!

Changelog
Spoiler
  • Version 1.4c
    • Fixed lama.back().
  • Version 1.4b
    • Fixed potential infinite loop in path resolver for longest path first multiblock movement.
  • Version 1.4a
    • Improvements on turtles' awareness of each other. Previously turtles may have (with a very, very small chance) moved into and/or out of the way of other turtles in such a way that the blocked turtle may have wrongly diagnosed the reason for its movement failure. This should not happen anymore.
  • Version 1.4
    • Important: from now on you must use lama.refuel() instead of turtle.refuel().
    • Extended state validation to cases when the turtle isn't moving. This is achieved by also replacing turtle.refuel() and comparing the command ID we got from that to a newly generated one during initialization, where we'd expect a higher one. There's a slight chance for this to fail if a rollback only went back a couple of ticks. But if the game crashes so hard it can't save anymore it usually involves a lot more rollback.
    • When the API enters an invalid state (command ID indicating rollback or fuel level mismatch) it will now lock down and throw errors whenever any function other than lama.set() is called. This is to avoid turtles running amok when they don't know where they are. They'll just stay put until reinitialized by the player.
    • Added parameter to lama.moveto(), lama.navigate() and lama.waypoint.moveto() that can be used to tell the turtle to move along the short (default) or long axes first. For example: when going from (0, 0, 0) to (3, 1, 0) the first axis would be the long axis, the second the short one. This gives more control over which areas turtles will avoid when moving.
    • Went back to blocking when encountering invulnerable entities (sorry). This is to avoid having to use constructs like repeat until lama.moveto(x, y, z, f, math.huge, true, true –[[ longest axis first ]]) to cover players blocking turtles, and turtles changing paths in such cases.
  • Version 1.3
    • Important: Changed / introduced folder structure. The API is now in an apis folder and the programs (lama-conf) in a programs folder. This breaks the old installer on pastebin, get the new one if you plan on using it, please. You'll also have to either move the files or adjust your os.loadAPI paths. Sorry for the inconvenience.
    • Switched to lazy initialization. This means calling os.loadAPI("apis/lama") will no longer block due to the API finishing pending moves. Instead, the first call to any function in the API will trigger initialization and may block. A new function, lama.init() has been added specifically for this, but any function will trigger the same logic before doing its own thing. The intention is to allow other startup programs to run before continuing interruped movement.
    • Fixed broken math.huge serialization, which means resuming moves using an infinite number of tries didn't work. This was actually textutils.serialize/unserialize's fault, it writes inf and then reads that back as nil, because it's interpreted as a variable.
    • Fixed waypoints being deleted if some other part of the state was invalid.
    • Changed how indestructible blocks and invulnerable entities are handled. When one is encountered, the move will now fail immediately. This is because moves with an infinite number of tries would otherwise never return when hitting bedrock, for example.
    • Tested some more for robustness using my own mining program. It even survived two game crashes, so I feel this can safely be called stable now.
  • Version 1.2
    • Breaking Change: Added a setting useMinecraftCoordinates and it defaults to true. Set it back to false if you don't want to adjust your scripts. I totally forgot to check what kind of coordinate system Minecraft uses internally (i.e. what you see when you enable the debug screen with F3). So now the script uses one that's different. If this setting is true, it will make all API functions return and accept coordinates of Minecraft's coordinate system.
    • Internally the coordinate system used will always be the custom one, so you can upgrade and switch this setting on and off without breaking any state files.
    • Added setting startupPriority which allows setting the desired initialization priority of the API in multi-startup-script environments.
    • Added aliases lama.goto() for lama.moveto() and lama.waypoint.goto() for lama.waypoint.moveto(). Use at your own peril, since goto is a keyword in Lua 5.2, so in the case ComputerCraft ever updates its Lua implementation these will become unusable.
    • Added code to detect my startup API as alternative to Forairan's init-scripts.
    • Tightened up value validation here and there to avoid state corruption/weirdness (mostly: checking whether coordinates are integers).
  • Version 1.1
    • Added lama.moveto() function which allows issuing multiblock movement commands. The turtle will try to reach the specified coordinate by moving in straight lines; if you want smart navigation/pathfinding you'll have to use some other API on top of this one, or write it yourself, since I feel that's a bit beyond the scope of this API.
    • Added possibility to store waypoints (position plus facing). The related functions can be found in the lama.waypoint namespace.
    • Added lama.navigate() which allows issuing chained multiblock movement commands. It expects a table of coordinates or waypoints (can be mixed) and will try to move the turtle along the specified path. This will continue across turtle reboots.
    • Added functionality to lama-conf to manipulate waypoints.
    • Added more parameter type checking to avoid getting into an invalid state on bad input.
    • Changed the format of the state file by splitting it into several files, to reduce file i/o during moves. The API will automatically upgrade old state files it finds.
    • Fixed and improved validation of state files.
    • Fixed startup result being lost when the API was loaded a second time.
    • Lots of refactoring to make the code more readable and easier to maintain.
    • Switched to MIT license.

License
This API is licensed under the MIT License, which basically means you can do with it as you please.
airtonix #2
Posted 14 July 2013 - 07:33 PM
Sterling work, might I suggest that for someone with your level of organisation, that it would be great if you hosted the source code on either bitbucket or github.

then your pastebin reference can simply be a http.get wrapper for

https://raw.github.com/sangar/lama/master/blob/lama.lua

This way you get :

1. version control
2. branching
  1. master = release
  2. develop = latest unstable work
3. issue tracker
4. wiki pages
5. github pages (static cdn hosted sites)

Lastly, I think it'd great if you could assign shortcut names to positions and headings:



-- position ourselves in front of the sapling chest
lama.set(12,12,34, lama.side.north)
-- save current location as a label
lama.shortcut("saplingSupplyStation")

...

if app:getSaplingCount() < 1 then
  lama.goto("saplingSupplyStation")
end

Zudo #3
Posted 15 July 2013 - 03:49 AM
Wow…!
Sangar #4
Posted 16 July 2013 - 03:38 AM
Thanks!

Sterling work, might I suggest that for someone with your level of organisation, that it would be great if you hosted the source code on either bitbucket or github.

{snip}

Lastly, I think it'd great if you could assign shortcut names to positions and headings:

{snip}

Thanks! I wasn't sure whether I'd keep adding features or not, but now that I probably will, I'll put it on Github I guess.
The shortcuts are a sweet idea, I like it. I'll get working on it today or tomorrow. I wanted to add the example program as a lama.move function anyway, so that's a good usability extension to it.
acesoyster #5
Posted 17 July 2013 - 05:54 PM
Love it, was just about to write something like this as a part of a project I'm working on, but by chance checked the forums first.
Very nice indeed
Sangar #6
Posted 18 July 2013 - 09:24 AM
Glad it helps!

I've finished version 1.1 and thrown it up on Github. If I didn't miss anything in my testing it should upgrade keeping the state intact (i.e. you won't have to recalibrate any turtles already having the API installed). The main features are multiblock movement functionality (lama.moveto(), lama.waypoint.moveto() and lama.navigate()) as well as waypoints, as suggested by airtonix (lama.waypoint.* functions). There's also a couple of bug fixes in there, so I'd recommend updating even if you don't need the new features.

I'll update the first post when I have more time later. For now all up-to-date information can be found on the Github page. Done.
SierraNine #7
Posted 23 July 2013 - 05:01 PM
Great work! I have a gotcha, unfortunately…

Turtles do not require fuel to turn. Your method of accounting for actual movement vs saved state (ingenious!) can't detect a turn and a quit/chunk load colliding before state is written.

This is not a criticism, just an observation. I can offer no viable solution, The vulnerability, however slight, does exist.

Still way, way better than my (now obsolescent) method.

Thanks for your contribution to Trans-dimensional Turtle Domination!
Sangar #8
Posted 24 July 2013 - 04:49 AM
Thanks :)/>

And thanks for actually giving this some thought. Turns are, however, not an issue as far as I'm aware, because they are guaranteed to finish once you start them successfully. That is to say, they cannot fail by being "blocked" like a normal move can be (by blocks or entities being in the way) once they're queued. Unless they cannot be performed because the OS' event queue is full - in which case turle.native.turnLeft/turnRight functions return -1 right away (non-yielding) - they will always return true. And since the event queue is saved across chunk/world loads, we can be sure a turn will be properly performed once queued. So either way we can be sure to get the result we need to make the decision as to whether the command was successful or not without yielding, and therefore without the potential loss of information; unlike the move commands. Edit: to clarify, the fuel check is only used to see whether a move completed, it is not needed/used (or even applicable, as you pointed out) for turns.

Now, let us continue to welcome our new (old?) turtle overlords ;)/>
coaster3000 #9
Posted 24 July 2013 - 08:58 PM
Love your approach on a turtle api.

I was also wondering If I can reuse some of your api ideas. I am recreating I do not copy code.
Well more specifically.

hijackTurtleAPI function

I have to make my own version though since my api is meant to actually be a full copy to turtle.

Movement Failure Reasons System
- Also recreating but only because I want a challenge to make this myself :P/>


Whenever I ask people if I can recreate stuff. I Always Will credit them. Both name and links to threads or sites.

Also Reason why I am asking only about those 2 ideas. Is because I already made my api. I just want to add some stuff.

I always feel it is right to ask about using idea's that are already made. Even if someone is not copying code. That is why I ask. Even if licenses state I am allowed to use it. I Still like to ask.
Dlcruz129 #10
Posted 24 July 2013 - 09:00 PM
Great work!
Sangar #11
Posted 25 July 2013 - 05:01 AM
@coaster3000: I'm glad to hear that. Thanks for asking! I'm absolutely OK with that, go ahead and do great things :)/>

@Dlcruz129: thanks!

———-

Regarding update 1.2 I'd like to issue a quick statement. As mentioned in the changelog, there's a change as to how coordinates are interpreted by the API (this applies to functions taking or returning coordinates, such as lama.get(), lama.set() and lama.navigate()). Why? I forgot to check how Minecraft's coordinate system looks when I started out, and just went with what felt natural to me: I like to think of the "ground" as the first two axes, and "up" as the third. For reference, here is the difference in coordinate systems:
  • Internally (with useMinecraftCoordinates set to false, old behavior), x is forward, y is to the right and z is up. So it's a left-handed system.
  • When looking at Minecraft from that perspective, x goes to the right, y goes up, and z goes backwards. So it's a right-handed system.
Another difference is that Minecraft starts its facings with the south (i.e. south = 0, west = 1, …) whereas internally I start with the north (i.e. north = 0, east = 1, …)

Since I felt it would be weird to force my arbitrary coordinate system on people I decided it was worth the breaking change to set the default to use Minecraft coordinates. Sorry for the inconvenience! I'm pretty confident it won't happen again ;)/>
SierraNine #12
Posted 26 July 2013 - 03:32 PM
Thanks :)/>

And thanks for actually giving this some thought. Turns are, however, not an issue as far as I'm aware, because they are guaranteed to finish once you start them successfully. That is to say, they cannot fail by being "blocked" like a normal move can be (by blocks or entities being in the way) once they're queued. Unless they cannot be performed because the OS' event queue is full - in which case turle.native.turnLeft/turnRight functions return -1 right away (non-yielding) - they will always return true.

..snip..

Now, let us continue to welcome our new (old?) turtle overlords ;)/>

That's good to know. Thanks for the follow up!
jesusthekiller #13
Posted 28 July 2013 - 06:58 PM
I love the name! xD
Sangar #14
Posted 02 August 2013 - 06:57 AM
Glad to hear that ;)/>

——————–

I just released version 1.3. It brings a couple of fixes and an actual folder structure… please see the change log.

Also, what's with the forum auto-capitalizing thread titles? Makes abbreviations look somewhat… odd :(/>
River_Chief #15
Posted 02 August 2013 - 12:49 PM
Brilliant work! I started wading into this by first taking a look at your JAM. Everything seems to install fine then I select the quarry size, it "Writes initialization data to disk" and then I get a "jam773: out of space". My goal is learn from your quarry and then wrap my brain around your API. Any idea on the error?
Sangar #16
Posted 02 August 2013 - 03:26 PM
Thanks! I must warn you, JAM is very much work in progress right now, so it's not quite as stable as this API, yet :)/>
That error sounds like there's not enough space on the disk to write the files, which is pretty odd. Did you reduce the default disk space in the config or something?

Update: should be relatively stable now. I didn't do very extensive tests yet, but ran all configuration possibilities on a small scale - 3x3 holes - without problems. I also made the installer minify the downloaded sources in a very simplistic fashion, but it at least gets the files down to 50% of their original size. You may want to try re-downloading it with the new one to run it.

Also, this is getting kind of off-topic. I'll probably make a proper post for JAM soon-ish.
Edited on 02 August 2013 - 05:05 PM
Sangar #17
Posted 06 August 2013 - 09:08 AM
Bump for new version. See the change log for details. The largest update in version 1.4 is general state validation (not just while moving) by also providing a custom refueling function. This should allow the API to detect most rollbacks or other desynchronization of API state and real state, which will then cause it to lock down until reinitialized by the player. The main reason for this is to prevent turtles running around aimlessly, destroying stuff and whatnot if they get lost due to the state getting invalidated. As usual, upgrading should work without having to re-initialize any turtles that already have the API installed.
Ordinator #18
Posted 22 August 2013 - 07:28 AM
Absolutely fantastic solution!
Although there's a bit of a bug with the current checkin though. If you do nothing more than

os.loadAPI("apis/lama")
lama.back()

You'll get: "Peripheral 34: Expected string"

This is due to a missing
[private.direction.back] = "back"
on about line 940 of lama. It looks like it maybe need in a few other places like line 860 but I wouldn't conjecture.

Excelent tool though!
Sangar #19
Posted 22 August 2013 - 06:51 PM
Thanks for reporting this! Fixed in 1.4c.

I feel pretty bad for having a test script and not using it now. But who moves their turtles backwards, anyway!? ;)/>
Firnagzen #20
Posted 23 August 2013 - 11:00 PM
Hi, and thanks for this API! But I have a question: Would I be right in assuming that if I want to use Forairan's startup script, I would save my script as 01_whatever, so as to leave room for lama's startup script? (I would use your startup API, but I am not a programmer [just someone who knows how to program], and your documentation for it is a bit dense.)

EDIT: Additionally, I tried out JAM. When launched, the turtle turned left, demolished the dump chest, and then dug a hole to bedrock. I'm reasonably sure that shouldn't have happened. When I launched a second turtle, it turned right, demolished the torch/ignored items chest, and then went on a loop around the docking station before digging a hole to bedrock. And lastly, both turtles went down to bedrock and stayed there, repeating 'undiggable block error' or something similar. Um?
Sangar #21
Posted 24 August 2013 - 05:52 PM
Regarding startup script order, that's kind of up to you. The only reason LAMA isn't at 00_ per default is to allow scripts that do background stuff to start before it does (for example if you have a daemon script and run a daemon that sends the turtle's position via WLAN occasionally). Your program will just block until LAMA is initialized if it runs before LAMA's startup script (the API will automatically initialize itself the first time any function to it is called - besides set()).
So in short: if you don't know it probably doesn't matter.

As for JAM: that's totally intended, of course. Not. But: I have not continued working on it after I ran into a bug where CC deadlocks if a turtle moves next to a disk drive. Because of this JAM is practically unusable at the moment, since CC may just lock up your game at random. So I can't really recommend using it as it stands, anyway. If that CC bug ever gets fixed I might look into the issue you described. Until then I don't really see the point, sorry ;)/>
Firnagzen #22
Posted 24 August 2013 - 07:40 PM
I see. So the multi-startup script is just there so that you can 'sideline' the actual startup behaviour.

And thanks for the info on JAM, I don't suppose you could edit the readme to note that it shouldn't be used?

EDIT: I suppose you've considered using a computer with an attached disk drive in place of just a disk drive? (I mean using the computer to activate the turtle, instead of the drive.)
Sangar #23
Posted 24 August 2013 - 11:28 PM
Yeah, I probably should add a note somewhere… I just didn't really expect people to actually use it.

Using a computer instead of a disk drive won't work. What's stored on the disk drive right now is the global state of the quarry: which jobs were already taken. So without that the turtles wouldn't know where to go. And no, I don't intend to fiddle around with some Data-via-Redstone-API to have the turtles store that info on a computer instead. And wireless is just too expensive to make it a requirement.
Firnagzen #24
Posted 25 August 2013 - 02:13 AM
Eh, fair enough.
Ordinator #25
Posted 25 August 2013 - 03:33 AM
Thanks again for the cool Api I did find something that would be very handy:

It would be nice if there were a way to call the lama api and have it gracefully shut down any buffered move/navigate commands it has pending.
I say this because I was building a rather complicated turtle and accidentally sent it very far away with no good way of stopping it. Even destroying it and putting it back down, it just resumes its journey of course.

I was going write a script that listens for wifi signal from another computer and then deletes the .lama-path-state file and restarts the turtle but it would be much less kludgey if my wifi listener function could just call some lama api to shut down nicely.

Just an idea.
Sangar #26
Posted 25 August 2013 - 12:04 PM
Do you mean when the turtle is already running, or when starting it up?
For the first, you can either use the helper program lama-conf set … or call lama.set(…), which will completely reset the API's state (and lama.set() never triggers initialization).
For the second, yeah, I've been thinking about adding some kind of timeout in the initialization to allow aborting when the user presses a key or something. I'd probably add that to the startup script, so that the API itself never prints to the term.

Edit: I'm an idiot, for some reason I skipped the second paragraph. Interrupt it while moving? Hmmm… I'll have to think about that. We'll see.
Ordinator #27
Posted 26 August 2013 - 04:47 AM
Yes, interrupt a navigate() or moveto() that is still being executed. Probably not too simple to do cleanly and certainly not a sexy task. But handy and potentially pretty powerful.

I really think you've designed the startup behavior wonderfully as it is, silently and immediately resuming movement is very, very elegant. Adding a timeout before resume-ing a move might easily add timing issues with dependant programs, eg I may be assuming two neighboring turrles are working at the same speed or I may only wait so long for a wifi signal from this turtle. If you do go this route please, please add a way to turn it off too.
Anyway, just an idea.
McLeopold #28
Posted 05 September 2013 - 11:58 AM
For the second, yeah, I've been thinking about adding some kind of timeout in the initialization to allow aborting when the user presses a key or something. I'd probably add that to the startup script, so that the API itself never prints to the term.

I've added the same timeout to my resumeable scripts as well. I also had the thought that if the inventory of the turtle was blank or different when resuming, assume the turtle was broken and replaced and to abort the resume feature. Maybe even just do the timeout if it has a blank inventory.
michthom #29
Posted 31 December 2013 - 11:34 AM
Hi Sangar, thanks for the work so far - I just stumbled on LAMA while trying in vain to reimplement something similar.

In case it helps anyone else, I stumbled when trying to include LAMA in a resource pack e.g. to distribute with the programs that will require it: I foolishly copied the 'lama' minified version file into:

minecraft/resourcepacks/ResPackName/assets/computercraft/lua/rom/apis/lama

However when I tried that all I got was blank-screened turtles, that I was unable to restart with CTRL-R.
The approach that worked was to copy the lama-src version into that same location but renamed as just 'lama'.

Hmm. More complex than it first seemed, I'm struggling to get this to work consistently from within a resource pack, even with your 'bapil' API installed to get the path resolution.

Any advice/ideas?

Cheers
Mike
Edited on 31 December 2013 - 02:48 PM
michthom #30
Posted 13 January 2014 - 05:36 PM
Thanks to Sangar for responding off the forum with the issue, and to those on the CC IRC channel, particularly AmandaC.
Between us we found that some of the environment checks in the API needed to be moved, and Sangar has now incorporated the changes in the GitHub repository, here:
https://github.com/fnuecke/lama

So if you want to distribute a program that requires LAMA as an API, you can now simply create a folder structure like this:

[Your-Minecraft-Folder]:
resourcepacks:
[Your-Resource-Pack-Name]:
assets:
computercraft:
lua:
rom:
apis:
turtle:
lama
help:
[Your-Program-Name]
programs:
[Your-Program-Name]
pack.mcmeta
pack.png

And once you're done testing, zip up the files under [Your-Resource-Pack-Name] (e.g. NOT including that directory/folder in the zip) and distribute that zip file for others to put in their resourcepacks folder, unmolested.
joebodo #31
Posted 16 January 2014 - 08:08 AM
Here's some code that I use for turtles that need GPS coordinates. I find it useful for the turtles running around my base that need to know where the refuel or drop off station is located. I removed all the error checking to help with readability.

Hopefully you find this helpful (and add GPS support :)/> )


function enableGPS()
  local ploc = _getGPS()
  if not ploc then
	return
  end
  -- store the offset for later use
  loc.gxOff = ploc.x
  loc.gyOff = ploc.y
  loc.gzOff = ploc.z
  while turtle.detect() do
	turtle.turnRight()
  end
  -- get second position in order to determine heading
  turtle.forward()
  local nloc = _getGPS()
  turtle.back()
  -- orient to east (alternatively, you could store the heading offset - but you will have to rotate the coordinates accordingly)
  if nloc.x < ploc.x then
	turtle.turnRight()
	turtle.turnRight()
  elseif nloc.y < ploc.y then
	turtle.turnRight()
  elseif nloc.y > ploc.y then
	turtle.turnLeft()
  end
  return ploc
end

function _getGPS()
  local c = {}
  c.x, c.z, c.y = gps.locate(10)
  if c.x then
	return c
  end
end

-- if going to coordinates that are absolute, then just adjust the relative coordinates
function gotoLocation(nloc)
  if nloc.gps then
	return goto(
	  nloc.x - loc.gxOff,
	  nloc.y - loc.gyOff,
	  nloc.z - loc.gzOff,
	  nloc.dir)
  else
	return goto(nloc.x, nloc.y, nloc.z, nloc.dir)
  end
end

BTW here's a good forum post on setting up the GPS hosts:
http://www.computerc...osition-system/
Lyqyd #32
Posted 16 January 2014 - 10:20 AM
That is not a good GPS tutorial. It swaps around the Y and Z axes for no good reason, which will completely foul things up if you aren't paying attention.
joebodo #33
Posted 16 January 2014 - 09:39 PM
That is not a good GPS tutorial. It swaps around the Y and Z axes for no good reason, which will completely foul things up if you aren't paying attention.

Y and Z are swapped as this is the normal method for using a coordinate system (outside of minecraft).

In analytic geometry, unknown or generic coordinates are often denoted by the letters x and y on the plane, and x, y, and z in
three-dimensional space.
http://en.wikipedia.org/wiki/Cartesian_coordinate_system

Having used the normal coordinate system for just about forever, I didn't realize it would be confusing (If i post more code, I'll either make it clear it's swapped or adjust it to minecraft's preference).

I provided this to hopefully give the OP some ideas - it is not provided as a tutorial (not sure how you came to that conclusion).
Lyqyd #34
Posted 16 January 2014 - 10:11 PM
The post is in the Tutorials section of the forums. In ballistics, +y is up.
Oose #35
Posted 20 January 2014 - 06:19 AM
This is a really well made API. I had never thought of using fuel to check if a turtle had completed a move or not. Lots of practical applications, thanks for making this.
civilwargeeky #36
Posted 22 January 2014 - 10:39 PM
Wow. I'm sorry to say I won't be using your api at this time, but thank you so much for all the research on turtle movements and persistence. All of this information will be really helpful to improve my quarry's session persistence. I would have never considered to use the turtle fuel as an indicator as to whether or not the turtle moved! That is really a novel idea that I think more people should know about.
Manadar #37
Posted 03 February 2014 - 01:55 PM
Thanks for this API. The waypoint system is very pleasant to work with.

I'm having a whole range of issues with using this API and I'm not sure if it's the server or the mod installations, or if others are having similar issues.

For several times now, I've had some turtles dead-lock themselves after a fresh installation. I would go ahead and run lama-installer, run my simple script (just lama.init, lama.set) and the turtle would ask me to "Invalid state. Please reinitialize the turtle's position." repeatedly. This often goes hand in hand with "Cannot set position while moving or refueling." when I would start my program for the first time, before performing any moves whatsoever. Removing the label from the turtle, taking and replacing the turtle, then doing a reinstall does not solve this.

When I attempted to investigate the issue further, I found additional errors such as when indexing nil in lama:712, and one other instance where nil was being indexed around line 400. But since the files are minified, it was hard to track the bug to the responsible line of code in GitHub. Sorry I could not be of further use here.

Finally, I'm not sure if this is intended behavior, when I would abrupt a running program abnormally, either via Ctrl+T or with a pickaxe, the turtle would merrily continue on its old path. If this is intended behavior, it would be nice if there was a way to stop this unwanted behavior in some way.
LayZee #38
Posted 22 June 2014 - 09:51 PM
Hi,

it seems that Lama does not work in ComputerCraft v1.63. Calling
lama.init
,
lama.set
, and
lama.forward
never yields.

Has anyone else experienced this problem?
sjkeegs #39
Posted 02 July 2014 - 03:41 AM
it seems that Lama does not work in ComputerCraft v1.63.
There is a lot of code in there that has not been updated for CC1.6. I'm not surprised that it's not working.