diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/civclient.c freeciv-patched/client/civclient.c --- freeciv-cvs/client/civclient.c 2003-06-07 19:58:20.000000000 +0100 +++ freeciv-patched/client/civclient.c 2003-06-30 12:28:19.000000000 +0100 @@ -397,6 +397,10 @@ handle_ruleset_city((struct packet_ruleset_city *)packet); break; + case PACKET_RULESET_CALENDAR: + handle_ruleset_calendar((struct packet_ruleset_calendar *)packet); + break; + case PACKET_RULESET_GAME: handle_ruleset_game((struct packet_ruleset_game *)packet); break; 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-26 20:13:14.000000000 +0100 +++ freeciv-patched/client/gui-gtk/mapview.c 2003-06-30 12:28:19.000000000 +0100 @@ -213,14 +213,16 @@ { char buffer [512]; int d; + const struct calendar *cal = game_get_current_calendar(); gtk_frame_set_label( GTK_FRAME( main_frame_civ_name ), get_nation_name(game.player_ptr->nation) ); my_snprintf(buffer, sizeof(buffer), - _("Population: %s\nYear: %s\n" + _("Population: %s\nYear: %s\n%s (%d yr/turn)\n" "Gold: %d\nTax: %d Lux: %d Sci: %d"), population_to_text(civ_population(game.player_ptr)), - textyear(game.year), game.player_ptr->economic.gold, + textyear(game.year), cal->name, cal->turn_years, + game.player_ptr->economic.gold, game.player_ptr->economic.tax, game.player_ptr->economic.luxury, game.player_ptr->economic.science); 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-26 20:13:14.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/mapview.c 2003-06-30 12:28:19.000000000 +0100 @@ -214,16 +214,18 @@ { char buffer [512]; int d; + const struct calendar *cal = game_get_current_calendar(); int sol, flake; gtk_frame_set_label(GTK_FRAME(main_frame_civ_name), get_nation_name(game.player_ptr->nation)); my_snprintf(buffer, sizeof(buffer), - _("Population: %s\nYear: %s\n" + _("Population: %s\nYear: %s\n%s (%d yr/turn)\n" "Gold: %d\nTax: %d Lux: %d Sci: %d"), population_to_text(civ_population(game.player_ptr)), - textyear(game.year), game.player_ptr->economic.gold, + textyear(game.year), cal->name, cal->turn_years, + game.player_ptr->economic.gold, game.player_ptr->economic.tax, game.player_ptr->economic.luxury, game.player_ptr->economic.science); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/packhand.c freeciv-patched/client/packhand.c --- freeciv-cvs/client/packhand.c 2003-06-30 12:18:28.000000000 +0100 +++ freeciv-patched/client/packhand.c 2003-06-30 12:31:26.000000000 +0100 @@ -1127,6 +1127,7 @@ game.end_year=pinfo->end_year; game.year=pinfo->year; game.turn=pinfo->turn; + game.spaceage_year = pinfo->spaceage_year; game.min_players=pinfo->min_players; game.max_players=pinfo->max_players; game.nplayers=pinfo->nplayers; @@ -1822,6 +1823,10 @@ game.government_when_anarchy = packet->government_when_anarchy; game.default_government = packet->default_government; + game.num_calendars = packet->num_calendars; + if (game.num_calendars == 0) { + setup_default_calendars(); + } game.num_unit_types = packet->num_unit_types; game.num_impr_types = packet->num_impr_types; game.num_tech_types = packet->num_tech_types; @@ -2363,6 +2368,28 @@ /************************************************************************** ... **************************************************************************/ +void handle_ruleset_calendar(struct packet_ruleset_calendar *p) +{ + struct calendar *c; + + if (p->id < 0 || p->id >= game.num_calendars || p->id >= C_LAST) { + freelog(LOG_ERROR, + "Received bad calendar %d in handle_ruleset_calendar()", p->id); + return; + } + c = &game.calendars[p->id]; + + c->id = p->id; + sz_strlcpy(c->name, p->name); + c->first_year = p->first_year; + c->turn_years = p->turn_years; + c->req_tech = p->req_tech; + c->early_tech = p->early_tech; +} + +/************************************************************************** +... +**************************************************************************/ void handle_incite_cost(struct packet_generic_values *packet) { struct city *pcity=find_city_by_id(packet->id); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/packhand.h freeciv-patched/client/packhand.h --- freeciv-cvs/client/packhand.h 2003-06-27 15:51:10.000000000 +0100 +++ freeciv-patched/client/packhand.h 2003-06-30 12:28:20.000000000 +0100 @@ -57,6 +57,7 @@ void handle_ruleset_nation(struct packet_ruleset_nation *p); void handle_ruleset_city(struct packet_ruleset_city *packet); void handle_ruleset_game(struct packet_ruleset_game *packet); +void handle_ruleset_calendar(struct packet_ruleset_calendar *packet); void handle_diplomat_action(struct packet_diplomat_action *packet); void handle_sabotage_list(struct packet_sabotage_list *packet); void handle_player_attribute_chunk(struct packet_attribute_chunk *chunk); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/capstr.c freeciv-patched/common/capstr.c --- freeciv-cvs/common/capstr.c 2003-06-30 12:18:26.000000000 +0100 +++ freeciv-patched/common/capstr.c 2003-06-30 12:28:52.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 +root_tech" + "+diplomacy2 +citizens_style +root_tech calendar" /* "+1.14.0" is protocol for 1.14.0 release. * @@ -129,6 +129,8 @@ * multi style citizens icons. * * "root_tech" restricts who can acquire technology + * + * "calendar" adds support for customised game calendars. */ void init_our_capability(void) diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/game.c freeciv-patched/common/game.c --- freeciv-cvs/common/game.c 2003-06-30 12:18:29.000000000 +0100 +++ freeciv-patched/common/game.c 2003-06-30 12:28:20.000000000 +0100 @@ -660,6 +660,7 @@ game.end_year = GAME_DEFAULT_END_YEAR; game.year = GAME_START_YEAR; game.turn = 0; + game.spaceage_year = GAME_MAX_END_YEAR + 1; game.min_players = GAME_DEFAULT_MIN_PLAYERS; game.max_players = GAME_DEFAULT_MAX_PLAYERS; game.aifill = GAME_DEFAULT_AIFILL; @@ -810,55 +811,63 @@ } /*************************************************************** - Returns the next year in the game. + Returns the relevant calendar for the given year ***************************************************************/ -int game_next_year(int year) +const struct calendar *game_get_calendar(int year) { - int spaceshipparts, i; - Impr_Type_id parts[] = { B_SCOMP, B_SMODULE, B_SSTRUCTURAL, B_LAST }; - - if (year == 1) /* hacked it to get rid of year 0 */ - year = 0; + const static struct calendar spaceage_cal = { + 0, N_("Space Age"), 0, 1, A_NONE, A_NONE + }; + int calind; + + /* If a spaceship has been launched, then use the hard-coded 1 year/turn + * "space age" calendar (for Civ compatibility). Otherwise, we use a + * ruleset-defined calendar */ + if (game.spacerace && year >= game.spaceage_year) { + return &spaceage_cal; + } - /* !McFred: - - want year += 1 for spaceship. - */ - - /* test game with 7 normal AI's, gen 4 map, foodbox 10, foodbase 0: - * Gunpowder about 0 AD - * Railroad about 500 AD - * Electricity about 1000 AD - * Refining about 1500 AD (212 active units) - * about 1750 AD - * about 1900 AD - */ - - spaceshipparts= 0; - if (game.spacerace) { - for(i=0; parts[i] < B_LAST; i++) { - int t = improvement_types[parts[i]].tech_req; - if (tech_exists(t) && game.global_advances[t] != 0) - spaceshipparts++; + for (calind = 1; calind < game.num_calendars; ++calind) { + /* Someone must have the req_tech to reach a calendar. */ + if (tech_exists(game.calendars[calind].req_tech) + && !game.global_advances[game.calendars[calind].req_tech]) { + break; + } + /* Either the first_year must be reached, or someone must have + * the early_tech, to reach a calendar. */ + if (year < game.calendars[calind].first_year + && (game.calendars[calind].early_tech == A_NONE + || !game.global_advances[game.calendars[calind].early_tech])) { + break; } } + calind--; - if( year >= 1900 || ( spaceshipparts>=3 && year>0 ) ) - year += 1; - else if( year >= 1750 || spaceshipparts>=2 ) - year += 2; - else if( year >= 1500 || spaceshipparts>=1 ) - year += 5; - else if( year >= 1000 ) - year += 10; - else if( year >= 0 ) - year += 20; - else if( year >= -1000 ) /* used this line for tuning (was -1250) */ - year += 25; - else - year += 50; + return &game.calendars[calind]; +} - if (year == 0) - year = 1; +/*************************************************************** + Returns the relevant calendar for the current game year +***************************************************************/ +const struct calendar *game_get_current_calendar(void) +{ + return game_get_calendar(game.year); +} + +/*************************************************************** + Returns the next year in the game. +***************************************************************/ +int game_next_year(int year) +{ + int oldyear = year; + const struct calendar *cal = game_get_calendar(year); + + year += cal->turn_years; + + /* There is no such thing as "0AD", so skip a year if we passed it */ + if (oldyear < 0 && year >= 0) { + year++; + } return year; } @@ -1023,3 +1032,42 @@ #undef name_strlcpy } + +/*************************************************************** + Creates a set of calendars that reproduce the behaviour of + original Freeciv. These are used if the calendars cannot be + read from the rulesets (i.e. server and client do not share + the "calendars" capability). +***************************************************************/ +void setup_default_calendars(void) +{ + int i; + + assert(C_LAST >= 7); + game.num_calendars = 7; + for (i = 0; i < game.num_calendars; ++i) { + game.calendars[i].req_tech = A_NONE; + game.calendars[i].early_tech = A_NONE; + } + sz_strlcpy(game.calendars[0].name, N_("Prehistory")); + game.calendars[0].first_year = -4001; + game.calendars[0].turn_years = 50; + sz_strlcpy(game.calendars[1].name, N_("Ancient Age")); + game.calendars[1].first_year = -1001; + game.calendars[1].turn_years = 25; + sz_strlcpy(game.calendars[2].name, _("Classical Age")); + game.calendars[2].first_year = -1; + game.calendars[2].turn_years = 20; + sz_strlcpy(game.calendars[3].name, N_("Dark Ages")); + game.calendars[3].first_year = 1000; + game.calendars[3].turn_years = 10; + sz_strlcpy(game.calendars[4].name, N_("Middle Ages")); + game.calendars[4].first_year = 1500; + game.calendars[4].turn_years = 5; + sz_strlcpy(game.calendars[5].name, N_("Renaissance")); + game.calendars[5].first_year = 1750; + game.calendars[5].turn_years = 2; + sz_strlcpy(game.calendars[6].name, N_("Modern Age")); + game.calendars[6].first_year = 1900; + game.calendars[6].turn_years = 1; +} diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/game.h freeciv-patched/common/game.h --- freeciv-cvs/common/game.h 2003-06-30 12:18:29.000000000 +0100 +++ freeciv-patched/common/game.h 2003-06-30 12:28:20.000000000 +0100 @@ -28,6 +28,8 @@ #define MAX_LEN_DEMOGRAPHY 16 #define MAX_LEN_ALLOW_CONNECT 16 #define MAX_ID_LEN 33 +#define MAX_CALENDAR 20 +#define C_LAST MAX_CALENDAR enum server_states { PRE_GAME_STATE, @@ -48,6 +50,15 @@ struct unit; struct city; +struct calendar { + int id; + char name[MAX_LEN_NAME]; + int first_year; + int turn_years; + int req_tech; + int early_tech; +}; + #define OVERFLIGHT_NOTHING 1 #define OVERFLIGHT_FRIGHTEN 2 @@ -79,6 +90,7 @@ int end_year; int year; int turn; + int spaceage_year; /* The year in which the first space craft is launched */ int researchcost; /* Multiplier on cost of new research */ int diplcost, freecost, conquercost; int diplchance; @@ -155,6 +167,7 @@ int nation_count; int playable_nation_count; int styles_count; + int num_calendars; int watchtower_extra_vision; int watchtower_vision; @@ -203,6 +216,8 @@ char demography[MAX_LEN_DEMOGRAPHY]; char allow_connect[MAX_LEN_ALLOW_CONNECT]; + struct calendar calendars[C_LAST]; + /* used by the map editor to control game_save; could be used by the server too */ struct { bool save_random; @@ -233,6 +248,9 @@ int game_next_year(int); void game_advance_year(void); +const struct calendar *game_get_calendar(int year); +const struct calendar *game_get_current_calendar(void); +void setup_default_calendars(void); int civ_population(struct player *pplayer); struct city *game_find_city_by_name(const char *name); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets.c freeciv-patched/common/packets.c --- freeciv-cvs/common/packets.c 2003-06-30 12:18:26.000000000 +0100 +++ freeciv-patched/common/packets.c 2003-06-30 12:28:20.000000000 +0100 @@ -422,6 +422,8 @@ return receive_packet_ruleset_city(pc); case PACKET_RULESET_GAME: return receive_packet_ruleset_game(pc); + case PACKET_RULESET_CALENDAR: + return receive_packet_ruleset_calendar(pc); case PACKET_SPACESHIP_INFO: return receive_packet_spaceship_info(pc); @@ -1035,6 +1037,9 @@ dio_put_uint32(&dout, pinfo->timeout); dio_put_uint32(&dout, pinfo->end_year); dio_put_uint32(&dout, pinfo->year); + if (has_capability("calendar", pc->capability)) { + dio_put_sint16(&dout, pinfo->spaceage_year); + } dio_put_uint8(&dout, pinfo->min_players); dio_put_uint8(&dout, pinfo->max_players); dio_put_uint8(&dout, pinfo->nplayers); @@ -1083,6 +1088,11 @@ dio_get_uint32(&din, &pinfo->timeout); dio_get_uint32(&din, &pinfo->end_year); dio_get_uint32(&din, &pinfo->year); + if (has_capability("calendar", pc->capability)) { + dio_get_sint16(&din, &pinfo->spaceage_year); + } else { + pinfo->spaceage_year = GAME_MAX_END_YEAR + 1; + } dio_get_uint8(&din, &pinfo->min_players); dio_get_uint8(&din, &pinfo->max_players); dio_get_uint8(&din, &pinfo->nplayers); @@ -1862,6 +1872,10 @@ dio_put_uint8(&dout, packet->num_unit_types); dio_put_uint8(&dout, packet->num_impr_types); dio_put_uint8(&dout, packet->num_tech_types); + + if (has_capability("calendar", pc->capability)) { + dio_put_uint8(&dout, packet->num_calendars); + } dio_put_uint8(&dout, packet->nation_count); dio_put_uint8(&dout, packet->playable_nation_count); @@ -1909,6 +1923,12 @@ dio_get_uint8(&din, &packet->num_impr_types); dio_get_uint8(&din, &packet->num_tech_types); + if (has_capability("calendar", pc->capability)) { + dio_get_uint8(&din, &packet->num_calendars); + } else { + packet->num_calendars = 0; + } + dio_get_uint8(&din, &packet->nation_count); dio_get_uint8(&din, &packet->playable_nation_count); dio_get_uint8(&din, &packet->style_count); @@ -3149,6 +3169,42 @@ RECEIVE_PACKET_END(packet); } +/************************************************************************* +... +**************************************************************************/ +int send_packet_ruleset_calendar(struct connection *pc, + const struct packet_ruleset_calendar *packet) +{ + SEND_PACKET_START(PACKET_RULESET_CALENDAR); + + dio_put_uint8(&dout, packet->id); + dio_put_string(&dout, packet->name); + dio_put_sint16(&dout, packet->first_year); + dio_put_uint8(&dout, packet->turn_years); + dio_put_uint8(&dout, packet->req_tech); + dio_put_uint8(&dout, packet->early_tech); + + SEND_PACKET_END; +} + +/************************************************************************* +... +**************************************************************************/ +struct packet_ruleset_calendar * +receive_packet_ruleset_calendar(struct connection *pc) +{ + RECEIVE_PACKET_START(packet_ruleset_calendar, packet); + + dio_get_uint8(&din, &packet->id); + dio_get_string(&din, packet->name, sizeof(packet->name)); + dio_get_sint16(&din, &packet->first_year); + dio_get_uint8(&din, &packet->turn_years); + dio_get_uint8(&din, &packet->req_tech); + dio_get_uint8(&din, &packet->early_tech); + + RECEIVE_PACKET_END(packet); +} + /************************************************************************** ... **************************************************************************/ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets.h freeciv-patched/common/packets.h --- freeciv-cvs/common/packets.h 2003-06-30 12:18:26.000000000 +0100 +++ freeciv-patched/common/packets.h 2003-06-30 12:28:20.000000000 +0100 @@ -128,6 +128,7 @@ PACKET_FREEZE_HINT, PACKET_THAW_HINT, PACKET_PING_INFO, + PACKET_RULESET_CALENDAR, PACKET_LAST /* leave this last */ }; @@ -583,6 +584,7 @@ int playable_nation_count; int style_count; char team_name[MAX_NUM_TEAMS][MAX_LEN_NAME]; + int num_calendars; }; /********************************************************* @@ -829,6 +831,15 @@ int global_init_techs[MAX_NUM_TECH_LIST]; }; +struct packet_ruleset_calendar { + int id; + char name[MAX_LEN_NAME]; + int first_year; + int turn_years; + int req_tech; + int early_tech; +}; + /********************************************************* ... *********************************************************/ @@ -842,6 +853,7 @@ int end_year; int year; int turn; + int spaceage_year; int min_players, max_players, nplayers; int player_idx; int globalwarming; @@ -1096,6 +1108,10 @@ const struct packet_ruleset_game *packet); struct packet_ruleset_game * receive_packet_ruleset_game(struct connection *pc); +int send_packet_ruleset_calendar(struct connection *pc, + const struct packet_ruleset_calendar *packet); +struct packet_ruleset_calendar * +receive_packet_ruleset_calendar(struct connection *pc); int send_packet_generic_values(struct connection *pc, enum packet_type type, const struct packet_generic_values *req); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets_lsend.c freeciv-patched/common/packets_lsend.c --- freeciv-cvs/common/packets_lsend.c 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/packets_lsend.c 2003-06-30 12:28:20.000000000 +0100 @@ -311,6 +311,14 @@ conn_list_iterate_end; } +void lsend_packet_ruleset_calendar(struct conn_list *dest, + const struct packet_ruleset_calendar *packet) +{ + conn_list_iterate(*dest, pconn) + send_packet_ruleset_calendar(pconn, packet); + conn_list_iterate_end; +} + void lsend_packet_generic_values(struct conn_list *dest, enum packet_type type, const struct packet_generic_values *req) { diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets_lsend.h freeciv-patched/common/packets_lsend.h --- freeciv-cvs/common/packets_lsend.h 2003-06-07 19:58:26.000000000 +0100 +++ freeciv-patched/common/packets_lsend.h 2003-06-30 12:28:20.000000000 +0100 @@ -90,6 +90,8 @@ const struct packet_ruleset_city *packet); void lsend_packet_ruleset_game(struct conn_list *dest, const struct packet_ruleset_game *packet); +void lsend_packet_ruleset_calendar(struct conn_list *dest, + const struct packet_ruleset_calendar *packet); void lsend_packet_generic_values(struct conn_list *dest, enum packet_type type, const struct packet_generic_values *req); void lsend_packet_spaceship_info(struct conn_list *dest, diff -Nur -Xfreecivdiff.ignore freeciv-cvs/data/civ1/game.ruleset freeciv-patched/data/civ1/game.ruleset --- freeciv-cvs/data/civ1/game.ruleset 2002-08-26 14:18:04.000000000 +0100 +++ freeciv-patched/data/civ1/game.ruleset 2003-06-30 12:28:20.000000000 +0100 @@ -17,6 +17,57 @@ [options] global_init_techs="" +; Below: One section for each calendar, in order (see default ruleset) + +[calendar_prehistory] +name = _("Prehistory") +first_year = -4001 +turn_years = 50 +req_tech = "None" +early_tech = "None" + +[calendar_ancient_age] +name = _("Ancient Age") +first_year = -1001 +turn_years = 25 +req_tech = "None" +early_tech = "None" + +[calendar_classical_age] +name = _("Classical Age") +first_year = -1 +turn_years = 20 +req_tech = "None" +early_tech = "None" + +[calendar_dark_ages] +name = _("Dark Ages") +first_year = 1000 +turn_years = 10 +req_tech = "None" +early_tech = "None" + +[calendar_middle_ages] +name = _("Middle Ages") +first_year = 1500 +turn_years = 5 +req_tech = "None" +early_tech = "None" + +[calendar_renaissance] +name = _("Renaissance") +first_year = 1750 +turn_years = 2 +req_tech = "None" +early_tech = "None" + +[calendar_modern] +name = _("Modern Age") +first_year = 1900 +turn_years = 1 +req_tech = "None" +early_tech = "None" + [civstyle] min_city_center_food = 0 min_city_center_shield = 0 diff -Nur -Xfreecivdiff.ignore freeciv-cvs/data/civ2/game.ruleset freeciv-patched/data/civ2/game.ruleset --- freeciv-cvs/data/civ2/game.ruleset 2002-08-26 14:18:04.000000000 +0100 +++ freeciv-patched/data/civ2/game.ruleset 2003-06-30 12:28:20.000000000 +0100 @@ -17,6 +17,57 @@ [options] global_init_techs="" +; Below: One section for each calendar, in order (see default ruleset) + +[calendar_prehistory] +name = _("Prehistory") +first_year = -4001 +turn_years = 50 +req_tech = "None" +early_tech = "None" + +[calendar_ancient_age] +name = _("Ancient Age") +first_year = -1001 +turn_years = 25 +req_tech = "None" +early_tech = "None" + +[calendar_classical_age] +name = _("Classical Age") +first_year = -1 +turn_years = 20 +req_tech = "None" +early_tech = "None" + +[calendar_dark_ages] +name = _("Dark Ages") +first_year = 1000 +turn_years = 10 +req_tech = "None" +early_tech = "None" + +[calendar_middle_ages] +name = _("Middle Ages") +first_year = 1500 +turn_years = 5 +req_tech = "None" +early_tech = "None" + +[calendar_renaissance] +name = _("Renaissance") +first_year = 1750 +turn_years = 2 +req_tech = "None" +early_tech = "None" + +[calendar_modern] +name = _("Modern Age") +first_year = 1900 +turn_years = 1 +req_tech = "None" +early_tech = "None" + [civstyle] min_city_center_food = 1 min_city_center_shield = 1 diff -Nur -Xfreecivdiff.ignore freeciv-cvs/data/default/game.ruleset freeciv-patched/data/default/game.ruleset --- freeciv-cvs/data/default/game.ruleset 2002-08-26 14:18:04.000000000 +0100 +++ freeciv-patched/data/default/game.ruleset 2003-06-30 12:28:20.000000000 +0100 @@ -17,6 +17,105 @@ [options] global_init_techs="" +; /* <-- avoid gettext warnings +; +; Below: One section for each calendar. +; +; The actual tag used (the * in [calendar_*]) does not matter, except +; it must be unique within this file, and may be used in debug output +; when reading this file. +; +; The order is important; earlier calendars must come first. You +; cannot use more than 20 calendars in total. Note that there is no +; year zero in Freeciv, just as in the real world - the year after +; 1BC is 1AD. +; +; Notes: +; +; name = name as seen by user (if it's ever seen; usually not) +; these can be names like "Ancient", "Medieval", etc., +; or whatever is appropriate, but more specific names +; like "Iron Age" may be a bad idea, as it may seem a +; bit strange to users that they're in the Iron Age when +; nobody has Iron Working yet.... +; first_year = year when this calendar starts +; turn_years = number of years the game advances each turn +; req_tech = technology which some player must reach before we can +; start this calendar, even if we've already passed the +; appropriate year, or "None" if there is no such tech +; early_tech = technology at which we jump to this calendar, even if +; we haven't yet reached the appropriate year, or "None" +; if there is no such tech +; +; Normally you won't want to use both req_tech and early_tech. However, +; you could set first_year to 9999 for every calendar and use the two of +; them together, so that the calendar advances when both are researched. +; +; Note that special rules apply for the Space Race. Once any player +; launches a space craft, the game will switch to an internal "Space Age" +; (1 year/turn) calendar, regardless of those defined in this ruleset. +; This is for partial compatibility with older Civ games; however, merely +; discovering the technology required to build space components now has +; no effect on the game calendar. +; +; */ <-- avoid gettext warnings + +[calendar_prehistory] +name = _("Prehistory") +first_year = -4001 +turn_years = 50 +req_tech = "None" +early_tech = "None" +; 4001BC - 1001BC = 60 turns + +[calendar_ancient_age] +name = _("Ancient Age") +first_year = -1001 +turn_years = 25 +req_tech = "None" +early_tech = "None" +; 1001BC - 1BC = 40 turns, 100 cumulative + +[calendar_classical_age] +name = _("Classical Age") +first_year = -1 +turn_years = 20 +req_tech = "None" +early_tech = "None" +; 1BC - 1000AD = 50 turns, 150 cumulative + +[calendar_dark_ages] +name = _("Dark Ages") +first_year = 1000 +turn_years = 10 +req_tech = "None" +early_tech = "None" +; 1000 AD - 1500 AD = 50 turns, 200 cumulative + +[calendar_middle_ages] +name = _("Middle Ages") +first_year = 1500 +turn_years = 5 +req_tech = "None" +early_tech = "None" +; 1500 AD - 1750 AD = 50 turns, 250 cumulative + +[calendar_renaissance] +name = _("Renaissance") +first_year = 1750 +turn_years = 2 +req_tech = "None" +early_tech = "None" +; 1750 AD - 1900 AD = 75 turns, 325 cumulative + +[calendar_modern] +name = _("Modern Age") +first_year = 1900 +turn_years = 1 +req_tech = "None" +early_tech = "None" +; 1900 AD - 2000 AD = 100 turns, 425 cumulative + [civstyle] min_city_center_food = 1 min_city_center_shield = 1 diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/gamehand.c freeciv-patched/server/gamehand.c --- freeciv-cvs/server/gamehand.c 2003-06-30 12:18:29.000000000 +0100 +++ freeciv-patched/server/gamehand.c 2003-06-30 12:28:20.000000000 +0100 @@ -221,6 +221,7 @@ ginfo.end_year = game.end_year; ginfo.year = game.year; ginfo.turn = game.turn; + ginfo.spaceage_year = game.spaceage_year; ginfo.min_players = game.min_players; ginfo.max_players = game.max_players; ginfo.nplayers = game.nplayers; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/ruleset.c freeciv-patched/server/ruleset.c --- freeciv-cvs/server/ruleset.c 2003-06-30 12:18:28.000000000 +0100 +++ freeciv-patched/server/ruleset.c 2003-06-30 12:28:20.000000000 +0100 @@ -79,6 +79,7 @@ static void load_terrain_names(struct section_file *file); static void load_citystyle_names(struct section_file *file); static void load_nation_names(struct section_file *file); +static void load_calendar_names(struct section_file *file); static struct city_name* load_city_name_list(struct section_file *file, const char *secfile_str1, const char *secfile_str2); @@ -90,8 +91,7 @@ static void load_ruleset_terrain(struct section_file *file); static void load_ruleset_cities(struct section_file *file); static void load_ruleset_nations(struct section_file *file); - -static void load_ruleset_game(void); +static void load_ruleset_game(struct section_file *file); static void send_ruleset_techs(struct conn_list *dest); static void send_ruleset_units(struct conn_list *dest); @@ -101,6 +101,7 @@ static void send_ruleset_nations(struct conn_list *dest); static void send_ruleset_cities(struct conn_list *dest); static void send_ruleset_game(struct conn_list *dest); +static void send_ruleset_calendars(struct conn_list *dest); /************************************************************************** datafilename() wrapper: tries to match in two ways. @@ -1811,6 +1812,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.num_calendars = game.num_calendars; packet.nation_count = game.nation_count; packet.playable_nation_count = game.playable_nation_count; @@ -1908,6 +1910,40 @@ } /************************************************************************** + ... +**************************************************************************/ +static void load_calendar_names(struct section_file *file) +{ + char **sec; + int num_calendars; /* number of calendars in game.ruleset */ + int i; + const char *filename = secfile_filename(file); + + section_file_lookup(file, "datafile.description"); /* unused */ + + /* The names: */ + sec = secfile_get_secnames_prefix(file, "calendar_", &num_calendars); + freelog(LOG_VERBOSE, "%d calendars (including possibly unused)", + num_calendars); + if (num_calendars == 0) { + freelog(LOG_NORMAL, "No calendars; using default (%s)", filename); + } + if (num_calendars > C_LAST) { + freelog(LOG_FATAL, "Too many calendars (%d, max %d) (%s)", + num_calendars, C_LAST, filename); + exit(EXIT_FAILURE); + } + + game.num_calendars = num_calendars; + for (i = 0; i < num_calendars; ++i) { + char *name = secfile_lookup_str(file, "%s.name", sec[i]); + game.calendars[i].id = i; + name_strlcpy(game.calendars[i].name, name); + } + free(sec); +} + +/************************************************************************** This function loads a city name list from a section file. The file and two section names (which will be concatenated) are passed in. The malloc'ed city name list (which is all filled out) will be returned. @@ -2364,33 +2400,62 @@ section_file_free(file); } +static void load_calendars(struct section_file *file) +{ + char **sec; + const char *filename = secfile_filename(file); + int i, nval; + + sec = secfile_get_secnames_prefix(file, "calendar_", &nval); + for (i = 0; i < game.num_calendars; ++i ) { + game.calendars[i].first_year = + secfile_lookup_int(file, "%s.first_year", sec[i]); + game.calendars[i].turn_years = + secfile_lookup_int(file, "%s.turn_years", sec[i]); + game.calendars[i].req_tech = + lookup_tech(file, sec[i], "req_tech", 0, filename, + game.calendars[i].name); + if (game.calendars[i].req_tech == A_LAST) { + game.calendars[i].req_tech = A_NONE; + } + game.calendars[i].early_tech = + lookup_tech(file, sec[i], "early_tech", 0, filename, + game.calendars[i].name); + if (game.calendars[i].early_tech == A_LAST) { + game.calendars[i].early_tech = A_NONE; + } + } + free(sec); + + if (game.num_calendars == 0) { + setup_default_calendars(); + } +} + /************************************************************************** Load ruleset file **************************************************************************/ -static void load_ruleset_game() +static void load_ruleset_game(struct section_file *file) { - struct section_file file; char *datafile_options; char *sval; - const char *filename; + const char *filename = secfile_filename(file); - openload_ruleset_file(&file, "game"); - filename = secfile_filename(&file); - datafile_options = check_ruleset_capabilities(&file, "+1.11.1", filename); - (void) section_file_lookup(&file, "datafile.description"); /* unused */ + datafile_options = check_ruleset_capabilities(file, "+1.11.1", filename); + (void) section_file_lookup(file, "datafile.description"); /* unused */ game.rgame.min_city_center_food = - secfile_lookup_int(&file, "civstyle.min_city_center_food"); + secfile_lookup_int(file, "civstyle.min_city_center_food"); game.rgame.min_city_center_shield = - secfile_lookup_int(&file, "civstyle.min_city_center_shield"); + secfile_lookup_int(file, "civstyle.min_city_center_shield"); game.rgame.min_city_center_trade = - secfile_lookup_int(&file, "civstyle.min_city_center_trade"); + secfile_lookup_int(file, "civstyle.min_city_center_trade"); /* if the server variable citymindist is set (!= 0) the ruleset setting is overwritten by citymindist */ if (game.citymindist == 0) { game.rgame.min_dist_bw_cities = - secfile_lookup_int(&file, "civstyle.min_dist_bw_cities"); + secfile_lookup_int(file, "civstyle.min_dist_bw_cities"); if (game.rgame.min_dist_bw_cities < 1) { freelog(LOG_ERROR, "Bad value %i for min_dist_bw_cities. Using 2.", game.rgame.min_dist_bw_cities); @@ -2401,9 +2466,9 @@ } game.rgame.init_vis_radius_sq = - secfile_lookup_int(&file, "civstyle.init_vis_radius_sq"); + secfile_lookup_int(file, "civstyle.init_vis_radius_sq"); - sval = secfile_lookup_str(&file, "civstyle.hut_overflight" ); + sval = secfile_lookup_str(file, "civstyle.hut_overflight" ); if (mystrcasecmp(sval, "Nothing") == 0) { game.rgame.hut_overflight = OVERFLIGHT_NOTHING; } else if (mystrcasecmp(sval, "Frighten") == 0) { @@ -2415,9 +2480,9 @@ } game.rgame.pillage_select = - secfile_lookup_bool(&file, "civstyle.pillage_select"); + secfile_lookup_bool(file, "civstyle.pillage_select"); - sval = secfile_lookup_str(&file, "civstyle.nuke_contamination" ); + sval = secfile_lookup_str(file, "civstyle.nuke_contamination" ); if (mystrcasecmp(sval, "Pollution") == 0) { game.rgame.nuke_contamination = CONTAMINATION_POLLUTION; } else if (mystrcasecmp(sval, "Fallout") == 0) { @@ -2429,14 +2494,14 @@ } game.rgame.granary_food_ini = - secfile_lookup_int(&file, "civstyle.granary_food_ini"); + secfile_lookup_int(file, "civstyle.granary_food_ini"); if (game.rgame.granary_food_ini < 0) { freelog(LOG_ERROR, "Bad value %i for granary_food_ini. Using 1.", game.rgame.granary_food_ini); game.rgame.granary_food_ini = 1; } game.rgame.granary_food_inc = - secfile_lookup_int(&file, "civstyle.granary_food_inc"); + secfile_lookup_int(file, "civstyle.granary_food_inc"); if (game.rgame.granary_food_inc < 0 || /* can't have a granary size of zero */ (game.rgame.granary_food_ini == 0 && @@ -2447,7 +2512,7 @@ } game.rgame.tech_cost_style = - secfile_lookup_int(&file, "civstyle.tech_cost_style"); + secfile_lookup_int(file, "civstyle.tech_cost_style"); if (game.rgame.tech_cost_style < 0 || game.rgame.tech_cost_style > 2) { freelog(LOG_ERROR, "Bad value %i for tech_cost_style. Using 0.", game.rgame.tech_cost_style); @@ -2455,7 +2520,7 @@ } game.rgame.tech_leakage = - secfile_lookup_int(&file, "civstyle.tech_leakage"); + secfile_lookup_int(file, "civstyle.tech_leakage"); if (game.rgame.tech_leakage < 0 || game.rgame.tech_leakage > 3) { freelog(LOG_ERROR, "Bad value %i for tech_leakage. Using 0.", game.rgame.tech_leakage); @@ -2472,11 +2537,13 @@ /* * Load global initial techs */ - lookup_tech_list(&file, "options", "global_init_techs", + lookup_tech_list(file, "options", "global_init_techs", game.rgame.global_init_techs, filename); - section_file_check_unused(&file, filename); - section_file_free(&file); + load_calendars(file); + + section_file_check_unused(file, filename); + section_file_free(file); } /************************************************************************** @@ -2837,13 +2904,34 @@ lsend_packet_ruleset_game(dest, &misc_p); } + /************************************************************************** + Send the calendar information from the game ruleset (all calendars) + to the specified connections. +**************************************************************************/ +static void send_ruleset_calendars(struct conn_list *dest) +{ + struct packet_ruleset_calendar packet; + struct calendar *c; + + for(c = game.calendars; c < game.calendars + game.num_calendars; ++c) { + packet.id = c->id; + sz_strlcpy(packet.name, c->name); + packet.first_year = c->first_year; + packet.turn_years = c->turn_years; + packet.req_tech = c->req_tech; + packet.early_tech = c->early_tech; + + lsend_packet_ruleset_calendar(dest, &packet); + } +} + /************************************************************************** ... **************************************************************************/ void load_rulesets(void) { struct section_file techfile, unitfile, buildfile, govfile, terrfile; - struct section_file cityfile, nationfile; + struct section_file cityfile, nationfile, gamefile; freelog(LOG_NORMAL, _("Loading rulesets")); @@ -2868,6 +2956,9 @@ openload_ruleset_file(&nationfile, "nations"); load_nation_names(&nationfile); + openload_ruleset_file(&gamefile, "game"); + load_calendar_names(&gamefile); + load_ruleset_techs(&techfile); load_ruleset_cities(&cityfile); load_ruleset_governments(&govfile); @@ -2875,7 +2966,7 @@ load_ruleset_terrain(&terrfile); /* terrain must precede nations */ load_ruleset_buildings(&buildfile); load_ruleset_nations(&nationfile); - load_ruleset_game(); + load_ruleset_game(&gamefile); translate_data_names(); } @@ -2895,6 +2986,7 @@ send_ruleset_buildings(dest); send_ruleset_nations(dest); send_ruleset_cities(dest); + send_ruleset_calendars(dest); conn_list_do_unbuffer(dest); } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/savegame.c freeciv-patched/server/savegame.c --- freeciv-cvs/server/savegame.c 2003-06-30 12:18:29.000000000 +0100 +++ freeciv-patched/server/savegame.c 2003-06-30 12:28:20.000000000 +0100 @@ -1828,6 +1828,9 @@ game.researchcost = secfile_lookup_int(file, "game.techlevel"); game.year = secfile_lookup_int(file, "game.year"); + game.spaceage_year = secfile_lookup_int_default(file, + GAME_MAX_END_YEAR + 1, + "game.spaceage_year"); if (has_capability("turn", savefile_options)) { game.turn = secfile_lookup_int(file, "game.turn"); @@ -2221,6 +2224,7 @@ secfile_insert_int(file, game.end_year, "game.end_year"); secfile_insert_int(file, game.year, "game.year"); secfile_insert_int(file, game.turn, "game.turn"); + secfile_insert_int(file, game.spaceage_year, "game.spaceage_year"); secfile_insert_int(file, game.researchcost, "game.researchcost"); secfile_insert_int(file, game.min_players, "game.min_players"); secfile_insert_int(file, game.max_players, "game.max_players"); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/spacerace.c freeciv-patched/server/spacerace.c --- freeciv-cvs/server/spacerace.c 2003-06-07 19:58:49.000000000 +0100 +++ freeciv-patched/server/spacerace.c 2003-06-30 12:28:20.000000000 +0100 @@ -26,6 +26,7 @@ #include "shared.h" #include "spaceship.h" +#include "gamehand.h" #include "gamelog.h" #include "plrhand.h" #include "srv_main.h" @@ -186,6 +187,9 @@ textyear(arrival)); send_spaceship_info(pplayer, NULL); + + game.spaceage_year = game.year; + send_game_info(NULL); } /************************************************************************** diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/srv_main.c freeciv-patched/server/srv_main.c --- freeciv-cvs/server/srv_main.c 2003-06-30 12:18:26.000000000 +0100 +++ freeciv-patched/server/srv_main.c 2003-06-30 12:28:20.000000000 +0100 @@ -1617,6 +1617,7 @@ if (game.is_new_game) { load_rulesets(); /* otherwise rulesets were loaded when savegame was loaded */ + game.year = game.calendars[0].first_year; } nations_avail = fc_calloc(game.playable_nation_count, sizeof(int));