ML Text Based Game: Fantasy Quest
Haha I just found this old game I wrote in ML for a programming languages class in college. It takes about 20 minutes to play. Maybe it’ll be useful to someone out there?
Code
/* First, text descriptions of all the places in the game. */ description(valley, 'You find yourself in a pleasant valley, with a trail ahead.'). description(path, 'You are on a path, with ravines on both sides.'). description(cliff, 'You are teetering on the edge of a cliff.'). description(fork, 'There is a fork in the path.'). description(maze(_), 'You are in a maze of twisty trails, all alike.'). description(gate, 'You see a large locked gate before you.'). description(dungeon(0), 'You wake up with an aching head. Finally you manage to look around. You are in a small dungeon room. The walls are slimy and damp.'). description(dungeon(1), 'The wall appears slimy.'). description(dungeon(2), 'You see a small window above you, but there is little light coming through.'). description(dungeon(3), 'The sound of water can be heard.'). description(dungeon(4), 'The wall is slimy to the touch.'). description(dungeondoor, 'A guard walks by and grins at you with broken teeth.'). description(alley1, 'You find yourself in a rotting, fetid alley.'). description(alley2, 'The smell grows fainter. You see shorter buildings and people ahead'). description(town(0), 'You find yourself in town outside of the alley.'). description(town(1), 'You find yourself on a fairly busy street.'). description(town(2), 'A colorful marketplace looms ahead.'). description(town(3), 'You wander past the marketplace and towards the service district'). description(town(4), 'A weaver tries to get you to buy and other hawkers preach about their wares'). description(town(5), 'The streets grow narrow.'). description(town(6), 'A blacksmith sits before his forge. He asks you if you've seen his missing horseshoe and offers a reward if you find it.'). description(town(7), 'You can see the alley in the distance ahead of you.'). description(town(8), 'The marketplace is full of many exotic fruits and vegtables'). description(town(9), 'Past the market place houses line the streets.'). description(town(10), 'Houses grow sparce and delaphidated out here.'). description(town(11), 'Small boys play in sewage.'). description(town(12), 'A drunken man staggers towards you. You see the tavern ahead.'). description(town(13), 'You wander out of town and into the countryside.'). description(tavern, 'You enter the tavern you were in last night. The barkeep look as you oddly.'). /* report prints the description of your current location. */ report :- at(you,X), description(X,Y), write(Y), nl. /* These connect predicates establish the map. The meaning of connect(X,Dir,Y) is that if you are at X and you move in direction Dir, you get to Y. Recognized directions are forward, right, and left. */ connect(valley,forward,path). %outside of the town connect(path,right,cliff). connect(path,left,cliff). connect(path,forward,fork). connect(fork,left,maze(0)). connect(fork,right,gate). connect(gate,forward,mountaintop). connect(gate,left,valley). connect(gate,right,cliff). connect(maze(0),left,maze(1)). %the maze connect(maze(1),right,maze(2)). connect(maze(2),left,fork). connect(maze(0),right,maze(3)). connect(maze(_),_,maze(0)). connect(dungeon(0),forward,dungeon(1)). %the dungeon connect(dungeon(0),left,dungeon(1)). connect(dungeon(1),forward,dungeon(2)). connect(dungeon(1),left,dungeon(2)). connect(dungeon(2),left,dungeon(3)). connect(dungeon(3),right,dungeon(2)). connect(dungeon(3),forward,dungeon(4)). connect(dungeon(4),forward,dungeondoor). connect(dungeon(4),right,dungeon(1)). connect(dungeon(4),left,dungeon(3)). connect(dungeondoor,forward,alley(1)). connect(dungeondoor,right,dungeon(4)). connect(dungeondoor,left,dungeon(4)). connect(alley(1),forward,alley(2)). %the alley outside the dungeon connect(alley(2),forward,town(0)). connect(town(0),right,town(1)). %the town connect(town(0),forward,town(7)). connect(town(1),right,town(2)). connect(town(2),right,town(8)). connect(town(2),right,town(3)). connect(town(8),forward,town(9)). connect(town(8),right,town(2)). connect(town(8),left,town(2)). connect(town(9),right,town(12)). connect(town(10),left,town(10)). connect(town(12),forward,tavern). connect(town(12),right,town(9)). connect(town(12),left,town(9)). connect(town(10),forward,town(11)). connect(town(10),right,town(9)). connect(town(10),left,town(9)). connect(town(11),right,town(13)). connect(town(11),forward,town(13)). connect(town(11),left,town(10)). connect(town(13),forward,valley). connect(town(13),right,town(11)). connect(town(13),left,town(11)). connect(town(3),forward,town(4)). connect(town(4),left,town(5)). connect(town(5),forward,town(6)). connect(town(6),right,town(7)). connect(town(7),forward,town(0)). connect(tavern,forward,town(12)). %tavern always takes you back to connect(tavern,right,town(12)). %town no matter where you turn connect(tavern,left,town(12)). /* Don't move past the gate if its locked */ move(Dir) :- at(locked, Loc), at(you,Loc), at(locked, Loc), report. /* move(Dir) moves you in direction Dir, then prints the description of your new location. */ move(Dir) :- at(you,Loc), connect(Loc,Dir,Next), retract(at(you,Loc)), assert(at(you,Next)), report. /* But if the argument was not a legal direction, print an error message and don't move. */ move(_) :- write('You can't go that way.n'), report. /* Shorthand for moves. */ forward :- move(forward). left :- move(left). right :- move(right). /* Displays a message if there is an item at this location */ item :- isat(Item, Loc), at(you, Loc), write('there is '), write(Item), write(' on the ground!n'). /* But if there is no item in the same place, nothing happens. */ item. /* Picks up the item at that location */ pickup :- at(you, Loc), /* you are at this location */ isat(Item, Loc), /* the item is at this location */ assert(has(you, Item)), /* you pick up the item */ retractall(isat(Item, Loc)), /* remove this item from that location */ write('You picked up the '), write(Item), write('! n'). /* Or there is nothing there */ pickup :- write('There is nothing here!n'). /* Drop the item you're carrying */ drop :- at(you, Loc), has(you, Item), assert(isat(Item, Loc)), retract(has(you, Item)), write('You dropped the '), write(Item), write('.n'). /* Or they don't have an item to drop */ drop :- write('You are not carrying any items!n'). /* You have a sword and the ogre attacks, you kill it! */ ogre :- at(ogre,Loc), at(you,Loc), has(you, sword), write('An ogre attacks you! You slice off his head just before he can suck your brains out!n'). /* If you and the ogre are at the same place, and you don't have a sword then it kills you. */ ogre :- at(ogre,Loc), at(you,Loc), write('An ogre attacks you and sucks your brain out through '), write('your eye sockets. Your body lies broken on the ground.n'), retract(at(you,Loc)), assert(at(you,done)). /* But if you and the ogre are not in the same place, nothing happens. */ ogre. /* They have a coin and are at the dungeon door */ guard :- at(you, dungeondoor), has(you, coin), write('"You there!" you yell at the guard.n'), write('The guard's smile fades. "What do you want?" comes his grim reply. n'), write('"I think I've found something!" you say, flashing the coin. "Open the door."n'), write('The guard's brows furrowed through the slats in the door window. Finally he grumbled '), write('and keys jingled as he toyed with his belt. The door opened with a creak and he pushed'), write('his bulk through.n With one hand you '), write('punch the guard in the face, knocking him out and escaping the dungeon. n'), move(forward). /* You approach the guard and don't have a coin */ guard :- at(you, dungeondoor), write('"You're going to hang tomorrow pig." The guard says, his spitle hitting you in the eye. Slowly he moves off. You wonder if he's a bit daft and move off.nn'), move(left). /* Not at the guard, nothing happens. */ guard. /* If you have a horseshoe the blacksmith gives you a sword! */ blacksmith :- at(you, town(6)), has(you, horseshoe), write('"You found it!" The black smith exclaims when you show him his lost horseshoe. "Here is your reward." He hands you a fine crafted sword.n'), retract(has(you, horseshoe)), % he takes the horseshoe back assert(has(you, sword)). %you take your reward /* You don't have the horseshoe, the blacksmith says nothing. */ blacksmith. /* You have the coin still, and you walk into the tavern and buy a drink */ tavern :- at(you, tavern), has(you, coin), write('"Give me a drink." You tell the bartender, ignoring his weary looks, and handing over the coin you found in the dungeon.n'), retract(has(you, coin)). % you give him the coin /* You don't have the coin so you leave without a drink. */ tavern. /* They walk through the gate with the key */ treasure :- at(treasure,Loc), at(you,Loc), has(you, key), write('The key you carry is hit by lightening and you die.n'), write('You were so close!n'), retract(at(you,Loc)), assert(at(you,done)). /* If you and the treasure are at the same place and they don't have a key then they win. */ treasure :- at(treasure,Loc), at(you,Loc), write('You find a beaten old chest. Curious you wander over to open it...'), write('Colin's decapitated head rolls out at you, his eyes empty and staring.n'), retract(at(you,Loc)), assert(at(you,done)). /* But if you and the treasure are not in the same place, nothing happens. */ treasure. /* If you are at the cliff, you fall off and die. */ cliff :- at(you,cliff), write('You fall off and die.n'), retract(at(you,cliff)), assert(at(you,done)). /* But if you are not at the cliff nothing happens. */ cliff. /* Have the key with you to open the gate */ locked :- at(locked,Loc), at(you,Loc), has(you, key), retract(at(locked, Loc)), /* unlock the gate */ write('You unlocked the gate with your key.n'). /* At the gate but don't have a key */ locked :- at(locked,Loc), at(you,Loc), write('The gate is locked!n'). /* Not at the gate, nothing happens */ locked. /* Main loop. Stop if player won or lost. */ main :- at(you,done), write('You wake up screaming in bed! Good thing it was all just a dream!!n'). /* Main loop. Not done, so get a move from the user and make it. Then run all our special behaviors. Then repeat. */ main :- write('nNext move -- '), read(Move), call(Move), guard, blacksmith, tavern, item, ogre, treasure, cliff, locked, main. /* This is the starting point for the game. We assert the initial conditions, print an initial report, then start the main loop. */ go :- retractall(at(_,_)), % clean up from previous runs retractall(has(_,_)), % remove all items you had before retractall(isat(_,_)), % remove empty locations of old items assert(at(you,dungeon(0))), assert(at(ogre,maze(3))), assert(at(treasure,mountaintop)), assert(at(locked, gate)), assert(at(lockeddoor, dungeondoor)), assert(isat(key, path)), assert(isat(coin, dungeon(3))), assert(isat(horseshoe, town(1))), write('nn Your name is James Pattern. Last night your friend Colin asked you to the Inn for a drink. He talked excitedly of treasure on a mountain top and ogres out to get him. You laugh at him good naturedly and think he had a bit too much to drink.n On your way home later that night you hear the scuffling of feet. You spin but see nothing in the dark alley behind you. You continue on until something sharp hits you over the head.... You wake up with an aching head and a groan. Finally you manage to look around.nn'), write('WELCOME TO FANTASY QUEST!!!'), write('nn'), write('Legal moves are left, right, forward, pickup, and drop.n'), write('End each move with a period.nn'), report, main.
Explanation
The main loop of this program is located at the very bottom of the script. It starts out by removing all of the locations, item locations, and items the player had on their character before they started playing. Once that has been done it sets up the game by placing all the items and obstacles in the appropriate places. After the game is setup its ready for the user to begin playing. It introduces them to the game by writing text to the screen to detail where the player is.
Legal Moves
Movement: Forward, Left, Right – This moves the character on the game map. To do this, the program first calls the move(Dir) and then checks the game map to see if there are any connections between the player’s current position and a positing direction they are trying to move. If there is a position available it retracts the players old location and asserts their new location to the new position on the map. If a player has entered a movement that is not connected to another part of the map then the game notifies them that they cannot move that direction.
Pickup – This move allows players to pick up items they will encounter as they move through the game map. A player can pick up as many items as they like. Once a player has picked up an item it will remain with them as they navigate the map until they decide to drop it. The pickup code first checks to see if there is an item at the same location the character is located. If there is, the game retracts the item from its location and asserts that the player now has that item in their possession. If the player tries call pickup and there is no item at that location it gives them an error message.
Drop – This allows the players to drop items they have picked up in the game. A player can drop as many items as they have. Once they don’t have any more items it will notify them. However, a player cannot specify which item they mean to pickup or drop. In order to drop an item, the code first checks to see if they have any items. If they have an item it retracts the item as being in their possession and then asserts that the item is now available at the location where it has been dropped. This way if they character was to return to that location at a later time they could again pick up the item.
Item Notification
In order for a player to notice that there are items around the map an item call was put into the code. This checks to see if there are any items at that particular location and then lists any items that it finds. This way the player is notified of the item being available for them to pickup as they play.
Gameplay
You were at the tavern having drinks with a friend. He tells you that he was trying to find treasure but was chased away by an ogre. You have a few drinks with him and then laugh it off and leave. As you’re leaving someone hits you over the head.
Dungeon & Coin – You wake up in a dungeon that is patrolled by a guard. In order to escape from the dungeon you must first find a coin in your cell. Once you have the coin you can go up to the door of the cell. You tell the guard you found something great and flash the coin to catch his interest. He, being a dull witted fellow, falls for it and opens the door. You knock him out and are free.
Blacksmith & Horseshoe – Beyond the dungeon you find yourself in an alley. Outside of the alley you wander back into town. Along the way you stumble upon an expensive looking horseshoe and decide (or not) to pick it up. As you continue around town you’ll find a blacksmith whose looking for a horseshoe he lost and is offering a great reward for it. If you have the horseshoe the blacksmith gives you your reward: a sword. The horseshoe is retracted from your possession and a sword is added to them.
Tavern & Coin – As you continue through town you may eventually wander back into the tavern you met your friend at the night before. If you happen to still have a coin you will buy yourself a drink, otherwise you’ll leave dejectedly.
Gate & Key – As you continue out of town you’ll find yourself in a valley along a path. On the path you will find a key and decide (or not) to pick it up. You will need this key in order to unlock a gate that lies at the base of a mountaintop. Without this key you cannot pass through the gate. However, once the gate is unlocked all is not clear. You must first drop the key before passing through otherwise you’ll be struck by lightning.
Ogre & Sword – Outside of the town you may find yourself stuck in an endless maze. Somewhere hidden in that maze lies an evil ogre waiting to suck your brains out. If you happen to have a sword with you, all is fair and well as you cut off its head before it can touch you. If you weren’t so lucky as to help the blacksmith out you will find yourself dead and buried.
Cliffside – There are other treacherous obstacles outside of the town. If you don’t watch your step you can fall down the cliff and die!
Treasure – Beyond the gate, and the treacherous lightning attracting key you will find the treasure your friend only dreamed about.
Game Over – That’s it! I hope you’ll play!