aStar implementation with todos

This commit is contained in:
Jonas Mucke
2020-04-19 10:18:22 +02:00
parent 3dc9b88237
commit 13bdabe156
4 changed files with 266 additions and 102 deletions

208
src/Overlap/AI/AI_Hero.gd Normal file
View File

@@ -0,0 +1,208 @@
extends Node
const PrioQueue = preload("prio_queue.gd") # Relative pat
enum{
BOSS,
TORCH,
MINION,
RED,
BLUE,
GREEN,
HEART,
BONFIRE,
BARREL,
TERMINAL_SYMBOL
}
enum{
LENGTH,
WAY
}
enum{
DAMAGE,
SLOW,
WALL,
FIELD
}
enum{
STEP,
ROLL,
NOTHING
}
var Grid = []
var used_Flags = []
var numbers = [0,0,0,0,0,0,0,0,0]
var prios = [7,6,5,4,3,2,0,0,4]
var totalPrioTurn = 0
var executesTurn = false
var abortProb = 0.01
#calculates the sum of all present prios
func calcTotalPrio():
var sum = 0
var i = BOSS
while i != TERMINAL_SYMBOL:
if(numbers[i]>0):
sum += prios[i]
i=i+1
return sum
#calculates the relative porio
func calcRelPrio(index, sum):
return prios[index]/sum
#calucaltes the prio table of all enemies[0,1)
func calcPrioTable():
var table = [0,0,0,0,0,0,0,0,0]
var lower = 0
var sum = calcTotalPrio()
var i = 0;
while i != TERMINAL_SYMBOL:
lower += calcRelPrio(i, sum)
table[i] = lower
i = i+1
return table
#updates heart and bonfire prio
func adjustPrio(currentHealth, maxHealth):
var prioVal = 10 - (currentHealth/maxHealth)*10
var bonfire = prioVal
var hearts = prioVal -1
if(hearts < 0):
hearts = 0
prios[BONFIRE]=bonfire
prios[HEART]=hearts
#return the enemie which will be attacked
func calcEnemie():
var table = calcPrioTable()
var number = randf()
var i = TERMINAL_SYMBOL-1
while table[i] > number:
i=i-1
return i
#returns a move
func getMoveDescription(myPosition : Vector2, targetPositions):
var way = AStar(myPosition, targetPositions[0])
#TODO choose enemie with loest distance
return 0
func getFieldState(position):
pass
func getCost(position):
# var cost = 0
# for i in Feld[position.x][position.y]:
# match i:
# DAMAGE : cost += damage*prios[BONFIRE]*3
# SLOW : cost += 2
#
#return cost
return 0
#return an heurestic of distance
# curr - current position
# targ - atarget position
func h(curr, targ):
return min(abs(target[0]-curr[0]),abs(target[0]-curr[0]))
# currCost - currentCost
# position - position of the field to move to
func g(currCost, position):
return curr + getCost(position)
#returns the list of adjacent nodes
func adjacent(currentPosition):
var adj := []
#adj.append([STEP, Vector2(0,0)])
var p = currentPosition
var pot_adj_step = [[p[0]-1, p[1]-1], [p[0]-1, p[1]-0], [p[0]-1, p[1]+1],
[p[0]+0, p[1]-1], [p[0]+0, p[1]+1],
[p[0]+1, p[1]-1], [p[0]+1, p[1]+0], [p[0]+1, p[1]+1]]
var pot_adj_roll = [[p[0]-2, p[1]-2], [p[0]-2, p[1]-0], [p[0]-2, p[1]+2],
[p[0]+0, p[1]-2], [p[0]+0, p[1]+2],
[p[0]+2, p[1]-2], [p[0]+2, p[1]+0], [p[0]+2, p[1]+2]]
for next in pot_adj_step:
if(next[0]<0):
continue
if(next[0]>13):
continue
if(next[1]<0):
continue
if(next[1]>6):
continue
if(used_Flags[next[0]][next[1]]==true):
continue
if(Grid[next[0]][next[1]][0]!=WALL):
adj.append([STEP, Vector2(next[0],next[1])])
for next in pot_adj_roll:
if(next[0]<0):
continue
if(next[0]>13):
continue
if(next[1]<0):
continue
if(next[1]>6):
continue
if(used_Flags[next[0]][next[1]]==true):
continue
if(Grid[next[0]][next[1]][0]!=WALL):
adj.append([ROLL, Vector2(next[0],next[1])])
return adj
func AStar(source, target):
#swap rtarget and source, when target source istr reached, do inversxse step
# node layout [g+h(x), g(x), current, from, kind]
var tmp = source
source = target
target = tmp
var Q = PrioQueue.new()
Q.insert([0,0, [source[0], source[1]]])
while !Q.empty():
var node = Q.delMin()
#check if reached
if(node[2][0]==target[0] and node[2][1]==target[1]):
return [node[4], 0]#todo map movement]
#set flag
used_Flags[current[0]][current[1]] = true
var adj_list = adjacent(node[2])
for i in adj_ist:
var move_cost = 0
if(i[0]==STEP):
move_cost = 1
else:
rmove_cost = 2
return [NOTHING, 0]
# Called when the node enters the scene tree for the first time.
func _ready():
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

View File

@@ -0,0 +1,53 @@
extends Node
# Priority Queue implementation with binary heap
var heaplist
var currentSize
# node layout [g+h(x), g(x), position]
func _init():
heaplist = [[0]]
currentSize = 0
func percUp(i):
while floor(i / 2) > 0:
if heaplist[i][0] < heaplist[floor(i / 2)][0]:
var tmp = heaplist[floor(i / 2)]
heaplist[floor(i / 2)] = heaplist[i]
heaplist[i] = tmp
i = floor(i / 2)
func insert(k):
heaplist.append(k)
currentSize += 1
percUp(currentSize)
func percDown(i):
while (i * 2) <= currentSize:
var mc = minChild(i)
if heaplist[i][0] > heaplist[mc][0]:
var tmp = heaplist[i]
heaplist[i] = heaplist[mc]
heaplist[mc] = tmp
i = mc
func minChild(i):
if i * 2 + 1 > currentSize:
return i * 2
else:
if heaplist[i*2][0] < heaplist[i*2+1][0]:
return i * 2
else:
return i * 2 + 1
func delMin():
var retval = heaplist[1]
heaplist[1] = heaplist[currentSize]
heaplist.remove(currentSize - 1)
currentSize -= 1
percDown(1)
return retval
func empty():
return currentSize < 1

View File

@@ -1,97 +0,0 @@
extends Node
enum{
BOSS,
TORCH,
MINION,
RED,
BLUE,
GREEN,
HEART,
BONFIRE,
BARREL,
TERMINAL_SYMBOL
}
enum{
LENGTH,
WAY
}
var numbers = [0,0,0,0,0,0,0,0,0]
var prios = [7,6,5,4,3,2,0,0,4]
var totalPrioTurn = 0
var executesTurn = false
var abortProb = 0.01
func calcTotalPrio():
var sum = 0
var i = BOSS
while i != TERMINAL_SYMBOL:
if(numbers[i]>0):
sum += prios[i]
i=i+1
return sum
func calcRelPrio(index, sum):
return prios[index]/sum
func calcPrioTable():
var table = [0,0,0,0,0,0,0,0,0]
var lower = 0
var sum = calcTotalPrio()
var i = 0;
while i != TERMINAL_SYMBOL:
lower += calcRelPrio(i, sum)
table[i] = lower
i = i+1
return table
func adjustPrio(currentHealth, maxHealth):
var prioVal = 10 - (currentHealth/maxHealth)*10
var bonfire = prioVal
var hearts = prioVal -1
if(hearts < 0):
hearts = 0
prios[BONFIRE]=bonfire
prios[HEART]=hearts
func calcEnemie():
var table = calcPrioTable()
var number = randf()
var i = TERMINAL_SYMBOL-1
while table[i] > number:
i=i-1
return i
func getMoveDescription(myPosition : Vector2, targetPositions):
var way = AStar(myPosition, targetPositions[0])
for i in range(1, targetPositions.size()):
var tmp_way = AStar(myPosition, targetPositions[i])
if(tmp_way[LENGTH] < way[LENGTH]):
way = tmp_way
return way[WAY]
func h(curr, targ):
return sqrt(pow(curr,2)+pow(targ,2))
func h(curr, position):
func AStar(source, target):
pass
# Called when the node enters the scene tree for the first time.
func _ready():
prios[BOSS] = 1
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

View File

@@ -92,19 +92,19 @@ position = Vector2( 8.00002, -96 )
position = Vector2( -128, 16 )
[node name="Barrel7" parent="YSort" instance=ExtResource( 10 )]
position = Vector2( -56, 16 )
position = Vector2( -48, 16 )
[node name="Barrel8" parent="YSort" instance=ExtResource( 10 )]
position = Vector2( -72, 16 )
position = Vector2( -64, 16 )
[node name="Barrel9" parent="YSort" instance=ExtResource( 10 )]
position = Vector2( -88, 16 )
position = Vector2( -80, 16 )
[node name="Barrel10" parent="YSort" instance=ExtResource( 10 )]
position = Vector2( -104, 16 )
position = Vector2( -96, 16 )
[node name="Barrel11" parent="YSort" instance=ExtResource( 10 )]
position = Vector2( -120, 16 )
position = Vector2( -112, 16 )
[node name="Barrel2" parent="YSort" instance=ExtResource( 10 )]
position = Vector2( 8.00002, -48 )