diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/control.c freeciv-patched/client/control.c --- freeciv-cvs/client/control.c 2003-06-11 12:01:29.000000000 +0100 +++ freeciv-patched/client/control.c 2003-06-16 11:14:27.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-16 11:14:27.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-16 11:14:27.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-16 11:14:27.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-16 11:14:27.000000000 +0100 @@ -1148,13 +1148,17 @@ } /************************************************************************** - Draw a 1-pixel-width colored line onto the mapview or citydialog canvas. + Draw a colored line onto the mapview or citydialog canvas. **************************************************************************/ void gui_put_line(struct canvas_store *pcanvas_store, enum color_std color, - int start_x, int start_y, int dx, int dy) + enum line_type ltype, int start_x, int start_y, + int dx, int dy) { - gdk_gc_set_foreground(civ_gc, colors_standard[color]); - gdk_draw_line(pcanvas_store->pixmap, civ_gc, + GdkGC *gc; + + gc = (ltype == LINE_BORDER ? border_line_gc : civ_gc); + gdk_gc_set_foreground(gc, colors_standard[color]); + gdk_draw_line(pcanvas_store->pixmap, gc, start_x, start_y, start_x + dx, start_y + dy); } 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-16 11:14:27.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,8 @@ (game.player_ptr->spaceship.state!=SSHIP_NONE)); menus_set_active("
/_View/Map _Grid", draw_map_grid); + menus_set_sensitive("
/_View/National _Borders", game.borders > 0); + 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-16 11:14:27.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-16 11:14:27.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-16 11:14:27.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/mapctrl.c freeciv-patched/client/gui-gtk-2.0/mapctrl.c --- freeciv-cvs/client/gui-gtk-2.0/mapctrl.c 2003-06-07 19:58:22.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/mapctrl.c 2003-06-16 11:14:27.000000000 +0100 @@ -107,6 +107,21 @@ _("Minor Tribe Village"), NULL); count++; } + + if (game.borders > 0) { + struct player *owner = map_get_owner(xtile, ytile); + if (owner) { + my_snprintf(s, sizeof(s), _("Claimed by: %s"), + get_nation_name(owner->nation)); + gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, + "GtkLabel::label", s, NULL); + } else { + gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", b, + "GtkLabel::label", + _("Unclaimed territory"), NULL); + } + count++; + } if((pcity = map_get_city(xtile, ytile))) { my_snprintf(s, sizeof(s), _("City: %s(%s)"), pcity->name, 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-16 11:14:27.000000000 +0100 @@ -1232,13 +1232,17 @@ } /************************************************************************** - Draw a 1-pixel-width colored line onto the mapview or citydialog canvas. + Draw a colored line onto the mapview or citydialog canvas. **************************************************************************/ void gui_put_line(struct canvas_store *pcanvas_store, enum color_std color, - int start_x, int start_y, int dx, int dy) + enum line_type ltype, int start_x, int start_y, + int dx, int dy) { - gdk_gc_set_foreground(civ_gc, colors_standard[color]); - gdk_draw_line(pcanvas_store->pixmap, civ_gc, + GdkGC *gc; + + gc = (ltype == LINE_BORDER ? border_line_gc : civ_gc); + gdk_gc_set_foreground(gc, colors_standard[color]); + gdk_draw_line(pcanvas_store->pixmap, gc, start_x, start_y, start_x + dx, start_y + dy); } 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-16 11:14:27.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,8 @@ (game.player_ptr->spaceship.state!=SSHIP_NONE)); menus_set_active("
/_View/Map _Grid", draw_map_grid); + menus_set_sensitive("
/_View/National _Borders", game.borders > 0); + 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-16 11:14:27.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-sdl/mapview.c freeciv-patched/client/gui-sdl/mapview.c --- freeciv-cvs/client/gui-sdl/mapview.c 2003-06-07 19:58:23.000000000 +0100 +++ freeciv-patched/client/gui-sdl/mapview.c 2003-06-16 11:14:27.000000000 +0100 @@ -184,7 +184,8 @@ Draw a 1-pixel-width colored line onto the mapview or citydialog canvas. **************************************************************************/ void gui_put_line(struct canvas_store *pCanvas_store, enum color_std color, - int start_x, int start_y, int dx, int dy) + enum line_type ltype, int start_x, int start_y, + int dx, int dy) { putline(pCanvas_store->map, start_x, start_y, start_x + dx, start_y + dy, get_game_color(color, pCanvas_store->map)); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-stub/mapview.c freeciv-patched/client/gui-stub/mapview.c --- freeciv-cvs/client/gui-stub/mapview.c 2003-06-07 19:58:24.000000000 +0100 +++ freeciv-patched/client/gui-stub/mapview.c 2003-06-16 11:14:27.000000000 +0100 @@ -189,7 +189,8 @@ Draw a 1-pixel-width colored line onto the mapview or citydialog canvas. **************************************************************************/ void gui_put_line(struct canvas_store *pcanvas_store, enum color_std color, - int start_x, int start_y, int dx, int dy) + enum line_type ltype, int start_x, int start_y, + int dx, int dy) { /* PORTME */ } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-win32/mapview.c freeciv-patched/client/gui-win32/mapview.c --- freeciv-cvs/client/gui-win32/mapview.c 2003-06-07 19:58:25.000000000 +0100 +++ freeciv-patched/client/gui-win32/mapview.c 2003-06-16 11:14:27.000000000 +0100 @@ -1327,7 +1327,8 @@ Draw a 1-pixel-width colored line onto the mapview or citydialog canvas. **************************************************************************/ void gui_put_line(struct canvas_store *pcanvas_store, enum color_std color, - int start_x, int start_y, int dx, int dy) + enum line_type ltype, int start_x, int start_y, + int dx, int dy) { HDC hdc = CreateCompatibleDC(pcanvas_store->hdc); HPEN old = SelectObject(hdc, pen_std[color]); 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-16 11:14:27.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/gui_main.c freeciv-patched/client/gui-xaw/gui_main.c --- freeciv-cvs/client/gui-xaw/gui_main.c 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/client/gui-xaw/gui_main.c 2003-06-16 11:14:27.000000000 +0100 @@ -159,6 +159,9 @@ /* this GC will be the default one all thru freeciv */ GC civ_gc; +/* This is for drawing border lines */ +GC border_line_gc; + /* and this one is used for filling with the bg color */ GC fill_bg_gc; GC fill_tile_gc; @@ -370,6 +373,15 @@ GCForeground|GCBackground|GCFont|GCGraphicsExposures, &values); + values.line_width = 2; + values.line_style = LineOnOffDash; + values.cap_style = CapNotLast; + values.join_style = JoinMiter; + values.fill_style = FillSolid; + border_line_gc = XCreateGC(display, root_window, + GCGraphicsExposures|GCLineWidth|GCLineStyle + |GCCapStyle|GCJoinStyle|GCFillStyle, &values); + values.foreground = 0; values.background = 0; fill_bg_gc= XCreateGC(display, root_window, diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-xaw/gui_main.h freeciv-patched/client/gui-xaw/gui_main.h --- freeciv-cvs/client/gui-xaw/gui_main.h 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/client/gui-xaw/gui_main.h 2003-06-16 11:14:27.000000000 +0100 @@ -25,6 +25,7 @@ extern int display_depth; extern int screen_number; extern GC civ_gc; +extern GC border_line_gc; extern GC fill_bg_gc; extern GC fill_tile_gc; extern GC font_gc; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-xaw/mapview.c freeciv-patched/client/gui-xaw/mapview.c --- freeciv-cvs/client/gui-xaw/mapview.c 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/client/gui-xaw/mapview.c 2003-06-16 11:14:27.000000000 +0100 @@ -651,10 +651,14 @@ Draw a 1-pixel-width colored line onto the mapview or citydialog canvas. **************************************************************************/ void gui_put_line(struct canvas_store *pcanvas_store, enum color_std color, - int start_x, int start_y, int dx, int dy) + enum line_type ltype, int start_x, int start_y, + int dx, int dy) { - XSetForeground(display, civ_gc, colors_standard[color]); - XDrawLine(display, pcanvas_store->pixmap, civ_gc, + GC gc; + + gc = (ltype == LINE_BORDER ? border_line_gc : civ_gc); + XSetForeground(display, gc, colors_standard[color]); + XDrawLine(display, pcanvas_store->pixmap, gc, start_x, start_y, start_x + dx, start_y + dy); } 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-16 11:14:27.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-16 11:14:27.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/include/colors_g.h freeciv-patched/client/include/colors_g.h --- freeciv-cvs/client/include/colors_g.h 2003-01-03 16:09:44.000000000 +0000 +++ freeciv-patched/client/include/colors_g.h 2003-06-16 11:14:27.000000000 +0100 @@ -27,6 +27,10 @@ COLOR_STD_LAST }; +enum line_type { + LINE_NORMAL, LINE_BORDER +}; + enum Display_color_type { BW_DISPLAY, GRAYSCALE_DISPLAY, COLOR_DISPLAY }; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/include/mapview_g.h freeciv-patched/client/include/mapview_g.h --- freeciv-cvs/client/include/mapview_g.h 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/client/include/mapview_g.h 2003-06-16 11:14:27.000000000 +0100 @@ -51,7 +51,8 @@ enum color_std color, int canvas_x, int canvas_y, int width, int height); void gui_put_line(struct canvas_store *pcanvas_store, enum color_std color, - int start_x, int start_y, int dx, int dy); + enum line_type ltype, int start_x, int start_y, + int dx, int dy); void flush_mapcanvas(int canvas_x, int canvas_y, int pixel_width, int pixel_height); void dirty_rect(int canvas_x, int canvas_y, 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-16 11:14:27.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), LINE_BORDER, + canvas_x - 1, canvas_y + 1, + 0, NORMAL_TILE_HEIGHT - 1); + } + if (this_owner) { + gui_put_line(pcanvas_store, player_color(this_owner), LINE_BORDER, + 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), LINE_BORDER, + canvas_x + 1, canvas_y - 1, NORMAL_TILE_WIDTH - 1, 0); + } + if (this_owner) { + gui_put_line(pcanvas_store, player_color(this_owner), LINE_BORDER, + 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. **************************************************************************/ @@ -425,14 +467,21 @@ /* left side... */ gui_put_line(pcanvas_store, get_grid_color(map_x, map_y, map_x - 1, map_y), + LINE_NORMAL, canvas_x, canvas_y, 0, NORMAL_TILE_HEIGHT); /* top side... */ gui_put_line(pcanvas_store, get_grid_color(map_x, map_y, map_x, map_y - 1), + LINE_NORMAL, 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; @@ -441,7 +490,7 @@ if (MAPSTEP(x1, y1, map_x, map_y, DIR8_WEST)) { t2 = map_get_terrain(x1, y1); if (is_ocean(t1) ^ is_ocean(t2)) { - gui_put_line(pcanvas_store, COLOR_STD_OCEAN, + gui_put_line(pcanvas_store, COLOR_STD_OCEAN, LINE_NORMAL, canvas_x, canvas_y, 0, NORMAL_TILE_HEIGHT); } } @@ -450,7 +499,7 @@ if (MAPSTEP(x1, y1, map_x, map_y, DIR8_NORTH)) { t2 = map_get_terrain(x1, y1); if (is_ocean(t1) ^ is_ocean(t2)) { - gui_put_line(pcanvas_store, COLOR_STD_OCEAN, + gui_put_line(pcanvas_store, COLOR_STD_OCEAN, LINE_NORMAL, canvas_x, canvas_y, NORMAL_TILE_WIDTH, 0); } } @@ -504,6 +553,59 @@ } /************************************************************************** + Draw the borders of the given map tile at the given canvas position + in isometric view. +**************************************************************************/ +static void tile_draw_borders_iso(struct canvas_store *pcanvas_store, + int map_x, int map_y, + int canvas_x, int canvas_y, + enum draw_type draw) +{ + struct player *this_owner = map_get_owner(map_x, map_y), *adjc_owner; + int x1, y1; + + /* left side */ + if ((draw & D_M_L) && 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), LINE_BORDER, + canvas_x, + canvas_y + NORMAL_TILE_HEIGHT / 2 - 1, + NORMAL_TILE_WIDTH / 2, + -NORMAL_TILE_HEIGHT / 2); + } + if (this_owner) { + gui_put_line(pcanvas_store, player_color(this_owner), LINE_BORDER, + canvas_x, + canvas_y + NORMAL_TILE_HEIGHT / 2 + 1, + NORMAL_TILE_WIDTH / 2, + -NORMAL_TILE_HEIGHT / 2); + } + } + + /* top side */ + if ((draw & D_M_R) && 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), LINE_BORDER, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y - 1, + NORMAL_TILE_WIDTH / 2, + NORMAL_TILE_HEIGHT / 2); + } + if (this_owner) { + gui_put_line(pcanvas_store, player_color(this_owner), LINE_BORDER, + canvas_x + NORMAL_TILE_WIDTH / 2, + canvas_y + 1, + NORMAL_TILE_WIDTH / 2, + NORMAL_TILE_HEIGHT / 2); + } + } +} + +/************************************************************************** Draw the unique tile for the given map position, in isometric view. The coordinates have not been normalized, and are not guaranteed to be real (we have to draw unreal tiles too). @@ -559,6 +661,10 @@ offset_x, offset_y, offset_y_unit, width, height, height_unit, draw); + if (draw_borders && tile_get_known(map_x, map_y)) { + tile_draw_borders_iso(mapview_canvas.store, map_x, map_y, + canvas_x, canvas_y, draw); + } } else { gui_put_sprite(mapview_canvas.store, canvas_x, canvas_y, sprites.black_tile, offset_x, offset_y, width, height); 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-16 11:14:27.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-16 11:14:27.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/client/packhand.c 2003-06-16 11:14:27.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); @@ -1811,6 +1824,8 @@ game.num_impr_types = packet->num_impr_types; game.num_tech_types = packet->num_tech_types; + game.borders = packet->borders; + governments_alloc(packet->government_count); nations_alloc(packet->nation_count); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/capstr.c freeciv-patched/common/capstr.c --- freeciv-cvs/common/capstr.c 2003-06-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/capstr.c 2003-06-16 11:14:27.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/city.h 2003-06-16 11:14:27.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/game.c 2003-06-16 11:14:27.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/game.h 2003-06-16 11:14:27.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/map.c 2003-06-16 11:14:27.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/map.h 2003-06-16 11:14:27.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/packets.c 2003-06-16 11:14:27.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,12 @@ 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); + } else { + packet->borders = 0; + } + 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-13 11:53:08.000000000 +0100 +++ freeciv-patched/common/packets.h 2003-06-16 11:14:27.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-16 11:14:27.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-16 11:14:27.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-16 11:31:10.000000000 +0100 @@ -0,0 +1,88 @@ +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). + +Border calculation: the ownership of each tile is determined by the Freeciv +server. Each city claims a circle of tiles game.borders in radius (to disable +borders, just set game.borders to zero). Land cities claim only land tiles, +and sea cities (in SMAC mode) only sea tiles, although coastal land cities +do additionally claim any immediately adjacent sea tiles. When cities from +two players are closer than 2*game.borders each claims tiles up to half the +distance between them (in the case of ties, the older city wins). The clients +are sent information on the ownership of tiles, and then draw borders between +any pairs of tiles with different owners (this includes "no owner"). In the +case of fog of war, each player is sent ownership information for tiles that +can be directly seen, and for fogged tiles only if the player owns the tile, +has just lost ownership of the tile, or the tile is directly adjacent to one +that the player owns. This means that you always know your own borders exactly, +but have limited knowledge of other players' borders. + +Borders are drawn as dashed lines between tiles, in the colour of the owning +player. Client support consists of: +- Code to draw borders in iso and non-iso map views. +- Menu options to turn border display on/off. +- Display of player colour in the player dialog. +- Display of tile ownership in the middle-mouse-button map popup. + +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, + and each player's idea of the tile ownership, are. The borders are simply + recalculated upon loading a savefile. Likewise, the tile packets now + include an extra 16-bit unsigned integer, so a new capability ("borders") + is used. Unlike earlier versions of this patch, the borders capability + is not essential. + +Borders should be displayed for both isometric and non-isometric view, in +GTK, GTK2 and Xaw clients. Borders are drawn by common client code +(in client/mapview_common.c) so other clients which use this should have +partial support (i.e. no support for menu options, player dialog, etc.). + +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 in later patches: +* Some border colours are hard to see. +* 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. +* Support for other clients. +* Define whether territory may overlap onto other continents in ruleset + ('Gibraltar' effect). +* 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. diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/citytools.c freeciv-patched/server/citytools.c --- freeciv-cvs/server/citytools.c 2003-06-13 11:53:08.000000000 +0100 +++ freeciv-patched/server/citytools.c 2003-06-16 11:14:27.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-16 11:14:27.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-16 11:14:27.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-16 11:14:27.000000000 +0100 @@ -321,6 +321,19 @@ } /************************************************************************** + Returns TRUE if the given player owns a tile adjacent to that passed. +**************************************************************************/ +static bool player_owns_adjc_tile(struct player *pplayer, int x, int y) +{ + adjc_iterate(x, y, x1, y1) { + if (map_get_owner(x1, y1) == pplayer) { + return TRUE; + } + } adjc_iterate_end; + return FALSE; +} + +/************************************************************************** Send tile information to all the clients in dest which know and see the tile. Also updates player knowledge. If dest is NULL, sends to all clients (game.game_connections) which know and see tile. @@ -336,6 +349,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; @@ -351,6 +365,20 @@ update_tile_knowledge(pplayer,x,y); } send_packet_tile_info(pconn, &info); + } else if (pplayer && map_get_known(x, y, pplayer) + && !map_get_seen(x, y, pplayer)) { + struct player_tile *plrtile = map_get_player_tile(x, y, pplayer); + /* Update the owner of a fogged tile ONLY if we are gaining or losing + * ownership, OR if the tile is adjacent to one we do own */ + info.known = TILE_KNOWN_FOGGED; + info.type = plrtile->terrain; + info.special = plrtile->special; + info.continent = ptile->continent; + if (ptile->owner == pplayer || plrtile->owner == pplayer + || player_owns_adjc_tile(pplayer, x, y)) { + plrtile->owner = ptile->owner; + send_packet_tile_info(pconn, &info); + } } } conn_list_iterate_end; @@ -375,6 +403,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; @@ -383,16 +412,21 @@ info.continent = ptile->continent; } else if (map_get_known(x, y, pplayer)) { + plrtile = map_get_player_tile(x, y, pplayer); if (map_get_seen(x, y, pplayer) != 0) { /* known and seen */ update_tile_knowledge(pplayer,x,y); /* visible; update info */ info.known = TILE_KNOWN; } else { /* known but not seen */ info.known = TILE_KNOWN_FOGGED; + if (ptile->owner == pplayer || plrtile->owner == pplayer + || player_owns_adjc_tile(pplayer, x, y)) { + plrtile->owner = ptile->owner; + } } - plrtile = map_get_player_tile(x, y, pplayer); info.type = plrtile->terrain; info.special = plrtile->special; info.continent = ptile->continent; + info.owner = plrtile->owner ? plrtile->owner->player_no : MAP_TILE_OWNER_NULL; } else { /* unknown (the client needs these sometimes to draw correctly) */ info.known = TILE_UNKNOWN; info.type = ptile->terrain; @@ -909,6 +943,7 @@ plrtile->terrain = T_UNKNOWN; plrtile->special = S_NO_SPECIAL; plrtile->city = NULL; + plrtile->owner = NULL; plrtile->seen = 0; plrtile->pending_seen = 0; @@ -942,6 +977,7 @@ plrtile->terrain = ptile->terrain; plrtile->special = ptile->special; + plrtile->owner = ptile->owner; } /*************************************************************** @@ -1425,6 +1461,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 +1477,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-16 11:14:27.000000000 +0100 @@ -35,6 +35,7 @@ struct player_tile { enum tile_terrain_type terrain; enum tile_special_type special; + struct player *owner; /* Player owning this tile, or NULL. */ unsigned short seen; unsigned short own_seen; /* If you build a city with an unknown square within city radius @@ -90,6 +91,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-13 11:53:08.000000000 +0100 +++ freeciv-patched/server/plrhand.c 2003-06-16 11:14:27.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-16 11:14:27.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-16 11:14:27.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/ruleset.c freeciv-patched/server/ruleset.c --- freeciv-cvs/server/ruleset.c 2003-06-13 11:53:08.000000000 +0100 +++ freeciv-patched/server/ruleset.c 2003-06-16 11:14:27.000000000 +0100 @@ -1768,6 +1768,7 @@ packet.num_unit_types = game.num_unit_types; packet.num_impr_types = game.num_impr_types; packet.num_tech_types = game.num_tech_types; + packet.borders = game.borders; packet.nation_count = game.nation_count; packet.playable_nation_count = game.playable_nation_count; 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-16 11:14:28.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-13 11:53:08.000000000 +0100 +++ freeciv-patched/server/savegame.c 2003-06-16 11:14:28.000000000 +0100 @@ -213,6 +213,32 @@ } /*************************************************************** + Converts a tile owner pointer into a char suitable for + writing to the savefile. +***************************************************************/ +static char owner2char(struct player *owner) +{ + if (!owner) { + return '+'; + } else { + int plrno = owner->player_no; + return (plrno < 10 ? '0' + plrno : + plrno < 36 ? 'a' + plrno - 10 : 'A' + plrno - 36); + } +} + +/*************************************************************** + Obtains a tile owner pointer from the savefile information. +***************************************************************/ +static struct player *char2owner(char ch) +{ + return (ch == '+' ? NULL : + ch >= '0' && ch <= '9' ? get_player(ch - '0') : + ch >= 'a' && ch <= 'z' ? get_player(ch - 'a' + 10) : + get_player(ch - 'A' + 36)); +} + +/*************************************************************** Quote the memory block denoted by data and length so it consists only of " a-f0-9:". The returned string has to be freed by the caller using free(). @@ -1187,6 +1213,13 @@ map_get_player_tile(x, y, plr)->terrain = char2terrain(ch)); + /* Load tile ownership information if we're using borders */ + if (game.borders > 0) { + LOAD_MAP_DATA(secfile_lookup_str(file, "player%d.map_o%03d", plrno, y), + map_get_player_tile(x, y, plr)->owner = + char2owner(ch)); + } + /* get 4-bit segments of 12-bit "special" field. */ LOAD_MAP_DATA(secfile_lookup_str(file, "player%d.map_l%03d", plrno, y), map_get_player_tile(x, y, plr)->special = @@ -1577,6 +1610,13 @@ (x, y, plr)->terrain], "player%d.map_t%03d", plrno); + /* put tile ownership information if we're using borders */ + if (game.borders > 0) { + SAVE_PLAYER_MAP_DATA(file, + owner2char(map_get_player_tile(x, y, plr)->owner), + "player%d.map_o%03d", plrno); + } + /* put 4-bit segments of 12-bit "special flags" field */ SAVE_PLAYER_MAP_DATA(file, bin2ascii_hex(map_get_player_tile(x, y, plr)-> @@ -1869,6 +1909,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 +2183,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 +2305,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-16 11:07:40.000000000 +0100 +++ freeciv-patched/server/stdinhand.c 2003-06-16 11:14:28.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 */