powergrid-engine 1.10.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 +2 -0
- package/dist/src/available-moves.js +110 -9
- package/dist/src/engine.js +290 -57
- package/dist/src/gamestate.d.ts +13 -1
- package/dist/src/maps/europe.d.ts +62 -0
- package/dist/src/maps/europe.js +356 -0
- package/dist/src/maps/korea.js +107 -0
- package/dist/src/maps/northamerica.d.ts +62 -0
- package/dist/src/maps/northamerica.js +330 -0
- package/dist/src/maps/northerneurope.js +75 -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 +16 -0
- package/dist/src/maps.js +19 -8
- package/dist/src/move.d.ts +2 -0
- package/package.json +1 -1
- package/src/available-moves.ts +158 -10
- package/src/engine.spec.ts +17 -0
- package/src/engine.ts +305 -52
- package/src/gamestate.ts +33 -6
- package/src/maps/europe.ts +391 -0
- package/src/maps/korea.ts +109 -0
- package/src/maps/northamerica.ts +360 -0
- package/src/maps/northerneurope.ts +76 -0
- package/src/maps/southafrica.ts +247 -116
- package/src/maps/ukireland.ts +170 -40
- package/src/maps.ts +53 -13
- package/src/move.ts +7 -0
|
@@ -66,6 +66,15 @@ function availableMoves(G, player) {
|
|
|
66
66
|
canBid = canBid.filter((p) => p.type != gamestate_1.PowerPlantType.Uranium);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
// No nuclear plants for Republic of Ireland (Green region) on UK&I.
|
|
70
|
+
// The restriction lifts as soon as the player has any non-Green city
|
|
71
|
+
// (Scotland/Wales/England/Northern Ireland = Brown/Yellow/Red/Pink/Orange).
|
|
72
|
+
if (G.map.name == 'UK & Ireland') {
|
|
73
|
+
const playerCities = player.cities.map((c) => G.map.cities.find((c_) => c_.name == c.name));
|
|
74
|
+
if (playerCities.every((c) => c.region == 'green')) {
|
|
75
|
+
canBid = canBid.filter((p) => p.type != gamestate_1.PowerPlantType.Uranium);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
69
78
|
if (canBid.length > 0) {
|
|
70
79
|
moves[move_1.MoveName.ChoosePowerPlant] = canBid.map((p) => p.number);
|
|
71
80
|
}
|
|
@@ -107,6 +116,14 @@ function availableMoves(G, player) {
|
|
|
107
116
|
moves[move_1.MoveName.Bid] = undefined;
|
|
108
117
|
}
|
|
109
118
|
}
|
|
119
|
+
// No nuclear plants for Republic of Ireland (Green region) on UK&I.
|
|
120
|
+
if (G.map.name == 'UK & Ireland') {
|
|
121
|
+
const playerCities = player.cities.map((c) => G.map.cities.find((c_) => c_.name == c.name));
|
|
122
|
+
if (playerCities.every((c) => c.region == 'green') &&
|
|
123
|
+
G.chosenPowerPlant.type == gamestate_1.PowerPlantType.Uranium) {
|
|
124
|
+
moves[move_1.MoveName.Bid] = undefined;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
110
127
|
if (G.options.fastBid) {
|
|
111
128
|
if (player.id != G.auctioningPlayer) {
|
|
112
129
|
moves[move_1.MoveName.Pass] = [true];
|
|
@@ -135,17 +152,22 @@ function availableMoves(G, player) {
|
|
|
135
152
|
else {
|
|
136
153
|
maxPriceAvailable = 16;
|
|
137
154
|
}
|
|
138
|
-
|
|
155
|
+
// Korea: each side is offered separately, tagged with the side. The
|
|
156
|
+
// player's chosenSide locks them to one side once they make a buy.
|
|
157
|
+
const isKorea = G.coalResupplyNorth !== undefined;
|
|
158
|
+
const allowSouth = !isKorea || G.chosenSide !== 'north';
|
|
159
|
+
const allowNorth = isKorea && G.chosenSide !== 'south';
|
|
160
|
+
if (allowSouth && G.coalMarket > 0) {
|
|
139
161
|
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
140
162
|
const coalPrices = (_c = G.coalPrices) !== null && _c !== void 0 ? _c : prices_1.default[gamestate_1.ResourceType.Coal];
|
|
141
163
|
const price = coalPrices[coalPrices.length - G.coalMarket];
|
|
142
164
|
if (player.money >= price &&
|
|
143
165
|
player.coalCapacity + player.hybridCapacity > hybridCapacityUsed + player.coalLeft &&
|
|
144
166
|
price <= maxPriceAvailable) {
|
|
145
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Coal });
|
|
167
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Coal, side: 'south' } : { resource: gamestate_1.ResourceType.Coal });
|
|
146
168
|
}
|
|
147
169
|
}
|
|
148
|
-
else {
|
|
170
|
+
else if (allowSouth) {
|
|
149
171
|
if (G.options.variant == 'recharged' && G.map.name == 'USA' && G.coalSupply > 0) {
|
|
150
172
|
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
151
173
|
if (player.money >= 8 &&
|
|
@@ -154,17 +176,48 @@ function availableMoves(G, player) {
|
|
|
154
176
|
}
|
|
155
177
|
}
|
|
156
178
|
}
|
|
157
|
-
|
|
179
|
+
// South Africa: $8 flat coal from the storage pool below the market.
|
|
180
|
+
// Always available alongside the regular market option (not gated on
|
|
181
|
+
// market being empty), as long as there are cubes in storage.
|
|
182
|
+
if (allowSouth && G.coalStorage !== undefined && G.coalStorage > 0) {
|
|
183
|
+
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
184
|
+
if (player.money >= 8 &&
|
|
185
|
+
player.coalCapacity + player.hybridCapacity > hybridCapacityUsed + player.coalLeft &&
|
|
186
|
+
8 <= maxPriceAvailable) {
|
|
187
|
+
toBuy.push({ resource: gamestate_1.ResourceType.Coal, fromStorage: true });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (allowNorth && G.coalMarketNorth > 0) {
|
|
191
|
+
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.oilLeft - player.oilCapacity) : 0;
|
|
192
|
+
const coalPrices = G.coalPricesNorth;
|
|
193
|
+
const price = coalPrices[coalPrices.length - G.coalMarketNorth];
|
|
194
|
+
if (player.money >= price &&
|
|
195
|
+
player.coalCapacity + player.hybridCapacity > hybridCapacityUsed + player.coalLeft &&
|
|
196
|
+
price <= maxPriceAvailable) {
|
|
197
|
+
toBuy.push({ resource: gamestate_1.ResourceType.Coal, side: 'north' });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (allowSouth && G.oilMarket > 0) {
|
|
158
201
|
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.coalLeft - player.coalCapacity) : 0;
|
|
159
202
|
const oilPrices = (_d = G.oilPrices) !== null && _d !== void 0 ? _d : prices_1.default[gamestate_1.ResourceType.Oil];
|
|
160
203
|
const price = oilPrices[oilPrices.length - G.oilMarket];
|
|
161
204
|
if (player.money >= price &&
|
|
162
205
|
player.oilCapacity + player.hybridCapacity > hybridCapacityUsed + player.oilLeft &&
|
|
163
206
|
price <= maxPriceAvailable) {
|
|
164
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Oil });
|
|
207
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Oil, side: 'south' } : { resource: gamestate_1.ResourceType.Oil });
|
|
165
208
|
}
|
|
166
209
|
}
|
|
167
|
-
if (G.
|
|
210
|
+
if (allowNorth && G.oilMarketNorth > 0) {
|
|
211
|
+
const hybridCapacityUsed = player.hybridCapacity > 0 ? Math.max(0, player.coalLeft - player.coalCapacity) : 0;
|
|
212
|
+
const oilPrices = G.oilPricesNorth;
|
|
213
|
+
const price = oilPrices[oilPrices.length - G.oilMarketNorth];
|
|
214
|
+
if (player.money >= price &&
|
|
215
|
+
player.oilCapacity + player.hybridCapacity > hybridCapacityUsed + player.oilLeft &&
|
|
216
|
+
price <= maxPriceAvailable) {
|
|
217
|
+
toBuy.push({ resource: gamestate_1.ResourceType.Oil, side: 'north' });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (allowSouth && G.garbageMarket > 0) {
|
|
168
221
|
const garbagePrices = (_e = G.garbagePrices) !== null && _e !== void 0 ? _e : prices_1.default[gamestate_1.ResourceType.Garbage];
|
|
169
222
|
let price = garbagePrices[garbagePrices.length - G.garbageMarket];
|
|
170
223
|
// $1 cheaper for players in Wien in Central Europe
|
|
@@ -177,16 +230,26 @@ function availableMoves(G, player) {
|
|
|
177
230
|
if (player.money >= price &&
|
|
178
231
|
player.garbageCapacity > player.garbageLeft &&
|
|
179
232
|
price <= maxPriceAvailable) {
|
|
180
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Garbage });
|
|
233
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Garbage, side: 'south' } : { resource: gamestate_1.ResourceType.Garbage });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (allowNorth && G.garbageMarketNorth > 0) {
|
|
237
|
+
const garbagePrices = G.garbagePricesNorth;
|
|
238
|
+
const price = garbagePrices[garbagePrices.length - G.garbageMarketNorth];
|
|
239
|
+
if (player.money >= price &&
|
|
240
|
+
player.garbageCapacity > player.garbageLeft &&
|
|
241
|
+
price <= maxPriceAvailable) {
|
|
242
|
+
toBuy.push({ resource: gamestate_1.ResourceType.Garbage, side: 'north' });
|
|
181
243
|
}
|
|
182
244
|
}
|
|
183
|
-
|
|
245
|
+
// Uranium is South only (or non-Korea maps).
|
|
246
|
+
if (allowSouth && G.uraniumMarket > 0) {
|
|
184
247
|
const uraniumPrices = (_f = G.uraniumPrices) !== null && _f !== void 0 ? _f : prices_1.default[gamestate_1.ResourceType.Uranium];
|
|
185
248
|
const price = uraniumPrices[uraniumPrices.length - G.uraniumMarket];
|
|
186
249
|
if (player.money >= price &&
|
|
187
250
|
player.uraniumCapacity > player.uraniumLeft &&
|
|
188
251
|
price <= maxPriceAvailable) {
|
|
189
|
-
toBuy.push({ resource: gamestate_1.ResourceType.Uranium });
|
|
252
|
+
toBuy.push(isKorea ? { resource: gamestate_1.ResourceType.Uranium, side: 'south' } : { resource: gamestate_1.ResourceType.Uranium });
|
|
190
253
|
}
|
|
191
254
|
}
|
|
192
255
|
if (toBuy.length > 0) {
|
|
@@ -221,6 +284,44 @@ function availableMoves(G, player) {
|
|
|
221
284
|
}
|
|
222
285
|
return;
|
|
223
286
|
}
|
|
287
|
+
// UK & Ireland: starting a network on an island where the player has
|
|
288
|
+
// no city yet pays the first-house base + crossIslandSurcharge. There
|
|
289
|
+
// is no sea edge so dijkstra reports the target city as unreachable
|
|
290
|
+
// (price=9999); we override here. The first build ever (player.cities
|
|
291
|
+
// empty) goes through the normal first-build path and pays no surcharge.
|
|
292
|
+
if (cityData.island && G.map.crossIslandSurcharge !== undefined && player.cities.length > 0) {
|
|
293
|
+
const playerIslands = new Set(player.cities
|
|
294
|
+
.map((c) => { var _a; return (_a = G.map.cities.find((mc) => mc.name == c.name)) === null || _a === void 0 ? void 0 : _a.island; })
|
|
295
|
+
.filter((i) => !!i));
|
|
296
|
+
if (!playerIslands.has(cityData.island)) {
|
|
297
|
+
city.price = 10 + othersCount * 5 + G.map.crossIslandSurcharge;
|
|
298
|
+
if (othersCount == G.step) {
|
|
299
|
+
city.price = 9999;
|
|
300
|
+
}
|
|
301
|
+
if (player.cities.find((c) => c.name == city.name)) {
|
|
302
|
+
city.price = 9999;
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// South Africa's cross-border foreign-country spaces: cap at 1 occupant
|
|
308
|
+
// ever, and the dijkstra path cost (30 via the cross-border edge) is the
|
|
309
|
+
// complete cost — no 10+position*5 house base is added. Players cannot
|
|
310
|
+
// start in one of these (you have to build INTO South Africa first).
|
|
311
|
+
if (cityData.singleOccupancy) {
|
|
312
|
+
if (player.cities.length == 0) {
|
|
313
|
+
city.price = 9999;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (othersCount >= 1) {
|
|
317
|
+
city.price = 9999;
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (player.cities.find((c) => c.name == city.name)) {
|
|
321
|
+
city.price = 9999;
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
224
325
|
city.price += 10 + othersCount * 5;
|
|
225
326
|
if (othersCount == G.step) {
|
|
226
327
|
city.price = 9999;
|