All map files converted to new YAML standard.

This commit is contained in:
Patrick Marsee 2019-03-09 19:08:46 -05:00
parent c5029ac0fc
commit adfb6b83f4
17 changed files with 3123 additions and 2691 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@ maps
saves
__pycache__
winsh.py
yamltest.py

File diff suppressed because it is too large Load diff

View file

@ -1,100 +1,100 @@
#gameevents.py
# Experimental: events are ordered in the order that they were created,
# to resolve issues where two events happen at the same time.
_eventNum = 0
def resetEventNum():
global _eventNum
_eventNum = 0
class GameEvent(object):
def __init__(self, eventType: str):
global _eventNum
self.eventType = eventType
# Experimental, also NOT THREAD SAFE!
self.eventNum = _eventNum
_eventNum += 1
def __str__(self):
return "{0} ({1})".format(self.eventType, self.eventNum)
def __eq__(self, other):
if isinstance(other, GameEvent):
return self.eventNum == other.eventNum
else:
return self.eventNum == other
def __ne__(self, other):
if isinstance(other, GameEvent):
return self.eventNum != other.eventNum
else:
return self.eventNum != other
def __lt__(self, other):
if isinstance(other, GameEvent):
return self.eventNum < other.eventNum
else:
return self.eventNum < other
def __le__(self, other):
if isinstance(other, GameEvent):
return self.eventNum <= other.eventNum
else:
return self.eventNum <= other
def __gt__(self, other):
if isinstance(other, GameEvent):
return self.eventNum > other.eventNum
else:
return self.eventNum > other
def __ge__(self, other):
if isinstance(other, GameEvent):
return self.eventNum >= other.eventNum
else:
return self.eventNum >= other
class NoOpEvent(GameEvent):
def __init__(self):
super(NoOpEvent, self).__init__('noop')
class GoEvent(GameEvent):
def __init__(self, actor, x, y):
super(GoEvent, self).__init__('go')
self.actor = actor
self.x = x
self.y = y
class ArriveEvent(GameEvent):
def __init__(self, actor, x, y, t):
super(ArriveEvent, self).__init__('arrive')
self.actor = actor
self.x = x
self.y = y
self.t = t
class UseEvent(GameEvent):
def __init__(self, thing):
super(UseEvent, self).__init__('use')
self.thing = thing
class UseOnEvent(GameEvent):
def __init__(self, item, thing):
super(UseOnEvent, self).__init__('useon')
self.thing = thing # thing can be a coordinate pair?
self.item = item
class TakeEvent(GameEvent):
def __init__(self, item):
super(TakeEvent, self).__init__('take')
self.item = item
class DropEvent(GameEvent):
def __init__(self, item):
super(DropEvent, self).__init__('drop')
self.item = item
#gameevents.py
# Experimental: events are ordered in the order that they were created,
# to resolve issues where two events happen at the same time.
_eventNum = 0
def resetEventNum():
global _eventNum
_eventNum = 0
class GameEvent(object):
def __init__(self, eventType: str):
global _eventNum
self.eventType = eventType
# Experimental, also NOT THREAD SAFE!
self.eventNum = _eventNum
_eventNum += 1
def __str__(self):
return "{0} ({1})".format(self.eventType, self.eventNum)
def __eq__(self, other):
if isinstance(other, GameEvent):
return self.eventNum == other.eventNum
else:
return self.eventNum == other
def __ne__(self, other):
if isinstance(other, GameEvent):
return self.eventNum != other.eventNum
else:
return self.eventNum != other
def __lt__(self, other):
if isinstance(other, GameEvent):
return self.eventNum < other.eventNum
else:
return self.eventNum < other
def __le__(self, other):
if isinstance(other, GameEvent):
return self.eventNum <= other.eventNum
else:
return self.eventNum <= other
def __gt__(self, other):
if isinstance(other, GameEvent):
return self.eventNum > other.eventNum
else:
return self.eventNum > other
def __ge__(self, other):
if isinstance(other, GameEvent):
return self.eventNum >= other.eventNum
else:
return self.eventNum >= other
class NoOpEvent(GameEvent):
def __init__(self):
super(NoOpEvent, self).__init__('noop')
class GoEvent(GameEvent):
def __init__(self, actor, x, y):
super(GoEvent, self).__init__('go')
self.actor = actor
self.x = x
self.y = y
class ArriveEvent(GameEvent):
def __init__(self, actor, x, y, t):
super(ArriveEvent, self).__init__('arrive')
self.actor = actor
self.x = x
self.y = y
self.t = t
class UseEvent(GameEvent):
def __init__(self, thing):
super(UseEvent, self).__init__('use')
self.thing = thing
class UseOnEvent(GameEvent):
def __init__(self, item, thing):
super(UseOnEvent, self).__init__('useon')
self.thing = thing # thing can be a coordinate pair?
self.item = item
class TakeEvent(GameEvent):
def __init__(self, item):
super(TakeEvent, self).__init__('take')
self.item = item
class DropEvent(GameEvent):
def __init__(self, item):
super(DropEvent, self).__init__('drop')
self.item = item

View file

@ -1,439 +1,439 @@
# gamegui.py
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
from tile import Tile
from gamebase import GameBase
import io
class App(ttk.Frame):
def __init__(self, master, gameBase):
#print('Initializing...')
super(App, self).__init__(master)
self.gameBase = gameBase
self.gameBase.outstream = io.StringIO()
self.gameBase.requestInput = self.requestInput
self.gameBase.onLevelLoad = self.getGraphics
self.selected = (-1, -1)
self.parent = master
self.mapSize = (800, 450)
self.hasChanged = False
self.fileName = 'Untitled'
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames = StringVar(value=self.invTuple)
#self.project = Project()
self.tool = StringVar()
self.brush = StringVar()
self.history = []
self.redos = []
#self.selectedArea = (0, 0, self.project.x-1, self.project.y-1)
self.parent.clipboard_clear()
self.parent.clipboard_append('')
self.grid()
self.createWidgets()
self.makeTheDisplayWork()
self.bindKeys()
#print('Done.')
def createWidgets(self):
#print('Creating Widgets...')
self.initWidth, self.initHeight = 0, 0
# create menu bar
self.createMenuBar()
# create map
self.createMapView()
# create text out
self.createTextOut()
# create inventory list
self.createInventoryView()
#self.tool.set('setone')
#brushes = ttk.Combobox(self, textvariable = self.brush, values = tuple(sorted(Project.tileID.keys())))
#brushes.grid(column = 0, row = 6, sticky = (E, W))
#brushes.state(['readonly'])
#brushes.set('Dirt')
#ttk.Separator(self, orient = VERTICAL).grid(column = 1, row = 0, rowspan = 9, sticky = (N, S))
ttk.Sizegrip(self).grid(column = 1, row = 1, sticky = (S, E))
self.columnconfigure(0, weight = 1)
self.rowconfigure(0, weight = 1)
#print('Done.')
def createMenuBar(self):
#print('Creating the menubar...')
menubar = Menu(self.parent)
menuFile = Menu(menubar)
#menuEdit = Menu(menubar)
menuHelp = Menu(menubar)
menubar.add_cascade(menu = menuFile, label = 'File')
menuFile.add_command(label = 'New', command = lambda: self.loadLevel('maps/apartment.xml'), accelerator = 'Ctrl+N')
menuFile.add_command(label = 'Open...', command = self.fileOpen, accelerator = 'Ctrl+O')
menuFile.add_command(label = 'Save', command = self.fileSave, accelerator = 'Ctrl+S')
menuFile.add_command(label = 'Save As...', command = self.fileSaveAs)
menuFile.add_separator()
menuFile.add_command(label = 'Exit', command = self.onQuit, accelerator = 'Ctrl+Q')
#menubar.add_cascade(menu = menuEdit, label = 'Edit')
#menuEdit.add_command(label = 'Undo', command = self.undo, accelerator = 'Ctrl+Z')
#menuEdit.add_command(label = 'Redo', command = self.redo, accelerator = 'Ctrl+Y')
#menuEdit.add_separator()
#menuEdit.add_command(label = 'Cut', command = self.cut, accelerator = 'Ctrl+X')
#menuEdit.add_command(label = 'Copy', command = self.copy, accelerator = 'Ctrl+C')
#menuEdit.add_command(label = 'Paste', command = self.paste, accelerator = 'Ctrl+V')
menubar.add_cascade(menu = menuHelp, label = 'Help')
menuHelp.add_command(label = 'About', command = self.about)
menuHelp.add_separator()
menuHelp.add_command(label = 'Read Me', command = self.readme)
self.parent.configure(menu = menubar)
#print('Done.')
def createMapView(self):
mapFrame = ttk.LabelFrame(self, text = "map")
mapFrame.grid(column = 0, row = 0)
self.levelDisplay = Canvas(mapFrame, width = self.mapSize[0], height = self.mapSize[1], scrollregion = '0 0 2048 2048')
self.levelDisplay.grid(column = 0, row = 0)
vbar = ttk.Scrollbar(mapFrame, orient = VERTICAL, command = self.levelDisplay.yview)
self.levelDisplay.configure(yscrollcommand = vbar.set)
vbar.grid(column = 1, row = 0, sticky = (N, S))
hbar = ttk.Scrollbar(mapFrame, orient = HORIZONTAL, command = self.levelDisplay.xview)
self.levelDisplay.configure(xscrollcommand = hbar.set)
hbar.grid(column = 0, row = 1, sticky = (E, W))
self.bind('<Configure>', self.onResize)
def createTextOut(self):
textFrame = ttk.LabelFrame(self, text = "Info")
textFrame.grid(column = 0, row = 1)
self.infoDisplay = Text(textFrame, width = 80, height = 8, state = 'disabled')
self.infoDisplay.grid(column = 0, row = 0)
vbar = ttk.Scrollbar(textFrame, orient = VERTICAL, command = self.infoDisplay.yview)
self.infoDisplay.configure(yscrollcommand = vbar.set)
vbar.grid(column = 1, row = 0, sticky = (N, S))
self.infoCursor = 0
def createInventoryView(self):
invFrame = ttk.LabelFrame(self, text = "Inventory")
invFrame.grid(column = 1, row = 0)
self.invDisplay = Listbox(invFrame, height = 24, listvariable = self.invNames)
self.invDisplay.grid(column = 0, row = 0)
vbar = ttk.Scrollbar(invFrame, orient = VERTICAL, command = self.invDisplay.yview)
self.invDisplay.configure(yscrollcommand = vbar.set)
vbar.grid(column = 1, row = 0, sticky = (N, S))
def getGraphics(self):
self.tiles = {}
for i in range(len(self.gameBase.level.floorColors)):
self.tiles['e{0}'.format(i)] = Tile(self.gameBase.level.floorColors[i])
for i in range(len(self.gameBase.level.wallColors)):
self.tiles['w{0}'.format(i)] = Tile(self.gameBase.level.wallColors[i])
self.tiles['player'] = Tile('clear', 'blue', 'o')
for thing in self.gameBase.level.thingNames:
graphic = self.gameBase.level.thingNames[thing].graphic
self.tiles[thing] = Tile(graphic[0], graphic[1], graphic[2])
def makeTheDisplayWork(self):
#print('Making the display work...')
# level display
self.context = Menu(self.levelDisplay)
self.context.add_command(label = 'Load Map', command = lambda: self.loadLevel('maps/apartment.xml'))
self.context.add_command(label = 'Go', command = lambda: self.go(self.selected[0], self.selected[1]))
self.context.add_command(label = 'Run', command = lambda: self.go(self.selected[0], self.selected[1], True))
self.context.add_command(label = 'Look', command = lambda: self.look(self.selected[0], self.selected[1]))
self.context.add_command(label = 'Use', command = lambda: self.use(self.selected[0], self.selected[1]))
self.context.add_command(label = 'Take', command = lambda: self.take(self.selected[0], self.selected[1]))
#self.context.add_command(label = 'Cut', command = self.cut, accelerator = 'Ctrl+X')
#self.context.add_command(label = 'Goblin...')
#self.context.entryconfigure('Goblin...', command = self.configureGoblin, state = DISABLED)
#self.refreshDisplay()
self.levelDisplay.bind('<1>', self.handleClick)
self.levelDisplay.bind('<Double-1>', self.handleDoubleClick)
#self.levelDisplay.bind('<B1-Motion>', self.handleDragEvent)
#self.levelDisplay.bind('<ButtonRelease-1>', self.handleReleaseEvent)
self.levelDisplay.bind('<3>', self.handleRightClick)
# inventory list
self.invContext = Menu(self.invDisplay)
self.invContext.add_command(label = 'Look', command = lambda: self.look(self.invTuple[self.invDisplay.curselection()[0]]))
self.invContext.add_command(label = 'Use', command = lambda: self.use(self.invTuple[self.invDisplay.curselection()[0]]))
self.invContext.add_command(label = 'Drop', command = lambda: self.drop(self.invTuple[self.invDisplay.curselection()[0]]))
self.invDisplay.bind('<<ListboxSelect>>', lambda e: self.look(self.invTuple[self.invDisplay.curselection()[0]]))
self.invDisplay.bind('<3>', lambda e: self.invContext.post(e.x_root, e.y_root))
#print('Done.')
pass
def bindKeys(self):
self.parent.bind('<Control-n>', lambda e: self.fileNew())
self.parent.bind('<Control-o>', lambda e: self.fileOpen())
self.parent.bind('<Control-s>', lambda e: self.fileSave())
#self.parent.bind('<Control-z>', lambda e: self.undo())
#self.parent.bind('<Control-y>', lambda e: self.redo())
#self.parent.bind('<Control-x>', lambda e: self.cut())
#self.parent.bind('<Control-c>', lambda e: self.copy())
#self.parent.bind('<Control-v>', lambda e: self.paste())
self.parent.bind('<Control-q>', lambda e: self.onQuit())
def refreshDisplay(self):
#print('Refreshing the display...')
# refresh the map
self.levelDisplay.delete('all')
for y in range(self.gameBase.level.dimensions[1]):
for x in range(self.gameBase.level.dimensions[0]):
pos = self.gameBase.level.mapMatrix[y][x]
if pos[0] == 'w':
self.tiles['w{0}'.format(pos[1])].paint(self.levelDisplay, x, y)
else:
self.tiles['e{0}'.format(pos[1])].paint(self.levelDisplay, x, y)
for name in self.gameBase.level.thingNames:
thing = self.gameBase.level.getThingByName(name)
self.tiles[name].paint(self.levelDisplay, thing.x, thing.y)
self.tiles['player'].paint(self.levelDisplay, self.gameBase.playerx, self.gameBase.playery)
# refresh the info box
self.gameBase.outstream.seek(self.infoCursor)
#print(self.gameBase.outstream.tell())
#print(self.gameBase.outstream.read())
self.infoDisplay['state'] = 'normal'
self.infoDisplay.insert('end', self.gameBase.outstream.read())
self.infoDisplay.see('end -1 chars')
self.infoDisplay['state'] = 'disabled'
self.infoCursor = self.gameBase.outstream.tell()
#print(self.infoCursor)
#print('Done.')
def handleClick(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
if (x, y) != self.selected:
self.selected = (x, y)
self.look(x, y)
def handleDoubleClick(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
thing = self.gameBase.level.getThingAtCoords(x, y)
if thing != None and thing.useable:
self.use(x, y)
else:
self.go(x, y)
def handleRightClick(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
self.selected = (x, y)
self.context.post(event.x_root, event.y_root)
#def openInvContext(self, event):
# self.invContext.post(event.x_root, event.y_root)
def handleDragEvent(self, event):
x = min(int(self.levelDisplay.canvasx(event.x) / 32), self.project.x-1)
y = min(int(self.levelDisplay.canvasy(event.y) / 32), self.project.y-1)
if self.tool.get() == 'select':
rect = self.levelDisplay.find_withtag('selectArea')
self.selectedArea = (min(x, self.firstX), min(y, self.firstY),
max(x, self.firstX), max(y, self.firstY))
self.levelDisplay.coords(rect,
(self.selectedArea[0]*32, self.selectedArea[1]*32,
self.selectedArea[2]*32+31, self.selectedArea[3]*32+31))
def handleReleaseEvent(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
if self.tool.get() == 'select':
rect = self.levelDisplay.find_withtag('selectArea')
self.selectedArea = (min(x, self.firstX), min(y, self.firstY),
max(x, self.firstX), max(y, self.firstY))
self.levelDisplay.coords(rect,
(self.selectedArea[0]*32, self.selectedArea[1]*32,
self.selectedArea[2]*32+31, self.selectedArea[3]*32+31))
tiles = self.project.getTiles(self.selectedArea)
for y in range(len(tiles)):
for x in range(len(tiles[0])):
if type(tiles[y][x]) == Project.GoblinSettings:
self.context.entryconfigure('Goblin...', state = NORMAL)
break
break
else: pass
def loadLevel(self, fileName):
self.gameBase.loadMap([fileName])
#self.getGraphics()
self.refreshDisplay()
def go(self, x, y, running = False):
#print("go called")
#print(x, y)
if running:
self.gameBase.go(['-r', str(x), str(y)])
else:
self.gameBase.go([str(x), str(y)])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
def look(self, x, y = 1):
#print("look called")
#if x == self.gameBase.playerx and y == self.gameBase.playery:
# self.gameBase.look([
if isinstance(x, int):
thing = self.gameBase.level.getThingAtCoords(x, y)
if thing != None:
self.gameBase.look([thing.name])
else:
self.gameBase.look([])
else:
self.gameBase.look([x])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
def use(self, x, y = 1):
if isinstance(x, int):
self.gameBase.use([str(x), str(y)])
else:
self.gameBase.use([x])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
def take(self, x, y):
self.gameBase.take([str(x), str(y)])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames.set(self.invTuple)
def drop(self, item):
self.gameBase.drop([item])
self.gameBase.gameEventLoop()
self.refreshDisplay()
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames.set(self.invTuple)
def requestInput(self, prompt = ''):
answer = messagebox.askyesno(message=prompt, icon='question', title='Prompt')
if answer:
return 'y'
else:
return 'n'
def fileNew(self):
#print('Creating a new project...')
if self.askToSave():
self.newDialog = Toplevel(self.parent)
self.newDialog.title('New Project')
newFrame = Frame(self.newDialog)
newFrame.grid()
self.hei = StringVar()
self.wid = StringVar()
ttk.Label(newFrame, text = 'Width:').grid(column = 0, row = 0, sticky = W)
ttk.Label(newFrame, text = 'Height:').grid(column = 0, row = 1, sticky = W)
Spinbox(newFrame, from_ = 16, to = 255, increment = 1, textvariable = self.wid
).grid(column = 1, row = 0, sticky = W)
Spinbox(newFrame, from_ = 16, to = 255, increment = 1, textvariable = self.hei
).grid(column = 1, row = 1, sticky = W)
ttk.Button(newFrame, text = 'Create', command = self.__confirmNewDimensions,
default = 'active').grid(column = 0, row = 2)
ttk.Button(newFrame, text = 'Cancel', command = self.newDialog.destroy
).grid(column = 1, row = 2)
#print('Done.')
def fileOpen(self):
#print('Opening a project...')
if self.askToSave():
newName = filedialog.askopenfilename(defaultextension = '.dat', initialdir = 'saves')
if newName != '':
self.fileName = newName
self.gameBase.loadGame((self.fileName,))
self.gameBase.gameEventLoop()
self.refreshDisplay()
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames.set(self.invTuple)
#print('Done.')
def fileSave(self):
#print('Saving a project...')
newName = self.fileName
if self.fileName == 'Untitled':
self.fileSaveAs()
elif newName != '':
self.fileName = newName
self.gameBase.saveGame((self.fileName,))
self.hasChanged = False
#print('Done.')
def fileSaveAs(self):
newName = filedialog.asksaveasfilename(defaultextension = '.dat', initialdir = 'saves')
if newName != '':
self.fileName = newName
self.gameBase.saveGame((self.fileName,))
self.hasChanged = False
def onQuit(self):
if self.askToSave():
exit()
def askToSave(self):
if self.hasChanged:
insecure = messagebox.askyesnocancel(
message = 'Do you want to save ' + self.fileName + ' before continuing?',
icon = 'warning', title = 'New File')
print(type(insecure))
if insecure == None: return False
elif insecure == True:
self.fileSave()
return True
else: return True
else: return True
def about(self):
self.newDialog = Toplevel(self.parent)
self.newDialog.title('About')
newFrame = Frame(self.newDialog)
newFrame.grid()
ttk.Label(newFrame, text = 'I Am Gnome Level Editor v.0.9.0013').grid()
ttk.Button(newFrame, text = 'Okay', command = self.newDialog.destroy).grid()
def readme(self):
self.newDialog = Toplevel(self.parent)
self.newDialog.title('About')
newFrame = Frame(self.newDialog)
newFrame.grid()
text = Text(newFrame, width=80, height=40, wrap = 'word')
text.grid(column = 0, row = 0)
sbar = ttk.Scrollbar(newFrame, orient = VERTICAL, command = text.yview)
sbar.grid(column = 1, row = 0, sticky = (N, S, W))
text.configure(yscrollcommand = sbar.set)
text.state(['disabled'])
file = open('iag_readme.txt', 'r')
text.insert('1.0', file.read())
def onResize(self, event):
if self.initWidth == 0 and self.initHeight == 0:
self.initWidth = event.width
self.initHeight = event.height
else:
wDelta = event.width - int(self.initWidth)
hDelta = event.height - int(self.initHeight)
self.levelDisplay.configure(width = self.mapSize[0] + wDelta, height = self.mapSize[1] + hDelta)
# main
if __name__ == '__main__':
root = Tk()
root.title('Game Gui (debug)')
#root.geometry("1024x768")
#root.resizable(FALSE, FALSE)
root.option_add('*tearOff', FALSE)
root.columnconfigure(0, weight = 1)
root.rowconfigure(0, weight = 1)
newApp = App(root, GameBase())
newApp.grid(sticky = (N, S, E, W))
root.mainloop()
# gamegui.py
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
from tile import Tile
from gamebase import GameBase
import io
class App(ttk.Frame):
def __init__(self, master, gameBase):
#print('Initializing...')
super(App, self).__init__(master)
self.gameBase = gameBase
self.gameBase.outstream = io.StringIO()
self.gameBase.requestInput = self.requestInput
self.gameBase.onLevelLoad = self.getGraphics
self.selected = (-1, -1)
self.parent = master
self.mapSize = (800, 450)
self.hasChanged = False
self.fileName = 'Untitled'
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames = StringVar(value=self.invTuple)
#self.project = Project()
self.tool = StringVar()
self.brush = StringVar()
self.history = []
self.redos = []
#self.selectedArea = (0, 0, self.project.x-1, self.project.y-1)
self.parent.clipboard_clear()
self.parent.clipboard_append('')
self.grid()
self.createWidgets()
self.makeTheDisplayWork()
self.bindKeys()
#print('Done.')
def createWidgets(self):
#print('Creating Widgets...')
self.initWidth, self.initHeight = 0, 0
# create menu bar
self.createMenuBar()
# create map
self.createMapView()
# create text out
self.createTextOut()
# create inventory list
self.createInventoryView()
#self.tool.set('setone')
#brushes = ttk.Combobox(self, textvariable = self.brush, values = tuple(sorted(Project.tileID.keys())))
#brushes.grid(column = 0, row = 6, sticky = (E, W))
#brushes.state(['readonly'])
#brushes.set('Dirt')
#ttk.Separator(self, orient = VERTICAL).grid(column = 1, row = 0, rowspan = 9, sticky = (N, S))
ttk.Sizegrip(self).grid(column = 1, row = 1, sticky = (S, E))
self.columnconfigure(0, weight = 1)
self.rowconfigure(0, weight = 1)
#print('Done.')
def createMenuBar(self):
#print('Creating the menubar...')
menubar = Menu(self.parent)
menuFile = Menu(menubar)
#menuEdit = Menu(menubar)
menuHelp = Menu(menubar)
menubar.add_cascade(menu = menuFile, label = 'File')
menuFile.add_command(label = 'New', command = lambda: self.loadLevel('maps/apartment.xml'), accelerator = 'Ctrl+N')
menuFile.add_command(label = 'Open...', command = self.fileOpen, accelerator = 'Ctrl+O')
menuFile.add_command(label = 'Save', command = self.fileSave, accelerator = 'Ctrl+S')
menuFile.add_command(label = 'Save As...', command = self.fileSaveAs)
menuFile.add_separator()
menuFile.add_command(label = 'Exit', command = self.onQuit, accelerator = 'Ctrl+Q')
#menubar.add_cascade(menu = menuEdit, label = 'Edit')
#menuEdit.add_command(label = 'Undo', command = self.undo, accelerator = 'Ctrl+Z')
#menuEdit.add_command(label = 'Redo', command = self.redo, accelerator = 'Ctrl+Y')
#menuEdit.add_separator()
#menuEdit.add_command(label = 'Cut', command = self.cut, accelerator = 'Ctrl+X')
#menuEdit.add_command(label = 'Copy', command = self.copy, accelerator = 'Ctrl+C')
#menuEdit.add_command(label = 'Paste', command = self.paste, accelerator = 'Ctrl+V')
menubar.add_cascade(menu = menuHelp, label = 'Help')
menuHelp.add_command(label = 'About', command = self.about)
menuHelp.add_separator()
menuHelp.add_command(label = 'Read Me', command = self.readme)
self.parent.configure(menu = menubar)
#print('Done.')
def createMapView(self):
mapFrame = ttk.LabelFrame(self, text = "map")
mapFrame.grid(column = 0, row = 0)
self.levelDisplay = Canvas(mapFrame, width = self.mapSize[0], height = self.mapSize[1], scrollregion = '0 0 2048 2048')
self.levelDisplay.grid(column = 0, row = 0)
vbar = ttk.Scrollbar(mapFrame, orient = VERTICAL, command = self.levelDisplay.yview)
self.levelDisplay.configure(yscrollcommand = vbar.set)
vbar.grid(column = 1, row = 0, sticky = (N, S))
hbar = ttk.Scrollbar(mapFrame, orient = HORIZONTAL, command = self.levelDisplay.xview)
self.levelDisplay.configure(xscrollcommand = hbar.set)
hbar.grid(column = 0, row = 1, sticky = (E, W))
self.bind('<Configure>', self.onResize)
def createTextOut(self):
textFrame = ttk.LabelFrame(self, text = "Info")
textFrame.grid(column = 0, row = 1)
self.infoDisplay = Text(textFrame, width = 80, height = 8, state = 'disabled')
self.infoDisplay.grid(column = 0, row = 0)
vbar = ttk.Scrollbar(textFrame, orient = VERTICAL, command = self.infoDisplay.yview)
self.infoDisplay.configure(yscrollcommand = vbar.set)
vbar.grid(column = 1, row = 0, sticky = (N, S))
self.infoCursor = 0
def createInventoryView(self):
invFrame = ttk.LabelFrame(self, text = "Inventory")
invFrame.grid(column = 1, row = 0)
self.invDisplay = Listbox(invFrame, height = 24, listvariable = self.invNames)
self.invDisplay.grid(column = 0, row = 0)
vbar = ttk.Scrollbar(invFrame, orient = VERTICAL, command = self.invDisplay.yview)
self.invDisplay.configure(yscrollcommand = vbar.set)
vbar.grid(column = 1, row = 0, sticky = (N, S))
def getGraphics(self):
self.tiles = {}
for i in range(len(self.gameBase.level.floorColors)):
self.tiles['e{0}'.format(i)] = Tile(self.gameBase.level.floorColors[i])
for i in range(len(self.gameBase.level.wallColors)):
self.tiles['w{0}'.format(i)] = Tile(self.gameBase.level.wallColors[i])
self.tiles['player'] = Tile('clear', 'blue', 'o')
for thing in self.gameBase.level.thingNames:
graphic = self.gameBase.level.thingNames[thing].graphic
self.tiles[thing] = Tile(graphic[0], graphic[1], graphic[2])
def makeTheDisplayWork(self):
#print('Making the display work...')
# level display
self.context = Menu(self.levelDisplay)
self.context.add_command(label = 'Load Map', command = lambda: self.loadLevel('maps/apartment.xml'))
self.context.add_command(label = 'Go', command = lambda: self.go(self.selected[0], self.selected[1]))
self.context.add_command(label = 'Run', command = lambda: self.go(self.selected[0], self.selected[1], True))
self.context.add_command(label = 'Look', command = lambda: self.look(self.selected[0], self.selected[1]))
self.context.add_command(label = 'Use', command = lambda: self.use(self.selected[0], self.selected[1]))
self.context.add_command(label = 'Take', command = lambda: self.take(self.selected[0], self.selected[1]))
#self.context.add_command(label = 'Cut', command = self.cut, accelerator = 'Ctrl+X')
#self.context.add_command(label = 'Goblin...')
#self.context.entryconfigure('Goblin...', command = self.configureGoblin, state = DISABLED)
#self.refreshDisplay()
self.levelDisplay.bind('<1>', self.handleClick)
self.levelDisplay.bind('<Double-1>', self.handleDoubleClick)
#self.levelDisplay.bind('<B1-Motion>', self.handleDragEvent)
#self.levelDisplay.bind('<ButtonRelease-1>', self.handleReleaseEvent)
self.levelDisplay.bind('<3>', self.handleRightClick)
# inventory list
self.invContext = Menu(self.invDisplay)
self.invContext.add_command(label = 'Look', command = lambda: self.look(self.invTuple[self.invDisplay.curselection()[0]]))
self.invContext.add_command(label = 'Use', command = lambda: self.use(self.invTuple[self.invDisplay.curselection()[0]]))
self.invContext.add_command(label = 'Drop', command = lambda: self.drop(self.invTuple[self.invDisplay.curselection()[0]]))
self.invDisplay.bind('<<ListboxSelect>>', lambda e: self.look(self.invTuple[self.invDisplay.curselection()[0]]))
self.invDisplay.bind('<3>', lambda e: self.invContext.post(e.x_root, e.y_root))
#print('Done.')
pass
def bindKeys(self):
self.parent.bind('<Control-n>', lambda e: self.fileNew())
self.parent.bind('<Control-o>', lambda e: self.fileOpen())
self.parent.bind('<Control-s>', lambda e: self.fileSave())
#self.parent.bind('<Control-z>', lambda e: self.undo())
#self.parent.bind('<Control-y>', lambda e: self.redo())
#self.parent.bind('<Control-x>', lambda e: self.cut())
#self.parent.bind('<Control-c>', lambda e: self.copy())
#self.parent.bind('<Control-v>', lambda e: self.paste())
self.parent.bind('<Control-q>', lambda e: self.onQuit())
def refreshDisplay(self):
#print('Refreshing the display...')
# refresh the map
self.levelDisplay.delete('all')
for y in range(self.gameBase.level.dimensions[1]):
for x in range(self.gameBase.level.dimensions[0]):
pos = self.gameBase.level.mapMatrix[y][x]
if pos[0] == 'w':
self.tiles['w{0}'.format(pos[1])].paint(self.levelDisplay, x, y)
else:
self.tiles['e{0}'.format(pos[1])].paint(self.levelDisplay, x, y)
for name in self.gameBase.level.thingNames:
thing = self.gameBase.level.getThingByName(name)
self.tiles[name].paint(self.levelDisplay, thing.x, thing.y)
self.tiles['player'].paint(self.levelDisplay, self.gameBase.playerx, self.gameBase.playery)
# refresh the info box
self.gameBase.outstream.seek(self.infoCursor)
#print(self.gameBase.outstream.tell())
#print(self.gameBase.outstream.read())
self.infoDisplay['state'] = 'normal'
self.infoDisplay.insert('end', self.gameBase.outstream.read())
self.infoDisplay.see('end -1 chars')
self.infoDisplay['state'] = 'disabled'
self.infoCursor = self.gameBase.outstream.tell()
#print(self.infoCursor)
#print('Done.')
def handleClick(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
if (x, y) != self.selected:
self.selected = (x, y)
self.look(x, y)
def handleDoubleClick(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
thing = self.gameBase.level.getThingAtCoords(x, y)
if thing != None and thing.useable:
self.use(x, y)
else:
self.go(x, y)
def handleRightClick(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
self.selected = (x, y)
self.context.post(event.x_root, event.y_root)
#def openInvContext(self, event):
# self.invContext.post(event.x_root, event.y_root)
def handleDragEvent(self, event):
x = min(int(self.levelDisplay.canvasx(event.x) / 32), self.project.x-1)
y = min(int(self.levelDisplay.canvasy(event.y) / 32), self.project.y-1)
if self.tool.get() == 'select':
rect = self.levelDisplay.find_withtag('selectArea')
self.selectedArea = (min(x, self.firstX), min(y, self.firstY),
max(x, self.firstX), max(y, self.firstY))
self.levelDisplay.coords(rect,
(self.selectedArea[0]*32, self.selectedArea[1]*32,
self.selectedArea[2]*32+31, self.selectedArea[3]*32+31))
def handleReleaseEvent(self, event):
x = int(self.levelDisplay.canvasx(event.x) / 32)
y = int(self.levelDisplay.canvasy(event.y) / 32)
if self.tool.get() == 'select':
rect = self.levelDisplay.find_withtag('selectArea')
self.selectedArea = (min(x, self.firstX), min(y, self.firstY),
max(x, self.firstX), max(y, self.firstY))
self.levelDisplay.coords(rect,
(self.selectedArea[0]*32, self.selectedArea[1]*32,
self.selectedArea[2]*32+31, self.selectedArea[3]*32+31))
tiles = self.project.getTiles(self.selectedArea)
for y in range(len(tiles)):
for x in range(len(tiles[0])):
if type(tiles[y][x]) == Project.GoblinSettings:
self.context.entryconfigure('Goblin...', state = NORMAL)
break
break
else: pass
def loadLevel(self, fileName):
self.gameBase.loadMap([fileName])
#self.getGraphics()
self.refreshDisplay()
def go(self, x, y, running = False):
#print("go called")
#print(x, y)
if running:
self.gameBase.go(['-r', str(x), str(y)])
else:
self.gameBase.go([str(x), str(y)])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
def look(self, x, y = 1):
#print("look called")
#if x == self.gameBase.playerx and y == self.gameBase.playery:
# self.gameBase.look([
if isinstance(x, int):
thing = self.gameBase.level.getThingAtCoords(x, y)
if thing != None:
self.gameBase.look([thing.name])
else:
self.gameBase.look([])
else:
self.gameBase.look([x])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
def use(self, x, y = 1):
if isinstance(x, int):
self.gameBase.use([str(x), str(y)])
else:
self.gameBase.use([x])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
def take(self, x, y):
self.gameBase.take([str(x), str(y)])
self.gameBase.gameEventLoop()
self.refreshDisplay() #inefficient, but will work for now.
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames.set(self.invTuple)
def drop(self, item):
self.gameBase.drop([item])
self.gameBase.gameEventLoop()
self.refreshDisplay()
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames.set(self.invTuple)
def requestInput(self, prompt = ''):
answer = messagebox.askyesno(message=prompt, icon='question', title='Prompt')
if answer:
return 'y'
else:
return 'n'
def fileNew(self):
#print('Creating a new project...')
if self.askToSave():
self.newDialog = Toplevel(self.parent)
self.newDialog.title('New Project')
newFrame = Frame(self.newDialog)
newFrame.grid()
self.hei = StringVar()
self.wid = StringVar()
ttk.Label(newFrame, text = 'Width:').grid(column = 0, row = 0, sticky = W)
ttk.Label(newFrame, text = 'Height:').grid(column = 0, row = 1, sticky = W)
Spinbox(newFrame, from_ = 16, to = 255, increment = 1, textvariable = self.wid
).grid(column = 1, row = 0, sticky = W)
Spinbox(newFrame, from_ = 16, to = 255, increment = 1, textvariable = self.hei
).grid(column = 1, row = 1, sticky = W)
ttk.Button(newFrame, text = 'Create', command = self.__confirmNewDimensions,
default = 'active').grid(column = 0, row = 2)
ttk.Button(newFrame, text = 'Cancel', command = self.newDialog.destroy
).grid(column = 1, row = 2)
#print('Done.')
def fileOpen(self):
#print('Opening a project...')
if self.askToSave():
newName = filedialog.askopenfilename(defaultextension = '.dat', initialdir = 'saves')
if newName != '':
self.fileName = newName
self.gameBase.loadGame((self.fileName,))
self.gameBase.gameEventLoop()
self.refreshDisplay()
self.invTuple = tuple(self.gameBase.playerInv.keys())
self.invNames.set(self.invTuple)
#print('Done.')
def fileSave(self):
#print('Saving a project...')
newName = self.fileName
if self.fileName == 'Untitled':
self.fileSaveAs()
elif newName != '':
self.fileName = newName
self.gameBase.saveGame((self.fileName,))
self.hasChanged = False
#print('Done.')
def fileSaveAs(self):
newName = filedialog.asksaveasfilename(defaultextension = '.dat', initialdir = 'saves')
if newName != '':
self.fileName = newName
self.gameBase.saveGame((self.fileName,))
self.hasChanged = False
def onQuit(self):
if self.askToSave():
exit()
def askToSave(self):
if self.hasChanged:
insecure = messagebox.askyesnocancel(
message = 'Do you want to save ' + self.fileName + ' before continuing?',
icon = 'warning', title = 'New File')
print(type(insecure))
if insecure == None: return False
elif insecure == True:
self.fileSave()
return True
else: return True
else: return True
def about(self):
self.newDialog = Toplevel(self.parent)
self.newDialog.title('About')
newFrame = Frame(self.newDialog)
newFrame.grid()
ttk.Label(newFrame, text = 'I Am Gnome Level Editor v.0.9.0013').grid()
ttk.Button(newFrame, text = 'Okay', command = self.newDialog.destroy).grid()
def readme(self):
self.newDialog = Toplevel(self.parent)
self.newDialog.title('About')
newFrame = Frame(self.newDialog)
newFrame.grid()
text = Text(newFrame, width=80, height=40, wrap = 'word')
text.grid(column = 0, row = 0)
sbar = ttk.Scrollbar(newFrame, orient = VERTICAL, command = text.yview)
sbar.grid(column = 1, row = 0, sticky = (N, S, W))
text.configure(yscrollcommand = sbar.set)
text.state(['disabled'])
file = open('iag_readme.txt', 'r')
text.insert('1.0', file.read())
def onResize(self, event):
if self.initWidth == 0 and self.initHeight == 0:
self.initWidth = event.width
self.initHeight = event.height
else:
wDelta = event.width - int(self.initWidth)
hDelta = event.height - int(self.initHeight)
self.levelDisplay.configure(width = self.mapSize[0] + wDelta, height = self.mapSize[1] + hDelta)
# main
if __name__ == '__main__':
root = Tk()
root.title('Game Gui (debug)')
#root.geometry("1024x768")
#root.resizable(FALSE, FALSE)
root.option_add('*tearOff', FALSE)
root.columnconfigure(0, weight = 1)
root.rowconfigure(0, weight = 1)
newApp = App(root, GameBase())
newApp.grid(sticky = (N, S, E, W))
root.mainloop()

1769
gamemap.py

File diff suppressed because it is too large Load diff

View file

@ -1,213 +1,213 @@
# gameshell.py
from shell import Shell
from gamebase import GameBase
import sys as _sys
#import re
import heapq
#import gamemap
import gameevents
#from os import get_terminal_size
#import random
class GameShell(Shell):
UP = 1
RIGHT = 2
DOWN = 4
LEFT = 8
WALLS = ('++', '++', ' +', '++', '++', '||', '++', '|+', '+ ', '++',
'==', '++', '++', '+|', '++', '++')
def __init__(self, gameBase):
super(GameShell, self).__init__()
self.outstream = _sys.stdout
self.gameBase = gameBase
self.colorMode = 0
# register functions
self.registerCommand('map', self.showMap)
self.registerCommand('ls', self.showMap)
self.registerCommand('go', self.gameBase.go)
self.registerCommand('move', self.gameBase.go)
self.registerCommand('walk', self.gameBase.go)
self.registerCommand('look', self.gameBase.look)
self.registerCommand('use', self.gameBase.use)
self.registerCommand('loadMap', self.gameBase.loadMap)
self.registerCommand('man', self.man)
self.registerCommand('help', self.man)
self.registerCommand('save', self.gameBase.saveGame)
self.registerCommand('load', self.gameBase.loadGame)
self.registerCommand('take', self.gameBase.take)
self.registerCommand('get', self.gameBase.take)
self.registerCommand('drop', self.gameBase.drop)
self.registerCommand('inv', self.inv)
self.registerCommand('bag', self.inv)
self.registerCommand('items', self.inv)
self.registerCommand('status', self.status)
self.registerCommand('options', self.options)
self.registerCommand('colorTest', self.colorTest)
self.registerAlias('run', ['go', '-r'])
# Helper functions
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
while i < len(args):
if args[i] == 'color':
i += 1
if args[i] in ('0', '3', '4', '8', '24'):
self.colorMode = int(args[i])
i += 1
def __colorTestRoutine(self, lower, upper):
colors = []
step = int((upper - lower) / 8)
#print(step)
for g in range(lower, upper, step):
colors.append(self.color(upper-1, g, lower, False))
#print(len(colors))
colors.append(self.color(upper-1, upper-1, lower, False))
for r in range(upper-step, lower-1, -step):
colors.append(self.color(r, upper-1, lower, False))
#print(len(colors))
for b in range(lower+step, upper, step):
colors.append(self.color(lower, upper-1, b, False))
#print(len(colors))
colors.append(self.color(lower, upper-1, upper-1, False))
for g in range(upper-step, lower-1, -step):
colors.append(self.color(lower, g, upper-1, False))
#print(len(colors))
for r in range(lower+step, upper, step):
colors.append(self.color(r, lower, upper-1, False))
colors.append(self.color(upper-1, lower, upper-1, False))
#print(len(colors))
for b in range(upper-step, lower, -step):
colors.append(self.color(upper-1, lower, b, False))
#print(len(colors))
colors.append('\x1b[0m')
print(' '.join(colors))
def colorTest(self, args):
for i in (3, 4, 8, 24):
print(i)
self.colorMode = i
self.__colorTestRoutine(0, 128) # dark
self.__colorTestRoutine(0, 256) # medium
self.__colorTestRoutine(128, 256) # light
def showMap(self, args):
"""map [-l]
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'
rows = []
index = 0
exits = {}
doors = {}
useables = {}
items = {}
level = self.gameBase.level
textColor = level.wallColors[0]
floorColor = level.floorColors[0]
for y in range(level.dimensions[1]):
rows.append(['{0}{1:2} {2}{3}'.format(self.clearColor(), y, self.color(textColor[1:]), self.color(floorColor[1:], fg = False))])
rows[-1].append(self.color(textColor[1:]))
for x in range(level.dimensions[0]):
pos = level.mapMatrix[y][x]
thing = level.getThingAtPos(index)
if x == self.gameBase.playerx and y == self.gameBase.playery:
if '#0000FF' != textColor:
textColor = '#0000FF'
rows[-1].append(self.color(textColor[1:]))
rows[-1].append('()')
elif thing:
if thing.graphic[1] != textColor:
textColor = thing.graphic[1]
rows[-1].append(self.color(textColor[1:]))
if thing.thingType == 'x': # exit
rows[-1].append('X{0}'.format(thing.exitid))
exits[thing.exitid] = (thing.name, thing.graphic[1])
elif thing.thingType == 'd': # door
doors[len(doors)+1] = (thing.name, thing.graphic[1])
rows[-1].append('D{0}'.format(len(doors)))
elif thing.thingType == 'u': # useable
useables[len(useables)+1] = (thing.name, thing.graphic[1])
rows[-1].append('U{0}'.format(len(useables)))
elif thing.thingType == 'i': # item
items[len(items)+1] = (thing.name, thing.graphic[1])
rows[-1].append('I{0}'.format(len(items)))
elif pos[0] == 'w':
if level.wallColors[level.mapMatrix[y][x][1]] != textColor:
textColor = level.wallColors[level.mapMatrix[y][x][1]]
rows[-1].append(self.color(textColor[1:]))
sides = 0
if y > 0 and level.mapMatrix[y-1][x][0] == 'w':
sides += GameShell.UP
if x < level.dimensions[0]-1 and level.mapMatrix[y][x+1][0] == 'w':
sides += GameShell.RIGHT
if y < level.dimensions[1]-1 and level.mapMatrix[y+1][x][0] == 'w':
sides += GameShell.DOWN
if x > 0 and level.mapMatrix[y][x-1][0] == 'w':
sides += GameShell.LEFT
rows[-1].append(GameShell.WALLS[sides])
else:
rows[-1].append(' ')
index += 1
rows[-1] = ''.join(rows[-1])
print(xAxis)
print('{0}\n'.format(self.clearColor(False)).join(rows) + self.clearColor())
self.setClearColor()
if len(args) > 0:
if args[0] == '-l' or args[0] == 'l' or args[0] == 'legend':
legend = ["\n---Legend---\n", "{0}(){1} - {2}".format(self.color('0000FF'), self.clearColor(), self.gameBase.playerName),
"Xn - Exit to another area"]
for i in exits:
legend.append(' {0}X{1}{2} - {3}'.format(self.color(exits[i][1][1:]), i, self.clearColor(), exits[i][0]))
legend.append("Un - Useable object")
for i in useables:
legend.append(' {0}U{1}{2} - {3}'.format(self.color(useables[i][1][1:]), i, self.clearColor(), useables[i][0]))
legend.append("In - Item")
for i in items:
legend.append(' {0}I{1}{2} - {3}'.format(self.color(items[i][1][1:]), i, self.clearColor(), items[i][0]))
legend.append("Dn - Door")
for i in doors:
legend.append(' {0}D{1}{2} - {3}'.format(self.color(doors[i][1][1:]), i, self.clearColor(), doors[i][0]))
print('\n'.join(legend))
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
return
def status(self, args):
ret = []
if self.gameBase.level != None:
ret.append("Level:{0:.>74}".format(self.gameBase.level.name))
else:
ret.append("Level:{0:.>74}".format("None"))
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("Player name:{0:.>68}".format(self.gameBase.playerName))
ret.append("Player position:{0:.>64}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.playerx), self.gameBase.playery)))
ret.append("Prev. position:{0:.>65}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.prevx), self.gameBase.prevy)))
print('\n'.join(ret))
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
return
def inv(self, args):
print('\n'.join([i for i in self.gameBase.playerInv]))
def update(self):
self.gameBase.gameEventLoop()
if __name__ == '__main__':
sh = GameShell(GameBase())
sh.run()
# gameshell.py
from shell import Shell
from gamebase import GameBase
import sys as _sys
#import re
import heapq
#import gamemap
import gameevents
#from os import get_terminal_size
#import random
class GameShell(Shell):
UP = 1
RIGHT = 2
DOWN = 4
LEFT = 8
WALLS = ('++', '++', ' +', '++', '++', '||', '++', '|+', '+ ', '++',
'==', '++', '++', '+|', '++', '++')
def __init__(self, gameBase):
super(GameShell, self).__init__()
self.outstream = _sys.stdout
self.gameBase = gameBase
self.colorMode = 0
# register functions
self.registerCommand('map', self.showMap)
self.registerCommand('ls', self.showMap)
self.registerCommand('go', self.gameBase.go)
self.registerCommand('move', self.gameBase.go)
self.registerCommand('walk', self.gameBase.go)
self.registerCommand('look', self.gameBase.look)
self.registerCommand('use', self.gameBase.use)
self.registerCommand('loadMap', self.gameBase.loadMap)
self.registerCommand('man', self.man)
self.registerCommand('help', self.man)
self.registerCommand('save', self.gameBase.saveGame)
self.registerCommand('load', self.gameBase.loadGame)
self.registerCommand('take', self.gameBase.take)
self.registerCommand('get', self.gameBase.take)
self.registerCommand('drop', self.gameBase.drop)
self.registerCommand('inv', self.inv)
self.registerCommand('bag', self.inv)
self.registerCommand('items', self.inv)
self.registerCommand('status', self.status)
self.registerCommand('options', self.options)
self.registerCommand('colorTest', self.colorTest)
self.registerAlias('run', ['go', '-r'])
# Helper functions
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
while i < len(args):
if args[i] == 'color':
i += 1
if args[i] in ('0', '3', '4', '8', '24'):
self.colorMode = int(args[i])
i += 1
def __colorTestRoutine(self, lower, upper):
colors = []
step = int((upper - lower) / 8)
#print(step)
for g in range(lower, upper, step):
colors.append(self.color(upper-1, g, lower, False))
#print(len(colors))
colors.append(self.color(upper-1, upper-1, lower, False))
for r in range(upper-step, lower-1, -step):
colors.append(self.color(r, upper-1, lower, False))
#print(len(colors))
for b in range(lower+step, upper, step):
colors.append(self.color(lower, upper-1, b, False))
#print(len(colors))
colors.append(self.color(lower, upper-1, upper-1, False))
for g in range(upper-step, lower-1, -step):
colors.append(self.color(lower, g, upper-1, False))
#print(len(colors))
for r in range(lower+step, upper, step):
colors.append(self.color(r, lower, upper-1, False))
colors.append(self.color(upper-1, lower, upper-1, False))
#print(len(colors))
for b in range(upper-step, lower, -step):
colors.append(self.color(upper-1, lower, b, False))
#print(len(colors))
colors.append('\x1b[0m')
print(' '.join(colors))
def colorTest(self, args):
for i in (3, 4, 8, 24):
print(i)
self.colorMode = i
self.__colorTestRoutine(0, 128) # dark
self.__colorTestRoutine(0, 256) # medium
self.__colorTestRoutine(128, 256) # light
def showMap(self, args):
"""map [-l]
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'
rows = []
index = 0
exits = {}
doors = {}
useables = {}
items = {}
level = self.gameBase.level
textColor = level.wallColors[0]
floorColor = level.floorColors[0]
for y in range(level.dimensions[1]):
rows.append(['{0}{1:2} {2}{3}'.format(self.clearColor(), y, self.color(textColor[1:]), self.color(floorColor[1:], fg = False))])
rows[-1].append(self.color(textColor[1:]))
for x in range(level.dimensions[0]):
pos = level.mapMatrix[y][x]
thing = level.getThingAtPos(index)
if x == self.gameBase.playerx and y == self.gameBase.playery:
if '#0000FF' != textColor:
textColor = '#0000FF'
rows[-1].append(self.color(textColor[1:]))
rows[-1].append('()')
elif thing:
if thing.graphic[1] != textColor:
textColor = thing.graphic[1]
rows[-1].append(self.color(textColor[1:]))
if thing.thingType == 'x': # exit
rows[-1].append('X{0}'.format(thing.exitid))
exits[thing.exitid] = (thing.name, thing.graphic[1])
elif thing.thingType == 'd': # door
doors[len(doors)+1] = (thing.name, thing.graphic[1])
rows[-1].append('D{0}'.format(len(doors)))
elif thing.thingType == 'u': # useable
useables[len(useables)+1] = (thing.name, thing.graphic[1])
rows[-1].append('U{0}'.format(len(useables)))
elif thing.thingType == 'i': # item
items[len(items)+1] = (thing.name, thing.graphic[1])
rows[-1].append('I{0}'.format(len(items)))
elif pos[0] == 'w':
if level.wallColors[level.mapMatrix[y][x][1]] != textColor:
textColor = level.wallColors[level.mapMatrix[y][x][1]]
rows[-1].append(self.color(textColor[1:]))
sides = 0
if y > 0 and level.mapMatrix[y-1][x][0] == 'w':
sides += GameShell.UP
if x < level.dimensions[0]-1 and level.mapMatrix[y][x+1][0] == 'w':
sides += GameShell.RIGHT
if y < level.dimensions[1]-1 and level.mapMatrix[y+1][x][0] == 'w':
sides += GameShell.DOWN
if x > 0 and level.mapMatrix[y][x-1][0] == 'w':
sides += GameShell.LEFT
rows[-1].append(GameShell.WALLS[sides])
else:
rows[-1].append(' ')
index += 1
rows[-1] = ''.join(rows[-1])
print(xAxis)
print('{0}\n'.format(self.clearColor(False)).join(rows) + self.clearColor())
self.setClearColor()
if len(args) > 0:
if args[0] == '-l' or args[0] == 'l' or args[0] == 'legend':
legend = ["\n---Legend---\n", "{0}(){1} - {2}".format(self.color('0000FF'), self.clearColor(), self.gameBase.playerName),
"Xn - Exit to another area"]
for i in exits:
legend.append(' {0}X{1}{2} - {3}'.format(self.color(exits[i][1][1:]), i, self.clearColor(), exits[i][0]))
legend.append("Un - Useable object")
for i in useables:
legend.append(' {0}U{1}{2} - {3}'.format(self.color(useables[i][1][1:]), i, self.clearColor(), useables[i][0]))
legend.append("In - Item")
for i in items:
legend.append(' {0}I{1}{2} - {3}'.format(self.color(items[i][1][1:]), i, self.clearColor(), items[i][0]))
legend.append("Dn - Door")
for i in doors:
legend.append(' {0}D{1}{2} - {3}'.format(self.color(doors[i][1][1:]), i, self.clearColor(), doors[i][0]))
print('\n'.join(legend))
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
return
def status(self, args):
ret = []
if self.gameBase.level != None:
ret.append("Level:{0:.>74}".format(self.gameBase.level.name))
else:
ret.append("Level:{0:.>74}".format("None"))
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("Player name:{0:.>68}".format(self.gameBase.playerName))
ret.append("Player position:{0:.>64}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.playerx), self.gameBase.playery)))
ret.append("Prev. position:{0:.>65}".format("{0}{1}".format(self.gameBase.numberToLetter(self.gameBase.prevx), self.gameBase.prevy)))
print('\n'.join(ret))
#heapq.heappush(self.gameBase.eventQueue, (self.gameBase.gameTime, gameevents.NoOpEvent()))
return
def inv(self, args):
print('\n'.join([i for i in self.gameBase.playerInv]))
def update(self):
self.gameBase.gameEventLoop()
if __name__ == '__main__':
sh = GameShell(GameBase())
sh.run()

568
shell.py
View file

@ -1,284 +1,284 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# gameshell.py
#
# Copyright 2018 chees <chees@DESKTOP-0CA7MCF>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
# Ver. 0.1.0033
import types as _types
import traceback as _tb
import math as _math
import re as _re
_CONV24TO8 = 6 / 256
class Shell(object):
def __init__(self):
self.__commands = {'exit': self.exitShell, 'batch': self.batch, 'alias': self.makeAlias, 'def': self.defineBatch}
self.__aliases = {}
self.__batches = {}
self.ps1 = '> '
self.ps2 = '. '
self.colorMode = 0 # bits of color depth. Supports: 0, 3, 4, 8, 24
self.prevColor = '\x1b[0m'
self.__exit = False
def __color24(self, r, g, b, fg = True):
if fg:
return '\x1b[38;2;{0};{1};{2}m'.format(r, g, b)
else:
return '\x1b[48;2;{0};{1};{2}m'.format(r, g, b)
def __color8(self, r, g, b, fg = True):
r = _math.floor(r * _CONV24TO8)
g = _math.floor(g * _CONV24TO8)
b = _math.floor(b * _CONV24TO8)
ret = 16 + b + 6 * g + 36 * r
if fg:
return '\x1b[38;5;{0}m'.format(ret)
else:
return '\x1b[48;5;{0}m'.format(ret)
def __color4(self, r, g, b, fg = True):
color = _math.floor(r / 128) + 2 * _math.floor(g / 128) + 4 * _math.floor(b / 128)
r2, g2, b2 = r % 128, g % 128, b % 128
if r2 + g2 + b2 >= 192:
color += 60
if fg:
color += 30
else:
color += 40
return '\x1b[{0}m'.format(color)
def __color3(self, r, g, b, fg = True):
color = _math.floor(r / 128) + 2 * _math.floor(g / 128) + 4 * _math.floor(b / 128)
if fg:
color += 30
else:
color += 40
return '\x1b[{0}m'.format(color)
def colorFromHex(self, color):
"""expects string formmatted like 3377DD"""
return int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16)
def color(self, r, g = 0, b = 0, fg = True, setPrevColor = True):
if isinstance(r, str):
r, g, b = self.colorFromHex(r)
ret = ''
if self.colorMode == 0: # no color
ret = ''
elif self.colorMode == 3:
ret = self.__color3(r, g, b, fg)
elif self.colorMode == 4:
ret = self.__color4(r, g, b, fg)
elif self.colorMode == 8:
ret = self.__color8(r, g, b, fg)
elif self.colorMode == 24:
ret = self.__color24(r, g, b, fg)
else:
ret = ''
if ret == self.prevColor:
return ''
if setPrevColor:
self.prevColor = ret
return ret
def setColor(self, r, g = 0, b = 0, fg = True):
"""Set the text color."""
print(color(r, g, b, fg), end = '')
return
def clearColor(self, setPrevColor = True):
ret = ''
if self.colorMode > 0:
ret = '\x1b[0m'
if ret == self.prevColor:
return ''
if setPrevColor:
self.prevColor = ret
return ret
def setClearColor(self):
print(self.clearColor())
return
def run(self):
"""The main game/shell loop"""
while not self.__exit:
print(self.ps1, end = '')
command = self.scanInput()
# we have to handle shell built-ins first (when we get some)
self.handleCommand(command)
self.update()
self.__exit = False
def man(self, args):
help(self.__commands[args[0]])
def registerCommand(self, commandName: str, command: _types.FunctionType):
"""command must be a function that takes one argument: a list of strings,
conventionally called args or argv"""
self.__commands[commandName] = command
def registerAlias(self, a: str, original: list):
"""makes 'a' an alias for original.
'a' must be one token, but original can be multiple."""
self.__aliases[a] = original
def registerBatch(self, name: str, commands: list):
self.__batches[name] = commands
def getAlias(self, a: str):
if a in self.__aliases:
return self.__aliases[a]
else:
return None
def getBatch(self, name: str):
if name in self.__batches:
return ['batch']
else:
return None
def scanLine(self, instr):
"""Take a line of text and turn it into an argument list"""
if instr == '':
return []
inQuotes = False
ret = []
argStart = 0
c = 0
while c < len(instr):
if inQuotes:
if instr[c] == '"':
inQuotes = False
ret.append(instr[argStart:c])
argStart = c+1
else:
if instr[c] == '"':
inQuotes = True
if argStart != c:
ret.append(instr[argStart:c])
argStart = c+1
elif instr[c] in ' \t\n':
if argStart != c:
ret.append(instr[argStart:c])
argStart = c + 1
c += 1
if argStart != c:
ret.append(instr[argStart:c])
a = self.getAlias(ret[0])
if a:
ret = a + ret[1:]
b = self.getBatch(ret[0])
if b:
ret = b + ret
ret[0] = _re.sub(r'\A\$\((\w+)\)', r'\1', ret[0])
return ret
# Default functions
def exitShell(self, args):
"""The default exit command."""
self.__exit = True
def makeAlias(self, args):
"""Make an alias."""
self.registerAlias(args[0], args[1:])
def defineBatch(self, args):
"""Define a batch file."""
if len(args) < 1:
raise ValueError('def takes at least one argument')
ret = []
command = input(self.ps2)
while command != 'end':
ret.append(command)
command = input(self.ps2)
for i in args:
self.registerBatch(i, ret)
def batch(self, args):
"""Run commands in batch mode
$0 is the name of the batch
$1 - $n are individual arguments
$* is all the arguments except 0
$>0 - $>n is all arguments after the nth
$>=0 - $>=n is the nth and later arguments"""
script = self.__batches[args[0]]
var = _re.compile(r'\$((?:[>][=]?)?[0-9]+)')
u = False
for line in script:
if u:
self.update()
else:
u = True
newLine = line.replace(r'$*', ' '.join(args[1:]))
matches = var.finditer(newLine)
for m in matches:
n = m.group(1)
if n[0] == '>':
if n[1] == '=':
num = int(n[2:])
else:
num = int(n[1:])+1
newLine = newLine.replace(m.group(), ' '.join(args[num:]))
else:
newLine = newLine.replace(m.group(), args[int(n)])
newLine = _re.sub(r'\A({0})'.format(args[0]), r'$(\1)', newLine)
#print(newLine)
self.handleCommand(self.scanLine(newLine))
# Beyond this point are functions that are called within the main loop.
def scanInput(self):
"""Parses input. Override this for custom input parsing, or input source."""
return self.scanLine(input())
def handleCommand(self, command):
if len(command) == 0:
return
if command[0] in self.__commands:
try:
self.__commands[command[0]](command[1:])
except Exception as e:
_tb.print_exc()
print(e)
else:
self.handleUnknownCommand(command)
def handleUnknownCommand(self, command):
"""Handle commands that aren't registered. Override this if you want to do
something with those commands."""
print("Bad command.")
def update(self):
"""Runs at the end of each loop. Does nothing by default. Override this if
there is something you want the shell to do between every command."""
pass
def main(args):
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# gameshell.py
#
# Copyright 2018 chees <chees@DESKTOP-0CA7MCF>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
# Ver. 0.1.0033
import types as _types
import traceback as _tb
import math as _math
import re as _re
_CONV24TO8 = 6 / 256
class Shell(object):
def __init__(self):
self.__commands = {'exit': self.exitShell, 'batch': self.batch, 'alias': self.makeAlias, 'def': self.defineBatch}
self.__aliases = {}
self.__batches = {}
self.ps1 = '> '
self.ps2 = '. '
self.colorMode = 0 # bits of color depth. Supports: 0, 3, 4, 8, 24
self.prevColor = '\x1b[0m'
self.__exit = False
def __color24(self, r, g, b, fg = True):
if fg:
return '\x1b[38;2;{0};{1};{2}m'.format(r, g, b)
else:
return '\x1b[48;2;{0};{1};{2}m'.format(r, g, b)
def __color8(self, r, g, b, fg = True):
r = _math.floor(r * _CONV24TO8)
g = _math.floor(g * _CONV24TO8)
b = _math.floor(b * _CONV24TO8)
ret = 16 + b + 6 * g + 36 * r
if fg:
return '\x1b[38;5;{0}m'.format(ret)
else:
return '\x1b[48;5;{0}m'.format(ret)
def __color4(self, r, g, b, fg = True):
color = _math.floor(r / 128) + 2 * _math.floor(g / 128) + 4 * _math.floor(b / 128)
r2, g2, b2 = r % 128, g % 128, b % 128
if r2 + g2 + b2 >= 192:
color += 60
if fg:
color += 30
else:
color += 40
return '\x1b[{0}m'.format(color)
def __color3(self, r, g, b, fg = True):
color = _math.floor(r / 128) + 2 * _math.floor(g / 128) + 4 * _math.floor(b / 128)
if fg:
color += 30
else:
color += 40
return '\x1b[{0}m'.format(color)
def colorFromHex(self, color):
"""expects string formmatted like 3377DD"""
return int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16)
def color(self, r, g = 0, b = 0, fg = True, setPrevColor = True):
if isinstance(r, str):
r, g, b = self.colorFromHex(r)
ret = ''
if self.colorMode == 0: # no color
ret = ''
elif self.colorMode == 3:
ret = self.__color3(r, g, b, fg)
elif self.colorMode == 4:
ret = self.__color4(r, g, b, fg)
elif self.colorMode == 8:
ret = self.__color8(r, g, b, fg)
elif self.colorMode == 24:
ret = self.__color24(r, g, b, fg)
else:
ret = ''
if ret == self.prevColor:
return ''
if setPrevColor:
self.prevColor = ret
return ret
def setColor(self, r, g = 0, b = 0, fg = True):
"""Set the text color."""
print(color(r, g, b, fg), end = '')
return
def clearColor(self, setPrevColor = True):
ret = ''
if self.colorMode > 0:
ret = '\x1b[0m'
if ret == self.prevColor:
return ''
if setPrevColor:
self.prevColor = ret
return ret
def setClearColor(self):
print(self.clearColor())
return
def run(self):
"""The main game/shell loop"""
while not self.__exit:
print(self.ps1, end = '')
command = self.scanInput()
# we have to handle shell built-ins first (when we get some)
self.handleCommand(command)
self.update()
self.__exit = False
def man(self, args):
help(self.__commands[args[0]])
def registerCommand(self, commandName: str, command: _types.FunctionType):
"""command must be a function that takes one argument: a list of strings,
conventionally called args or argv"""
self.__commands[commandName] = command
def registerAlias(self, a: str, original: list):
"""makes 'a' an alias for original.
'a' must be one token, but original can be multiple."""
self.__aliases[a] = original
def registerBatch(self, name: str, commands: list):
self.__batches[name] = commands
def getAlias(self, a: str):
if a in self.__aliases:
return self.__aliases[a]
else:
return None
def getBatch(self, name: str):
if name in self.__batches:
return ['batch']
else:
return None
def scanLine(self, instr):
"""Take a line of text and turn it into an argument list"""
if instr == '':
return []
inQuotes = False
ret = []
argStart = 0
c = 0
while c < len(instr):
if inQuotes:
if instr[c] == '"':
inQuotes = False
ret.append(instr[argStart:c])
argStart = c+1
else:
if instr[c] == '"':
inQuotes = True
if argStart != c:
ret.append(instr[argStart:c])
argStart = c+1
elif instr[c] in ' \t\n':
if argStart != c:
ret.append(instr[argStart:c])
argStart = c + 1
c += 1
if argStart != c:
ret.append(instr[argStart:c])
a = self.getAlias(ret[0])
if a:
ret = a + ret[1:]
b = self.getBatch(ret[0])
if b:
ret = b + ret
ret[0] = _re.sub(r'\A\$\((\w+)\)', r'\1', ret[0])
return ret
# Default functions
def exitShell(self, args):
"""The default exit command."""
self.__exit = True
def makeAlias(self, args):
"""Make an alias."""
self.registerAlias(args[0], args[1:])
def defineBatch(self, args):
"""Define a batch file."""
if len(args) < 1:
raise ValueError('def takes at least one argument')
ret = []
command = input(self.ps2)
while command != 'end':
ret.append(command)
command = input(self.ps2)
for i in args:
self.registerBatch(i, ret)
def batch(self, args):
"""Run commands in batch mode
$0 is the name of the batch
$1 - $n are individual arguments
$* is all the arguments except 0
$>0 - $>n is all arguments after the nth
$>=0 - $>=n is the nth and later arguments"""
script = self.__batches[args[0]]
var = _re.compile(r'\$((?:[>][=]?)?[0-9]+)')
u = False
for line in script:
if u:
self.update()
else:
u = True
newLine = line.replace(r'$*', ' '.join(args[1:]))
matches = var.finditer(newLine)
for m in matches:
n = m.group(1)
if n[0] == '>':
if n[1] == '=':
num = int(n[2:])
else:
num = int(n[1:])+1
newLine = newLine.replace(m.group(), ' '.join(args[num:]))
else:
newLine = newLine.replace(m.group(), args[int(n)])
newLine = _re.sub(r'\A({0})'.format(args[0]), r'$(\1)', newLine)
#print(newLine)
self.handleCommand(self.scanLine(newLine))
# Beyond this point are functions that are called within the main loop.
def scanInput(self):
"""Parses input. Override this for custom input parsing, or input source."""
return self.scanLine(input())
def handleCommand(self, command):
if len(command) == 0:
return
if command[0] in self.__commands:
try:
self.__commands[command[0]](command[1:])
except Exception as e:
_tb.print_exc()
print(e)
else:
self.handleUnknownCommand(command)
def handleUnknownCommand(self, command):
"""Handle commands that aren't registered. Override this if you want to do
something with those commands."""
print("Bad command.")
def update(self):
"""Runs at the end of each loop. Does nothing by default. Override this if
there is something you want the shell to do between every command."""
pass
def main(args):
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))

View file

@ -1,51 +1,51 @@
{
"openingText": "Floor 1 map loaded successfully. Normally, this would describe the environment.",
"playerStart": [5, 26],
"layout": [
"w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ",
"w w ",
"w w w w w w w w w w w ",
"w w w w w w w ",
"w w w w w w w w w w w ",
"w w w w w w w w w ",
"w w w w w w ",
"w w w w w w w w w w w w ",
"w w w w w w w w w w w w w ",
"w w w w w w w w w w w w w w w w w w ",
"w w w w w w w w w w w ",
"w w w w w w w w w ",
"w w w w w w w ",
"w w w w w w w w w w w w w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w ",
"w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w w w w w w w ",
"w w w w w w ",
"w w w w ",
"w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w w ",
"w w w w w ",
"w w w w w w ",
"w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w "
],
"things": [
{
"type": "exit",
"id": 1,
"location": [5, 10],
"destination": "testing/test2.xml",
"name": "upstairs"
},
{
"type": "exit",
"id": 2,
"location": [21, 23],
"destination": "testing/test4.xml",
"name": "downstairs"
}
]
}
{
"openingText": "Floor 1 map loaded successfully. Normally, this would describe the environment.",
"playerStart": [5, 26],
"layout": [
"w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ",
"w w ",
"w w w w w w w w w w w ",
"w w w w w w w ",
"w w w w w w w w w w w ",
"w w w w w w w w w ",
"w w w w w w ",
"w w w w w w w w w w w w ",
"w w w w w w w w w w w w w ",
"w w w w w w w w w w w w w w w w w w ",
"w w w w w w w w w w w ",
"w w w w w w w w w ",
"w w w w w w w ",
"w w w w w w w w w w w w w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w ",
"w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w w w w w w w ",
"w w w w w w ",
"w w w w ",
"w w w w w w ",
"w w w w w w w w w w ",
"w w w w w w w ",
"w w w w w ",
"w w w w w w ",
"w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w "
],
"things": [
{
"type": "exit",
"id": 1,
"location": [5, 10],
"destination": "testing/test2.xml",
"name": "upstairs"
},
{
"type": "exit",
"id": 2,
"location": [21, 23],
"destination": "testing/test4.xml",
"name": "downstairs"
}
]
}

View file

@ -1,35 +1,35 @@
<map openingText="Floor 1 map loaded successfully. Normally, this would describe the environment." playerStart="5, 26">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w w
w w w w w w w w w w w
w w w w w w w
w w w w w w w w w w w
w w w w w w w w w
w w w w w w
w w w w w w w w w w w w
w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w
w w w w w w w w w w w
w w w w w w w w w
w w w w w w w
w w w w w w w w w w w w w w w w w w
w w w w w w w w w w
w w w w w w
w w w w w w
w w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w
w w w w w w
w w w w
w w w w w w
w w w w w w w w w w
w w w w w w w
w w w w w
w w w w w w
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
</layout>
<exit id="1" location="5, 10" destination="testing/test2.xml" name="upstairs"/>
<exit id="2" location="21, 23" destination="testing/test4.xml" name="downstairs"/>
</map>
<map openingText="Floor 1 map loaded successfully. Normally, this would describe the environment." playerStart="5, 26">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w w
w w w w w w w w w w w
w w w w w w w
w w w w w w w w w w w
w w w w w w w w w
w w w w w w
w w w w w w w w w w w w
w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w
w w w w w w w w w w w
w w w w w w w w w
w w w w w w w
w w w w w w w w w w w w w w w w w w
w w w w w w w w w w
w w w w w w
w w w w w w
w w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w
w w w w w w
w w w w
w w w w w w
w w w w w w w w w w
w w w w w w w
w w w w w
w w w w w w
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
</layout>
<exit id="1" location="5, 10" destination="testing/test2.xml" name="upstairs"/>
<exit id="2" location="21, 23" destination="testing/test4.xml" name="downstairs"/>
</map>

View file

@ -1,45 +1,45 @@
%YAML 1.2
---
openingText: Floor 1 map loaded successfully. Normally, this would describe the environment.
playerStart: [5, 26]
layout: |
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w0
w w0
w w w w w w w w w w w0
w w w w w w w0
w w w w w w w w w w w0
w w w w w w w w w0
w w w w w w0
w w w w w w w w w w w w0
w w w w w w w w w w w w w0
W w w w w w w w w w w w w w w w w w0
w w w w w w w w w w w0
w w w w w w w w w0
w w w w w w w0
w w w w w w w w w w w w w w w w w w0
w w w w w w w w w w0
w w w w w w0
w w w w w w0
w w w w w w w w w w0
w w w w w w w w w w0
w w w w w w w w w w w w0
w w w w w w0
w w w w0
w w w w w w0
w w w w w w w w w w0
w w w w w w w0
w w w w w0
w w w w w w0
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w0
things:
- !Exit
id: 1
location: [5, 10]
destination: testing/test2.xml
name: upstairs
- !Exit
id: 2
location: [21, 23]
destination: testing/test4.xml
name: downstairs
%YAML 1.2
---
openingText: Floor 1 map loaded successfully. Normally, this would describe the environment.
playerStart: [5, 26]
layout: |
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w0
w w0
w w w w w w w w w w w0
w w w w w w w0
w w w w w w w w w w w0
w w w w w w w w w0
w w w w w w0
w w w w w w w w w w w w0
w w w w w w w w w w w w w0
W w w w w w w w w w w w w w w w w w0
w w w w w w w w w w w0
w w w w w w w w w0
w w w w w w w0
w w w w w w w w w w w w w w w w w w0
w w w w w w w w w w0
w w w w w w0
w w w w w w0
w w w w w w w w w w0
w w w w w w w w w w0
w w w w w w w w w w w w0
w w w w w w0
w w w w0
w w w w w w0
w w w w w w w w w w0
w w w w w w w0
w w w w w0
w w w w w w0
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w0
loadAlways:
- !Exit
id: 1
location: [5, 10]
destination: testing/test2.yml
name: upstairs
- !Exit
id: 2
location: [21, 23]
destination: testing/test4.yml
name: downstairs

View file

@ -1,37 +1,37 @@
<map openingText="Floor 2" playerStart="6, 10">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w w w w w w x3 w w w w w w w w w
w w w w w w w w w w w w w
w w w w w w w w w w
w w w w w w w
w w w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w
w x1 x2 w w w w
w w w w w w w
w w w w w w w w w
w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w x4 w
w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w
w w w w w w w w
w w w w w w w w w w
w w w w w w w w w
w w w w
w w w w
w w w w w w
w w w w w w w
w w w w
w w w w
w w w w w w
w w w w w w w w w w w w
</layout>
<exit id="1" location="5, 10" destination="testing/test1.xml" name="downstairs"/>
<exit id="2" location="7, 10" destination="testing/test3.xml" name="upstairs"/>
<exit id="3" location="6, 1" destination="testing/test3.xml" name="north"/>
<exit id="4" location="25, 14" destination="testing/test3.xml" name="east"/>
</map>
<map openingText="Floor 2" playerStart="6, 10">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w w w w w w x3 w w w w w w w w w
w w w w w w w w w w w w w
w w w w w w w w w w
w w w w w w w
w w w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w
w x1 x2 w w w w
w w w w w w w
w w w w w w w w w
w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w x4 w
w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w
w w w w w w w w
w w w w w w w w w w
w w w w w w w w w
w w w w
w w w w
w w w w w w
w w w w w w w
w w w w
w w w w
w w w w w w
w w w w w w w w w w w w
</layout>
<exit id="1" location="5, 10" destination="testing/test1.xml" name="downstairs"/>
<exit id="2" location="7, 10" destination="testing/test3.xml" name="upstairs"/>
<exit id="3" location="6, 1" destination="testing/test3.xml" name="north"/>
<exit id="4" location="25, 14" destination="testing/test3.xml" name="east"/>
</map>

62
testing/test2.yml Normal file
View file

@ -0,0 +1,62 @@
%YAML 1.2
---
layout: |
w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0
w0w0w0w0w0w0 w0 w0 w0 w0w0w0w0w0w0
w0w0w0w0 w0 w0 w0w0 w0 w0w0w0w0
w0w0w0w0 w0 w0 w0w0 w0w0
w0w0 w0 w0w0w0 w0
w0w0 w0w0w0 w0w0w0w0w0 w0
w0 w0 w0 w0 w0w0w0w0w0 w0
w0 w0 w0 w0 w0w0w0w0w0 w0
w0 w0 w0w0w0w0 w0w0w0w0w0w0w0w0w0w0
w0w0w0w0w0w0w0w0w0w0 w0w0w0 w0w0 w0w0w0w0
w0 w0w0 w0 w0
w0 w0 w0w0w0 w0 w0
w0 w0w0 w0w0w0w0 w0 w0
w0 w0w0 w0w0w0w0w0w0w0w0w0 w0 w0w0w0w0
w0w0w0w0w0 w0w0w0 w0w0w0w0w0w0w0 w0w0 w0
w0w0w0w0 w0w0w0 w0w0w0w0w0w0w0 w0w0 w0
w0 w0w0w0w0w0 w0 w0 w0w0w0w0w0w0w0w0w0w0w0w0
w0 w0w0w0w0w0 w0 w0 e0
w0w0w0w0w0w0w0w0 w0 w0 e0
w0w0w0w0w0w0 w0 w0 w0 e0
w0 w0 w0 w0 e0
w0 w0 w0 w0 e0
w0 w0w0w0w0 w0 e0
w0 w0w0w0w0 w0 w0 e0
w0 w0 w0 w0 e0
w0 w0 w0 w0 e0
w0 w0 w0w0w0w0 e0
w0w0w0w0w0w0w0w0w0w0w0w0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0
openingText: Floor 2
playerStart: [6, 10]
description: ''
floorColors: ['#9F7F5F']
wallColors: ['#7F3F0F']
loadAlways:
- !Exit
name: downstairs
location: [5, 10]
id: 1
destination: testing/test1.yml
graphic: {fgc: '#7F7F7F', shape: '#'}
- !Exit
name: upstairs
location: [7, 10]
id: 2
destination: testing/test3.yml
graphic: {fgc: '#7F7F7F', shape: '#'}
- !Exit
name: north
location: [6, 1]
id: 3
destination: testing/test3.yml
graphic: {fgc: '#7F7F7F', shape: '#'}
- !Exit
name: east
location: [25, 14]
id: 4
destination: testing/test3.yml
graphic: {fgc: '#7F7F7F', shape: '#'}
loadOnce: []

View file

@ -1,26 +1,26 @@
<map openingText="Floor 3" playerStart="6, 10">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w x3 w w w w w w w w w w w w w w w w w w
w w w w w w w w w
w w w w w w w w w
w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w w w
w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w w w w
w w w x2 w w w w w w
w w w w w w w w
w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w w w w
w w w w w w w w w x4 w
w w w w w w w w w w
w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w
</layout>
<exit id="2" location="7, 10" destination="testing/test2.xml" name="downstairs"/>
<exit id="3" location="6, 1" destination="testing/test2.xml" name="north"/>
<exit id="4" location="25, 14" destination="testing/test2.xml" name="east"/>
</map>
<map openingText="Floor 3" playerStart="6, 10">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w x3 w w w w w w w w w w w w w w w w w w
w w w w w w w w w
w w w w w w w w w
w w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w w w
w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w w w w
w w w x2 w w w w w w
w w w w w w w w
w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w w w w
w w w w w w w w w x4 w
w w w w w w w w w w
w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w
</layout>
<exit id="2" location="7, 10" destination="testing/test2.xml" name="downstairs"/>
<exit id="3" location="6, 1" destination="testing/test2.xml" name="north"/>
<exit id="4" location="25, 14" destination="testing/test2.xml" name="east"/>
</map>

46
testing/test3.yml Normal file
View file

@ -0,0 +1,46 @@
%YAML 1.2
---
layout: |
w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0
w0 w0w0w0w0 w0w0w0w0w0w0w0w0 w0w0w0w0w0w0
w0 w0w0 w0 w0 w0w0w0w0
w0 w0w0 w0 w0 w0w0w0w0
w0w0w0 w0 w0w0 w0w0w0
w0w0w0 w0w0 w0w0 w0w0w0
w0w0w0w0w0w0w0w0w0w0 w0 w0w0 w0
w0w0w0w0w0w0w0w0w0w0 w0 w0w0 w0
w0w0w0w0w0 w0w0w0w0 w0 w0w0w0w0w0w0 w0
w0w0w0w0w0 w0w0w0 w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0
w0 w0w0 w0w0 w0w0 w0 w0
w0 w0w0 w0w0w0 w0 w0
w0 w0w0 w0w0 w0w0w0 w0w0 w0 w0
w0 w0w0 w0w0w0w0w0w0w0w0w0w0w0w0w0w0 w0w0w0w0w0w0
w0w0w0w0 w0w0w0w0 w0 w0
w0w0w0w0 w0w0w0w0 w0 w0
w0 w0w0w0w0w0w0 w0 w0
w0w0w0w0w0w0w0w0w0w0w0w0e0e0e0e0e0e0e0e0e0e0w0w0w0w0w0w0w0w0
openingText: Floor 3
playerStart: [6, 10]
description: ''
floorColors: ['#9F7F5F']
wallColors: ['#7F3F0F']
loadAlways:
- !Exit
name: downstairs
location: [7, 10]
id: 2
destination: testing/test2.yml
graphic: {fgc: '#7F7F7F', shape: '#'}
- !Exit
name: north
location: [6, 1]
id: 3
destination: testing/test2.yml
graphic: {fgc: '#7F7F7F', shape: '#'}
- !Exit
name: east
location: [25, 14]
id: 4
destination: testing/test2.yml
graphic: {fgc: '#7F7F7F', shape: '#'}
loadOnce: []

View file

@ -1,34 +1,34 @@
<map openingText="Basement" playerStart="22, 22">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w
w w w w w w w w w
w w w w w w w w w w
w w w w w w
w w w w w w w w w w w w w w w w w w w w
w w
w w
w w w w w w w w w w w w w w w w w w w w w w w w w
w w w w
w w w w
w w w w w w w w
w w w w
w w w w
w w w w
w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w
w w w w
w w w w
w w w w w w
w w w w w w
w w x2 w
w w w
w w w w
w w w w w
w w w w
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
</layout>
<exit id="2" location="23, 22" destination="testing/test1.xml" name="upstairs"/>
</map>
<map openingText="Basement" playerStart="22, 22">
<layout>
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w w
w w w w w w w w w
w w w w w w w w w w
w w w w w w
w w w w w w w w w w w w w w w w w w w w
w w
w w
w w w w w w w w w w w w w w w w w w w w w w w w w
w w w w
w w w w
w w w w w w w w
w w w w
w w w w
w w w w
w w w w w w w w
w w w w w w w w w w
w w w w w w w w w w w w w w w w w w w
w w w w
w w w w
w w w w w w
w w w w w w
w w x2 w
w w w
w w w w
w w w w w
w w w w
w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w
</layout>
<exit id="2" location="23, 22" destination="testing/test1.xml" name="upstairs"/>
</map>

44
testing/test4.yml Normal file
View file

@ -0,0 +1,44 @@
%YAML 1.2
---
layout: |
w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0
w0w0w0w0w0w0w0w0 w0w0w0w0w0w0w0w0w0w0w0 w0
w0w0 w0 w0w0 w0 w0 w0 w0
w0w0 w0 w0w0w0 w0 w0 w0 w0
w0 w0w0 w0 w0 w0
w0 w0w0 w0w0w0 w0w0w0w0w0w0w0w0w0w0 w0w0w0w0
w0 w0
w0 w0
w0w0w0w0 w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0 w0
w0 w0 w0 w0
w0 w0 w0 w0
w0 w0w0 w0w0 w0 w0 w0
w0 w0 w0 w0
w0 w0 w0 w0
w0 w0 w0 w0
w0 w0w0 w0w0 w0 w0 w0
w0 w0 w0w0w0 w0w0w0 w0 w0
w0w0w0w0w0w0w0w0w0w0 w0w0w0 w0w0w0 w0 w0w0
w0 w0 w0 w0
w0 w0 w0 w0
w0 w0 w0w0 w0 w0
w0 w0 w0w0 w0 w0
w0 w0 w0
w0 w0 w0
w0 w0 w0 w0
w0 w0 w0 w0 w0
w0 w0 w0 w0
w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0w0
openingText: Basement
playerStart: [22, 22]
description: ''
floorColors: ['#9F7F5F']
wallColors: ['#7F3F0F']
loadAlways:
- !Exit
name: upstairs
location: [23, 22]
id: 2
destination: testing/test1.xml
graphic: {fgc: '#7F7F7F', shape: '#'}
loadOnce: []

88
tile.py
View file

@ -1,44 +1,44 @@
from tkinter import *
class Tile:
"""A representation of a tile on the display"""
shapes = {'circle' : 'o', 'cross' : 'x', 'triangle' : '^', 'none' : ' ',
'square' : '#', 'vertical' : '|', 'horizontal' : '-'}
def __init__(self, bgroundColor, fgroundColor = 'white', fgroundShape = ' '):
self.bgc = bgroundColor
self.fgc = fgroundColor
self.fgs = fgroundShape
def paint(self, display, x, y): #display being a canvas
if type(display) != Canvas:
raise TypeError('Display must be a tkinter.Canvas.')
else:
tag = '(' + str(int(x)) + ', ' + str(int(y)) + ')'
display.delete(tag) #delete the old tile before creating a new one.
if self.bgc != 'clear':
display.create_rectangle((x*32, y*32, x*32+32, y*32+32),
fill = self.bgc, width = 0, tags = (tag))
if self.fgs == Tile.shapes['triangle']:
display.create_polygon((x*32+15, y*32+2, x*32+2, y*32+30,
x*32+30, y*32+30, x*32+16, y*32+2),
fill = self.fgc, width = 0, tags = (tag))
elif self.fgs == Tile.shapes['circle']:
display.create_oval((x*32+2, y*32+2, x*32+30, y*32+30),
fill = self.fgc, width = 0, tags = (tag))
elif self.fgs == Tile.shapes['cross']:
display.create_line((x*32+2, y*32+2, x*32+30, y*32+30),
fill = self.fgc, width = 3, tags = (tag))
display.create_line((x*32+30, y*32+2, x*32+2, y*32+30),
fill = self.fgc, width = 3, tags = (tag))
elif self.fgs == Tile.shapes['square']:
display.create_rectangle((x*32+2, y*32+2, x*32+30, y*32+30),
fill = self.fgc, width = 0, tags = (tag))
elif self.fgs == Tile.shapes['vertical']:
display.create_line((x*32+16, y*32, x*32+16, y*32+32),
fill = self.fgc, width = 3, tags = (tag))
elif self.fgs == Tile.shapes['horizontal']:
display.create_line((x*32, y*32+16, x*32+32, y*32+16),
fill = self.fgc, width = 3, tags = (tag))
else: pass
from tkinter import *
class Tile:
"""A representation of a tile on the display"""
shapes = {'circle' : 'o', 'cross' : 'x', 'triangle' : '^', 'none' : ' ',
'square' : '#', 'vertical' : '|', 'horizontal' : '-'}
def __init__(self, bgroundColor, fgroundColor = 'white', fgroundShape = ' '):
self.bgc = bgroundColor
self.fgc = fgroundColor
self.fgs = fgroundShape
def paint(self, display, x, y): #display being a canvas
if type(display) != Canvas:
raise TypeError('Display must be a tkinter.Canvas.')
else:
tag = '(' + str(int(x)) + ', ' + str(int(y)) + ')'
display.delete(tag) #delete the old tile before creating a new one.
if self.bgc != 'clear':
display.create_rectangle((x*32, y*32, x*32+32, y*32+32),
fill = self.bgc, width = 0, tags = (tag))
if self.fgs == Tile.shapes['triangle']:
display.create_polygon((x*32+15, y*32+2, x*32+2, y*32+30,
x*32+30, y*32+30, x*32+16, y*32+2),
fill = self.fgc, width = 0, tags = (tag))
elif self.fgs == Tile.shapes['circle']:
display.create_oval((x*32+2, y*32+2, x*32+30, y*32+30),
fill = self.fgc, width = 0, tags = (tag))
elif self.fgs == Tile.shapes['cross']:
display.create_line((x*32+2, y*32+2, x*32+30, y*32+30),
fill = self.fgc, width = 3, tags = (tag))
display.create_line((x*32+30, y*32+2, x*32+2, y*32+30),
fill = self.fgc, width = 3, tags = (tag))
elif self.fgs == Tile.shapes['square']:
display.create_rectangle((x*32+2, y*32+2, x*32+30, y*32+30),
fill = self.fgc, width = 0, tags = (tag))
elif self.fgs == Tile.shapes['vertical']:
display.create_line((x*32+16, y*32, x*32+16, y*32+32),
fill = self.fgc, width = 3, tags = (tag))
elif self.fgs == Tile.shapes['horizontal']:
display.create_line((x*32, y*32+16, x*32+32, y*32+16),
fill = self.fgc, width = 3, tags = (tag))
else: pass