Fixed most input validation bugs, and did too many improvements to remember. Did I mention that I am typing these words with my hands?
This commit is contained in:
parent
ee5c4da549
commit
4a398cc2a3
11 changed files with 546 additions and 253 deletions
170
gameshell.py
170
gameshell.py
|
@ -3,6 +3,7 @@
|
|||
from shell import Shell
|
||||
from gamebase import GameBase
|
||||
import sys as _sys
|
||||
import os as _os
|
||||
#import re
|
||||
import heapq
|
||||
#import gamemap
|
||||
|
@ -23,12 +24,12 @@ class GameShell(Shell):
|
|||
WALLS = ('++', '++', ' +', '++', '++', '||', '++', '|+', '+ ', '++',
|
||||
'==', '++', '++', '+|', '++', '++')
|
||||
|
||||
def __init__(self, gameBase):
|
||||
def __init__(self, gameBase, gameData = 'testing/testdata.yml'):
|
||||
super(GameShell, self).__init__()
|
||||
self.outstream = _sys.stdout
|
||||
self.gameBase = gameBase
|
||||
self.colorMode = 0
|
||||
data = self.gameBase.loadGameData('testing/testdata.yml')
|
||||
data = self.gameBase.loadGameData(gameData)
|
||||
self.gameTitle = 'Game Shell' # should be changed for actual games
|
||||
if 'title' in data:
|
||||
self.gameTitle = data['title']
|
||||
|
@ -38,12 +39,16 @@ class GameShell(Shell):
|
|||
self.openingText = '{}\nIn Development'
|
||||
if 'openingText' in data:
|
||||
self.openingText = data['openingText']
|
||||
if 'playerName' in data:
|
||||
self.gameBase.playerName = data['playerName']
|
||||
if 'playerDescription' in data:
|
||||
self.gameBase.playerDescription = data['playerDescription']
|
||||
self.ps2 = '?> '
|
||||
self.__inGame = False
|
||||
|
||||
# register functions
|
||||
|
||||
self.registerCommand('load', self.gameBase.loadGame) # should always be available
|
||||
self.registerCommand('load', self.loadGame) # should always be available
|
||||
self.registerCommand('flippetywick', self.devMode)
|
||||
self.registerCommand('options', self.options)
|
||||
self.registerCommand('colorTest', self.colorTest)
|
||||
|
@ -62,7 +67,6 @@ class GameShell(Shell):
|
|||
|
||||
def man(self, args):
|
||||
super(GameShell, self).man(args)
|
||||
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
|
||||
|
||||
def options(self, args):
|
||||
i = 0
|
||||
|
@ -171,25 +175,26 @@ If -l is given, a map legend will be printed under the map."""
|
|||
for i in things[1:]:
|
||||
if priorities[i.thingType] < priorities[thing.thingType]:
|
||||
thing = i
|
||||
if thing.graphic[1] != textColor:
|
||||
textColor = thing.graphic[1]
|
||||
if thing.graphic.foreground != textColor:
|
||||
textColor = thing.graphic.foreground
|
||||
#print(textColor)
|
||||
rows[-1].append(self.color(textColor[1:]))
|
||||
if thing.thingType == 'p': # player
|
||||
rows[-1].append('()')
|
||||
elif thing.thingType == 'x': # exit
|
||||
rows[-1].append('X{0}'.format(thing.exitid))
|
||||
exits[thing.exitid] = (thing.name, thing.graphic[1])
|
||||
exits[thing.exitid] = (thing.name, thing.graphic.foreground)
|
||||
elif thing.thingType == 'n': # NPC
|
||||
characters[len(characters)+1] = (thing.name, thing.graphic[1])
|
||||
characters[len(characters)+1] = (thing.name, thing.graphic.foreground)
|
||||
rows[-1].append('C{0}'.format(len(characters)))
|
||||
elif thing.thingType == 'd': # door
|
||||
doors[len(doors)+1] = (thing.name, thing.graphic[1])
|
||||
doors[len(doors)+1] = (thing.name, thing.graphic.foreground)
|
||||
rows[-1].append('D{0}'.format(len(doors)))
|
||||
elif thing.thingType == 'u': # useable
|
||||
useables[len(useables)+1] = (thing.name, thing.graphic[1])
|
||||
useables[len(useables)+1] = (thing.name, thing.graphic.foreground)
|
||||
rows[-1].append('U{0}'.format(len(useables)))
|
||||
elif thing.thingType == 'i': # item
|
||||
items[len(items)+1] = (thing.name, thing.graphic[1])
|
||||
items[len(items)+1] = (thing.name, thing.graphic.foreground)
|
||||
rows[-1].append('I{0}'.format(len(items)))
|
||||
else: # entrance
|
||||
rows[-1].append(' ')
|
||||
|
@ -254,7 +259,7 @@ If -l is given, a map legend will be printed under the map."""
|
|||
ret.append("Gametime:{0:.>71.3}".format(self.gameBase.gameTime))
|
||||
ret.append("Event queue:")
|
||||
for i in sorted(self.gameBase.eventQueue):
|
||||
ret.append("{0:.<8.3}:{1:.>72}".format(i[0], str(i[1])))
|
||||
ret.append("{0:.<8.3}:{1:.>71}".format(i[0], str(i[1])))
|
||||
ret.append("custom values:")
|
||||
for i in self.gameBase.customValues:
|
||||
ret.append("{0:<22}: {1}".format(i, self.gameBase.customValues[i]))
|
||||
|
@ -283,19 +288,19 @@ If -l is given, a map legend will be printed under the map."""
|
|||
response = input("Do you want to save before exiting (Y/n/x)? ")
|
||||
if len(response) > 0:
|
||||
if response[0] in 'Nn':
|
||||
super(GameShell, self).exitShell(args)
|
||||
pass
|
||||
elif response[0] in 'Xx': # cancel
|
||||
return
|
||||
else:
|
||||
sf = input('Save file: ')
|
||||
if len(sf) > 0:
|
||||
gameBase.saveGame([sf])
|
||||
self.gameBase.saveGame([sf])
|
||||
else:
|
||||
print('No save file given, cancelling exit.')
|
||||
else:
|
||||
sf = input('Save file: ')
|
||||
if len(sf) > 0:
|
||||
gameBase.saveGame([sf])
|
||||
self.gameBase.saveGame([sf])
|
||||
else:
|
||||
print('No save file given, cancelling exit.')
|
||||
try:
|
||||
|
@ -305,6 +310,43 @@ If -l is given, a map legend will be printed under the map."""
|
|||
return
|
||||
self.gameMode()
|
||||
|
||||
def loadGame(self, args):
|
||||
# Check if there's a name in args. If not, just present a list of save files.
|
||||
if len(args) == 0:
|
||||
import pickle as _pi
|
||||
for fileName in _os.listdir('saves'):
|
||||
with open(f'saves/{fileName}', 'rb') as f:
|
||||
player, levelname, persist, eventQueue, customValues, gameTime, nextThing = _pi.load(f)
|
||||
print(f'{fileName[:-4]}\n - {levelname[5:-4]}')
|
||||
return
|
||||
if self.__inGame:
|
||||
response = input("Do you want to save before exiting (Y/n/x)? ")
|
||||
if len(response) > 0:
|
||||
if response[0] in 'Nn':
|
||||
pass
|
||||
elif response[0] in 'Xx': # cancel
|
||||
return
|
||||
else:
|
||||
sf = input('Save file: ')
|
||||
if len(sf) > 0:
|
||||
self.gameBase.saveGame([sf])
|
||||
else:
|
||||
print('No save file given, cancelling exit.')
|
||||
return
|
||||
else:
|
||||
sf = input('Save file: ')
|
||||
if len(sf) > 0:
|
||||
self.gameBase.saveGame([sf])
|
||||
else:
|
||||
print('No save file given, cancelling exit.')
|
||||
return
|
||||
try:
|
||||
self.gameBase.loadGame(args)
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
return
|
||||
self.gameMode()
|
||||
|
||||
def gameMode(self):
|
||||
"""Mode for in-game."""
|
||||
if not self.__inGame:
|
||||
|
@ -366,7 +408,7 @@ If -l is given, a map legend will be printed under the map."""
|
|||
|
||||
# IO calls
|
||||
|
||||
def container(self, player, cont):
|
||||
def container(self, player, cont: list):
|
||||
"""container IO
|
||||
Player is modified through side-effect."""
|
||||
# Pretty print: get length of the longest inventory item's name
|
||||
|
@ -393,36 +435,64 @@ Player is modified through side-effect."""
|
|||
print(i.name)
|
||||
# Now, actually interacting with the container
|
||||
timeSpent = 0.5 # using a container always takes at least 1/2 second, even just opening and closing it again.
|
||||
instr = input("Take, store, or exit: ")
|
||||
instr = input("Look, take, store, or exit: ")
|
||||
while instr != "exit":
|
||||
instr = instr.split()
|
||||
if instr[0] == "take":
|
||||
# take something out of the container
|
||||
if instr[1] == "the":
|
||||
del instr[1]
|
||||
thing = ' '.join(instr[1:])
|
||||
for i in range(len(cont)):
|
||||
if thing == cont[i].name:
|
||||
player.addThing(cont[i])
|
||||
del cont[i]
|
||||
if len(instr) != 0:
|
||||
if instr[0] == "take":
|
||||
# take something out of the container
|
||||
if len(instr) > 1 and instr[1] == "the":
|
||||
del instr[1]
|
||||
thingName = ' '.join(instr[1:])
|
||||
if len(thingName) == 0:
|
||||
print(f"{self.gameBase.player.name} takes nothing.")
|
||||
else:
|
||||
for i in range(len(cont)):
|
||||
if thingName == cont[i].name:
|
||||
player.addThing(cont[i])
|
||||
del cont[i]
|
||||
timeSpent += 0.5
|
||||
print(f"{thingName} taken.")
|
||||
break
|
||||
else:
|
||||
# If it got here, it didn't find it.
|
||||
print(f"No {thingName} in container.")
|
||||
elif instr[0] == "store":
|
||||
# store something in the container
|
||||
if len(instr) > 1 and instr[1] == "the":
|
||||
del instr[1]
|
||||
thingName = ' '.join(instr[1:])
|
||||
if len(thingName) == 0:
|
||||
print(f"{self.gameBase.player.name} stores nothing.")
|
||||
elif thingName in player.thingNames:
|
||||
cont.append(player.removeThingByName(thingName))
|
||||
print(f"{thingName} stored.")
|
||||
timeSpent += 0.5
|
||||
print("{0} taken.".format(thing))
|
||||
break
|
||||
else:
|
||||
# If it got here, it didn't find it.
|
||||
print("No {0} in container.".format(thing))
|
||||
elif instr[0] == "store":
|
||||
# store something in the container
|
||||
if instr[1] == "the":
|
||||
del instr[1]
|
||||
thingName = ' '.join(instr[1:])
|
||||
if thingName in player.thingNames:
|
||||
cont.append(player.removeThingByName(thingName))
|
||||
print("{0} stored.".format(thingName))
|
||||
timeSpent += 0.5
|
||||
else:
|
||||
print("No {0} in inventory.".format(thingName))
|
||||
instr = input("Take, store, or exit: ")
|
||||
else:
|
||||
print(f"No {thingName} in inventory.")
|
||||
elif instr[0] == "look":
|
||||
# look at something in the container
|
||||
if len(instr) > 1 and instr[1] == "at":
|
||||
del instr[1]
|
||||
if len(instr) > 1 and instr[1] == "the":
|
||||
del instr[1]
|
||||
thingName = ' '.join(instr[1:])
|
||||
if len(thingName) == 0:
|
||||
print(f"{self.gameBase.player.name} looks at nothing.")
|
||||
else:
|
||||
# Check the container first.
|
||||
for i in range(len(cont)):
|
||||
if thingName == cont[i].name:
|
||||
print(self.gameBase.justifyText(str(cont[i])))
|
||||
break
|
||||
else:
|
||||
# If it wasn't there, try the player's inventory.
|
||||
if thingName in player.thingNames:
|
||||
print(self.gameBase.justifyText(str(player.getThingByName(thingName))))
|
||||
else:
|
||||
# If we get here, it just isn't there.
|
||||
print(f"There is no {thingName} to look at.")
|
||||
instr = input("Look, take, store, or exit: ")
|
||||
return cont, timeSpent
|
||||
|
||||
def info(self, items):
|
||||
|
@ -456,7 +526,11 @@ Player is modified through side-effect."""
|
|||
print(_tw.fill('{}: {}'.format(lineNo+1, options[lineNo]), width = TERM_SIZE))
|
||||
answer = -1
|
||||
while answer < 0 or answer >= len(options):
|
||||
answer = int(input(self.ps2)) - 1
|
||||
answerString = input(self.ps2)
|
||||
if not answerString.isdigit():
|
||||
# If the player inputs a non-integer, just prompt again.
|
||||
continue
|
||||
answer = int(answerString) - 1
|
||||
return answer
|
||||
|
||||
def endDialog(self):
|
||||
|
@ -479,14 +553,14 @@ Player is modified through side-effect."""
|
|||
else:
|
||||
sf = input('Save file: ')
|
||||
if len(sf) > 0:
|
||||
gameBase.saveGame([sf])
|
||||
self.gameBase.saveGame([sf])
|
||||
super(GameShell, self).exitShell(args)
|
||||
else:
|
||||
print('No save file given, cancelling exit.')
|
||||
else:
|
||||
sf = input('Save file: ')
|
||||
if len(sf) > 0:
|
||||
gameBase.saveGame([sf])
|
||||
self.gameBase.saveGame([sf])
|
||||
super(GameShell, self).exitShell(args)
|
||||
else:
|
||||
print('No save file given, cancelling exit.')
|
||||
|
@ -497,3 +571,7 @@ if __name__ == '__main__':
|
|||
sh = GameShell(GameBase())
|
||||
sh.menuMode()
|
||||
sh.run()
|
||||
|
||||
# |\_/|
|
||||
# /0 0\
|
||||
# \o/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue