-2

Im trying to make my first Tkinter project and decided on a Chess game. Ive written most of the basic program but when I tried to execute the pre-programmed pawn movements the pawn images don't change even tho it seems like the module registers the movement.

Here is all the details:

The widget structure is just one frame with label widgets placed in a grid representing a classical chess board.

My program has two classes, boot and move. Both is called (instantiated?) directly. Boot creates the board layout and also the object called game containing two nested dictionaries game.pawns and game.squares .

game.pawns

game.pawns contains information about each pawn such as position ect and is reached like: game.pawns['B_Bishop_C']['pos'] where first letter is the color and the last letter is the horizontal starting position. More details about dictionary keys and values are the code (line 25) found in git.

game.squares

game.squares contains information about the squares such as if it is occupied and by which pawn. Also very importantly it contains the label widget with key ['wdgt']. Each square is reached with a string: '0 to 7' + 'A to H' so regular chess positioning but with one less index. Ex Upper left '0A', down right '7H'.

Ex: game.squares['0B']['widget'] would access the label widget where a black knight is standing (white at bottom).

Problem

So back to the problem: For some reason when I try to .config the label to change the image it doesn't change even tho the imaged shows as it is added with the winfo command.

Code

Here is the code where called when I move a pawn to a empty square(where the error is)

img = game.pawns[self.current_pawn]['img']
game.squares[pos]['wdgt'].image = img
game.squares[pos]['wdgt'].config(image=img)
#replace image of target square to the new pawn

game.squares[game.pawns[self.current_pawn]['pos']]['occ'] = None
#Changes occ of old square

game.pawns[self.current_pawn]['pos'] = pos                         
#changes moving pawn attribute position to new

game.squares[game.pawns[self.current_pawn]['pos']]['wdgt'].config(image = '')       
#remvoes pawn from old square

game.squares[pos]['occ'] = pawn
#Changes occ of new square

Here is my GitHub:

https://gits-15.sys.kth.se/markusjs/Chess

Note:

Code from above is around line 250.

self.current_pawn is in same form as dict key for game.pawns

To run the code PIL and Tkitner is needed.

Also pawns must be in the folder with the relative path given when creating the pawns at line 122-149

From line 300 and down is only pawn movement code.

There are probably some undiscoverd problems in the program

Things I tried:

Referencing image.

Using image without alpha (transparency).

Tkinter Label does not show Image

All help is appreciated.

  • Your repository is not publicly accessible. – Paul M. Jan 27 '22 at 23:06
  • 1
    Please [edit] your question to include a [mcve], and try to create an example that doesn't depend on a large number of external images. – Bryan Oakley Jan 27 '22 at 23:07
  • Sorry for the troubles. I've made the repository public. If I was to make a minimal reproducible example I would still have to include basically the whole program to mimic the same senario so I don't thinks it's especially effective here. You can paste the code from my GitHub now since it public:) – johnsonswegmark Jan 28 '22 at 00:48

1 Answers1

0

In your move function in line 315, you are reassigning the game.pawns dictionary with the new dictionary. But the original dictionary is not being passed to that function!

def move(self, event):
    if self.is_white:
        pawn = 'W_' + self.current_pawn[1:]  # piece of current player color (whites or blacks)
    else:
        pawn = 'B_' + self.current_pawn[1:]

    pos = str(self.row) + chr(self.col + ord('A')) #position of the square

    # Save the current selected pawn in a variable to pass it to aftermove (with its new position) method

    img = game.pawns[self.current_pawn]['img'] #image of moving pawn is saved on attribute img 

    game.squares[pos]['wdgt'].image = img   #widget reference as key ('0B') and then attribute image from widget (tkinter label). No change done to image on widget 
    
    game.squares[pos]['wdgt'].config(image=img) #config widget gets image from attribute 

    game.squares[game.pawns[self.current_pawn]['pos']]['occ'] = None #square where the pawn is currently on gets empty occ (None)

    game.pawns[self.current_pawn]['pos'] = pos #dict key for moving pawn gets new position (position of new square)

    game.squares[game.pawns[self.current_pawn]['pos']]['wdgt'].config(image = '') #config widget on label of new square and get rid of image

The game.pawns dictionary doesn't have the key of the pawn you are moving. Since you are reassigning the dict itself in this function, it would not work anyway. You need to pass that dict along with the new position of your pawn:

def move(self, event):
    if self.is_white:
        pawn = 'W_' + self.current_pawn[1:]  # piece of current player color (whites or blacks)
    else:
        pawn = 'B_' + self.current_pawn[1:]

    pos = str(self.row) + chr(self.col + ord('A')) #position of the square

    # Save the current selected pawn in a variable to pass it to aftermove (with its new position) method

    img = game.pawns[self.current_pawn]['img'] #image of moving pawn is saved on attribute img 

    game.squares[pos]['wdgt'].image = img   #widget reference as key ('0B') and then attribute image from widget (tkinter label). No change done to image on widget 
    
    game.squares[pos]['wdgt'].config(image=img) #config widget gets image from attribute 

    game.squares[game.pawns[self.current_pawn]['pos']]['occ'] = None #square where the pawn is currently on gets empty occ (None)

    temp = game.pawns   #dict dictionary object holding all pawn info such as position ect gets saved in temp

    game.pawns[self.current_pawn]['pos'] = pos #dict key for moving pawn gets new position (position of new square)

    game.squares[game.pawns[self.current_pawn]['pos']]['wdgt'].config(image = '') #config widget on label of new square and get rid of image

    aftermove(temp, pawn, pos)

Now the dict is passed along with the new position of your selected pawn:

def aftermove(dict, piece, pos):  #takes dict with piece and its old position as input and the targets postion as a string 'A1' 
    if self.is_white:
        pawn = 'W_' + self.current_pawn[1:]  # piece of current player color (whites or blacks)
    else:
        pawn = 'B_' + self.current_pawn[1:]

    game.squares[game.pawns[self.current_pawn]['pos']]['occ'] = None #square where the pawn is currently on gets empty occ (None)

    temp = game.pawns   #dict dictionary object holding all pawn info such as position ect gets saved in temp

    game.pawns[self.current_pawn]['pos'] = pos #dict key for moving pawn gets new position (position of new square)

    game.squares[game.pawns[self.current_pawn]['pos']]['wdgt'].config(image = '') #config widget on label of new square and get rid of image

     aftermove(temp, pawn, pos)  #after move function itself called again to retrace steps until no more pieces left to move hence no more recursion needed            

         return           #return to stop recursion looping which causes program to crash when it reaches the maximum recursion depth limit for the amount of pawns there are.
PJMan0300
  • 86
  • 5