code clean
This commit is contained in:
parent
3223521d67
commit
a0715f5be0
@ -13,7 +13,7 @@ python -m pip install --user arcade
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
from tetris import Tetris, Status, Scheduler
|
from tetris import Tetris, Status, AbstractScheduler
|
||||||
|
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
@ -99,7 +99,7 @@ GHOST_ALPHA = 50
|
|||||||
MATRIX_SRITE_ALPHA = 100
|
MATRIX_SRITE_ALPHA = 100
|
||||||
|
|
||||||
|
|
||||||
class ArcadeScheduler(Scheduler):
|
class ArcadeScheduler(AbstractScheduler):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._tasks = {}
|
self._tasks = {}
|
||||||
@ -232,9 +232,8 @@ class TetrArcade(Tetris, arcade.Window):
|
|||||||
self.remove_action(action)
|
self.remove_action(action)
|
||||||
|
|
||||||
def show_text(self, text):
|
def show_text(self, text):
|
||||||
self.scheduler.stop(self.del_highlight_text)
|
|
||||||
self.highlight_texts.append(text)
|
self.highlight_texts.append(text)
|
||||||
self.scheduler.start(self.del_highlight_text, HIGHLIGHT_TEXT_DISPLAY_DELAY)
|
self.scheduler.restart(self.del_highlight_text, HIGHLIGHT_TEXT_DISPLAY_DELAY)
|
||||||
|
|
||||||
def del_highlight_text(self):
|
def del_highlight_text(self):
|
||||||
if self.highlight_texts:
|
if self.highlight_texts:
|
||||||
|
173
tetris.py
173
tetris.py
@ -62,10 +62,23 @@ class T_Spin:
|
|||||||
T_SPIN = "T-SPIN"
|
T_SPIN = "T-SPIN"
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractScheduler:
|
||||||
|
|
||||||
|
def start(task, period):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def stop(self, task):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def restrart(self, task, period):
|
||||||
|
self.stop(task)
|
||||||
|
self.start(task, period)
|
||||||
|
|
||||||
|
|
||||||
class Tetromino:
|
class Tetromino:
|
||||||
|
|
||||||
|
|
||||||
class TetrominoBase:
|
class AbstractTetromino:
|
||||||
# Super rotation system
|
# Super rotation system
|
||||||
SRS = {
|
SRS = {
|
||||||
Rotation.COUNTERCLOCKWISE: (
|
Rotation.COUNTERCLOCKWISE: (
|
||||||
@ -96,7 +109,7 @@ class Tetromino:
|
|||||||
return self.__class__()
|
return self.__class__()
|
||||||
|
|
||||||
|
|
||||||
class O(TetrominoBase):
|
class O(AbstractTetromino):
|
||||||
|
|
||||||
SRS = {
|
SRS = {
|
||||||
Rotation.COUNTERCLOCKWISE: (tuple(), tuple(), tuple(), tuple()),
|
Rotation.COUNTERCLOCKWISE: (tuple(), tuple(), tuple(), tuple()),
|
||||||
@ -109,7 +122,7 @@ class Tetromino:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class I(TetrominoBase):
|
class I(AbstractTetromino):
|
||||||
|
|
||||||
SRS = {
|
SRS = {
|
||||||
Rotation.COUNTERCLOCKWISE: (
|
Rotation.COUNTERCLOCKWISE: (
|
||||||
@ -129,31 +142,31 @@ class Tetromino:
|
|||||||
MINOES_COLOR = "cyan"
|
MINOES_COLOR = "cyan"
|
||||||
|
|
||||||
|
|
||||||
class T(TetrominoBase):
|
class T(AbstractTetromino):
|
||||||
|
|
||||||
MINOES_POSITIONS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 0))
|
MINOES_POSITIONS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 0))
|
||||||
MINOES_COLOR = "magenta"
|
MINOES_COLOR = "magenta"
|
||||||
|
|
||||||
|
|
||||||
class L(TetrominoBase):
|
class L(AbstractTetromino):
|
||||||
|
|
||||||
MINOES_POSITIONS = (Coord(-1, 0), Coord(0, 0), Coord(1, 0), Coord(1, 1))
|
MINOES_POSITIONS = (Coord(-1, 0), Coord(0, 0), Coord(1, 0), Coord(1, 1))
|
||||||
MINOES_COLOR = "orange"
|
MINOES_COLOR = "orange"
|
||||||
|
|
||||||
|
|
||||||
class J(TetrominoBase):
|
class J(AbstractTetromino):
|
||||||
|
|
||||||
MINOES_POSITIONS = (Coord(-1, 1), Coord(-1, 0), Coord(0, 0), Coord(1, 0))
|
MINOES_POSITIONS = (Coord(-1, 1), Coord(-1, 0), Coord(0, 0), Coord(1, 0))
|
||||||
MINOES_COLOR = "blue"
|
MINOES_COLOR = "blue"
|
||||||
|
|
||||||
|
|
||||||
class S(TetrominoBase):
|
class S(AbstractTetromino):
|
||||||
|
|
||||||
MINOES_POSITIONS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 1))
|
MINOES_POSITIONS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 1))
|
||||||
MINOES_COLOR = "green"
|
MINOES_COLOR = "green"
|
||||||
|
|
||||||
|
|
||||||
class Z(TetrominoBase):
|
class Z(AbstractTetromino):
|
||||||
|
|
||||||
MINOES_POSITIONS = (Coord(-1, 1), Coord(0, 1), Coord(0, 0), Coord(1, 0))
|
MINOES_POSITIONS = (Coord(-1, 1), Coord(0, 1), Coord(0, 0), Coord(1, 0))
|
||||||
MINOES_COLOR = "red"
|
MINOES_COLOR = "red"
|
||||||
@ -169,15 +182,6 @@ class Tetromino:
|
|||||||
return cls.random_bag.pop()()
|
return cls.random_bag.pop()()
|
||||||
|
|
||||||
|
|
||||||
class Scheduler:
|
|
||||||
|
|
||||||
def start(task, period):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def stop(self, task):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
class Tetris():
|
class Tetris():
|
||||||
|
|
||||||
|
|
||||||
@ -189,7 +193,7 @@ class Tetris():
|
|||||||
{"name": "TRIPLE", T_Spin.NO_T_SPIN: 5, T_Spin.T_SPIN: 16},
|
{"name": "TRIPLE", T_Spin.NO_T_SPIN: 5, T_Spin.T_SPIN: 16},
|
||||||
{"name": "TETRIS", T_Spin.NO_T_SPIN: 8}
|
{"name": "TETRIS", T_Spin.NO_T_SPIN: 8}
|
||||||
)
|
)
|
||||||
scheduler = Scheduler()
|
scheduler = AbstractScheduler()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.high_score = 0
|
self.high_score = 0
|
||||||
@ -251,69 +255,12 @@ class Tetris():
|
|||||||
):
|
):
|
||||||
self.game_over()
|
self.game_over()
|
||||||
|
|
||||||
def cell_is_free(self, position):
|
|
||||||
return (
|
|
||||||
0 <= position.x < NB_COLS
|
|
||||||
and 0 <= position.y
|
|
||||||
and not self.matrix[position.y][position.x]
|
|
||||||
)
|
|
||||||
|
|
||||||
def can_move(self, potential_position, minoes_positions):
|
|
||||||
return all(
|
|
||||||
self.cell_is_free(potential_position+mino_position)
|
|
||||||
for mino_position in minoes_positions
|
|
||||||
)
|
|
||||||
|
|
||||||
def move(self, movement, prelock_on_stuck=True):
|
|
||||||
potential_position = self.current_piece.position + movement
|
|
||||||
if self.can_move(potential_position, self.current_piece.minoes_positions):
|
|
||||||
if self.current_piece.prelocked:
|
|
||||||
self.scheduler.stop(self.lock)
|
|
||||||
self.scheduler.start(self.lock, self.lock_delay)
|
|
||||||
self.current_piece.position = potential_position
|
|
||||||
self.current_piece.last_rotation_point_used = None
|
|
||||||
self.move_ghost()
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
if (
|
|
||||||
prelock_on_stuck and not self.current_piece.prelocked
|
|
||||||
and movement == Movement.DOWN
|
|
||||||
):
|
|
||||||
self.current_piece.prelocked = True
|
|
||||||
self.scheduler.start(self.lock, self.lock_delay)
|
|
||||||
return False
|
|
||||||
|
|
||||||
def move_left(self):
|
def move_left(self):
|
||||||
self.move(Movement.LEFT)
|
self.move(Movement.LEFT)
|
||||||
|
|
||||||
def move_right(self):
|
def move_right(self):
|
||||||
self.move(Movement.RIGHT)
|
self.move(Movement.RIGHT)
|
||||||
|
|
||||||
def rotate(self, direction):
|
|
||||||
rotated_minoes_positions = tuple(
|
|
||||||
Coord(-direction*mino_position.y, direction*mino_position.x)
|
|
||||||
for mino_position in self.current_piece.minoes_positions
|
|
||||||
)
|
|
||||||
for rotation_point, liberty_degree in enumerate(
|
|
||||||
self.current_piece.SRS[direction][self.current_piece.orientation],
|
|
||||||
start = 1
|
|
||||||
):
|
|
||||||
potential_position = self.current_piece.position + liberty_degree
|
|
||||||
if self.can_move(potential_position, rotated_minoes_positions):
|
|
||||||
if self.current_piece.prelocked:
|
|
||||||
self.scheduler.stop(self.lock)
|
|
||||||
self.scheduler.start(self.lock, self.lock_delay)
|
|
||||||
self.current_piece.position = potential_position
|
|
||||||
self.current_piece.minoes_positions = rotated_minoes_positions
|
|
||||||
self.current_piece.orientation = (
|
|
||||||
(self.current_piece.orientation + direction) % 4
|
|
||||||
)
|
|
||||||
self.current_piece.last_rotation_point_used = rotation_point
|
|
||||||
self.move_ghost()
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def rotate_counterclockwise(self):
|
def rotate_counterclockwise(self):
|
||||||
self.rotate(Rotation.COUNTERCLOCKWISE)
|
self.rotate(Rotation.COUNTERCLOCKWISE)
|
||||||
|
|
||||||
@ -329,16 +276,8 @@ class Tetris():
|
|||||||
):
|
):
|
||||||
self.ghost_piece.position += Movement.DOWN
|
self.ghost_piece.position += Movement.DOWN
|
||||||
|
|
||||||
def drop(self):
|
|
||||||
self.move(Movement.DOWN)
|
|
||||||
|
|
||||||
def add_to_score(self, ds):
|
|
||||||
self.score += ds
|
|
||||||
if self.score > self.high_score:
|
|
||||||
self.high_score = self.score
|
|
||||||
|
|
||||||
def soft_drop(self):
|
def soft_drop(self):
|
||||||
if self.move(Movement.DOWN):
|
if self.drop():
|
||||||
self.add_to_score(1)
|
self.add_to_score(1)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -349,6 +288,69 @@ class Tetris():
|
|||||||
self.add_to_score(2)
|
self.add_to_score(2)
|
||||||
self.lock()
|
self.lock()
|
||||||
|
|
||||||
|
def drop(self):
|
||||||
|
self.move(Movement.DOWN)
|
||||||
|
|
||||||
|
def move(self, movement, prelock_on_stuck=True):
|
||||||
|
potential_position = self.current_piece.position + movement
|
||||||
|
if self.can_move(potential_position, self.current_piece.minoes_positions):
|
||||||
|
if self.current_piece.prelocked:
|
||||||
|
self.scheduler.restart(self.lock, self.lock_delay)
|
||||||
|
self.current_piece.position = potential_position
|
||||||
|
self.current_piece.last_rotation_point_used = None
|
||||||
|
self.move_ghost()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
if (
|
||||||
|
prelock_on_stuck and not self.current_piece.prelocked
|
||||||
|
and movement == Movement.DOWN
|
||||||
|
):
|
||||||
|
self.current_piece.prelocked = True
|
||||||
|
self.scheduler.start(self.lock, self.lock_delay)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def rotate(self, direction):
|
||||||
|
rotated_minoes_positions = tuple(
|
||||||
|
Coord(-direction*mino_position.y, direction*mino_position.x)
|
||||||
|
for mino_position in self.current_piece.minoes_positions
|
||||||
|
)
|
||||||
|
for rotation_point, liberty_degree in enumerate(
|
||||||
|
self.current_piece.SRS[direction][self.current_piece.orientation],
|
||||||
|
start = 1
|
||||||
|
):
|
||||||
|
potential_position = self.current_piece.position + liberty_degree
|
||||||
|
if self.can_move(potential_position, rotated_minoes_positions):
|
||||||
|
if self.current_piece.prelocked:
|
||||||
|
self.scheduler.restart(self.lock, self.lock_delay)
|
||||||
|
self.current_piece.position = potential_position
|
||||||
|
self.current_piece.minoes_positions = rotated_minoes_positions
|
||||||
|
self.current_piece.orientation = (
|
||||||
|
(self.current_piece.orientation + direction) % 4
|
||||||
|
)
|
||||||
|
self.current_piece.last_rotation_point_used = rotation_point
|
||||||
|
self.move_ghost()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def can_move(self, potential_position, minoes_positions):
|
||||||
|
return all(
|
||||||
|
self.cell_is_free(potential_position+mino_position)
|
||||||
|
for mino_position in minoes_positions
|
||||||
|
)
|
||||||
|
|
||||||
|
def cell_is_free(self, position):
|
||||||
|
return (
|
||||||
|
0 <= position.x < NB_COLS
|
||||||
|
and 0 <= position.y
|
||||||
|
and not self.matrix[position.y][position.x]
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_to_score(self, ds):
|
||||||
|
self.score += ds
|
||||||
|
if self.score > self.high_score:
|
||||||
|
self.high_score = self.score
|
||||||
|
|
||||||
def lock(self):
|
def lock(self):
|
||||||
if self.move(Movement.DOWN):
|
if self.move(Movement.DOWN):
|
||||||
return
|
return
|
||||||
@ -493,8 +495,7 @@ class Tetris():
|
|||||||
self.pressed_actions[-1]()
|
self.pressed_actions[-1]()
|
||||||
if not self.auto_repeat:
|
if not self.auto_repeat:
|
||||||
self.auto_repeat = True
|
self.auto_repeat = True
|
||||||
self.scheduler.stop(self.repeat_action)
|
self.scheduler.restart(self.repeat_action, AUTOREPEAT_PERIOD)
|
||||||
self.scheduler.start(self.repeat_action, AUTOREPEAT_PERIOD)
|
|
||||||
else:
|
else:
|
||||||
self.stop_autorepeat()
|
self.stop_autorepeat()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user