Mods/basic robot/tutorial

From Minetest


Tutorial 1

Index of robots-tutorial - sign at wall, spawner with code on ground.

There is a 'live' tutorial-parcour about programming rnd's basic_robots
at his ROBOTS-server, 46.150.38.198:30000.
It can be reached via teleporter near the spawn.

How to reach the tutorial

  • At login, solve the math-quiz to get teleported out of the spawn-building
it might take up to 10 seconds for the dialog to pop up
  • look for the teleporter - it has 2 big oranges on top, and a big black button at the floor
  • stand on that button, and punch it

Layout of the tutorial-area

  • big test-area
  • tutorials (0..9, plus some more)
  • Wall
    • automatic door to next area
    • robots with example-programs, and signs at base of wall
  • "Lobby" with teleporter

Operation Basics

Short summary about the operation of basic_robots:

  • There is a spawner ("cpu"), that has to be put on the ground somewhere.
This means that players cannot activate their own robots in areas protected by other players.
The spawner acts as a kind of basestation.
Robots can only move a certain distance from it.
  • Rightclick the spawner to access a form with the code, the inventory and the library
the inventory has 4*8 slots, same size as a chest, or the player's inventory.
the library has 16 slots, same as a bookshelf
  • When pressing the "start"-button, the spawner creates a robot ("worker") on the space above it
Each spawner can only control one robot at a time.
    • With no code, the robot can be steered with a remote-control
    • otherwise, the robot executes the code from the form
  • The "Stop"-button stops the program execution, and the robot disappears.
  • The code is running in a sandbox, and is called once every second.

In the following chapters,, we present some of those programs, that have been written by rnd and users at his server.

Service Programs

'Service' means, programs that run in place on the robot/spawner, and (maybe) provide some service.

In this tutorial-parcour at the robots-server, the robots are started with a button-push
on the big black keypads over the spawner.

The keypad is set to send a 2=ON to the spawner for starting the program.

The keypads are part of the mod basic_machines.

Hello World

To tell the robot what to do, write commands into his code-area.
Rightclick the robot-spawner to see the code.

 -- This simple program makes the robot 'talk', as in 'write text to the chat'.
 say("Hello! I'm a robot.")
 say("A random number: " .. math.random() )
 self.remove()   -- stop

These commands would be repeated every second,
but "self.remove()" removes the robot, and thus ends the program.

(Not much 'service' in this program, but it runs 'in place' :)

Chest-Access

basic_robot-Tutorial - Chest-Access

With "insert" and "take", robots can put stuff into chests and other containers,
as well as take items out.

This example has a chest, one robot on the left, another on the right,
and one keypad for each robot.

The first robot places 2 apples into the chest on its left:

 insert.left("default:apple 2")
 --say("Done: insert")
 self.remove()

The other robot takes 1 apple from the chest on its right:

 take.right("default:apple")
 --say("Done: take")
 self.remove()

Note: there are no checks for errors, e.g.

  • if there are enough apples in the inventory,
  • if there is a chest with enough room next to the robot,
  • if the chest can be accessed (it might belong to some other player),
  • if the action failed for some other reason,

etc.

Catching all those possible errors (and dealing with them) can make 'simple programs' quite complicated.

Math quiz1

The robot generates a math-question (like "WHAT IS 13*19 ?"), and listens to the chat.
Players answer via chat, and the robot will announce "Correct" or "Wrong".

 -- MATH QUIZ by rnd
 -- QUIZ: asks math question
 if not state then
   state=1;
   a=0; b=0; question = "";
   function generate_question()
 	a = math.random(12)+3;
 	b = math.random(12)+3;
 	question = "WHAT IS " .. a .."*".. b .. " ? ";
 	say(question)
   end
   generate_question()
 end
 self.listen(1)

 speaker, msg = self.listen_msg()
 msg = tonumber(msg)
 if msg then

   if msg == a*b then
   	say(speaker .. " ANSWERED CORRECTLY! ")
 	generate_question()
   else
 	say("WRONG! " .. question)
   end
 
 end
 turn.left()

Note: it doesn't keep track of who answered, doesn't keep score, and there is only one form of quiz (i.e. a*b).

Math quiz2

The robot generates a math-question (like "WHAT IS 13*19 ?"), and listens to the chat.
Players answer via chat, and if the correct answer comes up,
the robot fills a chest on top of the robot with some items as a reward for that player.

 -- math quiz robot: answer correct and take reward from chest
 -- QUIZ: asks math question
 if not state then 
   state = 1;
   a=0;b=0; question = "";
   function generate_question()
	a = math.random(12)+10;
	b = math.random(12)+10;
	question = "WHAT IS " .. a .."*".. b .. " ? ";
	say(question)
   end
   generate_question()
   self.listen(1)
 end

 speaker, msg = self.listen_msg()
 msg = tonumber(msg)
 if msg then 
   if msg == a*b then
	say(speaker .. " ANSWERED CORRECTLY!  You get reward in chest")
	insert.up("default:apple")
	insert.up("default:pine_tree")
	generate_question()
   else
	say("WRONG! " .. question)
   end
 end
 turn.left()

(Note: there is no check which player takes the price from the chest :)
Also, there is no check if the robot still has items in his inventory to give as reward.

Smelter Robot

basic_robot - Smelter-robot, fills furnace

This robot moves ore to be smelted from the chest at the left into the furnace at its top.
The lumps of coal come from the robot's inventory.

 --smelter robot: put cobble in chest and it will be smelted to stone in the furnace
 insert.up("default:coal_lump","fuel")
 if take.left("default:cobble") then
   insert.up("default:cobble","src")
 end

The keypad to start the robot with a button-push comes from the mod basic_machines.
The furnace starts operating as soon as it has both fuel and ore.

Mobile Programs

'Mobile' means, programs for robots that move around, dig, build, etc.

Simple movement1

This robot will move forward, until blocked, e.g. by a wall, cliff, or some other obstacle.

 move.forward()

This command will be repeated every second.

Simple movement2

You can make robots move in all directions and turn around.
The robot can't fly, but it can move up one block above the ground.

 move.forward()
 move.up()

Climbing upstairs.

Simple movement3

Now, we also check for success of the movement.

 -- Using the "if" sentence you can check when robot can't walk anymore
 self.spam(1)
 if move.forward() then
   say("walking ..")
 else
   say("I hit obstacle. removing robot"); self.remove()
 end

The command "move.forward()" is actually a function,
that returns true or false as a result,
meaning the move was successful or not.

So, the if-statement checks if moving forward failed, and if that happens, ends the program.

Explorer1

Moving forward as above, but when moving fails, the robot will turn 90° to the left.

 -- A very simple robot: it will turn left when it can't go forward anymore.
 if not move.forward() then
   turn.left()
 end

So, the if-statement checks if moving forward failed, and turns left instead.

Explorer1.1

Simple moves as above, but detects air on the right, to trigger a new turn.

 -- Follow the right wall
 if read_node.right()=="air" then
   turn.right()
 end
 if not move.forward() then
   turn.left()
 end

This is essentially a maze-runner, with the strategy "follow the right wall".

Explorer2

 --EXPLORER by rnd
 if not move.forward() then
	say ("i see " .. read_node.forward())
	if math.random(2)==1 then
		turn.left()
	else
		turn.right()
	end
 end

Moves forward until it hits an obstacle (and reports it),
then randomly turns left or right.

Explorer3

 -- ADVANCED EXPLORER, can climb stairs
 node = read_node.down()
 if node == "air" then
	move.down()
 else -- walk around
 
	if read_node.forward()~="air" then
		move.up()
	end
	
	if not move.forward() then
		if math.random(2)==1 then
			turn.left()
		else
			turn.right()
		end
	end
 end

...

Road-Tracker

There is a cobble-road at the tutorial-parcour, with turns, crossings, deadends etc.
and his program moves along this road.

 -- FOLLOW COBBLE ROAD by rnd
 --tracks road

 --run then tracker.step()
 if not tracker then
	tracker = {};
	tracker.road = "default:cobble";

	tracker.step = function()
		if read_node.forward_down() == tracker.road then
			if not move.forward() then turn.angle(180) end
		else
			turn.left();
			if read_node.forward_down() ~= tracker.road then
				turn.right(); turn.right();
				if read_node.forward_down() ~= tracker.road then
					turn.right() 
				end
			end
		end
	end
 end
 
 tracker.step()

...

Surveyor

There is an area at the robot-tutorial paved with glass-blocks.
This robot walks the outer edge of that area and measures the area size.

 if not area then
	area = "default:glass"
	state = 0;
	width = 0; height = 0; i=0; j=0;
	step  = 0;
	move.forward(); turn.left()
	startpos = self.pos();
	self.spam(1)
 end
 
 pos = self.pos();
 if state ~= 1 and j>0 and (pos.x-startpos.x)^2<1 and (pos.z-startpos.z)^2<1 then
	say("finished walking around along "..j .. " edges,  " .. step .. " steps")
	if step == 2*(height+width)-4 then 
		say("area is rectangle of size " .. width .." x " .. height)
	else
		say("this area is not rectangle")
	end
	self.remove()
	state = 1
 end
 
 if state == 0 then
	turn.left();
	if read_node.forward_down()==area then  -- we can turn left and go
		j=j+1
	else 
		turn.right()
	end
 	
	node = read_node.forward_down();
	if node ~= area then 
		if j == 1 then 
			height = i+1
		elseif j == 2 then 
			width = i+1	
			--say("master, field width is " .. width .. " and field height is " .. height)
		end
		j=j+1; i=0;
		turn.right()
	else
		move.forward(); i = i+1;
		step = step+1;
	end
 end

Follower

This program tries to follow a player.
From the positions of the player and the robot, it calculates direction and distance.

 -- follower, by rnd
 if not state then
	name  = "rnd";
	owner = "rnd";
      --name  = "singleplayer";
      --owner = "singleplayer";
	gdist = 3;
	state = 0
	self.listen(1)
	self.spam(1)
 end
	-- process commands: follow / attack a player
	speaker, msg = self.listen_msg();
	if speaker == owner then
		if string.sub(msg,1,1)=="." then
			if string.sub(msg,2,5) == "kill" then
				pl=find_player(4);
				if pl and pl~= owner then
					if attack(pl) then
						attack(pl); attack(pl); attack(pl);
						say("I killed " .. pl .. " master. ")
					end
				end
			elseif string.sub(msg,2,3) == "go" then
				name = string.sub(msg,5) or owner;
				say("ok master, i follow " .. name.. " now")
			end
		end
	end
 	
	-- calculate positions and directions:
	pos  = self.pos()
	tpos = player.getpos(name);
	if not tpos then say ("master " .. name .. " left "); name = owner; tpos = player.getpos(name); end
	dir = self.viewdir();
 
	tpos.x = tpos.x-pos.x; tpos.z = tpos.z-pos.z;
	tdir   = {x=math.abs(tpos.x),z=math.abs(tpos.z)};
 
 if tdir.x<gdist and tdir.z< gdist then
	-- stay away
 else
	if state == 0 then
		if tdir.x>tdir.z then
			cdir = 1
		elseif  tdir.z>tdir.x then
			cdir = 2
		elseif math.rnd(2) == 1 then
			cdir = 1
		else
			cdir = 2
		end
 
		if cdir == 1 then -- x
			if dir.x^2<0.5 then
				turn.right();dir = self.viewdir();
			end
			if dir.x*tpos.x<0 then
				turn.angle(180)
			end
		elseif  cdir == 2 then -- z
			if dir.z^2<0.5 then
				turn.right();dir = self.viewdir();
			end
			if dir.z*tpos.z<0 then
				turn.angle(180)
			end
		end
	else
		state = state - 1
	end
 	
	-- move:
	if not move.forward() then
		if state == 0 then state = 3 end -- stuck
		node =  read_node.forward()
		if node~="air" and state == 3 then
			if read_node.down()~="air" then move.up() end
		else
			if math.random(2)==1 then turn.left() else turn.right() end
		end
	else
		move.down()
	end
 end

If the robot gets stuck, it tries to move in a random direction.
But there is no real pathfinding.

The program also listens to chat for commands, currently ".go playerX" and ".kill playerX".

Tree-Harvester

This robot moves around randomly, until it finds a pine-tree.
When one is found, it digs/harvests all of its wood.
To climb up the whole height of the tree, it places leaves under the bot.

This works well for pines, because pines are a simple vertical column of wood, plus some leaves.
Appletrees or jungletrees have a more complicated form,
so this algorithm would only get some parts of such trees.

Also, this program does not harvest apples.

 --TREE HARVESTER by rnd
 -- ADVANCED tree harvester/explorer for pine-trees
 tree   = "default:pine_tree";
 leaves = "default:pine_needles";

 if read_node.up() == tree then -- dig up
	dig.up(); 
	move.up(); 
	place.down(leaves) 
 else -- go down if can
	node = read_node.down()
	if node == leaves or node == tree then 
		dig.down(); move.down() 
	elseif node == "air" then
		move.down()
	else -- walk around
		node = read_node.forward();
		if node == tree then 
			say("Tree found")
			dig.forward() 
		elseif node ~= "air" then
			move.up()
		end
		if not move.forward() then
			if math.random(2)==1 then
				turn.left()
			else
				turn.right()
			end
		end
	end
 end

Note: at the start the robot needs some leaves in its inventory for climbing up.

Digger

 --HOLE DIGGER by rnd
 if not state then
	a=3; b=3; c=5;
	state = 0; dig.forward(); move.forward()
	angle = 1;     -- 1 turn right
	i=1; j=1; k=1; a=a-1;
 end
 
 if state == 0 then
	for j = 1,b do
		for i = 1,a do
			dig.forward();
			move.forward();
			if i==a and j< b then
				turn.angle(90*angle);
				dig.forward(); move.forward();
				turn.angle(90*angle);
				angle = -angle;
			end
		end
		if j==b then
			if (k%2 == 1) then dig.forward() end
			dig.down(); move.down(); turn.angle(180);
			k=k+1; if k>c then state = 1 end
		end
	end
 end

...

Demo-Farm

There is a small field near spawn, to show how to automate farming, and how to use fertilizer.

The farming bots turn around, and continue with the next row when reaching the wall / fence.

Farming corn

--FARMING by rnd
if not s then 
  plant = "farming:corn_8"; seed = "farming:corn"; weed = "farming:weed"
  wall  = "default:fence_wood";

  harvest_step = function(node) 
  if node==plant or node == weed or node == "air" then 
		dig.forward(); move.forward(); local nutrient = read_text.down("nutrient",1)
		if nutrient<8 then insert.down("farming:fertilizer","") end
	else
		move.forward()
	end
	place.backward(seed)
end

s=0; angle = 90 
end

if s==0 then -- walk
	node = read_node.forward();
	if node~=wall then harvest_step(node);
	else 
		turn.angle(angle); node = read_node.forward()
		if node == wall then turn.angle(180); harvest_step(node); turn.angle(-angle)
		else harvest_step(node); turn.angle(angle) angle=-angle;
		end
	end
end

Note:

  • The nutrient-value is an integer stored in the soil-nodes.
  • The program does not check if fertilizer is in the inventory.
  • The program does not check for soil before planting (i.e. planting on dirt will waste the seed).

Making fertilizer

Currently, there are two recipes for fertilizer:

  • 3 leaves
  • 3 papyrus

Robots cannot harvest leaves from trees easily, so here is a papyrus-farm:

--FARMING papyrus
if not s then 
plant = "default:papyrus"; seed = "air";
wall  = "default:fence_wood";
y0 = self.pos().y
y1 = y0+2;
harvest_step = function(node) 
	if node==plant then 
		move.forward();
		local step = 0
		while (read_node.up() == plant and step < 4) do
			step = step+1; move.up()
		end
		move.down();dig.up(); move.up()
		s=1 
	else
		move.forward()
	end
end

s=0; angle=90 
t = 0;
end

if s==0 then -- walk
	node = read_node.forward();
	if t==0 and node~=wall then 
		harvest_step(node);
	else 
		if t == 0 then
			turn.angle(angle); node = read_node.forward()
			if node == wall then 
				turn.angle(180); harvest_step(node);
				t = 1
			else harvest_step(node); t=2
			end
		elseif t == 1 then
			turn.angle(-angle); t=0
		elseif t == 2 then
			turn.angle(angle); angle=-angle; t=0
		end
	end
elseif s==1 then
	if self.pos().y>y0 then dig.down() move.down()
                       else craft("farming:fertilizer") s = 0 end
end

Note: the robot can now craft items, such as fertilizer.

Debug

Screenshot for current problem - 2017-01-18:

robot-library does not update title of books


Tutorial 2

File:Robots-Tutorial2 Index.png
Index of robots-tutorial - sign at wall, spawner with code on ground.

There is a 'live' tutorial-parcour about programming rnd's at his server ROBOTS_SKYBLOCK, 46.150.38.60:30000.
It can be reached via teleporter at spawn, and via stairs.

How to reach the tutorial

As a new player, you spawn at the 'arrival-hub', at 64,8,-96.
You can get back there with the command /spawn.

At the wall in front, you see big signs

  • "to your island"
there is a button on the floor at 54,8,-88 that teleports to your personal island
  • "spawn"
button on floor at 64,8,-88, this will teleport to the 'old spawn' at 16017,8,16016
  • "lab" - punch the button on the floor at 73,8,-87
this will teleport you to the start of the tutorial-area at 15986,-7,16000

There are also stairs down to the tutorial-area at the 'old spawn', with a big sign "TUTORIAL".

Layout of the tutorial-area

The robots have big numbers on top of them at the wall.
..

Operation Basics

Short summary about the operation of basic_robots:

  • There is a spawner ("cpu"), that has to be put on the ground somewhere.
This means that players cannot activate their own robots in areas protected by other players.
The spawner acts as a kind of basestation.
Robots can only move a certain distance from it.
  • Rightclick the spawner to access a form with the code, the inventory and the library
the inventory has 4*8 slots, same size as a chest, or the player's inventory.
the library has 16 slots, same as a bookshelf
  • When pressing the "start"-button, the spawner creates a robot ("worker") on the space above it
Each spawner can only control one robot at a time.
    • With no code, the robot can be steered with a remote-control
    • otherwise, the robot executes the code from the form
  • The "Stop"-button stops the program execution, and the robot disappears.
  • The code is running in a sandbox, and is called once every second.

In the following chapters, we present some of those programs, that have been written by rnd and users at his server.

Tutorial-Programs

In this tutorial-parcour, the robots are started by punching the big keypads mounted above the spawners.

The keypads are set to send a signal 2=ON to the spawner for starting the program.

The keypads are part of the mod basic_machines.

#00 - Hello

To tell the robot what to do, write commands into his code-area.
Rightclick the robot-spawner to see the code.

say("Hello! im a robot")
self.remove()

These commands would be repeated every second,
but "self.remove()" removes the robot, and thus ends the program.

Moving

#01 - Forward

Simple movement

move.forward()

When the robot hits a wall (or other obstacle), movement fails.
So it looks like the robot stopped, but it actually tries again every second.

#02 - Climb

Robots can climb too, if there is a block to step on.

move.forward()
move.up()

As above - this one stops moving when it hits the ceiling.

#03 - Forward & Stop

Move forward until hitting an obstacle, then stopping the program.

self.spam(1)
if move.forward() then
  say("walking ..")
else
  say("I hit obstacle. removing robot"); self.remove()
end

The spam-option needs to be set to allow output of more than one messages.

#04 - Forward & Left

Another very simple robot: it will turn left when it can't go forward anymore.

if not move.forward() then
  turn.left()
end

Output

#05 - Talk

Text-output via say().

text = "This is a recorded message. Now robot will remove itself.";
say(text)
self.remove()

You can make robot remember stuff by using variables.

#06 - talk, variables

xx

if not text then
  text = "This is one time message.."
  say(text)
end
turn.right()

Variables are always set new when robot runs.
To change that you can use "if" to only set it once.
This robot will say "hello" only once, but will turn around all the time.

Build & Mine

#07 - Place

You can use robot to build houses and more.
Here "place" command is used to place dirt block right of robot.
NOTE: you need to have dirt in robot "storage" or it can't place it.

place.right("default:dirt")

#08 - Dig

This robot digs a block to the left. It puts it in storage.
NOTE: robot can only dig 1 block per operation.

dig.left()

xx

Inventory-Access

#09 - Insert

With "insert" robot can put stuff inside chests and more.
This robot places 2 apples in the chest on its right

insert.right("default:apple 2")
self.remove()

xx

#10 - Take

This robot takes 1 apple from the chest on its left.

take.left("default:apple")
self.remove()

xx

Manipulations

#11 - read_node & activate

The robot uses read_node() to look at the state of the light-block,
and activate() to turn it on and off.

if not pn then pn="LightControl"; -- say(pn) -- hajo, 2017-04-13
  self.label(pn)   -- show program-name instead of robot-id
  write_text.up("Press this button")  -- label the keypad above robot
  turn.left(); turn.left(); move.forward()  -- move to the light
  i=0
end

i=i+1
n=read_node.forward(); --say(n)
if      n=="basic_machines:light_on" then
  say("The light is ON")
  activate.forward(-1)  --turn the light OFF
elseif  n=="basic_machines:light_off" then
  say("The light is OFF")
  activate.forward(1)  --turn it ON again
else
  say("No light found !")
  self.remove() 
end

if i>9 then  -- enough for now 
  say("stop")
  self.remove() 
end

xx

#12 - Simple lightswitch

Settings on the keypad:

  • target: 0 -1 0 (means directly below)
  • mode: 3 (means toggle)
--no robot here


#13 - os

The robot can call functions from the operating-system, e.g. to get the time and date.

self.label("TimeDate")  -- program runs too short for this to be visible

td = os.date("%Y-%m-%d  %H:%M:%S")
msg = "Time and date"
say(msg..": "..td)

ok=write_text.up(msg)  -- label the button above the robot
ok=write_text.down("This robot was last run: "..td)  -- write text on cpu-box

self.remove()  -- stop program

This robot also writes the time&date onto its own spawner.


#14 - Fun

BS-generator

--BS-generator by rnd / stop+countdown: 2017-04-24 hajo

if not progname then
  progname="BS-generator"
  ok=write_text.up("Press again to stop")  -- label button above robot

  t=read_text.down();   -- program-name or countdown-value
  n=tonumber(t)  -- returns nil if text is not a number
  if n then
-- say(t.."=>"..n)
   say("Enough BS, for now.")
   i=0  -- countdown will stop immediately
  else
    i=20  -- countdown-timer
  end

	 pretexts = {"Our challenge to","The facilitators","Our number-one internal clients","The white-collar workers","The human resources","Our parallel controls",
	"To continue our growth, we must","Brand identities", "A low-risk high-yield calibration","Collaborative milestones","The policy makers",
	"The Co-Head of Customer Relations","Cutting-edge philosophies","The executive committee"}
	 adverbs = {"appropriately","assertively","authoritatively","collaboratively","compellingly","competently","completely","continually","conveniently","credibly","distinctively","dramatically","dynamically","efficiently","energistically","enthusiastically","fungibly","globally","holisticly","interactively","intrinsically","monotonectally","objectively","phosfluorescently","proactively","professionally","progressively","quickly","rapidiously","seamlessly","synergistically","uniquely"}
	 verbs = {"actualize","administrate","aggregate","architect","benchmark","brand","build","cloudify","communicate","conceptualize","coordinate","create","cultivate","customize","deliver","deploy","develop","dinintermediate disseminate","drive","embrace","e-enable","empower","enable","engage","engineer","enhance","envisioneer","evisculate","evolve","expedite","exploit","extend","fabricate","facilitate","fashion","formulate","foster","generate","grow","harness","impact","implement","incentivize","incubate","initiate","innovate","integrate","iterate","leverage existing","leverage other's","maintain","matrix","maximize","mesh","monetize","morph","myocardinate","negotiate","network","optimize","orchestrate","parallel task","plagiarize","pontificate","predominate","procrastinate","productivate","productize","promote","provide access to","pursue","recaptiualize","reconceptualize","redefine","re-engineer","reintermediate","reinvent","repurpose","restore","revolutionize","right-shore","scale","seize","simplify","strategize","streamline","supply","syndicate","synergize","synthesize","target","transform","transition","underwhelm","unleash","utilize","visualize","whiteboard"}
	 adjectives = {"24/7","24/365","accurate","adaptive","alternative","an expanded array of","B2B","B2C","backend","backward-compatible","best-of-breed","bleeding-edge","bricks-and-clicks","business","clicks-and-mortar","client-based","client-centered","client-centric","client-focused","cloud-based","cloud-centric","cloudified","collaborative","compelling","competitive","cooperative","corporate","cost effective","covalent","cross functional","cross-media","cross-platform","cross-unit","customer directed","customized","cutting-edge","distinctive","distributed","diverse","dynamic","e-business","economically sound","effective","efficient","elastic","emerging","empowered","enabled","end-to-end","enterprise","enterprise-wide","equity invested","error-free","ethical","excellent","exceptional","extensible","extensive","flexible","focused","frictionless","front-end","fully researched","fully tested","functional","functionalized","fungible","future-proof","global","go forward","goal-oriented","granular","high standards in","high-payoff","hyperscale","high-quality","highly efficient","holistic","impactful","inexpensive","innovative","installed base","integrated","interactive","interdependent","intermandated","interoperable","intuitive","just in time","leading-edge","leveraged","long-term high-impact","low-risk high-yield","magnetic","maintainable","market positioning","market-driven","mission-critical","multidisciplinary","multifunctional","multimedia based","next-generation","on-demand","one-to-one","open-source","optimal","orthogonal","out-of-the-box","pandemic","parallel","performance based","plug-and-play","premier","premium","principle-centered","proactive","process-centric","professional","progressive","prospective","quality","real-time","reliable","resource-sucking","resource-maximizing","resource-leveling","revolutionary","robust","scalable","seamless","stand-alone","standardized","standards compliant","state of the art","sticky","strategic","superior","sustainable","synergistic","tactical","team building","team driven","technically sound","timely","top-line","transparent","turnkey","ubiquitous","unique","user-centric","user friendly","value-added","vertical","viral","virtual","visionary","web-enabled","wireless","world-class","worldwide"}
	 nouns = {"action items","alignments","applications","architectures","bandwidth","benefits","best practices","catalysts for change","channels","clouds","collaboration and idea-sharing","communities","content","convergence","core competencies","customer service","data","deliverables","e-business","e-commerce","e-markets","e-tailers","e-services","experiences","expertise","functionalities","fungibility","growth strategies","human capital","ideas","imperatives","infomediaries","information","infrastructures","initiatives","innovation","intellectual capital","interfaces","internal or 'organic' sources","leadership","leadership skills","manufactured products","markets","materials","meta-services","methodologies","methods of empowerment","metrics","mindshare","models","networks","niches","niche markets","nosql","opportunities","'outside the box' thinking","outsourcing","paradigms","partnerships","platforms","portals","potentialities","rocess improvements","processes","products","quality vectors","relationships","resources","results","ROI","scenarios","schemas","services","solutions","sources","strategic theme areas","storage","supply chains","synergy","systems","technologies","technology","testing procedures","total linkage","users","value","vortals","web-readiness","web services","virtualization"}

	make_bs = function()
		local pretext = pretexts[math.random(#pretexts)];
		local adverb = adverbs[math.random(#adverbs)];
		local verb = verbs[math.random(#verbs)];
		local adjective = adjectives[math.random(#adjectives)];
		local noun = nouns[math.random(#nouns)];
		return pretext .. " " .. adverb .. " "  .. verb .. " " .. adjective .. " " .. noun .."."
	end

	msg = ""; 
  for i = 1, 16 do msg = msg .. "\n" .. make_bs() end; 
	--book.write(1,"BS",msg);
	--bookname = check_inventory.down("a","library",1)
	self.label(msg)
end

i=i-1
ok=write_text.down(i)   -- write countdown-value on cpu-box

if i<1 then   -- end the program
  ok=write_text.down(progname)  -- write program-name on cpu-box
  ok=write_text.up("Press button to get some B***S***")  -- label button
  self.remove()  
end

--take.down("library",bookname)
--insert.forward("main",bookname)
--self.remove()

This creates a number of sentences full of nonsense.

#15 - keypad

How to use a keypad as keyboard for robot.

if not s then
	s=1
	cmd = "";
end

if s==1 then
	text = read_text.backward();
	if text~="" then
		cmd = text;
		write_text.backward("")
		s=2
	end
end

if s==2 then
  local num = tonumber(cmd);
	if num then 
		say("you entered a number " .. num)
	else 
		say("you entered string '" .. cmd .. "'. ");
	end
  s = 1;
end

The keypad writes textinput from the user onto a sign mounted at the wall behind the robot,

The robot reads the text from that sign, and clears it.
Then it tries to convert the text to a number.
Depending on a successfull conversion, it announces if the text was a number or a string.

After that, it keeps looking at the sign until the user writes something new.

#16 - greeting robot

Finds and remembers nearby players.

if not db then 
	player =""
	player_old = "" 
	db = {};
	state = 0;
end

player = find_player(5);
if player then 
  player = player[1]
	if state == 0 then move.up();state = 1 else move.down();state = 0 end
	if player~=player_old then
		if db[player] == nil then
			say("hi " .. player .. ". nice to meet you :D")
			db[player]=2;
		else
			if db[player]>5 then 
				attack(player)
				say("stop annoying me " .. player .. " !!!!!")
			else
				say("hi again " .. player .. ", for the " .. db[player] .. ". time") 
			end
			db[player]=db[player]+1;
			
		end
	end
end
player_old = player

#17 - Smelter robot

put cobble in chest and it will be smelted to stone in furnace.

  insert.up("default:coal_lump","fuel")
  take.right("default:cobble")
  insert.up("default:cobble","src")
  activate.up(1)
  say("1 coal inserted in furnace, 1 cobble taken from chest, 1 cobble inserted in furnace")
self.remove()


#18 - Math-quiz

Math quiz robot: answer correct and take reward from chest.

-- QUIZ: asks math question, like ""WHAT IS 12*13 ?"
if not state then 
state = 1;
a=0;b=0; question = "";
function generate_question()
	a = math.random(12)+10;
	b = math.random(12)+10;
	question = "WHAT IS " .. a .."*".. b .. " ? ";
	say(question)
end
generate_question()
self.listen(1)
end

speaker, msg = self.listen_msg()
msg = tonumber(msg)
if msg then 

if msg == a*b then
	say(speaker .. " ANSWERED CORRECTLY!  You get reward in chest")
  insert.up("default:apple")
  insert.up("default:pine_tree")
	generate_question()
	else
	  say("WRONG! " .. question)
	end
end
turn.left()

#19 - Measure area

This robot walks the outer edge and measures the area size.

if not area then
  self.label("")
	area = "default:glass"
	state = 0;
	width = 0;height = 0;i=0;j=0;
	step = 0;
	move.forward();turn.left()
	startpos = self.pos();
	self.spam(1)
end

pos = self.pos();
if state ~= 1 and j>0 and (pos.x-startpos.x)^2<1 and (pos.z-startpos.z)^2<1 then
	say("finished walking around along "..j .. " edges,  " .. step .. " steps")
	if step == 2*(height+width)-4 then 
		say("area is rectangle of size " .. width .." x " .. height)
	else
		say("this area is not rectangle")
	end
	self.remove()
	state = 1
end

if state == 0 then
	turn.left();
	if read_node.forward_down()==area then  -- we can turn left and go
		j=j+1
	else 
		turn.right()
	end
	
	node = read_node.forward_down();
	if node ~= area then 
		if j == 1 then 
			height = i+1
		elseif j == 2 then 
			width = i+1
	
			--say("master, field width is " .. width .. " and field height is " .. height)
		end
		j=j+1;i=0;
		turn.right()
	else
		move.forward(); i = i+1;
		step = step+1;
	end
end

#20 - Roadtracker

This robot follows the cobble roads.

--tracks road
--run then tracker.step()
if not tracker then
 self.label("")
	tracker = {};
	tracker.road = "default:cobble";

	tracker.step = function()
		if read_node.forward_down() == tracker.road then
			if not move.forward() then turn.angle(180) end
		else
			turn.left();
			if read_node.forward_down() ~= tracker.road then
				turn.right(); turn.right();
				if read_node.forward_down() ~= tracker.road then
					turn.right() 
				end
			end
		end
	end
end

tracker.step()