Index: proj/include/ent.h
===================================================================
--- proj/include/ent.h	(revision 308)
+++ proj/include/ent.h	(revision 309)
@@ -71,7 +71,8 @@
 int    (map_collides_bullet)(const map_t *p, const bullet_t *bullet);
 int16_t (map_get_width)   (const map_t *p);
 int16_t (map_get_height)  (const map_t *p);
-int (map_make_dijkstra)(map_t *p, uint16_t x, uint16_t y);
+int (map_make_dijkstra)(map_t *p, int16_t x, int16_t y);
+int (map_where_to_follow)(const map_t *p, float x, float y, float *theta);
 int (gunner_collides_bullet)(const gunner_t *shooter, const bullet_t *bull);
 double (distance_gunners)(const gunner_t *shooter1, const gunner_t *shooter2);
 int (gunner_collides_gunner)(const gunner_t *shooter1, const gunner_t *shooter2);
Index: proj/include/proj_macros.h
===================================================================
--- proj/include/proj_macros.h	(revision 308)
+++ proj/include/proj_macros.h	(revision 309)
@@ -29,4 +29,6 @@
 #define MELEE_RANGE    80
 #define MELEE_DAMAGE   1
 
+#define ZOMBIE_SPEED    1.0
+
 #endif /* end of include guard: PROJ_MACROS_H_INCLUDED */
Index: proj/src/ent.c
===================================================================
--- proj/src/ent.c	(revision 308)
+++ proj/src/ent.c	(revision 309)
@@ -216,9 +216,18 @@
     basic_sprite_t *bsp_background;
     sprite_t *background;
     uint8_t *collide;
-    int *x_prev;
-    int *y_prev;
+    uint8_t *collide_gunner;
+    int32_t *prev;
+    uint8_t *visited;
 };
+static int (map_collides_gunner_pos)(const map_t *p, double shooter_x, double shooter_y, double radius) {
+    for (double x = -radius; x <= radius; x += 1) {
+        double y1 = sqrt(radius*radius - x*x);
+        double y2 = -y1;
+        if (map_collides_point(p, shooter_x + x, shooter_y + y1) || map_collides_point(p, shooter_x + x, shooter_y + y2)) return 1;
+    }
+    return 0;
+}
 map_t* (map_ctor)(const char **background, const char **collide){
     map_t *ret = malloc(sizeof(map_t));
     if(ret == NULL) return NULL;
@@ -226,8 +235,8 @@
     ret->bsp_background = NULL;
     ret->background     = NULL;
     ret->collide        = NULL;
-    ret->x_prev         = NULL;
-    ret->y_prev         = NULL;
+    ret->prev           = NULL;
+    ret->visited        = NULL;
 
     ret->bsp_background = basic_sprite_ctor(background, 0, 0);
     ret->background     = sprite_ctor(ret->bsp_background);
@@ -246,10 +255,17 @@
     }
     basic_sprite_dtor(bsp_collide);
 
-    ret->x_prev = malloc(W*H*sizeof(int));
-    ret->y_prev = malloc(W*H*sizeof(int));
+    ret->collide_gunner = malloc(W*H*sizeof(uint8_t));
+    if(ret->collide_gunner == NULL){ map_dtor(ret); return NULL; }
+    for(size_t i = 0; i < W*H; ++i){
+        int16_t x = i%W, y = i/W;
+        ret->collide_gunner[i] = (map_collides_gunner_pos(ret, x, y, 36) ? 1 : 0);
+    }
 
-    if(ret->x_prev == NULL || ret->y_prev == NULL){
+    ret->prev = malloc(W*H*sizeof(int32_t));
+    ret->visited = malloc(W*H*sizeof(uint8_t));
+
+    if(ret->prev == NULL || ret->visited == NULL){
         map_dtor(ret);
         return NULL;
     }
@@ -260,8 +276,8 @@
     sprite_dtor(p->background);
     basic_sprite_dtor(p->bsp_background);
     free(p->collide);
-    free(p->x_prev);
-    free(p->y_prev);
+    free(p->prev);
+    free(p->visited);
     free(p);
 }
 int16_t (map_get_x_screen)(const map_t *p){ return (-x_origin)*scale; }
@@ -275,40 +291,55 @@
     uint32_t pos = x_ + y_*w;
     return p->collide[pos];
 }
-int (map_make_dijkstra)(map_t *p, uint16_t x, uint16_t y){
+int (map_collides_gunner)(const map_t *p, const gunner_t *shooter) {
+    double radius = max(sprite_get_w(shooter->dude), sprite_get_h(shooter->dude))/2.0;
+    return map_collides_gunner_pos(p, gunner_get_x(shooter), gunner_get_y(shooter), radius);
+}
+int (map_make_dijkstra)(map_t *p, int16_t x, int16_t y){
+
     const uint16_t W = basic_sprite_get_w(p->bsp_background),
                    H = basic_sprite_get_h(p->bsp_background);
-    for(size_t i = 0; i < W*H; ++i)
-        p->x_prev[i] = p->y_prev[i] = -1;
+
+    static uint8_t first_time = true;
+    if(first_time){
+        for(size_t i = 0; i < W*H; ++i) p->prev[i] = -1;
+        first_time = false;
+    }
     /// ACTUAL DIJKSTRA
     queue_t *q = queue_ctor();
+
+    memset(p->visited, false, W*H*sizeof(uint8_t));
+
     int *ptr;
-    p->x_prev[y*W+x] = x; p->x_prev[y*W+x] = y;
-    ptr = malloc(sizeof(int)); *ptr = y*W+x; queue_push(q, ptr);
+    int32_t c, pos;
+    c = y*W+x; p->prev[c] = c; ptr = malloc(sizeof(int)); *ptr = c; queue_push(q, ptr);
+
     while(!queue_empty(q)){
-        int c = *(int*)list_node_val(queue_top(q)); free(queue_top(q)); queue_pop(q);
-        if(p->collide[c]){ p->x_prev[c] = p->y_prev[c] = -1; continue; }
-        uint16_t x = c%W, y = c/W;
-        if(0   <= x-1){ int pos = y*W+(x-1); if(p->x_prev[pos] == -1){ p->x_prev[pos] = x; p->y_prev[pos] = y; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
-        if(x+1 <  W  ){ int pos = y*W+(x+1); if(p->x_prev[pos] == -1){ p->x_prev[pos] = x; p->y_prev[pos] = y; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
-        if(0   <= y-1){ int pos = (y-1)*W+x; if(p->x_prev[pos] == -1){ p->x_prev[pos] = x; p->y_prev[pos] = y; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
-        if(y+1 <  H  ){ int pos = (y+1)*W+x; if(p->x_prev[pos] == -1){ p->x_prev[pos] = x; p->y_prev[pos] = y; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
+        c = *(int*)queue_top(q); free(queue_top(q)); queue_pop(q);
+        x = c%W, y = c/W;
+        if(p->visited[c]) continue;
+        p->visited[c] = true;
+        if(p->collide_gunner[c]) continue;
+        if(0   <= x-1){ pos = y*W+(x-1); if(!p->visited[pos] && p->prev[pos] != c){ p->prev[pos] = c; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
+        if(x+1 <  W  ){ pos = y*W+(x+1); if(!p->visited[pos] && p->prev[pos] != c){ p->prev[pos] = c; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
+        if(0   <= y-1){ pos = (y-1)*W+x; if(!p->visited[pos] && p->prev[pos] != c){ p->prev[pos] = c; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
+        if(y+1 <  H  ){ pos = (y+1)*W+x; if(!p->visited[pos] && p->prev[pos] != c){ p->prev[pos] = c; ptr = malloc(sizeof(int)); *ptr = pos; queue_push(q, ptr); }}
     }
-    return SUCCESS;
-}
 
+    queue_dtor(q);
 
-int (map_collides_gunner)(const map_t *p, const gunner_t *shooter) {
-    double radius = max(sprite_get_w(shooter->dude), sprite_get_h(shooter->dude))/2.0;
-    double shooter_x = gunner_get_x(shooter);
-    double shooter_y = gunner_get_y(shooter);
-    for (double x = -radius; x < radius; x += 1) {
-        double y1 = sqrt(radius*radius - x*x);
-        double y2 = -y1;
-        if (map_collides_point(p, shooter_x + x, shooter_y + y1) || map_collides_point(p, shooter_x + x, shooter_y + y2)) return 1;
-    }
-    return 0;
+    return SUCCESS;
 }
+int (map_where_to_follow)(const map_t *p, float x, float y, float *theta){
+    const uint16_t W = basic_sprite_get_w(p->bsp_background);
+    int x_ = x, y_ = y;
+    int pos = y_*W+x_;
+    //printf("Is in %d,%d\n", x_, y_);
+    int newx = p->prev[pos]%W, newy = p->prev[pos]/W;
+    //printf("from %d,%d to %d,%d\n", x_, y_, newx, newy);
+    *theta = atan2(-(newy-y_), newx-x_);
+    return SUCCESS;
+}
 
 int (map_collides_bullet)(const map_t *p, const bullet_t *bull){
     double radius = max(sprite_get_w(bull->b), sprite_get_h(bull->b))/2.0;
Index: proj/src/proj.c
===================================================================
--- proj/src/proj.c	(revision 308)
+++ proj/src/proj.c	(revision 309)
@@ -83,6 +83,10 @@
     {
         graph_clear_screen();
         text_t *txt = text_ctor(consolas, "Loading...");
+        text_set_pos(txt, graph_get_XRes()/2, graph_get_YRes()/2);
+        text_set_valign(txt, text_valign_center);
+        text_set_halign(txt, text_halign_center);
+        text_set_color(txt, TEXT_COLOR);
         text_draw(txt);
         text_dtor(txt);
         graph_draw();
@@ -362,6 +366,7 @@
         /* Get a request message. */
         if((r = get_interrupts_vector(&int_vector))) return r;
         for (uint32_t i = 0, n = 1; i < 32; i++, n <<= 1) {
+            if(!good) break;
             if (int_vector & n) {
                 interrupt_handler(i);
                 switch (i) {
@@ -394,19 +399,6 @@
                     case KBC_IRQ:
                     if ((scancode[0]) == ESC_BREAK_CODE) {
                         good = false;
-                        // reset game
-                        while(list_size(bullet_list) > 0){
-                            bullet_t *p = (bullet_t*)list_erase(bullet_list, list_begin(bullet_list));
-                            bullet_dtor(p);
-                        }
-                        list_node_t *it = list_begin(shooter_list);
-                        while (it != list_end(shooter_list)) {
-                            gunner_t *p = *(gunner_t**)list_node_val(it);
-                            get_random_spawn(map1, p, shooter_list);
-                            gunner_set_curr_health(p, gunner_get_health(p));
-                            it = list_node_next(it);
-                        }
-                        timer_reset(in_game_timer);
                     }
                     break;
                     case MOUSE_IRQ:
@@ -445,7 +437,6 @@
 
 #define ZOMBIES_NUM             5
 #define ZOMBIE_HEALTH_FACTOR    1.1
-
 static int (zombies)(void){
 
     int r;
@@ -478,15 +469,30 @@
 
     int health = 50;
 
+    /** #DEV */ /* {
+        gunner_t *zombie = gunner_ctor(bsp_zombie, bsp_nothing, gunner_melee | gunner_follow, 3);
+        gunner_set_health(zombie, health);
+        gunner_set_curr_health(zombie, health);
+        health *= ZOMBIE_HEALTH_FACTOR;
+        gunner_set_pos(zombie, 1100, 75);
+        list_push_back(shooter_list, zombie);
+    }*/ //\#DEV
+
+    map_make_dijkstra(map1, gunner_get_x(shooter1), gunner_get_y(shooter1));
+
     while (good && !dead) {
         /* Get a request message. */
         if((r = get_interrupts_vector(&int_vector))) return r;
         for (uint32_t i = 0, n = 1; i < 32; i++, n <<= 1) {
+            if(!good || dead) break;
             if (int_vector & n) {
                 interrupt_handler(i);
                 switch (i) {
                     case TIMER0_IRQ:
                     if (no_interrupts % 60 == 0) timer_update(in_game_timer);
+                    if (no_interrupts %  6 == 0){
+                        map_make_dijkstra(map1, gunner_get_x(shooter1), gunner_get_y(shooter1));
+                    }
 
                     update_movement(map1, shooter1, keys, shooter_list);
 
@@ -504,7 +510,7 @@
                     ent_set_origin(gunner_get_x(shooter1)-ent_get_XLength()/2.0,
                                    gunner_get_y(shooter1)-ent_get_YLength()/2.0);
 
-                    while(list_size(shooter_list) < ZOMBIES_NUM){
+                    while(list_size(shooter_list) < ZOMBIES_NUM+1){
                         gunner_t *zombie = gunner_ctor(bsp_zombie, bsp_nothing, gunner_melee | gunner_follow, 3);
                         gunner_set_health(zombie, health);
                         gunner_set_curr_health(zombie, health);
Index: proj/src/proj_func.c
===================================================================
--- proj/src/proj_func.c	(revision 308)
+++ proj/src/proj_func.c	(revision 309)
@@ -83,15 +83,33 @@
     }
 
     // Update zombie positions
-    map_make_dijkstra(map, gunner_get_x(p), gunner_get_y(p));
     list_node_t *it = list_begin(shooter_list);
     while(it != list_end(shooter_list)){
         gunner_t *g = *(gunner_t**)list_node_val(it);
         if(gunner_get_type(g) & gunner_follow){
-            //float theta = 0.0;
-            //map_where_to_follow(map, &theta);
-            //float c = fm_cos(theta), s = fm_sin(theta);
-
+            float theta = 0.0;
+            map_where_to_follow(map, gunner_get_x(g), gunner_get_y(g), &theta);
+            float c = fm_cos(theta), s = fm_sin(theta);
+            float dx = ZOMBIE_SPEED*c, dy = -ZOMBIE_SPEED*s;
+            double x = gunner_get_x(g);
+            double y = gunner_get_y(g);
+            gunner_set_pos(g, x+dx, y+dy);
+            if (map_collides_gunner(map, g)){
+                //printf("Zombie colliding with map\n");
+                gunner_set_pos(g, x, y);
+            } else {
+                list_node_t *it = list_begin(shooter_list);
+                while (it != list_end(shooter_list)) {
+                    gunner_t *p2 = *(gunner_t**)list_node_val(it);
+                    if (g != p2 && gunner_collides_gunner(g, p2)) {
+                        //printf("Zombie colliding with zombie\n");
+                        gunner_set_pos(g, x, y);
+                        break;
+                    }
+                    it = list_node_next(it);
+                }
+            }
+            gunner_set_angle(g, theta-M_PI_2); /*printf("angle: %d.%d\n", (int)theta, abs((int)(theta*1000)%1000));*/
         }
         it = list_node_next(it);
     }
