X-Git-Url: https://git.ucc.asn.au/?p=progcomp2013.git;a=blobdiff_plain;f=qchess%2Fsrc%2Fmain.py;h=748a4592688d48ee0a85165a2e784242282ae39f;hp=8dac056306f38d70b6f725c25e950f56c640b9af;hb=5287b4f869be70ddae4b59a44c448be33f95ccda;hpb=444244d5c7698bb7861cdb7c0ec6bfb0e8cebfb7 diff --git a/qchess/src/main.py b/qchess/src/main.py index 8dac056..748a459 100644 --- a/qchess/src/main.py +++ b/qchess/src/main.py @@ -28,9 +28,29 @@ def make_player(name, colour): if len(s) > 1: address = s[1] return NetworkReceiver(colour, address) + if s[0] == "internal": + + import inspect + internal_agents = inspect.getmembers(sys.modules[__name__], inspect.isclass) + internal_agents = [x for x in internal_agents if issubclass(x[1], InternalAgent)] + internal_agents.remove(('InternalAgent', InternalAgent)) + + if len(s) != 2: + sys.stderr.write(sys.argv[0] + " : '@internal' should be followed by ':' and an agent name\n") + sys.stderr.write(sys.argv[0] + " : Choices are: " + str(map(lambda e : e[0], internal_agents)) + "\n") + return None + + for a in internal_agents: + if s[1] == a[0]: + return a[1](name, colour) + + sys.stderr.write(sys.argv[0] + " : Can't find an internal agent matching \"" + s[1] + "\"\n") + sys.stderr.write(sys.argv[0] + " : Choices are: " + str(map(lambda e : e[0], internal_agents)) + "\n") + return None + else: - return AgentPlayer(name, colour) + return ExternalAgent(name, colour) @@ -44,15 +64,23 @@ def main(argv): global turn_delay global agent_timeout - global log_file + global log_files global src_file + global graphics_enabled + global always_reveal_states - - + max_moves = None + src_file = None style = "quantum" colour = "white" - graphics_enabled = True + + # Get the important warnings out of the way + if platform.system() == "Windows": + sys.stderr.write(sys.argv[0] + " : Warning - You are using " + platform.system() + "\n") + if platform.release() == "Vista": + sys.stderr.write(sys.argv[0] + " : God help you.\n") + players = [] i = 0 @@ -60,7 +88,11 @@ def main(argv): i += 1 arg = argv[i] if arg[0] != '-': - players.append(make_player(arg, colour)) + p = make_player(arg, colour) + if not isinstance(p, Player): + sys.stderr.write(sys.argv[0] + " : Fatal error creating " + colour + " player\n") + return 100 + players.append(p) if colour == "white": colour = "black" elif colour == "black": @@ -74,20 +106,36 @@ def main(argv): style = "classical" elif arg[1] == '-' and arg[2:] == "quantum": style = "quantum" + elif arg[1] == '-' and arg[2:] == "reveal": + always_reveal_states = True elif (arg[1] == '-' and arg[2:] == "graphics"): - graphics_enabled = not graphics_enabled + graphics_enabled = True + elif (arg[1] == '-' and arg[2:] == "no-graphics"): + graphics_enabled = False elif (arg[1] == '-' and arg[2:].split("=")[0] == "file"): # Load game from file if len(arg[2:].split("=")) == 1: - src_file = sys.stdout + src_file = sys.stdin else: - src_file = arg[2:].split("=")[1] + f = arg[2:].split("=")[1] + if f[0:7] == "http://": + src_file = HttpReplay(f) + else: + src_file = FileReplay(f.split(":")[0]) + + if len(f.split(":")) == 2: + max_moves = int(f.split(":")[1]) + elif (arg[1] == '-' and arg[2:].split("=")[0] == "log"): # Log file if len(arg[2:].split("=")) == 1: - log_file = sys.stdout + log_files.append(LogFile(sys.stdout)) else: - log_file = arg[2:].split("=")[1] + f = arg[2:].split("=")[1] + if f[0] == '@': + log_files.append(ShortLog(f[1:])) + else: + log_files.append(LogFile(open(f, "w", 0))) elif (arg[1] == '-' and arg[2:].split("=")[0] == "delay"): # Delay if len(arg[2:].split("=")) == 1: @@ -109,13 +157,37 @@ def main(argv): # Create the board - board = Board(style) + + # Construct a GameThread! Make it global! Damn the consequences! + + if src_file != None: + # Hack to stop ReplayThread from exiting + #if len(players) == 0: + # players = [HumanPlayer("dummy", "white"), HumanPlayer("dummy", "black")] + + # Normally the ReplayThread exits if there are no players + # TODO: Decide which behaviour to use, and fix it + end = (len(players) == 0) + if end: + players = [Player("dummy", "white"), Player("dummy", "black")] + elif len(players) != 2: + sys.stderr.write(sys.argv[0] + " : Usage " + sys.argv[0] + " white black\n") + if graphics_enabled: + sys.stderr.write(sys.argv[0] + " : (You won't get a GUI, because --file was used, and the author is lazy)\n") + return 44 + game = ReplayThread(players, src_file, end=end, max_moves=max_moves) + else: + board = Board(style) + board.max_moves = max_moves + game = GameThread(board, players) + + # Initialise GUI if graphics_enabled == True: try: - graphics = GraphicsThread(board, grid_sz = [64,64]) # Construct a GraphicsThread! + graphics = GraphicsThread(game.board, grid_sz = [64,64]) # Construct a GraphicsThread! except Exception,e: graphics = None @@ -158,35 +230,66 @@ def main(argv): # If using windows, select won't work; use horrible TimeoutPlayer hack - if agent_timeout > 0 and platform.system() == "Windows": - sys.stderr.write(sys.argv[0] + " : Warning - You are using Windows\n") - sys.stderr.write(sys.argv[0] + " : - Timeouts will be implemented with a terrible hack.\n") + if agent_timeout > 0: + if platform.system() == "Windows": + for i in range(len(players)): + if isinstance(players[i], ExternalAgent) or isinstance(players[i], InternalAgent): + players[i] = TimeoutPlayer(players[i], agent_timeout) - for i in range(len(players)): - if isinstance(players[i], AgentPlayer): - players[i] = TimeoutPlayer(players[i], agent_timeout) + else: + warned = False + # InternalAgents get wrapped to an ExternalAgent when there is a timeout + # This is not confusing at all. + for i in range(len(players)): + if isinstance(players[i], InternalAgent): + players[i] = ExternalWrapper(players[i]) - # Could potentially wrap TimeoutPlayer around internal classes... - # But that would suck - - # Construct a GameThread! Make it global! Damn the consequences! - game = GameThread(board, players) + log_init(game.board, players) + if graphics != None: game.start() # This runs in a new thread graphics.run() - game.join() - return game.error + graphics.error + if game.is_alive(): + game.join() + + + error = game.error + graphics.error else: game.run() - return game.error + error = game.error + + + for l in log_files: + l.close() + + if src_file != None and src_file != sys.stdin: + src_file.close() + + sys.stdout.write(game.final_result + "\n") + + return error # This is how python does a main() function... if __name__ == "__main__": - sys.exit(main(sys.argv)) + try: + sys.exit(main(sys.argv)) + except KeyboardInterrupt: + sys.stderr.write(sys.argv[0] + " : Got KeyboardInterrupt. Stopping everything\n") + if isinstance(graphics, StoppableThread): + graphics.stop() + graphics.run() # Will clean up graphics because it is stopped, not run it (a bit dodgy) + + if isinstance(game, StoppableThread): + game.stop() + if game.is_alive(): + game.join() + + sys.exit(102) +