Functional programming -- 2009-2010 -- info.uvt.ro/Laboratory/Robots

From Wikiversity


Functional programming (Spring 2010):

To be finalized...

Installing PLT Robots[edit]

Installing 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[edit]

Creating 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:

  1. open a console; (Applications -> System Tools -> Terminal);
  2. inside the console switch to the folder where you have installed PLT Robots: cd ./plt-robots;
  3. create an empty file: touch ./sources/exercise-1.ss
  4. open the empty file in DrScheme: ./scripts/open-with-drscheme.bash ./sources/exercise-1.ss
  5. paste the following code;
  6. 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:

  1. make the robot go forward until it reaches the a wall,
  2. then make the robot turn left,
  3. and apply the whole process again;
Fuzzy robot

Now make the robot do the following:

  1. 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;
  2. then it chooses a random direction between 'left and 'right and turns that way;
  3. 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 just zap-robot! it;
    • if there is a 'prize or 'food just grab-robot! it;

API[edit]

Robot API[edit]

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;
  • 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);
  • 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;
  • 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: