@@ -52,12 +52,20 @@ export type GameEndActionResponse = Readonly<{
52
52
type : 'GameEnd' ;
53
53
} > ;
54
54
55
+ export type OptionalConditionActionResponse = Readonly < {
56
+ condition : WinCondition ;
57
+ conditionId : number ;
58
+ toPlayer : PlayerID ;
59
+ type : 'OptionalCondition' ;
60
+ } > ;
61
+
55
62
export type GameOverActionResponses =
56
63
| AttackUnitGameOverActionResponse
57
64
| BeginTurnGameOverActionResponse
58
65
| CaptureGameOverActionResponse
59
66
| GameEndActionResponse
60
- | PreviousTurnGameOverActionResponse ;
67
+ | PreviousTurnGameOverActionResponse
68
+ | OptionalConditionActionResponse ;
61
69
62
70
function check (
63
71
previousMap : MapData ,
@@ -92,6 +100,7 @@ const pickWinningPlayer = (
92
100
condition . players ?. length ? condition . players : activeMap . active
93
101
) . find (
94
102
( playerID ) =>
103
+ ( ! condition . optional || ! condition . completed ?. has ( playerID ) ) &&
95
104
activeMap . getPlayer ( playerID ) . stats . destroyedUnits >= condition . amount ,
96
105
) ;
97
106
}
@@ -138,19 +147,20 @@ export function checkGameOverConditions(
138
147
const gameState : MutableGameState = actionResponse
139
148
? [ [ actionResponse , map ] ]
140
149
: [ ] ;
141
- const gameEndResponse = condition
142
- ? ( {
143
- condition,
144
- conditionId : activeMap . config . winConditions . indexOf ( condition ) ,
145
- toPlayer : pickWinningPlayer (
146
- previousMap ,
147
- activeMap ,
148
- lastActionResponse ,
150
+
151
+ const winningPlayer = condition
152
+ ? pickWinningPlayer ( previousMap , activeMap , lastActionResponse , condition )
153
+ : undefined ;
154
+
155
+ const gameEndResponse =
156
+ condition ?. type === WinCriteria . Default || condition ?. optional === false
157
+ ? ( {
149
158
condition,
150
- ) ,
151
- type : 'GameEnd' ,
152
- } as const )
153
- : checkGameEnd ( map ) ;
159
+ conditionId : activeMap . config . winConditions . indexOf ( condition ) ,
160
+ toPlayer : winningPlayer ,
161
+ type : 'GameEnd' ,
162
+ } as const )
163
+ : checkGameEnd ( map ) ;
154
164
155
165
if ( gameEndResponse ) {
156
166
let newGameState : GameState = [ ] ;
@@ -162,6 +172,38 @@ export function checkGameOverConditions(
162
172
] ;
163
173
}
164
174
175
+ const optionalConditionResponse =
176
+ condition ?. type !== WinCriteria . Default &&
177
+ condition ?. optional === true &&
178
+ winningPlayer &&
179
+ ! condition . completed ?. has ( winningPlayer )
180
+ ? ( {
181
+ condition,
182
+ conditionId : activeMap . config . winConditions . indexOf ( condition ) ,
183
+ toPlayer : winningPlayer ,
184
+ type : 'OptionalCondition' ,
185
+ } as const )
186
+ : null ;
187
+
188
+ if ( optionalConditionResponse ) {
189
+ let newGameState : GameState = [ ] ;
190
+ [ newGameState , map ] = processRewards ( map , optionalConditionResponse ) ;
191
+ map = applyGameOverActionResponse ( map , optionalConditionResponse ) ;
192
+ return [
193
+ ...gameState ,
194
+ ...newGameState ,
195
+ [
196
+ // update `optionalConditionResponse.condition` with the new `map.config` updated in `applyGameOverActionResponse()`
197
+ {
198
+ ...optionalConditionResponse ,
199
+ condition :
200
+ map . config . winConditions [ optionalConditionResponse . conditionId ] ,
201
+ } ,
202
+ map ,
203
+ ] ,
204
+ ] ;
205
+ }
206
+
165
207
if (
166
208
actionResponse ?. type === 'AttackUnitGameOver' ||
167
209
actionResponse ?. type === 'BeginTurnGameOver'
@@ -231,6 +273,24 @@ export function applyGameOverActionResponse(
231
273
}
232
274
case 'GameEnd' :
233
275
return map ;
276
+ case 'OptionalCondition' : {
277
+ const { condition, conditionId, toPlayer } = actionResponse ;
278
+ if ( condition . type === WinCriteria . Default ) {
279
+ return map ;
280
+ }
281
+ const winConditions = Array . from ( map . config . winConditions ) ;
282
+ winConditions [ conditionId ] = {
283
+ ...condition ,
284
+ completed : condition . completed
285
+ ? new Set ( [ ...condition . completed , toPlayer ] )
286
+ : new Set ( [ toPlayer ] ) ,
287
+ } ;
288
+ return map . copy ( {
289
+ config : map . config . copy ( {
290
+ winConditions,
291
+ } ) ,
292
+ } ) ;
293
+ }
234
294
default : {
235
295
actionResponse satisfies never ;
236
296
throw new UnknownTypeError ( 'applyGameOverActionResponse' , type ) ;
0 commit comments