Functional programming -- 2009-2010 -- info.uvt.ro/Laboratory/Robots
Installing PLT Robots
editInstalling PLT Scheme
edit- the first step in using this simulation code is to have a working PLT Scheme install;
- in order to install PLT Scheme you have two options:
- use the provided script which installs a version of PLT Scheme specially for the purpose of this lab (this works only on Linux-es derived from Ubuntu or Debian);
- see the dedicated page for tools;
Installing PLT Robots
edit- please note for the moment this installation procedure works only in Linux and requires PLT Scheme to be already installed; but fortunately the code itself is portable and runs under Windows, only the installation and running scripts aren't;
- open a terminal (from Applications -> System Tools -> Terminal);
- inside the terminal run the following commands exactly as entered (the lines starting with
#
are comments and can be ignored):
# we assume that we are in our home directory # first we create a folder to hold the source code mkdir ./plt-robots # then we go inside that folder cd ./plt-robots # then we download and unpack the source code wget -O - http://gitorious.org/plt-robots/mainline/archive-tarball/stable | tar -xzv --strip 1 # (optional step) we install a specific version of PLT Scheme specially for this purpose # in order to run this don't enter the following line except the hash character # ./scripts/install-scheme.bash from-binary-deb # and finally we run the script which detects if we have the correct version of PLT Scheme ./scripts/detect-scheme.bash # and if all went Ok we can just test our first robot: ./scripts/run-with-mred.bash ./sources/test-4.ss
- the source code repository is held at Gitorious (for those interested);
Creating and testing our own robots
editCreating a new source file
edit- just open your favorite text editor (for example from the terminal):
# we assume that we are already inside the plt-robots directory # if not just cd in there # we edit a new file inside the sources folder nano ./sources/my-first-robot-v1.ss
- inside this file we have to put at minimum the following lines (see the comments for their meaning):
; this line says that we want to speak standard Scheme :) #lang scheme ; this line says that we would like to import all the ; goodies from the robots/base module (see the API for explanations) (require robots/base) ; we need to define a function that receives as sole argument a robot instance ; and controls it according to the rules specified in the API section (define (control-robot! boty) ; for now our robot only turns once to the left (turn-robot! boty 'left) ; and then it moves forward (move-robot! boty) ; and we recursively apply the same rules for the entire eternity (control-robot! boty)) ; now we need to give life to our robot (simulate-robot control-robot!)
Testing the code
edit- again inside the console:
# we assume that we are already inside the plt-robots directory # if not just cd in there # just use the helper script to start the robot ./scripts/run-with-mred.bash ./sources/my-first-robot-v1.ss
Using DrScheme (recommended)
edit- another way to edit and test our robots would be by using DrScheme interface;
- just open a console and:
# we assume that we are already inside the plt-robots directory # if not just cd in there # if the file does not exist then we must create it # touch creates an empty file touch ./sources/my-first-robot-v2.ss # or we could just copy it from our previous endeavor cp ./sources/my-first-robot-v1.ss ./sources/my-first-robot-v2.ss # now by using the helper script we just open the file ./scripts/open-with-drscheme.bash ./sources/my-first-robot-v2.ss
Exercises
edit- Dummy robot
The first exercise is to create your own robot control function. Again the steps are the following:
- open a console; (Applications -> System Tools -> Terminal);
- inside the console switch to the folder where you have installed PLT Robots:
cd ./plt-robots
; - create an empty file:
touch ./sources/exercise-1.ss
- open the empty file in DrScheme:
./scripts/open-with-drscheme.bash ./sources/exercise-1.ss
- paste the following code;
- now just press the run button;
#lang scheme (require robots/base) (define (control! bot) (turn-robot! bot) ) (simulate-robot control! 'empty)
- Moving the robot
Based on the previous example write a (recursive) function move-robot-n!
that takes two arguments (the robot and a number) which moves the robot exactly n steps forward:
#lang scheme (require robots/base) (define (move-robot-n! bot n) ... ) (define (control! bot) (move-robot-n! bot 5) ) (simulate-robot control! 'empty)
- Finding the edge
Now make the robot move forward until it reaches the wall. (Check the API section to see how you could use either the look-robot?
, feel-robot?
or just move-robot!
functions).
- Going around the edge
Now make the robot do the following:
- make the robot go forward until it reaches the a wall,
- then make the robot turn left,
- and apply the whole process again;
- Fuzzy robot
Now make the robot do the following:
- it chooses a random number between 1 and 5 (see the random function in the PLT Scheme Reference) and moves (if it can) that many tiles forward;
- then it chooses a random direction between
'left
and'right
and turns that way; - and it applies the whole process again;
- Narrow sighted robot
Based on the Fuzzy robot exercise, now make the robot do the following:
- before any move or turn operation try to see if there is something before the robot:
- if there is a
'baddie
justzap-robot!
it; - if there is a
'prize
or'food
justgrab-robot!
it;
- if there is a
API
editRobot API
editAll these functions should be used only inside the control function of the robot!
- feel-robot?
- description: by "feeling" the robot understands looking exactly in front of him (to the adjacent tile) and deciding if he sees the queried object;
- inputs:
- a robot instance;
- (optionally) a symbol or list of symbols that we are trying to "feel";
- (by default the things to feel for are:
'(food prize)
);
- outputs:
- it returns the symbol which was "felt" (which equates to the true value),
- or it returns
#f
(false) in case none of the things were felt;
- examples:
; this goes inside a robot control function ... (case (feel-robot? boty '(baddie prize food)) ((baddie) (printf "in front of me there is a bug; i'd better avoid it!\n")) ((food prize) (printf "hmm... there is something delicious in front of me! yum yum!\n") (grab-robot! boty)) (else (printf "nothing to see here... moving along...\n"))) ...
- smell-robot?
- description: it resembles the
feel-robot?
function, but this time the sensor instead of looking just in front of the robot, it senses all around the robot in the 8 adjacent tiles; - inputs: just like in the case of
feel-robot?
- outputs: just like in the case of
feel-robot?
- notes: be careful as the robot smells even on diagonal, and by successively turning the robot we might never "feel" the things we are smelling;
- examples:
; this goes inside a robot control function ... (when (smell-robot? boty 'baddie) (printf "yikes! there is a bug near me! i'd better run!\n) (move-robot! boty)) ...
- look-robot?
- description: by looking we mean that the robot just compares all the in front of him for something until either there is something else than space;
- inputs: just like in the case of
feel-robot?
- outputs:
- it returns a number (which equates to the true value), that represents the number of empty tiles from the robot to that particular target; (for example if the thing is just in front of the robot the value is
0
); - or if none of the things we are looking for are seen it just returns
#f
;
- it returns a number (which equates to the true value), that represents the number of empty tiles from the robot to that particular target; (for example if the thing is just in front of the robot the value is
- examples:
; this goes inside a robot control function ... (let ((outcome (look-robot? boty '(prize food)))) (cond ((false? outcome) (printf "nothing interesting in sight... only walls and bugs... maybe turning around would help\n") (turn-robot! boty 'left)) ((> outcome 5) (printf "i kind of see something... but i'm to lazy to wander at that distance...\n")) (else (printf "ok! definitly worth going for it!\n") (move-robot! boty outcome) (if (grab-robot! boty) (printf "yum! yum! ate it!\n") (printf "too late... some one got there before i did... better luck next time\n"))) )) ...
- grab-robot!
- description: the robot tries to take what is directly in front of him;
- inputs: a robot instance;
- outputs:
- it returns a symbol denoting the thing that was just grabbed (it can be either
'food
,'prize
, or'baddie
); - or it returns
#f
if nothing was grabbed (there was an empty space, a wall or another robot);
- it returns a symbol denoting the thing that was just grabbed (it can be either
- notes: even if the robot can grab a
'baddie
this is not a very good idea as your robot is going to get poisoned and doing this multiple times will die; - examples: see previous examples;
- turn-robot!
- description: it allows the robot to turn either to the left or to the right;
- inputs:
- a robot instance;
- a symbol denoting the direction (either
'left
or'right
);
- outputs:
- it always returns
#t
;
- it always returns
- examples: see previous examples;
- move-robot!
- description: it allows the robot to move forward one or multiple tiles at a time;
- inputs:
- a robot instance;
- (optional) the number of forward steps to make;
- outputs:
- it returns a number representing how many steps were actually made,
- or it returns
#f
if no step was even made;
- notes: for example we could ask the robot to move forward a million tiles, but this is not possible as it would soon hit something; thus the robot actually says how many steps was able to make;
- examples: see previous examples;
- simulate-robot
- description: it's a simple function that takes the root control function and just starts the simulation;
- inputs:
- the robot control function;
- (optional) the symbol denoting a map to load for simulation;
- outputs: nothing;
- examples:
(define (control-robot! boty) ...) ; let's try our robot on the "patterns" map (simulate-robot control-robot! 'patterns) ; and now inside the Minotaur's maze (simulate-robot control-robot! 'maze)
World API
edit- create-world
- description: it creates a world initialized with a map file;
- inputs: the symbol denoting the map file;
- outputs: the newly created world instance;
- examples:
- create-robot
- description: given a robot control function and a name it creates a new robot inside the world;
- inputs:
- a world instance;
- a symbol giving a name to the newly created robot;
- a robot control function;
- outputs: the newly created robot;
- examples:
- simulate-world
- description: given a world it starts and displays the simulation;
- inputs: a world instance;
- outputs: nothing;
- examples: