Homework/KarelExamples.hs

104 lines
2.7 KiB
Haskell

-- | This module defines some example worlds and programs for testing
-- your Karel interpreter.
module KarelExamples where
import Prelude hiding (Either(..))
import KarelSyntax
import KarelState
--
-- * Trivial worlds
--
-- | A world that is all walls.
wallWorld :: World
wallWorld = const Nothing
-- | A world that is completely empty of walls and beepers.
emptyWorld :: World
emptyWorld = const (Just 0)
-- | A robot that starts at the origin, facing north, with the
-- given number of beepers.
originBot :: Int -> Robot
originBot b = ((0,0),North,b)
--
-- * Demo world
--
-- | A 10x5 room with some beepers in a line, illustrated below.
--
-- XXXXXXXXXXXX
-- X X
-- X X
-- X X
-- X @ 2 3 4 X
-- X X
-- XXXXXXXXXXXX
--
-- The @ symbol is coordinate (1,1).
-- Clear spaces are from (0,0) to (9,4).
-- There are beepers at the following locations:
-- * 2 beepers at (4,1)
-- * 3 beepers at (6,1)
-- * 4 beepers at (8,1)
--
demoWorld :: World
demoWorld (4,1) = Just 2
demoWorld (6,1) = Just 3
demoWorld (8,1) = Just 4
demoWorld (x,y) | x >= 0 && x < 10 &&
y >= 0 && y < 5 = Just 0
| otherwise = Nothing
-- | An initial robot state for the demo world. The robot starts at
-- (1,1), facing East, with 1 beeper in its bag.
demoBot :: Robot
demoBot = ((1,1),East,1)
--
-- * Program generators
--
-- | Generate a program that does the following n times:
-- 1. moves in a straight line until it finds a beeper
-- 2. picks it up
-- 3. returns to its original position and facing.
fetcher :: Int -> Prog
fetcher n = ([("fetch",fetch)], main)
where
fetch = Block
[ While (Not Beeper) -- do until we find a beeper:
(If (Clear Front) -- can we move forward?
Move -- if yes, then do it
Shutdown) -- if not, shut down
, PickBeeper ]
main = Block
[ Iterate n $ Block -- repeat n times:
[ PutBeeper -- put a beeper down to mark our place
, Move -- move forward one space
, Call "fetch" -- go get a new beeper
, Turn Back -- turn around
, Move -- move forward one space
, Call "fetch" -- go back to where we started
, Turn Back ] -- turn back to our initial facing
, Shutdown ]
-- | Generates a statement that moves the robot in a rectangle of
-- the given dimensions.
rectangle :: Int -> Int -> Stmt
rectangle w h = Block
[ While (Not (Facing North)) (Turn Right)
, Iterate h Move
, Turn Right
, Iterate w Move
, Turn Right
, Iterate h Move
, Turn Right
, Iterate w Move
, Turn Right ]