Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Source code from Episode 003 of the_dev_aspect
//
// --------- Model ---------
//
type Details =
{ Name: string
Description: string }
type Item =
{ Details: Details }
type RoomId =
| RoomId of string
type Exit =
| PassableExit of string * destination: RoomId
| LockedExit of string * key: Item * next: Exit
| NoExit of string option
type Exits =
{ North: Exit
South: Exit
East: Exit
West: Exit }
type Room =
{ Id: RoomId
Details: Details
Items: Item list
Exits: Exits }
type Player =
{ Details: Details
Location: RoomId
Inventory: Item list }
type World =
{ Rooms: Map<RoomId, Room>
Player: Player }
// --------- Initial World ---------
let key: Item =
{ Details =
{ Name = "A shiny key"
Description = "This key looks like it could open a nearby door."} }
let allRooms = [
{ Id = RoomId "center"
Details =
{ Name = "A central room"
Description = "You are standing in a central room with exits in all directions. A single brazier lights the room."}
Items = []
Exits =
{ North = PassableExit ("You see a darkened passageway to the north.", RoomId "north1")
South = PassableExit ("You see door to the south. A waft of cold air hits your face.", RoomId "south1")
East = LockedExit ("You see a locked door to the east.", key, PassableExit ("You see an open door to the east.", RoomId "east1"))
West = PassableExit ("You see an interesting room to the west.", RoomId "west1") }}
{ Id = RoomId "north1"
Details =
{ Name = "A dark room"
Description = "You are standing in a very dark room. You hear the faint sound of rats scurrying along the floor."}
Items = []
Exits =
{ North = NoExit None
South = PassableExit ("You see an dimly lit room to the south.", RoomId "center")
East = NoExit None
West = NoExit None }}
{ Id = RoomId "south1"
Details =
{ Name = "A cold room"
Description = "You are standing in a room that feels very cold. Your breath instantly turns into a white puff."}
Items = []
Exits =
{ North = PassableExit ("You see an exit to the north. That room looks much warmer.", RoomId "center")
South = NoExit None
East = NoExit None
West = NoExit None }}
{ Id = RoomId "west1"
Details =
{ Name = "A cozy room"
Description = "This room seems very cozy, as if someone had made a home here. Various personal belongings are strewn about."}
Items = [ key ]
Exits =
{ North = NoExit None
South = NoExit None
East = PassableExit ("You see a doorway back to the lit room.", RoomId "center")
West = NoExit None }}
{ Id = RoomId "east1"
Details =
{ Name = "An open meadow"
Description = "You are in an open meadow. The sun is bright and it takes some time for your eyes to adjust."}
Items = []
Exits =
{ North = NoExit None
South = NoExit None
East = NoExit None
West = PassableExit ("You see stone doorway to the west. Why would you want to go back there?", RoomId "center") }}
]
let player =
{ Details = { Name = "Luke"; Description = "Just your average adventurer."}
Inventory = []
Location = RoomId "center" }
let gameWorld =
{ Rooms =
allRooms
|> Seq.map (fun room -> (room.Id, room))
|> Map.ofSeq
Player = player}
//
// --------- Logic ---------
//
//
// --------- Model ---------
//
type Details =
{ Name: string
Description: string }
type Item =
{ Details: Details }
type RoomId =
| RoomId of string
type Exit =
| PassableExit of string * destination: RoomId
| LockedExit of string * key: Item * next: Exit
| NoExit of string option
type Exits =
{ North: Exit
South: Exit
East: Exit
West: Exit }
type Room =
{ Id: RoomId
Details: Details
Items: Item list
Exits: Exits }
type Player =
{ Details: Details
Location: RoomId
Inventory: Item list }
type World =
{ Rooms: Map<RoomId, Room>
Player: Player }
// --------- Initial World ---------
let key: Item =
{ Details =
{ Name = "A shiny key"
Description = "This key looks like it could open a nearby door."} }
let allRooms = [
{ Id = RoomId "center"
Details =
{ Name = "A central room"
Description = "You are standing in a central room with exits in all directions. A single brazier lights the room."}
Items = []
Exits =
{ North = PassableExit ("You see a darkened passageway to the north.", RoomId "north1")
South = PassableExit ("You see door to the south. A waft of cold air hits your face.", RoomId "south1")
East = LockedExit ("You see a locked door to the east.", key, PassableExit ("You see an open door to the east.", RoomId "east1"))
West = PassableExit ("You see an interesting room to the west.", RoomId "west1") }}
{ Id = RoomId "north1"
Details =
{ Name = "A dark room"
Description = "You are standing in a very dark room. You hear the faint sound of rats scurrying along the floor."}
Items = []
Exits =
{ North = NoExit None
South = PassableExit ("You see an dimly lit room to the south.", RoomId "center")
East = NoExit None
West = NoExit None }}
{ Id = RoomId "south1"
Details =
{ Name = "A cold room"
Description = "You are standing in a room that feels very cold. Your breath instantly turns into a white puff."}
Items = []
Exits =
{ North = PassableExit ("You see an exit to the north. That room looks much warmer.", RoomId "center")
South = NoExit None
East = NoExit None
West = NoExit None }}
{ Id = RoomId "west1"
Details =
{ Name = "A cozy room"
Description = "This room seems very cozy, as if someone had made a home here. Various personal belongings are strewn about."}
Items = [ key ]
Exits =
{ North = NoExit None
South = NoExit None
East = PassableExit ("You see a doorway back to the lit room.", RoomId "center")
West = NoExit None }}
{ Id = RoomId "east1"
Details =
{ Name = "An open meadow"
Description = "You are in an open meadow. The sun is bright and it takes some time for your eyes to adjust."}
Items = []
Exits =
{ North = NoExit None
South = NoExit None
East = NoExit None
West = PassableExit ("You see stone doorway to the west. Why would you want to go back there?", RoomId "center") }}
]
let player =
{ Details = { Name = "Luke"; Description = "Just your average adventurer."}
Inventory = []
Location = RoomId "center" }
let gameWorld =
{ Rooms =
allRooms
|> Seq.map (fun room -> (room.Id, room))
|> Map.ofSeq
Player = player}
//
// --------- Logic ---------
//
type Result<'TSuccess, 'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
let bind processFunc lastResult =
match lastResult with
| Success s -> processFunc s
| Failure f -> Failure f
let (>>=) x f =
bind f x
let switch processFunc input =
Success (processFunc input)
let getRoom world roomId =
match world.Rooms.TryFind roomId with
| Some room -> Success room
| None -> Failure "Room does not exist!"
let describeDetails details =
sprintf "\n\n%s\n\n%s\n\n" details.Name details.Description
let extractDetailsFromRoom (room: Room) =
room.Details
let describeCurrentRoom world =
world.Player.Location
|> getRoom world
|> (bind (switch extractDetailsFromRoom) >> bind (switch describeDetails))
let north ({ North = northExit }: Exits) = northExit
let south ({ South = southExit }: Exits) = southExit
let east ({ East = eastExit }: Exits) = eastExit
let west ({ West = westExit }: Exits) = westExit
let getCurrentRoom world =
world.Player.Location
|> getRoom world
let setCurrentRoom world room =
{ world with
Player = { world.Player with Location = room.Id} }
let getExit direction exits =
match (direction exits) with
| PassableExit (_, roomId) -> Success roomId
| LockedExit (_, _, _) -> Failure "There is a locked door in that direction."
| NoExit (_) -> Failure "There is no room in that direction."
let move direction world =
world
|> getCurrentRoom
>>= switch (fun room -> room.Exits)
>>= getExit direction
>>= getRoom world
>>= switch (setCurrentRoom world)
let displayResult result =
match result with
| Success s -> printf "%s" s
| Failure f -> printf "%s" f
gameWorld
|> move south
|> bind (move north)
|> bind (move east)
|> bind describeCurrentRoom
|> displayResult
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment