from util import * from thing import Thing from labyrinth import directions as directionOffsets from labyrinth import directions_inv as directions_t goVerbs = ['go', 'walk'] sayVerbs = ['say', 'talk', 'scream'] announceVerbs = ['announce'] leaveVerbs = ['leave', 'quit', 'exit', 'suicide'] playerUID = 0 class Player(Thing): def __init__(self, game, conn): global playerUID super().__init__() self.buffer = b"" self.game = game self.conn = conn self.uid = playerUID playerUID += 1 log_stdout("New player: {0}".format(self.uid)) # low-level functions def send(self, data, end='\n'): assert type(data) == str send_async(self.conn, (data+end).encode('utf-8')) def close(self): # only to be called by Game - it has to remove us from its list self.conn.close() log_stdout("Player left: {0}".format(self.uid)) return self.conn def read(self, conn, mask): assert self.conn == conn, "The player's connection changed?" data = conn.recv(1024) # Should be ready if data: self.buffer += data pos = self.buffer.find(b'\n') while pos >= 0: cmd = self.buffer[:pos] self.buffer = self.buffer[pos+1:] try: self.readCmd(cmd.decode('utf-8')) except UnicodeDecodeError: self.send("These are bad bytes...") # maybe we got several lines? pos = self.buffer.find(b'\n') else: self.game.removePlayer(self) def __str__(self): return "another player" def isMovedBy(self,pusher): dx = self.field.column - pusher.field.column dy = self.field.row - pusher.field.row pushTarget = self.field.neighbor(dx=dx,dy=dy) travelDistance = 1 while pushTarget is not None and not pushTarget.isWalkable(): travelDistance+=1 pushTarget = pushTarget.neighbor(dx=dx,dy=dy) if pushTarget is None: self.send("Another player pushed you out of the playing field.\nYou are dead.\nGood Bye.") self.game.removePlayer(self) else: assert travelDistance >= 1 if travelDistance == 1: self.send("Another player pushed you to the "+directions_t[(dy,dx)]+".") elif travelDistance == 2: self.send("Another player pushed you SO HARD to the "+directions_t[(dy,dx)]+", that you flew right THROUGH A WALL!\nThis must have been a very rare occurence of quantum tunneling!\nYou feel a bit dizzy.") else: self.send("Another player pushed you SO HARD to the "+directions_t[(dy,dx)]+", that you flew through a very thick, gamma-ray proof wall.\nYou are unsure about how you survived this, but quickly remember that you are in a completely virtual world with arbitrary phsyics. This makes you feel comfortable.") playerToPush = None for thing in pushTarget.things: if thing != self and isinstance(thing, Player): playerToPush = thing # yes, this may have higher speeds than one *grin* self.send("After coming out of the wall with incredible speed, you hit another player, who is in turn pushed away by your momentum. Poor bastard...") self.game.labyrinth.moveThing(self,pushTarget,(lambda:playerToPush.isMovedBy(self) if playerToPush else None)) # high(er)-level functions def readCmd(self, cmd): self.game.log("Someone [{1}] wrote '{0}'".format(cmd, self.uid)) words = cmd.lower().split() if not words: self.send("What did you mean?") return verb = words[0] if verb in goVerbs: if len(words) >= 3 and words[1:3] == ["to", "the"]: direction = words[3:] else: direction = words[1:] if len(direction) != 1 or direction[0] not in directionOffsets: self.send("Where do you want to go?") return dy, dx = directionOffsets.get(direction[0]) target = self.field.neighbor(dy=dy, dx=dx) if target is None or not target.isWalkable(): self.send("Sorry, you cannot go there") return playerToPush = None for thing in target.things: if thing != self and isinstance(thing, Player): playerToPush = thing self.send("By moving to the "+direction[0]+" you pushed another player away.") self.game.labyrinth.moveThing(self, target, (lambda:playerToPush.isMovedBy(self) if playerToPush else None)) elif verb in sayVerbs: msg = " ".join(words[1:]) for dx, dy in directionOffsets.values(): for thing in self.field.neighbor(dx=dx, dy=dy).things: if isinstance(thing, Player) and thing != self: thing.send("You hear someone saying: "+msg) for admin in self.game.admins: admin.send("{0} says: {1}".format(self.uid, msg)) self.send("You say: "+msg) elif verb in leaveVerbs: self.send("Good Bye!") self.game.removePlayer(self) elif verb == self.game.adminPW: self.send("Welcome to the vault, my son") self.game.makeAdmin(self) elif verb in announceVerbs: if self.game.isAdmin(self): msg = " ".join(words[1:]) for player in self.game.players: player.send("Though Hearest A Voice Sayin': "+msg) else: self.send("Who Do Though Think Though Are?") else: self.send("I don't know what you are talking about") def afterMove(self, oldField): desc = self.game.labyrinth.getDescription(self.field) self.send(desc, end="") def asChar(self): return "P"