Skip to content

Commit 11b180e

Browse files
author
Sofia "dzshn" N. L
committed
refactor: miscellaneous API changes (non-breaking)
- include the types submodule, MinoType and MoveKind to __all__ - create MinoType enum; includes EMPTY, GARBAGE and GHOST minos - allow BaseGame to be initialised with a seed, board (or board size), level and score - add height and width properties to BaseGame - update render to use the board height by default
1 parent 6ada2e6 commit 11b180e

File tree

4 files changed

+75
-21
lines changed

4 files changed

+75
-21
lines changed

tetris/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
from tetris import engine
2+
from tetris import types
23
from tetris.engine import DefaultEngine
34
from tetris.engine import Engine
45
from tetris.game import BaseGame
6+
from tetris.types import MinoType
57
from tetris.types import Move
68
from tetris.types import MoveDelta
9+
from tetris.types import MoveKind
710
from tetris.types import PartialMove
811
from tetris.types import Piece
912
from tetris.types import PieceType
1013
from tetris.types import PlayingStatus
1114

1215
__version__ = "0.4.0"
1316
__all__ = (
14-
"engine",
17+
"BaseGame",
1518
"DefaultEngine",
19+
"engine",
1620
"Engine",
17-
"BaseGame",
21+
"MinoType",
1822
"Move",
1923
"MoveDelta",
24+
"MoveKind",
2025
"PartialMove",
2126
"Piece",
2227
"PieceType",
2328
"PlayingStatus",
29+
"types",
2430
)

tetris/engine/scorer.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,11 @@
77
class GuidelineScorer(Scorer):
88
def __init__(self): # type: ignore[no-untyped-def]
99
self.score = 0
10+
self.level = 0
1011
self.line_clears = 0
1112
self.combo = 0
1213
self.back_to_back = 0
1314

14-
@property
15-
def level(self) -> int:
16-
return self.line_clears // 10 + 1
17-
1815
def judge(self, delta: MoveDelta) -> None:
1916
if delta.kind == MoveKind.soft_drop:
2017
if not delta.auto:
@@ -95,6 +92,8 @@ def judge(self, delta: MoveDelta) -> None:
9592

9693
self.score += score
9794
self.line_clears += line_clears
95+
if line_clears and self.line_clears % 10 == 0:
96+
self.level += 1
9897

9998

10099
class NoScorer(Scorer):

tetris/game.py

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,57 @@
77

88
from tetris.engine import DefaultEngine
99
from tetris.engine import Engine
10+
from tetris.types import Board
11+
from tetris.types import MinoType
1012
from tetris.types import Move
1113
from tetris.types import MoveDelta
1214
from tetris.types import MoveKind
1315
from tetris.types import PartialMove
1416
from tetris.types import PieceType
1517
from tetris.types import PlayingStatus
18+
from tetris.types import Seed
1619

1720
_default_tiles = {
18-
0: " ",
19-
PieceType.I: "I",
20-
PieceType.J: "J",
21-
PieceType.L: "L",
22-
PieceType.O: "O",
23-
PieceType.S: "S",
24-
PieceType.T: "T",
25-
PieceType.Z: "Z",
26-
8: "@",
27-
9: "X",
21+
MinoType.EMPTY: " ",
22+
MinoType.I: "I",
23+
MinoType.J: "J",
24+
MinoType.L: "L",
25+
MinoType.O: "O",
26+
MinoType.S: "S",
27+
MinoType.T: "T",
28+
MinoType.Z: "Z",
29+
MinoType.GHOST: "@",
30+
MinoType.GARBAGE: "X",
2831
}
2932

3033

3134
class BaseGame:
32-
def __init__(self, engine: Engine = DefaultEngine):
35+
def __init__(
36+
self,
37+
engine: Engine = DefaultEngine,
38+
seed: Optional[Seed] = None,
39+
board: Optional[Board] = None,
40+
board_size: tuple[int, int] = (20, 10),
41+
level: int = 0,
42+
score: int = 0,
43+
):
3344
self.engine = engine
3445
self.seed = secrets.token_bytes()
35-
self.board = np.zeros((40, 10), dtype=np.int8)
46+
if board is None:
47+
# Internally, we use 2x the height to "buffer" the board being pushed above the view
48+
self.board = np.zeros((board_size[0] * 2, board_size[1]), dtype=np.int8)
49+
50+
else:
51+
self.board = board
52+
3653
self.gravity = engine.gravity(self)
3754
self.queue = engine.queue(seed=self.seed)
3855
self.rs = engine.rs(self.board)
56+
3957
self.scorer = engine.scorer()
58+
self.scorer.level = level
59+
self.scorer.score = score
60+
4061
self.piece = self.rs.spawn(self.queue.pop())
4162
self.status = PlayingStatus.playing
4263
self.delta: Optional[MoveDelta] = None
@@ -51,9 +72,17 @@ def score(self) -> int:
5172
def level(self) -> int:
5273
return self.scorer.level
5374

75+
@property
76+
def height(self) -> int:
77+
return self.board.shape[0] // 2
78+
79+
@property
80+
def width(self) -> int:
81+
return self.board.shape[1]
82+
5483
def reset(self) -> None:
5584
self.seed = secrets.token_bytes()
56-
self.board = np.zeros((40, 10), dtype=np.int8)
85+
self.board[:] = 0
5786
self.gravity = self.engine.gravity(self)
5887
self.queue = self.engine.queue(seed=self.seed)
5988
self.rs = self.engine.rs(self.board)
@@ -101,7 +130,7 @@ def _lock_piece(self) -> None:
101130

102131
# If all tiles are out of view (half of the internal size), it's a lock-out
103132
for x, y in piece.minos:
104-
if self.piece.x + x > self.board.shape[0] / 2:
133+
if self.piece.x + x > self.height:
105134
break
106135

107136
else:
@@ -121,7 +150,14 @@ def _lock_piece(self) -> None:
121150

122151
self.hold_lock = False
123152

124-
def render(self, tiles: dict[int, str] = _default_tiles, lines: int = 20) -> str:
153+
def render(
154+
self,
155+
tiles: dict[MinoType, str] = _default_tiles,
156+
lines: Optional[int] = None,
157+
) -> str:
158+
if lines is None:
159+
lines = self.height
160+
125161
board = self.board.copy()
126162
piece = self.piece
127163
ghost_x = piece.x

tetris/types.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ def __repr__(self) -> str:
3232
return f"{self.__class__.__name__}.{self.name}"
3333

3434

35+
class MinoType(enum.IntEnum):
36+
EMPTY = 0
37+
I = enum.auto() # noqa
38+
J = enum.auto()
39+
L = enum.auto()
40+
O = enum.auto() # noqa
41+
S = enum.auto()
42+
T = enum.auto()
43+
Z = enum.auto()
44+
GHOST = enum.auto()
45+
GARBAGE = enum.auto()
46+
47+
3548
@dataclasses.dataclass
3649
class Piece:
3750
__slots__ = ("type", "x", "y", "r", "minos")

0 commit comments

Comments
 (0)