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. The client-side viewer is available as a closed-source DOS application (based on the PCC 1.x graphics kernel) as well as an open-source application (based on the PCC II kernel), which runs on Windows, Linux, etc. You need the viewer to watch your battles. The viewer works with any client. 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 and torps are small, and do not explicitly do such avoidance. Note that this does mean 2-D. The 3-D display is just eye-candy. 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). 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 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. What's Wrong with TKF? ======================= "There already is a multi-ship combat engine for VGAP", you might ask, "why not use that?". The Killing Floor was revolutionary when it came out, but it has quite a number of problems which have not been solved in the past years. DOCUMENTATION. The only available documentation describes technical things, how to set up and use it. There are only vague hints about its rules: What are its formulas? How do ships pick targets? How does 1:1 combat in TKF relate to Tim-VCR or PVCR combat? STABILITY. TKF is not the most stable thing. Both the viewer and the host are quite crash-prone. POLITICS. TKF is closed-source shareware. Some may not like either of these points. In particular, this restriction means it runs only on selected operating systems. Parts of these points also apply to TVCR2, although the author of this document has not tried that engine yet. 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-