ogamejs 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,8 +44,8 @@ Ogame.Fleets.getTrip(
44
44
  { galaxy: 3, system: 42, position: 6 },
45
45
  { drives: { combustion: 16, hyperspace: 12 } },
46
46
  );
47
- // → { distance: 40000, fleetSpeed: 19500, duration: 1595, fuel: 258287,
48
- // cargo: 6650000, cargoAfterFuel: 6391713 }
47
+ // → { distance: 40000, fleetSpeed: 19500, duration: 15862, fuel: 216148,
48
+ // cargo: 6650000, cargoAfterFuel: 6433852 }
49
49
 
50
50
  // And how it would go
51
51
  Ogame.Fleets.simulateCombat(
@@ -259,19 +259,29 @@ Ogame.Research.getResearchTime(Ogame.models.Research[122], 10, 12, 2); // Plasma
259
259
 
260
260
  ### `Ogame.Fleets`
261
261
 
262
- #### `getDistance(origin, target)`
262
+ #### `getDistance(origin, target, universe = {})`
263
263
 
264
264
  Coordinates are `{ galaxy, system, position }`. The scale is not linear.
265
265
 
266
266
  ```javascript
267
267
  Ogame.Fleets.getDistance({ galaxy: 1, system: 1, position: 1 }, { galaxy: 4, system: 1, position: 1 });
268
268
  // → 60000
269
+
270
+ // Most universes are donuts: the last galaxy touches the first
271
+ Ogame.Fleets.getDistance(
272
+ { galaxy: 1, system: 1, position: 1 },
273
+ { galaxy: 6, system: 1, position: 1 },
274
+ { galaxies: 6, systems: 499, donutGalaxy: true, donutSystem: true },
275
+ );
276
+ // → 20000
269
277
  ```
270
278
 
271
- #### `getShipSpeed(ship, drives = {})` / `getFleetSpeed(fleet, drives = {})` / `getActiveDrive(ship, drives = {})`
279
+ #### `getShipSpeed(ship, drives = {}, bonus = 0)` / `getFleetSpeed(fleet, drives = {})` / `getActiveDrive(ship, drives = {}, bonus = 0)`
272
280
 
273
281
  `drives` holds the `{ combustion, impulse, hyperspace }` levels. Each level adds 10%, 20% or 30% of the ship's base speed, and only the drive the ship actually flies on counts.
274
282
 
283
+ `bonus` adds to that, as a share of the base speed: `1` for the class bonus that doubles a ship's speed (Collector transporters, General warships), `0.05` for a 5% life form bonus. In a fleet, each entry carries its own `speedBonus`.
284
+
275
285
  A few ships switch to a better drive once the matching technology is high enough. `getActiveDrive` tells you which one is in use — and since a switch also changes the fuel burn, it reports that too.
276
286
 
277
287
  ```javascript
@@ -287,11 +297,15 @@ Ogame.Fleets.getFleetSpeed([{ ship: Ogame.models.Destroyable[1], count: 100 }],
287
297
 
288
298
  #### `getFlightTime(distance, fleetSpeed, speedPercent = 100, universeFleetSpeed = 1)`
289
299
 
290
- `(10 + 35000 / speedPercent × √(distance × 10 / fleetSpeed)) / universeFleetSpeed`, in seconds.
300
+ `(10 + 350000 / speedPercent × √(distance × 10 / fleetSpeed)) / universeFleetSpeed`, in seconds — at 100%, the familiar `10 + 3500 × √(distance × 10 / fleetSpeed)`.
291
301
 
292
- #### `getFuelConsumption(fleet, distance, speedPercent = 100, drives = {})`
302
+ #### `getFuelConsumption(fleet, distance, speedPercent = 100, drives = {}, options = {})`
293
303
 
294
- `1 + round(Σ(consumption × count) × distance / 35000 × (speedPercent / 100 + 1)²)`, in deuterium.
304
+ Each ship type is billed on its own, at least one unit, then the bills add up:
305
+ `Σ max(1, round(consumption × count × distance / 35000 × (shipSpeedValue / 10 + 1)²))`, in deuterium.
306
+ `shipSpeedValue` is `speedPercent / 10` for the slowest ship and `speedPercent / 10 × √(fleetSpeed / shipSpeed)` for the faster ones it holds back, which burn less than at full throttle.
307
+
308
+ `consumption` is the ship's own after the universe factor (`options.deuteriumFactor`, `globalDeuteriumSaveFactor` in the API) and the entry's `fuelReduction` (General, life forms, capped at `MAX_FUEL_REDUCTION`, 90%), each rounded down and never below one unit.
295
309
 
296
310
  #### `getTrip(fleet, origin, target, options = {})`
297
311
 
@@ -304,10 +318,12 @@ Ogame.Fleets.getTrip(
304
318
  { galaxy: 3, system: 42, position: 6 },
305
319
  { drives: { combustion: 16, hyperspace: 12 }, speedPercent: 100, roundTrip: false },
306
320
  );
307
- // → { distance: 40000, fleetSpeed: 19500, duration: 1595, fuel: 258287,
308
- // cargo: 6650000, cargoAfterFuel: 6391713 }
321
+ // → { distance: 40000, fleetSpeed: 19500, duration: 15862, fuel: 216148,
322
+ // cargo: 6650000, cargoAfterFuel: 6433852 }
309
323
  ```
310
324
 
325
+ `options` also takes `universeFleetSpeed`, `deuteriumFactor` and `universe` (the donut shape passed to `getDistance`).
326
+
311
327
  `cargoAfterFuel` is what is left once the deuterium is loaded — the number that decides whether a raid is worth flying.
312
328
 
313
329
  #### `getDebris(ship, number, factor, deuteriumFactor = 0)`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ogamejs",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "OGame formulas as a dependency-free ESM library: building and research costs, production, build times, fleet debris and marketplace rates.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -6,26 +6,49 @@ function assertCoordinates(coordinates, name) {
6
6
  }
7
7
  }
8
8
 
9
+ // In a donut universe the fleet takes the shorter way round.
10
+ function gap(from, to, size, donut) {
11
+ const direct = Math.abs(from - to);
12
+
13
+ if (!donut) {
14
+ return direct;
15
+ }
16
+
17
+ if (!Number.isInteger(size) || size <= 0) {
18
+ throw new Error(`a donut universe needs its size, received ${size}`);
19
+ }
20
+
21
+ return Math.min(direct, size - direct);
22
+ }
23
+
9
24
  /**
10
25
  *
11
26
  * Return the distance between two coordinates, in OGame distance units
12
27
  *
13
28
  * The scale is not linear: crossing a galaxy costs far more than crossing a
14
- * system, which costs far more than moving inside one.
29
+ * system, which costs far more than moving inside one. Most universes are
30
+ * donuts: the last galaxy (or system) touches the first, and the fleet takes the
31
+ * shorter way round.
15
32
  * @param {import('../types.js').Coordinates} origin Where the fleet leaves from
16
33
  * @param {import('../types.js').Coordinates} target Where it goes
34
+ * @param {import('../types.js').UniverseShape} [universe] How the universe wraps,
35
+ * flat when left out
17
36
  * @returns {number} The distance
18
37
  */
19
- function getDistance(origin, target) {
38
+ function getDistance(origin, target, universe = {}) {
20
39
  assertCoordinates(origin, 'origin');
21
40
  assertCoordinates(target, 'target');
22
41
 
42
+ const {
43
+ galaxies, systems, donutGalaxy = false, donutSystem = false,
44
+ } = universe;
45
+
23
46
  if (origin.galaxy !== target.galaxy) {
24
- return 20000 * Math.abs(origin.galaxy - target.galaxy);
47
+ return 20000 * gap(origin.galaxy, target.galaxy, galaxies, donutGalaxy);
25
48
  }
26
49
 
27
50
  if (origin.system !== target.system) {
28
- return 2700 + 95 * Math.abs(origin.system - target.system);
51
+ return 2700 + 95 * gap(origin.system, target.system, systems, donutSystem);
29
52
  }
30
53
 
31
54
  if (origin.position !== target.position) {
@@ -1,6 +1,9 @@
1
1
  import getDistance from './distance.js';
2
2
  import { getFleetSpeed, getActiveDrive } from './speed.js';
3
3
 
4
+ /** The game stops the fuel discounts here, however many add up. */
5
+ const MAX_FUEL_REDUCTION = 0.9;
6
+
4
7
  function assertSpeedPercent(speedPercent) {
5
8
  if (!Number.isFinite(speedPercent) || speedPercent <= 0 || speedPercent > 100) {
6
9
  throw new Error(`speedPercent must be between 1 and 100, received ${speedPercent}`);
@@ -11,7 +14,9 @@ function assertSpeedPercent(speedPercent) {
11
14
  *
12
15
  * Return the one way flight time of a fleet
13
16
  *
14
- * `(10 + 35000 / speedPercent * sqrt(distance * 10 / fleetSpeed)) / universeFleetSpeed`
17
+ * `(10 + 350000 / speedPercent * sqrt(distance * 10 / fleetSpeed)) / universeFleetSpeed`
18
+ *
19
+ * At 100% that is the well known `10 + 3500 * sqrt(distance * 10 / fleetSpeed)`.
15
20
  * @param {number} distance The distance to cross, from `getDistance`
16
21
  * @param {number} fleetSpeed The speed of the slowest ship, from `getFleetSpeed`
17
22
  * @param {number} [speedPercent] The fleet speed slider, 10 to 100 in game
@@ -25,7 +30,7 @@ function getFlightTime(distance, fleetSpeed, speedPercent = 100, universeFleetSp
25
30
  throw new Error(`fleetSpeed must be greater than 0, received ${fleetSpeed}`);
26
31
  }
27
32
 
28
- const seconds = 10 + (35000 / speedPercent) * Math.sqrt((distance * 10) / fleetSpeed);
33
+ const seconds = 10 + (350000 / speedPercent) * Math.sqrt((distance * 10) / fleetSpeed);
29
34
 
30
35
  return Math.round(seconds / universeFleetSpeed);
31
36
  }
@@ -34,31 +39,57 @@ function getFlightTime(distance, fleetSpeed, speedPercent = 100, universeFleetSp
34
39
  *
35
40
  * Return the deuterium a fleet burns for a one way trip
36
41
  *
37
- * `1 + round(sum(consumption * count) * distance / 35000 * (speedPercent / 100 + 1) ** 2)`
42
+ * Each ship type is billed on its own, then the bills add up:
43
+ * `max(1, round(consumption * count * distance / 35000 * (shipSpeedValue / 10 + 1) ** 2))`
44
+ *
45
+ * `shipSpeedValue` is the speed the ship really flies at, on the game's 1 to 10
46
+ * scale: `speedPercent / 10` for the slowest ship, less for the faster ones held
47
+ * back by it, `speedPercent / 10 * sqrt(fleetSpeed / shipSpeed)`. A faster ship
48
+ * flying slower than it could burns less than at full throttle.
49
+ *
50
+ * `consumption` is the ship's own, after the universe deuterium factor and the
51
+ * entry's `fuelReduction` (General, life forms), each rounded down and never
52
+ * below one unit.
38
53
  * @param {import('../types.js').FleetEntry[]} fleet The ships taking off
39
54
  * @param {number} distance The distance to cross, from `getDistance`
40
55
  * @param {number} [speedPercent] The fleet speed slider, 10 to 100 in game
41
56
  * @param {import('../types.js').Drives} [drives] Drive levels, needed because a
42
57
  * ship that switched drive also changed its consumption
58
+ * @param {object} [options] Universe settings
59
+ * @param {number} [options.deuteriumFactor] The universe deuterium consumption
60
+ * factor (`globalDeuteriumSaveFactor` in the API), 1 when left out
43
61
  * @returns {number} The fuel needed, in deuterium
44
62
  */
45
- function getFuelConsumption(fleet, distance, speedPercent = 100, drives = {}) {
63
+ function getFuelConsumption(fleet, distance, speedPercent = 100, drives = {}, options = {}) {
46
64
  assertSpeedPercent(speedPercent);
47
65
 
48
- if (!Array.isArray(fleet) || fleet.length === 0) {
49
- throw new Error('fleet must be a non empty array of { ship, count }');
66
+ const { deuteriumFactor = 1 } = options;
67
+
68
+ if (!Number.isFinite(deuteriumFactor) || deuteriumFactor <= 0) {
69
+ throw new Error(`deuteriumFactor must be greater than 0, received ${deuteriumFactor}`);
50
70
  }
51
71
 
52
- const speedFactor = (speedPercent / 100 + 1) ** 2;
72
+ const fleetSpeed = getFleetSpeed(fleet, drives);
53
73
 
54
- const consumption = fleet.reduce((total, { ship, count }) => {
55
- // A ship that switched drive also changed how much it burns.
56
- const { fuelConsumption } = getActiveDrive(ship, drives);
74
+ const total = fleet
75
+ .filter(({ count }) => count > 0)
76
+ .reduce((sum, {
77
+ ship, count, speedBonus = 0, fuelReduction = 0,
78
+ }) => {
79
+ // A ship that switched drive also changed how much it burns.
80
+ const { speed, fuelConsumption } = getActiveDrive(ship, drives, speedBonus);
81
+ const speedValue = (speedPercent / 10) * Math.sqrt(fleetSpeed / speed);
82
+ // Kept in percent until the end: 1 - 0.9 lands just under 0.1 in binary.
83
+ const saved = Math.round(Math.min(Math.max(fuelReduction, 0), MAX_FUEL_REDUCTION) * 10000);
84
+ const perShip = Math.max(1, Math.floor(
85
+ (Math.floor(fuelConsumption * deuteriumFactor) * (10000 - saved)) / 10000,
86
+ ));
87
+ const base = Math.max(1, Math.round(perShip * count));
57
88
 
58
- return total + fuelConsumption * count;
59
- }, 0);
89
+ return sum + Math.max(1, Math.round((base * distance) / 35000 * (speedValue / 10 + 1) ** 2));
90
+ }, 0);
60
91
 
61
- return 1 + Math.round((consumption * distance) / 35000 * speedFactor);
92
+ return Math.max(1, total);
62
93
  }
63
94
 
64
95
  /**
@@ -70,6 +101,9 @@ function getFuelConsumption(fleet, distance, speedPercent = 100, drives = {}) {
70
101
  * @param {object} [options] Trip options
71
102
  * @param {number} [options.speedPercent] The fleet speed slider, 10 to 100 in game
72
103
  * @param {number} [options.universeFleetSpeed] The universe fleet speed
104
+ * @param {number} [options.deuteriumFactor] The universe deuterium consumption factor
105
+ * @param {import('../types.js').UniverseShape} [options.universe] How the universe
106
+ * wraps, for the distance
73
107
  * @param {import('../types.js').Drives} [options.drives] The drive technology levels
74
108
  * @param {boolean} [options.roundTrip] Whether to account for the way back too
75
109
  * @returns {{
@@ -82,14 +116,17 @@ function getTrip(fleet, origin, target, options = {}) {
82
116
  const {
83
117
  speedPercent = 100,
84
118
  universeFleetSpeed = 1,
119
+ deuteriumFactor = 1,
120
+ universe = {},
85
121
  drives = {},
86
122
  roundTrip = false,
87
123
  } = options;
88
124
 
89
- const distance = getDistance(origin, target);
125
+ const distance = getDistance(origin, target, universe);
90
126
  const fleetSpeed = getFleetSpeed(fleet, drives);
91
127
  const oneWay = getFlightTime(distance, fleetSpeed, speedPercent, universeFleetSpeed);
92
- const fuel = getFuelConsumption(fleet, distance, speedPercent, drives) * (roundTrip ? 2 : 1);
128
+ const fuel = getFuelConsumption(fleet, distance, speedPercent, drives, { deuteriumFactor })
129
+ * (roundTrip ? 2 : 1);
93
130
  const cargo = fleet.reduce((total, { ship, count }) => total + ship.cargo * count, 0);
94
131
 
95
132
  return {
@@ -102,4 +139,6 @@ function getTrip(fleet, origin, target, options = {}) {
102
139
  };
103
140
  }
104
141
 
105
- export { getFlightTime, getFuelConsumption, getTrip };
142
+ export {
143
+ getFlightTime, getFuelConsumption, getTrip, MAX_FUEL_REDUCTION,
144
+ };
@@ -1,7 +1,9 @@
1
1
  import getDebris from './getDebris.js';
2
2
  import getDistance from './distance.js';
3
3
  import getShipSpeed, { getActiveDrive, getFleetSpeed } from './speed.js';
4
- import { getFlightTime, getFuelConsumption, getTrip } from './flight.js';
4
+ import {
5
+ getFlightTime, getFuelConsumption, getTrip, MAX_FUEL_REDUCTION,
6
+ } from './flight.js';
5
7
  import simulateCombat, { DEFAULT_REPAIR_FACTOR, DEFAULT_PLUNDER_RATIO } from './combat.js';
6
8
  import { getCombatStatistics, simulateCombats, DEFAULT_RUNS } from './combatStatistics.js';
7
9
  import {
@@ -52,6 +54,7 @@ export {
52
54
  EXPEDITION_TOP_TIER_BASE,
53
55
  MOON_DEBRIS_THRESHOLD,
54
56
  MAX_MOON_CHANCE,
57
+ MAX_FUEL_REDUCTION,
55
58
  DEFAULT_REPAIR_FACTOR,
56
59
  DEFAULT_PLUNDER_RATIO,
57
60
  DEFAULT_RUNS,
@@ -32,9 +32,15 @@ function driveLevel(drives, drive) {
32
32
  return level;
33
33
  }
34
34
 
35
- function speedWith(baseSpeed, drive, drives) {
35
+ function assertBonus(bonus) {
36
+ if (!Number.isFinite(bonus) || bonus < 0) {
37
+ throw new Error(`speed bonus must be a number >= 0, received ${bonus}`);
38
+ }
39
+ }
40
+
41
+ function speedWith(baseSpeed, drive, drives, bonus) {
36
42
  // eslint-disable-next-line security/detect-object-injection -- drive is a known key
37
- return Math.floor(baseSpeed * (1 + DRIVE_BONUS[drive] * driveLevel(drives, drive)));
43
+ return Math.floor(baseSpeed * (1 + DRIVE_BONUS[drive] * driveLevel(drives, drive) + bonus));
38
44
  }
39
45
 
40
46
  /**
@@ -44,15 +50,21 @@ function speedWith(baseSpeed, drive, drives) {
44
50
  * A few ships switch to a better drive once the matching technology is high
45
51
  * enough — a small cargo moves to the impulse drive at Impulse 5. When several
46
52
  * drives are available the ship uses whichever ends up fastest.
53
+ *
54
+ * `bonus` adds to the drive bonus, as a share of the base speed: the class
55
+ * bonus that doubles a ship's speed is 1, a 5% life form bonus 0.05.
47
56
  * @param {import('../types.js').DestroyableEntry} ship An entry of models/destroyable.js
48
57
  * @param {import('../types.js').Drives} [drives] Drive levels
58
+ * @param {number} [bonus] Extra speed, as a share of the base speed
49
59
  * @returns {{drive: string, speed: number, fuelConsumption: number}} The active drive
50
60
  */
51
- function getActiveDrive(ship, drives = {}) {
61
+ function getActiveDrive(ship, drives = {}, bonus = 0) {
52
62
  if (!ship || !ship.drive) {
53
63
  throw new Error('expected an entry of models/destroyable.js');
54
64
  }
55
65
 
66
+ assertBonus(bonus);
67
+
56
68
  const candidates = [
57
69
  { drive: ship.drive, speed: ship.speed, fuelConsumption: ship.fuelConsumption },
58
70
  ...(ship.driveUpgrades ?? [])
@@ -62,7 +74,7 @@ function getActiveDrive(ship, drives = {}) {
62
74
  return candidates
63
75
  .map(({ drive, speed, fuelConsumption }) => ({
64
76
  drive,
65
- speed: speedWith(speed, drive, drives),
77
+ speed: speedWith(speed, drive, drives, bonus),
66
78
  fuelConsumption,
67
79
  }))
68
80
  .reduce((best, candidate) => (candidate.speed > best.speed ? candidate : best));
@@ -73,15 +85,18 @@ function getActiveDrive(ship, drives = {}) {
73
85
  * Return the speed of a ship, drive technologies included
74
86
  * @param {import('../types.js').DestroyableEntry} ship An entry of models/destroyable.js
75
87
  * @param {import('../types.js').Drives} [drives] Drive levels
88
+ * @param {number} [bonus] Extra speed, as a share of the base speed (class, life forms)
76
89
  * @returns {number} The speed the ship flies at
77
90
  */
78
- function getShipSpeed(ship, drives = {}) {
79
- return getActiveDrive(ship, drives).speed;
91
+ function getShipSpeed(ship, drives = {}, bonus = 0) {
92
+ return getActiveDrive(ship, drives, bonus).speed;
80
93
  }
81
94
 
82
95
  /**
83
96
  *
84
97
  * Return the speed of a whole fleet, which is the speed of its slowest ship
98
+ *
99
+ * Each entry may carry its own `speedBonus` (class, life forms).
85
100
  * @param {import('../types.js').FleetEntry[]} fleet The ships taking off
86
101
  * @param {import('../types.js').Drives} [drives] Drive levels
87
102
  * @returns {number} The fleet speed
@@ -93,7 +108,7 @@ function getFleetSpeed(fleet, drives = {}) {
93
108
 
94
109
  const speeds = fleet
95
110
  .filter(({ count }) => count > 0)
96
- .map(({ ship }) => getShipSpeed(ship, drives));
111
+ .map(({ ship, speedBonus = 0 }) => getShipSpeed(ship, drives, speedBonus));
97
112
 
98
113
  if (speeds.length === 0) {
99
114
  throw new Error('fleet must hold at least one ship with a count above 0');
package/src/types.js CHANGED
@@ -120,6 +120,19 @@
120
120
  * @typedef {object} FleetEntry A group of identical ships
121
121
  * @property {DestroyableEntry} ship The ship
122
122
  * @property {number} count How many of them
123
+ * @property {number} [speedBonus] Extra speed, as a share of the ship's base
124
+ * speed: 1 for the class bonus that doubles it, 0.05 for a 5% life form bonus,
125
+ * summed
126
+ * @property {number} [fuelReduction] Deuterium saved, as a share: the General's
127
+ * class discount plus the life form one, capped at 0.9 like the game does
128
+ */
129
+
130
+ /**
131
+ * @typedef {object} UniverseShape How the universe wraps around
132
+ * @property {number} [galaxies] The number of galaxies
133
+ * @property {number} [systems] The number of systems per galaxy
134
+ * @property {boolean} [donutGalaxy] Whether the last galaxy touches the first
135
+ * @property {boolean} [donutSystem] Whether the last system touches the first
123
136
  */
124
137
 
125
138
  /**
@@ -3,11 +3,15 @@
3
3
  * Return the distance between two coordinates, in OGame distance units
4
4
  *
5
5
  * The scale is not linear: crossing a galaxy costs far more than crossing a
6
- * system, which costs far more than moving inside one.
6
+ * system, which costs far more than moving inside one. Most universes are
7
+ * donuts: the last galaxy (or system) touches the first, and the fleet takes the
8
+ * shorter way round.
7
9
  * @param {import('../types.js').Coordinates} origin Where the fleet leaves from
8
10
  * @param {import('../types.js').Coordinates} target Where it goes
11
+ * @param {import('../types.js').UniverseShape} [universe] How the universe wraps,
12
+ * flat when left out
9
13
  * @returns {number} The distance
10
14
  */
11
- declare function getDistance(origin: import('../types.js').Coordinates, target: import('../types.js').Coordinates): number;
15
+ declare function getDistance(origin: import('../types.js').Coordinates, target: import('../types.js').Coordinates, universe?: import('../types.js').UniverseShape): number;
12
16
  export default getDistance;
13
17
  //# sourceMappingURL=distance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"distance.d.ts","sourceRoot":"","sources":["../../src/fleets/distance.js"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,MAAM,EAJhB,OAAO,aAAa,EAAE,WAIN,EAAE,MAAM,EAHxB,OAAO,aAAa,EAAE,WAGE,GAFtB,MAAM,CAoBlB;eAEc,WAAW"}
1
+ {"version":3,"file":"distance.d.ts","sourceRoot":"","sources":["../../src/fleets/distance.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;GAaG;AACH,iBAAS,WAAW,CAAC,MAAM,EANhB,OAAO,aAAa,EAAE,WAMN,EAAE,MAAM,EALxB,OAAO,aAAa,EAAE,WAKE,EAAE,QAAQ,AAJ1C,CAEA,EAFQ,OAAO,aAAa,EAAE,aAIiB,GAFrC,MAAM,CAwBlB;eAEc,WAAW"}
@@ -1,8 +1,12 @@
1
+ /** The game stops the fuel discounts here, however many add up. */
2
+ declare const MAX_FUEL_REDUCTION = 0.9;
1
3
  /**
2
4
  *
3
5
  * Return the one way flight time of a fleet
4
6
  *
5
- * `(10 + 35000 / speedPercent * sqrt(distance * 10 / fleetSpeed)) / universeFleetSpeed`
7
+ * `(10 + 350000 / speedPercent * sqrt(distance * 10 / fleetSpeed)) / universeFleetSpeed`
8
+ *
9
+ * At 100% that is the well known `10 + 3500 * sqrt(distance * 10 / fleetSpeed)`.
6
10
  * @param {number} distance The distance to cross, from `getDistance`
7
11
  * @param {number} fleetSpeed The speed of the slowest ship, from `getFleetSpeed`
8
12
  * @param {number} [speedPercent] The fleet speed slider, 10 to 100 in game
@@ -14,15 +18,30 @@ declare function getFlightTime(distance: number, fleetSpeed: number, speedPercen
14
18
  *
15
19
  * Return the deuterium a fleet burns for a one way trip
16
20
  *
17
- * `1 + round(sum(consumption * count) * distance / 35000 * (speedPercent / 100 + 1) ** 2)`
21
+ * Each ship type is billed on its own, then the bills add up:
22
+ * `max(1, round(consumption * count * distance / 35000 * (shipSpeedValue / 10 + 1) ** 2))`
23
+ *
24
+ * `shipSpeedValue` is the speed the ship really flies at, on the game's 1 to 10
25
+ * scale: `speedPercent / 10` for the slowest ship, less for the faster ones held
26
+ * back by it, `speedPercent / 10 * sqrt(fleetSpeed / shipSpeed)`. A faster ship
27
+ * flying slower than it could burns less than at full throttle.
28
+ *
29
+ * `consumption` is the ship's own, after the universe deuterium factor and the
30
+ * entry's `fuelReduction` (General, life forms), each rounded down and never
31
+ * below one unit.
18
32
  * @param {import('../types.js').FleetEntry[]} fleet The ships taking off
19
33
  * @param {number} distance The distance to cross, from `getDistance`
20
34
  * @param {number} [speedPercent] The fleet speed slider, 10 to 100 in game
21
35
  * @param {import('../types.js').Drives} [drives] Drive levels, needed because a
22
36
  * ship that switched drive also changed its consumption
37
+ * @param {object} [options] Universe settings
38
+ * @param {number} [options.deuteriumFactor] The universe deuterium consumption
39
+ * factor (`globalDeuteriumSaveFactor` in the API), 1 when left out
23
40
  * @returns {number} The fuel needed, in deuterium
24
41
  */
25
- declare function getFuelConsumption(fleet: import('../types.js').FleetEntry[], distance: number, speedPercent?: number, drives?: import('../types.js').Drives): number;
42
+ declare function getFuelConsumption(fleet: import('../types.js').FleetEntry[], distance: number, speedPercent?: number, drives?: import('../types.js').Drives, options?: {
43
+ deuteriumFactor?: number;
44
+ }): number;
26
45
  /**
27
46
  *
28
47
  * Return everything about a trip: distance, duration, fuel and cargo left
@@ -32,6 +51,9 @@ declare function getFuelConsumption(fleet: import('../types.js').FleetEntry[], d
32
51
  * @param {object} [options] Trip options
33
52
  * @param {number} [options.speedPercent] The fleet speed slider, 10 to 100 in game
34
53
  * @param {number} [options.universeFleetSpeed] The universe fleet speed
54
+ * @param {number} [options.deuteriumFactor] The universe deuterium consumption factor
55
+ * @param {import('../types.js').UniverseShape} [options.universe] How the universe
56
+ * wraps, for the distance
35
57
  * @param {import('../types.js').Drives} [options.drives] The drive technology levels
36
58
  * @param {boolean} [options.roundTrip] Whether to account for the way back too
37
59
  * @returns {{
@@ -43,6 +65,8 @@ declare function getFuelConsumption(fleet: import('../types.js').FleetEntry[], d
43
65
  declare function getTrip(fleet: import('../types.js').FleetEntry[], origin: import('../types.js').Coordinates, target: import('../types.js').Coordinates, options?: {
44
66
  speedPercent?: number;
45
67
  universeFleetSpeed?: number;
68
+ deuteriumFactor?: number;
69
+ universe?: import('../types.js').UniverseShape;
46
70
  drives?: import('../types.js').Drives;
47
71
  roundTrip?: boolean;
48
72
  }): {
@@ -53,5 +77,5 @@ declare function getTrip(fleet: import('../types.js').FleetEntry[], origin: impo
53
77
  cargo: number;
54
78
  cargoAfterFuel: number;
55
79
  };
56
- export { getFlightTime, getFuelConsumption, getTrip };
80
+ export { getFlightTime, getFuelConsumption, getTrip, MAX_FUEL_REDUCTION, };
57
81
  //# sourceMappingURL=flight.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"flight.d.ts","sourceRoot":"","sources":["../../src/fleets/flight.js"],"names":[],"mappings":"AASA;;;;;;;;;;GAUG;AACH,iBAAS,aAAa,CAAC,QAAQ,EANpB,MAMoB,EAAE,UAAU,EALhC,MAKgC,EAAE,YAAY,AAJtD,CACA,EADQ,MAIoD,EAAE,kBAAkB,AAHhF,CACA,EADQ,MAG4E,GAF1E,MAAM,CAYlB;AAED;;;;;;;;;;;GAWG;AACH,iBAAS,kBAAkB,CAAC,KAAK,EAPtB,OAAO,aAAa,EAAE,UAAU,EAOV,EAAE,QAAQ,EANhC,MAMgC,EAAE,YAAY,AALtD,CACA,EADQ,MAKoD,EAAE,MAAM,AAJpE,CAEA,EAFQ,OAAO,aAAa,EAAE,MAI2C,GAF/D,MAAM,CAmBlB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,iBAAS,OAAO,CAAC,KAAK,EAdX,OAAO,aAAa,EAAE,UAAU,EAcrB,EAAE,MAAM,EAbnB,OAAO,aAAa,EAAE,WAaH,EAAE,MAAM,EAZ3B,OAAO,aAAa,EAAE,WAYK,EAAE,OAAO,AAX5C,CAKA,EAJA;IAAyB,YAAY,AAArC,CACA,EADQ,MAAM,CACd;IAAyB,kBAAkB,AAA3C,CACA,EADQ,MAAM,CACd;IAA+C,MAAM,AAArD,CACA,EADQ,OAAO,aAAa,EAAE,MAAM,CACpC;IAA0B,SAAS,AAAnC,CACA,EADQ,OAAO,CACf;CAMiD,GANvC;IACR,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IACrE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;CACvC,CAyBH;AAED,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"flight.d.ts","sourceRoot":"","sources":["../../src/fleets/flight.js"],"names":[],"mappings":"AAGA,mEAAmE;AACnE,QAAA,MAAM,kBAAkB,MAAM,CAAC;AAQ/B;;;;;;;;;;;;GAYG;AACH,iBAAS,aAAa,CAAC,QAAQ,EANpB,MAMoB,EAAE,UAAU,EALhC,MAKgC,EAAE,YAAY,AAJtD,CACA,EADQ,MAIoD,EAAE,kBAAkB,AAHhF,CACA,EADQ,MAG4E,GAF1E,MAAM,CAYlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,iBAAS,kBAAkB,CAAC,KAAK,EAVtB,OAAO,aAAa,EAAE,UAAU,EAUV,EAAE,QAAQ,EAThC,MASgC,EAAE,YAAY,AARtD,CACA,EADQ,MAQoD,EAAE,MAAM,AAPpE,CAEA,EAFQ,OAAO,aAAa,EAAE,MAO2C,EAAE,OAAO,AALlF,CAGA,EAFA;IAAyB,eAAe,AAAxC,CAEA,EAFQ,MAAM,CAEd;CAEuF,GAF7E,MAAM,CAgClB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,iBAAS,OAAO,CAAC,KAAK,EAjBX,OAAO,aAAa,EAAE,UAAU,EAiBrB,EAAE,MAAM,EAhBnB,OAAO,aAAa,EAAE,WAgBH,EAAE,MAAM,EAf3B,OAAO,aAAa,EAAE,WAeK,EAAE,OAAO,AAd5C,CAQA,EAPA;IAAyB,YAAY,AAArC,CACA,EADQ,MAAM,CACd;IAAyB,kBAAkB,AAA3C,CACA,EADQ,MAAM,CACd;IAAyB,eAAe,AAAxC,CACA,EADQ,MAAM,CACd;IAAsD,QAAQ,AAA9D,CAEA,EAFQ,OAAO,aAAa,EAAE,aAAa,CAE3C;IAA+C,MAAM,AAArD,CACA,EADQ,OAAO,aAAa,EAAE,MAAM,CACpC;IAA0B,SAAS,AAAnC,CACA,EADQ,OAAO,CACf;CAMiD,GANvC;IACR,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IACrE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;CACvC,CA4BH;AAED,OAAO,EACL,aAAa,EAAE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,GAC/D,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import getDebris from './getDebris.js';
2
2
  import getDistance from './distance.js';
3
3
  import getShipSpeed, { getActiveDrive, getFleetSpeed } from './speed.js';
4
- import { getFlightTime, getFuelConsumption, getTrip } from './flight.js';
4
+ import { getFlightTime, getFuelConsumption, getTrip, MAX_FUEL_REDUCTION } from './flight.js';
5
5
  import simulateCombat, { DEFAULT_REPAIR_FACTOR, DEFAULT_PLUNDER_RATIO } from './combat.js';
6
6
  import { getCombatStatistics, simulateCombats, DEFAULT_RUNS } from './combatStatistics.js';
7
7
  import { getWaveChance, getMoonbreakWaves, getMoonbreakChance, getMoonbreakLosses, MIN_MOON_SIZE, MAX_MOON_SIZE, WAVES_PER_ATTACKER } from './moonbreak.js';
@@ -28,6 +28,6 @@ declare const Fleets: {
28
28
  getCargoCapacity: typeof getCargoCapacity;
29
29
  getMoonLockShips: typeof getMoonLockShips;
30
30
  };
31
- export { MIN_MOON_SIZE, MAX_MOON_SIZE, WAVES_PER_ATTACKER, EXPEDITION_FIND_TIERS, EXPEDITION_TOP_TIER_BASE, MOON_DEBRIS_THRESHOLD, MAX_MOON_CHANCE, DEFAULT_REPAIR_FACTOR, DEFAULT_PLUNDER_RATIO, DEFAULT_RUNS, };
31
+ export { MIN_MOON_SIZE, MAX_MOON_SIZE, WAVES_PER_ATTACKER, EXPEDITION_FIND_TIERS, EXPEDITION_TOP_TIER_BASE, MOON_DEBRIS_THRESHOLD, MAX_MOON_CHANCE, MAX_FUEL_REDUCTION, DEFAULT_REPAIR_FACTOR, DEFAULT_PLUNDER_RATIO, DEFAULT_RUNS, };
32
32
  export default Fleets;
33
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fleets/index.js"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,YAAY,EAAE,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,cAAc,EAAE,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEzF,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;CAoBX,CAAC;AAEF,OAAO,EACL,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,GACb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fleets/index.js"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,YAAY,EAAE,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EACL,aAAa,EAAE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,EAC/D,MAAM,aAAa,CAAC;AACrB,OAAO,cAAc,EAAE,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEzF,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;CAoBX,CAAC;AAEF,OAAO,EACL,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,GACb,CAAC;eAEa,MAAM"}
@@ -24,11 +24,15 @@ declare const DRIVE_RESEARCH: Readonly<{
24
24
  * A few ships switch to a better drive once the matching technology is high
25
25
  * enough — a small cargo moves to the impulse drive at Impulse 5. When several
26
26
  * drives are available the ship uses whichever ends up fastest.
27
+ *
28
+ * `bonus` adds to the drive bonus, as a share of the base speed: the class
29
+ * bonus that doubles a ship's speed is 1, a 5% life form bonus 0.05.
27
30
  * @param {import('../types.js').DestroyableEntry} ship An entry of models/destroyable.js
28
31
  * @param {import('../types.js').Drives} [drives] Drive levels
32
+ * @param {number} [bonus] Extra speed, as a share of the base speed
29
33
  * @returns {{drive: string, speed: number, fuelConsumption: number}} The active drive
30
34
  */
31
- declare function getActiveDrive(ship: import('../types.js').DestroyableEntry, drives?: import('../types.js').Drives): {
35
+ declare function getActiveDrive(ship: import('../types.js').DestroyableEntry, drives?: import('../types.js').Drives, bonus?: number): {
32
36
  drive: string;
33
37
  speed: number;
34
38
  fuelConsumption: number;
@@ -38,12 +42,15 @@ declare function getActiveDrive(ship: import('../types.js').DestroyableEntry, dr
38
42
  * Return the speed of a ship, drive technologies included
39
43
  * @param {import('../types.js').DestroyableEntry} ship An entry of models/destroyable.js
40
44
  * @param {import('../types.js').Drives} [drives] Drive levels
45
+ * @param {number} [bonus] Extra speed, as a share of the base speed (class, life forms)
41
46
  * @returns {number} The speed the ship flies at
42
47
  */
43
- declare function getShipSpeed(ship: import('../types.js').DestroyableEntry, drives?: import('../types.js').Drives): number;
48
+ declare function getShipSpeed(ship: import('../types.js').DestroyableEntry, drives?: import('../types.js').Drives, bonus?: number): number;
44
49
  /**
45
50
  *
46
51
  * Return the speed of a whole fleet, which is the speed of its slowest ship
52
+ *
53
+ * Each entry may carry its own `speedBonus` (class, life forms).
47
54
  * @param {import('../types.js').FleetEntry[]} fleet The ships taking off
48
55
  * @param {import('../types.js').Drives} [drives] Drive levels
49
56
  * @returns {number} The fleet speed
@@ -1 +1 @@
1
- {"version":3,"file":"speed.d.ts","sourceRoot":"","sources":["../../src/fleets/speed.js"],"names":[],"mappings":"AAEA,QAAA,MAAQ,MAAM;;;;;CAAe,CAAC;AAE9B,+DAA+D;AAC/D,QAAA,MAAM,WAAW;IACf,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;IACxB,CAAC,MAAM,CAAC,OAAO,CAAC,MAAK;IACrB,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;IACxB,CAAC,MAAM,CAAC,IAAI,CAAC,IAAG;EAChB,CAAC;AAEH,sEAAsE;AACtE,QAAA,MAAM,cAAc;IAClB,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;IACxB,CAAC,MAAM,CAAC,OAAO,CAAC,MAAK;IACrB,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;EACxB,CAAC;AAsBH;;;;;;;;;;GAUG;AACH,iBAAS,cAAc,CAAC,IAAI,EAJjB,OAAO,aAAa,EAAE,gBAIL,EAAE,MAAM,AAHjC,CACA,EADQ,OAAO,aAAa,EAAE,MAGQ,GAF5B;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAC,CAoBnE;AAED;;;;;;GAMG;AACH,iBAAS,YAAY,CAAC,IAAI,EAJf,OAAO,aAAa,EAAE,gBAIP,EAAE,MAAM,AAH/B,CACA,EADQ,OAAO,aAAa,EAAE,MAGM,GAF1B,MAAM,CAIlB;AAED;;;;;;GAMG;AACH,iBAAS,aAAa,CAAC,KAAK,EAJjB,OAAO,aAAa,EAAE,UAAU,EAIf,EAAE,MAAM,AAHjC,CACA,EADQ,OAAO,aAAa,EAAE,MAGQ,GAF5B,MAAM,CAgBlB;AAED,OAAO,EACL,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,GAC3D,CAAC;eACa,YAAY"}
1
+ {"version":3,"file":"speed.d.ts","sourceRoot":"","sources":["../../src/fleets/speed.js"],"names":[],"mappings":"AAEA,QAAA,MAAQ,MAAM;;;;;CAAe,CAAC;AAE9B,+DAA+D;AAC/D,QAAA,MAAM,WAAW;IACf,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;IACxB,CAAC,MAAM,CAAC,OAAO,CAAC,MAAK;IACrB,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;IACxB,CAAC,MAAM,CAAC,IAAI,CAAC,IAAG;EAChB,CAAC;AAEH,sEAAsE;AACtE,QAAA,MAAM,cAAc;IAClB,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;IACxB,CAAC,MAAM,CAAC,OAAO,CAAC,MAAK;IACrB,CAAC,MAAM,CAAC,UAAU,CAAC,MAAK;EACxB,CAAC;AA4BH;;;;;;;;;;;;;;GAcG;AACH,iBAAS,cAAc,CAAC,IAAI,EALjB,OAAO,aAAa,EAAE,gBAKL,EAAE,MAAM,AAJjC,CACA,EADQ,OAAO,aAAa,EAAE,MAIQ,EAAE,KAAK,AAH7C,CACA,EADQ,MAGyC,GAFvC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAC,CAsBnE;AAED;;;;;;;GAOG;AACH,iBAAS,YAAY,CAAC,IAAI,EALf,OAAO,aAAa,EAAE,gBAKP,EAAE,MAAM,AAJ/B,CACA,EADQ,OAAO,aAAa,EAAE,MAIM,EAAE,KAAK,AAH3C,CACA,EADQ,MAGuC,GAFrC,MAAM,CAIlB;AAED;;;;;;;;GAQG;AACH,iBAAS,aAAa,CAAC,KAAK,EAJjB,OAAO,aAAa,EAAE,UAAU,EAIf,EAAE,MAAM,AAHjC,CACA,EADQ,OAAO,aAAa,EAAE,MAGQ,GAF5B,MAAM,CAgBlB;AAED,OAAO,EACL,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,GAC3D,CAAC;eACa,YAAY"}
package/types/types.d.ts CHANGED
@@ -283,6 +283,35 @@ export type FleetEntry = {
283
283
  * How many of them
284
284
  */
285
285
  count: number;
286
+ /**
287
+ * Extra speed, as a share of the ship's base
288
+ * speed: 1 for the class bonus that doubles it, 0.05 for a 5% life form bonus,
289
+ * summed
290
+ */
291
+ speedBonus?: number;
292
+ /**
293
+ * Deuterium saved, as a share: the General's
294
+ * class discount plus the life form one, capped at 0.9 like the game does
295
+ */
296
+ fuelReduction?: number;
297
+ };
298
+ export type UniverseShape = {
299
+ /**
300
+ * The number of galaxies
301
+ */
302
+ galaxies?: number;
303
+ /**
304
+ * The number of systems per galaxy
305
+ */
306
+ systems?: number;
307
+ /**
308
+ * Whether the last galaxy touches the first
309
+ */
310
+ donutGalaxy?: boolean;
311
+ /**
312
+ * Whether the last system touches the first
313
+ */
314
+ donutSystem?: boolean;
286
315
  };
287
316
  export type Drives = {
288
317
  /**
@@ -426,6 +455,18 @@ export type Resources = {
426
455
  * @typedef {object} FleetEntry A group of identical ships
427
456
  * @property {DestroyableEntry} ship The ship
428
457
  * @property {number} count How many of them
458
+ * @property {number} [speedBonus] Extra speed, as a share of the ship's base
459
+ * speed: 1 for the class bonus that doubles it, 0.05 for a 5% life form bonus,
460
+ * summed
461
+ * @property {number} [fuelReduction] Deuterium saved, as a share: the General's
462
+ * class discount plus the life form one, capped at 0.9 like the game does
463
+ */
464
+ /**
465
+ * @typedef {object} UniverseShape How the universe wraps around
466
+ * @property {number} [galaxies] The number of galaxies
467
+ * @property {number} [systems] The number of systems per galaxy
468
+ * @property {boolean} [donutGalaxy] Whether the last galaxy touches the first
469
+ * @property {boolean} [donutSystem] Whether the last system touches the first
429
470
  */
430
471
  /**
431
472
  * @typedef {object} Drives The drive technology levels
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.js"],"names":[],"mappings":"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"}