diff --git a/engines/fullgame/action.c b/engines/fullgame/action.c
index 1e162d5451d83411b71768b48c342e0a6d328431..9c6b7aae3184401c43a77bc586329ac122467d9a 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 c6c63fc0f8c2dcc57c2f666a34bc80810943430c..1e3302cd53cb080927ea4121e9c4e3b9e54fd67c 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 7eaeabd47ec649510a9219aaa9fb6ae10673ec22..80fb6fa2757d0232867358d6c0d7413fd6923c2a 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 5a23adb6ff56231dea675d1c91a9c0e74a01cf71..9b3c3deb3e4a8147744fd3ed6befaac9cb1f0203 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 f546c24480cdabf8174ae785120b98db063b7f63..75c53a0a410689371fe95c488c6c87bfb290c085 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 af3be273e4df23c5a7acddd5c48af43c7c9498dd..aa05003468a1605948753cac1f42f3a70ce69f49 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 a93f4a643ba14e1ecc99d12ab20f0c20ecf07c77..f13c78c26dddec238f4eea9adcb1c69c761c6dd7 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
Binary files a/engines/fullgame/main and /dev/null differ
diff --git a/engines/fullgame/map.c b/engines/fullgame/map.c
index bf46bfd3482b84e2a2b74b85d8a88d9c0b07e2fe..93c51c113770ea917ed0ee0a33cb915d0ff628ce 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 ac18b48ddc8d0852892a25e79727cca5ca01c311..b73f52d3ad5c7ad608af6009b0a7a12f42dd7a1f 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 a28df34963e00c4483f79ba04e4b129bafd4a992..e731ead2cd3ec9ce1ce4936ce92a9bafcef32bb1 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 5627a69d5c5591580c5139ee6db37aeb0ab96e92..1af49af4e9bba0fd2cd31b020c9528cbef3c6693 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 0d7a136aa6395f89aa196b540056cdfbfe5ed160..b4efc1b7e44686bdc7cabe9ff4b97ae958e7a4dc 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 c6e6beb3ecac4a20ca61d075d5ddf138f5b0868c..0000000000000000000000000000000000000000
--- 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 f1942872142517f4c28f2453705607804ba5b383..0000000000000000000000000000000000000000
--- 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 75c2ffc58a09b2d40421cc903355ff040d053569..0000000000000000000000000000000000000000
--- 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 b8d98c3b748cf09ea1dbfa8ef58c86a4128b78f4..0000000000000000000000000000000000000000
--- 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 8fc275757935a3f63a23fb6db71d790cafe858ff..0000000000000000000000000000000000000000
--- 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 0000000000000000000000000000000000000000..20996c4e54ef97acfaa03cfcc346f3c59a63d27e
--- /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 0000000000000000000000000000000000000000..47dcd0927364b3bac5a7ddbc44bd0b7b361973d3
--- /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 0239546295a7b135acde219fcaeca02622df0ca3..0000000000000000000000000000000000000000
--- 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 7117b459b1f76f6d4f477df02af9edb56d2ea8d2..0000000000000000000000000000000000000000
--- 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 714d9b4188addd70212c12179b4e48d89d9b64be..f44128caad6cb268be0ec9c38f1205cf24d87349 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 c19b3c69b0c4c5f93d9c9dd9285ea208bbdd6074..f060e9162b8fa1e75eae923ad17494a6c37fadfa 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 0000000000000000000000000000000000000000..798e8d2176bea929fe7da24b1386b1d29b0f08f2
--- /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 0000000000000000000000000000000000000000..2d36b1bac9964351999166e77dc231604a2c3687
--- /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 a2ee2b9d6504c627eeb485829f07cf2611f658e7..f412d70d69454ce293386f925f08996bca979727 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 f2f0371fa470ad579745c4fd3a5044d05ec00222..0000000000000000000000000000000000000000
--- 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 7753cd592f70bbe6fe6a26f7491e675e5ccf958b..0000000000000000000000000000000000000000
--- 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 a28df34963e00c4483f79ba04e4b129bafd4a992..0000000000000000000000000000000000000000
--- 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 5627a69d5c5591580c5139ee6db37aeb0ab96e92..0000000000000000000000000000000000000000
--- 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