diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/control.c freeciv-patched/client/control.c --- freeciv-cvs/client/control.c 2003-06-07 19:58:20.000000000 +0100 +++ freeciv-patched/client/control.c 2003-06-09 14:43:37.000000000 +0100 @@ -924,6 +924,19 @@ } /************************************************************************** + Toggle display of national borders on the map +**************************************************************************/ +void request_toggle_map_borders(void) +{ + if (!can_client_change_view()) { + return; + } + + draw_borders ^= 1; + update_map_canvas_visible(); +} + +/************************************************************************** Toggle display of city names **************************************************************************/ void request_toggle_city_names(void) @@ -1710,6 +1723,14 @@ } /************************************************************************** + Toggle map borders on the mapview on/off based on a keypress. +**************************************************************************/ +void key_map_borders_toggle(void) +{ + request_toggle_map_borders(); +} + +/************************************************************************** ... **************************************************************************/ void key_city_names_toggle(void) diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/control.h freeciv-patched/client/control.h --- freeciv-cvs/client/control.h 2003-06-07 19:58:20.000000000 +0100 +++ freeciv-patched/client/control.h 2003-06-09 14:43:37.000000000 +0100 @@ -63,6 +63,7 @@ void request_unit_wait(struct unit *punit); void request_unit_wakeup(struct unit *punit); void request_toggle_map_grid(void); +void request_toggle_map_borders(void); void request_toggle_city_names(void); void request_toggle_city_growth(void); void request_toggle_city_productions(void); @@ -115,6 +116,7 @@ void key_fog_of_war_toggle(void); void key_end_turn(void); void key_map_grid_toggle(void); +void key_map_borders_toggle(void); void key_unit_move(enum direction8 gui_dir); void key_unit_airbase(void); void key_unit_auto_attack(void); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk/gui_main.c freeciv-patched/client/gui-gtk/gui_main.c --- freeciv-cvs/client/gui-gtk/gui_main.c 2003-06-07 19:58:21.000000000 +0100 +++ freeciv-patched/client/gui-gtk/gui_main.c 2003-06-09 14:43:37.000000000 +0100 @@ -97,6 +97,7 @@ GdkGC *fill_tile_gc; GdkGC *thin_line_gc; GdkGC *thick_line_gc; +GdkGC *border_line_gc; GdkPixmap *gray50, *gray25, *black50; GdkPixmap *mask_bitmap; @@ -876,6 +877,7 @@ * the tileset can change at runtime. */ thin_line_gc = gdk_gc_new(root_window); thick_line_gc = gdk_gc_new(root_window); + border_line_gc = gdk_gc_new(root_window); gdk_gc_set_line_attributes(thin_line_gc, 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, @@ -884,6 +886,10 @@ GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); + gdk_gc_set_line_attributes(border_line_gc, 2, + GDK_LINE_ON_OFF_DASH, + GDK_CAP_NOT_LAST, + GDK_JOIN_MITER); fill_tile_gc = gdk_gc_new(root_window); gdk_gc_set_fill(fill_tile_gc, GDK_STIPPLED); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk/gui_main.h freeciv-patched/client/gui-gtk/gui_main.h --- freeciv-cvs/client/gui-gtk/gui_main.h 2003-06-07 19:58:21.000000000 +0100 +++ freeciv-patched/client/gui-gtk/gui_main.h 2003-06-09 14:43:37.000000000 +0100 @@ -26,6 +26,7 @@ extern GdkGC * fill_tile_gc; extern GdkGC * thin_line_gc; extern GdkGC * thick_line_gc; +extern GdkGC * border_line_gc; extern GdkPixmap * gray50; extern GdkPixmap * gray25; extern GdkPixmap * black50; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk/mapview.c freeciv-patched/client/gui-gtk/mapview.c --- freeciv-cvs/client/gui-gtk/mapview.c 2003-06-07 19:58:21.000000000 +0100 +++ freeciv-patched/client/gui-gtk/mapview.c 2003-06-09 15:27:24.000000000 +0100 @@ -1544,6 +1544,67 @@ } /************************************************************************** + Draw the borders of the given map tile at the given canvas position + in isometric view. +**************************************************************************/ +static void tile_draw_borders_iso(GdkDrawable *pm, int map_x, int map_y, + int canvas_x, int canvas_y, + enum draw_type draw) +{ + struct player *owner = map_get_owner(map_x, map_y), *owner1; + int x1, y1; + + if ((draw & D_M_L) && MAPSTEP(x1, y1, map_x, map_y, DIR8_WEST) + && owner != (owner1 = map_get_owner(x1, y1)) + && tile_get_known(x1, y1)) { + if (owner1) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner1)]); + gdk_draw_line(pm, border_line_gc, + canvas_x, + canvas_y + NORMAL_TILE_HEIGHT / 2 - 1, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y - 1); + } + + if (owner) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner)]); + gdk_draw_line(pm, border_line_gc, + canvas_x, + canvas_y + NORMAL_TILE_HEIGHT / 2 + 1, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y + 1); + } + } + + if ((draw & D_M_R) && MAPSTEP(x1, y1, map_x, map_y, DIR8_NORTH) + && owner != (owner1 = map_get_owner(x1, y1)) + && tile_get_known(x1, y1)) { + if (owner1) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner1)]); + gdk_draw_line(pm, border_line_gc, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y - 1, + canvas_x + NORMAL_TILE_WIDTH, + canvas_y + NORMAL_TILE_HEIGHT / 2 - 1); + } + + if (owner) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner)]); + gdk_draw_line(pm, border_line_gc, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y + 1, + canvas_x + NORMAL_TILE_WIDTH, + canvas_y + NORMAL_TILE_HEIGHT / 2 + 1); + } + } +} + + +/************************************************************************** Only used for isometric view. **************************************************************************/ static void pixmap_put_tile_iso(GdkDrawable *pm, int x, int y, @@ -1695,6 +1756,11 @@ } } + /* Draw national borders. */ + if (draw_borders) { + tile_draw_borders_iso(pm, x, y, canvas_x, canvas_y, draw); + } + if (draw_coastline && !draw_terrain) { enum tile_terrain_type t1 = map_get_terrain(x, y), t2; int x1, y1; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk/menu.c freeciv-patched/client/gui-gtk/menu.c --- freeciv-cvs/client/gui-gtk/menu.c 2003-06-07 19:58:21.000000000 +0100 +++ freeciv-patched/client/gui-gtk/menu.c 2003-06-09 14:43:37.000000000 +0100 @@ -82,6 +82,7 @@ MENU_KINGDOM_REVOLUTION, MENU_VIEW_SHOW_MAP_GRID, + MENU_VIEW_SHOW_NATIONAL_BORDERS, MENU_VIEW_SHOW_CITY_NAMES, MENU_VIEW_SHOW_CITY_GROWTH_TURNS, MENU_VIEW_SHOW_CITY_PRODUCTIONS, @@ -230,6 +231,10 @@ if (draw_map_grid ^ GTK_CHECK_MENU_ITEM(widget)->active) key_map_grid_toggle(); break; + case MENU_VIEW_SHOW_NATIONAL_BORDERS: + if (draw_borders ^ GTK_CHECK_MENU_ITEM(widget)->active) + key_map_borders_toggle(); + break; case MENU_VIEW_SHOW_CITY_NAMES: if (draw_city_names ^ GTK_CHECK_MENU_ITEM(widget)->active) { key_city_names_toggle(); @@ -612,6 +617,8 @@ NULL, 0, "" }, { "/" N_("View") "/" N_("Map _Grid"), "g", view_menu_callback, MENU_VIEW_SHOW_MAP_GRID, "" }, + { "/" N_("View") "/" N_("National _Borders"), "b", + view_menu_callback, MENU_VIEW_SHOW_NATIONAL_BORDERS, "" }, { "/" N_("View") "/" N_("City _Names"), "n", view_menu_callback, MENU_VIEW_SHOW_CITY_NAMES, "" }, { "/" N_("View") "/" N_("City G_rowth"), "r", @@ -1048,6 +1055,7 @@ (game.player_ptr->spaceship.state!=SSHIP_NONE)); menus_set_active("
/_View/Map _Grid", draw_map_grid); + menus_set_active("
/_View/National _Borders", draw_borders); menus_set_active("
/_View/City _Names", draw_city_names); menus_set_sensitive("
/_View/City G_rowth", draw_city_names); menus_set_active("
/_View/City G_rowth", draw_city_growth); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk/plrdlg.c freeciv-patched/client/gui-gtk/plrdlg.c --- freeciv-cvs/client/gui-gtk/plrdlg.c 2003-06-07 19:58:21.000000000 +0100 +++ freeciv-patched/client/gui-gtk/plrdlg.c 2003-06-09 15:30:24.000000000 +0100 @@ -35,6 +35,7 @@ #include "civclient.h" #include "climisc.h" #include "clinet.h" +#include "tilespec.h" #include "chatline.h" #include "colors.h" @@ -74,7 +75,7 @@ static void players_list_ucallback(GtkWidget *w, gint row, gint column); static void players_sship_callback(GtkWidget *w, gpointer data); -#define NUM_COLUMNS 13 /* number of columns in total */ +#define NUM_COLUMNS 14 /* number of columns in total */ #define DEF_SORT_COLUMN 2 /* default sort column (1 = nation) */ /**************************************************************** @@ -135,7 +136,8 @@ void create_players_dialog(void) { static const char *titles_[NUM_COLUMNS] = - { N_("Name"), N_("Flag"), N_("Nation"), N_("Team"), N_("AI"), + { N_("Name"), N_("Flag"), N_("Nation"), + N_("Color"), N_("Team"), N_("AI"), N_("Embassy"), N_("Dipl.State"), N_("Vision"), N_("Reputation"), N_("State"), N_("Host"), N_("Idle"), N_("Ping") }; @@ -263,9 +265,11 @@ { static char namebuf[MAX_LEN_NAME], flagbuf[1], aibuf[2], dsbuf[32], repbuf[32], statebuf[32], idlebuf[32]; + static const char *colbuf = ""; const struct player_diplstate *pds; - /* we assume that neither name, team nor the nation of a player changes */ + /* we assume that the player's name, flag, + * nation and color never change. */ if (update == 0) { /* the playername */ my_snprintf(namebuf, sizeof(namebuf), "%-16s", game.players[i].name); @@ -278,11 +282,14 @@ /* the nation */ row[2] = (char *) get_nation_name(game.players[i].nation); + /* the nation color, empty since it's a block of color (no text). */ + row[3] = colbuf; + /* the team */ if (game.players[i].team != TEAM_NONE) { - row[3] = (char *) team_get_by_id(game.players[i].team)->name; + row[4] = (char *) team_get_by_id(game.players[i].team)->name; } else { - row[3] = (char *) ""; + row[4] = (char *) ""; } } @@ -333,15 +340,15 @@ reputation_text(game.players[i].reputation)); /* assemble the whole lot */ - row[4] = aibuf; - row[5] = get_embassy_status(game.player_ptr, &game.players[i]); - row[6] = dsbuf; - row[7] = get_vision_status(game.player_ptr, &game.players[i]); - row[8] = repbuf; - row[9] = statebuf; - row[10] = (char *) player_addr_hack(&game.players[i]); /* Fixme */ - row[11] = idlebuf; - row[12] = get_ping_time_text(&game.players[i]); + row[5] = aibuf; + row[6] = get_embassy_status(game.player_ptr, &game.players[i]); + row[7] = dsbuf; + row[8] = get_vision_status(game.player_ptr, &game.players[i]); + row[9] = repbuf; + row[10] = statebuf; + row[11] = (char *) player_addr_hack(&game.players[i]); /* Fixme */ + row[12] = idlebuf; + row[13] = get_ping_time_text(&game.players[i]); } #define MIN_DIMENSION 5 @@ -401,12 +408,15 @@ { if (players_dialog_shell && !is_plrdlg_frozen()) { GdkColor *state_col; + GtkStyle *style; const char *row_texts[NUM_COLUMNS]; int i, j, row, sort_needed = 0; gtk_clist_freeze(GTK_CLIST(players_list)); - for (i = 0; i < game.nplayers; i++) { + players_iterate(pplayer) { + int i = pplayer->player_no; + /* skip barbarians */ if (is_barbarian(&game.players[i])) { continue; @@ -438,7 +448,7 @@ * The nation already had a row in the player report. In that * case we just update the row. */ - for (j = 4; j < NUM_COLUMNS; j++) { + for (j = 5; j < NUM_COLUMNS; j++) { gtk_clist_set_text(GTK_CLIST(players_list), row, j, row_texts[j]); } @@ -456,6 +466,13 @@ state_col = colors_standard[COLOR_STD_BLACK]; } gtk_clist_set_foreground(GTK_CLIST(players_list), row, state_col); + /* Make the background of column 3 match the nation's border colour. */ + style = gtk_style_new(); + style->fg[GTK_STATE_NORMAL] + = *(colors_standard[player_color(pplayer)]); + style->base[GTK_STATE_NORMAL] + = *(colors_standard[player_color(pplayer)]); + gtk_clist_set_cell_style(GTK_CLIST(players_list), row, 3, style); } if (sort_needed) { @@ -469,7 +486,7 @@ gtk_clist_thaw(GTK_CLIST(players_list)); gtk_widget_show_all(players_list); - } + } players_iterate_end; } /************************************************************************** diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk-2.0/gui_main.c freeciv-patched/client/gui-gtk-2.0/gui_main.c --- freeciv-cvs/client/gui-gtk-2.0/gui_main.c 2003-06-07 19:58:21.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/gui_main.c 2003-06-09 15:06:39.000000000 +0100 @@ -99,6 +99,7 @@ GdkGC *fill_tile_gc; GdkGC *thin_line_gc; GdkGC *thick_line_gc; +GdkGC *border_line_gc; GdkPixmap *gray50, *gray25, *black50; GdkPixmap *mask_bitmap; @@ -1114,6 +1115,7 @@ /* for isometric view. always create. the tileset can change at run time. */ thin_line_gc = gdk_gc_new(root_window); thick_line_gc = gdk_gc_new(root_window); + border_line_gc = gdk_gc_new(root_window); gdk_gc_set_line_attributes(thin_line_gc, 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, @@ -1122,6 +1124,10 @@ GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); + gdk_gc_set_line_attributes(border_line_gc, 2, + GDK_LINE_ON_OFF_DASH, + GDK_CAP_NOT_LAST, + GDK_JOIN_MITER); fill_tile_gc = gdk_gc_new(root_window); gdk_gc_set_fill(fill_tile_gc, GDK_STIPPLED); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk-2.0/gui_main.h freeciv-patched/client/gui-gtk-2.0/gui_main.h --- freeciv-cvs/client/gui-gtk-2.0/gui_main.h 2003-06-07 19:58:21.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/gui_main.h 2003-06-09 15:06:39.000000000 +0100 @@ -30,6 +30,7 @@ extern GdkGC * fill_tile_gc; extern GdkGC * thin_line_gc; extern GdkGC * thick_line_gc; +extern GdkGC * border_line_gc; extern GdkPixmap * gray50; extern GdkPixmap * gray25; extern GdkPixmap * black50; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk-2.0/mapview.c freeciv-patched/client/gui-gtk-2.0/mapview.c --- freeciv-cvs/client/gui-gtk-2.0/mapview.c 2003-06-07 19:58:22.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/mapview.c 2003-06-09 15:26:51.000000000 +0100 @@ -1627,6 +1627,68 @@ } } + +/************************************************************************** + Draw the borders of the given map tile at the given canvas position + in isometric view. +**************************************************************************/ +static void tile_draw_borders_iso(GdkDrawable *pm, int map_x, int map_y, + int canvas_x, int canvas_y, + enum draw_type draw) +{ + struct player *owner = map_get_owner(map_x, map_y), *owner1; + int x1, y1; + + if ((draw & D_M_L) && MAPSTEP(x1, y1, map_x, map_y, DIR8_WEST) + && owner != (owner1 = map_get_owner(x1, y1)) + && tile_get_known(x1, y1)) { + if (owner1) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner1)]); + gdk_draw_line(pm, border_line_gc, + canvas_x, + canvas_y + NORMAL_TILE_HEIGHT / 2 - 1, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y - 1); + } + + if (owner) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner)]); + gdk_draw_line(pm, border_line_gc, + canvas_x, + canvas_y + NORMAL_TILE_HEIGHT / 2 + 1, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y + 1); + } + } + + if ((draw & D_M_R) && MAPSTEP(x1, y1, map_x, map_y, DIR8_NORTH) + && owner != (owner1 = map_get_owner(x1, y1)) + && tile_get_known(x1, y1)) { + if (owner1) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner1)]); + gdk_draw_line(pm, border_line_gc, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y - 1, + canvas_x + NORMAL_TILE_WIDTH, + canvas_y + NORMAL_TILE_HEIGHT / 2 - 1); + } + + if (owner) { + gdk_gc_set_foreground(border_line_gc, + colors_standard[player_color(owner)]); + gdk_draw_line(pm, border_line_gc, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y + 1, + canvas_x + NORMAL_TILE_WIDTH, + canvas_y + NORMAL_TILE_HEIGHT / 2 + 1); + } + } +} + + /************************************************************************** Only used for isometric view. **************************************************************************/ @@ -1779,6 +1841,11 @@ } } + /* Draw national borders. */ + if (draw_borders) { + tile_draw_borders_iso(pm, x, y, canvas_x, canvas_y, draw); + } + if (draw_coastline && !draw_terrain) { enum tile_terrain_type t1 = map_get_terrain(x, y), t2; int x1, y1; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk-2.0/menu.c freeciv-patched/client/gui-gtk-2.0/menu.c --- freeciv-cvs/client/gui-gtk-2.0/menu.c 2003-06-07 19:58:22.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/menu.c 2003-06-09 15:06:39.000000000 +0100 @@ -83,6 +83,7 @@ MENU_KINGDOM_REVOLUTION, MENU_VIEW_SHOW_MAP_GRID, + MENU_VIEW_SHOW_NATIONAL_BORDERS, MENU_VIEW_SHOW_CITY_NAMES, MENU_VIEW_SHOW_CITY_GROWTH_TURNS, MENU_VIEW_SHOW_CITY_PRODUCTIONS, @@ -231,6 +232,11 @@ if (draw_map_grid ^ GTK_CHECK_MENU_ITEM(widget)->active) key_map_grid_toggle(); break; + case MENU_VIEW_SHOW_NATIONAL_BORDERS: + if (draw_borders ^ GTK_CHECK_MENU_ITEM(widget)->active) { + key_map_borders_toggle(); + } + break; case MENU_VIEW_SHOW_CITY_NAMES: if (draw_city_names ^ GTK_CHECK_MENU_ITEM(widget)->active) { key_city_names_toggle(); @@ -611,6 +617,8 @@ NULL, 0, "" }, { "/" N_("View") "/" N_("Map _Grid"), "g", view_menu_callback, MENU_VIEW_SHOW_MAP_GRID, "" }, + { "/" N_("View") "/" N_("National _Borders"), "b", + view_menu_callback, MENU_VIEW_SHOW_NATIONAL_BORDERS, "" }, { "/" N_("View") "/" N_("City _Names"), "n", view_menu_callback, MENU_VIEW_SHOW_CITY_NAMES, "" }, { "/" N_("View") "/" N_("City G_rowth"), "r", @@ -1067,6 +1075,7 @@ (game.player_ptr->spaceship.state!=SSHIP_NONE)); menus_set_active("
/_View/Map _Grid", draw_map_grid); + menus_set_active("
/_View/National _Borders", draw_borders); menus_set_active("
/_View/City _Names", draw_city_names); menus_set_sensitive("
/_View/City G_rowth", draw_city_names); menus_set_active("
/_View/City G_rowth", draw_city_growth); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk-2.0/plrdlg.c freeciv-patched/client/gui-gtk-2.0/plrdlg.c --- freeciv-cvs/client/gui-gtk-2.0/plrdlg.c 2003-06-07 19:58:22.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/plrdlg.c 2003-06-09 15:30:38.000000000 +0100 @@ -39,6 +39,7 @@ #include "gui_stuff.h" #include "inteldlg.h" #include "spaceshipdlg.h" +#include "tilespec.h" #include "colors.h" #include "graphics.h" #include "options.h" @@ -62,7 +63,7 @@ static void players_intel_callback(GtkMenuItem *item, gpointer data); static void players_sship_callback(GtkMenuItem *item, gpointer data); -#define NUM_COLUMNS 13 /* number of columns in total */ +#define NUM_COLUMNS 14 /* number of columns in total */ #define DEF_SORT_COLUMN 2 /* default sort column (2 = nation) */ #define COLOR_COLUMN (NUM_COLUMNS) /* color column */ #define PLRNO_COLUMN (NUM_COLUMNS+1) /* plrno column */ @@ -159,6 +160,7 @@ N_("Name"), N_("Flag"), N_("Nation"), + N_("Color"), N_("Team"), N_("AI"), N_("Embassy"), @@ -176,6 +178,7 @@ G_TYPE_STRING, G_TYPE_NONE, G_TYPE_STRING, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING, @@ -196,6 +199,7 @@ GtkWidget *menubar, *menu, *item; model_types[1] = GDK_TYPE_PIXBUF; + model_types[3] = GDK_TYPE_COLOR; model_types[COLOR_COLUMN] = GDK_TYPE_COLOR; intl_slist(ARRAY_SIZE(titles), titles, &titles_done); @@ -241,6 +245,11 @@ col = gtk_tree_view_column_new_with_attributes(titles[i], renderer, "active", i, NULL); + } else if (model_types[i] == GDK_TYPE_COLOR) { + renderer = gtk_cell_renderer_text_new(); + + col = gtk_tree_view_column_new_with_attributes(titles[i], renderer, + "background-gdk", i, NULL); } else { renderer = gtk_cell_renderer_text_new(); g_object_set(renderer, "weight", "bold", NULL); @@ -407,7 +416,8 @@ gtk_list_store_set(store, it, 0, (gchar *)plr->name, /* the playername */ 2, (gchar *)get_nation_name(plr->nation), /* the nation */ - 3, (gchar *)team, + 3, colors_standard[player_color(plr)], /* the color */ + 4, (gchar *)team, PLRNO_COLUMN, (gint)i, /* the playerid */ -1); @@ -449,18 +459,18 @@ /* assemble the whole lot */ g_value_init(&value, G_TYPE_STRING); g_value_set_static_string(&value, state); - gtk_list_store_set_value(store, it, 9, &value); + gtk_list_store_set_value(store, it, 10, &value); g_value_unset(&value); gtk_list_store_set(store, it, - 4, (gboolean)plr->ai.control, - 5, (gchar *)get_embassy_status(game.player_ptr, plr), - 6, (gchar *)dsbuf, - 7, (gchar *)get_vision_status(game.player_ptr, plr), - 8, (gchar *)reputation_text(plr->reputation), - 10, (gchar *)player_addr_hack(plr), /* Fixme */ - 11, (gint)idle, - 12, (gchar *)get_ping_time_text(plr), + 5, (gboolean)plr->ai.control, + 6, (gchar *)get_embassy_status(game.player_ptr, plr), + 7, (gchar *)dsbuf, + 8, (gchar *)get_vision_status(game.player_ptr, plr), + 9, (gchar *)reputation_text(plr->reputation), + 11, (gchar *)player_addr_hack(plr), /* Fixme */ + 12, (gint)idle, + 13, (gchar *)get_ping_time_text(plr), -1); /* set flag. */ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-xaw/actions.c freeciv-patched/client/gui-xaw/actions.c --- freeciv-cvs/client/gui-xaw/actions.c 2003-06-07 19:58:25.000000000 +0100 +++ freeciv-patched/client/gui-xaw/actions.c 2003-06-09 15:06:39.000000000 +0100 @@ -151,6 +151,11 @@ key_map_grid_toggle(); } +static void xaw_key_map_borders_toggle(Widget w, XEvent *event, String *argv, Cardinal *argc) +{ + key_map_borders_toggle(); +} + static void xaw_key_move_north(Widget w, XEvent *event, String *argv, Cardinal *argc) { key_unit_move(DIR8_NORTH); @@ -615,6 +620,7 @@ { "key-end-turn", xaw_key_end_turn }, { "key-focus-to-next-unit", xaw_key_focus_to_next_unit }, { "key-map-grid-toggle", xaw_key_map_grid_toggle }, + { "key-map-borders-toggle", xaw_key_map_borders_toggle }, { "key-move-north", xaw_key_move_north }, { "key-move-north-east", xaw_key_move_north_east }, { "key-move-east", xaw_key_move_east }, diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-xaw/menu.c freeciv-patched/client/gui-xaw/menu.c --- freeciv-cvs/client/gui-xaw/menu.c 2003-02-15 19:26:18.000000000 +0000 +++ freeciv-patched/client/gui-xaw/menu.c 2003-06-09 15:06:39.000000000 +0100 @@ -128,6 +128,7 @@ static struct MenuEntry view_menu_entries[]={ { { N_("Map Grid"), 0 }, "ctl-g", MENU_VIEW_SHOW_MAP_GRID, 0 }, + { { N_("National Borders"), 0 }, "ctl-b", MENU_VIEW_SHOW_NATIONAL_BORDERS, 0 }, { { N_("City Names"), 0 }, "ctl-n", MENU_VIEW_SHOW_CITY_NAMES, 0 }, { { N_("City Growth"), 0 }, "ctl-r", MENU_VIEW_SHOW_CITY_GROWTH, 0 }, @@ -512,6 +513,9 @@ case MENU_VIEW_SHOW_MAP_GRID: key_map_grid_toggle(); break; + case MENU_VIEW_SHOW_NATIONAL_BORDERS: + key_map_borders_toggle(); + break; case MENU_VIEW_SHOW_CITY_NAMES: key_city_names_toggle(); menu_entry_sensitive(MENU_VIEW, MENU_VIEW_SHOW_CITY_GROWTH, diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-xaw/menu.h freeciv-patched/client/gui-xaw/menu.h --- freeciv-cvs/client/gui-xaw/menu.h 2002-11-25 16:51:44.000000000 +0000 +++ freeciv-patched/client/gui-xaw/menu.h 2003-06-09 15:06:39.000000000 +0100 @@ -49,6 +49,7 @@ MENU_KINGDOM_REVOLUTION, MENU_VIEW_SHOW_MAP_GRID, + MENU_VIEW_SHOW_NATIONAL_BORDERS, MENU_VIEW_SHOW_CITY_NAMES, MENU_VIEW_SHOW_CITY_GROWTH, MENU_VIEW_SHOW_CITY_PRODUCTIONS, diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/mapview_common.c freeciv-patched/client/mapview_common.c --- freeciv-cvs/client/mapview_common.c 2003-06-07 19:58:20.000000000 +0100 +++ freeciv-patched/client/mapview_common.c 2003-06-09 14:53:40.000000000 +0100 @@ -392,6 +392,48 @@ /************************************************************************** + Draw the borders of the given map tile at the given canvas position + in non-isometric view. +**************************************************************************/ +static void tile_draw_borders(struct canvas_store *pcanvas_store, + int map_x, int map_y, + int canvas_x, int canvas_y) +{ + struct player *this_owner = map_get_owner(map_x, map_y), *adjc_owner; + int x1, y1; + + /* left side */ + if (MAPSTEP(x1, y1, map_x, map_y, DIR8_WEST) + && this_owner != (adjc_owner = map_get_owner(x1, y1)) + && tile_get_known(x1, y1)) { + if (adjc_owner) { + gui_put_line(pcanvas_store, player_color(adjc_owner), + canvas_x - 1, canvas_y + 1, + 0, NORMAL_TILE_HEIGHT - 1); + } + if (this_owner) { + gui_put_line(pcanvas_store, player_color(this_owner), + canvas_x + 1, canvas_y + 1, + 0, NORMAL_TILE_HEIGHT - 1); + } + } + + /* top side */ + if (MAPSTEP(x1, y1, map_x, map_y, DIR8_NORTH) + && this_owner != (adjc_owner = map_get_owner(x1, y1)) + && tile_get_known(x1, y1)) { + if (adjc_owner) { + gui_put_line(pcanvas_store, player_color(adjc_owner), + canvas_x + 1, canvas_y - 1, NORMAL_TILE_WIDTH - 1, 0); + } + if (this_owner) { + gui_put_line(pcanvas_store, player_color(this_owner), + canvas_x + 1, canvas_y + 1, NORMAL_TILE_WIDTH - 1, 0); + } + } +} + +/************************************************************************** Draw the given map tile at the given canvas position in non-isometric view. **************************************************************************/ @@ -433,6 +475,11 @@ canvas_x, canvas_y, NORMAL_TILE_WIDTH, 0); } + /* Draw national borders. */ + if (draw_borders) { + tile_draw_borders(pcanvas_store, map_x, map_y, canvas_x, canvas_y); + } + if (draw_coastline && !draw_terrain) { enum tile_terrain_type t1 = map_get_terrain(map_x, map_y), t2; int x1, y1; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/options.c freeciv-patched/client/options.c --- freeciv-cvs/client/options.c 2003-06-07 19:58:20.000000000 +0100 +++ freeciv-patched/client/options.c 2003-06-09 14:43:37.000000000 +0100 @@ -150,6 +150,7 @@ bool draw_units = TRUE; bool draw_focus_unit = FALSE; bool draw_fog_of_war = TRUE; +bool draw_borders = TRUE; #define VIEW_OPTION(name) { #name, &name } #define VIEW_OPTION_TERMINATOR { NULL, NULL } @@ -171,6 +172,7 @@ VIEW_OPTION(draw_units), VIEW_OPTION(draw_focus_unit), VIEW_OPTION(draw_fog_of_war), + VIEW_OPTION(draw_borders), VIEW_OPTION_TERMINATOR }; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/options.h freeciv-patched/client/options.h --- freeciv-cvs/client/options.h 2003-06-07 19:58:20.000000000 +0100 +++ freeciv-patched/client/options.h 2003-06-09 14:43:37.000000000 +0100 @@ -92,6 +92,7 @@ extern bool draw_units; extern bool draw_focus_unit; extern bool draw_fog_of_war; +extern bool draw_borders; typedef struct { const char *name; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/packhand.c freeciv-patched/client/packhand.c --- freeciv-cvs/client/packhand.c 2003-06-07 19:58:20.000000000 +0100 +++ freeciv-patched/client/packhand.c 2003-06-09 14:43:37.000000000 +0100 @@ -490,7 +490,7 @@ } } - if (draw_map_grid && can_client_change_view()) { + if ((draw_map_grid || draw_borders) && can_client_change_view()) { /* We have to make sure we update any workers on the map grid, then * redraw the city descriptions on top of them. */ update_map_canvas(pcity->x - CITY_MAP_SIZE / 2, @@ -1681,6 +1681,19 @@ tile_changed = TRUE; ptile->special = packet->special; } + if (packet->owner == MAP_TILE_OWNER_NULL) { + if (ptile->owner) { + ptile->owner = NULL; + tile_changed = TRUE; + } + } else { + struct player *newowner = get_player(packet->owner); + + if (ptile->owner != newowner) { + ptile->owner = newowner; + tile_changed = TRUE; + } + } ptile->known = packet->known; reset_move_costs(packet->x, packet->y); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/capstr.c freeciv-patched/common/capstr.c --- freeciv-cvs/common/capstr.c 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/capstr.c 2003-06-09 14:43:37.000000000 +0100 @@ -78,7 +78,7 @@ "city_struct_minor_cleanup obsolete_last class_legend " \ "+impr_req +waste +fastfocus +continent +small_dipl " \ "+no_nation_selected +diplomacy +no_extra_tiles" \ - "+diplomacy2 +citizens_style" + "+diplomacy2 +citizens_style borders" /* "+1.14.0" is protocol for 1.14.0 release. * * "conn_info" is sending the conn_id field. To preserve compatability @@ -126,6 +126,8 @@ * * "citizens_style": is support for loading of ruleset-specified * multi style citizens icons. + * + * "borders" is support for national borders. */ void init_our_capability(void) diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/city.h freeciv-patched/common/city.h --- freeciv-cvs/common/city.h 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/city.h 2003-06-09 14:43:37.000000000 +0100 @@ -316,6 +316,17 @@ TYPED_LIST_ITERATE(struct city, citylist, pcity) #define city_list_iterate_end LIST_ITERATE_END +#define cities_iterate(pcity) \ +{ \ + players_iterate(CI_player) { \ + city_list_iterate(CI_player->cities, pcity) { + +#define cities_iterate_end \ + } city_list_iterate_end; \ + } players_iterate_end; \ +} + + /* properties */ struct player *city_owner(struct city *pcity); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/game.c freeciv-patched/common/game.c --- freeciv-cvs/common/game.c 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/game.c 2003-06-09 14:43:37.000000000 +0100 @@ -433,7 +433,7 @@ /************************************************************************** ... **************************************************************************/ -int civ_score(struct player *pplayer) +int civ_score_old(struct player *pplayer) { int i; struct city *pcity; @@ -691,6 +691,7 @@ game.spacerace = GAME_DEFAULT_SPACERACE; game.fogofwar = GAME_DEFAULT_FOGOFWAR; game.fogofwar_old= game.fogofwar; + game.borders = GAME_DEFAULT_BORDERS; game.auto_ai_toggle = GAME_DEFAULT_AUTO_AI_TOGGLE; game.notradesize = GAME_DEFAULT_NOTRADESIZE; game.fulltradesize = GAME_DEFAULT_FULLTRADESIZE; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/game.h freeciv-patched/common/game.h --- freeciv-cvs/common/game.h 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/game.h 2003-06-09 14:43:37.000000000 +0100 @@ -160,6 +160,8 @@ int watchtower_vision; int allowed_city_names; + int borders; /* 0=no borders, otherwise distance of border from city. */ + char rulesetdir[MAX_LEN_NAME]; int firepower_factor; /* See README.rulesets */ struct { @@ -246,7 +248,8 @@ void game_remove_unit(struct unit *punit); void game_remove_city(struct city *pcity); int total_player_citizens(struct player *pplayer); -int civ_score(struct player *pplayer); +int total_player_territory(struct player *pplayer); +int civ_score_old(struct player *pplayer); void initialize_globals(void); void translate_data_names(void); @@ -313,6 +316,10 @@ #define GAME_DEFAULT_FOGOFWAR TRUE +#define GAME_DEFAULT_BORDERS 7 +#define GAME_MIN_BORDERS 0 /* 0 means no national borders. */ +#define GAME_MAX_BORDERS 24 /* Performance sucks if this is too large, so limit at 24. */ + #define GAME_DEFAULT_DIPLCHANCE 80 #define GAME_MIN_DIPLCHANCE 1 #define GAME_MAX_DIPLCHANCE 99 diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/map.c freeciv-patched/common/map.c --- freeciv-cvs/common/map.c 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/map.c 2003-06-09 14:43:37.000000000 +0100 @@ -213,6 +213,23 @@ unit_list_init(&ptile->units); ptile->worked = NULL; /* pointer to city working tile */ ptile->assigned = 0; /* bitvector */ + ptile->owner = NULL; /* Tile not claimed by any nation. */ +} + +/************************************************************************** + Return the player who owns this tile (or NULL if none). +**************************************************************************/ +struct player *map_get_owner(int x, int y) +{ + return MAP_TILE(x, y)->owner; +} + +/************************************************************************** + Set the owner of a tile (may be NULL). +**************************************************************************/ +void map_set_owner(int x, int y, struct player *owner) +{ + MAP_TILE(x, y)->owner = owner; } /*************************************************************** diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/map.h freeciv-patched/common/map.h --- freeciv-cvs/common/map.h 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/map.h 2003-06-09 14:43:37.000000000 +0100 @@ -59,6 +59,7 @@ struct city *worked; /* city working tile, or NULL if none */ unsigned short continent; signed char move_cost[8]; /* don't know if this helps! */ + struct player *owner; /* Player owning this tile, or NULL. */ }; @@ -251,6 +252,8 @@ (dest_y) = (src_y) + DIR_DY[(dir)], \ normalize_map_pos(&(dest_x), &(dest_y))) +struct player *map_get_owner(int x, int y); +void map_set_owner(int x, int y, struct player *pplayer); struct city *map_get_city(int x, int y); void map_set_city(int x, int y, struct city *pcity); enum tile_terrain_type map_get_terrain(int x, int y); @@ -600,6 +603,8 @@ } \ } +#define MAP_TILE_OWNER_NULL MAX_UINT8 + #define MAP_DEFAULT_HUTS 50 #define MAP_MIN_HUTS 0 #define MAP_MAX_HUTS 500 diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets.c freeciv-patched/common/packets.c --- freeciv-cvs/common/packets.c 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/packets.c 2003-06-09 15:04:05.000000000 +0100 @@ -1160,6 +1160,9 @@ if (has_capability("continent", pc->capability)) { dio_get_uint16(&din, (int *)&packet->continent); } + if (has_capability("borders", pc->capability)) { + dio_get_uint16(&din, &packet->owner); + } RECEIVE_PACKET_END(packet); } @@ -1190,6 +1193,9 @@ if (has_capability("continent", pc->capability)) { dio_put_uint16(&dout, pinfo->continent); } + if (has_capability("borders", pc->capability)) { + dio_put_uint16(&dout, pinfo->owner); + } SEND_PACKET_END; } @@ -1867,6 +1873,10 @@ dio_put_uint8(&dout, packet->playable_nation_count); dio_put_uint8(&dout, packet->style_count); + if (has_capability("borders", pc->capability)) { + dio_put_uint8(&dout, packet->borders); + } + dio_put_tech_list(&dout, packet->rtech.partisan_req); if (has_capability("team", pc->capability)) { @@ -1913,6 +1923,10 @@ dio_get_uint8(&din, &packet->playable_nation_count); dio_get_uint8(&din, &packet->style_count); + if (has_capability("borders", pc->capability)) { + dio_get_uint8(&din, &packet->borders); + } + dio_get_tech_list(&din, packet->rtech.partisan_req); for (i = 0; i < MAX_NUM_TEAMS; i++) { diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets.h freeciv-patched/common/packets.h --- freeciv-cvs/common/packets.h 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/packets.h 2003-06-09 14:43:37.000000000 +0100 @@ -263,7 +263,7 @@ tile info *********************************************************/ struct packet_tile_info { - int x, y, type, special, known; + int x, y, type, special, known, owner; unsigned short continent; }; @@ -561,6 +561,7 @@ info for its own "control" packet, done separately.) *********************************************************/ struct packet_ruleset_control { + int borders; int aqueduct_size; int sewer_size; int add_to_size_limit; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/shared.h freeciv-patched/common/shared.h --- freeciv-cvs/common/shared.h 2003-06-07 19:58:27.000000000 +0100 +++ freeciv-patched/common/shared.h 2003-06-09 14:43:37.000000000 +0100 @@ -110,6 +110,7 @@ /* This is duplicated in rand.h to avoid extra includes: */ #define MAX_UINT32 0xFFFFFFFF +#define MAX_UINT8 0xFF #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define ADD_TO_POINTER(p, n) ((void *)((char *)(p)+(n))) diff -Nur -Xfreecivdiff.ignore freeciv-cvs/data/Freeciv freeciv-patched/data/Freeciv --- freeciv-cvs/data/Freeciv 2003-06-07 19:58:27.000000000 +0100 +++ freeciv-patched/data/Freeciv 2003-06-09 15:50:49.000000000 +0100 @@ -2775,6 +2775,7 @@ Shift: btn-adjust-workers() \n\ : btn-select-mapcanvas() \n\ Ctrlg: key-map-grid-toggle() \n\ + Ctrlb: key-map-borders-toggle() \n\ Ctrln: key-city-names-toggle() \n\ Ctrlp: key-city-productions-toggle() \n\ Shiftc: key-unit-connect() \n\ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/doc/README.borders_patch freeciv-patched/doc/README.borders_patch --- freeciv-cvs/doc/README.borders_patch 1970-01-01 01:00:00.000000000 +0100 +++ freeciv-patched/doc/README.borders_patch 2003-06-09 15:19:00.000000000 +0100 @@ -0,0 +1,74 @@ +Borders Patch +------------- +Authors: Stewart Adcock + Ben Webb + +This patch adds national borders. This version aims to mimic the borders in +SMAC, Civ:CTP, and other versions of Civ. Earlier builds of FreecivAC +incorporated a different design that took into account fog-of-war and player +knowledge. The consensus opinion was that this other implementation sucks +(it seems that only I preferred it). + +Currently, the only non-cosmetic effects of the borders are: + (1) in the placement of workers on city tiles. A worker may not be placed + in the territory of another nation. + (2) civscore routines are modified to use the new territorial claims. This + no longer uses a different analysis of territory. Is this desirable? + One fairly significant change is the required transfer of the civ_score() + function from common/game.c to server/srv_main.c. This function is only + ever used in the server so nothing should be broken. The territory + measurement routines are also applied within the historian report code. + The historian reports have also been modified slightly. Now, "LARGEST" + refers to the greatest territorial area, whilst the greatest population + is now termed "MOST POPULOUS". This could be a separate patch. + (3) Earlier versions of this patch added an extra field in the city structure, + and changed the savegame format, to keep track of which turn a city was + founded in. Freeciv proper now does this anyway, so we use its code now. + (4) Borders are not stored in savegames due to the excessive size increase + that results, although the value of the "borders" server variable is. + Instead, the borders are simply recalculated upon loading a savefile. + Likewise, the tile packets now include an extra 8-bit unsigned integer, + so a new capability ("borders") is used. Unlike earlier versions of this + patch, the borders capability is not essential. + +Border colour selection is only quickly hacked together. This will be refined +in a further planned patch. + +Borders should be displayed for both isometric and non-isometric view, in +GTK, GTK2 and Xaw clients. + +This implementation will continue to work with ocean cities / water bases, +which are used in FreecivAC. This should not make the possible later addition +of multiple oceans, as indicated in the TODO list, any more complex. + +I have also added a very useful cities_iterate macro. This is consistent with +players_iterate etc. + +The code used for updating city worker states is slightly less than optimal, +but was implemented such that it uses the original code. + + +Unresolved issues +----------------- +To do/fix __before__ application of patch to CVS: +* Clients receive border information for all players in explored territory - + this enables city locations to be guessed at rather accurately. A better + solution would be to only send updated information for non-fogged tiles. +* Borders are redrawn too many times when cities are founded, destroyed + or change ownership. Redraws should be frozen until all relevant tile_info + packets have been received. +* A player's own borders do not seem to be redrawn properly when new cities + are founded, if they are fogged. + +To do/fix in later patches: +* Support for other clients. +* Define whether territory may overlap onto other continents in ruleset. +* Record change of territory with respect to time. +* Settlers to only build roads/irrigation on own territory. +* Optional minimap view coloured to show territories. +* Integrate into diplomacy. This is started, but not included in this + patch (read: very buggy). Two new treaty clauses: + - Declare war on other nations. + - Remove units from territory. +* Dodgy colour selections. I've got ideas to fix-up this, but that will be a + separate patch. diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/citytools.c freeciv-patched/server/citytools.c --- freeciv-cvs/server/citytools.c 2003-06-07 19:58:48.000000000 +0100 +++ freeciv-patched/server/citytools.c 2003-06-09 14:43:37.000000000 +0100 @@ -849,6 +849,9 @@ pcity->owner = ptaker->player_no; city_list_insert(&ptaker->cities, pcity); + /* Update national borders. */ + map_update_borders_city_change(pcity); + transfer_city_units(ptaker, pgiver, &old_city_units, pcity, NULL, kill_outside, transfer_unit_verbose); @@ -983,6 +986,9 @@ city_list_insert(&pplayer->cities, pcity); add_city_to_minimap(x, y); + /* Update the national borders. */ + map_update_borders_city_change(pcity); + /* it is possible to build a city on a tile that is already worked * this will displace the worker on the newly-built city's tile -- Syela */ for (y_itr = 0; y_itr < CITY_MAP_SIZE; y_itr++) { @@ -1141,6 +1147,7 @@ /* DO NOT remove city from minimap here. -- Syela */ game_remove_city(pcity); + map_update_borders_city_destroyed(x, y); players_iterate(other_player) { if (map_get_known_and_seen(x, y, other_player)) { @@ -1831,6 +1838,10 @@ if (ptile->worked && ptile->worked != pcity) return FALSE; + if (ptile->owner && ptile->owner->player_no != pcity->owner) { + return FALSE; + } + return TRUE; } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/gamelog.c freeciv-patched/server/gamelog.c --- freeciv-cvs/server/gamelog.c 2003-06-07 19:58:48.000000000 +0100 +++ freeciv-patched/server/gamelog.c 2003-06-09 14:43:37.000000000 +0100 @@ -25,6 +25,7 @@ #include "log.h" #include "map.h" #include "mem.h" +#include "report.h" #include "support.h" #include "gamelog.h" diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/mapgen.c freeciv-patched/server/mapgen.c --- freeciv-cvs/server/mapgen.c 2003-06-07 19:58:48.000000000 +0100 +++ freeciv-patched/server/mapgen.c 2003-06-09 14:43:37.000000000 +0100 @@ -1750,6 +1750,7 @@ for (x = 0 ; x < map.xsize ; x++) { map_set_terrain(x, y, T_OCEAN); map_set_continent(x, y, 0); + map_set_owner(x, y, NULL); } for (x = 0 ; x < map.xsize; x++) { map_set_terrain(x, 0, myrand(9) > 0 ? T_ARCTIC : T_TUNDRA); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/maphand.c freeciv-patched/server/maphand.c --- freeciv-cvs/server/maphand.c 2003-06-07 19:58:48.000000000 +0100 +++ freeciv-patched/server/maphand.c 2003-06-09 14:43:38.000000000 +0100 @@ -336,6 +336,7 @@ info.x = x; info.y = y; + info.owner = ptile->owner ? ptile->owner->player_no : MAP_TILE_OWNER_NULL; conn_list_iterate(*dest, pconn) { struct player *pplayer = pconn->player; @@ -375,6 +376,7 @@ info.x = x; info.y = y; + info.owner = ptile->owner ? ptile->owner->player_no : MAP_TILE_OWNER_NULL; if (!pplayer) { /* observer sees all */ info.known=TILE_KNOWN; @@ -1425,6 +1427,8 @@ send_all_known_tiles(NULL); } + + map_update_borders_landmass_change(x, y); gamelog(GAMELOG_MAP, _("(%d,%d) land created from ocean"), x, y); return OLC_OCEAN_TO_LAND; @@ -1439,8 +1443,200 @@ send_all_known_tiles(NULL); } + map_update_borders_landmass_change(x, y); + gamelog(GAMELOG_MAP, _("(%d,%d) ocean created from land"), x, y); return OLC_LAND_TO_OCEAN; } return OLC_NONE; } + +/************************************************************************* + Return pointer to the oldest adjacent city to this tile. If + there is a city on the exact tile, that is returned instead. +*************************************************************************/ +static struct city *map_get_adjc_city(int x, int y) +{ + struct city *closest = NULL; /* Closest city */ + struct tile *ptile; + + ptile = map_get_tile(x, y); + if (ptile->city) { + return ptile->city; + } + + adjc_iterate(x, y, xp, yp) { + ptile = map_get_tile(xp, yp); + if (ptile->city && + (!closest || ptile->city->turn_founded < closest->turn_founded)) { + closest = ptile->city; + } + } adjc_iterate_end; + + return closest; +} + +/************************************************************************* + Return pointer to the closest city to this tile, which must be + on the same continent if the city is not immediately adjacent. + If two or more cities are equally distant, then return the + oldest (i.e. the one with the lowest id). This also correctly + works for water bases in SMAC mode, and allows coastal cities + to claim one square of ocean. If no cities are within game.borders + distance, returns NULL. + + NOTE: The behaviour of this function will eventually depend + upon some planned ruleset options. +*************************************************************************/ +static struct city *map_get_closest_city(int x, int y) +{ + struct city *closest; /* Closest city */ + int distsq; /* Squared distance to city */ + int cldistsq; /* Squared distance to closest city */ + + closest = map_get_adjc_city(x, y); + if (!closest) { + cldistsq = game.borders * game.borders; + cities_iterate(pcity) { + if (map_get_continent(pcity->x, pcity->y) == map_get_continent(x, y)) { + distsq = sq_map_distance(pcity->x, pcity->y, x, y); + if (distsq < cldistsq || + (distsq == cldistsq && + (!closest || closest->turn_founded > pcity->turn_founded))) { + closest = pcity; + cldistsq = distsq; + } + } + } cities_iterate_end; + } + + return closest; +} + +/************************************************************************* + Update tile worker states for all cities that have the given map tile + within their radius. Does not sync with client. +*************************************************************************/ +static void tile_update_owner(int x, int y) +{ + cities_iterate(pcity) { + int cityx, cityy; + if (map_to_city_map(&cityx, &cityy, pcity, x, y)) { + update_city_tile_status_map(pcity, x, y); +#if 0 + update_city_tile_status_map(pcity, cityx, cityy); +#endif + } + } cities_iterate_end; +} + +/************************************************************************* + Recalculate the borders around a given position. +*************************************************************************/ +static void map_update_borders_recalculate_position(int x, int y) +{ + if (game.borders > 0) { + iterate_outward(x, y, game.borders, xp, yp) { + struct city *pccity = map_get_closest_city(xp, yp); + struct player *new_owner = pccity ? get_player(pccity->owner) : NULL; + + if (new_owner != map_get_owner(xp, yp)) { + map_set_owner(xp, yp, new_owner); + send_tile_info(NULL, xp, yp); + tile_update_owner(xp, yp); + } + } iterate_outward_end; + } +} + +/************************************************************************* + Modify national territories as resulting from a city being destroyed. + x,y coords for (already deleted) city's location. + Tile worker states are updated as necessary, but not sync'd with client. +*************************************************************************/ +void map_update_borders_city_destroyed(int x, int y) +{ + map_update_borders_recalculate_position(x, y); +} + +/************************************************************************* + Modify national territories resulting from a change of landmass. + Tile worker states are updated as necessary, but not sync'd with client. + NOTE: Currently just recalculates all borders from scratch - this is + really inefficient. + NOTE: The behaviour of this function will eventually depend upon some + planned ruleset options, hence the passed (but unused) x,y parameters. +*************************************************************************/ +void map_update_borders_landmass_change(int x, int y) +{ + if (game.borders > 0) { + map_calculate_borders(); + + whole_map_iterate(xp, yp) { + send_tile_info(NULL, xp, yp); + } whole_map_iterate_end; + } +} + +/************************************************************************* + Modify national territories resulting from new city or change of city + ownership. + Tile worker states are updated as necessary, but not sync'd with client. +*************************************************************************/ +void map_update_borders_city_change(struct city *pcity) +{ + map_update_borders_recalculate_position(pcity->x, pcity->y); +} + +/************************************************************************* + Delete the territorial claims to all tiles. +*************************************************************************/ +void map_clear_borders(void) +{ + whole_map_iterate(x, y) { + map_set_owner(x, y, NULL); + } whole_map_iterate_end; +} + +/************************************************************************* + Minimal code that calculates all national territories from scratch. +*************************************************************************/ +void map_calculate_territory(void) +{ + /* Clear any old territorial claims. */ + map_clear_borders(); + + if (game.borders > 0) { + /* Loop over all cities and claim territory. */ + cities_iterate(pcity) { + /* Loop over all map tiles within this city's sphere of influence. */ + iterate_outward(pcity->x, pcity->y, game.borders, x, y) { + struct city *pccity = map_get_closest_city(x, y); + + if (pccity) { + map_set_owner(x, y, get_player(pccity->owner)); + } + } iterate_outward_end; + } cities_iterate_end; + } +} + +/************************************************************************* + Calculate all national territories from scratch. This can be slow, but + is only performed occasionally, i.e. after loading a saved game. Doesn't + send any tile information to the clients. Tile worker states are updated + as necessary, but not sync'd with client. +*************************************************************************/ +void map_calculate_borders(void) +{ + if (game.borders > 0) { + map_calculate_territory(); + + /* Fix tile worker states. */ + cities_iterate(pcity) { + map_city_radius_iterate(pcity->x, pcity->y, map_x, map_y) { + update_city_tile_status_map(pcity, map_x, map_y); + } map_city_radius_iterate_end; + } cities_iterate_end; + } +} diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/maphand.h freeciv-patched/server/maphand.h --- freeciv-cvs/server/maphand.h 2003-06-07 19:58:48.000000000 +0100 +++ freeciv-patched/server/maphand.h 2003-06-09 14:43:38.000000000 +0100 @@ -90,6 +90,13 @@ void disable_fog_of_war(void); bool is_coast_seen(int x, int y, struct player *pplayer); +void map_update_borders_city_destroyed(int x, int y); +void map_update_borders_city_change(struct city *pcity); +void map_update_borders_landmass_change(int x, int y); +void map_clear_borders(void); +void map_calculate_territory(void); +void map_calculate_borders(void); + enum ocean_land_change check_terrain_ocean_land_change(int x, int y, enum tile_terrain_type oldter); #endif /* FC__MAPHAND_H */ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/plrhand.c freeciv-patched/server/plrhand.c --- freeciv-cvs/server/plrhand.c 2003-06-07 19:58:49.000000000 +0100 +++ freeciv-patched/server/plrhand.c 2003-06-09 14:43:38.000000000 +0100 @@ -1353,6 +1353,11 @@ ai_data_done(pplayer); game_remove_player(pplayer); game_renumber_players(pplayer->player_no); + +/* Update borders. + * Recalculating all borders from scratch is probably cheaper than updating for each removed city. + */ + map_calculate_borders(); } /************************************************************************** diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/report.c freeciv-patched/server/report.c --- freeciv-cvs/server/report.c 2003-06-07 19:58:49.000000000 +0100 +++ freeciv-patched/server/report.c 2003-06-09 14:43:38.000000000 +0100 @@ -32,6 +32,7 @@ #include "citytools.h" +#include "maphand.h" #include "report.h" static void page_conn_etype(struct conn_list *dest, const char *caption, @@ -42,7 +43,8 @@ HISTORIAN_ADVANCED=1, HISTORIAN_MILITARY=2, HISTORIAN_HAPPIEST=3, - HISTORIAN_LARGEST=4}; + HISTORIAN_LARGEST=4, + HISTORIAN_TERRITORY=5}; #define HISTORIAN_FIRST HISTORIAN_RICHEST #define HISTORIAN_LAST HISTORIAN_LARGEST @@ -52,6 +54,7 @@ N_("%s report on the most ADVANCED Civilizations in the World."), N_("%s report on the most MILITARIZED Civilizations in the World."), N_("%s report on the HAPPIEST Civilizations in the World."), + N_("%s report on the most POPULOUS Civilizations in the World."), N_("%s report on the LARGEST Civilizations in the World.") }; @@ -135,6 +138,8 @@ { 'b', DEM_COL_BEST } }; +#define USER_AREA_MULT (1000) + /************************************************************************** ... **************************************************************************/ @@ -184,6 +189,11 @@ case HISTORIAN_LARGEST: size[j].value = total_player_citizens(pplayer); break; + case HISTORIAN_TERRITORY: + size[j].value=total_player_territory(pplayer); + break; + default: + freelog(LOG_DEBUG, "Unknown historian type."); } size[j].player = pplayer; j++; @@ -858,6 +868,7 @@ /************************************************************************** Create a log file of the civilizations so you can see what was happening. +NOTE: This should be ammended to use new territory definition. **************************************************************************/ static void log_civ_score(void) { @@ -1071,6 +1082,155 @@ } /************************************************************************** +Returns the given player's landarea and settledarea. "landarea" is the +claimed territory. "settledarea" is claimed territory which is also +within owned cities' radii. +**************************************************************************/ +static void player_get_landarea(struct player *pplayer, + int *return_landarea, + int *return_settledarea) +{ + int settled; /* Whether a particular tile is settled by this player. */ + struct city *pcity; + + if (pplayer) { + if (return_landarea) { + *return_landarea = 0; + whole_map_iterate(x, y) { + if (map_get_owner(x, y) == pplayer) + (*return_landarea)++; + } whole_map_iterate_end; + + *return_landarea *= USER_AREA_MULT; + } + if (return_settledarea) { + *return_settledarea = 0; + whole_map_iterate(x, y) { + settled=0; + if (map_get_owner(x, y) == pplayer) { + map_city_radius_iterate(x, y, x_itr, y_itr) { + if ( (pcity=map_get_city(x_itr, y_itr)) && + pcity->owner == pplayer->player_no ) { + settled = 1; + } + } map_city_radius_iterate_end; + } + *return_settledarea += settled; + } whole_map_iterate_end; + + *return_settledarea *= USER_AREA_MULT; + } + } +} + +/************************************************************************** +Return number of tiles claimed by player's nation. +**************************************************************************/ +int total_player_territory(struct player *pplayer) +{ + return (pplayer->score.landarea); +} + +/************************************************************************** +Return the overall civilisation score. +If borders are disabled for this game, then the default border radius is +used to calculate the territories. +**************************************************************************/ +int civ_score(struct player *pplayer) +{ + int i; + struct city *pcity; + int landarea, settledarea; + int orig_borders; + + pplayer->score.happy=0; /* done */ + pplayer->score.content=0; /* done */ + pplayer->score.unhappy=0; /* done */ + pplayer->score.taxmen=0; /* done */ + pplayer->score.scientists=0; /* done */ + pplayer->score.elvis=0; /* done */ + pplayer->score.wonders=0; /* done */ + pplayer->score.techs=0; /* done */ + pplayer->score.techout=0; /* done */ + pplayer->score.landarea=0; /* done */ + pplayer->score.settledarea=0; /* done */ + pplayer->score.population=0; + pplayer->score.cities=0; /* done */ + pplayer->score.units=0; /* done */ + pplayer->score.pollution=0; /* done */ + pplayer->score.bnp=0; /* done */ + pplayer->score.mfg=0; /* done */ + pplayer->score.literacy=0; + pplayer->score.spaceship=0; + + if (is_barbarian(pplayer)) return 0; + + city_list_iterate(pplayer->cities, pcity) { + pplayer->score.happy+=pcity->ppl_happy[4]; + pplayer->score.content+=pcity->ppl_content[4]; + pplayer->score.unhappy+=pcity->ppl_unhappy[4]; + pplayer->score.taxmen+=pcity->ppl_taxman; + pplayer->score.scientists+=pcity->ppl_scientist; + pplayer->score.elvis+=pcity->ppl_elvis; + pplayer->score.population+=city_population(pcity); + pplayer->score.cities++; + pplayer->score.pollution+=pcity->pollution; + pplayer->score.techout+=pcity->science_total; + pplayer->score.bnp+=pcity->trade_prod; + pplayer->score.mfg+=pcity->shield_surplus; + if (city_got_building(pcity, B_UNIVERSITY)) + pplayer->score.literacy+=city_population(pcity); + else if (city_got_building(pcity,B_LIBRARY)) + pplayer->score.literacy+=(city_population(pcity)/2); + } + city_list_iterate_end; + + if ( (orig_borders=game.borders) ) { + game.borders=GAME_DEFAULT_BORDERS; + map_calculate_territory(); + } + + player_get_landarea(pplayer, &landarea, &settledarea); + pplayer->score.landarea=landarea; + pplayer->score.settledarea=settledarea; + + if (orig_borders==0) { + /* Delete territorial claims. */ + game.borders=0; + map_clear_borders(); + } + + for (i=0;iscore.techs++; + pplayer->score.techs+=(((pplayer->future_tech)*5)/2); + + unit_list_iterate(pplayer->units, punit) + if (is_military_unit(punit)) pplayer->score.units++; + unit_list_iterate_end; + + for (i=0;iscore.wonders++; + } + + /* How much should a spaceship be worth?? + This gives 100 points per 10,000 citizens. --dwp + */ + if (pplayer->spaceship.state == SSHIP_ARRIVED) { + pplayer->score.spaceship += (int)(100 * pplayer->spaceship.habitation + * pplayer->spaceship.success_rate); + } + + return (total_player_citizens(pplayer) + +pplayer->score.happy + +pplayer->score.techs*2 + +pplayer->score.wonders*5 + +pplayer->score.spaceship); +} + +/************************************************************************** ... **************************************************************************/ void report_scores(bool final) diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/report.h freeciv-patched/server/report.h --- freeciv-cvs/server/report.h 2003-01-03 16:09:50.000000000 +0000 +++ freeciv-patched/server/report.h 2003-06-09 14:43:38.000000000 +0100 @@ -26,6 +26,7 @@ void report_top_five_cities(struct conn_list *dest); bool is_valid_demography(const char *demographics, char **error_message); void report_demographics(struct connection *pconn); +int civ_score(struct player *pplayer); void report_scores(bool final); /* See also report_server_options() in stdinhand.h */ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/sanitycheck.c freeciv-patched/server/sanitycheck.c --- freeciv-cvs/server/sanitycheck.c 2003-06-07 19:58:49.000000000 +0100 +++ freeciv-patched/server/sanitycheck.c 2003-06-09 14:43:38.000000000 +0100 @@ -144,6 +144,8 @@ if (city_map_to_map(&map_x, &map_y, pcity, x, y)) { struct tile *ptile = map_get_tile(map_x, map_y); + struct player *owner = map_get_owner(map_x, map_y); + switch (get_worker_city(pcity, x, y)) { case C_TILE_EMPTY: if (map_get_tile(map_x, map_y)->worked) { @@ -157,6 +159,12 @@ "empty but occupied by an enemy unit!", pcity->name, x, y); } + if (game.borders > 0 + && owner && owner->player_no != pcity->owner) { + freelog(LOG_ERROR, "Tile at %s->%d,%d marked as " + "empty but in enemy territory!", + pcity->name, x, y); + } break; case C_TILE_WORKER: if (map_get_tile(map_x, map_y)->worked != pcity) { @@ -169,11 +177,18 @@ "worked but occupied by an enemy unit!", pcity->name, x, y); } + if (game.borders > 0 + && owner && owner->player_no != pcity->owner) { + freelog(LOG_ERROR, "Tile at %s->%d,%d marked as " + "worked but in enemy territory!", + pcity->name, x, y); + } break; case C_TILE_UNAVAILABLE: if (!map_get_tile(map_x, map_y)->worked && !is_enemy_unit_tile(ptile, pplayer) - && map_get_known(map_x, map_y, pplayer)) { + && map_get_known(map_x, map_y, pplayer) + && (!owner || owner->player_no == pcity->owner)) { freelog(LOG_ERROR, "Tile at %s->%d,%d marked as " "unavailable but seems to be available!", pcity->name, x, y); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/savegame.c freeciv-patched/server/savegame.c --- freeciv-cvs/server/savegame.c 2003-06-07 19:58:49.000000000 +0100 +++ freeciv-patched/server/savegame.c 2003-06-09 14:43:38.000000000 +0100 @@ -1869,6 +1869,9 @@ game.rapturedelay = secfile_lookup_int_default(file, GAME_DEFAULT_RAPTUREDELAY, "game.rapturedelay"); + /* National borders setting. */ + game.borders = secfile_lookup_int_default(file, 0, "game.borders"); + if (has_capability("watchtower", savefile_options)) { game.watchtower_extra_vision = secfile_lookup_int(file, "game.watchtower_extra_vision"); @@ -2140,6 +2143,9 @@ initialize_globals(); apply_unit_ordering(); + /* Rebuild national borders. */ + map_calculate_borders(); + /* Make sure everything is consistent. */ players_iterate(pplayer) { unit_list_iterate(pplayer->units, punit) { @@ -2259,6 +2265,7 @@ secfile_insert_int(file, game.onsetbarbarian, "game.onsetbarbs"); secfile_insert_int(file, game.occupychance, "game.occupychance"); secfile_insert_str(file, game.demography, "game.demography"); + secfile_insert_int(file, game.borders, "game.borders"); secfile_insert_int(file, game.watchtower_vision, "game.watchtower_vision"); secfile_insert_int(file, game.watchtower_extra_vision, "game.watchtower_extra_vision"); secfile_insert_int(file, game.allowed_city_names, "game.allowed_city_names"); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/stdinhand.c freeciv-patched/server/stdinhand.c --- freeciv-cvs/server/stdinhand.c 2003-06-07 19:58:49.000000000 +0100 +++ freeciv-patched/server/stdinhand.c 2003-06-09 14:43:38.000000000 +0100 @@ -604,6 +604,13 @@ "changes in squares not observed."), NULL, GAME_DEFAULT_FOGOFWAR) + GEN_INT("borders", game.borders, SSET_RULES_FLEXIBLE, SSET_TO_CLIENT, + N_("National border's radius"), + N_("If this is set to greater than 0, nations will have territory " + "delineated by borders placed on the loci between cities, with " + "the maximum distance from any city specified."), NULL, + GAME_MIN_BORDERS, GAME_MAX_BORDERS, GAME_DEFAULT_BORDERS) + GEN_INT("diplchance", game.diplchance, SSET_RULES_FLEXIBLE, SSET_TO_CLIENT, N_("Chance in diplomat/spy contests"), /* xgettext:no-c-format */