[Initial Import Ben.Lippmeier@anu.edu.au**20080201055838] { adddir ./bin adddir ./doc adddir ./log adddir ./src adddir ./src/Game adddir ./src/Util adddir ./src/Verb addfile ./Makefile hunk ./Makefile 1 + +all : + @echo "* Building AAdvent" + @ghc -fglasgow-exts -isrc --make src/Main.hs -o bin/aadvent + + +# -- clean +.PHONY : clean +clean : + @echo "* Cleaning up" + + @rm -f make/Makefile.deps \ + bin/* + + @find src \ + -name "*.o" \ + -o -name "*.hi" \ + -follow | xargs -n 1 rm -f + + @echo + + + +# -- build documents +srcHs = $(shell find src -name "*.hs" -follow) + +.PHONY : doc +doc : $(srcHs) + @echo "* Building documentation" + @haddock -h -o doc --ignore-all-exports $^ + addfile ./README hunk ./README 1 +An Augmented Adventure v1.0 + maintainer: Ben.Lippmeier@anu.edu.au (Ben Lippmeier) + +Written for the COMP1100 course at the + Department of Computer Science, Australian National University. + +A text adventure, similar to zork. Designed to be easy to extend. + addfile ./doc/Format.html hunk ./doc/Format.html 1 + + +Format
 ContentsIndex
Format
Documentation
formatScript :: Int -> String -> String
Produced by Haddock version 0.7
addfile ./doc/Game-Item.html hunk ./doc/Game-Item.html 1 + + +Game.Item
 ContentsIndex
Game.Item
Description
Defines the initial items in the game. +
Synopsis
parseItem :: String -> Maybe ItemId
gameItems :: [Object]
Documentation
parseItem :: String -> Maybe ItemId
Parse an item name into an item descriptor. +
gameItems :: [Object]
The initial items in the game. +
Produced by Haddock version 0.7
addfile ./doc/Game-Property.html hunk ./doc/Game-Property.html 1 + + +Game.Property
 ContentsIndex
Game.Property
Description
Defines the initial properties in the game. +
Synopsis
gameProperties :: [Object]
Documentation
gameProperties :: [Object]
The initial properties in the game, and their states. +
Produced by Haddock version 0.7
addfile ./doc/Game-Room.html hunk ./doc/Game-Room.html 1 + + +Game.Room
 ContentsIndex
Game.Room
Description
Defines the initial rooms in the game. +
Synopsis
gameRooms :: [Object]
Documentation
gameRooms :: [Object]
The initial rooms in the game. +
Produced by Haddock version 0.7
addfile ./doc/Main.html hunk ./doc/Main.html 1 + + +Main
 ContentsIndex
Main
Description
Contains the user interaction loop. +
Synopsis
initWorld :: World
banner :: String
main :: IO ()
getPlayerInput :: World -> IO World
handleInput :: World -> String -> IO World
command :: Verb -> [String] -> World -> IO World
Documentation
initWorld :: World
The initial state of the world. +
banner :: String
This banner is displayed when the program starts up. +
main :: IO ()
Program entry point. +
getPlayerInput :: World -> IO World
Get commands from the user and use them to change the world. +
handleInput :: World -> String -> IO World
Handles a player command. + The player may not perform any actions whilst dead. + All commands have the form: <verb> [args..] +
command :: Verb -> [String] -> World -> IO World
Use the verb to decide what function to call to handle the command. +
Produced by Haddock version 0.7
addfile ./doc/Util-Item.html hunk ./doc/Util-Item.html 1 + + +Util.Item
 ContentsIndex
Util.Item
Description
Utils for Items. +
Synopsis
isItem :: ItemId -> Object -> Bool
itemName :: Object -> Name
Documentation
isItem :: ItemId -> Object -> Bool
Checks if some object is an Item with a specific ItemId. +
itemName :: Object -> Name
Get the name of an item. +
Produced by Haddock version 0.7
addfile ./doc/Util-Mobile.html hunk ./doc/Util-Mobile.html 1 + + +Util.Mobile
 ContentsIndex
Util.Mobile
Description
Utils for Mobiles. +
Synopsis
isMob :: MobId -> Object -> Bool
mobSetLocation :: RoomId -> Object -> Object
mobAddItem :: ItemId -> Object -> Object
mobRemoveItem :: ItemId -> Object -> Object
mobLocation :: Object -> RoomId
mobInventory :: Object -> [ItemId]
Documentation
isMob :: MobId -> Object -> Bool
Checks if some object is a Mobile with a specific MobileId. +
mobSetLocation :: RoomId -> Object -> Object
Sets the location of a mobile. +
mobAddItem :: ItemId -> Object -> Object
Adds an item to a mobiles inventory. +
mobRemoveItem :: ItemId -> Object -> Object
Removes an item from a mobiles inventory. +
mobLocation :: Object -> RoomId
Get the location of a mobile. +
mobInventory :: Object -> [ItemId]
Get the inventory of a mobile. +
Produced by Haddock version 0.7
addfile ./doc/Util-Property.html hunk ./doc/Util-Property.html 1 + + +Util.Property
 ContentsIndex
Util.Property
Description
Utils for properties. +
Synopsis
isProp :: PropId -> Object -> Bool
propBoolSet :: Bool -> Object -> Object
propBoolGet :: Object -> Bool
Documentation
isProp :: PropId -> Object -> Bool
Checks if some object is a Property with a specific PropId. +
propBoolSet :: Bool -> Object -> Object
Sets a Boolean property. +
propBoolGet :: Object -> Bool
Gets a Boolean property. +
Produced by Haddock version 0.7
addfile ./doc/Util-Room.html hunk ./doc/Util-Room.html 1 + + +Util.Room
 ContentsIndex
Util.Room
Description
Utils for rooms. +
Synopsis
isRoom :: RoomId -> Object -> Bool
roomId :: Object -> RoomId
roomInventory :: Object -> [ItemId]
roomAddItem :: ItemId -> Object -> Object
roomRemoveItem :: ItemId -> Object -> Object
Documentation
isRoom :: RoomId -> Object -> Bool
Checks if some object is a Room with a specific RoomId. +
roomId :: Object -> RoomId
Get the RoomId from a room. +
roomInventory :: Object -> [ItemId]
Get the inventory of a room. +
roomAddItem :: ItemId -> Object -> Object
Add an item to a room. +
roomRemoveItem :: ItemId -> Object -> Object
Remove an item from a room. +
Produced by Haddock version 0.7
addfile ./doc/Util-World.html hunk ./doc/Util-World.html 1 + + +Util.World
 ContentsIndex
Util.World
Synopsis
worldPlayer :: World -> Object
worldPlayerRoom :: World -> Object
worldPlayerLocation :: World -> RoomId
getObject :: (Object -> Bool) -> World -> Object
modifyObject :: (Object -> Bool) -> (Object -> Object) -> World -> World
Documentation
worldPlayer :: World -> Object
Get the player object from the world. +
worldPlayerRoom :: World -> Object
Determine what room the player is in and get that object from the world. +
worldPlayerLocation :: World -> RoomId
Return the RoomId of the room that the player is currently in. +
getObject :: (Object -> Bool) -> World -> Object
Use a predicate to get some object from the world. +
modifyObject
:: (Object -> Bool)A predicate determining which objects to modify. +
-> (Object -> Object)The modification function. +
-> World
-> World
Modify some objects in the world. +
Produced by Haddock version 0.7
addfile ./doc/Util.html hunk ./doc/Util.html 1 + + +Util
 ContentsIndex
Util
Description
This module re-exports everything in the Util.* sub-modules. +
Produced by Haddock version 0.7
addfile ./doc/Verb-Drop.html hunk ./doc/Verb-Drop.html 1 + + +Verb.Drop
 ContentsIndex
Verb.Drop
Description
The drop verb. +
Documentation
cmdDrop
:: VerbShould be Drop. +
-> [String]The name of the item to drop. +
-> World
-> IO World
Produced by Haddock version 0.7
addfile ./doc/Verb-Get.html hunk ./doc/Verb-Get.html 1 + + +Verb.Get
 ContentsIndex
Verb.Get
Description
The get verb. +
Documentation
cmdGet
:: VerbShould be Get. +
-> [String]The name of the item to get. +
-> World
-> IO World
Produced by Haddock version 0.7
addfile ./doc/Verb-Go.html hunk ./doc/Verb-Go.html 1 + + +Verb.Go
 ContentsIndex
Verb.Go
Description
The go verb handles the standard n,s,e,w,u,d directions. +
Synopsis
cmdGo :: Verb -> [String] -> World -> IO World
Documentation
cmdGo
:: VerbShould be Go +
-> [String]Should be empty. +
-> World
-> IO World
Move in some direction. +
Produced by Haddock version 0.7
addfile ./doc/Verb-Inv.html hunk ./doc/Verb-Inv.html 1 + + +Verb.Inv
 ContentsIndex
Verb.Inv
Description
The inv verb. Show the player's inventory. +
Documentation
cmdInv :: Verb -> [String] -> World -> IO World
Produced by Haddock version 0.7
addfile ./doc/Verb-Look.html hunk ./doc/Verb-Look.html 1 + + +Verb.Look
 ContentsIndex
Verb.Look
Description
The look verb. +
Synopsis
cmdLook :: Verb -> [String] -> World -> IO World
Documentation
cmdLook
:: VerbShould be Look. +
-> [String]The name of the item to look at, if empty then we're looking + at the current room. +
-> World
-> IO World
Look at something. + The something could be: the current room, a room detail, + an item in the room, or an item in the inventory of the player. +
Produced by Haddock version 0.7
addfile ./doc/Verb-Special.html hunk ./doc/Verb-Special.html 1 + + +Verb.Special
 ContentsIndex
Verb.Special
Description
Special verbs. + These commands are specific to a particular room or item. +
Synopsis
cmdSpecial :: Verb -> [String] -> World -> IO World
giveGrue :: Maybe ItemId -> Object -> World -> IO World
Documentation
cmdSpecial
:: VerbShould be (VerbSpecial verb) where verb is a string. +
-> [String]Arguments to this verb. +
-> World
-> IO World
giveGrue
:: Maybe ItemIdItem to give to the grue. +
-> ObjectThe player object. +
-> World
-> IO World
Give the grue something. +
Produced by Haddock version 0.7
addfile ./doc/Verb-Type.html hunk ./doc/Verb-Type.html 1 + + +Verb.Type
 ContentsIndex
Verb.Type
Description
The Verb type and parser. +
Synopsis
data Verb
= Look
| Inv
| Get
| Drop
| Go Direction
| VerbSpecial String
parseVerb :: String -> Verb
Documentation
data Verb
The Verb data type. + This type represents the commands which the player can use to + interact with the world. +
Constructors
Look
Inv
Get
Drop
Go Direction
VerbSpecial String
show/hide Instances
Eq Verb
Show Verb
parseVerb :: String -> Verb
Parse a string into a verb. + If the verb is not a standard one like Look, Inv, Get etc then it is + considered special and might be relavent only to a particular room or item. +
Produced by Haddock version 0.7
addfile ./doc/Verb-Util.html hunk ./doc/Verb-Util.html 1 + + +Verb.Util
 ContentsIndex
Verb.Util
Description
Utility functions used by several different verbs. +
Synopsis
showItemList :: World -> [ItemId] -> String
Documentation
showItemList :: World -> [ItemId] -> String
Show a list of item names as a single string. +
Produced by Haddock version 0.7
addfile ./doc/Verb.html hunk ./doc/Verb.html 1 + + +Verb
 ContentsIndex
Verb
Description
This module re-exports everything in the Verb.* submodules. +
Produced by Haddock version 0.7
addfile ./doc/World.html hunk ./doc/World.html 1 + + +World
 ContentsIndex
World
Description
Defines the main types for the game. +
Synopsis
type Name = String
type Script = String
type Inventory = [ItemId]
type Detail = (String, String)
type World = [Object]
data Object
= Mob MobId Name RoomId Inventory
| Room RoomId Name Script [Detail] [(Direction, Exit)] Inventory
| Item ItemId Name Script
| Property PropId Prop
data MobId = Player
data RoomId
= Living
| Bedroom
| Kitchen
| Basement
| Porch
| Path
data Exit
= Exit RoomId
| Door RoomId PropId String
data Direction
= North
| South
| East
| West
| Down
| Up
| Direct String
data ItemId
= ItemUnknown String
| PocketLint
| KeyFrontDoor
| Rope
| Knife
| Amulet
data PropId
= PlayerIsAlive
| FrontDoorUnlocked
| FrontDoorKeyRevealed
data Prop = PropBool Bool
Documentation
type Name = String
The name of something. +
type Script = String
A description of something. +
type Inventory = [ItemId]
An inventory, carried by some Mobile. +
type Detail = (String, String)
A detail of a room. +
type World = [Object]
The world is a list of all the objects in the game. +
data Object
An object in the game world. +
Constructors
Mob MobId Name RoomId InventoryA mobile. Mobiles are players or other creatures + which can carry items and move between rooms. +
Room RoomId Name Script [Detail] [(Direction, Exit)] InventoryA room in the world. +
Item ItemId Name ScriptAn item in the world. +
Property PropId PropSome property of the world. +
show/hide Instances
Eq Object
Show Object
data MobId
ID codes for Mobiles. +
Constructors
Player
show/hide Instances
Eq MobId
Show MobId
data RoomId
Each room in the world has an associated RoomId. +
Constructors
Living
Bedroom
Kitchen
Basement
Porch
Path
show/hide Instances
Eq RoomId
Show RoomId
data Exit
An exit can either be freely passable, or have a door in it. + If it is a Door then the associated property in the World must have the value + (PropBool True) for the player to pass. + If the player tries to pass through a door which is closed, the associated bump + bump string is printed. +
Constructors
Exit RoomId
Door RoomId PropId String
show/hide Instances
Eq Exit
Show Exit
data Direction
An exit direction. (Direct String) can be used to represent a special named + direction, ie not (n,s,e,w,u,d). +
Constructors
North
South
East
West
Down
Up
Direct String
show/hide Instances
data ItemId
Each item in the world has an associated ItemId. +
Constructors
ItemUnknown String
PocketLint
KeyFrontDoor
Rope
Knife
Amulet
show/hide Instances
Eq ItemId
Show ItemId
data PropId
Each property in the world has an associated PropId. +
Constructors
PlayerIsAlive
FrontDoorUnlocked
FrontDoorKeyRevealed
show/hide Instances
Eq PropId
Show PropId
data Prop
Possible properties. +
Constructors
PropBool Bool
show/hide Instances
Eq Prop
Show Prop
Produced by Haddock version 0.7
addfile ./doc/doc-index-A.html hunk ./doc/doc-index-A.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (A)
Amulet
addfile ./doc/doc-index-B.html hunk ./doc/doc-index-B.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (B)
Basement
Bedroom
addfile ./doc/doc-index-C.html hunk ./doc/doc-index-C.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (C)
cmdDrop
cmdGet
cmdGo
cmdInv
cmdLook
cmdSpecial
addfile ./doc/doc-index-D.html hunk ./doc/doc-index-D.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (D)
Detail
Direct
Direction
Door
Down
Drop
addfile ./doc/doc-index-E.html hunk ./doc/doc-index-E.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (E)
East
Exit
1 (Type/Class)
2 (Data Constructor)
addfile ./doc/doc-index-F.html hunk ./doc/doc-index-F.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (F)
FrontDoorKeyRevealed
FrontDoorUnlocked
formatScript
addfile ./doc/doc-index-G.html hunk ./doc/doc-index-G.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (G)
Get
Go
gameItems
gameProperties
gameRooms
getObject
getPlayerInput
giveGrue
addfile ./doc/doc-index-I.html hunk ./doc/doc-index-I.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (I)
Inv
Inventory
Item
ItemId
ItemUnknown
isItem
isMob
isProp
isRoom
itemName
addfile ./doc/doc-index-K.html hunk ./doc/doc-index-K.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (K)
KeyFrontDoor
Kitchen
Knife
addfile ./doc/doc-index-L.html hunk ./doc/doc-index-L.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (L)
Living
Look
addfile ./doc/doc-index-M.html hunk ./doc/doc-index-M.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (M)
Mob
MobId
main
mobAddItem
mobInventory
mobLocation
mobRemoveItem
mobSetLocation
modifyObject
addfile ./doc/doc-index-N.html hunk ./doc/doc-index-N.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (N)
Name
North
addfile ./doc/doc-index-O.html hunk ./doc/doc-index-O.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (O)
Object
addfile ./doc/doc-index-P.html hunk ./doc/doc-index-P.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (P)
Path
Player
PlayerIsAlive
PocketLint
Porch
Prop
PropBool
PropId
Property
parseItem
parseVerb
propBoolGet
propBoolSet
addfile ./doc/doc-index-R.html hunk ./doc/doc-index-R.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (R)
Room
RoomId
Rope
roomAddItem
roomId
roomInventory
roomRemoveItem
addfile ./doc/doc-index-S.html hunk ./doc/doc-index-S.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (S)
Script
South
showItemList
addfile ./doc/doc-index-U.html hunk ./doc/doc-index-U.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (U)
Up
addfile ./doc/doc-index-V.html hunk ./doc/doc-index-V.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (V)
Verb
VerbSpecial
addfile ./doc/doc-index-W.html hunk ./doc/doc-index-W.html 1 + + + (Index)
 ContentsIndex
ABCDEFGIKLMNOPRSUVW
Index (W)
West
World
worldPlayer
worldPlayerLocation
worldPlayerRoom
addfile ./doc/doc-index.html hunk ./doc/doc-index.html 1 + + + (Index)
 ContentsIndex
Index
ABCDEFGIKLMNOPRSUVW
addfile ./doc/haddock.css hunk ./doc/haddock.css 1 +/* -------- Global things --------- */ + +BODY { + background-color: #ffffff; + color: #000000; + font-family: sans-serif; + } + +A:link { color: #0000e0; text-decoration: none } +A:visited { color: #0000a0; text-decoration: none } +A:hover { background-color: #e0e0ff; text-decoration: none } + +TABLE.vanilla { + width: 100%; + border-width: 0px; + /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ +} + +TABLE.vanilla2 { + border-width: 0px; +} + +/* font is a little too small in MSIE */ +TT { font-size: 100%; } +PRE { font-size: 100%; } + +LI P { margin: 0pt } + +TD { + border-width: 0px; +} + +TABLE.narrow { + border-width: 0px; +} + +TD.s8 { height: 8px; } +TD.s15 { height: 15px; } + +SPAN.keyword { text-decoration: underline; } + +/* Resize the buttom image to match the text size */ +IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } + +/* --------- Contents page ---------- */ + +DIV.node { + padding-left: 3em; +} + +DIV.cnode { + padding-left: 1.75em; +} + +SPAN.pkg { + position: absolute; + left: 50em; +} + +/* --------- Documentation elements ---------- */ + +TD.children { + padding-left: 25px; + } + +TD.synopsis { + padding: 2px; + background-color: #f0f0f0; + font-family: monospace + } + +TD.decl { + padding: 2px; + background-color: #f0f0f0; + font-family: monospace; + vertical-align: top; + } + +/* + arg is just like decl, except that wrapping is not allowed. It is + used for function and constructor arguments which have a text box + to the right, where if wrapping is allowed the text box squashes up + the declaration by wrapping it. +*/ +TD.arg { + padding: 2px; + background-color: #f0f0f0; + font-family: monospace; + vertical-align: top; + white-space: nowrap; + } + +TD.recfield { padding-left: 20px } + +TD.doc { + padding-top: 2px; + padding-left: 10px; + } + +TD.ndoc { + padding: 2px; + } + +TD.rdoc { + padding: 2px; + padding-left: 10px; + width: 100%; + } + +TD.body { + padding-left: 10px + } + +TD.pkg { + width: 100%; + padding-left: 10px +} + +TD.indexentry { + vertical-align: top; + padding-right: 10px + } + +TD.indexannot { + vertical-align: top; + padding-left: 20px; + white-space: nowrap + } + +TD.indexlinks { + width: 100% + } + +/* ------- Section Headings ------- */ + +TD.section1 { + padding-top: 15px; + font-weight: bold; + font-size: 150% + } + +TD.section2 { + padding-top: 10px; + font-weight: bold; + font-size: 130% + } + +TD.section3 { + padding-top: 5px; + font-weight: bold; + font-size: 110% + } + +TD.section4 { + font-weight: bold; + font-size: 100% + } + +/* -------------- The title bar at the top of the page */ + +TD.infohead { + color: #ffffff; + font-weight: bold; + padding-right: 10px; + text-align: left; +} + +TD.infoval { + color: #ffffff; + padding-right: 10px; + text-align: left; +} + +TD.topbar { + background-color: #000099; + padding: 5px; +} + +TD.title { + color: #ffffff; + padding-left: 10px; + width: 100% + } + +TD.topbut { + padding-left: 5px; + padding-right: 5px; + border-left-width: 1px; + border-left-color: #ffffff; + border-left-style: solid; + white-space: nowrap; + } + +TD.topbut A:link { + color: #ffffff + } + +TD.topbut A:visited { + color: #ffff00 + } + +TD.topbut A:hover { + background-color: #6060ff; + } + +TD.topbut:hover { + background-color: #6060ff + } + +TD.modulebar { + background-color: #0077dd; + padding: 5px; + border-top-width: 1px; + border-top-color: #ffffff; + border-top-style: solid; + } + +/* --------- The page footer --------- */ + +TD.botbar { + background-color: #000099; + color: #ffffff; + padding: 5px + } +TD.botbar A:link { + color: #ffffff; + text-decoration: underline + } +TD.botbar A:visited { + color: #ffff00 + } +TD.botbar A:hover { + background-color: #6060ff + } + addfile ./doc/haddock.js hunk ./doc/haddock.js 1 +// Haddock JavaScript utilities +function toggle(button,id) +{ + var n = document.getElementById(id).style; + if (n.display == "none") + { + button.src = "minus.gif"; + n.display = "block"; + } + else + { + button.src = "plus.gif"; + n.display = "none"; + } +} addfile ./doc/haskell_icon.gif binary ./doc/haskell_icon.gif oldhex * newhex *47494638376110001000f70f00000000800000008000808000000080800080008080c0c0c08080 *80ff000000ff00ffff000000ffff00ff00ffffffffff0000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *000000000000000000000000000000000000000000000000000000000000000000000000000000 *0021f90401000000002c000000001000100007086c0001007840b0a0418202073e38b0b021c387 *07143e2440c0a143040e091cd0787021c686151f84347800e343901d4b12646870e44a930d0952 *3ca832a6cc990555b2bc2992e4c79d3847ea2c88b3a7c89a2c8b8aa43874e941a60810003840b5 *aa55aa511346ddca75abc080003b addfile ./doc/index.html hunk ./doc/index.html 1 + + +
 ContentsIndex
Modules
Format
show/hideGame
Game.Item
Game.Property
Game.Room
Main
show/hideUtil
Util.Item
Util.Mobile
Util.Property
Util.Room
Util.World
show/hideVerb
Verb.Drop
Verb.Get
Verb.Go
Verb.Inv
Verb.Look
Verb.Special
Verb.Type
Verb.Util
World
Produced by Haddock version 0.7
addfile ./doc/minus.gif binary ./doc/minus.gif oldhex * newhex *47494638396109000900910000fefefe8282820202020000002c00000000090009000002118c8f *a00bc6eb5e0b40583b6596f1a11f14003b addfile ./doc/plus.gif binary ./doc/plus.gif oldhex * newhex *47494638396109000900910000fefefe8282820202020000002c00000000090009000002148c8f *a00bb6b29c82ca897b5b7871cfce74085200003b addfile ./src/Format.hs hunk ./src/Format.hs 1 +-- | Formatting utils. +module Format where + +import System.IO + +maxCol = 60 +format = formatScript maxCol + +-- | Format a description so it fits nicely in the given number of screen columns. +formatScript :: Int -> String -> String +formatScript maxCol xx + = " " ++ formatScript' maxCol 0 xx + +formatScript' _ _ [] = [] +formatScript' maxCol _ ('\n':xs) = "\n " ++ formatScript' maxCol 0 xs + +formatScript' maxCol curCol (' ':xs) + | curCol > maxCol = "\n " ++ formatScript' maxCol 0 xs + | otherwise = ' ' : formatScript' maxCol (curCol + 1) xs + +formatScript' maxCol curCol (x:xs) = x : formatScript' maxCol (curCol + 1) xs + + + + addfile ./src/Game/Item.hs hunk ./src/Game/Item.hs 1 +-- | Defines the initial items in the game. + +module Game.Item where + +import World +import Util.World + +-- | Parse an item name into an item descriptor. +parseItem :: String -> Maybe ItemId +parseItem str + = case str of + "key" -> Just KeyFrontDoor + "amulet" -> Just Amulet + "rope" -> Just Rope + "knife" -> Just Knife + "lint" -> Just PocketLint + "fan" -> Just Fan + "fusebox" -> Just Fusebox + "lantern" -> Just Lantern + "jar" -> Just JamJar + "iguana" -> Just Iguana + _ -> Nothing + + +-- | The initial items in the game. +gameItems :: [Object] +gameItems + = [ Item PocketLint + "lint" + (script "Some pocket lint.") + (script "Just regular pocket lint, not very interesting.") + + , Item KeyFrontDoor + "key" + (script "An iron key.") + (script "The key is well worn and you see traces of oil at the base.") + + , Item Rope + "rope" + (script "A rope.") + (script "This rope has been left outside for too long and is beginning to rot.") + + , Item Knife + "knife" + (script "A gleaming kitchen knife.") + (script "It looks sharp, be careful not to cut yourself.") + + , Item Amulet + "amulet" + (script "A jade amulet.") + (script "The pretty jade amulet has the shape of some kind of aquarium fish. When you turn it over you see \ + \the number '1100' inscribed on the back. ") + + , Item Fan + "fan" + (scriptPropBool PFanOn + "A four bladed electric fan is attached to the cavern wall by large steel bolts. The fan is humming loudly." + "A four bladed electric fan is attached to the cavern wall by large steel bolts.") + + + (scriptPropBool PFanOn + "Further inspection reveals that a tiny rock has fallen into the fan and become wedged between the \ + \fan blades and their outer casing. The electric fan motor has stalled and is humming loudly as it \ + \tries to turn." + + "A tiny rock has fallen into the fan and become wedged between the fan blades and their outer casing.") + + , Item Fusebox + "fusebox" + (script "A fusebox is attached to the wall next to the door.") + (script "You look inside the fusebox and discover a single circuit breaker.") + + , Item Lantern + "lantern" + (script "An electric lantern.") + (script "The lantern is made from plastic.") + + + , Item JamJar + "jamjar" + (script "A small jar of strawberry jam.") + (script "mmmm tasty!") + + , Item Iguana + "iguana" + (script "A green iguana eyes you warily.") + (script "The iguana peers back at you.") + + ] + + + addfile ./src/Game/Property.hs hunk ./src/Game/Property.hs 1 +-- | Defines the initial properties in the game. + +module Game.Property where + +import World + + +-- | The initial properties in the game, and their states. +gameProperties :: [Object] +gameProperties + = [ Property PPlayerMoves (PropInt 0) + , Property PlayerHasQuit (PropBool False) + , Property PlayerIsAlive (PropBool True) + + , Property FrontDoorKeyRevealed (PropBool False) + , Property FrontDoorUnlocked (PropBool False) + + , Property PGrateOpen (PropBool False) + + , Property PFanAttached (PropBool True) + , Property PFanOn (PropBool True) + + , Property PGrueHunger (PropInt 0) + + , Property PIguanaWaitCount (PropInt 0) + , Property PIguanaRoom (PropRoomId Living) ] addfile ./src/Game/Room.hs hunk ./src/Game/Room.hs 1 +-- | Defines the initial rooms in the game. + +module Game.Room where + +import World +import Util.World +import Util.Property + +-- | The initial rooms in the game. +gameRooms :: [Object] +gameRooms + = [ Room Path + "Forest Path" + + (script "You are on a narrow path leading through the forest. It's autumn and the path is covered in golden \ + \leaves which crunch underfoot. A letterbox sits atop a post on the edge of the path, and you see a \ + \small white house to the south. It smells like it's going to rain.") + + [ ( "path" + , "The dirt path looks like it has been worn into the forest floor by many generations of \ + \trampling computer science students.") + + , ( "forest" + , "The trees seem wise and knowing.") + + , ( "leaves" + , "The dry autumn leaves are golden yellow. They crunch as you step on them.") + + , ( "house" + , "It looks like it needs a new coat of paint.") + + , ( "letterbox" + , "The letterbox has a shiny brass numeral '5' attached to it.") + + ] + + + [(South, Exit Porch)] + + [] + + + , Room Porch + "Front Porch" + + (script "You are on the front porch of a small single story house which has been nestled in amongst the forest \ + \trees. A rickety wooden chair stands next to the front door which leads inside to the east. \ + \A path leads through the forest to the north and you can hear crickets chirping in the distance.") + + [ ( "house" + , "The white paint covering the house is flaking off.") + + , ( "porch" + , "The porch is made from old wooden slats and is worn down near the front door.") + + , ( "forest" + , "A long time ago someone cut down some of the trees to make a clearing for the house. \ + \You see old tree stumps scattered about.") + + , ( "chair" + , "It's an old upholstered office chair which has seen better days. The leather covering the seat \ + \is cracked and you can see the springs inside.") + + , ( "door" + , "The front door has a lock near the handle. You'll need the key.") + + , ( "path" + , "You see footprints in the dust.") + + , ( "footprints" + , "They're about the same size as the shoes you are wearing.") + + , ( "crickets" + , "They're hiding under the leaf litter. You can hear them but you can't see them.") + + ] + + [ (North, Exit Path) + , (East, Door Living FrontDoorUnlocked "The front door is locked.\n")] + + [Rope] + + + , Room Living + "Living Room" + + (script "You are standing in a small living room inside a house in the forest. The walls have been covered \ + \in a floral wall paper which matches the curtains covering the window to the west. There is a door \ + \to the west and through the window you can see that it leads to the front porch. A door leads to the \ + \bedroom in the east, and there is a cramped kitchenette to the south.") + + [ ( "walls" + , "The wall paper design incorporates images of roses and thistle.") + + , ( "curtains" + , "The curtains are a deep red, the same color as the roses on the walls.") + + , ( "window" + , "It's a large picture window, through it you see the front porch and the forest outside.") + + , ( "breaker" + , "The circuit breaker isn't labeled, but you could switch it if you wanted to.") + + , ( "circuit" + , "The circuit breaker isn't labeled, but you could switch it if you wanted to.") + + ] + + [ (West, Door Porch FrontDoorUnlocked "The front door is locked.\n") + , (East, Exit Bedroom) + , (South, Exit Kitchen)] + + [Fusebox, Iguana] + + + , Room Kitchen + "Kitchen" + + (scriptPropBool PFanOn + "You are in a cramped kitchen at the end of the living room, which lies to the north. A long kitchen bench \ + \stands in the middle of the room and the odor of lemon soap is in the air. There is a door \ + \in the east wall which looks like it would lead to the basement.\n\ + \You hear a faint humming sound." + + "You are in a cramped kitchen at the end of the living room, which lies to the north. A long kitchen bench \ + \stands in the middle of the room and the odor of lemon soap is in the air. There is a door \ + \in the east wall which looks like it would lead to the basement.") + + [ ( "bench" + , "The bench is covered by light green tiles. The tiles are \ + \wet and look like someone has recently cleaned them." ) + + , ( "door" + , "The basement door has a large iron bar across it, but you could lift it and pass through." ) + ] + + + [ (North, Exit Living) + , (East, Exit Basement)] + + [Knife] + + + , Room Bedroom + "Bedroom" + + (script "You are in a small bedroom. There is a double bed in the center of the room which is covered by a \ + \freshly laundered floral quilt. You can see the autumn forest through the window in the northern \ + \wall. A door leads back to the living room to the west.") + + [ ( "bed" + , "The double bed has been freshly made.") + + , ( "wall" + , "The wall has the same rose and thistle wall paper you saw in the living room.") + ] + + [ (West, Exit Living)] + + [Amulet] + + + , Room Basement + "Basement" + + (scriptPropBool PFanOn + "You are standing in the basement of the house. The walls are lined with shelves full of what looks \ + \to be home-made fruit jam. There are a set of stairs which lead up into the house and there is an \ + \iron grate leading down through the floor.\n\ + \There is a loud humming sound which seems to be coming from under the floor.\n\ + \There is a grue here." + + "You are standing in the basement of the house. The walls are lined with shelves full of what looks \ + \to be home-made fruit jam. There are a set of stairs which lead up into the house and there is an \ + \iron grate in the floor.\n\ + \There is a grue here.") + + [ ( "walls" + , "The walls are made from big blocks of grey stone. The stone is covered in dust and is crumbling \ + \in some places.") + + , ( "shelves" + , "The wooden shelves are stacked with jars of fruit jam") + + , ( "jam" + , "The jam looks thick, red and tasty. Strawberry perhaps?") + + , ( "stairs" + , "They lead back up into the kitchen.") + + , ( "floor" + , "The floor is made from shiny white tiles. The tiles look new, which seems odd in contrast with \ + \the old stone walls.") + + , ( "grue" + , "It looks anxious, like it wants something.") + + , ( "grate" + , "The iron grate looks unfinished. You're not sure where it would lead." ) + ] + + [ (West, Exit Kitchen) + , (Up, Exit Kitchen) + , (Down, Door Cavern PGrateOpen "The iron grate is closed.\n") ] + + [] + + , Room Cavern + "Cavern" + + (script "You are crouching in a small, rough-hewn cavern. From the marks on the walls it looks like this cavern was \ + \hollowed out manually by someone with a pick-axe. An iron grate leads up to the basement above you and a \ + \narrow shaft has been cut into the wall to the east. ") + + [] + + [ (Up, Exit Basement) + , (East, Exit Shaft) ] + + [Fan] + + , Room Shaft + "Shaft" + + (script "You are crawling on your hands and knees through a tunnel which extends away from a cavern to the west. \ + \Old pieces of rock and stone jut out of the walls around you and you have to keep your head down to avoid \ + \bumping it on the uneven ceiling. You think you can see a blur of blue light further down the tunnel to the \ + \east.") + + [] + + [ (West, Exit Cavern) + , (East, Exit Sewer) ] + + [] + + , Room Sewer + "Sewer" + + (script "You are in what looks to be an old, dry sewer tunnel.") + + [] + + [ (West, Exit Shaft) ] + + [Lantern] + + ] + addfile ./src/IO.hs hunk ./src/IO.hs 1 + +module IO where + +import System.IO + +type State = Handle + + +initState = stdout + +out :: State -> String -> IO () +out state str + = putStr str addfile ./src/Main.hs hunk ./src/Main.hs 1 +-- | Contains the user interaction loop. + +module Main where + +import Verb +import World +import Format +import Util + +import Game.Item +import Game.Room +import Game.Property + +import System.IO +import System.Time +import System.Environment +import System.Console.GetOpt + +import Data.List + +import Control.Monad.State +import State + +import Network +import Network.BSD +import Network.Socket hiding (accept) + +import Control.Concurrent + +-- | The initial state of the world. +initWorld :: World +initWorld + = [Mob Player "Molly" Path [PocketLint]] + ++ gameRooms + ++ gameItems + ++ gameProperties + + +-- | This banner is displayed when the program starts up. +banner :: String +banner = "\n\n" + ++ " +-------------------------------------------------------------------+\n" + ++ " | COMP1100 ANU An Augmented Adventure UNA 0011PMOC |\n" + ++ " | S2/2006 DEMO 6002\\2S |\n" + ++ " +-------------------------------------------------------------------+\n" + ++ " type help for help\n" + +data Flag + = FAddr String + | FPort String + deriving (Show) + +isFAddr (FAddr _) = True +isFAddr _ = False + +isFPort (FPort _) = True +isFPort _ = False + +-- | Program entry point. +main :: IO () +main + = do args <- getArgs + + let (flags, _, unrec) + = getOpt Permute + [ Option ['a'] ["address"] (ReqArg FAddr "ADDR") "server ADDR" + , Option ['p'] ["port"] (ReqArg FPort "PORT") "server PORT" ] + args + + addr <- netChooseAddr flags + port <- netChoosePort flags + + netInit addr port + return () + + +netChooseAddr :: [Flag] -> IO (Maybe HostAddress) +netChooseAddr flags + | Just (FAddr strAddr) <- find isFAddr flags + = do addr <- inet_addr strAddr + return $ Just addr + + | otherwise + = return Nothing + + +netChoosePort :: [Flag] -> IO PortNumber +netChoosePort flags + | Just (FPort strPort) <- find isFPort flags + = do let port = fromIntegral (read strPort :: Int) + return port + + | otherwise + = return 4000 + + +netInit :: Maybe HostAddress -> PortNumber -> IO () +netInit maddr port + | Just addr <- maddr + = do + addrStr <- inet_ntoa addr + + -- make a new socket and bind it to the given address + s <- socket AF_INET Stream 0 + bindSocket s (SockAddrInet port addr) + + + setSocketOption s ReuseAddr 1 + + -- listen on the socket + listen s 5 + + outLog $ "AAdvent startup" + outLog $ " addr = " ++ addrStr + outLog $ " port = " ++ show port + + netIdle s + + | otherwise + = do + s <- listenOn (PortNumber port) + setSocketOption s ReuseAddr 1 + + outLog $ "AAdvent startup" + outLog $ " port = " ++ show port + + netIdle s + + + +netIdle :: Socket -> IO () +netIdle socket + = do + (handle, hostName, hostPort) + <- liftIO $ accept socket + + outLog $ "Accepted connection from " ++ hostName ++ ":" ++ show hostPort + + -- Fork a new game. + tid <- forkOS (mainIO handle hostName hostPort) + + netIdle socket + + +outLog :: String -> IO () +outLog str + = do + time <- timeString + putStr $ "* " ++ time ++ " - " ++ str ++ "\n" + hFlush stdout + + + +mainIO :: Handle -> HostName -> PortNumber -> IO () +mainIO handle hostName portNumber + = do + tid <- myThreadId + + let state = (stateInit initWorld) + { stateHandleOut = handle + , stateHandleIn = handle + , stateHostName = Just hostName + , stateHostPort = Just portNumber } + + runStateT mainAM state + + outLog $ "Disconnect from " ++ hostName ++ ":" ++ show portNumber + hClose handle + + +timeString :: IO String +timeString + = do + clock <- getClockTime + calTime <- toCalendarTime clock + let str = calendarTimeToString calTime + + return str + + +mainAM :: AM () +mainAM + = do -- display the startup banner. + out banner + + -- perform a look so the player sees the room that they're in from the start. + command Look [] initWorld + + -- enter the main interaction loop. + getInput + + +-- | Get commands from the user and use them to change the world. +getInput :: AM () +getInput + = do + -- print the prompt + out ("> ") + outFlush + + -- get a command from the player + mInput <- getPlayerLine + getInput2 mInput + + +getInput2 mInput + + -- player has disconnected + | Nothing <- mInput + = return () + + -- got a command + | Just line <- mInput + = do + -- run the command + world <- gets stateWorld + handleInput world line + world' <- gets stateWorld + + -- check if the player has quit, otherwise get another command. + if (propBoolGet (getObject (isProp PlayerHasQuit) world')) + then return () + else getInput + + +-- | Handles a player command. +-- The player may not perform any actions whilst dead. +-- All commands have the form: \ [args..] +-- +handleInput :: World -> String -> AM () +handleInput world input + + -- If the command line was empty, leave the world as it was. + | [] <- ww + = return () + + -- If the player is not alive, then they can't do anything besides quit + | not $ propBoolGet (getObject (isProp PlayerIsAlive) world) + = do out "You can't do anything when you're dead!\n\n" + return () + + -- If they are alive they can run a command + | (w:ws) <- ww + = do world <- getWorld + command (parseVerb w) ws world + + -- pulse the world + world' <- gets stateWorld + worldPulse world + + -- Break up the command into individual words. + where ww = words input + + + +-- | Use the verb to decide what function to call to handle the command. +-- +command :: Verb -> [String] -> World -> AM () + +command verb ss world + = case verb of + Look -> cmdLook verb ss world + Go _ -> cmdGo verb ss world + Get -> cmdGet verb ss world + Drop -> cmdDrop verb ss world + Inv -> cmdInv verb ss world + Use -> cmdUse verb ss world + + VerbSpecial str + -> cmdSpecial verb ss world + + +worldPulse :: World -> AM () +worldPulse world + = do + -- increment the player move count + modifyWorld $ modifyObject + (isProp PPlayerMoves) + propIntInc + + -- + worldPulse_Iguana + + +worldPulse_Iguana :: AM () +worldPulse_Iguana + = do + -- increment the iguana wait count + modifyWorld $ modifyObject + (isProp PIguanaWaitCount) + propIntInc + + -- check if it's time for it to move + world <- gets stateWorld + let count = propIntGet (getObject (isProp PIguanaWaitCount) world) + + -- if we can see the iguana, it blinks + let playerRoom = worldPlayerLocation world + + when (count > 5) + $ do modifyWorld $ modifyObject + (isProp PIguanaWaitCount) + (propIntMod (\x -> 0)) + + when (playerRoom == Living) + $ do out $ "The iguana blinks.\n\n" + + + + + + + + + addfile ./src/State.hs hunk ./src/State.hs 1 + +module State where + +import World + +import Network +import System.IO +import Control.Monad.State + +type AM = StateT AdventS IO + + +data AdventS + = AdventS + { stateWorld :: World + , stateHandleOut :: Handle + , stateHandleIn :: Handle + , stateHostName :: Maybe HostName + , stateHostPort :: Maybe PortNumber } + + +stateInit world + = AdventS + { stateWorld = world + , stateHandleOut = stdout + , stateHandleIn = stdin + , stateHostName = Nothing + , stateHostPort = Nothing } + + + + + +out :: String -> AM () +out str + = do state <- get + let str' = crlf str + liftIO (hPutStr (stateHandleOut state) str') + +crlf :: String -> String +crlf ('\n':xs) = '\r' : '\n' : crlf xs +crlf (x:xs) = x : crlf xs +crlf [] = [] + + + +outFlush :: AM () +outFlush + = do state <- get + liftIO (hFlush (stateHandleOut state)) + + + +getWorld :: AM World +getWorld + = do state <- get + return $ stateWorld state + + +setWorld :: World -> AM () +setWorld world + = do state <- get + put (state { stateWorld = world }) + return () + + +modifyWorld :: (World -> World) -> AM () +modifyWorld f + = do state <- get + let world' = f (stateWorld state) + put $ state { stateWorld = world' } + return () + + + +-- | Get a line from the player. +-- We get the charaters one at a time so we can handle the backspace key +-- correctly. +getPlayerLine :: AM (Maybe String) +getPlayerLine + = getPlayerLine2 [] + + +getPlayerLine2 :: String -> AM (Maybe String) +getPlayerLine2 prev + = do hIn <- gets stateHandleIn + + eof <- liftIO $ hIsEOF hIn + + if eof + then return Nothing + else do + c <- liftIO $ hGetChar hIn + getPlayerLineC prev c + + +getPlayerLineC :: String -> Char -> AM (Maybe String) +getPlayerLineC prev c + | '\n' <- c + = return $ Just prev + + | elem c ['\DEL', '\b'] + , prev == [] + = do hOut <- gets stateHandleOut + + liftIO $ hPutStr hOut "\DEL " + liftIO $ hFlush hOut + getPlayerLine2 prev + + | elem c ['\DEL', '\b'] + , prev /= [] + = do + hOut <- gets stateHandleOut + + liftIO $ hPutStr hOut "\DEL \b" + liftIO $ hFlush hOut + getPlayerLine2 (init prev) + + | otherwise + = do + getPlayerLine2 (prev ++ [c]) + + + + + + + addfile ./src/Util.hs hunk ./src/Util.hs 1 +-- | This module re-exports everything in the Util.* sub-modules. +module Util + ( module Util.Mobile + , module Util.Room + , module Util.Item + , module Util.Property + , module Util.World) +where + +import Util.Mobile +import Util.Room +import Util.Item +import Util.Property +import Util.World + + + + + + + addfile ./src/Util/Item.hs hunk ./src/Util/Item.hs 1 +-- | Utils for Items. + +module Util.Item where + +import World + +-- | Checks if some object is an Item with a specific ItemId. +isItem :: ItemId -> Object -> Bool +isItem itemId (Item id _ _ _) = itemId == id +isItem _ _ = False + +-- | Get the name of an item. +itemName :: Object -> Name +itemName (Item id name short long) = name + + +-- | Get the short description of an item. +itemShort :: Object -> (World -> Script) +itemShort (Item id name short long) = short addfile ./src/Util/Mobile.hs hunk ./src/Util/Mobile.hs 1 +-- | Utils for Mobiles. + +module Util.Mobile where + +import Data.List +import World + +-- | Checks if some object is a Mobile with a specific MobileId. +isMob :: MobId -> Object -> Bool +isMob mobId (Mob id _ _ _) = mobId == id +isMob _ _ = False + +-- | Sets the location of a mobile. +mobSetLocation :: RoomId -> Object -> Object +mobSetLocation roomId' (Mob mobId name roomId inv) + = Mob mobId name roomId' inv + +-- | Adds an item to a mobiles inventory. +mobAddItem :: ItemId -> Object -> Object +mobAddItem + itemId (Mob mobId name loc inv) + = (Mob mobId name loc (itemId : inv)) + +-- | Removes an item from a mobiles inventory. +mobRemoveItem :: ItemId -> Object -> Object +mobRemoveItem + itemId (Mob mobId name loc inv) + = (Mob mobId name loc (delete itemId inv)) + +-- | Get the location of a mobile. +mobLocation :: Object -> RoomId +mobLocation (Mob _ _ loc _ ) = loc + +-- | Get the inventory of a mobile. +mobInventory :: Object -> [ItemId] +mobInventory (Mob _ _ _ inv) = inv addfile ./src/Util/Property.hs hunk ./src/Util/Property.hs 1 +-- | Utils for properties. + +module Util.Property where + +import World + + +-- | Checks if some object is a Property with a specific PropId. +isProp :: PropId -> Object -> Bool +isProp propId (Property id _) = propId == id +isProp _ _ = False + + +-- | Sets a Boolean property. +propBoolSet :: Bool -> Object -> Object +propBoolSet newVal (Property propId (PropBool val)) + = (Property propId (PropBool newVal)) + +-- | Flips a Boolean property. +propBoolFlip :: Object -> Object +propBoolFlip (Property propId (PropBool val)) + = (Property propId (PropBool (not val))) + +-- | Gets a Boolean property. +propBoolGet :: Object -> Bool +propBoolGet (Property _ (PropBool val)) = val + + +propIntInc :: Object -> Object +propIntInc (Property propId (PropInt i)) + = Property propId (PropInt (i+1)) + +propIntGet :: Object -> Int +propIntGet (Property _ (PropInt val)) = val + + +propIntMod :: (Int -> Int) -> Object -> Object +propIntMod f (Property propId (PropInt i)) + = Property propId (PropInt (f i)) addfile ./src/Util/Room.hs hunk ./src/Util/Room.hs 1 +-- | Utils for rooms. + +module Util.Room where + +import Data.List +import World + +-- | Checks if some object is a Room with a specific RoomId. +isRoom :: RoomId -> Object -> Bool +isRoom roomId (Room id _ _ _ _ _) = roomId == id +isRoom _ _ = False + + +-- | Get the RoomId from a room. +roomId :: Object -> RoomId +roomId (Room id name script details exits items) = id + +-- | Get the inventory of a room. +roomInventory :: Object -> [ItemId] +roomInventory (Room id name script details exits items) = items + +-- | Add an item to a room. +roomAddItem :: ItemId -> Object -> Object +roomAddItem + itemId (Room roomId name script details exits items) + = (Room roomId name script details exits (itemId : items)) + +-- | Remove an item from a room. +roomRemoveItem :: ItemId -> Object -> Object +roomRemoveItem + itemId (Room roomId name script details exits items) + = (Room roomId name script details exits (delete itemId items)) + + +roomRemoveDetail :: String -> Object -> Object +roomRemoveDetail name room + | Room id name script details exits items <- room + = let details'= filter (\(d, s) -> d /= name) details + in Room id name script details' exits items + + + + +roomAddDetail :: (String, String) -> Object -> Object +roomAddDetail det + (Room id name script details exits items) + = (Room id name script (det : details) exits items) + + addfile ./src/Util/World.hs hunk ./src/Util/World.hs 1 +-- Utils for the World. + +module Util.World where + +import Data.List + +import World +import State +import Util.Mobile +import Util.Room +import Util.Property + + +-- | Get the player object from the world. +worldPlayer :: World -> Object +worldPlayer world = getObject (isMob Player) world + + +-- | Determine what room the player is in and get that object from the world. +worldPlayerRoom :: World -> Object +worldPlayerRoom world = room + where (Mob id name loc inv) = getObject (isMob Player) world + room = getObject (isRoom loc) world + + +-- | Return the RoomId of the room that the player is currently in. +worldPlayerLocation :: World -> RoomId +worldPlayerLocation world = loc + where (Mob id name loc inv) = getObject (isMob Player) world + + +-- | Use a predicate to get some object from the world. +getObject + :: (Object -> Bool) + -> World + -> Object + +getObject idFun world + | Just obj <- find idFun world + = obj + + +-- | Modify some objects in the world. +modifyObject + :: (Object -> Bool) -- ^ A predicate determining which objects to modify. + -> (Object -> Object) -- ^ The modification function. + -> World -> World + +modifyObject hasId modFun (o:os) + | hasId o + = modFun o : os + + | otherwise + = o : modifyObject hasId modFun os + + + +-- | Kill the player +playerKill :: World -> AM () +playerKill world + = modifyWorld $ modifyObject + (isProp PlayerIsAlive) + (propBoolSet False) + + + +script :: Script -> World -> Script +script str world = str + + +scriptPropBool :: PropId -> Script -> Script -> World -> Script +scriptPropBool propId s1 s2 world + | propBoolGet (getObject (isProp propId) world) + = s1 + + | otherwise + = s2 + + addfile ./src/Verb.hs hunk ./src/Verb.hs 1 +-- | This module re-exports everything in the Verb.* submodules. + +module Verb + ( module Verb.Type + , module Verb.Look + , module Verb.Go + , module Verb.Inv + , module Verb.Get + , module Verb.Drop + , module Verb.Use + , module Verb.Special ) +where + +import Verb.Type +import Verb.Look +import Verb.Go +import Verb.Inv +import Verb.Get +import Verb.Drop +import Verb.Use +import Verb.Special + + addfile ./src/Verb/Drop.hs hunk ./src/Verb/Drop.hs 1 +-- | The drop verb. + +module Verb.Drop +where + +import Verb.Type +import Game.Item +import World +import Util +import State + +-- Drop a carried item into the current room. +cmdDrop :: Verb -- ^ Should be Drop. + -> [String] -- ^ The name of the item to drop. + -> World -> AM () + +cmdDrop Drop [itemName] world + | Just itemId <- parseItem itemName + , player <- getObject (isMob Player) world + , roomId <- mobLocation player + , elem itemId (mobInventory player) + = do + -- remove the item from the player's inventory. + modifyWorld $ modifyObject + (isMob Player) + (mobRemoveItem itemId) + + -- add the item to the current room. + modifyWorld $ modifyObject + (isRoom roomId) + (roomAddItem itemId) + + out "ok.\n\n" + + -- you can't drop items you don't have. + | otherwise + = do out "You don't have that.\n\n" + + + +cmdDrop Drop _ world + = do + -- an item name wasn't given.. + out "What do you want to drop?.\n\n" addfile ./src/Verb/Get.hs hunk ./src/Verb/Get.hs 1 +-- | The get verb. + +module Verb.Get +where + +import Verb.Type +import Game.Item +import World +import Util +import Verb.Util +import State + +-- Get an item from the current room. +cmdGet :: Verb -- ^ Should be Get. + -> [String] -- ^ The name of the item to get. + -> World -> AM () + +cmdGet Get [itemName] world + + -- Don't let the player get anything if the room is dark + | worldRoomIsDark world + = do out $ "It's too dark, you can't see anything!\n\n" + + + -- Cavern: don't let the player get the fan from the wall if it's still attached + | Just Fan <- parseItem itemName + , propBoolGet (getObject (isProp PFanAttached) world) + = do out $ "The fan is attached firmly to the wall.\n\n" + + + -- Living: don't let the player have the fusebox + | Just Fusebox <- parseItem itemName + = do out $ "The fusebox is attached firmly to the wall.\n\n" + + -- Iguana: you can't get the iguana when its not tame. + | Just Iguana <- parseItem itemName + = do out $ "The iguana hisses at you and scurries out of reach.\n\n" + + -- Successful item pickup + | Just itemId <- parseItem itemName + , loc <- mobLocation (getObject (isMob Player) world) + , elem itemId (roomInventory (getObject (isRoom loc) world)) + = do + -- remove the item from the current room. + modifyWorld $ modifyObject + (isRoom loc) + (roomRemoveItem itemId) + + -- add the item to the player's inventory. + modifyWorld $ modifyObject + (isMob Player) + (mobAddItem itemId) + + out $ "ok.\n\n" + + -- Item isn't in this room. + | otherwise + = do out $ "It's not here.\n\n" + + +cmdGet Get _ world + = do + -- an item name wasn't given.. + out $ "What do you want to get?.\n\n" addfile ./src/Verb/Go.hs hunk ./src/Verb/Go.hs 1 +-- | The go verb handles the standard n,s,e,w,u,d directions. + +module Verb.Go +where + +import Verb.Type +import Verb.Look + +import World +import Util + +import State + +-- | Move in some direction. +cmdGo :: Verb -- ^ Should be Go + -> [String] -- ^ Should be empty. + -> World -> AM () + +cmdGo (Go dir) _ world + + -- if there is no an exit in the requested direction then print an error message. + | Nothing <- lookup dir exits + = do out "You can't go that way!\n\n" + return () + + + -- requested direction has an exit associated with it. + | Just (Exit newRoom) <- lookup dir exits + = do + -- change the location of the player. + modifyWorld $ modifyObject + (isMob Player) + (mobSetLocation newRoom) + + -- do a look so the player can see where they are. + world' <- getWorld + cmdLook Look [] world' + return () + + + -- requested direction has a door in it. + -- the player can only pass through if it's open. + -- + | Just (Door newRoom propId blockedStr) <- lookup dir exits + , Property _ (PropBool isOpen) + <- getObject (isProp propId) world + + = if isOpen + then do + -- the door is open. move the player. + modifyWorld $ modifyObject + (isMob Player) + (mobSetLocation newRoom) + + -- do a look so the player can see where they are. + world' <- getWorld + cmdLook Look [] world' + return () + + else do + -- the door is closed, print the bump message. + out $ blockedStr ++ "\n" + return () + + where (Room roomId name script details exits items) + = worldPlayerRoom world + + + + + + + + + + + addfile ./src/Verb/Inv.hs hunk ./src/Verb/Inv.hs 1 +-- | The inv verb. Show the player's inventory. + +module Verb.Inv +where + +import Verb.Type +import Verb.Util + +import World +import Util +import Format +import State + + +cmdInv :: Verb -- Should be Inv. + -> [String] -- Should be empty. + -> World -> AM () + +cmdInv Inv _ world + | Mob _ _ _ inv <- worldPlayer world + = do out " Items carried:\n" + out (format $ showItemList world inv) + out "\n" + + + + addfile ./src/Verb/Look.hs hunk ./src/Verb/Look.hs 1 +-- | The look verb. + +module Verb.Look where + +import Verb.Type +import Verb.Util +import Game.Item + +import World +import Format +import Util +import State + +import Control.Monad (when) + + + +-- | Look at something. +-- The something could be: the current room, a room detail, +-- an item in the room, or an item in the inventory of the player. +-- +cmdLook :: Verb -- ^ Should be Look. + -> [String] -- ^ The name of the item to look at, if empty then we're looking + -- at the current room. + -> World -> AM () + + +-- Look at something +-- could be: a room detail, an item in the room, or a carried item. +-- +cmdLook Look [name] world + + + | worldRoomIsDark world + = do out $ "It's too dark!\n\n" + + -- Look at an item in this room, or being carried. + | Just itemId <- parseItem name + + , player <- getObject (isMob Player) world -- get the player object, + , playerInv <- mobInventory player -- and find out what items are being carried. + + , room <- worldPlayerRoom world -- lookup the current room, + , roomInv <- roomInventory room -- and find out what items are in it. + + , elem itemId playerInv || elem itemId roomInv -- check if the requested item is visible. + , Item _ _ _ script + <- getObject (isItem itemId) world -- if so, look up its description. + = do + out $ format (script world) ++ "\n\n" + return () + + + -- Look at a detail in the room + | room <- worldPlayerRoom world -- lookup the current room, + , Room _ _ _ details _ _ <- room -- and find out what details are visible + , Just script <- lookup name details -- then check if there is a room detail with this name. + = do + out $ format script ++ "\n\n" + return () + + + -- There's nothing visible to the player which has the requested name. + | otherwise + = do + out $ "There is no " ++ name ++ " here.\n\n" + return () + + +-- If no arguments are given to the look verb, then show +-- the description of the current room. +-- +cmdLook Look _ world + + -- see if the current room is dark. + | worldRoomIsDark world + = do + out $ "\n* A dark room.\n" + let str = "There is no light in this room. You stumble about but you can't see anything. You are \ + \likely to be eaten by a grue.\n" + + out $ format str ++ "\n" + return () + + + -- lookup the current room. + | Room id name sc details exits items + <- worldPlayerRoom world + = do + -- print the room name. + out $ "\n* " ++ name ++ "\n" + + -- if we're using the lantern, print a warning message) + when (worldRoomIsIlluminated world) + $ out " You look around this dark room with your electric lantern...\n" + + -- print the room description. + out $ format (sc world) ++ "\n" + + -- if there are items in the room, print them. + when (items /= []) + (do out "\n Items here:\n" + out $ format (showItemList world items)) + + out "\n" + + return () + addfile ./src/Verb/Special.hs hunk ./src/Verb/Special.hs 1 +-- | Special verbs. +-- These commands are specific to a particular room or item. + +module Verb.Special where + +import System.Exit + +import Verb.Type +import Verb.Util + +import Game.Item +import World +import Util +import State +import Control.Monad.State + +-- Perform a special action. +cmdSpecial + :: Verb -- ^ Should be (VerbSpecial verb) where verb is a string. + -> [String] -- ^ Arguments to this verb. + -> World -> AM () + +cmdSpecial (VerbSpecial verb) ss world + + -- end the game + | elem verb ["quit"] + = do out "GoodBye, adventurer.\n\n" + modifyWorld $ modifyObject + (isProp PlayerHasQuit) + (propBoolSet True) + + + + + -- Get command help + | verb == "help" + = do out "\n* Commands ------------------------------------------------- \n\ + \ help Get this help.\n\ + \ quit Quit the game.\n\ + \ n, s, e, w, u, d Move in a certain direction.\n\ + \ look Look at your surroundings.\n\ + \ look Look at a certain thing.\n\ + \ inv Check your inventory.\n\ + \ get Pick something up.\n\ + \ drop Drop something on the floor.\n\ + \ open Open something.\n\ + \ unlock Unlock something.\n\ + \ kill Try and kill something.\n\ + \ give Give an item away.\n\ + \ switch Switch something.\n\ + \ use Use something on something else.\n\n" + + -- Get move count + | verb == "moves" + = do let moves = propIntGet (getObject (isProp PPlayerMoves) world) + out $ "You have made " ++ show moves ++ " moves.\n" + + -- Basement: Try and kill the grue. + -- Trying to kill the grue is a bad idea. + -- The player needs a weapon (ie the Knife) to attempt this. + -- + | Basement <- worldPlayerLocation world + , player <- worldPlayer world + , elem verb ["kill", "fight", "attack"] + , ["grue"] <- ss + = if elem Knife (mobInventory player) + then do + out "The grue fights back!\n" + out "You die!\n\n" + + -- kill the player. + modifyWorld $ modifyObject + (isProp PlayerIsAlive) + (propBoolSet False) + + + else do + out "You don't have a weapon.\n\n" + + + +------- Actions below this line cannot be performed if the room is dark. ---------------------- +------- + + | worldRoomIsDark world + = do out "It's too dark, you can't see anything!\n\n" + + + -- Path: open the letterbox. + -- The property FrontDoorKeyRevealed records if the player has already + -- discovered the key. + -- + | Path <- worldPlayerLocation world + , elem verb ["open"] + , [thing] <- ss + , elem thing ["letterbox", "box"] + = if propBoolGet (getObject (isProp FrontDoorKeyRevealed) world) + then do + out "The letterbox is empty.\n\n" + + else do + out "You look inside the letterbox and discover a key.\n\n" + + -- set the property. + modifyWorld $ modifyObject + (isProp FrontDoorKeyRevealed) + (propBoolSet True) + + -- add the key to the world. + modifyWorld $ modifyObject + (isRoom Path) + (roomAddItem KeyFrontDoor) + + + + -- Porch: unlock the front door. + -- The property FrontDoorUnlocked records whether the door is currently unlocked. + -- + | Porch <- worldPlayerLocation world + , player <- worldPlayer world + , elem verb ["open", "unlock"] + , ["door"] <- ss + = if elem KeyFrontDoor (mobInventory player) + then do + -- unlock the door. + modifyWorld $ modifyObject + (isProp FrontDoorUnlocked) + (propBoolSet True) + + out "You hear a click.\n\n" + + else do + -- can't unlock the door without the door key. + out "You don't have the key.\n\n" + + + -- Living: switch the breaker + -- + -- + | Living <- worldPlayerLocation world + , elem verb ["switch", "flip"] + , elem ss [ ["circuit"], ["breaker"] ] + = do out "You flip the circuit breaker.\n\n" + + -- change the property, so the room descriptions change + modifyWorld $ modifyObject + (isProp PFanOn) + (propBoolFlip) + + + -- Basement: Give the grue something. + | Basement <- worldPlayerLocation world + , player <- worldPlayer world + , verb == "give" + , "grue" : itemName : [] <- ss + , maybeItem <- parseItem itemName + = giveGrue maybeItem player world + + + -- Basement: Open the grate. + | Basement <- worldPlayerLocation world + , verb == "open" + , ss == ["grate"] + = if propBoolGet (getObject (isProp PGrateOpen) world) + then do + out "The grate is already open.\n\n" + + else do + out "ok.\n\n" + + -- open the grate + modifyWorld $ modifyObject + (isProp PGrateOpen) + (propBoolSet True) + + + -- Some impossible or unhandled action. + | otherwise + = do out ("I don't see how to do that here.\n\n") + + + +-- | Give the grue something. +giveGrue + :: Maybe ItemId -- ^ Item to give to the grue. + -> Object -- ^ The player object. + -> World -> AM () + +giveGrue maybeItem player world + + -- an unrecognised item. + | Nothing <- maybeItem + = do out "You're not carrying that.\n\n" + + -- an item the player isn't carrying. + | Just itemId <- maybeItem + , not (elem itemId (mobInventory player)) + = do out "You're not carrying that.\n\n" + + -- an item that the player has, and the grue wants. + | Just itemId <- maybeItem + , elem itemId (mobInventory player) + , elem itemId [Amulet] + = do out "The grue smiles and thanks you.\n" + + -- remove the item from the player. + modifyWorld $ modifyObject + (isMob Player) + (mobRemoveItem itemId) + + -- make the grue look happy + modifyWorld $ modifyObject + (isRoom Basement) + (roomRemoveDetail "grue") + + modifyWorld $ modifyObject + (isRoom Basement) + (roomAddDetail ("grue", "The grue looks pleased and contented.")) + + + -- give something back to the player + out "The grue gives you a small jar of jam to show its appreciation.\n\n" + modifyWorld $ modifyObject + (isMob Player) + (mobAddItem JamJar) + + + -- an item that the player has, but the grue is interested in. + | otherwise + = do out "The grue doesn't seem interested.\n\n" + + + addfile ./src/Verb/Type.hs hunk ./src/Verb/Type.hs 1 +-- | The Verb type and parser. + +module Verb.Type where + +import World + + +-- | The Verb data type. +-- This type represents the commands which the player can use to +-- interact with the world. +-- +data Verb + = Look -- Look at the room or a thing. + | Inv -- Check player inventory. + | Get -- Get something from a room. + | Drop -- Drop something in a room. + | Go Direction -- Move in some direction. + | Use -- Use something on something else + | VerbSpecial String -- A special verb, relevant to a particular room or item. + deriving (Eq, Show) + + +-- | Parse a string into a verb. +-- If the verb is not a standard one like Look, Inv, Get etc then it is +-- considered 'special' and might be relavent only to a particular room or item. +-- +parseVerb :: String -> Verb +parseVerb str + = case str of + + -- moving + "n" -> Go North + "north" -> Go North + + "s" -> Go South + "south" -> Go South + + "e" -> Go East + "east" -> Go East + + "w" -> Go West + "west" -> Go West + + "u" -> Go Up + "up" -> Go Up + + "d" -> Go Down + "down" -> Go Down + + -- + "look" -> Look + "inv" -> Inv + "inventory" -> Inv + "get" -> Get + "drop" -> Drop + "use" -> Use + + -- + _ -> VerbSpecial str addfile ./src/Verb/Use.hs hunk ./src/Verb/Use.hs 1 + +module Verb.Use where + +import Verb.Type +import Verb.Util +import Game.Item +import World +import State +import Util +import Format + +cmdUse :: Verb + -> [String] + -> World -> AM () + +cmdUse Use ss world + + -- Don't let the player use anything if the room is dark + | worldRoomIsDark world + = do out "It's too dark, you can't see anything!\n\n" + + -- Cavern: Try and unjam the fan with the knife when it's switched on. + | Cavern <- worldPlayerLocation world + , player <- worldPlayer world + + , propBoolGet (getObject (isProp PFanAttached) world) + , ss == ["knife", "fan"] + + = withCarriedItem Knife "knife" (unjamFanWithKnife player) world + + + | otherwise + = do out "I don't see how you can do that here.\n\n" + + + +unjamFanWithKnife :: Object -> World -> AM () +unjamFanWithKnife player world + | propBoolGet (getObject (isProp PFanOn) world) + = do + let str = "You try and unjam the fan with your knife. You've just managed to leaver the tiny rock out \ + \when the fan blades spring back to life. They spin around and clip the knife causing you to \ + \loose grip and cut yourself badly on the forearm.\n\ + \You bleed to death from your wound." + + out (format str) + out ("\n\n") + + playerKill world + + + | not $ propBoolGet (getObject (isProp PFanOn) world) + = do out "You succeed in un-jamming the fan.\n\n" + + + +withCarriedItem + :: ItemId -> String + -> (World -> AM ()) + -> World -> AM () + +withCarriedItem itemId itemName fun world + | player <- worldPlayer world + , elem itemId (mobInventory player) + = fun world + + | otherwise + = do out $ "You're not carrying a " ++ itemName ++ ".\n\n" + addfile ./src/Verb/Util.hs hunk ./src/Verb/Util.hs 1 +-- | Utility functions used by several different verbs. + +module Verb.Util +where + +import World +import Util + + +-- | Show a list of item names as a single string. +showItemList + :: World -> [ItemId] -> String + +showItemList world [] = "" +showItemList world items + = concatMap (\id -> itemShort (getObject (isItem id) world) world ++ "\n") items + + + + +worldRoomIsDark :: World -> Bool +worldRoomIsDark world = isDark + where + player = worldPlayer world + gotLantern = elem Lantern (mobInventory player) + isDark = (worldRoomNoLight world) && (not gotLantern) + +worldRoomIsIlluminated :: World -> Bool +worldRoomIsIlluminated world = isIlluminated + where + player = worldPlayer world + gotLantern = elem Lantern (mobInventory player) + isIlluminated = (worldRoomNoLight world) && gotLantern + + +worldRoomNoLight :: World -> Bool +worldRoomNoLight world + = (not $ propBoolGet (getObject (isProp PFanOn) world)) + && (elem (worldPlayerLocation world) [Basement, Cavern, Shaft, Sewer]) + addfile ./src/World.hs hunk ./src/World.hs 1 +-- | Defines the main types for the game. +module World where + +import Data.List + + +-- | The name of something. +type Name = String + +-- | A description of something. +type Script = String + +-- | An inventory, carried by some Mobile. +type Inventory = [ItemId] + +-- | A detail of a room. +type Detail = (String, String) + +-- | The world is a list of all the objects in the game. +type World + = [Object] + +-- | An object in the game world. +data Object + = Mob MobId + Name + RoomId + Inventory -- ^ A mobile. Mobiles are players or other creatures + -- which can carry items and move between rooms. + + | Room RoomId + Name + (World -> Script) + [Detail] + [(Direction, Exit)] + Inventory -- ^ A room in the world. + + | Item ItemId + Name + (World -> Script) + (World -> Script) -- ^ An item in the world. + + | Property + PropId + Prop -- ^ Some property of the world. + + + + +-- | ID codes for Mobiles. +data MobId + = Player + deriving (Show, Eq) + + +-- | Each room in the world has an associated RoomId. +data RoomId + = Living + | Bedroom + | Kitchen + | Basement + | Cavern + | Shaft + | Sewer + | Porch + | Path + deriving (Show, Eq) + + +-- | An exit can either be freely passable, or have a door in it. +-- If it is a Door then the associated property in the World must have the value +-- (PropBool True) for the player to pass. +-- If the player tries to pass through a door which is closed, the associated bump +-- bump string is printed. +-- +data Exit + = Exit RoomId + | Door RoomId PropId String + deriving (Show, Eq) + + +-- | An exit direction. (Direct String) can be used to represent a special named +-- direction, ie not (n,s,e,w,u,d). +data Direction + = North + | South + | East + | West + | Down + | Up + | Direct String + deriving (Eq, Show) + + +-- | Each item in the world has an associated ItemId. +data ItemId + = ItemUnknown String + | PocketLint + | KeyFrontDoor + | Rope + | Knife + | Amulet + | Lantern + | Fan + | Fusebox + | JamJar + | Iguana + deriving (Eq, Show) + + +-- | Each property in the world has an associated PropId. +data PropId + = PPlayerMoves -- number of moves the player has made + | PlayerHasQuit -- player has quit the game + | PlayerIsAlive -- player is currently alive + + | FrontDoorUnlocked -- front door of house is unlocked + | FrontDoorKeyRevealed -- front door key has been found in letterbox + + -- Basement grate is open. + | PGrateOpen + + -- ^ Cavern fan is on (set by the circuit breaker in the living room) + | PFanOn + + -- ^ Cavern fan is attached to the wall. + | PFanAttached + + -- ^ When the player is in the same room as the grue and it's dark, the grue gets hungry. + | PGrueHunger + + -- ^ The iguana moves to a different room after a set number of player moves. + | PIguanaWaitCount + + -- ^ The room the iguana is currently in + | PIguanaRoom + + deriving (Eq, Show) + + +-- | Possible properties. +data Prop + = PropBool Bool + | PropInt Int + | PropRoomId RoomId + deriving (Eq, Show) + addfile ./walkthrough hunk ./walkthrough 1 + +-------------------------------------------------------------------+ + | COMP1100 ANU An Augmented Adventure UNA 0011PMOC | + | S2/2006 DEMO 6002\2S | + +-------------------------------------------------------------------+ + type help for help + +* Forest Path + You are on a narrow path leading through the forest. It's autumn + and the path is covered in golden leaves which crunch underfoot. + A letterbox sits atop a post on the edge of the path, and you + see a small white house to the south. It smells like it's going + to rain. + +> look path + The dirt path looks like it has been worn into the forest floor + by many generations of trampling computer science students. + +> look letterbox + The letterbox has a shiny brass numeral '5' attached to it. + +> s + +* Front Porch + You are on the front porch of a small single story house which + has been nestled in amongst the forest trees. A rickety wooden + chair stands next to the front door which leads inside to the + east. A path leads through the forest to the north and you can + hear crickets chirping in the distance. + + Items here: + A rope. + +> get rope +ok. + +> e +The front door is locked. + +> open door +You don't have the key. + +> n + +* Forest Path + You are on a narrow path leading through the forest. It's autumn + and the path is covered in golden leaves which crunch underfoot. + A letterbox sits atop a post on the edge of the path, and you + see a small white house to the south. It smells like it's going + to rain. + +> open letterbox +You look inside the letterbox and discover a key. + +> look + +* Forest Path + You are on a narrow path leading through the forest. It's autumn + and the path is covered in golden leaves which crunch underfoot. + A letterbox sits atop a post on the edge of the path, and you + see a small white house to the south. It smells like it's going + to rain. + + Items here: + An iron key. + +> get key +ok. + +> inv + Items carried: + An iron key. + A rope. + Some pocket lint. + +> look lint + Just regular pocket lint, not very interesting. + +> s + +* Front Porch + You are on the front porch of a small single story house which + has been nestled in amongst the forest trees. A rickety wooden + chair stands next to the front door which leads inside to the + east. A path leads through the forest to the north and you can + hear crickets chirping in the distance. + +> unlock door +You hear a click. + +> e + +* Living Room + You are standing in a small living room inside a house in the + forest. The walls have been covered in a floral wall paper which + matches the curtains covering the window to the west. There is + a door to the west and through the window you can see that it + leads to the front porch. A door leads to the bedroom in the east, + and there is a cramped kitchenette to the south. + + Items here: + There is a fusebox on the wall next to the door. + +> look fusebox + You look inside the fusebox and discover a single circuit breaker. + +> look breaker + The circuit breaker isn't labeled, but you could switch it if + you wanted to. + +> e + +* Bedroom + You are in a small bedroom. There is a double bed in the center + of the room which is covered by a freshly laundered floral quilt. + You can see the autumn forest through the window in the northern + wall. A door leads back to the living room to the west. + + Items here: + A jade amulet. + +> look bed + The double bed has been freshly made. + +> look amulet + The pretty jade amulet has the shape of some kind of aquarium + fish. When you turn it over you see the number '1100' inscribed + on the back. + +> get amulet +ok. + +> w + +* Living Room + You are standing in a small living room inside a house in the + forest. The walls have been covered in a floral wall paper which + matches the curtains covering the window to the west. There is + a door to the west and through the window you can see that it + leads to the front porch. A door leads to the bedroom in the east, + and there is a cramped kitchenette to the south. + + Items here: + There is a fusebox on the wall next to the door. + +> s + +* Kitchen + You are in a cramped kitchen at the end of the living room, which + lies to the north. A long kitchen bench stands in the middle of + the room and the odor of lemon soap is in the air. There is a + door in the east wall which looks like it would lead to the basement. + You hear a faint humming sound. + + Items here: + A gleaming kitchen knife. + +> get knife +ok. + +> look bench + The bench is covered by light green tiles. The tiles are wet and + look like someone has recently cleaned them. + +> e + +* Basement + You are standing in the basement of the house. The walls are lined + with shelves full of what looks to be home-made fruit jam. There + are a set of stairs which lead up into the house and there is + an iron grate leading down through the floor. + There is a loud humming sound which seems to be coming from under + the floor. + There is a grue here. + +> look grue + It looks anxious, like it wants something. + +-------------------------------------------------------------------------------- +> kill grue +The grue fights back! +You die! +-------------------------------------------------------------------------------- + +> give grue lint +The grue doesn't seem interested. + +> inv + Items carried: + A gleaming kitchen knife. + A jade amulet. + An iron key. + A rope. + Some pocket lint. + +> give grue rope +The grue doesn't seem interested. + +> give grue amulet +The grue smiles and thanks you. +The grue gives you a small jar of jam to show its appreciation. + +> look grue + The grue looks pleased and content. + +> inv + Items carried: + A small jar of strawberry jam. + A gleaming kitchen knife. + An iron key. + A rope. + Some pocket lint. + +> look jar + mmmm tasty! + +> look + +* Basement + You are standing in the basement of the house. The walls are lined + with shelves full of what looks to be home-made fruit jam. There + are a set of stairs which lead up into the house and there is + an iron grate leading down through the floor. + There is a loud humming sound which seems to be coming from under + the floor. + There is a grue here. + +> d +The iron grate is closed. + +> open grate +ok. + +> d + +* Cavern + You are crouching in a small, rough-hewn cavern. From the marks + on the walls it looks like this cavern was hollowed out manually + by someone with a pick-axe. An iron grate leads up to the basement + above you and a narrow shaft has been cut into the wall to the + east. + + Items here: + A four bladed electric fan is attached to the cavern wall by large + steel bolts. The fan is humming loudly. + +> look fan + Further inspection reveals that a tiny rock has fallen into the + fan and become wedged between the fan blades and their outer casing. + The electric fan motor has stalled and is humming loudly as it + tries to turn. + +> look knife + It looks sharp, be careful not to cut yourself. + +----------------------------------------------------------------------- +> use knife fan + You try and unjam the fan with your knife. You've just managed + to leaver the tiny rock out when the fan blades spring back to + life. They spin around and clip the knife causing you to loose + grip and cut yourself badly on the forearm. + You bleed to death from your wound. +----------------------------------------------------------------------- + +> u + +* Basement + You are standing in the basement of the house. The walls are lined + with shelves full of what looks to be home-made fruit jam. There + are a set of stairs which lead up into the house and there is + an iron grate leading down through the floor. + There is a loud humming sound which seems to be coming from under + the floor. + There is a grue here. + +> u + +* Kitchen + You are in a cramped kitchen at the end of the living room, which + lies to the north. A long kitchen bench stands in the middle of + the room and the odor of lemon soap is in the air. There is a + door in the east wall which looks like it would lead to the basement. + You hear a faint humming sound. + +> n + +* Living Room + You are standing in a small living room inside a house in the + forest. The walls have been covered in a floral wall paper which + matches the curtains covering the window to the west. There is + a door to the west and through the window you can see that it + leads to the front porch. A door leads to the bedroom in the east, + and there is a cramped kitchenette to the south. + + Items here: + There is a fusebox on the wall next to the door. + +> switch breaker +You flip the circuit breaker. + +> s + +* Kitchen + You are in a cramped kitchen at the end of the living room, which + lies to the north. A long kitchen bench stands in the middle of + the room and the odor of lemon soap is in the air. There is a + door in the east wall which looks like it would lead to the basement. + +> e + +* A dark room. + There is no light in this room. You stumble about but you can't + see anything. You are likely to be eaten by a grue. + +> w + +* Kitchen + You are in a cramped kitchen at the end of the living room, which + lies to the north. A long kitchen bench stands in the middle of + the room and the odor of lemon soap is in the air. There is a + door in the east wall which looks like it would lead to the basement. + +> n + +* Living Room + You are standing in a small living room inside a house in the + forest. The walls have been covered in a floral wall paper which + matches the curtains covering the window to the west. There is + a door to the west and through the window you can see that it + leads to the front porch. A door leads to the bedroom in the east, + and there is a cramped kitchenette to the south. + + Items here: + There is a fusebox on the wall next to the door. + +> switch breaker +You flip the circuit breaker. + +> s + +* Kitchen + You are in a cramped kitchen at the end of the living room, which + lies to the north. A long kitchen bench stands in the middle of + the room and the odor of lemon soap is in the air. There is a + door in the east wall which looks like it would lead to the basement. + You hear a faint humming sound. + +> e + +* Basement + You are standing in the basement of the house. The walls are lined + with shelves full of what looks to be home-made fruit jam. There + are a set of stairs which lead up into the house and there is + an iron grate leading down through the floor. + There is a loud humming sound which seems to be coming from under + the floor. + There is a grue here. + +> d + +* Cavern + You are crouching in a small, rough-hewn cavern. From the marks + on the walls it looks like this cavern was hollowed out manually + by someone with a pick-axe. An iron grate leads up to the basement + above you and a narrow shaft has been cut into the wall to the + east. + + Items here: + A four bladed electric fan is attached to the cavern wall by large + steel bolts. The fan is humming loudly. + +> e + +* Shaft + You are crawling on your hands and knees through a tunnel which + extends away from a cavern to the west. Old pieces of rock and + stone jut out of the walls around you and you have to keep your + head down to avoid bumping it on the uneven ceiling. You think + you can see a blur of blue light further down the tunnel to the + east. + +> e + +* Sewer + You are in what looks to be an old, dry sewer tunnel. + + Items here: + An electric lantern. + +> get lantern +ok. + +> w + +* Shaft + You are crawling on your hands and knees through a tunnel which + extends away from a cavern to the west. Old pieces of rock and + stone jut out of the walls around you and you have to keep your + head down to avoid bumping it on the uneven ceiling. You think + you can see a blur of blue light further down the tunnel to the + east. + +> w + +* Cavern + You are crouching in a small, rough-hewn cavern. From the marks + on the walls it looks like this cavern was hollowed out manually + by someone with a pick-axe. An iron grate leads up to the basement + above you and a narrow shaft has been cut into the wall to the + east. + + Items here: + A four bladed electric fan is attached to the cavern wall by large + steel bolts. The fan is humming loudly. + +> u + +* Basement + You are standing in the basement of the house. The walls are lined + with shelves full of what looks to be home-made fruit jam. There + are a set of stairs which lead up into the house and there is + an iron grate leading down through the floor. + There is a loud humming sound which seems to be coming from under + the floor. + There is a grue here. + +> u + +* Kitchen + You are in a cramped kitchen at the end of the living room, which + lies to the north. A long kitchen bench stands in the middle of + the room and the odor of lemon soap is in the air. There is a + door in the east wall which looks like it would lead to the basement. + You hear a faint humming sound. + +> n + +* Living Room + You are standing in a small living room inside a house in the + forest. The walls have been covered in a floral wall paper which + matches the curtains covering the window to the west. There is + a door to the west and through the window you can see that it + leads to the front porch. A door leads to the bedroom in the east, + and there is a cramped kitchenette to the south. + + Items here: + There is a fusebox on the wall next to the door. + +> switch breaker +You flip the circuit breaker. + +> s + +* Kitchen + You are in a cramped kitchen at the end of the living room, which + lies to the north. A long kitchen bench stands in the middle of + the room and the odor of lemon soap is in the air. There is a + door in the east wall which looks like it would lead to the basement. + +> e + +* Basement + You look around this dark room with your electric lantern... + You are standing in the basement of the house. The walls are lined + with shelves full of what looks to be home-made fruit jam. There + are a set of stairs which lead up into the house and there is + an iron grate in the floor. + There is a grue here. + +> d + +* Cavern + You look around this dark room with your electric lantern... + You are crouching in a small, rough-hewn cavern. From the marks + on the walls it looks like this cavern was hollowed out manually + by someone with a pick-axe. An iron grate leads up to the basement + above you and a narrow shaft has been cut into the wall to the + east. + + Items here: + A four bladed electric fan is attached to the cavern wall by large + steel bolts. + +> look fan + A tiny rock has fallen into the fan and become wedged between + the fan blades and their outer casing. + +> use knife fan +You succeed in un-jamming the fan. + +> quit +GoodBye, adventurer. + + + + }