+ if s == [-1,-1]:
+ game.final_result = "network terminate"
+ game.stop()
+ return s
+
+ def update(self, result):
+ #debug(str(self) + " update(\""+str(result)+"\") called")
+ if self.network.server == True:
+ if self.player == None:
+ self.send_message(result)
+ elif self.player != None:
+ result = self.get_response()
+ if result == "-1 -1":
+ game.final_result = "network terminate"
+ game.stop()
+ return "-1 -1"
+ self.board.update(result, deselect=False)
+
+
+
+ if self.player != None:
+ result = self.player.update(result)
+
+ return result
+
+
+
+ def base_player(self):
+ if self.player == None:
+ return self
+ else:
+ return self.player.base_player()
+
+ def quit(self, result):
+ try:
+ self.send_message("-1 -1")
+ except:
+ pass
+
+class Network():
+ def __init__(self, address = (None,4562)):
+ self.socket = socket.socket()
+ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ #self.socket.setblocking(0)
+ self.address = address
+ self.server = (address[0] == None)
+
+
+ self.connected = False
+
+ def connect(self):
+ #debug(str(self) + "Tries to connect")
+ self.connected = True
+ if self.address[0] == None:
+ self.host = "0.0.0.0" #socket.gethostname() # Breaks things???
+ self.socket.bind((self.host, self.address[1]))
+ self.socket.listen(5)
+
+ self.src, self.actual_address = self.socket.accept()
+
+ self.src.send("ok\n")
+ s = self.get_response()
+ if s == "QUIT":
+ self.src.close()
+ return
+ elif s != "ok":
+ self.src.close()
+ self.__init__(colour, (self.address[0], int(s)), baseplayer)
+ return
+
+ else:
+ time.sleep(0.3)
+ self.socket.connect(self.address)
+ self.src = self.socket
+ self.src.send("ok\n")
+ s = self.get_response()
+ if s == "QUIT":
+ self.src.close()
+ return
+ elif s != "ok":
+ self.src.close()
+ self.__init__(colour, (self.address[0], int(s)), baseplayer)
+ return
+
+
+
+ def __str__(self):
+ return "@network:"+str(self.address)
+
+ def get_response(self):
+
+ # Timeout the start of the message (first character)
+ if network_timeout_start > 0.0:
+ ready = select.select([self.src], [], [], network_timeout_start)[0]
+ else:
+ ready = [self.src]
+ if self.src in ready:
+ s = self.src.recv(1)
+ else:
+ raise Exception("UNRESPONSIVE")
+
+
+ while s[len(s)-1] != '\n':
+ # Timeout on each character in the message
+ if network_timeout_delay > 0.0:
+ ready = select.select([self.src], [], [], network_timeout_delay)[0]
+ else:
+ ready = [self.src]
+ if self.src in ready:
+ s += self.src.recv(1)
+ else:
+ raise Exception("UNRESPONSIVE")
+
+
+ return s.strip(" \r\n")
+
+ def send_message(self,s):
+ if network_timeout_start > 0.0:
+ ready = select.select([], [self.src], [], network_timeout_start)[1]
+ else:
+ ready = [self.src]
+
+ if self.src in ready:
+ self.src.send(s + "\n")
+ else:
+ raise Exception("UNRESPONSIVE")
+
+
+
+ def close(self):
+ self.src.shutdown()
+ self.src.close()
+# --- network.py --- #
+import threading
+
+# A thread that can be stopped!
+# Except it can only be stopped if it checks self.stopped() periodically
+# So it can sort of be stopped
+class StoppableThread(threading.Thread):
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self._stop = threading.Event()
+
+ def stop(self):
+ self._stop.set()
+
+ def stopped(self):
+ return self._stop.isSet()# --- thread_util.py --- #
+log_files = []
+import datetime
+import urllib2
+
+class LogFile():
+ def __init__(self, log, name):
+ self.name = name
+ self.log = log
+ self.logged = []
+ self.log.write("# Log starts " + str(datetime.datetime.now()) + "\n")
+
+ def write(self, s):
+ now = datetime.datetime.now()
+ self.log.write(str(now) + " : " + s + "\n")
+ self.logged.append((now, s))
+
+ def setup(self, board, players):
+
+ for p in players:
+ self.log.write("# " + str(p.colour) + " : " + str(p.name) + "\n")
+
+ self.log.write("# Initial board\n")
+ for x in range(0, w):
+ for y in range(0, h):
+ if board.grid[x][y] != None:
+ self.log.write(str(board.grid[x][y]) + "\n")
+
+ self.log.write("# Start game\n")
+
+ def close(self):
+ self.log.write("# EOF\n")
+ if self.log != sys.stdout:
+ self.log.close()
+
+class ShortLog(LogFile):
+ def __init__(self, file_name):
+ if file_name == "":
+ self.log = sys.stdout
+ else:
+ self.log = open(file_name, "w", 0)
+ LogFile.__init__(self, self.log, "@"+file_name)
+ self.file_name = file_name
+ self.phase = 0
+
+ def write(self, s):
+ now = datetime.datetime.now()
+ self.logged.append((now, s))
+
+ if self.phase == 0:
+ if self.log != sys.stdout:
+ self.log.close()
+ self.log = open(self.file_name, "w", 0)
+ self.log.write("# Short log updated " + str(datetime.datetime.now()) + "\n")
+ LogFile.setup(self, game.board, game.players)
+
+ elif self.phase == 1:
+ for message in self.logged[len(self.logged)-2:]:
+ self.log.write(str(message[0]) + " : " + message[1] + "\n")
+
+ self.phase = (self.phase + 1) % 2
+
+ def close(self):
+ if self.phase == 1:
+ ending = self.logged[len(self.logged)-1]
+ self.log.write(str(ending[0]) + " : " + ending[1] + "\n")
+ self.log.write("# EOF\n")
+ if self.log != sys.stdout:
+ self.log.close()
+
+
+class HeadRequest(urllib2.Request):
+ def get_method(self):
+ return "HEAD"
+
+class HttpGetter(StoppableThread):
+ def __init__(self, address):
+ StoppableThread.__init__(self)
+ self.address = address
+ self.log = urllib2.urlopen(address)
+ self.lines = []
+ self.lock = threading.RLock() #lock for access of self.state
+ self.cond = threading.Condition() # conditional
+
+ def run(self):
+ while not self.stopped():
+ line = self.log.readline()
+ if line == "":
+ date_mod = datetime.datetime.strptime(self.log.headers['last-modified'], "%a, %d %b %Y %H:%M:%S GMT")
+ self.log.close()
+
+ next_log = urllib2.urlopen(HeadRequest(self.address))
+ date_new = datetime.datetime.strptime(next_log.headers['last-modified'], "%a, %d %b %Y %H:%M:%S GMT")
+ while date_new <= date_mod and not self.stopped():
+ next_log = urllib2.urlopen(HeadRequest(self.address))
+ date_new = datetime.datetime.strptime(next_log.headers['last-modified'], "%a, %d %b %Y %H:%M:%S GMT")
+ if self.stopped():
+ break
+
+ self.log = urllib2.urlopen(self.address)
+ line = self.log.readline()
+
+ self.cond.acquire()
+ self.lines.append(line)
+ self.cond.notifyAll()
+ self.cond.release()
+
+ #sys.stderr.write(" HttpGetter got \'" + str(line) + "\'\n")
+
+ self.log.close()
+
+
+
+
+
+class HttpReplay():
+ def __init__(self, address):
+ self.getter = HttpGetter(address)
+ self.getter.start()
+
+ def readline(self):
+ self.getter.cond.acquire()
+ while len(self.getter.lines) == 0:
+ self.getter.cond.wait()
+
+ result = self.getter.lines[0]
+ self.getter.lines = self.getter.lines[1:]
+ self.getter.cond.release()
+
+ return result
+
+
+ def close(self):
+ self.getter.stop()
+
+class FileReplay():
+ def __init__(self, filename):
+ self.f = open(filename, "r", 0)
+ self.filename = filename
+ self.mod = os.path.getmtime(filename)
+ self.count = 0
+
+ def readline(self):
+ line = self.f.readline()
+
+ while line == "":
+ mod2 = os.path.getmtime(self.filename)
+ if mod2 > self.mod:
+ #sys.stderr.write("File changed!\n")
+ self.mod = mod2
+ self.f.close()
+ self.f = open(self.filename, "r", 0)
+
+ new_line = self.f.readline()
+
+ if " ".join(new_line.split(" ")[0:3]) != "# Short log":
+ for i in range(self.count):
+ new_line = self.f.readline()
+ #sys.stderr.write("Read back " + str(i) + ": " + str(new_line) + "\n")
+ new_line = self.f.readline()
+ else:
+ self.count = 0
+
+ line = new_line
+
+ self.count += 1
+ return line
+
+ def close(self):
+ self.f.close()
+