mirror of
https://github.com/creyD/ludum_dare_46.git
synced 2026-06-11 21:22:22 +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 )
|
||||
|
||||
[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 )
|
||||
|
||||
Reference in New Issue
Block a user