diff -ruN -X freeciv/diff_ignore freeciv/ai/aiunit.c freeciv.mod/ai/aiunit.c --- freeciv/ai/aiunit.c Wed Jan 10 19:50:44 2001 +++ freeciv.mod/ai/aiunit.c Sun Jan 14 17:26:27 2001 @@ -318,7 +318,7 @@ if (unknown > most_unknown && (landnear || !unit_flag(punit->type, F_TRIREME)) && map_get_continent(x1, y1) == con - && can_unit_move_to_tile(punit, x1, y1, 0) + && can_unit_move_to_tile(punit, x1, y1, 0, FALSE, FALSE) && !((pcity = map_get_city(x1,y1)) && (unit_flag(punit->type, F_DIPLOMAT) || unit_flag(punit->type, F_CARAVAN))) @@ -329,13 +329,15 @@ } } square_iterate_end; - if (most_unknown > 0) { /* a tile have unexplored territory adjacent */ - int res = handle_unit_move_request(punit, best_x, best_y, FALSE, FALSE); - if (!res) /* This shouldn't happen */ + if (most_unknown > 0) { /* a tile have unexplored territory adjacent */ + int res = handle_unit_move_request(punit, best_x, best_y, FALSE, + FALSE, FALSE, FALSE); + if (!res) /* This shouldn't happen */ break; if (!player_find_unit_by_id(pplayer, id)) - return 0; /* died */ - x = punit->x; y = punit->y; + return 0; /* died */ + x = punit->x; + y = punit->y; } else { break; } @@ -776,7 +778,7 @@ "Stationary escort @(%d,%d) received %d best @(%d,%d)", punit->x, punit->y, i, x, y); if (i >= 40 * SHIELD_WEIGHTING) - handle_unit_move_request(punit, x, y, FALSE, FALSE); + handle_unit_move_request(punit, x, y, FALSE, FALSE, FALSE, FALSE); /* otherwise don't bother, but free cities are free cities and must be snarfed. -- Syela */ } if (aunit && unit_list_find(&map_get_tile(x, y)->units, id) && aunit->ai.bodyguard) @@ -966,8 +968,11 @@ freelog(LOG_DEBUG, "Bodyguard at (%d, %d) is adjacent to (%d, %d)", i, j, punit->x, punit->y); - if (aunit->moves_left) return(0); - else return handle_unit_move_request(punit, i, j, FALSE, FALSE); + if (aunit->moves_left) + return (0); + else + return handle_unit_move_request(punit, i, j, FALSE, + FALSE, FALSE, FALSE); } unit_list_iterate_end; } /* end j */ @@ -1187,8 +1192,9 @@ /* aggro defense goes here -- Syela */ ai_military_findvictim(pplayer, punit, &dest_x, &dest_y); punit->ai.ai_role=AIUNIT_NONE; - handle_unit_move_request(punit, dest_x, dest_y, FALSE, FALSE); - /* might bash someone */ + handle_unit_move_request(punit, dest_x, dest_y, FALSE, + FALSE, FALSE, FALSE); + /* might bash someone */ } else { freelog(LOG_DEBUG, "GOHOME(%d,%d)", punit->goto_dest_x, punit->goto_dest_y); @@ -1576,11 +1582,15 @@ } /* else nothing to kill */ } else { /* goto does NOT work for fast units */ freelog(LOG_DEBUG, "%s's %s at (%d, %d) bashing (%d, %d)", - pplayer->name, unit_types[punit->type].name, - punit->x, punit->y, dest_x, dest_y); - handle_unit_move_request(punit, dest_x, dest_y, FALSE, FALSE); - punit = find_unit_by_id(id); - if (punit) flag = punit->moves_left; else flag = 0; + pplayer->name, unit_types[punit->type].name, + punit->x, punit->y, dest_x, dest_y); + handle_unit_move_request(punit, dest_x, dest_y, FALSE, + FALSE, FALSE, FALSE); + punit = find_unit_by_id(id); + if (punit) + flag = punit->moves_left; + else + flag = 0; } if (punit) if (stay_and_defend_city(punit)) return; @@ -1641,7 +1651,7 @@ } else { req.unit_id = punit->id; req.city_id = pcity->id; - handle_unit_establish_trade(pplayer, &req); + handle_unit_establish_trade(pplayer, &req, FALSE, FALSE); } } } @@ -2297,10 +2307,11 @@ y = map_adjust_x(leader->y + dy); if (warmap.cost[x][y] > safest - && can_unit_move_to_tile(leader, x, y, FALSE)) { + && can_unit_move_to_tile(leader, x, y, FALSE, FALSE, FALSE)) { safest = warmap.cost[x][y]; - freelog(LOG_DEBUG, "Barbarian leader: safest is %d, %d, safeness %d", - x, y, safest); + freelog(LOG_DEBUG, + "Barbarian leader: safest is %d, %d, safeness %d", x, y, + safest); safest_x = x; safest_y = y; } diff -ruN -X freeciv/diff_ignore freeciv/client/civclient.c freeciv.mod/client/civclient.c --- freeciv/client/civclient.c Sun Jan 7 14:09:56 2001 +++ freeciv.mod/client/civclient.c Sun Jan 14 22:39:56 2001 @@ -361,6 +361,10 @@ handle_conn_info((struct packet_conn_info *)packet); break; + case PACKET_RESULT: + handle_result((struct packet_generic_integer *)packet); + break; + default: freelog(LOG_ERROR, "Received unknown packet (type %d) from server!", type); /* Old clients (<= some 1.11.5-devel, capstr +1.11) used to exit() @@ -415,13 +419,18 @@ { struct packet_move_unit move; - move.unid=punit->id; - move.x=punit->x; - move.y=punit->y; + move.unid = punit->id; + move.x = punit->x; + move.y = punit->y; + move.dry_run = FALSE; +#ifdef PROFILE_RESULTS + move.report_result = TRUE; +#else + move.report_result = FALSE; +#endif send_packet_move_unit(&aconnection, &move); } - /************************************************************************** ... **************************************************************************/ diff -ruN -X freeciv/diff_ignore freeciv/client/civclient.h freeciv.mod/client/civclient.h --- freeciv/client/civclient.h Wed Aug 9 15:11:38 2000 +++ freeciv.mod/client/civclient.h Sun Jan 14 22:38:56 2001 @@ -16,6 +16,9 @@ #include "packets.h" /* enum report_type */ #include "game.h" /* enum client_states */ +#define PROFILE_RESULTS +/*#undef PROFILE_RESULTS*/ + void handle_packet_input(char *packet, int type); void send_unit_info(struct unit *punit); diff -ruN -X freeciv/diff_ignore freeciv/client/packhand.c freeciv.mod/client/packhand.c --- freeciv/client/packhand.c Wed Jan 10 22:24:06 2001 +++ freeciv.mod/client/packhand.c Sun Jan 14 22:48:41 2001 @@ -36,6 +36,7 @@ #include "support.h" #include "unit.h" #include "worklist.h" +#include "result.h" #include "chatline_g.h" #include "citydlg_g.h" @@ -2163,4 +2164,32 @@ popup_sabotage_dialog(pcity); } +} + +/************************************************************************** +... +**************************************************************************/ +void handle_result(struct packet_generic_integer *packet) +{ +#ifdef PROFILE_RESULTS + enum result result = packet->value; + static int counts[R_LAST]; + static int total = 0; + + counts[result]++; + total++; + if ((total % 100) == 0) { + int i; + + for (i = 0; i < R_LAST; i++) + if (counts[i] > 0) { + int promille = (counts[i] * 1000) / total; + freelog(LOG_DEBUG, "%4d/%4d = %3d.%d%% for %2d '%s'", + counts[i], total, promille / 10, promille % 10, + i, get_result_string(i)); + } + } +#endif + + freelog(LOG_DEBUG, "Got result %d", packet->value); } diff -ruN -X freeciv/diff_ignore freeciv/client/packhand.h freeciv.mod/client/packhand.h --- freeciv/client/packhand.h Sun Aug 27 08:57:22 2000 +++ freeciv.mod/client/packhand.h Sun Jan 14 15:22:37 2001 @@ -58,5 +58,6 @@ void handle_ruleset_game(struct packet_ruleset_game *packet); void handle_diplomat_action(struct packet_diplomat_action *packet); void handle_sabotage_list(struct packet_sabotage_list *packet); +void handle_result(struct packet_generic_integer *packet); #endif /* FC__PACKHAND_H */ diff -ruN -X freeciv/diff_ignore freeciv/common/Makefile.am freeciv.mod/common/Makefile.am --- freeciv/common/Makefile.am Mon Aug 14 14:48:27 2000 +++ freeciv.mod/common/Makefile.am Sun Jan 14 16:10:05 2001 @@ -60,6 +60,8 @@ rand.h \ registry.c \ registry.h \ + result.h \ + result.c \ sbuffer.c \ sbuffer.h \ shared.c \ diff -ruN -X freeciv/diff_ignore freeciv/common/capstr.c freeciv.mod/common/capstr.c --- freeciv/common/capstr.c Sat Oct 28 00:20:07 2000 +++ freeciv.mod/common/capstr.c Sun Jan 14 16:50:47 2001 @@ -73,7 +73,8 @@ #define CAPABILITY "+1.11 diplomat_investigate_fix production_change_fix" \ " game_ruleset nuclear_fallout land_channel_requirement event_wonder_obsolete" \ " event00_fix conn_info gen_impr_oversights diplo_move_city packet_short_city" \ -" indef_impr_types worklist_true_ids shared_vision activity_patrol" +" indef_impr_types worklist_true_ids shared_vision activity_patrol" \ +" ext_move_unit" /* "+1.11" is protocol for 1.11.0 stable release. @@ -129,6 +130,9 @@ "activity_patrol" is the patrol activity and the ability to send a goto route from the client to the server (for both goto and patrol activities). + + "ext_move_unit" extends packet_move_unit to include dry_run and + report_result. */ void init_our_capability(void) diff -ruN -X freeciv/diff_ignore freeciv/common/packets.c freeciv.mod/common/packets.c --- freeciv/common/packets.c Fri Dec 15 18:56:06 2000 +++ freeciv.mod/common/packets.c Sun Jan 14 20:41:49 2001 @@ -247,6 +247,7 @@ case PACKET_ADVANCE_FOCUS: case PACKET_PLAYER_CANCEL_PACT: case PACKET_PLAYER_REMOVE_VISION: + case PACKET_RESULT: return receive_packet_generic_integer(pc); case PACKET_ALLOC_NATION: @@ -2586,13 +2587,16 @@ cptr=put_uint8(cptr, request->x); cptr=put_uint8(cptr, request->y); cptr=put_uint16(cptr, request->unid); + + if (pc && has_capability("ext_move_unit", pc->capability)) { + cptr = put_uint8(cptr, request->dry_run); + cptr = put_uint8(cptr, request->report_result); + } put_uint16(buffer, cptr-buffer); return send_connection_data(pc, buffer, cptr-buffer); } - - /************************************************************************** ... **************************************************************************/ @@ -2607,6 +2611,14 @@ iget_uint8(&iter, &packet->x); iget_uint8(&iter, &packet->y); iget_uint16(&iter, &packet->unid); + + if (pc && has_capability("ext_move_unit", pc->capability)) { + iget_uint8(&iter, &packet->dry_run); + iget_uint8(&iter, &packet->report_result); + } else { + packet->dry_run = 0; + packet->report_result = 0; + } pack_iter_end(&iter, pc); remove_packet_from_buffer(pc->buffer); diff -ruN -X freeciv/diff_ignore freeciv/common/packets.h freeciv.mod/common/packets.h --- freeciv/common/packets.h Sat Oct 28 00:20:09 2000 +++ freeciv.mod/common/packets.h Sun Jan 14 15:22:37 2001 @@ -115,6 +115,7 @@ PACKET_PLAYER_REMOVE_VISION, PACKET_GOTO_ROUTE, PACKET_PATROL_ROUTE, + PACKET_RESULT, PACKET_LAST /* leave this last */ }; @@ -270,15 +271,14 @@ /********************************************************* packet represents a request to the server, for moving the -units with the corresponding id's from the unids array, -to the position x,y -unids[] is a compressed array, containing garbage after -last 0 id. +unit with the corresponding id to the position x,y. +If dry_run is set the server will not carry out the +movement. If report_result the server will send a +PACKET_RESULT back. *********************************************************/ struct packet_move_unit { - int x, y, unid; + int x, y, unid, dry_run, report_result; }; - /********************************************************* diff -ruN -X freeciv/diff_ignore freeciv/common/result.c freeciv.mod/common/result.c --- freeciv/common/result.c Thu Jan 1 01:00:00 1970 +++ freeciv.mod/common/result.c Sun Jan 14 20:42:14 2001 @@ -0,0 +1,52 @@ + +#include + +#include "result.h" + +const char *get_result_string(enum result result) +{ + + static const char *const tmp[] = { + "R_OK", + "R_ABORTING_GOTO", + "R_AI_BODYGUARD", + "R_AI_DIPLOMAT_ON_GOTO", + "R_AI_GOTO", + "R_AI_SOME_CASE", + "R_BAD_ACTIVITY", + "R_BAD_DESTINATION", + "R_BAD_DESTINATION_FOR_SHIP", + "R_BARBARIANS_ENTER_HUT", + "R_CANT_ATTACK", + "R_CANT_ATTACK_ALLIED_CITY", + "R_CANT_ATTACK_NO_ATTACK", + "R_CANT_ATTACK_NON_AN_ENEMY", + "R_CANT_ATTACK_NOT_ALLIED_AND_NOT_AN_ENEMY", + "R_CANT_CAPTURE_CITY", + "R_CANT_CAPTURE_CITY_NOT_AN_ENEMY", + "R_CANT_EST_TRADEROUTE", + "R_CANT_MOVE_UNIT", + "R_CITY_NOT_FOUND", + "R_DEFERRED_DIPLOMAT_ACTION", + "R_DESTINATION_NOT_ADJACENT", + "R_GROUND_UNIT_ATTACKING_FROM_SEA", + "R_ID_INVALID_OR_NOT_OWNER", + "R_KILLED_BY_BARBARIANS", + "R_MAX_TRADEROUTES", + "R_MAY_KILLED_BY_BARBARIANS", + "R_MAY_NOT_ENOUGH_MOVES_LEFT", + "R_NON_ALLIED_UNITS_BLOCKING", + "R_NOT_A_CARAVAN", + "R_NO_TRANSPORTER_CAPACITY", + "R_SAME_POSITION", + "R_TRADEROUTE_ALREADY_EST", + "R_UNIT_TO_FAR", + "R_ZERO_MOVES_LEFT", + "R_ZOC", + "R_LAST" + }; + assert(result >= 0); + assert(result <= R_LAST); + + return tmp[result]; +} diff -ruN -X freeciv/diff_ignore freeciv/common/result.h freeciv.mod/common/result.h --- freeciv/common/result.h Thu Jan 1 01:00:00 1970 +++ freeciv.mod/common/result.h Sun Jan 14 20:42:36 2001 @@ -0,0 +1,67 @@ +/********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ +#ifndef FC__RESULT_H +#define FC__RESULT_H + +#undef R_OK /* is used by access(2) see unistd.h */ + +/* + * extracted from server/ using + * grep R_ *.c | grep send_res | sed "s/^.*[ ,]\(R_.*\)).*$/\1/g" | sort | uniq + */ + +enum result { + R_OK, + + R_ABORTING_GOTO, + R_AI_BODYGUARD, + R_AI_DIPLOMAT_ON_GOTO, + R_AI_GOTO, + R_AI_SOME_CASE, + R_BAD_ACTIVITY, + R_BAD_DESTINATION, + R_BAD_DESTINATION_FOR_SHIP, + R_BARBARIANS_ENTER_HUT, + R_CANT_ATTACK, + R_CANT_ATTACK_ALLIED_CITY, + R_CANT_ATTACK_NO_ATTACK, + R_CANT_ATTACK_NON_AN_ENEMY, + R_CANT_ATTACK_NOT_ALLIED_AND_NOT_AN_ENEMY, + R_CANT_CAPTURE_CITY, + R_CANT_CAPTURE_CITY_NOT_AN_ENEMY, + R_CANT_EST_TRADEROUTE, + R_CANT_MOVE_UNIT, + R_CITY_NOT_FOUND, + R_DEFERRED_DIPLOMAT_ACTION, + R_DESTINATION_NOT_ADJACENT, + R_GROUND_UNIT_ATTACKING_FROM_SEA, + R_ID_INVALID_OR_NOT_OWNER, + R_KILLED_BY_BARBARIANS, + R_MAX_TRADEROUTES, + R_MAY_KILLED_BY_BARBARIANS, + R_MAY_NOT_ENOUGH_MOVES_LEFT, + R_NON_ALLIED_UNITS_BLOCKING, + R_NOT_A_CARAVAN, + R_NO_TRANSPORTER_CAPACITY, + R_SAME_POSITION, + R_TRADEROUTE_ALREADY_EST, + R_UNIT_TO_FAR, + R_ZERO_MOVES_LEFT, + R_ZOC, + + R_LAST +}; + +const char *get_result_string(enum result result); + +#endif diff -ruN -X freeciv/diff_ignore freeciv/server/barbarian.c freeciv.mod/server/barbarian.c --- freeciv/server/barbarian.c Tue Jan 9 00:44:31 2001 +++ freeciv.mod/server/barbarian.c Sun Jan 14 20:45:09 2001 @@ -250,10 +250,12 @@ unit_list_iterate(map_get_tile(x, y)->units, punit2) { if( punit2->owner == me ) { send_unit_info( 0, punit2); - do { - do rand_neighbour(x, y, &xu, &yu); - while( !is_free_land(xu, yu, me) ); - } while( !handle_unit_move_request(punit2, xu, yu, TRUE, FALSE) ); + do { + do + rand_neighbour(x, y, &xu, &yu); + while (!is_free_land(xu, yu, me)); + } while (!handle_unit_move_request(punit2, xu, yu, TRUE, + FALSE, FALSE, FALSE)); freelog(LOG_DEBUG, "Moved barbarian unit from %d %d to %d, %d", x,y,xu,yu); } } @@ -267,10 +269,12 @@ send_unit_info( 0, punit2); while(1) { rand_neighbour(x, y, &xu, &yu); - if( can_unit_move_to_tile(punit2, xu, yu, TRUE) ) break; - if( can_unit_move_to_tile(punit2, xb, yb, TRUE) ) { - xu = xb; yu = yb; - break; + if (can_unit_move_to_tile(punit2, xu, yu, TRUE, FALSE, FALSE)) + break; + if (can_unit_move_to_tile(punit2, xb, yb, TRUE, FALSE, FALSE)) { + xu = xb; + yu = yb; + break; } if( is_free_sea(xu, yu, me) ) { boat = find_a_unit_type(L_BARBARIAN_BOAT, -1); @@ -279,7 +283,8 @@ break; } } - handle_unit_move_request(punit2, xu, yu, TRUE, FALSE); + handle_unit_move_request(punit2, xu, yu, TRUE, FALSE, FALSE, + FALSE); } unit_list_iterate_end; } diff -ruN -X freeciv/diff_ignore freeciv/server/diplomats.c freeciv.mod/server/diplomats.c --- freeciv/server/diplomats.c Wed Jan 10 22:24:09 2001 +++ freeciv.mod/server/diplomats.c Sun Jan 14 20:45:36 2001 @@ -466,7 +466,8 @@ /* Now, try to move the briber onto the victim's square. */ diplomat_id = pdiplomat->id; - if (!handle_unit_move_request(pdiplomat, victim_x, victim_y, FALSE, FALSE)) { + if (!handle_unit_move_request(pdiplomat, victim_x, victim_y, FALSE, + FALSE, FALSE, FALSE)) { pdiplomat->moves_left = 0; } if (player_find_unit_by_id(pplayer, diplomat_id)) { diff -ruN -X freeciv/diff_ignore freeciv/server/gotohand.c freeciv.mod/server/gotohand.c --- freeciv/server/gotohand.c Tue Jan 9 00:44:33 2001 +++ freeciv.mod/server/gotohand.c Sun Jan 14 20:46:05 2001 @@ -1194,10 +1194,12 @@ return; last_tile = same_pos(x, y, punit->goto_dest_x, punit->goto_dest_y); if (!handle_unit_move_request(punit, x, y, FALSE, - !(last_tile && trigger_special_ability))) { + !(last_tile + && trigger_special_ability), FALSE, + FALSE)) { freelog(LOG_DEBUG, "Couldn't handle it."); if (punit->moves_left) { - punit->activity=ACTIVITY_IDLE; + punit->activity = ACTIVITY_IDLE; send_unit_info(0, punit); return; } diff -ruN -X freeciv/diff_ignore freeciv/server/srv_main.c freeciv.mod/server/srv_main.c --- freeciv/server/srv_main.c Tue Jan 9 00:44:35 2001 +++ freeciv.mod/server/srv_main.c Sun Jan 14 15:22:37 2001 @@ -1041,7 +1041,8 @@ break; case PACKET_UNIT_ESTABLISH_TRADE: - handle_unit_establish_trade(pplayer, (struct packet_unit_request *)packet); + handle_unit_establish_trade(pplayer, (struct packet_unit_request *)packet, + FALSE, FALSE); break; case PACKET_UNIT_HELP_BUILD_WONDER: diff -ruN -X freeciv/diff_ignore freeciv/server/unithand.c freeciv.mod/server/unithand.c --- freeciv/server/unithand.c Wed Jan 10 22:24:09 2001 +++ freeciv.mod/server/unithand.c Sun Jan 14 22:39:12 2001 @@ -32,6 +32,7 @@ #include "rand.h" #include "support.h" #include "unit.h" +#include "result.h" #include "cityhand.h" #include "citytools.h" @@ -276,9 +277,10 @@ } break; case DIPLOMAT_MOVE: - if(pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_MOVE, - pcity->x, pcity->y)) { - handle_unit_move_request(pdiplomat, pcity->x, pcity->y, FALSE, TRUE); + if (pcity && diplomat_can_do_action(pdiplomat, DIPLOMAT_MOVE, + pcity->x, pcity->y)) { + handle_unit_move_request(pdiplomat, pcity->x, pcity->y, + FALSE, TRUE, FALSE, FALSE); } break; case DIPLOMAT_STEAL: @@ -472,8 +474,9 @@ if(punit) { if (!same_pos(punit->x, punit->y, pinfo->x, pinfo->y)) { - punit->ai.control=0; - handle_unit_move_request(punit, pinfo->x, pinfo->y, FALSE, FALSE); + punit->ai.control = 0; + handle_unit_move_request(punit, pinfo->x, pinfo->y, FALSE, + FALSE, FALSE, FALSE); } else if(punit->activity!=pinfo->activity || punit->activity_target!=pinfo->activity_target || @@ -497,9 +500,12 @@ { struct unit *punit; - punit=player_find_unit_by_id(pplayer, pmove->unid); - if(punit) { - handle_unit_move_request(punit, pmove->x, pmove->y, FALSE, FALSE); + punit = player_find_unit_by_id(pplayer, pmove->unid); + if (punit) { + handle_unit_move_request(punit, pmove->x, pmove->y, FALSE, FALSE, + pmove->dry_run, pmove->report_result); + } else if (pmove->dry_run) { + send_result(pplayer, R_ID_INVALID_OR_NOT_OWNER); } } @@ -680,7 +686,8 @@ int old_moves = punit->moves_left; int full_moves = unit_move_rate (punit); punit->moves_left = full_moves; - if (handle_unit_move_request(punit, def_x, def_y, FALSE, FALSE)) { + if (handle_unit_move_request(punit, def_x, def_y, FALSE, + FALSE, FALSE, FALSE)) { punit->moves_left = old_moves - (full_moves - punit->moves_left); if (punit->moves_left < 0) { punit->moves_left = 0; @@ -823,9 +830,10 @@ } /************************************************************************** -Return 1 if unit is alive, and 0 if it was killed +Return 1 if unit is alive, and 0 if it was killed. +If dry_run is true return 1 means is alive, and 0 may-get-killed. **************************************************************************/ -int handle_unit_enter_hut(struct unit *punit) +int handle_unit_enter_hut(struct unit *punit, int dry_run) { struct player *pplayer = unit_owner(punit); int ok = 1; @@ -834,16 +842,23 @@ return ok; } - map_get_tile(punit->x, punit->y)->special^=S_HUT; - send_tile_info(0, punit->x, punit->y); + if (!dry_run) { + map_get_tile(punit->x, punit->y)->special ^= S_HUT; + send_tile_info(0, punit->x, punit->y); + } - if (game.rgame.hut_overflight==OVERFLIGHT_FRIGHTEN && is_air_unit(punit)) { - notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - _("Game: Your overflight frightens the tribe;" - " they scatter in terror.")); + if (game.rgame.hut_overflight == OVERFLIGHT_FRIGHTEN + && is_air_unit(punit)) { + if (!dry_run) + notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, + _("Game: Your overflight frightens the tribe;" + " they scatter in terror.")); return ok; } + if (dry_run) + return 0; + switch (myrand(12)) { case 0: hut_get_gold(punit, 25); @@ -882,9 +897,13 @@ 'move_diplomat_city' is another special case which should normally be FALSE. If TRUE, try to move diplomat (or spy) into city (should be allied) instead of telling client to popup diplomat/spy dialog. + + If dry_run is true no changes will be made. A result packet will be + send back in every case. **************************************************************************/ int handle_unit_move_request(struct unit *punit, int dest_x, int dest_y, - int igzoc, int move_diplomat_city) + int igzoc, int move_diplomat_city, + int dry_run, int report_result) { struct player *pplayer = unit_owner(punit); struct tile *pdesttile = map_get_tile(dest_x, dest_y); @@ -893,16 +912,24 @@ struct city *pcity = pdesttile->city; /* barbarians shouldn't enter huts */ - if (is_barbarian(pplayer) && pdesttile->special&S_HUT) { + if (is_barbarian(pplayer) && pdesttile->special & S_HUT) { + if (report_result) + send_result(pplayer, R_BARBARIANS_ENTER_HUT); return 0; } /* this occurs often during lag, and to the AI due to some quirks -- Syela */ - if (same_pos(punit->x, punit->y, dest_x, dest_y)) + if (same_pos(punit->x, punit->y, dest_x, dest_y)) { + if (report_result) + send_result(pplayer, R_SAME_POSITION); return 0; + } - if (do_airline(punit, dest_x, dest_y)) + if (do_airline(punit, dest_x, dest_y, dry_run)) { + if (report_result) + send_result(pplayer, R_OK); return 1; + } if (unit_flag(punit->type, F_CARAVAN) && pcity @@ -913,7 +940,8 @@ req.unit_id = punit->id; req.city_id = pcity->id; req.name[0] = '\0'; - return handle_unit_establish_trade(pplayer, &req); + return handle_unit_establish_trade(pplayer, &req, + dry_run, report_result); } /* Pop up a diplomat action dialog in the client. If the AI has used @@ -929,7 +957,16 @@ || is_non_allied_city_tile(pdesttile, punit->owner) || !move_diplomat_city)) { struct packet_diplomat_action packet; - if (punit->activity == ACTIVITY_GOTO && pplayer->ai.control) + if (punit->activity == ACTIVITY_GOTO && pplayer->ai.control) { + if (report_result) + send_result(pplayer, R_AI_DIPLOMAT_ON_GOTO); + return 0; + } + + if (report_result) + send_result(pplayer, R_DEFERRED_DIPLOMAT_ACTION); + + if (dry_run) return 0; /* If we didn't send_unit_info the client would sometimes think that @@ -956,15 +993,19 @@ /*** Try to attack if there is an enemy unit on the target tile ***/ if (pdefender && players_at_war(punit->owner, pdefender->owner)) { - if (!can_unit_attack_tile(punit, dest_x , dest_y)) { + if (!can_unit_attack_tile(punit, dest_x, dest_y)) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - _("Game: You can't attack there.")); + _("Game: You can't attack there.")); + if (report_result) + send_result(pplayer, R_CANT_ATTACK); return 0; } - if (punit->moves_left<=0) { + if (punit->moves_left <= 0) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - _("Game: This unit has no moves left.")); + _("Game: This unit has no moves left.")); + if (report_result) + send_result(pplayer, R_ZERO_MOVES_LEFT); return 0; } @@ -973,23 +1014,32 @@ _("Game: Can't attack %s's unit in the city of %s " "because you are not at war with %s."), unit_owner(pdefender)->name, - pcity->name, - city_owner(pcity)->name); + pcity->name, city_owner(pcity)->name); + if (report_result) + send_result(pplayer, R_CANT_ATTACK_ALLIED_CITY); + return 0; } /* DO NOT Auto-attack. Findvictim routine will decide if we should. */ if (pplayer->ai.control && punit->activity == ACTIVITY_GOTO) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - _("Game: Aborting GOTO for AI attack procedures.")); + _("Game: Aborting GOTO for AI attack procedures.")); + if (report_result) + send_result(pplayer, R_AI_GOTO); + return 0; } if (punit->activity == ACTIVITY_GOTO && - (dest_x != punit->goto_dest_x || dest_y != punit->goto_dest_y)) { + (dest_x != punit->goto_dest_x || dest_y != punit->goto_dest_y)) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - _("Game: %s aborted GOTO as there are units in the way."), - unit_types[punit->type].name); + _ + ("Game: %s aborted GOTO as there are units in the way."), + unit_types[punit->type].name); + if (report_result) + send_result(pplayer, R_ABORTING_GOTO); + return 0; } @@ -1016,12 +1066,19 @@ my_snprintf(message, sizeof(message), _("Game: A %s cannot attack other units."), unit_name(punit->type)); - notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - message); + notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, message); + if (report_result) + send_result(pplayer, R_CANT_ATTACK_NO_ATTACK); + return 0; } - handle_unit_attack_request(punit, pdefender); + if (report_result) + send_result(pplayer, R_OK); + + if (!dry_run) + handle_unit_attack_request(punit, pdefender); + return 1; } /* End attack case */ @@ -1032,20 +1089,26 @@ notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, _("Game: No war declared against %s, cannot attack."), game.players[pdefender->owner].name); - return 0; - } + if (report_result) + send_result(pplayer, R_CANT_ATTACK_NOT_ALLIED_AND_NOT_AN_ENEMY); + return 0; + } { struct unit *bodyguard; if (pplayer->ai.control && - punit->ai.bodyguard > 0 && - (bodyguard = unit_list_find(&psrctile->units, punit->ai.bodyguard)) && - !bodyguard->moves_left) { + punit->ai.bodyguard > 0 && + (bodyguard = unit_list_find(&psrctile->units, punit->ai.bodyguard)) + && !bodyguard->moves_left) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - _("Game: %s doesn't want to leave its bodyguard."), - unit_types[punit->type].name); + _("Game: %s doesn't want to leave its bodyguard."), + unit_types[punit->type].name); + + if (report_result) + send_result(pplayer, R_AI_BODYGUARD); + return 0; } } @@ -1053,12 +1116,18 @@ /* Mao had this problem with chariots ending turns next to enemy cities. -- Syela */ if (pplayer->ai.control && punit->moves_left <= map_move_cost(punit, dest_x, dest_y) && - unit_types[punit->type].move_rate > map_move_cost(punit, dest_x, dest_y) && - enemies_at(punit, dest_x, dest_y) && - !enemies_at(punit, punit->x, punit->y)) { + unit_types[punit->type].move_rate > map_move_cost(punit, dest_x, + dest_y) + && enemies_at(punit, dest_x, dest_y) + && !enemies_at(punit, punit->x, punit->y)) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, - _("Game: %s ending move early to stay out of trouble."), - unit_types[punit->type].name); + _ + ("Game: %s ending move early to stay out of trouble."), + unit_types[punit->type].name); + + if (report_result) + send_result(pplayer, R_AI_SOME_CASE); + return 0; } @@ -1069,21 +1138,29 @@ notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, _("Game: Only ground troops can take over " "a city.")); + + if(report_result) + send_result(pplayer,R_CANT_CAPTURE_CITY); + return 0; } if (!players_at_war(pcity->owner, punit->owner)) { notify_player_ex(pplayer, punit->x, punit->y, E_NOEVENT, _("Game: No war declared against %s, cannot take " - "over city."), - game.players[pcity->owner].name); + "over city."), game.players[pcity->owner].name); + + if (report_result) + send_result(pplayer, R_CANT_CAPTURE_CITY_NOT_AN_ENEMY); + return 0; } } /******* ok now move the unit *******/ - if(can_unit_move_to_tile(punit, dest_x, dest_y, igzoc) && - try_move_unit(punit, dest_x, dest_y)) { + if (can_unit_move_to_tile(punit, dest_x, dest_y, igzoc, + dry_run, report_result) && + try_move_unit(punit, dest_x, dest_y, dry_run, report_result)) { int src_x = punit->x; int src_y = punit->y; int move_cost = map_move_cost(punit, dest_x, dest_y); @@ -1091,28 +1168,45 @@ int take_from_land = punit->activity == ACTIVITY_IDLE; int survived; - survived = move_unit(punit, dest_x, dest_y, 1, take_from_land, move_cost); - if (!survived) + survived = move_unit(punit, dest_x, dest_y, 1, + take_from_land, move_cost, FALSE); + if (!survived) { + if (report_result) { + if (dry_run) + send_result(pplayer, R_MAY_KILLED_BY_BARBARIANS); + else + send_result(pplayer, R_KILLED_BY_BARBARIANS); + } return 1; + } - /* bodyguard code */ - if(pplayer->ai.control && punit->ai.bodyguard > 0) { - struct unit *bodyguard = unit_list_find(&psrctile->units, punit->ai.bodyguard); - if (bodyguard) { - int success; - /* FIXME: it is stupid to set to ACTIVITY_IDLE if the unit is - ACTIVITY_FORTIFIED and the unit has no chance of moving anyway */ - handle_unit_activity_request(bodyguard, ACTIVITY_IDLE); - success = handle_unit_move_request(bodyguard, - dest_x, dest_y, igzoc, FALSE); - freelog(LOG_DEBUG, "Dragging %s from (%d,%d)->(%d,%d) (Success=%d)", - unit_types[bodyguard->type].name, src_x, src_y, - dest_x, dest_y, success); - handle_unit_activity_request(bodyguard, ACTIVITY_FORTIFYING); + if (!dry_run) { + /* bodyguard code */ + if (pplayer->ai.control && punit->ai.bodyguard > 0) { + struct unit *bodyguard = + unit_list_find(&psrctile->units, punit->ai.bodyguard); + if (bodyguard) { + int success; + /* FIXME: it is stupid to set to ACTIVITY_IDLE if the unit is + ACTIVITY_FORTIFIED and the unit has no chance of moving anyway */ + handle_unit_activity_request(bodyguard, ACTIVITY_IDLE); + success = handle_unit_move_request(bodyguard, + dest_x, dest_y, igzoc, + FALSE, FALSE, FALSE); + freelog(LOG_DEBUG, + "Dragging %s from (%d,%d)->(%d,%d) (Success=%d)", + unit_types[bodyguard->type].name, src_x, src_y, dest_x, + dest_y, success); + handle_unit_activity_request(bodyguard, ACTIVITY_FORTIFYING); + } } } + + if (report_result) + send_result(pplayer, R_OK); return 1; } else { + /* the result is already sent */ return 0; } } @@ -1138,9 +1232,8 @@ return; if (!(same_pos(punit->x, punit->y, pcity_dest->x, pcity_dest->y) - || try_move_unit(punit, pcity_dest->x, pcity_dest->y))) - return; - + || try_move_unit(punit, pcity_dest->x, pcity_dest->y, + FALSE, FALSE))) return; /* we're there! */ pcity_dest->shield_stock+=50; @@ -1165,28 +1258,52 @@ /************************************************************************** ... **************************************************************************/ -int handle_unit_establish_trade(struct player *pplayer, - struct packet_unit_request *req) +int handle_unit_establish_trade(struct player *pplayer, + struct packet_unit_request *req, + int dry_run, int report_result) { struct unit *punit; struct city *pcity_homecity, *pcity_dest; int revenue; punit = player_find_unit_by_id(pplayer, req->unit_id); - if (!punit || !unit_flag(punit->type, F_CARAVAN)) + if (!punit) { + if (report_result) + send_result(pplayer, R_ID_INVALID_OR_NOT_OWNER); + return 0; + } + + if (!unit_flag(punit->type, F_CARAVAN)) { + if (report_result) + send_result(pplayer, R_NOT_A_CARAVAN); return 0; + } pcity_homecity=player_find_city_by_id(pplayer, punit->homecity); pcity_dest=find_city_by_id(req->city_id); - if(!pcity_homecity || !pcity_dest) + if (!pcity_homecity || !pcity_dest) { + if (report_result) + send_result(pplayer, R_CITY_NOT_FOUND); + return 0; + } - if (!is_tiles_adjacent(punit->x, punit->y, pcity_dest->x, pcity_dest->y)) + if (!is_tiles_adjacent(punit->x, punit->y, pcity_dest->x, pcity_dest->y)) { + if (report_result) + send_result(pplayer, R_UNIT_TO_FAR); + return 0; + } if (!(same_pos(punit->x, punit->y, pcity_dest->x, pcity_dest->y) - || try_move_unit(punit, pcity_dest->x, pcity_dest->y))) + || try_move_unit(punit, pcity_dest->x, pcity_dest->y, dry_run, + report_result))) { + + if (report_result) + send_result(pplayer, R_CANT_MOVE_UNIT); + return 0; + } if (!can_establish_trade_route(pcity_homecity, pcity_dest)) { int i; @@ -1195,44 +1312,65 @@ " a trade route here!"), unit_name(punit->type)); for (i=0;i<4;i++) { - if (pcity_homecity->trade[i]==pcity_dest->id) { + if (pcity_homecity->trade[i] == pcity_dest->id) { notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, _(" A traderoute already exists between %s and %s!"), pcity_homecity->name, pcity_dest->name); + + if (report_result) + send_result(pplayer, R_TRADEROUTE_ALREADY_EST); + return 0; } } - if (city_num_trade_routes(pcity_homecity)==4) { + if (city_num_trade_routes(pcity_homecity) == 4) { notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, _(" The city of %s already has 4 trade routes!"), pcity_homecity->name); + + if (report_result) + send_result(pplayer, R_MAX_TRADEROUTES); + return 0; } - if (city_num_trade_routes(pcity_dest)==4) { + if (city_num_trade_routes(pcity_dest) == 4) { notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, _(" The city of %s already has 4 trade routes!"), pcity_dest->name); + + if (report_result) + send_result(pplayer, R_MAX_TRADEROUTES); + return 0; } + + if (report_result) + send_result(pplayer, R_CANT_EST_TRADEROUTE); + return 0; } - revenue = establish_trade_route(pcity_homecity, pcity_dest); - conn_list_do_buffer(&pplayer->connections); - notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, - _("Game: Your %s from %s has arrived in %s," - " and revenues amount to %d in gold and research."), - unit_name(punit->type), pcity_homecity->name, - pcity_dest->name, revenue); - wipe_unit(punit); - pplayer->economic.gold+=revenue; - update_tech(pplayer, revenue); - send_player_info(pplayer, pplayer); - city_refresh(pcity_homecity); - city_refresh(pcity_dest); - send_city_info(pplayer, pcity_homecity); - send_city_info(city_owner(pcity_dest), pcity_dest); - conn_list_do_unbuffer(&pplayer->connections); + if (report_result) + send_result(pplayer, R_OK); + + if (!dry_run) { + revenue = establish_trade_route(pcity_homecity, pcity_dest); + conn_list_do_buffer(&pplayer->connections); + notify_player_ex(pplayer, pcity_dest->x, pcity_dest->y, E_NOEVENT, + _("Game: Your %s from %s has arrived in %s," + " and revenues amount to %d in gold and research."), + unit_name(punit->type), pcity_homecity->name, + pcity_dest->name, revenue); + wipe_unit(punit); + pplayer->economic.gold += revenue; + update_tech(pplayer, revenue); + send_player_info(pplayer, pplayer); + city_refresh(pcity_homecity); + city_refresh(pcity_dest); + send_city_info(pplayer, pcity_homecity); + send_city_info(city_owner(pcity_dest), pcity_dest); + conn_list_do_unbuffer(&pplayer->connections); + } return 1; } diff -ruN -X freeciv/diff_ignore freeciv/server/unithand.h freeciv.mod/server/unithand.h --- freeciv/server/unithand.h Tue Jan 9 00:44:38 2001 +++ freeciv.mod/server/unithand.h Sun Jan 14 21:03:02 2001 @@ -36,13 +36,15 @@ void handle_unit_build_city(struct player *pplayer, struct packet_unit_request *req); void handle_unit_info(struct player *pplayer, struct packet_unit_info *pinfo); -int handle_unit_enter_hut(struct unit *punit); +int handle_unit_enter_hut(struct unit *punit, int dry_run); int handle_unit_move_request(struct unit *punit, int dest_x, int dest_y, - int igzoc, int move_diplomat_city); + int igzoc, int move_diplomat_city, + int dry_run, int report_result); void handle_unit_help_build_wonder(struct player *pplayer, struct packet_unit_request *req); -int handle_unit_establish_trade(struct player *pplayer, - struct packet_unit_request *req); +int handle_unit_establish_trade(struct player *pplayer, + struct packet_unit_request *req, + int dry_run, int report_result); void handle_unit_enter_city(struct unit *punit, struct city *pcity); void handle_unit_auto_request(struct player *pplayer, struct packet_unit_request *req); diff -ruN -X freeciv/diff_ignore freeciv/server/unittools.c freeciv.mod/server/unittools.c --- freeciv/server/unittools.c Wed Jan 10 17:52:57 2001 +++ freeciv.mod/server/unittools.c Sun Jan 14 22:37:11 2001 @@ -33,6 +33,7 @@ #include "shared.h" #include "support.h" #include "unit.h" +#include "result.h" #include "barbarian.h" #include "cityhand.h" @@ -621,7 +622,8 @@ 9) there is not a peaceful but un-allied city on the target tile 10) there is no non-allied unit blocking (zoc) [or igzoc is true] **************************************************************************/ -int can_unit_move_to_tile(struct unit *punit, int dest_x, int dest_y, int igzoc) +int can_unit_move_to_tile(struct unit *punit, int dest_x, int dest_y, + int igzoc, int dry_run, int report_result) { struct tile *pfromtile,*ptotile; int zoc; @@ -634,28 +636,49 @@ && punit->activity!=ACTIVITY_GOTO && punit->activity!=ACTIVITY_PATROL && !punit->connecting) + { + if (report_result) + send_result(unit_owner(punit), R_BAD_ACTIVITY); return 0; + } /* 2) */ if (dest_x<0 || dest_x>=map.xsize || dest_y<0 || dest_y>=map.ysize) + { + if (report_result) + send_result(unit_owner(punit), R_BAD_DESTINATION); return 0; + } /* 3) */ if (!is_tiles_adjacent(src_x, src_y, dest_x, dest_y)) + { + if (report_result) + send_result(unit_owner(punit), R_DESTINATION_NOT_ADJACENT); return 0; + } pfromtile = map_get_tile(src_x, src_y); ptotile = map_get_tile(dest_x, dest_y); /* 4) */ if (is_non_allied_unit_tile(ptotile, punit->owner)) + { + if (report_result) + send_result(unit_owner(punit), R_NON_ALLIED_UNITS_BLOCKING); return 0; + } if (is_ground_unit(punit)) { /* 5) */ if (ptotile->terrain==T_OCEAN && ground_unit_transporter_capacity(dest_x, dest_y, punit->owner) <= 0) - return 0; + { + if (report_result) + send_result(unit_owner(punit), R_NO_TRANSPORTER_CAPACITY); + + return 0; + } /* Moving from ocean */ if (pfromtile->terrain==T_OCEAN) { @@ -672,15 +695,21 @@ notify_player_ex(unit_owner(punit), src_x, src_y, E_NOEVENT, _("Game: Cannot attack from sea.")); } + + if (report_result) + send_result(unit_owner(punit), R_GROUND_UNIT_ATTACKING_FROM_SEA); return 0; } } } else if (is_sailing_unit(punit)) { /* 7) */ - if (ptotile->terrain!=T_OCEAN - && ptotile->terrain!=T_UNKNOWN - && !is_allied_city_tile(ptotile, punit->owner)) + if (ptotile->terrain != T_OCEAN + && ptotile->terrain != T_UNKNOWN + && !is_allied_city_tile(ptotile, punit->owner)) { + if (report_result) + send_result(unit_owner(punit), R_BAD_DESTINATION_FOR_SHIP); return 0; + } } /* 8) */ @@ -688,6 +717,9 @@ notify_player_ex(unit_owner(punit), src_x, src_y, E_NOEVENT, _("Game: Cannot attack unless you declare war first.")); + + if (report_result) + send_result(unit_owner(punit), R_CANT_ATTACK_NON_AN_ENEMY); return 0; } @@ -697,6 +729,9 @@ notify_player_ex(unit_owner(punit), src_x, src_y, E_NOEVENT, _("Game: Cannot attack unless you declare war first.")); + + if (report_result) + send_result(unit_owner(punit), R_CANT_ATTACK_NON_AN_ENEMY); return 0; } @@ -706,16 +741,14 @@ notify_player_ex(unit_owner(punit), src_x, src_y, E_NOEVENT, _("Game: %s can only move into your own zone of control."), unit_types[punit->type].name); + + if (report_result) + send_result(unit_owner(punit), R_ZOC); } return zoc; } - - - - - /*************************************************************************** Return 1 if upgrading this unit could cause passengers to get stranded at sea, due to transport capacity changes @@ -1398,7 +1431,7 @@ _("Game: Moved your %s due to changing" " land to sea at (%d, %d)."), unit_name(punit2->type), punit2->x, punit2->y); - move_unit(punit2, x, y, 1, 0, 0); + move_unit(punit2, x, y, 1, 0, 0, FALSE); if (punit2->activity == ACTIVITY_SENTRY) handle_unit_activity_request(punit2, ACTIVITY_IDLE); goto START; @@ -1423,7 +1456,7 @@ _("Game: Embarked your %s due to changing" " land to sea at (%d, %d)."), unit_name(punit2->type), punit2->x, punit2->y); - move_unit(punit2, x, y, 1, 0, 0); + move_unit(punit2, x, y, 1, 0, 0, FALSE); if (punit2->activity == ACTIVITY_SENTRY) handle_unit_activity_request(punit2, ACTIVITY_IDLE); goto START; @@ -1468,7 +1501,7 @@ _("Game: Moved your %s due to changing" " sea to land at (%d, %d)."), unit_name(punit2->type), punit2->x, punit2->y); - move_unit(punit2, x, y, 1, 1, 0); + move_unit(punit2, x, y, 1, 1, 0, FALSE); if (punit2->activity == ACTIVITY_SENTRY) handle_unit_activity_request(punit2, ACTIVITY_IDLE); goto START; @@ -1493,7 +1526,7 @@ _("Game: Docked your %s due to changing" " sea to land at (%d, %d)."), unit_name(punit2->type), punit2->x, punit2->y); - move_unit(punit2, x, y, 1, 1, 0); + move_unit(punit2, x, y, 1, 1, 0, FALSE); if (punit2->activity == ACTIVITY_SENTRY) handle_unit_activity_request(punit2, ACTIVITY_IDLE); goto START; @@ -1778,7 +1811,7 @@ if (move_cost == -1) move_cost = punit->moves_left; - return move_unit(punit, dest_x, dest_y, 0, 0, move_cost); + return move_unit(punit, dest_x, dest_y, 0, 0, move_cost, FALSE); } return 0; } @@ -2428,21 +2461,40 @@ 2) or have it's moves set to 0 a unit can always move atleast once **************************************************************************/ -int try_move_unit(struct unit *punit, int dest_x, int dest_y) +int try_move_unit(struct unit *punit, int dest_x, int dest_y, int dry_run, + int report_result) { - if (myrand(1+map_move_cost(punit, dest_x, dest_y))>punit->moves_left && - punit->moves_leftmoves_left=0; - send_unit_info(&game.players[punit->owner], punit); + int cost = map_move_cost(punit, dest_x, dest_y); + + /* if unit didn't use any movement the unit can move regardless of cost */ + if (punit->moves_left >= unit_move_rate(punit)) + return punit->moves_left; + + /* unit has enough moves left */ + if (punit->moves_left >= cost) + return punit->moves_left; + + /* now we roll the dice */ + + if (myrand(1 + cost) <= punit->moves_left) + /* success */ + return punit->moves_left; + else { + /* failed */ + if (!dry_run) { + punit->moves_left = 0; + send_unit_info(&game.players[punit->owner], punit); + } + if (report_result) + send_result(unit_owner(punit), R_MAY_NOT_ENOUGH_MOVES_LEFT); + return 0; } - return punit->moves_left; } - /************************************************************************** go by airline, if both cities have an airport and neither has been used this turn the unit will be transported by it and have it's moves set to 0 **************************************************************************/ -int do_airline(struct unit *punit, int dest_x, int dest_y) +int do_airline(struct unit *punit, int dest_x, int dest_y, int dry_run) { struct city *city1, *city2; int src_x = punit->x; @@ -2454,18 +2506,20 @@ return 0; if (!unit_can_airlift_to(punit, city2)) return 0; - city1->airlift=0; - city2->airlift=0; - notify_player_ex(unit_owner(punit), dest_x, dest_y, E_NOEVENT, - _("Game: %s transported succesfully."), - unit_name(punit->type)); + if (!dry_run) { + city1->airlift = 0; + city2->airlift = 0; - move_unit(punit, dest_x, dest_y, 0, 0, punit->moves_left); + notify_player_ex(unit_owner(punit), dest_x, dest_y, E_NOEVENT, + _("Game: %s transported succesfully."), + unit_name(punit->type)); - send_city_info(city_owner(city1), city1); - send_city_info(city_owner(city2), city2); + move_unit(punit, dest_x, dest_y, 0, 0, punit->moves_left, dry_run); + send_city_info(city_owner(city1), city1); + send_city_info(city_owner(city2), city2); + } return 1; } @@ -2523,7 +2577,7 @@ { int move_cost = get_unit_type(punit->type)->paratroopers_mr_sub; punit->paradropped = 1; - return move_unit(punit, dest_x, dest_y, 0, 0, move_cost); + return move_unit(punit, dest_x, dest_y, 0, 0, move_cost, FALSE); } } @@ -2957,7 +3011,8 @@ Note that the src and dest need not be adjacent. **************************************************************************/ int move_unit(struct unit *punit, const int dest_x, const int dest_y, - int transport_units, int take_from_land, int move_cost) + int transport_units, int take_from_land, int move_cost, + int dry_run) { int src_x = punit->x; int src_y = punit->y; @@ -2966,97 +3021,105 @@ struct tile *psrctile = map_get_tile(src_x, src_y); struct tile *pdesttile = map_get_tile(dest_x, dest_y); - conn_list_do_buffer(&pplayer->connections); + if (!dry_run) { + conn_list_do_buffer(&pplayer->connections); - if (punit->ai.ferryboat) { - struct unit *ferryboat; - ferryboat = unit_list_find(&psrctile->units, punit->ai.ferryboat); - if (ferryboat) { - freelog(LOG_DEBUG, "%d disembarking from ferryboat %d", - punit->id, punit->ai.ferryboat); - ferryboat->ai.passenger = 0; - punit->ai.ferryboat = 0; - } - } - /* A transporter should not take units with it when on an attack goto -- fisch */ - if ((punit->activity == ACTIVITY_GOTO) && - get_defender(pplayer, punit, punit->goto_dest_x, punit->goto_dest_y) && - psrctile->terrain != T_OCEAN) { - transport_units = 0; - } - - /* A ground unit cannot hold units on an ocean tile */ - if (transport_units - && is_ground_unit(punit) - && pdesttile->terrain == T_OCEAN) - transport_units = 0; - - /* Make sure we don't accidentally insert units into a transporters list */ - unit_list_iterate(pdesttile->units, pcargo) { - if (pcargo->transported_by == punit->id) - pcargo->transported_by = -1; - } unit_list_iterate_end; + if (punit->ai.ferryboat) { + struct unit *ferryboat; + ferryboat = unit_list_find(&psrctile->units, punit->ai.ferryboat); + if (ferryboat) { + freelog(LOG_DEBUG, "%d disembarking from ferryboat %d", + punit->id, punit->ai.ferryboat); + ferryboat->ai.passenger = 0; + punit->ai.ferryboat = 0; + } + } + /* A transporter should not take units with it when on an attack goto -- fisch */ + if ((punit->activity == ACTIVITY_GOTO) && + get_defender(pplayer, punit, punit->goto_dest_x, + punit->goto_dest_y) && psrctile->terrain != T_OCEAN) { + transport_units = 0; + } + + /* A ground unit cannot hold units on an ocean tile */ + if (transport_units && is_ground_unit(punit) + && pdesttile->terrain == T_OCEAN) + transport_units = 0; + + /* Make sure we don't accidentally insert units into a transporters list */ + unit_list_iterate(pdesttile->units, pcargo) { + if (pcargo->transported_by == punit->id) + pcargo->transported_by = -1; + } + unit_list_iterate_end; - /* Transporting units. We first make a list of the units to be moved and - then insert them again. The way this is done makes sure that the - units stay in the same order. */ - if (get_transporter_capacity(punit) && transport_units) { - struct unit_list cargo_units; - - /* First make a list of the units to be moved. */ - unit_list_init(&cargo_units); - assign_units_to_transporter(punit, take_from_land); - unit_list_iterate(psrctile->units, pcargo) { - if (pcargo->transported_by == punit->id) { - unit_list_unlink(&psrctile->units, pcargo); - unit_list_insert(&cargo_units, pcargo); + /* Transporting units. We first make a list of the units to be moved and + then insert them again. The way this is done makes sure that the + units stay in the same order. */ + if (get_transporter_capacity(punit) && transport_units) { + struct unit_list cargo_units; + + /* First make a list of the units to be moved. */ + unit_list_init(&cargo_units); + assign_units_to_transporter(punit, take_from_land); + unit_list_iterate(psrctile->units, pcargo) { + if (pcargo->transported_by == punit->id) { + unit_list_unlink(&psrctile->units, pcargo); + unit_list_insert(&cargo_units, pcargo); + } } - } unit_list_iterate_end; - - /* Insert them again. */ - unit_list_iterate(cargo_units, pcargo) { - unfog_area(pplayer, dest_x, dest_y, get_unit_type(pcargo->type)->vision_range); - pcargo->x = dest_x; - pcargo->y = dest_y; - unit_list_insert(&pdesttile->units, pcargo); - check_unit_activity(pcargo); - send_unit_info_to_onlookers(0, pcargo, src_x, src_y, 1, 0); - fog_area(pplayer, src_x, src_y, get_unit_type(pcargo->type)->vision_range); - handle_unit_move_consequences(pcargo, src_x, src_y, dest_x, dest_y); - } unit_list_iterate_end; - unit_list_unlink_all(&cargo_units); - } + unit_list_iterate_end; - /* We first unfog the destination, then move the unit and send the move, - and then fog the old territory. This means that the player gets a chance to - see the newly explored territory while the client moves the unit, and both - areas are visible during the move */ - unfog_area(pplayer, dest_x, dest_y, get_unit_type(punit->type)->vision_range); - - unit_list_unlink(&psrctile->units, punit); - punit->x = dest_x; - punit->y = dest_y; - punit->moved = 1; - punit->transported_by = -1; - punit->moves_left = MAX(0, punit->moves_left - move_cost); - unit_list_insert(&pdesttile->units, punit); - check_unit_activity(punit); - - /* set activity to sentry if boarding a ship */ - if (is_ground_unit(punit) && - pdesttile->terrain == T_OCEAN && - !(pplayer->ai.control)) { - set_unit_activity(punit, ACTIVITY_SENTRY); - } - send_unit_info_to_onlookers(0, punit, src_x, src_y, 0, 0); - fog_area(pplayer, src_x, src_y, get_unit_type(punit->type)->vision_range); + /* Insert them again. */ + unit_list_iterate(cargo_units, pcargo) { + unfog_area(pplayer, dest_x, dest_y, + get_unit_type(pcargo->type)->vision_range); + pcargo->x = dest_x; + pcargo->y = dest_y; + unit_list_insert(&pdesttile->units, pcargo); + check_unit_activity(pcargo); + send_unit_info_to_onlookers(0, pcargo, src_x, src_y, 1, 0); + fog_area(pplayer, src_x, src_y, + get_unit_type(pcargo->type)->vision_range); + handle_unit_move_consequences(pcargo, src_x, src_y, dest_x, + dest_y); + } + unit_list_iterate_end; + unit_list_unlink_all(&cargo_units); + } - handle_unit_move_consequences(punit, src_x, src_y, dest_x, dest_y); + /* We first unfog the destination, then move the unit and send the + move, and then fog the old territory. This means that the + player gets a chance to see the newly explored territory while + the client moves the unit, and both areas are visible during + the move */ + unfog_area(pplayer, dest_x, dest_y, + get_unit_type(punit->type)->vision_range); + + unit_list_unlink(&psrctile->units, punit); + punit->x = dest_x; + punit->y = dest_y; + punit->moved = 1; + punit->transported_by = -1; + punit->moves_left = MAX(0, punit->moves_left - move_cost); + unit_list_insert(&pdesttile->units, punit); + check_unit_activity(punit); + + /* set activity to sentry if boarding a ship */ + if (is_ground_unit(punit) && + pdesttile->terrain == T_OCEAN && !(pplayer->ai.control)) { + set_unit_activity(punit, ACTIVITY_SENTRY); + } + send_unit_info_to_onlookers(0, punit, src_x, src_y, 0, 0); + fog_area(pplayer, src_x, src_y, + get_unit_type(punit->type)->vision_range); - conn_list_do_unbuffer(&pplayer->connections); + handle_unit_move_consequences(punit, src_x, src_y, dest_x, dest_y); - if (map_get_tile(dest_x, dest_y)->special&S_HUT) - return handle_unit_enter_hut(punit); + conn_list_do_unbuffer(&pplayer->connections); + } + if (map_get_tile(dest_x, dest_y)->special & S_HUT) + return handle_unit_enter_hut(punit, dry_run); else return 1; } @@ -3095,7 +3158,9 @@ if (is_tiles_adjacent(punit->x, punit->y, x, y)) { int last_tile = (index+1)%pgr->length == pgr->last_index; freelog(LOG_DEBUG, "handling\n"); - res = handle_unit_move_request(punit, x, y, 0, !last_tile); + res = + handle_unit_move_request(punit, x, y, 0, !last_tile, FALSE, + FALSE); if (!player_find_unit_by_id(pplayer, unitid)) return; if (!res && punit->moves_left) { @@ -3126,4 +3191,12 @@ } } } /* end while*/ +} + +void send_result(struct player *dest, enum result result) +{ + struct packet_generic_integer req; + + req.value = result; + send_packet_generic_integer(dest->current_conn, PACKET_RESULT, &req); } diff -ruN -X freeciv/diff_ignore freeciv/server/unittools.h freeciv.mod/server/unittools.h --- freeciv/server/unittools.h Tue Jan 9 00:44:38 2001 +++ freeciv.mod/server/unittools.h Sun Jan 14 22:36:26 2001 @@ -13,6 +13,8 @@ #ifndef FC__UNITTOOLS_H #define FC__UNITTOOLS_H +#include "result.h" + struct city; struct player; struct unit; @@ -47,8 +49,8 @@ int zoc_ok_move_gen(struct unit *punit, int x1, int y1, int x2, int y2); int zoc_ok_move(struct unit *punit,int x, int y); int unit_really_ignores_zoc(struct unit *punit); -int can_unit_move_to_tile(struct unit *punit, int dest_x, int dest_y, int igzoc); - +int can_unit_move_to_tile(struct unit *punit, int dest_x, int dest_y, + int igzoc, int dry_run, int report_result); /* turn update related */ void player_restore_units(struct player *pplayer); @@ -90,16 +92,18 @@ void send_unit_info_to_onlookers(struct conn_list *dest, struct unit *punit, int x, int y, int carried, int select_it); void send_all_known_units(struct conn_list *dest); - +void send_result(struct player *dest, enum result result); /* doing a unit activity */ void do_nuclear_explosion(int x, int y); -int try_move_unit(struct unit *punit, int dest_x, int dest_y); -int do_airline(struct unit *punit, int dest_x, int dest_y); +int try_move_unit(struct unit *punit, int dest_x, int dest_y, + int dry_run, int report_result); +int do_airline(struct unit *punit, int dest_x, int dest_y, int dry_run); int do_paradrop(struct unit *punit, int dest_x, int dest_y); void assign_units_to_transporter(struct unit *ptrans, int take_from_land); int move_unit(struct unit *punit, const int dest_x, const int dest_y, - int transport_units, int take_from_land, int move_cost); + int transport_units, int take_from_land, int move_cost, + int dry_run); void goto_route_execute(struct unit *punit); #endif /* FC__UNITTOOLS_H */