From f68ebe2eafcff406ab0394036ecbb19560663756 Mon Sep 17 00:00:00 2001
From: mszczepa <marin.szczepanski@inria.fr>
Date: Mon, 23 May 2022 13:35:10 +0200
Subject: [PATCH] Fullgame engine as lib + level interr avec la lib

---
 engines/fullgame/action.c            | 171 +++++++-------------
 engines/fullgame/action.h            |  52 +++----
 engines/fullgame/agdbentures.h       |   6 +-
 engines/fullgame/common.c            |  40 +----
 engines/fullgame/common.h            |  34 +---
 engines/fullgame/events.c            |  75 ++++++---
 engines/fullgame/events.h            |  36 ++---
 engines/fullgame/main                | Bin 24008 -> 0 bytes
 engines/fullgame/map.c               | 219 +++++++-------------------
 engines/fullgame/map.h               |  59 +++----
 engines/fullgame/read_input.c        | 150 ++++++++++++------
 engines/fullgame/read_input.h        |  30 ++--
 levels/interrupteurs/Makefile        |   7 +-
 levels/interrupteurs/action.c        | 224 ---------------------------
 levels/interrupteurs/action.h        |  62 --------
 levels/interrupteurs/agdbentures.h   |   9 --
 levels/interrupteurs/common.c        |  45 ------
 levels/interrupteurs/common.h        |  46 ------
 levels/interrupteurs/custom_map.c    | 116 ++++++++++++++
 levels/interrupteurs/custom_map.h    |  38 +++++
 levels/interrupteurs/events.c        |  58 -------
 levels/interrupteurs/events.h        |  37 -----
 levels/interrupteurs/events_map.c    |  61 ++++----
 levels/interrupteurs/events_map.h    |  19 +--
 levels/interrupteurs/input_manager.c |  57 +++++++
 levels/interrupteurs/input_manager.h |   9 ++
 levels/interrupteurs/main.c          |  66 +++-----
 levels/interrupteurs/map.c           | 208 -------------------------
 levels/interrupteurs/map.h           |  69 ---------
 levels/interrupteurs/read_input.c    |  83 ----------
 levels/interrupteurs/read_input.h    |  32 ----
 31 files changed, 626 insertions(+), 1492 deletions(-)
 delete mode 100755 engines/fullgame/main
 delete mode 100644 levels/interrupteurs/action.c
 delete mode 100644 levels/interrupteurs/action.h
 delete mode 100644 levels/interrupteurs/agdbentures.h
 delete mode 100644 levels/interrupteurs/common.c
 delete mode 100644 levels/interrupteurs/common.h
 create mode 100644 levels/interrupteurs/custom_map.c
 create mode 100644 levels/interrupteurs/custom_map.h
 delete mode 100644 levels/interrupteurs/events.c
 delete mode 100644 levels/interrupteurs/events.h
 create mode 100644 levels/interrupteurs/input_manager.c
 create mode 100644 levels/interrupteurs/input_manager.h
 delete mode 100644 levels/interrupteurs/map.c
 delete mode 100644 levels/interrupteurs/map.h
 delete mode 100644 levels/interrupteurs/read_input.c
 delete mode 100644 levels/interrupteurs/read_input.h

diff --git a/engines/fullgame/action.c b/engines/fullgame/action.c
index 1e162d54..9c6b7aae 100644
--- a/engines/fullgame/action.c
+++ b/engines/fullgame/action.c
@@ -21,68 +21,49 @@
 
 #include "action.h"
 
-/***********************************/
-/*   Constants, types, variables   */
-/***********************************/
-
-/***********************************/
-/*      Methods and functions      */
-/***********************************/
-
-void turn_right (void)
-{
+void turn_right(void) {
+    map * m = current_map();
     int d;
-    switch (player_direction) {
+    switch (m->player_direction) {
         case UP: d=RIGHT; break;
         case LEFT: d=UP; break;
         case DOWN: d=LEFT; break;
         case RIGHT: d=DOWN; break;
         default: assert(false);
     }
-    player_direction = d;
+    m->player_direction = d;
 }
 
-void turn_left (void)
-{
+
+void turn_left(void) {
+    map * m = current_map();
     int d;
-    switch (player_direction) {
+    switch (m->player_direction) {
         case UP: d=LEFT; break;
         case LEFT: d=DOWN; break;
         case DOWN: d=RIGHT; break;
         case RIGHT: d=UP; break;
         default: assert(false);
     }
-    player_direction = d;
+    m->player_direction = d;
 }
 
-void coord_in_dir_n (int y, int x, int dir, int *cy, int *cx, int n)
-{
-    assert (dir >= 1 && dir <= 9);
 
+void coord_in_dir_n(int y, int x, direction dir, int *cy, int *cx, int n) {
     // warning: (0, 0) is top left
 
     // vertical movement
-    if (dir >= 7) {
-        // 7, 8, 9
+    if (dir == UP) {
         *cy = y - n;
-        /* BUGLINE: forgetting that y = 0 is at the top
-         * y = player_y + 1;
-         */
-    } else if (dir <= 3) {
-        // 1, 2, 3
+    } else if (dir == DOWN) {
         *cy = y + n;
     } else {
         *cy = y;
     }
 
-    if (dir % 3 == 0) {
-        // 3, 6, 9
+    if (dir == RIGHT) {
         *cx = x + n;
-        /* BUGLINE: thinking x is also inverted because y is
-         * x = pox_x - 1;
-         */
-    } else if (dir % 3 == 1) {
-        // 1, 4, 7
+    } else if (dir == LEFT) {
         *cx = x - n;
     } else {
         *cx = x;
@@ -90,101 +71,107 @@ void coord_in_dir_n (int y, int x, int dir, int *cy, int *cx, int n)
 }
 
 
-void coord_in_dir (int y, int x, int dir, int *cy, int *cx)
-{
-    coord_in_dir_n (y, x, dir, cy, cx, 1);
+void coord_in_dir(int y, int x, direction dir, int *cy, int *cx) {
+    coord_in_dir_n(y, x, dir, cy, cx, 1);
 }
 
-void player_in_dir(int *cy, int *cx)
-{
-    coord_in_dir (player_y, player_x, player_direction, cy, cx);
+
+void player_in_dir(int *cy, int *cx) {
+    map * m = current_map();
+    coord_in_dir(m->player_y, m->player_x, m->player_direction, cy, cx);
 }
 
-void player_in_dir_n(int *cy, int *cx, int n)
-{
-    coord_in_dir_n (player_y, player_x, player_direction, cy, cx, n);
+
+void player_in_dir_n(int *cy, int *cx, int n) {
+    map * m = current_map();
+    coord_in_dir_n(m->player_y, m->player_x, m->player_direction, cy, cx, n);
 }
 
 
-int player_idx_in_dir(void)
-{
+int player_idx_in_dir(void) {
     int y, x;
     player_in_dir(&y, &x);
-    return coord_idx (y, x);
+    return coord_idx(y, x);
 }
 
-int player_idx_in_dir_n(int n)
-{
+
+int player_idx_in_dir_n(int n) {
     int y, x;
     player_in_dir_n(&y, &x, n);
-    return coord_idx (y, x);
+    return coord_idx(y, x);
 }
 
+
 void up() {
-    player_direction = UP;
+    current_map()->player_direction = UP;
     forward();
 }
 
+
 void up_n(unsigned n) {
-    player_direction = UP;
+    current_map()->player_direction = UP;
     forward_n(n);
 }
 
+
 void down() {
-    player_direction = DOWN;
+    current_map()->player_direction = DOWN;
     forward();
 }
 
+
 void down_n(unsigned n) {
-    player_direction = DOWN;
+    current_map()->player_direction = DOWN;
     forward_n(n);
 }
 
+
 void left() {
-    player_direction = LEFT;
+    current_map()->player_direction = LEFT;
     forward();
 }
 
+
 void left_n(unsigned n) {
-    player_direction = LEFT;
+    current_map()->player_direction = LEFT;
     forward_n(n);
 }
 
+
 void right() {
-    player_direction = RIGHT;
+    current_map()->player_direction = RIGHT;
     forward();
 }
 
+
 void right_n(unsigned n) {
-    player_direction = RIGHT;
+    current_map()->player_direction = RIGHT;
     forward_n(n);
 }
 
 
-void forward (void)
-{
+void forward(void) {
     int y, x;
-    coord_in_dir (player_y, player_x, player_direction, &y, &x);
+    map * m = current_map();
+    coord_in_dir(m->player_y, m->player_x, m->player_direction, &y, &x);
 
     // in this version there is no screen transition
     // screen edges act as obstaces
     if (collision(y, x)) {
-        printf ("You bump into something!\n");
+        printf("You bump into something!\n");
         return ;
     }
 
-    player_x = x;
-    player_y = y;
+    m->player_x = x;
+    m->player_y = y;
 }
 
-void forward_n (unsigned num_steps)
-{
+
+void forward_n(unsigned num_steps) {
     for (unsigned int i=0; i<num_steps; i++) {
         forward();
         /* the last apply_event will be done by the main loop
-        this avoids triggering an event twice
-        BUGIDEA: remove the next if and observe how events are applied twice at the end
-        of a FORWARD_N */
+        this avoids triggering an event twice */
         if (i < num_steps - 1)
             apply_events();
         if (exit_main_loop)
@@ -192,60 +179,16 @@ void forward_n (unsigned num_steps)
     }
 }
 
+
 int collision(int y, int x) {
-    if (x < 0 || x > SCREEN_WIDTH - 1 || y < 0 || y > SCREEN_HEIGHT -1) {
-        /* BUGLINE: off by one
-         * if (x < 0 || x > SCREEN_WIDTH || y < 0 || y > SCREEN_HEIGHT) {
-         */
+    map * m = current_map();
+    if (x < 0 || x > m->width - 1 || y < 0 || y > m->height -1) {
         return -1;
     }
 
-    // complex but allows modifiying the possible obstacles quickly. Maybe strlen(OBSTACLES) could be a literal defined in move.h
-    /* BUGIDEA:
-     * adding a char at the end of OBSTACLES, hence erasing the \0, making 
-     * strlen fail...
-     */
     if (is_obstacle(y, x)) {
         return 1;
     }
 
     return 0;
 }
-
-void talk(void)
-{
-    int y, x;
-    player_in_dir_n(&y, &x, 2); /* talk at distance 2 */
-
-    monster *mon = is_monster(y, x);
-    if (!mon) {
-        printf("There is no one to talk to here.\n");
-        return;
-    }
-
-    talk_monster(mon);
-}
-
-
-
-void fight(equipment eq)
-{
-    int y, x;
-    player_in_dir(&y, &x);
-
-    monster *mon = is_monster(y, x);
-    if (!mon) {
-        printf("There is no monster to fight here.\n");
-        return;
-    }
-
-    fight_monster(mon, eq);
-
-    map *m = current_map();
-
-    /* BUGIDEA: forgetting to remove the monster from the map */
-    int i = coord_idx(mon->pos_y, mon->pos_x);
-    m->monsters[i] = NULL;
-    free(mon);
-
-}
diff --git a/engines/fullgame/action.h b/engines/fullgame/action.h
index c6c63fc0..1e3302cd 100644
--- a/engines/fullgame/action.h
+++ b/engines/fullgame/action.h
@@ -2,53 +2,39 @@
 #define ACTION_H
 
 #include "agdbentures.h"
+#include <stdlib.h>
 
-// the width of a screen, in tiles
-#define SCREEN_WIDTH 60
-
-// the height of the screen, in tiles
-#define SCREEN_HEIGHT 8
-
-#define UP 8
-#define DOWN 2
-#define LEFT 4
-#define RIGHT 6
-
-/**
- * pos_x : current x position of the character
- * pos_y : current y position of the character
- * dir : Defines the direction in which the player moves. 
- * Must be in [1..9], where 5 is no movement, 1 is down-left, 9 is top-right... Do you follow?
- * If dir is not in [1..9], it is treated as 5, so no movement occurs.
- */
-
-void turn_right (void);
-void turn_left (void);
+void turn_right(void);
+void turn_left(void);
 
 
 /**
  * Computes the coordinates from (x,y) when moving 1 square in direction 'dir'
  * and stores the results in pointers (*cx, *cy).
  */
-void coord_in_dir (int y, int x, int dir, int *cy, int *cx);
+void coord_in_dir (int y, int x, direction dir, int *cy, int *cx);
 
 /**
  * Idem but when moving 'n' squares in direction 'dir'.
  */
-void coord_in_dir_n (int y, int x, int dir, int *cy, int *cx, int n);
+void coord_in_dir_n(int y, int x, direction dir, int *cy, int *cx, int n);
+
+// Same 2 functions but using the player's position
+void player_in_dir(int *cy, int *cx);
+void player_in_dir_n(int *cy, int *cx, int n);
 
 // Functions to move the character
-void up();
+void up(void);
 void up_n(unsigned n);
-void down();
+void down(void);
 void down_n(unsigned n);
-void left();
+void left(void);
 void left_n(unsigned n);
-void right();
+void right(void);
 void right_n(unsigned n);
 
-void forward (void);
-void forward_n (unsigned num_steps);
+void forward(void);
+void forward_n(unsigned num_steps);
 
 /**
  * Verifies if the player can move to tile (x, y).
@@ -59,7 +45,9 @@ void forward_n (unsigned num_steps);
  */
 int collision(int x, int y);
 
-void talk(void);
-void fight(equipment eq);
+/**
+ * Activates the switch in front of the player.
+ */
+void touch(void);
 
-#endif//ACTION_H
+#endif //ACTION_H
diff --git a/engines/fullgame/agdbentures.h b/engines/fullgame/agdbentures.h
index 7eaeabd4..80fb6fa2 100644
--- a/engines/fullgame/agdbentures.h
+++ b/engines/fullgame/agdbentures.h
@@ -2,11 +2,9 @@
 #define AGDBENTURES_H
 
 #include "common.h"
-#include "monster.h"
 #include "map.h"
 #include "action.h"
-#include "shop.h"
 #include "events.h"
-#include "items.h"
+#include "read_input.h"
 
-#endif//AGDBENTURES_H
+#endif //AGDBENTURES_H
diff --git a/engines/fullgame/common.c b/engines/fullgame/common.c
index 5a23adb6..9b3c3deb 100644
--- a/engines/fullgame/common.c
+++ b/engines/fullgame/common.c
@@ -1,50 +1,14 @@
 #include "common.h"
 
-const char *str_map =
-"\
-                                             ~~~~~          \n\
-                +-----+                      ~~~~~          \n\
-                +--D--+                      ~~~~~          \n\
-                                             ~~~~~          \n\
-                                               T        >   \n\
- @  $$$$$$$$$$$$$                            ~~~~~          \n\
-                                             ~~~~~          \n\
-";
-
-const char *str_shop =
-"\
-+---------+\n\
-| [[[/))) |\n\
-|    S    |\n\
-+---------+\n\
-|         |\n\
-|    @    |\n\
-+----D----+\n\
-";
-
-// x position of the character
-int player_x = -1;
-
-// y position of the character
-int player_y = -1;
-
-// Initial direction: facing East
-int player_direction = 6;
-
-// nomber of hit/health points
-int health_points = 20;
-
 // when true, the main loop ends. Should only be used in level_failed and level_success
 bool exit_main_loop = false;
 
-void level_failed(void)
-{
+void level_failed(void) {
     printf("DEFEAT!\n");
     exit_main_loop = true;
 }
 
-void level_success()
-{
+void level_success() {
     printf("VICTORY!\n");
     exit_main_loop = true;
 }
diff --git a/engines/fullgame/common.h b/engines/fullgame/common.h
index f546c244..75c53a0a 100644
--- a/engines/fullgame/common.h
+++ b/engines/fullgame/common.h
@@ -6,41 +6,11 @@
 #include <string.h>
 #include <assert.h>
 #include <stdbool.h>
-#include "items.h"
 
-
-#define max(a,b) (a>b?a:b)
-
-/** number of slots in the player's inventory.
- * Each slot can stack several items of the same type, up to stack_limit
-*/
-#define INVENTORY_SIZE MAX_POSSIBLE_ITEMS
-
-// the list of all possible items
-type * list[MAX_POSSIBLE_ITEMS];
-
-// the player's inventory
-instance inventory[INVENTORY_SIZE];
-
-// x position of the character
-extern int player_x;
-
-// y position of the character
-extern int player_y;
-
-// the direction the player is facing
-extern int player_direction;
-
-// the player's life
-extern int health_points;
-
-const char* str_map;
-const char * str_shop;
-
-bool exit_main_loop;
+extern bool exit_main_loop;
 
 void level_failed(void);
 
 void level_success(void);
 
-#endif//COMMON_H
+#endif //COMMON_H
diff --git a/engines/fullgame/events.c b/engines/fullgame/events.c
index af3be273..aa050034 100644
--- a/engines/fullgame/events.c
+++ b/engines/fullgame/events.c
@@ -20,36 +20,65 @@
 
 #include "events.h"
 
-void load_events() {
-    // The events have to be hardcoded...
-    // add more events here (the list MUST be full, that is to say have NUMBER_OF_EVENTS elements)
-    event_list[0].trigger = walks_on_item;
-    event_list[0].resolution = pick_item;
+event * event_list = NULL;
 
-    event_list[1].trigger = can_enter_building;
-    event_list[1].resolution = enter_building;
+void add_event(void (* event_to_add) (void)) {
+    if (!event_list) {
+        event_list = malloc(sizeof(event));
+        event_list->event = event_to_add;
+        event_list->next = NULL;
+        return;
+    }
 
-    event_list[2].trigger = walks_on_water;
-    event_list[2].resolution = drown;
+    event * cur = event_list;
 
-    event_list[3].trigger = walks_on_monster;
-    event_list[3].resolution = hit_by_monster;
+    while (cur->next){
+        cur = cur->next;
+    }
 
-    event_list[4].trigger = death_imminent;
-    event_list[4].resolution = death;
-    
-    event_list[5].trigger = verify_exit;
-    event_list[5].resolution = event_level_success;
+    cur->next = malloc(sizeof(event));
+    cur->next->event = event_to_add;
+    cur->next->next = NULL;    
 }
 
-void apply_events() {
-    int trig_res;
+void remove_event(void (* event_to_remove) (void)) {
+    if (!event_list)
+        return;
+
+    event * cur = event_list;
+    event * pred = NULL;
 
-    for (int i = 0; i < NUMBER_OF_EVENTS; i++) {
-        trig_res = event_list[i].trigger();
-        if (trig_res) {
-            event_list[i].resolution(trig_res);
-        }
+    while (cur->event != event_to_remove && cur) {
+        pred = cur;
+        cur = cur->next;
     }
     
+    if (!cur)
+        return;
+    
+    if (!pred) {
+        event_list = cur->next;
+    } else {
+        pred->next = cur->next;
+    }
+
+    free(cur);
+}
+
+void remove_all_events(void) {
+    event * to_free;
+
+    while (event_list) {
+        to_free = event_list;
+        event_list = to_free->next;
+        free(to_free);
+    }
+}
+
+void apply_events(void) {
+    event * cur = event_list;
+    while (cur != NULL) {
+        cur->event();
+        cur = cur->next;
+    }    
 }
diff --git a/engines/fullgame/events.h b/engines/fullgame/events.h
index a93f4a64..f13c78c2 100644
--- a/engines/fullgame/events.h
+++ b/engines/fullgame/events.h
@@ -1,32 +1,20 @@
-#pragma once
+#ifndef EVENTS_H
+#define EVENTS_H
 
-#include "common.h"
-// include all files containing trigger and resolution functions
-#include "events_player.h"
-#include "events_map.h"
+#include "agdbentures.h"
 
-#define NUMBER_OF_EVENTS 6
-
-// The structure of a single event
-typedef struct _event {
-    // the trigger function, only reads and can't write the state of the game
-    int (*trigger)(void);
-
-    /* the resolution function, called if trigger returned a non-null value
-     * the parameter trig will be the result of trigger (in some cases this may avoid redundant checks)
-     */
-    void (*resolution) (int trig);
+typedef struct Event {
+    void (* event) (void);
+    struct Event * next;
 } event;
 
-event event_list[NUMBER_OF_EVENTS];
-
-
-/**
- * Reads all events the game wants and loads them in a table to call them later.
- */
-void load_events();
+void add_event(void (* event_to_add) (void));
+void remove_event(void (* event_to_remove) (void));
+void remove_all_events(void);
 
 /**
  * Applies all triggers and events in sequence. Due to this, the event ordering matters.
  */
-void apply_events();
+void apply_events(void);
+
+#endif // EVENTS_H
diff --git a/engines/fullgame/main b/engines/fullgame/main
deleted file mode 100755
index a06e1d1a13a25850ead7f0fb6cdfdd8f620355ca..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 24008
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
X-LB-)z4!e3chdtdlx~}X4Q2ldd5peC

diff --git a/engines/fullgame/map.c b/engines/fullgame/map.c
index bf46bfd3..93c51c11 100644
--- a/engines/fullgame/map.c
+++ b/engines/fullgame/map.c
@@ -1,207 +1,94 @@
 #include "map.h"
 
+
 static map_stack mstack;
 
-void init_map_stack(void)
-{
+
+void init_map_stack(void) {
     mstack.length = 0;
 }
 
-map* current_map (void)
-{
+
+map * current_map(void) {
+    if (mstack.length <= 0)
+        return NULL;
     return &mstack.maps[mstack.length-1];
 }
 
 
-void load_map(const char * str_map, const char * new_name) {
-    map *m;
-
-    /*BUGIDEA : forgetting to save player position */
-    if (mstack.length > 0) {
-        m = current_map();
-        m->player_x = player_x;
-        m->player_y = player_y;
+map * load_map(const char * name, int width, int height, int player_x, int player_y, unsigned player_direction) {
+    if (mstack.length >= MAX_MAPS - 1) {
+        printf("load_map: can't load a new map, the maximum number has been reached.\n");
+        return current_map();
     }
 
+    map * m;
     mstack.length++;
-
     m = current_map();
-    m->exit_x = -1;
-    m->exit_y = -1;
-    m->player_x = -1;
-    m->player_y = -1;
-
-    /* initialize the map */
-    /* width is the num of characters in the first line */
-    const char *ch = strchr (str_map, '\n');
-    if (! ch) {
-        fprintf (stderr, "Error: cannot find line return in map description!");
-        exit(EXIT_FAILURE);
-    }
-    m->width = ch - str_map;
-    m->height = 0;
-    while (ch) {
-        ch = strchr (ch+1, '\n');
-        m->height++;
-    }
 
-    /* printf ("Size of map: %dx%d\n", m->width, m->height); */
+    m->player_x = player_x;
+    m->player_y = player_y;
+    m->player_direction = player_direction;
+    m->width = width;
+    m->height = height;
 
     /* allocating enough space to hold the map */
-    m->name = (char*) malloc(sizeof(char) * (strlen(new_name) + 1));
-    strcpy(m->name, new_name);
-    m->floor = (floortype*)malloc(m->width * m->height * sizeof(floortype));
-    m->items = (itemtype*)malloc(m->width * m->height * sizeof(itemtype));
-    m->monsters = (monster**)malloc(m->width * m->height * sizeof(monster*));
-
-    for (int i=0; i<m->width*m->height; i++) {
-        m->items[i] = NO_ITEM;
-        m->monsters[i] = NULL;
-    }
-
-    ch = str_map;
-    floortype f;
-    monster *mon;
-    for (int y=0; y<m->height; y++) {
-        for (int x=0; x<m->width; x++) {
-            f = EMPTY;
-            switch (*ch) {
-                case '+':
-                case '|':
-                case '-': f=WALL; break;
-                case '$': m->items[y*m->width + x] = I_GOLD;
-                          f=GRASS; break;
-                case ' ': f=GRASS; break;
-                case '~': f=WATER; break;
-                case 'D': f=DOOR; break;
-                case '@': f=GRASS;
-                          m->player_x = x;
-                          m->player_y = y;
-                          break;
-                case '>': f=GRASS;
-                          m->exit_x = x;
-                          m->exit_y = y;
-                          break;
-                case 'S': f=GRASS;
-                          mon = (monster*)malloc(sizeof(monster));
-                          mon->pos_x = x;
-                          mon->pos_y = y;
-                          mon->name = "Shopkeeper";
-                          mon->health_points = 1200;
-                          mon->armor = 3;
-                          mon->weapon = 12;
-                          m->monsters[y*m->width + x] = mon;
-                          break;
-                case 'T': f=GRASS;
-                          mon = (monster*)malloc(sizeof(monster));
-                          mon->pos_x = x;
-                          mon->pos_y = y;
-                          mon->name = "Troll";
-                          mon->health_points = 25;
-                          mon->armor = 1;
-                          mon->weapon = 4;
-                          m->monsters[y*m->width + x] = mon;
-                          break;
-                case '[': /* armor */
-                case '/': /* wand */
-                case ')': /* weapon */
-                          f=GRASS;
-                          break;
-                default:
-                          fprintf (stderr, "Unknown map character '%c'!\n",*ch);
-            }
-            m->floor[y*m->width + x] = f;
-            ch++;
-        }
-        assert (*ch == '\n');
-        ch++;
-    }
-
-    player_x = m->player_x;
-    player_y = m->player_y;
-    assert (player_x != -1 && player_y != -1);
-}
-
-
-void unload_map (void)
-{
-    map *m = current_map();
-
-    for (int i=0; i<m->width*m->height; i++) {
-        free(m->monsters[i]);
-    }
-    free(m->floor);
-    free(m->items);
-    free(m->monsters);
-    free(m->name);
+    m->name = (char *) malloc(sizeof(char) * (strlen(name) + 1));
+    strcpy(m->name, name);
+    m->floor = (tile **) malloc(m->width * m->height * sizeof(tile *));
+    m->entities = (entity **) malloc(m->width * m->height * sizeof(entity *));
 
-    mstack.length--;
-    m = current_map();
-
-    /* place player at saved position on previous map */
-    player_x = m->player_x;
-    player_y = m->player_y;
-}
-
-int coord_idx(int y, int x)
-{
-    map *m = current_map();
-    return y * m->width + x;
-}
-
-int player_idx(void)
-{
-    return coord_idx (player_y, player_x);
+    return m;
 }
 
 
+map * unload_map(void) {
+    if (mstack.length > 0) {
+        map * m = current_map();
 
+        free(m->name);
 
+        for (int i = 0; i < m->width * m->height; i++) {
+            if (m->entities[i] != NULL) {
+                if (m->entities[i]->stats)
+                    free(m->entities[i]->stats);
 
-bool is_obstacle(int y, int x)
-{
-    map *m = current_map();
-    int i = coord_idx(y, x);
+                free(m->entities[i]);
+            }
+            if (m->floor[i] != NULL) {
+                free(m->floor[i]);
+            }
+        }
 
-    floortype f = m->floor[i];
+        free(m->entities);
+        free(m->floor);
 
-    if (f == WALL) {
-        return true;
+        mstack.length--;
+    } else {
+        printf("unload_map: Can't unload map: map stack is already empty.\n");
     }
-    return false;
+    return current_map();
 }
 
 
-
-
-itemtype item(int y, int x)
-{
-    map *m = current_map();
-    int i = coord_idx(y, x);
-
-    return m->items[i]; /* BUGIDEA: was 'm->items[i] == NO_ITEMS' */
+void free_map_stack(void) {
+    while (mstack.length > 0) {
+        unload_map();
+    }    
 }
 
-monster* is_monster(int y, int x)
-{
-    map *m = current_map();
-    int i = coord_idx(y, x);
-    return m->monsters[i];
+
+int coord_idx(int y, int x) {
+    return y * current_map()->width + x;
 }
 
 
-void remove_item(void)
-{
+int player_idx(void) {
     map *m = current_map();
-    int i = player_idx();
-    assert (m->items[i] != NO_ITEM);
-    m->items[i] = NO_ITEM;
+    return coord_idx(m->player_y, m->player_x);
 }
 
 
-
-bool is_water(int y, int x)
-{
-    map *m = current_map();
-    return m->floor[coord_idx(y,x)] == WATER;
+bool is_obstacle(int y, int x) {
+    return current_map()->floor[coord_idx(y, x)]->obstacle;
 }
diff --git a/engines/fullgame/map.h b/engines/fullgame/map.h
index ac18b48d..b73f52d3 100644
--- a/engines/fullgame/map.h
+++ b/engines/fullgame/map.h
@@ -1,32 +1,39 @@
 #ifndef MAP_H
 #define MAP_H
 
+typedef enum Direction {
+    UP,
+    DOWN,
+    LEFT,
+    RIGHT,
+    UNKNOWN
+} direction;
+
 #include "agdbentures.h"
 
-typedef enum {
-    EMPTY,       /* unreachable area */
-    GRASS,
-    DIRT,
-    WOOD,
-    WALL,
-    WATER,
-    DOOR,
-    FLOORTYPE_N, /* last one to know how many types there are */
-} floortype;
+typedef struct {
+    int id; // identifier to display the tile
+    bool obstacle; // whether the player can move on it or not
+} tile;
+
+typedef struct {
+    int id; // identifier to display and use in events
+    int category; // used to group in events, like monster, NPC...
+    int * stats; // any property the entity may have (life points, state...)
+} entity;
 
 typedef struct {
     char * name; // shop, overworld, dungeon_Nth_level...
-    floortype *floor;  /* matrix of floortype */
-    itemtype *items;   /* matrix of items */
-    monster **monsters; /* matrix of monsters */
-    int width;   /* size of map */
+    tile ** floor; // immobile floor
+    entity ** entities; // ennemies, NPCs, items, switches... anything used by events
+    int width; // map size
     int height;
-    int player_x; /* position of player */
+    int player_x; // player position
     int player_y;
-    int exit_x;
-    int exit_y;   /* position of the exit if any */
+    direction player_direction;
 } map;
 
+
 #define MAX_MAPS 256
 
 typedef struct {
@@ -36,22 +43,16 @@ typedef struct {
 
 
 void init_map_stack(void);
-void load_map(const char * str_map, const char * new_name);
-void unload_map(void);
+map * load_map(const char * name, int width, int height, int player_x, int player_y, unsigned player_direction);
+map * unload_map(void);
 
 int coord_idx(int y, int x);
 int player_idx(void);
 
-map* current_map (void);
-
-bool is_obstacle(int y, int x);
-itemtype item(int y, int x);
-void remove_item(void);
-
-bool is_water(int y, int x);
-monster* is_monster(int y, int x);
+map * current_map(void);
 
+void free_map_stack(void);
 
+bool is_obstacle(int y, int x);
 
-void receive_damage(monster *mon);
-#endif//MAP_H
+#endif //MAP_H
diff --git a/engines/fullgame/read_input.c b/engines/fullgame/read_input.c
index a28df349..e731ead2 100644
--- a/engines/fullgame/read_input.c
+++ b/engines/fullgame/read_input.c
@@ -1,22 +1,71 @@
 #include "read_input.h"
 
-int read_input_file(const char* filename, CommandList* commands) {
 
-    FILE* input_file = fopen(filename, "r");
+typedef struct {
+    command * com;
+} commandList;
+
+bool file_inputs = false;
+commandList * internal_list = NULL;
+
+
+command * allocate_command(char * command_buffer, size_t buffer_len) {
+    // Allocate the new command structure
+    command * com = malloc(sizeof(command));
+
+    com->command_buffer = command_buffer;
+    command_buffer[buffer_len-1] = '\0';
+
+    // count args and replace space with \0
+    com->n_args = 0;
+    for (size_t current_char_index = 0; current_char_index < buffer_len; current_char_index++) {
+        if (command_buffer[current_char_index] == ' ') {
+            com->n_args++;
+            command_buffer[current_char_index] = '\0';
+        }
+    }
+
+    // redo a pass to place args pointers
+    if (com->n_args > 0)
+        com->args = malloc(sizeof(char *) * com->n_args);
+    else
+        com->args = NULL;
+    int n_args = 0;
+    for (size_t current_char_index = 0; n_args < com->n_args; current_char_index++) {
+        if (command_buffer[current_char_index] == '\0') {
+            com->args[n_args] = command_buffer + current_char_index + 1;
+            n_args++;
+        }
+    }
+
+    com->next = NULL;
+
+    return com;
+}
+
+
+bool read_input_file(const char * filename) {
+    FILE * input_file = fopen(filename, "r");
+
+    if (!input_file)
+        return false;
 
     size_t command_length;
-    char* line = NULL;
+    char * line = NULL;
+
+    if (!internal_list)
+        internal_list = malloc(sizeof(commandList));
 
     // Push a sentinel
-    Command sentinel;
-    commands->command = &sentinel;
-    Command* prev_command = commands->command;
+    command sentinel;
+    internal_list->com = &sentinel;
+    command * prev_command = internal_list->com;
 
     while (!feof(input_file)) {
         int linesize = getline(&line, &command_length, input_file);
 
         if (linesize != -1) {
-            Command* next = allocate_command(line, linesize);
+            command * next = allocate_command(line, linesize);
             prev_command->next = next;
             prev_command = next;
         } else {
@@ -26,58 +75,65 @@ int read_input_file(const char* filename, CommandList* commands) {
     }
 
     // Remove the sentinel
-    commands->command = commands->command->next;
+    internal_list->com = internal_list->com->next;
 
     fclose(input_file);
-    return 0;
+    return true;
 }
 
-Command* allocate_command(char* command_buffer, size_t buffer_len) {
-    // Allocate the new command structure
-    Command* command = malloc(sizeof(Command));
 
-    command->command_buffer = command_buffer;
-    command_buffer[buffer_len-1] = '\0';
+void free_command(command * com) {
+    if (!com)
+        return;
+    free(com->command_buffer); // Free the buffer allocated by getline
+    if (com->args != NULL)
+        free(com->args);
+    free(com);
+}
 
-    // count args and replace space with \0
-    command->n_args = 0;
-    for (size_t current_char_index = 0; current_char_index < buffer_len; current_char_index++) {
-        if (command_buffer[current_char_index] == ' ') {
-            command->n_args ++;
-            command_buffer[current_char_index] = '\0';
-        }
-    }
 
-    // redo a pass to place args pointers
-    if (command->n_args > 0)
-        command->args = malloc(sizeof(char*) * command->n_args);
-    else
-        command->args = NULL;
-    int n_args = 0;
-    for (size_t current_char_index = 0; n_args < command->n_args; current_char_index++) {
-        if (command_buffer[current_char_index] == '\0') {
-            command->args[n_args] = command_buffer + current_char_index + 1;
-            n_args++;
-        }
-    }
+void free_commands(commandList* commands) {
+    free_command(commands->com);
+}
+
 
-    command->next = NULL;
+bool init_inputs(const char * filename) {
+    if (strlen(filename) == 0) {
+        file_inputs = false;
+        return true;
+    }
 
-    return command;
+    file_inputs = true;
+    return read_input_file(filename);
 }
 
-void free_command(Command* command) {
-    // Free next commands
-    if (command->next != NULL) {
-        free_command(command->next);
+
+command * get_next_input(void) {
+    command * i;
+
+    if (file_inputs) {
+
+        if (!internal_list || !internal_list->com)
+            return NULL;
+
+        i= internal_list->com;
+        internal_list->com = i->next;
+        if (!internal_list->com) {
+            free(internal_list);
+            internal_list = NULL;
+        }
+        return i;
+        
+    } else {
+        return NULL;
+        // todo get command from standard input
     }
-    // Free current command
-    free(command->command_buffer); // Free the buffer allocated by getline
-    if (command->args != NULL)
-        free(command->args);
-    free(command);
 }
 
-void free_commands(CommandList* commands) {
-    free_command(commands->command);
+
+command * get_and_free_input(command * i) {
+    command * r = get_next_input();
+    if (i)
+        free_command(i);
+    return r;
 }
diff --git a/engines/fullgame/read_input.h b/engines/fullgame/read_input.h
index 5627a69d..1af49af4 100644
--- a/engines/fullgame/read_input.h
+++ b/engines/fullgame/read_input.h
@@ -3,30 +3,22 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
 
 // Command structure to hold a single instruction with arguments as strings
-struct Command {
-    char* command_buffer;
+typedef struct Command {
+    char * command_buffer;
     int n_args;
-    char** args;
+    char ** args;
 
     struct Command* next;
-};
+} command;
 
-typedef struct Command Command;
 
-// A list of commands with its size
-typedef struct {
-    Command* command;
-} CommandList;
+bool init_inputs(const char * filename);
+command * get_next_input(void);
+void free_command(command * i);
+command * get_and_free_input(command * i);
 
-// Reads the whole given input file and returns a list of commands.
-// 1 means means the function failed and 0 succeeded
-int read_input_file(const char* filename, CommandList* commands);
-
-void free_commands(CommandList* commands);
-
-// Takes a command buffer as input and prepare all the interior data in a new allocated buffer
-Command* allocate_command(char* command_buffer, size_t buffer_len);
-
-#endif
+#endif // READ_INPUT_H
diff --git a/levels/interrupteurs/Makefile b/levels/interrupteurs/Makefile
index 0d7a136a..b4efc1b7 100644
--- a/levels/interrupteurs/Makefile
+++ b/levels/interrupteurs/Makefile
@@ -1,5 +1,7 @@
 MAINPROG := main
-OBJECTS := main.o map.o action.o common.o events.o events_map.o read_input.o
+OBJECTS := main.o \
+		../../engines/fullgame/map.o ../../engines/fullgame/action.o ../../engines/fullgame/common.o ../../engines/fullgame/events.o ../../engines/fullgame/read_input.o \
+		events_map.o custom_map.o input_manager.o
 
 #DEFINES := -Dtemplate -Dinverse_xy -Dstring_comparison
 #DEFINES := -Dstack_alloc -Dinverse_xy -Dstring_comparison
@@ -7,7 +9,7 @@ OBJECTS := main.o map.o action.o common.o events.o events_map.o read_input.o
 #DEFINES := -Dstring_comparison
 DEFINES :=
 
-CC := clang
+CC := gcc
 CFLAGS := -g -Wall -Wextra $(DEFINES)
 
 all: main
@@ -17,6 +19,7 @@ main: $(OBJECTS)
 
 clean:
 	rm *.o
+	rm ../../engines/fullgame/*.o
 
 clear: clean
 	rm main
diff --git a/levels/interrupteurs/action.c b/levels/interrupteurs/action.c
deleted file mode 100644
index c6e6beb3..00000000
--- a/levels/interrupteurs/action.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/**
- * Very simple program representing a character moving in 8 directions. Can't pass through walls,
- * and can pick "items" by walking on it.
- * 
- * Concepts used: Variable locality, reference passing, remainder operator
- * 
- * Possible bugs:
- *  - not understanding the % operator
- *  - passing a negative int while the parameter is an unsigned. I think in that case it underflows and is MAX_UNSIGNED - n
- *  - confusing x and y, because this program does level[y][x]
- * 
- * Game design related tip:
- *   it is common in fighting games to represent the directional inputs using numbers from 1 to 9.
- *   Just think on how they are disposed on a numeric keypad:
- *    ↖  ↑  ↗
- *     7 8 9
- *   ← 4 5 6 →
- *     1 2 3
- *    ↙  ↓  ↘
-*/
-
-#include "action.h"
-
-/***********************************/
-/*   Constants, types, variables   */
-/***********************************/
-
-/***********************************/
-/*      Methods and functions      */
-/***********************************/
-
-void turn_right (void)
-{
-    int d;
-    switch (player_direction) {
-        case UP: d=RIGHT; break;
-        case LEFT: d=UP; break;
-        case DOWN: d=LEFT; break;
-        case RIGHT: d=DOWN; break;
-        default: assert(false);
-    }
-    player_direction = d;
-}
-
-void turn_left (void)
-{
-    int d;
-    switch (player_direction) {
-        case UP: d=LEFT; break;
-        case LEFT: d=DOWN; break;
-        case DOWN: d=RIGHT; break;
-        case RIGHT: d=UP; break;
-        default: assert(false);
-    }
-    player_direction = d;
-}
-
-void coord_in_dir_n (int y, int x, int dir, int *cy, int *cx, int n)
-{
-    assert (dir >= 1 && dir <= 9);
-
-    // warning: (0, 0) is top left
-
-    // vertical movement
-    if (dir >= 7) {
-        // 7, 8, 9
-        *cy = y - n;
-        /* BUGLINE: forgetting that y = 0 is at the top
-         * y = player_y + 1;
-         */
-    } else if (dir <= 3) {
-        // 1, 2, 3
-        *cy = y + n;
-    } else {
-        *cy = y;
-    }
-
-    if (dir % 3 == 0) {
-        // 3, 6, 9
-        *cx = x + n;
-        /* BUGLINE: thinking x is also inverted because y is
-         * x = pox_x - 1;
-         */
-    } else if (dir % 3 == 1) {
-        // 1, 4, 7
-        *cx = x - n;
-    } else {
-        *cx = x;
-    }
-}
-
-
-void coord_in_dir (int y, int x, int dir, int *cy, int *cx)
-{
-    coord_in_dir_n (y, x, dir, cy, cx, 1);
-}
-
-void player_in_dir(int *cy, int *cx)
-{
-    coord_in_dir (player_y, player_x, player_direction, cy, cx);
-}
-
-void player_in_dir_n(int *cy, int *cx, int n)
-{
-    coord_in_dir_n (player_y, player_x, player_direction, cy, cx, n);
-}
-
-
-int player_idx_in_dir(void)
-{
-    int y, x;
-    player_in_dir(&y, &x);
-    return coord_idx (y, x);
-}
-
-int player_idx_in_dir_n(int n)
-{
-    int y, x;
-    player_in_dir_n(&y, &x, n);
-    return coord_idx (y, x);
-}
-
-void up() {
-    player_direction = UP;
-    forward();
-}
-
-void up_n(unsigned n) {
-    player_direction = UP;
-    forward_n(n);
-}
-
-void down() {
-    player_direction = DOWN;
-    forward();
-}
-
-void down_n(unsigned n) {
-    player_direction = DOWN;
-    forward_n(n);
-}
-
-void left() {
-    player_direction = LEFT;
-    forward();
-}
-
-void left_n(unsigned n) {
-    player_direction = LEFT;
-    forward_n(n);
-}
-
-void right() {
-    player_direction = RIGHT;
-    forward();
-}
-
-void right_n(unsigned n) {
-    player_direction = RIGHT;
-    forward_n(n);
-}
-
-void forward (void)
-{
-    int y, x;
-    coord_in_dir (player_y, player_x, player_direction, &y, &x);
-
-    // in this version there is no screen transition
-    // screen edges act as obstaces
-    if (collision(y, x)) {
-        printf ("You bump into something!\n");
-        return ;
-    }
-
-    player_x = x;
-    player_y = y;
-}
-
-void forward_n (unsigned num_steps)
-{
-    for (unsigned int i=0; i<num_steps; i++) {
-        forward();
-        /* the last apply_event will be done by the main loop
-        this avoids triggering an event twice
-        BUGIDEA: remove the next if and observe how events are applied twice at the end
-        of a FORWARD_N */
-        if (i < num_steps - 1)
-            apply_events();
-        if (exit_main_loop)
-            i = num_steps;
-    }
-}
-
-int collision(int y, int x) {
-    if (x < 0 || x > SCREEN_WIDTH - 1 || y < 0 || y > SCREEN_HEIGHT -1) {
-        /* BUGLINE: off by one
-         * if (x < 0 || x > SCREEN_WIDTH || y < 0 || y > SCREEN_HEIGHT) {
-         */
-        return -1;
-    }
-
-    // complex but allows modifiying the possible obstacles quickly. Maybe strlen(OBSTACLES) could be a literal defined in move.h
-    /* BUGIDEA:
-     * adding a char at the end of OBSTACLES, hence erasing the \0, making 
-     * strlen fail...
-     */
-    if (is_obstacle(y, x)) {
-        return 1;
-    }
-
-    return 0;
-}
-
-void touch(void)
-{
-    int y, x;
-    player_in_dir_n(&y, &x, 1);
-    // @AGDB this bug is just an inversion of x and y, but the result is funny
-    #ifdef inverse_xy
-    activate_switch(x, y);
-    #else
-    activate_switch(y, x);
-    #endif
-}
diff --git a/levels/interrupteurs/action.h b/levels/interrupteurs/action.h
deleted file mode 100644
index f1942872..00000000
--- a/levels/interrupteurs/action.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef ACTION_H
-#define ACTION_H
-
-#include "agdbentures.h"
-#include <stdlib.h>
-
-#define UP 8
-#define DOWN 2
-#define LEFT 4
-#define RIGHT 6
-
-/**
- * pos_x : current x position of the character
- * pos_y : current y position of the character
- * dir : Defines the direction in which the player moves. 
- * Must be in [1..9], where 5 is no movement, 1 is down-left, 9 is top-right... Do you follow?
- * If dir is not in [1..9], it is treated as 5, so no movement occurs.
- */
-
-void turn_right (void);
-void turn_left (void);
-
-
-/**
- * Computes the coordinates from (x,y) when moving 1 square in direction 'dir'
- * and stores the results in pointers (*cx, *cy).
- */
-void coord_in_dir (int y, int x, int dir, int *cy, int *cx);
-
-/**
- * Idem but when moving 'n' squares in direction 'dir'.
- */
-void coord_in_dir_n (int y, int x, int dir, int *cy, int *cx, int n);
-
-// Functions to move the character
-void up();
-void up_n(unsigned n);
-void down();
-void down_n(unsigned n);
-void left();
-void left_n(unsigned n);
-void right();
-void right_n(unsigned n);
-
-void forward (void);
-void forward_n (unsigned num_steps);
-
-/**
- * Verifies if the player can move to tile (x, y).
- * Returns 0  if (x, y) is accessible
- * Returns 1  if (x, y) is no accessible because it's occupied by an obstacle
- * Returns -1 if (x, y) is outside the screen. In that case it's up to the game to decide
- * wether the player will transition to another screen or can't move anymore.
- */
-int collision(int x, int y);
-
-/**
- * Activates the switch in front of the player.
- */
-void touch(void);
-
-#endif//ACTION_H
diff --git a/levels/interrupteurs/agdbentures.h b/levels/interrupteurs/agdbentures.h
deleted file mode 100644
index 75c2ffc5..00000000
--- a/levels/interrupteurs/agdbentures.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef AGDBENTURES_H
-#define AGDBENTURES_H
-
-#include "common.h"
-#include "map.h"
-#include "action.h"
-#include "events.h"
-
-#endif//AGDBENTURES_H
diff --git a/levels/interrupteurs/common.c b/levels/interrupteurs/common.c
deleted file mode 100644
index b8d98c3b..00000000
--- a/levels/interrupteurs/common.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "common.h"
-
-const char *str_map =
-"\
-+-----+--+\n\
-|X   X|~~|\n\
-|     +--+\n\
-|>    D  @\n\
-|     +--+\n\
-|X   X|~~|\n\
-+-----+--+\n\
-";
-
-// x position of the character
-int player_x = -1;
-
-// y position of the character
-int player_y = -1;
-
-// Initial direction: facing East
-int player_direction = 6;
-
-// when true, the main loop ends. Should only be used in level_failed and level_success
-bool exit_main_loop = false;
-
-// @AGDB in the exercise we forget the +1 so the string doesn't end in \0 and played_order becomes corrupted
-#ifdef string_comparison
-const char correct_order[N_SWITCHES] = "2103";
-char played_order[N_SWITCHES] = "";
-#else
-const char correct_order[N_SWITCHES+1] = "2103";
-char played_order[N_SWITCHES+1] = "";
-#endif
-
-void level_failed(void)
-{
-    printf("DEFEAT!\n");
-    exit_main_loop = true;
-}
-
-void level_success()
-{
-    printf("VICTORY!\n");
-    exit_main_loop = true;
-}
diff --git a/levels/interrupteurs/common.h b/levels/interrupteurs/common.h
deleted file mode 100644
index 8fc27575..00000000
--- a/levels/interrupteurs/common.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdbool.h>
-
-// the width of a screen, in tiles
-#define SCREEN_WIDTH 10
-
-// the height of the screen, in tiles
-#define SCREEN_HEIGHT 7
-
-// number of switches
-#define N_SWITCHES 4
-
-// x position of the character
-extern int player_x;
-
-// y position of the character
-extern int player_y;
-
-// the direction the player is facing
-extern int player_direction;
-
-extern const char * str_map;
-
-extern bool exit_main_loop;
-
-// the order in which the switches are activated and the expected order
-// @AGDB see common.c for explanation about this bug
-#ifdef string_comparison
-extern char played_order[N_SWITCHES];
-extern const char correct_order[N_SWITCHES];
-#else
-extern char played_order[N_SWITCHES+1];
-extern const char correct_order[N_SWITCHES+1];
-#endif
-
-void level_failed(void);
-
-void level_success(void);
-
-#endif//COMMON_H
diff --git a/levels/interrupteurs/custom_map.c b/levels/interrupteurs/custom_map.c
new file mode 100644
index 00000000..20996c4e
--- /dev/null
+++ b/levels/interrupteurs/custom_map.c
@@ -0,0 +1,116 @@
+#include "custom_map.h"
+
+const char *str_map =
+"\
++-----+--+\n\
+|X   X|~~|\n\
+|     +--+\n\
+|>    D  @\n\
+|     +--+\n\
+|X   X|~~|\n\
++-----+--+\n\
+";
+
+#ifdef string_comparison
+// @AGDB in the exercise we forget the +1 so the string doesn't end in \0 and played_order becomes corrupted
+const char correct_order[N_SWITCHES] = "2103";
+char played_order[N_SWITCHES] = "";
+#else
+const char correct_order[N_SWITCHES+1] = "2103";
+char played_order[N_SWITCHES+1] = "";
+#endif
+
+#ifdef template
+entity template_swi = {SWI, 0, NULL};
+#endif
+
+#ifdef stack_alloc
+/* @AGDB returning a local variable address has undefined results
+ which depend of the compiler. With GCC, this returns NULL and the switch is not existent */
+entity * create_switch(int n) {
+    entity swi;
+
+    swi.category = SWI;
+    swi.id = n;
+    swi.stats = malloc(sizeof(int));
+    swi.stats[0] = DEACTIVATED;
+    return &swi;
+}
+#else // stack_alloc
+entity * create_switch(int n) {
+    entity * swi = malloc(sizeof(entity));
+    #ifdef template
+    /* @AGDB using a template will have all the switches be the same
+    + memory leak because the malloc is lost */
+    swi = &template_swi;
+    #endif
+    swi->category = SWI;
+    swi->id = n;
+    // a switch has only one stat: its state
+    swi->stats = malloc(sizeof(int));
+    swi->stats[0] = DEACTIVATED;
+    return swi;
+}
+#endif // stack_alloc
+
+
+void init_map(map * m) {
+    const char *ch = strchr (str_map, '\n');
+    if (! ch) {
+        fprintf (stderr, "Error: cannot find line return in map description!");
+        exit(EXIT_FAILURE);
+    }
+    m->width = ch - str_map;
+    m->height = 0;
+    while (ch) {
+        ch = strchr (ch+1, '\n');
+        m->height++;
+    }
+
+    // we have 4 switches only
+    int nth_swi = 0;
+
+    ch = str_map;
+    tile * f;
+    entity * i;
+    for (int y=0; y<m->height; y++) {
+        for (int x=0; x<m->width; x++) {
+            f = malloc(sizeof(tile));
+            f->id = EMPTY;
+            f->obstacle = false;
+            i = NULL;
+            switch (*ch) {
+                case '+':
+                case '|':
+                case '-': f->id=WALL; f->obstacle = true; break;
+                case ' ': f->id=GRASS; break;
+                case '~': f->id=WATER; break;
+                case 'D': f->id=DOOR;
+                          f->obstacle = true;
+                          break;
+                case '>': f->id=GRASS;
+                          m->player_x = x;
+                          m->player_y = y;
+                          break;
+                case '@': f->id=GRASS;
+                          i = malloc(sizeof(entity));
+                          i->category = FLAG;
+                          i->id = 0;
+                          i->stats = NULL;
+                          break;
+                case 'X': f->id=WALL; f->obstacle = true;
+                          assert(nth_swi < N_SWITCHES);
+                          i = create_switch(nth_swi);
+                          nth_swi++;
+                          break;
+                default:
+                          fprintf (stderr, "Unknown map character '%c'!\n",*ch);
+            }
+            m->floor[y*m->width + x] = f;
+            m->entities[y*m->width+x] = i;
+            ch++;
+        }
+        assert (*ch == '\n');
+        ch++;
+    }
+}
diff --git a/levels/interrupteurs/custom_map.h b/levels/interrupteurs/custom_map.h
new file mode 100644
index 00000000..47dcd092
--- /dev/null
+++ b/levels/interrupteurs/custom_map.h
@@ -0,0 +1,38 @@
+#ifndef CUSTOM_MAP_H
+#define CUSTOM_MAP_H
+
+#include "../../engines/fullgame/agdbentures.h"
+
+#define DEACTIVATED 0
+#define ACTIVATED 1
+#define N_SWITCHES 4
+
+typedef enum {
+    EMPTY,       /* unreachable area */
+    GRASS,
+    WALL,
+    WATER,
+    DOOR,
+    FLOORTYPE_N, /* last one to know how many types there are */
+} floortype;
+
+typedef enum {
+    FLAG, // win if reached
+    SWI
+} entitytype;
+
+extern const char * str_map;
+
+// the order in which the switches are activated and the expected order
+#ifdef string_comparison
+// @AGDB see common.c for explanation about this bug
+extern char played_order[N_SWITCHES];
+extern const char correct_order[N_SWITCHES];
+#else
+extern char played_order[N_SWITCHES+1];
+extern const char correct_order[N_SWITCHES+1];
+#endif
+
+void init_map(map * m);
+
+#endif // CUSTOM_MAP_H
diff --git a/levels/interrupteurs/events.c b/levels/interrupteurs/events.c
deleted file mode 100644
index 02395462..00000000
--- a/levels/interrupteurs/events.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * The event manager. Loads, watches and triggers events.
- * Called by the main program at each frame (main loop).
- * 
- * Concepts used:
- *  - pointers to functions
- *  - side-effecting functions
- *  - communication with the main function (to stop the main loop)
- * 
- * Possible bugs:
- *  - creating a trigger function which changes the state of the game
- *  - calling two events in the wrong order because they were loaded in reverse
- * 
- * Game design related tip:
- *  Simple games may not use events at all. More complete game engines have several complex
- *  events loops. For example, have a look at how Unity handles the execution sequence:
- *  <https://docs.unity3d.com/Manual/ExecutionOrder.html>
- *  Of course, if you create a game with Unity you will probably not use all of them.
-*/
-
-#include "events.h"
-
-event event_list[NUMBER_OF_EVENTS];
-
-int return_false() {
-    return false;
-}
-
-void load_events() {
-    // The events have to be hardcoded...
-    // add more events here (the list MUST be full, that is to say have NUMBER_OF_EVENTS elements)
-    event_list[0].trigger = verify_switch_order;
-    event_list[0].resolution = trap_door;
-    event_list[0].once = true;
-
-    event_list[1].trigger = walks_on_water;
-    event_list[1].resolution = drown;
-    event_list[1].once = false;
-
-    event_list[2].trigger = verify_exit;
-    event_list[2].resolution = event_level_success;
-    event_list[2].once = false;
-}
-
-void apply_events() {
-    int trig_res;
-
-    for (int i = 0; i < NUMBER_OF_EVENTS; i++) {
-        trig_res = event_list[i].trigger();
-        if (trig_res) {
-            event_list[i].resolution(trig_res);
-            if (event_list[i].once) {
-                event_list[i].trigger = return_false;
-            }
-        }
-    }
-    
-}
diff --git a/levels/interrupteurs/events.h b/levels/interrupteurs/events.h
deleted file mode 100644
index 7117b459..00000000
--- a/levels/interrupteurs/events.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef EVENTS_H
-#define EVENTS_H
-
-#include "common.h"
-// include all files containing trigger and resolution functions
-#include "events_map.h"
-
-#define NUMBER_OF_EVENTS 3
-
-// The structure of a single event
-typedef struct _event {
-    // the trigger function, only reads and can't write the state of the game
-    int (*trigger)(void);
-
-    /* the resolution function, called if trigger returned a non-null value
-     * the parameter trig will be the result of trigger (in some cases this may avoid redundant checks)
-     */
-    void (*resolution) (int trig);
-
-    // if the event can be done only once (= the resolution function is called once)
-    bool once;
-} event;
-
-extern event event_list[NUMBER_OF_EVENTS];
-
-
-/**
- * Reads all events the game wants and loads them in a table to call them later.
- */
-void load_events();
-
-/**
- * Applies all triggers and events in sequence. Due to this, the event ordering matters.
- */
-void apply_events();
-
-#endif // EVENTS_H
diff --git a/levels/interrupteurs/events_map.c b/levels/interrupteurs/events_map.c
index 714d9b41..f44128ca 100644
--- a/levels/interrupteurs/events_map.c
+++ b/levels/interrupteurs/events_map.c
@@ -1,49 +1,47 @@
 #include "events_map.h"
 
-int verify_exit(void)
-{
-    map *m = current_map();
-    if (player_x == m->exit_x && player_y == m->exit_y) {
-        return true;
-    } else {
-        return false;
+int once = 1;
+
+void verify_exit(void) {
+    map * m = current_map();
+    int i = player_idx();
+    if (m->entities[i] && m->entities[i]->category == FLAG) {
+        printf("You reached the exit!\n");
+        level_success();
     }
 }
 
-void event_level_success(__attribute__((unused)) int trig) {
-    level_success();
-}
 
-int verify_switch_order() {
-    // not all switches are on
-    if (strlen(played_order) < 4) {
-        return 0;
+void verify_switch_order(void) {
+    // not all switches are on or this event has already been done
+    if (!once || strlen(played_order) < 4) {
+        return;
     }
 
+    int trig;
+
+    #ifdef string_comparison
     /* @AGDB use strcmp instead of strncmp
      and set the size of these strings to N_SWITCHES instead of N_SWITCHES+1
      see common.c for more explanations
-     in the end the comparaison will never work even if the order is correct
-    */
-    #ifdef string_comparison
+     in the end the comparaison will never work even if the order is correct */
     if (strcmp(played_order, correct_order)) {
     #else
     if (strncmp(played_order, correct_order, 4)) {
     #endif
-        return -1;
+        trig = -1;
     } else {
-        return 1;
+        trig = 1;
     }
-}
 
-void trap_door(int trig) {
     map * m = current_map();
 
     for (int i = 0; i < m->width * m->height; i++) {
-        if (m->floor[i] == GRASS && trig == -1) {
-            m->floor[i] = WATER;
-        } else if (m->floor[i] == DOOR && trig == 1) {
-            m->floor[i] = GRASS;
+        if (m->floor[i]->id == GRASS && trig == -1) {
+            m->floor[i]->id = WATER;
+        } else if (m->floor[i]->id == DOOR && trig == 1) {
+            m->floor[i]->id = GRASS;
+            m->floor[i]->obstacle = false;
         }
     }
 
@@ -51,13 +49,14 @@ void trap_door(int trig) {
         printf("You activated the switches in a wrong order! A trap triggers and the whole room becomes flooded!\n");
     else if (trig == 1)
         printf("You activated the switches in the correct order!\nThe door opens!\n");
-}
 
-int walks_on_water() {
-    return is_water(player_y, player_x);
+    once = 0;
 }
 
-void drown(__attribute__((unused)) int trig) {
-    printf("You drown!\n");
-    level_failed();
+
+void drown(void) {
+    if (current_map()->floor[player_idx()]->id == WATER) {
+        printf("You drown!\n");
+        level_failed();
+    }
 }
diff --git a/levels/interrupteurs/events_map.h b/levels/interrupteurs/events_map.h
index c19b3c69..f060e916 100644
--- a/levels/interrupteurs/events_map.h
+++ b/levels/interrupteurs/events_map.h
@@ -1,27 +1,18 @@
 #ifndef EVENTS_MAP_H
 #define EVENTS_MAP_H
 
-#include "common.h"
-#include "map.h"
+#include "../../engines/fullgame/agdbentures.h"
+#include "custom_map.h"
 
 // Renvoie true si le joueur se trouve sur la case de victoire.
-int verify_exit(void);
-
-// Fonction interne qui ne fait qu'appeler level_success
-void event_level_success(__attribute__((unused)) int trig);
+void verify_exit(void);
 
 /* renvoie 0 si les 4 interrupteurs ne sont pas encore allumés,
  1 s'ils sont allumés dans le bon ordre,
  -1 s'ils sont allumés dans le mauvais ordre */
-int verify_switch_order();
-
-// selon le résultat de verify_switch_order, ouvre la porte ou active le piège
-void trap_door(int trig);
-
-// S'active si le joueur est au-dessus de l'eau
-int walks_on_water();
+void verify_switch_order(void);
 
 // Le joueur se noie et level_failed est appelé
-void drown(__attribute__((unused)) int trig);
+void drown(void);
 
 #endif // EVENTS_MAP_H
diff --git a/levels/interrupteurs/input_manager.c b/levels/interrupteurs/input_manager.c
new file mode 100644
index 00000000..798e8d21
--- /dev/null
+++ b/levels/interrupteurs/input_manager.c
@@ -0,0 +1,57 @@
+#include "input_manager.h"
+
+void activate_switch(int y, int x) {
+    map * m = current_map();
+    int i = coord_idx(y, x);
+
+    if (!m->entities[i] || m->entities[i]->category != SWI) {
+        printf("There is no switch to touch in front of you.\n");
+        return;
+    } else if (m->entities[i]->stats[0] == ACTIVATED) {
+        printf("This switch is already activated.\n");
+        return;
+    } 
+
+    m->entities[i]->stats[0] = ACTIVATED;
+
+    printf("You activate the %dth switch.\n", m->entities[i]->id);
+
+    char buffer[2];
+    sprintf(buffer, "%d", m->entities[i]->id);
+    strcat(played_order, buffer);
+}
+
+void touch(void) {
+    int y, x;
+    player_in_dir_n(&y, &x, 1);
+    #ifdef inverse_xy
+    // @AGDB this bug is just an inversion of x and y, but the result is funny
+    activate_switch(x, y);
+    #else
+    activate_switch(y, x);
+    #endif
+}
+
+void apply_input(command * c) {
+    if (!strcmp(c->command_buffer, "UP")) {
+        up();
+    } else if (!strcmp(c->command_buffer, "UP_N")) {
+        up_n(atoi(c->args[0]));
+    } else if (!strcmp(c->command_buffer, "DOWN")) {
+        down();
+    } else if (!strcmp(c->command_buffer, "DOWN_N")) {
+        down_n(atoi(c->args[0]));
+    } else if (!strcmp(c->command_buffer, "LEFT")) {
+        left();
+    } else if (!strcmp(c->command_buffer, "LEFT_N")) {
+        left_n(atoi(c->args[0]));
+    } else if (!strcmp(c->command_buffer, "RIGHT")) {
+        right();
+    } else if (!strcmp(c->command_buffer, "RIGHT_N")) {
+        right_n(atoi(c->args[0]));
+    } else if (!strcmp(c->command_buffer, "TOUCH")) {
+        touch();
+    } else {
+        printf("Unknown input command.\n");
+    }
+}
diff --git a/levels/interrupteurs/input_manager.h b/levels/interrupteurs/input_manager.h
new file mode 100644
index 00000000..2d36b1ba
--- /dev/null
+++ b/levels/interrupteurs/input_manager.h
@@ -0,0 +1,9 @@
+#ifndef INPUT_MANAGER_H
+#define INPUT_MANAGER_H
+
+#include "../../engines/fullgame/agdbentures.h"
+#include "custom_map.h"
+
+void apply_input(command * c);
+
+#endif // INPUT_MANAGER_H
\ No newline at end of file
diff --git a/levels/interrupteurs/main.c b/levels/interrupteurs/main.c
index a2ee2b9d..f412d70d 100644
--- a/levels/interrupteurs/main.c
+++ b/levels/interrupteurs/main.c
@@ -6,10 +6,10 @@
  * map_height: 7
  * map_width: 10
  * 
- * BUG: todo interrupteur
- * tag: todo interrupteur
+ * BUG: several bugs. One is a string comparison forgetting the \0, one is a template used instead of malloc, one is a stack alloc, the last one is an inversion of y and x
+ * tag: inverse_xy stack_alloc template string_comparison
  * 
- * HINT1: todo interrupteur
+ * HINT1: What is the value of current_map()->entities for switches?
  */ 
 
 /**
@@ -43,69 +43,47 @@
  *      - ... and many others!
 */
 
-#include "agdbentures.h"
-#include "read_input.h"
+#include "../../engines/fullgame/agdbentures.h"
+#include "events_map.h"
+#include "input_manager.h"
+#include "custom_map.h"
 
 
-void apply_input(Command * c) {
-    if (!strcmp(c->command_buffer, "UP")) {
-        up();
-    } else if (!strcmp(c->command_buffer, "UP_N")) {
-        up_n(atoi(c->args[0]));
-    } else if (!strcmp(c->command_buffer, "DOWN")) {
-        down();
-    } else if (!strcmp(c->command_buffer, "DOWN_N")) {
-        down_n(atoi(c->args[0]));
-    } else if (!strcmp(c->command_buffer, "LEFT")) {
-        left();
-    } else if (!strcmp(c->command_buffer, "LEFT_N")) {
-        left_n(atoi(c->args[0]));
-    } else if (!strcmp(c->command_buffer, "RIGHT")) {
-        right();
-    } else if (!strcmp(c->command_buffer, "RIGHT_N")) {
-        right_n(atoi(c->args[0]));
-    } else if (!strcmp(c->command_buffer, "TOUCH")) {
-        touch();
-    } else {
-        printf("Unknown input command.\n");
-    }
-}
-
 int main() {
 
-    CommandList inputs;
     char * filename = "input.txt";
 
-    if (read_input_file(filename, &inputs)) {
+    if (!init_inputs(filename)) {
         printf("Error while reading the inputs!\n");
-        free_commands(&inputs);
-        exit(1);
+        return EXIT_FAILURE;
     }
 
-    load_map(str_map, "overworld");
-    load_events();
+    init_map(load_map("overworld", 10, 7, 1, 3, RIGHT));
+    add_event(verify_exit);
+    add_event(verify_switch_order);
+    add_event(drown);
 
-    Command * command = inputs.command;
+    command * com = get_next_input();
 
     // The Holy Main Loop
     while (!exit_main_loop) {
-        apply_input(command);
+        apply_input(com);
 
         /* since the events may be applied if the input is FORWARD_N, 
            we need to check to avoid triggering the same event twice*/
         if (!exit_main_loop)
             apply_events();
+        
+        com = get_and_free_input(com);
 
         // plus aucun input mais on a pas encore gagné ou perdu -> défaite
-        // exception à la règle qui dit d'appeler level_* seulement depuis une résolution d'event
-        if (command->next == NULL && !exit_main_loop)
+        if (com == NULL && !exit_main_loop)
             level_failed();
-        else
-            command = command->next;
     }
 
-    free_commands(&inputs);
-    unload_map();
+    free_command(com);
+    remove_all_events();
+    free_map_stack();
     
-    return 0;
+    return EXIT_SUCCESS;
 }
diff --git a/levels/interrupteurs/map.c b/levels/interrupteurs/map.c
deleted file mode 100644
index f2f0371f..00000000
--- a/levels/interrupteurs/map.c
+++ /dev/null
@@ -1,208 +0,0 @@
-#include "map.h"
-
-static map_stack mstack;
-
-#ifdef template
-interactable template_swi = {0,0,DEACTIVATED,-1};
-#endif
-
-#ifndef stack_alloc
-interactable * create_switch(int x, int y, int n) {
-    // @AGDB always return the same switch, so they all light up at once
-    interactable * swi = malloc(sizeof(interactable));
-    #ifdef template
-    // @AGDB this creates memory leak because the malloc above is never free'd
-    swi = &template_swi; /* copy template */
-    #else
-    swi->state = DEACTIVATED;
-    #endif
-    swi->x = x;
-    swi->y = y;
-    swi->number = n;
-    return swi;
-}
-#else//stack_alloc
-interactable * create_switch(int x, int y, int n) {
-    // @AGDB does not allocate but returns a local address instead
-    interactable swi;
-    swi.x = x;
-    swi.y = y;
-    swi.state = DEACTIVATED;
-    swi.number = n;
-    return &swi;
-}
-#endif//stack_alloc
-
-
-void init_map_stack(void)
-{
-    mstack.length = 0;
-}
-
-map* current_map (void)
-{
-    return &mstack.maps[mstack.length-1];
-}
-
-
-void load_map(const char * str_map, const char * new_name) {
-    map *m;
-
-    /*BUGIDEA : forgetting to save player position */
-    if (mstack.length > 0) {
-        m = current_map();
-        m->player_x = player_x;
-        m->player_y = player_y;
-    }
-
-    mstack.length++;
-
-    m = current_map();
-    m->exit_x = -1;
-    m->exit_y = -1;
-    m->player_x = -1;
-    m->player_y = -1;
-
-    /* initialize the map */
-    /* width is the num of characters in the first line */
-    const char *ch = strchr (str_map, '\n');
-    if (! ch) {
-        fprintf (stderr, "Error: cannot find line return in map description!");
-        exit(EXIT_FAILURE);
-    }
-    m->width = ch - str_map;
-    m->height = 0;
-    while (ch) {
-        ch = strchr (ch+1, '\n');
-        m->height++;
-    }
-
-    /* printf ("Size of map: %dx%d\n", m->width, m->height); */
-
-    /* allocating enough space to hold the map */
-    m->name = (char*) malloc(sizeof(char) * (strlen(new_name) + 1));
-    strcpy(m->name, new_name);
-    m->floor = (floortype*)malloc(m->width * m->height * sizeof(floortype));
-    m->inter = (interactable**) malloc(m->width * m->height * sizeof(interactable));
-
-    // we have 4 switches only
-    int nth_swi = 0;
-
-    ch = str_map;
-    floortype f;
-    interactable * i;
-    for (int y=0; y<m->height; y++) {
-        for (int x=0; x<m->width; x++) {
-            f = EMPTY;
-            i = NULL;
-            switch (*ch) {
-                case '+':
-                case '|':
-                case '-': f=WALL; break;
-                case ' ': f=GRASS; break;
-                case '~': f=WATER; break;
-                case 'D': f=DOOR;
-                          m->door_x = x;
-                          m->door_y = y;
-                          break;
-                case '>': f=GRASS;
-                          m->player_x = x;
-                          m->player_y = y;
-                          break;
-                case '@': f=GRASS;
-                          m->exit_x = x;
-                          m->exit_y = y;
-                          break;
-                case 'X': f=WALL;
-                          assert(nth_swi < 4);
-                          i = create_switch(x, y, nth_swi);
-                          nth_swi++;
-                          break;
-                default:
-                          fprintf (stderr, "Unknown map character '%c'!\n",*ch);
-            }
-            m->floor[y*m->width + x] = f;
-            m->inter[y*m->width+x] = i;
-            ch++;
-        }
-        assert (*ch == '\n');
-        ch++;
-    }
-
-    player_x = m->player_x;
-    player_y = m->player_y;
-    assert (player_x != -1 && player_y != -1);
-}
-
-
-void unload_map (void)
-{
-    map *m = current_map();
-
-    free(m->floor);
-    free(m->name);
-
-    // @AGDB if the bug is stack_alloc, those free are invalid because m->inter[i] is on the stack
-    for (int i = 0; i < m->width * m->height; i++) {
-        if (m->inter[i] != NULL)
-            free(m->inter[i]);
-    }
-
-    free(m->inter);
-
-    mstack.length--;
-    m = current_map();
-
-    /* place player at saved position on previous map */
-    player_x = m->player_x;
-    player_y = m->player_y;
-}
-
-int coord_idx(int y, int x)
-{
-    map *m = current_map();
-    return y * m->width + x;
-}
-
-int player_idx(void)
-{
-    return coord_idx (player_y, player_x);
-}
-
-bool is_obstacle(int y, int x)
-{
-    map *m = current_map();
-    int i = coord_idx(y, x);
-
-    floortype f = m->floor[i];
-
-    return (f == WALL || f == DOOR || f == ON_SWI || f == OFF_SWI);
-}
-
-
-bool is_water(int y, int x)
-{
-    map *m = current_map();
-    return m->floor[coord_idx(y,x)] == WATER;
-}
-
-void activate_switch(int y, int x) {
-    map * m = current_map();
-    int i = coord_idx(y, x);
-
-    if (m->inter[i] == NULL) {
-        printf("There is no switch to touch in front of you.\n");
-        return;
-    } else if (m->inter[i]->state == ACTIVATED) {
-        printf("This switch is already activated.\n");
-        return;
-    } 
-
-    m->inter[i]->state = ACTIVATED;
-
-    printf("You activate the %dth switch.\n", m->inter[i]->number);
-
-    char buffer[2];
-    sprintf(buffer, "%d", m->inter[i]->number);
-    strcat(played_order, buffer);
-}
diff --git a/levels/interrupteurs/map.h b/levels/interrupteurs/map.h
deleted file mode 100644
index 7753cd59..00000000
--- a/levels/interrupteurs/map.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef MAP_H
-#define MAP_H
-
-#include "agdbentures.h"
-
-#define ACTIVATED 1
-#define DEACTIVATED 0
-
-typedef enum {
-    EMPTY,       /* unreachable area */
-    GRASS,
-    WALL,
-    WATER,
-    DOOR,
-    OFF_SWI,
-    ON_SWI,
-    FLOORTYPE_N, /* last one to know how many types there are */
-} floortype;
-
-typedef struct {
-    int x;
-    int y;
-    int number;
-    int state;
-} interactable;
-
-typedef struct {
-    char * name; // shop, overworld, dungeon_Nth_level...
-    floortype *floor;  /* matrix of floortype */
-    interactable ** inter;
-    int width;   /* size of map */
-    int height;
-    int player_x; /* position of player */
-    int player_y;
-    int exit_x;
-    int exit_y;   /* position of the exit if any */
-    int door_x;
-    int door_y;
-} map;
-
-#define MAX_MAPS 256
-
-typedef struct {
-    map maps[MAX_MAPS];
-    int length;
-} map_stack;
-
-
-void init_map_stack(void);
-void load_map(const char * str_map, const char * new_name);
-void unload_map(void);
-
-int coord_idx(int y, int x);
-int player_idx(void);
-
-map* current_map (void);
-
-bool is_obstacle(int y, int x);
-
-bool is_water(int y, int x);
-
-/**
- * active l'interrupteur donné,
- * ou affiche un message s'il n'y en a pas à cette position,
- * ou affiche un message s'il est déjà activé.
- */
-void activate_switch(int y, int x);
-
-#endif//MAP_H
diff --git a/levels/interrupteurs/read_input.c b/levels/interrupteurs/read_input.c
deleted file mode 100644
index a28df349..00000000
--- a/levels/interrupteurs/read_input.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include "read_input.h"
-
-int read_input_file(const char* filename, CommandList* commands) {
-
-    FILE* input_file = fopen(filename, "r");
-
-    size_t command_length;
-    char* line = NULL;
-
-    // Push a sentinel
-    Command sentinel;
-    commands->command = &sentinel;
-    Command* prev_command = commands->command;
-
-    while (!feof(input_file)) {
-        int linesize = getline(&line, &command_length, input_file);
-
-        if (linesize != -1) {
-            Command* next = allocate_command(line, linesize);
-            prev_command->next = next;
-            prev_command = next;
-        } else {
-            free(line);
-        }
-        line = NULL;
-    }
-
-    // Remove the sentinel
-    commands->command = commands->command->next;
-
-    fclose(input_file);
-    return 0;
-}
-
-Command* allocate_command(char* command_buffer, size_t buffer_len) {
-    // Allocate the new command structure
-    Command* command = malloc(sizeof(Command));
-
-    command->command_buffer = command_buffer;
-    command_buffer[buffer_len-1] = '\0';
-
-    // count args and replace space with \0
-    command->n_args = 0;
-    for (size_t current_char_index = 0; current_char_index < buffer_len; current_char_index++) {
-        if (command_buffer[current_char_index] == ' ') {
-            command->n_args ++;
-            command_buffer[current_char_index] = '\0';
-        }
-    }
-
-    // redo a pass to place args pointers
-    if (command->n_args > 0)
-        command->args = malloc(sizeof(char*) * command->n_args);
-    else
-        command->args = NULL;
-    int n_args = 0;
-    for (size_t current_char_index = 0; n_args < command->n_args; current_char_index++) {
-        if (command_buffer[current_char_index] == '\0') {
-            command->args[n_args] = command_buffer + current_char_index + 1;
-            n_args++;
-        }
-    }
-
-    command->next = NULL;
-
-    return command;
-}
-
-void free_command(Command* command) {
-    // Free next commands
-    if (command->next != NULL) {
-        free_command(command->next);
-    }
-    // Free current command
-    free(command->command_buffer); // Free the buffer allocated by getline
-    if (command->args != NULL)
-        free(command->args);
-    free(command);
-}
-
-void free_commands(CommandList* commands) {
-    free_command(commands->command);
-}
diff --git a/levels/interrupteurs/read_input.h b/levels/interrupteurs/read_input.h
deleted file mode 100644
index 5627a69d..00000000
--- a/levels/interrupteurs/read_input.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef READ_INPUT_H
-#define READ_INPUT_H
-
-#include <stdlib.h>
-#include <stdio.h>
-
-// Command structure to hold a single instruction with arguments as strings
-struct Command {
-    char* command_buffer;
-    int n_args;
-    char** args;
-
-    struct Command* next;
-};
-
-typedef struct Command Command;
-
-// A list of commands with its size
-typedef struct {
-    Command* command;
-} CommandList;
-
-// Reads the whole given input file and returns a list of commands.
-// 1 means means the function failed and 0 succeeded
-int read_input_file(const char* filename, CommandList* commands);
-
-void free_commands(CommandList* commands);
-
-// Takes a command buffer as input and prepare all the interior data in a new allocated buffer
-Command* allocate_command(char* command_buffer, size_t buffer_len);
-
-#endif
-- 
GitLab