@civ-clone/base-city-lifecycle 0.0.0-stage → 0.1.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.
Files changed (61) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/workflows/build-on-push.yml +39 -0
  3. package/.prettierrc +4 -0
  4. package/LICENSE +21 -0
  5. package/README.md +42 -2
  6. package/lib/assignWorkers.d.ts +114 -0
  7. package/lib/assignWorkers.js +184 -0
  8. package/lib/assignWorkers.js.map +1 -0
  9. package/lib/assignWorkers.ts +372 -0
  10. package/lib/canBeWorked.d.ts +28 -0
  11. package/lib/canBeWorked.js +27 -0
  12. package/lib/canBeWorked.js.map +1 -0
  13. package/lib/canBeWorked.ts +43 -0
  14. package/lib/captured.d.ts +12 -0
  15. package/lib/captured.js +30 -0
  16. package/lib/captured.js.map +1 -0
  17. package/lib/captured.ts +31 -0
  18. package/lib/claimName.d.ts +12 -0
  19. package/lib/claimName.js +9 -0
  20. package/lib/claimName.js.map +1 -0
  21. package/lib/claimName.ts +13 -0
  22. package/lib/created.d.ts +41 -0
  23. package/lib/created.js +52 -0
  24. package/lib/created.js.map +1 -0
  25. package/lib/created.ts +110 -0
  26. package/lib/destroyed.d.ts +23 -0
  27. package/lib/destroyed.js +29 -0
  28. package/lib/destroyed.js.map +1 -0
  29. package/lib/destroyed.ts +39 -0
  30. package/lib/events.d.ts +39 -0
  31. package/lib/events.js +33 -0
  32. package/lib/events.js.map +1 -0
  33. package/lib/events.ts +51 -0
  34. package/lib/famine.d.ts +41 -0
  35. package/lib/famine.js +44 -0
  36. package/lib/famine.js.map +1 -0
  37. package/lib/famine.ts +68 -0
  38. package/lib/foodStorage.d.ts +21 -0
  39. package/lib/foodStorage.js +27 -0
  40. package/lib/foodStorage.js.map +1 -0
  41. package/lib/foodStorage.ts +30 -0
  42. package/lib/occupiedTiles.d.ts +39 -0
  43. package/lib/occupiedTiles.js +50 -0
  44. package/lib/occupiedTiles.js.map +1 -0
  45. package/lib/occupiedTiles.ts +84 -0
  46. package/lib/playerActions.d.ts +72 -0
  47. package/lib/playerActions.js +68 -0
  48. package/lib/playerActions.js.map +1 -0
  49. package/lib/playerActions.ts +114 -0
  50. package/lib/processYield.d.ts +30 -0
  51. package/lib/processYield.js +54 -0
  52. package/lib/processYield.js.map +1 -0
  53. package/lib/processYield.ts +82 -0
  54. package/lib/unsupported.d.ts +6 -0
  55. package/lib/unsupported.js +9 -0
  56. package/lib/unsupported.js.map +1 -0
  57. package/lib/unsupported.ts +8 -0
  58. package/package.json +45 -4
  59. package/tests/base-city-lifecycle.test.ts +536 -0
  60. package/tests/r3b.test.ts +341 -0
  61. package/tsconfig.json +16 -0
@@ -0,0 +1,372 @@
1
+ // Lifted from library-city 0.1.4 (`lib/assignWorkers.ts`), unchanged but for where the yields come from, so a game's
2
+ // rules can place a city's citizens without depending on library-city (civ-clone/web-renderer Civ2 M2a, R3b).
3
+ // library-city re-exports this in R3b.
4
+ import {
5
+ AvailableSpecialistRegistry,
6
+ instance as availableSpecialistRegistryInstance,
7
+ } from '@civ-clone/core-city/AvailableSpecialistRegistry';
8
+ import {
9
+ CityGrowthRegistry,
10
+ instance as cityGrowthRegistryInstance,
11
+ } from '@civ-clone/core-city-growth/CityGrowthRegistry';
12
+ import Food from '@civ-clone/base-terrain-yield-food/Food';
13
+ import Production from '@civ-clone/base-terrain-yield-production/Production';
14
+ import Trade from '@civ-clone/base-terrain-yield-trade/Trade';
15
+ import {
16
+ PlayerWorldRegistry,
17
+ instance as playerWorldRegistryInstance,
18
+ } from '@civ-clone/core-player-world/PlayerWorldRegistry';
19
+ import {
20
+ SpecialistRegistry,
21
+ instance as specialistRegistryInstance,
22
+ } from '@civ-clone/core-city/SpecialistRegistry';
23
+ import {
24
+ WorkedTileRegistry,
25
+ instance as workedTileRegistryInstance,
26
+ } from '@civ-clone/core-city/WorkedTileRegistry';
27
+ import City from '@civ-clone/core-city/City';
28
+ import Tile from '@civ-clone/core-world/Tile';
29
+ import Yield from '@civ-clone/core-yield/Yield';
30
+ import { reduceYield } from '@civ-clone/core-yield/lib/reduceYields';
31
+ import WorkedTile from '@civ-clone/core-city/WorkedTile';
32
+ import CityGrowth from '@civ-clone/core-city-growth/CityGrowth';
33
+ import Specialist from '@civ-clone/core-city/Specialist';
34
+
35
+ /**
36
+ * How many citizens `city` has placed: one per worked tile, the city centre included, and one per `Specialist`. A city
37
+ * of size `n` has `n + 1`.
38
+ */
39
+ export const citizenCount = (
40
+ city: City,
41
+ workedTileRegistry: WorkedTileRegistry = workedTileRegistryInstance,
42
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance
43
+ ): number =>
44
+ workedTileRegistry.getByCity(city).length +
45
+ specialistRegistry.getByCity(city).length;
46
+
47
+ /**
48
+ * Makes a citizen of `city` a `Specialist` of the first available kind (an Entertainer, in Civ1). Returns `null` when
49
+ * the ruleset offers no specialists.
50
+ */
51
+ export const addSpecialist = (
52
+ city: City,
53
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance,
54
+ availableSpecialistRegistry: AvailableSpecialistRegistry = availableSpecialistRegistryInstance
55
+ ): Specialist | null => {
56
+ const [SpecialistType] = availableSpecialistRegistry.entries();
57
+
58
+ if (!SpecialistType) {
59
+ return null;
60
+ }
61
+
62
+ const specialist = new SpecialistType(city);
63
+
64
+ specialistRegistry.register(specialist);
65
+
66
+ return specialist;
67
+ };
68
+
69
+ /**
70
+ * Turns `specialist` into the next available kind, wrapping back to the first. Returns the `Specialist` that replaces
71
+ * it, or `specialist` itself when there is nothing to change it to.
72
+ */
73
+ export const changeSpecialist = (
74
+ specialist: Specialist,
75
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance,
76
+ availableSpecialistRegistry: AvailableSpecialistRegistry = availableSpecialistRegistryInstance
77
+ ): Specialist => {
78
+ const city = specialist.city(),
79
+ types = availableSpecialistRegistry.entries(),
80
+ NextType =
81
+ types[
82
+ (types.indexOf(specialist.constructor as typeof Specialist) + 1) %
83
+ types.length
84
+ ];
85
+
86
+ if (!NextType || specialist instanceof NextType) {
87
+ return specialist;
88
+ }
89
+
90
+ const replacement = new NextType(city);
91
+
92
+ specialistRegistry.unregister(specialist);
93
+ specialistRegistry.register(replacement);
94
+
95
+ return replacement;
96
+ };
97
+
98
+ /**
99
+ * Puts one of `city`'s specialists back to work, preferring the first available kind (Entertainers), and returns
100
+ * whether there was one to remove.
101
+ */
102
+ const removeSpecialist = (
103
+ city: City,
104
+ specialistRegistry: SpecialistRegistry,
105
+ availableSpecialistRegistry: AvailableSpecialistRegistry
106
+ ): boolean => {
107
+ const specialists = specialistRegistry.getByCity(city),
108
+ [DefaultType] = availableSpecialistRegistry.entries(),
109
+ specialist =
110
+ specialists.find(
111
+ (specialist) => DefaultType && specialist instanceof DefaultType
112
+ ) ?? specialists[specialists.length - 1];
113
+
114
+ if (!specialist) {
115
+ return false;
116
+ }
117
+
118
+ specialistRegistry.unregister(specialist);
119
+
120
+ return true;
121
+ };
122
+
123
+ export const getHighestValueCityTiles = (city: City) =>
124
+ sortTiles(city.tiles().entries(), city);
125
+
126
+ export const sortTiles = (
127
+ tiles: Tile[],
128
+ city: City,
129
+ weights: [typeof Yield, number][] = [
130
+ [Food, 8],
131
+ [
132
+ Production,
133
+ 3 *
134
+ (reduceYield(city.tilesWorked().yields(city.player()), Production) === 0
135
+ ? 3
136
+ : 1),
137
+ ],
138
+ [
139
+ Trade,
140
+ 1 *
141
+ (reduceYield(city.tilesWorked().yields(city.player()), Trade) === 0
142
+ ? 2
143
+ : 1),
144
+ ],
145
+ ]
146
+ ): Tile[] =>
147
+ tiles.sort(
148
+ (a: Tile, b: Tile) =>
149
+ b.score(city.player(), weights) - a.score(city.player(), weights)
150
+ );
151
+
152
+ export const getHighestValueAvailableCityTiles = (
153
+ city: City,
154
+ playerWorldRegistry: PlayerWorldRegistry = playerWorldRegistryInstance,
155
+ workedTileRegistry: WorkedTileRegistry = workedTileRegistryInstance
156
+ ) =>
157
+ getHighestValueCityTiles(city).filter(
158
+ (tile) =>
159
+ workedTileRegistry.tileCanBeWorkedBy(tile, city) &&
160
+ playerWorldRegistry.getByPlayer(city.player()).includes(tile)
161
+ );
162
+
163
+ /**
164
+ * Rearranges the tiles `city` works from scratch. Its specialists stay as they are.
165
+ */
166
+ export const reassignWorkers = (
167
+ city: City,
168
+ playerWorldRegistry: PlayerWorldRegistry = playerWorldRegistryInstance,
169
+ cityGrowthRegistry: CityGrowthRegistry = cityGrowthRegistryInstance,
170
+ workedTileRegistry: WorkedTileRegistry = workedTileRegistryInstance,
171
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance,
172
+ availableSpecialistRegistry: AvailableSpecialistRegistry = availableSpecialistRegistryInstance
173
+ ) => {
174
+ workedTileRegistry
175
+ .getBy('city', city)
176
+ .forEach((workedTile: WorkedTile) =>
177
+ workedTileRegistry.unregister(workedTile)
178
+ );
179
+
180
+ workedTileRegistry.register(new WorkedTile(city.tile(), city));
181
+
182
+ assignWorkers(
183
+ city,
184
+ playerWorldRegistry,
185
+ cityGrowthRegistry,
186
+ workedTileRegistry,
187
+ specialistRegistry,
188
+ availableSpecialistRegistry
189
+ );
190
+ };
191
+
192
+ /**
193
+ * Places each of `city`'s citizens that has no job on the best tile available, or makes them a specialist if there is
194
+ * no tile left to work.
195
+ */
196
+ export const assignWorkers: (
197
+ city: City,
198
+ playerWorldRegistry?: PlayerWorldRegistry,
199
+ cityGrowthRegistry?: CityGrowthRegistry,
200
+ workedTileRegistry?: WorkedTileRegistry,
201
+ specialistRegistry?: SpecialistRegistry,
202
+ availableSpecialistRegistry?: AvailableSpecialistRegistry
203
+ ) => void = (
204
+ city: City,
205
+ playerWorldRegistry: PlayerWorldRegistry = playerWorldRegistryInstance,
206
+ cityGrowthRegistry: CityGrowthRegistry = cityGrowthRegistryInstance,
207
+ workedTileRegistry: WorkedTileRegistry = workedTileRegistryInstance,
208
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance,
209
+ availableSpecialistRegistry: AvailableSpecialistRegistry = availableSpecialistRegistryInstance
210
+ ): void => {
211
+ const cityGrowth = cityGrowthRegistry.getByCity(city),
212
+ placed = () =>
213
+ citizenCount(city, workedTileRegistry, specialistRegistry) >=
214
+ cityGrowth.size() + 1;
215
+
216
+ getHighestValueAvailableCityTiles(
217
+ city,
218
+ playerWorldRegistry,
219
+ workedTileRegistry
220
+ ).some((tile) => {
221
+ if (placed()) {
222
+ return true;
223
+ }
224
+
225
+ workedTileRegistry.register(new WorkedTile(tile, city));
226
+
227
+ return false;
228
+ });
229
+
230
+ while (
231
+ !placed() &&
232
+ addSpecialist(city, specialistRegistry, availableSpecialistRegistry)
233
+ ) {}
234
+ };
235
+
236
+ /**
237
+ * Places one new citizen of `city` on the best tile available, or makes them a specialist if there is no tile left.
238
+ */
239
+ export const assignWorker: (
240
+ city: City,
241
+ playerWorldRegistry?: PlayerWorldRegistry,
242
+ cityGrowthRegistry?: CityGrowthRegistry,
243
+ workedTileRegistry?: WorkedTileRegistry,
244
+ specialistRegistry?: SpecialistRegistry,
245
+ availableSpecialistRegistry?: AvailableSpecialistRegistry
246
+ ) => void = (
247
+ city: City,
248
+ playerWorldRegistry: PlayerWorldRegistry = playerWorldRegistryInstance,
249
+ cityGrowthRegistry: CityGrowthRegistry = cityGrowthRegistryInstance,
250
+ workedTileRegistry: WorkedTileRegistry = workedTileRegistryInstance,
251
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance,
252
+ availableSpecialistRegistry: AvailableSpecialistRegistry = availableSpecialistRegistryInstance
253
+ ): void => {
254
+ const [newTile] = getHighestValueAvailableCityTiles(
255
+ city,
256
+ playerWorldRegistry,
257
+ workedTileRegistry
258
+ );
259
+
260
+ if (!newTile) {
261
+ addSpecialist(city, specialistRegistry, availableSpecialistRegistry);
262
+
263
+ return;
264
+ }
265
+
266
+ workedTileRegistry.register(new WorkedTile(newTile, city));
267
+ };
268
+
269
+ export type WorkedTileChange = 'removed' | 'added' | 'reassigned' | 'none';
270
+
271
+ /**
272
+ * Changes whether `tile` is worked by `city`, as a player clicking it on the city map would.
273
+ *
274
+ * A tile the city works stops being worked, and its worker becomes a specialist. Any other tile is worked by a
275
+ * specialist, or by a citizen with no job, if the city has one and is allowed to work it. With every citizen already
276
+ * working a tile, the city's workers are reassigned instead. The city centre is always worked.
277
+ */
278
+ export const changeWorkedTile: (
279
+ city: City,
280
+ tile: Tile,
281
+ playerWorldRegistry?: PlayerWorldRegistry,
282
+ cityGrowthRegistry?: CityGrowthRegistry,
283
+ workedTileRegistry?: WorkedTileRegistry,
284
+ specialistRegistry?: SpecialistRegistry,
285
+ availableSpecialistRegistry?: AvailableSpecialistRegistry
286
+ ) => WorkedTileChange = (
287
+ city: City,
288
+ tile: Tile,
289
+ playerWorldRegistry: PlayerWorldRegistry = playerWorldRegistryInstance,
290
+ cityGrowthRegistry: CityGrowthRegistry = cityGrowthRegistryInstance,
291
+ workedTileRegistry: WorkedTileRegistry = workedTileRegistryInstance,
292
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance,
293
+ availableSpecialistRegistry: AvailableSpecialistRegistry = availableSpecialistRegistryInstance
294
+ ): WorkedTileChange => {
295
+ if (tile === city.tile() || !city.tiles().includes(tile)) {
296
+ return 'none';
297
+ }
298
+
299
+ if (workedTileRegistry.getByTile(tile)?.city() === city) {
300
+ workedTileRegistry.unregisterByTile(tile);
301
+
302
+ addSpecialist(city, specialistRegistry, availableSpecialistRegistry);
303
+
304
+ return 'removed';
305
+ }
306
+
307
+ const size = cityGrowthRegistry.getByCity(city).size();
308
+
309
+ if (workedTileRegistry.getByCity(city).length >= size + 1) {
310
+ reassignWorkers(
311
+ city,
312
+ playerWorldRegistry,
313
+ cityGrowthRegistry,
314
+ workedTileRegistry,
315
+ specialistRegistry,
316
+ availableSpecialistRegistry
317
+ );
318
+
319
+ return 'reassigned';
320
+ }
321
+
322
+ if (
323
+ !workedTileRegistry.tileCanBeWorkedBy(tile, city) ||
324
+ !playerWorldRegistry.getByPlayer(city.player()).includes(tile)
325
+ ) {
326
+ return 'none';
327
+ }
328
+
329
+ if (citizenCount(city, workedTileRegistry, specialistRegistry) >= size + 1) {
330
+ removeSpecialist(city, specialistRegistry, availableSpecialistRegistry);
331
+ }
332
+
333
+ workedTileRegistry.register(new WorkedTile(tile, city));
334
+
335
+ return 'added';
336
+ };
337
+
338
+ /**
339
+ * Takes jobs away from `city`'s citizens until it has no more than its size allows: specialists first, then the
340
+ * workers on the least valuable tiles.
341
+ */
342
+ export const releaseCitizens = (
343
+ city: City,
344
+ cityGrowth: CityGrowth,
345
+ workedTileRegistry: WorkedTileRegistry = workedTileRegistryInstance,
346
+ specialistRegistry: SpecialistRegistry = specialistRegistryInstance
347
+ ): void => {
348
+ const specialists = specialistRegistry.getByCity(city);
349
+
350
+ while (
351
+ specialists.length > 0 &&
352
+ citizenCount(city, workedTileRegistry, specialistRegistry) >
353
+ cityGrowth.size() + 1
354
+ ) {
355
+ specialistRegistry.unregister(specialists.pop()!);
356
+ }
357
+
358
+ reduceWorkers(city, cityGrowth).forEach((tile: Tile): void =>
359
+ workedTileRegistry.unregisterByTile(tile)
360
+ );
361
+ };
362
+
363
+ export const reduceWorkers = (city: City, cityGrowth: CityGrowth): Tile[] =>
364
+ sortTiles(
365
+ city
366
+ .tilesWorked()
367
+ .entries()
368
+ .filter((tile: Tile) => tile !== city.tile()),
369
+ city
370
+ ).slice(cityGrowth.size());
371
+
372
+ export default assignWorkers;
@@ -0,0 +1,28 @@
1
+ import City from '@civ-clone/core-city/City';
2
+ import { CityRegistry } from '@civ-clone/core-city/CityRegistry';
3
+ import Tile from '@civ-clone/core-world/Tile';
4
+ import { UnitRegistry } from '@civ-clone/core-unit/UnitRegistry';
5
+ import { WorkedTileRegistry } from '@civ-clone/core-city/WorkedTileRegistry';
6
+ /**
7
+ * Whether no city works `tile` yet.
8
+ */
9
+ export declare const isNotWorked: (
10
+ tile: Tile,
11
+ workedTileRegistry: WorkedTileRegistry
12
+ ) => boolean;
13
+ /**
14
+ * Whether no other player's unit stands on `tile`.
15
+ */
16
+ export declare const isNotOccupiedByEnemy: (
17
+ tile: Tile,
18
+ city: City,
19
+ unitRegistry: UnitRegistry
20
+ ) => boolean;
21
+ /**
22
+ * Whether `tile` is not the centre of a city other than `city`.
23
+ */
24
+ export declare const isNotAnotherCity: (
25
+ tile: Tile,
26
+ city: City,
27
+ cityRegistry: CityRegistry
28
+ ) => boolean;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isNotAnotherCity = exports.isNotOccupiedByEnemy = exports.isNotWorked = void 0;
4
+ /**
5
+ * Whether no city works `tile` yet.
6
+ */
7
+ const isNotWorked = (tile, workedTileRegistry) => !workedTileRegistry.tileIsWorked(tile);
8
+ exports.isNotWorked = isNotWorked;
9
+ /**
10
+ * Whether no other player's unit stands on `tile`.
11
+ */
12
+ const isNotOccupiedByEnemy = (tile, city, unitRegistry) => !unitRegistry
13
+ .getByTile(tile)
14
+ .some((unit) => unit.player() !== city.player());
15
+ exports.isNotOccupiedByEnemy = isNotOccupiedByEnemy;
16
+ /**
17
+ * Whether `tile` is not the centre of a city other than `city`.
18
+ */
19
+ const isNotAnotherCity = (tile, city, cityRegistry) => {
20
+ const otherTileCity = cityRegistry.getByTile(tile);
21
+ if (otherTileCity === null) {
22
+ return true;
23
+ }
24
+ return otherTileCity === city;
25
+ };
26
+ exports.isNotAnotherCity = isNotAnotherCity;
27
+ //# sourceMappingURL=canBeWorked.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canBeWorked.js","sourceRoot":"","sources":["canBeWorked.ts"],"names":[],"mappings":";;;AAOA;;GAEG;AACI,MAAM,WAAW,GAAG,CACzB,IAAU,EACV,kBAAsC,EAC7B,EAAE,CAAC,CAAC,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAHxC,QAAA,WAAW,eAG6B;AAErD;;GAEG;AACI,MAAM,oBAAoB,GAAG,CAClC,IAAU,EACV,IAAU,EACV,YAA0B,EACjB,EAAE,CACX,CAAC,YAAY;KACV,SAAS,CAAC,IAAI,CAAC;KACf,IAAI,CAAC,CAAC,IAAU,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAP9C,QAAA,oBAAoB,wBAO0B;AAE3D;;GAEG;AACI,MAAM,gBAAgB,GAAG,CAC9B,IAAU,EACV,IAAU,EACV,YAA0B,EACjB,EAAE;IACX,MAAM,aAAa,GAAG,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAEnD,IAAI,aAAa,KAAK,IAAI,EAAE;QAC1B,OAAO,IAAI,CAAC;KACb;IAED,OAAO,aAAa,KAAK,IAAI,CAAC;AAChC,CAAC,CAAC;AAZW,QAAA,gBAAgB,oBAY3B"}
@@ -0,0 +1,43 @@
1
+ import City from '@civ-clone/core-city/City';
2
+ import { CityRegistry } from '@civ-clone/core-city/CityRegistry';
3
+ import Tile from '@civ-clone/core-world/Tile';
4
+ import Unit from '@civ-clone/core-unit/Unit';
5
+ import { UnitRegistry } from '@civ-clone/core-unit/UnitRegistry';
6
+ import { WorkedTileRegistry } from '@civ-clone/core-city/WorkedTileRegistry';
7
+
8
+ /**
9
+ * Whether no city works `tile` yet.
10
+ */
11
+ export const isNotWorked = (
12
+ tile: Tile,
13
+ workedTileRegistry: WorkedTileRegistry
14
+ ): boolean => !workedTileRegistry.tileIsWorked(tile);
15
+
16
+ /**
17
+ * Whether no other player's unit stands on `tile`.
18
+ */
19
+ export const isNotOccupiedByEnemy = (
20
+ tile: Tile,
21
+ city: City,
22
+ unitRegistry: UnitRegistry
23
+ ): boolean =>
24
+ !unitRegistry
25
+ .getByTile(tile)
26
+ .some((unit: Unit) => unit.player() !== city.player());
27
+
28
+ /**
29
+ * Whether `tile` is not the centre of a city other than `city`.
30
+ */
31
+ export const isNotAnotherCity = (
32
+ tile: Tile,
33
+ city: City,
34
+ cityRegistry: CityRegistry
35
+ ): boolean => {
36
+ const otherTileCity = cityRegistry.getByTile(tile);
37
+
38
+ if (otherTileCity === null) {
39
+ return true;
40
+ }
41
+
42
+ return otherTileCity === city;
43
+ };
@@ -0,0 +1,12 @@
1
+ import CityBuild from '@civ-clone/core-city-build/CityBuild';
2
+ /**
3
+ * Clears what a captured city was building, so its new owner chooses: the item was its previous owner's choice, at
4
+ * its previous owner's price (civ-clone/web-renderer#670, #500). The city is asked for as a captured city's even if
5
+ * its previous owner had chosen nothing (civ-clone/web-renderer#716).
6
+ */
7
+ export declare const clearCapturedBuild: (cityBuild: CityBuild) => void;
8
+ /**
9
+ * A captured city keeps what it was building, at its new owner's price, without its previous owner's queue
10
+ * (civ-clone/web-renderer#670). Asked for as a captured city's if nothing was being built (civ-clone/web-renderer#716).
11
+ */
12
+ export declare const keepCapturedBuild: (cityBuild: CityBuild) => void;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.keepCapturedBuild = exports.clearCapturedBuild = void 0;
4
+ /**
5
+ * Clears what a captured city was building, so its new owner chooses: the item was its previous owner's choice, at
6
+ * its previous owner's price (civ-clone/web-renderer#670, #500). The city is asked for as a captured city's even if
7
+ * its previous owner had chosen nothing (civ-clone/web-renderer#716).
8
+ */
9
+ const clearCapturedBuild = (cityBuild) => {
10
+ if (cityBuild.building() === null) {
11
+ cityBuild.setCleared('captured');
12
+ return;
13
+ }
14
+ cityBuild.cancel('captured');
15
+ };
16
+ exports.clearCapturedBuild = clearCapturedBuild;
17
+ /**
18
+ * A captured city keeps what it was building, at its new owner's price, without its previous owner's queue
19
+ * (civ-clone/web-renderer#670). Asked for as a captured city's if nothing was being built (civ-clone/web-renderer#716).
20
+ */
21
+ const keepCapturedBuild = (cityBuild) => {
22
+ if (cityBuild.building() === null) {
23
+ cityBuild.setCleared('captured');
24
+ return;
25
+ }
26
+ cityBuild.clearQueue();
27
+ cityBuild.reprice();
28
+ };
29
+ exports.keepCapturedBuild = keepCapturedBuild;
30
+ //# sourceMappingURL=captured.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captured.js","sourceRoot":"","sources":["captured.ts"],"names":[],"mappings":";;;AAEA;;;;GAIG;AACI,MAAM,kBAAkB,GAAG,CAAC,SAAoB,EAAQ,EAAE;IAC/D,IAAI,SAAS,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACjC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAEjC,OAAO;KACR;IAED,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC/B,CAAC,CAAC;AARW,QAAA,kBAAkB,sBAQ7B;AAEF;;;GAGG;AACI,MAAM,iBAAiB,GAAG,CAAC,SAAoB,EAAQ,EAAE;IAC9D,IAAI,SAAS,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACjC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAEjC,OAAO;KACR;IAED,SAAS,CAAC,UAAU,EAAE,CAAC;IACvB,SAAS,CAAC,OAAO,EAAE,CAAC;AACtB,CAAC,CAAC;AATW,QAAA,iBAAiB,qBAS5B"}
@@ -0,0 +1,31 @@
1
+ import CityBuild from '@civ-clone/core-city-build/CityBuild';
2
+
3
+ /**
4
+ * Clears what a captured city was building, so its new owner chooses: the item was its previous owner's choice, at
5
+ * its previous owner's price (civ-clone/web-renderer#670, #500). The city is asked for as a captured city's even if
6
+ * its previous owner had chosen nothing (civ-clone/web-renderer#716).
7
+ */
8
+ export const clearCapturedBuild = (cityBuild: CityBuild): void => {
9
+ if (cityBuild.building() === null) {
10
+ cityBuild.setCleared('captured');
11
+
12
+ return;
13
+ }
14
+
15
+ cityBuild.cancel('captured');
16
+ };
17
+
18
+ /**
19
+ * A captured city keeps what it was building, at its new owner's price, without its previous owner's queue
20
+ * (civ-clone/web-renderer#670). Asked for as a captured city's if nothing was being built (civ-clone/web-renderer#716).
21
+ */
22
+ export const keepCapturedBuild = (cityBuild: CityBuild): void => {
23
+ if (cityBuild.building() === null) {
24
+ cityBuild.setCleared('captured');
25
+
26
+ return;
27
+ }
28
+
29
+ cityBuild.clearQueue();
30
+ cityBuild.reprice();
31
+ };
@@ -0,0 +1,12 @@
1
+ import City from '@civ-clone/core-city/City';
2
+ /**
3
+ * What keeps the names cities have been given: a game's `cityNames` (core-civilization's `CityNameRegistry`), of which
4
+ * only this much is asked.
5
+ */
6
+ export type CityNames = {
7
+ claim(name: string): void;
8
+ };
9
+ /**
10
+ * `city`'s name is claimed, so that no city founded later is given it too.
11
+ */
12
+ export declare const claimName: (city: City, cityNames: CityNames) => void;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.claimName = void 0;
4
+ /**
5
+ * `city`'s name is claimed, so that no city founded later is given it too.
6
+ */
7
+ const claimName = (city, cityNames) => cityNames.claim(city.name());
8
+ exports.claimName = claimName;
9
+ //# sourceMappingURL=claimName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claimName.js","sourceRoot":"","sources":["claimName.ts"],"names":[],"mappings":";;;AAQA;;GAEG;AACI,MAAM,SAAS,GAAG,CAAC,IAAU,EAAE,SAAoB,EAAQ,EAAE,CAClE,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AADlB,QAAA,SAAS,aACS"}
@@ -0,0 +1,13 @@
1
+ import City from '@civ-clone/core-city/City';
2
+
3
+ /**
4
+ * What keeps the names cities have been given: a game's `cityNames` (core-civilization's `CityNameRegistry`), of which
5
+ * only this much is asked.
6
+ */
7
+ export type CityNames = { claim(name: string): void };
8
+
9
+ /**
10
+ * `city`'s name is claimed, so that no city founded later is given it too.
11
+ */
12
+ export const claimName = (city: City, cityNames: CityNames): void =>
13
+ cityNames.claim(city.name());
@@ -0,0 +1,41 @@
1
+ import { AvailableSpecialistRegistry } from '@civ-clone/core-city/AvailableSpecialistRegistry';
2
+ import { CityGrowthRegistry } from '@civ-clone/core-city-growth/CityGrowthRegistry';
3
+ import { PlayerWorldRegistry } from '@civ-clone/core-player-world/PlayerWorldRegistry';
4
+ import { RuleRegistry } from '@civ-clone/core-rule/RuleRegistry';
5
+ import { SpecialistRegistry } from '@civ-clone/core-city/SpecialistRegistry';
6
+ import { WorkedTileRegistry } from '@civ-clone/core-city/WorkedTileRegistry';
7
+ import { AvailableCityBuildItemsRegistry } from '@civ-clone/core-city-build/AvailableCityBuildItemsRegistry';
8
+ import City from '@civ-clone/core-city/City';
9
+ import CityBuild from '@civ-clone/core-city-build/CityBuild';
10
+ import { CityBuildRegistry } from '@civ-clone/core-city-build/CityBuildRegistry';
11
+ import CityGrowth from '@civ-clone/core-city-growth/CityGrowth';
12
+ /**
13
+ * Gives a new city its build, whose first item is asked for as a new city's (civ-clone/web-renderer#716).
14
+ */
15
+ export declare const registerCityBuild: (
16
+ city: City,
17
+ cityBuildRegistry: CityBuildRegistry,
18
+ availableBuildItemsRegistry: AvailableCityBuildItemsRegistry,
19
+ ruleRegistry?: RuleRegistry
20
+ ) => CityBuild;
21
+ /**
22
+ * Gives a new city its growth: its size and food store.
23
+ */
24
+ export declare const registerCityGrowth: (
25
+ city: City,
26
+ cityGrowthRegistry?: CityGrowthRegistry,
27
+ ruleRegistry?: RuleRegistry
28
+ ) => CityGrowth;
29
+ /**
30
+ * A new city works its own centre, taking it from any city that worked it, which its `TileReassigned` rules then let
31
+ * choose another, and puts its citizens to work.
32
+ */
33
+ export declare const workCityTile: (
34
+ city: City,
35
+ ruleRegistry?: RuleRegistry,
36
+ playerWorldRegistry?: PlayerWorldRegistry,
37
+ cityGrowthRegistry?: CityGrowthRegistry,
38
+ workedTileRegistry?: WorkedTileRegistry,
39
+ specialistRegistry?: SpecialistRegistry,
40
+ availableSpecialistRegistry?: AvailableSpecialistRegistry
41
+ ) => void;