]> Untitled Git - axy/ft/a-maze-ing.git/commitdiff
Prompt
authorAxy <gilliardmarthey.axel@gmail.com>
Thu, 26 Mar 2026 18:56:44 +0000 (19:56 +0100)
committerAxy <gilliardmarthey.axel@gmail.com>
Thu, 26 Mar 2026 18:56:44 +0000 (19:56 +0100)
amazeing/config/config_parser.py
amazeing/display/observer.py
amazeing/display/tty.py
example.conf

index 3bf152d462efc1a62df9cea1edb20f88d39a3b6e..2b9f4bf2049a1f7b799bbf732a4561c222756cb7 100644 (file)
@@ -236,6 +236,9 @@ def DefaultedField[T, U](
         def default(self) -> U:
             return default
 
+        def merge(self, vals: list[T]) -> U:
+            return cls.merge(self, vals) if len(vals) > 0 else self.default()
+
     return Inner
 
 
@@ -254,6 +257,9 @@ def DefaultedStrField[T, U](
                 acc.append(res[0])
             return self.merge(acc)  # type: ignore
 
+        def merge(self, vals: list[T]) -> U:
+            return cls.merge(self, vals) if len(vals) > 0 else self.default()
+
     return Inner
 
 
@@ -272,16 +278,14 @@ def MappedField[T, U, V](
             return mapping(self.__inner.default())
 
         def merge(self, vals: list[T]) -> V:
-            return mapping(self.__inner.merge(vals))
+            res = mapping(self.__inner.merge(vals))
+            return res
 
     return Inner
 
 
 def ListParser[T](parser: Parser[T]) -> Type[ConfigField[list[T]]]:
     class Inner(ConfigField[list[T]]):
-        def __init__(self, name: str) -> None:
-            super().__init__(name)
-
         def parse(self, s: str) -> ParseResult[list[T]]:
             return parser_map(lambda e: [e], parser)(s)
 
@@ -353,12 +357,22 @@ def fields_parser(
                 for name, values in res.items()
             }
         )
+
+        def default_lists(d: dict[str, list[Any]]) -> dict[str, list[Any]]:
+            for field in fields.keys():
+                if field not in d:
+                    d[field] = []
+            return d
+
         return parser_map(
             fields_map,
-            fold(
-                parse_line,
-                fold_fn,
-                lambda: {name: [] for name in fields.keys()},
+            parser_map(
+                default_lists,
+                fold(
+                    parse_line,
+                    fold_fn,
+                    lambda: {name: [] for name in fields.keys()},
+                ),
             ),
         )(s)
 
@@ -386,6 +400,8 @@ class Config:
     tilemap_box_size: IVec2
     tilemap_box_bridge_size: IVec2
     tilemap_box: list[ColoredLine]
+    prompt_size: IVec2
+    prompt: list[ColoredLine]
     maze_pattern: list[str]
 
     def __init__(self) -> None:
@@ -445,10 +461,21 @@ class Config:
                     "TILEMAP_BOX": DefaultedStrField(
                         ListParser(parse_colored_line),
                         [
-                            '"{1000,500,500:0,0,0}╔═╦╗"',
-                            '"{1000,500,500:0,0,0}║ ║║"',
-                            '"{1000,500,500:0,0,0}╠═╬╣"',
-                            '"{1000,500,500:0,0,0}╚═╩╝"',
+                            '"{RED:BLACK}╔═╦╗"',
+                            '"{RED:BLACK}║ ║║"',
+                            '"{RED:BLACK}╠═╬╣"',
+                            '"{RED:BLACK}╚═╩╝"',
+                        ],
+                    ),
+                    "PROMPT_SIZE": DefaultedField(CoordField, IVec2(32, 5)),
+                    "PROMPT": DefaultedStrField(
+                        ListParser(parse_colored_line),
+                        [
+                            '"{WHITE:BLACK}                                "',
+                            '"{WHITE:BLACK} q: quit         r: regenerate  "',
+                            '"{WHITE:BLACK} c: color next   k: play/pause  "',
+                            '"{WHITE:BLACK} v: color prev   p: toggle path "',
+                            '"{WHITE:BLACK}                                "',
                         ],
                     ),
                 }
index 8303a5cf217a07649fb7559cb065863fd1206807..dee7ce501acc0b7449f6911212a79de24985387d 100644 (file)
@@ -78,6 +78,11 @@ class TTYTracker:
                 self.full_style.cycle()
                 self.path_style.cycle()
                 self.empty_style.cycle()
+            if event.sym == "v":
+                self.filler_style.cycle(-1)
+                self.full_style.cycle(-1)
+                self.path_style.cycle(-1)
+                self.empty_style.cycle(-1)
             else:
                 continue
 
index 36bc147404316b22485ee37a46108337d16ce41f..bebf9cfc5b14e7a98600a1389eccf5070033a73a 100644 (file)
@@ -291,7 +291,7 @@ def extract_pairs(
             config.tilemap_background,
         )
         for e in tilemaps
-    ] + [config.tilemap_box]
+    ] + [config.tilemap_box, config.prompt]
     pairs = {
         pair
         for tilemap in all_tilemaps
@@ -397,6 +397,7 @@ class TileMaps:
                 x += width
             self.box.append(line)
             y += height
+        self.prompt: int = add_style(config.prompt, config.prompt_size)
 
 
 class TileCycle[T]:
@@ -411,7 +412,7 @@ class TileCycle[T]:
         cb(styles[i])
 
     def cycle(self, by: int = 1) -> None:
-        new = (self.__i + by) % len(self.__styles)
+        new = abs((self.__i + by) % len(self.__styles))
         if new != self.__i:
             self.__cb(self.__styles[new])
         self.__i = new
@@ -436,6 +437,7 @@ class TTYBackend:
             self.__dims * IVec2.splat(2) + IVec2.splat(1)
         )
 
+        self.__uninit: bool = False
         self.__screen: curses.window = curses.initscr()
         curses.start_color()
         curses.noecho()
@@ -450,11 +452,6 @@ class TTYBackend:
         self.__drawn: QuadTree = QuadTree()
         self.__pad: ScrollablePad = ScrollablePad(dims, self.pad_callback)
 
-        maze_box = FBox(
-            IVec2(BInt(dims.x), BInt(dims.y)),
-            lambda at, into: self.__pad.present(at, into, self.__scratch),
-        )
-
         self.__filler_boxes: list[DBox] = []
 
         def filler_box(
@@ -500,26 +497,39 @@ class TTYBackend:
         layout = layout_split(
             layout_fair, layout_sort_chunked(layout_fair, layout_priority, f)
         )
-        maze_box = VBox(
-            layout,
-            [
-                (filler_box(), 0),
-                (
-                    HBox(
-                        layout,
-                        [
-                            (filler_box(), 0),
-                            (maze_box, 1),
-                            (filler_box(), 0),
-                        ],
+
+        def fullpadded(box: Box) -> Box:
+            return VBox(
+                layout,
+                [
+                    (filler_box(), 0),
+                    (
+                        HBox(
+                            layout,
+                            [
+                                (filler_box(), 0),
+                                (box, 1),
+                                (filler_box(), 0),
+                            ],
+                        ),
+                        1,
                     ),
-                    1,
-                ),
-                (filler_box(), 0),
-            ],
-        )
+                    (filler_box(), 0),
+                ],
+            )
 
-        prompt_box = filler_box()
+        maze_box = FBox(
+            IVec2(BInt(dims.x), BInt(dims.y)),
+            lambda at, into: self.__pad.present(at, into, self.__scratch),
+        )
+        maze_box = fullpadded(maze_box)
+        prompt_box = FBox(
+            IVec2(BInt(config.prompt_size.x), BInt(config.prompt_size.y)),
+            lambda at, into: self.__tilemap.draw_at_wrapping(
+                IVec2.splat(0), at, into, self.tilemaps.prompt, self.__scratch
+            ),
+        )
+        prompt_box = fullpadded(prompt_box)
 
         def border_line_box(y: int) -> Box:
             return HBox.noassoc(
@@ -559,8 +569,6 @@ class TTYBackend:
         self.__style_bimap: BiMap[int, IVec2] = BiMap()
         self.__bg_init: Callable[[IVec2], int] | None = None
 
-        self.__uninit: bool = False
-
     def __del__(self) -> None:
         self.uninit()
 
index 03540a4036b82c7815df41d133f6568f2684bdb9..cd98fc503f05af3a9484f69bbcfb851d2a1b61d3 100644 (file)
@@ -5,37 +5,43 @@ EXIT=24,24
 OUTPUT_FILE=test
 PERFECT=False
 SEED=111
-TILEMAP_WALL_SIZE=2,1
-TILEMAP_CELL_SIZE=4,2
-TILEMAP_FULL="{1000,1000,1000:1000,1000,1000}######"
-TILEMAP_FULL="{1000,1000,1000:1000,1000,1000}######"
-TILEMAP_FULL="{1000,1000,1000:1000,1000,1000}######"
-TILEMAP_FULL=1"{100,1000,1000:1000,1000,1000}███{1000,100,1000:1000,1000,1000}███"
-TILEMAP_FULL=1"{100,1000,1000:1000,1000,1000}######"
-TILEMAP_FULL=1"{100,1000,1000:1000,1000,1000}######"
-TILEMAP_PATH="{100,100,1000:100,100,1000}      "
-TILEMAP_PATH="{100,100,1000:100,100,1000}      "
-TILEMAP_PATH="{100,100,1000:100,100,1000}      "
-TILEMAP_EMPTY="{0,0,0:0,0,0}      "
-TILEMAP_EMPTY="{0,0,0:0,0,0}      "
-TILEMAP_EMPTY="{0,0,0:0,0,0}      "
-TILEMAP_BACKGROUND_SIZE=8,4
-TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}##      "
-TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}######  "
-TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}    ##  "
-TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}##  ##  "
-TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}##      "
-TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}######  "
-TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}    ##  "
-TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}##  ##  "
 
+#TILEMAP_WALL_SIZE=2,1
+#TILEMAP_CELL_SIZE=4,2
+#
+#TILEMAP_FULL="{1000,1000,1000:1000,1000,1000}######"
+#TILEMAP_FULL="{1000,1000,1000:1000,1000,1000}######"
+#TILEMAP_FULL="{1000,1000,1000:1000,1000,1000}######"
+#
+#TILEMAP_FULL=1"{100,1000,1000:1000,1000,1000}███{1000,100,1000:1000,1000,1000}███"
+#TILEMAP_FULL=1"{100,1000,1000:1000,1000,1000}######"
+#TILEMAP_FULL=1"{100,1000,1000:1000,1000,1000}######"
+#
+#TILEMAP_PATH="{100,100,1000:100,100,1000}      "
+#TILEMAP_PATH="{100,100,1000:100,100,1000}      "
+#TILEMAP_PATH="{100,100,1000:100,100,1000}      "
+#
+#TILEMAP_EMPTY="{0,0,0:0,0,0}      "
+#TILEMAP_EMPTY="{0,0,0:0,0,0}      "
+#TILEMAP_EMPTY="{0,0,0:0,0,0}      "
+#
+#TILEMAP_BACKGROUND_SIZE=8,4
+#TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}##      "
+#TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}######  "
+#TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}    ##  "
+#TILEMAP_BACKGROUND="{1000,1000,1000:0,0,0}##  ##  "
+#TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}##      "
+#TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}######  "
+#TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}    ##  "
+#TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}##  ##  "
+#
 #TILEMAP_BOX_SIZE=1,1
 #TILEMAP_BOX_BRIDGE_SIZE=1,1
-#TILEMAP_BOX="{200,100,100:0,0,0}+-++"
-#TILEMAP_BOX="{200,100,100:0,0,0}| ||"
-#TILEMAP_BOX="{200,100,100:0,0,0}+-++"
-#TILEMAP_BOX="{200,100,100:0,0,0}+-++"
-
+#TILEMAP_BOX="{1000,500,500:0,0,0}+-++"
+#TILEMAP_BOX="{1000,500,500:0,0,0}| ||"
+#TILEMAP_BOX="{1000,500,500:0,0,0}+-++"
+#TILEMAP_BOX="{1000,500,500:0,0,0}+-++"
+#
 #MAZE_PATTERN=" #   # "
 #MAZE_PATTERN="  # #  "
 #MAZE_PATTERN="   #   "