-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathAgentManager.gd
160 lines (132 loc) · 4.61 KB
/
AgentManager.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
extends Node2D
export(PackedScene) var Agent
onready var TextBox = get_parent().get_node("Main_HUD/HUD/right_menu/SystemStats/TextOutput")
var rng = RandomNumberGenerator.new()
var dataFile:String = "./DATA.dat"
var POP_MAX:int = 128
var popCount:int = 0
var popLog:Dictionary = {} #format hash:[organisms born with this type, list of children counts, list of food counts]
var logFile:File = File.new()
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func arr_join(arr:Array, separator:String = "")->String:
var output:String = "";
for s in arr:
output += str(s) + separator
output = output.left( output.length() - separator.length() )
return output
func logOrg(sites:Array):
var key:String = arr_join(sites).sha256_text()
if key in popLog:
popLog[key][0] += 1
popLog[key][1] += 1
else:
popLog[key] = [1,1,[],[]]
func remOrg(sites:Array,offspring:int,food:int):
var key:String = arr_join(sites).sha256_text()
popLog[key][0] -= 1
popLog[key][2].append(offspring)
popLog[key][3].append(food)
#if popLog[key][0] == 0:
#popLog.erase(key)
func mean(array:Array)->float:
if len(array) == 0: return float('inf')
var sum:float = 0.0
for element in array:
sum += element
return sum / len(array)
func compareWithNull(val1:float, val2:float):
if val1 != null and val2 != null:
if val1 != val2:
return val1 > val2
else:
#signals a tie
return null
elif val1 == null and val2 != null:
return false
elif val1 != null and val2 == null:
return true
else:
return false
func customComparison(a:Array,b:Array)->bool:
var alife:int = a[1][0]
var blife:int = b[1][0]
var atot:int = a[1][1]
var btot:int = b[1][1]
var aoffs:Array = a[1][2]
var boffs:Array = b[1][2]
var afoods:Array = a[1][3]
var bfoods:Array = b[1][3]
if (alife > 0) == (blife > 0): #both alive or both dead (sort groups)
#this helper function lets you handle ties with ifs
var comp = compareWithNull(alife,blife)
if comp == null:
comp = compareWithNull(atot,btot)
if comp == null:
comp = compareWithNull(mean(afoods),mean(bfoods))
if comp == null:
comp = compareWithNull(mean(aoffs),mean(boffs))
return comp
else:
#one alive one dead, prefer alive
return alife > blife
func sortedDictionary(dict:Dictionary)->Array:
var items:Array = []
for key in dict.keys():
items.append([key,dict[key]])
items.sort_custom(self, "customComparison")
return items
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
if popCount < 1:
for _i in range(10):
var pos:Vector2 = Vector2(rng.randi_range(64, 3840-64),rng.randi_range(64, 2160-64))
handle_agent_spawn(pos)
var result:String = "Population Size: " + str(popCount) + "\n\nCount Total ID ave_Child ave_Food\n"
#for key in popLog.keys():
# result += str(popLog[key][0]) + " " + key.substr(0,7) + " " + str(mean(popLog[key][1])) + " " + str(mean(popLog[key][2])) + "\n"
var firstBreak:bool = false
for pair in sortedDictionary(popLog):
var key:String = pair[0]
var value:Array = pair[1]
if not firstBreak and value[0] == 0:
result += "\n"
firstBreak = true
result += str(value[0]) + " " + str(value[1]) + " " + key.substr(0,7) + " " + str(mean(value[2])).substr(0,6) + " " + str(mean(value[3])).substr(0,6) + "\n"
TextBox.text = result
#ItemList.add_item(result)
func handle_agent_birth(parent: Agent):
if popCount < POP_MAX:
popCount += 1
var child:Agent = Agent.instance()
add_child(child)
var parentHash:String = arr_join(parent.Genome.sites).sha256_text()
child.global_position = parent.global_position
var newGenomeSites:Array = parent.get_mutated_genome()
var childHash:String = arr_join(newGenomeSites).sha256_text()
child.on_birth(newGenomeSites)
#print(popCount, " \tBABY ", newGenomeSites)
logOrg(newGenomeSites)
fileWrite(parentHash+","+childHash)
func handle_agent_death(agent: Agent):
popCount -= 1
remOrg(agent.Genome.sites,agent.children_had_tracker,agent.food_eaten_tracker)
func handle_agent_spawn(pos: Vector2):
if popCount < POP_MAX:
popCount += 1
var agent_instance:Agent = Agent.instance()
add_child(agent_instance)
agent_instance.global_position = pos
agent_instance.on_spawn()
var childHash:String = arr_join(agent_instance.Genome.sites).sha256_text()
logOrg(agent_instance.Genome.sites)
fileWrite("null,"+childHash)
func fileWrite(line:String):
if logFile.file_exists(dataFile):
var _trash = logFile.open(dataFile,File.READ_WRITE)
else:
var _trash = logFile.open(dataFile,File.WRITE_READ)
logFile.seek_end()
logFile.store_line(line)
logFile.close()