[freeciv-ai] (PR#8474) RFC: clean up road_bonus()
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=8474 >
Forgetting that this ticket existed, I tried to rewrite road_bonus to
work with the same algorithm under hex maps. I completely failed.
So instead I wrote a new algorithm. The patch includes it. I'm not
sure it's better, but at least it should be comprehensible.
Note this patch doesn't apply anymore because road_bonus has had some
variable renames and added comments.
jason
Index: server/settlers.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/settlers.c,v
retrieving revision 1.186
diff -u -r1.186 settlers.c
--- server/settlers.c 3 Aug 2004 03:08:54 -0000 1.186
+++ server/settlers.c 3 Aug 2004 19:39:21 -0000
@@ -699,57 +699,114 @@
}
/**************************************************************************
+ Determine if the given tile has a road, or if one is being built.
+**************************************************************************/
+static bool has_road(int map_x, int map_y, enum tile_special_type special)
+{
+ struct tile *ptile = map_get_tile(map_x, map_y);
+
+ if (tile_has_special(ptile, special)) {
+ /* There's already a road here. */
+ return TRUE;
+ }
+
+ unit_list_iterate(ptile->units, punit) {
+ if ((punit->activity == ACTIVITY_ROAD && special == S_ROAD)
+ || punit->activity == ACTIVITY_RAILROAD) {
+ /* Someone's building a road. */
+ return TRUE;
+ }
+ } unit_list_iterate_end;
+
+ /* No road. */
+ return FALSE;
+}
+
+/**************************************************************************
Calculate the attractiveness
"spc" will be S_ROAD or S_RAILROAD for sane calls.
**************************************************************************/
-static int road_bonus(int x, int y, enum tile_special_type spc)
+static int road_bonus(int x, int y, enum tile_special_type special)
{
- int m = 0, k;
- bool rd[12], te[12];
- int ii[12] = { -1, 0, 1, -1, 1, -1, 0, 1, 0, -2, 2, 0 };
- int jj[12] = { -1, -1, -1, 0, 0, 1, 1, 1, -2, 0, 0, 2 };
- struct tile *ptile;
- bool is_border = IS_BORDER_MAP_POS(x, y, 2);
+ int goodness = 0, dir_index;
+ struct tile *ptile = map_get_tile(x, y);
- assert(spc == S_ROAD || spc == S_RAILROAD);
+ assert(special == S_ROAD || special == S_RAILROAD);
- if (!normalize_map_pos(&x, &y))
- return 0;
+ for (dir_index = 0; dir_index < map.num_valid_dirs / 2; dir_index++) {
+ enum direction8 dir1 = map.valid_dirs[dir_index];
+ enum direction8 dir2a = DIR_REVERSE(dir1);
+ enum direction8 dir2b = dir_cw(dir2a);
+ enum direction8 dir2c = dir_ccw(dir2a);
+ int x1, y1, x2, y2;
- for (k = 0; k < 12; k++) {
- int x1 = x + ii[k], y1 = y + jj[k];
- if (is_border && !normalize_map_pos(&x1, &y1)) {
- rd[k] = FALSE;
- te[k] = FALSE;
- } else {
- ptile = map_get_tile(x1, y1);
- rd[k] = tile_has_special(ptile, spc);
- te[k] = (ptile->terrain == T_MOUNTAINS || is_ocean(ptile->terrain));
- if (!rd[k]) {
- unit_list_iterate(ptile->units, punit) {
- if (punit->activity == ACTIVITY_ROAD
- || punit->activity == ACTIVITY_RAILROAD) {
- rd[k] = TRUE;
- }
- } unit_list_iterate_end;
+ if (!MAPSTEP(x1, y1, x, y, dir1) || !has_road(x1, y1, special)) {
+ continue;
+ }
+
+ if (MAPSTEP(x2, y2, x, y, dir2a) && has_road(x2, y2, special)) {
+ /* If opposite sides have a road, we want one here to connect
+ * them. */
+ freelog(LOG_NORMAL, "%d,%d connects opposite %d,%d through %d,%d.",
+ x1, y1, x2, y2, x, y);
+ goodness = 5;
+ }
+
+ if (MAPSTEP(x2, y2, x, y, dir2b) && has_road(x2, y2, special)) {
+ /* If nearly-opposite sides have a road, we want one here to connect
+ * them _unless_ there's already one adjacent connecting them.
+ * Consider:
+ *
+ * 1 2 3
+ * 4 5 6
+ * 7 8 9
+ *
+ * if 1 and 6 have a road, we want one at 5 unless there's already one
+ * at 2.
+ */
+ enum direction8 dir3;
+ int x3, y3;
+
+ /* This code is crafted to work for both hex and rectangular maps. */
+ if (is_cardinal_dir(dir2b)) {
+ dir3 = dir_cw(dir2b);
+ } else {
+ dir3 = dir_ccw(dir1);
+ }
+ if (!MAPSTEP(x3, y3, x, y, dir3) || !has_road(x3, y3, special)) {
+ freelog(LOG_NORMAL, "%d,%d connects nearly opposite %d,%d "
+ "through %d,%d; %d,%d is empty.",
+ x1, y1, x2, y2, x, y, x3, y3);
+ goodness = 5;
+ }
+ }
+
+ if (MAPSTEP(x2, y2, x, y, dir2c) && has_road(x2, y2, special)) {
+ /* Same as the above code, but for the other direction. */
+ enum direction8 dir3;
+ int x3, y3;
+
+ if (is_cardinal_dir(dir2c)) {
+ dir3 = dir_ccw(dir2b);
+ } else {
+ dir3 = dir_cw(dir1);
+ }
+ if (!MAPSTEP(x3, y3, x, y, dir3) || !has_road(x3, y3, special)) {
+ freelog(LOG_NORMAL, "%d,%d connects nearly opposite %d,%d "
+ "through %d,%d; %d,%d is empty.",
+ x1, y1, x2, y2, x, y, x3, y3);
+ goodness = 5;
}
}
}
- if (rd[0] && !rd[1] && !rd[3] && (!rd[2] || !rd[8]) &&
- (!te[2] || !te[4] || !te[7] || !te[6] || !te[5])) m++;
- if (rd[2] && !rd[1] && !rd[4] && (!rd[7] || !rd[10]) &&
- (!te[0] || !te[3] || !te[7] || !te[6] || !te[5])) m++;
- if (rd[5] && !rd[6] && !rd[3] && (!rd[5] || !rd[11]) &&
- (!te[2] || !te[4] || !te[7] || !te[1] || !te[0])) m++;
- if (rd[7] && !rd[6] && !rd[4] && (!rd[0] || !rd[9]) &&
- (!te[2] || !te[3] || !te[0] || !te[1] || !te[5])) m++;
-
- if (rd[1] && !rd[4] && !rd[3] && (!te[5] || !te[6] || !te[7])) m++;
- if (rd[3] && !rd[1] && !rd[6] && (!te[2] || !te[4] || !te[7])) m++;
- if (rd[4] && !rd[1] && !rd[6] && (!te[0] || !te[3] || !te[5])) m++;
- if (rd[6] && !rd[4] && !rd[3] && (!te[0] || !te[1] || !te[2])) m++;
- return(m);
+ /* If there are units on the tile, they probably want a road to travel
+ * on. */
+ unit_list_iterate(ptile->units, punit) {
+ goodness++;
+ } unit_list_iterate_end;
+
+ return goodness;
}
/**************************************************************************
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freeciv-ai] (PR#8474) RFC: clean up road_bonus(),
Jason Short <=
|
|