Example #1
0
// Returns an array of all points that can be reached by walking from a
// specific location that end in a certain general area.  Assumes that a 1x1
// unit is doing the walking.
//    Format:
//    points = AllPathablePoints(src, dst, min, max)
//
//    Inputs:
//    src - table[x,y] - Where the path starts.
//    dst - table[x,y] - Another point near where the path should go.
//    min - integer    - Minimum distance from dst that the path should end at.
//    max - integer    - Maximum distance from dst that the path should end at.
//
//    Outputs:
//    points - array[table[x,y]]
func AllPathablePointsFunc(a *Ai) lua.GoFunction {
	return func(L *lua.State) int {
		if !game.LuaCheckParamsOk(L, "AllPathablePoints", game.LuaPoint, game.LuaPoint, game.LuaInteger, game.LuaInteger) {
			return 0
		}
		min := L.ToInteger(-2)
		max := L.ToInteger(-1)
		x1, y1 := game.LuaToPoint(L, -4)
		x2, y2 := game.LuaToPoint(L, -3)

		a.ent.Game().DetermineLos(x2, y2, max, grid)
		var dst []int
		for x := x2 - max; x <= x2+max; x++ {
			for y := y2 - max; y <= y2+max; y++ {
				if x > x2-min && x < x2+min && y > y2-min && y < y2+min {
					continue
				}
				if x < 0 || y < 0 || x >= len(grid) || y >= len(grid[0]) {
					continue
				}
				if !grid[x][y] {
					continue
				}
				dst = append(dst, a.ent.Game().ToVertex(x, y))
			}
		}
		vis := 0
		for i := range grid {
			for j := range grid[i] {
				if grid[i][j] {
					vis++
				}
			}
		}
		base.Log().Printf("Visible: %d", vis)
		graph := a.ent.Game().Graph(a.ent.Side(), true, nil)
		src := []int{a.ent.Game().ToVertex(x1, y1)}
		reachable := algorithm.ReachableDestinations(graph, src, dst)
		L.NewTable()
		base.Log().Printf("%d/%d reachable from (%d, %d) -> (%d, %d)", len(reachable), len(dst), x1, y1, x2, y2)
		for i, v := range reachable {
			_, x, y := a.ent.Game().FromVertex(v)
			L.PushInteger(i + 1)
			game.LuaPushPoint(L, x, y)
			L.SetTable(-3)
		}
		return 1
	}
}
Example #2
0
// Performs a move action to the closest one of any of the specifed inputs
// points.  The movement can be restricted to not spend more than a certain
// amount of ap.
//    Format:
//    success, p = DoMove(dsts, max_ap)
//
//    Input:
//    dsts  - array[table[x,y]] - Array of all points that are acceptable
//                                destinations.
//    max_ap - integer - Maxmium ap to spend while doing this move, if the
//                       required ap exceeds this the entity will still move
//                       as far as possible towards a destination.
//
//    Output:
//    success = bool - True iff the move made it to a position in dsts.
//    p - table[x,y] - New position of this entity, or nil if the move failed.
func DoMoveFunc(a *Ai) lua.GoFunction {
	return func(L *lua.State) int {
		if !game.LuaCheckParamsOk(L, "DoMove", game.LuaArray, game.LuaInteger) {
			return 0
		}
		me := a.ent
		max_ap := L.ToInteger(-1)
		L.Pop(1)
		cur_ap := me.Stats.ApCur()
		if max_ap > cur_ap {
			max_ap = cur_ap
		}
		n := int(L.ObjLen(-1))
		dsts := make([]int, n)[0:0]
		for i := 1; i <= n; i++ {
			L.PushInteger(i)
			L.GetTable(-2)
			x, y := game.LuaToPoint(L, -1)
			dsts = append(dsts, me.Game().ToVertex(x, y))
			L.Pop(1)
		}
		var move *actions.Move
		var ok bool
		for i := range me.Actions {
			move, ok = me.Actions[i].(*actions.Move)
			if ok {
				break
			}
		}
		if !ok {
			// TODO: what to do here?  This poor guy didn't have a move action :(
			L.PushNil()
			L.PushNil()
			return 2
		}
		exec := move.AiMoveToPos(me, dsts, max_ap)
		if exec != nil {
			a.execs <- exec
			<-a.pause
			// TODO: Need to get a resolution
			x, y := me.Pos()
			v := me.Game().ToVertex(x, y)
			complete := false
			for i := range dsts {
				if v == dsts[i] {
					complete = true
					break
				}
			}
			L.PushBoolean(complete)
			game.LuaPushPoint(L, x, y)
			base.Log().Printf("Finished move")
		} else {
			base.Log().Printf("Didn't bother moving")
			L.PushBoolean(true)
			L.PushNil()
		}
		return 2
	}
}
Example #3
0
// Performs an aoe attack against centered at the specified position.
//    Format:
//    res = DoAoeAttack(attack, pos)
//
//    Inputs:
//    attack - string     - Name of the attack to use.
//    pos    - table[x,y] - Position to center the aoe around.
//
//    Outputs:
//    res - boolean - true if the action performed, nil otherwise.
func DoAoeAttackFunc(a *Ai) lua.GoFunction {
	return func(L *lua.State) int {
		if !game.LuaCheckParamsOk(L, "DoAoeAttack", game.LuaString, game.LuaPoint) {
			return 0
		}
		me := a.ent
		name := L.ToString(-2)
		action := getActionByName(me, name)
		if action == nil {
			game.LuaDoError(L, fmt.Sprintf("Entity '%s' (id=%d) has no action named '%s'.", me.Name, me.Id, name))
			return 0
		}
		attack, ok := action.(*actions.AoeAttack)
		if !ok {
			game.LuaDoError(L, fmt.Sprintf("Action '%s' is not an aoe attack.", name))
			return 0
		}
		tx, ty := game.LuaToPoint(L, -1)
		exec := attack.AiAttackPosition(me, tx, ty)
		if exec != nil {
			a.execs <- exec
			<-a.pause
			L.PushBoolean(true)
		} else {
			L.PushNil()
		}
		return 1
	}
}
Example #4
0
// Computes the ranged distance between two points.
//    Format:
//    dist = RangedDistBetweenPositions(p1, p2)
//
//    Input:
//    p1 - table[x,y]
//    p2 - table[x,y]
//
//    Output:
//    dist - integer - The ranged distance between the two positions.
func RangedDistBetweenPositionsFunc(a *Ai) lua.GoFunction {
	return func(L *lua.State) int {
		if !game.LuaCheckParamsOk(L, "RangedDistBetweenPositions", game.LuaPoint, game.LuaPoint) {
			return 0
		}
		x1, y1 := game.LuaToPoint(L, -2)
		x2, y2 := game.LuaToPoint(L, -1)
		dx := x2 - x1
		if dx < 0 {
			dx = -dx
		}
		dy := y2 - y1
		if dy < 0 {
			dy = -dy
		}
		if dx > dy {
			L.PushInteger(dx)
		} else {
			L.PushInteger(dy)
		}
		return 1
	}
}