Example Language Compiler for MUD - wwestlake/Labyrinth GitHub Wiki
Example Language Compiler for MUD
-
Domain Model: Defines the basic elements like
User
,Room
,Map
, andContext
. - Command Types: Defines the possible commands that can be parsed and executed.
- Parsers: Uses FParsec to create parsers for the command language.
- Context Functions: Utility functions to access the context, like checking if an item is in the user’s inventory.
- Command Processor: A function that processes commands based on the context.
-
Example Context: An example
Context
is provided to test the commands. - Example Usage: Demonstrates how to parse and process commands.
This concept is a starting point and can be expanded to include more complex commands, error handling, and other MUD-specific logic.
open FParsec
open System
// Define the domain model
type User = { Name: string; Health: int; Inventory: string list }
type Room = { Name: string; Enemies: string list; Items: string list }
type Map = { Rooms: Room list }
type Context = { User: User; CurrentRoom: Room; Map: Map }
// Define the commands
type Command =
| Attack of string
| Take of string
| Move of string
| Say of string
| If of (Context -> bool) * Command
// Basic parsers
let ws = spaces
let str_ws s = pstring s .>> ws
let identifier = many1Satisfy2L isLetter (isLetter <|> isDigit) "identifier" .>> ws
// Context functions
let getEnemy context enemyName =
context.CurrentRoom.Enemies |> List.tryFind (fun enemy -> enemy = enemyName)
let userHasItem context itemName =
context.User.Inventory |> List.contains itemName
// Command parsers
let attackParser =
str_ws "attack" >>. identifier |>> Attack
let takeParser =
str_ws "take" >>. identifier |>> Take
let moveParser =
str_ws "move" >>. identifier |>> Move
let sayParser =
str_ws "say" >>. many1Satisfy (fun c -> c <> '\n') |>> Say
// Conditional parser
let ifParser, ifParserRef = createParserForwardedToRef<Command, unit>()
let conditionParser =
str_ws "if" >>. between (str_ws "(") (str_ws ")") identifier .>>. ifParser
|>> (fun (cond, command) ->
let conditionFunc context =
match cond with
| "lowHealth" -> context.User.Health < 20
| item -> userHasItem context item
If(conditionFunc, command))
do ifParserRef := choice [attackParser; takeParser; moveParser; sayParser]
// Command processor
let processCommand context (command: Command) =
match command with
| Attack enemy ->
match getEnemy context enemy with
| Some _ -> printfn "You attack the %s." enemy
| None -> printfn "No enemy named %s found." enemy
| Take item ->
if userHasItem context item then
printfn "You already have the %s." item
else if List.contains item context.CurrentRoom.Items then
printfn "You take the %s." item
else
printfn "No item named %s found." item
| Move direction ->
printfn "You move %s." direction
| Say message ->
printfn "%s says: %s" context.User.Name message
| If(condition, command) ->
if condition context then
processCommand context command
// Example context
let exampleContext =
{
User = { Name = "Hero"; Health = 15; Inventory = ["sword"; "shield"] }
CurrentRoom = { Name = "Dungeon"; Enemies = ["goblin"; "orc"]; Items = ["potion"; "key"] }
Map = { Rooms = [] }
}
// Example usage
let runExampleCommand input =
match run (ws >>. ifParser) input with
| Success(result, _, _) -> processCommand exampleContext result
| Failure(errorMsg, _, _) -> printfn "Error: %s" errorMsg
// Test the parser and processor
runExampleCommand "attack goblin"
runExampleCommand "take potion"
runExampleCommand "say Hello, world!"
runExampleCommand "if (lowHealth) say I'm low on health!"