Genetics System Help

Godot Version

Godot 4.6

Question

Hello! I’m attempting a test-run of a genetics system to see how I want to do it in my horse ranch game, but I’m struggling a bit with the code. It’s just a series of ColorRects and Labels in a menu, I want to see what systems might be necessary before I start messing with sprites and stuff. I’ve got the color mixing set up using a global dictionary of colors and lerp in the ‘foal creator’ code which works just fine, leg and face markings are determined by pick_random from a separate global dictionary of patterns (as the genes that control those aren’t well known so I’m determining them via rng instead of inheriting them) but then we get to the coat patterns. I have separate sections for the stallion and mare, and I’m trying to get the foal to then pull randomly from their results to decide what they inherit

stallion and mare body patterns code, for reference:

@onready var _coat_one: Label = $VBoxContainer/pat1
@onready var _coat_two: Label = $VBoxContainer/pat2
@onready var _coat_three: Label = $VBoxContainer/pat3
@onready var _coat_four: Label = $VBoxContainer/pat4

func _ready():
	var _patterns: Array = BodyPatterns.PATTERNS.keys()
	
func pick_random():
	_coat_one.text = BodyPatterns.PATTERNS.keys().pick_random()
	_coat_two.text = BodyPatterns.PATTERNS.keys().pick_random()
	_coat_three.text = BodyPatterns.PATTERNS.keys().pick_random()
	_coat_four.text = BodyPatterns.PATTERNS.keys().pick_random()

this is my foal code for the body patterns currently, dom for dominant gene and rec for recessive gene which are just sections of the menu:

@onready var _dad_dom_one: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat1"
@onready var _dad_dom_two: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat2"
@onready var _dad_rec_one: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat3"
@onready var _dad_rec_two: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat4"

@onready var _mom_dom_one: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat1"
@onready var _mom_dom_two: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat2"
@onready var _mom_rec_one: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat3"
@onready var _mom_rec_two: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat4"

@onready var _foal_dom_one: Label = $VBoxContainer/pat1
@onready var _foal_dom_two: Label = $VBoxContainer/pat2
@onready var _foal_rec_one: Label = $VBoxContainer/pat3
@onready var _foal_rec_two: Label = $VBoxContainer/pat4

func _ready():
	var _array: Array = [ _dad_dom_one, _dad_dom_two, _dad_rec_one, _dad_rec_two, _mom_dom_one, _mom_dom_two, _mom_rec_one, _mom_rec_two]
	
func pick_random(_array: Array):
	_foal_dom_one.text = _array.pick_random()
	_foal_dom_two.text = _array.pick_random()
	_foal_rec_one.text = _array.pick_random()
	_foal_rec_two.text = _array.pick_random()

except… nothing happens. the patterns section of the menu stays default, but I’m not getting errors either. It’s not returning the parent label defaults, just its own. I don’t really know what to do here, I’m still new to a lot of this and there’s a lot of stuff I don’t know. It’s been hard to find resources to help online either. Any tips?

Where are you calling your pick_random function?

oh yeah sorry I forgot to include that. It’s connected to a button press in the main container script for the foal section. same code I used for everyone, just with nodes changed, and it works on the other two so I haven’t been bothering with it. I double checked and the call for the foal’s coat section was missing but after adding it back I now get “invalid call to function ‘pick_random’ in base ‘(foal script)’. Expected 1 arguments.”

this is the whole code, if it matters

@onready var _name: PanelContainer = $VBoxContainer/name
@onready var _coatcolor: PanelContainer = $VBoxContainer/colors
@onready var _bodypatterns: PanelContainer = $VBoxContainer/coat
@onready var _leg_face_patterns: PanelContainer = $VBoxContainer/legface

@onready var _randomize_foal: Button = $VBoxContainer/VBoxContainer3/RandButton

func _ready():
	_randomize_foal.pressed.connect(on_randomize_foal_pressed)
	
func on_randomize_foal_pressed():
	_coatcolor.pick_random()
	_bodypatterns.pick_random()
	_leg_face_patterns.pick_random()
	_name.pick_random()

Your function expects an argument, an array. You have to pass an array when you call the function.

how would I go about fixing that?

You declared the function with an array as an argument, so you need to pass an array when calling it. If you want to call it without passing an array, remove the _array: Array from the function declaration.

I don’t know where your array is so I don’t know what’s the best way for your function to get a reference to it.

when I remove that it turns the whole pick_random section red saying that _array isn’t declared, that’s why I added it in the first place. I have the array just above, in the ready section because that’s how I have everything else set up. Should I just move it out of ready?

You’re declaring the array on ready so it can only be accessed in the context of ready. Declare it outside of ready and just set the value to it on ready.

In the other script you are declaring _patterns on ready but you never actually try to access that variable in the function. If you did, you’d get the same error for the same reason.

ah okay, thank you!

however now its telling me ‘invalid assignment of property or key ‘text’ with the value of type ‘label’ on a base object of type ‘label’ :thinking:

I added .text to the labels listed in the array, which got the rng working, but its only showing me the default text and not what the randomizer is supposed to be replacing it with. “rm” should be one of the two traits listed in the Mare’s recessive category, '“dm” should be one of her dominant traits, and “rd” should be one of the Stallion’s recessive traits.

Can you show what the code looks now after the changes?

extends PanelContainer

@onready var _dad_dom_one: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat1"
@onready var _dad_dom_two: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat2"
@onready var _dad_rec_one: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat3"
@onready var _dad_rec_two: Label = $"../../../dad/VBoxContainer/coat/VBoxContainer/pat4"

@onready var _mom_dom_one: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat1"
@onready var _mom_dom_two: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat2"
@onready var _mom_rec_one: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat3"
@onready var _mom_rec_two: Label = $"../../../mom/VBoxContainer/coat/VBoxContainer/pat4"

@onready var _foal_dom_one: Label = $VBoxContainer/pat1
@onready var _foal_dom_two: Label = $VBoxContainer/pat2
@onready var _foal_rec_one: Label = $VBoxContainer/pat3
@onready var _foal_rec_two: Label = $VBoxContainer/pat4

@onready var _array: Array = [ _dad_dom_one.text, _dad_dom_two.text, _dad_rec_one.text, _dad_rec_two.text, _mom_dom_one.text, _mom_dom_two.text, _mom_rec_one.text, _mom_rec_two.text]

	
func pick_random():
	_foal_dom_one.text = _array.pick_random()
	_foal_dom_two.text = _array.pick_random()
	_foal_rec_one.text = _array.pick_random()
	_foal_rec_two.text = _array.pick_random()

I think the issue is that you are getting the text values from the labels on ready. I assume that on ready the label texts have not yet been changed from the default. The array is never updated when the texts change in the labels.
So instead of making an array of the text values, remove the .text from the array elements so you’ll have an array of label references.
Then, put the .text in the function like this:

@onready var _array: Array = [ _dad_dom_one, _dad_dom_two, (...)]

func pick_random():
    _foal_dom_one.text = _array.pick_random().text
    _foal_dom_two.text = _array.pick_random().text
    _foal_rec_one.text = _array.pick_random().text
    _foal_rec_two.text = _array.pick_random().text

yes, that works! thank you!

1 Like