powergrid-engine 1.9.7 → 1.10.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.
@@ -201,7 +201,26 @@ function availableMoves(G, player) {
201
201
  ? G.map.cities.map((c) => ({ name: c.name, price: 0 }))
202
202
  : dijkstra(G, player).map((c) => ({ name: c.name, price: c.price }));
203
203
  toBuild.forEach((city) => {
204
+ const cityData = G.map.cities.find((c) => c.name == city.name);
204
205
  const othersCount = G.players.filter((p) => p.cities.find((c) => city.name == c.name)).length;
206
+ // Transregional cities (e.g. Strasbourg on Baden-Württemberg) are only open
207
+ // in Step 2 onward. The slot fee is replaced by a flat 15 (Step 2) or 20
208
+ // (Step 3); the dijkstra connection cost from the player's existing network
209
+ // is still paid on top.
210
+ if (cityData.transregional) {
211
+ if (G.step < 2) {
212
+ city.price = 9999;
213
+ return;
214
+ }
215
+ city.price += G.step == 3 ? 20 : 15;
216
+ if (othersCount == G.step) {
217
+ city.price = 9999;
218
+ }
219
+ if (player.cities.find((c) => c.name == city.name)) {
220
+ city.price = 9999;
221
+ }
222
+ return;
223
+ }
205
224
  city.price += 10 + othersCount * 5;
206
225
  if (othersCount == G.step) {
207
226
  city.price = 9999;
@@ -17,6 +17,7 @@ const randomizeMap_1 = require("./randomizeMap");
17
17
  const utils_1 = require("./utils");
18
18
  exports.playerColors = ['limegreen', 'mediumorchid', 'red', 'dodgerblue', 'yellow', 'brown'];
19
19
  const citiesToStep2 = [10, 7, 7, 7, 6];
20
+ const citiesToStep2BadenWurttemberg = [9, 6, 6, 6, 5];
20
21
  const citiesToEndGame = [21, 17, 17, 15, 14];
21
22
  const cityIncome = [10, 22, 33, 44, 54, 64, 73, 82, 90, 98, 105, 112, 118, 124, 129, 134, 138, 142, 145, 148, 150, 150];
22
23
  const regionsInPlay = [3, 3, 4, 5, 5];
@@ -279,7 +280,9 @@ function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original',
279
280
  seed,
280
281
  round: 1,
281
282
  auctionSkips: 0,
282
- citiesToStep2: citiesToStep2[numPlayers - 2],
283
+ citiesToStep2: (forceMap || finalMap).name == 'Baden-Württemberg'
284
+ ? citiesToStep2BadenWurttemberg[numPlayers - 2]
285
+ : citiesToStep2[numPlayers - 2],
283
286
  citiesToEndGame: citiesToEndGame[numPlayers - 2],
284
287
  resourceResupply: [
285
288
  `[${coalResupply[p][0]}, ${oilResupply[p][0]}, ${garbageResupply[p][0]}, ${uraniumResupply[p][0]}]`,
@@ -289,7 +292,10 @@ function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original',
289
292
  paymentTable: cityIncome,
290
293
  variant,
291
294
  minimunBid: 0,
292
- plantDiscountActive: variant == 'recharged' && (forceMap || finalMap).name != 'China' && (forceMap || finalMap).name != 'Russia',
295
+ plantDiscountActive: variant == 'recharged' &&
296
+ (forceMap || finalMap).name != 'China' &&
297
+ (forceMap || finalMap).name != 'Russia' &&
298
+ (forceMap || finalMap).name != 'Baden-Württemberg',
293
299
  discardSmallestPlant: false,
294
300
  cardsLeft: powerPlantsDeck.length,
295
301
  nextCardWeak: variant == 'recharged',
@@ -457,12 +463,27 @@ function move(G, move, playerNumber, isUndo = false) {
457
463
  G.options.variant == 'original' &&
458
464
  G.map.name != 'China' &&
459
465
  G.map.name != 'Russia') {
460
- G.log.push({
461
- type: 'event',
462
- event: `Everyone passed, removing lowest numbered Power Plant (${G.actualMarket[0].number}).`,
463
- });
464
- G.actualMarket.shift();
465
- addPowerPlant(G);
466
+ if (G.map.name == 'Baden-Württemberg') {
467
+ // Baden-Württemberg: remove the two lowest plants
468
+ const removed = [];
469
+ for (let i = 0; i < 2 && G.actualMarket.length > 0; i++) {
470
+ removed.push(G.actualMarket[0].number);
471
+ G.actualMarket.shift();
472
+ addPowerPlant(G);
473
+ }
474
+ G.log.push({
475
+ type: 'event',
476
+ event: `Everyone passed, removing the two lowest numbered Power Plants (${removed.join(', ')}).`,
477
+ });
478
+ }
479
+ else {
480
+ G.log.push({
481
+ type: 'event',
482
+ event: `Everyone passed, removing lowest numbered Power Plant (${G.actualMarket[0].number}).`,
483
+ });
484
+ G.actualMarket.shift();
485
+ addPowerPlant(G);
486
+ }
466
487
  }
467
488
  toResourcesPhase(G);
468
489
  }
@@ -742,7 +763,10 @@ function move(G, move, playerNumber, isUndo = false) {
742
763
  addPowerPlant(G);
743
764
  }
744
765
  G.round++;
745
- setPlayerOrder(G);
766
+ if (G.map.name != 'Baden-Württemberg') {
767
+ // Baden-Württemberg: player order is determined AFTER the auction phase, not before it.
768
+ setPlayerOrder(G);
769
+ }
746
770
  G.players.forEach((p) => {
747
771
  p.passed = p.isDropped;
748
772
  });
@@ -753,7 +777,10 @@ function move(G, move, playerNumber, isUndo = false) {
753
777
  G.step = 3;
754
778
  }
755
779
  G.plantDiscountActive =
756
- G.options.variant == 'recharged' && G.map.name != 'China' && G.map.name != 'Russia';
780
+ G.options.variant == 'recharged' &&
781
+ G.map.name != 'China' &&
782
+ G.map.name != 'Russia' &&
783
+ G.map.name != 'Baden-Württemberg';
757
784
  setCurrentPlayer(G, G.playerOrder[0]);
758
785
  }
759
786
  else {
@@ -1023,7 +1050,8 @@ function move(G, move, playerNumber, isUndo = false) {
1023
1050
  if (G.actualMarket.length > 0 &&
1024
1051
  player.cities.length >= G.actualMarket[0].number &&
1025
1052
  G.map.name != 'China' &&
1026
- G.map.name != 'Russia') {
1053
+ G.map.name != 'Russia' &&
1054
+ G.map.name != 'Baden-Württemberg') {
1027
1055
  G.actualMarket.shift();
1028
1056
  addPowerPlant(G);
1029
1057
  }
@@ -1699,6 +1727,10 @@ function isValid(player, powerPlants) {
1699
1727
  return true;
1700
1728
  }
1701
1729
  function toResourcesPhase(G) {
1730
+ if (G.map.name == 'Baden-Württemberg') {
1731
+ // Baden-Württemberg: player order is determined AFTER the auction phase, every round.
1732
+ setPlayerOrder(G);
1733
+ }
1702
1734
  G.players.forEach((p) => {
1703
1735
  p.bid = 0;
1704
1736
  p.passed = p.isDropped;
@@ -10,14 +10,14 @@ export declare enum Cities {
10
10
  Friedrichshafen = "Friedrichshafen",
11
11
  Ravensburg = "Ravensburg",
12
12
  Biberach = "Biberach",
13
- Sigmarincen = "Sigmarincen",
13
+ Sigmarincen = "Sigmaringen",
14
14
  Konstanz = "Konstanz",
15
15
  Ulm = "Ulm",
16
16
  Augsburg = "Augsburg",
17
17
  Basel = "Basel",
18
- Waldshuttiencen = "Waldshut-Tiencen",
18
+ Waldshuttiencen = "Waldshut-Tiengen",
19
19
  Singen = "Singen",
20
- Tuttlincen = "Tuttlincen",
20
+ Tuttlincen = "Tuttlingen",
21
21
  Donaueschingen = "Donaueschingen",
22
22
  Freiburg = "Freiburg",
23
23
  Lorrach = "Lorrach",
@@ -25,22 +25,22 @@ export declare enum Cities {
25
25
  Schwabischhall = "Schwabisch Hall",
26
26
  Heilbronn = "Heilbronn",
27
27
  Sinsheim = "Sinsheim",
28
- Heidelber = "Heidelber",
28
+ Heidelber = "Heidelberg",
29
29
  Mannheim = "Mannheim",
30
- Luowigshafen = "Luowigshafen",
30
+ Luowigshafen = "Ludwigshafen",
31
31
  Nurnberg = "Nurnberg",
32
32
  Ellwangen = "Ellwangen",
33
- Coppingen = "Coppingen",
34
- Reutlincen = "Reutlincen",
33
+ Coppingen = "G\u00F6ppingen",
34
+ Reutlincen = "Reutlingen",
35
35
  Stuttgart = "Stuttgart",
36
36
  Ludwigsburg = "Ludwigsburg",
37
37
  Boblingen = "Boblingen",
38
- Laha = "Laha",
38
+ Laha = "Lahr",
39
39
  Badenbaden = "Baden-Baden",
40
40
  Offenburg = "Offenburg",
41
41
  Strasbourg = "Strasbourg",
42
42
  Pforzheim = "Pforzheim",
43
43
  Rastatt = "Rastatt",
44
- Karlsruhf = "Karlsruhf"
44
+ Karlsruhf = "Karlsruhe"
45
45
  }
46
46
  export declare const map: GameMap;
@@ -14,14 +14,14 @@ var Cities;
14
14
  Cities["Friedrichshafen"] = "Friedrichshafen";
15
15
  Cities["Ravensburg"] = "Ravensburg";
16
16
  Cities["Biberach"] = "Biberach";
17
- Cities["Sigmarincen"] = "Sigmarincen";
17
+ Cities["Sigmarincen"] = "Sigmaringen";
18
18
  Cities["Konstanz"] = "Konstanz";
19
19
  Cities["Ulm"] = "Ulm";
20
20
  Cities["Augsburg"] = "Augsburg";
21
21
  Cities["Basel"] = "Basel";
22
- Cities["Waldshuttiencen"] = "Waldshut-Tiencen";
22
+ Cities["Waldshuttiencen"] = "Waldshut-Tiengen";
23
23
  Cities["Singen"] = "Singen";
24
- Cities["Tuttlincen"] = "Tuttlincen";
24
+ Cities["Tuttlincen"] = "Tuttlingen";
25
25
  Cities["Donaueschingen"] = "Donaueschingen";
26
26
  Cities["Freiburg"] = "Freiburg";
27
27
  Cities["Lorrach"] = "Lorrach";
@@ -29,23 +29,23 @@ var Cities;
29
29
  Cities["Schwabischhall"] = "Schwabisch Hall";
30
30
  Cities["Heilbronn"] = "Heilbronn";
31
31
  Cities["Sinsheim"] = "Sinsheim";
32
- Cities["Heidelber"] = "Heidelber";
32
+ Cities["Heidelber"] = "Heidelberg";
33
33
  Cities["Mannheim"] = "Mannheim";
34
- Cities["Luowigshafen"] = "Luowigshafen";
34
+ Cities["Luowigshafen"] = "Ludwigshafen";
35
35
  Cities["Nurnberg"] = "Nurnberg";
36
36
  Cities["Ellwangen"] = "Ellwangen";
37
- Cities["Coppingen"] = "Coppingen";
38
- Cities["Reutlincen"] = "Reutlincen";
37
+ Cities["Coppingen"] = "G\u00F6ppingen";
38
+ Cities["Reutlincen"] = "Reutlingen";
39
39
  Cities["Stuttgart"] = "Stuttgart";
40
40
  Cities["Ludwigsburg"] = "Ludwigsburg";
41
41
  Cities["Boblingen"] = "Boblingen";
42
- Cities["Laha"] = "Laha";
42
+ Cities["Laha"] = "Lahr";
43
43
  Cities["Badenbaden"] = "Baden-Baden";
44
44
  Cities["Offenburg"] = "Offenburg";
45
45
  Cities["Strasbourg"] = "Strasbourg";
46
46
  Cities["Pforzheim"] = "Pforzheim";
47
47
  Cities["Rastatt"] = "Rastatt";
48
- Cities["Karlsruhf"] = "Karlsruhf";
48
+ Cities["Karlsruhf"] = "Karlsruhe";
49
49
  })(Cities = exports.Cities || (exports.Cities = {}));
50
50
  exports.map = {
51
51
  name: 'Baden-Württemberg',
@@ -56,8 +56,8 @@ exports.map = {
56
56
  { name: Cities.Sigmarincen, region: Regions.Purple, x: 1111, y: 1803 },
57
57
  { name: Cities.Konstanz, region: Regions.Purple, x: 1088, y: 2163 },
58
58
  { name: Cities.Ulm, region: Regions.Purple, x: 1541, y: 1499 },
59
- { name: Cities.Augsburg, region: Regions.Purple, x: 1830, y: 1505 },
60
- { name: Cities.Basel, region: Regions.Green, x: 103, y: 2271 },
59
+ { name: Cities.Augsburg, region: Regions.Purple, x: 1830, y: 1505, transregional: true },
60
+ { name: Cities.Basel, region: Regions.Green, x: 103, y: 2271, transregional: true },
61
61
  { name: Cities.Waldshuttiencen, region: Regions.Green, x: 502, y: 2166 },
62
62
  { name: Cities.Singen, region: Regions.Green, x: 874, y: 2084 },
63
63
  { name: Cities.Tuttlincen, region: Regions.Green, x: 870, y: 1854 },
@@ -70,8 +70,8 @@ exports.map = {
70
70
  { name: Cities.Sinsheim, region: Regions.Red, x: 920, y: 785 },
71
71
  { name: Cities.Heidelber, region: Regions.Red, x: 817, y: 660 },
72
72
  { name: Cities.Mannheim, region: Regions.Red, x: 710, y: 540 },
73
- { name: Cities.Luowigshafen, region: Regions.Red, x: 579, y: 588 },
74
- { name: Cities.Nurnberg, region: Regions.Blue, x: 1837, y: 771 },
73
+ { name: Cities.Luowigshafen, region: Regions.Red, x: 579, y: 588, transregional: true },
74
+ { name: Cities.Nurnberg, region: Regions.Blue, x: 1837, y: 771, transregional: true },
75
75
  { name: Cities.Ellwangen, region: Regions.Blue, x: 1637, y: 1030 },
76
76
  { name: Cities.Coppingen, region: Regions.Blue, x: 1387, y: 1233 },
77
77
  { name: Cities.Reutlincen, region: Regions.Blue, x: 1107, y: 1443 },
@@ -81,7 +81,7 @@ exports.map = {
81
81
  { name: Cities.Laha, region: Regions.Yellow, x: 296, y: 1575 },
82
82
  { name: Cities.Badenbaden, region: Regions.Yellow, x: 554, y: 1259 },
83
83
  { name: Cities.Offenburg, region: Regions.Yellow, x: 395, y: 1422 },
84
- { name: Cities.Strasbourg, region: Regions.Yellow, x: 211, y: 1330 },
84
+ { name: Cities.Strasbourg, region: Regions.Yellow, x: 211, y: 1330, transregional: true },
85
85
  { name: Cities.Pforzheim, region: Regions.Yellow, x: 794, y: 1095 },
86
86
  { name: Cities.Rastatt, region: Regions.Yellow, x: 509, y: 1109 },
87
87
  { name: Cities.Karlsruhf, region: Regions.Yellow, x: 638, y: 974 },
@@ -160,4 +160,43 @@ exports.map = {
160
160
  layout: 'Portrait',
161
161
  adjustRatio: [0.425, 0.425],
162
162
  mapPosition: [100, -90],
163
+ resupply: [
164
+ // Coal
165
+ [
166
+ [3, 4, 3],
167
+ [4, 5, 3],
168
+ [5, 6, 4],
169
+ [5, 7, 5],
170
+ [7, 9, 6], // 6P
171
+ ],
172
+ // Oil
173
+ [
174
+ [2, 2, 4],
175
+ [2, 3, 4],
176
+ [3, 4, 5],
177
+ [4, 5, 6],
178
+ [5, 6, 7],
179
+ ],
180
+ // Garbage
181
+ [
182
+ [1, 2, 3],
183
+ [1, 2, 3],
184
+ [2, 3, 4],
185
+ [3, 3, 5],
186
+ [3, 5, 6],
187
+ ],
188
+ // Uranium
189
+ [
190
+ [1, 1, 1],
191
+ [1, 1, 1],
192
+ [1, 2, 2],
193
+ [2, 3, 2],
194
+ [2, 3, 3],
195
+ ],
196
+ ],
197
+ mapSpecificRules: 'Phase order change: buy power plants first, then determine player order. ' +
198
+ 'If no power plant is sold in a round, remove the two lowest-numbered plants from the market and replace them from the draw stack. ' +
199
+ 'Never remove a power plant whose number is equal to or lower than the number of cities any player has powered. ' +
200
+ 'Transregional cities (e.g. Strasbourg) are only available starting in Step 2. ' +
201
+ 'Step 2 begins when any player connects to 9 cities (2 players), 6 cities (3–5 players), or 5 cities (6 players).',
163
202
  };
@@ -5,6 +5,7 @@ export interface City {
5
5
  region: string;
6
6
  x: number;
7
7
  y: number;
8
+ transregional?: boolean;
8
9
  }
9
10
  export interface Connection {
10
11
  nodes: string[];
package/dist/src/maps.js CHANGED
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mapsRecharged = exports.maps = void 0;
4
4
  const america_1 = require("./maps/america");
5
+ // import { map as australia } from './maps/australia';
6
+ const badenwurttemberg_1 = require("./maps/badenwurttemberg");
5
7
  const benelux_1 = require("./maps/benelux");
6
8
  const brazil_1 = require("./maps/brazil");
7
9
  const centraleurope_1 = require("./maps/centraleurope");
@@ -28,8 +30,8 @@ exports.maps = [
28
30
  benelux_1.map,
29
31
  russia_1.map,
30
32
  centraleurope_1.map,
33
+ badenwurttemberg_1.map,
31
34
  // australia,
32
- // badenwurttemberg,
33
35
  // japan,
34
36
  // korea,
35
37
  // northerneurope,
@@ -50,8 +52,8 @@ exports.mapsRecharged = [
50
52
  benelux_1.map,
51
53
  russia_1.map,
52
54
  centraleurope_1.map,
55
+ badenwurttemberg_1.map,
53
56
  // australia,
54
- // badenwurttemberg,
55
57
  // china,
56
58
  // japan,
57
59
  // korea,
package/package.json CHANGED
@@ -1,11 +1,19 @@
1
1
  {
2
2
  "name": "powergrid-engine",
3
- "version": "1.9.7",
3
+ "version": "1.10.0",
4
4
  "description": "An engine for Power Grid",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.ts",
7
7
  "source": "index.ts",
8
- "repository": "git@github.com:LucasAMello/powergrid-engine.git",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/boardgamers/powergrid.git",
11
+ "directory": "engine"
12
+ },
13
+ "homepage": "https://github.com/boardgamers/powergrid#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/boardgamers/powergrid/issues"
16
+ },
9
17
  "publishConfig": {
10
18
  "access": "public"
11
19
  },
@@ -256,7 +256,30 @@ export function availableMoves(G: GameState, player: Player): AvailableMoves {
256
256
  : dijkstra(G, player).map((c) => ({ name: c.name, price: c.price }));
257
257
 
258
258
  toBuild.forEach((city) => {
259
+ const cityData = G.map.cities.find((c) => c.name == city.name)!;
259
260
  const othersCount = G.players.filter((p) => p.cities.find((c) => city.name == c.name)).length;
261
+
262
+ // Transregional cities (e.g. Strasbourg on Baden-Württemberg) are only open
263
+ // in Step 2 onward. The slot fee is replaced by a flat 15 (Step 2) or 20
264
+ // (Step 3); the dijkstra connection cost from the player's existing network
265
+ // is still paid on top.
266
+ if (cityData.transregional) {
267
+ if (G.step < 2) {
268
+ city.price = 9999;
269
+ return;
270
+ }
271
+ city.price += G.step == 3 ? 20 : 15;
272
+
273
+ if (othersCount == G.step) {
274
+ city.price = 9999;
275
+ }
276
+
277
+ if (player.cities.find((c) => c.name == city.name)) {
278
+ city.price = 9999;
279
+ }
280
+ return;
281
+ }
282
+
260
283
  city.price += 10 + othersCount * 5;
261
284
 
262
285
  if (othersCount == G.step) {
package/src/engine.ts CHANGED
@@ -14,6 +14,7 @@ import { asserts, shuffle } from './utils';
14
14
  export const playerColors = ['limegreen', 'mediumorchid', 'red', 'dodgerblue', 'yellow', 'brown'];
15
15
 
16
16
  const citiesToStep2 = [10, 7, 7, 7, 6];
17
+ const citiesToStep2BadenWurttemberg = [9, 6, 6, 6, 5];
17
18
  const citiesToEndGame = [21, 17, 17, 15, 14];
18
19
  const cityIncome = [10, 22, 33, 44, 54, 64, 73, 82, 90, 98, 105, 112, 118, 124, 129, 134, 138, 142, 145, 148, 150, 150];
19
20
  const regionsInPlay = [3, 3, 4, 5, 5];
@@ -330,7 +331,10 @@ export function setup(
330
331
  seed,
331
332
  round: 1,
332
333
  auctionSkips: 0,
333
- citiesToStep2: citiesToStep2[numPlayers - 2],
334
+ citiesToStep2:
335
+ (forceMap || finalMap).name == 'Baden-Württemberg'
336
+ ? citiesToStep2BadenWurttemberg[numPlayers - 2]
337
+ : citiesToStep2[numPlayers - 2],
334
338
  citiesToEndGame: citiesToEndGame[numPlayers - 2],
335
339
  resourceResupply: [
336
340
  `[${coalResupply[p][0]}, ${oilResupply[p][0]}, ${garbageResupply[p][0]}, ${uraniumResupply[p][0]}]`,
@@ -341,7 +345,10 @@ export function setup(
341
345
  variant,
342
346
  minimunBid: 0,
343
347
  plantDiscountActive:
344
- variant == 'recharged' && (forceMap || finalMap).name != 'China' && (forceMap || finalMap).name != 'Russia',
348
+ variant == 'recharged' &&
349
+ (forceMap || finalMap).name != 'China' &&
350
+ (forceMap || finalMap).name != 'Russia' &&
351
+ (forceMap || finalMap).name != 'Baden-Württemberg',
345
352
  discardSmallestPlant: false,
346
353
  cardsLeft: powerPlantsDeck.length,
347
354
  nextCardWeak: variant == 'recharged',
@@ -545,13 +552,29 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
545
552
  G.map.name != 'China' &&
546
553
  G.map.name != 'Russia'
547
554
  ) {
548
- G.log.push({
549
- type: 'event',
550
- event: `Everyone passed, removing lowest numbered Power Plant (${G.actualMarket[0].number}).`,
551
- });
555
+ if (G.map.name == 'Baden-Württemberg') {
556
+ // Baden-Württemberg: remove the two lowest plants
557
+ const removed: number[] = [];
558
+ for (let i = 0; i < 2 && G.actualMarket.length > 0; i++) {
559
+ removed.push(G.actualMarket[0].number);
560
+ G.actualMarket.shift();
561
+ addPowerPlant(G);
562
+ }
563
+ G.log.push({
564
+ type: 'event',
565
+ event: `Everyone passed, removing the two lowest numbered Power Plants (${removed.join(
566
+ ', '
567
+ )}).`,
568
+ });
569
+ } else {
570
+ G.log.push({
571
+ type: 'event',
572
+ event: `Everyone passed, removing lowest numbered Power Plant (${G.actualMarket[0].number}).`,
573
+ });
552
574
 
553
- G.actualMarket.shift();
554
- addPowerPlant(G);
575
+ G.actualMarket.shift();
576
+ addPowerPlant(G);
577
+ }
555
578
  }
556
579
 
557
580
  toResourcesPhase(G);
@@ -882,7 +905,10 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
882
905
 
883
906
  G.round++;
884
907
 
885
- setPlayerOrder(G);
908
+ if (G.map.name != 'Baden-Württemberg') {
909
+ // Baden-Württemberg: player order is determined AFTER the auction phase, not before it.
910
+ setPlayerOrder(G);
911
+ }
886
912
 
887
913
  G.players.forEach((p) => {
888
914
  p.passed = p.isDropped;
@@ -897,7 +923,10 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
897
923
  }
898
924
 
899
925
  G.plantDiscountActive =
900
- G.options.variant == 'recharged' && G.map.name != 'China' && G.map.name != 'Russia';
926
+ G.options.variant == 'recharged' &&
927
+ G.map.name != 'China' &&
928
+ G.map.name != 'Russia' &&
929
+ G.map.name != 'Baden-Württemberg';
901
930
  setCurrentPlayer(G, G.playerOrder[0]);
902
931
  } else {
903
932
  toResourcesPhase(G);
@@ -1218,7 +1247,8 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
1218
1247
  G.actualMarket.length > 0 &&
1219
1248
  player.cities.length >= G.actualMarket[0].number &&
1220
1249
  G.map.name != 'China' &&
1221
- G.map.name != 'Russia'
1250
+ G.map.name != 'Russia' &&
1251
+ G.map.name != 'Baden-Württemberg'
1222
1252
  ) {
1223
1253
  G.actualMarket.shift();
1224
1254
  addPowerPlant(G);
@@ -1994,6 +2024,11 @@ function isValid(player: Player, powerPlants: PowerPlant[]) {
1994
2024
  }
1995
2025
 
1996
2026
  function toResourcesPhase(G: GameState) {
2027
+ if (G.map.name == 'Baden-Württemberg') {
2028
+ // Baden-Württemberg: player order is determined AFTER the auction phase, every round.
2029
+ setPlayerOrder(G);
2030
+ }
2031
+
1997
2032
  G.players.forEach((p) => {
1998
2033
  p.bid = 0;
1999
2034
  p.passed = p.isDropped;
@@ -12,14 +12,14 @@ export enum Cities {
12
12
  Friedrichshafen = 'Friedrichshafen',
13
13
  Ravensburg = 'Ravensburg',
14
14
  Biberach = 'Biberach',
15
- Sigmarincen = 'Sigmarincen',
15
+ Sigmarincen = 'Sigmaringen',
16
16
  Konstanz = 'Konstanz',
17
17
  Ulm = 'Ulm',
18
18
  Augsburg = 'Augsburg',
19
19
  Basel = 'Basel',
20
- Waldshuttiencen = 'Waldshut-Tiencen',
20
+ Waldshuttiencen = 'Waldshut-Tiengen',
21
21
  Singen = 'Singen',
22
- Tuttlincen = 'Tuttlincen',
22
+ Tuttlincen = 'Tuttlingen',
23
23
  Donaueschingen = 'Donaueschingen',
24
24
  Freiburg = 'Freiburg',
25
25
  Lorrach = 'Lorrach',
@@ -27,23 +27,23 @@ export enum Cities {
27
27
  Schwabischhall = 'Schwabisch Hall',
28
28
  Heilbronn = 'Heilbronn',
29
29
  Sinsheim = 'Sinsheim',
30
- Heidelber = 'Heidelber',
30
+ Heidelber = 'Heidelberg',
31
31
  Mannheim = 'Mannheim',
32
- Luowigshafen = 'Luowigshafen',
32
+ Luowigshafen = 'Ludwigshafen',
33
33
  Nurnberg = 'Nurnberg',
34
34
  Ellwangen = 'Ellwangen',
35
- Coppingen = 'Coppingen',
36
- Reutlincen = 'Reutlincen',
35
+ Coppingen = 'Göppingen',
36
+ Reutlincen = 'Reutlingen',
37
37
  Stuttgart = 'Stuttgart',
38
38
  Ludwigsburg = 'Ludwigsburg',
39
39
  Boblingen = 'Boblingen',
40
- Laha = 'Laha',
40
+ Laha = 'Lahr',
41
41
  Badenbaden = 'Baden-Baden',
42
42
  Offenburg = 'Offenburg',
43
43
  Strasbourg = 'Strasbourg',
44
44
  Pforzheim = 'Pforzheim',
45
45
  Rastatt = 'Rastatt',
46
- Karlsruhf = 'Karlsruhf',
46
+ Karlsruhf = 'Karlsruhe',
47
47
  }
48
48
 
49
49
  export const map: GameMap = {
@@ -55,8 +55,8 @@ export const map: GameMap = {
55
55
  { name: Cities.Sigmarincen, region: Regions.Purple, x: 1111, y: 1803 },
56
56
  { name: Cities.Konstanz, region: Regions.Purple, x: 1088, y: 2163 },
57
57
  { name: Cities.Ulm, region: Regions.Purple, x: 1541, y: 1499 },
58
- { name: Cities.Augsburg, region: Regions.Purple, x: 1830, y: 1505 },
59
- { name: Cities.Basel, region: Regions.Green, x: 103, y: 2271 },
58
+ { name: Cities.Augsburg, region: Regions.Purple, x: 1830, y: 1505, transregional: true },
59
+ { name: Cities.Basel, region: Regions.Green, x: 103, y: 2271, transregional: true },
60
60
  { name: Cities.Waldshuttiencen, region: Regions.Green, x: 502, y: 2166 },
61
61
  { name: Cities.Singen, region: Regions.Green, x: 874, y: 2084 },
62
62
  { name: Cities.Tuttlincen, region: Regions.Green, x: 870, y: 1854 },
@@ -69,8 +69,8 @@ export const map: GameMap = {
69
69
  { name: Cities.Sinsheim, region: Regions.Red, x: 920, y: 785 },
70
70
  { name: Cities.Heidelber, region: Regions.Red, x: 817, y: 660 },
71
71
  { name: Cities.Mannheim, region: Regions.Red, x: 710, y: 540 },
72
- { name: Cities.Luowigshafen, region: Regions.Red, x: 579, y: 588 },
73
- { name: Cities.Nurnberg, region: Regions.Blue, x: 1837, y: 771 },
72
+ { name: Cities.Luowigshafen, region: Regions.Red, x: 579, y: 588, transregional: true },
73
+ { name: Cities.Nurnberg, region: Regions.Blue, x: 1837, y: 771, transregional: true },
74
74
  { name: Cities.Ellwangen, region: Regions.Blue, x: 1637, y: 1030 },
75
75
  { name: Cities.Coppingen, region: Regions.Blue, x: 1387, y: 1233 },
76
76
  { name: Cities.Reutlincen, region: Regions.Blue, x: 1107, y: 1443 },
@@ -80,7 +80,7 @@ export const map: GameMap = {
80
80
  { name: Cities.Laha, region: Regions.Yellow, x: 296, y: 1575 },
81
81
  { name: Cities.Badenbaden, region: Regions.Yellow, x: 554, y: 1259 },
82
82
  { name: Cities.Offenburg, region: Regions.Yellow, x: 395, y: 1422 },
83
- { name: Cities.Strasbourg, region: Regions.Yellow, x: 211, y: 1330 },
83
+ { name: Cities.Strasbourg, region: Regions.Yellow, x: 211, y: 1330, transregional: true },
84
84
  { name: Cities.Pforzheim, region: Regions.Yellow, x: 794, y: 1095 },
85
85
  { name: Cities.Rastatt, region: Regions.Yellow, x: 509, y: 1109 },
86
86
  { name: Cities.Karlsruhf, region: Regions.Yellow, x: 638, y: 974 },
@@ -159,4 +159,44 @@ export const map: GameMap = {
159
159
  layout: 'Portrait',
160
160
  adjustRatio: [0.425, 0.425],
161
161
  mapPosition: [100, -90],
162
+ resupply: [
163
+ // Coal
164
+ [
165
+ [3, 4, 3], // 2P
166
+ [4, 5, 3], // 3P
167
+ [5, 6, 4], // 4P
168
+ [5, 7, 5], // 5P
169
+ [7, 9, 6], // 6P
170
+ ],
171
+ // Oil
172
+ [
173
+ [2, 2, 4],
174
+ [2, 3, 4],
175
+ [3, 4, 5],
176
+ [4, 5, 6],
177
+ [5, 6, 7],
178
+ ],
179
+ // Garbage
180
+ [
181
+ [1, 2, 3],
182
+ [1, 2, 3],
183
+ [2, 3, 4],
184
+ [3, 3, 5],
185
+ [3, 5, 6],
186
+ ],
187
+ // Uranium
188
+ [
189
+ [1, 1, 1],
190
+ [1, 1, 1],
191
+ [1, 2, 2],
192
+ [2, 3, 2],
193
+ [2, 3, 3],
194
+ ],
195
+ ],
196
+ mapSpecificRules:
197
+ 'Phase order change: buy power plants first, then determine player order. ' +
198
+ 'If no power plant is sold in a round, remove the two lowest-numbered plants from the market and replace them from the draw stack. ' +
199
+ 'Never remove a power plant whose number is equal to or lower than the number of cities any player has powered. ' +
200
+ 'Transregional cities (e.g. Strasbourg) are only available starting in Step 2. ' +
201
+ 'Step 2 begins when any player connects to 9 cities (2 players), 6 cities (3–5 players), or 5 cities (6 players).',
162
202
  };
package/src/maps.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import seedrandom from 'seedrandom';
2
2
  import { PowerPlant } from './gamestate';
3
3
  import { map as america, mapRecharged as americaRecharged } from './maps/america';
4
+ // import { map as australia } from './maps/australia';
5
+ import { map as badenwurttemberg } from './maps/badenwurttemberg';
4
6
  import { map as benelux } from './maps/benelux';
5
7
  import { map as brazil } from './maps/brazil';
6
8
  import { map as centraleurope } from './maps/centraleurope';
@@ -13,8 +15,6 @@ import { map as middleeast } from './maps/middleeast';
13
15
  import { map as quebec } from './maps/quebec';
14
16
  import { map as russia } from './maps/russia';
15
17
  import { map as spainportugal } from './maps/spainportugal';
16
- // import { map as australia } from './maps/australia';
17
- // import { map as badenwurttemberg } from './maps/badenwurttemberg';
18
18
  // import { map as japan } from './maps/japan';
19
19
  // import { map as korea } from './maps/korea';
20
20
  // import { map as northerneurope } from './maps/northerneurope';
@@ -26,6 +26,10 @@ export interface City {
26
26
  region: string;
27
27
  x: number;
28
28
  y: number;
29
+ // Transregional cities (e.g. Strasbourg on Baden-Württemberg) only open in Step 2,
30
+ // and connecting to them costs a fixed price (transregionalConnectionCost on the GameMap)
31
+ // instead of the normal dijkstra path cost.
32
+ transregional?: boolean;
29
33
  }
30
34
 
31
35
  export interface Connection {
@@ -89,8 +93,8 @@ export const maps: GameMap[] = [
89
93
  benelux,
90
94
  russia,
91
95
  centraleurope,
96
+ badenwurttemberg,
92
97
  // australia,
93
- // badenwurttemberg,
94
98
  // japan,
95
99
  // korea,
96
100
  // northerneurope,
@@ -112,8 +116,8 @@ export const mapsRecharged: GameMap[] = [
112
116
  benelux,
113
117
  russia,
114
118
  centraleurope,
119
+ badenwurttemberg,
115
120
  // australia,
116
- // badenwurttemberg,
117
121
  // china,
118
122
  // japan,
119
123
  // korea,