mirror of
https://github.com/kristoferssolo/Tetris.git
synced 2025-10-21 20:00:35 +00:00
fix imports
This commit is contained in:
parent
e9cd973360
commit
080ba1b9cb
@ -1,9 +1,4 @@
|
||||
from .log import log
|
||||
from .screens import Game, Main, Tetris
|
||||
from .screens import Game, Main, Preview, Score, Tetris
|
||||
|
||||
__all__ = [
|
||||
"log",
|
||||
"Main",
|
||||
"Game",
|
||||
"Preview",
|
||||
]
|
||||
__all__ = ["Main", "Game", "Preview", "Score", "Tetris", "log"]
|
||||
|
||||
@ -4,7 +4,7 @@ import pygame
|
||||
from utils import CONFIG, Figure, GameMode
|
||||
|
||||
from game.log import log
|
||||
from game.sprites.tetromino import Tetromino
|
||||
from game.sprites import Tetromino
|
||||
|
||||
from .base import BaseScreen
|
||||
from .preview import Preview
|
||||
@ -24,7 +24,7 @@ class Game(BaseScreen):
|
||||
score: Score object.
|
||||
preview: Preview object.
|
||||
next_figures: List of upcoming figures.
|
||||
music: Pygame music that plays in the background.
|
||||
music: Music that plays in the background.
|
||||
"""
|
||||
|
||||
def __init__(self, game_mode: GameMode) -> None:
|
||||
|
||||
@ -5,8 +5,7 @@ import pygame
|
||||
from utils import CONFIG, Direction, Figure, GameMode, Rotation
|
||||
|
||||
from game.log import log
|
||||
from game.sprites.block import Block
|
||||
from game.sprites.tetromino import Tetromino
|
||||
from game.sprites import Block, Tetromino
|
||||
from game.timer import Timer, Timers
|
||||
|
||||
from .base import BaseScreen, SceenElement
|
||||
@ -91,31 +90,61 @@ class Tetris(BaseScreen):
|
||||
self._handle_down_key(keys)
|
||||
self._handle_drop_key(keys)
|
||||
|
||||
def move_down(self) -> None:
|
||||
"""Move the current tetromino down."""
|
||||
self.tetromino.move_down()
|
||||
def move_down(self) -> bool:
|
||||
"""
|
||||
Move the current tetromino down.
|
||||
|
||||
def move_left(self) -> None:
|
||||
"""Move the current tetromino to the left."""
|
||||
self.tetromino.move_horizontal(Direction.LEFT)
|
||||
Returns:
|
||||
True if the movement was successful, False otherwise.
|
||||
"""
|
||||
return self.tetromino.move_down()
|
||||
|
||||
def move_right(self) -> None:
|
||||
"""Move the current tetromino to the right."""
|
||||
self.tetromino.move_horizontal(Direction.RIGHT)
|
||||
def move_left(self) -> bool:
|
||||
"""
|
||||
Move the current tetromino to the left.
|
||||
|
||||
def rotate(self) -> None:
|
||||
"""Rotate the current tetromino clockwise."""
|
||||
self.tetromino.rotate()
|
||||
Returns:
|
||||
True if the movement was successful, False otherwise.
|
||||
"""
|
||||
return self.tetromino.move_horizontal(Direction.LEFT)
|
||||
|
||||
def rotate_reverse(self) -> None:
|
||||
"""Rotate the current tetromino counter-clockwise."""
|
||||
self.tetromino.rotate(Rotation.COUNTER_CLOCKWISE)
|
||||
def move_right(self) -> bool:
|
||||
"""
|
||||
Move the current tetromino to the right.
|
||||
|
||||
def drop(self) -> None:
|
||||
"""Drop the current tetromino."""
|
||||
self.tetromino.drop()
|
||||
Returns:
|
||||
True if the movement was successful, False otherwise.
|
||||
"""
|
||||
return self.tetromino.move_horizontal(Direction.RIGHT)
|
||||
|
||||
def create_new_tetromino(self) -> None:
|
||||
def rotate(self) -> bool:
|
||||
"""
|
||||
Rotate the current tetromino clockwise.
|
||||
|
||||
Returns:
|
||||
True if the rotation was successful, False otherwise.
|
||||
"""
|
||||
return self.tetromino.rotate()
|
||||
|
||||
def rotate_reverse(self) -> bool:
|
||||
"""
|
||||
Rotate the current tetromino counter-clockwise.
|
||||
|
||||
Returns:
|
||||
True if the rotation was successful, False otherwise.
|
||||
"""
|
||||
return self.tetromino.rotate(Rotation.COUNTER_CLOCKWISE)
|
||||
|
||||
def drop(self) -> bool:
|
||||
"""
|
||||
Drop the current tetromino.
|
||||
|
||||
Returns:
|
||||
True if the movement was successful, False otherwise.
|
||||
"""
|
||||
return self.tetromino.drop()
|
||||
|
||||
def create_new_tetromino(self, shape: Optional[Figure] = None) -> Tetromino:
|
||||
"""Create a new tetromino and perform necessary actions."""
|
||||
self._play_landing_sound()
|
||||
self._check_finished_rows()
|
||||
@ -128,9 +157,11 @@ class Tetris(BaseScreen):
|
||||
self.sprites,
|
||||
self.create_new_tetromino,
|
||||
self.field,
|
||||
self.get_next_figure(),
|
||||
shape or self.get_next_figure(),
|
||||
)
|
||||
|
||||
return self.tetromino
|
||||
|
||||
def _check_game_over(self) -> bool:
|
||||
"""
|
||||
Check if the game is over.
|
||||
|
||||
@ -31,7 +31,7 @@ class Tetromino:
|
||||
def __init__(
|
||||
self,
|
||||
group: pygame.sprite.Group,
|
||||
create_new: Callable[[], None],
|
||||
create_new: Callable[[Optional[Figure]], "Tetromino"],
|
||||
field: np.ndarray[Optional[Block], Any],
|
||||
shape: Optional[Figure] = None,
|
||||
) -> None:
|
||||
@ -42,32 +42,44 @@ class Tetromino:
|
||||
self.field = field
|
||||
self.blocks = self._initialize_blocks(group)
|
||||
|
||||
def move_down(self) -> None:
|
||||
def move_down(self) -> bool:
|
||||
"""
|
||||
Moves the Tetromino down.
|
||||
|
||||
If there is a collision, the Tetromino is placed on the field, and a new one is created.
|
||||
|
||||
Returns:
|
||||
True if the movement was successful, False otherwise.
|
||||
"""
|
||||
if not self._check_horizontal_collision(self.blocks, Direction.DOWN):
|
||||
for block in self.blocks:
|
||||
block.pos.y += 1
|
||||
else:
|
||||
return True
|
||||
|
||||
for block in self.blocks:
|
||||
self.field[int(block.pos.y), int(block.pos.x)] = block
|
||||
self.create_new()
|
||||
|
||||
def move_horizontal(self, direction: Direction) -> None:
|
||||
self.create_new(None)
|
||||
|
||||
return False
|
||||
|
||||
def move_horizontal(self, direction: Direction) -> bool:
|
||||
"""
|
||||
Moves the Tetromino horizontally.
|
||||
|
||||
Args:
|
||||
direction: Direction to move (LEFT or RIGHT).
|
||||
|
||||
Returns:
|
||||
True if the movement was successful, False otherwise.
|
||||
"""
|
||||
if not self._check_vertical_collision(self.blocks, direction):
|
||||
for block in self.blocks:
|
||||
block.pos.x += direction.value
|
||||
return True
|
||||
return False
|
||||
|
||||
def rotate(self, rotation: Rotation = Rotation.CLOCKWISE) -> None:
|
||||
def rotate(self, rotation: Rotation = Rotation.CLOCKWISE) -> bool:
|
||||
"""
|
||||
Rotates the Tetromino.
|
||||
|
||||
@ -75,9 +87,12 @@ class Tetromino:
|
||||
|
||||
Args:
|
||||
rotation: Rotation to perform (CLOCKWISE or COUNTER_CLOCKWISE).
|
||||
|
||||
Returns:
|
||||
True if the rotation was successful, False otherwise.
|
||||
"""
|
||||
if self.figure == Figure.O:
|
||||
return
|
||||
return False
|
||||
|
||||
pivot: pygame.Vector2 = self.blocks[0].pos
|
||||
|
||||
@ -88,19 +103,48 @@ class Tetromino:
|
||||
|
||||
if self._are_new_positions_valid(new_positions):
|
||||
self._update_block_positions(new_positions)
|
||||
return
|
||||
return True
|
||||
|
||||
if any(pos.x < 0 for pos in new_positions):
|
||||
self.move_horizontal(Direction.RIGHT)
|
||||
else:
|
||||
self.move_horizontal(Direction.LEFT)
|
||||
|
||||
def drop(self) -> None:
|
||||
"""Drops the Tetromino to the bottom of the game field."""
|
||||
return False
|
||||
|
||||
def next_rotation(self) -> "Tetromino":
|
||||
self.rotate()
|
||||
return self
|
||||
|
||||
def drop(self) -> bool:
|
||||
"""
|
||||
Drops the Tetromino to the bottom of the game field.
|
||||
|
||||
Returns:
|
||||
True if the drop was successful, False otherwise.
|
||||
"""
|
||||
|
||||
while not self._check_horizontal_collision(self.blocks, Direction.DOWN):
|
||||
for block in self.blocks:
|
||||
block.pos.y += 1
|
||||
|
||||
return True
|
||||
|
||||
def check_collision(self, direction: Direction) -> bool:
|
||||
"""
|
||||
Checks if there is a collision in the given direction.
|
||||
|
||||
Args:
|
||||
direction: Direction to check (UP, DOWN, LEFT, or RIGHT).
|
||||
|
||||
Returns:
|
||||
True if there is a collision, False otherwise.
|
||||
"""
|
||||
|
||||
return self._check_horizontal_collision(
|
||||
self.blocks, direction
|
||||
) or self._check_vertical_collision(self.blocks, direction)
|
||||
|
||||
def _check_vertical_collision(
|
||||
self, blocks: list[Block], direction: Direction
|
||||
) -> bool:
|
||||
|
||||
@ -3,7 +3,8 @@ from .enum import Direction, GameMode, Rotation
|
||||
from .figure import Figure, FigureConfig
|
||||
from .log import log
|
||||
from .path import BASE_PATH
|
||||
from .size import Size
|
||||
from .tuples import BestMove, Size
|
||||
from .weights import Weights
|
||||
|
||||
__all__ = [
|
||||
"BASE_PATH",
|
||||
@ -15,4 +16,5 @@ __all__ = [
|
||||
"Direction",
|
||||
"Rotation",
|
||||
"GameMode",
|
||||
"Weights",
|
||||
]
|
||||
|
||||
@ -5,7 +5,7 @@ from pygame import Vector2 as Vec2
|
||||
|
||||
from .colors import TokyoNightNight
|
||||
from .path import BASE_PATH
|
||||
from .size import Size
|
||||
from .tuples import Size
|
||||
|
||||
PADDING = 20
|
||||
|
||||
|
||||
@ -99,4 +99,4 @@ class Figure(Enum):
|
||||
|
||||
@classmethod
|
||||
def random(cls) -> "Figure":
|
||||
return random.choice(list(Figure))
|
||||
return random.choice(list(cls))
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
from typing import NamedTuple, Union
|
||||
|
||||
from .enum import Direction
|
||||
|
||||
|
||||
class Size(NamedTuple):
|
||||
width: int | float
|
||||
@ -9,3 +11,8 @@ class Size(NamedTuple):
|
||||
if isinstance(other, Size):
|
||||
return Size(self.width - other.width, self.height - other.height)
|
||||
return Size(self.width - other, self.height - other)
|
||||
|
||||
|
||||
class BestMove(NamedTuple):
|
||||
rotation: int
|
||||
direction: Direction
|
||||
9
src/utils/weights.py
Normal file
9
src/utils/weights.py
Normal file
@ -0,0 +1,9 @@
|
||||
from attrs import define
|
||||
|
||||
|
||||
@define
|
||||
class Weights:
|
||||
height: float
|
||||
lines: float
|
||||
holes: float
|
||||
bumpiness: float
|
||||
@ -2,7 +2,7 @@ import unittest
|
||||
|
||||
import numpy as np
|
||||
from ai.fitness.bumpiness import get_bumpiness
|
||||
from ai.fitness.holes import get_holes
|
||||
from ai.fitness.holes import holes
|
||||
from ai.fitness.peaks import get_peaks_sum
|
||||
from ai.fitness.transitions import (
|
||||
get_col_transition,
|
||||
@ -58,7 +58,7 @@ class TestFitness(unittest.TestCase):
|
||||
np.array([0, 1, 0, 0, 0]),
|
||||
)
|
||||
for field, answer in zip(self.fields, answers):
|
||||
self.assertTrue(np.array_equal(get_holes(field), answer))
|
||||
self.assertTrue(np.array_equal(holes(field), answer))
|
||||
|
||||
def test_get_wells(self) -> None:
|
||||
answers = (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user