To many if statments I need help

Godot 4.2

I really want to know how to optimize my code I know it working is the thing that matters but this is awful to type and it looks atrocious and I have no clue how else to do it

it’s an inventory script if you could not tell

extends Control

@export var Sl1 = 0
@export var Sl2 = 0
@export var Sl3 = 0
@export var Sl4 = 0
@export var Sl5 = 0
@export var Sl6 = 0
@export var Sl7 = 0
@export var Sl8 = 0
@export var Sl9 = 0

@export var Slot1item = "nothing"
@export var Slot2item = "nothing"
@export var Slot3item = "nothing"
@export var Slot4item = "nothing"
@export var Slot5item = "nothing"
@export var Slot6item = "nothing"
@export var Slot7item = "nothing"
@export var Slot8item = "nothing"
@export var Slot9item = "nothing"

@onready var StoneTex = preload("res://Sprites/stone.png")
@onready var CopperTex = preload("res://Sprites/Copper.png")
@onready var IronTex = preload("res://Sprites/iron.png")
@onready var CoalTex = preload("res://Sprites/coal.png")
@onready var SilverTex = preload("res://Sprites/silverore.png")
@onready var GoldTex = preload("res://Sprites/gold .png")
@onready var SulferTex = preload("res://Sprites/Sulfurclump.png")
@onready var JadeTex = preload("res://Sprites/Jade.png")
@onready var BismuthTex = preload("res://Sprites/Bismite.png")
@onready var RubyTex = preload("res://Sprites/ruby.png")

@onready var IronBarTex = preload("res://Sprites/iron ingot.png")





func Item_Type(atlas_coord):
	
	var stone = atlas_coord.y < 5
	var copper = atlas_coord.y < 8 and atlas_coord.y > 4
	var iron = atlas_coord.y < 11 and atlas_coord.y > 7
	var coal = atlas_coord.y < 14 and atlas_coord.y > 10
	var silver = atlas_coord.y < 17 and atlas_coord.y > 13
	var gold = atlas_coord.y < 20 and atlas_coord.y > 16
	var sulfer = atlas_coord.y < 23 and atlas_coord.y > 19
	var jade = atlas_coord.y < 25 and atlas_coord.y > 22
	var bismuth = atlas_coord.y < 27 and atlas_coord.y > 24
	var ruby = atlas_coord.y < 29 and atlas_coord.y > 26
	
	
	var item = "nothing"
	
	if stone:
		item = "Stone"
		Item_Give(item)
	if copper:
		item = "Copper"
		Item_Give(item)
	if iron:
		item = "Iron"
		Item_Give(item)
	if coal:
		item = "Coal"
		Item_Give(item)
	if silver:
		item = "Silver"
		Item_Give(item)
	if gold:
		item = "Gold"
		Item_Give(item)
	if sulfer:
		item = "Sulfer"
		Item_Give(item)
	if jade:
		item = "Jade"
		Item_Give(item)
	if bismuth:
		item = "Bismuth"
		Item_Give(item)
	if ruby:
		item = "Ruby"
		Item_Give(item)
func Item_Give(item):
	
	var Slot1Filled = $R1SL1/Label.visible
	var Slot2Filled = $R1SL2/Label.visible
	var Slot3Filled = $R1SL3/Label.visible
	var Slot4Filled = $R1SL4/Label.visible
	var Slot5Filled = $R1SL5/Label.visible
	var Slot6Filled = $R1SL6/Label.visible
	var Slot7Filled = $R1SL7/Label.visible
	var Slot8Filled = $R1SL8/Label.visible
	var Slot9Filled = $R1SL9/Label.visible
	
	if Slot1Filled == false:
		$R1SL1/Label.visible = true
		Sl1 = Sl1 + 1
		$R1SL1/Label.text = str(Sl1)
		if item == "Stone":
			$R1SL1.icon = StoneTex
			Slot1item = "Stone"
		if item == "Copper":
			$R1SL1.icon = CopperTex
			Slot1item = "Copper"
		if item == "Iron":
			$R1SL1.icon = IronTex
			Slot1item = "Iron"
		if item == "Coal":
			$R1SL1.icon = CoalTex
			Slot1item = "Coal"
		if item == "Silver":
			$R1SL1.icon = SilverTex
			Slot1item = "Silver"
		if item == "Gold":
			$R1SL1.icon = GoldTex
			Slot1item = "Gold"
		if item == "Sulfer":
			$R1SL1.icon = SulferTex
			Slot1item = "Sulfer"
		if item == "Jade":
			$R1SL1.icon = JadeTex
			Slot1item = "Jade"
		if item == "Bismuth":
			$R1SL1.icon = BismuthTex
			Slot1item = "Bismuth"
		if item == "Ruby":
			$R1SL1.icon = RubyTex
			Slot1item = "Ruby"
	elif Slot1item == item:
		Sl1 = Sl1 + 1
		$R1SL1/Label.text = str(Sl1)
	elif Slot2Filled == false:
		$R1SL2/Label.visible = true
		Sl2 = Sl2 + 1
		$R1SL2/Label.text = str(Sl2)
		if item == "Stone":
			$R1SL2.icon = StoneTex
			Slot2item = "Stone"
		if item == "Copper":
			$R1SL2.icon = CopperTex
			Slot2item = "Copper"
		if item == "Iron":
			$R1SL2.icon = IronTex
			Slot2item = "Iron"
		if item == "Coal":
			$R1SL2.icon = CoalTex
			Slot2item = "Coal"
		if item == "Silver":
			$R1SL2.icon = SilverTex
			Slot2item = "Silver"
		if item == "Gold":
			$R1SL2.icon = GoldTex
			Slot2item = "Gold"
		if item == "Sulfer":
			$R1SL2.icon = SulferTex
			Slot2item = "Sulfer"
		if item == "Jade":
			$R1SL2.icon = JadeTex
			Slot2item = "Jade"
		if item == "Bismuth":
			$R1SL2.icon = BismuthTex
			Slot2item = "Bismuth"
		if item == "Ruby":
			$R1SL2.icon = RubyTex
			Slot2item = "Ruby"
	elif Slot2item == item:
		Sl2 = Sl2 + 1
		$R1SL2/Label.text = str(Sl2)
	elif Slot3Filled == false:
		$R1SL3/Label.visible = true
		Sl3 = Sl3 + 1
		$R1SL3/Label.text = str(Sl3)
		if item == "Stone":
			$R1SL3.icon = StoneTex
			Slot3item = "Stone"
		if item == "Copper":
			$R1SL3.icon = CopperTex
			Slot3item = "Copper"
		if item == "Iron":
			$R1SL3.icon = IronTex
			Slot3item = "Iron"
		if item == "Coal":
			$R1SL3.icon = CoalTex
			Slot3item = "Coal"
		if item == "Silver":
			$R1SL3.icon = SilverTex
			Slot3item = "Silver"
		if item == "Gold":
			$R1SL3.icon = GoldTex
			Slot3item = "Gold"
		if item == "Sulfer":
			$R1SL3.icon = SulferTex
			Slot3item = "Sulfer"
		if item == "Jade":
			$R1SL3.icon = JadeTex
			Slot3item = "Jade"
		if item == "Bismuth":
			$R1SL3.icon = BismuthTex
			Slot3item = "Bismuth"
		if item == "Ruby":
			$R1SL3.icon = RubyTex
			Slot3item = "Ruby"
	elif Slot3item == item:
		Sl3 = Sl3 + 1
		$R1SL3/Label.text = str(Sl3)
	elif Slot4Filled == false:
		$R1SL4/Label.visible = true
		Sl4 = Sl4 + 1
		$R1SL4/Label.text = str(Sl4)
		if item == "Stone":
			$R1SL4.icon = StoneTex
			Slot4item = "Stone"
		if item == "Copper":
			$R1SL4.icon = CopperTex
			Slot4item = "Copper"
		if item == "Iron":
			$R1SL4.icon = IronTex
			Slot4item = "Iron"
		if item == "Coal":
			$R1SL4.icon = CoalTex
			Slot4item = "Coal"
		if item == "Silver":
			$R1SL4.icon = SilverTex
			Slot4item = "Silver"
		if item == "Gold":
			$R1SL4.icon = GoldTex
			Slot4item = "Gold"
		if item == "Sulfer":
			$R1SL4.icon = SulferTex
			Slot4item = "Sulfer"
		if item == "Jade":
			$R1SL4.icon = JadeTex
			Slot4item = "Jade"
		if item == "Bismuth":
			$R1SL4.icon = BismuthTex
			Slot4item = "Bismuth"
		if item == "Ruby":
			$R1SL4.icon = RubyTex
			Slot4item = "Ruby"
	elif Slot4item == item:
		Sl4 = Sl4 + 1
		$R1SL4/Label.text = str(Sl4)
	elif Slot5Filled == false:
		$R1SL5/Label.visible = true
		Sl5 = Sl5 + 1
		$R1SL5/Label.text = str(Sl5)
		if item == "Stone":
			$R1SL5.icon = StoneTex
			Slot5item = "Stone"
		if item == "Copper":
			$R1SL5.icon = CopperTex
			Slot5item = "Copper"
		if item == "Iron":
			$R1SL5.icon = IronTex
			Slot5item = "Iron"
		if item == "Coal":
			$R1SL5.icon = CoalTex
			Slot5item = "Coal"
		if item == "Silver":
			$R1SL5.icon = SilverTex
			Slot5item = "Silver"
		if item == "Gold":
			$R1SL5.icon = GoldTex
			Slot5item = "Gold"
		if item == "Sulfer":
			$R1SL5.icon = SulferTex
			Slot5item = "Sulfer"
		if item == "Jade":
			$R1SL5.icon = JadeTex
			Slot5item = "Jade"
		if item == "Bismuth":
			$R1SL5.icon = BismuthTex
			Slot5item = "Bismuth"
		if item == "Ruby":
			$R1SL5.icon = RubyTex
			Slot5item = "Ruby"
	elif Slot5item == item:
		Sl5 = Sl5 + 1
		$R1SL5/Label.text = str(Sl5)
	elif Slot6Filled == false:
		$R1SL6/Label.visible = true
		Sl6 = Sl6 + 1
		$R1SL6/Label.text = str(Sl6)
		if item == "Stone":
			$R1SL6.icon = StoneTex
			Slot6item = "Stone"
		if item == "Copper":
			$R1SL6.icon = CopperTex
			Slot6item = "Copper"
		if item == "Iron":
			$R1SL6.icon = IronTex
			Slot6item = "Iron"
		if item == "Coal":
			$R1SL6.icon = CoalTex
			Slot6item = "Coal"
		if item == "Silver":
			$R1SL6.icon = SilverTex
			Slot6item = "Silver"
		if item == "Gold":
			$R1SL6.icon = GoldTex
			Slot6item = "Gold"
		if item == "Sulfer":
			$R1SL6.icon = SulferTex
			Slot6item = "Sulfer"
		if item == "Jade":
			$R1SL6.icon = JadeTex
			Slot6item = "Jade"
		if item == "Bismuth":
			$R1SL6.icon = BismuthTex
			Slot6item = "Bismuth"
		if item == "Ruby":
			$R1SL6.icon = RubyTex
			Slot6item = "Ruby"
	elif Slot6item == item:
		Sl6 = Sl6 + 1
		$R1SL6/Label.text = str(Sl6)
	elif Slot7Filled == false:
		$R1SL7/Label.visible = true
		Sl7 = Sl7 + 1
		$R1SL7/Label.text = str(Sl7)
		if item == "Stone":
			$R1SL7.icon = StoneTex
			Slot7item = "Stone"
		if item == "Copper":
			$R1SL7.icon = CopperTex
			Slot7item = "Copper"
		if item == "Iron":
			$R1SL7.icon = IronTex
			Slot7item = "Iron"
		if item == "Coal":
			$R1SL7.icon = CoalTex
			Slot7item = "Coal"
		if item == "Silver":
			$R1SL7.icon = SilverTex
			Slot7item = "Silver"
		if item == "Gold":
			$R1SL7.icon = GoldTex
			Slot7item = "Gold"
		if item == "Sulfer":
			$R1SL7.icon = SulferTex
			Slot7item = "Sulfer"
		if item == "Jade":
			$R1SL7.icon = JadeTex
			Slot7item = "Jade"
		if item == "Bismuth":
			$R1SL7.icon = BismuthTex
			Slot7item = "Bismuth"
		if item == "Ruby":
			$R1SL7.icon = RubyTex
			Slot7item = "Ruby"
	elif Slot7item == item:
		Sl7 = Sl7 + 1
		$R1SL7/Label.text = str(Sl7)
	elif Slot8Filled == false:
		$R1SL8/Label.visible = true
		Sl8 = Sl8 + 1
		$R1SL8/Label.text = str(Sl8)
		if item == "Stone":
			$R1SL8.icon = StoneTex
			Slot8item = "Stone"
		if item == "Copper":
			$R1SL8.icon = CopperTex
			Slot8item = "Copper"
		if item == "Iron":
			$R1SL8.icon = IronTex
			Slot8item = "Iron"
		if item == "Coal":
			$R1SL8.icon = CoalTex
			Slot8item = "Coal"
		if item == "Silver":
			$R1SL8.icon = SilverTex
			Slot8item = "Silver"
		if item == "Gold":
			$R1SL8.icon = GoldTex
			Slot8item = "Gold"
		if item == "Sulfer":
			$R1SL8.icon = SulferTex
			Slot8item = "Sulfer"
		if item == "Jade":
			$R1SL8.icon = JadeTex
			Slot8item = "Jade"
		if item == "Bismuth":
			$R1SL8.icon = BismuthTex
			Slot8item = "Bismuth"
		if item == "Ruby":
			$R1SL8.icon = RubyTex
			Slot8item = "Ruby"
	elif Slot8item == item:
		Sl8 = Sl8 + 1
		$R1SL8/Label.text = str(Sl8)
	elif Slot9Filled == false:
		$R1SL9/Label.visible = true
		Sl9 = Sl9 + 1
		$R1SL9/Label.text = str(Sl9)
		if item == "Stone":
			$R1SL9.icon = StoneTex
			Slot9item = "Stone"
		if item == "Copper":
			$R1SL9.icon = CopperTex
			Slot9item = "Copper"
		if item == "Iron":
			$R1SL9.icon = IronTex
			Slot9item = "Iron"
		if item == "Coal":
			$R1SL9.icon = CoalTex
			Slot9item = "Coal"
		if item == "Silver":
			$R1SL9.icon = SilverTex
			Slot9item = "Silver"
		if item == "Gold":
			$R1SL9.icon = GoldTex
			Slot9item = "Gold"
		if item == "Sulfer":
			$R1SL9.icon = SulferTex
			Slot9item = "Sulfer"
		if item == "Jade":
			$R1SL9.icon = JadeTex
			Slot9item = "Jade"
		if item == "Bismuth":
			$R1SL9.icon = BismuthTex
			Slot9item = "Bismuth"
		if item == "Ruby":
			$R1SL9.icon = RubyTex
			Slot9item = "Ruby"
	elif Slot9item == item:
		Sl9 = Sl9 + 1
		$R1SL9/Label.text = str(Sl9)
	else:
		pass

first, you have related data: e.g. “coal” and CoalTex
you can organize your data into a smaller package

enum {
	STONE, COPPER, IRON, COAL,
	SILVER, GOLD, SULFER, JADE,
	BISMUTH, RUBY,
	MATERIAL_COUNT
}

var materials = {
	STONE:{"name":"stone", "icon": StoneTex},
	COPPER:{"name":"copper", "icon":CopperTex},
	IRON:{"name":"iron", "icon":IronTex},
	COAL:{"name":"coal", "icon":CoalTex},
	SILVER:{"name":"silver", "icon":SilverTex},
	GOLD:{"name":"gold", "icon":GoldTex},
	SULFER:{"name":"sulfer", "icon":SulferTex},
	JADE:{"name":"jade", "icon":JadeTex},
	BISMUTH:{"name":"bismuth", "icon":BismuthTex},
	RUBY:{"name":"ruby", "icon":RubyTex},
}

Then select the resources in item_type function.
although sometimes its not possible to get rid of all if statements. you can leverage if/elif to handle boundaries though


func Item_Type(atlas_coord):
	var type = MATERIAL_COUNT # use count for validity check
	if atlas_coord.y < 5:
		type = STONE
	elif atlas_coord.y < 8:
		type = COPPER
	elif atlas_coord.y < 11:
		type = IRON
	elif atlas_coord.y < 14:
		type = COAL
	elif atlas_coord.y < 17:
		type = SILVER
	elif atlas_coord.y < 20:
		type = GOLD
	elif atlas_coord.y < 23:
		type = SULFER
	elif atlas_coord.y < 25:
		type = JADE
	elif atlas_coord.y < 27:
		type = BISMUTH
	elif atlas_coord.y < 29:
		type = RUBY
	else:
		printerr("Atlas coordinate out of range of materials!")

	var item = {}
	if type < MAX_MATERIALS:
		item = materials[type]
	Item_Give(item)

then in your item_give function you can collapse the slot resource assignment like this. We saved on if statements by leveraging past logic and stored them into the item data.

func Item_Give(item):
	if item.is_empty():
		return
...
	if Slot1Filled == false:
		$R1SL1/Label.visible = true
		Sl1 = Sl1 + 1
		$R1SL1/Label.text = str(Sl1)
		$R1SL1.icon = item.icon
		Slot1item = item.name
	elif Slot1item == item.name:
		Sl1 = Sl1 + 1
		$R1SL1/Label.text = str(Sl1)
	elif Slot2Filled == false:
		$R1SL2/Label.visible = true
		Sl2 = Sl2 + 1
		$R1SL2/Label.text = str(Sl2)
		$R1SL2.icon = item.icon
		Slot2item = item.name
	elif Slot2item == item.name:
		Sl2 = Sl2 + 1
		$R1SL2/Label.text = str(Sl2)
	... # etc

You may be able to collapse your slots and labels but I’ll leave that a challenge for you.

3 Likes

There’s a lot going on here, but overall always consider structuring your data such that it minimises repetition, enables iteration and promotes re-usability. This should generally result in code that more easily scales and is easier to manage/read.

For example your Item_Type logic and dependent information could be compressed down to:

@onready var items = {
	"Stone": {"texture": preload("res://Sprites/stone.png"), "min": 0, "max": 4},
	"Copper": {"texture": preload("res://Sprites/Copper.png"), "min": 5, "max": 7},
	"Iron": {"texture": preload("res://Sprites/iron.png"), "min": 8, "max": 10},
	"Coal": {"texture": preload("res://Sprites/coal.png"), "min": 11, "max": 13},
	"Silver": {"texture": preload("res://Sprites/silverore.png"), "min": 14, "max": 16},
	"Gold": {"texture": preload("res://Sprites/gold.png"), "min": 17, "max": 19},
	"Sulfer": {"texture": preload("res://Sprites/Sulfurclump.png"), "min": 20, "max": 22},
	"Jade": {"texture": preload("res://Sprites/Jade.png"), "min": 23, "max": 25},
	"Bismuth": {"texture": preload("res://Sprites/Bismite.png"), "min": 26, "max": 28},
	"Ruby": {"texture": preload("res://Sprites/ruby.png"), "min": 29, "max": 31}
}


func Item_Type(atlas_coord) -> void:
	for name in items.keys():
		if atlas_coord.y >= items[name]["min"] and atlas_coord.y <= items[name]["max"]:
			Item_Give(name)

Here the many individual variables and separate checks have been refactored into a single data table (a Dictionary) containing the same information without repetition, and then a for loop that iterates over this table, running the atlas_coord lookup for each element in the Dictionary (~55 rows down to ~17).

The Item_Type function now just loops through all the ‘keys’ in the dictionary (for name in items.keys() which will give you [“Stone”,“Copper”,“Iron”…]) and checks if the y value of atlas_coord is in the min and max range of an item. When a match is found, it calls Item_Give with the name of the item.

This means if you ever need to add an item, you just add one new row to the items dictionary, instead of 4 new rows to the Item_Type function. Pulling your information into a separate dictionary also makes this re-usable to other functions if necessary.

The Item_Give function can be refactored in essentially the same way, creating a ‘slots’ dictionary where the key is just a number representing the slot number, then each row is contains the count, node reference, a reference to what item is associated, and maybe the label.

3 Likes

First Thank you this is so much better than what I was doing but I am having trouble understanding what MATERIAL_COUNT and MAX_MATERIAL are for?

I might have made a typo, i changed names a few times and missed refactoring.

The name i landed on was MATERIAL_COUNT, AS MAX_MATERIAL was a little vague and confusing.

But MATERIAL_COUNT is meant to be placed at the end of the enumeration and can be checked to make sure you are not passing a value out of range of range.

enum {
ROCK,  # 0
PAPER, # 1
SCISSOR, # 2
HAND_SIGN_COUNT # 3
}

func _ready()
   attack(463763355)

func attack(hand:int):
  If hand < HAND_SIGN_COUNT:
     return # invalid hand

  If hand == ROCK:
    ...
  ...

We can technically pass any number but we dont have code to handle it so we can gate keep.

But if we want to add a new attack and keep HAND_SIGN_COUNT as the last element in the enum:

enum {
ROCK,  # 0
PAPER, # 1
SCISSOR, # 2
FIRE, #3
ICE, #4
WIND, #5
HAND_SIGN_COUNT # 6
}

It automatically gets updated and we can add new features and still check if the attack is within range of defined behaviors.

Basically its defensive programming to prevent bugs

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