2019-10-11 14:35:39 -04:00
|
|
|
# gameutil.py
|
|
|
|
|
|
|
|
# This is a home for nice helper functions that were useful, but also cluttered
|
|
|
|
# the GameBase class.
|
|
|
|
|
|
|
|
import re as _re
|
|
|
|
|
|
|
|
coordRegex = _re.compile(r'(?:(-?[a-zA-Z]+) ?(-?[0-9]+))|(?:(-?[0-9]+),? (-?[0-9]+))|(?:\(([0-9]+), ([0-9]+)\))')
|
|
|
|
|
|
|
|
def letterToNumber(letter):
|
|
|
|
if letter.isdecimal():
|
|
|
|
return int(letter)
|
|
|
|
ret = 0
|
|
|
|
sign = 1
|
|
|
|
start = 0
|
|
|
|
for i in range(len(letter)):
|
|
|
|
if letter[i] == '-':
|
|
|
|
sign = -sign
|
|
|
|
start -= 1
|
|
|
|
elif letter[i].isalpha():
|
|
|
|
if letter[i].isupper():
|
|
|
|
ret += (ord(letter[i]) - ord('A')) * (26**(i+start))
|
|
|
|
else:
|
|
|
|
ret += (ord(letter[i]) - ord('a')) * (26**(i+start))
|
|
|
|
else:
|
|
|
|
return ret * sign
|
|
|
|
return ret * sign
|
|
|
|
|
|
|
|
def numberToLetter(number):
|
|
|
|
if isinstance(number, str):
|
|
|
|
return number
|
|
|
|
ret = ''
|
|
|
|
sign = ''
|
|
|
|
if number == 0:
|
|
|
|
return 'A'
|
|
|
|
elif number < 0:
|
|
|
|
sign = '-'
|
|
|
|
number = -number
|
|
|
|
while number > 0:
|
|
|
|
ret += chr(ord('A') + number % 26)
|
|
|
|
number = int(number / 26)
|
|
|
|
return sign + ret
|
|
|
|
|
|
|
|
def parseCoords(level, args, usePlayerCoords = True, player = None):
|
|
|
|
"""Takes an argument list, and figures out what it's talking about.
|
|
|
|
Returns (thing, x, y). "Thing" can be None."""
|
|
|
|
if level == None:
|
|
|
|
raise ValueError('Coordinates cannot be parsed because there is no map.')
|
2020-05-10 23:26:21 -04:00
|
|
|
if len(args) == 0:
|
|
|
|
return None, -1, -1
|
2019-10-11 14:35:39 -04:00
|
|
|
x = -1
|
|
|
|
y = -1
|
|
|
|
|
|
|
|
# first, try by name for objects in the map
|
|
|
|
name = ' '.join(args)
|
|
|
|
thing = level.getThingByName(name)
|
|
|
|
if thing != None:
|
|
|
|
if usePlayerCoords:
|
|
|
|
return thing, thing.playerx, thing.playery
|
|
|
|
else:
|
|
|
|
return thing, thing.x, thing.y
|
|
|
|
|
|
|
|
# Second, try by name for objects in the inventory
|
|
|
|
if player != None:
|
|
|
|
if name in player.thingNames:
|
|
|
|
return player.getThingByName(name), -1, -1
|
|
|
|
|
|
|
|
# Third, try by location
|
|
|
|
coordStr = args[0]
|
|
|
|
if len(args) > 1:
|
|
|
|
coordStr += ' ' + args[1]
|
|
|
|
match = coordRegex.match(coordStr)
|
|
|
|
if match != None: # if coordinates were given
|
|
|
|
groups = match.groups()
|
|
|
|
ind = 0
|
|
|
|
for i in range(len(groups)):
|
|
|
|
if groups[i] == None or groups[i] == match.group():
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
ind = i
|
|
|
|
break
|
|
|
|
x = letterToNumber(groups[ind])
|
|
|
|
y = letterToNumber(groups[ind+1])
|
|
|
|
thing = level.getThingAtCoords(x, y)
|
|
|
|
if thing != None and usePlayerCoords:
|
|
|
|
return thing, thing.playerx, thing.playery
|
|
|
|
else:
|
|
|
|
return thing, x, y
|
|
|
|
else: # if a name was given
|
|
|
|
return None, -1, -1
|
|
|
|
|
|
|
|
def startDialog(thing, outstream, dialog):
|
|
|
|
if 'dialogs' in thing.customValues:
|
|
|
|
if isinstance(thing.customValues['dialogs'], list):
|
|
|
|
if 'dialogPtr' in thing.customValues and isinstance(thing.customValues['dialogPtr'], int):
|
|
|
|
dialog(thing.customValues['dialogs'][thing.customValues['dialogPtr']], thing)
|
|
|
|
else:
|
|
|
|
dialog(thing.customValues['dialogs'][0], thing)
|
|
|
|
elif isinstance(thing.customValues['dialogs'], str):
|
|
|
|
dialog(thing.customValues['dialogs'], thing)
|
|
|
|
else:
|
|
|
|
raise GameError("Character '{}' has dialog of an unexpected type.".format(thing.name))
|
|
|
|
else:
|
|
|
|
print("{} has nothing to say to you.".format(thing.name), file = outstream)
|