player.py 3.06 KB
Newer Older
1
from util import *
Ralf's avatar
Ralf committed
2
3
from thing import Thing
from labyrinth import directions as directionOffsets
4

Ralf's avatar
Ralf committed
5
6
goVerbs = ['go', 'walk']
sayVerbs = ['say', 'talk', 'scream']
Ralf's avatar
Ralf committed
7
announceVerbs = ['announce']
8
leaveVerbs = ['leave', 'quit', 'exit', 'suicide']
Ralf's avatar
Ralf committed
9

Ralf's avatar
Ralf committed
10
11
playerUID = 0

Ralf's avatar
Ralf committed
12
class Player(Thing):
Ralf's avatar
Ralf committed
13
	def __init__(self, game, conn):
Ralf's avatar
Ralf committed
14
		global playerUID
Constantin's avatar
Constantin committed
15
		super().__init__()
Ralf's avatar
Ralf committed
16
17
18
		self.buffer = b""
		self.game = game
		self.conn = conn
Ralf's avatar
Ralf committed
19
20
21
		self.uid = playerUID
		playerUID += 1
		log_stdout("New player: {0}".format(self.uid))
Ralf's avatar
Ralf committed
22
23
	
	# low-level functions
24
	def send(self, data, end='\n'):
Ralf's avatar
Ralf committed
25
		assert type(data) == str
26
		send_async(self.conn, (data+end).encode('utf-8'))
Ralf's avatar
Ralf committed
27
28
29
	
	def close(self): # only to be called by Game - it has to remove us from its list
		self.conn.close()
Ralf's avatar
Ralf committed
30
		log_stdout("Player left: {0}".format(self.uid))
31
		return self.conn
Ralf's avatar
Ralf committed
32
33
34
35
36
37
38
	
	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')
Ralf's avatar
Ralf committed
39
			while pos >= 0:
Ralf's avatar
Ralf committed
40
41
				cmd = self.buffer[:pos]
				self.buffer = self.buffer[pos+1:]
42
43
44
45
				try:
					self.readCmd(cmd.decode('utf-8'))
				except UnicodeDecodeError:
					self.send("These are bad bytes...")
Ralf's avatar
Ralf committed
46
47
				# maybe we got several lines?
				pos = self.buffer.find(b'\n')
Ralf's avatar
Ralf committed
48
49
50
		else:
			self.game.removePlayer(self)
	
Ralf's avatar
Ralf committed
51
	def __str__(self):
Constantin's avatar
Constantin committed
52
53
		return "another player"
	
Ralf's avatar
Ralf committed
54
55
	# high(er)-level functions
	def readCmd(self, cmd):
Ralf's avatar
Ralf committed
56
		self.game.log("Someone [{1}] wrote '{0}'".format(cmd, self.uid))
Ralf's avatar
Ralf committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
		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
			self.game.labyrinth.moveThing(self, target)
		elif verb in sayVerbs:
			msg = " ".join(words[1:])
			for dx, dy in [(0, 0)]+directionOffsets.values():
				for thing in self.field.neighbor(dx=dx, dy=dy):
					if isinstance(thing, Player) and thing != self:
						thing.send("You hear someone saying: "+msg)
Ralf's avatar
Ralf committed
82
83
			for admin in self.game.admins:
				admin.send("{0} says: {1}".format(self.uid, msg))
Ralf's avatar
Ralf committed
84
			self.send("You say: "+msg)
85
86
87
		elif verb in leaveVerbs:
			self.send("Good Bye!")
			self.game.removePlayer(self)
Ralf's avatar
Ralf committed
88
89
90
91
92
93
94
95
96
97
		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?")
98
99
		else:
			self.send("I don't know what you are talking about")
Ralf's avatar
Ralf committed
100
	
Constantin's avatar
Constantin committed
101
102
	def afterMove(self, oldField):
		desc = self.game.labyrinth.getDescription(self.field)
103
		self.send(desc, end="")
Ralf's avatar
Ralf committed
104
105
106
	
	def asChar(self):
		return "P"