Optimizing is generally a waste of time unless you've determined that your code isn't meeting its speed requirements, and you've timed it to determine where it's bogging down. Getting it to work should be a much higher priority.
Making your code more legible, on the other hand, is always important. If your code looks messy now, while it's fresh in your mind, you may have trouble following it at all months from now. One way to write legible code is to break everything into separate methods, so that the bulk of your code looks like this:
func game():
make_board()
make_pieces()
make_player_1()
if two_players():
make_player_2()
display_game_is_ready()
# input goes through _input()
# Game will end when check_game_end()
# is called by timer.
Note that this is less optimized than doing everything in one, long method, but it's usually more important that you can read and follow it when you need to make changes.