powergrid-viewer 1.5.4

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.
Files changed (57) hide show
  1. package/README.md +35 -0
  2. package/dist/img/help.ba7779cc.svg +1 -0
  3. package/dist/img/log.04ef6981.svg +1 -0
  4. package/dist/img/pass.da9065dc.svg +3 -0
  5. package/dist/img/rules.64f9aae5.svg +28 -0
  6. package/dist/img/sound-off.72ada995.svg +3 -0
  7. package/dist/img/sound-on.c55edd90.svg +3 -0
  8. package/dist/img/undo.208666d2.svg +3 -0
  9. package/dist/media/notification.55fa47dd.ogg +0 -0
  10. package/dist/media/notification.ac905963.mp3 +0 -0
  11. package/dist/media/piece-drop.eef5f607.mp3 +0 -0
  12. package/dist/powergrid-viewer.css +1 -0
  13. package/dist/powergrid-viewer.umd.min.js +35 -0
  14. package/package.json +49 -0
  15. package/src/audio/notification.mp3 +0 -0
  16. package/src/audio/notification.ogg +0 -0
  17. package/src/audio/piece-drop.mp3 +0 -0
  18. package/src/components/Calculator.vue +62 -0
  19. package/src/components/Game.vue +1354 -0
  20. package/src/components/PlayerBoard.vue +230 -0
  21. package/src/components/boards/CityCount.vue +82 -0
  22. package/src/components/boards/Map.vue +196 -0
  23. package/src/components/boards/PlayerOrder.vue +68 -0
  24. package/src/components/boards/PowerPlantMarket.vue +184 -0
  25. package/src/components/boards/Resources.vue +446 -0
  26. package/src/components/buttons/Button.vue +26 -0
  27. package/src/components/buttons/HelpButton.vue +18 -0
  28. package/src/components/buttons/LogButton.vue +15 -0
  29. package/src/components/buttons/PassButton.vue +18 -0
  30. package/src/components/buttons/RulesButton.vue +14 -0
  31. package/src/components/buttons/SoundButton.vue +18 -0
  32. package/src/components/buttons/UndoButton.vue +17 -0
  33. package/src/components/buttons/index.js +9 -0
  34. package/src/components/pieces/Card.vue +131 -0
  35. package/src/components/pieces/Coal.vue +40 -0
  36. package/src/components/pieces/Garbage.vue +40 -0
  37. package/src/components/pieces/House.vue +51 -0
  38. package/src/components/pieces/Hybrid.vue +37 -0
  39. package/src/components/pieces/Oil.vue +40 -0
  40. package/src/components/pieces/Piece.vue +104 -0
  41. package/src/components/pieces/Uranium.vue +32 -0
  42. package/src/components/pieces/index.js +10 -0
  43. package/src/icons/help.svg +1 -0
  44. package/src/icons/log.svg +1 -0
  45. package/src/icons/pass.svg +3 -0
  46. package/src/icons/rules.svg +28 -0
  47. package/src/icons/sound-off.svg +3 -0
  48. package/src/icons/sound-on.svg +3 -0
  49. package/src/icons/undo.svg +3 -0
  50. package/src/launch.ts +87 -0
  51. package/src/main.ts +3 -0
  52. package/src/self-contained.ts +97 -0
  53. package/src/shims-tsx.d.ts +13 -0
  54. package/src/shims-vue.d.ts +4 -0
  55. package/src/types/ui-data.ts +34 -0
  56. package/src/wrapper.ts +8 -0
  57. package/tsconfig.json +23 -0
@@ -0,0 +1,230 @@
1
+ <template>
2
+ <g class="player-board">
3
+ <rect width="350" height="100" x="0" y="0" fill="gold" :stroke="color" />
4
+ <rect width="350" height="25" x="0" y="0" :fill="color" />
5
+ <foreignObject height="30" width="30" x="-30" y="-5">
6
+ <img
7
+ :src="avatar || `https://avatars.dicebear.com/api/pixel-art/${player.name}.svg`"
8
+ width="100%"
9
+ height="100%"
10
+ style="border-radius: 50%"
11
+ />
12
+ </foreignObject>
13
+ <text x="5" y="13" font-weight="600" fill="black">
14
+ {{ getPlayerName() }}
15
+ </text>
16
+ <text v-if="showMoney" x="250" y="13" font-weight="600" fill="black">Money: ${{ player.money }}</text>
17
+
18
+ <Card
19
+ v-for="(powerPlant, i) in player.powerPlants"
20
+ :key="'powerPlant_' + powerPlant.number"
21
+ :targetState="{ x: player.powerPlants.length < 5 ? 20 + 80 * i : 5 + 70 * i, y: 30 }"
22
+ :owner="owner"
23
+ :powerPlant="powerPlant"
24
+ :canClick="canUse(powerPlant)"
25
+ @click="powerPlantClick(powerPlant)"
26
+ />
27
+
28
+ <template v-if="!preferences.disableHelp">
29
+ <template v-for="(powerPlant, i) in player.powerPlants">
30
+ <rect
31
+ v-if="canUse(powerPlant)"
32
+ :key="i + '_' + i + '_helper'"
33
+ :x="player.powerPlants.length < 5 ? 20 + 80 * i : 5 + 70 * i"
34
+ :y="30"
35
+ width="60"
36
+ height="40"
37
+ fill="none"
38
+ stroke="blue"
39
+ stroke-width="4px"
40
+ rx="2px"
41
+ />
42
+ </template>
43
+ </template>
44
+
45
+ <g v-if="canClickResources">
46
+ <rect width="30" height="30" x="0" y="71" fill="none" stroke="blue" stroke-width="2px" rx="2px" />
47
+ <rect width="30" height="30" x="70" y="71" fill="none" stroke="blue" stroke-width="2px" rx="2px" />
48
+ </g>
49
+
50
+ <Coal
51
+ :pieceId="'Coal' + player.id"
52
+ :targetState="{ x: 5, y: 76 }"
53
+ :canClick="canClickResources"
54
+ @click="clickResource('coal')"
55
+ />
56
+ <text text-anchor="middle" x="40" y="85" fill="black">{{ player.coalLeft }}</text>
57
+
58
+ <Oil
59
+ :pieceId="'Oil' + player.id"
60
+ :targetState="{ x: 75, y: 76 }"
61
+ :canClick="canClickResources"
62
+ @click="clickResource('oil')"
63
+ />
64
+ <text text-anchor="middle" x="110" y="85" fill="black">{{ player.oilLeft }}</text>
65
+
66
+ <Garbage :pieceId="'Garbage' + player.id" :targetState="{ x: 145, y: 76 }" />
67
+ <text text-anchor="middle" x="180" y="85" fill="black">{{ player.garbageLeft }}</text>
68
+
69
+ <Uranium :pieceId="'Uranium' + player.id" :targetState="{ x: 215, y: 76 }" />
70
+ <text text-anchor="middle" x="250" y="85" fill="black">{{ player.uraniumLeft }}</text>
71
+ </g>
72
+ </template>
73
+ <script lang="ts">
74
+ import { MoveName, Player } from 'powergrid-engine';
75
+ import { Phase, PowerPlant, PowerPlantType, ResourceType } from 'powergrid-engine/src/gamestate';
76
+ import { Vue, Component, Prop, Inject } from 'vue-property-decorator';
77
+ import { Preferences } from '../types/ui-data';
78
+ import { Coal, Oil, Garbage, Uranium, Card } from './pieces';
79
+
80
+ @Component({
81
+ components: {
82
+ Coal,
83
+ Oil,
84
+ Garbage,
85
+ Uranium,
86
+ Card,
87
+ },
88
+ })
89
+ export default class PlayerBoard extends Vue {
90
+ @Prop() color?: string;
91
+ @Prop() avatar?: string;
92
+ @Prop() player!: Player;
93
+ @Prop() isCurrentPlayer?: boolean;
94
+ @Prop() owner?: number;
95
+ @Prop() ended?: boolean;
96
+ @Prop() isPlayer?: boolean;
97
+ @Prop() ranking?: number;
98
+ @Prop() showMoney?: boolean;
99
+ @Prop() showBid?: boolean;
100
+ @Prop() phase?: Phase;
101
+
102
+ @Inject() preferences!: Preferences;
103
+
104
+ powerPlantClicked?: PowerPlant;
105
+
106
+ getPlayerName() {
107
+ let name = '';
108
+ if (this.isCurrentPlayer) {
109
+ name += '• ';
110
+ }
111
+
112
+ name += this.player.name;
113
+
114
+ if (this.ended) {
115
+ switch (this.ranking) {
116
+ case 1:
117
+ name += ' (1st)';
118
+ break;
119
+ case 2:
120
+ name += ' (2nd)';
121
+ break;
122
+ case 3:
123
+ name += ' (3rd)';
124
+ break;
125
+ case 4:
126
+ case 5:
127
+ case 6:
128
+ name += ` (${this.ranking}th)`;
129
+ break;
130
+ }
131
+ } else if (this.player.skipAuction) {
132
+ name += ' (Skipping)';
133
+ } else if (this.player.passed) {
134
+ name += ' (Passed)';
135
+ } else if (this.player.bid && !this.isCurrentPlayer && this.showBid) {
136
+ name += ' (Bid: $' + this.player.bid + ')';
137
+ }
138
+
139
+ return name;
140
+ }
141
+
142
+ canUse(powerPlant) {
143
+ if (!this.isCurrentPlayer) return false;
144
+
145
+ if (this.player.availableMoves?.[MoveName.DiscardPowerPlant]) {
146
+ return powerPlant.number !== this.player.powerPlants[this.player.powerPlants.length - 1].number;
147
+ } else {
148
+ if (!this.player.availableMoves?.[MoveName.UsePowerPlant]) return false;
149
+
150
+ if (!this.player.powerPlantsNotUsed.includes(powerPlant.number) || this.player.resourcesUsed.length > 0) {
151
+ return false;
152
+ }
153
+
154
+ switch (powerPlant.type) {
155
+ case PowerPlantType.Coal: {
156
+ return this.player.coalLeft >= powerPlant.cost;
157
+ }
158
+
159
+ case PowerPlantType.Oil: {
160
+ return this.player.oilLeft >= powerPlant.cost;
161
+ }
162
+
163
+ case PowerPlantType.Garbage: {
164
+ return this.player.garbageLeft >= powerPlant.cost;
165
+ }
166
+
167
+ case PowerPlantType.Uranium: {
168
+ return this.player.uraniumLeft >= powerPlant.cost;
169
+ }
170
+
171
+ case PowerPlantType.Hybrid: {
172
+ return this.player.coalLeft + this.player.oilLeft >= powerPlant.cost;
173
+ }
174
+
175
+ case PowerPlantType.Wind:
176
+ case PowerPlantType.Nuclear:
177
+ return this.player.coalLeft + this.player.oilLeft >= powerPlant.cost;
178
+ }
179
+ }
180
+ }
181
+
182
+ powerPlantClick(powerPlant: PowerPlant) {
183
+ if (this.phase == Phase.Bureaucracy && powerPlant.type == PowerPlantType.Hybrid) {
184
+ if (
185
+ this.player.coalLeft == 0 ||
186
+ this.player.oilLeft == 0 ||
187
+ this.player.coalLeft + this.player.oilLeft == powerPlant.cost
188
+ ) {
189
+ this.player.resourcesUsed = Array(Math.min(powerPlant.cost, this.player.coalLeft))
190
+ .fill(ResourceType.Coal)
191
+ .concat(
192
+ Array(powerPlant.cost - Math.min(powerPlant.cost, this.player.coalLeft)).fill(ResourceType.Oil)
193
+ );
194
+ this.$emit('powerPlantClick', powerPlant);
195
+ } else {
196
+ this.powerPlantClicked = powerPlant;
197
+ this.player.resourcesUsed = Array(powerPlant.cost).fill(null);
198
+ }
199
+ } else {
200
+ this.$emit('powerPlantClick', powerPlant);
201
+ }
202
+ }
203
+
204
+ get canClickResources() {
205
+ return (
206
+ (this.player.availableMoves && this.player.availableMoves['DiscardResources']) ||
207
+ this.player.resourcesUsed.some((r) => r == null)
208
+ );
209
+ }
210
+
211
+ clickResource(resourceType) {
212
+ if (this.player.availableMoves && this.player.availableMoves['DiscardResources']) {
213
+ this.$emit('discardResource', resourceType);
214
+ } else if (this.player.resourcesUsed.some((r) => r == null)) {
215
+ const index = this.player.resourcesUsed.findIndex((r) => r == null)!;
216
+ this.player.resourcesUsed[index] = resourceType;
217
+
218
+ if (resourceType == 'coal') {
219
+ this.player.coalLeft--;
220
+ } else if (resourceType == 'oil') {
221
+ this.player.oilLeft--;
222
+ }
223
+
224
+ if (!this.player.resourcesUsed.some((r) => r == null)) {
225
+ this.$emit('powerPlantClick', this.powerPlantClicked);
226
+ }
227
+ }
228
+ }
229
+ }
230
+ </script>
@@ -0,0 +1,82 @@
1
+ <template>
2
+ <g>
3
+ <rect width="730" height="50" x="10" y="10" rx="3" fill="goldenrod" />
4
+ <template v-for="index in 21">
5
+ <rect
6
+ :key="'playerCityCount' + index"
7
+ width="28"
8
+ height="38"
9
+ :x="46 + 33 * (index - 1)"
10
+ y="16"
11
+ rx="2"
12
+ fill="darkgoldenrod"
13
+ :stroke="index == citiesToStep2 || index == citiesToEndGame ? '#916a08' : 'darkgoldenrod'"
14
+ stroke-width="2px"
15
+ />
16
+ <text
17
+ :key="'playerCityCountText' + index"
18
+ text-anchor="middle"
19
+ style="font-size: 24px; font-family: monospace"
20
+ letter-spacing="-2"
21
+ :x="59 + 33 * (index - 1)"
22
+ y="35"
23
+ fill="gold"
24
+ >
25
+ {{ index }}
26
+ </text>
27
+ </template>
28
+ <template v-for="house in houses">
29
+ <House
30
+ :key="house.id"
31
+ :pieceId="house.id"
32
+ :targetState="{ x: house.x, y: house.y }"
33
+ :owner="house.owner"
34
+ :ownerName="house.ownerName"
35
+ :color="house.color"
36
+ />
37
+ </template>
38
+ </g>
39
+ </template>
40
+
41
+ <script lang="ts">
42
+ import type { GameState } from 'powergrid-engine';
43
+ import { Vue, Component, Prop } from 'vue-property-decorator';
44
+ import { House } from '../pieces';
45
+ import { Piece } from '../../types/ui-data';
46
+
47
+ @Component({
48
+ components: {
49
+ House
50
+ },
51
+ })
52
+ export default class CityCount extends Vue {
53
+ @Prop() citiesToStep2?: number;
54
+ @Prop() citiesToEndGame?: number;
55
+ @Prop() playerColors?: string[];
56
+
57
+ houses: Piece[] = [];
58
+
59
+ createPieces(gameState: GameState) {
60
+ this.houses = [];
61
+ const adjustCityCount: number[][] = [];
62
+ for (let i = 0; i < 22; i++) adjustCityCount[i] = [];
63
+
64
+ gameState.players.forEach((player, pi) => adjustCityCount[player.cities.length].push(pi));
65
+ gameState.players.forEach((player, pi) => {
66
+ let x = (adjustCityCount[player.cities.length].length == 1 ? 23 : 20) + 33 * player.cities.length;
67
+ x += (adjustCityCount[player.cities.length].indexOf(pi) % 2) * 6;
68
+
69
+ this.houses.push({
70
+ id: pi + '_cityCount',
71
+ x: x,
72
+ y:
73
+ 15 +
74
+ (adjustCityCount[player.cities.length].indexOf(pi) * 30) /
75
+ adjustCityCount[player.cities.length].length,
76
+ color: this.playerColors![pi],
77
+ owner: pi,
78
+ });
79
+ });
80
+ }
81
+ }
82
+ </script>
@@ -0,0 +1,196 @@
1
+ <template>
2
+ <g>
3
+ <!-- <template v-for="polygon in polygons">
4
+ <polygon
5
+ :key="'pol_ ' + polygon.region"
6
+ :points="polygon.points.map((p) => `${p[0]},${p[1]}`).join(' ')"
7
+ :fill="polygon.region"
8
+ opacity="0.8"
9
+ stroke="black"
10
+ ></polygon>
11
+ </template> -->
12
+
13
+ <template v-for="city in cities">
14
+ <circle :key="city.name + '_region'" r="25" :cx="city.x" :cy="city.y" :fill="city.region" stroke="black">
15
+ <title>{{ city.name }}</title>
16
+ </circle>
17
+ <circle :key="city.name + '_circle'" r="20" :cx="city.x" :cy="city.y" fill="gray" stroke="black">
18
+ <title>{{ city.name }}</title>
19
+ </circle>
20
+ </template>
21
+
22
+ <template v-for="connection in connections">
23
+ <line
24
+ :key="connection.nodes[0] + '_' + connection.nodes[1] + '_line1'"
25
+ :x1="getX1(connection)"
26
+ :y1="getY1(connection)"
27
+ :x2="getX2(connection)"
28
+ :y2="getY2(connection)"
29
+ stroke-width="10"
30
+ stroke="black"
31
+ />
32
+ <line
33
+ :key="connection.nodes[0] + '_' + connection.nodes[1] + '_line2'"
34
+ :x1="getX1(connection)"
35
+ :y1="getY1(connection)"
36
+ :x2="getX2(connection)"
37
+ :y2="getY2(connection)"
38
+ stroke-width="9"
39
+ stroke="gray"
40
+ />
41
+ </template>
42
+
43
+ <template v-for="city in cities">
44
+ <circle
45
+ :key="city.name + '_circle2'"
46
+ :class="[{ canClick: canBuild(city) }]"
47
+ r="20"
48
+ :cx="city.x"
49
+ :cy="city.y"
50
+ fill="gray"
51
+ @click="canBuild(city) && build(city)"
52
+ >
53
+ <title>{{ city.name }}</title>
54
+ </circle>
55
+ </template>
56
+
57
+ <template v-for="connection in connections">
58
+ <circle
59
+ v-if="connection.cost > 0"
60
+ :key="connection.nodes[0] + '_' + connection.nodes[1] + '_border'"
61
+ stroke="black"
62
+ :r="10 + (connection.cost * 10) / 28"
63
+ :cx="(getX1(connection) + getX2(connection)) / 2"
64
+ :cy="(getY1(connection) + getY2(connection)) / 2"
65
+ :fill="connection.cost > 15 ? 'gold' : connection.cost > 10 ? 'lightgray' : 'tan'"
66
+ />
67
+ <circle
68
+ v-if="connection.cost > 0"
69
+ :key="connection.nodes[0] + '_' + connection.nodes[1] + '_circle'"
70
+ :r="6 + (connection.cost * 10) / 28"
71
+ :cx="(getX1(connection) + getX2(connection)) / 2"
72
+ :cy="(getY1(connection) + getY2(connection)) / 2"
73
+ fill="gray"
74
+ stroke="black"
75
+ />
76
+ <text
77
+ v-if="connection.cost > 0"
78
+ :key="connection.nodes[0] + '_' + connection.nodes[1] + '_text'"
79
+ text-anchor="middle"
80
+ :style="`font-size: ${12 + (connection.cost * 6) / 28}px`"
81
+ fill="black"
82
+ :x="(getX1(connection) + getX2(connection)) / 2"
83
+ :y="(getY1(connection) + getY2(connection)) / 2"
84
+ >
85
+ {{ connection.cost }}
86
+ </text>
87
+ </template>
88
+ <template v-for="house in houses">
89
+ <House
90
+ :key="house.id"
91
+ :pieceId="house.id"
92
+ :targetState="{ x: house.x, y: house.y }"
93
+ :owner="house.owner"
94
+ :ownerName="house.ownerName"
95
+ :color="house.color"
96
+ />
97
+ </template>
98
+
99
+ <template v-if="!preferences.disableHelp">
100
+ <template v-for="city in cities">
101
+ <circle
102
+ v-if="canBuild(city)"
103
+ :key="city.name + '_circleHelp'"
104
+ :class="[{ canClick: canBuild(city) }]"
105
+ r="18"
106
+ :cx="city.x"
107
+ :cy="city.y"
108
+ fill="none"
109
+ stroke="blue"
110
+ stroke-width="4px"
111
+ />
112
+ </template>
113
+ </template>
114
+ </g>
115
+ </template>
116
+
117
+ <script lang="ts">
118
+ import type { GameState } from 'powergrid-engine';
119
+ import { Vue, Component, Prop, Inject } from 'vue-property-decorator';
120
+ import { House } from '../pieces';
121
+ import { Piece, Preferences } from '../../types/ui-data';
122
+ import { City, Connection, Polygon } from 'powergrid-engine/src/maps';
123
+
124
+ @Component({
125
+ components: {
126
+ House
127
+ },
128
+ })
129
+ export default class Map extends Vue {
130
+ @Prop() polygons?: Polygon[];
131
+ @Prop() cities?: City[];
132
+ @Prop() connections?: Connection[];
133
+ @Prop() playerColors?: string[];
134
+ @Prop() buildableCities?: string[];
135
+
136
+ @Inject() preferences!: Preferences;
137
+
138
+ houses: Piece[] = [];
139
+
140
+ createPieces(gameState: GameState) {
141
+ this.houses = [];
142
+ gameState.players.forEach((player, pi) => {
143
+ player.cities.forEach((cityPiece) => {
144
+ const city = gameState.map.cities.find((city) => city.name == cityPiece.name)!;
145
+ let offsetX, offsetY;
146
+ if (cityPiece.position == 0) {
147
+ offsetX = -6;
148
+ offsetY = -18;
149
+ } else if (cityPiece.position == 1) {
150
+ offsetX = -15;
151
+ offsetY = -4;
152
+ } else {
153
+ offsetX = 1;
154
+ offsetY = -4;
155
+ }
156
+
157
+ this.houses.push({
158
+ id: pi + '_' + cityPiece.name,
159
+ x: city.x + offsetX,
160
+ y: city.y + offsetY,
161
+ color: this.playerColors![pi],
162
+ owner: pi,
163
+ });
164
+ });
165
+ });
166
+ }
167
+
168
+ getX1(connection) {
169
+ const city = this.cities!.find((city) => city.name == connection.nodes[0])!;
170
+ return city.x;
171
+ }
172
+
173
+ getY1(connection) {
174
+ const city = this.cities!.find((city) => city.name == connection.nodes[0])!;
175
+ return city.y;
176
+ }
177
+
178
+ getX2(connection) {
179
+ const city = this.cities!.find((city) => city.name == connection.nodes[1])!;
180
+ return city.x;
181
+ }
182
+
183
+ getY2(connection) {
184
+ const city = this.cities!.find((city) => city.name == connection.nodes[1])!;
185
+ return city.y;
186
+ }
187
+
188
+ canBuild(city: City) {
189
+ return !!this.buildableCities!.find((cityName) => cityName == city.name);
190
+ }
191
+
192
+ build(city: City) {
193
+ this.$emit('build', city);
194
+ }
195
+ }
196
+ </script>
@@ -0,0 +1,68 @@
1
+ <template>
2
+ <g>
3
+ <rect x="10" y="10" width="185" height="40" rx="3" fill="goldenrod" />
4
+ <template v-for="index in 6">
5
+ <rect
6
+ :key="'playerOrder' + index"
7
+ :x="15 + 30 * (index - 1)"
8
+ y="15"
9
+ width="24"
10
+ height="30"
11
+ rx="2"
12
+ fill="darkgoldenrod"
13
+ />
14
+ <text
15
+ :key="'playerOrderText' + index"
16
+ text-anchor="middle"
17
+ style="font-size: 32px; font-family: monospace"
18
+ :x="27 + 30 * (index - 1)"
19
+ y="30"
20
+ fill="gold"
21
+ >
22
+ {{ index }}
23
+ </text>
24
+ </template>
25
+ <template v-for="house in houses">
26
+ <House
27
+ :key="house.id"
28
+ :pieceId="house.id"
29
+ :targetState="{ x: house.x, y: house.y }"
30
+ :owner="house.owner"
31
+ :ownerName="house.ownerName"
32
+ :color="house.color"
33
+ />
34
+ </template>
35
+ </g>
36
+ </template>
37
+
38
+ <script lang="ts">
39
+ import type { GameState } from 'powergrid-engine';
40
+ import { Vue, Component, Prop } from 'vue-property-decorator';
41
+ import { House } from '../pieces';
42
+ import { Piece } from '../../types/ui-data';
43
+
44
+ @Component({
45
+ components: {
46
+ House
47
+ },
48
+ })
49
+ export default class PlayerOrder extends Vue {
50
+ @Prop() playerColors?: string[];
51
+
52
+ houses: Piece[] = [];
53
+
54
+ createPieces(gameState: GameState) {
55
+ this.houses = [];
56
+ gameState.playerOrder.forEach((p, i) => {
57
+ this.houses.push({
58
+ id: p + '_order',
59
+ x: 20 + 30 * i,
60
+ y: 22,
61
+ color: this.playerColors![p],
62
+ owner: p,
63
+ ownerName: gameState.players[p].name
64
+ });
65
+ });
66
+ }
67
+ }
68
+ </script>