~ubuntu-branches/debian/squeeze/freeciv/squeeze

« back to all changes in this revision

Viewing changes to server/unittools.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2010-02-23 22:09:02 UTC
  • mfrom: (1.2.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20100223220902-kiyrmr9i4152cka5
Tags: 2.2.0-1
[ Karl Goetz ]
* Remove civserver files in /etc/ggzd/ (Closes: 523772, 517787)
* Adding ${misc:Depends} to all binary packages (lintian warnings)

[ Clint Adams ]
* New upstream version.
  - Drop data_dsc_use_bindir.diff (binary pathnames have changed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include <stdlib.h>
21
21
#include <string.h>
22
22
 
 
23
/* utility */
23
24
#include "fcintl.h"
24
25
#include "log.h"
25
26
#include "mem.h"
27
28
#include "shared.h"
28
29
#include "support.h"
29
30
 
 
31
/* common */
 
32
#include "base.h"
30
33
#include "city.h"
31
34
#include "combat.h"
32
35
#include "events.h"
40
43
#include "unit.h"
41
44
#include "unitlist.h"
42
45
 
 
46
/* aicore */
 
47
#include "path_finding.h"
 
48
#include "pf_tools.h"
 
49
 
 
50
/* ai */
 
51
#include "advdiplomacy.h"
 
52
#include "aiexplorer.h"
 
53
#include "aiferry.h"
 
54
#include "aitools.h"
 
55
#include "aiunit.h"
 
56
 
 
57
/* server */
 
58
#include "aiiface.h"
43
59
#include "barbarian.h"
44
60
#include "citytools.h"
45
61
#include "cityturn.h"
47
63
#include "gamehand.h"
48
64
#include "gotohand.h"
49
65
#include "maphand.h"
 
66
#include "notify.h"
50
67
#include "plrhand.h"
51
68
#include "script_signal.h"
52
69
#include "sernet.h"
56
73
#include "unithand.h"
57
74
#include "unittools.h"
58
75
 
59
 
#include "advdiplomacy.h"
60
 
#include "aiexplorer.h"
61
 
#include "aitools.h"
62
 
#include "aiunit.h"
63
 
 
64
76
/* We need this global variable for our sort algorithm */
65
77
static struct tile *autoattack_target;
66
78
 
246
258
     * available candidates. */
247
259
    int candidate_to_upgrade = myrand(unit_list_size(candidates));
248
260
    struct unit *punit = unit_list_get(candidates, candidate_to_upgrade);
249
 
    struct unit_type *upgrade_type
250
 
      = can_upgrade_unittype(pplayer, unit_type(punit));
251
 
 
252
 
    notify_player(pplayer, punit->tile, E_UNIT_UPGRADED,
253
 
                  _("%s was upgraded for free to %s."),
254
 
                  unit_name_translation(punit),
255
 
                  utype_name_translation(upgrade_type));
256
 
 
257
 
    /* For historical reasons some veteran status may be lost while
258
 
     * upgrading.  Note that the upgraded unit may have the NoVeteran
259
 
     * flag set. */
260
 
    if (utype_has_flag(upgrade_type, F_NO_VETERAN)) {
261
 
      punit->veteran = 0;
262
 
    } else {
263
 
      punit->veteran = MAX(punit->veteran
264
 
                           - game.info.autoupgrade_veteran_loss, 0);
265
 
    }
266
 
    assert(test_unit_upgrade(punit, TRUE) == UR_OK);
267
 
    upgrade_unit(punit, upgrade_type, TRUE);
 
261
    struct unit_type *type_from = unit_type(punit);
 
262
    struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
 
263
 
 
264
    upgrade_unit(punit, type_to, TRUE);
 
265
    notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server,
 
266
                  _("%s was upgraded for free to %s."),
 
267
                  utype_name_translation(type_from),
 
268
                  unit_link(punit));
268
269
    unit_list_unlink(candidates, punit);
269
270
    upgrades--;
270
271
  }
271
272
 
272
 
  unit_list_unlink_all(candidates);
273
273
  unit_list_free(candidates);
274
274
}
275
275
 
276
276
/***************************************************************************
277
 
  Pay the cost of supported units of one city
278
 
***************************************************************************/
279
 
void pay_for_units(struct player *pplayer, struct city *pcity)
280
 
{
281
 
  int potential_gold = 0;
282
 
 
283
 
  built_impr_iterate(pcity, pimpr) {
284
 
    if (can_city_sell_building(pcity, pimpr)) {
285
 
      potential_gold += impr_sell_gold(pimpr);
286
 
    }
287
 
  } built_impr_iterate_end;
288
 
 
289
 
  unit_list_iterate_safe(pcity->units_supported, punit) {
290
 
 
291
 
    if (pplayer->economic.gold + potential_gold < punit->upkeep[O_GOLD]) {
292
 
      /* We cannot upkeep this unit any longer and selling off city
293
 
       * improvements will not help so we will have to disband */
294
 
      assert(pplayer->economic.gold + potential_gold >= 0);
295
 
      
296
 
      notify_player(pplayer, NULL, E_UNIT_LOST,
297
 
                    _("Not enough gold to pay upkeep "
298
 
                      "for %s. Unit disbanded."),
299
 
                    unit_name_translation(punit));
300
 
      wipe_unit(punit);
301
 
    } else {
302
 
      /* Gold can get negative here as city improvements will be sold
303
 
       * afterwards to balance our budget. FIXME: Should units with gold 
304
 
       * upkeep give gold when they are disbanded? */
305
 
      pplayer->economic.gold -= punit->upkeep[O_GOLD];
306
 
    }
307
 
  } unit_list_iterate_safe_end;
308
 
}
309
 
 
310
 
/***************************************************************************
311
277
  1. Do Leonardo's Workshop upgrade if applicable.
312
278
 
313
279
  2. Restore/decrease unit hitpoints.
314
280
 
315
281
  3. Kill dead units.
316
282
 
317
 
  4. Randomly kill units on unsafe terrain or unsafe-ocean.
318
 
 
319
 
  5. Rescue airplanes by returning them to base automatically.
320
 
 
321
 
  6. Decrease fuel of planes in the air.
322
 
 
323
 
  7. Refuel planes that are in bases.
324
 
 
325
 
  8. Kill planes that are out of fuel.
 
283
  4. Rescue airplanes by returning them to base automatically.
 
284
 
 
285
  5. Decrease fuel of planes in the air.
 
286
 
 
287
  6. Refuel planes that are in bases.
 
288
 
 
289
  7. Kill planes that are out of fuel.
326
290
****************************************************************************/
327
291
void player_restore_units(struct player *pplayer)
328
292
{
337
301
    /* 3) Check that unit has hitpoints */
338
302
    if (punit->hp<=0) {
339
303
      /* This should usually only happen for heli units,
340
 
         but if any other units get 0 hp somehow, catch
341
 
         them too.  --dwp  */
342
 
      notify_player(pplayer, punit->tile, E_UNIT_LOST, 
343
 
          _("Your %s has run out of hit points."), 
344
 
          unit_name_translation(punit));
 
304
       * but if any other units get 0 hp somehow, catch
 
305
       * them too.  --dwp  */
 
306
      notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
 
307
                    _("Your %s has run out of hit points."), 
 
308
                    unit_tile_link(punit));
345
309
      wipe_unit(punit);
346
310
      continue; /* Continue iterating... */
347
311
    }
348
312
 
349
 
    /* 4) Check for units on unsafe terrains. */
350
 
    if (unit_has_type_flag(punit, F_TRIREME)) {
351
 
      /* Triremes away from coast have a chance of death. */
352
 
      /* Note if a trireme died on a TER_UNSAFE terrain, this would
353
 
       * erronously give the high seas message.  This is impossible under
354
 
       * the current rulesets. */
355
 
      int loss_chance = unit_loss_pct(pplayer, punit->tile, punit);
356
 
 
357
 
      if (myrand(100) < loss_chance) {
358
 
        notify_player(pplayer, punit->tile, E_UNIT_LOST, 
359
 
                         _("Your %s has been lost on the high seas."),
360
 
                         unit_name_translation(punit));
361
 
        wipe_unit(punit);
362
 
        continue; /* Continue iterating... */
363
 
      } else if (loss_chance > 0) {
364
 
        if (maybe_make_veteran(punit)) {
365
 
          notify_player(pplayer, punit->tile, E_UNIT_BECAME_VET,
366
 
                           _("Your %s survived on the high seas "
367
 
                           "and became more experienced!"), 
368
 
                           unit_name_translation(punit));
369
 
        }
370
 
      }
371
 
    } else if (!(is_air_unit(punit) || is_heli_unit(punit))
372
 
               && (myrand(100) < unit_loss_pct(pplayer,
373
 
                                               punit->tile, punit))) {
374
 
      /* All units may have a chance of dying if they are on TER_UNSAFE
375
 
       * terrain. */
376
 
      notify_player(pplayer, punit->tile, E_UNIT_LOST,
377
 
                       _("Your %s has been lost on unsafe terrain."),
378
 
                       unit_name_translation(punit));
379
 
      wipe_unit(punit);
380
 
      continue;                 /* Continue iterating... */
381
 
    }
382
 
 
383
 
    /* 5) Rescue planes if needed */
384
 
    if (is_air_unit(punit)) {
 
313
    /* 4) Rescue planes if needed */
 
314
    if (utype_fuel(unit_type(punit))) {
385
315
      /* Shall we emergency return home on the last vapors? */
386
316
 
387
317
      /* I think this is strongly against the spirit of client goto.
389
319
 
390
320
      if (punit->fuel <= 1
391
321
          && !is_unit_being_refueled(punit)) {
392
 
        bool carrier_found = FALSE;
393
 
 
394
 
        unit_list_iterate(punit->tile->units, carrier) {
395
 
          if ((unit_has_type_flag(carrier, F_CARRIER)
396
 
               || (unit_has_type_flag(punit, F_MISSILE)
397
 
                   && unit_has_type_flag(carrier, F_MISSILE_CARRIER)))
398
 
              && get_transporter_capacity(carrier) >
399
 
                 get_transporter_occupancy(carrier)) {
400
 
            put_unit_onto_transporter(punit, carrier);
401
 
            carrier_found = TRUE;
402
 
            break;
403
 
          }
404
 
        } unit_list_iterate_end;
405
 
       
406
 
        if (!carrier_found) {
407
 
          iterate_outward(punit->tile, punit->moves_left / SINGLE_MOVE, itr_tile) {
408
 
            if (is_airunit_refuel_point(itr_tile, unit_owner(punit),
409
 
                                        unit_type(punit), FALSE)
410
 
                &&(air_can_move_between(punit->moves_left / SINGLE_MOVE, punit->tile,
411
 
                                        itr_tile, unit_owner(punit)) >= 0)) {
 
322
        struct unit *carrier;
 
323
 
 
324
        carrier = find_transport_from_tile(punit, punit->tile);
 
325
        if (carrier) {
 
326
          put_unit_onto_transporter(punit, carrier);
 
327
        } else {
 
328
          bool alive = true;
 
329
 
 
330
          struct pf_map *pfm;
 
331
          struct pf_parameter parameter;
 
332
 
 
333
          pft_fill_unit_parameter(&parameter, punit);
 
334
          pfm = pf_map_new(&parameter);
 
335
 
 
336
          pf_map_iterate_move_costs(pfm, ptile, move_cost, TRUE) {
 
337
            if (move_cost > punit->moves_left) {
 
338
              /* Too far */
 
339
              break;
 
340
            }
 
341
 
 
342
            if (is_airunit_refuel_point(ptile, pplayer,
 
343
                                        unit_type(punit), FALSE)) {
 
344
 
 
345
              struct pf_path *path;
 
346
              int id = punit->id;
 
347
 
 
348
              /* Client orders may be running for this unit - if so
 
349
               * we free them before engaging goto. */
412
350
              free_unit_orders(punit);
413
 
              punit->goto_tile = itr_tile;
414
 
              set_unit_activity(punit, ACTIVITY_GOTO);
415
 
              (void) do_unit_goto(punit, GOTO_MOVE_ANY, FALSE);
416
 
 
417
 
              if (!is_unit_being_refueled(punit)) {
418
 
                unit_list_iterate(punit->tile->units, carrier) {
419
 
                  if ((unit_has_type_flag(carrier, F_CARRIER)
420
 
                       || (unit_has_type_flag(punit, F_MISSILE)
421
 
                           && unit_has_type_flag(carrier, F_MISSILE_CARRIER)))
422
 
                      && get_transporter_capacity(carrier) >
423
 
                         get_transporter_occupancy(carrier)) {
 
351
 
 
352
              path = pf_map_get_path(pfm, ptile);
 
353
 
 
354
              alive = ai_follow_path(punit, path, ptile);
 
355
 
 
356
              if (!alive) {
 
357
                freelog(LOG_ERROR, "rescue plane: unit %d died enroute!", id);
 
358
              } else if (!same_pos(punit->tile, ptile)) {
 
359
                  /* Enemy units probably blocked our route
 
360
                   * FIXME: We should try find alternative route around
 
361
                   * the enemy unit instead of just giving up and crashing. */
 
362
                  freelog(LOG_DEBUG,
 
363
                          "rescue plane: unit %d could not move to refuel point!",
 
364
                          punit->id);
 
365
              }
 
366
 
 
367
              if (alive) {
 
368
                /* Clear activity. Unit info will be sent in the end of
 
369
                 * the function. */
 
370
                unit_activity_handling(punit, ACTIVITY_IDLE);
 
371
                punit->goto_tile = NULL;
 
372
 
 
373
                if (!is_unit_being_refueled(punit)) {
 
374
                  carrier = find_transport_from_tile(punit, punit->tile);
 
375
                  if (carrier) {
424
376
                    put_unit_onto_transporter(punit, carrier);
425
 
                    break;
426
377
                  }
427
 
                } unit_list_iterate_end;
428
 
              }
 
378
                }
429
379
 
430
 
              notify_player(pplayer, punit->tile, E_UNIT_ORDERS, 
431
 
                            _("Your %s has returned to refuel."),
432
 
                            unit_name_translation(punit));
 
380
                notify_player(pplayer, unit_tile(punit),
 
381
                              E_UNIT_ORDERS, ftc_server,
 
382
                              _("Your %s has returned to refuel."),
 
383
                              unit_link(punit));
 
384
              }
 
385
              pf_path_destroy(path);
433
386
              break;
434
387
            }
435
 
          } iterate_outward_end;
 
388
          } pf_map_iterate_move_costs_end;
 
389
          pf_map_destroy(pfm);
 
390
 
 
391
          if (!alive) {
 
392
            /* Unit died trying to move to refuel point. */
 
393
            return;
 
394
          }
436
395
        }
437
396
      }
438
397
 
439
 
      /* 6) Update fuel */
 
398
      /* 5) Update fuel */
440
399
      punit->fuel--;
441
400
 
442
 
      /* 7) Automatically refuel air units in cities, airbases, and
 
401
      /* 6) Automatically refuel air units in cities, airbases, and
443
402
       *    transporters (carriers). */
444
403
      if (is_unit_being_refueled(punit)) {
445
 
        punit->fuel=unit_type(punit)->fuel;
 
404
        punit->fuel = utype_fuel(unit_type(punit));
446
405
      }
447
406
    }
448
407
  } unit_list_iterate_safe_end;
449
408
 
450
 
  /* 8) Check if there are air units without fuel */
 
409
  /* 7) Check if there are air units without fuel */
451
410
  unit_list_iterate_safe(pplayer->units, punit) {
452
 
    if (is_air_unit(punit) && punit->fuel <= 0
453
 
        && unit_type(punit)->fuel > 0) {
454
 
      notify_player(pplayer, punit->tile, E_UNIT_LOST, 
455
 
                       _("Your %s has run out of fuel."),
456
 
                       unit_name_translation(punit));
 
411
    if (punit->fuel <= 0 && utype_fuel(unit_type(punit))) {
 
412
      notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
 
413
                    _("Your %s has run out of fuel."),
 
414
                    unit_tile_link(punit));
457
415
      wipe_unit(punit);
458
416
    } 
459
417
  } unit_list_iterate_safe_end;
475
433
{
476
434
  bool was_lower;
477
435
  struct unit_class *class = unit_class(punit);
478
 
  struct city *pcity = tile_get_city(punit->tile);
 
436
  struct city *pcity = tile_city(punit->tile);
479
437
 
480
438
  was_lower=(punit->hp < unit_type(punit)->hp);
481
439
 
486
444
  /* Bonus recovery HP (traditionally from the United Nations) */
487
445
  punit->hp += get_unit_bonus(punit, EFT_UNIT_RECOVER);
488
446
 
489
 
  if (!pcity && !tile_has_special(punit->tile, S_AIRBASE)
 
447
  if (!pcity && !tile_has_native_base(punit->tile, unit_type(punit))
490
448
      && punit->transported_by == -1) {
491
449
    punit->hp -= unit_type(punit)->hp * class->hp_loss_pct / 100;
492
450
  }
541
499
  /* Includes barracks (100%), fortress (25%), etc. */
542
500
  hp += base * get_unit_bonus(punit, EFT_HP_REGEN) / 100;
543
501
 
544
 
  if (punit->tile->city) {
 
502
  if (tile_city(punit->tile)) {
545
503
    hp = MAX(hp, base / 3);
546
504
  }
547
505
 
560
518
  Calculate the total amount of activity performed by all units on a tile
561
519
  for a given task.
562
520
**************************************************************************/
563
 
static int total_activity (struct tile *ptile, enum unit_activity act)
 
521
static int total_activity(struct tile *ptile, enum unit_activity act)
564
522
{
565
523
  int total = 0;
566
524
 
567
525
  unit_list_iterate (ptile->units, punit)
568
 
    if (punit->activity == act)
 
526
    if (punit->activity == act) {
569
527
      total += punit->activity_count;
 
528
    }
570
529
  unit_list_iterate_end;
571
530
  return total;
572
531
}
587
546
  return total;
588
547
}
589
548
 
 
549
/**************************************************************************
 
550
  Calculate the total amount of base building activity performed by all
 
551
  units on a tile for a given base.
 
552
**************************************************************************/
 
553
static int total_activity_base(struct tile *ptile, Base_type_id base)
 
554
{
 
555
  int total = 0;
 
556
 
 
557
  unit_list_iterate (ptile->units, punit)
 
558
    if (punit->activity == ACTIVITY_BASE
 
559
        && punit->activity_base == base) {
 
560
      total += punit->activity_count;
 
561
    }
 
562
  unit_list_iterate_end;
 
563
  return total;
 
564
}
 
565
 
 
566
/**************************************************************************
 
567
  Check the total amount of activity performed by all units on a tile
 
568
  for a given task.
 
569
**************************************************************************/
 
570
static bool total_activity_done(struct tile *ptile, enum unit_activity act)
 
571
{
 
572
  return total_activity(ptile, act) >= tile_activity_time(act, ptile);
 
573
}
 
574
 
590
575
/***************************************************************************
591
576
  Maybe settler/worker gains a veteran level?
592
577
****************************************************************************/
614
599
    return;
615
600
  }
616
601
 
617
 
  notify_player(unit_owner(punit), punit->tile, E_UNIT_BECAME_VET,
 
602
  notify_player(unit_owner(punit), unit_tile(punit),
 
603
                E_UNIT_BECAME_VET, ftc_server,
618
604
                /* TRANS: Your <unit> became ... */
619
605
                _("Your %s became more experienced!"),
620
 
                unit_name_translation(punit));
 
606
                unit_link(punit));
 
607
}
 
608
 
 
609
/**************************************************************************
 
610
  Pillages base from tile
 
611
**************************************************************************/
 
612
static void unit_pillage_base(struct tile *ptile, struct base_type *pbase)
 
613
{
 
614
  if (territory_claiming_base(pbase)) {
 
615
    /* Clearing borders will take care of the vision providing
 
616
     * bases as well. */
 
617
    map_clear_border(ptile);
 
618
  } else {
 
619
    struct player *owner = tile_owner(ptile);
 
620
 
 
621
    if (pbase->vision_main_sq >= 0 && owner) {
 
622
    /* Base provides vision, but no borders. */
 
623
      map_refog_circle(owner, ptile, pbase->vision_main_sq, -1,
 
624
                       game.info.vision_reveal_tiles, V_MAIN);
 
625
    }
 
626
    if (pbase->vision_invis_sq >= 0 && owner) {
 
627
    /* Base provides vision, but no borders. */
 
628
      map_refog_circle(owner, ptile, pbase->vision_invis_sq, -1,
 
629
                       game.info.vision_reveal_tiles, V_INVIS);
 
630
    }
 
631
  }
 
632
  tile_remove_base(ptile, pbase);
621
633
}
622
634
 
623
635
/**************************************************************************
635
647
  struct tile *ptile = punit->tile;
636
648
  bool check_adjacent_units = FALSE;
637
649
  
638
 
  if (activity != ACTIVITY_IDLE && activity != ACTIVITY_FORTIFIED
639
 
      && activity != ACTIVITY_GOTO && activity != ACTIVITY_EXPLORE) {
 
650
  switch (activity) {
 
651
  case ACTIVITY_IDLE:
 
652
  case ACTIVITY_EXPLORE:
 
653
  case ACTIVITY_FORTIFIED:
 
654
  case ACTIVITY_GOTO:
 
655
  case ACTIVITY_PATROL_UNUSED:
 
656
  case ACTIVITY_UNKNOWN:
 
657
  case ACTIVITY_LAST:
640
658
    /*  We don't need the activity_count for the above */
 
659
    break;
 
660
 
 
661
  case ACTIVITY_FORTIFYING:
 
662
  case ACTIVITY_SENTRY:
 
663
    punit->activity_count += get_activity_rate_this_turn(punit);
 
664
    break;
 
665
 
 
666
  case ACTIVITY_POLLUTION:
 
667
  case ACTIVITY_ROAD:
 
668
  case ACTIVITY_MINE:
 
669
  case ACTIVITY_IRRIGATE:
 
670
  case ACTIVITY_FORTRESS:
 
671
  case ACTIVITY_RAILROAD:
 
672
  case ACTIVITY_PILLAGE:
 
673
  case ACTIVITY_TRANSFORM:
 
674
  case ACTIVITY_AIRBASE:
 
675
  case ACTIVITY_FALLOUT:
 
676
  case ACTIVITY_BASE:
641
677
    punit->activity_count += get_activity_rate_this_turn(punit);
642
678
 
643
679
    /* settler may become veteran when doing something useful */
644
 
    if (activity != ACTIVITY_FORTIFYING && activity != ACTIVITY_SENTRY
645
 
       && maybe_settler_become_veteran(punit)) {
 
680
    if (maybe_settler_become_veteran(punit)) {
646
681
      notify_unit_experience(punit);
647
682
    }
648
 
  }
 
683
    break;
 
684
  };
649
685
 
650
686
  unit_restore_movepoints(pplayer, punit);
651
687
 
652
 
  if (activity == ACTIVITY_EXPLORE) {
 
688
  switch (activity) {
 
689
  case ACTIVITY_IDLE:
 
690
  case ACTIVITY_FORTIFIED:
 
691
  case ACTIVITY_FORTRESS:
 
692
  case ACTIVITY_SENTRY:
 
693
  case ACTIVITY_GOTO:
 
694
  case ACTIVITY_UNKNOWN:
 
695
  case ACTIVITY_AIRBASE:
 
696
  case ACTIVITY_FORTIFYING:
 
697
  case ACTIVITY_PATROL_UNUSED:
 
698
  case ACTIVITY_LAST:
 
699
    /* no default, ensure all handled */
 
700
    break;
 
701
 
 
702
  case ACTIVITY_EXPLORE:
653
703
    do_explore(punit);
654
704
    return;
655
 
  }
656
705
 
657
 
  if (activity==ACTIVITY_PILLAGE) {
658
 
    if (punit->activity_target == S_LAST) { /* case for old save files */
 
706
  case ACTIVITY_PILLAGE:
 
707
    if (punit->activity_target == S_LAST
 
708
        && punit->activity_base == -1) { /* case for old save files */
659
709
      if (punit->activity_count >= 1) {
660
 
        enum tile_special_type what
661
 
          = get_preferred_pillage(get_tile_infrastructure_set(ptile, NULL));
 
710
        enum tile_special_type what;
 
711
        bv_bases bases;
 
712
 
 
713
        BV_CLR_ALL(bases);
 
714
        base_type_iterate(pbase) {
 
715
          if (tile_has_base(ptile, pbase)) {
 
716
            if (pbase->pillageable) {
 
717
              BV_SET(bases, base_index(pbase));
 
718
            }
 
719
          }
 
720
        } base_type_iterate_end;
 
721
 
 
722
        what = get_preferred_pillage(get_tile_infrastructure_set(ptile, NULL),
 
723
                                     bases);
662
724
 
663
725
        if (what != S_LAST) {
664
 
          tile_clear_special(ptile, what);
 
726
          if (what > S_LAST) {
 
727
            unit_pillage_base(ptile, base_by_number(what - S_LAST - 1));
 
728
          } else {
 
729
            tile_clear_special(ptile, what);
 
730
          }
665
731
          update_tile_knowledge(ptile);
666
732
          set_unit_activity(punit, ACTIVITY_IDLE);
667
733
          check_adjacent_units = TRUE;
675
741
                                     punit->activity_target) >= 1) {
676
742
      enum tile_special_type what_pillaged = punit->activity_target;
677
743
 
678
 
      tile_clear_special(ptile, what_pillaged);
 
744
      if (what_pillaged == S_LAST && punit->activity_base != -1) {
 
745
        unit_pillage_base(ptile, base_by_number(punit->activity_base));
 
746
      } else {
 
747
        tile_clear_special(ptile, what_pillaged);
 
748
      }
679
749
      unit_list_iterate (ptile->units, punit2) {
680
750
        if ((punit2->activity == ACTIVITY_PILLAGE) &&
681
751
            (punit2->activity_target == what_pillaged)) {
684
754
        }
685
755
      } unit_list_iterate_end;
686
756
      update_tile_knowledge(ptile);
687
 
      
688
 
      ai_incident_pillage(unit_owner(punit), tile_owner(ptile));
689
 
      
 
757
 
 
758
      call_incident(INCIDENT_PILLAGE, unit_owner(punit), tile_owner(ptile));
 
759
 
690
760
      /* Change vision if effects have changed. */
691
761
      unit_list_refresh_vision(ptile->units);
692
762
    }
693
 
  }
 
763
    break;
694
764
 
695
 
  if (activity == ACTIVITY_POLLUTION) {
696
 
    if (total_activity(ptile, ACTIVITY_POLLUTION)
697
 
        >= tile_activity_time(ACTIVITY_POLLUTION, ptile)) {
 
765
  case ACTIVITY_POLLUTION:
 
766
    if (total_activity_done(ptile, ACTIVITY_POLLUTION)) {
698
767
      tile_clear_special(ptile, S_POLLUTION);
699
768
      unit_activity_done = TRUE;
700
769
    }
701
 
  }
 
770
    break;
702
771
 
703
 
  if (activity == ACTIVITY_FALLOUT) {
704
 
    if (total_activity(ptile, ACTIVITY_FALLOUT)
705
 
        >= tile_activity_time(ACTIVITY_FALLOUT, ptile)) {
 
772
  case ACTIVITY_FALLOUT:
 
773
    if (total_activity_done(ptile, ACTIVITY_FALLOUT)) {
706
774
      tile_clear_special(ptile, S_FALLOUT);
707
775
      unit_activity_done = TRUE;
708
776
    }
709
 
  }
710
 
 
711
 
  if (activity == ACTIVITY_FORTRESS) {
712
 
    if (total_activity (ptile, ACTIVITY_FORTRESS)
713
 
        >= tile_activity_time(ACTIVITY_FORTRESS, ptile)) {
714
 
      tile_set_special(ptile, S_FORTRESS);
715
 
      map_claim_ownership(ptile, unit_owner(punit), ptile);
716
 
      unit_activity_done = TRUE;
717
 
 
718
 
      /* watchtower becomes effective
719
 
       * FIXME: Reqs on other specials will not be updated immediately. */
720
 
      unit_list_refresh_vision(ptile->units);
721
 
    }
722
 
  }
723
 
 
724
 
  if (activity == ACTIVITY_AIRBASE) {
725
 
    if (total_activity (ptile, ACTIVITY_AIRBASE)
726
 
        >= tile_activity_time(ACTIVITY_AIRBASE, ptile)) {
727
 
      tile_set_special(ptile, S_AIRBASE);
728
 
      unit_activity_done = TRUE;
729
 
    }
730
 
  }
731
 
  
732
 
  if (activity == ACTIVITY_IRRIGATE) {
733
 
    if (total_activity (ptile, ACTIVITY_IRRIGATE)
734
 
        >= tile_activity_time(ACTIVITY_IRRIGATE, ptile)) {
735
 
      struct terrain *old = tile_get_terrain(ptile);
 
777
    break;
 
778
 
 
779
  case ACTIVITY_BASE:
 
780
    if (total_activity_base(ptile, punit->activity_base)
 
781
        >= tile_activity_base_time(ptile, punit->activity_base)) {
 
782
      struct base_type *new_base = base_by_number(punit->activity_base);
 
783
 
 
784
      create_base(ptile, new_base, unit_owner(punit));
 
785
 
 
786
      unit_activity_done = TRUE;
 
787
    }
 
788
    break;
 
789
 
 
790
  case ACTIVITY_IRRIGATE:
 
791
    if (total_activity_done(ptile, ACTIVITY_IRRIGATE)) {
 
792
      struct terrain *old = tile_terrain(ptile);
736
793
 
737
794
      tile_apply_activity(ptile, ACTIVITY_IRRIGATE);
738
795
      check_terrain_change(ptile, old);
739
796
      unit_activity_done = TRUE;
740
797
    }
741
 
  }
742
 
 
743
 
  if (activity == ACTIVITY_ROAD) {
 
798
    break;
 
799
 
 
800
  case ACTIVITY_MINE:
 
801
  case ACTIVITY_TRANSFORM:
 
802
    if (total_activity_done(ptile, activity)) {
 
803
      struct terrain *old = tile_terrain(ptile);
 
804
 
 
805
      tile_apply_activity(ptile, activity);
 
806
      check_terrain_change(ptile, old);
 
807
      unit_activity_done = TRUE;
 
808
      check_adjacent_units = TRUE;
 
809
    }
 
810
    break;
 
811
 
 
812
  case ACTIVITY_ROAD:
744
813
    if (total_activity (ptile, ACTIVITY_ROAD)
745
814
        + total_activity (ptile, ACTIVITY_RAILROAD)
746
815
        >= tile_activity_time(ACTIVITY_ROAD, ptile)) {
747
816
      tile_set_special(ptile, S_ROAD);
748
817
      unit_activity_done = TRUE;
749
818
    }
750
 
  }
 
819
    break;
751
820
 
752
 
  if (activity == ACTIVITY_RAILROAD) {
753
 
    if (total_activity (ptile, ACTIVITY_RAILROAD)
754
 
        >= tile_activity_time(ACTIVITY_RAILROAD, ptile)) {
 
821
  case ACTIVITY_RAILROAD:
 
822
    if (total_activity_done(ptile, ACTIVITY_RAILROAD)) {
755
823
      tile_set_special(ptile, S_RAILROAD);
756
824
      unit_activity_done = TRUE;
757
825
    }
758
 
  }
759
 
  
760
 
  if (activity == ACTIVITY_MINE) {
761
 
    if (total_activity (ptile, ACTIVITY_MINE)
762
 
        >= tile_activity_time(ACTIVITY_MINE, ptile)) {
763
 
      struct terrain *old = tile_get_terrain(ptile);
764
 
 
765
 
      tile_apply_activity(ptile, ACTIVITY_MINE);
766
 
      check_terrain_change(ptile, old);
767
 
      unit_activity_done = TRUE;
768
 
      check_adjacent_units = TRUE;
769
 
    }
770
 
  }
771
 
 
772
 
  if (activity == ACTIVITY_TRANSFORM) {
773
 
    if (total_activity (ptile, ACTIVITY_TRANSFORM)
774
 
        >= tile_activity_time(ACTIVITY_TRANSFORM, ptile)) {
775
 
      struct terrain *old = tile_get_terrain(ptile);
776
 
 
777
 
      tile_apply_activity(ptile, ACTIVITY_TRANSFORM);
778
 
      check_terrain_change(ptile, old);
779
 
      unit_activity_done = TRUE;
780
 
      check_adjacent_units = TRUE;
781
 
    }
782
 
  }
 
826
    break;
 
827
  };
783
828
 
784
829
  if (unit_activity_done) {
785
830
    update_tile_knowledge(ptile);
796
841
    adjc_iterate(ptile, ptile2) {
797
842
      unit_list_iterate(ptile2->units, punit2) {
798
843
        if (!can_unit_continue_current_activity(punit2)) {
799
 
          handle_unit_activity_request(punit2, ACTIVITY_IDLE);
 
844
          unit_activity_handling(punit2, ACTIVITY_IDLE);
800
845
        }
801
846
      } unit_list_iterate_end;
802
847
    } adjc_iterate_end;
803
848
  }
804
849
 
805
 
  if (activity==ACTIVITY_FORTIFYING) {
 
850
  if (activity == ACTIVITY_FORTIFYING) {
806
851
    if (punit->activity_count >= 1) {
807
852
      set_unit_activity(punit,ACTIVITY_FORTIFIED);
808
853
    }
822
867
  unit_list_iterate(ptile->units, punit2) {
823
868
    if (!can_unit_continue_current_activity(punit2))
824
869
    {
825
 
      handle_unit_activity_request(punit2, ACTIVITY_IDLE);
 
870
      unit_activity_handling(punit2, ACTIVITY_IDLE);
826
871
    }
827
872
  } unit_list_iterate_end;
828
873
}
864
909
                                      struct unit_type *u_type,
865
910
                                      struct tile **dst_tile)
866
911
{
 
912
  struct tile *pcenter = city_tile(pcity);
 
913
  struct player *powner = city_owner(pcity);
867
914
  int bestvalue = 0;
 
915
 
868
916
  /* coords of best tile in arg pointers */
869
 
  map_city_radius_iterate(pcity->tile, ptile) {
 
917
  city_tile_iterate(pcenter, ptile) {
870
918
    int value;
871
 
    if (is_ocean(ptile->terrain)) {
872
 
      continue;
873
 
    }
874
 
    if (tile_get_city(ptile))
875
 
      continue;
876
 
    if (unit_list_size(ptile->units) > 0)
877
 
      continue;
 
919
 
 
920
    if (is_ocean_tile(ptile)) {
 
921
      continue;
 
922
    }
 
923
 
 
924
    if (NULL != tile_city(ptile)) {
 
925
      continue;
 
926
    }
 
927
 
 
928
    if (0 < unit_list_size(ptile->units)) {
 
929
      continue;
 
930
    }
878
931
 
879
932
    /* City has not changed hands yet; see place_partisans(). */
880
 
    value = get_virtual_defense_power(NULL, u_type, city_owner(pcity),
 
933
    value = get_virtual_defense_power(NULL, u_type, powner,
881
934
                                      ptile, FALSE, 0);
882
935
    value *= 10;
883
936
 
884
 
    if (ptile->continent != tile_get_continent(pcity->tile)) {
 
937
    if (tile_continent(ptile) != tile_continent(pcenter)) {
885
938
      value /= 2;
886
939
    }
887
940
 
891
944
      *dst_tile = ptile;
892
945
      bestvalue = value;
893
946
    }
894
 
  } map_city_radius_iterate_end;
 
947
  } city_tile_iterate_end;
895
948
 
896
949
  return bestvalue > 0;
897
950
}
952
1005
{
953
1006
  int a = 0, d, db;
954
1007
  struct player *pplayer = unit_owner(punit);
955
 
  struct city *pcity = tile_get_city(ptile);
 
1008
  struct city *pcity = tile_city(ptile);
956
1009
 
957
1010
  if (pcity && pplayers_allied(city_owner(pcity), unit_owner(punit))
958
1011
      && !is_non_allied_unit_tile(ptile, pplayer)) {
961
1014
  }
962
1015
 
963
1016
  /* Calculate how well we can defend at (x,y) */
964
 
  db = 10 + tile_get_terrain(ptile)->defense_bonus / 10;
 
1017
  db = 10 + tile_terrain(ptile)->defense_bonus / 10;
965
1018
  if (tile_has_special(ptile, S_RIVER))
966
1019
    db += (db * terrain_control.river_defense_bonus) / 100;
967
1020
  d = unit_def_rating_basic_sq(punit) * db;
1005
1058
            TILE_XY(src_tile),
1006
1059
            city_name(pcity));
1007
1060
    if (verbose) {
1008
 
      notify_player(unit_owner(punit), pcity->tile, E_UNIT_RELOCATED,
1009
 
                       _("Teleported your %s to %s."),
1010
 
                       unit_name_translation(punit),
1011
 
                       city_name(pcity));
 
1061
      notify_player(unit_owner(punit), city_tile(pcity),
 
1062
                    E_UNIT_RELOCATED, ftc_server,
 
1063
                    _("Teleported your %s to %s."),
 
1064
                    unit_link(punit),
 
1065
                    city_link(pcity));
1012
1066
    }
1013
1067
 
1014
1068
    /* Silently free orders since they won't be applicable anymore. */
1016
1070
 
1017
1071
    if (move_cost == -1)
1018
1072
      move_cost = punit->moves_left;
1019
 
    return move_unit(punit, dst_tile, move_cost);
 
1073
    move_unit(punit, dst_tile, move_cost);
 
1074
    return TRUE;
1020
1075
  }
1021
1076
  return FALSE;
1022
1077
}
1044
1099
  }
1045
1100
 
1046
1101
  pplayer = unit_owner(punit);
1047
 
  punit_tile = punit->tile;
 
1102
  punit_tile = unit_tile(punit);
1048
1103
 
1049
1104
  square_iterate(punit_tile, DIST, ptile) {
1050
1105
    if (count >= ARRAY_SIZE(tiles)) {
1067
1122
 
1068
1123
    if (verbose) {
1069
1124
      /* TRANS: A unit is moved to resolve stack conflicts. */
1070
 
      notify_player(pplayer, ptile, E_UNIT_RELOCATED, _("Moved your %s."),
1071
 
                    unit_name_translation(punit));
 
1125
      notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
 
1126
                    _("Moved your %s."),
 
1127
                    unit_link(punit));
1072
1128
    }
1073
1129
    move_unit(punit, ptile, 0);
1074
1130
    return;
1077
1133
  /* Didn't find a place to bounce the unit, just disband it. */
1078
1134
  if (verbose) {
1079
1135
    /* TRANS: A unit is disbanded to resolve stack conflicts. */
1080
 
    notify_player(pplayer, punit_tile, E_UNIT_LOST,
 
1136
    notify_player(pplayer, punit_tile, E_UNIT_LOST_MISC, ftc_server,
1081
1137
                  _("Disbanded your %s."),
1082
 
                  unit_name_translation(punit));
 
1138
                  unit_tile_link(punit));
1083
1139
  }
1084
1140
  wipe_unit(punit);
1085
1141
}
1095
1151
{
1096
1152
  unit_list_iterate_safe(pplayer->units, punit) {
1097
1153
    struct tile *ptile = punit->tile;
1098
 
    struct city *pcity = tile_get_city(ptile);
 
1154
    struct city *pcity = tile_city(ptile);
1099
1155
 
1100
1156
    if (NULL != pcity && !pplayers_allied(city_owner(pcity), pplayer)) {
1101
1157
      bounce_unit(punit, verbose);
1187
1243
bool is_unit_being_refueled(const struct unit *punit)
1188
1244
{
1189
1245
  return (punit->transported_by != -1                   /* Carrier */
1190
 
          || punit->tile->city                          /* City    */
1191
 
          || tile_has_special(punit->tile, S_AIRBASE)); /* Airbase */
 
1246
          || tile_city(punit->tile)                 /* City    */
 
1247
          || tile_has_native_base(punit->tile,
 
1248
                                  unit_type(punit))); /* Airbase */
1192
1249
}
1193
1250
 
1194
1251
/**************************************************************************
1198
1255
                             const struct unit_type *type,
1199
1256
                             bool unit_is_on_carrier)
1200
1257
{
 
1258
  int cap;
1201
1259
  struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1202
1260
 
1203
 
  if ((is_allied_city_tile(ptile, pplayer)
1204
 
       && !is_non_allied_unit_tile(ptile, pplayer))
1205
 
      || (contains_special(plrtile->special, S_AIRBASE)
1206
 
          && !is_non_allied_unit_tile(ptile, pplayer)))
1207
 
    return TRUE;
1208
 
 
1209
 
  if (utype_has_flag(type, F_MISSILE)) {
1210
 
    int cap = missile_carrier_capacity(ptile, pplayer);
1211
 
    if (unit_is_on_carrier)
1212
 
      cap++;
1213
 
    return cap>0;
1214
 
  } else {
1215
 
    int cap = airunit_carrier_capacity(ptile, pplayer);
1216
 
    if (unit_is_on_carrier)
1217
 
      cap++;
1218
 
    return cap>0;
1219
 
  }
 
1261
  if (!is_non_allied_unit_tile(ptile, pplayer)) {
 
1262
    if (is_allied_city_tile(ptile, pplayer)) {
 
1263
      return TRUE;
 
1264
    }
 
1265
 
 
1266
    base_type_iterate(pbase) {
 
1267
      if (BV_ISSET(plrtile->bases, base_index(pbase))
 
1268
          && is_native_base_to_utype(pbase, type)) {
 
1269
        return TRUE;
 
1270
      }
 
1271
    } base_type_iterate_end;
 
1272
  }
 
1273
 
 
1274
  cap = unit_class_transporter_capacity(ptile, pplayer, utype_class(type));
 
1275
 
 
1276
  if (unit_is_on_carrier) {
 
1277
    cap++;
 
1278
  }
 
1279
 
 
1280
  return cap > 0;
1220
1281
}
1221
1282
 
1222
1283
/**************************************************************************
1251
1312
  punit->hp = MAX(punit->hp * unit_type(punit)->hp / old_hp, 1);
1252
1313
  punit->moves_left = punit->moves_left * unit_move_rate(punit) / old_mr;
1253
1314
 
 
1315
  if (utype_has_flag(to_unit, F_NO_VETERAN)) {
 
1316
    punit->veteran = 0;
 
1317
  } else if (is_free) {
 
1318
    punit->veteran = MAX(punit->veteran
 
1319
                         - game.info.autoupgrade_veteran_loss, 0);
 
1320
  } else {
 
1321
    punit->veteran = MAX(punit->veteran
 
1322
                         - game.info.upgrade_veteran_loss, 0);
 
1323
  }
 
1324
 
 
1325
  /* update unit upkeep */
 
1326
  city_units_upkeep(game_find_city_by_number(punit->homecity));
 
1327
 
1254
1328
  conn_list_do_buffer(pplayer->connections);
1255
1329
 
1256
1330
  unit_refresh_vision(punit);
1284
1358
  struct city *pcity;
1285
1359
 
1286
1360
  /* Register unit */
1287
 
  punit->id = get_next_id_number();
 
1361
  punit->id = identity_number();
1288
1362
  idex_register_unit(punit);
1289
1363
 
1290
1364
  assert(ptile != NULL);
1310
1384
  if (ptrans) {
1311
1385
    /* Set transporter for unit. */
1312
1386
    punit->transported_by = ptrans->id;
 
1387
  } else {
 
1388
    assert(!ptile || can_unit_exist_at_tile(punit, ptile));
1313
1389
  }
1314
1390
 
1315
1391
  /* Assume that if moves_left < 0 then the unit is "fresh",
1328
1404
    send_city_info(pplayer, pcity);
1329
1405
  }
1330
1406
 
1331
 
  punit->server.vision = vision_new(pplayer, ptile, TRUE);
 
1407
  punit->server.vision = vision_new(pplayer, ptile);
1332
1408
  unit_refresh_vision(punit);
1333
1409
 
1334
1410
  send_unit_info(NULL, punit);
1335
1411
  maybe_make_contact(ptile, unit_owner(punit));
1336
1412
  wakeup_neighbor_sentries(punit);
1337
1413
 
 
1414
  /* update unit upkeep */
 
1415
  city_units_upkeep(game_find_city_by_number(homecity_id));
 
1416
 
1338
1417
  /* The unit may have changed the available tiles in nearby cities. */
1339
 
  map_city_radius_iterate(ptile, ptile1) {
1340
 
    struct city *acity = tile_get_city(ptile1);
1341
 
 
1342
 
    if (acity) {
1343
 
      update_city_tile_status_map(acity, ptile);
1344
 
    }
1345
 
  } map_city_radius_iterate_end;
1346
 
 
 
1418
  city_map_update_tile_now(ptile);
1347
1419
  sync_cities();
1348
1420
 
 
1421
  /* Initialize aiferry stuff for new unit */
 
1422
  aiferry_init_ferry(punit);
 
1423
 
1349
1424
  return punit;
1350
1425
}
1351
1426
 
1355
1430
**************************************************************************/
1356
1431
static void server_remove_unit(struct unit *punit)
1357
1432
{
1358
 
  struct city *pcity = tile_get_city(punit->tile);
 
1433
  struct tile *ptile = punit->tile;
 
1434
  struct city *pcity = tile_city(ptile);
1359
1435
  struct city *phomecity = game_find_city_by_number(punit->homecity);
1360
 
  struct tile *unit_tile = punit->tile;
1361
1436
  struct unit *ptrans;
1362
1437
 
1363
1438
#ifdef DEBUG
1364
 
  unit_list_iterate(punit->tile->units, pcargo) {
 
1439
  unit_list_iterate(ptile->units, pcargo) {
1365
1440
    assert(pcargo->transported_by != punit->id);
1366
1441
  } unit_list_iterate_end;
1367
1442
#endif
1368
1443
 
 
1444
  if (-1 != punit->transported_by) {
 
1445
    ptrans = game_find_unit_by_number(punit->transported_by);
 
1446
  } else {
 
1447
    ptrans = NULL;
 
1448
  }
 
1449
 
1369
1450
  /* Since settlers plot in new cities in the minimap before they
1370
1451
     are built, so that no two settlers head towards the same city
1371
1452
     spot, we need to ensure this reservation is cleared should
1374
1455
    ai_unit_new_role(punit, AIUNIT_NONE, NULL);
1375
1456
  }
1376
1457
 
1377
 
  if (-1 != punit->transported_by) {
1378
 
    ptrans = game_find_unit_by_number(punit->transported_by);
1379
 
  } else {
1380
 
    ptrans = NULL;
1381
 
  }
1382
 
 
1383
1458
  conn_list_iterate(game.est_connections, pconn) {
1384
 
    if ((!pconn->player && pconn->observer)
1385
 
        || (pconn->player 
1386
 
            && map_is_known_and_seen(punit->tile, pconn->player, V_MAIN))) {
 
1459
    if ((NULL == pconn->playing && pconn->observer)
 
1460
        || (NULL != pconn->playing
 
1461
            && map_is_known_and_seen(ptile, pconn->playing, V_MAIN))) {
1387
1462
      /* FIXME: this sends the remove packet to all players, even those who
1388
1463
       * can't see the unit.  This potentially allows some limited cheating.
1389
1464
       * However fixing it requires changes elsewhere since sometimes the
1405
1480
 
1406
1481
  /* check if this unit had F_GAMELOSS flag */
1407
1482
  if (unit_has_type_flag(punit, F_GAMELOSS) && unit_owner(punit)->is_alive) {
1408
 
    notify_conn(game.est_connections, punit->tile, E_UNIT_LOST,
1409
 
                   _("Unable to defend %s, %s has lost the game."),
1410
 
                   unit_name_translation(punit),
1411
 
                   player_name(unit_owner(punit)));
1412
 
    notify_player(unit_owner(punit), punit->tile, E_GAME_END,
1413
 
                  _("Losing %s meant losing the game! "
 
1483
    notify_conn(game.est_connections, ptile, E_UNIT_LOST_MISC, ftc_server,
 
1484
                _("Unable to defend %s, %s has lost the game."),
 
1485
                unit_link(punit),
 
1486
                player_name(unit_owner(punit)));
 
1487
    notify_player(unit_owner(punit), ptile, E_GAME_END, ftc_server,
 
1488
                  _("Losing %s meant losing the game! "
1414
1489
                  "Be more careful next time!"),
1415
 
                  unit_name_translation(punit));
 
1490
                  unit_link(punit));
1416
1491
    unit_owner(punit)->is_dying = TRUE;
1417
1492
  }
1418
1493
 
1425
1500
  }
1426
1501
 
1427
1502
  /* This unit may have blocked tiles of adjacent cities. Update them. */
1428
 
  map_city_radius_iterate(unit_tile, ptile1) {
1429
 
    struct city *pcity = tile_get_city(ptile1);
1430
 
    if (pcity) {
1431
 
      update_city_tile_status_map(pcity, unit_tile);
1432
 
    }
1433
 
  } map_city_radius_iterate_end;
 
1503
  city_map_update_tile_now(ptile);
1434
1504
  sync_cities();
1435
1505
 
1436
1506
  if (phomecity) {
1437
1507
    city_refresh(phomecity);
1438
1508
    send_city_info(city_owner(phomecity), phomecity);
1439
1509
  }
 
1510
 
1440
1511
  if (pcity && pcity != phomecity) {
1441
1512
    city_refresh(pcity);
1442
1513
    send_city_info(city_owner(pcity), pcity);
1443
1514
  }
1444
 
  if (pcity && unit_list_size(unit_tile->units) == 0) {
 
1515
 
 
1516
  if (pcity && unit_list_size(ptile->units) == 0) {
1445
1517
    /* The last unit in the city was killed: update the occupied flag. */
1446
1518
    send_city_info(NULL, pcity);
1447
1519
  }
1448
1520
}
1449
1521
 
1450
1522
/**************************************************************************
 
1523
  Handle units destroyed when their transport is destroyed
 
1524
**************************************************************************/
 
1525
static void unit_lost_with_transport(const struct player *pplayer,
 
1526
                                     struct unit *pcargo,
 
1527
                                     struct unit_type *ptransport)
 
1528
{
 
1529
  notify_player(pplayer, unit_tile(pcargo), E_UNIT_LOST_MISC, ftc_server,
 
1530
                _("%s lost when %s was lost."),
 
1531
                unit_tile_link(pcargo),
 
1532
                utype_name_translation(ptransport));
 
1533
  server_remove_unit(pcargo);
 
1534
}
 
1535
 
 
1536
/**************************************************************************
1451
1537
  Remove the unit, and passengers if it is a carrying any. Remove the 
1452
1538
  _minimum_ number, eg there could be another boat on the square.
1453
1539
**************************************************************************/
1454
1540
void wipe_unit(struct unit *punit)
1455
1541
{
1456
 
  bool wipe_cargo = TRUE; /* This used to be a function parameter. */
1457
1542
  struct tile *ptile = punit->tile;
1458
1543
  struct player *pplayer = unit_owner(punit);
1459
 
  struct unit_type *putype_save = unit_type(punit);
 
1544
  struct unit_type *putype_save = unit_type(punit); /* for notify messages */
 
1545
  int drowning = 0;
 
1546
  int saved_id = punit->id;
 
1547
  int homecity_id = punit->homecity;
1460
1548
 
1461
1549
  /* First pull all units off of the transporter. */
1462
1550
  if (get_transporter_capacity(punit) > 0) {
1465
1553
        /* Could use unload_unit_from_transporter here, but that would
1466
1554
         * call send_unit_info for the transporter unnecessarily. */
1467
1555
        pull_unit_from_transporter(pcargo, punit);
 
1556
        if (!can_unit_exist_at_tile(pcargo, ptile)) {
 
1557
          drowning++;
 
1558
        }
1468
1559
        if (pcargo->activity == ACTIVITY_SENTRY) {
1469
1560
          /* Activate sentried units - like planes on a disbanded carrier.
1470
1561
           * Note this will activate ground units even if they just change
1471
1562
           * transporter. */
1472
1563
          set_unit_activity(pcargo, ACTIVITY_IDLE);
1473
1564
        }
1474
 
        send_unit_info(NULL, pcargo);
1475
 
      } 
 
1565
        if (!can_unit_exist_at_tile(pcargo, ptile)) {
 
1566
          drowning++;
 
1567
          /* No need for send_unit_info() here. Unit info will be sent
 
1568
           * when it is assigned to a new transport or it will be removed. */
 
1569
        } else {
 
1570
          send_unit_info(NULL, pcargo);
 
1571
        }
 
1572
      }
1476
1573
    } unit_list_iterate_end;
1477
1574
  }
1478
1575
 
1479
 
  /* No need to wipe the cargo unless it's a ground transporter. */
1480
 
  wipe_cargo &= is_ground_units_transport(punit);
1481
 
 
1482
 
  /* FIXME: is this the correct time to remove the unit?
1483
 
   * putype_save used to bypass this for two later notify messages
1484
 
   */
1485
 
  /* Now remove the unit. */
1486
 
  server_remove_unit(punit);
1487
 
 
1488
 
  /* Finally reassign, bounce, or destroy all ground units at this location.
1489
 
   * There's no need to worry about air units; they can fly away. */
1490
 
  if (wipe_cargo
1491
 
      && is_ocean(tile_get_terrain(ptile))
1492
 
      && !tile_get_city(ptile)) {
 
1576
  script_signal_emit("unit_lost", 2,
 
1577
                     API_TYPE_UNIT, punit,
 
1578
                     API_TYPE_PLAYER, pplayer);
 
1579
 
 
1580
  if (unit_alive(saved_id)) {
 
1581
    /* Now remove the unit. */
 
1582
    server_remove_unit(punit);
 
1583
  }
 
1584
 
 
1585
  /* update unit upkeep */
 
1586
  city_units_upkeep(game_find_city_by_number(homecity_id));
 
1587
 
 
1588
  /* Finally reassign, bounce, or destroy all units that cannot exist at this
 
1589
   * location without transport. */
 
1590
  if (drowning) {
1493
1591
    struct city *pcity = NULL;
1494
 
    int capacity = ground_unit_transporter_capacity(ptile, pplayer);
1495
 
 
1496
 
    /* Get rid of excess standard units. */
1497
 
    if (capacity < 0) {
1498
 
      unit_list_iterate_safe(ptile->units, pcargo) {
1499
 
        if (is_ground_unit(pcargo)
1500
 
            && pcargo->transported_by == -1
1501
 
            && !unit_has_type_flag(pcargo, F_UNDISBANDABLE)
1502
 
            && !unit_has_type_flag(pcargo, F_GAMELOSS)) {
1503
 
          server_remove_unit(pcargo);
1504
 
          if (++capacity >= 0) {
1505
 
            break;
1506
 
          }
1507
 
        }
1508
 
      } unit_list_iterate_safe_end;
1509
 
    }
1510
 
 
1511
 
    /* Get rid of excess undisbandable/gameloss units. */
1512
 
    if (capacity < 0) {
1513
 
      unit_list_iterate_safe(ptile->units, pcargo) {
1514
 
        if (is_ground_unit(pcargo) && pcargo->transported_by == -1) {
 
1592
 
 
1593
    /* First save undisbandable and gameloss units */
 
1594
    unit_list_iterate_safe(ptile->units, pcargo) {
 
1595
      if (pcargo->transported_by == -1
 
1596
          && !can_unit_exist_at_tile(pcargo, ptile)
 
1597
          && (unit_has_type_flag(pcargo, F_UNDISBANDABLE)
 
1598
           || unit_has_type_flag(pcargo, F_GAMELOSS))) {
 
1599
        struct unit *ptransport = find_transport_from_tile(pcargo, ptile);
 
1600
        if (ptransport != NULL) {
 
1601
          put_unit_onto_transporter(pcargo, ptransport);
 
1602
          send_unit_info(NULL, pcargo);
 
1603
        } else {
1515
1604
          if (unit_has_type_flag(pcargo, F_UNDISBANDABLE)) {
1516
1605
            pcity = find_closest_owned_city(unit_owner(pcargo),
1517
1606
                                            pcargo->tile, TRUE, NULL);
1518
1607
            if (pcity && teleport_unit_to_city(pcargo, pcity, 0, FALSE)) {
1519
 
              notify_player(pplayer, ptile, E_UNIT_RELOCATED,
 
1608
              notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1520
1609
                            _("%s escaped the destruction of %s, and "
1521
1610
                              "fled to %s."),
1522
 
                            unit_name_translation(pcargo),
 
1611
                            unit_link(pcargo),
1523
1612
                            utype_name_translation(putype_save),
1524
 
                            city_name(pcity));
 
1613
                            city_link(pcity));
1525
1614
            }
1526
 
          }
1527
 
          if (!unit_has_type_flag(pcargo, F_UNDISBANDABLE) || !pcity) {
1528
 
            notify_player(pplayer, ptile, E_UNIT_LOST,
1529
 
                             _("%s lost when %s was lost."),
1530
 
                             unit_name_translation(pcargo),
1531
 
                             utype_name_translation(putype_save));
1532
 
            server_remove_unit(pcargo);
1533
 
          }
1534
 
          if (++capacity >= 0) {
1535
 
            break;
1536
 
          }
1537
 
        }
1538
 
      } unit_list_iterate_safe_end;
1539
 
    }
1540
 
 
1541
 
    /* Reassign existing units.  This is an O(n^2) operation as written. */
1542
 
    unit_list_iterate(ptile->units, ptrans) {
1543
 
      if (is_ground_units_transport(ptrans)) {
1544
 
        int occupancy = get_transporter_occupancy(ptrans);
1545
 
 
1546
 
        unit_list_iterate(ptile->units, pcargo) {
1547
 
          if (occupancy >= get_transporter_capacity(ptrans)) {
1548
 
            break;
1549
 
          }
1550
 
          if (is_ground_unit(pcargo) && pcargo->transported_by == -1) {
1551
 
            put_unit_onto_transporter(pcargo, ptrans);
1552
 
            occupancy++;
1553
 
          }
1554
 
        } unit_list_iterate_end;
1555
 
      }
1556
 
    } unit_list_iterate_end;
 
1615
          }
 
1616
          if (!unit_has_type_flag(pcargo, F_UNDISBANDABLE) || !pcity) {
 
1617
            unit_lost_with_transport(pplayer, pcargo, putype_save);
 
1618
          }
 
1619
        }
 
1620
 
 
1621
        drowning--;
 
1622
        if (!drowning) {
 
1623
          break;
 
1624
        }
 
1625
      }
 
1626
    } unit_list_iterate_safe_end;
 
1627
  }
 
1628
 
 
1629
  /* Then other units */
 
1630
  if (drowning) {
 
1631
    unit_list_iterate_safe(ptile->units, pcargo) {
 
1632
      if (pcargo->transported_by == -1
 
1633
          && !can_unit_exist_at_tile(pcargo, ptile)) {
 
1634
        struct unit *ptransport = find_transport_from_tile(pcargo, ptile);
 
1635
 
 
1636
        if (ptransport != NULL) {
 
1637
          put_unit_onto_transporter(pcargo, ptransport);
 
1638
          send_unit_info(NULL, pcargo);
 
1639
        } else {
 
1640
          unit_lost_with_transport(pplayer, pcargo, putype_save);
 
1641
        }
 
1642
 
 
1643
        drowning--;
 
1644
        if (!drowning) {
 
1645
          break;
 
1646
        }
 
1647
      }
 
1648
    } unit_list_iterate_safe_end;
1557
1649
  }
1558
1650
}
1559
1651
 
1564
1656
**************************************************************************/
1565
1657
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
1566
1658
{
 
1659
  char pkiller_link[MAX_LEN_LINK], punit_link[MAX_LEN_LINK];
1567
1660
  struct player *pvictim = unit_owner(punit);
1568
1661
  struct player *pvictor = unit_owner(pkiller);
1569
1662
  int ransom, unitcount = 0;
1570
 
  
 
1663
 
 
1664
  sz_strlcpy(pkiller_link, unit_link(pkiller));
 
1665
  sz_strlcpy(punit_link, unit_tile_link(punit));
 
1666
 
1571
1667
  /* barbarian leader ransom hack */
1572
1668
  if( is_barbarian(pvictim) && unit_has_type_role(punit, L_BARBARIAN_LEADER)
1573
1669
      && (unit_list_size(punit->tile->units) == 1)
1574
 
      && (is_ground_unit(pkiller) || is_heli_unit(pkiller)) ) {
 
1670
      && uclass_has_flag(unit_class(pkiller), UCF_COLLECT_RANSOM)) {
 
1671
    /* Occupying units can collect ransom if leader is alone in the tile */
1575
1672
    ransom = (pvictim->economic.gold >= game.info.ransom_gold) 
1576
1673
             ? game.info.ransom_gold : pvictim->economic.gold;
1577
 
    notify_player(pvictor, pkiller->tile, E_UNIT_WIN_ATT,
1578
 
                     _("Barbarian leader captured, %d gold ransom paid."),
1579
 
                     ransom);
 
1674
    notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
 
1675
                  _("Barbarian leader captured, %d gold ransom paid."),
 
1676
                  ransom);
1580
1677
    pvictor->economic.gold += ransom;
1581
1678
    pvictim->economic.gold -= ransom;
1582
1679
    send_player_info(pvictor, NULL);   /* let me see my new gold :-) */
1591
1688
  }
1592
1689
 
1593
1690
  if (!is_stack_vulnerable(punit->tile) || unitcount == 1) {
1594
 
    notify_player(pvictor, pkiller->tile, E_UNIT_WIN_ATT,
1595
 
                  /* TRANS: "... Cannon ... the Polish Destroyer." */
1596
 
                  _("Your attacking %s succeeded against the %s %s!"),
1597
 
                  unit_name_translation(pkiller),
1598
 
                  nation_adjective_for_player(pvictim),
1599
 
                  unit_name_translation(punit));
 
1691
    notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
 
1692
                  /* TRANS: "... Cannon ... the Polish Destroyer." */
 
1693
                  _("Your attacking %s succeeded against the %s %s!"),
 
1694
                  pkiller_link,
 
1695
                  nation_adjective_for_player(pvictim),
 
1696
                  punit_link);
1600
1697
    if (vet) {
1601
1698
      notify_unit_experience(pkiller);
1602
1699
    }
1603
 
    notify_player(pvictim, punit->tile, E_UNIT_LOST,
1604
 
                  /* TRANS: "Cannon ... the Polish Destroyer." */
1605
 
                  _("%s lost to an attack by the %s %s."),
1606
 
                  unit_name_translation(punit),
1607
 
                  nation_adjective_for_player(pvictor),
1608
 
                  unit_name_translation(pkiller));
 
1700
    notify_player(pvictim, unit_tile(punit), E_UNIT_LOST_DEF, ftc_server,
 
1701
                  /* TRANS: "Cannon ... the Polish Destroyer." */
 
1702
                  _("%s lost to an attack by the %s %s."),
 
1703
                  punit_link,
 
1704
                  nation_adjective_for_player(pvictor),
 
1705
                  pkiller_link);
1609
1706
 
1610
1707
    wipe_unit(punit);
1611
1708
  } else { /* unitcount > 1 */
1634
1731
    } unit_list_iterate_end;
1635
1732
 
1636
1733
    /* Inform the destroyer: lots of different cases here! */
1637
 
    notify_player(pvictor, pkiller->tile, E_UNIT_WIN_ATT,
1638
 
                  /* TRANS: "... Cannon ... the Polish Destroyer ...." */
1639
 
                  PL_("Your attacking %s succeeded against the %s %s "
1640
 
                      "(and %d other unit)!",
1641
 
                      "Your attacking %s succeeded against the %s %s "
1642
 
                      "(and %d other units)!", unitcount - 1),
1643
 
                  unit_name_translation(pkiller),
1644
 
                  nation_adjective_for_player(pvictim),
1645
 
                  unit_name_translation(punit),
1646
 
                  unitcount - 1);
 
1734
    notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
 
1735
                  /* TRANS: "... Cannon ... the Polish Destroyer ...." */
 
1736
                  PL_("Your attacking %s succeeded against the %s %s "
 
1737
                      "(and %d other unit)!",
 
1738
                      "Your attacking %s succeeded against the %s %s "
 
1739
                      "(and %d other units)!", unitcount - 1),
 
1740
                  pkiller_link,
 
1741
                  nation_adjective_for_player(pvictim),
 
1742
                  punit_link,
 
1743
                  unitcount - 1);
1647
1744
    if (vet) {
1648
1745
      notify_unit_experience(pkiller);
1649
1746
    }
1654
1751
     *
1655
1752
     * Also if a large number of units die you don't find out what type
1656
1753
     * they all are. */
1657
 
    for (i = 0; i<MAX_NUM_PLAYERS+MAX_NUM_BARBARIANS; i++) {
 
1754
    for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
1658
1755
      if (num_killed[i] == 1) {
1659
 
        if (i == player_index(pvictim)) {
1660
 
          assert(other_killed[i] == NULL);
1661
 
          notify_player(player_by_number(i), punit->tile, E_UNIT_LOST,
1662
 
                        /* TRANS: "Cannon ... the Polish Destroyer." */
1663
 
                        _("%s lost to an attack by the %s %s."),
1664
 
                        unit_name_translation(punit),
1665
 
                        nation_adjective_for_player(pvictor),
1666
 
                        unit_name_translation(pkiller));
1667
 
        } else {
1668
 
          assert(other_killed[i] != punit);
1669
 
          notify_player(player_by_number(i), punit->tile, E_UNIT_LOST,
1670
 
                        /* TRANS: "Cannon lost when the Polish Destroyer
1671
 
                         * attacked the German Musketeers." */
1672
 
                        _("%s lost when the %s %s attacked the %s %s."),
1673
 
                        unit_name_translation(other_killed[i]),
1674
 
                        nation_adjective_for_player(pvictor),
1675
 
                        unit_name_translation(pkiller),
1676
 
                        nation_adjective_for_player(pvictim),
1677
 
                        unit_name_translation(punit));
1678
 
        }
 
1756
        if (i == player_index(pvictim)) {
 
1757
          assert(other_killed[i] == NULL);
 
1758
          notify_player(player_by_number(i), unit_tile(punit),
 
1759
                        E_UNIT_LOST_DEF, ftc_server,
 
1760
                        /* TRANS: "Cannon ... the Polish Destroyer." */
 
1761
                        _("%s lost to an attack by the %s %s."),
 
1762
                        punit_link,
 
1763
                        nation_adjective_for_player(pvictor),
 
1764
                        pkiller_link);
 
1765
        } else {
 
1766
          assert(other_killed[i] != punit);
 
1767
          notify_player(player_by_number(i), unit_tile(punit),
 
1768
                        E_UNIT_LOST_DEF, ftc_server,
 
1769
                        /* TRANS: "Cannon lost when the Polish Destroyer
 
1770
                         * attacked the German Musketeers." */
 
1771
                        _("%s lost when the %s %s attacked the %s %s."),
 
1772
                        unit_link(other_killed[i]),
 
1773
                        nation_adjective_for_player(pvictor),
 
1774
                        pkiller_link,
 
1775
                        nation_adjective_for_player(pvictim),
 
1776
                        punit_link);
 
1777
        }
1679
1778
      } else if (num_killed[i] > 1) {
1680
 
        if (i == player_index(pvictim)) {
1681
 
          int others = num_killed[i] - 1;
 
1779
        if (i == player_index(pvictim)) {
 
1780
          int others = num_killed[i] - 1;
1682
1781
 
1683
 
          if (others == 1) {
1684
 
            notify_player(player_by_number(i), punit->tile, E_UNIT_LOST,
1685
 
                          /* TRANS: "Musketeers (and Cannon) lost to an
1686
 
                           * attack from the Polish Destroyer." */
1687
 
                          _("%s (and %s) lost to an attack from the %s %s."),
1688
 
                          unit_name_translation(punit),
1689
 
                          unit_name_translation(other_killed[i]),
1690
 
                          nation_adjective_for_player(pvictor),
1691
 
                          unit_name_translation(pkiller));
1692
 
          } else {
1693
 
            notify_player(player_by_number(i), punit->tile, E_UNIT_LOST,
1694
 
                          /* TRANS: "Musketeers and 3 other units lost to
1695
 
                           * an attack from the Polish Destroyer."
1696
 
                           * (only happens with at least 2 other units) */
1697
 
                          PL_("%s and %d other unit lost to an attack "
1698
 
                              "from the %s %s.",
1699
 
                              "%s and %d other units lost to an attack "
1700
 
                              "from the %s %s.", others),
1701
 
                          unit_name_translation(punit),
1702
 
                          others,
1703
 
                          nation_adjective_for_player(pvictor),
1704
 
                          unit_name_translation(pkiller));
1705
 
          }
1706
 
        } else {
1707
 
          notify_player(player_by_number(i), punit->tile, E_UNIT_LOST,
1708
 
                        /* TRANS: "2 units lost when the Polish Destroyer
1709
 
                         * attacked the German Musketeers."
1710
 
                         * (only happens with at least 2 other units) */
1711
 
                        PL_("%d unit lost when the %s %s attacked the %s %s.",
1712
 
                            "%d units lost when the %s %s attacked the %s %s.",
1713
 
                            num_killed[i]),
1714
 
                        num_killed[i],
1715
 
                        nation_adjective_for_player(pvictor),
1716
 
                        unit_name_translation(pkiller),
1717
 
                        nation_adjective_for_player(pvictim),
1718
 
                        unit_name_translation(punit));
1719
 
        }
 
1782
          if (others == 1) {
 
1783
            notify_player(player_by_number(i), unit_tile(punit),
 
1784
                          E_UNIT_LOST_DEF, ftc_server,
 
1785
                          /* TRANS: "Musketeers (and Cannon) lost to an
 
1786
                           * attack from the Polish Destroyer." */
 
1787
                          _("%s (and %s) lost to an attack from the %s %s."),
 
1788
                          punit_link,
 
1789
                          unit_link(other_killed[i]),
 
1790
                          nation_adjective_for_player(pvictor),
 
1791
                          pkiller_link);
 
1792
          } else {
 
1793
            notify_player(player_by_number(i), unit_tile(punit),
 
1794
                          E_UNIT_LOST_DEF, ftc_server,
 
1795
                          /* TRANS: "Musketeers and 3 other units lost to
 
1796
                           * an attack from the Polish Destroyer."
 
1797
                           * (only happens with at least 2 other units) */
 
1798
                          PL_("%s and %d other unit lost to an attack "
 
1799
                              "from the %s %s.",
 
1800
                              "%s and %d other units lost to an attack "
 
1801
                              "from the %s %s.", others),
 
1802
                          punit_link,
 
1803
                          others,
 
1804
                          nation_adjective_for_player(pvictor),
 
1805
                          pkiller_link);
 
1806
          }
 
1807
        } else {
 
1808
          notify_player(player_by_number(i), unit_tile(punit),
 
1809
                        E_UNIT_LOST_DEF, ftc_server,
 
1810
                        /* TRANS: "2 units lost when the Polish Destroyer
 
1811
                         * attacked the German Musketeers."
 
1812
                         * (only happens with at least 2 other units) */
 
1813
                        PL_("%d unit lost when the %s %s attacked the %s %s.",
 
1814
                            "%d units lost when the %s %s attacked the %s %s.",
 
1815
                            num_killed[i]),
 
1816
                        num_killed[i],
 
1817
                        nation_adjective_for_player(pvictor),
 
1818
                        pkiller_link,
 
1819
                        nation_adjective_for_player(pvictim),
 
1820
                        punit_link);
 
1821
        }
1720
1822
      }
1721
1823
    }
1722
1824
 
1736
1838
void package_unit(struct unit *punit, struct packet_unit_info *packet)
1737
1839
{
1738
1840
  packet->id = punit->id;
1739
 
  packet->owner = unit_owner(punit)->player_no;
 
1841
  packet->owner = player_number(unit_owner(punit));
1740
1842
  packet->x = punit->tile->x;
1741
1843
  packet->y = punit->tile->y;
1742
1844
  packet->homecity = punit->homecity;
 
1845
  output_type_iterate(o) {
 
1846
    packet->upkeep[o] = punit->upkeep[o];
 
1847
  } output_type_iterate_end;
1743
1848
  packet->veteran = punit->veteran;
1744
 
  packet->type = unit_type(punit)->index;
 
1849
  packet->type = utype_number(unit_type(punit));
1745
1850
  packet->movesleft = punit->moves_left;
1746
1851
  packet->hp = punit->hp;
1747
1852
  packet->activity = punit->activity;
 
1853
  packet->activity_base = punit->activity_base;
1748
1854
  packet->activity_count = punit->activity_count;
1749
 
  packet->unhappiness = punit->unhappiness;
1750
 
  output_type_iterate(o) {
1751
 
    packet->upkeep[o] = punit->upkeep[o];
1752
 
  } output_type_iterate_end;
1753
1855
  packet->ai = punit->ai.control;
1754
1856
  packet->fuel = punit->fuel;
1755
1857
  if (punit->goto_tile) {
1761
1863
    assert(!is_normal_map_pos(255, 255));
1762
1864
  }
1763
1865
  packet->activity_target = punit->activity_target;
 
1866
  packet->activity_base = punit->activity_base;
1764
1867
  packet->paradropped = punit->paradropped;
1765
1868
  packet->done_moving = punit->done_moving;
1766
1869
  if (punit->transported_by == -1) {
1784
1887
      packet->orders[i] = punit->orders.list[i].order;
1785
1888
      packet->orders_dirs[i] = punit->orders.list[i].dir;
1786
1889
      packet->orders_activities[i] = punit->orders.list[i].activity;
 
1890
      packet->orders_bases[i] = punit->orders.list[i].base;
1787
1891
    }
1788
1892
  } else {
1789
1893
    packet->orders_length = packet->orders_index = 0;
1816
1920
  packet->info_city_id = info_city_id;
1817
1921
 
1818
1922
  packet->id = punit->id;
1819
 
  packet->owner = unit_owner(punit)->player_no;
 
1923
  packet->owner = player_number(unit_owner(punit));
1820
1924
  packet->x = punit->tile->x;
1821
1925
  packet->y = punit->tile->y;
1822
1926
  packet->veteran = punit->veteran;
1823
 
  packet->type = unit_type(punit)->index;
 
1927
  packet->type = utype_number(unit_type(punit));
1824
1928
  packet->hp = punit->hp;
1825
1929
  packet->occupied = (get_transporter_occupancy(punit) > 0);
1826
1930
  if (punit->activity == ACTIVITY_EXPLORE
1827
1931
      || punit->activity == ACTIVITY_GOTO) {
1828
1932
    packet->activity = ACTIVITY_IDLE;
 
1933
    packet->activity_base = -1;
1829
1934
  } else {
1830
1935
    packet->activity = punit->activity;
 
1936
    packet->activity_base = punit->activity_base;
1831
1937
  }
1832
1938
 
1833
1939
  /* Transported_by information is sent to the client even for units that
1889
1995
  package_short_unit(punit, &sinfo, UNIT_INFO_IDENTITY, FALSE, FALSE);
1890
1996
            
1891
1997
  conn_list_iterate(dest, pconn) {
1892
 
    struct player *pplayer = pconn->player;
 
1998
    struct player *pplayer = pconn->playing;
1893
1999
 
1894
2000
    /* Be careful to consider all cases where pplayer is NULL... */
1895
2001
    if ((!pplayer && pconn->observer) || pplayer == unit_owner(punit)) {
1939
2045
**************************************************************************/
1940
2046
void send_all_known_units(struct conn_list *dest)
1941
2047
{
1942
 
  int p;
1943
 
  
1944
2048
  conn_list_do_buffer(dest);
1945
2049
  conn_list_iterate(dest, pconn) {
1946
 
    struct player *pplayer = pconn->player;
1947
 
    if (!pconn->player && !pconn->observer) {
 
2050
    struct player *pplayer = pconn->playing;
 
2051
 
 
2052
    if (NULL == pplayer && !pconn->observer) {
1948
2053
      continue;
1949
2054
    }
1950
 
    for(p=0; p<game.info.nplayers; p++) { /* send the players units */
1951
 
      struct player *unitowner = &game.players[p];
 
2055
 
 
2056
    players_iterate(unitowner) {
1952
2057
      unit_list_iterate(unitowner->units, punit) {
1953
2058
        if (!pplayer || can_player_see_unit(pplayer, punit)) {
1954
2059
          send_unit_info_to_onlookers(pconn->self, punit,
1955
2060
                                      punit->tile, FALSE);
1956
2061
        }
1957
 
      }
1958
 
      unit_list_iterate_end;
1959
 
    }
 
2062
      } unit_list_iterate_end;
 
2063
    } players_iterate_end;
1960
2064
  }
1961
2065
  conn_list_iterate_end;
1962
2066
  conn_list_do_unbuffer(dest);
1972
2076
**************************************************************************/
1973
2077
static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
1974
2078
{
1975
 
  struct city *pcity = tile_get_city(ptile);
 
2079
  struct city *pcity = NULL;
1976
2080
 
1977
2081
  unit_list_iterate_safe(ptile->units, punit) {
1978
 
    notify_player(unit_owner(punit), ptile, E_UNIT_LOST,
1979
 
                  _("Your %s was nuked by %s."),
1980
 
                  unit_name_translation(punit),
1981
 
                  pplayer == unit_owner(punit)
1982
 
                  ? _("yourself")
1983
 
                  : nation_plural_for_player(pplayer));
 
2082
    notify_player(unit_owner(punit), ptile, E_UNIT_LOST_MISC, ftc_server,
 
2083
                  _("Your %s was nuked by %s."),
 
2084
                  unit_tile_link(punit),
 
2085
                  pplayer == unit_owner(punit)
 
2086
                  ? _("yourself")
 
2087
                  : nation_plural_for_player(pplayer));
1984
2088
    if (unit_owner(punit) != pplayer) {
1985
 
      notify_player(pplayer, ptile, E_UNIT_WIN,
1986
 
                    _("The %s %s was nuked."),
1987
 
                    nation_adjective_for_player(unit_owner(punit)),
1988
 
                    unit_name_translation(punit));
 
2089
      notify_player(pplayer, ptile, E_UNIT_WIN, ftc_server,
 
2090
                    _("The %s %s was nuked."),
 
2091
                    nation_adjective_for_player(unit_owner(punit)),
 
2092
                    unit_tile_link(punit));
1989
2093
    }
1990
2094
    wipe_unit(punit);
1991
2095
  } unit_list_iterate_safe_end;
1992
2096
 
 
2097
  pcity = tile_city(ptile);
 
2098
 
1993
2099
  if (pcity) {
1994
 
    notify_player(city_owner(pcity), ptile, E_CITY_NUKED,
1995
 
                  _("%s was nuked by %s."),
1996
 
                  city_name(pcity),
1997
 
                  pplayer == city_owner(pcity)
1998
 
                  ? _("yourself")
1999
 
                  : nation_plural_for_player(pplayer));
 
2100
    notify_player(city_owner(pcity), ptile, E_CITY_NUKED, ftc_server,
 
2101
                  _("%s was nuked by %s."),
 
2102
                  city_link(pcity),
 
2103
                  pplayer == city_owner(pcity)
 
2104
                  ? _("yourself")
 
2105
                  : nation_plural_for_player(pplayer));
2000
2106
 
2001
2107
    if (city_owner(pcity) != pplayer) {
2002
 
      notify_player(pplayer, ptile, E_CITY_NUKED,
2003
 
                    _("You nuked %s."),
2004
 
                    city_name(pcity));
 
2108
      notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
 
2109
                    _("You nuked %s."),
 
2110
                    city_link(pcity));
2005
2111
    }
2006
2112
 
2007
 
    city_reduce_size(pcity, pcity->size / 2);
 
2113
    city_reduce_size(pcity, pcity->size / 2, pplayer);
2008
2114
  }
2009
2115
 
2010
 
  if (!is_ocean(tile_get_terrain(ptile)) && myrand(2) == 1) {
 
2116
  if (!is_ocean_tile(ptile) && myrand(2) == 1) {
2011
2117
    if (game.info.nuke_contamination == CONTAMINATION_POLLUTION) {
2012
2118
      if (!tile_has_special(ptile, S_POLLUTION)) {
2013
2119
        tile_set_special(ptile, S_POLLUTION);
2028
2134
**************************************************************************/
2029
2135
void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
2030
2136
{
2031
 
  if (tile_owner(ptile)) {
2032
 
    ai_incident_nuclear(pplayer, tile_owner(ptile));
2033
 
  } else if (tile_get_city(ptile)) {
2034
 
    ai_incident_nuclear(pplayer, city_owner(tile_get_city(ptile)));
2035
 
  } else {
2036
 
    ai_incident_nuclear(pplayer, NULL);
2037
 
  }
 
2137
  struct player *victim = tile_owner(ptile);
 
2138
 
 
2139
  call_incident(INCIDENT_NUCLEAR, pplayer, victim);
2038
2140
 
2039
2141
  square_iterate(ptile, 1, ptile1) {
2040
2142
    do_nuke_tile(pplayer, ptile1);
2041
2143
  } square_iterate_end;
2042
2144
 
2043
 
  notify_conn(NULL, ptile, E_NUKE,
2044
 
              _("The %s detonated a nuke!"),
2045
 
              nation_plural_for_player(pplayer));
 
2145
  notify_conn(NULL, ptile, E_NUKE, ftc_server,
 
2146
              _("The %s detonated a nuke!"),
 
2147
              nation_plural_for_player(pplayer));
2046
2148
}
2047
2149
 
2048
2150
/**************************************************************************
2052
2154
bool do_airline(struct unit *punit, struct city *city2)
2053
2155
{
2054
2156
  struct tile *src_tile = punit->tile;
2055
 
  struct city *city1 = src_tile->city;
 
2157
  struct city *city1 = tile_city(src_tile);
2056
2158
 
2057
2159
  if (!city1)
2058
2160
    return FALSE;
2061
2163
  if (get_transporter_occupancy(punit) > 0) {
2062
2164
    return FALSE;
2063
2165
  }
2064
 
  city1->airlift = FALSE;
2065
 
  city2->airlift = FALSE;
2066
 
 
2067
 
  notify_player(unit_owner(punit), city2->tile, E_UNIT_RELOCATED,
2068
 
                   _("%s transported successfully."),
2069
 
                   unit_name_translation(punit));
2070
 
 
2071
 
  (void) move_unit(punit, city2->tile, punit->moves_left);
 
2166
  city1->airlift--;
 
2167
  city2->airlift--;
 
2168
 
 
2169
  notify_player(unit_owner(punit), city_tile(city2),
 
2170
                E_UNIT_RELOCATED, ftc_server,
 
2171
                _("%s transported successfully."),
 
2172
                unit_link(punit));
 
2173
 
 
2174
  move_unit(punit, city2->tile, punit->moves_left);
2072
2175
 
2073
2176
  /* airlift fields have changed. */
2074
2177
  send_city_info(city_owner(city1), city1);
2082
2185
**************************************************************************/
2083
2186
void do_explore(struct unit *punit)
2084
2187
{
2085
 
  switch (ai_manage_explorer(punit)) {
2086
 
  case MR_DEATH:
2087
 
    /* don't use punit! */
2088
 
    return;
2089
 
  case MR_OK:
2090
 
    /* FIXME: ai_manage_explorer() isn't supposed to change the activity,
2091
 
     * but don't count on this.  See PR#39792.
2092
 
     */
2093
 
    if (punit->activity == ACTIVITY_EXPLORE) {
2094
 
      break;
2095
 
    }
2096
 
    /* fallthru */
2097
 
  default:
2098
 
    handle_unit_activity_request(punit, ACTIVITY_IDLE);
2099
 
 
2100
 
    /* FIXME: When the ai_manage_explorer() call changes the activity from
2101
 
     * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2102
 
     * alone.  We reset it here.  See PR#12931. */
 
2188
  struct player *owner = unit_owner(punit);
 
2189
 
 
2190
  if (owner->ai->funcs.auto_explorer) {
 
2191
    switch (owner->ai->funcs.auto_explorer(punit)) {
 
2192
      case MR_DEATH:
 
2193
        /* don't use punit! */
 
2194
        return;
 
2195
      case MR_OK:
 
2196
        /* FIXME: ai_manage_explorer() isn't supposed to change the activity,
 
2197
         * but don't count on this.  See PR#39792.
 
2198
         */
 
2199
        if (punit->activity == ACTIVITY_EXPLORE) {
 
2200
          break;
 
2201
        }
 
2202
        /* fallthru */
 
2203
      default:
 
2204
        unit_activity_handling(punit, ACTIVITY_IDLE);
 
2205
 
 
2206
        /* FIXME: When the ai_manage_explorer() call changes the activity from
 
2207
         * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
 
2208
         * alone.  We reset it here.  See PR#12931. */
 
2209
        punit->ai.control = FALSE;
 
2210
        break;
 
2211
    };
 
2212
  } else {
 
2213
    unit_activity_handling(punit, ACTIVITY_IDLE);
2103
2214
    punit->ai.control = FALSE;
2104
 
    break;
2105
 
  };
 
2215
  }
2106
2216
  send_unit_info(NULL, punit); /* probably duplicate */
2107
2217
}
2108
2218
 
2116
2226
  struct player *pplayer = unit_owner(punit);
2117
2227
 
2118
2228
  if (!unit_has_type_flag(punit, F_PARATROOPERS)) {
2119
 
    notify_player(pplayer, punit->tile, E_BAD_COMMAND,
2120
 
                     _("This unit type can not be paradropped."));
 
2229
    notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
 
2230
                  _("This unit type can not be paradropped."));
2121
2231
    return FALSE;
2122
2232
  }
2123
2233
 
2126
2236
  }
2127
2237
 
2128
2238
  if (get_transporter_occupancy(punit) > 0) {
2129
 
    notify_player(pplayer, punit->tile, E_BAD_COMMAND,
2130
 
                     _("You cannot paradrop a unit that is "
2131
 
                       "transporting other units."));
 
2239
    notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
 
2240
                  _("You cannot paradrop a unit that is "
 
2241
                    "transporting other units."));
2132
2242
  }
2133
2243
 
2134
2244
  if (!map_is_known(ptile, pplayer)) {
2135
 
    notify_player(pplayer, ptile, E_BAD_COMMAND,
2136
 
                     _("The destination location is not known."));
 
2245
    notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
 
2246
                  _("The destination location is not known."));
2137
2247
    return FALSE;
2138
2248
  }
2139
2249
 
2140
2250
  /* Safe terrain according to player map? */
2141
 
  if (!is_native_terrain(punit, map_get_player_tile(ptile, pplayer)->terrain)) {
2142
 
    notify_player(pplayer, ptile, E_BAD_COMMAND,
2143
 
                     _("This unit cannot paradrop into %s."),
2144
 
                     terrain_name_translation(
2145
 
                        map_get_player_tile(ptile, pplayer)->terrain));
 
2251
  if (!is_native_terrain(unit_type(punit),
 
2252
                         map_get_player_tile(ptile, pplayer)->terrain,
 
2253
                         map_get_player_tile(ptile, pplayer)->special,
 
2254
                         map_get_player_tile(ptile, pplayer)->bases)) {
 
2255
    notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
 
2256
                  _("This unit cannot paradrop into %s."),
 
2257
                  terrain_name_translation(
 
2258
                      map_get_player_tile(ptile, pplayer)->terrain));
2146
2259
    return FALSE;
2147
2260
  }
2148
2261
 
2149
2262
  if (map_is_known_and_seen(ptile, pplayer, V_MAIN)
2150
 
      && ((tile_get_city(ptile)
2151
 
          && pplayers_non_attack(pplayer, city_owner(tile_get_city(ptile))))
 
2263
      && ((tile_city(ptile)
 
2264
           && pplayers_non_attack(pplayer, city_owner(tile_city(ptile))))
2152
2265
      || is_non_attack_unit_tile(ptile, pplayer))) {
2153
 
    notify_player(pplayer, ptile, E_BAD_COMMAND,
2154
 
                     _("Cannot attack unless you declare war first."));
2155
 
    return FALSE;    
 
2266
    notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
 
2267
                  _("Cannot attack unless you declare war first."));
 
2268
    return FALSE;
2156
2269
  }
2157
2270
 
2158
2271
  {
2159
2272
    int range = unit_type(punit)->paratroopers_range;
2160
2273
    int distance = real_map_distance(punit->tile, ptile);
2161
2274
    if (distance > range) {
2162
 
      notify_player(pplayer, ptile, E_BAD_COMMAND,
2163
 
                       _("The distance to the target (%i) "
2164
 
                         "is greater than the unit's range (%i)."),
2165
 
                       distance, range);
 
2275
      notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
 
2276
                    _("The distance to the target (%i) "
 
2277
                      "is greater than the unit's range (%i)."),
 
2278
                    distance, range);
2166
2279
      return FALSE;
2167
2280
    }
2168
2281
  }
2170
2283
  /* Safe terrain, really? Not transformed since player last saw it. */
2171
2284
  if (!can_unit_exist_at_tile(punit, ptile)) {
2172
2285
    map_show_circle(pplayer, ptile, unit_type(punit)->vision_radius_sq);
2173
 
    notify_player(pplayer, ptile, E_UNIT_LOST,
2174
 
                     _("Your %s paradropped into the %s "
2175
 
                       "and was lost."),
2176
 
                     unit_name_translation(punit),
2177
 
                     terrain_name_translation(ptile->terrain));
 
2286
    notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
 
2287
                  _("Your %s paradropped into the %s and was lost."),
 
2288
                  unit_tile_link(punit),
 
2289
                  terrain_name_translation(tile_terrain(ptile)));
2178
2290
    server_remove_unit(punit);
2179
2291
    return TRUE;
2180
2292
  }
2181
2293
 
2182
 
  if ((tile_get_city(ptile) && pplayers_non_attack(pplayer, city_owner(tile_get_city(ptile))))
 
2294
  if ((tile_city(ptile)
 
2295
       && pplayers_non_attack(pplayer, city_owner(tile_city(ptile))))
2183
2296
      || is_non_allied_unit_tile(ptile, pplayer)) {
2184
2297
    map_show_circle(pplayer, ptile, unit_type(punit)->vision_radius_sq);
2185
2298
    maybe_make_contact(ptile, pplayer);
2186
 
    notify_player(pplayer, ptile, E_UNIT_LOST,
2187
 
                     _("Your %s was killed by enemy units at the "
2188
 
                       "paradrop destination."),
2189
 
                     unit_name_translation(punit));
 
2299
    notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
 
2300
                  _("Your %s was killed by enemy units at the "
 
2301
                    "paradrop destination."),
 
2302
                  unit_tile_link(punit));
2190
2303
    server_remove_unit(punit);
2191
2304
    return TRUE;
2192
2305
  }
2195
2308
  {
2196
2309
    int move_cost = unit_type(punit)->paratroopers_mr_sub;
2197
2310
    punit->paradropped = TRUE;
2198
 
    return move_unit(punit, ptile, move_cost);
2199
 
  }
2200
 
}
2201
 
 
2202
 
/**************************************************************************
2203
 
  Get gold from entering a hut.
2204
 
**************************************************************************/
2205
 
static void hut_get_gold(struct unit *punit, int cred)
2206
 
{
2207
 
  struct player *pplayer = unit_owner(punit);
2208
 
  notify_player(pplayer, punit->tile, E_HUT_GOLD,
2209
 
                   _("You found %d gold."), cred);
2210
 
  pplayer->economic.gold += cred;
2211
 
}
2212
 
 
2213
 
/**************************************************************************
2214
 
  Get a tech from entering a hut.
2215
 
**************************************************************************/
2216
 
static void hut_get_tech(struct unit *punit)
2217
 
{
2218
 
  struct player *pplayer = unit_owner(punit);
2219
 
  Tech_type_id new_tech;
2220
 
  const char* tech_name;
2221
 
  
2222
 
  new_tech = give_random_free_tech(pplayer);
2223
 
  
2224
 
  tech_name = advance_name_for_player(pplayer, new_tech);
2225
 
  notify_player(pplayer, punit->tile, E_HUT_TECH,
2226
 
                   _("You found %s in ancient scrolls of wisdom."),
2227
 
                   tech_name);
2228
 
  script_signal_emit("tech_researched", 3,
2229
 
                     API_TYPE_TECH_TYPE, &advances[new_tech],
2230
 
                     API_TYPE_PLAYER, pplayer,
2231
 
                     API_TYPE_STRING, "hut");
2232
 
  notify_embassies(pplayer, NULL, NULL, E_TECH_GAIN,
2233
 
                   _("The %s have acquired %s"
2234
 
                     " from ancient scrolls of wisdom."),
2235
 
                   nation_plural_for_player(pplayer),
2236
 
                   tech_name);
2237
 
}
2238
 
 
2239
 
/**************************************************************************
2240
 
  Get a mercenary unit from entering a hut.
2241
 
**************************************************************************/
2242
 
static void hut_get_mercenaries(struct unit *punit)
2243
 
{
2244
 
  struct player *pplayer = unit_owner(punit);
2245
 
  
2246
 
  notify_player(pplayer, punit->tile, E_HUT_MERC,
2247
 
                   _("A band of friendly mercenaries joins your cause."));
2248
 
  (void) create_unit(pplayer, punit->tile,
2249
 
                     find_a_unit_type(L_HUT, L_HUT_TECH), FALSE,
2250
 
                     punit->homecity, -1);
2251
 
}
2252
 
 
2253
 
/**************************************************************************
2254
 
  Get barbarians from hut, unless close to a city.
2255
 
  Unit may die: returns 1 if unit is alive after, or 0 if it was killed.
2256
 
**************************************************************************/
2257
 
static bool hut_get_barbarians(struct unit *punit)
2258
 
{
2259
 
  struct player *pplayer = unit_owner(punit);
2260
 
  bool ok = TRUE;
2261
 
 
2262
 
  if (city_exists_within_city_radius(punit->tile, TRUE)
2263
 
      || unit_has_type_flag(punit, F_GAMELOSS)) {
2264
 
    notify_player(pplayer, punit->tile, E_HUT_BARB_CITY_NEAR,
2265
 
                     _("An abandoned village is here."));
2266
 
  } else {
2267
 
    /* save coords and type in case unit dies */
2268
 
    struct tile *unit_tile = punit->tile;
2269
 
    struct unit_type *type = unit_type(punit);
2270
 
 
2271
 
    ok = unleash_barbarians(unit_tile);
2272
 
 
2273
 
    if (ok) {
2274
 
      notify_player(pplayer, unit_tile, E_HUT_BARB,
2275
 
                       _("You have unleashed a horde of barbarians!"));
2276
 
    } else {
2277
 
      notify_player(pplayer, unit_tile, E_HUT_BARB_KILLED,
2278
 
                       _("Your %s has been killed by barbarians!"),
2279
 
                       utype_name_translation(type));
2280
 
    }
2281
 
  }
2282
 
  return ok;
2283
 
}
2284
 
 
2285
 
/**************************************************************************
2286
 
  Get new city from hut, or settlers (nomads) if terrain is poor.
2287
 
**************************************************************************/
2288
 
static void hut_get_city(struct unit *punit)
2289
 
{
2290
 
  struct player *pplayer = unit_owner(punit);
2291
 
 
2292
 
  if (city_can_be_built_here(punit->tile, punit)) {
2293
 
    notify_player(pplayer, punit->tile, E_HUT_CITY,
2294
 
                     _("You found a friendly city."));
2295
 
    create_city(pplayer, punit->tile,
2296
 
                city_name_suggestion(pplayer, punit->tile));
2297
 
 
2298
 
    if (unit_has_type_flag(punit, F_CITIES) || unit_has_type_flag(punit, F_SETTLERS)) {
2299
 
      /* In case city was found during autosettler activities */
2300
 
      initialize_infrastructure_cache(pplayer);
2301
 
    }
2302
 
 
2303
 
    /* Init ai.choice. Handling ferryboats might use it. */
2304
 
    init_choice(&punit->tile->city->ai.choice);
2305
 
 
2306
 
  } else {
2307
 
    notify_player(pplayer, punit->tile, E_HUT_SETTLER,
2308
 
                     _("Friendly nomads are impressed by you,"
2309
 
                       " and join you."));
2310
 
    (void) create_unit(pplayer, punit->tile, get_role_unit(F_CITIES,0),
2311
 
                0, punit->homecity, -1);
2312
 
  }
2313
 
}
2314
 
 
2315
 
/**************************************************************************
2316
 
  Return 1 if unit is alive, and 0 if it was killed
2317
 
**************************************************************************/
2318
 
static bool unit_enter_hut(struct unit *punit)
2319
 
{
2320
 
  struct player *pplayer = unit_owner(punit);
 
2311
    move_unit(punit, ptile, move_cost);
 
2312
    return TRUE;
 
2313
  }
 
2314
}
 
2315
 
 
2316
/**************************************************************************
 
2317
  Give 25 Gold or kill the unit. For H_LIMITEDHUTS
 
2318
  Return TRUE if unit is alive, and FALSE if it was killed
 
2319
**************************************************************************/
 
2320
static bool hut_get_limited(struct unit *punit)
 
2321
{
2321
2322
  bool ok = TRUE;
2322
2323
  int hut_chance = myrand(12);
2323
 
  
2324
 
  if (game.info.hut_overflight == OVERFLIGHT_NOTHING && is_air_unit(punit)) {
2325
 
    return ok;
 
2324
  struct player *pplayer = unit_owner(punit);
 
2325
  /* 1 in 12 to get barbarians */
 
2326
  if (hut_chance != 0) {
 
2327
    int cred = 25;
 
2328
    notify_player(pplayer, unit_tile(punit), E_HUT_GOLD, ftc_server,
 
2329
                  _("You found %d gold."), cred);
 
2330
    pplayer->economic.gold += cred;
 
2331
  } else if (city_exists_within_city_radius(punit->tile, TRUE)
 
2332
             || unit_has_type_flag(punit, F_GAMELOSS)) {
 
2333
    notify_player(pplayer, unit_tile(punit),
 
2334
                  E_HUT_BARB_CITY_NEAR, ftc_server,
 
2335
                  _("An abandoned village is here."));
 
2336
  } else {
 
2337
    notify_player(pplayer, unit_tile(punit), E_HUT_BARB_KILLED, ftc_server,
 
2338
                  _("Your %s has been killed by barbarians!"),
 
2339
                  unit_tile_link(punit));
 
2340
    wipe_unit(punit);
 
2341
    ok = FALSE;
 
2342
  }
 
2343
  return ok;
 
2344
}
 
2345
 
 
2346
/**************************************************************************
 
2347
  Due to the effects in the scripted hut behavior can not be predicted,
 
2348
  unit_enter_hut returns nothing.
 
2349
**************************************************************************/
 
2350
static void unit_enter_hut(struct unit *punit)
 
2351
{
 
2352
  struct player *pplayer = unit_owner(punit);
 
2353
  enum hut_behavior behavior = unit_class(punit)->hut_behavior;
 
2354
 
 
2355
  /* FIXME: Should we still run "hut_enter" script when
 
2356
   *        hut_behavior is HUT_NOTHING or HUT_FRIGHTEN? */ 
 
2357
  if (behavior == HUT_NOTHING) {
 
2358
    return;
2326
2359
  }
2327
2360
 
2328
2361
  tile_clear_special(punit->tile, S_HUT);
2329
2362
  update_tile_knowledge(punit->tile);
2330
2363
 
2331
 
  if (game.info.hut_overflight == OVERFLIGHT_FRIGHTEN && is_air_unit(punit)) {
2332
 
    notify_player(pplayer, punit->tile, E_HUT_BARB,
2333
 
                     _("Your overflight frightens the tribe;"
2334
 
                       " they scatter in terror."));
2335
 
    return ok;
 
2364
  if (behavior == HUT_FRIGHTEN) {
 
2365
    notify_player(pplayer, unit_tile(punit), E_HUT_BARB, ftc_server,
 
2366
                  _("Your overflight frightens the tribe;"
 
2367
                    " they scatter in terror."));
 
2368
    return;
2336
2369
  }
2337
2370
  
2338
2371
  /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
2339
 
  if (pplayer->ai.control && ai_handicap(pplayer, H_LIMITEDHUTS) 
2340
 
      && hut_chance != 10) {
2341
 
    hut_chance = 0;
 
2372
  if (pplayer->ai_data.control && ai_handicap(pplayer, H_LIMITEDHUTS)) {
 
2373
    (void) hut_get_limited(punit);
 
2374
    return;
2342
2375
  }
2343
2376
 
2344
2377
  script_signal_emit("hut_enter", 1, API_TYPE_UNIT, punit);
2345
2378
 
2346
 
  switch (hut_chance) {
2347
 
  case 0:
2348
 
    hut_get_gold(punit, 25);
2349
 
    break;
2350
 
  case 1: case 2: case 3:
2351
 
    hut_get_gold(punit, 50);
2352
 
    break;
2353
 
  case 4:
2354
 
    hut_get_gold(punit, 100);
2355
 
    break;
2356
 
  case 5: case 6: case 7:
2357
 
    hut_get_tech(punit);
2358
 
    break;
2359
 
  case 8: case 9:
2360
 
    if (num_role_units(L_HUT) != 0) {
2361
 
      hut_get_mercenaries(punit);
2362
 
    } else {
2363
 
      hut_get_gold(punit, 25);
2364
 
    }
2365
 
    break;
2366
 
  case 10:
2367
 
    ok = hut_get_barbarians(punit);
2368
 
    break;
2369
 
  case 11:
2370
 
    hut_get_city(punit);
2371
 
    break;
2372
 
  }
2373
 
 
2374
2379
  send_player_info(pplayer, pplayer);       /* eg, gold */
2375
 
  return ok;
 
2380
  return;
2376
2381
}
2377
2382
 
2378
2383
/****************************************************************************
2425
2430
  the list, since we wish to leave its transport out of combat
2426
2431
  if at all possible.
2427
2432
*****************************************************************/
2428
 
static int compare_units(const void *p, const void *q)
 
2433
static int compare_units(const struct unit *const *p1,
 
2434
                         const struct unit *const *q1)
2429
2435
{
2430
 
  struct unit * const *p1 = p;
2431
 
  struct unit * const *q1 = q;
2432
2436
  struct unit *p1def = get_defender(*p1, autoattack_target);
2433
2437
  struct unit *q1def = get_defender(*q1, autoattack_target);
2434
2438
  int p1uwc = unit_win_chance(*p1, p1def);
2487
2491
    double threshold = 0.25;
2488
2492
    struct tile *ptile = penemy->tile;
2489
2493
 
2490
 
    if (tile_get_city(ptile) && unit_list_size(ptile->units) == 1) {
 
2494
    if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
2491
2495
      /* Don't leave city defenseless */
2492
2496
      threshold = 0.90;
2493
2497
    }
2497
2501
         || get_transporter_capacity(punit) > 0)
2498
2502
        && penemywin > threshold) {
2499
2503
#ifdef REALLY_DEBUG_THIS
2500
 
      freelog(LOG_NORMAL, "AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
 
2504
      freelog(LOG_TEST, "AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
2501
2505
              unit_rule_name(penemy),
2502
2506
              unit_rule_name(punit), 
2503
 
              punit->tile->x, punit->tile->y, penemywin, 1.0 - punitwin, 
 
2507
              TILE_XY(punit->tile),
 
2508
              penemywin,
 
2509
              1.0 - punitwin, 
2504
2510
              threshold);
2505
2511
#endif
2506
2512
 
2507
 
      handle_unit_activity_request(penemy, ACTIVITY_IDLE);
2508
 
      (void) handle_unit_move_request(penemy, punit->tile, FALSE, FALSE);
 
2513
      unit_activity_handling(penemy, ACTIVITY_IDLE);
 
2514
      (void) unit_move_handling(penemy, punit->tile, FALSE, FALSE);
2509
2515
    }
2510
2516
#ifdef REALLY_DEBUG_THIS
2511
2517
      else {
2512
 
      freelog(LOG_NORMAL, "!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
 
2518
      freelog(LOG_TEST, "!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
2513
2519
              unit_rule_name(penemy),
2514
2520
              unit_rule_name(punit), 
2515
 
              punit->tile->x, punit->tile->y, penemywin, 1.0 - punitwin, 
 
2521
              TILE_XY(punit->tile),
 
2522
              penemywin,
 
2523
              1.0 - punitwin, 
2516
2524
              threshold);
2517
2525
      continue;
2518
2526
    }
2524
2532
    if (game_find_unit_by_number(sanity1)) {
2525
2533
      send_unit_info(NULL, punit);
2526
2534
    } else {
2527
 
      unit_list_unlink_all(autoattack);
2528
2535
      unit_list_free(autoattack);
2529
2536
      return FALSE; /* moving unit dead */
2530
2537
    }
2531
2538
  } unit_list_iterate_safe_end;
2532
2539
 
2533
 
  unit_list_unlink_all(autoattack);
2534
2540
  unit_list_free(autoattack);
2535
2541
  if (game_find_unit_by_number(sanity1)) {
2536
2542
    /* We could have lost movement in combat */
2558
2564
*****************************************************************/
2559
2565
static void wakeup_neighbor_sentries(struct unit *punit)
2560
2566
{
2561
 
  /* There may be sentried units with a sightrange>3, but we don't
 
2567
  bool alone_in_city;
 
2568
 
 
2569
  if (NULL != tile_city(unit_tile(punit))) {
 
2570
    int count = 0;
 
2571
 
 
2572
    unit_list_iterate(unit_tile(punit)->units, aunit) {
 
2573
      /* Consider only unit not transported. */
 
2574
      if (-1 == punit->transported_by) {
 
2575
        count++;
 
2576
      }
 
2577
    } unit_list_iterate_end;
 
2578
 
 
2579
    alone_in_city = (1 == count);
 
2580
  } else {
 
2581
    alone_in_city = FALSE;
 
2582
  }
 
2583
 
 
2584
  /* There may be sentried units with a sightrange > 3, but we don't
2562
2585
     wake them up if the punit is farther away than 3. */
2563
 
  square_iterate(punit->tile, 3, ptile) {
 
2586
  square_iterate(unit_tile(punit), 3, ptile) {
2564
2587
    unit_list_iterate(ptile->units, penemy) {
 
2588
      int distance_sq = sq_map_distance(punit->tile, ptile);
2565
2589
      int radius_sq = get_unit_vision_at(penemy, penemy->tile, V_MAIN);
2566
 
      enum unit_move_type move_type = unit_type(penemy)->move_type;
2567
 
      struct terrain *pterrain = tile_get_terrain(ptile);
2568
2590
 
2569
2591
      if (!pplayers_allied(unit_owner(punit), unit_owner(penemy))
2570
 
          && penemy->activity == ACTIVITY_SENTRY
2571
 
          && radius_sq >= sq_map_distance(punit->tile, ptile)
2572
 
          && can_player_see_unit(unit_owner(penemy), punit)
2573
 
          /* on board transport; don't awaken */
2574
 
          && !(move_type == LAND_MOVING && is_ocean(pterrain))) {
2575
 
        set_unit_activity(penemy, ACTIVITY_IDLE);
2576
 
        send_unit_info(NULL, penemy);
 
2592
          && penemy->activity == ACTIVITY_SENTRY
 
2593
          && radius_sq >= distance_sq
 
2594
          /* If the unit moved on a city, and the unit is alone, consider
 
2595
           * it is visible. */
 
2596
          && (alone_in_city
 
2597
              || can_player_see_unit(unit_owner(penemy), punit))
 
2598
          /* on board transport; don't awaken */
 
2599
          && can_unit_exist_at_tile(penemy, unit_tile(penemy))) {
 
2600
        set_unit_activity(penemy, ACTIVITY_IDLE);
 
2601
        send_unit_info(NULL, penemy);
2577
2602
      }
2578
2603
    } unit_list_iterate_end;
2579
2604
  } square_iterate_end;
2587
2612
          && ppatrol->orders.vigilant) {
2588
2613
        if (maybe_cancel_patrol_due_to_enemy(ppatrol)) {
2589
2614
          cancel_orders(ppatrol, "  stopping because of nearby enemy");
2590
 
          notify_player(unit_owner(ppatrol), ppatrol->tile, E_UNIT_ORDERS,
2591
 
                        _("Orders for %s aborted after enemy movement was "
2592
 
                          "spotted."),
2593
 
                        unit_name_translation(ppatrol));
2594
 
        }
 
2615
          notify_player(unit_owner(ppatrol), unit_tile(ppatrol),
 
2616
                        E_UNIT_ORDERS, ftc_server,
 
2617
                        _("Orders for %s aborted after enemy movement was "
 
2618
                          "spotted."),
 
2619
                        unit_link(ppatrol));
 
2620
        }
2595
2621
      }
2596
2622
    } unit_list_iterate_end;
2597
2623
  } square_iterate_end;
2598
2624
}
2599
2625
 
2600
2626
/**************************************************************************
2601
 
Does: 1) updates  the units homecity and the city it enters/leaves (the
2602
 
         cities happiness varies). This also takes into account if the
 
2627
Does: 1) updates the unit's homecity and the city it enters/leaves (the
 
2628
         city's happiness varies). This also takes into account when the
2603
2629
         unit enters/leaves a fortress.
2604
 
      2) handles any huts at the units destination.
 
2630
      2) process any huts at the unit's destination.
2605
2631
      3) updates adjacent cities' unavailable tiles.
2606
2632
 
2607
 
FIXME: Sometimes it is not neccesary to send cities because the goverment
2608
 
       doesn't care if a unit is away or not.
 
2633
FIXME: Sometimes it is not necessary to send cities because the goverment
 
2634
       doesn't care whether a unit is away or not.
2609
2635
**************************************************************************/
2610
 
static void handle_unit_move_consequences(struct unit *punit,
2611
 
                                          struct tile *src_tile,
2612
 
                                          struct tile *dst_tile,
2613
 
                                          bool passenger)
 
2636
static void unit_move_consequences(struct unit *punit,
 
2637
                                   struct tile *src_tile,
 
2638
                                   struct tile *dst_tile,
 
2639
                                   bool passenger)
2614
2640
{
2615
 
  struct city *fromcity = tile_get_city(src_tile);
2616
 
  struct city *tocity = tile_get_city(dst_tile);
2617
 
  struct city *homecity = NULL;
2618
 
  struct player *pplayer = unit_owner(punit);
2619
 
  /*  struct government *g = government_of_player(pplayer);*/
2620
 
  bool refresh_homecity = FALSE;
2621
 
 
2622
 
  if (punit->homecity != 0) {
2623
 
    homecity = game_find_city_by_number(punit->homecity);
2624
 
  }
 
2641
  struct city *fromcity = tile_city(src_tile);
 
2642
  struct city *tocity = tile_city(dst_tile);
 
2643
  struct city *homecity_start_pos = NULL;
 
2644
  struct city *homecity_end_pos = NULL;
 
2645
  int homecity_id_start_pos = punit->homecity;
 
2646
  int homecity_id_end_pos = punit->homecity;
 
2647
  struct player *pplayer_start_pos = unit_owner(punit);
 
2648
  struct player *pplayer_end_pos = pplayer_start_pos;
 
2649
  struct unit_type *type_start_pos = unit_type(punit);
 
2650
  struct unit_type *type_end_pos = type_start_pos;
 
2651
  bool refresh_homecity_start_pos = FALSE;
 
2652
  bool refresh_homecity_end_pos = FALSE;
 
2653
  int saved_id = punit->id;
 
2654
  bool unit_died = FALSE;
2625
2655
 
2626
2656
  if (tocity) {
2627
 
    handle_unit_enter_city(punit, tocity, passenger);
2628
 
  }
2629
 
 
2630
 
  /* We only do this for non-AI players to now make sure the AI turns
 
2657
    unit_enter_city(punit, tocity, passenger);
 
2658
 
 
2659
    if(!unit_alive(saved_id)) {
 
2660
      /* Unit died inside unit_enter_city().
 
2661
       * This means that some cleanup has already taken place when it was
 
2662
       * removed from game. */
 
2663
      unit_died = TRUE;
 
2664
    } else {
 
2665
      /* In case script has changed something about unit */
 
2666
      pplayer_end_pos = unit_owner(punit);
 
2667
      type_end_pos = unit_type(punit);
 
2668
      homecity_id_end_pos = punit->homecity;
 
2669
    }
 
2670
  }
 
2671
 
 
2672
  if (homecity_id_start_pos != 0) {
 
2673
    homecity_start_pos = game_find_city_by_number(homecity_id_start_pos);
 
2674
  }
 
2675
  if (homecity_id_start_pos != homecity_id_end_pos) {
 
2676
    homecity_end_pos = game_find_city_by_number(homecity_id_end_pos);
 
2677
  } else {
 
2678
    homecity_end_pos = homecity_start_pos;
 
2679
  }
 
2680
 
 
2681
  /* We only do refreshes for non-AI players to now make sure the AI turns
2631
2682
     doesn't take too long. Perhaps we should make a special refresh_city
2632
 
     functions that only refreshed happiness. */
2633
 
  if (!pplayer->ai.control) {
2634
 
    /* might have changed owners or may be destroyed */
2635
 
    tocity = tile_get_city(dst_tile);
2636
 
 
2637
 
    if (tocity) { /* entering a city */
2638
 
      if (city_owner(tocity) == unit_owner(punit)) {
2639
 
        if (tocity != homecity) {
2640
 
          city_refresh(tocity);
2641
 
          send_city_info(pplayer, tocity);
2642
 
        }
2643
 
      }
2644
 
      if (homecity) {
2645
 
        refresh_homecity = TRUE;
2646
 
      }
2647
 
    }
2648
 
 
2649
 
    if (fromcity) { /* leaving a city */
2650
 
      if (homecity) {
2651
 
        refresh_homecity = TRUE;
2652
 
      }
2653
 
      if (fromcity != homecity && city_owner(fromcity) == unit_owner(punit)) {
2654
 
        city_refresh(fromcity);
2655
 
        send_city_info(pplayer, fromcity);
2656
 
      }
2657
 
    }
2658
 
 
2659
 
    /* entering/leaving a fortress or friendly territory */
2660
 
    if (homecity) {
2661
 
      if ((game.info.happyborders > 0 && tile_owner(src_tile) != tile_owner(dst_tile))
2662
 
          ||
2663
 
          (tile_has_special(dst_tile, S_FORTRESS)
2664
 
           && is_friendly_city_near(unit_owner(punit), dst_tile))
2665
 
          ||
2666
 
          (tile_has_special(src_tile, S_FORTRESS) 
2667
 
           && is_friendly_city_near(unit_owner(punit), src_tile))) {
2668
 
        refresh_homecity = TRUE;
2669
 
      }
2670
 
    }
2671
 
    
2672
 
    if (refresh_homecity) {
2673
 
      city_refresh(homecity);
2674
 
      send_city_info(pplayer, homecity);
2675
 
    }
2676
 
  }
2677
 
 
2678
 
  /* The unit block different tiles of adjacent enemy cities before and
2679
 
     after. Update the relevant cities. */
2680
 
 
2681
 
  /* First check cities near the source. */
2682
 
  map_city_radius_iterate(src_tile, tile1) {
2683
 
    struct city *pcity = tile_get_city(tile1);
2684
 
 
2685
 
    if (pcity) {
2686
 
      update_city_tile_status_map(pcity, src_tile);
2687
 
      send_city_info(NULL, pcity);
2688
 
    }
2689
 
  } map_city_radius_iterate_end;
2690
 
  /* Then check cities near the destination. */
2691
 
  map_city_radius_iterate(dst_tile, tile1) {
2692
 
    struct city *pcity = tile_get_city(tile1);
2693
 
 
2694
 
    if (pcity) {
2695
 
      update_city_tile_status_map(pcity, dst_tile);
2696
 
      send_city_info(NULL, pcity);
2697
 
    }
2698
 
  } map_city_radius_iterate_end;
 
2683
     functions that only refreshed happines. */
 
2684
 
 
2685
  /* might have changed owners or may be destroyed */
 
2686
  tocity = tile_city(dst_tile);
 
2687
 
 
2688
  if (tocity) { /* entering a city */
 
2689
    if (tocity->owner == pplayer_end_pos) {
 
2690
      if (tocity != homecity_end_pos && !pplayer_end_pos->ai_data.control) {
 
2691
        city_refresh(tocity);
 
2692
        send_city_info(pplayer_end_pos, tocity);
 
2693
      }
 
2694
    }
 
2695
    if (homecity_start_pos) {
 
2696
      refresh_homecity_start_pos = TRUE;
 
2697
    }
 
2698
  }
 
2699
 
 
2700
  if (fromcity) { /* leaving a city */
 
2701
    if (homecity_start_pos) {
 
2702
      refresh_homecity_start_pos = TRUE;
 
2703
    }
 
2704
    if (fromcity != homecity_start_pos
 
2705
        && fromcity->owner == pplayer_start_pos
 
2706
        && !pplayer_start_pos->ai_data.control) {
 
2707
      city_refresh(fromcity);
 
2708
      send_city_info(pplayer_start_pos, fromcity);
 
2709
    }
 
2710
  }
 
2711
 
 
2712
  /* entering/leaving a fortress or friendly territory */
 
2713
  if (homecity_start_pos || homecity_end_pos) {
 
2714
    if ((game.info.happyborders > 0 && tile_owner(src_tile) != tile_owner(dst_tile))
 
2715
        || (tile_has_base_flag_for_unit(dst_tile,
 
2716
                                        type_end_pos,
 
2717
                                        BF_NOT_AGGRESSIVE)
 
2718
            && is_friendly_city_near(pplayer_end_pos, dst_tile))
 
2719
        || (tile_has_base_flag_for_unit(src_tile,
 
2720
                                        type_start_pos,
 
2721
                                        BF_NOT_AGGRESSIVE)
 
2722
            && is_friendly_city_near(pplayer_start_pos, src_tile))) {
 
2723
      refresh_homecity_start_pos = TRUE;
 
2724
      refresh_homecity_end_pos = TRUE;
 
2725
    }
 
2726
  }
 
2727
 
 
2728
  if (refresh_homecity_start_pos && !pplayer_start_pos->ai_data.control) {
 
2729
    city_refresh(homecity_start_pos);
 
2730
    send_city_info(pplayer_start_pos, homecity_start_pos);
 
2731
  }
 
2732
  if (refresh_homecity_end_pos
 
2733
      && (!refresh_homecity_start_pos
 
2734
          || homecity_start_pos != homecity_end_pos)
 
2735
      && !pplayer_end_pos->ai_data.control) {
 
2736
    city_refresh(homecity_end_pos);
 
2737
    send_city_info(pplayer_end_pos, homecity_end_pos);
 
2738
  }
 
2739
 
 
2740
  city_map_update_tile_now(dst_tile);
2699
2741
  sync_cities();
2700
2742
}
2701
2743
 
2704
2746
**************************************************************************/
2705
2747
static void check_unit_activity(struct unit *punit)
2706
2748
{
2707
 
  if (punit->activity != ACTIVITY_IDLE
2708
 
      && punit->activity != ACTIVITY_SENTRY
2709
 
      && punit->activity != ACTIVITY_EXPLORE
2710
 
      && punit->activity != ACTIVITY_GOTO) {
 
2749
  switch (punit->activity) {
 
2750
  case ACTIVITY_IDLE:
 
2751
  case ACTIVITY_SENTRY:
 
2752
  case ACTIVITY_EXPLORE:
 
2753
  case ACTIVITY_GOTO:
 
2754
    break;
 
2755
  case ACTIVITY_POLLUTION:
 
2756
  case ACTIVITY_ROAD:
 
2757
  case ACTIVITY_MINE:
 
2758
  case ACTIVITY_IRRIGATE:
 
2759
  case ACTIVITY_FORTIFIED:
 
2760
  case ACTIVITY_FORTRESS:
 
2761
  case ACTIVITY_RAILROAD:
 
2762
  case ACTIVITY_PILLAGE:
 
2763
  case ACTIVITY_TRANSFORM:
 
2764
  case ACTIVITY_UNKNOWN:
 
2765
  case ACTIVITY_AIRBASE:
 
2766
  case ACTIVITY_FORTIFYING:
 
2767
  case ACTIVITY_FALLOUT:
 
2768
  case ACTIVITY_PATROL_UNUSED:
 
2769
  case ACTIVITY_BASE:
 
2770
  case ACTIVITY_LAST:
2711
2771
    set_unit_activity(punit, ACTIVITY_IDLE);
2712
 
  }
 
2772
    break;
 
2773
  };
2713
2774
}
2714
2775
 
2715
2776
/**************************************************************************
2732
2793
  struct unit *ptransporter = NULL;
2733
2794
  struct vision *old_vision = punit->server.vision;
2734
2795
  struct vision *new_vision;
 
2796
  int saved_id = punit->id;
 
2797
  bool unit_lives;
2735
2798
    
2736
2799
  conn_list_do_buffer(pplayer->connections);
2737
2800
 
2751
2814
 
2752
2815
    /* Insert them again. */
2753
2816
    unit_list_iterate(cargo_units, pcargo) {
 
2817
      /* FIXME: Some script may have killed unit while it has been
 
2818
       *        in cargo_units list, but it has not been unlinked
 
2819
       *        from this list. pcargo may be invalid pointer. */
2754
2820
      struct vision *old_vision = pcargo->server.vision;
2755
 
      struct vision *new_vision = vision_new(unit_owner(pcargo), pdesttile, TRUE);
 
2821
      struct vision *new_vision = vision_new(unit_owner(pcargo), pdesttile);
2756
2822
 
2757
2823
      pcargo->server.vision = new_vision;
2758
2824
      vision_layer_iterate(v) {
2774
2840
      vision_clear_sight(old_vision);
2775
2841
      vision_free(old_vision);
2776
2842
 
2777
 
      handle_unit_move_consequences(pcargo, psrctile, pdesttile, TRUE);
 
2843
      unit_move_consequences(pcargo, psrctile, pdesttile, TRUE);
2778
2844
    } unit_list_iterate_end;
2779
 
    unit_list_unlink_all(cargo_units);
2780
2845
    unit_list_free(cargo_units);
2781
2846
  }
2782
2847
 
 
2848
  unit_lives = unit_alive(saved_id);
 
2849
  if (unit_lives) {
 
2850
    wakeup_neighbor_sentries(punit);
 
2851
  }
 
2852
 
2783
2853
  /* We first unfog the destination, then move the unit and send the
2784
2854
     move, and then fog the old territory. This means that the player
2785
2855
     gets a chance to see the newly explored territory while the
2787
2857
     move */
2788
2858
 
2789
2859
  /* Enhance vision if unit steps into a fortress */
2790
 
  new_vision = vision_new(unit_owner(punit), pdesttile, TRUE);
2791
 
  punit->server.vision = new_vision;
2792
 
  vision_layer_iterate(v) {
2793
 
    vision_change_sight(new_vision, v,
2794
 
                        get_unit_vision_at(punit, pdesttile, v));
2795
 
  } vision_layer_iterate_end;
2796
 
 
2797
 
  ASSERT_VISION(new_vision);
2798
 
 
2799
 
  /* Claim ownership of fortress? */
2800
 
  if (tile_has_special(pdesttile, S_FORTRESS)
2801
 
      && (!tile_owner(pdesttile) || pplayers_at_war(tile_owner(pdesttile), pplayer))) {
2802
 
    map_claim_ownership(pdesttile, pplayer, pdesttile);
2803
 
  }
2804
 
 
2805
 
  unit_list_unlink(psrctile->units, punit);
2806
 
  punit->tile = pdesttile;
2807
 
  punit->moved = TRUE;
2808
 
  if (punit->transported_by != -1) {
2809
 
    ptransporter = game_find_unit_by_number(punit->transported_by);
2810
 
    pull_unit_from_transporter(punit, ptransporter);
2811
 
  }
2812
 
  punit->moves_left = MAX(0, punit->moves_left - move_cost);
2813
 
  if (punit->moves_left == 0) {
2814
 
    punit->done_moving = TRUE;
2815
 
  }
2816
 
  unit_list_prepend(pdesttile->units, punit);
2817
 
  check_unit_activity(punit);
 
2860
  if (unit_lives) {
 
2861
    new_vision = vision_new(unit_owner(punit), pdesttile);
 
2862
    punit->server.vision = new_vision;
 
2863
    vision_layer_iterate(v) {
 
2864
      vision_change_sight(new_vision, v,
 
2865
                          get_unit_vision_at(punit, pdesttile, v));
 
2866
    } vision_layer_iterate_end;
 
2867
 
 
2868
    ASSERT_VISION(new_vision);
 
2869
 
 
2870
    /* Claim ownership of fortress? */
 
2871
    if (game.info.borders > 0
 
2872
        && tile_has_claimable_base(pdesttile, unit_type(punit))
 
2873
        && (!tile_owner(pdesttile)
 
2874
            || pplayers_at_war(tile_owner(pdesttile), pplayer))) {
 
2875
      map_claim_ownership(pdesttile, pplayer, pdesttile);
 
2876
      map_claim_border(pdesttile, pplayer);
 
2877
      city_thaw_workers_queue();
 
2878
      city_refresh_queue_processing();
 
2879
    }
 
2880
 
 
2881
    unit_list_unlink(psrctile->units, punit);
 
2882
    punit->tile = pdesttile;
 
2883
    punit->moved = TRUE;
 
2884
    if (punit->transported_by != -1) {
 
2885
      ptransporter = game_find_unit_by_number(punit->transported_by);
 
2886
      pull_unit_from_transporter(punit, ptransporter);
 
2887
    }
 
2888
    punit->moves_left = MAX(0, punit->moves_left - move_cost);
 
2889
    if (punit->moves_left == 0) {
 
2890
      punit->done_moving = TRUE;
 
2891
    }
 
2892
    unit_list_prepend(pdesttile->units, punit);
 
2893
    check_unit_activity(punit);
 
2894
  }
2818
2895
 
2819
2896
  /*
2820
2897
   * Transporter info should be send first becouse this allow us get right
2828
2905
  if (ptransporter) {
2829
2906
    send_unit_info(NULL, ptransporter);
2830
2907
  }
2831
 
  
 
2908
 
2832
2909
  /* Send updated information to anyone watching.  If the unit moves
2833
2910
   * in or out of a city we update the 'occupied' field.  Note there may
2834
2911
   * be cities at both src and dest under some rulesets.
2835
2912
   *   If unit is about to take over enemy city, unit is seen by
2836
2913
   * those players seeing inside cities of old city owner. After city
2837
 
   * has been transferred, updated info is sent inside
2838
 
   * handle_unit_enter_city() */
2839
 
  send_unit_info_to_onlookers(NULL, punit, psrctile, FALSE);
2840
 
    
2841
 
  /* Special checks for ground units in the ocean. */
2842
 
  if (!can_unit_survive_at_tile(punit, pdesttile)) {
2843
 
    ptransporter = find_transporter_for_unit(punit, pdesttile);
2844
 
    if (ptransporter) {
2845
 
      put_unit_onto_transporter(punit, ptransporter);
2846
 
    }
2847
 
 
2848
 
    /* Set activity to sentry if boarding a ship. */
2849
 
    if (ptransporter && !pplayer->ai.control && !unit_has_orders(punit)
2850
 
        && !can_unit_exist_at_tile(punit, pdesttile)) {
2851
 
      set_unit_activity(punit, ACTIVITY_SENTRY);
2852
 
    }
2853
 
 
2854
 
    /*
2855
 
     * Transporter info should be send first becouse this allow us get right
2856
 
     * update_menu effect in client side.
2857
 
     */
2858
 
    
2859
 
    /*
2860
 
     * Send updated information to anyone watching that transporter has cargo.
2861
 
     */
2862
 
    if (ptransporter) {
2863
 
      send_unit_info(NULL, ptransporter);
2864
 
    }
2865
 
 
2866
 
    /*
2867
 
     * Send updated information to anyone watching that unit is on transport.
2868
 
     * All players without shared vison with owner player get
2869
 
     * REMOVE_UNIT package.
2870
 
     */
2871
 
    send_unit_info_to_onlookers(NULL, punit, punit->tile, TRUE);
 
2914
   * has been transferred, updated info is sent by unit_enter_city() */
 
2915
  if (unit_lives) {
 
2916
    send_unit_info_to_onlookers(NULL, punit, psrctile, FALSE);
 
2917
    
 
2918
    /* Special checks for ground units in the ocean. */
 
2919
    if (!can_unit_survive_at_tile(punit, pdesttile)) {
 
2920
      ptransporter = find_transporter_for_unit(punit);
 
2921
      if (ptransporter) {
 
2922
        put_unit_onto_transporter(punit, ptransporter);
 
2923
      }
 
2924
 
 
2925
      /* Set activity to sentry if boarding a ship. */
 
2926
      if (ptransporter && !pplayer->ai_data.control && !unit_has_orders(punit)
 
2927
          && !can_unit_exist_at_tile(punit, pdesttile)) {
 
2928
        set_unit_activity(punit, ACTIVITY_SENTRY);
 
2929
      }
 
2930
 
 
2931
      /*
 
2932
       * Transporter info should be send first because this allow us get right
 
2933
       * update_menu effect in client side.
 
2934
       */
 
2935
    
 
2936
      /*
 
2937
       * Send updated information to anyone watching that transporter has cargo.
 
2938
       */
 
2939
      if (ptransporter) {
 
2940
        send_unit_info(NULL, ptransporter);
 
2941
      }
 
2942
 
 
2943
      /*
 
2944
       * Send updated information to anyone watching that unit is on transport.
 
2945
       * All players without shared vison with owner player get
 
2946
       * REMOVE_UNIT package.
 
2947
       */
 
2948
      send_unit_info_to_onlookers(NULL, punit, punit->tile, TRUE);
 
2949
    }
2872
2950
  }
2873
 
  
2874
 
  if ((pcity = tile_get_city(psrctile))) {
 
2951
 
 
2952
  if ((pcity = tile_city(psrctile))) {
2875
2953
    refresh_dumb_city(pcity);
2876
2954
  }
2877
 
  if ((pcity = tile_get_city(pdesttile))) {
 
2955
  if ((pcity = tile_city(pdesttile))) {
2878
2956
    refresh_dumb_city(pcity);
2879
2957
  }
2880
2958
 
2887
2965
      /* We're only concerned with known, unfogged tiles which may contain
2888
2966
       * hidden units that are no longer visible.  These units will not
2889
2967
       * have been handled by the fog code, above. */
2890
 
      if (tile_get_known(tile1, pplayer) == TILE_KNOWN) {
 
2968
      if (TILE_KNOWN_SEEN == tile_get_known(tile1, pplayer)) {
2891
2969
        unit_list_iterate(tile1->units, punit2) {
2892
2970
          if (punit2 != punit && !can_player_see_unit(pplayer, punit2)) {
2893
2971
            unit_goes_out_of_sight(pplayer, punit2);
2897
2975
    } players_iterate_end;
2898
2976
  } square_iterate_end;
2899
2977
 
2900
 
  handle_unit_move_consequences(punit, psrctile, pdesttile, FALSE);
2901
 
  script_signal_emit("unit_moved", 3,
2902
 
                     API_TYPE_UNIT, punit,
2903
 
                     API_TYPE_TILE, psrctile,
2904
 
                     API_TYPE_TILE, pdesttile);
2905
 
  wakeup_neighbor_sentries(punit);
2906
 
  if (!unit_survive_autoattack(punit)) {
2907
 
    conn_list_do_unbuffer(pplayer->connections);
 
2978
  if (unit_lives) {
 
2979
    unit_move_consequences(punit, psrctile, pdesttile, FALSE);
 
2980
 
 
2981
    /* FIXME: Should signal emit be after sentried units have been
 
2982
     *        waken up in case script causes unit death? */
 
2983
    script_signal_emit("unit_moved", 3,
 
2984
                       API_TYPE_UNIT, punit,
 
2985
                       API_TYPE_TILE, psrctile,
 
2986
                       API_TYPE_TILE, pdesttile);
 
2987
    unit_lives = unit_alive(saved_id);
 
2988
 
 
2989
    if (!unit_lives) {
 
2990
      /* Script caused unit to die */
 
2991
      return FALSE;
 
2992
    }
 
2993
  }
 
2994
 
 
2995
  if (unit_lives) {
 
2996
    wakeup_neighbor_sentries(punit);
 
2997
    unit_lives = unit_survive_autoattack(punit);
 
2998
  }
 
2999
 
 
3000
  if (unit_lives) {
 
3001
    maybe_make_contact(pdesttile, unit_owner(punit));
 
3002
  }
 
3003
 
 
3004
  conn_list_do_unbuffer(pplayer->connections);
 
3005
 
 
3006
  if (!unit_lives) {
2908
3007
    return FALSE;
2909
3008
  }
2910
 
  maybe_make_contact(pdesttile, unit_owner(punit));
2911
 
 
2912
 
  conn_list_do_unbuffer(pplayer->connections);
2913
 
 
2914
 
  if (game.info.timeout != 0 && game.timeoutaddenemymove > 0) {
 
3009
 
 
3010
  if (game.info.timeout != 0 && game.server.timeoutaddenemymove > 0) {
2915
3011
    bool new_information_for_enemy = FALSE;
2916
3012
 
2917
3013
    phase_players_iterate(penemy) {
2937
3033
   * right order.  This is probably not a bug. */
2938
3034
 
2939
3035
  if (tile_has_special(pdesttile, S_HUT)) {
2940
 
    return unit_enter_hut(punit);
2941
 
  } else {
2942
 
    return TRUE;
 
3036
    int saved_id = punit->id;
 
3037
 
 
3038
    unit_enter_hut(punit);
 
3039
 
 
3040
    return unit_alive(saved_id);
2943
3041
  }
 
3042
 
 
3043
  return TRUE;
2944
3044
}
2945
3045
 
2946
3046
/**************************************************************************
2967
3067
 
2968
3068
  circle_iterate(punit->tile, radius_sq, ptile) {
2969
3069
    struct unit *penemy = is_non_allied_unit_tile(ptile, pplayer);
2970
 
    struct vision_base *pdcity = map_get_player_base(ptile, pplayer);
 
3070
 
 
3071
    struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
2971
3072
 
2972
3073
    if ((penemy && can_player_see_unit(pplayer, penemy))
2973
3074
        || (pdcity && !pplayers_allied(pplayer, vision_owner(pdcity))
3004
3105
  struct player *pplayer = unit_owner(punit);
3005
3106
  int moves_made = 0;
3006
3107
  enum unit_activity activity;
 
3108
  Base_type_id base;
3007
3109
 
3008
3110
  assert(unit_has_orders(punit));
3009
3111
 
3036
3138
    if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
3037
3139
      /* "Patrol" orders are stopped if an enemy is near. */
3038
3140
      cancel_orders(punit, "  stopping because of nearby enemy");
3039
 
      notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3040
 
                       _("Orders for %s aborted as there "
3041
 
                         "are units nearby."),
3042
 
                       unit_name_translation(punit));
 
3141
      notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3142
                    _("Orders for %s aborted as there are units nearby."),
 
3143
                    unit_link(punit));
3043
3144
      return TRUE;
3044
3145
    }
3045
3146
 
3088
3189
      if (player_find_unit_by_id(pplayer, unitid)) {
3089
3190
        /* Build failed. */
3090
3191
        cancel_orders(punit, " orders canceled; failed to build city");
3091
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3092
 
                         _("Orders for %s aborted because building "
3093
 
                           "of city failed."),
3094
 
                           unit_name_translation(punit));
 
3192
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3193
                      _("Orders for %s aborted because building "
 
3194
                        "of city failed."),
 
3195
                      unit_link(punit));
3095
3196
        return TRUE;
3096
3197
      } else {
3097
3198
        /* Build succeeded => unit "died" */
3099
3200
      }
3100
3201
    case ORDER_ACTIVITY:
3101
3202
      activity = order.activity;
3102
 
      if (!can_unit_do_activity(punit, activity)) {
3103
 
        cancel_orders(punit, "  orders canceled because of failed activity");
3104
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3105
 
                         _("Orders for %s aborted since they "
3106
 
                           "give an invalid activity."),
3107
 
                         unit_name_translation(punit));
3108
 
        return TRUE;
 
3203
      base = order.base;
 
3204
      if ((activity == ACTIVITY_BASE && !can_unit_do_activity_base(punit, base))
 
3205
          || (activity != ACTIVITY_BASE
 
3206
              && !can_unit_do_activity(punit, activity))) {
 
3207
        cancel_orders(punit, "  orders canceled because of failed activity");
 
3208
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3209
                      _("Orders for %s aborted since they "
 
3210
                        "give an invalid activity."),
 
3211
                      unit_link(punit));
 
3212
        return TRUE;
3109
3213
      }
3110
3214
      punit->done_moving = TRUE;
3111
 
      set_unit_activity(punit, activity);
 
3215
 
 
3216
      if (activity != ACTIVITY_BASE) {
 
3217
        set_unit_activity(punit, activity);
 
3218
      } else {
 
3219
        set_unit_activity_base(punit, base);
 
3220
      }
3112
3221
      send_unit_info(NULL, punit);
3113
3222
      break;
3114
3223
    case ORDER_MOVE:
3115
3224
      /* Move unit */
3116
3225
      if (!(dst_tile = mapstep(punit->tile, order.dir))) {
3117
 
        cancel_orders(punit, "  move order sent us to invalid location");
3118
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3119
 
                         _("Orders for %s aborted since they "
3120
 
                           "give an invalid location."),
3121
 
                         unit_name_translation(punit));
3122
 
        return TRUE;
 
3226
        cancel_orders(punit, "  move order sent us to invalid location");
 
3227
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3228
                      _("Orders for %s aborted since they "
 
3229
                        "give an invalid location."),
 
3230
                      unit_link(punit));
 
3231
        return TRUE;
3123
3232
      }
3124
3233
 
3125
3234
      if (!last_order
3126
 
          && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
3127
 
        cancel_orders(punit, "  orders canceled because of enemy");
3128
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3129
 
                         _("Orders for %s aborted as there "
3130
 
                           "are units in the way."),
3131
 
                         unit_name_translation(punit));
3132
 
        return TRUE;
 
3235
          && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
 
3236
        cancel_orders(punit, "  orders canceled because of enemy");
 
3237
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3238
                      _("Orders for %s aborted as there "
 
3239
                        "are units in the way."),
 
3240
                      unit_link(punit));
 
3241
        return TRUE;
3133
3242
      }
3134
3243
 
3135
3244
      freelog(LOG_DEBUG, "  moving to %d,%d",
3136
3245
              dst_tile->x, dst_tile->y);
3137
 
      res = handle_unit_move_request(punit, dst_tile, FALSE, !last_order);
 
3246
      res = unit_move_handling(punit, dst_tile, FALSE, !last_order);
3138
3247
      if (!player_find_unit_by_id(pplayer, unitid)) {
3139
3248
        freelog(LOG_DEBUG, "  unit died while moving.");
3140
3249
        /* A player notification should already have been sent. */
3149
3258
      }
3150
3259
 
3151
3260
      if (!res && punit->moves_left > 0) {
3152
 
        /* Movement failed (ZOC, etc.) */
3153
 
        cancel_orders(punit, "  attempt to move failed.");
3154
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3155
 
                         _("Orders for %s aborted because of "
3156
 
                           "failed move."),
3157
 
                         unit_name_translation(punit));
3158
 
        return TRUE;
 
3261
        /* Movement failed (ZOC, etc.) */
 
3262
        cancel_orders(punit, "  attempt to move failed.");
 
3263
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3264
                      _("Orders for %s aborted because of failed move."),
 
3265
                      unit_link(punit));
 
3266
        return TRUE;
3159
3267
      }
3160
3268
 
3161
3269
      if (!res && punit->moves_left == 0) {
3188
3296
      return FALSE;
3189
3297
    case ORDER_HOMECITY:
3190
3298
      freelog(LOG_DEBUG, "  orders: changing homecity");
3191
 
      if (punit->tile->city) {
3192
 
        handle_unit_change_homecity(pplayer, unitid, punit->tile->city->id);
 
3299
      if (tile_city(punit->tile)) {
 
3300
        handle_unit_change_homecity(pplayer, unitid, tile_city(punit->tile)->id);
3193
3301
      } else {
3194
 
        cancel_orders(punit, "  no homecity");
3195
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3196
 
                         _("Attempt to change homecity for %s failed."),
3197
 
                         unit_name_translation(punit));
3198
 
        return TRUE;
 
3302
        cancel_orders(punit, "  no homecity");
 
3303
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3304
                      _("Attempt to change homecity for %s failed."),
 
3305
                      unit_link(punit));
 
3306
        return TRUE;
3199
3307
      }
3200
3308
      break;
3201
 
    case ORDER_TRADEROUTE:
 
3309
    case ORDER_TRADE_ROUTE:
3202
3310
      freelog(LOG_DEBUG, "  orders: establishing trade route.");
3203
3311
      handle_unit_establish_trade(pplayer, unitid);
3204
3312
      if (player_find_unit_by_id(pplayer, unitid)) {
3205
 
        cancel_orders(punit, "  no trade route city");
3206
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3207
 
                         _("Attempt to establish trade route for %s failed."),
3208
 
                         unit_name_translation(punit));
3209
 
        return TRUE;
 
3313
        cancel_orders(punit, "  no trade route city");
 
3314
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3315
                      _("Attempt to establish trade route for %s failed."),
 
3316
                      unit_link(punit));
 
3317
        return TRUE;
3210
3318
      } else {
3211
3319
        return FALSE;
3212
3320
      }
3214
3322
      freelog(LOG_DEBUG, "  orders: building wonder");
3215
3323
      handle_unit_help_build_wonder(pplayer, unitid);
3216
3324
      if (player_find_unit_by_id(pplayer, unitid)) {
3217
 
        cancel_orders(punit, "  no wonder city");
3218
 
        notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3219
 
                         _("Attempt to build wonder for %s failed."),
3220
 
                         unit_name_translation(punit));
3221
 
        return TRUE;
 
3325
        cancel_orders(punit, "  no wonder city");
 
3326
        notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3327
                      _("Attempt to build wonder for %s failed."),
 
3328
                      unit_link(punit));
 
3329
        return TRUE;
3222
3330
      } else {
3223
3331
        return FALSE;
3224
3332
      }
3225
3333
    case ORDER_LAST:
3226
3334
      cancel_orders(punit, "  client sent invalid order!");
3227
 
      notify_player(pplayer, punit->tile, E_UNIT_ORDERS,
3228
 
                       _("Your %s has invalid orders."),
3229
 
                       unit_name_translation(punit));
 
3335
      notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
 
3336
                    _("Your %s has invalid orders."),
 
3337
                    unit_link(punit));
3230
3338
      return TRUE;
3231
3339
    }
3232
3340