You are a knight in the kingdom of Mario. One day, the evil Dark King kidnapped the princess of your kingdom. The King of Mario has ordered you to save the princess from the Dark Lord's clutches and bring her back safely. However, in order to find the Dark King, you need to find 3 keys from each of his 3 generals which will unlock the door to his personal room where you can defeat him and rescue the princess.
- A huge maze map for players to be lost in
- Many enemies to meet and bosses to kill
- Simple game available for all ages
- Use N S W E to move in North, South, East, West directions
- Follow the instructions during the game
- Controls are case sensitive
- For example:
Press N to move North
Press S to move South
Press W to move West
- Players have starting armour durability of 10
- Every death will decrease their armour durability by 1
- When it reaches 0, players will be teleported to the start of the maze with full armour durability
- Basic foot soldier which you will encounter throughout the maze
- There are 3 enemy general at different locations of the maze
- Defeat one to collect a key
- Defeat all three to get 3 keys
- Behind a locked door in the maze
- Requires 3 keys dropped from the enemy general to unlock the door
- Defeat him to rescue the princess
- Libdw - The library used
from libdw import sm as sm
- Random - The module used
import random
As usual, we will use the start()
and the step()
methods from the Libdw library to get the game running.
For example:
game = Maze()
game.start()
game.step(0)
In order for the game to run properly, we need the step()
method to loop infinitely till the player has won the game for which the game will exit on its own.
After the player has defeated the Dark Lord, the condition to exit the game will be called in the form of the next_state = 'F'
and output = 99
whereby the step()
method will return a string instead of its output.
To enable the step()
method to loop infinitely, we use recursion whereby the step()
method will return itself till a base case is called.
For example:
def step(self, inp):
(x, output) = self.getNextValues(self.state, inp)
self.state = x
if output == "F" and x == 99: # base case
return print("\nThanks for playing! \nHope you had a great time! \nExiting Game...")
else:
return self.step(output) # recursive, ensures that the state machine loops infinitely by itself
There is only one class which is the Maze(sm.SM)
class which is inherited from its parent Libdw class.
The constructor, __init__
method, contains the inital state, inital number of keys as well as durability.
The default values of the number of keys is 0 while the starting durability is 10.
The number of keys is capped at 3.
For example:
class Maze(sm.SM):
def __init__(self, key = 0, durability = 10):
self.start_state = 0
self.key = key
if self.key > 3:
self.key = 3
self.durability = durability
Players will navigate their way in the maze through the commands given in the console
which uses State Machines from the Libdw library to map out the maze map.
Examples of using state machines:
elif state == 3:
if inp == 'E':
self.interlude()
output = input("Checkpoint Reached! \n"
"Press N to move North \n"
"Press S to move South \n"
"Press W to move West ")
next_state = 3.5 # indicate a crossroad
else:
next_state = 2
output = 'N'
return next_state, output
Different state numbers correspond to different locations in the maze
Another example:
elif state == 3.5:
if inp == 'N':
self.interlude()
self.soldier()
if self.AmourDurability() == True:
next_state = 1
output = "y"
else:
next_state = 7
output = input("Press W to move West \n"
"Press S to move South")
elif inp == 'S':
self.interlude()
self.soldier()
if self.AmourDurability() == True:
next_state = 1
output = "y"
else:
next_state = 4
output = input("Press W to move West \n"
"Press N to move North")
Since the enemy solider is a fixed entity and occurs frequently, we create the soldier()
method to simplify the code.
The code below shows what happens if you defeat the enemy soldier and the consequences if you failed to do so.
For example:
def soldier(self):
print("\nEncountered Enemy Soldier \n"
"Prepare to attack.. \n")
attack = input("Press a to attack")
if attack == "a":
if self.soldier_defeat() == True:
print("Enenmy Soldier : Ughhhhhhh... \n"
"You have defeated the enemy soldier\n"
"Please continue on your path... \n")
else:
self.durability -= 1
self.AmourDurability()
print("\nYou have died \n"
"You will be revived at your current location \n"
"Your armour durability will drop by 1 \n"
"You left {} armour durability \n".format(self.durability))
if self.durability == 0:
return True
else:
return self.soldier()
else:
return self.soldier()
Application of the code:
if inp == 'N':
self.interlude()
self.soldier()
if self.AmourDurability() == True:
next_state = 1
output = "y"
else:
next_state = 7
output = input("Press W to move West \n"
"Press S to move South"
As explained from above, durability will decrease for every death.
When fighting enemies, there's a chance that the player will die.
After 10 deaths, durability will reach zero which would mean game over in the sense that the player will be teleported to the beginining of the game where he will start all over again.
For example in the soldier()
method,
the self.durability
attribute will decrease by 1 during any fights if the player dies.
The method, AmourDurability()
, will be used to check if self.durability
has reached zero, whereby it will return True, and the player will be teleported to the start of the game.
If self.durability
has not reached zero, nothing will happen and the player will continue in his path.
For example:
def AmourDurability(self):
if self.durability == 0:
print("You have died \n"
"Unfortunately, your durability has reached 0 \n"
"You wil not be able to continue on this path \n"
"you will be revived at the start of the maze with full durability \n")
self.Died = True
return self.Died
else:
pass # Nothing happen
if self.AmourDurability() == True:
next_state = 1 # teleported to entrance of the maze
output = "y"
In this game, we will be using the random.randint function to scale the enemies in accordance to their ranks.
The soldier of course will be the easiest to defeat, thus it has the lowest 'score', followed by the Enemy General and the Dark Lord
For example:
def soldier_defeat(self):
x = random.randint(0, 10) # score
if x > 3:
return True
else:
return False
def Boss_defeat(self): ## Enemy General
x = random.randint(0, 10)
if x > 4:
return True
else:
return False
def FinalBoss_defeat(self): # Dark Lord
x = random.randint(0, 10)
if x > 5:
return True
else:
return False