예제 #1
0
파일: move.go 프로젝트: hilerchyn/haunts
func (exec *moveExec) measureCost(ent *game.Entity, g *game.Game) int {
	if len(exec.Path) == 0 {
		base.Error().Printf("Zero length path")
		return -1
	}
	if g.ToVertex(ent.Pos()) != exec.Path[0] {
		base.Error().Printf("Path doesn't begin at ent's position, %d != %d", g.ToVertex(ent.Pos()), exec.Path[0])
		return -1
	}
	graph := g.Graph(ent.Side(), true, nil)
	v := g.ToVertex(ent.Pos())
	cost := 0
	for _, step := range exec.Path[1:] {
		dsts, costs := graph.Adjacent(v)
		ok := false
		prev := v
		base.Log().Printf("Adj(%d):", v)
		for j := range dsts {
			base.Log().Printf("Node %d", dsts[j])
			if dsts[j] == step {
				cost += int(costs[j])
				v = dsts[j]
				ok = true
				break
			}
		}
		base.Log().Printf("%d -> %d: %t", prev, v, ok)
		if !ok {
			return -1
		}
	}
	return cost
}
예제 #2
0
파일: move.go 프로젝트: hilerchyn/haunts
func (a *Move) AiMoveToPos(ent *game.Entity, dst []int, max_ap int) game.ActionExec {
	base.Log().Printf("PATH: Request move to %v", dst)
	graph := ent.Game().Graph(ent.Side(), false, nil)
	src := []int{ent.Game().ToVertex(ent.Pos())}
	_, path := algorithm.Dijkstra(graph, src, dst)
	base.Log().Printf("PATH: Found path of length %d", len(path))
	ppx, ppy := ent.Pos()
	if path == nil {
		return nil
	}
	_, xx, yy := ent.Game().FromVertex(path[len(path)-1])
	base.Log().Printf("PATH: %d,%d -> %d,%d", ppx, ppy, xx, yy)
	if ent.Stats.ApCur() < max_ap {
		max_ap = ent.Stats.ApCur()
	}
	path = limitPath(ent, src[0], path, max_ap)
	_, xx, yy = ent.Game().FromVertex(path[len(path)-1])
	base.Log().Printf("PATH: (limited) %d,%d -> %d,%d", ppx, ppy, xx, yy)
	if len(path) <= 1 {
		return nil
	}
	var exec moveExec
	exec.SetBasicData(ent, a)
	exec.Path = path
	return &exec
}
예제 #3
0
파일: entity.go 프로젝트: RickDakan/haunts
func WaypointsFunc(me *game.Entity) lua.GoFunction {
	return func(L *lua.State) int {
		if !game.LuaCheckParamsOk(L, "Waypoints") {
			return 0
		}
		g := me.Game()
		L.NewTable()
		count := 0
		for _, wp := range g.Waypoints {
			if wp.Side != me.Side() {
				continue
			}
			count++
			L.PushInteger(count)
			L.NewTable()
			L.PushString("Name")
			L.PushString(wp.Name)
			L.SetTable(-3)
			L.PushString("Radius")
			L.PushNumber(wp.Radius)
			L.SetTable(-3)
			L.PushString("Pos")
			game.LuaPushPoint(L, int(wp.X), int(wp.Y))
			L.SetTable(-3)
			L.SetTable(-3)
		}
		return 1
	}
}
예제 #4
0
func (a *AoeAttack) AiBestTarget(ent *game.Entity, extra_dist int, spec AiAoeTarget) (x, y int, targets []*game.Entity) {
	ex, ey := ent.Pos()
	max := 0
	best_dist := 10000
	var bx, by int
	var radius int
	if a.Range > 0 {
		radius += a.Range
	}
	if extra_dist > 0 {
		radius += extra_dist
	}
	for x := ex - radius; x <= ex+radius; x++ {
		for y := ey - radius; y <= ey+radius; y++ {
			if !ent.HasLos(x, y, 1, 1) {
				continue
			}
			targets = a.getTargetsAt(ent.Game(), x, y)
			ok := true
			count := 0
			for i := range targets {
				if targets[i].Side() != ent.Side() {
					count++
				} else if ent.Side() == game.SideHaunt && spec == AiAoeHitMinionsOk {
					if targets[i].HauntEnt == nil || targets[i].HauntEnt.Level != game.LevelMinion {
						ok = false
					}
				} else if spec != AiAoeHitAlliesOk {
					ok = false
				}
			}
			dx := x - ex
			if dx < 0 {
				dx = -dx
			}
			dy := y - ey
			if dy < 0 {
				dy = -dy
			}
			dist := dx
			if dy > dx {
				dist = dy
			}
			if ok && (count > max || count == max && dist < best_dist) {
				max = count
				best_dist = dist
				bx, by = x, y
			}
		}
	}
	return bx, by, a.getTargetsAt(ent.Game(), bx, by)
}
예제 #5
0
파일: move.go 프로젝트: RickDakan/haunts
func (a *Move) findPath(ent *game.Entity, x, y int) {
	g := ent.Game()
	dst := g.ToVertex(x, y)
	if dst != a.dst || !a.calculated {
		a.dst = dst
		a.calculated = true
		src := g.ToVertex(a.ent.Pos())
		graph := g.Graph(ent.Side(), true, nil)
		cost, path := algorithm.Dijkstra(graph, []int{src}, []int{dst})
		if len(path) <= 1 {
			return
		}
		a.path = algorithm.Map(path, [][2]int{}, func(a interface{}) interface{} {
			_, x, y := g.FromVertex(a.(int))
			return [2]int{int(x), int(y)}
		}).([][2]int)
		a.cost = int(cost)

		if path_tex != nil {
			pix := path_tex.Pix()
			for i := range pix {
				for j := range pix[i] {
					pix[i][j] = 0
				}
			}
			current := 0.0
			for i := 1; i < len(a.path); i++ {
				src := g.ToVertex(a.path[i-1][0], a.path[i-1][1])
				dst := g.ToVertex(a.path[i][0], a.path[i][1])
				v, cost := graph.Adjacent(src)
				for j := range v {
					if v[j] == dst {
						current += cost[j]
						break
					}
				}
				pix[a.path[i][1]][a.path[i][0]] += byte(current)
			}
			path_tex.Remap()
		}
	}
}
예제 #6
0
파일: move.go 프로젝트: hilerchyn/haunts
func (a *Move) findPath(ent *game.Entity, x, y int) {
	g := ent.Game()
	dst := g.ToVertex(x, y)
	if dst != a.dst || !a.calculated {
		a.dst = dst
		a.calculated = true
		src := g.ToVertex(a.ent.Pos())
		graph := g.Graph(ent.Side(), true, nil)
		cost, path := algorithm.Dijkstra(graph, []int{src}, []int{dst})
		if len(path) <= 1 {
			return
		}
		a.path = algorithm.Map(path, [][2]int{}, func(a interface{}) interface{} {
			_, x, y := g.FromVertex(a.(int))
			return [2]int{int(x), int(y)}
		}).([][2]int)
		a.cost = int(cost)
		a.drawPath(ent, g, graph, src)
	}
}
예제 #7
0
파일: move.go 프로젝트: hilerchyn/haunts
func limitPath(ent *game.Entity, start int, path []int, max int) []int {
	total := 0
	graph := ent.Game().Graph(ent.Side(), true, nil)
	for last := 1; last < len(path); last++ {
		adj, cost := graph.Adjacent(start)
		found := false
		for index := range adj {
			if adj[index] == path[last] {
				total += int(cost[index])
				if total > max {
					return path[0:last]
				}
				start = adj[index]
				found = true
				break
			}
		}
		if !found {
			base.Log().Printf("PATH: DIdn't find, %d / %d", last+1, len(path))
			return path[0:last]
		}
	}
	return path
}