mirror of
https://github.com/creyD/ludum_dare_46.git
synced 2026-06-17 07:30:19 +02:00
aStar implementation with todos
This commit is contained in:
208
src/Overlap/AI/AI_Hero.gd
Normal file
208
src/Overlap/AI/AI_Hero.gd
Normal 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
|
||||||
53
src/Overlap/AI/prio_queue.gd
Normal file
53
src/Overlap/AI/prio_queue.gd
Normal 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
|
||||||
@@ -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
|
|
||||||
@@ -92,19 +92,19 @@ position = Vector2( 8.00002, -96 )
|
|||||||
position = Vector2( -128, 16 )
|
position = Vector2( -128, 16 )
|
||||||
|
|
||||||
[node name="Barrel7" parent="YSort" instance=ExtResource( 10 )]
|
[node name="Barrel7" parent="YSort" instance=ExtResource( 10 )]
|
||||||
position = Vector2( -56, 16 )
|
position = Vector2( -48, 16 )
|
||||||
|
|
||||||
[node name="Barrel8" parent="YSort" instance=ExtResource( 10 )]
|
[node name="Barrel8" parent="YSort" instance=ExtResource( 10 )]
|
||||||
position = Vector2( -72, 16 )
|
position = Vector2( -64, 16 )
|
||||||
|
|
||||||
[node name="Barrel9" parent="YSort" instance=ExtResource( 10 )]
|
[node name="Barrel9" parent="YSort" instance=ExtResource( 10 )]
|
||||||
position = Vector2( -88, 16 )
|
position = Vector2( -80, 16 )
|
||||||
|
|
||||||
[node name="Barrel10" parent="YSort" instance=ExtResource( 10 )]
|
[node name="Barrel10" parent="YSort" instance=ExtResource( 10 )]
|
||||||
position = Vector2( -104, 16 )
|
position = Vector2( -96, 16 )
|
||||||
|
|
||||||
[node name="Barrel11" parent="YSort" instance=ExtResource( 10 )]
|
[node name="Barrel11" parent="YSort" instance=ExtResource( 10 )]
|
||||||
position = Vector2( -120, 16 )
|
position = Vector2( -112, 16 )
|
||||||
|
|
||||||
[node name="Barrel2" parent="YSort" instance=ExtResource( 10 )]
|
[node name="Barrel2" parent="YSort" instance=ExtResource( 10 )]
|
||||||
position = Vector2( 8.00002, -48 )
|
position = Vector2( 8.00002, -48 )
|
||||||
|
|||||||
Reference in New Issue
Block a user