Commit b483dfcd authored by Ralf's avatar Ralf

make walls a thing

parent 9d20f69f
......@@ -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)
......
# 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):
......
......@@ -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"
......@@ -8,5 +8,8 @@ class Thing():
def afterMove(self, oldField):
pass
def asChar(self):
def blocksMove(self):
return False
def __repr__(self):
return "?"
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 "#"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment