Functional programming -- 2009-2010 -- info.uvt.ro/Laboratory/Robots
From Wikiversity
[edit] Installing PLT Robots
[edit] Installing PLT Scheme
- 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;
[edit] Installing PLT Robots
- 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);
[edit] Creating and testing our own robots
[edit] Creating a new source file
- 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!)
[edit] Testing the code
- 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
[edit] Using DrScheme (recommended)
- 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
[edit] Exercises
- 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
'leftand'rightand 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
'baddiejustzap-robot!it; - if there is a
'prizeor'foodjustgrab-robot!it;
- if there is a
[edit] API
[edit] Robot API
All 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
#fif 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
'baddiethis 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
'leftor'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
#fif 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)
[edit] World API
- 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: