Very interesting and unique problem, couldn't you just create an independent copy and run your tests on that copy and delete it once you are done.
from copy import deepcopy
#some other code...
temp_state = deepcopy(original_state)
You then run your tests on temp_state
and once you are done using it:
del temp_state
As for your second problem, you could make the bot analyze a piece's placement once it have reached 2 blocks down or whatever to solve for your problem. Or, you could have an unseeable few extra lines at the top (beyond the screen) that the player cannot see but the bot can use for making decisions.
Furthermore, and I'm sure you have already done this, you can use itertools
to create the list of strings such as lllllus,llllluus
(quoting your comment). In specific, try itertools.product
and itertools.combinations
.