Mentions légales du service

Skip to content
Snippets Groups Projects
Commit e47ad8e6 authored by Florent Bouchez Tichadou's avatar Florent Bouchez Tichadou
Browse files

initial import : separation from easytracker

parent 70ab1f87
No related branches found
No related tags found
No related merge requests found
Showing
with 1986 additions and 90 deletions
all:
bash copy_levels.sh
NOTES.org 0 → 100644
Notes en vrac
============================ Competences ======================
1- Trouver le/les bug
1.1- Comprendre la specification du programme
1.1.1- Formuler des hypotheses et des contrats sur des bouts de programme et des variables
1.1.2- Identifier les hypotheses qui ont le plus de chances de causer un bug
1.2- Savoir verifier une hypothese
1.2.1- Trouver un input qui pourrait faire planter l'hypothese
1.2.2- Identifier des variables et des endroits du programme ou il est interessant de tracer.
1.2.3- Ne pas ajouter de nouveaux bugs pendant le tracing (avec des effets de bord)
2- Correction d'un bug
2.1- Ne pas ajouter de nouveaux bugs pendant la correction
3- Outils de tracing
3.0- Lire le code et le simuler dans la tete
3.1- Print
3.2- Valgrind
3.3- GDB
===============================================================
les debuggers plus experimentes font plus de backward reasoning que les novices (de voir la sortie et d'essayer
de deduire ce qui a pu causer ca) plutot que du forward reasoning (on fait du tracing et on espere trouver une erreur)
On peut demander pour chaque exercice, combien de temps l'etudiant pense qu'il va mettre pour resoudre le bug.
On peut aussi demander tout ce qui peut planter dans le programme.
Utilisation de rr dans un module special (Florent a surement raison en fait)
Est ce qu'on a des niveaux sans debugger par ce que ya bcp d'autres methodes de tracing (dans la tete, papier, print) ?
Plusieurs bugs par niveau ?
On peut demander a l'etudiant de nommer les variables et fonctions qu'on va utiliser
pour qu'il s'approprie le code, on donne une description en texte et/ou en pseudocode et on demande un nom
dans la literature de debug, on demande d'abord aux etudiants d'implementer leur propre truc avant de le debugger.
Est ce qu'on ne donne que la spec ou des fonctions de validation ?
* Idees de niveaux / gameplay
Jeu plus à la baba is you que du zelda pur
-> moins de baston et plus de réflexion
Des clés à trouver pour ouvrir des portes.
De la lave, etc.
** Evolution gameplay
1 -> petit a petit on fait un snake (carte 2D, deplacement, generer pommes, attraper des pommes, score, agrandissement, condition de defaite) ya deja plusieurs choses a faire
2 -> on enleve l'agrandissement du serpent et la condition de defaite et on garde juste le deplacement et attraper des choses, on ajoute une collision avec des murs
2' -> etape intermediaire ou on sort juste a pied d'un labyrinthe et IA pour sortir ? Ici on peut mettre les inventaires avec des cles de couleurs pour ouvrir des portes
3 -> mtn on est plutot en sokoban, il faut mettre des caisses sur des emplacements finaux (algorithme pour pousser les caisses, condition de victoire, compteur de tour).
4 -> projet "final" faire une IA qui joue au sokoban ?
* Idées de niveaux / bugs
On demande a des etudiants d'implementer des specs et on regarde les bugs qu'ils font pour les mettre dans agdbentures ?
** niveaux avec "beaucoup" de modifications (mais pas forcement dur)
calcul de denivele ou on ne fait que une somme alors que parfois il faut soustraire (ajout complet du if)
** bugs arithmetique
- mauvais calcul de score quand on mange un truc dans snake
** bugs tableaux
- implementation du passage d'un bord a l'autre (tore), avec le bug le deplacement sort juste de la map
- meme chose mais avec des bornes par ce que cette fois il y a des murs et on peut en faire un parametre d'initialisation de la map dans les niveaux futurs.
** bugs tableaux de taille dynamique
- les elements ne sont pas copies lors de la reallocation
** bugs de listes chainees
- inventaire sous forme LC
=> quand ajout 1er element, on perd le reste
- boucle infinie sur une recherche
** bug random
- module random perso, qui renvoie toujours la meme suite de nombres
- pb avec seed
- seed pas utilisée
** bugs memoire
- malloc sur sizeof(*structure) au lieu de sizeof(structure)
=> espace trop petit
-> intro valgrind ?
- passage par copie sans pointeur et on perd le resultat
- segfaults
pointeurs déclarés mais non alloués
** algorithmes (derniers niveaux)
- tri de pilier de differentes tailles pour faire un escalier, plusieurs off-by-one dans les tris
- plus court chemin sans tests de cycle.
- backtracking dans un labyrinthe sans le backtrack (cest ptet un peu chaud ?)
=============== DEROULEMENT ==================
Partie 0.5 => Exos sans bugs, il faut formuler des invariants
Il faut trouver des inputs chiants qui peuvent faire planter le programme (cest tres proche du testing)
A partir de maintenant pour chaque exo avant de commencer on demande une liste d'hypotheses a verifier (ce qui peut avoir mal tourne)
==============================
Partie 1 => Tracing only, single step ou full run (pas besoin de controle, juste regarder l'etat du programme)
differentes categories melangees "Off by one" au sens large:
- vrai off by one (indice de boucle, de tableau), erreur de calcul en general
- il faut mettre une ligne dans/dehors une boucle/condition
- il faut ajouter enlever une ligne dans une sequence d'instruction
- bug lie au langage (ici C) :
* passage par copie/reference
* bug memoire (voir section bug memoire)
* juste segfault (on fait run a la segfault et on regarde, la il faut gdb)
/!\ On ne fait pas de reecriture complete de bout de code
bug direct au debut
puis on ajoute l'usage de structures de donnees mais sans bug dedans, juste usage
direct ou indirect ensuite
programmes court, maxi 50-60 lignes y compris definitions de structure
structures possibles :
Liste chainees
Tableaux dynamiques
bug direct cest que la cause est directement ce qu'on print/trace
bug indirect, il faut comprendre comment une valeur est construite et le bug est dans la construction (resultat d'algorithme.
mauvais usage d'une structure)
bug de structure, un invariant de structure est casse ou il y a un bug de langage.
classification partie 1
| off by one/arithmetic | control flow | add/remove instruction | language bug
direct | | | |
direct + struct sans bug | | | |
indirect | | | |
****************
3eme dimension => Programe long au runtime (et eventuellement en code) qui fait office de transition
- Transition single step mieux que full run par ce que bug observable des le debut et les structures de donnees sont encore petites et lisibles
Exactement comme Partie 1 mais les programmes sont plus longs (au moins en runtime pas forcement en taille de code, mais ca peut)
Contrainte qui reste "le bug doit etre observable tot dans l'execution".
=========================
Partie 2 => Tracing et single step intractable on doit ajouter breakpoint, watchpoint
Dans cette partie les programmes sont plus longs potentiellement avec des fichiers d'input ou des problemes complexes (en terme de calcul pas en terme de difficulte).
On garde la meme classification que partie 1 avec direct/indirect etc mais cette fois les bugs arrivent a des effets de bords.
Il faut qu'on ne puisse pas single stepper ou alors que avec un print il faille filtrer les print (possible de trouver le bug en ne printant pas systematiquement)
Technique:
- break function pour regarder les arguments
* cas special des fonctions recursives ou on peut faire ca
- break conditionnel pour s'arreter quand on condition est vraie (par exemple invariant viole)
- watchpoint
* simple tracage pour voir l'evolution d'une variable
* watchpoint memoire pour detecter des alias
=========================
Partie 3 => "Challenge" parfois il faut completement reecrire des bouts de programme (cette fois on suppose qu'on trouve bien les bugs mais cest dur a corriger maintenant en plus)
**** METRIQUES *****
- Temps
- Nombre de compilation
- Nombre d'execution
# Agdbentures
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.inria.fr/CORSE/agdbentures.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.inria.fr/CORSE/agdbentures/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
Separating Agdbentures from Easytracker.
#!/usr/bin/env python
"""
Starting point of the game.
This program will launch the graphical window
and will show a console.
"""
import logging
from main_window import MainWindow
if __name__ == "__main__":
# silent logs
# change the logging level if you are debugging
logging.basicConfig(level=logging.INFO)
app = MainWindow()
app.start()
""" A minimalist agdbentures version with just CLI to test levels"""
from level_controller import level_controller
from easytracker import init_tracker
tracker = init_tracker("GDB")
level_controller().load_level()
while True:
print(tracker.get_console_output()) # type: ignore
command = input("Command: ")
if command == "quit":
tracker.force_program_stop()
break
if command == "unlock":
# check if current level is a success and load next level otherwise do nothing
if level_controller().current_level.success:
level_controller().unlock_next_level()
level_controller().load_level()
continue
pause_reason = tracker.send_direct_command(command)
print(pause_reason)
level_controller().on_tracker_breaked(command, pause_reason)
T E P I D M O N K E Y F O N T S
freeware fonts for a freeware world
Site: http://www.tepidmonkey.com/
E-mail: brandon@tepidmonkey.com
Thanks for your interest in my fonts!
For help on how to unzip, unstuff or install one of my
fonts, please visit my site at
www.tepidmonkey.com and go to the Help section.
If you have any comments or questions, you can e-mail
me at brandon@tepidmonkey.com and I'll try to reply as
soon as possible.
Every week, I present a brand new original font for
your downloading pleasure, so be sure to visit my web
site every Sunday.
You may use this font(s) for non-commercial and
commercial purposes. You are not allowed to sell this
font for any fee at all. You are allowed to
redistribute it as long as you don't charge ANYTHING
for it (at all) and if you include this unaltered
Read Me file. You may not change any aspect of the font
file or this file.
For the full set of terms of use (which override what
is listed here), go to www.tepidmonkey.com
and visit the Terms section.
\ No newline at end of file
File added
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="10" height="10" tilewidth="32" tileheight="32" infinite="0" nextlayerid="4" nextobjectid="1">
<tileset firstgid="1" source="tilesets/Basic.tsx"/>
<layer id="3" name="Grid" width="10" height="10">
<data encoding="csv">
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4
</data>
</layer>
<layer id="1" name="Marker" width="10" height="10">
<data encoding="csv">
5,3,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="2" name="Moving" width="10" height="10">
<data encoding="csv">
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
</data>
</layer>
</map>
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="12" height="12" tilewidth="16" tileheight="16" infinite="0" nextlayerid="5" nextobjectid="1">
<tileset firstgid="1" source="tilesets/0x72_DungeonTilesetII_v1.4.tsx"/>
<layer id="1" name="Grid" width="12" height="12">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
130,130,130,130,162,130,131,130,130,130,195,130,
131,195,130,130,130,194,130,130,130,130,130,130,
130,130,132,195,131,162,130,130,194,130,130,162,
194,130,132,195,130,130,130,195,132,162,130,130,
130,130,131,130,130,131,130,130,131,130,194,131,
130,195,130,130,162,130,195,130,194,130,130,130,
194,130,131,130,130,131,162,130,130,195,130,130,
162,132,195,132,130,131,130,130,131,130,131,194,
130,132,130,130,162,130,130,132,130,130,132,130,
0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="4" name="Border" width="12" height="12">
<data encoding="csv">
228,228,228,228,228,228,228,228,228,228,228,228,
259,34,34,34,34,34,34,34,34,34,34,260,
258,0,0,0,0,0,0,0,0,0,0,257,
258,0,0,0,0,0,0,0,0,0,0,257,
258,0,0,0,0,0,0,0,0,0,0,257,
258,0,0,0,0,0,0,0,0,0,0,257,
258,0,0,0,0,0,0,0,0,0,0,257,
258,0,0,0,0,0,0,0,0,0,0,257,
258,0,0,0,0,0,0,0,0,0,0,257,
258,0,0,0,0,0,0,0,0,0,0,257,
291,325,325,325,325,325,325,325,325,325,325,292,
323,323,323,323,323,323,323,323,323,323,323,324
</data>
</layer>
<layer id="2" name="Marker" width="12" height="12" visible="0">
<data encoding="csv">
196,358,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="Moving" width="12" height="12" visible="0">
<data encoding="csv">
169,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
</map>
assets/tileset_images/0x72_DungeonTilesetII_v1.4.png

34.9 KiB

assets/tileset_images/character.png

760 B

assets/tileset_images/exit.png

768 B

assets/tileset_images/grid.png

607 B

assets/tileset_images/start.png

717 B

This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.5" tiledversion="1.7.2" name="Basic" tilewidth="32" tileheight="32" tilecount="4" columns="0">
<grid orientation="orthogonal" width="1" height="1"/>
<tile id="1">
<image width="32" height="32" source="../tileset_images/character.png"/>
</tile>
<tile id="3">
<image width="32" height="32" source="../tileset_images/grid.png"/>
</tile>
<tile id="4">
<image width="32" height="32" source="../tileset_images/start.png"/>
</tile>
<tile id="2">
<image width="32" height="32" source="../tileset_images/exit.png"/>
</tile>
</tileset>
#!/usr/bin/bash
mkdir -p levels/scripts/$1
mkdir -p levels/source/$1
\ No newline at end of file
"""Level controller."""
from subprocess import run
import os
import shutil
from importlib import import_module
from easytracker import tracker_interface, PauseReason
DEBUG_LEVEL = -1 # level number to debug, -1 to use progress file as usual
DEBUG_EVENTS = 0 # 0 1
# load level list from file and append level number for alphabetical order
LEVEL_LIST = ["first_level", "move", "snake", "enter_shop", "last_level"]
def create_folder_if_not_exist(folder):
"""creates the given folder if it doesn't exist yet"""
try:
os.mkdir(folder)
except FileExistsError:
pass
# pylint: disable=too-many-instance-attributes
class LevelController:
"""Level controller.
This class is responsible to load the python code
for the current level, and to do the level switch
when the user goes to the next level.
"""
def __init__(self):
# creates the saves directory if it doesn't exist
create_folder_if_not_exist("saves")
# init common directories
self.agdbenture_dir = os.path.join(os.path.dirname(__file__))
self.saves_dir = os.path.join(self.agdbenture_dir, "saves")
self.levels_dir = os.path.join(self.agdbenture_dir, "levels")
self.levels_source_dir = os.path.join(self.levels_dir, "source")
self.levels_script_dir = os.path.join(self.levels_dir, "scripts")
# load past progress from file
self.progress = []
self.__load_progress()
# compute next level to do
self.current_level_number = 0
if self.progress:
self.current_level_number = LEVEL_LIST.index(self.progress[-1]) + 1
# Debug option to go to a specific level
if DEBUG_LEVEL != -1:
self.current_level_number = DEBUG_LEVEL
self.current_level_name = LEVEL_LIST[self.current_level_number]
# prepare empty level data
self.current_level = None
self.working_directory = None
self.script_directory = None
# Progress management
def __load_progress(self):
"""Loads all the levels played by the user from saves/progress.txt"""
try:
with open(
os.path.join(self.saves_dir, "progress.txt"), "r", encoding="utf-8"
) as progress_file:
self.progress = [name.strip() for name in progress_file.readlines()]
except FileNotFoundError:
# We do nothing if no progress file is found
pass
def __save_progress(self):
"""Saves the current progress into the progress file"""
with open(
os.path.join(self.saves_dir, "progress.txt"), "w", encoding="utf-8"
) as progress_file:
for name in self.progress:
print(name, file=progress_file)
def clear_progress(self):
"""Clears the current progress and saves it into the progress file"""
self.progress = []
self.__save_progress()
# level loading and success
def load_level(self):
"""Prepare the level code and loads it into easytracker.
It loads the level control script.
For that, python dynamicity is used to instantiate
the next level class from its name.
Thank you python :)"""
self.working_directory = os.path.join(self.saves_dir, self.current_level_name)
self.__prepare_level_source_code()
self.__prepare_level_script()
tracker_interface().send_direct_command(f"cd {self.working_directory}")
tracker_interface().load_program(f"{self.current_level.executable_name}")
def __prepare_level_source_code(self):
"""copy or load the source code and compiles it"""
try:
os.mkdir(self.working_directory)
src_dir = os.path.join(self.levels_source_dir, self.current_level_name)
# if the folder doesn't exist, copy the source code in it
shutil.copytree(src_dir, self.working_directory, dirs_exist_ok=True)
except FileExistsError:
pass
# Compile once
run(["make", "-C", self.working_directory, "-s"], check=False)
def __prepare_level_script(self):
"""dynamicaly loads the current level module"""
self.script_directory = os.path.join(
self.levels_script_dir, self.current_level_name
)
# Import level class and instatiate level
level_class = import_module(
f"levels.scripts.{self.current_level_name}.level"
).Level
self.current_level = level_class(self.working_directory, self.script_directory)
def unlock_next_level(self):
"""Updates progress and saves it"""
# add the current level to the progress
self.progress.append(self.current_level_name)
# load the next level
self.current_level_number += 1
self.current_level_name = LEVEL_LIST[self.current_level_number]
self.__save_progress()
# event forwarding
def on_tracker_breaked(self, command: str, pause_reason: PauseReason):
"""Sends the GDB event to the current level to be processed"""
if DEBUG_EVENTS:
print(pause_reason)
if self.current_level is not None:
self.current_level.on_tracker_breaked(command, pause_reason)
instance = LevelController()
def level_controller():
"""returns a global instance to the level controller"""
return instance
*.o
level
MAINPROG := level
OBJECTS := read_input.o main.o
CC := gcc
CFLAGS := -g
all: level
$(MAINPROG): $(OBJECTS)
$(CC) $(OBJECTS) -o $@
clean:
rm *.o
clear: clean
rm level
.PHONY: all clean clear
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment