powergrid-engine 1.11.0 → 1.12.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/dist/src/available-moves.d.ts +1 -0
- package/dist/src/available-moves.js +66 -0
- package/dist/src/engine.js +72 -9
- package/dist/src/gamestate.d.ts +2 -1
- package/dist/src/maps/europe.d.ts +62 -0
- package/dist/src/maps/europe.js +356 -0
- package/dist/src/maps/northamerica.d.ts +62 -0
- package/dist/src/maps/northamerica.js +330 -0
- package/dist/src/maps/southafrica.d.ts +26 -26
- package/dist/src/maps/southafrica.js +239 -116
- package/dist/src/maps/ukireland.js +163 -40
- package/dist/src/maps.d.ts +10 -0
- package/dist/src/maps.js +12 -4
- package/dist/src/move.d.ts +1 -0
- package/package.json +1 -1
- package/src/available-moves.ts +88 -1
- package/src/engine.spec.ts +17 -0
- package/src/engine.ts +70 -12
- package/src/gamestate.ts +10 -3
- package/src/maps/europe.ts +391 -0
- package/src/maps/northamerica.ts +360 -0
- package/src/maps/southafrica.ts +247 -116
- package/src/maps/ukireland.ts +170 -40
- package/src/maps.ts +37 -6
- package/src/move.ts +4 -0
package/dist/src/maps.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface City {
|
|
|
6
6
|
x: number;
|
|
7
7
|
y: number;
|
|
8
8
|
transregional?: boolean;
|
|
9
|
+
singleOccupancy?: boolean;
|
|
10
|
+
island?: string;
|
|
9
11
|
}
|
|
10
12
|
export interface Connection {
|
|
11
13
|
nodes: string[];
|
|
@@ -28,6 +30,7 @@ export interface GameMap {
|
|
|
28
30
|
powerPlantMarketPosition?: [number, number];
|
|
29
31
|
actualMarketWidth?: number;
|
|
30
32
|
mapPosition?: [number, number];
|
|
33
|
+
mapRotation?: number;
|
|
31
34
|
buttonsPosition?: [number, number];
|
|
32
35
|
playerBoardsPosition?: [number, number];
|
|
33
36
|
supplyPosition?: [number, number];
|
|
@@ -51,7 +54,14 @@ export interface GameMap {
|
|
|
51
54
|
powerPlantsDeck: PowerPlant[];
|
|
52
55
|
};
|
|
53
56
|
regionalPowerPlants?: Record<string, PowerPlant[]>;
|
|
57
|
+
crossIslandSurcharge?: number;
|
|
54
58
|
mapSpecificRules?: string;
|
|
59
|
+
devBackdrop?: {
|
|
60
|
+
src: string;
|
|
61
|
+
width: number;
|
|
62
|
+
height: number;
|
|
63
|
+
opacity?: number;
|
|
64
|
+
};
|
|
55
65
|
}
|
|
56
66
|
export declare const maps: GameMap[];
|
|
57
67
|
export declare const mapsRecharged: GameMap[];
|
package/dist/src/maps.js
CHANGED
|
@@ -8,6 +8,7 @@ const benelux_1 = require("./maps/benelux");
|
|
|
8
8
|
const brazil_1 = require("./maps/brazil");
|
|
9
9
|
const centraleurope_1 = require("./maps/centraleurope");
|
|
10
10
|
const china_1 = require("./maps/china");
|
|
11
|
+
const europe_1 = require("./maps/europe");
|
|
11
12
|
const france_1 = require("./maps/france");
|
|
12
13
|
const germany_1 = require("./maps/germany");
|
|
13
14
|
const indian_1 = require("./maps/indian");
|
|
@@ -15,10 +16,13 @@ const italy_1 = require("./maps/italy");
|
|
|
15
16
|
// import { map as japan } from './maps/japan';
|
|
16
17
|
const korea_1 = require("./maps/korea");
|
|
17
18
|
const middleeast_1 = require("./maps/middleeast");
|
|
19
|
+
const northamerica_1 = require("./maps/northamerica");
|
|
18
20
|
const northerneurope_1 = require("./maps/northerneurope");
|
|
19
21
|
const quebec_1 = require("./maps/quebec");
|
|
20
22
|
const russia_1 = require("./maps/russia");
|
|
23
|
+
const southafrica_1 = require("./maps/southafrica");
|
|
21
24
|
const spainportugal_1 = require("./maps/spainportugal");
|
|
25
|
+
const ukireland_1 = require("./maps/ukireland");
|
|
22
26
|
exports.maps = [
|
|
23
27
|
america_1.map,
|
|
24
28
|
germany_1.map,
|
|
@@ -36,10 +40,12 @@ exports.maps = [
|
|
|
36
40
|
badenwurttemberg_1.map,
|
|
37
41
|
northerneurope_1.map,
|
|
38
42
|
korea_1.map,
|
|
43
|
+
europe_1.map,
|
|
44
|
+
northamerica_1.map,
|
|
45
|
+
southafrica_1.map,
|
|
46
|
+
ukireland_1.map,
|
|
39
47
|
// australia,
|
|
40
48
|
// japan,
|
|
41
|
-
// southafrica,
|
|
42
|
-
// ukireland,
|
|
43
49
|
];
|
|
44
50
|
exports.mapsRecharged = [
|
|
45
51
|
america_1.mapRecharged,
|
|
@@ -58,9 +64,11 @@ exports.mapsRecharged = [
|
|
|
58
64
|
badenwurttemberg_1.map,
|
|
59
65
|
northerneurope_1.map,
|
|
60
66
|
korea_1.map,
|
|
67
|
+
europe_1.map,
|
|
68
|
+
northamerica_1.map,
|
|
69
|
+
southafrica_1.map,
|
|
70
|
+
ukireland_1.map,
|
|
61
71
|
// australia,
|
|
62
72
|
// china,
|
|
63
73
|
// japan,
|
|
64
|
-
// southafrica,
|
|
65
|
-
// ukireland,
|
|
66
74
|
];
|
package/dist/src/move.d.ts
CHANGED
package/package.json
CHANGED
package/src/available-moves.ts
CHANGED
|
@@ -14,6 +14,9 @@ export interface AvailableMoves {
|
|
|
14
14
|
// Korea: which side's market this buy option draws from.
|
|
15
15
|
// Omitted on all other maps.
|
|
16
16
|
side?: 'north' | 'south';
|
|
17
|
+
// South Africa: $8 flat buy from the coal storage pool below the market.
|
|
18
|
+
// Distinct from the regular market buy (which can also be offered alongside).
|
|
19
|
+
fromStorage?: boolean;
|
|
17
20
|
}[];
|
|
18
21
|
[MoveName.Build]?: { name: string; price: number }[];
|
|
19
22
|
[MoveName.UsePowerPlant]?: {
|
|
@@ -91,6 +94,18 @@ export function availableMoves(G: GameState, player: Player): AvailableMoves {
|
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
|
|
97
|
+
// No nuclear plants for Republic of Ireland (Green region) on UK&I.
|
|
98
|
+
// The restriction lifts as soon as the player has any non-Green city
|
|
99
|
+
// (Scotland/Wales/England/Northern Ireland = Brown/Yellow/Red/Pink/Orange).
|
|
100
|
+
if (G.map.name == 'UK & Ireland') {
|
|
101
|
+
const playerCities = player.cities.map(
|
|
102
|
+
(c) => G.map.cities.find((c_) => c_.name == c.name)!
|
|
103
|
+
);
|
|
104
|
+
if (playerCities.every((c) => c.region == 'green')) {
|
|
105
|
+
canBid = canBid.filter((p) => p.type != PowerPlantType.Uranium);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
94
109
|
if (canBid.length > 0) {
|
|
95
110
|
moves[MoveName.ChoosePowerPlant] = canBid.map((p) => p.number);
|
|
96
111
|
}
|
|
@@ -138,6 +153,19 @@ export function availableMoves(G: GameState, player: Player): AvailableMoves {
|
|
|
138
153
|
}
|
|
139
154
|
}
|
|
140
155
|
|
|
156
|
+
// No nuclear plants for Republic of Ireland (Green region) on UK&I.
|
|
157
|
+
if (G.map.name == 'UK & Ireland') {
|
|
158
|
+
const playerCities = player.cities.map(
|
|
159
|
+
(c) => G.map.cities.find((c_) => c_.name == c.name)!
|
|
160
|
+
);
|
|
161
|
+
if (
|
|
162
|
+
playerCities.every((c) => c.region == 'green') &&
|
|
163
|
+
G.chosenPowerPlant.type == PowerPlantType.Uranium
|
|
164
|
+
) {
|
|
165
|
+
moves[MoveName.Bid] = undefined;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
141
169
|
if (G.options.fastBid) {
|
|
142
170
|
if (player.id != G.auctioningPlayer) {
|
|
143
171
|
moves[MoveName.Pass] = [true];
|
|
@@ -160,7 +188,7 @@ export function availableMoves(G: GameState, player: Player): AvailableMoves {
|
|
|
160
188
|
break;
|
|
161
189
|
}
|
|
162
190
|
|
|
163
|
-
const toBuy: { resource: ResourceType; side?: 'north' | 'south' }[] = [];
|
|
191
|
+
const toBuy: { resource: ResourceType; side?: 'north' | 'south'; fromStorage?: boolean }[] = [];
|
|
164
192
|
let maxPriceAvailable: number;
|
|
165
193
|
if (G.map.maxPriceAvailable) {
|
|
166
194
|
maxPriceAvailable = G.map.maxPriceAvailable[G.step - 1];
|
|
@@ -202,6 +230,21 @@ export function availableMoves(G: GameState, player: Player): AvailableMoves {
|
|
|
202
230
|
}
|
|
203
231
|
}
|
|
204
232
|
|
|
233
|
+
// South Africa: $8 flat coal from the storage pool below the market.
|
|
234
|
+
// Always available alongside the regular market option (not gated on
|
|
235
|
+
// market being empty), as long as there are cubes in storage.
|
|
236
|
+
if (allowSouth && G.coalStorage !== undefined && G.coalStorage > 0) {
|
|
237
|
+
const hybridCapacityUsed =
|
|
238
|
+
player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
239
|
+
if (
|
|
240
|
+
player.money >= 8 &&
|
|
241
|
+
player.coalCapacity + player.hybridCapacity > hybridCapacityUsed + player.coalLeft &&
|
|
242
|
+
8 <= maxPriceAvailable
|
|
243
|
+
) {
|
|
244
|
+
toBuy.push({ resource: ResourceType.Coal, fromStorage: true });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
205
248
|
if (allowNorth && G.coalMarketNorth! > 0) {
|
|
206
249
|
const hybridCapacityUsed =
|
|
207
250
|
player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
@@ -341,6 +384,50 @@ export function availableMoves(G: GameState, player: Player): AvailableMoves {
|
|
|
341
384
|
return;
|
|
342
385
|
}
|
|
343
386
|
|
|
387
|
+
// UK & Ireland: starting a network on an island where the player has
|
|
388
|
+
// no city yet pays the first-house base + crossIslandSurcharge. There
|
|
389
|
+
// is no sea edge so dijkstra reports the target city as unreachable
|
|
390
|
+
// (price=9999); we override here. The first build ever (player.cities
|
|
391
|
+
// empty) goes through the normal first-build path and pays no surcharge.
|
|
392
|
+
if (cityData.island && G.map.crossIslandSurcharge !== undefined && player.cities.length > 0) {
|
|
393
|
+
const playerIslands = new Set(
|
|
394
|
+
player.cities
|
|
395
|
+
.map((c) => G.map.cities.find((mc) => mc.name == c.name)?.island)
|
|
396
|
+
.filter((i): i is string => !!i)
|
|
397
|
+
);
|
|
398
|
+
if (!playerIslands.has(cityData.island)) {
|
|
399
|
+
city.price = 10 + othersCount * 5 + G.map.crossIslandSurcharge;
|
|
400
|
+
|
|
401
|
+
if (othersCount == G.step) {
|
|
402
|
+
city.price = 9999;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (player.cities.find((c) => c.name == city.name)) {
|
|
406
|
+
city.price = 9999;
|
|
407
|
+
}
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// South Africa's cross-border foreign-country spaces: cap at 1 occupant
|
|
413
|
+
// ever, and the dijkstra path cost (30 via the cross-border edge) is the
|
|
414
|
+
// complete cost — no 10+position*5 house base is added. Players cannot
|
|
415
|
+
// start in one of these (you have to build INTO South Africa first).
|
|
416
|
+
if (cityData.singleOccupancy) {
|
|
417
|
+
if (player.cities.length == 0) {
|
|
418
|
+
city.price = 9999;
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (othersCount >= 1) {
|
|
422
|
+
city.price = 9999;
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
if (player.cities.find((c) => c.name == city.name)) {
|
|
426
|
+
city.price = 9999;
|
|
427
|
+
}
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
344
431
|
city.price += 10 + othersCount * 5;
|
|
345
432
|
|
|
346
433
|
if (othersCount == G.step) {
|
package/src/engine.spec.ts
CHANGED
|
@@ -141,6 +141,23 @@ describe('Engine', () => {
|
|
|
141
141
|
expect(ended(G)).to.be.false;
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
+
it('should place UK & Ireland Step 3 card third from last with two plants below it', () => {
|
|
145
|
+
// UK & Ireland rules: the Step 3 card (plant 99) goes at deck.length - 3
|
|
146
|
+
// so two plants sit below it, and Step 3 fires two auctions earlier than
|
|
147
|
+
// a standard "Step 3 at the bottom" deck.
|
|
148
|
+
const G = setup(5, { map: 'UK & Ireland', variant: 'recharged', randomizeMap: false }, 'ukireland-test-seed');
|
|
149
|
+
|
|
150
|
+
const step3Idx = G.powerPlantsDeck.findIndex((p) => p.number === 99);
|
|
151
|
+
expect(step3Idx).to.equal(G.powerPlantsDeck.length - 3);
|
|
152
|
+
|
|
153
|
+
// The two plants below Step 3 are real plants (not another Step 3 card or
|
|
154
|
+
// undefined slots).
|
|
155
|
+
expect(G.powerPlantsDeck[step3Idx + 1]).to.exist;
|
|
156
|
+
expect(G.powerPlantsDeck[step3Idx + 2]).to.exist;
|
|
157
|
+
expect(G.powerPlantsDeck[step3Idx + 1].number).to.not.equal(99);
|
|
158
|
+
expect(G.powerPlantsDeck[step3Idx + 2].number).to.not.equal(99);
|
|
159
|
+
});
|
|
160
|
+
|
|
144
161
|
it('should allow invalid move when isUndo is true', () => {
|
|
145
162
|
const game = undo;
|
|
146
163
|
const options: GameOptions = {
|
package/src/engine.ts
CHANGED
|
@@ -15,6 +15,7 @@ export const playerColors = ['limegreen', 'mediumorchid', 'red', 'dodgerblue', '
|
|
|
15
15
|
|
|
16
16
|
const citiesToStep2 = [10, 7, 7, 7, 6];
|
|
17
17
|
const citiesToStep2BadenWurttemberg = [9, 6, 6, 6, 5];
|
|
18
|
+
const citiesToStep2UKIreland = [7, 7, 7, 7, 6];
|
|
18
19
|
const citiesToEndGame = [21, 17, 17, 15, 14];
|
|
19
20
|
const cityIncome = [10, 22, 33, 44, 54, 64, 73, 82, 90, 98, 105, 112, 118, 124, 129, 134, 138, 142, 145, 148, 150, 150];
|
|
20
21
|
const regionsInPlay = [3, 3, 4, 5, 5];
|
|
@@ -260,7 +261,14 @@ export function setup(
|
|
|
260
261
|
const region = regions[Math.floor(rng() * regions.length)];
|
|
261
262
|
if (
|
|
262
263
|
playRegions.size == 0 ||
|
|
263
|
-
regionConnections[regions.indexOf(region)].some((con) => playRegions.has(con))
|
|
264
|
+
regionConnections[regions.indexOf(region)].some((con) => playRegions.has(con)) ||
|
|
265
|
+
// UK & Ireland: regions on the two islands have no edges between
|
|
266
|
+
// them (no sea connection). Skipping the connectivity check lets
|
|
267
|
+
// the random selection span both islands; the cross-island
|
|
268
|
+
// surcharge handles the disconnect at build time. Without this,
|
|
269
|
+
// requiring 5-of-6 regions for 5p would loop forever (GB has 4
|
|
270
|
+
// regions, IE has 2).
|
|
271
|
+
chosenMap.name === 'UK & Ireland'
|
|
264
272
|
) {
|
|
265
273
|
playRegions.add(region);
|
|
266
274
|
|
|
@@ -333,6 +341,8 @@ export function setup(
|
|
|
333
341
|
const oilPricesNorth = chosenMap.oilPricesNorth ? cloneDeep(chosenMap.oilPricesNorth) : undefined;
|
|
334
342
|
const garbagePricesNorth = chosenMap.garbagePricesNorth ? cloneDeep(chosenMap.garbagePricesNorth) : undefined;
|
|
335
343
|
|
|
344
|
+
const isSouthAfrica = (forceMap || finalMap).name == 'South Africa';
|
|
345
|
+
|
|
336
346
|
const G: GameState = {
|
|
337
347
|
map: forceMap || finalMap,
|
|
338
348
|
players,
|
|
@@ -343,6 +353,9 @@ export function setup(
|
|
|
343
353
|
oilSupply,
|
|
344
354
|
garbageSupply,
|
|
345
355
|
uraniumSupply,
|
|
356
|
+
// South Africa: separate coal pool below the market. Starts empty;
|
|
357
|
+
// used coal returns here; refill draws from here first.
|
|
358
|
+
coalStorage: isSouthAfrica ? 0 : undefined,
|
|
346
359
|
coalResupply,
|
|
347
360
|
oilResupply,
|
|
348
361
|
garbageResupply,
|
|
@@ -383,6 +396,8 @@ export function setup(
|
|
|
383
396
|
citiesToStep2:
|
|
384
397
|
(forceMap || finalMap).name == 'Baden-Württemberg'
|
|
385
398
|
? citiesToStep2BadenWurttemberg[numPlayers - 2]
|
|
399
|
+
: (forceMap || finalMap).name == 'UK & Ireland'
|
|
400
|
+
? citiesToStep2UKIreland[numPlayers - 2]
|
|
386
401
|
: citiesToStep2[numPlayers - 2],
|
|
387
402
|
citiesToEndGame: citiesToEndGame[numPlayers - 2],
|
|
388
403
|
resourceResupply: [
|
|
@@ -755,7 +770,17 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
|
|
|
755
770
|
}
|
|
756
771
|
}
|
|
757
772
|
|
|
758
|
-
|
|
773
|
+
if (G.map.name == 'Europe') {
|
|
774
|
+
// Europe: do NOT draw a replacement from the deck.
|
|
775
|
+
// The future market shrinks from 5 to 4; reorganize
|
|
776
|
+
// the remaining 8 plants so actual stays at 4.
|
|
777
|
+
const market = [...G.actualMarket, ...G.futureMarket];
|
|
778
|
+
market.sort((a, b) => a.number - b.number);
|
|
779
|
+
G.actualMarket = market.slice(0, 4);
|
|
780
|
+
G.futureMarket = market.slice(4);
|
|
781
|
+
} else {
|
|
782
|
+
addPowerPlant(G);
|
|
783
|
+
}
|
|
759
784
|
}
|
|
760
785
|
}
|
|
761
786
|
|
|
@@ -883,13 +908,26 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
|
|
|
883
908
|
G.garbageSupply -= garbageResupplyNorthValue;
|
|
884
909
|
}
|
|
885
910
|
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
911
|
+
// South Africa pulls from coalStorage first, then coalSupply.
|
|
912
|
+
// Other maps just pull from coalSupply.
|
|
913
|
+
let coalResupplyValue: number;
|
|
914
|
+
if (G.coalStorage !== undefined) {
|
|
915
|
+
const wantCoal = Math.min(G.coalResupply![G.players.length - 2][G.step - 1], coalCapSouth);
|
|
916
|
+
const fromStorage = Math.min(G.coalStorage, wantCoal);
|
|
917
|
+
const fromSupply = Math.min(G.coalSupply, wantCoal - fromStorage);
|
|
918
|
+
coalResupplyValue = fromStorage + fromSupply;
|
|
919
|
+
G.coalMarket += coalResupplyValue;
|
|
920
|
+
G.coalStorage -= fromStorage;
|
|
921
|
+
G.coalSupply -= fromSupply;
|
|
922
|
+
} else {
|
|
923
|
+
coalResupplyValue = Math.min(
|
|
924
|
+
G.coalSupply,
|
|
925
|
+
G.coalResupply![G.players.length - 2][G.step - 1],
|
|
926
|
+
coalCapSouth
|
|
927
|
+
);
|
|
928
|
+
G.coalMarket += coalResupplyValue;
|
|
929
|
+
G.coalSupply -= coalResupplyValue;
|
|
930
|
+
}
|
|
893
931
|
|
|
894
932
|
let oilResupplyValue: number;
|
|
895
933
|
if (G.map.name == 'Middle East') {
|
|
@@ -1284,6 +1322,11 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
|
|
|
1284
1322
|
price = coalPrices[coalPrices.length - G.coalMarketNorth!];
|
|
1285
1323
|
player.coalLeft++;
|
|
1286
1324
|
G.coalMarketNorth!--;
|
|
1325
|
+
} else if (move.data.fromStorage) {
|
|
1326
|
+
// South Africa: $8 flat from the storage pool below the market.
|
|
1327
|
+
price = 8;
|
|
1328
|
+
player.coalLeft++;
|
|
1329
|
+
G.coalStorage!--;
|
|
1287
1330
|
} else if (G.coalMarket == 0) {
|
|
1288
1331
|
price = 8;
|
|
1289
1332
|
player.coalLeft++;
|
|
@@ -1375,8 +1418,14 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
|
|
|
1375
1418
|
player.money -= move.data.price;
|
|
1376
1419
|
|
|
1377
1420
|
if (G.options.trackTotalSpent) {
|
|
1378
|
-
|
|
1379
|
-
|
|
1421
|
+
const cityData = G.map.cities.find((c) => c.name == move.data.name)!;
|
|
1422
|
+
if (cityData.singleOccupancy) {
|
|
1423
|
+
// SA cross-border: no house base — full price is "connection".
|
|
1424
|
+
player.totalSpentConnections += move.data.price;
|
|
1425
|
+
} else {
|
|
1426
|
+
player.totalSpentCities += 10 + position * 5;
|
|
1427
|
+
player.totalSpentConnections += move.data.price - (10 + position * 5);
|
|
1428
|
+
}
|
|
1380
1429
|
}
|
|
1381
1430
|
|
|
1382
1431
|
G.log.push({
|
|
@@ -1417,7 +1466,12 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
|
|
|
1417
1466
|
switch (resourceType) {
|
|
1418
1467
|
case ResourceType.Coal:
|
|
1419
1468
|
player.coalLeft--;
|
|
1420
|
-
|
|
1469
|
+
// SA: used coal returns to the separate storage pool below the market.
|
|
1470
|
+
if (G.coalStorage !== undefined) {
|
|
1471
|
+
G.coalStorage++;
|
|
1472
|
+
} else {
|
|
1473
|
+
G.coalSupply++;
|
|
1474
|
+
}
|
|
1421
1475
|
break;
|
|
1422
1476
|
|
|
1423
1477
|
case ResourceType.Oil:
|
|
@@ -1484,6 +1538,10 @@ export function move(G: GameState, move: Move, playerNumber: number, isUndo = fa
|
|
|
1484
1538
|
G.coalMarketNorth!++;
|
|
1485
1539
|
const coalPrices = G.coalPricesNorth!;
|
|
1486
1540
|
price = coalPrices[coalPrices.length - G.coalMarketNorth!];
|
|
1541
|
+
} else if (lastMove.data.fromStorage) {
|
|
1542
|
+
price = 8;
|
|
1543
|
+
player.coalLeft--;
|
|
1544
|
+
G.coalStorage!++;
|
|
1487
1545
|
} else if (lastMove.fromSupply) {
|
|
1488
1546
|
price = 8;
|
|
1489
1547
|
player.coalLeft--;
|
package/src/gamestate.ts
CHANGED
|
@@ -19,11 +19,13 @@ export type MapName =
|
|
|
19
19
|
| 'Central Europe'
|
|
20
20
|
| 'Baden-Württemberg'
|
|
21
21
|
| 'Northern Europe'
|
|
22
|
-
| 'Korea'
|
|
22
|
+
| 'Korea'
|
|
23
|
+
| 'Europe'
|
|
24
|
+
| 'North America'
|
|
25
|
+
| 'South Africa'
|
|
26
|
+
| 'UK & Ireland';
|
|
23
27
|
// | 'Australia'
|
|
24
28
|
// | 'Japan'
|
|
25
|
-
// | 'South Africa'
|
|
26
|
-
// | 'UK & Ireland'
|
|
27
29
|
export type Variant = 'original' | 'recharged';
|
|
28
30
|
|
|
29
31
|
export interface GameOptions {
|
|
@@ -121,6 +123,11 @@ export interface GameState {
|
|
|
121
123
|
oilSupply: number;
|
|
122
124
|
garbageSupply: number;
|
|
123
125
|
uraniumSupply: number;
|
|
126
|
+
// South Africa: coal used to power plants returns here instead of coalSupply.
|
|
127
|
+
// Market refills draw from this pool first, then fall back to coalSupply.
|
|
128
|
+
// Players can always buy a coal cube from here for $8 (on top of the normal
|
|
129
|
+
// market). Undefined on non-SA maps.
|
|
130
|
+
coalStorage?: number;
|
|
124
131
|
coalMarket: number;
|
|
125
132
|
oilMarket: number;
|
|
126
133
|
garbageMarket: number;
|