Loading game.py +2 −1 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import random class Game: def __init__(self, labyrinthFileName, adminPW, logFileName=None, port=1234): self.players = [] self.admins = [] with open(labyrinthFileName,'r') as f: self.labyrinth = labyrinth.Labyrinth(game=self,stream=f) self.sock = socket.socket() Loading @@ -16,7 +17,6 @@ class Game: self.sel.register(self.sock, selectors.EVENT_READ, self.accept) self.logFile = None if logFileName is None else open(logFileName, 'a') self.adminPW = adminPW self.admins = [] # low-level functions def accept(self, sock, mask): Loading Loading @@ -57,6 +57,7 @@ class Game: print(*args, file=self.logFile, flush=True) def showAdmins(self): if not self.admins: return lab = self.labyrinth.writelab() for admin in self.admins: admin.send(lab) Loading labyrinth.py +45 −39 Original line number Diff line number Diff line # class for the labyrinth from enum import Enum import itertools from functools import reduce from wall import Wall directions = {"north": (-1, 0), "east": (0, 1), "west": (0, -1), "south": (1, 0)} directions_inv = {v:k for k, v in directions.items()} class Labyrinth: class GroundType(Enum): FLOOR = 1 WALL = 2 def describeThings(things): # always starts with there is/there are if len(things) == 0: return "there is nothing" elif len(things) == 1: return "there is "+str(things[0]) else: return "there are "+(", ".join([x.toString() for x in things[:-1]]))+" and "+things[-1].toString() class Labyrinth: class Field: def __init__(self,groundtype,column,row,labyrinth): def __init__(self,column,row,labyrinth): # please only read from these members self.groundtype = groundtype self.column = column self.row = row self.labyrinth = labyrinth Loading @@ -23,25 +30,15 @@ class Labyrinth: def _removeThing(self,thing): self.things.remove(thing) def _addThing(self,thing): assert self.things.count(thing) == 0 assert self.groundtype != Labyrinth.GroundType.WALL assert thing not in self.things self.things.append(thing) def neighbor(self,dy,dx): return self.labyrinth.getTileAt(self.row + dy, self.column + dx) def isWalkable(self): # this may be more complicated in the future return self.groundtype == Labyrinth.GroundType.FLOOR def __str__(self): # always starts with there is/there are if self.groundtype == Labyrinth.GroundType.WALL: return "there is a wall" else: if len(self.things) == 0: return "there is nothing" elif len(self.things) == 1: return "there is "+str(self.things[0]) else: return "there are "+(", ".join([x.toString() for x in self.things[:-1]]))+" and "+self.things[-1].toString() for thing in self.things: if thing.blocksMove(): return False return True # constructor for a completely read labyrinth def __init__(self,game=None,width=None,height=None,stream=None): Loading @@ -49,7 +46,7 @@ class Labyrinth: if width is not None: # empty labyrinth of given size assert height is not None assert stream is None self.tiles = [[Labyrinth.Field(Labyrinth.GroundType.FLOOR,col,row,self) for col in range(width)] for row in range(height)] self.tiles = [[Labyrinth.Field(col,row,self) for col in range(width)] for row in range(height)] elif height is not None: assert False # width None, height not elif stream is not None: Loading @@ -60,11 +57,17 @@ class Labyrinth: tiles = [] for rownum,line in enumerate(stream): row = [] for colnum,char in enumerate(line): for colnum,char in enumerate(line[:-1]): field = Labyrinth.Field(colnum,rownum,self) if char in [' ','0','_']: row.append(Labyrinth.Field(Labyrinth.GroundType.FLOOR,colnum,rownum,self)) pass elif char in ['W','w','#','1']: row.append(Labyrinth.Field(Labyrinth.GroundType.WALL,colnum,rownum,self)) wall = Wall() wall.field = field field._addThing(wall) else: raise Exception("Unexpected character '{0}'".format(char)) row.append(field) tiles.append(row) return tiles Loading @@ -72,13 +75,10 @@ class Labyrinth: result = "" for row in self.tiles: for field in row: if field.groundtype == Labyrinth.GroundType.WALL: result += "#" else: if not field.things: result += "." elif len(field.things) == 1: result += field.things[0].asChar() result += repr(field.things[0]) else: result += "+" result += "\n" Loading @@ -103,12 +103,18 @@ class Labyrinth: return reduce(lambda x,y:x+y, self.tiles) def getFreeTiles (self): return list(filter(lambda f: f.groundtype == Labyrinth.GroundType.FLOOR and len(f.things) == 0 ,self.getTiles())) return list(filter(Labyrinth.Field.isWalkable, self.getTiles())) def getDescription (self, field): def getDescription (self, player): descr = "" for name,field in zip(["North","South","West","East"], [self.getTileAt(field.row+row,field.column+column) for row,column in [(-1,0),(1,0),(0,-1),(0,1)]]): descr += "In the "+name+" "+("there is a wall" if field is None else str(field))+".\n" local = list(filter(lambda thing: thing != player, player.field.things)) if local: descr += "Next to you, "+describeThings(local)+"\n" for direction, (dy,dx) in directions.items(): field = player.field.neighbor(dx=dx, dy=dy) if field is None: continue if field.things: descr += "In the "+direction+", "+describeThings(field.things)+"\n" return descr def moveThing (self, thing, newField, beforeFinish=None): Loading @@ -130,7 +136,7 @@ class Labyrinth: def createThing (self, thing, field): thing.field = field field._addThing(thing) thing.onMove(field) if thing.onMove(field): thing.afterMove(field) self.game.showAdmins() Loading player.py +2 −2 Original line number Diff line number Diff line Loading @@ -132,8 +132,8 @@ class Player(Thing): self.send("I don't know what you are talking about") def afterMove(self, oldField): desc = self.game.labyrinth.getDescription(self.field) desc = self.game.labyrinth.getDescription(self) self.send(desc, end="") def asChar(self): def __repr__(self): return "P" thing.py +4 −1 Original line number Diff line number Diff line Loading @@ -8,5 +8,8 @@ class Thing(): def afterMove(self, oldField): pass def asChar(self): def blocksMove(self): return False def __repr__(self): return "?" wall.py 0 → 100644 +17 −0 Original line number Diff line number Diff line from thing import Thing class Wall(Thing): def __init__(self): super().__init__() def onMove(self, newField): return False def blocksMove(self): return True def __str__(self): return "a wall" def __repr__(self): return "#" Loading
game.py +2 −1 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import random class Game: def __init__(self, labyrinthFileName, adminPW, logFileName=None, port=1234): self.players = [] self.admins = [] with open(labyrinthFileName,'r') as f: self.labyrinth = labyrinth.Labyrinth(game=self,stream=f) self.sock = socket.socket() Loading @@ -16,7 +17,6 @@ class Game: self.sel.register(self.sock, selectors.EVENT_READ, self.accept) self.logFile = None if logFileName is None else open(logFileName, 'a') self.adminPW = adminPW self.admins = [] # low-level functions def accept(self, sock, mask): Loading Loading @@ -57,6 +57,7 @@ class Game: print(*args, file=self.logFile, flush=True) def showAdmins(self): if not self.admins: return lab = self.labyrinth.writelab() for admin in self.admins: admin.send(lab) Loading
labyrinth.py +45 −39 Original line number Diff line number Diff line # class for the labyrinth from enum import Enum import itertools from functools import reduce from wall import Wall directions = {"north": (-1, 0), "east": (0, 1), "west": (0, -1), "south": (1, 0)} directions_inv = {v:k for k, v in directions.items()} class Labyrinth: class GroundType(Enum): FLOOR = 1 WALL = 2 def describeThings(things): # always starts with there is/there are if len(things) == 0: return "there is nothing" elif len(things) == 1: return "there is "+str(things[0]) else: return "there are "+(", ".join([x.toString() for x in things[:-1]]))+" and "+things[-1].toString() class Labyrinth: class Field: def __init__(self,groundtype,column,row,labyrinth): def __init__(self,column,row,labyrinth): # please only read from these members self.groundtype = groundtype self.column = column self.row = row self.labyrinth = labyrinth Loading @@ -23,25 +30,15 @@ class Labyrinth: def _removeThing(self,thing): self.things.remove(thing) def _addThing(self,thing): assert self.things.count(thing) == 0 assert self.groundtype != Labyrinth.GroundType.WALL assert thing not in self.things self.things.append(thing) def neighbor(self,dy,dx): return self.labyrinth.getTileAt(self.row + dy, self.column + dx) def isWalkable(self): # this may be more complicated in the future return self.groundtype == Labyrinth.GroundType.FLOOR def __str__(self): # always starts with there is/there are if self.groundtype == Labyrinth.GroundType.WALL: return "there is a wall" else: if len(self.things) == 0: return "there is nothing" elif len(self.things) == 1: return "there is "+str(self.things[0]) else: return "there are "+(", ".join([x.toString() for x in self.things[:-1]]))+" and "+self.things[-1].toString() for thing in self.things: if thing.blocksMove(): return False return True # constructor for a completely read labyrinth def __init__(self,game=None,width=None,height=None,stream=None): Loading @@ -49,7 +46,7 @@ class Labyrinth: if width is not None: # empty labyrinth of given size assert height is not None assert stream is None self.tiles = [[Labyrinth.Field(Labyrinth.GroundType.FLOOR,col,row,self) for col in range(width)] for row in range(height)] self.tiles = [[Labyrinth.Field(col,row,self) for col in range(width)] for row in range(height)] elif height is not None: assert False # width None, height not elif stream is not None: Loading @@ -60,11 +57,17 @@ class Labyrinth: tiles = [] for rownum,line in enumerate(stream): row = [] for colnum,char in enumerate(line): for colnum,char in enumerate(line[:-1]): field = Labyrinth.Field(colnum,rownum,self) if char in [' ','0','_']: row.append(Labyrinth.Field(Labyrinth.GroundType.FLOOR,colnum,rownum,self)) pass elif char in ['W','w','#','1']: row.append(Labyrinth.Field(Labyrinth.GroundType.WALL,colnum,rownum,self)) wall = Wall() wall.field = field field._addThing(wall) else: raise Exception("Unexpected character '{0}'".format(char)) row.append(field) tiles.append(row) return tiles Loading @@ -72,13 +75,10 @@ class Labyrinth: result = "" for row in self.tiles: for field in row: if field.groundtype == Labyrinth.GroundType.WALL: result += "#" else: if not field.things: result += "." elif len(field.things) == 1: result += field.things[0].asChar() result += repr(field.things[0]) else: result += "+" result += "\n" Loading @@ -103,12 +103,18 @@ class Labyrinth: return reduce(lambda x,y:x+y, self.tiles) def getFreeTiles (self): return list(filter(lambda f: f.groundtype == Labyrinth.GroundType.FLOOR and len(f.things) == 0 ,self.getTiles())) return list(filter(Labyrinth.Field.isWalkable, self.getTiles())) def getDescription (self, field): def getDescription (self, player): descr = "" for name,field in zip(["North","South","West","East"], [self.getTileAt(field.row+row,field.column+column) for row,column in [(-1,0),(1,0),(0,-1),(0,1)]]): descr += "In the "+name+" "+("there is a wall" if field is None else str(field))+".\n" local = list(filter(lambda thing: thing != player, player.field.things)) if local: descr += "Next to you, "+describeThings(local)+"\n" for direction, (dy,dx) in directions.items(): field = player.field.neighbor(dx=dx, dy=dy) if field is None: continue if field.things: descr += "In the "+direction+", "+describeThings(field.things)+"\n" return descr def moveThing (self, thing, newField, beforeFinish=None): Loading @@ -130,7 +136,7 @@ class Labyrinth: def createThing (self, thing, field): thing.field = field field._addThing(thing) thing.onMove(field) if thing.onMove(field): thing.afterMove(field) self.game.showAdmins() Loading
player.py +2 −2 Original line number Diff line number Diff line Loading @@ -132,8 +132,8 @@ class Player(Thing): self.send("I don't know what you are talking about") def afterMove(self, oldField): desc = self.game.labyrinth.getDescription(self.field) desc = self.game.labyrinth.getDescription(self) self.send(desc, end="") def asChar(self): def __repr__(self): return "P"
thing.py +4 −1 Original line number Diff line number Diff line Loading @@ -8,5 +8,8 @@ class Thing(): def afterMove(self, oldField): pass def asChar(self): def blocksMove(self): return False def __repr__(self): return "?"
wall.py 0 → 100644 +17 −0 Original line number Diff line number Diff line from thing import Thing class Wall(Thing): def __init__(self): super().__init__() def onMove(self, newField): return False def blocksMove(self): return True def __str__(self): return "a wall" def __repr__(self): return "#"