numbers of turns to finish.
 
 Enemies' AI is very dumb so far: Each turn, they try to move towards their
-shortest-path-wise nearest enemy. If no enemy is found in their surroundings,
-they just wait. Contrary to the player, they by default see the whole map. (To
-make them see only what is in their line of sight, enable ENEMY_FOV in the
-server config file; see below "Hacking / server internals and configuration".)
+shortest-path-wise nearest enemy visible to them. If they see no enemy, they
+just wait.
 
 Once you start a new world, every move of yours is recorded in a file called
 "record". Once you re-start the game, all of your previous moves are replayed
 are to appear of the given type on the map on game start.
 
 A line of "PLAYER_TYPE" followed by a number sets the map object type (id) of
-the player's creature. "ENEMY_FOV" followed by "0" or "1" sets whether enemies
-see the whole map or only that to which they have an unobstructed line of sight.
-Since plomrogue's FOV algorithm is currently very expensive, this is disabled by
-default.
+the player's creature.
 
 All these definition block members must be present within their blocks, but only
 "ACTION" / "OBJECT" / "MAP_TYPE" must be positioned at their respective blocks'
 
 WIDTH 64
 
 PLAYER_TYPE 0
-ENEMY_FOV 0
 
 ACTION 1
 NAME wait
 
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t, UINT16_MAX */
 #include <stdlib.h> /* free() */
 #include "../common/try_malloc.h" /* try_malloc() */
-#include "field_of_view.h" /* build_fov_map() */
+#include "field_of_view.h" /* VISIBLE */
 #include "map_object_actions.h" /* get_moa_id_by_name() */
 #include "map_objects.h" /* struct MapObj */
 #include "world.h" /* global world */
     uint32_t map_size = world.map.size.y * world.map.size.x;
     uint16_t max_score = UINT16_MAX - 1;
     uint16_t * score_map = try_malloc(map_size * sizeof(uint16_t), f_name);
-    uint8_t * fov_map = world.enemy_fov ? build_fov_map(mo_origin) : NULL;
     uint32_t i;
     for (i = 0; i < map_size; i++)
     {
-        if (world.enemy_fov)
-        {
-            score_map[i] = fov_map[i] & VISIBLE ? max_score : UINT16_MAX;
-        }
-        else
-        {
-            score_map[i] = max_score;
-        }
+        score_map[i] = mo_origin->fov_map[i] & VISIBLE ? max_score : UINT16_MAX;
     }
-    free(fov_map);
     struct MapObj * mo = world.map_objs;
     for (; mo != NULL; mo = mo->next)
     {
 
 /* set_members() helper specifically for editing world.map members. */
 static uint8_t set_map_members(char * token0,char * token1,uint8_t * map_flags);
 
-/* If "token0" matches "comparand", set world.enemy_fov to "token1". */
-static uint8_t set_enemy_fov(char * token0, char * comparand, char * token1);
-
 /* If "token0" matches "comparand", set world.player_type to int in "token1". */
 static uint8_t set_player_type(char * token0, char * comparand, char * token1);
 
     char * str_obj = "OBJECT";
     char * str_map = "MAP_TYPE";
     char * str_player = "PLAYER_TYPE";
-    char * str_enemyfov = "ENEMY_FOV";
     static struct MapObjAct ** moa_p_p = &world.map_obj_acts;
     static struct MapObjDef ** mod_p_p = &world.map_obj_defs;
     static uint8_t action_flags = READY_ACT;
     static struct EntryHead * moa = NULL;
     static struct EntryHead * mod = NULL;
     if (!token0 || !strcmp(token0, str_act) || !strcmp(token0, str_obj)
-                || !strcmp(token0, str_map) || !strcmp(token0, str_player)
-                || !strcmp(token0, str_enemyfov))
+                || !strcmp(token0, str_map) || !strcmp(token0, str_player))
     {
         parse_and_reduce_to_readyflag(&action_flags, READY_ACT);
         parse_and_reduce_to_readyflag(&object_flags, READY_OBJ);
                                   (struct EntryHead *) world.map_obj_defs)
                    || start_map(token0, str_map, &map_flags)
                    || set_player_type(token0, str_player, token1)
-                   || set_enemy_fov(token0, str_enemyfov, token1)
                    || set_members(token0, token1, &object_flags, &action_flags,
                                   &map_flags, (struct MapObjDef *)mod,
                                   (struct MapObjAct *) moa)))
 
 
 
-static uint8_t set_enemy_fov(char * token0, char * comparand, char * token1)
-{
-    if (strcmp(token0, comparand))
-    {
-        return 0;
-    }
-    parsetest_int(token1, '8');
-    int test = atoi(token1) > 1;
-    err_line(test, "Value must be 0 or 1.");
-    world.enemy_fov = atoi(token1);
-    return 1;
-}
-
-
-
 static uint8_t set_player_type(char * token0, char * comparand, char * token1)
 {
     if (strcmp(token0, comparand))
 
 #include "../common/rexit.h" /* exit_err() */
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "cleanup.h" /* set_cleanup_flag() */
+#include "field_of_view.h" /* build_fov_map() */
 #include "map.h" /* init_map() */
-#include "map_objects.h" /* MapObjDef, free_map_objects(), add_map_objects() */
+#include "map_objects.h" /* MapObj, MapObjDef, free_map_objects(),
+                          * add_map_objects(), get_player()
+                          */
 #include "run.h" /* obey_msg(), io_loop() */
 #include "world.h" /* global world */
 
         }
     }
     set_cleanup_flag(CLEANUP_MAP_OBJECTS);
+    struct MapObj * mo;
+    for (mo = world.map_objs; NULL != mo; mo = mo->next)
+    {
+        mo->fov_map = mo->lifepoints ? build_fov_map(mo) : NULL;
+    }
     if (world.turn)
     {
         exit_trouble(unlink(world.path_record), f_name, "unlink()");
 
                                   */
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "cleanup.h" /* set_cleanup_flag() */
-#include "field_of_view.h" /* VISIBLE, build_fov_map() */
+#include "field_of_view.h" /* VISIBLE */
 #include "map.h" /* yx_to_map_pos() */
-#include "map_objects.h" /* structs MapObj, MapObjDef, get_map_obj_def() */
+#include "map_objects.h" /* structs MapObj, MapObjDef, get_map_obj_def(),
+                          * get_player()
+                          */
 #include "world.h" /* global world  */
 
 
 static char * build_visible_map(struct MapObj * player)
 {
     char * f_name = "build_visible_map()";
-    uint8_t * fov_map = build_fov_map(player);
     uint32_t map_size = world.map.size.y * world.map.size.x;
     char * visible_map = try_malloc(map_size, f_name);
     memset(visible_map, ' ', map_size);
     uint16_t pos_i;
     for (pos_i = 0; pos_i < map_size; pos_i++)
     {
-        if (fov_map[pos_i] & VISIBLE)
+        if (player->fov_map[pos_i] & VISIBLE)
         {
             visible_map[pos_i] = world.map.cells[pos_i];
         }
     {
         for (o = world.map_objs; o != 0; o = o->next)
         {
-            if (   fov_map[yx_to_map_pos(&o->pos)] & VISIBLE
+            if (   player->fov_map[yx_to_map_pos(&o->pos)] & VISIBLE
                 && (   (0 == i && 0 == o->lifepoints)
                     || (1 == i && 0 < o->lifepoints)))
             {
             }
         }
     }
-    free(fov_map);
     return visible_map;
 }
 
 
 #include "../common/rexit.h" /* exit_err() */
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "../common/yx_uint8.h" /* struct yx_uint8 */
+#include "field_of_view.h" /* build_fov_map() */
 #include "map_objects.h" /* structs MapObj, MapObjDef, get_player(),
                           * set_object_position(), own_map_object(),
                           * get_map_object_def()
     if (passable)
     {
         set_object_position(mo, target);
+        free(mo->fov_map);
+        mo->fov_map = build_fov_map(mo);
     }
     if (mo == get_player())
     {
 
  * (where noth-east is 'e', east 'd' etc.) Move either succeeds, or another
  * actor is encountered and hit (which leads ot its lifepoint decreasing by one
  * and eventually death), or the move fails due to an impassable target square.
+ * On success, update object's field of view map.
  */
 extern void actor_move(struct MapObj * mo);
 
 
     }
     free_map_objects(mo_start->owns);
     free_map_objects(mo_start->next);
+    free(mo_start->fov_map);
     free(mo_start);
     if (mo_start == world.map_objs)  /* So add_map_objects()' NULL-delimited  */
     {                                /* map object iteration loop does not    */
 
     struct MapObj * next;        /* pointer to next one in map object chain */
     struct MapObj * owns;        /* chain of map objects owned / in inventory */
     struct yx_uint8 pos;         /* coordinate on map */
+    uint8_t * fov_map;           /* map of the object's field of view */
     uint8_t id;                  /* individual map object's unique identifier */
     uint8_t type;                /* ID of appropriate map object definition */
     uint8_t lifepoints;          /* 0: object is inanimate; >0: hitpoints */