diff --git a/pyproject.toml b/pyproject.toml index c671c6b..a1944b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "scrap_engine" authors = [{ name = "lxgr", email = "lxgr@protonmail.com" }] description = "A 2D ascii game engine for the terminal" keywords = ["game", "Ascii"] -version = "1.5.4" +version = "1.5.4-rc1" license = { text = "GPL-3.0-only" } readme = "README.md" requires-python = ">=3.12" @@ -21,6 +21,16 @@ Homepage = "https://github.com/lxgr-linux/scrap_engine" Issues = "https://github.com/lxgr-linux/scrap_engine/issue" Repository = "https://github.com/lxgr-linux/scrap_engine.git" +[tool.basedpyright] +reportMissingTypeStubs = false +reportUnknownMemberType = false +reportUnannotatedClassAttribute = false +deprecateTypingAliases = false +reportImplicitStringConcatenation = false +executionEnvironments = [ + { root = "src" }, +] + [tool.ruff] line-length = 88 target-version = "py312" diff --git a/src/scrap_engine/addable/misc/box.py b/src/scrap_engine/addable/misc/box.py index fd742be..17178db 100644 --- a/src/scrap_engine/addable/misc/box.py +++ b/src/scrap_engine/addable/misc/box.py @@ -1,7 +1,10 @@ +from typing import override + from scrap_engine.addable.addable import Addable from scrap_engine.addable.area import HasArea from scrap_engine.addable.object_group import ObjectGroup from scrap_engine.addable.state import DEFAULT_STATE +from scrap_engine.map import Map class Box(ObjectGroup[Addable], HasArea): @@ -16,14 +19,17 @@ def __init__(self, height: int, width: int): self.__width: int = width @property + @override def height(self) -> int: return self.__height @property + @override def width(self) -> int: return self.__width - def add(self, _map, x: int, y: int): + @override + def add(self, _map: Map, x: int, y: int): """ Adds the box to a certain coordinate on a certain map. """ @@ -34,6 +40,7 @@ def add(self, _map, x: int, y: int): obj.add(self.map, obj.rx + self.x, obj.ry + self.y) self.added = True + @override def add_ob(self, obj: Addable, x: int, y: int): """ Adds an object(group) to a certain coordinate relative to the box. @@ -56,6 +63,7 @@ def set_ob(self, obj: Addable, x: int, y: int): if self.added: obj.set(obj.rx + self.x, obj.ry + self.y) + @override def remove(self): """ Removes the box from the map. diff --git a/src/scrap_engine/addable/misc/circle.py b/src/scrap_engine/addable/misc/circle.py index f84ebf5..844ca27 100644 --- a/src/scrap_engine/addable/misc/circle.py +++ b/src/scrap_engine/addable/misc/circle.py @@ -1,9 +1,9 @@ import math -from typing import Type +from typing import Type, override from scrap_engine.addable.state import DEFAULT_STATE, State -from ..object import Object +from ..object import ArgProto, Object from .box import Box @@ -18,18 +18,18 @@ def __init__( radius: int, state: State = DEFAULT_STATE, ob_class: Type[Object] = Object, - ob_args=None, + ob_args: ArgProto = None, ): super().__init__(0, 0) if ob_args is None: ob_args = {} - self.char = char + self.char: str = char self.ob_class = ob_class self.ob_args = ob_args self.state = state self.__gen(radius) - def __gen(self, radius): + def __gen(self, radius: int): self.radius = radius for i in range(-(int(radius) + 1), int(radius + 1) + 1): for j in range(-(int(radius) + 1), int(radius + 1) + 1): @@ -42,7 +42,7 @@ def __gen(self, radius): j, ) - def rechar(self, char): + def rechar(self, char: str): """ Changes the chars the circle is filled with. """ @@ -50,7 +50,8 @@ def rechar(self, char): for obj in self.obs: obj.rechar(char) - def resize(self, radius): + @override + def resize(self, radius: int): """ Resizes the circle. """ diff --git a/src/scrap_engine/addable/misc/frame.py b/src/scrap_engine/addable/misc/frame.py index 8e9dace..4e6f05e 100644 --- a/src/scrap_engine/addable/misc/frame.py +++ b/src/scrap_engine/addable/misc/frame.py @@ -1,8 +1,8 @@ -from typing import Optional, Type +from typing import Optional, Type, override from scrap_engine.addable.state import DEFAULT_STATE, State -from ..object import Object +from ..object import ArgProto, Object from .box import Box from .square import Square @@ -28,7 +28,7 @@ def __init__( vertical_chars: Optional[list[str]] = None, state: State = DEFAULT_STATE, ob_class: Type[Object] = Object, - ob_args=None, + ob_args: ArgProto = None, ): super().__init__(height, width) if ob_args is None: @@ -83,13 +83,16 @@ def __gen_obs(self): ob_class=Object, ob_args=self.ob_args, ) - for i, j in zip(self.vertical_chars, range(2)) + for i, _ in zip(self.vertical_chars, range(2)) ] for obj, rx, ry in zip(self.verticals, [0, self.width - 1], [1, 1]): self.add_ob(obj, rx, ry) def rechar( - self, corner_chars=None, horizontal_chars=None, vertical_chars=None + self, + corner_chars: Optional[list[str]] = None, + horizontal_chars: Optional[list[str]] = None, + vertical_chars: Optional[list[str]] = None, ): """ Rechars the frame. @@ -108,7 +111,8 @@ def rechar( for obj, _c in zip(self.verticals, self.vertical_chars): obj.rechar(_c) - def resize(self, height, width): + @override + def resize(self, height: int, width: int): """ Changes the frames size. """ diff --git a/src/scrap_engine/addable/misc/line.py b/src/scrap_engine/addable/misc/line.py index 89891e6..c03f660 100644 --- a/src/scrap_engine/addable/misc/line.py +++ b/src/scrap_engine/addable/misc/line.py @@ -3,7 +3,7 @@ from scrap_engine.addable.state import DEFAULT_STATE, State -from ..object import Object +from ..object import ArgProto, Object from .box import Box LineType = Literal["straight", "crippled"] @@ -22,7 +22,7 @@ def __init__( l_type: LineType = "straight", state: State = DEFAULT_STATE, ob_class: Type[Object] = Object, - ob_args=None, + ob_args: ArgProto = None, ): super().__init__(0, 0) if ob_args is None: diff --git a/src/scrap_engine/addable/misc/square.py b/src/scrap_engine/addable/misc/square.py index cc9ef86..6e4c293 100644 --- a/src/scrap_engine/addable/misc/square.py +++ b/src/scrap_engine/addable/misc/square.py @@ -2,7 +2,7 @@ from scrap_engine.addable.state import DEFAULT_STATE, State -from ..object import Object +from ..object import ArgProto, Object from .box import Box @@ -13,12 +13,12 @@ class Square(Box): def __init__( self, - char, - width, - height, + char: str, + width: int, + height: int, state: State = DEFAULT_STATE, ob_class: Type[Object] = Object, - ob_args=None, + ob_args: ArgProto = None, ): super().__init__(height, width) if ob_args is None: @@ -34,9 +34,7 @@ def __create(self): for ry in range(self.height): for rx in range(self.width): self.add_ob( - self.ob_class( - self.char, self.state, arg_proto=self.ob_args - ), + self.ob_class(self.char, self.state, arg_proto=self.ob_args), rx, ry, ) diff --git a/src/scrap_engine/addable/misc/text.py b/src/scrap_engine/addable/misc/text.py index 9e9e25b..435d93b 100644 --- a/src/scrap_engine/addable/misc/text.py +++ b/src/scrap_engine/addable/misc/text.py @@ -1,15 +1,16 @@ -from typing import Generic, TypeVar +from typing import Any, Generic, TypeVar, override from scrap_engine.addable.area import HasArea from scrap_engine.addable.state import DEFAULT_STATE, State +from scrap_engine.map import Map -from ..object import Object +from ..object import ArgProto, Object from ..object_group import ObjectGroup T = TypeVar("T", bound=Object) -class Text(HasArea, ObjectGroup[T], Generic[T]): +class Text(ObjectGroup[T], HasArea, Generic[T]): """ A datatype containing a string, that can be added to a map. Different Texts can be added together with the '+' operator. @@ -17,12 +18,12 @@ class Text(HasArea, ObjectGroup[T], Generic[T]): def __init__( self, - text, + text: str, state: State = DEFAULT_STATE, - esccode="", + esccode: str = "", ob_class: type[T] = Object, - ob_args=None, - ignore="", + ob_args: ArgProto = None, + ignore: str = "", ): super().__init__([], state) if ob_args is None: @@ -35,6 +36,7 @@ def __init__( self.__texter(text) @property + @override def width(self) -> int: """ The Texts peak width @@ -42,13 +44,14 @@ def width(self) -> int: return sorted(len(i) for i in self.text.split("\n"))[-1] @property + @override def height(self) -> int: """ The Texts height """ return len(self.text.split("\n")) - def __add__(self, other): + def __add__(self, other: "Text[Any]"): self.text += other.text self.obs += other.obs for obj in self.obs: @@ -58,7 +61,7 @@ def __add__(self, other): self.add(self.map, self.x, self.y) return self - def __texter(self, text): + def __texter(self, text: str): for txt in text.split("\n"): for char in txt: if self.esccode != "": @@ -69,7 +72,8 @@ def __texter(self, text): for obj in self.obs: obj.group = self - def add(self, _map, x, y): + @override + def add(self, _map: Map, x: int, y: int): """ Adds the text to a certain coordinate on a certain map. """ @@ -84,6 +88,7 @@ def add(self, _map, x, y): obj.add(self.map, x + i, y + line) count += len(text) + @override def remove(self): """ Removes the text from the map. @@ -92,6 +97,7 @@ def remove(self): for obj in self.obs: obj.remove() + @override def rem_ob(self, obj: T): """ Removes an object from the group. @@ -112,7 +118,7 @@ def rem_ob(self, obj: T): return 0 return 1 - def rechar(self, text: str, esccode=""): + def rechar(self, text: str, esccode: str = ""): """ Changes the string contained in the text. """ diff --git a/src/scrap_engine/addable/object.py b/src/scrap_engine/addable/object.py index 3b76f70..ee55210 100644 --- a/src/scrap_engine/addable/object.py +++ b/src/scrap_engine/addable/object.py @@ -1,16 +1,25 @@ +from typing import Any, Literal, Optional, override + from ..error import CoordinateError from ..map.map import Map from .addable import Addable from .area import HasArea from .state import DEFAULT_STATE, State +type ArgProto = Optional[dict[str, Any]] # pyright: ignore[reportExplicitAny] + -class Object(HasArea, Addable): +class Object(Addable, HasArea): """ An object, containing a character, that can be added to a map. """ - def __init__(self, char: str, state: State = DEFAULT_STATE, arg_proto=None): + def __init__( + self, + char: str, + state: State = DEFAULT_STATE, + arg_proto: ArgProto = None, + ): if arg_proto is None: arg_proto = {} super().__init__(state) @@ -18,6 +27,7 @@ def __init__(self, char: str, state: State = DEFAULT_STATE, arg_proto=None): self.arg_proto = arg_proto self.backup = None + @override def add(self, _map: Map, x: int, y: int): """ Adds the object to a certain coordinate on a certain map. @@ -36,6 +46,7 @@ def add(self, _map: Map, x: int, y: int): self.added = True return 0 + @override def set(self, x: int, y: int): """ Sets the object to a certain coordinate. @@ -63,7 +74,7 @@ def set(self, x: int, y: int): obj.action(self) return 0 - def redraw(self): + def redraw(self) -> Literal[0, 1]: """ Redraws the object on the map. """ @@ -91,9 +102,7 @@ def __backup_setter(self): ].backup = self.backup else: self.map.map[self.y][self.x] = self.backup - del self.map.obmap[self.y][self.x][ - self.map.obmap[self.y][self.x].index(self) - ] + del self.map.obmap[self.y][self.x][self.map.obmap[self.y][self.x].index(self)] def action(self, ob): """ @@ -118,7 +127,7 @@ def pull_ob(self): """ return - def rechar(self, char): + def rechar(self, char: str): """ Changes the objects character. """ @@ -129,6 +138,7 @@ def rechar(self, char): self.redraw() return 0 + @override def remove(self): """ Removes the object from the map. diff --git a/src/scrap_engine/error.py b/src/scrap_engine/error.py index 449d01c..47ebb00 100644 --- a/src/scrap_engine/error.py +++ b/src/scrap_engine/error.py @@ -1,10 +1,14 @@ +from scrap_engine.addable import Addable +from scrap_engine.map import Map + + class CoordinateError(Exception): """ An Error that is thrown, when an object is added to a non-existing part of a map. """ - def __init__(self, obj, _map, x, y): + def __init__(self, obj: Addable, _map: Map, x: int, y: int): self.ob = obj self.x = x self.y = y diff --git a/src/scrap_engine/interfaces/__init__.py b/src/scrap_engine/interfaces/__init__.py new file mode 100644 index 0000000..b42163e --- /dev/null +++ b/src/scrap_engine/interfaces/__init__.py @@ -0,0 +1,28 @@ +from typing import Literal, Protocol + +from scrap_engine.addable.state import State + + +class IObject(Protocol): + x: int + y: int + state: State + + def redraw(self) -> Literal[0, 1]: ... + + +class IMap(Protocol): + def show(self, init: bool = False): ... + + def blur_in( + self, + blurmap: "IMap", + esccode: str = "\033[37m", + ): ... + + def resize( + self, + height: int, + width: int, + background: str = "#", + ): ... diff --git a/src/scrap_engine/map/map.py b/src/scrap_engine/map/map.py index 518a42d..ae80d1d 100644 --- a/src/scrap_engine/map/map.py +++ b/src/scrap_engine/map/map.py @@ -1,4 +1,7 @@ import functools +from typing import Callable + +from scrap_engine.interfaces import IObject from ..consts import MAXCACHE_FRAME, MAXCACHE_LINE, screen_height, screen_width @@ -10,23 +13,25 @@ class Map: def __init__( self, - height=screen_height - 1, - width=screen_width, - background="#", - dynfps=True, + height: int = screen_height - 1, + width: int = screen_width, + background: str = "#", + dynfps: bool = True, ): - self.height = height - self.width = width - self.dynfps = dynfps - self.background = background - self.map = [ + self.height: int = height + self.width: int = width + self.dynfps: bool = dynfps + self.background: str = background + self.map: list[list[str]] = [ [self.background for _ in range(width)] for _ in range(height) ] - self.obmap = [[[] for _ in range(width)] for _ in range(height)] - self.obs = [] - self.out_old = "" + self.obmap: list[list[list[IObject]]] = [ + [[] for _ in range(width)] for _ in range(height) + ] + self.obs: list[IObject] = [] + self.out_old: str = "" - def blur_in(self, blurmap, esccode="\033[37m"): + def blur_in(self, blurmap: "Map", esccode: str = "\033[37m"): """ Sets another maps content as its background. """ @@ -43,7 +48,7 @@ def blur_in(self, blurmap, esccode="\033[37m"): for obj in self.obs: obj.redraw() - def show(self, init=False): + def show(self, init: bool = False): """ Prints the maps content. """ @@ -55,7 +60,7 @@ def show(self, init=False): @staticmethod @functools.lru_cache(MAXCACHE_FRAME) - def __show_map(show_line, _map): + def __show_map(show_line: Callable[[tuple[str]], str], _map: tuple[tuple[str]]): out = "\033[H" for arr in _map: out += show_line(arr) @@ -63,20 +68,18 @@ def __show_map(show_line, _map): @staticmethod @functools.lru_cache(MAXCACHE_LINE) - def __show_line(arr): + def __show_line(arr: tuple[str]) -> str: out_line = "" for char in arr: out_line += char return out_line - def resize(self, height, width, background="#"): + def resize(self, height: int, width: int, background: str = "#"): """ Resizes the map to a certain size. """ self.background = background - self.map = [ - [self.background for _ in range(width)] for _ in range(height) - ] + self.map = [[self.background for _ in range(width)] for _ in range(height)] self.obmap = [ [[] for _ in range(max(width, self.width))] for _ in range(max(height, self.height)) diff --git a/src/scrap_engine/map/submap.py b/src/scrap_engine/map/submap.py index 7bcfb0e..ec625f5 100644 --- a/src/scrap_engine/map/submap.py +++ b/src/scrap_engine/map/submap.py @@ -11,18 +11,18 @@ class Submap(Map): def __init__( self, - bmap, - x, - y, - height=screen_height - 1, - width=screen_width, - dynfps=True, + bmap: Map, + x: int, + y: int, + height: int = screen_height - 1, + width: int = screen_width, + dynfps: bool = True, ): super().__init__(height, width, dynfps=dynfps) del self.background - self.y = y - self.x = x - self.bmap = bmap + self.y: int = y + self.x: int = x + self.bmap: Map = bmap self.remap() def remap(self): @@ -59,7 +59,7 @@ def __map_to_parent(height, width, _y, _x, parent, child): def __full_bg(background, width, height): return [[background for _ in range(width)] for _ in range(height)] - def set(self, x, y): + def set(self, x: int, y: int): """ Changes the coordinates on the map, the submap is at. """ @@ -70,7 +70,7 @@ def set(self, x, y): self.remap() return 0 - def full_show(self, init=False): + def full_show(self, init: bool = False): """ Combines remap() and show(). """