game.py 2.29 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
Constantin's avatar
Constantin committed
6
from treasure import Treasure
Constantin's avatar
Constantin committed
7
from euclid import Euclid
Ralf's avatar
Ralf committed
8
9

class Game:
Ralf's avatar
Ralf committed
10
	def __init__(self, labyrinthFileName, adminPW, logFileName=None, port=1234):
Ralf's avatar
Ralf committed
11
		self.players = []
Ralf's avatar
Ralf committed
12
		self.admins = []
Constantin's avatar
changes  
Constantin committed
13
		with open(labyrinthFileName,'r') as f:
Ralf's avatar
Ralf committed
14
			self.labyrinth = labyrinth.Labyrinth(game=self,stream=f)
Constantin's avatar
Constantin committed
15
		treasure = Treasure(self)
Constantin's avatar
Constantin committed
16
17
		ttile = random.choice(self.labyrinth.getFreeTiles())
		self.labyrinth.createThing(treasure,ttile)
Constantin's avatar
Constantin committed
18
19
20
		euclid = Euclid(self)
		etile = random.choice(self.labyrinth.getFreeTiles())
		self.labyrinth.createThing(euclid,etile)
Ralf's avatar
Ralf committed
21
		self.sock = socket.socket()
Constantin's avatar
changes  
Constantin committed
22
		self.sock.bind(('0.0.0.0', port))
Ralf's avatar
Ralf committed
23
24
25
		self.sock.listen(100)
		self.sel = selectors.DefaultSelector()
		self.sel.register(self.sock, selectors.EVENT_READ, self.accept)
Ralf's avatar
Ralf committed
26
		self.logFile = None if logFileName is None else open(logFileName, 'a')
Ralf's avatar
Ralf committed
27
		self.adminPW = adminPW
Ralf's avatar
Ralf committed
28
	
Ralf's avatar
Ralf committed
29
	# low-level functions
Ralf's avatar
Ralf committed
30
31
32
	def accept(self, sock, mask):
		assert sock == self.sock
		conn, addr = sock.accept()  # Should be ready
Constantin's avatar
Constantin committed
33
		tile = random.choice(self.labyrinth.getFreeTiles())
Ralf's avatar
Ralf committed
34
		player = Player(self, conn)
Constantin's avatar
Constantin committed
35
		self.labyrinth.createThing(player,tile)
Ralf's avatar
Ralf committed
36
37
38
39
40
		self.players.append(player)
		self.sel.register(conn, selectors.EVENT_READ, player.read)
	
	def removePlayer(self, player):
		assert player in self.players
41
		self.sel.unregister(player.close())
Ralf's avatar
Ralf committed
42
		self.players.remove(player)
Ralf's avatar
Ralf committed
43
44
45
		if player in self.admins:
			self.admins.remove(player)
		self.labyrinth.removeThing(player)
Ralf's avatar
Ralf committed
46
47
48
49
50
51
52
		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
53
54
		if self.logFile is not None:
			self.logFile.close()
Ralf's avatar
Ralf committed
55
56
57
58
59
60
61
	
	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
62
	
Ralf's avatar
Ralf committed
63
64
65
	def log(self, *args):
		if self.logFile is not None:
			print(*args, file=self.logFile, flush=True)
Ralf's avatar
Ralf committed
66
67
	
	def showAdmins(self):
Ralf's avatar
Ralf committed
68
		if not self.admins: return
Ralf's avatar
Ralf committed
69
70
71
		lab = self.labyrinth.writelab()
		for admin in self.admins:
			admin.send(lab)
Ralf's avatar
Ralf committed
72

Ralf's avatar
Ralf committed
73
	# high(er)-level functions
Ralf's avatar
Ralf committed
74
75
76
77
	def makeAdmin(self, player):
		assert player in self.players
		if not player in self.admins:
			self.admins.append(player)
Ralf's avatar
Ralf committed
78
	
Ralf's avatar
Ralf committed
79
80
	def isAdmin(self, player):
		return player in self.admins