<URL: http://bugs.freeciv.org/Ticket/Display.html?id=19132 >
This version of the patch modifies also mapgenerator. Only tiles
native to initial unit are considered as starting positions.
- ML
diff -Nurd -X.diff_ignore freeciv/server/gamehand.c freeciv/server/gamehand.c
--- freeciv/server/gamehand.c 2006-07-17 23:56:22.000000000 +0300
+++ freeciv/server/gamehand.c 2007-01-10 19:49:31.000000000 +0200
@@ -59,30 +59,13 @@
}
/****************************************************************************
- Place a starting unit for the player.
+ Get unit_type for given role character
****************************************************************************/
-static void place_starting_unit(struct tile *ptile, struct player *pplayer,
- char crole)
+struct unit_type *crole_to_unit_type(char crole,struct player *pplayer)
{
- struct unit_type *utype;
+ struct unit_type *utype = NULL;
enum unit_flag_id role;
- assert(!is_non_allied_unit_tile(ptile, pplayer));
-
- /* For scenarios or dispersion, huts may coincide with player starts (in
- * other cases, huts are avoided as start positions). Remove any such hut,
- * and make sure to tell the client, since we may have already sent this
- * tile (with the hut) earlier: */
- if (tile_has_special(ptile, S_HUT)) {
- tile_clear_special(ptile, S_HUT);
- update_tile_knowledge(ptile);
- freelog(LOG_VERBOSE, "Removed hut on start position for %s",
- pplayer->name);
- }
-
- /* Expose visible area. */
- map_show_circle(pplayer, ptile, game.info.init_vis_radius_sq);
-
switch(crole) {
case 'c':
role = L_CITIES;
@@ -116,16 +99,65 @@
break;
default:
assert(FALSE);
- return;
+ return NULL;
}
/* Create the unit of an appropriate type, if it exists */
if (num_role_units(role) > 0) {
- utype = first_role_unit_for_player(pplayer, role);
+ if (pplayer != NULL) {
+ utype = first_role_unit_for_player(pplayer, role);
+ }
if (utype == NULL) {
utype = get_role_unit(role, 0);
}
+ }
+
+ return utype;
+}
+
+/****************************************************************************
+ Place a starting unit for the player. Returns tile where unit was really
+ placed.
+****************************************************************************/
+static struct tile *place_starting_unit(struct tile *starttile,
+ struct player *pplayer,
+ char crole)
+{
+ struct tile *ptile = NULL;
+ struct unit_type *utype = crole_to_unit_type(crole, pplayer);
+
+ if (utype != NULL) {
+ iterate_outward(starttile, map.xsize + map.ysize, itertile) {
+ if (!is_non_allied_unit_tile(itertile, pplayer)
+ && is_native_tile(utype, itertile)) {
+ ptile = itertile;
+ break;
+ }
+ } iterate_outward_end;
+ }
+
+ if (ptile == NULL) {
+ /* No place where unit may exist. */
+ return NULL;
+ }
+
+ assert(!is_non_allied_unit_tile(ptile, pplayer));
+
+ /* For scenarios or dispersion, huts may coincide with player starts (in
+ * other cases, huts are avoided as start positions). Remove any such hut,
+ * and make sure to tell the client, since we may have already sent this
+ * tile (with the hut) earlier: */
+ if (tile_has_special(ptile, S_HUT)) {
+ tile_clear_special(ptile, S_HUT);
+ update_tile_knowledge(ptile);
+ freelog(LOG_VERBOSE, "Removed hut on start position for %s",
+ pplayer->name);
+ }
+
+ /* Expose visible area. */
+ map_show_circle(pplayer, ptile, game.info.init_vis_radius_sq);
+ if (utype != NULL) {
/* We cannot currently handle sea units as start units.
* TODO: remove this code block when we can. */
if (get_unit_move_type(utype) == SEA_MOVING) {
@@ -134,11 +166,14 @@
notify_player(pplayer, NULL, E_BAD_COMMAND,
_("Sea moving start units are not yet supported. "
"Nobody gets %s."), utype->name);
- return;
+ return NULL;
}
(void) create_unit(pplayer, ptile, utype, FALSE, 0, 0);
+ return ptile;
}
+
+ return NULL;
}
/****************************************************************************
@@ -170,6 +205,7 @@
{
const int NO_START_POS = -1;
int start_pos[game.info.nplayers];
+ int placed_units[game.info.nplayers];
bool pos_used[map.num_start_positions];
int i, num_used = 0;
@@ -239,7 +275,12 @@
= map.start_positions[start_pos[pplayer->player_no]];
/* Place the first unit. */
- place_starting_unit(pos.tile, pplayer, game.info.start_units[0]);
+ if (place_starting_unit(pos.tile, pplayer,
+ game.info.start_units[0]) != NULL) {
+ placed_units[pplayer->player_no] = 1;
+ } else {
+ placed_units[pplayer->player_no] = 0;
+ }
} players_iterate_end;
/* Place all other units. */
@@ -255,7 +296,10 @@
ptile = find_dispersed_position(pplayer, &p);
/* Create the unit of an appropriate type. */
- place_starting_unit(ptile, pplayer, game.info.start_units[i]);
+ if (place_starting_unit(ptile, pplayer,
+ game.info.start_units[i]) != NULL) {
+ placed_units[pplayer->player_no]++;
+ }
}
/* Place nation specific start units (not role based!) */
@@ -263,10 +307,18 @@
while (nation->init_units[i] != NULL && i < MAX_NUM_UNIT_LIST) {
ptile = find_dispersed_position(pplayer, &p);
create_unit(pplayer, ptile, nation->init_units[i], FALSE, 0, 0);
+ placed_units[pplayer->player_no]++;
i++;
}
} players_iterate_end;
+ players_iterate(pplayer) {
+ if (placed_units[pplayer->player_no] == 0) {
+ /* No units at all for some player! */
+ die(_("No units placed for %s!"), pplayer->name);
+ }
+ } players_iterate_end;
+
shuffle_players();
}
diff -Nurd -X.diff_ignore freeciv/server/gamehand.h freeciv/server/gamehand.h
--- freeciv/server/gamehand.h 2006-07-17 23:56:22.000000000 +0300
+++ freeciv/server/gamehand.h 2007-01-10 19:49:59.000000000 +0200
@@ -23,6 +23,8 @@
void send_game_state(struct conn_list *dest, int state);
void send_start_phase_to_clients(void);
+struct unit_type *crole_to_unit_type(char crole,struct player *pplayer);
+
int update_timeout(void);
void increase_timeout_because_unit_moved(void);
diff -Nurd -X.diff_ignore freeciv/server/generator/mapgen.c freeciv/server/generator/mapgen.c
--- freeciv/server/generator/mapgen.c 2006-07-17 23:56:22.000000000 +0300
+++ freeciv/server/generator/mapgen.c 2007-01-10 19:39:46.000000000 +0200
@@ -1127,7 +1127,7 @@
based on the map.size server parameter and the specified topology. If
not map.xsize and map.ysize will be used.
**************************************************************************/
-void map_fractal_generate(bool autosize)
+void map_fractal_generate(bool autosize, struct unit_type *initial_unit)
{
/* save the current random state: */
RANDOM_STATE rstate = get_myrand_state();
@@ -1232,7 +1232,7 @@
}
for(;;) {
- success = create_start_positions(mode);
+ success = create_start_positions(mode, initial_unit);
if (success) {
break;
}
diff -Nurd -X.diff_ignore freeciv/server/generator/mapgen.h freeciv/server/generator/mapgen.h
--- freeciv/server/generator/mapgen.h 2006-07-17 23:56:22.000000000 +0300
+++ freeciv/server/generator/mapgen.h 2007-01-10 19:39:33.000000000 +0200
@@ -15,6 +15,6 @@
#include "shared.h" /* bool type */
-void map_fractal_generate(bool autosize);
+void map_fractal_generate(bool autosize, struct unit_type *initial_unit);
#endif /* FC__MAPGEN_H */
diff -Nurd -X.diff_ignore freeciv/server/generator/startpos.c freeciv/server/generator/startpos.c
--- freeciv/server/generator/startpos.c 2006-08-18 10:51:26.000000000 +0300
+++ freeciv/server/generator/startpos.c 2007-01-10 19:39:18.000000000 +0200
@@ -17,6 +17,7 @@
#include "game.h"
#include "log.h"
#include "fcintl.h"
+#include "movement.h"
#include "map.h"
@@ -82,6 +83,7 @@
struct start_filter_data {
int count; /* Number of existing start positions. */
int min_value;
+ struct unit_type *initial_unit;
int *value;
};
@@ -119,6 +121,11 @@
return FALSE;
}
+ /* Has to be native for tile for initial unit */
+ if (!is_native_tile(pdata->initial_unit, ptile)) {
+ return FALSE;
+ }
+
/* A longstanding bug allowed starting positions to exist on poles,
* sometimes. This hack prevents it by setting a fixed distance from
* the pole (dependent on map temperature) that a start pos must be.
@@ -193,7 +200,8 @@
Returns true on success
**************************************************************************/
-bool create_start_positions(enum start_mode mode)
+bool create_start_positions(enum start_mode mode,
+ struct unit_type *initial_unit)
{
struct tile *ptile;
int k, sum;
@@ -350,6 +358,7 @@
data.count = 0;
data.value = tile_value;
data.min_value = 900;
+ data.initial_unit = initial_unit;
sum = 0;
for (k = 1; k <= map.num_continents; k++) {
sum += islands[islands_index[k]].starters;
diff -Nurd -X.diff_ignore freeciv/server/generator/startpos.h freeciv/server/generator/startpos.h
--- freeciv/server/generator/startpos.h 2006-07-17 23:56:22.000000000 +0300
+++ freeciv/server/generator/startpos.h 2007-01-10 19:39:27.000000000 +0200
@@ -21,6 +21,7 @@
MT_VARIABLE
};
-bool create_start_positions(enum start_mode mode);
+bool create_start_positions(enum start_mode mode,
+ struct unit_type *initial_unit);
#endif
diff -Nurd -X.diff_ignore freeciv/server/srv_main.c freeciv/server/srv_main.c
--- freeciv/server/srv_main.c 2006-07-21 23:18:07.000000000 +0300
+++ freeciv/server/srv_main.c 2007-01-10 19:53:13.000000000 +0200
@@ -1878,7 +1878,9 @@
/* If we have a tile map, and map.generator==0, call map_fractal_generate
* anyway to make the specials, huts and continent numbers. */
if (map_is_empty() || (map.generator == 0 && game.info.is_new_game)) {
- map_fractal_generate(TRUE);
+ struct unit_type *utype = crole_to_unit_type(game.info.start_units[0], NULL);
+
+ map_fractal_generate(TRUE, utype);
}
/* start the game */
_______________________________________________
Freeciv-dev mailing list
[email protected]
https://mail.gna.org/listinfo/freeciv-dev