Trashing is now a specific action. If an effect trashes a card without using state.doTrash, it should be sure to append to the state.trash list itself. Otherwise, in a very realistic sense, it's dropping the card on the floor.
With trashing handled more consistently, we can now set the total number of cards in the game as an invariant and check it every turn. If the number decreases, cards are being dropped on the floor (and if it increases, cards are being duplicated).
While refactoring trashing, I caught a couple of cases where cards were being dropped (mostly by attempts to mutate a list with .concat, which does nothing). There are almost certainly other cases. We should create and check this invariant, and close this bug when we can get through many thousands of games while guaranteeing that no cards are lost.
Trashing is now a specific action. If an effect trashes a card without using state.doTrash, it should be sure to append to the state.trash list itself. Otherwise, in a very realistic sense, it's dropping the card on the floor.
With trashing handled more consistently, we can now set the total number of cards in the game as an invariant and check it every turn. If the number decreases, cards are being dropped on the floor (and if it increases, cards are being duplicated).
While refactoring trashing, I caught a couple of cases where cards were being dropped (mostly by attempts to mutate a list with .concat, which does nothing). There are almost certainly other cases. We should create and check this invariant, and close this bug when we can get through many thousands of games while guaranteeing that no cards are lost.