From 3fb1723a513f6fab26bc7830df0cc84fc25388e3 Mon Sep 17 00:00:00 2001
From: Florent Bouchez Tichadou <florent.bouchez-tichadou@imag.fr>
Date: Tue, 20 Jun 2023 17:06:48 +0200
Subject: [PATCH] [ale] fix

---
 lib/graphic/constants.py          |   2 +-
 lib/graphic/sprites/sp_objects.py |  14 +-
 lib/graphic/style.py              | 262 ++++++++++++++++--------------
 lib/graphic/views/game.py         | 170 +++++++++----------
 lib/graphic/views/menu/ingame.py  |   6 +-
 lib/graphic/window.py             |  11 +-
 6 files changed, 237 insertions(+), 228 deletions(-)

diff --git a/lib/graphic/constants.py b/lib/graphic/constants.py
index 8154ed16..4b5af0e2 100644
--- a/lib/graphic/constants.py
+++ b/lib/graphic/constants.py
@@ -24,7 +24,7 @@ class Anim:
     HIT_UPDATE_RATE = 10
     HIT_SPEED = 5 / 300
     TEXT_UPDATE_RATE = 1.5
-    POST_TEXT_DELAY = 50    # time during which a box 'blocks' another box appearance
+    POST_TEXT_DELAY = 50  # time during which a box 'blocks' another box appearance
 
 
 TILESETS = {
diff --git a/lib/graphic/sprites/sp_objects.py b/lib/graphic/sprites/sp_objects.py
index e161111f..8ef039a9 100644
--- a/lib/graphic/sprites/sp_objects.py
+++ b/lib/graphic/sprites/sp_objects.py
@@ -157,7 +157,7 @@ class SpObject(arcade.Sprite, SpCoordinates):
 
     def update(self):
         # if self.name == 'WOP':
-            # log.debug(f"WOP update {self.in_action} queue {len(self.action_queue)}")
+        # log.debug(f"WOP update {self.in_action} queue {len(self.action_queue)}")
 
         if self.in_action:
             assert self.action_hook != None
@@ -349,7 +349,6 @@ class SpObject(arcade.Sprite, SpCoordinates):
         self.auto_dir = True
         self.start_moving()
 
-
     def handle_move_action(self, payload):
         log.debug(f"Handling move action for {self} with {payload}")
         # now dealing with movement
@@ -385,7 +384,6 @@ class SpObject(arcade.Sprite, SpCoordinates):
             self.set_relative_position(target_x, target_y, direct=self.direction)
             return
 
-
         dx, dy = target_x - self.coord_x, target_y - self.coord_y
 
         # player always go for the straight-line
@@ -396,21 +394,15 @@ class SpObject(arcade.Sprite, SpCoordinates):
 
         # Otherwise, move selfect / wop from current position to new position
         path = find_path(
-            self,
-            self.amap.game_view.layers["walls"],
-            target_x,
-            target_y,
-            self.amap
+            self, self.amap.game_view.layers["walls"], target_x, target_y, self.amap
         )
         log.debug(f"Moving {self.name} along path {path}")
 
         if path:
-            self.follow_path(path, auto_dir=not self.name=='Player')
+            self.follow_path(path, auto_dir=not self.name == 'Player')
         else:
             log.error(f"Cannot move {self.name} to destination!")
 
-
-
     def disappear(self):
         self.visible = False
         ## TODO: really update this list, still used?
diff --git a/lib/graphic/style.py b/lib/graphic/style.py
index 247801aa..005f2f1c 100644
--- a/lib/graphic/style.py
+++ b/lib/graphic/style.py
@@ -39,7 +39,6 @@ class MenuButton(arcade.gui.UIFlatButton):
     """
 
     def __init__(self, *args, **kwargs):
-
         if "style" not in kwargs:
             kwargs["style"] = {}
         kwargs["style"]["font_name"] = cst.Fonts.KENNEY
@@ -48,16 +47,16 @@ class MenuButton(arcade.gui.UIFlatButton):
             kwargs["width"] = 180
         super().__init__(*args, **kwargs)
 
+
 class SkipButton(arcade.gui.UIFlatButton):
     """
     Skip button in the Agdbentures style that is meant to be more in the 'background'
     """
 
     def __init__(self, *args, **kwargs):
-
         if "style" not in kwargs:
             kwargs["style"] = {}
-        kwargs["style"]["font_name"] = font_name=cst.Fonts.FURACODE
+        kwargs["style"]["font_name"] = font_name = cst.Fonts.FURACODE
         kwargs["style"]["font_size"] = 12
         if "width" not in kwargs:
             kwargs["width"] = 180
@@ -67,7 +66,6 @@ class SkipButton(arcade.gui.UIFlatButton):
         super().__init__(*args, **kwargs)
 
 
-
 class UnLockedButton(MenuButton):
     """
     Button to display unlocked levels
@@ -92,7 +90,6 @@ class DoneButton(MenuButton):
         super().__init__(*args, **kwargs)
 
 
-
 class BlinkButton(MenuButton):
     """
     Button to draw attention.
@@ -113,16 +110,13 @@ class BlinkButton(MenuButton):
         # self.color = (20, self.green, 20)
         super().__init__(*args, **kwargs)
 
-
     def start_blinking(self):
         self._is_blinking = True
 
-
     def stop_blinking(self):
         self._is_blinking = False
         self._style["bg_color"] = self.init_color
 
-
     ## does not work, color is not changed
     def on_update(self, delta_time):
         if self.pressed:
@@ -137,7 +131,7 @@ class BlinkButton(MenuButton):
         self._style["bg_color"] = (20, self.green, 120)
 
 
-# TODO: find a way to place the message box where we want, and not just have an 
+# TODO: find a way to place the message box where we want, and not just have an
 # anchor widget placed by the manager
 # TODO: refactor with generic label box
 class GenericBox(UIMouseFilterMixin, UIAnchorWidget):
@@ -146,15 +140,17 @@ class GenericBox(UIMouseFilterMixin, UIAnchorWidget):
     Copy from python arcade API UIMessageBox, but with our agdb style.
     """
 
-    def __init__(self,
-                 *,
-                 width: float = 300,
-                 height: float = 250,
-                 message_text: str,
-                 font_name: str = None,
-                 bg_texture: str = None,
-                 buttons=("Ok",),
-                 callback=None):
+    def __init__(
+        self,
+        *,
+        width: float = 300,
+        height: float = 250,
+        message_text: str,
+        font_name: str = None,
+        bg_texture: str = None,
+        buttons=("Ok",),
+        callback=None,
+    ):
         """
         A simple dialog box that pops up a message with buttons to close.
 
@@ -180,34 +176,49 @@ class GenericBox(UIMouseFilterMixin, UIAnchorWidget):
         else:
             bottom_height = 0
 
-        self._text_area = UITextArea(text=message_text,
-                                     width=width - 2*space,
-                                     height=height - 2*space - bottom_height,
-                                     # font_name="FuraCode Nerd Font",
-                                     # font_name="fonts:Fura Code Medium Nerd Font Complete.ttf",
-                                     # font_name="fonts:FuraCode",
-                                     font_name=font_name or cst.Fonts.BITSTREAM,
-                                     text_color=arcade.color.BLACK,)
+        self._text_area = UITextArea(
+            text=message_text,
+            width=width - 2 * space,
+            height=height - 2 * space - bottom_height,
+            # font_name="FuraCode Nerd Font",
+            # font_name="fonts:Fura Code Medium Nerd Font Complete.ttf",
+            # font_name="fonts:FuraCode",
+            font_name=font_name or cst.Fonts.BITSTREAM,
+            text_color=arcade.color.BLACK,
+        )
 
         self._bg_tex = arcade.load_texture(bg_texture or ":window:grey_panel.png")
 
         self._callback = callback
         # self._text_area.fit_content()
         children = [
-            UIAnchorWidget(child=self._text_area, anchor_x="center_x", anchor_y="top", align_x=0, align_y=-space)
+            UIAnchorWidget(
+                child=self._text_area,
+                anchor_x="center_x",
+                anchor_y="top",
+                align_x=0,
+                align_y=-space,
+            )
         ]
         if buttons:
-            children.append (
-                UIAnchorWidget(child=button_group, anchor_x="center_x", anchor_y="bottom", align_x=0, align_y=space)
+            children.append(
+                UIAnchorWidget(
+                    child=button_group,
+                    anchor_x="center_x",
+                    anchor_y="bottom",
+                    align_x=0,
+                    align_y=space,
+                )
+            )
+        group = UILayout(width=width, height=height, children=children).with_background(
+            self._bg_tex
         )
-        group = UILayout(width=width, height=height, children=children).with_background(self._bg_tex)
         super().__init__(child=group)
 
     def show_all_message(self):
         # Used only for boxes with animated text
         pass
 
-
     def on_ok(self, event):
         self.parent.remove(self)
         if self._callback is not None:
@@ -227,15 +238,14 @@ class ConfirmationBox(MessageBox):
     """
     Display a box asking if user really wants to do it.
     """
- 
-    def __init__(self, message: str, callback = None):
 
+    def __init__(self, message: str, callback=None):
         super().__init__(
             width=300,
             height=200,
             callback=callback,
             message_text=message,
-            buttons=("Ok", "Cancel")
+            buttons=("Ok", "Cancel"),
         )
 
 
@@ -246,7 +256,6 @@ class GreedyInputText(UIInputText):
     """
 
     def __init__(self, *args, **kwargs):
-
         super().__init__(*args, **kwargs)
         # TODO: try to have a visible caret. The following does not work
         # self.caret.color = (80, 20, 20)
@@ -258,31 +267,31 @@ class GreedyInputText(UIInputText):
         self._active = True
         super().on_event(event)
 
-        # Consume key presses/releases so they do not activate other widgets or 
+        # Consume key presses/releases so they do not activate other widgets or
         # the main game area
-        if isinstance(event, UIMousePressEvent) or \
-            isinstance(event, UIMouseReleaseEvent) or \
-            isinstance(event, UIKeyPressEvent) or \
-            isinstance(event, UIKeyReleaseEvent):
-                # log.debug(f"Consumed event in input area: {event}")
-                return EVENT_HANDLED
+        if (
+            isinstance(event, UIMousePressEvent)
+            or isinstance(event, UIMouseReleaseEvent)
+            or isinstance(event, UIKeyPressEvent)
+            or isinstance(event, UIKeyReleaseEvent)
+        ):
+            # log.debug(f"Consumed event in input area: {event}")
+            return EVENT_HANDLED
 
 
 class GenericLabelBox(UIMouseFilterMixin, UIAnchorWidget):
-
-
-    def __init__(self,
-                 *,
-                 width=300,
-                 height=100,
-                 label=None,       # if given a string, will add a label at top of the box
-                 text="",
-                 with_input=False, # change to True to have an input field in the box
-                 callback=None,
-                 buttons=[],
-                 texture=None
-                 ):
-
+    def __init__(
+        self,
+        *,
+        width=300,
+        height=100,
+        label=None,  # if given a string, will add a label at top of the box
+        text="",
+        with_input=False,  # change to True to have an input field in the box
+        callback=None,
+        buttons=[],
+        texture=None,
+    ):
         self._callback = callback
         space = 20
 
@@ -294,15 +303,15 @@ class GenericLabelBox(UIMouseFilterMixin, UIAnchorWidget):
                 text=label,
                 font_name=cst.Fonts.FURACODE,
                 font_size=12,
-                text_color=arcade.color.DARK_RED
+                text_color=arcade.color.DARK_RED,
             )
 
-        self._top_message = UITextArea (
-            text=self._full_text + "\xA0\n", ## Reserve a bit more space than necessary
-            width=width - 2*space,
+        self._top_message = UITextArea(
+            text=self._full_text + "\xA0\n",  ## Reserve a bit more space than necessary
+            width=width - 2 * space,
             font_name=cst.Fonts.FURACODE,
             font_size=14,
-            text_color=arcade.color.BLACK
+            text_color=arcade.color.BLACK,
         )
         # Compute the height necessary for the whole text
         self._top_message.fit_content()
@@ -313,7 +322,7 @@ class GenericLabelBox(UIMouseFilterMixin, UIAnchorWidget):
         else:
             # The entry where user input is stored
             self._entry_area = GreedyInputText(
-                width=width-2*space,
+                width=width - 2 * space,
                 height=35,
                 font_name=cst.Fonts.FURACODE,
                 font_size=20,
@@ -323,11 +332,9 @@ class GenericLabelBox(UIMouseFilterMixin, UIAnchorWidget):
             )
             # Add padding only to we can change the background color
             self._entry_padding = UIPadding(
-                child=self._entry_area,
-                bg_color=arcade.color.DARK_GRAY
+                child=self._entry_area, bg_color=arcade.color.DARK_GRAY
             )
-            cur_height += self._entry_padding.height + 2*space
-
+            cur_height += self._entry_padding.height + 2 * space
 
         self._buttons_texts = buttons
         if buttons:
@@ -341,22 +348,31 @@ class GenericLabelBox(UIMouseFilterMixin, UIAnchorWidget):
                 button.on_click = self.on_ok
             cur_height += button_group.height + space
 
-
         # same background as the message box but darker
         # self._bg_tex = arcade.load_texture(":window:grey_panel2.png")
         self._bg_tex = arcade.load_texture(texture or ":window:grey_panel.png")
 
-        children=[
-            UIAnchorWidget(child=self._top_message.with_space_around(), anchor_x="center_x", anchor_y="top", align_x=space/2, align_y=-space),
+        children = [
+            UIAnchorWidget(
+                child=self._top_message.with_space_around(),
+                anchor_x="center_x",
+                anchor_y="top",
+                align_x=space / 2,
+                align_y=-space,
+            ),
         ]
         if with_input:
             children.append(
                 UIAnchorWidget(
-                    child=self._entry_padding.with_space_around(bottom=space,right=space),
+                    child=self._entry_padding.with_space_around(
+                        bottom=space, right=space
+                    ),
                     anchor_x="center_x",
                     anchor_y="bottom",
-                    align_x=space/2,
-                    align_y=0))
+                    align_x=space / 2,
+                    align_y=0,
+                )
+            )
         if buttons:
             children.append(
                 UIAnchorWidget(
@@ -364,26 +380,31 @@ class GenericLabelBox(UIMouseFilterMixin, UIAnchorWidget):
                     anchor_x="center_x",
                     anchor_y="bottom",
                     align_x=0,
-                    align_y=space))
+                    align_y=space,
+                )
+            )
         if label:
             children.append(
                 UIAnchorWidget(
-                    child=self._top_label.with_space_around(left=space/2,right=space/2).with_background(self._bg_tex),
+                    child=self._top_label.with_space_around(
+                        left=space / 2, right=space / 2
+                    ).with_background(self._bg_tex),
                     anchor_x="center_x",
                     anchor_y="top",
                     align_x=0,
-                    align_y=space/2))
-
+                    align_y=space / 2,
+                )
+            )
 
-        group = UILayout(width=width, height=cur_height + 2*space, children=children).with_background(self._bg_tex)
+        group = UILayout(
+            width=width, height=cur_height + 2 * space, children=children
+        ).with_background(self._bg_tex)
         super().__init__(child=group)
 
-
     def show_all_message(self):
         # Used only for boxes with animated text
         pass
 
-
     def close(self, event):
         log.debug(f"Removing label/input box from parent {self.parent}")
         self.parent.remove(self)
@@ -393,36 +414,30 @@ class GenericLabelBox(UIMouseFilterMixin, UIAnchorWidget):
             else:
                 self._callback(event)
 
-
     def on_ok(self, event):
         self.parent.remove(self)
         if self._callback is not None:
             self._callback(event.source.text)
 
 
-
 class AnimGenericLabelBox(GenericLabelBox):
-
-    def __init__(self,
-                 *args,
-                 **kwargs
-                 ):
+    def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
 
         self._idx_text = 1
         self._words = self._full_text.split(' ')
         self.frame_count = 0
 
-        self.active_box = True # either animating text, or in follow-up delay
+        self.active_box = True  # either animating text, or in follow-up delay
         self.anim_text = True  # currently animating text
 
         # Now erase text and put only the first char
         self._idx_word = -1
-        self._text=""
+        self._text = ""
         self.prepare_next_word()
-        self._previous_words=""
+        self._previous_words = ""
         self._last_word = ""
-        self._top_message.text=self._text
+        self._top_message.text = self._text
 
     def animation_finished(self):
         self.anim_text = False
@@ -438,7 +453,9 @@ class AnimGenericLabelBox(GenericLabelBox):
         self._last_word = ""
         word = self._words[self._idx_word]
         self._current_word = word
-        self._anim_word = ["\xA0"]*len(word)  # list of non-breaking space, so that pyglet will not break word into multiple lines
+        self._anim_word = ["\xA0"] * len(
+            word
+        )  # list of non-breaking space, so that pyglet will not break word into multiple lines
         self._idx_char_in_word = -1
 
     def show_all_message(self):
@@ -465,13 +482,13 @@ class AnimGenericLabelBox(GenericLabelBox):
             self._previous_words += self._last_word + ' '
             self.prepare_next_word()
         else:
-            self._anim_word[self._idx_char_in_word] = self._current_word[self._idx_char_in_word]
+            self._anim_word[self._idx_char_in_word] = self._current_word[
+                self._idx_char_in_word
+            ]
             self._last_word = ''.join(self._anim_word)
         self._top_message.text = self._previous_words + self._last_word
 
 
-
-
 class GreedyLabelBox(AnimGenericLabelBox):
     """
     Box that greedily consumes all keyboard / mouse events until it is closed
@@ -507,19 +524,18 @@ class GreedyLabelBox(AnimGenericLabelBox):
                 return EVENT_HANDLED
 
 
-
 class OutputBox(AnimGenericLabelBox):
-
     def __init__(self, *args, **kwargs):
-        super().__init__(*args,
-                         texture=":window:grey_panel2.png",
-                         label=message('output/messagelabel'),
-                         **kwargs)
+        super().__init__(
+            *args,
+            texture=":window:grey_panel2.png",
+            label=message('output/messagelabel'),
+            **kwargs,
+        )
         # add a label at the top
 
 
 class InputBox(GreedyLabelBox):
-
     def __init__(self, *args, **kwargs):
         super().__init__(*args, with_input=True, **kwargs)
 
@@ -527,13 +543,12 @@ class InputBox(GreedyLabelBox):
 # class LogBox(GenericBox):
 # class LogBox(arcade.gui.UITextArea):
 class LogBox(UITexturePane):
-
     def __init__(self):
         self.my_text = ""
 
-        self.log_width=170
-        self.log_height=400
-        self.log_hidden_height=1
+        self.log_width = 170
+        self.log_height = 400
+        self.log_hidden_height = 1
         self.appearing = False
 
         self._log_area = UITextArea(
@@ -549,15 +564,15 @@ class LogBox(UITexturePane):
 
         transp_rect = arcade.Texture.create_filled(
             name='log_bg',
-            size=(10,10),
+            size=(10, 10),
             color=arcade.color.BLACK + (120,),
         )
-        pad=10
+        pad = 10
 
         super().__init__(
             child=self._log_area,
             tex=transp_rect,
-            padding=(pad,pad,pad,pad),
+            padding=(pad, pad, pad, pad),
         )
 
     def reset(self):
@@ -574,8 +589,7 @@ class LogBox(UITexturePane):
 
         # self._log_area.height = self.log_height
         self._log_area.text += "\n" + msg
-        self._log_area.layout.view_y = -99999999 # scroll to bottom
-
+        self._log_area.layout.view_y = -99999999  # scroll to bottom
 
     def on_update(self, event):
         # make the box appear as soon as there is content in it
@@ -602,8 +616,6 @@ class LogBox(UITexturePane):
         return EVENT_UNHANDLED
 
 
-
-
 def transparent_rect(left, right, top, bottom):
     arcade.draw_lrtb_rectangle_filled(
         left=left,
@@ -613,8 +625,11 @@ def transparent_rect(left, right, top, bottom):
         color=arcade.color.BLACK + (80,),
     )
 
+
 def draw_bar(l, r, t, b):
-    arcade.draw_lrtb_rectangle_filled(left=l, right=r, top=t, bottom=b, color=arcade.color.WHITE)
+    arcade.draw_lrtb_rectangle_filled(
+        left=l, right=r, top=t, bottom=b, color=arcade.color.WHITE
+    )
 
 
 def draw_pause(left, right, top, bottom):
@@ -631,18 +646,27 @@ def draw_pause(left, right, top, bottom):
     )
     # Crude "pause" symbol
     draw_bar(left + space, left + space + width, top - space, top - space - height)
-    off=width+2*space/3
-    draw_bar(left + space + off, left + space + off + width, top - space, top - space - height)
+    off = width + 2 * space / 3
+    draw_bar(
+        left + space + off,
+        left + space + off + width,
+        top - space,
+        top - space - height,
+    )
+
 
+cosPi6 = cos(pi / 6)
 
-cosPi6 = cos(pi/6)
 
 def draw_play(left, top):
     tsize = 40
     space = 20
     arcade.draw_triangle_filled(
-        left+space, top-space,
-        left+space, top-space-tsize,
-        left+space+tsize*cosPi6, top-space-tsize/2,
+        left + space,
+        top - space,
+        left + space,
+        top - space - tsize,
+        left + space + tsize * cosPi6,
+        top - space - tsize / 2,
         color=arcade.color.WHITE,
     )
diff --git a/lib/graphic/views/game.py b/lib/graphic/views/game.py
index 5ce080d4..e547c811 100644
--- a/lib/graphic/views/game.py
+++ b/lib/graphic/views/game.py
@@ -47,6 +47,7 @@ from graphic.amap import Amap
 from graphic.sprites.path import find_path, to_absolute, to_relative
 from level.console import ConsoleInputThread
 
+
 # pylint: disable=fixme unused-argument too-many-instance-attributes too-many-branches
 class GameView(EmptyView):
     """Game view class."""
@@ -65,8 +66,10 @@ class GameView(EmptyView):
         self.wop: NPC
         self.objects = None  # dictionnary for sprite objects
 
-        self.has_started = False # whether the inferior has started or not (
-        self.executing = False # whether the inferior is executing (running or on pause) or not
+        self.has_started = False  # whether the inferior has started or not (
+        self.executing = (
+            False  # whether the inferior is executing (running or on pause) or not
+        )
         self.on_pause = False  # whether the inferior is paused by gdb or running
 
         ##
@@ -126,7 +129,7 @@ class GameView(EmptyView):
         self.camera_gui = arcade.Camera(self.window.width, self.window.height)
         # cst.Win.BUTTON_H)
         # self.camera_gui.position = (Vec2(0, self.window.height * 2 / 3))
-        self.dragging_camera = False # True when user is click-dragging map
+        self.dragging_camera = False  # True when user is click-dragging map
 
         # Text informations
         self.draw_text = False
@@ -165,7 +168,9 @@ class GameView(EmptyView):
 
         if Config.SHOW_FPS:
             arcade.enable_timings()
-            graph = arcade.PerfGraph(cst.Win.GRAPH_WIDTH, cst.Win.GRAPH_HEIGHT, graph_data="FPS")
+            graph = arcade.PerfGraph(
+                cst.Win.GRAPH_WIDTH, cst.Win.GRAPH_HEIGHT, graph_data="FPS"
+            )
             graph.center_x = cst.Win.GRAPH_WIDTH / 2
             graph.center_y = self.window.height - cst.Win.GRAPH_HEIGHT / 2
             self.locked_sprites.append(graph)
@@ -287,7 +292,6 @@ class GameView(EmptyView):
             )
         )
 
-
     def adjust_buttons(self):
         """
         Deactivates some buttons if level does not yet allow them
@@ -350,7 +354,8 @@ class GameView(EmptyView):
 
         # otherwise, show compilation errors
         msg = (
-            message('compilation/error') + "\n"
+            message('compilation/error')
+            + "\n"
             + result.stdout.decode()
             + "\n"
             + result.stderr.decode()
@@ -387,7 +392,9 @@ class GameView(EmptyView):
         with open("config.editor") as f:
             command = f.readline()
         command = command.replace("<FOLDER>", Config.LEVEL_DIR)
-        command = command.replace("<FILE>", os.path.join(self.level.source_level_dir, "main.c"))
+        command = command.replace(
+            "<FILE>", os.path.join(self.level.source_level_dir, "main.c")
+        )
         log.debug(f"Opening in editor with command '{command}'")
         try:
             subprocess.run(command.split())
@@ -491,7 +498,6 @@ class GameView(EmptyView):
         self.change_map("main")
 
     def change_map(self, map_name):
-
         log.debug(f"Changing to map {map_name}")
 
         if self.current_map:
@@ -634,8 +640,7 @@ class GameView(EmptyView):
         else:
             self.metadata['map_height'] = self.amap.height
 
-
-        # TODO: why custom code for guard? Should actually only to that if 
+        # TODO: why custom code for guard? Should actually only to that if
         # required by the level
         # => Need to clean that up and make it more generic
         self.guard.far_move = 'crowflies'
@@ -643,7 +648,6 @@ class GameView(EmptyView):
         self.level_maps['main']['tile_map'].sprite_lists['objects'].append(self.guard)
         self.level_maps['main']['objects']['guard'] = self.guard
 
-
         # combine objects/coordinates of all maps to pass to the tracker
         sp_objs = {'exit': self.exit}
         sp_coords = {}
@@ -657,7 +661,7 @@ class GameView(EmptyView):
 
         # Instantiate the level object that will launch easytracker
         # We shutdown the previous level
-        assert self.level is None # will break soon...
+        assert self.level is None  # will break soon...
         self.level = self.level_cls(
             self.metadata,
             code_window,
@@ -668,8 +672,7 @@ class GameView(EmptyView):
         )
         self.console_input_thread.set_tracker(self.level.tracker)
 
-
-        self.set_reset_level() # prepare the level with common code used also for restart
+        self.set_reset_level()  # prepare the level with common code used also for restart
 
         # start the thread that will handle easytracker for this level
         self.level.start()
@@ -688,7 +691,6 @@ class GameView(EmptyView):
         self.executing = False
         self.on_pause = False
 
-
         self.exit.reset()
         self.breaklight.reset()
 
@@ -715,7 +717,7 @@ class GameView(EmptyView):
 
         # Clear box queue
         self.message_list = []
-        self.clear_box() # remove any box that might still be open
+        self.clear_box()  # remove any box that might still be open
         while not self.box_queue.empty():
             self.box_queue.get()
         self.message_box_close_hook = None
@@ -743,7 +745,9 @@ class GameView(EmptyView):
         """
 
         self.has_started = True
-        self.executing = True # whether the inferior is executing (running or on pause) or not
+        self.executing = (
+            True  # whether the inferior is executing (running or on pause) or not
+        )
 
         if not self.is_inside_camera(self.exit):
             self.camera_mode = 'center_to_exit'
@@ -756,7 +760,6 @@ class GameView(EmptyView):
 
         pass
 
-
     def reset_level(self):
         """
         Reset a currently running level.
@@ -772,7 +775,7 @@ class GameView(EmptyView):
         self.disappeared_sprites = []
 
         self.executing = False
-        self.set_reset_level() # call common code that init/reinit a level
+        self.set_reset_level()  # call common code that init/reinit a level
 
     def trigger_restart_level(self):
         """
@@ -794,7 +797,6 @@ class GameView(EmptyView):
         self.level.send_level_control("validate")
         # self.level.restart()    # notify the level thread
 
-
     def on_show_view(self):
         """
         View focus hook.
@@ -818,9 +820,7 @@ class GameView(EmptyView):
             self.box_message(self.message_list.pop(0), position=position)
             return
         self.box_message(
-            self.message_list.pop(0),
-            buttons=["more", "skip"],
-            position=position
+            self.message_list.pop(0), buttons=["more", "skip"], position=position
         )
 
     def box_message(self, message: str, error=False, buttons=["Ok"], position=None):
@@ -834,9 +834,9 @@ class GameView(EmptyView):
         """
         assert not self.current_message_box
         # if (
-            # self.current_message_box
+        # self.current_message_box
         # ):  # WARNING: the previous message box has been removed
-            # self.manager.remove(self.current_message_box)
+        # self.manager.remove(self.current_message_box)
 
         mb = GreedyLabelBox(
             width=300,
@@ -846,7 +846,7 @@ class GameView(EmptyView):
             buttons=buttons,
         )
         self.current_message_box = mb
-        self.current_message_box_type = 'block' # blocks interaction with gdb
+        self.current_message_box_type = 'block'  # blocks interaction with gdb
         self.manager.add(self.current_message_box)
         # if not position:
         # mb.center_x = self.window.width / 2
@@ -865,7 +865,6 @@ class GameView(EmptyView):
         self.manager.remove(self.current_message_box)
         self.current_message_box = None
 
-
     def close_message_box(self, event) -> None:
         """Remove the box message if shown."""
         if not self.current_message_box:
@@ -892,44 +891,42 @@ class GameView(EmptyView):
             self.message_box_close_hook()
             self.message_box_close_hook = None
 
-
     def input_box(self, prompt: str):
         assert not self.current_message_box
         # if (
-            # self.current_message_box
+        # self.current_message_box
         # ):  # WARNING: the previous message box has been removed
-            # self.manager.remove(self.current_message_box)
+        # self.manager.remove(self.current_message_box)
         it = InputBox(text=prompt, callback=self.close_input_box)
         self.current_message_box = it
-        self.current_message_box_type = 'block' # blocks interaction with gdb
+        self.current_message_box_type = 'block'  # blocks interaction with gdb
         self.manager.add(it)  #  .with_border())
 
-
     def close_input_box(self, answer):
         self.clear_box()
         self.send_to_stdin(answer)
 
     def output_box(self, text: str):
         """
-        Used to show some output from the inferior, e.g., strings shown using 
+        Used to show some output from the inferior, e.g., strings shown using
         the 'message' function'
         """
         assert not self.current_message_box
         # if (
-            # self.current_message_box
+        # self.current_message_box
         # ):  # WARNING: the previous message box has been removed
-            # self.manager.remove(self.current_message_box)
+        # self.manager.remove(self.current_message_box)
         lab = OutputBox(width=400, text=text)
         self.current_message_box = lab
-        self.current_message_box_type = 'pass' # any action will make it disappear
+        self.current_message_box_type = 'pass'  # any action will make it disappear
         self.manager.add(lab)  #  .with_border())
 
     def show_errors(self, message: str):
         assert not self.current_message_box
         # if (
-            # self.current_message_box
+        # self.current_message_box
         # ):  # WARNING: the previous message box has been removed
-            # self.manager.remove(self.current_message_box)
+        # self.manager.remove(self.current_message_box)
         err = ErrorBox(message)
         self.manager.add(err)
         self.current_message_box = err
@@ -941,7 +938,6 @@ class GameView(EmptyView):
         """
         self.output_logbox.append(msg)
 
-
     def box_queue_handle_next(self):
         if self.box_queue.empty():
             return
@@ -977,15 +973,12 @@ class GameView(EmptyView):
         elif btype == 'error':
             self.show_errors(msg)
 
-
-
-    def box_append_queue(self, btype, msg, hook = None):
+    def box_append_queue(self, btype, msg, hook=None):
         """
         :param: hook can a be a function to be called when the box is closed
         """
         self.box_queue.put((btype, msg, hook))
 
-
     def append_input_box(self, prompt):
         self.box_append_queue('input', prompt)
 
@@ -997,7 +990,6 @@ class GameView(EmptyView):
     ###
 
     def rescale(self, scale):
-
         self.rescale_map(scale)
         self.amap.change_scale(self.scale)
 
@@ -1020,7 +1012,6 @@ class GameView(EmptyView):
         new_scale = self.compute_scale(width, height)
         self.rescale(new_scale)
 
-
     ###
     ### Drawing methods, used for drawing frames
     ###
@@ -1061,12 +1052,11 @@ class GameView(EmptyView):
         self.camera_gui.use()
 
         # Pause is independant of the camera location
-        if self.on_pause: # TODO: also check if executing?
+        if self.on_pause:  # TODO: also check if executing?
             self.show_inferior_paused()
         else:
             self.show_inferior_running()
 
-
         self.print_osd_msg()
         self.manager.draw()
 
@@ -1086,7 +1076,6 @@ class GameView(EmptyView):
             top=self.camera_sprites.viewport_height,
         )
 
-
     ###
     ### Called at each tick. Will handle moving objects on the map.
     ###
@@ -1101,7 +1090,9 @@ class GameView(EmptyView):
 
         if self.metadata["interactive"]:
             # log.debug(f"Checking pause {self.level} and {self.level.is_running}").
-            assert self.level # why would there not be a level? mixup with level.tracker?
+            assert (
+                self.level
+            )  # why would there not be a level? mixup with level.tracker?
             if self.level and not self.level.is_running:
                 self.on_pause = True
 
@@ -1133,7 +1124,7 @@ class GameView(EmptyView):
         self.update_state()
 
         # Sometimes we are drawing text on screen
-        # Here an ad-hoc hack to append dots during the validation process to 
+        # Here an ad-hoc hack to append dots during the validation process to
         # show the game is not frozen
         if self.draw_text:
             self.text_pause_time += delta_time
@@ -1141,11 +1132,10 @@ class GameView(EmptyView):
                 self.text_pause_time = 0
                 self.draw_text_dots += "."
 
-
         # see if there is any box to show
         self.box_queue_handle_next()
 
-        # Update collision: do we need to check for collision? Seems the role 
+        # Update collision: do we need to check for collision? Seems the role
         # of the inferior, not the gui...
         # TODO: use this
         # pylint: disable=unused-variable
@@ -1194,20 +1184,19 @@ class GameView(EmptyView):
         self.camera_sprites.move_to(pos_centered, speed=speed)  # type: ignore
 
     def center_camera_to_player(self, speed=1):
-        if ( self.player.visible and
-             self.player.center_x is not None and
-             self.player.center_y is not None
-             # self.player.center_x >= 0 and
-             # self.player.center_y >= 0
-           ):
+        if (
+            self.player.visible
+            and self.player.center_x is not None
+            and self.player.center_y is not None
+            # self.player.center_x >= 0 and
+            # self.player.center_y >= 0
+        ):
             self.center_camera_to_position(
                 self.player.center_x, self.player.center_y, speed=speed
             )
         else:
             x0, y0 = to_absolute(0, 0, self.amap)
-            self.center_camera_to_position(
-                x0, y0, speed=speed
-            )
+            self.center_camera_to_position(x0, y0, speed=speed)
 
     def camera_show_player(self):
         if self.camera_mode == 'free' and not self.is_inside_camera(self.player):
@@ -1221,7 +1210,9 @@ class GameView(EmptyView):
         vp_w = self.camera_sprites.viewport_width
         vp_h = self.camera_sprites.viewport_height
         low_x, low_y = self.camera_sprites.goal_position
-        log.debug(f"Is target inside camera viewport? {vp_w}x{vp_h} {low_x}x{low_y} {obj}")
+        log.debug(
+            f"Is target inside camera viewport? {vp_w}x{vp_h} {low_x}x{low_y} {obj}"
+        )
         return (
             low_x < obj.center_x
             and obj.center_x < low_x + vp_w
@@ -1238,7 +1229,7 @@ class GameView(EmptyView):
             # moves
 
             # if self.player.moving or self.player.after_hit or self.player.after_move:
-                # return
+            # return
             try:
                 payload = self.level_output_queue.get_nowait()
             except queue.Empty:
@@ -1346,17 +1337,15 @@ class GameView(EmptyView):
         """
         # New command received, clear the text
         # self.draw_text = False
-        assert cmd != "q" # should to pass through filters and arrive here...
-        assert cmd != "quit" # should to pass through filters and arrive here...
-        assert cmd != "start" # should to pass through filters and arrive here...
+        assert cmd != "q"  # should to pass through filters and arrive here...
+        assert cmd != "quit"  # should to pass through filters and arrive here...
+        assert cmd != "start"  # should to pass through filters and arrive here...
         # if cmd == "start":
-            # self.gui_restart_level()
-            # return
+        # self.gui_restart_level()
+        # return
 
         # self.remove_box("more") # if a box is present, send 'more' event
 
-
-
     def object_update(self, who, payload):
         is_player = False
         if who == "player":
@@ -1397,7 +1386,6 @@ class GameView(EmptyView):
                 raise ValueError("Unknown action for payload: " + act)
             return
 
-
         if 'change/speed' in payload:
             payload['action'] = 'change/speed'
             payload['value'] = payload['change/speed']
@@ -1413,8 +1401,6 @@ class GameView(EmptyView):
         obj.append_action(payload)
         return
 
-
-
     def sprites_action(self, payload):
         if payload['action'] == 'hide':
             layer = self.layers[payload['layer']]
@@ -1536,7 +1522,6 @@ class GameView(EmptyView):
             multiline=True,
         )
 
-
     #
     # Handling events.
     # Interaction methods, mouse, keypresses, and how to communicate with
@@ -1564,14 +1549,12 @@ class GameView(EmptyView):
                 self.level.send_level_control(f"magic_breakpoint {x} {y}")
             return
 
-
     def on_mouse_drag(self, x, y, dx, dy, button, modifier):
         if button == arcade.MOUSE_BUTTON_LEFT:
             # dragging the map using the camera
             x, y = self.camera_sprites_center
             self.camera_mode = 'free'
-            self.center_camera_to_position(x - 2*dx, y - dy)
-
+            self.center_camera_to_position(x - 2 * dx, y - dy)
 
     def on_mouse_scroll(self, px_x, px_y, scroll_x, scroll_y):
         """
@@ -1607,27 +1590,33 @@ class GameView(EmptyView):
             else:
                 self.load_view("pause_game")
             return
-        if symbol == KEY.F and modifiers & KEY.MOD_CTRL:  # for fun, add a filter to the screen
+        if (
+            symbol == KEY.F and modifiers & KEY.MOD_CTRL
+        ):  # for fun, add a filter to the screen
             self.crt_filter_on = not self.crt_filter_on
             return
         if symbol == KEY.I and modifiers & KEY.MOD_CTRL:  # for 'i'nput
             # load file 'default.in' in base directory
             self.load_input_file(os.path.join(Config.ROOT_DIR, "default.in"))
 
-        if symbol == KEY.M and modifiers & KEY.MOD_CTRL: # for 'm'ake
+        if symbol == KEY.M and modifiers & KEY.MOD_CTRL:  # for 'm'ake
             self.compile_reload_level(None)
             return
-        if symbol == KEY.R and modifiers & KEY.MOD_CTRL: # restart level with Ctrl-R
+        if symbol == KEY.R and modifiers & KEY.MOD_CTRL:  # restart level with Ctrl-R
             self.trigger_restart_level()
             return
-        if symbol == KEY.V and modifiers & KEY.MOD_CTRL: # trigger validation as if level was finished
+        if (
+            symbol == KEY.V and modifiers & KEY.MOD_CTRL
+        ):  # trigger validation as if level was finished
             self.trigger_validation()
             return
         if symbol == KEY.P:  # only in 'bubble' mode (ComputeIt)
             if type(self.player) == spo.SpPlayerBubble:
                 self.player.prev_color()
             else:
-                log.warn("Cannot use 'P' key unless in special 'bubble' mode (ComputeIt)")
+                log.warn(
+                    "Cannot use 'P' key unless in special 'bubble' mode (ComputeIt)"
+                )
         if symbol == KEY.SPACE:
             if self.current_message_box:
                 self.current_message_box.show_all_message()
@@ -1636,12 +1625,14 @@ class GameView(EmptyView):
         if self.current_message_box is not None:
             if self.current_message_box_type == 'block':
                 # Do not continue interacting with level
-                log.debug(f"Message box is present, not passing key press {symbol} to inferior")
+                log.debug(
+                    f"Message box is present, not passing key press {symbol} to inferior"
+                )
                 return
             else:
                 self.close_message_box('more')
 
-        if symbol == KEY.C and modifiers & KEY.MOD_CTRL: # stop inferior execution
+        if symbol == KEY.C and modifiers & KEY.MOD_CTRL:  # stop inferior execution
             if self.level.is_running:
                 self.level.interrupt_inferior()
             elif self.level.is_validating:
@@ -1650,7 +1641,11 @@ class GameView(EmptyView):
                 log.debug(f"Will not Ctrl-C a not running inferior")
             return
 
-        if modifiers & KEY.MOD_CTRL or modifiers & KEY.MOD_ALT or modifiers & KEY.MOD_SHIFT:
+        if (
+            modifiers & KEY.MOD_CTRL
+            or modifiers & KEY.MOD_ALT
+            or modifiers & KEY.MOD_SHIFT
+        ):
             log.debug(f"Unknown key press {symbol} with modifier(s) {modifiers}")
             return
 
@@ -1707,7 +1702,6 @@ class GameView(EmptyView):
             else:
                 log.warn(message('sending/inf/pause').format(cmd=inferior_command))
 
-
     def load_input_file(self, file):
         log.info(f"Using {file=} to send gdb commands and input")
         if not os.path.exists(file):
@@ -1716,7 +1710,7 @@ class GameView(EmptyView):
 
         for l in open(file):
             if ">>>" in l:
-                _,cmd = l.split(" >>> ")
+                _, cmd = l.split(" >>> ")
             else:
                 cmd = l
             log.debug(f"auto-command: {cmd}")
@@ -1726,7 +1720,6 @@ class GameView(EmptyView):
                 self.level.send_console_command(cmd)
             # time.sleep(.05)
 
-
     def on_quit(self) -> None:
         """Handle quit event."""
         self.console_input_thread.set_tracker(None)
@@ -1737,4 +1730,3 @@ class GameView(EmptyView):
         self.level.print_thread.show_inferior_stdin(text)
         log.debug(f"Sending string to stdin: {text.encode()}")
         self.level.tracker.send_to_inferior_stdin(text, append_newline=True)
-
diff --git a/lib/graphic/views/menu/ingame.py b/lib/graphic/views/menu/ingame.py
index d9f5f94b..d8788f7d 100644
--- a/lib/graphic/views/menu/ingame.py
+++ b/lib/graphic/views/menu/ingame.py
@@ -16,6 +16,7 @@ from language import message
 
 from progress.progress_manager import ProgressionManager
 
+
 # pylint: disable=fixme unused-argument
 class GenericInGameView(EmptyView):
     """
@@ -153,7 +154,6 @@ class GenericInGameView(EmptyView):
 
 class EndView(GenericInGameView):
     def __init__(self):
-
         # Button creation
         buttons_infos = [
             ('REPLAY', self.on_click_replay),
@@ -165,7 +165,6 @@ class EndView(GenericInGameView):
         self.result_text = message('PAUSE')
         self.bg_color = COLOR.GRAY
 
-
     def add_details(self):
         if self.details not in self.v_box.children:
             self.v_box.add(self.details)
@@ -178,8 +177,6 @@ class EndView(GenericInGameView):
             if w in self.v_box.children:
                 self.v_box.remove(w)
 
-
-
     def set_victory(self):
         self.result_text = message('VICTORY')
         self.bg_color = COLOR.GO_GREEN
@@ -219,7 +216,6 @@ class EndView(GenericInGameView):
 
 class PauseView(GenericInGameView):
     def __init__(self):
-
         # Button creation
         buttons_infos = [
             ('RETURN_LEVEL', lambda _: self.load_view("game")),
diff --git a/lib/graphic/window.py b/lib/graphic/window.py
index a0171028..18d130a2 100644
--- a/lib/graphic/window.py
+++ b/lib/graphic/window.py
@@ -27,8 +27,11 @@ class BaseArcadeWindow(arcade.Window):
 
     def __init__(self, code_window_cls):
         super().__init__(
-            cst.Win.INIT_W, cst.Win.INIT_H, cst.Win.TITLE, resizable=True,
-            # update_rate=1/20  # impacts the refresh rate of the window, but 
+            cst.Win.INIT_W,
+            cst.Win.INIT_H,
+            cst.Win.TITLE,
+            resizable=True,
+            # update_rate=1/20  # impacts the refresh rate of the window, but
             # not the target FPS
         )  # type: ignore
         self.handle_signals()
@@ -64,7 +67,9 @@ class BaseArcadeWindow(arcade.Window):
         self.metadata = self.level_cls.metadata
 
         if self.code_window is None:
-            self.code_window = self.code_window_cls(self) # instantiate a window to show code, passing the main agdb window as parameter
+            self.code_window = self.code_window_cls(
+                self
+            )  # instantiate a window to show code, passing the main agdb window as parameter
         self.views["game"].launch_level(self.code_window)
 
         self.show_view(self.views["game"])
-- 
GitLab