FLAK
                   ------------------------------------
                           Fleet Action Kombat


Introduction
=============

  This is a multi-ship combat engine, intended to be used with PHost.
  It can probably also be used with HOST, although that has not been
  tested. It was designed in a joint venture of the PHost,
  Planetsserver, Blutmagie and Vagabond people.

  It is intended to be "plug-compatible" with existing ship lists. In
  1:1 combat, it attempts to mimic PVCR as close as possible. It was
  designed to be easy to use, for players and hosts.

  The server is a portable open-source application based on the PDK,
  included with the PCC2 source code.

  The client-side viewer is available in multiple versions:

  - included with PCC2/PlayVCR, portable, open-source application
    that runs on Windows and Linux: <http://phost.de/~stefan/pcc2.html>

  - built into PCC2 Web and the PCC2 Web Battle Simulator on
    PlanetsCentral: <https://planetscentral.com/play/sim.cgi>

  - as a DOS application, derived from PCC1: <http://phost.de/~stefan/flak/>

  - as part of PCC2ng (c2ng) which is currently in development:
    <http://phost.de/~stefan/pcc2ng.html>



Basic Concepts
===============

  The main problem with standard one-on-one combat is that small ships
  cannot team up against a big ship. In FLAK, they can. (Note that
  we'll use the term 'ship' when we actually mean 'ship or planet'.
  Planets behave mostly the same way as ships.)

  For each fight, you can form fleets. Each fleet will attack an enemy
  ship which matches their fighting strength. For example, a group of
  5 Rubies will rather attack a Cube rather than a single Outrider,
  because a Cube comes closer to the fighting strength of a five
  Rubies. Conversely, 5 groups of one Ruby each will attack the
  Outrider, since they independantly decide that a single Ruby is too
  small to attack a Cube. Therefore, you can make targeting decisions
  by defining small or large groups.

  The rule to remember is: fleets attack ships. It does not matter whether
  the enemy ship is part of a fleet or whether it fights alone.

  To form fleets, use the battle-order friendly codes. Normally, you
  can have up to 12 fleets in each fight, depending on the first digit
  of the battle order:
    1:   -99 .. -1
    2:     0 .. 99
    3:   100 .. 199
         ...
    11:  900 .. 999
    12:  non-numerical fcodes
  Only the order matters. With friendly codes 102 193 409 444 lfm, you'll
  get three groups:
    102 193
    409 444
    lfm
  The first one (with lowest battle order) starts closest in, followed
  by the second one, etc. You cannot affect distance between groups,
  i.e. if the friendly codes were 002 003 898 899 900, the overall
  picture would look the same: 3 groups, equal distances between groups:
    002 003
    898 899
    900
  Planets will always fight alone, as a 13th group. Their relative
  position in the battle setup is defined by their friendly code.

  Hosts can restrict the maximum fleet size. If you define a group
  with too many ships, FLAK will split it up. This way you might end up
  with more groups.


Immunities and other Exceptions
--------------------------------

  There are a number of "X cannot attack Y" rules. These are quite
  problematic for a fleet combat engine. If you have some fleet, which
  has an "X" member, and that fleet decides to attack "Y", "X" surely
  shall not sit there twiddling thumbs.

  The rule is: if no member of your fleet can attack a particular
  target, they'll leave that target alone. If someone can attack and
  someone can not, they will probably attack it, but they prefer ships
  which everyone can attack.

  Likewise, PHost has the Aggressor/Opponent concept. If you have no
  primary enemy and not the "Kill" mission, your ships will sit there
  patiently and wait to be attacked by some Aggressor. In FLAK, they'll
  get active. Once it has been determined that your ship will take part
  in combat, it will be aggressive.

  The rule is: if someone is aggressive to you, you are also aggressive
  to them.

  Ships which are not a possible target for anyone will not take part in
  the fight. For example, in deep space, noone can attack a fuelless ship,
  so that ship will be left out. Likewise, if Lizards, Tholians and Borg
  meet, but all the Lizards have primary enemy Tholian, all the Tholians
  have primary enemy Lizards, and the Borg have no PE/Kill order, the Borg
  will not take part in the fight.

  The rule is: if you do not want to attack, and nobody wants to attack
  you, you do not fight.

  - "Ships with matching friendly codes cannot attack". If someone in a
    fleet says 'My friendly code does not match, let's attack them', the
    fleet will attack. Only if the friendly codes of all ships match,
    they'll be safe. It is slightly less likely that a fleet attacks a
    ship when there is at least one ship with matching code.

  - "Fuelless ships cannot attack or be attacked". If a NUK planet
    takes part in the fight, that planet will fight the ship.
    Otherwise, the ship will not take part. (Actually, the ship will
    attack the planet, because planets obviously cannot move towards
    the ship.)

  - "Nobody can attack a cloaked ship". If you match their PE, the
    cloaked ship will decloak in order to attack you. Which you can
    obviously use to attack them with your full forces.

  - "Planets cannot attack Klingons or Rebels". This rule is enforced.
    If the Klingon or Rebel does not want to attack the planet, the
    planet will not fight them.

  - "Planets cannot attack Super Star Destroyers". If the SSD is not
    aggressive (no PE, no kill), it will not take part in the
    fight. Therefore, this rule is enforced as well.

  Intercept-attack is another special rule. If some intercept-attack
  happens, an extra battle will be fought before normal combat. For
  example, if a Lizard Class Cruiser intercepts an MBR, and the MBR
  intercepts a Loki, these 3 ships will fight first, using the usual
  rules.


Targeting in a Nutshell
------------------------

  Note that these rules all take part in a big formula (see below). This
  is not a "checklist".

  o We prefer ships that match our size.

  o We prefer slightly smaller ships over slightly bigger ones.

  o We prefer ships matching our PE over those which don't match.

  o We prefer ships which everyone can attack over ships which match one
    of our friendly codes.

  o We prefer damaged ships over undamaged ones.

  o We prefer close targets over far ones.

  o We prefer firing at our current target over switching to a new one.


Multi-Ship Effects
-------------------

  Of course, a proper multi-ship combat engine does something more than
  blindly extending 1:1 rules for multiple ships at once.

  o Proper 2-D movement. Ships avoid crashing into each other. Two
    fighting units will stop approaching each other at
    StandoffDistance, as usual. Unrelated ships avoid coming closer
    than 50% StandoffDistance. If some ships do come too close, they'll
    automatically step aside a bit. Own ships maintain at least 25%
    StandoffDistance. Fighters, torpedoes, or beam shots are small, and
    do not avoid (or hit) objects in the way.

    Note that this does mean 2-D. The 3-D display is just eye-candy;
    the third dimension has no effect on the rules.

  o Smarter fighters. If a target dies while a fighter is underway,
    the fighters will automatically advance to the next target. If a
    fighter's base dies, it will pick a new one. This might result in
    an overloaded ship at the end of the turn, in which case the
    excess fighters are destroyed.

  o Smarter torpedoes. If a torpedo moves towards a target, but that
    target dies inbetween, the torpedo randomly hits another member of
    the target's fleet. Ships inside a fleet communicate to not waste
    torpedoes. If only 10 torps are needed to smash an enemy, five
    torpers in a fleet would fire 2 torps each (actually, they'll
    probably fire 4 torps each to account for missing torpedoes and
    still have some safety; but still a lot of savings compared to 10
    torps each).

    If a torpedo ship dies, other ships from its fleet will gather up
    its torpedoes when they can carry them. This way, torpedo ships
    (like carriers) can pick up material from their less fortunate
    peers, to reduce losses. Likewise, if a torpedo hits a ship that
    is already dead, it may ricochet and hit another ship of its
    target fleet.

  o Fleet combat requires more concentration from ship commanders than
    1:1 combat. Therefore, if you come in with a big armada, you'll get
    a slight penalty. So avoid taking ships into combat which do not
    have enough offensive capability. (This is our lame excuse for the
    compensation cheat, see below.)

  o A ship's beams will fire at fighters which attack that ship's fleet,
    or which belong to its target's fleet. Likewise, fighters will
    intercept enemy fighters that target your fleet or which belong to
    their enemy. Unrelated fighters will be left alone.

  Another important effect is that attackers get more information
  about their opponents than in 1:1 combat. If you attack a planet
  with a scout, you'd normally only see the one ship which smashes
  your probe. With FLAK, you'll see the whole armada awaiting you.


Conclusion of a Fight
----------------------

  While in normal 1:1 combat, it is clear who captures whom, matters
  are more complicated in multi-ship combat. Currently, FLAK
  implements a very simple model:

  o Death or capture is declared at the end of each battle tick.
    Everything happens simultaneously. If a ship is hit by a lethal
    beam, it is still allowed to fire its own beam. It dies at the end
    of the battle tick.

  o When a ship gets captured, it is captured by the ship who placed
    the last shot on it during the tick when it died. Therefore, if
    many ships fight against one ship, it is more or less random who
    will get it.

    - If the captor dies after capturing a ship, but there are still
      other ships of his people, one of these will take the prey.

    - If all the captor's ships are dead, but there are still ships
      belonging to the people of the captured ship, one of those will
      take control of the ship (i.e. capture it back).

    - Otherwise, a random ship from the survivors is picked who takes
      the crewless ship. If everyone else's dead, the ship explodes.

    PAL/PBP and experience is awarded to race who finally captured the
    ship. Note that no points are awarded if captor and captee are
    allied, but full points are given (to the original owner) in case
    of capture back!

  o If the ship gets destroyed, or there is no surviving captor,
    PAL/PBP and experience are awarded to the player whose ship
    placed the last shot.

  o Experience is handled slightly different in FLAK. Normally,
    experience formulas have the form `their_mass * score / my_mass'.
    In FLAK, the computation is `sum(mass_i * score_i) / sum(my_masses)',
    for each ship `i' which entered the battle (`Score' is
    EPCombatKillScaling, for example).

    For example, when two 300 kt ships destroy a 500 kt ship, each is
    awarded 500*800 / (300+300) = 666 points. Conversely, if the 500
    kt ship wins, it gets (300*800 + 300*800) / 500 = 960 points.

    All participating ships get the same amount of points. If we
    replace the two 300 kt ships by a 580 kt battleship and a 20 kt
    probe, results are the same: 500*800 / (580+20) = 666.


Differences to 1:1 Combat
--------------------------

  When just two ships fight, results are intended to be close to
  normal PVCR combat, but not identical. Here are all known
  differences of FLAK to PVCR _for a one-on-one setup_.

  o Torps need time to travel (and continue to travel after the torper
    died)
  o Fighters continue firing when their carrier dies
    => Effect: this can lead to a result of mutual annihilation which is
       not possible in PVCR (but which is possible in Tim's VCR).

  o All clean-up (removal of dead units) happens at once, not in the
    middle of a battle tick.
    => Effect: more fairness, but also makes mutual annihilation more
       likely.

  o The fighter limit is `2 * Num_bays' (a big carrier can have more
    fighters out than a small one; in PVCR, they have the same limit,
    namely MaxFightersLaunched).
    => Effect: small. In PVCR, ships hardly ever get more fighters out
       than our limit. However, in FLAK, ships often start farther out
       and therefore have more time to launch fighters. Therefore, a
       group of small carriers gets overly strong without this change.

  o FLAK does not use the BeamHitFighterRange parameter; the
    BeamFiringRange is used for fighters as well.
    => Effect: small. However, in big fights, this avoids that ships
       fire across the whole battle arena, which simply looks dumb :)

  o Only one fighter intercept per race pair (that is, in 1:1 combat,
    only one fighter intercept at all per tick).
    => Effect: small. In big fights, unlimited fighter intercept would
       lead to too many losses, though.

  Considering PList, carriers tend to get a bit stronger with FLAK.
  An Exterminator-vs.-Death-Star fight yields a 50/50 chance for each
  ship to win. In FLAK, the Exterminator usually dies.


Formulas
=========

  o Targeting. We pick the ship where
       (Abs(Our_rating - Their_rating) + 100) * Multiplier / Divisor
    yields the smallest value. Here,
    - Our_rating is the sum of the ratings of all ships in our fleet
      which can possibly attack the target (a ship with just death rays
      cannot attack a planet). See below for how these ratings are
      computed.
    - Their_rating is the rating of the target ship
    - Multiplier contains factors which make choosing this target less
      likely. Summarized, this is the time needed to reach it.
      . Multiplier = Distance / Movement_speed (time to reach target)
      . Multiplier is at least 50
      . for planets, we assume a Movement_speed of 100.
    - Divisor consists of a number of bonuses which make choosing this
      target more likely. Summarized, this decides how easy it would be
      to kill that target.
      . start with 100
      . add 50 if target is smaller than we (Our_rating >= Their_rating)
      . add targeting modifiers (see under configuration) to prefer
        ships which match our PE, and to prefer ships which do not match
        friendly codes
      . add damage of the enemy (0..100)
      . add one for each 5 shield points already lost by the target
      . add 50 if we are already attacking that target

  o Compensation Cheat. Applying normal combat formulas to multi-ship
    combat yields an effect we call 'overcompensation'. Assuming equal
    ships, a 10-vs-10 scenario yields random distribution of results,
    which is what we want. However, slight imbalance will have a much
    larger effect than the imbalance suggests. For example, in a
    12-vs-10 situation, the 12-side usually keeps 6 ships, not 2. This
    effect is perfectly logical, but it is not desirable for our game:
    it somehow 'linearizes' combat (a 12/12 ship is twice as powerful
    as two 6/6 ships), which was not intended by ship list designers
    (the 12/12 ship costs much more than two 6/6 ships). Therefore,
    FLAK cheats: if someone places a shot, and he has fewer ships than
    his target, he will receive a bonus. The bonus is computed as
      (Target_strength + 1000) / (Our_strength + 1000)
    A typical top ship has a strength of 500. In our example, the 10-ship
    side receives a bonus of 7000 / 6000 = 1.16 = +16%. The maximum bonus
    is 2 = +100%.

    The bonus is implemented by scaling down the target's mass for
    computing weapon effects. In our example, if the target had a mass
    of 420 kt, it would, for purposes of weapon computations, be scaled
    down to 420 / 1.16 = 360 kt.

    If the bonus value is below 1.0, no modifications are applied to the
    formulas (i.e. the bonus never turns into a penalty).


Configuration
==============

  The battle engine is highly configurable. The defaults are sensible,
  but we want to allow everyone to try to tweak and improve the
  behaviour. If you have some good settings, please share them with
  us!

  o Targeting Ratings. The following options define the targeting
    mechanism.
       RatingMassScale    = 1
       RatingBeamScale    = 1
       RatingTorpScale    = 1
       RatingFighterScale = 8
    The rating of a ship is
       RatingMassScale * Ship_mass
       + RatingBeamScale * Beam_type * Beam_count
       + RatingTorpScale * Torp_type * Tube_count
       + RatingFighterScale * Bay_count
    The idea should be that two ships which are comparable in combat
    should have similar ratings. In fight, ships always choose "matching"
    targets, which match their rating as close as possible. These defaults
    should work for all ship lists.

  o Targeting modifiers. These configure how intense "other factors" affect
    targeting.
       RatingPEBonus      = 20
    applies if someone has this race as Primary Enemy.
       RatingFullAttBonus = 20
    applies if all ships from this group are aggressive (no FC match).
       RatingRandomBonus  = 20
    a random bonus 0 <= x < RatingRandomBonus is always given. Recall
    that ships usually accept targets which match their rating as close
    as possible. By giving one of these bonuses, they're accepting a
    greater tolerance for a matching ship. For example, setting
    RatingPEBonus = 500 will cause ships to rush at matching PE ships,
    ignoring most other conditions.

    In addition, a bonus of +50 is given if our target is smaller than
    we, and another +50 if we're keeping a target we're already
    attacking; these figures are not configurable.

  o Initial positions.
       StartingDistanceShip      = 26000
       StartingDistancePlanet    = 10000
    These parameters define the initial distance from the center for each
    unit.
       StartingDistancePerPlayer = 1000
    For each player taking part in the fight, the distance is increased
    by this value (e.g. +5000 in a 5-player fight).
       StartingDistancePerFleet  = 5000
    Fleets start this many meters apart.

    In a ship-only fight, starting positions are assigned on a circle.
    In a planet-vs.-ships fight, the ship-only races start in a half-
    circle on the left, and the planet starts on the right side.

  o Compensation.
       CompensationShipScale     = 0
       CompensationBeamScale     = 30
       CompensationTorpScale     = 90
       CompensationFighterScale  = 90
       CompensationLimit         = 500
    The compensation weight for a ship is
       CompensationShipScale
       + CompensationBeamScale * Beam_count
       + CompensationTorpScale * Tube_count
       + CompensationFighterScale * Bay_count
    but at most CompensationLimit. Note that, unlike for targeting
    ratings, weapon types have no effect. The above values are for PList;
    double all the 'Scale' parameters for the standard ship list. You can
    set all values to zero to turn off compensation, but this is not
    recommended.

  o Fleet Size Limit
       MaximumFleetSize          = 999
    This parameter gives the maximum size for a fleet. If a player has
    more ships than that with similar battle order, FLAK will build
    two fleets. Sensible values start in the magnitude of 10 or 20.

    Note that FLAK might build even smaller fleets sometimes. For
    example, assume a group of 15 ships, two of them are fuelless, and
    a MaximumFleetSize of 10. FLAK will build up fleets first, one
    with 10 ships and one with the remaining 5. After noticing that
    the fuelless ships cannot be attacked by someone else (which is
    not obvious from the start; there could be a NUKing planet
    around), FLAK will remove them from their group. Therefore, you'll
    probably end up with an 8/5 split instead of the expected 10/3.

    The default value accepts all sizes and never splits fleets.
    However, in Ragnarok-style endfights, it makes sense to split
    fleets to avoid making the fight look too stupid :).

  FLAK uses almost all the PHost battle parameters.

  o MaxFightersLaunched is not used. The fighter limit is hardwired to
    twice the number of fighter bays on each ship.

  o BeamHitFighterRange is not used. FLAK uses BeamFiringRange for
    firing at fighters, too.


Miscellaneous
==============

  FLAK combat data is transmitted in 'flakX.dat' files Although normal
  combat (a handful of ships) will only need some hundred bytes, a
  Ragnarok-style fight (all ships at once) can take up to 500k. Be
  careful. If you are not yet sending your players zipped results, you
  probably should now. (This large amount of memory can mainly be
  attributed to the fact that FLAK is highly configurable, and that we
  can change many aspects of a fight without having to exchange the
  viewer application. Maybe we'll switch to a less flexible but
  smaller format later.)

  The FLAK viewer needs the 'pconfig.src'/'shiplist.txt' file to play
  combat. It does not need the FLAK configuration itself.

  The viewer will tell you if it encounters a fight it cannot play. That
  is, if the server application does need an incompatible change, you will
  not see bogus results.


Why FLAK?
==========

  The 1:1 combat has been a point of criticism in VGAP since its
  conception.

  FLAK is not the first multi-ship combat system. There are some
  earlier systems, namely TKF (The Killing Floor) and TVCR2 (Tactical
  VCR 2).

  Unfortunately, those systems are largely undocumented and
  closed-source. FLAK aims to be a well-designed and documented combat
  system. In particular, it aims at being a reasonable choice with
  ship lists designed for PHost combat, and it aims to be friendly to
  automatic hosting on a Linux server.


Cast of Characters
===================

                    - Design, Ideas and Simulations -
                        (in no particular order)
                           Matthias Degenhardt
                             Sascha Rambeaud
                             Stefan Reuther
                            Alexander Babanov
                              Thomas Voigt
                             Stefan Glasauer

                               - Coding -
                             Stefan Reuther

                                - Beer -
                               Olaf Selke
                           Christian Brückner


-eof-