This Nim version proposes the following commands:

RCRPG/Nim is part of RCRPG. You may find other members of RCRPG at Category:RCRPG.

– alias <alias name> <command>: define an alias.

– aliases: list aliases.

– attack <direction>: use sledge to dig a tunnel in the given direction.

– drop all | <item>: drop all items or a specified item.

– east: move to East.

– equip <item>: equip an item present in inventory.

– help: display the list of commands and directions.

– inventory: list items in the inventory.

– look: display location, items and exits.

– name <name>: give a name to the current room.

– north: move to North.

– south: move to South.

– quit: quit game.

– take all | <item>: take all items or a specified item.

– unequip: unequip the equipped item.

– west: move to West.


Directions are: north, east, south, west, up, down.

Code

<lang Nim> import random import strformat import strutils import tables

type

 Direction = enum nowhere, north, east, south, west, up, down
 Item = enum none, sledge, ladder, gold, all
 Position = tuple[x, y, z: int]
 Delta = Position
 Room = ref object
   game: Game
   pos: Position
   items: seq[Item]
   passages: array[Direction, bool]
 Game = ref object
   pos: Position
   rooms: Table[Position, Room]
   roomNames: Table[Position, string]
   aliases: Table[string, string]
   inventory: seq[Item]
   equipped: Item


const

 IncPos: array[Direction, Delta] = [(0, 0, 0), (0, -1, 0), (1, 0, 0),
                                    (0, 1, 0), (-1, 0, 0), (0, 0, 1), (0, 0, -1)]
 OppositeDir: array[Direction, Direction] = [nowhere, south, west, north, east, down, up]
 # Command names and number of tokens required for this command.
 Commands = {"alias": 3, "aliases": 1, "quit": 1, "name": 2, "look": 1,
             "help": 1, "north": 1, "east": 1, "south": 1, "west": 1,
             "up": 1, "down": 1, "attack": 2, "inventory": 1,
             "take": 2, "drop": 2, "equip": 2, "unequip": 1}.toTable()
 StartRoomPos: Position = (0, 0, 0)
 PrizeRoomPos: Position = (1, 1, 5)


  1. Miscellaneous.

func nextPos(oldPos: Position; direction: Direction): Position =

 ## Compute new coordinates from current position and direction.
 (oldPos.x + IncPos[direction].x,
  oldPos.y + IncPos[direction].y,
  oldPos.z + IncPos[direction].z)
  1. ___________________________________________________________________________________________________

proc randomItems(): seq[Item] =

 ## Select randomly the items for a room.
 ## At most one sledge, one ladder and one gold.
 for item in [sledge, ladder, gold]:
   if rand(1) != 0:
     result.add(item)
  1. ___________________________________________________________________________________________________

template toItem(token: string): Item =

 ## Return item from token.
 parseEnum[Item](token.toLower, none)
  1. ___________________________________________________________________________________________________

template toDirection(token: string): Direction =

 ## Return direction from token.
 parseEnum[Direction](token.toLower, nowhere)
  1. ___________________________________________________________________________________________________

proc displayHelp() =

 ## Display help about commands.
 echo "Commands:"
 echo "– alias <alias name> <command>: define an alias."
 echo "– aliases: list aliases."
 echo "– attack <direction>: use sledge to dig a tunnel in the given direction."
 echo "– drop all | <item>: drop all items or a specified item."
 echo "– east: move to East."
 echo "– equip <item>: equip an item present in inventory."
 echo "– help: display this help."
 echo "– inventory: list items in the inventory."
 echo "– look: display location, items and exits."
 echo "– name <name>: give a name to the current room."
 echo "– north: move to North."
 echo "– south: move to South."
 echo "– quit: quit game."
 echo "– take all | <item>: take all items or a specified item."
 echo "– unequip: unequip the equipped item."
 echo "– west: move to West."
 echo "\nDirections:"
 echo "– north, east, south, west, up, down"
  1. Room.

func description(room: Room): string =

 ## Return the description of a room.
 result = "You are at "
 if room.pos in room.game.roomNames:
   result.add(room.game.roomNames[room.pos])
 else:
   result.add(fmt"{room.pos.x}, {room.pos.y}, {room.pos.z}")
 if room.items.len > 0:
   result.add("\nOn the ground you can see: " & room.items.join(", "))
 result.add("\nExits are: ")
 var exits: seq[string]
 for dir, passage in room.passages:
   if passage:
     exits.add(($dir).capitalizeAscii())
 result.add(if exits.len > 0: exits.join(", ") else: "None")
  1. ___________________________________________________________________________________________________

proc take(room: Room; item: Item): seq[Item] =

 ## Take an item in a room.
 if item == all:
   result = room.items
   room.items.setLen(0)
   echo "You now have everything in the room."
 else:
   let idx = room.items.find(item)
   if idx >= 0:
     room.items.delete(idx)
     result = @[item]
     echo "Taken ", item, "."
   else:
     echo "Item not found."


  1. Game.

proc newGame(): Game =

 ## Initialize a game.
 new(result)
 # Create rooms.
 result.rooms[StartRoomPos] = Room(game: result, pos: StartRoomPos, items: @[sledge])
 result.rooms[PrizeRoomPos] = Room(game: result, pos: PrizeRoomPos,
                                   items: @[gold, gold, gold, gold, gold])
 # Create room names.
 result.roomNames = {StartRoomPos: "the starting room",
                     PrizeRoomPos: "the prize room"}.toTable()
 # Create aliases.
 result.aliases = {"n": "north", "e": "east", "s": "south", "w": "west", "u": "up",
                   "d": "down", "a": "attack", "i": "inventory", "l": "look"}.toTable()
  1. ___________________________________________________________________________________________________

proc createAlias(game: Game; newAlias, command: string) =

 ## Create an alias for a command.
 if command in game.aliases:
   echo "You cannot alias an alias."
   return
 game.aliases[newAlias] = command
 echo "Alias created."
  1. ___________________________________________________________________________________________________

proc listAliases(game: Game) =

 ## List the defined aliases.
 for alias, command in game.aliases.pairs:
   echo fmt"{alias}: {command}"
  1. ___________________________________________________________________________________________________

proc look(game: Game) =

 ## Look at current room and display description.
 echo game.rooms[game.pos].description()
  1. ___________________________________________________________________________________________________

proc move(game: Game; direction: Direction) =

 ## Move in a direction.
 if direction == up and ladder notin game.rooms[game.pos].items:
   echo "You’ll need a ladder in this room to go up."
   return
 if game.rooms[game.pos].passages[direction]:
   game.pos = nextPos(game.pos, direction)
 else:
   echo "Can’t go that way."
  1. ___________________________________________________________________________________________________

proc displayInventory(game: Game) =

 ## Display the inventory.
 if game.inventory.len == 0:
   echo "You aren’t carrying anything."
 else:
   echo "Carrying: ", join(game.inventory, ", "), "."
 if game.equipped != none:
   echo "Holding: ", game.equipped, "."
  1. ___________________________________________________________________________________________________

proc take(game: Game; item: Item) =

 ## Take an item.
 game.inventory &= game.rooms[game.pos].take(item)
  1. ___________________________________________________________________________________________________

proc drop(game: Game; item: Item) =

 ## Drop an item.
 if item == all:
   game.rooms[game.pos].items.add(game.inventory)
   game.inventory.setLen(0)
   echo "Everything dropped."
 else:
   let idx = game.inventory.find(item)
   if idx >= 0:
     game.inventory.delete(idx)
     game.rooms[game.pos].items.add(item)
     echo "Dropped ", item, "."
   else:
     echo "Could not find item in inventory."
  1. ___________________________________________________________________________________________________

proc unequip(game: Game) =

 ## Unequip an item.
 if game.equipped == none:
   echo "You aren’t equipped with anything."
 else:
   game.inventory.add(game.equipped)
   echo "Unequipped ", game.equipped, "."
   game.equipped = none
  1. ___________________________________________________________________________________________________

proc equip(game: Game; item: Item) =

 ## Equip an item.
 let idx = game.inventory.find(item)
 if idx >= 0:
   if game.equipped != none:
     game.unequip()
   game.inventory.delete(idx)
   game.equipped = item
   echo "Equipped ", item, "."
 else:
   echo "You aren’t carrying that."
  1. ___________________________________________________________________________________________________

proc name(game: Game; newRoomNameTokens: varargs[string]) =

 ## Name a room.
 game.roomNames[game.pos] = newRoomNameTokens.join(" ")
  1. ___________________________________________________________________________________________________

proc dig(game: Game; direction: Direction) =

 ## Dig in a direction.
 if game.equipped != sledge:
   echo "You don’t have a digging tool equipped."
   return
 if not game.rooms[game.pos].passages[direction]:
   game.rooms[game.pos].passages[direction] = true
   let newRoomPos = nextPos(game.pos, direction)
   if newRoomPos notin game.rooms:
     game.rooms[newRoomPos] = Room(game: game, pos: newRoomPos, items: randomItems())
   game.rooms[newRoomPos].passages[OppositeDir[direction]] = true
   echo "You have dug a tunnel."
 else:
   echo "There’s already a tunnel that way."


  1. Main.

randomize() # Initialize the random generator. let game = newGame()

echo "Welcome to the dungeon!" echo "Grab the sledge and make your way to room 1,1,5 for treasure!"

while true:

 game.look()
 if game.pos == PrizeRoomPos:
   echo "You have found the prize room and the treasure!"
   break
 stdout.write("> ")
 var line: string
 if not stdin.readLine(line):
   break   # End of file.
 var tokens = line.strip().toLower.split()
 # Replace alias by the command.
 if tokens[0] in game.aliases:
   tokens[0] = game.aliases[tokens[0]]
 # Check command.
 if tokens[0] notin Commands:
   echo "Invalid command."
   continue
 if tokens.len != Commands[tokens[0]]:
   echo "Wrong number of parameters."
   continue
 # Process command.
 case tokens[0]
 of "alias":
   game.createAlias(tokens[1], tokens[2])
 of "aliases":
   game.listAliases()
 of "name":
   game.name(tokens[1])
 of "look":
   game.look()
 of "north", "east", "south", "west", "up", "down":
   game.move(tokens[0].toDirection)
 of "inventory":
   game.displayInventory()
 of "take":
   game.take(tokens[1].toItem)
 of "drop":
   game.drop(tokens[1].toItem)
 of "equip":
   game.equip(tokens[1].toItem)
 of "unequip":
   game.unequip()
 of "attack":
   let dir = tokens[1].toDirection
   if dir == nowhere:
     echo "Wrong direction."
   else:
     game.dig(dir)
 of "help":
   displayHelp()
 of "quit":
   break

echo "Thanks for playing" </lang>