game.py 2.93 KB
Newer Older
Ralf's avatar
Ralf committed
1 2 3
from player import Player
import selectors
import socket
Constantin Berhard's avatar
Constantin Berhard committed
4
import labyrinth
Constantin Berhard's avatar
Constantin Berhard committed
5
import random
Ralf's avatar
Ralf committed
6
import sys
7
import os
Ralf's avatar
Ralf committed
8
from util import log_file
Constantin Berhard's avatar
Constantin Berhard committed
9
from treasure import Treasure
Constantin Berhard's avatar
Constantin Berhard committed
10
from euclid import Euclid
Ralf's avatar
Ralf committed
11
from extern import Extern
Ralf's avatar
Ralf committed
12

13 14
scriptDir = os.path.dirname(os.path.realpath(__file__))

Ralf's avatar
Ralf committed
15
class Game:
Ralf's avatar
Ralf committed
16
	def __init__(self, labyrinthFileName, adminPW, logFileName=None, port=1234):
Ralf's avatar
Ralf committed
17
		self.players = []
Ralf's avatar
Ralf committed
18
		self.admins = []
Constantin Berhard's avatar
Constantin Berhard committed
19
		with open(labyrinthFileName,'r') as f:
Ralf's avatar
Ralf committed
20
			self.labyrinth = labyrinth.Labyrinth(game=self,stream=f)
Ralf's avatar
Ralf committed
21
		# set up labyrinth and its content
Constantin Berhard's avatar
Constantin Berhard committed
22
		treasure = Treasure(self)
23 24
		ttile = random.choice(self.labyrinth.getFreeTiles())
		self.labyrinth.createThing(treasure,ttile)
Constantin Berhard's avatar
Constantin Berhard committed
25 26
		euclid = Euclid(self)
		etile = random.choice(self.labyrinth.getFreeTiles())
Ralf's avatar
Ralf committed
27
		self.labyrinth.createThing(euclid,etile)
28
		eliza = Extern(self, "Eliza", "Z", os.path.join(scriptDir, "eliza"), "./simple")
Ralf's avatar
Ralf committed
29 30 31
		ztile = random.choice(self.labyrinth.getFreeTiles())
		self.labyrinth.createThing(eliza,ztile)
		# set up socket
Ralf's avatar
Ralf committed
32
		self.sock = socket.socket()
Constantin Berhard's avatar
Constantin Berhard committed
33
		self.sock.bind(('0.0.0.0', port))
Ralf's avatar
Ralf committed
34 35 36
		self.sock.listen(100)
		self.sel = selectors.DefaultSelector()
		self.sel.register(self.sock, selectors.EVENT_READ, self.accept)
Ralf's avatar
Ralf committed
37
		# log file and admin stuff
Ralf's avatar
Ralf committed
38
		self.logFile = None if logFileName is None else open(logFileName, 'a')
Ralf's avatar
Ralf committed
39
		self.adminPW = adminPW
Ralf's avatar
Ralf committed
40
	
Ralf's avatar
Ralf committed
41
	# low-level functions
Ralf's avatar
Ralf committed
42 43 44
	def accept(self, sock, mask):
		assert sock == self.sock
		conn, addr = sock.accept()  # Should be ready
Constantin Berhard's avatar
Constantin Berhard committed
45
		tile = random.choice(self.labyrinth.getFreeTiles())
Ralf's avatar
Ralf committed
46
		player = Player(self, conn)
Constantin Berhard's avatar
Constantin Berhard committed
47
		self.labyrinth.createThing(player,tile)
Ralf's avatar
Ralf committed
48 49 50 51 52
		self.players.append(player)
		self.sel.register(conn, selectors.EVENT_READ, player.read)
	
	def removePlayer(self, player):
		assert player in self.players
53
		self.sel.unregister(player.close())
Ralf's avatar
Ralf committed
54
		self.players.remove(player)
Ralf's avatar
Ralf committed
55 56 57
		if player in self.admins:
			self.admins.remove(player)
		self.labyrinth.removeThing(player)
Ralf's avatar
Ralf committed
58 59 60 61 62 63 64
		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
65 66
		if self.logFile is not None:
			self.logFile.close()
Ralf's avatar
Ralf committed
67 68 69 70 71 72 73
	
	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
74
	
Ralf's avatar
Ralf committed
75
	def logDebug(self, *args):
Ralf's avatar
Ralf committed
76
		if self.logFile is not None:
Ralf's avatar
Ralf committed
77
			log_file(self.logFile, *args, clock=True)
Ralf's avatar
Ralf committed
78 79 80
	def logInfo(self, *args):
		log_file(sys.stdout, *args)
		if self.logFile is not None:
Ralf's avatar
Ralf committed
81
			log_file(self.logFile, *args, clock=True)
Ralf's avatar
Ralf committed
82 83 84
	def logError(self, *args):
		log_file(sys.stderr, *args)
		if self.logFile is not None:
Ralf's avatar
Ralf committed
85
			log_file(self.logFile, *args, clock=True)
Ralf's avatar
Ralf committed
86 87
	
	def showAdmins(self):
Ralf's avatar
Ralf committed
88
		if not self.admins: return
Ralf's avatar
Ralf committed
89 90 91
		lab = self.labyrinth.writelab()
		for admin in self.admins:
			admin.send(lab)
Ralf's avatar
Ralf committed
92

Ralf's avatar
Ralf committed
93
	# high(er)-level functions
Ralf's avatar
Ralf committed
94 95 96 97
	def makeAdmin(self, player):
		assert player in self.players
		if not player in self.admins:
			self.admins.append(player)
Ralf's avatar
Ralf committed
98
	
Ralf's avatar
Ralf committed
99 100
	def isAdmin(self, player):
		return player in self.admins