# -*- coding: utf-8 -*- import os import random import pygame import classes.board import classes.extras as ex import classes.game_driver as gd import classes.level_controller as lc class Board(gd.BoardGame): def __init__(self, mainloop, speaker, config, screen_w, screen_h): self.level = lc.Level(self, mainloop, 1, 14) gd.BoardGame.__init__(self, mainloop, speaker, config, screen_w, screen_h, 13, 9) def create_game_objects(self, level=1): self.allow_unit_animations = False self.allow_teleport = False self.board.decolorable = False self.vis_buttons = [1, 1, 1, 1, 1, 0, 1, 1, 1] self.mainloop.info.hide_buttonsa(self.vis_buttons) self.board.draw_grid = False white = (255, 255, 255) if self.mainloop.scheme is None: font_col = (0, 0, 0) else: font_col = self.mainloop.scheme.u_font_color if self.mainloop.scheme.dark: white = (0, 0, 0) # setting level variable # data = [x_count, y_count, number_count, top_limit, ordered] if self.level.lvl == 1: data = [5, 4, 5, 3, 2] elif self.level.lvl == 2: data = [5, 5, 8, 3, 3] elif self.level.lvl == 3: data = [6, 4, 7, 4, 2] elif self.level.lvl == 4: data = [6, 5, 11, 4, 3] elif self.level.lvl == 5: data = [6, 6, 15, 4, 4] elif self.level.lvl == 6: data = [7, 4, 9, 5, 2] elif self.level.lvl == 7: data = [7, 5, 14, 5, 3] elif self.level.lvl == 8: data = [7, 6, 19, 5, 4] elif self.level.lvl == 9: data = [7, 7, 24, 5, 5] elif self.level.lvl == 10: data = [8, 4, 11, 6, 2] elif self.level.lvl == 11: data = [8, 5, 17, 6, 3] elif self.level.lvl == 12: data = [8, 6, 23, 6, 4] elif self.level.lvl == 13: data = [8, 7, 29, 6, 5] elif self.level.lvl == 14: data = [8, 8, 35, 6, 6] self.chapters = [1, 3, 6, 10, 14] # rescale the number of squares horizontally to better match the screen width m = data[0] % 2 if m == 0: data[0] = self.get_x_count(data[1], even=True) else: data[0] = self.get_x_count(data[1], even=False) self.data = data self.layout.update_layout(data[0], data[1]) self.board.level_start(data[0], data[1], self.layout.scale) self.unit_mouse_over = None self.units = [] self.choice_list = [x for x in range(1, data[2] + 1)] self.shuffled = self.choice_list[:] random.shuffle(self.shuffled) """ If the grid size is odd, then the number of inversions in a solvable situation are even. If the grid size is even, and the blank is on an odd row (first, third etc), then the number of inversions in a solvable situation are odd. If the grid size is even, and the blank is on an even row (second, fourth etc), then the number of inversions in a solvable situation are even. """ inversions = ex.inversions(self.shuffled) if inversions % 2 != 0: # if number of inversions is odd it is unsolvable # in unsolvable combinations swapping 2 squares will make it solvable temp = self.shuffled[0] self.shuffled[0] = self.shuffled[1] self.shuffled[1] = temp h1 = (data[1] - data[4]) // 2 # height of the top margin h2 = data[1] - h1 - data[4] # height of the bottom margin w2 = (data[0] - data[3]) // 2 # side margin width self.check = [h1, h2, w2] # create table to store 'binary' solution # find position of first door square x = w2 y = h1 self.mini_grid = [] if self.mainloop.scheme is None: dc_img_src = os.path.join('unit_bg', "universal_sq_dc.png") else: dc_img_src = None bg_img_src = os.path.join('unit_bg', "universal_sq_bg.png") # add objects to the board line = [] h_start = random.randrange(0, 155, 5) h_step = 100 // (data[2]) for i in range(data[2]): h = (h_start + (self.shuffled[i] - 1) * h_step) number_color = ex.hsv_to_rgb(h, self.mainloop.cl.bg_color_s, self.mainloop.cl.bg_color_v) fg_number_color = ex.hsv_to_rgb(h, self.mainloop.cl.fg_hover_s, self.mainloop.cl.fg_hover_v) font_color = [ex.hsv_to_rgb(h, self.mainloop.cl.font_color_s, self.mainloop.cl.font_color_v), ] caption = str(self.shuffled[i]) self.board.add_universal_unit(grid_x=x, grid_y=y, grid_w=1, grid_h=1, txt=caption, fg_img_src=bg_img_src, bg_img_src=bg_img_src, dc_img_src=dc_img_src, bg_color=(0, 0, 0, 0), border_color=None, font_color=font_color, bg_tint_color=number_color, fg_tint_color=fg_number_color, txt_align=(0, 0), font_type=2, multi_color=False, alpha=True, immobilized=False, fg_as_hover=True) self.units.append(self.board.ships[-1]) self.board.ships[-1].readable = False self.board.ships[i].checkable = True self.board.ships[i].init_check_images() line.append(i) x += 1 if x >= w2 + data[3] or i == data[2] - 1: x = w2 y += 1 self.mini_grid.append(line) line = [] if self.mainloop.scheme is not None: self.outline_all(font_col, 1) if self.mainloop.scheme is None: self.outline_all(0, 1) # horizontal self.board.add_unit(0, 0, data[0], h1, classes.board.Obstacle, "", white, "", 7) # top self.board.add_unit(0, h1 + data[4], data[0], h2, classes.board.Obstacle, "", white, "", 7) # bottom 1 # side obstacles self.board.add_unit(0, h1, w2, data[4], classes.board.Obstacle, "", white, "", 7) # left self.board.add_unit(w2 + data[3], h1, w2, data[4], classes.board.Obstacle, "", white, "", 7) # right self.board.all_sprites_list.move_to_front(self.board.units[0]) def show_info_dialog(self): self.mainloop.dialog.show_dialog(3, self.d["Re-arrange right"]) def auto_check_reset(self): for each in self.board.ships: if each.checkable: each.set_display_check(None) def handle(self, event): gd.BoardGame.handle(self, event) # send event handling up if event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN: self.auto_check_reset() if event.type == pygame.MOUSEMOTION or event.type == pygame.MOUSEBUTTONUP: self.default_hover(event) def update(self, game): game.fill((255, 255, 255)) gd.BoardGame.update(self, game) # rest of painting done by parent def check_result(self): current = [x for x in range(self.data[2] + 1)] # self.choice_list[:] # collect value and x position on the grid from ships list for i in range(len(self.board.ships)): x = self.board.ships[i].grid_x - self.check[2] y = self.board.ships[i].grid_y - self.check[0] w = self.data[3] pos = x + (y * w) current[pos] = int(self.board.ships[i].value) if pos < self.data[2]: if self.choice_list[pos] == current[pos]: self.board.ships[i].set_display_check(True) else: self.board.ships[i].set_display_check(False) else: self.board.ships[i].set_display_check(False) del (current[-1]) if self.choice_list == current: self.level.next_board() self.mainloop.redraw_needed[0] = True """ If the grid size is odd, then the number of inversions in a solvable situation are even. If the grid size is even, and the blank is on an odd row (first, third etc), then the number of inversions in a solvable situation are odd. If the grid size is even, and the blank is on an even row (second, fourth etc), then the number of inversions in a solvable situation are even. Consider the following configuration in the 3 x 2 case: 4 5 1 3 2 The equivalent permutation is 4, 5, 1, 3, 2. The number of inversions is 3 + 3 + 1 = 7. n = 3, so n is odd. Therefore, the number of inversions in a legal configuration must be even. It's not, so this configuration is illegal. Here's another example. Considering the following 4 x 2 case: 7 2 1 4 6 3 5 The equivalent permutation is 7, 2, 1, 4, 6, 3, 5. The number of inversions is 6 + 1 + 1 + 2 = 10. In this case, n = 4, so n is even. m = 2 and i = 1, so m - i is odd and we are in case 1.1c of the proof -> the number of inversions must be odd. They are not, so this configuration is illegal. """