Match not matching

Godot Version

Godot_v4.4.1-stable_win64

Question

VERY new programmer here, I thought I did something great already to learn by testing, but this code isn’t working like I wanted it to and I can’t understand why yet
Basically, whichever option between L, N and F I choose, (exported it to change it quickly) it always prints “There’s a mistake” instead of the requested “Health”

Earlier I had a “invalid index type string for a base of type array” error which isn’t showing up anymore, if that helps

enum Players {L, N, F}
@export var player: Players

func _ready(): 
	var player = {
		"L": 
				 {"Health": 30, "Atk": 50},
		"N": 
				 {"Health": 40, "Atk": 40},
		"F": 
				 {"Health": 50, "Atk": 30},
	}
	
	match player:
		player.L:
			print(player["L"]["Health"])
		player.N:
			print(player["N"]["Health"])
		player.F:
			print(player["F"]["Health"])
		_:
			print("There's a mistake")

The problem is that your exported enum variable called “player” is being completely overridden as soon as you enter the _ready() function, and you set it to be a dictionary instead.

A simple fix for this would be to rename the player inside the _ready() function to be something like player_stats, then reference it as such.

I don’t use GDScript much but try it like this:

enum Players {L, N, F}
@export var player: Players

func _ready():
    var player_stats = {
        "L": {"Health": 30, "Atk": 50},
        "N": {"Health": 40, "Atk": 40},
        "F": {"Health": 50, "Atk": 30},
    }

    match player:
        Players.L:
            print(player_stats["L"]["Health"])
        Players.N:
            print(player_stats["N"]["Health"])
        Players.F:
            print(player_stats["F"]["Health"])
        _:
            print("There's a mistake")
5 Likes

I just wanted to add that naming things clearly is really important. For example, the change @tibaverus suggested, renaming your dictionary to player_stats, really helps make the code easier to follow.

You might also consider renaming your player variable to something like current_player, and your Players enum to something more descriptive like AvailablePlayers, PlayerList, or PlayersOnTeam. For your enum values like L, N, and F, using full descriptive names is also a good idea. For instance:

enum AvailablePlayers { LEADER, NEUTRAL, FRIENDLY }

This makes your code much more readable (I have no idea what your L, N and F actually stand for).

match current_player:
    AvailablePlayers.LEADER:
        print(player_stats["LEADER"]["Health"])

It’s much clearer what’s going on, both now and when you come back to this code six months down the line. I’m only sharing this because you mentioned you’re new to coding, and I think this is really important for good code. I hope it helps!

PS I cannot tell you how many times I come back to my own code and think to myself “what on earth is that doing?” or “why have I done it like that?”. Clearer naming really helps to make code self explanatory so this does not happen quite so often (it still will though at times).

4 Likes

Technically the variable is not being overridden, it is being shadowed.
It ends in the same place in this example, but the reader should be aware that the class level variable still exists as it was defined and is accessible outside the scope of (in this case the _ready() function) the shadowing definition.
OP should be seeing a warning:
The local variable "player" is shadowing an already-declared variable at line x.

2 Likes

While this is true, I feel like for someone just starting off, this will just confuse them even more. What matter is that they should not name two different things the same.

3 Likes

Ohh now I get it! Thank you all for the quick and complete answers, I’ll try right away :slight_smile:

Just seconding what @pauldrewett said.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.