@gamepark/greylune 0.1.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/dist/Constants.d.ts +23 -0
- package/dist/Constants.d.ts.map +1 -0
- package/dist/Constants.js +17 -0
- package/dist/Constants.js.map +1 -0
- package/dist/GreyluneOptions.d.ts +11 -0
- package/dist/GreyluneOptions.d.ts.map +1 -0
- package/dist/GreyluneOptions.js +8 -0
- package/dist/GreyluneOptions.js.map +1 -0
- package/dist/GreyluneRules.d.ts +123 -0
- package/dist/GreyluneRules.d.ts.map +1 -0
- package/dist/GreyluneRules.js +122 -0
- package/dist/GreyluneRules.js.map +1 -0
- package/dist/GreyluneSetup.d.ts +18 -0
- package/dist/GreyluneSetup.d.ts.map +1 -0
- package/dist/GreyluneSetup.js +88 -0
- package/dist/GreyluneSetup.js.map +1 -0
- package/dist/Memory.d.ts +22 -0
- package/dist/Memory.d.ts.map +1 -0
- package/dist/Memory.js +23 -0
- package/dist/Memory.js.map +1 -0
- package/dist/PlayerColor.d.ts +7 -0
- package/dist/PlayerColor.d.ts.map +1 -0
- package/dist/PlayerColor.js +8 -0
- package/dist/PlayerColor.js.map +1 -0
- package/dist/Season.d.ts +7 -0
- package/dist/Season.d.ts.map +1 -0
- package/dist/Season.js +8 -0
- package/dist/Season.js.map +1 -0
- package/dist/Year.d.ts +8 -0
- package/dist/Year.d.ts.map +1 -0
- package/dist/Year.js +10 -0
- package/dist/Year.js.map +1 -0
- package/dist/ai/Evaluation.d.ts +118 -0
- package/dist/ai/Evaluation.d.ts.map +1 -0
- package/dist/ai/Evaluation.js +1069 -0
- package/dist/ai/Evaluation.js.map +1 -0
- package/dist/ai/GreyluneAI.d.ts +20 -0
- package/dist/ai/GreyluneAI.d.ts.map +1 -0
- package/dist/ai/GreyluneAI.js +113 -0
- package/dist/ai/GreyluneAI.js.map +1 -0
- package/dist/ai/Model.d.ts +38 -0
- package/dist/ai/Model.d.ts.map +1 -0
- package/dist/ai/Model.js +105 -0
- package/dist/ai/Model.js.map +1 -0
- package/dist/ai/Simulation.d.ts +13 -0
- package/dist/ai/Simulation.d.ts.map +1 -0
- package/dist/ai/Simulation.js +20 -0
- package/dist/ai/Simulation.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/material/Area.d.ts +9 -0
- package/dist/material/Area.d.ts.map +1 -0
- package/dist/material/Area.js +10 -0
- package/dist/material/Area.js.map +1 -0
- package/dist/material/Distance.d.ts +8 -0
- package/dist/material/Distance.d.ts.map +1 -0
- package/dist/material/Distance.js +9 -0
- package/dist/material/Distance.js.map +1 -0
- package/dist/material/Effect.d.ts +103 -0
- package/dist/material/Effect.d.ts.map +1 -0
- package/dist/material/Effect.js +83 -0
- package/dist/material/Effect.js.map +1 -0
- package/dist/material/EncounterCard.d.ts +61 -0
- package/dist/material/EncounterCard.d.ts.map +1 -0
- package/dist/material/EncounterCard.js +214 -0
- package/dist/material/EncounterCard.js.map +1 -0
- package/dist/material/EventTile.d.ts +17 -0
- package/dist/material/EventTile.d.ts.map +1 -0
- package/dist/material/EventTile.js +52 -0
- package/dist/material/EventTile.js.map +1 -0
- package/dist/material/LocationType.d.ts +42 -0
- package/dist/material/LocationType.d.ts.map +1 -0
- package/dist/material/LocationType.js +43 -0
- package/dist/material/LocationType.js.map +1 -0
- package/dist/material/MaterialSource.d.ts +8 -0
- package/dist/material/MaterialSource.d.ts.map +1 -0
- package/dist/material/MaterialSource.js +2 -0
- package/dist/material/MaterialSource.js.map +1 -0
- package/dist/material/MaterialType.d.ts +23 -0
- package/dist/material/MaterialType.d.ts.map +1 -0
- package/dist/material/MaterialType.js +24 -0
- package/dist/material/MaterialType.js.map +1 -0
- package/dist/material/Period.d.ts +6 -0
- package/dist/material/Period.d.ts.map +1 -0
- package/dist/material/Period.js +7 -0
- package/dist/material/Period.js.map +1 -0
- package/dist/material/PlayerState.d.ts +34 -0
- package/dist/material/PlayerState.d.ts.map +1 -0
- package/dist/material/PlayerState.js +106 -0
- package/dist/material/PlayerState.js.map +1 -0
- package/dist/material/QuestTile.d.ts +21 -0
- package/dist/material/QuestTile.d.ts.map +1 -0
- package/dist/material/QuestTile.js +32 -0
- package/dist/material/QuestTile.js.map +1 -0
- package/dist/material/Reaction.d.ts +49 -0
- package/dist/material/Reaction.d.ts.map +1 -0
- package/dist/material/Reaction.js +37 -0
- package/dist/material/Reaction.js.map +1 -0
- package/dist/material/Tokens.d.ts +29 -0
- package/dist/material/Tokens.d.ts.map +1 -0
- package/dist/material/Tokens.js +46 -0
- package/dist/material/Tokens.js.map +1 -0
- package/dist/material/Village.d.ts +23 -0
- package/dist/material/Village.d.ts.map +1 -0
- package/dist/material/Village.js +29 -0
- package/dist/material/Village.js.map +1 -0
- package/dist/material/VillageCard.d.ts +90 -0
- package/dist/material/VillageCard.d.ts.map +1 -0
- package/dist/material/VillageCard.js +359 -0
- package/dist/material/VillageCard.js.map +1 -0
- package/dist/material/Villager.d.ts +8 -0
- package/dist/material/Villager.d.ts.map +1 -0
- package/dist/material/Villager.js +7 -0
- package/dist/material/Villager.js.map +1 -0
- package/dist/material/VpToken.d.ts +10 -0
- package/dist/material/VpToken.d.ts.map +1 -0
- package/dist/material/VpToken.js +9 -0
- package/dist/material/VpToken.js.map +1 -0
- package/dist/rules/ActivateCardRule.d.ts +43 -0
- package/dist/rules/ActivateCardRule.d.ts.map +1 -0
- package/dist/rules/ActivateCardRule.js +183 -0
- package/dist/rules/ActivateCardRule.js.map +1 -0
- package/dist/rules/AutumnRule.d.ts +9 -0
- package/dist/rules/AutumnRule.d.ts.map +1 -0
- package/dist/rules/AutumnRule.js +42 -0
- package/dist/rules/AutumnRule.js.map +1 -0
- package/dist/rules/BonusTokenRule.d.ts +10 -0
- package/dist/rules/BonusTokenRule.d.ts.map +1 -0
- package/dist/rules/BonusTokenRule.js +20 -0
- package/dist/rules/BonusTokenRule.js.map +1 -0
- package/dist/rules/ChooseOutcomeRule.d.ts +9 -0
- package/dist/rules/ChooseOutcomeRule.d.ts.map +1 -0
- package/dist/rules/ChooseOutcomeRule.js +18 -0
- package/dist/rules/ChooseOutcomeRule.js.map +1 -0
- package/dist/rules/ChooseSkillRule.d.ts +10 -0
- package/dist/rules/ChooseSkillRule.d.ts.map +1 -0
- package/dist/rules/ChooseSkillRule.js +20 -0
- package/dist/rules/ChooseSkillRule.js.map +1 -0
- package/dist/rules/CustomMoveType.d.ts +17 -0
- package/dist/rules/CustomMoveType.d.ts.map +1 -0
- package/dist/rules/CustomMoveType.js +18 -0
- package/dist/rules/CustomMoveType.js.map +1 -0
- package/dist/rules/DiscardItemRule.d.ts +9 -0
- package/dist/rules/DiscardItemRule.d.ts.map +1 -0
- package/dist/rules/DiscardItemRule.js +19 -0
- package/dist/rules/DiscardItemRule.js.map +1 -0
- package/dist/rules/EncounterRule.d.ts +26 -0
- package/dist/rules/EncounterRule.d.ts.map +1 -0
- package/dist/rules/EncounterRule.js +75 -0
- package/dist/rules/EncounterRule.js.map +1 -0
- package/dist/rules/EventRule.d.ts +13 -0
- package/dist/rules/EventRule.d.ts.map +1 -0
- package/dist/rules/EventRule.js +39 -0
- package/dist/rules/EventRule.js.map +1 -0
- package/dist/rules/FinalScoringRule.d.ts +18 -0
- package/dist/rules/FinalScoringRule.d.ts.map +1 -0
- package/dist/rules/FinalScoringRule.js +30 -0
- package/dist/rules/FinalScoringRule.js.map +1 -0
- package/dist/rules/GreyluneRule.d.ts +87 -0
- package/dist/rules/GreyluneRule.d.ts.map +1 -0
- package/dist/rules/GreyluneRule.js +432 -0
- package/dist/rules/GreyluneRule.js.map +1 -0
- package/dist/rules/PlaceVillagerRule.d.ts +10 -0
- package/dist/rules/PlaceVillagerRule.d.ts.map +1 -0
- package/dist/rules/PlaceVillagerRule.js +17 -0
- package/dist/rules/PlaceVillagerRule.js.map +1 -0
- package/dist/rules/ReactionRule.d.ts +17 -0
- package/dist/rules/ReactionRule.d.ts.map +1 -0
- package/dist/rules/ReactionRule.js +48 -0
- package/dist/rules/ReactionRule.js.map +1 -0
- package/dist/rules/ResolveEffectsRule.d.ts +12 -0
- package/dist/rules/ResolveEffectsRule.d.ts.map +1 -0
- package/dist/rules/ResolveEffectsRule.js +85 -0
- package/dist/rules/ResolveEffectsRule.js.map +1 -0
- package/dist/rules/ResolveEncounterRule.d.ts +19 -0
- package/dist/rules/ResolveEncounterRule.d.ts.map +1 -0
- package/dist/rules/ResolveEncounterRule.js +86 -0
- package/dist/rules/ResolveEncounterRule.js.map +1 -0
- package/dist/rules/ResolveQuestRule.d.ts +17 -0
- package/dist/rules/ResolveQuestRule.d.ts.map +1 -0
- package/dist/rules/ResolveQuestRule.js +64 -0
- package/dist/rules/ResolveQuestRule.js.map +1 -0
- package/dist/rules/RuleId.d.ts +27 -0
- package/dist/rules/RuleId.d.ts.map +1 -0
- package/dist/rules/RuleId.js +28 -0
- package/dist/rules/RuleId.js.map +1 -0
- package/dist/rules/SeasonRule.d.ts +11 -0
- package/dist/rules/SeasonRule.d.ts.map +1 -0
- package/dist/rules/SeasonRule.js +32 -0
- package/dist/rules/SeasonRule.js.map +1 -0
- package/dist/rules/SpecialActionRule.d.ts +15 -0
- package/dist/rules/SpecialActionRule.d.ts.map +1 -0
- package/dist/rules/SpecialActionRule.js +32 -0
- package/dist/rules/SpecialActionRule.js.map +1 -0
- package/dist/rules/SpringRule.d.ts +7 -0
- package/dist/rules/SpringRule.d.ts.map +1 -0
- package/dist/rules/SpringRule.js +16 -0
- package/dist/rules/SpringRule.js.map +1 -0
- package/dist/rules/StraightenCardRule.d.ts +9 -0
- package/dist/rules/StraightenCardRule.d.ts.map +1 -0
- package/dist/rules/StraightenCardRule.js +11 -0
- package/dist/rules/StraightenCardRule.js.map +1 -0
- package/dist/rules/SummerRule.d.ts +30 -0
- package/dist/rules/SummerRule.d.ts.map +1 -0
- package/dist/rules/SummerRule.js +140 -0
- package/dist/rules/SummerRule.js.map +1 -0
- package/dist/rules/TellStoryRule.d.ts +22 -0
- package/dist/rules/TellStoryRule.d.ts.map +1 -0
- package/dist/rules/TellStoryRule.js +72 -0
- package/dist/rules/TellStoryRule.js.map +1 -0
- package/dist/rules/TheFirstStepRule.d.ts +5 -0
- package/dist/rules/TheFirstStepRule.d.ts.map +1 -0
- package/dist/rules/TheFirstStepRule.js +7 -0
- package/dist/rules/TheFirstStepRule.js.map +1 -0
- package/dist/rules/TravelRule.d.ts +13 -0
- package/dist/rules/TravelRule.d.ts.map +1 -0
- package/dist/rules/TravelRule.js +41 -0
- package/dist/rules/TravelRule.js.map +1 -0
- package/dist/rules/UseItemRule.d.ts +6 -0
- package/dist/rules/UseItemRule.d.ts.map +1 -0
- package/dist/rules/UseItemRule.js +35 -0
- package/dist/rules/UseItemRule.js.map +1 -0
- package/dist/rules/WinterRule.d.ts +24 -0
- package/dist/rules/WinterRule.d.ts.map +1 -0
- package/dist/rules/WinterRule.js +112 -0
- package/dist/rules/WinterRule.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isCustomMoveType, isMoveItemType } from '@gamepark/rules-api';
|
|
2
|
+
import { eventTileData, isFestival } from '../material/EventTile';
|
|
3
|
+
import { LocationType } from '../material/LocationType';
|
|
4
|
+
import { MaterialType } from '../material/MaterialType';
|
|
5
|
+
import { CustomMoveType } from './CustomMoveType';
|
|
6
|
+
import { GreyluneRule } from './GreyluneRule';
|
|
7
|
+
export class EventRule extends GreyluneRule {
|
|
8
|
+
get newcomer() {
|
|
9
|
+
return this.myVillagers.location((location) => location.type === LocationType.EventSpace && location.x === undefined);
|
|
10
|
+
}
|
|
11
|
+
onRuleStart() {
|
|
12
|
+
const moves = this.getPlayerMoves();
|
|
13
|
+
if (moves.length > 1)
|
|
14
|
+
return [];
|
|
15
|
+
return moves.length ? moves : this.endOfAction();
|
|
16
|
+
}
|
|
17
|
+
getPlayerMoves() {
|
|
18
|
+
const tile = this.eventTile;
|
|
19
|
+
if (tile === undefined || !this.newcomer.length)
|
|
20
|
+
return [];
|
|
21
|
+
return this.eventOptions.map((option) => isFestival(tile) ? this.newcomer.moveItem({ ...this.eventSpace, x: option }) : this.customMove(CustomMoveType.TakeEventOption, option));
|
|
22
|
+
}
|
|
23
|
+
afterItemMove(move) {
|
|
24
|
+
if (!isMoveItemType(MaterialType.Villager)(move) || move.location.type !== LocationType.EventSpace)
|
|
25
|
+
return [];
|
|
26
|
+
return move.location.x === undefined ? [] : this.takeOption(move.location.x);
|
|
27
|
+
}
|
|
28
|
+
onCustomMove(move) {
|
|
29
|
+
if (isCustomMoveType(CustomMoveType.TakeEventOption)(move))
|
|
30
|
+
return this.takeOption(move.data);
|
|
31
|
+
return super.onCustomMove(move);
|
|
32
|
+
}
|
|
33
|
+
takeOption(option) {
|
|
34
|
+
const ability = eventTileData[this.eventTile].abilities[option];
|
|
35
|
+
this.pushGains(ability.gains ?? []);
|
|
36
|
+
return [...this.payRequirements(ability.requirements), ...this.endOfAction()];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=EventRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventRule.js","sourceRoot":"","sources":["../../src/rules/EventRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,gBAAgB,EAAE,cAAc,EAAY,MAAM,qBAAqB,CAAA;AAC5F,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAkC,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAe7E,MAAM,OAAO,SAAU,SAAQ,YAAY;IAEzC,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;IACvH,CAAC;IAED,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QACnC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,CAAA;QAE/B,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA;IAClD,CAAC;IAED,cAAc;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAA;QAI3B,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM;YAAE,OAAO,EAAE,CAAA;QAC1D,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACtC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,eAAe,EAAE,MAAM,CAAC,CACvI,CAAA;IACH,CAAC;IAGD,aAAa,CAAC,IAAkD;QAC9D,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,UAAU;YAAE,OAAO,EAAE,CAAA;QAC7G,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC9E,CAAC;IAGD,YAAY,CAAC,IAAgB;QAC3B,IAAI,gBAAgB,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAc,CAAC,CAAA;QACvG,OAAO,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IAEO,UAAU,CAAC,MAAc;QAC/B,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,SAAU,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAChE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QACnC,OAAO,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;IAC/E,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MaterialRulesPart } from '@gamepark/rules-api';
|
|
2
|
+
import { LocationType } from '../material/LocationType';
|
|
3
|
+
import { MaterialSource } from '../material/MaterialSource';
|
|
4
|
+
import { MaterialType } from '../material/MaterialType';
|
|
5
|
+
import { PlayerColor } from '../PlayerColor';
|
|
6
|
+
import { GreyluneMove } from './GreyluneRule';
|
|
7
|
+
import { RuleId } from './RuleId';
|
|
8
|
+
type Count = {
|
|
9
|
+
rule: RuleId;
|
|
10
|
+
score: (source: MaterialSource, player: PlayerColor) => number;
|
|
11
|
+
};
|
|
12
|
+
export declare const finalScoring: Count[];
|
|
13
|
+
export declare class FinalScoringRule extends MaterialRulesPart<PlayerColor, MaterialType, LocationType, RuleId> {
|
|
14
|
+
onRuleStart(): GreyluneMove[];
|
|
15
|
+
}
|
|
16
|
+
export declare const scoreStillToCount: (source: MaterialSource, player: PlayerColor, rule?: RuleId) => number;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=FinalScoringRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FinalScoringRule.d.ts","sourceRoot":"","sources":["../../src/rules/FinalScoringRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAc,MAAM,gBAAgB,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,KAAK,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,KAAK,MAAM,CAAA;CAAE,CAAA;AAG7F,eAAO,MAAM,YAAY,EAAE,KAAK,EAK/B,CAAA;AAUD,qBAAa,gBAAiB,SAAQ,iBAAiB,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC;IACtG,WAAW,IAAI,YAAY,EAAE,CAU5B;CACF;AAQD,eAAO,MAAM,iBAAiB,WAAY,cAAc,UAAU,WAAW,SAAS,MAAM,KAAG,MAI9F,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { MaterialRulesPart } from '@gamepark/rules-api';
|
|
2
|
+
import { companionsScore, itemsScore, playerVp, questScore, skillScore } from '../material/PlayerState';
|
|
3
|
+
import { scoreMoves } from './GreyluneRule';
|
|
4
|
+
import { RuleId } from './RuleId';
|
|
5
|
+
export const finalScoring = [
|
|
6
|
+
{ rule: RuleId.QuestsScoring, score: questScore },
|
|
7
|
+
{ rule: RuleId.CompanionsScoring, score: companionsScore },
|
|
8
|
+
{ rule: RuleId.ItemsScoring, score: itemsScore },
|
|
9
|
+
{ rule: RuleId.SkillsScoring, score: skillScore }
|
|
10
|
+
];
|
|
11
|
+
export class FinalScoringRule extends MaterialRulesPart {
|
|
12
|
+
onRuleStart() {
|
|
13
|
+
const step = finalScoring.findIndex(({ rule }) => rule === this.game.rule?.id);
|
|
14
|
+
const next = finalScoring[step + 1];
|
|
15
|
+
return [
|
|
16
|
+
...this.game.players.flatMap((player) => {
|
|
17
|
+
const points = finalScoring[step].score(this, player);
|
|
18
|
+
return points ? scoreMoves(this, player, playerVp(this, player) + points) : [];
|
|
19
|
+
}),
|
|
20
|
+
next ? this.startRule(next.rule) : this.endGame()
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export const scoreStillToCount = (source, player, rule) => {
|
|
25
|
+
if (rule === undefined)
|
|
26
|
+
return 0;
|
|
27
|
+
const step = Math.max(0, finalScoring.findIndex((count) => count.rule === rule));
|
|
28
|
+
return finalScoring.slice(step).reduce((total, { score }) => total + score(source, player), 0);
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=FinalScoringRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FinalScoringRule.js","sourceRoot":"","sources":["../../src/rules/FinalScoringRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAIvD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEvG,OAAO,EAAgB,UAAU,EAAE,MAAM,gBAAgB,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAKjC,MAAM,CAAC,MAAM,YAAY,GAAY;IACnC,EAAE,IAAI,EAAE,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE;IACjD,EAAE,IAAI,EAAE,MAAM,CAAC,iBAAiB,EAAE,KAAK,EAAE,eAAe,EAAE;IAC1D,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE;IAChD,EAAE,IAAI,EAAE,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE;CAClD,CAAA;AAUD,MAAM,OAAO,gBAAiB,SAAQ,iBAAkE;IACtG,WAAW;QACT,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAC9E,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC,CAAA;QACnC,OAAO;YACL,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;gBACtC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;gBACrD,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAChF,CAAC,CAAC;YACF,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE;SAClD,CAAA;IACH,CAAC;CACF;AAQD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAsB,EAAE,MAAmB,EAAE,IAAa,EAAU,EAAE;IACtG,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,CAAA;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAA;IAChF,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;AAChG,CAAC,CAAA"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { CustomMove, Location, Material, MaterialMove, PlayerTurnRule } from '@gamepark/rules-api';
|
|
2
|
+
import { PlayerColor } from '../PlayerColor';
|
|
3
|
+
import { Count, Gain, Requirement } from '../material/Effect';
|
|
4
|
+
import { EventTile } from '../material/EventTile';
|
|
5
|
+
import { LocationType } from '../material/LocationType';
|
|
6
|
+
import { MaterialType } from '../material/MaterialType';
|
|
7
|
+
import { MaterialSource } from '../material/MaterialSource';
|
|
8
|
+
import { ReactionEffect, TriggerType } from '../material/Reaction';
|
|
9
|
+
import { VillageCard } from '../material/VillageCard';
|
|
10
|
+
import { Season } from '../Season';
|
|
11
|
+
import { RuleId } from './RuleId';
|
|
12
|
+
export type GreyluneMove = MaterialMove<PlayerColor, MaterialType, LocationType, RuleId>;
|
|
13
|
+
export type GreyluneMaterial = Material<PlayerColor, MaterialType, LocationType>;
|
|
14
|
+
export type SkillMarker = MaterialType.StrengthMarker | MaterialType.MagicMarker;
|
|
15
|
+
export type CostReduction = {
|
|
16
|
+
force?: number;
|
|
17
|
+
villagers?: number;
|
|
18
|
+
coins?: number;
|
|
19
|
+
noSurcharge?: boolean;
|
|
20
|
+
itemVp?: number;
|
|
21
|
+
freeSealValue?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type ReactionChoice = {
|
|
24
|
+
card: number;
|
|
25
|
+
option: number;
|
|
26
|
+
};
|
|
27
|
+
export declare abstract class GreyluneRule extends PlayerTurnRule<PlayerColor, MaterialType, LocationType, RuleId> {
|
|
28
|
+
get villageCards(): GreyluneMaterial;
|
|
29
|
+
get encounterCards(): GreyluneMaterial;
|
|
30
|
+
get villagers(): GreyluneMaterial;
|
|
31
|
+
get myVillagers(): GreyluneMaterial;
|
|
32
|
+
get activeVillagers(): GreyluneMaterial;
|
|
33
|
+
get adventurer(): GreyluneMaterial;
|
|
34
|
+
playerCard(index: number): VillageCard;
|
|
35
|
+
get coins(): number;
|
|
36
|
+
get force(): number;
|
|
37
|
+
get magic(): number;
|
|
38
|
+
get season(): Season;
|
|
39
|
+
get hasStoryToTell(): boolean;
|
|
40
|
+
canReceive(gains?: Gain[]): boolean;
|
|
41
|
+
get temporaryForce(): number;
|
|
42
|
+
get temporaryMagic(): number;
|
|
43
|
+
get tileOfTheYear(): GreyluneMaterial;
|
|
44
|
+
get eventTile(): EventTile | undefined;
|
|
45
|
+
get eventSpace(): Location<PlayerColor, LocationType>;
|
|
46
|
+
get hasUsedEvent(): boolean;
|
|
47
|
+
get eventOptions(): number[];
|
|
48
|
+
get gains(): Gain[];
|
|
49
|
+
pushGains(gains: Gain[], first?: boolean): void;
|
|
50
|
+
endOfAction(): GreyluneMove[];
|
|
51
|
+
amount(count: Count): number;
|
|
52
|
+
gainMove(gain: Gain): GreyluneMove | undefined;
|
|
53
|
+
onCustomMove(move: CustomMove): GreyluneMove[];
|
|
54
|
+
private get money();
|
|
55
|
+
gainCoins(amount: number): GreyluneMove[];
|
|
56
|
+
payCoins(amount: number): GreyluneMove[];
|
|
57
|
+
gainVp(amount: number): GreyluneMove[];
|
|
58
|
+
gainSkill(marker: SkillMarker, amount: number): GreyluneMove[];
|
|
59
|
+
moveSkillMarker(marker: SkillMarker, amount: number): GreyluneMove[];
|
|
60
|
+
skillGained(marker: SkillMarker, amount: number): GreyluneMove[];
|
|
61
|
+
gainVillagers(amount: number): GreyluneMove[];
|
|
62
|
+
canPay(requirements?: Requirement[], reduction?: CostReduction): boolean;
|
|
63
|
+
private canPayOne;
|
|
64
|
+
payRequirements(requirements?: Requirement[]): GreyluneMove[];
|
|
65
|
+
coinCost(requirements?: Requirement[]): number;
|
|
66
|
+
private payOne;
|
|
67
|
+
spendVillagers(amount: number): GreyluneMove[];
|
|
68
|
+
get costReduction(): CostReduction;
|
|
69
|
+
reduceCost(reduction: CostReduction): void;
|
|
70
|
+
reactionChoices(triggers: TriggerType[]): ReactionChoice[];
|
|
71
|
+
private canReact;
|
|
72
|
+
get playerCards(): GreyluneMaterial;
|
|
73
|
+
potentialReduction(triggers: TriggerType[]): CostReduction;
|
|
74
|
+
resume(triggers?: TriggerType[]): GreyluneMove[];
|
|
75
|
+
openReactions(triggers: TriggerType[], next: RuleId): GreyluneMove[];
|
|
76
|
+
reactionEffect(card: number, option: number): ReactionEffect;
|
|
77
|
+
useReaction(card: number, option: number): GreyluneMove[];
|
|
78
|
+
private payReactionCost;
|
|
79
|
+
private applyReaction;
|
|
80
|
+
nextActivePlayer(): PlayerColor | undefined;
|
|
81
|
+
seasonRule(player: PlayerColor): RuleId;
|
|
82
|
+
endOfTurn(): GreyluneMove[];
|
|
83
|
+
forgetAction(): void;
|
|
84
|
+
}
|
|
85
|
+
export declare const vpTokenFor: (total: number) => number;
|
|
86
|
+
export declare const scoreMoves: (source: MaterialSource, player: PlayerColor, total: number) => GreyluneMove[];
|
|
87
|
+
//# sourceMappingURL=GreyluneRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GreyluneRule.d.ts","sourceRoot":"","sources":["../../src/rules/GreyluneRule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import { getEnumValues, isCustomMoveType, PlayerTurnRule } from '@gamepark/rules-api';
|
|
2
|
+
import { BONUS_TOKEN_SCORES, MAX_SKILL, SCORE_TRACK_SIZE } from '../Constants';
|
|
3
|
+
import { Memory } from '../Memory';
|
|
4
|
+
import { bonusToken, GainType, gathered, placeVillager, RequirementType, SEAL } from '../material/Effect';
|
|
5
|
+
import { encounterCardData } from '../material/EncounterCard';
|
|
6
|
+
import { eventTileData, isFestival } from '../material/EventTile';
|
|
7
|
+
import { LocationType } from '../material/LocationType';
|
|
8
|
+
import { MaterialType } from '../material/MaterialType';
|
|
9
|
+
import { activeVillagers, keepsPotions, playerCoins, playerForce, playerMagic, playerSeason, playerVp, scoreValue, vpTokenTotal } from '../material/PlayerState';
|
|
10
|
+
import { ReactionType, TriggerType } from '../material/Reaction';
|
|
11
|
+
import { coinUnits } from '../material/Tokens';
|
|
12
|
+
import { getVillagerPlayer } from '../material/Villager';
|
|
13
|
+
import { isPotion, villageCardData } from '../material/VillageCard';
|
|
14
|
+
import { getVpToken, getVpTokenValue, VpTokenValue } from '../material/VpToken';
|
|
15
|
+
import { Season } from '../Season';
|
|
16
|
+
import { isLastYear } from '../Year';
|
|
17
|
+
import { CustomMoveType } from './CustomMoveType';
|
|
18
|
+
import { RuleId } from './RuleId';
|
|
19
|
+
export class GreyluneRule extends PlayerTurnRule {
|
|
20
|
+
get villageCards() {
|
|
21
|
+
return this.material(MaterialType.VillageCard);
|
|
22
|
+
}
|
|
23
|
+
get encounterCards() {
|
|
24
|
+
return this.material(MaterialType.EncounterCard);
|
|
25
|
+
}
|
|
26
|
+
get villagers() {
|
|
27
|
+
return this.material(MaterialType.Villager);
|
|
28
|
+
}
|
|
29
|
+
get myVillagers() {
|
|
30
|
+
return this.villagers.id((villager) => getVillagerPlayer(villager) === this.player);
|
|
31
|
+
}
|
|
32
|
+
get activeVillagers() {
|
|
33
|
+
return activeVillagers(this, this.player);
|
|
34
|
+
}
|
|
35
|
+
get adventurer() {
|
|
36
|
+
return this.material(MaterialType.Adventurer).id(this.player);
|
|
37
|
+
}
|
|
38
|
+
playerCard(index) {
|
|
39
|
+
return this.villageCards.getItem(index).id.front;
|
|
40
|
+
}
|
|
41
|
+
get coins() {
|
|
42
|
+
return playerCoins(this, this.player);
|
|
43
|
+
}
|
|
44
|
+
get force() {
|
|
45
|
+
return playerForce(this, this.player);
|
|
46
|
+
}
|
|
47
|
+
get magic() {
|
|
48
|
+
return playerMagic(this, this.player);
|
|
49
|
+
}
|
|
50
|
+
get season() {
|
|
51
|
+
return playerSeason(this, this.player);
|
|
52
|
+
}
|
|
53
|
+
get hasStoryToTell() {
|
|
54
|
+
const untold = this.encounterCards.location(LocationType.UntoldStories).player(this.player);
|
|
55
|
+
if (untold.filter((item) => encounterCardData[item.id.front].story > 0).length)
|
|
56
|
+
return true;
|
|
57
|
+
return (untold.length > 0 &&
|
|
58
|
+
this.reactionChoices([TriggerType.TellStory]).some(({ card, option }) => this.reactionEffect(card, option).type === ReactionType.StoryValue3));
|
|
59
|
+
}
|
|
60
|
+
canReceive(gains = []) {
|
|
61
|
+
return !gains.some((gain) => gain.type === GainType.TellStory) || this.hasStoryToTell;
|
|
62
|
+
}
|
|
63
|
+
get temporaryForce() {
|
|
64
|
+
return this.remind(Memory.TemporaryForce) ?? 0;
|
|
65
|
+
}
|
|
66
|
+
get temporaryMagic() {
|
|
67
|
+
return this.remind(Memory.TemporaryMagic) ?? 0;
|
|
68
|
+
}
|
|
69
|
+
get tileOfTheYear() {
|
|
70
|
+
return this.material(MaterialType.EventTile).location(LocationType.EventPile).rotation(true);
|
|
71
|
+
}
|
|
72
|
+
get eventTile() {
|
|
73
|
+
return this.tileOfTheYear.getItem()?.id;
|
|
74
|
+
}
|
|
75
|
+
get eventSpace() {
|
|
76
|
+
return { type: LocationType.EventSpace, parent: this.tileOfTheYear.getIndex() };
|
|
77
|
+
}
|
|
78
|
+
get hasUsedEvent() {
|
|
79
|
+
return this.myVillagers.location(LocationType.EventSpace).length > 0;
|
|
80
|
+
}
|
|
81
|
+
get eventOptions() {
|
|
82
|
+
const tile = this.eventTile;
|
|
83
|
+
if (tile === undefined)
|
|
84
|
+
return [];
|
|
85
|
+
const taken = this.villagers.location(LocationType.EventSpace).getItems().map((item) => item.location.x);
|
|
86
|
+
return eventTileData[tile].abilities.flatMap((ability, option) => this.canPay(ability.requirements) && !(isFestival(tile) && taken.includes(option)) ? [option] : []);
|
|
87
|
+
}
|
|
88
|
+
get gains() {
|
|
89
|
+
return this.remind(Memory.Gains) ?? [];
|
|
90
|
+
}
|
|
91
|
+
pushGains(gains, first = false) {
|
|
92
|
+
if (gains.length)
|
|
93
|
+
this.memorize(Memory.Gains, first ? [...gains, ...this.gains] : [...this.gains, ...gains]);
|
|
94
|
+
}
|
|
95
|
+
endOfAction() {
|
|
96
|
+
return [this.startRule(RuleId.ResolveEffects)];
|
|
97
|
+
}
|
|
98
|
+
amount(count) {
|
|
99
|
+
return count === SEAL ? (this.remind(Memory.SealValue) ?? 0) : count;
|
|
100
|
+
}
|
|
101
|
+
gainMove(gain) {
|
|
102
|
+
switch (gain.type) {
|
|
103
|
+
case GainType.Coins:
|
|
104
|
+
return this.customMove(CustomMoveType.GainCoins, this.amount(gain.count));
|
|
105
|
+
case GainType.Vp:
|
|
106
|
+
return this.customMove(CustomMoveType.GainVp, this.amount(gain.count));
|
|
107
|
+
case GainType.Score:
|
|
108
|
+
return this.customMove(CustomMoveType.GainVp, scoreValue(this, this.player, gain.score));
|
|
109
|
+
default:
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
onCustomMove(move) {
|
|
114
|
+
if (isCustomMoveType(CustomMoveType.GainCoins)(move))
|
|
115
|
+
return [...this.gainCoins(move.data), ...this.resume()];
|
|
116
|
+
if (isCustomMoveType(CustomMoveType.GainVp)(move))
|
|
117
|
+
return [...this.gainVp(move.data), ...this.resume()];
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
get money() {
|
|
121
|
+
return this.material(MaterialType.Coin).location(LocationType.PlayerCoins).player(this.player).money(coinUnits);
|
|
122
|
+
}
|
|
123
|
+
gainCoins(amount) {
|
|
124
|
+
return this.money.addMoney(amount, { type: LocationType.PlayerCoins, player: this.player });
|
|
125
|
+
}
|
|
126
|
+
payCoins(amount) {
|
|
127
|
+
return this.money.removeMoney(amount, { type: LocationType.PlayerCoins, player: this.player });
|
|
128
|
+
}
|
|
129
|
+
gainVp(amount) {
|
|
130
|
+
const total = playerVp(this, this.player) + amount;
|
|
131
|
+
const tokens = this.material(MaterialType.BonusToken).location(LocationType.BonusTokens).player(this.player).length;
|
|
132
|
+
if (total >= BONUS_TOKEN_SCORES[0] && tokens === 3)
|
|
133
|
+
this.pushGains([bonusToken], true);
|
|
134
|
+
if (total >= BONUS_TOKEN_SCORES[1] && tokens >= 2)
|
|
135
|
+
this.pushGains([bonusToken], true);
|
|
136
|
+
return scoreMoves(this, this.player, total);
|
|
137
|
+
}
|
|
138
|
+
gainSkill(marker, amount) {
|
|
139
|
+
const moves = this.moveSkillMarker(marker, amount);
|
|
140
|
+
return moves.length ? [...moves, ...this.skillGained(marker, amount)] : [];
|
|
141
|
+
}
|
|
142
|
+
moveSkillMarker(marker, amount) {
|
|
143
|
+
const markers = this.material(marker).player(this.player);
|
|
144
|
+
const { location } = markers.getItem();
|
|
145
|
+
const x = Math.min(MAX_SKILL, Math.max(0, (location.x ?? 0) + amount));
|
|
146
|
+
return x === location.x ? [] : [markers.moveItem({ ...location, x })];
|
|
147
|
+
}
|
|
148
|
+
skillGained(marker, amount) {
|
|
149
|
+
this.memorize(Memory.CurrentGain, { type: marker === MaterialType.StrengthMarker ? GainType.Force : GainType.Magic, count: amount });
|
|
150
|
+
return this.resume([TriggerType.GainSkill]);
|
|
151
|
+
}
|
|
152
|
+
gainVillagers(amount) {
|
|
153
|
+
return this.villagers.location(LocationType.VillagerReserve).player(this.player).limit(amount).moveItems({
|
|
154
|
+
type: LocationType.ActiveVillagers,
|
|
155
|
+
player: this.player
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
canPay(requirements = [], reduction = this.costReduction) {
|
|
159
|
+
return gathered(requirements).every((requirement) => this.canPayOne(requirement, reduction));
|
|
160
|
+
}
|
|
161
|
+
canPayOne(requirement, reduction = this.costReduction) {
|
|
162
|
+
const count = requirement.count ?? 1;
|
|
163
|
+
switch (requirement.type) {
|
|
164
|
+
case RequirementType.Force:
|
|
165
|
+
return this.force + this.temporaryForce >= count;
|
|
166
|
+
case RequirementType.Magic:
|
|
167
|
+
return this.magic + this.temporaryMagic >= count;
|
|
168
|
+
case RequirementType.Skills:
|
|
169
|
+
return this.force + this.temporaryForce + this.magic + this.temporaryMagic >= count;
|
|
170
|
+
case RequirementType.SpendCoins:
|
|
171
|
+
return this.coins >= Math.max(0, count - (reduction.coins ?? 0));
|
|
172
|
+
case RequirementType.SpendForce:
|
|
173
|
+
return this.force >= Math.max(0, count - (reduction.force ?? 0));
|
|
174
|
+
case RequirementType.SpendMagic:
|
|
175
|
+
return this.magic >= count;
|
|
176
|
+
case RequirementType.SpendVillagers:
|
|
177
|
+
return this.activeVillagers.length >= Math.max(0, count - (reduction.villagers ?? 0));
|
|
178
|
+
case RequirementType.ReturnVillager:
|
|
179
|
+
return this.activeVillagers.length >= count;
|
|
180
|
+
case RequirementType.DiscardItem:
|
|
181
|
+
return this.material(MaterialType.VillageCard).location(LocationType.Items).player(this.player).length >= 1;
|
|
182
|
+
case RequirementType.TellStories:
|
|
183
|
+
return this.encounterCards.location(LocationType.UntoldStories).player(this.player).length >= count;
|
|
184
|
+
default:
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
payRequirements(requirements = []) {
|
|
189
|
+
return gathered(requirements).flatMap((requirement) => this.payOne(requirement));
|
|
190
|
+
}
|
|
191
|
+
coinCost(requirements = []) {
|
|
192
|
+
const reduction = this.costReduction;
|
|
193
|
+
return requirements.reduce((total, requirement) => {
|
|
194
|
+
if (requirement.type === RequirementType.SpendCoins)
|
|
195
|
+
return total + Math.max(0, (requirement.count ?? 1) - (reduction.coins ?? 0));
|
|
196
|
+
if (requirement.type === RequirementType.SealCoins)
|
|
197
|
+
return total + (this.remind(Memory.SealValue) ?? 0);
|
|
198
|
+
return total;
|
|
199
|
+
}, 0);
|
|
200
|
+
}
|
|
201
|
+
payOne(requirement) {
|
|
202
|
+
const count = requirement.count ?? 1;
|
|
203
|
+
const reduction = this.costReduction;
|
|
204
|
+
switch (requirement.type) {
|
|
205
|
+
case RequirementType.SpendCoins:
|
|
206
|
+
case RequirementType.SealCoins:
|
|
207
|
+
return this.payCoins(this.coinCost([requirement]));
|
|
208
|
+
case RequirementType.SpendForce:
|
|
209
|
+
return this.moveSkillMarker(MaterialType.StrengthMarker, -Math.max(0, count - (reduction.force ?? 0)));
|
|
210
|
+
case RequirementType.SpendMagic:
|
|
211
|
+
return this.moveSkillMarker(MaterialType.MagicMarker, -count);
|
|
212
|
+
case RequirementType.SpendVillagers:
|
|
213
|
+
return this.spendVillagers(Math.max(0, count - (reduction.villagers ?? 0)));
|
|
214
|
+
case RequirementType.ReturnVillager:
|
|
215
|
+
return this.activeVillagers.limit(count).moveItems({ type: LocationType.VillagerReserve, player: this.player });
|
|
216
|
+
default:
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
spendVillagers(amount) {
|
|
221
|
+
if (amount <= 0)
|
|
222
|
+
return [];
|
|
223
|
+
return this.activeVillagers.limit(amount).moveItems({ type: LocationType.Camp });
|
|
224
|
+
}
|
|
225
|
+
get costReduction() {
|
|
226
|
+
return this.remind(Memory.CostReduction) ?? {};
|
|
227
|
+
}
|
|
228
|
+
reduceCost(reduction) {
|
|
229
|
+
this.memorize(Memory.CostReduction, { ...this.costReduction, ...reduction });
|
|
230
|
+
}
|
|
231
|
+
reactionChoices(triggers) {
|
|
232
|
+
const choices = [];
|
|
233
|
+
for (const card of this.playerCards.getIndexes()) {
|
|
234
|
+
const reaction = villageCardData[this.playerCard(card)].reaction;
|
|
235
|
+
if (!reaction || !reaction.triggers.some((trigger) => triggers.includes(trigger)))
|
|
236
|
+
continue;
|
|
237
|
+
if (!this.canReact(card, reaction))
|
|
238
|
+
continue;
|
|
239
|
+
reaction.options.forEach((effect, option) => {
|
|
240
|
+
if (effect.trigger === undefined || triggers.includes(effect.trigger))
|
|
241
|
+
choices.push({ card, option });
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
return choices;
|
|
245
|
+
}
|
|
246
|
+
canReact(card, reaction) {
|
|
247
|
+
const item = this.villageCards.getItem(card);
|
|
248
|
+
for (const requirement of reaction.requirements) {
|
|
249
|
+
if (requirement.type === RequirementType.Tilt && item.location.rotation === true)
|
|
250
|
+
return false;
|
|
251
|
+
if (requirement.type === RequirementType.DiscardCard && item.location.rotation === true)
|
|
252
|
+
return false;
|
|
253
|
+
if (!this.canPayOne(requirement))
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
return !(reaction.triggers.includes(TriggerType.TiltCard) && this.remind(Memory.LastTilted) === card);
|
|
257
|
+
}
|
|
258
|
+
get playerCards() {
|
|
259
|
+
return this.villageCards.player(this.player).location((location) => location.type === LocationType.Items || location.type === LocationType.Companions);
|
|
260
|
+
}
|
|
261
|
+
potentialReduction(triggers) {
|
|
262
|
+
const reduction = { ...this.costReduction };
|
|
263
|
+
for (const card of new Set(this.reactionChoices(triggers).map((choice) => choice.card))) {
|
|
264
|
+
for (const option of villageCardData[this.playerCard(card)].reaction.options) {
|
|
265
|
+
switch (option.type) {
|
|
266
|
+
case ReactionType.ReduceForceCost:
|
|
267
|
+
reduction.force = (reduction.force ?? 0) + 1;
|
|
268
|
+
break;
|
|
269
|
+
case ReactionType.ReduceVillagerCost:
|
|
270
|
+
reduction.villagers = (reduction.villagers ?? 0) + 1;
|
|
271
|
+
break;
|
|
272
|
+
case ReactionType.CheaperItem:
|
|
273
|
+
reduction.coins = (reduction.coins ?? 0) + 1;
|
|
274
|
+
break;
|
|
275
|
+
case ReactionType.ChooseSealValue:
|
|
276
|
+
reduction.freeSealValue = true;
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return reduction;
|
|
282
|
+
}
|
|
283
|
+
resume(triggers = []) {
|
|
284
|
+
return this.openReactions(triggers, RuleId.ResolveEffects);
|
|
285
|
+
}
|
|
286
|
+
openReactions(triggers, next) {
|
|
287
|
+
if (!triggers.length || !this.reactionChoices(triggers).length)
|
|
288
|
+
return [this.startRule(next)];
|
|
289
|
+
this.memorize(Memory.Trigger, triggers);
|
|
290
|
+
this.memorize(Memory.Resume, next);
|
|
291
|
+
return [this.startRule(RuleId.Reaction)];
|
|
292
|
+
}
|
|
293
|
+
reactionEffect(card, option) {
|
|
294
|
+
return villageCardData[this.playerCard(card)].reaction.options[option];
|
|
295
|
+
}
|
|
296
|
+
useReaction(card, option) {
|
|
297
|
+
const tiltedBefore = this.remind(Memory.LastTilted);
|
|
298
|
+
return [...this.payReactionCost(card), ...this.applyReaction(card, option, tiltedBefore)];
|
|
299
|
+
}
|
|
300
|
+
payReactionCost(card) {
|
|
301
|
+
const front = this.playerCard(card);
|
|
302
|
+
const reaction = villageCardData[front].reaction;
|
|
303
|
+
const moves = [];
|
|
304
|
+
let tilted = false;
|
|
305
|
+
for (const requirement of reaction.requirements) {
|
|
306
|
+
switch (requirement.type) {
|
|
307
|
+
case RequirementType.Tilt:
|
|
308
|
+
moves.push(this.villageCards.index(card).rotateItem(true));
|
|
309
|
+
tilted = true;
|
|
310
|
+
break;
|
|
311
|
+
case RequirementType.DiscardCard:
|
|
312
|
+
if (isPotion(front) && keepsPotions(this, this.player)) {
|
|
313
|
+
moves.push(this.villageCards.index(card).rotateItem(true));
|
|
314
|
+
tilted = true;
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
moves.push(this.villageCards.index(card).deleteItem());
|
|
318
|
+
}
|
|
319
|
+
break;
|
|
320
|
+
default:
|
|
321
|
+
moves.push(...this.payRequirements([requirement]));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (tilted) {
|
|
325
|
+
this.memorize(Memory.LastTilted, card);
|
|
326
|
+
const triggers = this.remind(Memory.Trigger) ?? [];
|
|
327
|
+
if (!triggers.includes(TriggerType.TiltCard))
|
|
328
|
+
this.memorize(Memory.Trigger, [...triggers, TriggerType.TiltCard]);
|
|
329
|
+
}
|
|
330
|
+
return moves;
|
|
331
|
+
}
|
|
332
|
+
applyReaction(card, option, tiltedBefore) {
|
|
333
|
+
const effect = this.reactionEffect(card, option);
|
|
334
|
+
switch (effect.type) {
|
|
335
|
+
case ReactionType.ExtraTravel:
|
|
336
|
+
this.memorize(Memory.TravelDistance, (this.remind(Memory.TravelDistance) ?? 0) + effect.count);
|
|
337
|
+
return [];
|
|
338
|
+
case ReactionType.PlaceVillager:
|
|
339
|
+
this.pushGains([placeVillager], true);
|
|
340
|
+
return [];
|
|
341
|
+
case ReactionType.TemporarySkills:
|
|
342
|
+
if (effect.force)
|
|
343
|
+
this.memorize(Memory.TemporaryForce, this.temporaryForce + effect.force);
|
|
344
|
+
if (effect.magic)
|
|
345
|
+
this.memorize(Memory.TemporaryMagic, this.temporaryMagic + effect.magic);
|
|
346
|
+
return [];
|
|
347
|
+
case ReactionType.IgnoreCondition:
|
|
348
|
+
this.memorize(Memory.IgnoredConditions, (this.remind(Memory.IgnoredConditions) ?? 0) + 1);
|
|
349
|
+
return [];
|
|
350
|
+
case ReactionType.StoryValue3:
|
|
351
|
+
this.memorize(Memory.StoryBoost, (this.remind(Memory.StoryBoost) ?? 0) + 1);
|
|
352
|
+
return [];
|
|
353
|
+
case ReactionType.ReduceForceCost:
|
|
354
|
+
this.reduceCost({ force: (this.costReduction.force ?? 0) + 1 });
|
|
355
|
+
return [];
|
|
356
|
+
case ReactionType.ReduceVillagerCost:
|
|
357
|
+
this.reduceCost({ villagers: (this.costReduction.villagers ?? 0) + 1 });
|
|
358
|
+
return [];
|
|
359
|
+
case ReactionType.CheaperItem:
|
|
360
|
+
this.reduceCost({ coins: (this.costReduction.coins ?? 0) + 1, itemVp: (this.costReduction.itemVp ?? 0) + 1 });
|
|
361
|
+
return [];
|
|
362
|
+
case ReactionType.ExtraCoins:
|
|
363
|
+
return this.gainCoins(effect.count);
|
|
364
|
+
case ReactionType.NoSurcharge:
|
|
365
|
+
this.reduceCost({ noSurcharge: true });
|
|
366
|
+
return [];
|
|
367
|
+
case ReactionType.ChooseSealValue:
|
|
368
|
+
this.reduceCost({ freeSealValue: true });
|
|
369
|
+
return [];
|
|
370
|
+
case ReactionType.OtherSkill: {
|
|
371
|
+
const gain = this.remind(Memory.CurrentGain);
|
|
372
|
+
this.pushGains([{ type: gain?.type === GainType.Force ? GainType.Magic : GainType.Force, count: 1 }], true);
|
|
373
|
+
return [];
|
|
374
|
+
}
|
|
375
|
+
case ReactionType.StraightenTilted:
|
|
376
|
+
return tiltedBefore === undefined ? [] : [this.villageCards.index(tiltedBefore).rotateItem(false)];
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
nextActivePlayer() {
|
|
380
|
+
const players = this.game.players;
|
|
381
|
+
const start = players.indexOf(this.player);
|
|
382
|
+
for (let step = 1; step <= players.length; step++) {
|
|
383
|
+
const player = players[(start + step) % players.length];
|
|
384
|
+
if (playerSeason(this, player) !== Season.Autumn)
|
|
385
|
+
return player;
|
|
386
|
+
}
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
seasonRule(player) {
|
|
390
|
+
return playerSeason(this, player) === Season.Spring ? RuleId.Spring : RuleId.Summer;
|
|
391
|
+
}
|
|
392
|
+
endOfTurn() {
|
|
393
|
+
this.forgetAction();
|
|
394
|
+
const next = this.nextActivePlayer();
|
|
395
|
+
if (next !== undefined)
|
|
396
|
+
return [this.startPlayerTurn(this.seasonRule(next), next)];
|
|
397
|
+
return [this.startRule(isLastYear(this) ? RuleId.QuestsScoring : RuleId.Winter)];
|
|
398
|
+
}
|
|
399
|
+
forgetAction() {
|
|
400
|
+
for (const key of getEnumValues(Memory))
|
|
401
|
+
this.forget(key);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
export const vpTokenFor = (total) => Math.min(100, Math.floor(total / SCORE_TRACK_SIZE) * SCORE_TRACK_SIZE);
|
|
405
|
+
export const scoreMoves = (source, player, total) => [
|
|
406
|
+
...vpTokenMoves(source, player, total),
|
|
407
|
+
...scoreMarkerMoves(source, player, total)
|
|
408
|
+
];
|
|
409
|
+
const scoreMarkerMoves = (source, player, total) => {
|
|
410
|
+
const marker = source.material(MaterialType.ScoreMarker).id(player);
|
|
411
|
+
const x = total - vpTokenFor(total);
|
|
412
|
+
return marker.getItem()?.location.x === x ? [] : [marker.moveItem({ type: LocationType.ScoreTrack, x })];
|
|
413
|
+
};
|
|
414
|
+
const vpTokenMoves = (source, player, total) => {
|
|
415
|
+
const value = vpTokenFor(total);
|
|
416
|
+
const tokens = source.material(MaterialType.VpToken);
|
|
417
|
+
const held = tokens.location(LocationType.PlayerVpTokens).player(player).getItem();
|
|
418
|
+
const heldValue = held ? vpTokenTotal(held.id, held.location.rotation === true) : 0;
|
|
419
|
+
if (value === heldValue)
|
|
420
|
+
return [];
|
|
421
|
+
const moves = [];
|
|
422
|
+
const wanted = value >= 75 ? VpTokenValue.Vp75 : VpTokenValue.Vp25;
|
|
423
|
+
if (held && getVpTokenValue(held.id) !== wanted) {
|
|
424
|
+
moves.push(tokens.location(LocationType.PlayerVpTokens).player(player).deleteItem());
|
|
425
|
+
}
|
|
426
|
+
if (value === 0)
|
|
427
|
+
return moves;
|
|
428
|
+
const flipped = value === 50 || value === 100;
|
|
429
|
+
moves.push(tokens.id(getVpToken(player, wanted)).moveItem({ type: LocationType.PlayerVpTokens, player, rotation: flipped }));
|
|
430
|
+
return moves;
|
|
431
|
+
};
|
|
432
|
+
//# sourceMappingURL=GreyluneRule.js.map
|