def _draw_buttons(self): size = Coords(x=6, y=1) return [ SelectionButton( surface=self.surface, pos=Coords(x=8, y=2), size=size, text='human', value='human', desc= """A typical human scum. Tends to have 4 legs and a gender of her choice. They love to watch the fire burn and have Vietnam flashbacks."""), SelectionButton(surface=self.surface, pos=Coords(x=8, y=3), size=size, text='random AI', value='random AI', desc="""Cute AI that shoots bullets in the dark. I\'m actually going to tell you what it does: import random as r r.choice(possible_moves) """) ]
def __post_init__(self): self.backdrop = Backdrop(sprite_group=self.sprite_group, pos=Coords(x=0, y=0), size=Coords(x=s.GRIDWIDTH, y=s.GRIDHEIGHT)) self.tp = Typewriter(surface=self.backdrop.image, config=self.go_config) self.tp.type('Game over')
def draw_buttons(self): w, h = self.frame.get_width(), self.frame.get_height() size = Coords(x=2.4, y=2.4) return [ Button(surface=self.frame, pos=Coords(x=0, y=0), size=size, value='queen', text='Q'), Button(surface=self.frame, pos=Coords(x=2.4, y=0), size=size, value='rook', text='R'), Button(surface=self.frame, pos=Coords(x=0, y=2.4), size=size, value='bishop', text='B'), Button(surface=self.frame, pos=Coords(x=2.4, y=2.4), size=size, value='knight', text='K') ]
def __post_init__(self): self.backdrop = Backdrop(sprite_group=self.sprite_group, pos=Coords(x=0, y=0), size=Coords(x=s.GRIDWIDTH, y=s.GRIDHEIGHT)) super().__post_init__() self.frame, self.f_rect = self.draw_frame() self.buttons = self.draw_buttons()
def _back_button(self): size = Coords(x=6, y=1) return [ Button(surface=self.surface, pos=Coords(x=8, y=4), size=size, text='back', value='back', config=TypewriterConfig(size=16, color=s.GREEN, pos='midleft')) ]
def clear_diagonals(self, grid, offset=None): """ Get free diagonals within offset """ moves = [] for diag in self.diagonals(self.row, self.col, 8, offset): for coords in diag: if grid[coords]: piece = PieceId(*[int(e) for e in str(grid[coords])]) if Color(piece.color) != self.color: moves.append(Coords(x=coords[1], y=coords[0])) break else: moves.append(Coords(x=coords[1], y=coords[0])) return moves
def clear_verticals(self, grid, offset=None, can_capture=True): """ Get free verticals within offset """ moves = [] for vert in self.verticals(self.row, self.col, 8, offset): for coords in vert: if grid[coords]: piece = PieceId(*[int(e) for e in str(grid[coords])]) if can_capture and Color(piece.color) != self.color: moves.append(Coords(x=coords[1], y=coords[0])) break else: moves.append(Coords(x=coords[1], y=coords[0])) return moves
def possible_moves(self, grid): moves = [] offset = np.array([[-2, -1], [-2, 1], [2, -1], [2, 1]]) idx = np.row_stack((offset, offset[:, ::-1])) + (self.row, self.col) idxs = idx[~((idx < 0) | (idx > 7)).any(1)] for coords in idxs: coords = tuple(coords) if grid[coords]: piece = PieceId(*[int(e) for e in str(grid[coords])]) if Color(piece.color) != self.color: moves.append(Coords(x=coords[1], y=coords[0])) else: moves.append(Coords(x=coords[1], y=coords[0])) return moves
def possible_moves(self, grid): moves = [] for move in self.clear_diagonals(grid, self.move_offset): # only move diagonally if there's an enemy piece. # due to logic in clear_diagonals there can only # be enemy pieces if grid[move.row, move.col]: moves.append(move) for move in self.clear_verticals(grid, offset=self.move_offset, can_capture=False): # only allow y-axis movement if move.col == self.col: moves.append(move) if not self.moved: # if pawn hasn't moved yet, then it gets a POWA MOVE # if no one is there powa_move = Coords( x=self.col, y=self.row + 2 if self.color == Color.black else self.row - 2 ) if powa_move.row < 0 or powa_move.row > 7: pass elif not grid[powa_move.row, powa_move.col]: moves.append(powa_move) return moves
def __post_init__(self): super().__init__(self.sprite_group) self.image = pg.Surface( (s.TILESIZE * self.size.x, s.TILESIZE * self.size.y)) self.image.fill(s.DARKGREY) self.rect = self.image.get_rect() self.x = self.pos.x self.y = self.pos.y self.rect = self.image.get_rect(midtop=(self.x * s.TILESIZE, self.y * s.TILESIZE)) self.buttons = self.draw_buttons() self.player_menu = PlayerMenu(surface=self.image, pos=Coords(x=8, y=1), size=Coords(x=6, y=6)) self.sel_buttons = self.player_menu.draw() self.draw_pixel_art()
def draw_legend(self): letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] config = TypewriterConfig(size=22, color=s.WHITE, padding=10, surface_color=s.DARKGREY) tp = Typewriter(surface=self.image, config=config) for i, l in enumerate(letters, start=1): num_w, num_h = tp.get_text_size(str(i)) l_w, l_h = tp.get_text_size(l) tp.type(text=str(i), coords=Coords(x=s.TILESIZE // 2 - num_w // 2, y=s.TILESIZE * 2 * i - num_h // 2)) tp.type(text=l, coords=Coords(x=i * s.TILESIZE * 2 - l_w // 2, y=self.image.get_height() - s.TILESIZE + l_h // 4))
def new(self, config=None): # initialize all variables and do all the setup for a new game self.wood = Wood( sprite_group=self.sprites, pos=Coords(x=1, y=1), size=Coords(x=18, y=18) ) self.board = Board( sprite_group=self.sprites, pos=self.wood.pos ) self.move = Console( sprite_group=self.sprites, title='MOVE', pos=Coords(x=20, y=1), size=Coords(x=11, y=10) ) self.console = Console( sprite_group=self.sprites, pos=Coords(x=20, y=12), size=Coords(x=11, y=11) ) self.game_over = GameOver( sprite_group=self.game_over_sprites, pos=Coords(x=13, y=7), size=Coords(x=5, y=6), color=s.LIGHTGREY ) self.promotion = Promotion( sprite_group=self.promotion_sprites, pos=Coords(x=13, y=7), size=Coords(x=5, y=6), color=s.LIGHTGREY, margin=4, frame_offset=s.TILESIZE+4, tp_config=TypewriterConfig( padding=5, size=22, color=s.WHITE, surface_color=s.DARKGREY, pos='midtop' ) ) self.board.set_console(self.console) self.players = {k: PlayerFactory.make(name=v)(k) for k, v in config['player'].items()} self.turn = Color.white
def draw_mouse_pos(self, screen): mpos = pg.mouse.get_pos() coords = Coords(x=s.TILESIZE * 3, y=s.TILESIZE) follow = pg.Surface((coords.x, coords.y)) rect = follow.get_rect(topleft=(0, 0)) tp = Typewriter(follow, TypewriterConfig(size=12, pos='center')) tp.type(str(mpos)) screen.blit(follow, rect)
def draw_buttons(self): size = Coords(x=6, y=6) return [ Button(surface=self.image, pos=Coords(x=1, y=8), size=size, text='PLAY', value='PLAY'), Button(surface=self.image, pos=Coords(x=8, y=8), size=size, text='CONFIG', value='CONFIG'), Button(surface=self.image, pos=Coords(x=15, y=8), size=size, text='QUIT', value='QUIT') ]
def draw_armies(self): for i, row in enumerate(self.grid): for j, cell in enumerate(row): if cell: c = str(cell) pid = PieceId(num=cell, color=Color(int(c[-2])), type=PieceType(int(c[-1]))) piece = PieceFactory.make(pid, Coords(x=j, y=i)) self.pieces[pid.num] = piece self.sprites.add(piece)
def events(self, events): move = None grid_click_pos = None promotion_click_pos = None prom = False for event in events: if event.type == pg.KEYDOWN: if event.key == pg.K_d: self.debug = not self.debug if event.type == pg.MOUSEBUTTONUP: if self.is_promoting and self.promotion.rect.collidepoint(event.pos): # check if click was in the promotion menu promotion_click_pos = event.pos elif not self.is_promoting and self.board.rect.collidepoint(event.pos): # check if click was inside chess grid grid_click_pos = event.pos if self.check_mate() or self.draw(): self.is_game_over = True return # no more mr nice guy # handle turn: move or promote is_machine = self.players[self.turn].type == 'machine' if not self.is_promoting and (grid_click_pos or is_machine): mpos = self.board.px_to_grid(Coords(x=grid_click_pos[0], y=grid_click_pos[1])) \ if grid_click_pos is not None else None move = self.players[self.turn].move( self.board, mpos ) elif self.is_promoting and (promotion_click_pos or is_machine): prom = self.players[self.turn].promote( board=self.board, pawn=self.pawn_prom, promotion_selector=self.promotion, pos=promotion_click_pos if promotion_click_pos else None ) self.is_promoting = False self.pawn_prom = None # check if there are any promotions to be done self.pawn_prom = self.board.promotions(self.turn) if self.pawn_prom: self.is_promoting = True if move: self.last_move = move # next turn happens when there are NO PENDING # PROMOTIONS and a MOVE or a PROMOTION took place. if not self.is_promoting and (move or prom): self.log_turn(prom) self.turn = Color.next(self.turn)
def _castle_move(self, king, rook, to): off = -1 if king.pos.col + 2 == to.col else 1 self.console.log('Castling!') # move king self.grid[to.row, to.col], self.grid[king.pos.row, king.pos.col] = \ self.grid[king.pos.row, king.pos.col], 0 # move rook self.grid[to.row, to.col+off], self.grid[rook.pos.row, rook.pos.col] = \ self.grid[rook.pos.row, rook.pos.col], 0 # update sprites king.pos = to rook.pos = Coords(x=to.col + off, y=to.row)
def new(self, config=None): self.title = Title(sprite_group=self.sprites, pos=Coords(x=s.GRIDWIDTH // 2, y=1), size=Coords(x=16, y=4)) self.menu = Menu(sprite_group=self.sprites, pos=Coords(x=s.GRIDWIDTH // 2, y=6), size=Coords(x=22, y=15)) self.console = Console(sprite_group=self.sprites, pos=Coords(x=6, y=7), size=Coords(x=6, y=6), color=s.WHITE, parent_color=s.DARKGREY, margin=6, frame_offset=s.TILESIZE, tp_config=TypewriterConfig( padding=5, size=22, color=s.DARKGREEN, surface_color=s.DARKGREY, pos='midtop'), config=TypewriterConfig(surface_color=s.BLACK, size=12, padding=5)) self.info_console = Console( sprite_group=self.sprites, pos=Coords(x=s.GRIDWIDTH // 2 + 4, y=7), size=Coords(x=6, y=6), title='INFO', color=s.WHITE, parent_color=s.DARKGREY, margin=6, frame_offset=s.TILESIZE, tp_config=TypewriterConfig(padding=5, size=22, color=s.DARKGREEN, surface_color=s.DARKGREY, pos='midtop'), config=TypewriterConfig(surface_color=s.BLACK, color=s.WHITE, size=12, padding=5)) self.menu.set_console(self.console) self.menu.set_info_console(self.info_console)
def scale_mouse(self, mpos): mpos = Coords(x=mpos[0], y=mpos[1]) offset = Coords(x=self.rect.x, y=self.rect.y) return mpos - offset
def scale_mouse(self, mpos): mpos = Coords(x=mpos[0], y=mpos[1]) offset = Coords(x=self.rect.x, y=self.rect.y) + Coords( x=self.margin, y=self.frame_offset) return mpos - offset
def px_to_grid(self, pos: Coords): coords = (pos - self.rect.topleft) / s.TILESIZE // 2 return Coords(x=coords.x, y=coords.y)
def update(self): # noinspection PyTypeChecker center = self.pos * s.TILESIZE * 2 + Coords(x=s.TILESIZE, y=s.TILESIZE) * 3 self.rect.center = (center.x, center.y)