Mods/basic robot/Turtle-Specs

From Minetest Wiki
Jump to: navigation, search

Contents

Design of a mini-language / minimal instruction-set for a turtlebot

based on basic_robots.

The goal is to teach programming to children, using turtle-like programmable robots in minetest.


We have turtleminer, with ambitious plans, but still in early development.

One big item on that todo-list is a visual code-editor, like blockly or scratch.

We have basic-robots, that are working, really powerful, and can do almost everything.

They are programmable in lua, using an in-game texteditor.

basic-robots should be 'more than good enough' to teach programming in general,
but (for kids) the presentation may need some tweaks.

It would be nice to have something like ComputerCraftEdu
with a visual-editor like blockly or scratch for minetest,
but implementing that would be a lot of work.


Maybe we can come up with smaller, simpler 'programming language'
that is more easy to incorporate into the basic-robot
that is still useful for an introduction to programming.

Concept of Turtle-commands

Turtles use commands like move-forward, move-up, turn-right, dig-forward.

These commands can be represented in different ways,
eg. as text, code, numbers, symbols, graphics/icons, etc..

Graphic symbols look nice, but a system like blockly or scratch would need a lot of them ...

For a limited number of simple actions this is easy,
but gets much more complicated if you want to express variables,
calculations, control-structures (if-then-else, for-loops) etc.)

There is a point where it becomes simpler to just write code, eg. for lua, in a texteditor.

Turtle-Programs

Some examples of existing programs that use basic_robots with turtle-commands:

Note1: all of these programs have a different instruction-set,
and no 'advanced features', like variables, calculation, or conditional execution.

But I remember that rnd once made such an advanced turtle...

Note2: all of the above example-program have the instructions of their turtle-scipt hardcoded.
But it would be possible to change that script on the fly, eg. from a book, with a remote-control,
by chat or via mail from another robot.

Idea

To minimize the work, we design a mini-language, a minimal instruction-set for a turtlebot,
that still introduces some basic concepts of programming.

I want to keep the number of instructions down (say 10-20),
as well as avoiding composite and variable-length instructions.


If the basics have been learned, move straight to 'real' coding, with lua and texteditor.

Requirements

  • what kind of programs do we want to 'write' with that language ?
as in, what instructions, how many steps/statements in a program
  • Other required features (as in variables / fuel, input/output, flowcontrol***...) ?
  • (usecase-examples please: task, environment/terrain, program that solves the task)
  • When do we want/need it to be usable ?

For example, I would like to use those robots to do simple tasks such as

Simple tasks

  • move the robot around
need instructions: move-forward, move-up, move-down, turn-right, turn-left
optional: move-backward, move-right, move-left
    • press a button, activate = open/close a door
more instructions: activate-forward
maybe other direcions too
  • dig a straight tunnel, size 1x2 (width 1, heigth 2)
more instructions: dig-forward
  • dig bigger tunnels, eg. 1x3, 2x2, 3x3
more instructions: dig-up, dig-down
  • dig stairs up, dig stairs down
nice-to-have, but optional: dig-forward-down and dig-forward-up
  • dig a room, eg. 5x5
  • stop after x operations
needs a counter (a variable), and operations for setting, counting up/down, checking
or some kind of 'fuel' that is used up by each operation
that means counting, checking and stopping is done internally
  • moving, and react to obstacles (eg. turn when hitting a wall)
check for success, conditional execution / jump / exceptions ...
might also need block-start / block-end, or labels / markers

Also, it would be nice to have the instructions of several of those 'programs' available at the same time.
Eg. ability to select different starting-points within a program,
or several remote-controls with different programs.


More complicated tasks

  • build a wall
needs an inventory for at least 1 type of material
needs instructions: build-forward
maybe build-backwards, or switch building on/off (for building a 'trail')
like pen-up / pen-down of a logo-turtle
optional: build-up, build-down
  • build stairs up
  • build stairs down
  • build a bridge
basic-robots can only move one space above ground,
so moving to the position for building a block might be a problem
maybe needs instructions: build-forward-down, build-forward-up
  • build a house
needs bigger inventory (different materials for floor, walls etc.),
and a command to select
  • look for ore
needs an instruction for looking at nodes
and then do what ?
output a message ...
  • plant & harvest wheat, flowers, trees
  • goal-seeking/homing: use find_nodes() to find an item, eg. a flower
this needs 2 real numbers (current- and old value), and a compare-instruction for them

These might be already too complicated for our 'simple' design.

More ideas:

  • Subroutines

TurtleBot using inventory as code-editor

For example, it might be fairly easy to implement the 'turtle-instructions' move-Forward,Backward,Up,Down,turn-Left,turn-Right, Dig-forward, Activate-forward (that makes a 'palette' of 8 instructions**, to fill the hotbar) with programs of upto 30 steps, using the inventory of the robot (That leaves 2 inventory-slots free for digging stone and ore).

Simple, as in 1 block = 1 instruction - but it means no i/o, no flowcontrol, no vars, no extras.

(**) The exact set of instruction can be discussed/modified somewhat: Eg. we could do without turn-Right (just do 3* turn-Left instead), or without move-Backward (do right-right-forward-right-right instead). Also, we might want to add a check-instruction (eg. 'if ok then...'), and perhaps one or more types of marker (start-, stop-marker). The robot consuming 'fuel' would be much like having a stop-marker.

(***) even without instructions for flowcontrol, at least we need to define the behaviour

  • when encountering an empty slot / an invalid instruction (such as dirt, stone etc.)
  • when reaching the last inventory-slot
  • when an instruction fails (eg. moving against a wall, diggging air, ...)

Possible behaviour:

  • indicate success/error (eg. with message, label, sound-effect...)
  • ignore / treat as success / treat as failure
  • stop program
  • continue with next instruction
  • continue with first instruction

If we add markers to our instructionset, we get some more options, eg. 'continue at next start-marker'.

For that, we 'just' need some blocks that represent those instructions/actions. Without making nice new graphics, we could use the existing keyboard-blocks for that. (see chars.png in the texture-directory of basic_robots)

Give the kids a chest full of such blocks, and let them place these blocks into the robots inventory, as a turtle-script, and we can think of a way to start the robot so that it would interpret the contents of its inventory as a script. (Eg. a special start-button, a special id, a special new command, look at the inventory for fuel or a start-marker...)

Do you have some suitable graphics to use as textures for such blocks ?

As an alternative idea: using a special remotecontrol as the visual-editor for the turtle-script (but that would need much more programming, formspec-design, rc-design, etc.).

A 'turtlebot' that works pretty much like that (but with its program represented as a text-script) is already on TechWelt - see the Robot_#18

Turtle-Commands

Instruction-set

Symbol Letter Description Code
Arrow right Arrow right move-Forward ok=move.forward()
f f
u Arrow up move-Up
u u
d Arrow down move-Down
d d
l l move-Left (optional)
r r move-Right (optional)
< < turn-Left turn.left()
> > turn-Right turn.right()
+/- +/- activate-Forward ok=activate.forward(1)
a a
Triangle-right - dig-Forward ok=dig.forward()
- -
Triangle up Triangle-up dig-Up
~ ~
Triangle down Triangle-down dig-Down
v v
1 1 select slot 1 mat=check_inventory.self(...,1); mat=...
2 2 select slot 2
3 3 select slot 3
.. .. etc. ..
7 7 select slot 7 mat="air"
8 8 select slot 8 mat="farming:wheat_8"
+ + build-Forward ok=place.forward(mat)
^ ^ build-Up
. . build-Down
_ _ build-Forward_Down (optional)
& & build-Backward on/off
green 0 marker-Start / marker-next
0
red 9 marker-Stop
9 9
yellow p marker-Pause
p p pause / pickup
.!. .!. pause / pickup
?  ? check if ok then continue-with-next-marker
n n look for node s=read_node.forward()
t t look for text s=read_text.forward(); ok=...
!  ! output string say(s)
= = compare string if s~=mat then continue-with-next-marker
# # (reserved) counter
, , (reserved)
:  : (reserved) define label
;  ; (reserved) marker-next
~~ ~~ (reserved) compare string2 ??
$ $ (reserved) compare real
%  % (reserved) counter#2 / random
° ° (reserved) look / find_nodes()
@ @ (reserved) reset
A A (reserved) Subroutines
.. .. etc. ..
Z Z (reserved)
( ( block-Start / Subroutine-Start / :
) ) block-End / Subroutine-End / ;

See also Alphabeth-blocks

Rules

Variant1

Basics
  • There is a set of available instructions ('turtle-commands'), see above.
  • There is a script with a sequence of turtle-commands
    • This script can be represented as a string, or by items in the inventory
  • Each turtle-command is represented by one character.
eg. 'f' stands for 'move-Forward'
  • If the script-string is empty, the inventory is used as the source for the script,
  • where the item in each slot represent one turtle-command (or building-materialsm etc.)
eg. the block 'arrow-right' means 'move-Forward' - same as 'f' when expressed as string.
  • There is a 'pause' variable. While true, execution of the script stops.
  • At the start, pause is set to false.
This can be changed with a remotecontrol
  • There is a variable 'mat', that contains the name of the current building-material.
  • At the start, mat is set to an empty string.
maybe start with 'dirt', or contents of slot 1 ?
  • mat can be set with the instructions 1,2, ... 8 to the name of the material in slots 1 .. 8.
the item-count of the material is removed
Some slots might be reserved for fixed strings, such as "farming:wheat_8" or "air"

Note: this might allow some tricks, eg. building with instruction-blocks / selfmodifying code

I'm not sure if/why we should restrict this
(eg. start script at position 9 would waste 1/4 script-length)
  • There is a variable 's', that is used as a temp. string, eg. for read_node().
  • At the start, s is set to an empty string.
maybe set it to the name of the robot, or the version-number,
or some status, eg. "robot1, fuel=99" ?
  • There is an instruction-pointer 'ip' that keeps track of the current instruction
i.e. the instruction-pointer starts at position 1.
  • Every script starts at the begin.
  • Every second, one instruction is executed
maybe only count actions like moving, digging, building ?
  • and the instruction-pointer advances one step
  • If the ip reaches the end of the script, it continues at the start.
This repeats until fuel runs out, or an end-instruction is reached.
  • Invalid instructions are ignored
such as blanks / empty slots, fuel, building-materials etc.
  • The turtle-interpreter scans forward until a valid instruction is found,
  • or the same position is reached again
eg. if the script is complete garbage, or empty, etc.
 ? errormessage / failure-sound ??
  •  ? instruction for pickup() -- p is already used for pause
also what range -- maybe first pickup(4), second pickup(8) ?
Fuel
  • A Turtle needs 'fuel' to run,
eg. leaves (coal would be too valuable - think of mining coal with a coal-burning turtle :)
maybe different types of fuel, eg. leaves for moving, wood or sticks for digging
maybe create a new fuel-item, with stacklimit > 99
  • Each step consumes 1 unit of fuel
this stops endless loops, and allows precise stopping of the turtle
maybe only have 'actions' (move,dig,build) consume fuel, not 'steps'
so internal processing would be free (look/read_node, check, output...)
  • Check for fuel is done before/after ...
  • If fuel runs out, the turtle goes into pause-mode
so the player can refill, and unpause with a remote-control
  • maybe require that fuel is put into a certain slot, eg. the last slot ?
How to represent fuel when using a script from a string ?
Conditionals
  • There is a global 'ok' variable that keeps track of the result of each operation, eg.
ok=move.forward()
Some instructions cannot fail, e.g. turning.
  • The check-instruction tests this variable, and can skip forward to the next marker.
Eg. this lua-code:
ok=move.forward()
if not ok then turn.left() end
could be expressed as turtle-instructions
f?<0
or, using instruction-blocks in the inventory:
Arrow right ? < green
where 0 is the next (green) marker, and '<' is executed when move-Forward failed
Strings
  • The instructions "n" does s=read_node.forward()
  • The instructions "t" does s=read_text.forward(); ok=...
and also sets 'ok' if some text was found
so we can at least identify objects with text (sign, chest, door, furnace...) even without string-compare
  • The instruction "=" compares s with mat, and (on mismatch) can skip forward to the next marker.

Eg. this little harvester

if read_node.forward() == "farming:wheat_8" then dig.forward() end
if read_node.forward() == "air"             then place.forward("farming:seed_wheat") end
move.forward()

Could be expressed as

8n=-0 7n=1+0 f
or, as instruction-blocks in the inventory:
8 n = - green 7 n = 1 + green Arrow right

where slot 8 has "farming:wheat_8", slot 7 has "air", slot 1 has "farming:wheat", and 0 is a (green) marker.

slot 1 needs to be setup by the user, slot 7 & 8 are fixed strings built into the turtle-interpreter.

Note: in this harvester-example, we cannot check for soil, because we have no turtle-instructions for 'read_node.down()' or 'read_node.forward_down()'

Also, 'farming:soil' would need an additional special string
  •  ? store / recall strings ?
  •  ? random ?
Variables

It would be nice to have variables and arithmetic, but with a small instruction-set,
and very little room (<30) for scripts, it seems not practical.

Eg. it would need instructions to set a value, add, substract, check, specify which var,
and represent values.

A simpler type of variable are flags and counters.

  • flag (aka boolean) - true and false (such as our internal 'ok'-variable)
  • counter with a specific max-value. Only needs an instruction 'decrement&test-for-zero'.
after reaching 0, the counter is restored to its max-value.
with a max-value of 1, a counter works just like a flag
  • to reset it, just repeat reading, until it reaches zero
Counter

The turtle only gets two counters (using the instructions # and %),
the max-value is specified by their stackcount in the inventory.

That means the max-value must be 1..99

To represent this when using a script from a string,
we can extend the script-string, eg. append ";#=5 %=3 fuel=99"

  • The instruction "#" decrements the current value of counter1 , and sets the ok-value:
    • ok=true: success means the value of the counter was > 0, anc could be decremented
    • ok=fail: value was = 0, and is now set to its max-value again
  • The instruction "%" works likewise on counter2

Such counters are also useful to keep trace of some state-of-processing.

Real

There is a specific usage for real numbers I would like to include with turtles:
finding the distance to something via find_nodes(), compare old & new distance-value,
with the goal of moving closer to it.

Eg. finding flowers on a plain of grass, without visiting each square.

That would need a special instruction like 'compare & store-when-less',
and a way to clear the old value, for the next search.

Maybe reset when find_nodes() returns nil, meaning 'no such node in range' ?
Subroutines

This is optional, but really nice-to-have:

  • Uppercase letters are reserved as names for subroutines
  • To define a subroutines:
A(-~f)
dig-Forward, dig-Up, move-Forward
  • To call a subroutines:
A
If an uppercase letter is followed by '(', the body of the subroutine followes, ended by ')'.
Otherwise, the interpreter tries to find & execute that subroutine
  • If not found, the program stops
 ? errormessage ?
  • The call-stack is only 1 level deep, so calls from a subroutine, and recursion are not allowed (yet).
  • If a '(' is encountered outside of a subroutine-definition, the interpreter ignores all following instructions upto the next ')'
So, (..) also serves as a block-comment.

...

Links

Forum:

Resources: