Added loci, and made dialog processing internal to the engine.
This commit is contained in:
parent
5010042430
commit
9cda61a895
11 changed files with 1860 additions and 1269 deletions
116
gameshell.py
116
gameshell.py
|
@ -9,6 +9,7 @@ import heapq
|
|||
import gameevents
|
||||
import textwrap as _tw
|
||||
from shutil import get_terminal_size as _gts
|
||||
import gameutil as _gu
|
||||
#import random
|
||||
|
||||
TERM_SIZE = _gts()[0]
|
||||
|
@ -27,9 +28,16 @@ class GameShell(Shell):
|
|||
self.outstream = _sys.stdout
|
||||
self.gameBase = gameBase
|
||||
self.colorMode = 0
|
||||
data = self.gameBase.loadGameData('testing/testdata.yml')
|
||||
self.gameTitle = 'Game Shell' # should be changed for actual games
|
||||
if 'title' in data:
|
||||
self.gameTitle = data['title']
|
||||
self.startLevel = 'testing/test1.yml' # should be changed for actual games
|
||||
if 'startLevel' in data:
|
||||
self.gameTitle = data['startLevel']
|
||||
self.openingText = '{}\nIn Development'
|
||||
if 'openingText' in data:
|
||||
self.gameTitle = data['openingText']
|
||||
self.ps2 = '?> '
|
||||
self.__inGame = False
|
||||
|
||||
|
@ -43,7 +51,10 @@ class GameShell(Shell):
|
|||
self.registerCommand('help', self.man)
|
||||
self.registerCommand('new', self.newGame)
|
||||
self.gameBase.registerIO('container', self.container)
|
||||
self.gameBase.registerIO('dialog', self.dialog)
|
||||
self.gameBase.registerIO('startDialog', self.startDialog)
|
||||
self.gameBase.registerIO('openDialog', self.openDialog)
|
||||
self.gameBase.registerIO('respondDialog', self.respondDialog)
|
||||
self.gameBase.registerIO('endDialog', self.endDialog)
|
||||
self.gameBase.registerIO('info', self.info)
|
||||
self.gameBase.registerIO('playercmd', self.playercmd)
|
||||
|
||||
|
@ -136,7 +147,7 @@ class GameShell(Shell):
|
|||
See a map of the local area. "ls" is an alias of map.
|
||||
"l" and "legend" are aliases of -l.
|
||||
If -l is given, a map legend will be printed under the map."""
|
||||
xAxis = ' ' + ''.join([self.gameBase.numberToLetter(i).ljust(2) for i in range(self.gameBase.level.dimensions[0])]) + '\n'
|
||||
xAxis = ' ' + ''.join([_gu.numberToLetter(i).ljust(2) for i in range(self.gameBase.level.dimensions[0])]) + '\n'
|
||||
rows = []
|
||||
index = 0
|
||||
exits = {}
|
||||
|
@ -154,11 +165,6 @@ If -l is given, a map legend will be printed under the map."""
|
|||
for x in range(level.dimensions[0]):
|
||||
pos = level.mapMatrix[y][x]
|
||||
things = level.getThingsAtPos(index)
|
||||
#if x == self.gameBase.playerx and y == self.gameBase.playery:
|
||||
# if self.gameBase.player != textColor:
|
||||
# textColor = '#0000FF'
|
||||
# rows[-1].append(self.color(textColor[1:]))
|
||||
# rows[-1].append('()')
|
||||
if len(things) > 0:
|
||||
# Prioritize types: p, n, i, u, d, x, a
|
||||
thing = things[0]
|
||||
|
@ -253,8 +259,8 @@ If -l is given, a map legend will be printed under the map."""
|
|||
for i in self.gameBase.customValues:
|
||||
ret.append("{0:<22}: {1}".format(i, self.gameBase.customValues[i]))
|
||||
ret.append("Player name:{0:.>68}".format(self.gameBase.player.name))
|
||||
ret.append("Player position:{0:.>64}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.player.x), self.gameBase.player.y)))
|
||||
ret.append("Prev. position:{0:.>65}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.player.prevx), self.gameBase.player.prevy)))
|
||||
ret.append("Player position:{0:.>64}".format("{0}{1}".format(_gu.numberToLetter(self.gameBase.player.x), self.gameBase.player.y)))
|
||||
ret.append("Prev. position:{0:.>65}".format("{0}{1}".format(_gu.numberToLetter(self.gameBase.player.prevx), self.gameBase.player.prevy)))
|
||||
ret.append("Inventory:")
|
||||
for i in self.gameBase.player.inventory:
|
||||
ret.append("{0:<8}: {1}".format(i.thingID, i.name))
|
||||
|
@ -303,6 +309,7 @@ If -l is given, a map legend will be printed under the map."""
|
|||
"""Mode for in-game."""
|
||||
if not self.__inGame:
|
||||
self.registerCommand('map', self.showMap)
|
||||
self.registerCommand('wait', self.gameBase.wait)
|
||||
self.registerCommand('ls', self.showMap)
|
||||
self.registerCommand('go', self.gameBase.go)
|
||||
self.registerCommand('move', self.gameBase.go)
|
||||
|
@ -324,6 +331,7 @@ If -l is given, a map legend will be printed under the map."""
|
|||
"""Mode for main menus and the like."""
|
||||
if self.__inGame:
|
||||
self.registerCommand('map', self.showMap)
|
||||
self.unregisterCommand('wait', self.gameBase.wait)
|
||||
self.unRegisterCommand('ls', self.showMap)
|
||||
self.unRegisterCommand('go', self.gameBase.go)
|
||||
self.unRegisterCommand('move', self.gameBase.go)
|
||||
|
@ -435,78 +443,24 @@ Player is modified through side-effect."""
|
|||
instr = input("Choose an item to view, or exit: ")
|
||||
return charsRead / 27 # based on average 250 words per minute, and word length of 5.5 + 1 for space.
|
||||
|
||||
def dialog(self, dialogObj):
|
||||
if 'script' in dialogObj:
|
||||
self.gameBase.parseScript(dialogObj['script'])
|
||||
if 'cond' in dialogObj:
|
||||
cases = dialogObj['cond']
|
||||
ret = 0
|
||||
for case in cases:
|
||||
cond = case['case'].split() # should be list like ["value", "==", 1]
|
||||
if len(cond) == 1 and (cond[0] == 'else' or self.gameBase.getValueFromString(cond[0])):
|
||||
ret = self.dialog(case)
|
||||
break
|
||||
elif len(cond) == 3 and self.gameBase.compareValues(cond[1], cond[0], cond[2]):
|
||||
ret = self.dialog(case)
|
||||
break
|
||||
else:
|
||||
raise RuntimeError("All routes are false: {}".format(testValue))
|
||||
if ret > 1:
|
||||
return ret - 1
|
||||
else:
|
||||
return ret
|
||||
# if ret == 1 or ret == 0, go back again.
|
||||
elif 'opener' in dialogObj:
|
||||
toPrint = dialogObj['opener'].split('\n') # split by lines so that fill doesn't erase newlines
|
||||
for line in toPrint:
|
||||
print(_tw.fill(line, width = TERM_SIZE))
|
||||
input('<ENTER>')
|
||||
while isinstance(dialogObj, dict):
|
||||
if 'action' in dialogObj:
|
||||
action = dialogObj['action']
|
||||
if action == 'answer':
|
||||
answer = 0
|
||||
skips = []
|
||||
j = 0 # follower to i
|
||||
if 'answers' in dialogObj and isinstance(dialogObj['answers'], list):
|
||||
for i in range(len(dialogObj['answers'])):
|
||||
ans = dialogObj['answers'][i]
|
||||
if ans[0] == '?':
|
||||
condEnd = ans.index(':')
|
||||
cond = ans[1:condEnd].strip().split()
|
||||
if self.gameBase.compareValues(cond):
|
||||
print(_tw.fill('{}: {}'.format(j+1, ans[condEnd+1:].strip()), width = TERM_SIZE))
|
||||
j += 1
|
||||
else:
|
||||
skips.append(i)
|
||||
else:
|
||||
print(_tw.fill('{}: {}'.format(j+1, ans), width = TERM_SIZE))
|
||||
j += 1
|
||||
answer = int(input(self.ps2)) - 1
|
||||
# account for offset if there were answer options that didn't meet conditions
|
||||
for i in skips:
|
||||
if i <= answer:
|
||||
answer += 1
|
||||
else:
|
||||
break
|
||||
if 'replies' in dialogObj and isinstance(dialogObj['replies'], list):
|
||||
ret = self.dialog(dialogObj['replies'][answer])
|
||||
if ret > 1:
|
||||
return ret - 1
|
||||
elif ret == 0:
|
||||
return 0
|
||||
# if ret == 1, then do this dialog again
|
||||
|
||||
elif len(action) >= 4 and action[:4] == 'back':
|
||||
if len(action) == 4:
|
||||
return 1
|
||||
return int(action[4:])
|
||||
elif action == 'exit':
|
||||
return 0
|
||||
else:
|
||||
raise RuntimeError('Malformed action: {}'.format(action))
|
||||
else:
|
||||
raise RuntimeError("Dialog branch with neither switch nor openner.")
|
||||
def startDialog(self):
|
||||
pass
|
||||
|
||||
def openDialog(self, opener):
|
||||
for line in opener:
|
||||
print(_tw.fill(line, width = TERM_SIZE))
|
||||
input("...")
|
||||
|
||||
def respondDialog(self, options):
|
||||
for lineNo in range(len(options)):
|
||||
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
|
||||
return answer
|
||||
|
||||
def endDialog(self):
|
||||
pass
|
||||
|
||||
def playercmd(self, args):
|
||||
self.handleCommand(args)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue