game.py 1.99 KB
Newer Older
Ralf's avatar
Ralf committed
1 2 3
from player import Player
import selectors
import socket
Constantin's avatar
changes  
Constantin committed
4
import labyrinth
Constantin's avatar
Constantin committed
5
import random
Ralf's avatar
Ralf committed
6 7

class Game:
Ralf's avatar
Ralf committed
8
	def __init__(self, labyrinthFileName, adminPW, logFileName=None, port=1234):
Ralf's avatar
Ralf committed
9
		self.players = []
Ralf's avatar
Ralf committed
10
		self.admins = []
Constantin's avatar
changes  
Constantin committed
11
		with open(labyrinthFileName,'r') as f:
Ralf's avatar
Ralf committed
12
			self.labyrinth = labyrinth.Labyrinth(game=self,stream=f)
Ralf's avatar
Ralf committed
13
		self.sock = socket.socket()
Constantin's avatar
changes  
Constantin committed
14
		self.sock.bind(('0.0.0.0', port))
Ralf's avatar
Ralf committed
15 16 17
		self.sock.listen(100)
		self.sel = selectors.DefaultSelector()
		self.sel.register(self.sock, selectors.EVENT_READ, self.accept)
Ralf's avatar
Ralf committed
18
		self.logFile = None if logFileName is None else open(logFileName, 'a')
Ralf's avatar
Ralf committed
19
		self.adminPW = adminPW
Ralf's avatar
Ralf committed
20
	
Ralf's avatar
Ralf committed
21
	# low-level functions
Ralf's avatar
Ralf committed
22 23 24
	def accept(self, sock, mask):
		assert sock == self.sock
		conn, addr = sock.accept()  # Should be ready
Constantin's avatar
Constantin committed
25
		tile = random.choice(self.labyrinth.getFreeTiles())
Ralf's avatar
Ralf committed
26
		player = Player(self, conn)
Constantin's avatar
Constantin committed
27
		self.labyrinth.createThing(player,tile)
Ralf's avatar
Ralf committed
28 29 30 31 32
		self.players.append(player)
		self.sel.register(conn, selectors.EVENT_READ, player.read)
	
	def removePlayer(self, player):
		assert player in self.players
33
		self.sel.unregister(player.close())
Ralf's avatar
Ralf committed
34
		self.players.remove(player)
Ralf's avatar
Ralf committed
35 36 37
		if player in self.admins:
			self.admins.remove(player)
		self.labyrinth.removeThing(player)
Ralf's avatar
Ralf committed
38 39 40 41 42 43 44
		assert player not in self.players # this ensure the player was in only once
	
	def close(self):
		for player in self.players:
			player.close()
		self.players.clear()
		self.sock.close()
Ralf's avatar
Ralf committed
45 46
		if self.logFile is not None:
			self.logFile.close()
Ralf's avatar
Ralf committed
47 48 49 50 51 52 53
	
	def run(self):
		while True:
			events = self.sel.select()
			for key, mask in events:
				callback = key.data
				callback(key.fileobj, mask)
Ralf's avatar
Ralf committed
54
	
Ralf's avatar
Ralf committed
55 56 57
	def log(self, *args):
		if self.logFile is not None:
			print(*args, file=self.logFile, flush=True)
Ralf's avatar
Ralf committed
58 59
	
	def showAdmins(self):
Ralf's avatar
Ralf committed
60
		if not self.admins: return
Ralf's avatar
Ralf committed
61 62 63
		lab = self.labyrinth.writelab()
		for admin in self.admins:
			admin.send(lab)
Ralf's avatar
Ralf committed
64

Ralf's avatar
Ralf committed
65
	# high(er)-level functions
Ralf's avatar
Ralf committed
66 67 68 69
	def makeAdmin(self, player):
		assert player in self.players
		if not player in self.admins:
			self.admins.append(player)
Ralf's avatar
Ralf committed
70
	
Ralf's avatar
Ralf committed
71 72
	def isAdmin(self, player):
		return player in self.admins