def __init__( self ): random.seed() self.difficulty = self.EASY self.stop = False self.gamemap = Gamemap() self.systems = Systems() self.engineering = Engineering() # N,S,E,W,Mine,Surface self.player_movements = [] self.sub_damage = 0 self.possible_player_locations = [] self.debug = True
class AbstractGame(object): def __init__(self, cont): self.cont = cont self.objects = [] def load_map(self, name): data = maps_list[name] self.gamemap = Gamemap(data["SizeX"], data["SizeY"]) for layer_name, default_tile in data["layers"].items(): create_default_obj = partial(self.add_object, default_tile) layer = self.gamemap.add_layer(layer_name, create_default_obj) for name, coord in data["objects"]: self.add_object(name, coord) def add_object(self, name, coord=(), *arg, **kwarg): cls = getattr(game_objects, name) layer = kwarg.pop("layer", None) if layer is None: layer = self.gamemap[cls.map_layer] obj = cls(layer, coord, *arg, **kwarg) self.objects.append(obj) self.send_drawdata(obj) return obj @public.send_meth("setListDrawdata") def send_all_drawdata(self): return ([obj.get_drawdata() for obj in self.objects],) @public.send_meth("setDrawdata") def send_drawdata(self, obj): return [obj.get_drawdata()]
def load_map(self, name): data = maps_list[name] self.gamemap = Gamemap(data["SizeX"], data["SizeY"]) for layer_name, default_tile in data["layers"].items(): create_default_obj = partial(self.add_object, default_tile) layer = self.gamemap.add_layer(layer_name, create_default_obj) for name, coord in data["objects"]: self.add_object(name, coord)
class CaptainSonar( object ): EASY = "Easy" NORMAL = "Normal" HARD = "Hard" MAX_DAMAGE = 4 def __init__( self ): random.seed() self.difficulty = self.EASY self.stop = False self.gamemap = Gamemap() self.systems = Systems() self.engineering = Engineering() # N,S,E,W,Mine,Surface self.player_movements = [] self.sub_damage = 0 self.possible_player_locations = [] self.debug = True def print_debug( self, txt ): if self.debug: print "[DEBUG] %s" % txt def start( self ): print "Captain Sonar AI" self.gamemap.load( self.choose_map() ) print "Placing AI sub on map" start_loc = self.gamemap.get_random_location() start_loc.visited = True self.gamemap.current = start_loc self.gamemap.print_map() self.difficulty = self.choose_difficulty() print "Starting game..." while not self.stop: self.get_player_direction() if self.check_gameover(): continue raw_input( "Press Enter when ready for next turn" ) self.do_comp_turn() def choose_map( self ): print "Loading default map" #return "../resources/blank_map.txt" return "../resources/alpha_map.txt" def choose_difficulty( self ): print "Choose AI difficulty:" print "1) Easy" inp = raw_input( "> " ).strip().lower() if inp in [ "1", "easy" ]: return self.EASY elif inp in [ "2", "normal" ]: return self.NORMAL elif inp in [ "3", "hard" ]: return self.HARD return self.EASY def get_player_direction( self ): while True: inp = raw_input( "Direction and systems: " ).strip() parts = inp.split( " " ) handled_dir = False for inp in parts: self.print_debug( "Handling '%s'" % inp ) if inp.lower() in [ "n", "north" ]: if len(self.player_movements) > 0 and self.player_movements[ -1 ] == Gamemap.SOUTH: print "Node already visited!" continue self.player_movements.append( Gamemap.NORTH ) handled_dir = True elif inp.lower() in [ "s", "south" ]: if len(self.player_movements) > 0 and self.player_movements[ -1 ] == Gamemap.NORTH: print "Node already visited!" continue self.player_movements.append( Gamemap.SOUTH ) handled_dir = True elif inp.lower() in [ "e", "east" ]: if len(self.player_movements) > 0 and self.player_movements[ -1 ] == Gamemap.WEST: print "Node already visited!" continue self.player_movements.append( Gamemap.EAST ) handled_dir = True elif inp.lower() in [ "w", "west" ]: if len(self.player_movements) > 0 and self.player_movements[ -1 ] == Gamemap.EAST: print "Node already visited!" continue self.player_movements.append( Gamemap.WEST ) handled_dir = True elif inp.lower().startswith( "surf" ): self.player_movements.append( Gamemap.SURFACE ) handled_dir = True elif inp.lower() in [ 'm', 'mine' ]: # Player has dropped a mine print "You have dropped a mine" self.player_movements.append( Gamemap.MINE ) elif inp.lower() in [ 'tm', 'triggermine', 'detonate' ]: # Player has detonated a mine self.player_detonate_mine() elif inp.lower() in [ 't', 'tor', 'torpedo' ]: # Player has launched a torpedo self.player_activate_torpedo() elif inp.lower() in [ 'd', 'dro', 'drone' ]: # Player is asking for a specific quadrant self.player_activate_drone() elif inp.lower().startswith( 'son' ): # Player should receive one true and one false piece of information (row, column, sector) self.player_activate_sonar() elif inp.lower().startswith( 'sil' ): # Player activating silence mode self.player_movements.append( Gamemap.SILENCE ) self.player_activate_silence() elif inp.lower().startswith( 'sc' ): # Player activating scenario system self.player_movements.append( Gamemap.SCENARIO ) self.player_activate_scenario() if not self.stop and not handled_dir: print "Invalid direction or no direction given" continue break def player_activate_torpedo( self ): while True: xy = raw_input( "Where is the impact (xy)? " ).strip().lower() if xy == 'cancel': break xy = xy.replace( " ", "" ) x = xy[ 0 ] y = xy[ 1: ] x = ord(x) - ord('a') try: y = int(y) - 1 except: print "Invalid Y coordinate - must be a number" continue if self.handle_impact_at( x, y ): break def player_activate_drone( self ): while True: sector = raw_input( "When sector? " ) try: sector = int(sector) except: print "Invalid sector" continue sector -= 1 # sector must be zero-based if self.gamemap.get_sector() == sector: print "AI Responds with YES" else: print "AI Responds with NO" break def player_activate_sonar( self ): # AI must give one true and one false piece of information sector = self.gamemap.get_sector() trues = { 'Row': str(self.gamemap.current.y + 1), 'Col': chr(self.gamemap.current.x + ord('A')), 'Sector': str(sector + 1) } falses = { "Row": [ str(i + 1) for i in xrange( len(self.gamemap.map) ) if i != self.gamemap.current.y ], 'Col': [ chr(i + ord('A')) for i in xrange( len(self.gamemap.map) ) if i != self.gamemap.current.x ], 'Sector': [ str(i + 1) for i in xrange( (len(self.gamemap.map) / 5) * (len(self.gamemap.map) / 5) ) if i != sector ] } true_cat = random.choice( trues.keys() ) false_cat = None while True: false_cat = random.choice( falses.keys() ) if false_cat == true_cat: continue break false_choice = random.choice( falses[ false_cat ] ) choices = [ "%s: %s" % (true_cat, trues[ true_cat ]), "%s: %s" % (false_cat, false_choice) ] self.print_debug( "%s: %s (TRUE)" % (true_cat, trues[ true_cat ] ) ) self.print_debug( "%s: %s (FALSE)" % (false_cat, false_choice ) ) random.shuffle( choices ) for c in choices: print c def player_activate_silence( self ): print "Player activates silence!" def player_activate_scenario( self ): print "Player activates scenario system!" def player_detonate_mine( self ): while True: inp = raw_input( "Detonate mine at xy: " ).strip().lower() if inp == 'cancel': break xy = xy.replace( " ", "" ) x = xy[ 0 ] y = xy[ 1: ] x = ord(x) - ord('a') if x < 0 or x >= len(self.gamemap.map): print "Invalid X coordinate" continue try: y = int(y) - 1 except: print "Invalid Y coordinate - must be a number" continue if self.handle_impact_at( x, y ): break def handle_impact_at( self, x, y ): print "Handling impact at [%d, %d]" % (x, y) impactat = self.gamemap.get( [x,y] ) if impactat is None: print "Invalid coordinate" return False neighbors = self.gamemap.get_neighbors( [x,y] ) # Destroy any mines at 'impactat' location impactat.mine = False # Check if direct hit on AI sub if impactat == self.gamemap.current: print "DIRECT HIT!" self.sub_damage += 2 elif self.gamemap.current in neighbors: print "INDIRECT HIT!" self.sub_damage += 1 else: print "ALL CLEAR!" if self.sub_damage >= self.MAX_DAMAGE: print "AI Sub Sank!" self.stop = True return True def do_comp_turn( self, silence=False ): self.analyze_player_map() d = self.comp_choose_direction() if not silence or self.debug: self.print_debug( "AI Sub moving %s" % d ) n = self.gamemap.get_in_dir( d ) n.visited = True self.gamemap.current = n self.gamemap.print_map() self.comp_charge_system() self.comp_damage_system( d ) if self.check_gameover(): return self.comp_activate_system() if not silence or self.debug: print "\n==================\nAI Sub Moves %s\n==================\n" % d def analyze_player_map( self ): """ Attempt to find the player. Populate the possible_player_locations list. """ self.possible_player_locations = [] for y in xrange( self.gamemap.height ): for x in xrange( self.gamemap.width ): node = self.gamemap.get( (x, y) ) if self.is_possible_player_location( x, y ): self.possible_player_locations.append( (x,y) ) self.print_debug( "Found %d possible player locations" % len(self.possible_player_locations) ) #for loc in self.possible_player_locations: #self.print_debug( " %s" % str(loc) ) def is_possible_player_location( self, x, y ): loc = (x, y) expected_sector = None sonar_info = None for dir in self.player_movements[::-1]: if dir.startswith( Gamemap.DRONE ): # Sonar(<sector>=YES|NO) d = dir[ (dir.find("(") + 1) : dir.find(")") ] sector, value = d.split( "=" ) if value == "yes": expected_sector = int(sector) else: expected_sector = None elif dir.startswith( Gamemap.SONAR ): # (row=%s, col=%s, sector=%s) d = dir[ (dir.find("(") + 1) : dir.find(")") ] rowstr, colstr, sectorstr = d.split( "," ) sonar_info = { 'row': rowstr.strip().split( "=" )[ 1 ], 'col': colstr.strip().split( "=" )[ 1 ], 'sector': sectorstr.strip().split( "=" )[ 1 ] } elif dir == Gamemap.MINE: pass elif dir == Gamemap.SILENCE: # Player could have moved 0-4 spaces in a single direction pass elif dir == Gamemap.SCENARIO: pass else: ret = True opp_dir = self.gamemap.get_opposite_direction( dir ) loc = self.gamemap.get_coord_in_dir( opp_dir, loc ) node = self.gamemap.get( loc ) if node is None: ret = False if ret and expected_sector is not None and not self.gamemap.is_in_sector( expected_sector, loc ); ret = False if ret and sonar_info is not None: # Only one of the info is true row_true = False col_true = False sec_true = False for key in [ 'row', 'col', 'sector' ]: if sonar_info[ key ] != "": if key == 'row' and int(sonar_info[ key ]) == loc[ 1 ]: row_true = True elif key == 'col' and int(sonar_info[ key ]) == loc[ 0 ]: col_true = True elif key == 'sector' and self.gamemap.is_in_sector( int(sonar_info[ key ]), loc ): sec_true = Trues # if all are false, then this loc cannot be where the player is if not row_true and not col_true and not sec_true: ret = False # Drone and Sonar info is only valid for one movement expected_sector = None sonar_info = None if not ret: return ret