Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2003:
[Freeciv-Dev] Re: (PR#4691) replace regular_map_pos_is_normal users with
Home

[Freeciv-Dev] Re: (PR#4691) replace regular_map_pos_is_normal users with

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: jdorje@xxxxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#4691) replace regular_map_pos_is_normal users with native coordinates
From: "rwetmore@xxxxxxxxxxxx" <rwetmore@xxxxxxxxxxxx>
Date: Wed, 17 Sep 2003 08:25:24 -0700
Reply-to: rt@xxxxxxxxxxxxxx

Sample code (and commentary) attached from the civmap program (Dec 2002).

This passes in the arguments, so there is no need to maintain obscure
relationships between internal macro code and things developers might
add at various unrelated locations. It also flags the macro code more
visibly in the comments, and through use of caps.

Cheers,
RossW
=====

Jason Short wrote:
[...]
>>In SAVE_NORMAL_MAP_DATA, where does y (or nat_y) come from?  Where are
>>they defined?
> 
> 
> These exist (and must match) both inside and outside the macro.  This is
> a significant hack; on the other hand, that's how it's already been done.
> 
> In the current code y is used at all three levels (caller,
> SAVE_NORMAL_MAP_DATA definition, SAVE_MAP_DATA definition):
> 
>   SAVE_NORMAL_MAP_DATA(file, terrain_chars[map_get_tile(x, y)->terrain],
>                      "map.t%03d");
> 
> 
> #define SAVE_NORMAL_MAP_DATA(secfile, get_xy_char, secfile_name)          \
>       SAVE_MAP_DATA(get_xy_char,                                        \
>                     secfile_insert_str(secfile, line, secfile_name, y))
> 
> #define SAVE_MAP_DATA(get_xy_char, secfile_insert_line) \
> {                                                       \
>   char *line = fc_malloc(map.xsize + 1);                \
>   int x, y;                                             \
> 
> It may be possible to decrease this hack by adding it as a parameter. 
> Hmm...
> 
> jason

/*
 * This loops over the entire map to load data. It inputs a line of
 * data using the macro SECFILE_LOOKUP_LINE and then loops using the
 * macro SET_XY_CHAR to load each char into tha map at (x,y). Internal 
 * variables x and y, xn and yn, and ch are allocated within the macro
 * but definable by the user (at the level where first used). User code
 * thus depends only on the macro interface and not macro internals.
 * 
 * ch:     a variable to hold a char
 * x, y:   variables for internal map coordinates
 * xn, yn: variables for output/native coordinates
 * map:    the map instance or context to update
 * SET_XY_CHAR: macro to load the map character at each (x, y).
 * SECFILE_LOOKUP_LINE: macro to input a line (*, yn) for processing.
 *
 * Note: some (but not all) of the code this is replacing used to skip
 * over lines that did not exist for backward-compatibility. We could 
 * add another parameter that specified whether it was OK to skip data,
 * but there's not really much advantage to exiting early in this case.
 * Instead, we let any map data type be empty, and just print an
 * informative warning message about it.
*/
#define LOAD_MAP_DATA(ch, xn, yn, x, y, map,                           \
                      SET_XY_CHAR, SECFILE_LOOKUP_LINE)                \
{                                                                      \
  char ch, *_line;                                                     \
  int x, y, xn, yn;                                                    \
  for (yn = 0; yn < map->ysize; yn++) {                                \
    _line = (SECFILE_LOOKUP_LINE);                                     \
    if (!_line || strlen(_line) != map->xsize) {                       \
      freelog(LOG_ERROR, "Invalid map data at line y=%d.  "            \
        "This can happen with old saved games, or it may "             \
        "indicate an invalid saved game file.  "                       \
        "Proceed at your own risk.", yn);                              \
      if(!_line) {                                                     \
        freelog(LOG_ERROR, _("Reason: line not found"));               \
      } else {                                                         \
        freelog(LOG_ERROR, _("Reason: line too short "                 \
                "(expected %d got %lu"), map->xsize,                   \
                (unsigned long) strlen(_line));                        \
      }                                                                \
      continue;                                                        \
    }                                                                  \
    for(xn = 0; xn < map->xsize; xn++) {                               \
      ch = _line[xn];                                                  \
      native_to_civmap_pos(map, &x, &y, xn, yn);                       \
      if (normalize_civmap_pos(map, &x, &y)) {                         \
        (SET_XY_CHAR);                                                 \
      } else {                                                         \
        /* assert(ch == '#'); */                                       \
      }                                                                \
    }                                                                  \
  }                                                                    \
}

/* 
 * This loops over the entire map to save data. It collects all the
 * data for a line using the macro GET_XY_CHAR and then executes the
 * macro SECFILE_INSERT_LINE. Internal variables x and y, xn and yn,
 * and line are allocated within the macro but definable by the user
 * (at the level where first used in the macros). User code thus
 * depends only on the macro interface and not macro internals.
 * 
 * line:   buffer variable to hold a line of chars
 * xn, yn: variables for output/native coordinates
 * x, y:   variables for internal map coordinates
 * map:    the map instance or context to save
 * GET_XY_CHAR: macro returning the map character for each (x, y).
 * SECFILE_INSERT_LINE: macro to output each processed line (*, yn).
 */

#define SAVE_MAP_DATA(line, xn, yn, x, y, map,                         \
                      GET_XY_CHAR, SECFILE_INSERT_LINE)                \
{                                                                      \
  char line[map->xsize + 1];                                           \
  int x, y, xn, yn;                                                    \
                                                                       \
  for (yn = 0; yn < map->ysize; yn++) {                                \
    for (xn = 0; xn < map->xsize; xn++) {                              \
      native_to_civmap_pos(map, &x, &y, xn, yn);                       \
      if (normalize_civmap_pos(map, &x, &y)) {                         \
        line[xn] = (GET_XY_CHAR);                                      \
        if(!isprint(line[xn] & 0x7f)) {                                \
          freelog(LOG_ERROR, "Trying to write invalid"                 \
                  " map data: '%c' %d", line[xn], line[xn]);           \
          assert(FALSE); /* exit(EXIT_FAILURE); ist fur das Gestapo */ \
        }                                                              \
      } else {                                                         \
        /* skipped over in loading */                                  \
        line[xn] = '#';                                                \
      }                                                                \
    }                                                                  \
    line[map->xsize] = '\0';                                           \
    (SECFILE_INSERT_LINE);                                             \
  }                                                                    \
}

#define SAVE_NORMAL_MAP_DATA(x, y, map,                                \
          GET_XY_CHAR, secfile, secname)                               \
        SAVE_MAP_DATA(line, xn, yn, x, y, map,                         \
          (GET_XY_CHAR), secfile_insert_str(secfile, line, secname, yn))

#define SAVE_PLAYER_MAP_DATA(x, y, map,                                \
          GET_XY_CHAR, secfile, secname, plrno)                        \
        SAVE_MAP_DATA(line, xn, yn, x, y, map,                         \
          (GET_XY_CHAR), secfile_insert_str(secfile, line, secname, plrno, yn))


[Prev in Thread] Current Thread [Next in Thread]