I'm new to coding and this is a text based adventure game with combat. Sleep and choice functions based on idea from https://codereview.stackexchange.com/a/52292/179642. Map idea from Codecademy battleship tutorial.
The actions in the fight
function are not in a loop because attacks reduce the opponent's hp but healing affects your own hp.
Any comments on new ideas/features, better coding methods greatly appreciated.
import random, time, sys
#initial variables or settings, and map generation
hp = 100
rMap = [('G', 'G', 'G', 'C', 'W'), ('F', 'F', 'G', 'W', 'M'), ('B', 'W', 'W', 'G', 'M'), ('F', 'F', 'G', 'G', 'G'), ('F', 'F', 'F', 'G', 'V')]
pMap = []
for x in range(5):
pMap.append(['?'] * 5)
legend = {'X': 'You', '?': 'Unexplored', 'G': 'Grassland', 'V': 'Village', 'F': 'Forest', 'M': 'Mountain', 'B': 'Bridge', 'W': 'Water', 'C': 'Castle'}
enemy = {'G': ('Wolf', 30, 0, 33, 33, 50), 'F': ('Bandit', 30, 1, 50, 33, 50), 'M': ('Troll', 80, 0, 33, 50, 50), 'C': ('Dragon', 170, 2, 0, 0, 100), 'B': ('Ogre', 100, 0.5, 100, 100, 100)}
posR = 4
posC = 4
inv = {'Bow' : 1, 'Arrow' : 0, 'Potion' : 0}
action = {'Punch': (8, 12, 'p'), 'Kick': (6, 20, 'k')}
def wait(value): #can be commented away for quicker testing
#time.sleep(value)
pass
def new_loc(): #whether there is an enemy when the player moves to a new location
for i in enemy:
if rMap[posR][posC] == i:
if random.randint(1, 100) <= enemy[i][5]:
fight(enemy[i][0], enemy[i][1], enemy[i][2])
loot(enemy[i][3], enemy[i][4])
if i == 'C':
print ('You win! Congratulations!')
sys.exit()
updatepos()
turn()
def turn(): #every turn or action by the player
global hp
print ('What do you want to do?')
wait(0.5)
print ('t to Travel, i to view Inventory, m to view Map')
c = choice(['t', 'i', 'm'])
if c == 't':
print ('Which direction do you want to move?')
d = []
if posR != 0:
if rMap[posR - 1][posC] != 'W':
print ('f to move forward')
d.append('f')
if posR != 4:
if rMap[posR + 1][posC] != 'W':
print ('b to move backward')
d.append('b')
if posC != 0:
if rMap[posR][posC - 1] != 'W':
print ('l to move left')
d.append('l')
if posC != 4:
if rMap[posR][posC + 1] != 'W':
print ('r to move right')
d.append('r')
sel_dir = choice(d)
if sel_dir == 'f':
move(-1, 0)
if sel_dir == 'b':
move(1, 0)
if sel_dir == 'l':
move(0, -1)
if sel_dir == 'r':
move(0, 1)
if c == 'i':
showInv()
turn()
if c == 'm':
updatepos()
turn()
def start(): #introduction to the game
print ('Your village has been burnt down by a dragon!')
wait(0.5)
print (' ')
print ('You have to find it and take revenge!')
print (' ')
updatepos()
turn()
def showAction(): #for debugging player actions in battle
for i in action:
print (i, action[i])
def updateAction(): #for updating actions linked to items
if inv['Potion'] > 0:
if 'Heal' not in action:
action['Heal'] = (40, 50, 'h')
if inv['Potion'] == 0:
if 'Heal' in action:
action.pop('Heal')
if inv['Arrow'] > 0:
if 'Shoot' not in action:
action['Shoot'] = (30, 40, 's')
if inv['Arrow'] == 0:
if 'Shoot' in action:
action.pop('Shoot')
def showInv(): #for viewing inventory
global hp
for i in inv:
if inv[i] > 0:
print (i + ':', inv[i])
if inv['Potion'] > 0:
updateAction()
print('Do you want to drink a Potion? y/n')
drink = choice(['y', 'n'])
if drink == 'y':
h = random.randint(action['Heal'][0], action['Heal'][1])
hp += h
print('You used a Potion')
wait(0.5)
print('You healed yourself for %d HP!' % h)
wait(0.5)
inv['Potion'] -= 1
print('You have %d Potions left' % (inv['Potion']))
turn()
def move(r, c): #when the player moves
global posR
global posC
posR = posR + r
posC = posC + c
wait(0.5)
if r == -1:
print ('Moving Forward...')
if r == 1:
print ('Moving Backward...')
if c == 1:
print ('Moving Right...')
if c == -1:
print ('Moving Left...')
new_loc()
def updatepos(): #updating the map position
pMap[posR][posC] = 'X'
if posR != 4:
pMap[posR + 1][posC] = rMap[posR + 1][posC]
if posR != 0:
pMap[posR - 1][posC] = rMap[posR - 1][posC]
if posC != 4:
pMap[posR][posC + 1] = rMap[posR][posC + 1]
if posC != 0:
pMap[posR][posC - 1] = rMap[posR][posC - 1]
showMap()
wait(0.5)
print ('You are now in %s' % legend[rMap[posR][posC]])
def showMap(): #prints the map and legend (for revealed areas)
print ('Map:')
for row in pMap:
for i in row:
print (i, end = ' ')
print()
print (' ')
legList = []
for row in pMap:
for i in row:
legList.append(i)
for i in legend:
if i in legList:
print (i, legend[i])
print (' ')
def choice(list): #get a valid choice from the user
while True:
userChoice = input('Choose an action:')
userChoice = userChoice.lower()
if userChoice in list:
return userChoice
else:
print ('Invalid choice. Try again.')
def fight(enemy, eHP, level): #fighting an enemy
print ('%s appeared!' % enemy)
wait(0.5)
global hp
enemyHP = eHP
while True:
if hp <= 0:
print ("You died :(. Game over")
sys.exit()
wait(1)
print ('Your hp: %d, %s hp: %d' % (hp, enemy, enemyHP))
wait(1)
updateAction()
act = []
for i in action:
print (i + ': ' + str(action[i][0]) + ' - ' + str(action[i][1]))
act.append(action[i][2])
act_str = ', '.join(str(x) for x in act)
print ('Choices: ' + act_str)
pmove = choice(act)
wait(0.7)
if pmove == 'p':
d = random.randint(action['Punch'][0], action['Punch'][1])
enemyHP -= d
print ('You punch %s for %d damage!' % (enemy, d))
elif pmove == 'k':
d = random.randint(action['Kick'][0], action['Kick'][1])
enemyHP -= d
print ('You kick %s for %d damage!' % (enemy, d))
elif pmove == 'h':
h = random.randint(action['Heal'][0], action['Heal'][1])
print ('You used a Potion')
print ('You heal yourself for %d HP!' % h)
inv['Potion'] -= 1
print ('You have %d Potions left' % (inv['Potion']))
updateAction()
hp += h
elif pmove == 's':
d = random.randint(action['Shoot'][0], action['Shoot'][1])
print ('You used an Arrow')
print ('You shoot %s for %d damage!' % (enemy, d))
inv['Arrow'] -= 1
print('You have %d Arrows left' % (inv['Arrow']))
updateAction()
enemyHP -= d
if enemyHP <= 0:
print("You defeated %s!" % enemy)
return
wait(1)
emove = random.randint (1, 3)
if emove == 1:
dam = random.randint(1, 5) + 10 * level
print ('%s scratches you for %d damage!' % (enemy, dam))
hp -= dam
elif emove == 2:
dam = random.randint(6, 10) + 0.5 * level
print ('%s bites you for %d damage!' % (enemy, dam))
hp -= dam
else:
heal = random.randint(9, 15) + 1 * level
print ('%s healed for %d HP!' % (enemy, heal))
enemyHP += heal
def loot(a, p): #probability of getting loot from enemy
wait(1)
pArrow = random.randint(1, 100)
pPotion = random.randint(1, 100)
if pArrow <= a:
inv['Arrow'] += 1
print ('You found an Arrow!')
wait(0.5)
print('You now have %d Arrows' % inv['Arrow'])
wait(0.7)
if pPotion <= p:
inv['Potion'] += 1
print ('You found a Potion!')
wait(0.5)
print('You now have %d Potions' % inv['Potion'])
wait(0.7)
start()
1 Answer 1
Nice work!
Here are some things you can improve:
- Style: PEP8 - you can check it with http://pep8online.com/ and there are many editors / editor-plugins that autocorrect or at least complain.
#can be commented away for quicker testing
is useless- Variable names:
inv
:inventory
would be better- What is an
rMap
, what apMap
?
- Documentation: Adding docstrings is usually a good idea.
Object Orientation
You could create a couple of objects and assign attributes / functions to them:
Game
: Command line interactions, contains the other objects.- Has the map(s) as a property
Player
: Has an intentory, a position, hp, ...
-
\$\begingroup\$ Thanks for the feedback!. Forgot to remove the
#
inwait
.rMap
is the real map, but is not shown to the player so there is some element of exploration.pMap
is the map shown to the player, and is updated to reveal the adjacent areas whenever the player moves to a new location. I'll update their names to reflect that. Right, realised that I used an object oriented language but did not use any objects... Silly me! Creating a class would also be a better way to manage the enemies' stats instead of a list within a dictionary. \$\endgroup\$Ben– Ben2018年09月15日 05:46:21 +00:00Commented Sep 15, 2018 at 5:46
Explore related questions
See similar questions with these tags.
Choose an action:
to give a little separation between each turn. \$\endgroup\$