powergrid-viewer 1.10.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powergrid-viewer",
3
- "version": "1.10.1",
3
+ "version": "1.11.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/boardgamers/powergrid.git",
@@ -22,10 +22,26 @@
22
22
  </template> -->
23
23
 
24
24
  <template v-for="city in cities">
25
- <circle :key="city.name + '_region'" r="25" :cx="city.x" :cy="city.y" :fill="city.region" stroke="black">
25
+ <circle
26
+ v-if="city.connectionCost == null"
27
+ :key="city.name + '_region'"
28
+ r="25"
29
+ :cx="city.x"
30
+ :cy="city.y"
31
+ :fill="city.region"
32
+ stroke="black"
33
+ >
26
34
  <title>{{ city.name }}</title>
27
35
  </circle>
28
- <circle :key="city.name + '_circle'" r="20" :cx="city.x" :cy="city.y" fill="gray" stroke="black">
36
+ <circle
37
+ v-if="city.connectionCost == null"
38
+ :key="city.name + '_circle'"
39
+ r="20"
40
+ :cx="city.x"
41
+ :cy="city.y"
42
+ fill="gray"
43
+ stroke="black"
44
+ >
29
45
  <title>{{ city.name }}</title>
30
46
  </circle>
31
47
  <!-- South Africa cross-border spaces: render a small red pennant
@@ -72,8 +88,65 @@
72
88
  />
73
89
  </template>
74
90
 
91
+ <!-- Bremen-style node-weighted districts: clean labeled tiles (entry-cost
92
+ number + 8/14/20 house slots), drawn AFTER the links so the gray lines
93
+ sit behind. Gated on connectionCost; other maps keep circular nodes. -->
94
+ <template v-for="city in cities">
95
+ <g v-if="city.connectionCost != null" :key="city.name + '_tile'">
96
+ <rect
97
+ :class="[{ canClick: canBuild(city) }]"
98
+ :x="city.x - 23"
99
+ :y="city.y - 23"
100
+ width="46"
101
+ height="46"
102
+ rx="7"
103
+ fill="gray"
104
+ :stroke="city.region"
105
+ stroke-width="4"
106
+ :transform="`rotate(45, ${city.x}, ${city.y})`"
107
+ @click="canBuild(city) && build(city)"
108
+ >
109
+ <title>{{ city.name }} — connect for {{ city.connectionCost }} (entry) + house</title>
110
+ </rect>
111
+ <!-- house slots laid out like the board: 8 top, 14 left, 20 right -->
112
+ <template v-for="(sc, i) in city.slotCosts">
113
+ <rect
114
+ :key="city.name + '_slot' + i"
115
+ :x="city.x + nodeSlotPos(i).dx - 6.5"
116
+ :y="city.y + nodeSlotPos(i).dy - 6.5"
117
+ width="13"
118
+ height="13"
119
+ rx="1"
120
+ fill="gray"
121
+ stroke="black"
122
+ stroke-width="1"
123
+ :transform="`rotate(45, ${city.x + nodeSlotPos(i).dx}, ${city.y + nodeSlotPos(i).dy})`"
124
+ />
125
+ <text
126
+ :key="city.name + '_slotlbl' + i"
127
+ :x="city.x + nodeSlotPos(i).dx"
128
+ :y="city.y + nodeSlotPos(i).dy"
129
+ font-size="10"
130
+ text-anchor="middle"
131
+ dominant-baseline="central"
132
+ fill="black"
133
+ :transform="
134
+ mapRotation
135
+ ? `rotate(${-mapRotation}, ${city.x + nodeSlotPos(i).dx}, ${
136
+ city.y + nodeSlotPos(i).dy
137
+ })`
138
+ : undefined
139
+ "
140
+ >
141
+ {{ sc }}
142
+ </text>
143
+ </template>
144
+ </g>
145
+ </template>
146
+
75
147
  <template v-for="city in cities">
76
148
  <circle
149
+ v-if="city.connectionCost == null"
77
150
  :key="city.name + '_circle2'"
78
151
  :class="[{ canClick: canBuild(city) }]"
79
152
  r="20"
@@ -135,6 +208,33 @@
135
208
  />
136
209
  </template>
137
210
 
211
+ <!-- Bremen entry-cost number, on top so it stays readable over houses -->
212
+ <template v-for="city in cities">
213
+ <g v-if="city.connectionCost != null" :key="city.name + '_cc'">
214
+ <circle
215
+ :cx="city.x"
216
+ :cy="city.y + 15"
217
+ r="11"
218
+ fill="goldenrod"
219
+ stroke="darkgoldenrod"
220
+ stroke-width="2"
221
+ />
222
+ <circle :cx="city.x" :cy="city.y + 15" r="7.5" fill="gray" stroke="darkgoldenrod" stroke-width="1" />
223
+ <text
224
+ :x="city.x"
225
+ :y="city.y + 15"
226
+ font-size="11"
227
+ font-weight="bold"
228
+ text-anchor="middle"
229
+ dominant-baseline="central"
230
+ fill="black"
231
+ :transform="mapRotation ? `rotate(${-mapRotation}, ${city.x}, ${city.y + 15})` : undefined"
232
+ >
233
+ {{ city.connectionCost }}
234
+ </text>
235
+ </g>
236
+ </template>
237
+
138
238
  <template v-for="city in cities">
139
239
  <!-- [10,15] city: X at bottom-right -->
140
240
  <template v-if="city.slotCosts && city.slotCosts.length === 2 && city.slotCosts[0] === 10">
@@ -251,8 +351,16 @@ export default class Map extends Vue {
251
351
  player.cities.forEach((cityPiece) => {
252
352
  const city = gameState.map.cities.find((city) => city.name == cityPiece.name)!;
253
353
  let offsetX, offsetY;
354
+ const isNodeWeighted = city.connectionCost != null;
254
355
  const is1520 = city.slotCosts?.length === 2 && city.slotCosts[0] === 15;
255
- if (is1520) {
356
+ if (isNodeWeighted) {
357
+ // Bremen tiles: 8 top, 14 left, 20 right — matches the board layout.
358
+ // The House piece is anchored top-left (~14×16 after its scale), so
359
+ // offset by half its size to center it on the slot.
360
+ const slot = this.nodeSlotPos(cityPiece.position);
361
+ offsetX = slot.dx - 7;
362
+ offsetY = slot.dy - 8;
363
+ } else if (is1520) {
256
364
  // [15,20] city: slot 0 (cost 15) → bottom-left, slot 1 (cost 20) → bottom-right
257
365
  if (cityPiece.position == 0) {
258
366
  offsetX = -15;
@@ -303,6 +411,13 @@ export default class Map extends Vue {
303
411
  return city.y;
304
412
  }
305
413
 
414
+ nodeSlotPos(i: number) {
415
+ // House slots laid out like the printed board: 0 = 8 (top), 1 = 14 (left), 2 = 20 (right).
416
+ if (i === 0) return { dx: 0, dy: -15 };
417
+ if (i === 1) return { dx: -15, dy: 0 };
418
+ return { dx: 15, dy: 0 };
419
+ }
420
+
306
421
  canBuild(city: City) {
307
422
  return !!this.buildableCities!.find((cityName) => cityName == city.name);
308
423
  }
@@ -10,7 +10,7 @@ function launchSelfContained(selector = '#app') {
10
10
 
11
11
  const emitter = launch(selector);
12
12
 
13
- let gameState = setup(6, { map: 'Australia', variant: 'recharged', showMoney: true, randomizeMap: false }, '7');
13
+ let gameState = setup(6, { map: 'Bremen', variant: 'recharged', showMoney: true, randomizeMap: false }, '0');
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