Added conditional evaluation to dialogs. Conditionals for the NPC have been tested, for the player have not.
This commit is contained in:
parent
b332d579e9
commit
ed7fe60a6d
3 changed files with 94 additions and 46 deletions
35
gamebase.py
35
gamebase.py
|
@ -233,6 +233,23 @@ Returns (thing, x, y). "Thing" can be None."""
|
||||||
raise GameError('Invalid argument to getValueFromString: {}'.format(arg))
|
raise GameError('Invalid argument to getValueFromString: {}'.format(arg))
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
def compareValues(self, operator: str, left: str, right: str):
|
||||||
|
"""Generalized comparisons, may eventually be extended to other operators"""
|
||||||
|
lval = self.getValueFromString(left)
|
||||||
|
rval = self.getValueFromString(right)
|
||||||
|
if operator == '==':
|
||||||
|
return lval == rval
|
||||||
|
elif operator == '!=':
|
||||||
|
return lval != rval
|
||||||
|
elif operator == '<=':
|
||||||
|
return lval <= rval
|
||||||
|
elif operator == '>=':
|
||||||
|
return lval >= rval
|
||||||
|
elif operator == '<':
|
||||||
|
return lval < rval
|
||||||
|
elif operator == '>':
|
||||||
|
return lval > rval
|
||||||
|
|
||||||
# commands
|
# commands
|
||||||
|
|
||||||
def go(self, args):
|
def go(self, args):
|
||||||
|
@ -876,26 +893,12 @@ Object can be the name of the object, or its coordinates."""
|
||||||
raise GameError('Incomplete If statement: if {}'.format(' '.join(args)))
|
raise GameError('Incomplete If statement: if {}'.format(' '.join(args)))
|
||||||
|
|
||||||
# evaluate condition
|
# evaluate condition
|
||||||
val = self.parseValue(args[0])
|
|
||||||
if args[1] in ('==', '!=', '<=', '>=', '<', '>'):
|
if args[1] in ('==', '!=', '<=', '>=', '<', '>'):
|
||||||
if len(args) < 4:
|
if len(args) < 4:
|
||||||
raise GameError('Incomplete If statement: if {}'.format(' '.join(args)))
|
raise GameError('Incomplete If statement: if {}'.format(' '.join(args)))
|
||||||
val2 = self.parseValue(args[2])
|
ret = self.compareValues(args[1], args[0], args[2])
|
||||||
if args[1] == '==':
|
|
||||||
ret = val == val2
|
|
||||||
elif args[1] == '!=':
|
|
||||||
ret = val != val2
|
|
||||||
elif args[1] == '<=':
|
|
||||||
ret = val <= val2
|
|
||||||
elif args[1] == '>=':
|
|
||||||
ret = val >= val2
|
|
||||||
elif args[1] == '<':
|
|
||||||
ret = val < val2
|
|
||||||
elif args[1] == '>':
|
|
||||||
ret = val > val2
|
|
||||||
args = args[3:]
|
|
||||||
else:
|
else:
|
||||||
ret = bool(val)
|
ret = bool(self.parseValue(args[0]))
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
if inverse:
|
if inverse:
|
||||||
ret = not ret
|
ret = not ret
|
||||||
|
|
89
gameshell.py
89
gameshell.py
|
@ -315,33 +315,74 @@ If -l is given, a map legend will be printed under the map."""
|
||||||
return charsRead / 27 # based on average 250 words per minute, and word length of 5.5 + 1 for space.
|
return charsRead / 27 # based on average 250 words per minute, and word length of 5.5 + 1 for space.
|
||||||
|
|
||||||
def dialog(self, dialogObj):
|
def dialog(self, dialogObj):
|
||||||
if 'opener' in dialogObj:
|
|
||||||
print(_tw.fill(dialogObj['opener'], width = TERM_SIZE))
|
|
||||||
if 'script' in dialogObj:
|
if 'script' in dialogObj:
|
||||||
self.gameBase.parseScript(dialogObj['script'])
|
self.gameBase.parseScript(dialogObj['script'])
|
||||||
while isinstance(dialogObj, dict):
|
if 'cond' in dialogObj:
|
||||||
if 'action' in dialogObj:
|
cases = dialogObj['cond']
|
||||||
action = dialogObj['action']
|
ret = 0
|
||||||
if action == 'answer':
|
for case in cases:
|
||||||
answer = 0
|
cond = case['case'].split() # should be list like ["value", "==", 1]
|
||||||
if 'answers' in dialogObj and isinstance(dialogObj['answers'], list):
|
if len(cond) == 1 and (cond[0] == 'else' or self.gameBase.getValueFromString(cond[0])):
|
||||||
for i in range(len(dialogObj['answers'])):
|
ret = self.dialog(case)
|
||||||
print(_tw.fill('{}: {}'.format(i+1, dialogObj['answers'][i]), width = TERM_SIZE))
|
break
|
||||||
answer = int(input(self.ps2)) - 1
|
elif len(cond) == 3 and self.gameBase.compareValues(cond[1], cond[0], cond[2]):
|
||||||
if 'replies' in dialogObj and isinstance(dialogObj['replies'], list):
|
ret = self.dialog(case)
|
||||||
ret = self.dialog(dialogObj['replies'][answer])
|
break
|
||||||
if ret > 1:
|
else:
|
||||||
return ret - 1
|
raise RuntimeError("All routes are false: {}".format(testValue))
|
||||||
elif ret == 0:
|
if ret > 1:
|
||||||
return 0
|
return ret - 1
|
||||||
# if ret == 1, then do this dialog again
|
else:
|
||||||
|
return ret
|
||||||
|
# if ret == 1 or ret == 0, go back again.
|
||||||
|
elif 'opener' in dialogObj:
|
||||||
|
print(_tw.fill(dialogObj['opener'], width = TERM_SIZE))
|
||||||
|
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[1], cond[0], cond[2]):
|
||||||
|
print(_tw.fill('{}: {}'.format(j+1, ans[condEnd+1:]), 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':
|
elif len(action) >= 4 and action[:4] == 'back':
|
||||||
if len(action) == 4:
|
if len(action) == 4:
|
||||||
return 1
|
return 1
|
||||||
return int(action[4:])
|
return int(action[4:])
|
||||||
elif action == 'exit':
|
elif action == 'exit':
|
||||||
return 0
|
return 0
|
||||||
|
else:
|
||||||
|
raise RuntimeError('Malformed action: {}'.format(action))
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Dialog branch with neither switch nor openner.")
|
||||||
|
|
||||||
def playercmd(self, args):
|
def playercmd(self, args):
|
||||||
self.handleCommand(args)
|
self.handleCommand(args)
|
||||||
|
|
|
@ -10,8 +10,12 @@ answers:
|
||||||
replies:
|
replies:
|
||||||
- opener: Yup.
|
- opener: Yup.
|
||||||
action: exit
|
action: exit
|
||||||
- opener: I would, but there's still a bunch of foreshadowing and stuff we
|
- cond:
|
||||||
have to get through first.
|
- case: tellmore < 5
|
||||||
action: back
|
opener: I would, but there's still a bunch of foreshadowing and stuff we
|
||||||
script: set tellmore += 1;
|
have to get through first.
|
||||||
printf "You have seen this text {} times." tellmore
|
action: back
|
||||||
|
script: set tellmore += 1
|
||||||
|
- case: else
|
||||||
|
opener: You really want to know more, don't you?
|
||||||
|
action: back
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue