From b483dfcd47dc84de124b4ac1970757f114a599e7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 1 Aug 2014 02:34:22 +0200 Subject: [PATCH] make walls a thing --- game.py | 3 +- labyrinth.py | 84 ++++++++++++++++++++++++++++------------------------ player.py | 4 +-- thing.py | 5 +++- wall.py | 17 +++++++++++ 5 files changed, 70 insertions(+), 43 deletions(-) create mode 100644 wall.py diff --git a/game.py b/game.py index 01033db..de496e7 100644 --- a/game.py +++ b/game.py @@ -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() @@ -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): @@ -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) diff --git a/labyrinth.py b/labyrinth.py index 9f1e2c7..d153a36 100644 --- a/labyrinth.py +++ b/labyrinth.py @@ -1,20 +1,27 @@ # 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()} +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 GroundType(Enum): - FLOOR = 1 - WALL = 2 - 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 @@ -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): @@ -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: @@ -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 @@ -72,15 +75,12 @@ class Labyrinth: result = "" for row in self.tiles: for field in row: - if field.groundtype == Labyrinth.GroundType.WALL: - result += "#" + if not field.things: + result += "." + elif len(field.things) == 1: + result += repr(field.things[0]) else: - if not field.things: - result += "." - elif len(field.things) == 1: - result += field.things[0].asChar() - else: - result += "+" + result += "+" result += "\n" return result @@ -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): @@ -130,8 +136,8 @@ class Labyrinth: def createThing (self, thing, field): thing.field = field field._addThing(thing) - thing.onMove(field) - thing.afterMove(field) + if thing.onMove(field): + thing.afterMove(field) self.game.showAdmins() def removeThing(self, thing): diff --git a/player.py b/player.py index df03c49..c5adb8a 100644 --- a/player.py +++ b/player.py @@ -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" diff --git a/thing.py b/thing.py index 8acd38e..8d0dd3c 100644 --- a/thing.py +++ b/thing.py @@ -8,5 +8,8 @@ class Thing(): def afterMove(self, oldField): pass - def asChar(self): + def blocksMove(self): + return False + + def __repr__(self): return "?" diff --git a/wall.py b/wall.py new file mode 100644 index 0000000..27c7d23 --- /dev/null +++ b/wall.py @@ -0,0 +1,17 @@ +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 "#" -- GitLab