powergrid-viewer 1.11.16 → 1.11.18
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.11.
|
|
3
|
+
"version": "1.11.18",
|
|
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.15.
|
|
21
|
+
"powergrid-engine": "1.15.18"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/assert": "^1.4.7",
|
package/src/components/Game.vue
CHANGED
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
:buildableCities="getBuildableCities()"
|
|
58
58
|
:blockedCities="G.blockedCities"
|
|
59
59
|
:pickableRegions="getPickableRegions()"
|
|
60
|
+
:noUraniumRegions="G.map.noUraniumRegions"
|
|
60
61
|
:devBackdrop="G.map.devBackdrop"
|
|
61
62
|
:mapRotation="G.map.mapRotation || 0"
|
|
62
63
|
@build="build($event)"
|
|
@@ -385,6 +385,32 @@
|
|
|
385
385
|
@click="onCityClick(city)"
|
|
386
386
|
/>
|
|
387
387
|
</template>
|
|
388
|
+
|
|
389
|
+
<!-- Regions where nuclear plants are banned: a nuclear-plant tile under a red
|
|
390
|
+
prohibition sign (ring + diagonal bar), matching the marker printed on
|
|
391
|
+
the physical board. -->
|
|
392
|
+
<g
|
|
393
|
+
v-for="marker in noUraniumMarkers"
|
|
394
|
+
:key="'noUranium_' + marker.region"
|
|
395
|
+
:transform="`translate(${marker.x}, ${marker.y})`"
|
|
396
|
+
>
|
|
397
|
+
<!-- nuclear plant tile: dark card with the red uranium barrel glyph -->
|
|
398
|
+
<rect x="-15" y="-11" width="30" height="22" rx="3" fill="#4a4a4a" stroke="black" stroke-width="1.5" />
|
|
399
|
+
<g transform="translate(-9, -7) scale(1.2)">
|
|
400
|
+
<path d="M1,2 l4,-2 l6,0 l4,2 l0,11 l-4,2 l-6,0 l-4,-2Z" fill="#ef3b3b" />
|
|
401
|
+
</g>
|
|
402
|
+
<!-- prohibition sign over it, tinted with the region's own colour -->
|
|
403
|
+
<circle cx="0" cy="0" r="20" fill="none" :stroke="marker.region" stroke-width="4.5" />
|
|
404
|
+
<line
|
|
405
|
+
x1="-14.1"
|
|
406
|
+
y1="-14.1"
|
|
407
|
+
x2="14.1"
|
|
408
|
+
y2="14.1"
|
|
409
|
+
:stroke="marker.region"
|
|
410
|
+
stroke-width="4.5"
|
|
411
|
+
stroke-linecap="round"
|
|
412
|
+
/>
|
|
413
|
+
</g>
|
|
388
414
|
</g>
|
|
389
415
|
</template>
|
|
390
416
|
|
|
@@ -410,6 +436,8 @@ export default class Map extends Vue {
|
|
|
410
436
|
@Prop() blockedCities?: string[];
|
|
411
437
|
// chooseRegions draft: region names the current player may pick this turn.
|
|
412
438
|
@Prop() pickableRegions?: string[];
|
|
439
|
+
// Regions where nuclear plants are banned; each gets a struck-through marker.
|
|
440
|
+
@Prop() noUraniumRegions?: string[];
|
|
413
441
|
@Prop() devBackdrop?: { src: string; width: number; height: number; opacity?: number };
|
|
414
442
|
@Prop({ default: 0 }) mapRotation!: number;
|
|
415
443
|
|
|
@@ -502,6 +530,81 @@ export default class Map extends Vue {
|
|
|
502
530
|
return { dx: 15, dy: 0 };
|
|
503
531
|
}
|
|
504
532
|
|
|
533
|
+
// One "no nuclear" marker per banned region. Placed at the most open spot
|
|
534
|
+
// inside the region — the point (within the region's own area) that is farthest
|
|
535
|
+
// from every city and every connection cost-label — so the marker never covers a
|
|
536
|
+
// city node or a connection cost. Uses the already-adjusted city coordinates, so
|
|
537
|
+
// it needs no knowledge of the map's adjustRatio.
|
|
538
|
+
get noUraniumMarkers(): { region: string; x: number; y: number }[] {
|
|
539
|
+
if (!this.noUraniumRegions || !this.cities || this.cities.length === 0) return [];
|
|
540
|
+
const cities = this.cities;
|
|
541
|
+
|
|
542
|
+
// Obstacles the marker must avoid: city centres and connection cost labels
|
|
543
|
+
// (drawn at each connection's midpoint).
|
|
544
|
+
const obstacles = cities.map((c) => ({ x: c.x, y: c.y }));
|
|
545
|
+
for (const con of this.connections ?? []) {
|
|
546
|
+
if (!con.cost || con.cost <= 0) continue;
|
|
547
|
+
const a = cities.find((c) => c.name === con.nodes[0]);
|
|
548
|
+
const b = cities.find((c) => c.name === con.nodes[1]);
|
|
549
|
+
if (a && b) obstacles.push({ x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 });
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const nearestDist = (x: number, y: number, pts: { x: number; y: number }[]) => {
|
|
553
|
+
let min = Infinity;
|
|
554
|
+
for (const p of pts) {
|
|
555
|
+
const d = Math.hypot(p.x - x, p.y - y);
|
|
556
|
+
if (d < min) min = d;
|
|
557
|
+
}
|
|
558
|
+
return min;
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
const markers: { region: string; x: number; y: number }[] = [];
|
|
562
|
+
for (const region of this.noUraniumRegions) {
|
|
563
|
+
const regionCities = cities.filter((c) => c.region === region);
|
|
564
|
+
if (regionCities.length === 0) continue;
|
|
565
|
+
|
|
566
|
+
const xs = regionCities.map((c) => c.x);
|
|
567
|
+
const ys = regionCities.map((c) => c.y);
|
|
568
|
+
const centroid = { x: xs.reduce((s, v) => s + v, 0) / xs.length, y: ys.reduce((s, v) => s + v, 0) / ys.length };
|
|
569
|
+
|
|
570
|
+
// Scan a grid over the region's bounding box for points that fall inside
|
|
571
|
+
// this region (nearest city belongs to it). Among those with enough
|
|
572
|
+
// clearance to not cover an obstacle, prefer the one closest to the
|
|
573
|
+
// region centre so the marker stays central rather than drifting to an
|
|
574
|
+
// empty edge. Fall back to the most open point if none clear the bar.
|
|
575
|
+
const MIN_CLEARANCE = 44; // marker radius (~22) + obstacle radius (~20) + gap
|
|
576
|
+
let central: { x: number; y: number; distToCentroid: number } | undefined;
|
|
577
|
+
let openest: { x: number; y: number; clearance: number } | undefined;
|
|
578
|
+
const step = 10;
|
|
579
|
+
for (let x = Math.min(...xs); x <= Math.max(...xs); x += step) {
|
|
580
|
+
for (let y = Math.min(...ys); y <= Math.max(...ys); y += step) {
|
|
581
|
+
let nearestCity = regionCities[0];
|
|
582
|
+
let nd = Infinity;
|
|
583
|
+
for (const c of cities) {
|
|
584
|
+
const d = Math.hypot(c.x - x, c.y - y);
|
|
585
|
+
if (d < nd) {
|
|
586
|
+
nd = d;
|
|
587
|
+
nearestCity = c;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (nearestCity.region !== region) continue;
|
|
591
|
+
|
|
592
|
+
const clearance = nearestDist(x, y, obstacles);
|
|
593
|
+
if (!openest || clearance > openest.clearance) openest = { x, y, clearance };
|
|
594
|
+
|
|
595
|
+
if (clearance >= MIN_CLEARANCE) {
|
|
596
|
+
const distToCentroid = Math.hypot(x - centroid.x, y - centroid.y);
|
|
597
|
+
if (!central || distToCentroid < central.distToCentroid) central = { x, y, distToCentroid };
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const chosen = central ?? openest;
|
|
603
|
+
markers.push({ region, x: chosen ? chosen.x : centroid.x, y: chosen ? chosen.y : centroid.y });
|
|
604
|
+
}
|
|
605
|
+
return markers;
|
|
606
|
+
}
|
|
607
|
+
|
|
505
608
|
canBuild(city: City) {
|
|
506
609
|
return !!this.buildableCities!.find((cityName) => cityName == city.name);
|
|
507
610
|
}
|