def try_place_max_prob(self, root, ship): '''Try to place the given ship, with base coordinate <root>. Try to maximize the probability of the ship not being hit, using the stat model, by trying both orientations. Return the result.''' ships = [ Ship(root[0], root[1], ship, True), Ship(root[0], root[1], ship, False) ] for s in sorted(ships, key=self.get_ship_prob): if self.try_place_ship(s): return True return False
def stage_current_ship(self): '''Stage the currently selected ship in the staging area. If no ship selected, do nothing.''' ship = self._get_current_ship() if ship is not None: self._staging_panel.stage_ship(Ship(0, 0, ship, True))
def load_callback(self, event=None, fname=None, warn=True): '''Read the JSON game configuration from file called <code>fname</code>. Return a dictionary representing the parsed JSON. All the strings are Unicode. May raise KeyError if JSON is not in the expected format (see battleship.json for example). May raise ValueError if fails to parse file May raise IOError if fails to find file''' while fname is None or isinstance(fname, list): fname = tkFileDialog.askopenfilename( defaultextension="json", initialdir=os.path.join(os.getcwd(), self.SAVE_DIR), filetypes=[("Battleship Games", "*.json")]) if isinstance(fname, list): self.game_frame.show_warning("Select one file only") fp = open(os.path.join(GameController.SAVE_DIR, fname), "r") obj = json.load( fp )["battleship"] # do this so we don't have to reference ["battleship"] every time fp.close() if not warn or tkMessageBox.askyesno( "Load Game", "Loading another game will cause you to lose all unsaved progress. Continue?" ): self.new_game_callback() #TODO just for now, to see if it works #print obj # load the models #TODO models go here grids = [ self.game_frame.my_grid._model, self.game_frame.their_grid._model ] # placing ships for grid, player in zip(grids, GameController.PLAYERS): for ship_name, coords in obj[player]["ships"].items(): s = Ship(type=str(ship_name), x=coords[0], y=coords[1], vertical=coords[2]) success = grid.add(s) #TODO handle the case when this fails (means bad initial config) assert success grid.finalize(error_check=False) # firing shots for grid, player in zip(grids, GameController.PLAYERS): for shot in obj[player]["shots"]: grid.process_shot(*shot) self.game_frame.redraw() return
def _place_ships_randomly(self): '''Place ships completely randomly. This method does not look at probabilities. Just picks random spots.''' valid_squares = set(zip(range(GridModel.SIZE), range(GridModel.SIZE))) i = 0 while i < len(Ship.SHORT_NAMES) and len(valid_squares) > 0: sq = random.sample(valid_squares, 1)[0] #note that Python does not support random.choice for sets v = random.choice([True, False]) ship = Ship(x=sq[0], y=sq[1], type=Ship.SHORT_NAMES[i], vertical=v) # try to place this ship if self.try_place_ship(ship): i += 1 valid_squares.difference_update(set(ship.get_covering_squares())) return len(self._placements) == len(Ship.SHORT_NAMES)
def can_add_ship(self, x, y, ship, vertical): '''Whether the given ship can be added to the grid. There are actually two use cases: - when placing initially, consider secret ships - when constructing model of opponent, hide secret ships''' s = Ship(x, y, ship, vertical) return self.can_add(s)
def _place_ships_randomly(self): '''Place ships completely randomly. This method does not look at probabilities. Just picks random spots.''' valid_squares = set(zip(range(GridModel.SIZE), range(GridModel.SIZE))) i = 0 while i < len(Ship.SHORT_NAMES) and len(valid_squares) > 0: sq = random.sample(valid_squares, 1)[ 0] #note that Python does not support random.choice for sets v = random.choice([True, False]) ship = Ship(x=sq[0], y=sq[1], type=Ship.SHORT_NAMES[i], vertical=v) # try to place this ship if self.try_place_ship(ship): i += 1 valid_squares.difference_update( set(ship.get_covering_squares())) return len(self._placements) == len(Ship.SHORT_NAMES)
def _create_ships(self): '''Create ships on the canvas.''' self._ship_squares = {} for i, ship in enumerate(Ship.SHORT_NAMES): y = self.TOP_PADDING + i * (self.Y_SPACING * 2 + self.RECT_SIZE) s = Ship(0, 0, ship, False) self._c.create_text(self.LEFT_PADDING, y, text=s.get_full_name().title(), anchor=NW) self._ship_squares[ship] = [None] * s.get_size() for x in range(s.get_size()): self._ship_squares[ship][x] = self._c.create_rectangle( self.LEFT_PADDING + x * self.RECT_SIZE, y + self.Y_SPACING, self.LEFT_PADDING + (x + 1) * self.RECT_SIZE, y + self.Y_SPACING + self.RECT_SIZE, fill=self.RECT_NULL_FILL, outline="black" )
def stage_ship_callback(self, event=None): '''Move a ship to the staging area.''' #ship = get_selected_ship() #move ship to staging area #that's about it if self.game_frame.my_grid_frame.ship_panel.get_current_ship() is not None: s = Ship(0, 0, self.game_frame.my_grid_frame.ship_panel.get_current_ship(), True) self.game_frame.my_grid_frame.staging_panel.add_ship(s) pass
def make_stat_model( self ): #, x_start=0, x_end=GridModel.SIZE, y_start=0, y_end=GridModel.SIZE): '''(re)compute the statistical model in the given range.''' # initialize all squares self.prelim_mark_stat_model() for x in range(0, GridModel.SIZE): for y in range(0, GridModel.SIZE): for ship in self._unsunk_ships: for v in [True, False]: s = Ship(x, y, ship, v) self.add_ship_to_stat_model(s)
def add_ship(self, x, y, ship, vertical, callback=None): '''Add a ship at (x, y). Vertical is the orientation - True of False.''' # sometimes nothing is selected, but grid is pressed. # ignore these events if ship is None: return False result = self._model.can_add_ship(x, y, ship, vertical) if result: if ship in self._model._ships: prev_ship = self._model._ships[ship] for sq in prev_ship.get_covering_squares(): self._set_tile_state(*sq) # reset state self._model.add_ship(x, y, ship, vertical) s = Ship(x, y, ship, vertical) self.add_ship_to_view(s) if callback is not None: callback() return result
def reset(self): for ship in Ship.SHORT_NAMES: s = Ship(0, 0, ship, False) self.update(s, [0] * s.get_size())
def add_ship(self, x, y, ship, vertical): '''Add a new ship, or change orientation of existing ship.''' s = Ship(x, y, ship, vertical) return self.add(s)