Copy of the final question at the bottom: "I have no idea how to solve this bug. One action is time dependent and the other one is player input dependent. Someone with an idea? Is there something in python working with mutable data which handles cases where one object gets changed at different times from different places?"
I code my own Tetris in Pygame. At the moment my goal is to rebuild the game mode "Survival" from here:
In this picture you see the original game. At that moment 6 lines already are added to the field. Every line will be generated at the bottom of the field with the grey colour with one free random spot. Everytime a line will be generated the information is added in my "locked" dictionary ( key = (x,y) : value = (153,153,153) ) and a function changes the y value in every key by 1 to the top. At the same time if the player clears a row (in this picture it would be the 6th row counting from the bottom) there is a function which deletes this cleared row in the "locked" dict and changes all y values which are greater than that line by 1 to the bottom.
Here are the two functions:
def clear_rows(grid, locked): # (0,0) is at the top left, x increases right, y increases down
i = len(grid) - 1 # last row
rows_cleared = 0
while i > -1:
row = grid[i]
if BLACK not in row: #which means the row is full and can be cleared
i_new = i rows_cleared
for j in range(len(row)):
del locked[(j, i_new)]
rows_cleared = 1
for key in sorted(list(locked), key=lambda x: x[1])[::-1]:
x_coord, y_coord = key
if y_coord < i_new:
new_key = (x_coord, y_coord 1)
locked[new_key] = locked.pop(key)
i -= 1
else:
i -= 1
return rows_cleared
and
def survival_add_line(locked):
for key in sorted(list(locked)):
x, y = key
new_key = (x, y - 1)
locked[new_key] = locked.pop(key)
gap = random.randint(0,9)
for i in range(10):
if not i == gap:
locked[(i, 19)] = SURVIVAL_GRAY
This is the code in my mainloop:
if level_time / 1000 >= 1:
survival_add_line(locked)
level_time = 0
if change_piece:
for pos in tetrimino_position:
locked[(pos[0], pos[1])] = current_piece.color
current_piece = next_pieces[0]
next_pieces.pop(0)
next_pieces.append(new_tetromino())
change_piece = False
cleared_lines = clear_rows(grid, locked)
I noticed the bug can only happen at the very bottom of the field. If I understand it right it happens when the player drops a piece in that exact moment when survival_add_line() is already called but before if change_piece. Survival_add_line() shifts every line one to the top, then the clear_row function wants to delete the last row (which is now the second last) and it can't find the key in the last row to delete --> KeyError.
I have no idea how to solve this bug. One action is time dependent and the other one is player input dependent. Someone with an idea? Is there something in python working with mutable data which handles cases where one object gets changed at different times from different places?
CodePudding user response:
Instead of calling both statements with if, an if/elif block gets the job done! (change_piece can now be delayed by 1 frame, but that's not noticeable for the player)
Posted on behalf of the question asker