Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2004:
[Freeciv-Dev] (PR#7399) RiverBoats
Home

[Freeciv-Dev] (PR#7399) RiverBoats

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#7399) RiverBoats
From: "Tarje Bargheer" <tarje@xxxxxxxxxx>
Date: Sun, 8 Feb 2004 16:49:08 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=7399 >

Appachment Adds option riverboats, meaning that some Boat types has the 
flag "RiverBoat", which enables it to travel along rivers. Only 
Triremes, Caravels, destroyers and transports are set to riverboats in 
the default ruleset. - This is not solely by divine decree, rather more 
or less random.

Patch by Tarje Bargheer: tarje@xxxxxxxxxx

? civgame.log
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.202
diff -r1.202 city.c
414c414
< 
---
>   
422c422,427
<   /* You can't build naval units inland. */
---
>   /*if it is a naval unit that can travel on rivers, and the city is on 
>    * a river, accept it*/
>   if (tile_has_special(map_get_tile(pcity->x, pcity->y), S_RIVER) & 
> unit_type_flag(id, F_RIVERBOAT)) {
>     return TRUE;
>   }
>   /* Otherwise, you can't build naval units inland. */
452a458,461
>   /*if it is a naval unit that can travel on rivers, accept it*/
>   if (tile_has_special(map_get_tile(pcity->x, pcity->y), S_RIVER) && 
> unit_type_flag(id, F_RIVERBOAT)) {
>     return TRUE;
>   }
454c463
<      ships may be built only in cities adjacent to ocean. */
---
>      ships may be built only in cities adjacent to ocean. If they are not 
> river-going */
Index: common/game.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.h,v
retrieving revision 1.131
diff -r1.131 game.h
98a99
>   bool riverboat;
302a304,305
> 
> #define GAME_DEFAULT_RIVERBOAT TRUE
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.160
diff -r1.160 map.c
969a970
>     - it is a riverboat travelling on rivers
Index: common/unit.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v
retrieving revision 1.198
diff -r1.198 unit.c
18a19
> #include <stdlib.h>
57c58
<  
---
>     
331c332
< ...
---
> tests if this is a unit that moves on oceans
335c336
<   return (unit_type(punit)->move_type == SEA_MOVING);
---
>   return (unit_type(punit)->move_type == SEA_MOVING) ;
337a339
> 
1285a1288,1337
> /***************************************************************************
>   Rules for riverboat movements are lined out in comments to unit_move_result
> ***************************************************************************/
> 
> bool invalid_riverboat_move(int src_x, int src_y, int dest_x, int dest_y,
>                           struct player *unit_owner)
> {
>   
>   struct tile *totile;
>   struct tile *fromtile;
>   fromtile = map_get_tile(src_x, src_y);
>   totile = map_get_tile(dest_x, dest_y);
>   
>   if(!tile_has_special(totile, S_RIVER) && !(totile->terrain == T_OCEAN)){
>     return TRUE;
>   }
> 
>   if((src_x != dest_x) && (src_y != dest_y) && 
>      tile_has_special(fromtile, S_RIVER)) {
>     return TRUE;
>   }
>   if((src_x != dest_x) && (src_y != dest_y) && 
>      tile_has_special(totile, S_RIVER)) {
>     if(is_allied_city_tile(totile, unit_owner) && fromtile->terrain == 
> T_OCEAN)
>       {/*entering city harbor from sea, ok.*/
>       } else {
>       return TRUE;
>       }
>   }
>   if (is_enemy_city_tile(totile, unit_owner)){
>     return TRUE;
>   }
>   if (is_allied_city_tile(totile, unit_owner)){
>     if (tile_has_special(fromtile, S_RIVER) &&
>       !tile_has_special(totile, S_RIVER)){
>       return TRUE;
>       }
>     if (tile_has_special(fromtile, S_RIVER) && 
>       (src_x != dest_x) && (src_y != dest_y)){
>       return TRUE;
>     }
>     }         
>   if (is_allied_city_tile(fromtile, unit_owner) &&
>       tile_has_special(totile, S_RIVER) &&
>       !tile_has_special(fromtile, S_RIVER)){
>     return TRUE;
>   }
>   return FALSE;
> }
> 
1298a1351,1355
>   11) Riverboats may only move along the travelled river 
>       - rivers may only be travelled by
>       horisontally or vertically (even from the sea-stream goes right on),
>       and may not occupy enemy cities along the river.
>       And they may not enter inland cities adjacent to rivers
1355a1413,1417
>       /*11) - 1*/
>       if ( tile_has_special(ptotile, S_RIVER) && 
>          unit_type_flag(type, F_RIVERBOAT)){/*then we have a riverboat 
> travelling  on a river, which is ok, so nothing should be returned yet.*/
>       }
>       else{
1356a1419
>       }
1359c1422
< 
---
>   
1377a1441,1448
>   /* 11) -2*/
>   if (unit_type_flag(type, F_RIVERBOAT)){
>     if (invalid_riverboat_move(src_x, src_y, dest_x, dest_y, unit_owner)){
>       return MR_NOT_RIVER_FOR_RIVERBOAT;
>     }
>   }
>          
>     
Index: common/unit.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v
retrieving revision 1.111
diff -r1.111 unit.h
77c77,78
<   MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_CITY
---
>   MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_CITY,
>   MR_NOT_RIVER_FOR_RIVERBOAT
274a276,278
> 
> bool invalid_riverboat_move(int src_x, int src_y, int dest_x, int dest_y,
>                           struct player *unit_owner);
Index: common/unittype.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.c,v
retrieving revision 1.29
diff -r1.29 unittype.c
49c49
<   "Undisbandable", "SuperSpy", "NoHome", "NoVeteran"
---
>   "Undisbandable", "SuperSpy", "NoHome", "NoVeteran", "Riverboat", "NoEffect"
124c124
< ...
---
> Checks if a unit is either a Ocean unit or a ocean unit that can move on 
> rivers
128c128
<   return (unit_types[id].move_type == SEA_MOVING);
---
>   return unit_types[id].move_type == SEA_MOVING;
390a391,394
>     /*if riverboat are not turned on, simply ignore all mentioning in the 
> rules*/
>     if (game.riverboat == FALSE && i == F_RIVERBOAT) {
>       return F_NO_EFFECT;
>     }
Index: common/unittype.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.h,v
retrieving revision 1.22
diff -r1.22 unittype.h
118a119,120
>   F_RIVERBOAT,        /* A sea unit that can move on rivers*/
>   F_NO_EFFECT,        /* This flag has no effect - currently needed for 
> ruling out riverboats*/
Index: common/aicore/pf_tools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/pf_tools.c,v
retrieving revision 1.12
diff -r1.12 pf_tools.c
24a25,26
> #include "common/unit.h"
> 
31c33
<   A cost function for SEA_MOVING.  Allows shore bombardment.
---
>   A cost function for SEA_MOVING.  Allows shore bombardment (but not 
> riverboat_movement).
46a49,68
> /*************************************************************
>   A cost function for SEA_MOVING.  Allows shore bombardment and
>   riverboat movement
>   Should be used in conjunction with a TB callback which 
>   prohibits going through an enemy city/tile.
> *************************************************************/
> static int seamove_river(int x, int y, enum direction8 dir,
>                    int x1, int y1, struct pf_parameter *param)
> {
>   /* MOVE_COST_FOR_VALID_SEA_STEP means ships can move between */
>   if ((map_get_tile(x, y)->move_cost[dir] == MOVE_COST_FOR_VALID_SEA_STEP)
>       || is_non_allied_unit_tile(map_get_tile(x1, y1), param->owner)
>       || is_non_allied_city_tile(map_get_tile(x1, y1), param->owner)
>       || !invalid_riverboat_move(x, y, x1, y1, param->owner)){
>     return SINGLE_MOVE;
>   } else {
>     return PF_IMPOSSIBLE_MC;
>   }
> }
> 
50c72
<   bombardment.
---
>   bombardment or riverboatmovement
56c78
<   if (map_get_tile(x, y)->move_cost[dir] == MOVE_COST_FOR_VALID_SEA_STEP
---
>   if ((map_get_tile(x, y)->move_cost[dir] == MOVE_COST_FOR_VALID_SEA_STEP)
63a86,102
> /*************************************************************
>   A cost function for SEA_MOVING.  Does not allow shore 
>   bombardment. But allows riverboatmoving
> *************************************************************/
> static int seamove_no_bombard_river(int x, int y, enum direction8 dir,
>                                   int x1, int y1, struct pf_parameter *param)
> {
>   /* MOVE_COST_FOR_VALID_SEA_STEP means ships can move between */
>   if ((map_get_tile(x, y)->move_cost[dir] == MOVE_COST_FOR_VALID_SEA_STEP
>        && !is_non_allied_city_tile(map_get_tile(x1, y1), param->owner))
>       || !(invalid_riverboat_move(x, y, x1 ,y1, param->owner))){
>     return SINGLE_MOVE;
>   } else {
>     return PF_IMPOSSIBLE_MC;
>   }
> }
> 
405a445
>     /*check for both riverboats and non-shore_bombers*/
407,409c447,457
<       parameter->get_MC = seamove_no_bombard;
<     } else {
<       parameter->get_MC = seamove;
---
>       if(unit_flag(punit, F_RIVERBOAT)){
>       parameter->get_MC = seamove_no_bombard_river;
>       } else {
>       parameter->get_MC = seamove_no_bombard;
>         }
>     } else {
>       if(unit_flag(punit, F_RIVERBOAT)){
>       parameter->get_MC = seamove_river;
>       } else {
>       parameter->get_MC = seamove;
>       }
Index: data/default/units.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/units.ruleset,v
retrieving revision 1.54
diff -r1.54 units.ruleset
147,148c147,148
< ;               therefore will not revolt along with its city of origin should
< ;               it be incited
---
> ;               therefore will not revolt along with its city of origin 
> should;                 it be incited
> ; "RiverBoat" = this unit (sea units only) can also travel on rivers.
1173c1173
< flags         = "Trireme"
---
> flags         = "Trireme", "RiverBoat"
1201c1201
< flags         = ""
---
> flags         = "RiverBoat"
1313c1313
< flags         = ""
---
> flags         = "RiverBoat"
1495c1495
< flags         = ""
---
> flags         = "RiverBoat"
Index: server/gotohand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/gotohand.c,v
retrieving revision 1.178
diff -r1.178 gotohand.c
265a266
>   bool riverboat;
287a289,293
>   if (punit && unit_flag(punit, F_RIVERBOAT))
>     riverboat = TRUE;
>   else
>     riverboat = FALSE;
> 
339a346,354
>       if (riverboat == TRUE){
>         /*If we are travelling straight north, south, east or west
>           (that is, if not moved in both y- and x-axis),
>           and there is a river on that tile -- is this working???*/
>         if (((x == x1)||(y == y1)) &&
>               tile_has_special(map_get_tile(x1, y1), S_RIVER)){
>           move_cost -= cost - SINGLE_MOVE; /*add SINGLE_MOVE, instead of 
> cost, made large by unpassable shoreline*/
>         }
>       }
501,561c516,576
< This function mark paths on the warmaps vector showing the shortest path to
< the destination.
< 
< It is an search via Dijkstra's Algorithm
< (see fx http://odin.ee.uwa.edu.au/~morris/Year2/PLDS210/dijkstra.html)
< We start with a list with only one tile (the
< starttile), and then tries to move in each of the 8 directions from there.
< This then gives us more tiles to more from. Repeat until we meet the
< destination or there is no remaining tiles.
< All possible paths coming out of the starttile are stored in local_vector.
< After we've reached the destination, only the paths connecting starttile
< with the destination are copied from local_vector to the warmap's vector.
< 
< Whenever we reach a tile we see how many movepoints it took to get there,
< and compare it to eventual previous moves to the tile. If the route is
< faster or just as fast we mark the direction from which we came on the
< local_vector array and also record the new movecost. If we come to a
< tile we have meet before, and the cost of the route we have taken is
< smaller than the previous one we add the tile to the list again, to get
< the tiles it leads to updated etc. The change in move_cost for the tile
< will then propagate out.
< We have a maxcost, as an upper limit for the length of gotos. When we
< arrive at the GOTO destination with a path we know that we don't have to
< follow other paths that have exceeded this length, and set maxcost to
< length+1. (the +1 because we still want to find alternative paths of the
< same length, and comparisons with maxcost are done with <).
< When we have found all paths of the shortest length to the destination we
< backtrack from the destination tile all the way back to the start tile,
< marking the routes on the warmap's vector as we go. (again by piling tiles
< on the queue). find_a_direction() can then use these routes to choose a
< path.
< Note that some move_cost values, like for going into unknown territory and
< attacking while on GOTO is values not directly related to the move cost,
< but rather meant to encourage/discourage certain behaviour.
< 
< The restrictions GOTO_MOVE_CARDINAL_ONLY and GOTO_MOVE_STRAIGHTEST are
< currently only used for settlers building irrigation and roads.
< 
< To avoid RR loops (which may cause find_a_direction() to move a unit in
< cute little cycles forever and ever...), when we have more than one path
< to a tile and the second one is via RR (move_cost 0), we do NOT mark the
< extra path.
< 
< At one point we used dir_ok to test if we were going in the right direction,
< but the cost of the dir_ok call was too high in itself, and the penalty
< sometimes lead to suboptimal paths chosen. The current implementation have
< the disadvantage that it will search until all move_cost's are larger than
< one found to the target, which can be expensive on RR (but not as bad as
< you might think as most AI GOTO's will be long anyway).
< 
< Often we'll already have a working warmap, So we could maybe avoid using
< this function to find a path if really_generate_warmap marked the paths
< on the warmap. On the other side, most of the time GOTOs will be relatively
< short, and doing extra work in really_generate_warmap, which will always
< check a lot of tiles, may not be worth it. really_generate_warmap() is also
< more crude than this function, so it would have to be expanded (which would
< be _very_ expensive in CPU).
< 
< FIXME: this is a bit of a mess in not respecting FoW, and only sometimes
< respecting if a square is known. (not introduced by me though) -Thue
< **************************************************************************/
---
>  *This function mark paths on the warmaps vector showing the shortest path to
>  *the destination.
>  *
>  *It is an search via Dijkstra's Algorithm
>  *(see fx http://odin.ee.uwa.edu.au/~morris/Year2/PLDS210/dijkstra.html)
>  *We start with a list with only one tile (the
>  *starttile), and then tries to move in each of the 8 directions from there.
>  *This then gives us more tiles to more from. Repeat until we meet the
>  *destination or there is no remaining tiles.
>  *All possible paths coming out of the starttile are stored in local_vector.
>  *After we've reached the destination, only the paths connecting starttile
>  *with the destination are copied from local_vector to the warmap's vector.
> 
>  *Whenever we reach a tile we see how many movepoints it took to get there,
>  *and compare it to eventual previous moves to the tile. If the route is
>  *faster or just as fast we mark the direction from which we came on the
>  *local_vector array and also record the new movecost. If we come to a
>  *tile we have meet before, and the cost of the route we have taken is
>  *smaller than the previous one we add the tile to the list again, to get
>  *the tiles it leads to updated etc. The change in move_cost for the tile
>  *will then propagate out.
>  *We have a maxcost, as an upper limit for the length of gotos. When we
>  *arrive at the GOTO destination with a path we know that we don't have to
>  *follow other paths that have exceeded this length, and set maxcost to
>  *length+1. (the +1 because we still want to find alternative paths of the
>  *same length, and comparisons with maxcost are done with <).
>  *When we have found all paths of the shortest length to the destination we
>  *backtrack from the destination tile all the way back to the start tile,
>  *marking the routes on the warmap's vector as we go. (again by piling tiles
>  *on the queue). find_a_direction() can then use these routes to choose a
>  *path.
>  *Note that some move_cost values, like for going into unknown territory and
>  *attacking while on GOTO is values not directly related to the move cost,
>  *but rather meant to encourage/discourage certain behaviour.
> 
>  *The restrictions GOTO_MOVE_CARDINAL_ONLY and GOTO_MOVE_STRAIGHTEST are
>  *currently only used for settlers building irrigation and roads.
> 
>  *To avoid RR loops (which may cause find_a_direction() to move a unit in
>  *cute little cycles forever and ever...), when we have more than one path
>  *to a tile and the second one is via RR (move_cost 0), we do NOT mark the
>  *extra path.
> 
>  *At one point we used dir_ok to test if we were going in the right direction,
>  *but the cost of the dir_ok call was too high in itself, and the penalty
>  *sometimes lead to suboptimal paths chosen. The current implementation have
>  *the disadvantage that it will search until all move_cost's are larger than
>  *one found to the target, which can be expensive on RR (but not as bad as
>  *you might think as most AI GOTO's will be long anyway).
> 
>  *Often we'll already have a working warmap, So we could maybe avoid using
>  *this function to find a path if really_generate_warmap marked the paths
>  *on the warmap. On the other side, most of the time GOTOs will be relatively
>  *short, and doing extra work in really_generate_warmap, which will always
>  *check a lot of tiles, may not be worth it. really_generate_warmap() is also
>  *more crude than this function, so it would have to be expanded (which would
>  *be _very_ expensive in CPU).
> 
>  *FIXME: this is a bit of a mess in not respecting FoW, and only sometimes
>  *respecting if a square is known. (not introduced by me though) -Thue
>  **************************************************************************/
1252c1267,1271
<        * (allow for bombardment and visiting ports) */
---
>        * (allow for bombardment and visiting ports).*/
>       return TRUE;
>     }
>     /*A riverboat moving towards river is also sane*/
>     if (tile_has_special(map_get_tile(x, y), S_RIVER) && 
> unit_type_flag(punit->type, F_RIVERBOAT)){
1261d1279
< 
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.163
diff -r1.163 ruleset.c
921c921
< 
---
>       
Index: server/stdinhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/stdinhand.c,v
retrieving revision 1.305
diff -r1.305 stdinhand.c
484a485,491
>   GEN_BOOL("riverboat", game.riverboat, SSET_RULES, SSET_TO_CLIENT,
>         N_("Whether some sea units should be able to sail on rivers"),
>         N_("If set to one, some sailing units (determined by ruleset"
>            "will be able to sail on rivers as well as ocean"), NULL, 
>         GAME_DEFAULT_RIVERBOAT)
> 
> 
Index: server/unithand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unithand.c,v
retrieving revision 1.287
diff -r1.287 unithand.c
896a897,899
>   } else if (reason == MR_NOT_RIVER_FOR_RIVERBOAT){
>     notify_player_ex(unit_owner(punit), src_x, src_y, E_NOEVENT,
>                    _("Game: Riverboats cannot move from one river to 
> another"));

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#7399) RiverBoats, Tarje Bargheer <=