def dungeon_map_generator(width=20, height=10): """ Generates random map with at least 10% cells occupied with traps and 5% with treasures. Rounding quantity of special cells performed to higher value (ceil) """ my_logger.debug("Checking correctness of input...") if not (isinstance(width, int) and isinstance(height, int)): my_logger.info( 'Wrong cell size! Width and height should be positive integers\n') return None if width < 2: width = 2 elif width > 119: width = 119 if height < 2: height = 2 elif height > 30: height = 30 my_logger.debug("Input check done") my_logger.debug("Calculating amount of traps and treasures...") cells_count = width * height treasures_count = ceil((cells_count) / 20) trap_count = ceil((cells_count) / 10) my_logger.debug("Traps and treasures quantity has been calculated") my_logger.debug("Generating map...") dungeon_map = ['T' for x in range(0, treasures_count)] dungeon_map.extend(['X' for x in range(0, trap_count)]) dungeon_map.extend( ['-' for x in range(0, cells_count - treasures_count - trap_count)]) shuffle(dungeon_map) dungeon_map = [ dungeon_map[x * width:x * width + width] for x in range(0, height) ] my_logger.debug("Map has been generated") return dungeon_map
def draw_character(self): health_info = "".join( ['Health: ', *["[#]" for x in range(0, self.health)], *["[ ]" for x in range(self.health, 3)]]) treasures_info = "".join( ['Treasures: ', *["[@]" for x in range(0, self.treasures)], *["[ ]" for x in range(self.treasures, 3)]]) my_logger.info(" ".join([health_info, treasures_info]))
def make_move(self, move_direction, width, height): """ Used to change coordinates of character """ try: if not move_direction in set(['w', 'd', 's', 'a']): raise MoveError("Appeared while player has moved") except MoveError as move_error: my_logger.exception(move_error) return False old_x = self.player_x old_y = self.player_y if move_direction == 'w': if self.player_y > 0: self.player_y -=1 my_logger.info('You have moved up') elif move_direction == 'd': if self.player_x < width - 1: self.player_x +=1 my_logger.info('You have moved right') elif move_direction == 's': if self.player_y < height - 1: self.player_y +=1 my_logger.info('You have moved down') elif move_direction == 'a': if self.player_x > 0: self.player_x -=1 my_logger.info('You have moved left') if old_x == self.player_x and old_y == self.player_y: my_logger.info("There is a wall!") return True
def load_game(self): """ Game load (pickle!) """ my_logger.info("Loading game...") in_file = open('dungeon.sav', 'rb') data = pickle.load(in_file) [ self.dungeon_map.dungeon_map, self.dungeon_map.map_size, self.player_map.dungeon_map, self.player.player_x, self.player.player_y, self.player.health, self.player.treasures ] = data my_logger.info("Game has been loaded!")
def run_farame(self): """ Game frame. Returns true if game could be resumed and false otherwise """ ret_value = True move = input( '\nEnter your move, please (w - up, d - right, s - down, a - left), or "save" for save game:\n' ) if move == "save": self.save_game() ret_value = False self.player.make_move(move, *self.dungeon_map.map_size) self.player_map.update_map(self.dungeon_map, self.player.player_x, self.player.player_y) self.player_map.draw_map() if self.dungeon_map.get_cell_content(self.player.player_x, self.player.player_y) == 'T': self.dungeon_map.set_cell_content(self.player.player_x, self.player.player_y, '-') self.player.add_treasure() elif self.dungeon_map.get_cell_content(self.player.player_x, self.player.player_y) == 'X': self.dungeon_map.set_cell_content(self.player.player_x, self.player.player_y, '-') self.player.apply_damage() self.player.draw_character() if self.player.is_dead(): my_logger.info("\n}}}This is a trap! You loose!{{{\n") ret_value = False elif self.player.is_winner(): my_logger.info("\n>>>This is a treasure! You are victorious!<<<\n") ret_value = False return ret_value
def enemy_update(self): while self.is_game_ongoing: if time.clock() - self.time > 3.0: self.time = time.clock() self.player_map.set_cell_content(self.enemy.enemy_x, self.enemy.enemy_y, self.enemy_cell) move_direction = random.choice(['w', 'a', 's', 'd']) self.enemy.make_move(move_direction, self.dungeon_map.map_size[0], self.dungeon_map.map_size[1]) self.enemy_cell = self.player_map.get_cell_content( self.enemy.enemy_x, self.enemy.enemy_y) if self.enemy_cell != '?': self.player_map.set_cell_content(self.enemy.enemy_x, self.enemy.enemy_y, '%') self.player_map.draw_map() self.player.draw_character() if self.player.player_x == self.enemy.enemy_x and self.player.player_y == self.enemy.enemy_y: self.player.apply_damage() self.enemy.randomize_initial_position(self.dungeon_map) my_logger.info('\n %[ You have been beaten by enemy!') my_logger.info( '\nEnter your move, please (w - up, d - right, s - down, a - left), or "save" for save game:\n' ) if self.player.is_dead(): self.is_game_ongoing = False else: time.sleep(0.1)
def setup_game(self): """ Game startup method: user should choose between playing new game or loading save """ my_logger.debug("Game start choice") start_game_choice = input( 'Enter "y" if you want to play a new game or\n"load" if you want to load existing game:\n' ) my_logger.debug("Game start choice handling") if start_game_choice == "load": self.load_game() else: map_request = input( 'Enter preferable map size in format "width:height", or just press enter to play with default map:\n' ) my_logger.info("Generating map...") if not len(map_request): map_size = [20, 10] else: map_size = [int(token) for token in map_request.split(':')] self.dungeon_map.set_map_size(*map_size) self.dungeon_map.generate_map() my_logger.info("Map has been generated successfully!") self.player_map.set_map_size(*map_size) self.player_map.init_map() self.player.reset() self.player.randomize_initial_position(self.dungeon_map) self.player_map.update_map(self.dungeon_map, self.player.player_x, self.player.player_y) self.player_map.draw_map()
def setup_new_game(self): """ This function is used to generate new map of size, specified by user """ while True: map_request = input( 'Enter preferable map size in format "width:height", or just press enter to play with default map:\n' ) my_logger.info("Generating map...") if not len(map_request): map_size = [20, 10] break else: try: map_size = [int(token) for token in map_request.split(':')] break except ValueError as val_error: my_logger.exception(val_error) my_logger.error("Try to enter map size once again!") self.dungeon_map.set_map_size(*map_size) self.dungeon_map.generate_map() my_logger.info("Map has been generated successfully!") self.player_map.set_map_size(*map_size) self.player_map.init_map() self.player.reset() self.player.randomize_initial_position(self.dungeon_map) self.enemy.randomize_initial_position(self.dungeon_map)
def draw_map(self): for row in self.dungeon_map: my_logger.info("".join(row))
def update_map(self, real_map, player_x, player_y): my_logger.debug("Checking for wall near player...") min_row_index = player_y - 1 if player_y - 1 > 0 else 0 max_row_index = player_y + 2 if player_y + 1 < self.map_size[ 1] else self.map_size[1] row_range = range(min_row_index, max_row_index) min_column_index = player_x - 1 if player_x - 1 > 0 else 0 max_column_index = player_x + 2 if player_x + 1 < self.map_size[ 0] else self.map_size[0] column_range = range(min_column_index, max_column_index) my_logger.debug("Wall check done") my_logger.debug("Checking for treasures and traps around") is_treasure = False is_trap = False for y in row_range: for x in column_range: if real_map.get_cell_content(x, y) == 'T': is_treasure = True elif real_map.get_cell_content(x, y) == 'X': is_trap = True if is_treasure and is_trap: cell_filler = '!' elif is_treasure: cell_filler = 't' elif is_trap: cell_filler = 'x' else: cell_filler = '-' my_logger.debug("Treasures and traps check done") my_logger.debug("Making output for player") for y in row_range: for x in column_range: if self.dungeon_map[y][x] == '@': self.dungeon_map[y][x] = '-' elif not self.dungeon_map[y][x] == '-': self.dungeon_map[y][x] = cell_filler self.dungeon_map[player_y][player_x] = '@' if is_treasure: my_logger.info('There is a treasure!') elif is_trap: my_logger.info('There is a trap!') my_logger.debug("Player output finished") return None
def check_around(player_x, player_y, map_size, dungeon_map, player_map): """ This function performs check for treasures/traps in surrounding cells """ is_treasure = False is_trap = False my_logger.debug("Checking for wall near player...") min_row_index = player_y - 1 if player_y - 1 > 0 else 0 max_row_index = player_y + 2 if player_y + 1 < map_size[1] else map_size[1] row_range = range(min_row_index, max_row_index) min_column_index = player_x - 1 if player_x - 1 > 0 else 0 max_column_index = player_x + 2 if player_x + 1 < map_size[ 0] else map_size[0] column_range = range(min_column_index, max_column_index) my_logger.debug("Wall check done") my_logger.debug("Checking for treasures and traps around") for y in row_range: for x in column_range: if dungeon_map[y][x] == 'T': is_treasure = True elif dungeon_map[y][x] == 'X': is_trap = True if is_treasure and is_trap: fill_cells = '!' elif is_treasure: fill_cells = 't' elif is_trap: fill_cells = 'x' else: fill_cells = '-' my_logger.debug("Treasures and traps check done") my_logger.debug("Making output for player") for y in row_range: for x in column_range: if not player_map[y][x] == '-': player_map[y][x] = fill_cells player_map[player_y][player_x] = '@' for row in player_map: my_logger.info("".join(row)) if is_treasure: my_logger.info('There is a treasure!') elif is_trap: my_logger.info('There is a trap!') my_logger.debug("Player output finished") return (is_treasure, is_trap)
def make_move(move_direction, player_position, map_size): """ Changes player position according to user input """ if not move_direction in set(['w', 'd', 's', 'a']): my_logger.info('Wrong direction! Try again!') old_position = player_position[:] if move_direction == 'w': if player_position[1] > 0: player_position[1] -= 1 my_logger.info('You have moved up') elif move_direction == 'd': if player_position[0] < map_size[0] - 1: player_position[0] += 1 my_logger.info('You have moved right') elif move_direction == 's': if player_position[1] < map_size[1] - 1: player_position[1] += 1 my_logger.info('You have moved down') elif move_direction == 'a': if player_position[0] > 0: player_position[0] -= 1 my_logger.info('You have moved left') if old_position == player_position: my_logger.info("There is a wall!")
def game_loop(): """ Main game function contains game loop and some surrounding stuff """ my_logger.debug("Game start choice") start_game_choice = input( 'Enter "y" if you want to play a new game or\n"load" if you want to load existing game:\n' ) my_logger.debug("Game start choice handling") if start_game_choice == "load": my_logger.info("Loading game...") in_file = open('dungeon.sav', 'rb') data = pickle.load(in_file) game_map = data[0] player_map = data[1] player_position = data[2] map_size = data[3] my_logger.info("Game has been loaded!") else: map_request = input( 'Enter preferable map size in format "width:height", or just press enter to play with default map:\n' ) my_logger.info("Generating map...") if not len(map_request): map_size = [20, 10] else: map_size = [int(token) for token in map_request.split(':')] game_map = dungeon_map_generator(*map_size) player_map = [['?' for x in range(0, map_size[0])] for y in range(0, map_size[1])] player_position = spawn_player(*map_size, game_map) my_logger.info("Map has been generated successfully!") my_logger.debug("Checking around...") check_around(*player_position, map_size, game_map, player_map) my_logger.debug("Check around has been done") my_logger.debug("Entering main game loop...") while True: move = input( '\nEnter your move, please (w - up, d - right, s - down, a - left), or "save" for save game:\n' ) if move == "save": data = [game_map, player_map, player_position, map_size] out_file = open('dungeon.sav', 'wb') pickle.dump(data, out_file) break player_map[player_position[1]][player_position[0]] = '-' make_move(move, player_position, map_size) check_around(*player_position, map_size, game_map, player_map) if game_map[player_position[1]][player_position[0]] == 'T': my_logger.info("\n>>>This is a treasure! You are victorious!<<<\n") break elif game_map[player_position[1]][player_position[0]] == 'X': my_logger.info("\n}}}This is a trap! You loose!{{{\n") break else: continue my_logger.debug("Main game loop has stopped") my_logger.debug("Printing game map...") for row in game_map: my_logger.info("".join(row)) my_logger.debug("Game map has been printed")
def make_move(self, move_direction, width, height): if not move_direction in set(['w', 'd', 's', 'a']): my_logger.info('Wrong direction! Try again!') return False old_x = self.player_x old_y = self.player_y if move_direction == 'w': if self.player_y > 0: self.player_y -= 1 my_logger.info('You have moved up') elif move_direction == 'd': if self.player_x < width - 1: self.player_x += 1 my_logger.info('You have moved right') elif move_direction == 's': if self.player_y < height - 1: self.player_y += 1 my_logger.info('You have moved down') elif move_direction == 'a': if self.player_x > 0: self.player_x -= 1 my_logger.info('You have moved left') if old_x == self.player_x and old_y == self.player_y: my_logger.info("There is a wall!") return True