powergrid-engine 1.9.9 → 1.11.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 +44 -9
- package/dist/src/engine.js +219 -49
- package/dist/src/gamestate.d.ts +12 -1
- package/dist/src/maps/korea.js +107 -0
- package/dist/src/maps/northerneurope.js +75 -0
- package/dist/src/maps.d.ts +6 -0
- package/dist/src/maps.js +7 -4
- package/dist/src/move.d.ts +1 -0
- package/package.json +1 -1
- package/src/available-moves.ts +71 -10
- package/src/engine.ts +237 -42
- package/src/gamestate.ts +24 -4
- package/src/maps/korea.ts +109 -0
- package/src/maps/northerneurope.ts +76 -0
- package/src/maps.ts +16 -7
- package/src/move.ts +3 -0
|
@@ -135,17 +135,22 @@ function availableMoves(G, player) {
|
|
|
135
135
|
else {
|
|
136
136
|
maxPriceAvailable = 16;
|
|
137
137
|
}
|
|
138
|
-
|
|
138
|
+
// Korea: each side is offered separately, tagged with the side. The
|
|
139
|
+
// player's chosenSide locks them to one side once they make a buy.
|
|
140
|
+
const isKorea = G.coalResupplyNorth !== undefined;
|
|
141
|
+
const allowSouth = !isKorea || G.chosenSide !== 'north';
|
|
142
|
+
const allowNorth = isKorea && G.chosenSide !== 'south';
|
|
143
|
+
if (allowSouth && G.coalMarket > 0) {
|
|
139
144
|
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
140
145
|
const coalPrices = (_c = G.coalPrices) !== null && _c !== void 0 ? _c : prices_1.default[gamestate_1.ResourceType.Coal];
|
|
141
146
|
const price = coalPrices[coalPrices.length - G.coalMarket];
|
|
142
147
|
if (player.money >= price &&
|
|
143
148
|
player.coalCapacity + player.hybridCapacity > hybridCapacityUsed + player.coalLeft &&
|
|
144
149
|
price <= maxPriceAvailable) {
|
|
145
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Coal });
|
|
150
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Coal, side: 'south' } : { resource: gamestate_1.ResourceType.Coal });
|
|
146
151
|
}
|
|
147
152
|
}
|
|
148
|
-
else {
|
|
153
|
+
else if (allowSouth) {
|
|
149
154
|
if (G.options.variant == 'recharged' && G.map.name == 'USA' && G.coalSupply > 0) {
|
|
150
155
|
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
151
156
|
if (player.money >= 8 &&
|
|
@@ -154,17 +159,37 @@ function availableMoves(G, player) {
|
|
|
154
159
|
}
|
|
155
160
|
}
|
|
156
161
|
}
|
|
157
|
-
if (G.
|
|
162
|
+
if (allowNorth && G.coalMarketNorth > 0) {
|
|
163
|
+
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
164
|
+
const coalPrices = G.coalPricesNorth;
|
|
165
|
+
const price = coalPrices[coalPrices.length - G.coalMarketNorth];
|
|
166
|
+
if (player.money >= price &&
|
|
167
|
+
player.coalCapacity + player.hybridCapacity > hybridCapacityUsed + player.coalLeft &&
|
|
168
|
+
price <= maxPriceAvailable) {
|
|
169
|
+
toBuy.push({ resource: gamestate_1.ResourceType.Coal, side: 'north' });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (allowSouth && G.oilMarket > 0) {
|
|
158
173
|
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.coalLeft - player.coalCapacity) : 0;
|
|
159
174
|
const oilPrices = (_d = G.oilPrices) !== null && _d !== void 0 ? _d : prices_1.default[gamestate_1.ResourceType.Oil];
|
|
160
175
|
const price = oilPrices[oilPrices.length - G.oilMarket];
|
|
161
176
|
if (player.money >= price &&
|
|
162
177
|
player.oilCapacity + player.hybridCapacity > hybridCapacityUsed + player.oilLeft &&
|
|
163
178
|
price <= maxPriceAvailable) {
|
|
164
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Oil });
|
|
179
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Oil, side: 'south' } : { resource: gamestate_1.ResourceType.Oil });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (allowNorth && G.oilMarketNorth > 0) {
|
|
183
|
+
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.coalLeft - player.coalCapacity) : 0;
|
|
184
|
+
const oilPrices = G.oilPricesNorth;
|
|
185
|
+
const price = oilPrices[oilPrices.length - G.oilMarketNorth];
|
|
186
|
+
if (player.money >= price &&
|
|
187
|
+
player.oilCapacity + player.hybridCapacity > hybridCapacityUsed + player.oilLeft &&
|
|
188
|
+
price <= maxPriceAvailable) {
|
|
189
|
+
toBuy.push({ resource: gamestate_1.ResourceType.Oil, side: 'north' });
|
|
165
190
|
}
|
|
166
191
|
}
|
|
167
|
-
if (G.garbageMarket > 0) {
|
|
192
|
+
if (allowSouth && G.garbageMarket > 0) {
|
|
168
193
|
const garbagePrices = (_e = G.garbagePrices) !== null && _e !== void 0 ? _e : prices_1.default[gamestate_1.ResourceType.Garbage];
|
|
169
194
|
let price = garbagePrices[garbagePrices.length - G.garbageMarket];
|
|
170
195
|
// $1 cheaper for players in Wien in Central Europe
|
|
@@ -177,16 +202,26 @@ function availableMoves(G, player) {
|
|
|
177
202
|
if (player.money >= price &&
|
|
178
203
|
player.garbageCapacity > player.garbageLeft &&
|
|
179
204
|
price <= maxPriceAvailable) {
|
|
180
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Garbage });
|
|
205
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Garbage, side: 'south' } : { resource: gamestate_1.ResourceType.Garbage });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (allowNorth && G.garbageMarketNorth > 0) {
|
|
209
|
+
const garbagePrices = G.garbagePricesNorth;
|
|
210
|
+
const price = garbagePrices[garbagePrices.length - G.garbageMarketNorth];
|
|
211
|
+
if (player.money >= price &&
|
|
212
|
+
player.garbageCapacity > player.garbageLeft &&
|
|
213
|
+
price <= maxPriceAvailable) {
|
|
214
|
+
toBuy.push({ resource: gamestate_1.ResourceType.Garbage, side: 'north' });
|
|
181
215
|
}
|
|
182
216
|
}
|
|
183
|
-
|
|
217
|
+
// Uranium is South only (or non-Korea maps).
|
|
218
|
+
if (allowSouth && G.uraniumMarket > 0) {
|
|
184
219
|
const uraniumPrices = (_f = G.uraniumPrices) !== null && _f !== void 0 ? _f : prices_1.default[gamestate_1.ResourceType.Uranium];
|
|
185
220
|
const price = uraniumPrices[uraniumPrices.length - G.uraniumMarket];
|
|
186
221
|
if (player.money >= price &&
|
|
187
222
|
player.uraniumCapacity > player.uraniumLeft &&
|
|
188
223
|
price <= maxPriceAvailable) {
|
|
189
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Uranium });
|
|
224
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Uranium, side: 'south' } : { resource: gamestate_1.ResourceType.Uranium });
|
|
190
225
|
}
|
|
191
226
|
}
|
|
192
227
|
if (toBuy.length > 0) {
|
package/dist/src/engine.js
CHANGED
|
@@ -70,7 +70,7 @@ function defaultSetupDeck(numPlayers, variant, rng, useNewRechargedSetup) {
|
|
|
70
70
|
}
|
|
71
71
|
exports.defaultSetupDeck = defaultSetupDeck;
|
|
72
72
|
function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original', showMoney = false, useNewRechargedSetup = true, trackTotalSpent = true, randomizeMap = false, }, seed, forceDeck, forceMap) {
|
|
73
|
-
var _a, _b, _c, _d;
|
|
73
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
74
74
|
seed = seed !== null && seed !== void 0 ? seed : Math.random().toString();
|
|
75
75
|
const rng = seedrandom_1.default(seed);
|
|
76
76
|
const chosenMap = lodash_1.cloneDeep(variant == 'original' ? maps_1.maps.find((m) => m.name == map) : maps_1.mapsRecharged.find((m) => m.name == map));
|
|
@@ -129,6 +129,15 @@ function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original',
|
|
|
129
129
|
let oilResupply;
|
|
130
130
|
let garbageResupply;
|
|
131
131
|
let uraniumResupply;
|
|
132
|
+
// Korea: parallel North-side resupply tables (no uranium row).
|
|
133
|
+
let coalResupplyNorth;
|
|
134
|
+
let oilResupplyNorth;
|
|
135
|
+
let garbageResupplyNorth;
|
|
136
|
+
if (chosenMap.resupplyNorth) {
|
|
137
|
+
coalResupplyNorth = chosenMap.resupplyNorth[0];
|
|
138
|
+
oilResupplyNorth = chosenMap.resupplyNorth[1];
|
|
139
|
+
garbageResupplyNorth = chosenMap.resupplyNorth[2];
|
|
140
|
+
}
|
|
132
141
|
if (chosenMap.resupply) {
|
|
133
142
|
coalResupply = chosenMap.resupply[0];
|
|
134
143
|
oilResupply = chosenMap.resupply[1];
|
|
@@ -227,6 +236,23 @@ function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original',
|
|
|
227
236
|
.map((n) => chosenMap.cities.find((city) => city.name == n).region)
|
|
228
237
|
.every((r) => playRegions.has(r)));
|
|
229
238
|
finalMap = filteredMap;
|
|
239
|
+
if (chosenMap.regionalPowerPlants) {
|
|
240
|
+
for (const region of playRegions) {
|
|
241
|
+
const replacements = chosenMap.regionalPowerPlants[region];
|
|
242
|
+
if (replacements) {
|
|
243
|
+
for (const newPlant of replacements) {
|
|
244
|
+
const swapIn = (arr) => {
|
|
245
|
+
const idx = arr.findIndex((p) => p.number === newPlant.number);
|
|
246
|
+
if (idx !== -1)
|
|
247
|
+
arr[idx] = { ...newPlant };
|
|
248
|
+
};
|
|
249
|
+
swapIn(actualMarket);
|
|
250
|
+
swapIn(futureMarket);
|
|
251
|
+
swapIn(powerPlantsDeck);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
230
256
|
}
|
|
231
257
|
const coalMarket = chosenMap.startingResources ? chosenMap.startingResources[0] : 24;
|
|
232
258
|
const oilMarket = chosenMap.startingResources ? chosenMap.startingResources[1] : 18;
|
|
@@ -236,14 +262,24 @@ function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original',
|
|
|
236
262
|
const totalOil = chosenMap.startingSupply ? chosenMap.startingSupply[1] : 24;
|
|
237
263
|
const totalGarbage = chosenMap.startingSupply ? chosenMap.startingSupply[2] : 24;
|
|
238
264
|
const totalUranium = chosenMap.startingSupply ? chosenMap.startingSupply[3] : 12;
|
|
239
|
-
|
|
240
|
-
const
|
|
241
|
-
const
|
|
265
|
+
// Korea: parallel North-side market and prices. Supply is shared — see below.
|
|
266
|
+
const coalMarketNorth = (_a = chosenMap.startingResourcesNorth) === null || _a === void 0 ? void 0 : _a[0];
|
|
267
|
+
const oilMarketNorth = (_b = chosenMap.startingResourcesNorth) === null || _b === void 0 ? void 0 : _b[1];
|
|
268
|
+
const garbageMarketNorth = (_c = chosenMap.startingResourcesNorth) === null || _c === void 0 ? void 0 : _c[2];
|
|
269
|
+
// Supply pools are shared between both sides for Korea. `startingSupply`
|
|
270
|
+
// represents the TOTAL cubes in the game; the supply pool is whatever is
|
|
271
|
+
// left after both markets are filled.
|
|
272
|
+
const coalSupply = totalCoal - coalMarket - (coalMarketNorth !== null && coalMarketNorth !== void 0 ? coalMarketNorth : 0);
|
|
273
|
+
const oilSupply = totalOil - oilMarket - (oilMarketNorth !== null && oilMarketNorth !== void 0 ? oilMarketNorth : 0);
|
|
274
|
+
const garbageSupply = totalGarbage - garbageMarket - (garbageMarketNorth !== null && garbageMarketNorth !== void 0 ? garbageMarketNorth : 0);
|
|
242
275
|
const uraniumSupply = totalUranium - uraniumMarket;
|
|
243
|
-
const coalPrices = lodash_1.cloneDeep((
|
|
244
|
-
const oilPrices = lodash_1.cloneDeep((
|
|
245
|
-
const garbagePrices = lodash_1.cloneDeep((
|
|
246
|
-
const uraniumPrices = lodash_1.cloneDeep((
|
|
276
|
+
const coalPrices = lodash_1.cloneDeep((_d = chosenMap.coalPrices) !== null && _d !== void 0 ? _d : prices_1.default.coal);
|
|
277
|
+
const oilPrices = lodash_1.cloneDeep((_e = chosenMap.oilPrices) !== null && _e !== void 0 ? _e : prices_1.default.oil);
|
|
278
|
+
const garbagePrices = lodash_1.cloneDeep((_f = chosenMap.garbagePrices) !== null && _f !== void 0 ? _f : prices_1.default.garbage);
|
|
279
|
+
const uraniumPrices = lodash_1.cloneDeep((_g = chosenMap.uraniumPrices) !== null && _g !== void 0 ? _g : prices_1.default.uranium);
|
|
280
|
+
const coalPricesNorth = chosenMap.coalPricesNorth ? lodash_1.cloneDeep(chosenMap.coalPricesNorth) : undefined;
|
|
281
|
+
const oilPricesNorth = chosenMap.oilPricesNorth ? lodash_1.cloneDeep(chosenMap.oilPricesNorth) : undefined;
|
|
282
|
+
const garbagePricesNorth = chosenMap.garbagePricesNorth ? lodash_1.cloneDeep(chosenMap.garbagePricesNorth) : undefined;
|
|
247
283
|
const G = {
|
|
248
284
|
map: forceMap || finalMap,
|
|
249
285
|
players,
|
|
@@ -266,6 +302,17 @@ function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original',
|
|
|
266
302
|
oilPrices,
|
|
267
303
|
garbagePrices,
|
|
268
304
|
uraniumPrices,
|
|
305
|
+
// Korea: parallel North-side fields. Undefined for non-Korea maps.
|
|
306
|
+
// Supply is shared with the primary `*Supply` fields above.
|
|
307
|
+
coalMarketNorth,
|
|
308
|
+
oilMarketNorth,
|
|
309
|
+
garbageMarketNorth,
|
|
310
|
+
coalResupplyNorth,
|
|
311
|
+
oilResupplyNorth,
|
|
312
|
+
garbageResupplyNorth,
|
|
313
|
+
coalPricesNorth,
|
|
314
|
+
oilPricesNorth,
|
|
315
|
+
garbagePricesNorth,
|
|
269
316
|
actualMarket,
|
|
270
317
|
futureMarket,
|
|
271
318
|
chosenPowerPlant: undefined,
|
|
@@ -289,6 +336,13 @@ function setup(numPlayers, { fastBid = false, map = 'USA', variant = 'original',
|
|
|
289
336
|
`[${coalResupply[p][1]}, ${oilResupply[p][1]}, ${garbageResupply[p][1]}, ${uraniumResupply[p][1]}]`,
|
|
290
337
|
`[${coalResupply[p][2]}, ${oilResupply[p][2]}, ${garbageResupply[p][2]}, ${uraniumResupply[p][2]}]`,
|
|
291
338
|
],
|
|
339
|
+
resourceResupplyNorth: coalResupplyNorth && oilResupplyNorth && garbageResupplyNorth
|
|
340
|
+
? [
|
|
341
|
+
`[${coalResupplyNorth[p][0]}, ${oilResupplyNorth[p][0]}, ${garbageResupplyNorth[p][0]}]`,
|
|
342
|
+
`[${coalResupplyNorth[p][1]}, ${oilResupplyNorth[p][1]}, ${garbageResupplyNorth[p][1]}]`,
|
|
343
|
+
`[${coalResupplyNorth[p][2]}, ${oilResupplyNorth[p][2]}, ${garbageResupplyNorth[p][2]}]`,
|
|
344
|
+
]
|
|
345
|
+
: undefined,
|
|
292
346
|
paymentTable: cityIncome,
|
|
293
347
|
variant,
|
|
294
348
|
minimunBid: 0,
|
|
@@ -340,7 +394,7 @@ function currentPlayers(G) {
|
|
|
340
394
|
}
|
|
341
395
|
exports.currentPlayers = currentPlayers;
|
|
342
396
|
function move(G, move, playerNumber, isUndo = false) {
|
|
343
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
397
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
344
398
|
const player = G.players[playerNumber];
|
|
345
399
|
const available = (_a = player.availableMoves) === null || _a === void 0 ? void 0 : _a[move.name];
|
|
346
400
|
updateGameState(G);
|
|
@@ -545,6 +599,11 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
545
599
|
else {
|
|
546
600
|
player.passed = true;
|
|
547
601
|
}
|
|
602
|
+
// Korea: end of this player's buying turn — clear the side lock
|
|
603
|
+
// so the next player can pick freely.
|
|
604
|
+
if (G.map.name == 'Korea') {
|
|
605
|
+
G.chosenSide = undefined;
|
|
606
|
+
}
|
|
548
607
|
if (G.players.filter((p) => !p.passed && !p.isDropped).length == 0) {
|
|
549
608
|
G.players.forEach((p) => {
|
|
550
609
|
p.passed = p.isDropped;
|
|
@@ -656,7 +715,34 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
656
715
|
player.targetCitiesPowered = 0;
|
|
657
716
|
}
|
|
658
717
|
if (G.players.filter((p) => !p.passed && !p.isDropped).length == 0) {
|
|
659
|
-
|
|
718
|
+
// Resupply is also capped by remaining market capacity (the
|
|
719
|
+
// prices array length minus current market size). Without
|
|
720
|
+
// this, smaller markets like Korea's can overflow past the
|
|
721
|
+
// number of slots and break price lookups.
|
|
722
|
+
const coalCapSouth = ((_d = (_c = G.coalPrices) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : prices_1.default[gamestate_1.ResourceType.Coal].length) - G.coalMarket;
|
|
723
|
+
const oilCapSouth = ((_f = (_e = G.oilPrices) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : prices_1.default[gamestate_1.ResourceType.Oil].length) - G.oilMarket;
|
|
724
|
+
const garbageCapSouth = ((_h = (_g = G.garbagePrices) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : prices_1.default[gamestate_1.ResourceType.Garbage].length) - G.garbageMarket;
|
|
725
|
+
const uraniumCapSouth = ((_k = (_j = G.uraniumPrices) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : prices_1.default[gamestate_1.ResourceType.Uranium].length) - G.uraniumMarket;
|
|
726
|
+
// Korea: North restocks FIRST from the shared supply pool, then
|
|
727
|
+
// South takes whatever remains. If supply runs short, South gets less.
|
|
728
|
+
let coalResupplyNorthValue = 0;
|
|
729
|
+
let oilResupplyNorthValue = 0;
|
|
730
|
+
let garbageResupplyNorthValue = 0;
|
|
731
|
+
if (G.coalResupplyNorth) {
|
|
732
|
+
const coalCapNorth = G.coalPricesNorth.length - G.coalMarketNorth;
|
|
733
|
+
const oilCapNorth = G.oilPricesNorth.length - G.oilMarketNorth;
|
|
734
|
+
const garbageCapNorth = G.garbagePricesNorth.length - G.garbageMarketNorth;
|
|
735
|
+
coalResupplyNorthValue = Math.min(G.coalSupply, G.coalResupplyNorth[G.players.length - 2][G.step - 1], coalCapNorth);
|
|
736
|
+
G.coalMarketNorth += coalResupplyNorthValue;
|
|
737
|
+
G.coalSupply -= coalResupplyNorthValue;
|
|
738
|
+
oilResupplyNorthValue = Math.min(G.oilSupply, G.oilResupplyNorth[G.players.length - 2][G.step - 1], oilCapNorth);
|
|
739
|
+
G.oilMarketNorth += oilResupplyNorthValue;
|
|
740
|
+
G.oilSupply -= oilResupplyNorthValue;
|
|
741
|
+
garbageResupplyNorthValue = Math.min(G.garbageSupply, G.garbageResupplyNorth[G.players.length - 2][G.step - 1], garbageCapNorth);
|
|
742
|
+
G.garbageMarketNorth += garbageResupplyNorthValue;
|
|
743
|
+
G.garbageSupply -= garbageResupplyNorthValue;
|
|
744
|
+
}
|
|
745
|
+
const coalResupplyValue = Math.min(G.coalSupply, G.coalResupply[G.players.length - 2][G.step - 1], coalCapSouth);
|
|
660
746
|
G.coalMarket += coalResupplyValue;
|
|
661
747
|
G.coalSupply -= coalResupplyValue;
|
|
662
748
|
let oilResupplyValue;
|
|
@@ -678,25 +764,33 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
678
764
|
}
|
|
679
765
|
}
|
|
680
766
|
else {
|
|
681
|
-
oilResupplyValue = Math.min(G.oilSupply, G.oilResupply[G.players.length - 2][G.step - 1]);
|
|
767
|
+
oilResupplyValue = Math.min(G.oilSupply, G.oilResupply[G.players.length - 2][G.step - 1], oilCapSouth);
|
|
682
768
|
G.oilMarket += oilResupplyValue;
|
|
683
769
|
G.oilSupply -= oilResupplyValue;
|
|
684
770
|
}
|
|
685
|
-
const garbageResupplyValue = Math.min(G.garbageSupply, G.garbageResupply[G.players.length - 2][G.step - 1]);
|
|
771
|
+
const garbageResupplyValue = Math.min(G.garbageSupply, G.garbageResupply[G.players.length - 2][G.step - 1], garbageCapSouth);
|
|
686
772
|
G.garbageMarket += garbageResupplyValue;
|
|
687
773
|
G.garbageSupply -= garbageResupplyValue;
|
|
688
774
|
let uraniumResupplyValue = 0;
|
|
689
775
|
if (G.options.variant != 'recharged' ||
|
|
690
776
|
(G.options.map != 'Germany' && G.options.map != 'Italy') ||
|
|
691
777
|
!G.card39Bought) {
|
|
692
|
-
uraniumResupplyValue = Math.min(G.uraniumSupply, G.uraniumResupply[G.players.length - 2][G.step - 1]);
|
|
778
|
+
uraniumResupplyValue = Math.min(G.uraniumSupply, G.uraniumResupply[G.players.length - 2][G.step - 1], uraniumCapSouth);
|
|
693
779
|
G.uraniumMarket += uraniumResupplyValue;
|
|
694
780
|
G.uraniumSupply -= uraniumResupplyValue;
|
|
695
781
|
}
|
|
696
|
-
G.
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
782
|
+
if (G.coalResupplyNorth) {
|
|
783
|
+
G.log.push({
|
|
784
|
+
type: 'event',
|
|
785
|
+
event: `Resupplying resources — North: [${coalResupplyNorthValue}, ${oilResupplyNorthValue}, ${garbageResupplyNorthValue}], South: [${coalResupplyValue}, ${oilResupplyValue}, ${garbageResupplyValue}, ${uraniumResupplyValue}].`,
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
else {
|
|
789
|
+
G.log.push({
|
|
790
|
+
type: 'event',
|
|
791
|
+
event: `Resupplying resources: [${coalResupplyValue}, ${oilResupplyValue}, ${garbageResupplyValue}, ${uraniumResupplyValue}].`,
|
|
792
|
+
});
|
|
793
|
+
}
|
|
700
794
|
if (G.map.name == 'Middle East' && G.step == 2 && G.futureMarket.length > 0) {
|
|
701
795
|
// If we aren't about to enter step 3, discard top two plants instead of one.
|
|
702
796
|
let powerPlantToPush = G.futureMarket.pop();
|
|
@@ -968,17 +1062,29 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
968
1062
|
case move_1.MoveName.BuyResource: {
|
|
969
1063
|
utils_1.asserts(move);
|
|
970
1064
|
G.chosenResource = move.data.resource;
|
|
1065
|
+
// Korea: lock the player to the side of their first buy this turn.
|
|
1066
|
+
// Subsequent buys must come from the same side until they pass.
|
|
1067
|
+
if (move.data.side) {
|
|
1068
|
+
G.chosenSide = move.data.side;
|
|
1069
|
+
}
|
|
1070
|
+
const isNorth = move.data.side === 'north';
|
|
971
1071
|
let price;
|
|
972
1072
|
switch (move.data.resource) {
|
|
973
1073
|
case gamestate_1.ResourceType.Coal: {
|
|
974
|
-
if (
|
|
1074
|
+
if (isNorth) {
|
|
1075
|
+
const coalPrices = G.coalPricesNorth;
|
|
1076
|
+
price = coalPrices[coalPrices.length - G.coalMarketNorth];
|
|
1077
|
+
player.coalLeft++;
|
|
1078
|
+
G.coalMarketNorth--;
|
|
1079
|
+
}
|
|
1080
|
+
else if (G.coalMarket == 0) {
|
|
975
1081
|
price = 8;
|
|
976
1082
|
player.coalLeft++;
|
|
977
1083
|
G.coalSupply--;
|
|
978
1084
|
move.fromSupply = true;
|
|
979
1085
|
}
|
|
980
1086
|
else {
|
|
981
|
-
const coalPrices = (
|
|
1087
|
+
const coalPrices = (_l = G.coalPrices) !== null && _l !== void 0 ? _l : prices_1.default[gamestate_1.ResourceType.Coal];
|
|
982
1088
|
price = coalPrices[coalPrices.length - G.coalMarket];
|
|
983
1089
|
player.coalLeft++;
|
|
984
1090
|
G.coalMarket--;
|
|
@@ -986,28 +1092,45 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
986
1092
|
break;
|
|
987
1093
|
}
|
|
988
1094
|
case gamestate_1.ResourceType.Oil: {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1095
|
+
if (isNorth) {
|
|
1096
|
+
const oilPrices = G.oilPricesNorth;
|
|
1097
|
+
price = oilPrices[oilPrices.length - G.oilMarketNorth];
|
|
1098
|
+
player.oilLeft++;
|
|
1099
|
+
G.oilMarketNorth--;
|
|
1100
|
+
}
|
|
1101
|
+
else {
|
|
1102
|
+
const oilPrices = (_m = G.oilPrices) !== null && _m !== void 0 ? _m : prices_1.default[gamestate_1.ResourceType.Oil];
|
|
1103
|
+
price = oilPrices[oilPrices.length - G.oilMarket];
|
|
1104
|
+
player.oilLeft++;
|
|
1105
|
+
G.oilMarket--;
|
|
1106
|
+
}
|
|
993
1107
|
break;
|
|
994
1108
|
}
|
|
995
1109
|
case gamestate_1.ResourceType.Garbage: {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1110
|
+
if (isNorth) {
|
|
1111
|
+
const garbagePrices = G.garbagePricesNorth;
|
|
1112
|
+
price = garbagePrices[garbagePrices.length - G.garbageMarketNorth];
|
|
1113
|
+
player.garbageLeft++;
|
|
1114
|
+
G.garbageMarketNorth--;
|
|
1115
|
+
}
|
|
1116
|
+
else {
|
|
1117
|
+
const garbagePrices = (_o = G.garbagePrices) !== null && _o !== void 0 ? _o : prices_1.default[gamestate_1.ResourceType.Garbage];
|
|
1118
|
+
price = garbagePrices[garbagePrices.length - G.garbageMarket];
|
|
1119
|
+
// $1 cheaper for players in Wien in Central Europe
|
|
1120
|
+
if (G.map.name == 'Central Europe') {
|
|
1121
|
+
const wienCity = player.cities.filter((c) => c.name == 'Wien');
|
|
1122
|
+
if ((wienCity === null || wienCity === void 0 ? void 0 : wienCity.length) > 0) {
|
|
1123
|
+
price--;
|
|
1124
|
+
}
|
|
1003
1125
|
}
|
|
1126
|
+
player.garbageLeft++;
|
|
1127
|
+
G.garbageMarket--;
|
|
1004
1128
|
}
|
|
1005
|
-
player.garbageLeft++;
|
|
1006
|
-
G.garbageMarket--;
|
|
1007
1129
|
break;
|
|
1008
1130
|
}
|
|
1009
1131
|
case gamestate_1.ResourceType.Uranium: {
|
|
1010
|
-
|
|
1132
|
+
// Uranium is only available from the South market (or non-Korea maps).
|
|
1133
|
+
const uraniumPrices = (_p = G.uraniumPrices) !== null && _p !== void 0 ? _p : prices_1.default[gamestate_1.ResourceType.Uranium];
|
|
1011
1134
|
price = uraniumPrices[uraniumPrices.length - G.uraniumMarket];
|
|
1012
1135
|
player.uraniumLeft++;
|
|
1013
1136
|
G.uraniumMarket--;
|
|
@@ -1109,10 +1232,17 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
1109
1232
|
break;
|
|
1110
1233
|
}
|
|
1111
1234
|
case move_1.MoveName.BuyResource: {
|
|
1235
|
+
const undoIsNorth = lastMove.data.side === 'north';
|
|
1112
1236
|
let price;
|
|
1113
1237
|
switch (lastMove.data.resource) {
|
|
1114
1238
|
case gamestate_1.ResourceType.Coal:
|
|
1115
|
-
if (
|
|
1239
|
+
if (undoIsNorth) {
|
|
1240
|
+
player.coalLeft--;
|
|
1241
|
+
G.coalMarketNorth++;
|
|
1242
|
+
const coalPrices = G.coalPricesNorth;
|
|
1243
|
+
price = coalPrices[coalPrices.length - G.coalMarketNorth];
|
|
1244
|
+
}
|
|
1245
|
+
else if (lastMove.fromSupply) {
|
|
1116
1246
|
price = 8;
|
|
1117
1247
|
player.coalLeft--;
|
|
1118
1248
|
G.coalSupply++;
|
|
@@ -1120,35 +1250,52 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
1120
1250
|
else {
|
|
1121
1251
|
player.coalLeft--;
|
|
1122
1252
|
G.coalMarket++;
|
|
1123
|
-
const coalPrices = (
|
|
1253
|
+
const coalPrices = (_q = G.coalPrices) !== null && _q !== void 0 ? _q : prices_1.default[gamestate_1.ResourceType.Coal];
|
|
1124
1254
|
price = coalPrices[coalPrices.length - G.coalMarket];
|
|
1125
1255
|
}
|
|
1126
1256
|
break;
|
|
1127
1257
|
case gamestate_1.ResourceType.Oil: {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1258
|
+
if (undoIsNorth) {
|
|
1259
|
+
player.oilLeft--;
|
|
1260
|
+
G.oilMarketNorth++;
|
|
1261
|
+
const oilPrices = G.oilPricesNorth;
|
|
1262
|
+
price = oilPrices[oilPrices.length - G.oilMarketNorth];
|
|
1263
|
+
}
|
|
1264
|
+
else {
|
|
1265
|
+
player.oilLeft--;
|
|
1266
|
+
G.oilMarket++;
|
|
1267
|
+
const oilPrices = (_r = G.oilPrices) !== null && _r !== void 0 ? _r : prices_1.default[gamestate_1.ResourceType.Oil];
|
|
1268
|
+
price = oilPrices[oilPrices.length - G.oilMarket];
|
|
1269
|
+
}
|
|
1132
1270
|
break;
|
|
1133
1271
|
}
|
|
1134
1272
|
case gamestate_1.ResourceType.Garbage: {
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1273
|
+
if (undoIsNorth) {
|
|
1274
|
+
player.garbageLeft--;
|
|
1275
|
+
G.garbageMarketNorth++;
|
|
1276
|
+
const garbagePrices = G.garbagePricesNorth;
|
|
1277
|
+
price = garbagePrices[garbagePrices.length - G.garbageMarketNorth];
|
|
1278
|
+
}
|
|
1279
|
+
else {
|
|
1280
|
+
player.garbageLeft--;
|
|
1281
|
+
G.garbageMarket++;
|
|
1282
|
+
const garbagePrices = (_s = G.garbagePrices) !== null && _s !== void 0 ? _s : prices_1.default[gamestate_1.ResourceType.Garbage];
|
|
1283
|
+
price = garbagePrices[garbagePrices.length - G.garbageMarket];
|
|
1284
|
+
// $1 cheaper for players in Wien in Central Europe
|
|
1285
|
+
if (G.map.name == 'Central Europe') {
|
|
1286
|
+
const wienCity = player.cities.filter((c) => c.name == 'Wien');
|
|
1287
|
+
if ((wienCity === null || wienCity === void 0 ? void 0 : wienCity.length) > 0) {
|
|
1288
|
+
price--;
|
|
1289
|
+
}
|
|
1144
1290
|
}
|
|
1145
1291
|
}
|
|
1146
1292
|
break;
|
|
1147
1293
|
}
|
|
1148
1294
|
case gamestate_1.ResourceType.Uranium: {
|
|
1295
|
+
// Uranium is only available from the South market (or non-Korea maps).
|
|
1149
1296
|
player.uraniumLeft--;
|
|
1150
1297
|
G.uraniumMarket++;
|
|
1151
|
-
const uraniumPrices = (
|
|
1298
|
+
const uraniumPrices = (_t = G.uraniumPrices) !== null && _t !== void 0 ? _t : prices_1.default[gamestate_1.ResourceType.Uranium];
|
|
1152
1299
|
price = uraniumPrices[uraniumPrices.length - G.uraniumMarket];
|
|
1153
1300
|
break;
|
|
1154
1301
|
}
|
|
@@ -1161,6 +1308,22 @@ function move(G, move, playerNumber, isUndo = false) {
|
|
|
1161
1308
|
G.chosenResource = undefined;
|
|
1162
1309
|
}
|
|
1163
1310
|
G.log.pop();
|
|
1311
|
+
// Korea: keep chosenSide locked while the player still has
|
|
1312
|
+
// outstanding BuyResource moves this phase, but clear it once
|
|
1313
|
+
// the last one is undone so they can switch sides again.
|
|
1314
|
+
if (G.map.name == 'Korea' && G.chosenSide) {
|
|
1315
|
+
let stillCommitted = false;
|
|
1316
|
+
for (let i = G.log.length - 1; i >= 0; i--) {
|
|
1317
|
+
const entry = G.log[i];
|
|
1318
|
+
if (entry.type !== 'move')
|
|
1319
|
+
continue;
|
|
1320
|
+
stillCommitted = entry.player === playerNumber && entry.move.name === move_1.MoveName.BuyResource;
|
|
1321
|
+
break;
|
|
1322
|
+
}
|
|
1323
|
+
if (!stillCommitted) {
|
|
1324
|
+
G.chosenSide = undefined;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1164
1327
|
break;
|
|
1165
1328
|
}
|
|
1166
1329
|
case move_1.MoveName.Build: {
|
|
@@ -1905,6 +2068,13 @@ function updateGameState(G) {
|
|
|
1905
2068
|
`[${G.coalResupply[p][1]}, ${G.oilResupply[p][1]}, ${G.garbageResupply[p][1]}, ${G.uraniumResupply[p][1]}]`,
|
|
1906
2069
|
`[${G.coalResupply[p][2]}, ${G.oilResupply[p][2]}, ${G.garbageResupply[p][2]}, ${G.uraniumResupply[p][2]}]`,
|
|
1907
2070
|
];
|
|
2071
|
+
if (G.coalResupplyNorth && G.oilResupplyNorth && G.garbageResupplyNorth) {
|
|
2072
|
+
G.resourceResupplyNorth = [
|
|
2073
|
+
`[${G.coalResupplyNorth[p][0]}, ${G.oilResupplyNorth[p][0]}, ${G.garbageResupplyNorth[p][0]}]`,
|
|
2074
|
+
`[${G.coalResupplyNorth[p][1]}, ${G.oilResupplyNorth[p][1]}, ${G.garbageResupplyNorth[p][1]}]`,
|
|
2075
|
+
`[${G.coalResupplyNorth[p][2]}, ${G.oilResupplyNorth[p][2]}, ${G.garbageResupplyNorth[p][2]}]`,
|
|
2076
|
+
];
|
|
2077
|
+
}
|
|
1908
2078
|
}
|
|
1909
2079
|
}
|
|
1910
2080
|
function fastAuction(G, player, bid) {
|
package/dist/src/gamestate.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { AvailableMoves } from './available-moves';
|
|
|
2
2
|
import { LogItem } from './log';
|
|
3
3
|
import { GameMap } from './maps';
|
|
4
4
|
import { Move } from './move';
|
|
5
|
-
export declare type MapName = 'USA' | 'Germany' | 'Brazil' | 'Spain & Portugal' | 'France' | 'Italy' | 'Quebec' | 'Middle East' | 'India' | 'China' | 'Benelux' | 'Russia' | 'Central Europe';
|
|
5
|
+
export declare type MapName = 'USA' | 'Germany' | 'Brazil' | 'Spain & Portugal' | 'France' | 'Italy' | 'Quebec' | 'Middle East' | 'India' | 'China' | 'Benelux' | 'Russia' | 'Central Europe' | 'Baden-Württemberg' | 'Northern Europe' | 'Korea';
|
|
6
6
|
export declare type Variant = 'original' | 'recharged';
|
|
7
7
|
export interface GameOptions {
|
|
8
8
|
fastBid?: boolean;
|
|
@@ -100,6 +100,15 @@ export interface GameState {
|
|
|
100
100
|
oilResupply?: number[][];
|
|
101
101
|
garbageResupply?: number[][];
|
|
102
102
|
uraniumResupply?: number[][];
|
|
103
|
+
coalMarketNorth?: number;
|
|
104
|
+
oilMarketNorth?: number;
|
|
105
|
+
garbageMarketNorth?: number;
|
|
106
|
+
coalResupplyNorth?: number[][];
|
|
107
|
+
oilResupplyNorth?: number[][];
|
|
108
|
+
garbageResupplyNorth?: number[][];
|
|
109
|
+
coalPricesNorth?: number[];
|
|
110
|
+
oilPricesNorth?: number[];
|
|
111
|
+
garbagePricesNorth?: number[];
|
|
103
112
|
coalPrices?: number[];
|
|
104
113
|
oilPrices?: number[];
|
|
105
114
|
garbagePrices?: number[];
|
|
@@ -108,6 +117,7 @@ export interface GameState {
|
|
|
108
117
|
futureMarket: PowerPlant[];
|
|
109
118
|
chosenPowerPlant: PowerPlant | undefined;
|
|
110
119
|
chosenResource?: ResourceType | undefined;
|
|
120
|
+
chosenSide?: 'north' | 'south';
|
|
111
121
|
currentBid: number | undefined;
|
|
112
122
|
auctioningPlayer: number | undefined;
|
|
113
123
|
step: number;
|
|
@@ -122,6 +132,7 @@ export interface GameState {
|
|
|
122
132
|
citiesToEndGame: number;
|
|
123
133
|
citiesBuiltInCurrentRound?: number;
|
|
124
134
|
resourceResupply: string[];
|
|
135
|
+
resourceResupplyNorth?: string[];
|
|
125
136
|
paymentTable: number[];
|
|
126
137
|
minimunBid: number;
|
|
127
138
|
plantDiscountActive: boolean;
|