powergrid-viewer 1.9.8 → 1.10.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powergrid-viewer",
3
- "version": "1.9.8",
3
+ "version": "1.10.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/boardgamers/powergrid.git",
@@ -18,7 +18,7 @@
18
18
  "vue": "^2.6.11",
19
19
  "vue-class-component": "^7.2.3",
20
20
  "vue-property-decorator": "^8.4.2",
21
- "powergrid-engine": "1.13.6"
21
+ "powergrid-engine": "1.14.1"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/assert": "^1.4.7",
@@ -110,6 +110,68 @@
110
110
  @buyResource="buyResource($event)"
111
111
  />
112
112
 
113
+ <!-- Australia: uranium-mine selling table. Six price rows $7 (top) →
114
+ $2 (bottom), two token slots each. Sellers place one token per mine
115
+ on the highest empty slot; the resource refill removes from the
116
+ cheap (bottom) end. Lives in the clear upper-left margin. -->
117
+ <g v-if="G.map.name === 'Australia' && G.uraniumMineMarket" transform="translate(15, 70)">
118
+ <rect x="0" y="0" width="104" height="430" rx="6" fill="#8aa84a" stroke="#4d6322" stroke-width="3" />
119
+ <text x="52" y="22" text-anchor="middle" font-weight="700" fill="black" style="font-size: 15px">
120
+ Uranium
121
+ </text>
122
+ <text x="52" y="38" text-anchor="middle" font-weight="600" fill="black" style="font-size: 11px">
123
+ mine market
124
+ </text>
125
+ <g v-for="row in 6" :key="'uraniumRow' + row" :transform="`translate(0, ${50 + (row - 1) * 59})`">
126
+ <text x="16" y="32" text-anchor="middle" font-weight="700" fill="black" style="font-size: 15px">
127
+ ${{ 8 - row }}
128
+ </text>
129
+ <rect
130
+ x="36"
131
+ y="14"
132
+ width="26"
133
+ height="26"
134
+ rx="3"
135
+ fill="goldenrod"
136
+ stroke="#4d6322"
137
+ stroke-width="1.5"
138
+ />
139
+ <rect
140
+ x="68"
141
+ y="14"
142
+ width="26"
143
+ height="26"
144
+ rx="3"
145
+ fill="goldenrod"
146
+ stroke="#4d6322"
147
+ stroke-width="1.5"
148
+ />
149
+ <circle
150
+ v-if="(G.uraniumMineMarket[6 - row] || 0) >= 1"
151
+ cx="49"
152
+ cy="27"
153
+ r="10"
154
+ fill="#46c655"
155
+ stroke="#1f5c25"
156
+ stroke-width="2"
157
+ />
158
+ <circle
159
+ v-if="(G.uraniumMineMarket[6 - row] || 0) >= 2"
160
+ cx="81"
161
+ cy="27"
162
+ r="10"
163
+ fill="#46c655"
164
+ stroke="#1f5c25"
165
+ stroke-width="2"
166
+ />
167
+ </g>
168
+ <!-- Removal rate: tokens taken from the cheapest slots each refill (current step). -->
169
+ <line x1="10" y1="402" x2="94" y2="402" stroke="#4d6322" stroke-width="1" />
170
+ <text x="52" y="420" text-anchor="middle" font-weight="700" fill="#22340f" style="font-size: 12px">
171
+ refill −{{ G.map.uraniumMineResupply[G.players.length - 2][G.step - 1] }}/rnd
172
+ </text>
173
+ </g>
174
+
113
175
  <g :transform="`translate(${G.map.roundInfoPosition[0]}, ${G.map.roundInfoPosition[1]})`">
114
176
  <template v-if="gameEnded(G)">
115
177
  <Button
@@ -175,6 +237,7 @@
175
237
  :showMoney="player == playerIndex || gameEnded(G) || G.options.showMoney"
176
238
  :showBid="!G.options.fastBid"
177
239
  :phase="G.phase"
240
+ :isAustralia="G.map.name === 'Australia'"
178
241
  @powerPlantClick="powerPlantClick($event)"
179
242
  @discardResource="discardResource($event)"
180
243
  />
@@ -368,6 +431,11 @@
368
431
  (S), <strong>{{ G.resourceResupplyNorth[0] }}</strong> (N)
369
432
  </template>
370
433
  </li>
434
+ <li v-if="G.map.uraniumMineResupply">
435
+ Uranium market: remove
436
+ <strong>{{ G.map.uraniumMineResupply[G.players.length - 2][0] }}</strong>
437
+ token(s) from the cheapest slots
438
+ </li>
371
439
  <li>Bureaucracy: remove <strong>highest</strong> power plant from market</li>
372
440
  </ul>
373
441
  </li>
@@ -385,6 +453,11 @@
385
453
  (S), <strong>{{ G.resourceResupplyNorth[1] }}</strong> (N)
386
454
  </template>
387
455
  </li>
456
+ <li v-if="G.map.uraniumMineResupply">
457
+ Uranium market: remove
458
+ <strong>{{ G.map.uraniumMineResupply[G.players.length - 2][1] }}</strong>
459
+ token(s) from the cheapest slots
460
+ </li>
388
461
  <li>Bureaucracy: remove <strong>highest</strong> power plant from market</li>
389
462
  </ul>
390
463
  </li>
@@ -399,6 +472,11 @@
399
472
  (S), <strong>{{ G.resourceResupplyNorth[2] }}</strong> (N)
400
473
  </template>
401
474
  </li>
475
+ <li v-if="G.map.uraniumMineResupply">
476
+ Uranium market: remove
477
+ <strong>{{ G.map.uraniumMineResupply[G.players.length - 2][2] }}</strong>
478
+ token(s) from the cheapest slots
479
+ </li>
402
480
  <li>Bureaucracy: remove <strong>lowest</strong> power plant from market</li>
403
481
  <li>All power plants available for auction</li>
404
482
  </ul>
@@ -18,19 +18,47 @@
18
18
  <Card
19
19
  v-for="(powerPlant, i) in player.powerPlants"
20
20
  :key="'powerPlant_' + powerPlant.number"
21
- :targetState="{ x: player.powerPlants.length < 5 ? 20 + 80 * i : 5 + 70 * i, y: 30 }"
21
+ :targetState="{ x: cardX(i), y: 30 }"
22
22
  :owner="owner"
23
23
  :powerPlant="powerPlant"
24
24
  :canClick="canUse(powerPlant)"
25
25
  @click="powerPlantClick(powerPlant)"
26
26
  />
27
27
 
28
+ <!-- Australia: mark uranium mines (they sell uranium instead of powering
29
+ cities, and don't count toward the 3-plant limit) with a green frame
30
+ and a uranium badge. -->
31
+ <template v-for="(powerPlant, i) in player.powerPlants">
32
+ <g v-if="isMine(powerPlant)" :key="'mine_' + powerPlant.number">
33
+ <rect
34
+ :x="cardX(i)"
35
+ y="30"
36
+ width="60"
37
+ height="40"
38
+ fill="none"
39
+ stroke="#2e8b3d"
40
+ stroke-width="3px"
41
+ rx="3px"
42
+ />
43
+ <circle :cx="cardX(i) + 51" cy="37" r="8" fill="#46c655" stroke="#1f5c25" stroke-width="1.5" />
44
+ <text
45
+ :x="cardX(i) + 51"
46
+ y="40"
47
+ text-anchor="middle"
48
+ fill="white"
49
+ style="font-size: 9px; font-weight: 700"
50
+ >
51
+ U
52
+ </text>
53
+ </g>
54
+ </template>
55
+
28
56
  <template v-if="!preferences.disableHelp">
29
57
  <template v-for="(powerPlant, i) in player.powerPlants">
30
58
  <rect
31
59
  v-if="canUse(powerPlant)"
32
60
  :key="i + '_' + i + '_helper'"
33
- :x="player.powerPlants.length < 5 ? 20 + 80 * i : 5 + 70 * i"
61
+ :x="cardX(i)"
34
62
  :y="30"
35
63
  width="60"
36
64
  height="40"
@@ -98,11 +126,27 @@ export default class PlayerBoard extends Vue {
98
126
  @Prop() showMoney?: boolean;
99
127
  @Prop() showBid?: boolean;
100
128
  @Prop() phase?: Phase;
129
+ // Australia: uranium plants are "mines" — flag so the hand marks them distinctly.
130
+ @Prop() isAustralia?: boolean;
101
131
 
102
132
  @Inject() preferences!: Preferences;
103
133
 
104
134
  powerPlantClicked?: PowerPlant;
105
135
 
136
+ // Horizontal position of the i-th power-plant card. Spacing compresses as the
137
+ // hand grows so Australia's mines (which don't count toward the 3-plant limit,
138
+ // so a player can hold many cards) stay on the board instead of overflowing
139
+ // off the right edge. Non-Australia hands never exceed 4, so they are unaffected.
140
+ cardX(i: number): number {
141
+ const n = this.player.powerPlants.length;
142
+ if (n < 5) return 20 + 80 * i;
143
+ return 5 + Math.min(70, 280 / (n - 1)) * i;
144
+ }
145
+
146
+ isMine(powerPlant: PowerPlant): boolean {
147
+ return this.isAustralia === true && powerPlant.type === PowerPlantType.Uranium;
148
+ }
149
+
106
150
  getPlayerName() {
107
151
  let name = '';
108
152
  if (this.isCurrentPlayer) {
@@ -123,13 +123,16 @@
123
123
  {{ resourceResupply[2] }}
124
124
  </text>
125
125
  <Garbage :pieceId="-1" :targetState="{ x: 382, y: 11 }" :canClick="false" :transparent="false" />
126
- <text x="414" y="20" font-weight="600" fill="black" style="font-size: 24px">
127
- {{ resourceResupply[3] }}
128
- </text>
129
- <Uranium :pieceId="-1" :targetState="{ x: 428, y: 12 }" :canClick="false" :transparent="false" />
126
+ <!-- Australia has no main-market uranium row, so its resupply indicator omits uranium. -->
127
+ <template v-if="!isAustraliaMarket">
128
+ <text x="414" y="20" font-weight="600" fill="black" style="font-size: 24px">
129
+ {{ resourceResupply[3] }}
130
+ </text>
131
+ <Uranium :pieceId="-1" :targetState="{ x: 428, y: 12 }" :canClick="false" :transparent="false" />
132
+ </template>
130
133
 
131
134
  <rect
132
- v-if="!isIndiaResourceMarket && !isNinePriceMarket"
135
+ v-if="!isIndiaResourceMarket && !isNinePriceMarket && !isAustraliaMarket"
133
136
  width="760"
134
137
  height="80"
135
138
  x="20"
@@ -138,8 +141,9 @@
138
141
  fill="goldenrod"
139
142
  />
140
143
  <rect v-if="isNinePriceMarket" width="780" height="80" x="20" y="40" rx="3" fill="goldenrod" />
144
+ <rect v-if="isAustraliaMarket" width="870" height="80" x="20" y="40" rx="3" fill="goldenrod" />
141
145
  <rect v-if="isIndiaResourceMarket" width="680" height="80" x="20" y="40" rx="3" fill="goldenrod" />
142
- <template v-for="index in isNinePriceMarket ? 9 : 8">
146
+ <template v-for="index in isNinePriceMarket ? 9 : isAustraliaMarket ? 10 : 8">
143
147
  <rect
144
148
  :key="'resources' + index"
145
149
  width="70"
@@ -160,7 +164,7 @@
160
164
  >
161
165
  {{ index }}
162
166
  </text>
163
- <g :key="'lines' + index" v-if="!isIndiaResourceMarket && !isNinePriceMarket">
167
+ <g :key="'lines' + index" v-if="!isIndiaResourceMarket && !isNinePriceMarket && !isAustraliaMarket">
164
168
  <line :x1="25 + 85 * (index - 1)" y1="68" :x2="95 + 85 * (index - 1)" y2="68" stroke="goldenrod" />
165
169
  <line :x1="25 + 85 * (index - 1)" y1="92" :x2="95 + 85 * (index - 1)" y2="92" stroke="goldenrod" />
166
170
 
@@ -188,6 +192,20 @@
188
192
  </g>
189
193
  </template>
190
194
 
195
+ <!-- Australia: the $1 and $2 spaces close once the Step 3 CO2 tax fires. -->
196
+ <template v-if="isAustraliaMarket && co2TaxActive">
197
+ <rect width="160" height="70" x="24" y="45" rx="2" fill="black" opacity="0.55" />
198
+ <text
199
+ text-anchor="middle"
200
+ style="font-size: 12px; font-family: monospace; font-weight: 700"
201
+ x="104"
202
+ y="84"
203
+ fill="white"
204
+ >
205
+ CO₂ closed
206
+ </text>
207
+ </template>
208
+
191
209
  <template v-if="isIndiaResourceMarket">
192
210
  <g :key="'separators'">
193
211
  <line x1="275" y1="40" x2="275" y2="140" stroke="red" />
@@ -198,7 +216,7 @@
198
216
  </g>
199
217
  </template>
200
218
 
201
- <template v-if="!isIndiaResourceMarket && !isNinePriceMarket">
219
+ <template v-if="!isIndiaResourceMarket && !isNinePriceMarket && !isAustraliaMarket">
202
220
  <rect width="30" height="30" x="705" y="45" rx="2" fill="darkgoldenrod" />
203
221
  <circle r="10" cx="732" cy="48" fill="yellow" />
204
222
  <text
@@ -366,7 +384,7 @@
366
384
  v-if="!isKorea && buyableResources.length > 0"
367
385
  x="15"
368
386
  y="35"
369
- width="770"
387
+ :width="isAustraliaMarket ? 880 : 770"
370
388
  height="90"
371
389
  rx="2"
372
390
  fill="none"
@@ -432,6 +450,10 @@ export default class Resources extends Vue {
432
450
 
433
451
  isKorea: boolean = false;
434
452
  isNinePriceMarket: boolean = false;
453
+ // Australia: coal/oil/garbage-only market that can reach $10 after the Step 3
454
+ // CO2 tax. co2TaxActive closes the $1/$2 columns once that shift has happened.
455
+ isAustraliaMarket: boolean = false;
456
+ co2TaxActive: boolean = false;
435
457
  coalsNorth: Piece[] = [];
436
458
  oilsNorth: Piece[] = [];
437
459
  garbagesNorth: Piece[] = [];
@@ -483,6 +505,9 @@ export default class Resources extends Vue {
483
505
  createPieces(gameState: GameState) {
484
506
  if (!gameState) return;
485
507
 
508
+ this.isAustraliaMarket = gameState.map?.name === 'Australia';
509
+ this.co2TaxActive = this.isAustraliaMarket && gameState.step >= 3;
510
+
486
511
  const isKorea = gameState.coalMarketNorth !== undefined;
487
512
  this.isKorea = isKorea;
488
513
 
@@ -558,6 +583,29 @@ export default class Resources extends Vue {
558
583
  );
559
584
  return;
560
585
  }
586
+
587
+ // Australia: coal/oil/garbage only (no uranium row — uranium lives in the
588
+ // separate mine market). Prices run $1–$8, shifting to $3–$10 at Step 3
589
+ // (CO2 tax). buildMainRowPieces positions cubes by price, so the shift is
590
+ // automatic; the template renders 10 price columns and closes $1/$2 once
591
+ // co2TaxActive.
592
+ if (this.isAustraliaMarket) {
593
+ this.coals = this.buildMainRowPieces(
594
+ gameState.coalPrices!, gameState.coalMarket, 'coal', 48, { maxPrice: 10 },
595
+ );
596
+ this.oils = this.buildMainRowPieces(
597
+ gameState.oilPrices!, gameState.oilMarket, 'oil', 70, { maxPrice: 10 },
598
+ );
599
+ this.garbages = this.buildMainRowPieces(
600
+ gameState.garbagePrices!, gameState.garbageMarket, 'garbage', 94, { maxPrice: 10 },
601
+ );
602
+ this.uraniums = [];
603
+ this.coalsNorth = [];
604
+ this.oilsNorth = [];
605
+ this.garbagesNorth = [];
606
+ return;
607
+ }
608
+
561
609
  this.isNinePriceMarket = false;
562
610
 
563
611
  // Non-Korea: original logic below (unchanged).
@@ -10,7 +10,7 @@ function launchSelfContained(selector = '#app') {
10
10
 
11
11
  const emitter = launch(selector);
12
12
 
13
- let gameState = setup(5, { map: 'Japan', variant: 'recharged', showMoney: true, randomizeMap: false }, '7');
13
+ let gameState = setup(6, { map: 'Australia', variant: 'recharged', showMoney: true, randomizeMap: false }, '7');
14
14
 
15
15
  // Dev coord-picker example (commented; uncomment + drop a board photo into
16
16
  // viewer/public/ to author city coordinates for a new map). See the picker