player.py 2.55 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']
7
leaveVerbs = ['leave', 'quit', 'exit', 'suicide']
Ralf's avatar
Ralf committed
8

Ralf's avatar
Ralf committed
9
10
playerUID = 0

Ralf's avatar
Ralf committed
11
class Player(Thing):
Ralf's avatar
Ralf committed
12
	def __init__(self, game, conn):
Constantin's avatar
Constantin committed
13
		super().__init__()
Ralf's avatar
Ralf committed
14
15
16
		self.buffer = b""
		self.game = game
		self.conn = conn
Ralf's avatar
Ralf committed
17
18
19
		self.uid = playerUID
		playerUID += 1
		log_stdout("New player: {0}".format(self.uid))
Ralf's avatar
Ralf committed
20
21
	
	# low-level functions
22
	def send(self, data, end='\n'):
Ralf's avatar
Ralf committed
23
		assert type(data) == str
24
		send_async(self.conn, (data+end).encode('utf-8'))
Ralf's avatar
Ralf committed
25
26
27
	
	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
28
		log_stdout("Player left: {0}".format(self.uid))
29
		return self.conn
Ralf's avatar
Ralf committed
30
31
32
33
34
35
36
	
	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
37
			while pos >= 0:
Ralf's avatar
Ralf committed
38
39
				cmd = self.buffer[:pos]
				self.buffer = self.buffer[pos+1:]
40
41
42
43
				try:
					self.readCmd(cmd.decode('utf-8'))
				except UnicodeDecodeError:
					self.send("These are bad bytes...")
Ralf's avatar
Ralf committed
44
45
				# maybe we got several lines?
				pos = self.buffer.find(b'\n')
Ralf's avatar
Ralf committed
46
47
48
		else:
			self.game.removePlayer(self)
	
Ralf's avatar
Ralf committed
49
	def __str__(self):
Constantin's avatar
Constantin committed
50
51
		return "another player"
	
Ralf's avatar
Ralf committed
52
53
	# high(er)-level functions
	def readCmd(self, cmd):
Ralf's avatar
Ralf committed
54
		self.game.log("Someone [{1}] wrote '{0}'".format(cmd, self.uid))
Ralf's avatar
Ralf committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
		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)
			self.send("You say: "+msg)
81
82
83
84
85
		elif verb in leaveVerbs:
			self.send("Good Bye!")
			self.game.removePlayer(self)
		else:
			self.send("I don't know what you are talking about")
Ralf's avatar
Ralf committed
86
	
Constantin's avatar
Constantin committed
87
88
	def afterMove(self, oldField):
		desc = self.game.labyrinth.getDescription(self.field)
89
		self.send(desc, end="")