powergrid-engine 1.9.7 → 1.9.9
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/dist/src/available-moves.js +19 -0
- package/dist/src/engine.js +43 -11
- package/dist/src/maps/badenwurttemberg.d.ts +9 -9
- package/dist/src/maps/badenwurttemberg.js +53 -14
- package/dist/src/maps.d.ts +1 -0
- package/dist/src/maps.js +4 -2
- package/package.json +10 -2
- package/src/available-moves.ts +23 -0
- package/src/engine.ts +46 -11
- package/src/maps/badenwurttemberg.ts +54 -14
- package/src/maps.ts +8 -4
|
@@ -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;
|
package/dist/src/engine.js
CHANGED
|
@@ -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:
|
|
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' &&
|
|
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.
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
-
|
|
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' &&
|
|
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 = "
|
|
13
|
+
Sigmarincen = "Sigmaringen",
|
|
14
14
|
Konstanz = "Konstanz",
|
|
15
15
|
Ulm = "Ulm",
|
|
16
16
|
Augsburg = "Augsburg",
|
|
17
17
|
Basel = "Basel",
|
|
18
|
-
Waldshuttiencen = "Waldshut-
|
|
18
|
+
Waldshuttiencen = "Waldshut-Tiengen",
|
|
19
19
|
Singen = "Singen",
|
|
20
|
-
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 = "
|
|
28
|
+
Heidelber = "Heidelberg",
|
|
29
29
|
Mannheim = "Mannheim",
|
|
30
|
-
Luowigshafen = "
|
|
30
|
+
Luowigshafen = "Ludwigshafen",
|
|
31
31
|
Nurnberg = "Nurnberg",
|
|
32
32
|
Ellwangen = "Ellwangen",
|
|
33
|
-
Coppingen = "
|
|
34
|
-
Reutlincen = "
|
|
33
|
+
Coppingen = "G\u00F6ppingen",
|
|
34
|
+
Reutlincen = "Reutlingen",
|
|
35
35
|
Stuttgart = "Stuttgart",
|
|
36
36
|
Ludwigsburg = "Ludwigsburg",
|
|
37
37
|
Boblingen = "Boblingen",
|
|
38
|
-
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 = "
|
|
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"] = "
|
|
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-
|
|
22
|
+
Cities["Waldshuttiencen"] = "Waldshut-Tiengen";
|
|
23
23
|
Cities["Singen"] = "Singen";
|
|
24
|
-
Cities["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"] = "
|
|
32
|
+
Cities["Heidelber"] = "Heidelberg";
|
|
33
33
|
Cities["Mannheim"] = "Mannheim";
|
|
34
|
-
Cities["Luowigshafen"] = "
|
|
34
|
+
Cities["Luowigshafen"] = "Ludwigshafen";
|
|
35
35
|
Cities["Nurnberg"] = "Nurnberg";
|
|
36
36
|
Cities["Ellwangen"] = "Ellwangen";
|
|
37
|
-
Cities["Coppingen"] = "
|
|
38
|
-
Cities["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"] = "
|
|
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"] = "
|
|
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
|
};
|
package/dist/src/maps.d.ts
CHANGED
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.
|
|
3
|
+
"version": "1.9.9",
|
|
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":
|
|
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
|
},
|
package/src/available-moves.ts
CHANGED
|
@@ -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:
|
|
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' &&
|
|
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.
|
|
549
|
-
|
|
550
|
-
|
|
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
|
-
|
|
554
|
-
|
|
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
|
-
|
|
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' &&
|
|
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 = '
|
|
15
|
+
Sigmarincen = 'Sigmaringen',
|
|
16
16
|
Konstanz = 'Konstanz',
|
|
17
17
|
Ulm = 'Ulm',
|
|
18
18
|
Augsburg = 'Augsburg',
|
|
19
19
|
Basel = 'Basel',
|
|
20
|
-
Waldshuttiencen = 'Waldshut-
|
|
20
|
+
Waldshuttiencen = 'Waldshut-Tiengen',
|
|
21
21
|
Singen = 'Singen',
|
|
22
|
-
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 = '
|
|
30
|
+
Heidelber = 'Heidelberg',
|
|
31
31
|
Mannheim = 'Mannheim',
|
|
32
|
-
Luowigshafen = '
|
|
32
|
+
Luowigshafen = 'Ludwigshafen',
|
|
33
33
|
Nurnberg = 'Nurnberg',
|
|
34
34
|
Ellwangen = 'Ellwangen',
|
|
35
|
-
Coppingen = '
|
|
36
|
-
Reutlincen = '
|
|
35
|
+
Coppingen = 'Göppingen',
|
|
36
|
+
Reutlincen = 'Reutlingen',
|
|
37
37
|
Stuttgart = 'Stuttgart',
|
|
38
38
|
Ludwigsburg = 'Ludwigsburg',
|
|
39
39
|
Boblingen = 'Boblingen',
|
|
40
|
-
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 = '
|
|
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,
|