@@ -28,34 +28,40 @@ export function card_elim(state) {
28
28
29
29
const candidates = state . hands . flatMap ( ( hand , playerIndex ) => hand . map ( order => ( { playerIndex, order } ) ) ) ;
30
30
31
- const all_ids = state . hands . flatMap ( hand => hand . flatMap ( o => this . thoughts [ o ] . possible . array ) ) ;
32
- const identities = state . base_ids . union ( all_ids ) . array ;
31
+ let identities = state . base_ids ;
32
+ for ( const order of state . hands . flat ( ) ) {
33
+ identities = identities . union ( this . thoughts [ order ] . possible ) ;
34
+
35
+ if ( identities . length === this . all_possible . length )
36
+ break ;
37
+ }
38
+
39
+ /** @type {(order: number) => void } */
40
+ const addToMap = ( order ) => {
41
+ const card = this . thoughts [ order ] ;
42
+ const id = card . identity ( { symmetric : this . playerIndex === - 1 } ) ;
43
+
44
+ if ( id !== undefined ) {
45
+ const id_hash = logCard ( id ) ;
46
+ certain_map . set ( id_hash , ( certain_map . get ( id_hash ) ?? new Set ( ) ) . add ( order ) ) ;
47
+ candidates . splice ( candidates . findIndex ( c => c . order === order ) , 1 ) ;
48
+ }
49
+ } ;
50
+
51
+ for ( const order of state . hands . flat ( ) )
52
+ addToMap ( order ) ;
33
53
34
54
/**
35
55
* The "typical" empathy operation. If there are enough known instances of an identity, it is removed from every card (including future cards).
36
56
* Returns true if at least one card was modified.
37
57
*/
38
58
const basic_elim = ( ) => {
39
59
let changed = false ;
60
+ const curr_identities = identities . array ;
61
+ let new_identities = identities ;
40
62
41
- /** @type {(index: number) => void } */
42
- const addToMap = ( index ) => {
43
- const { order } = candidates [ index ] ;
44
- const card = this . thoughts [ order ] ;
45
- const id = card . identity ( { symmetric : this . playerIndex === - 1 } ) ;
46
-
47
- if ( id !== undefined ) {
48
- const id_hash = logCard ( id ) ;
49
- certain_map . set ( id_hash , ( certain_map . get ( id_hash ) ?? new Set ( ) ) . add ( order ) ) ;
50
- candidates . splice ( index , 1 ) ;
51
- }
52
- } ;
53
-
54
- for ( let i = candidates . length - 1 ; i >= 0 ; i -- )
55
- addToMap ( i ) ;
56
-
57
- for ( let i = 0 ; i < identities . length ; i ++ ) {
58
- const identity = identities [ i ] ;
63
+ for ( let i = 0 ; i < curr_identities . length ; i ++ ) {
64
+ const identity = curr_identities [ i ] ;
59
65
const id_hash = logCard ( identity ) ;
60
66
61
67
const known_count = state . baseCount ( identity ) + ( certain_map . get ( id_hash ) ?. size ?? 0 ) + ( uncertain_ids . has ( identity ) ? 1 : 0 ) ;
@@ -67,9 +73,9 @@ export function card_elim(state) {
67
73
// Remove it from the list of future possibilities
68
74
this . all_possible = this . all_possible . subtract ( identity ) ;
69
75
this . all_inferred = this . all_inferred . subtract ( identity ) ;
76
+ new_identities = new_identities . subtract ( identity ) ;
70
77
71
- for ( let i = candidates . length - 1 ; i >= 0 ; i -- ) {
72
- const { order } = candidates [ i ] ;
78
+ for ( const { order } of candidates ) {
73
79
const { possible, inferred } = this . thoughts [ order ] ;
74
80
75
81
if ( ! possible . has ( identity ) || certain_map . get ( id_hash ) ?. has ( order ) || uncertain_map . get ( order ) ?. has ( identity ) )
@@ -89,12 +95,13 @@ export function card_elim(state) {
89
95
}
90
96
// Card can be further eliminated
91
97
else if ( updated_card . possible . length === 1 ) {
92
- identities . push ( updated_card . identity ( ) ) ;
93
- addToMap ( i ) ;
98
+ curr_identities . push ( updated_card . identity ( ) ) ;
99
+ addToMap ( order ) ;
94
100
}
95
101
}
96
- logger . debug ( `removing ${ id_hash } from ${ state . playerNames [ this . playerIndex ] } possibilities, now ${ this . all_possible . map ( logCard ) } ` ) ;
102
+ // logger.debug(`removing ${id_hash} from ${state.playerNames[this.playerIndex]} possibilities, now ${this.all_possible.map(logCard)}`);
97
103
}
104
+ identities = new_identities ;
98
105
return changed ;
99
106
} ;
100
107
@@ -155,13 +162,22 @@ export function card_elim(state) {
155
162
const total_multiplicity = ( identities ) => identities . reduce ( ( acc , id ) => acc += cardCount ( state . variant , id ) - state . baseCount ( id ) , 0 ) ;
156
163
157
164
for ( let i = 2 ; i <= cross_elim_candidates . length ; i ++ ) {
158
- const subsets = Utils . allSubsetsOfSize ( cross_elim_candidates , i ) ;
165
+ const subsets = Utils . allSubsetsOfSize ( cross_elim_candidates . filter ( ( { order } ) => this . thoughts [ order ] . possible . length <= i ) , i ) ;
159
166
160
167
for ( const subset of subsets ) {
161
- const identities = subset . reduce ( ( acc , { order } ) => acc . union ( this . thoughts [ order ] . possible ) , state . base_ids ) ;
168
+ let failed = false ;
169
+ let acc_ids = state . base_ids ;
170
+ for ( const { order } of subset ) {
171
+ acc_ids = acc_ids . union ( this . thoughts [ order ] . possible ) ;
172
+
173
+ if ( total_multiplicity ( acc_ids ) > subset . length ) {
174
+ failed = true ;
175
+ break ;
176
+ }
177
+ }
162
178
163
- if ( subset . length === total_multiplicity ( identities ) )
164
- perform_elim ( subset , identities ) ;
179
+ if ( ! failed && subset . length === total_multiplicity ( acc_ids ) )
180
+ perform_elim ( subset , acc_ids ) ;
165
181
}
166
182
}
167
183
0 commit comments