예제 #1
0
파일: pathfind.go 프로젝트: pimms/suckbot
func TileFind(start *TileWrapper, goal Status, tilestate *TileState) env.Direction {
	var pfstate t_pf_state
	var node *t_pathnode

	pfstate.init(env.MAX_SIZE * env.MAX_SIZE)
	pfstate.setTilestate(tilestate)
	pfstate.setStart(start, false)

	node = pfstate.startNode

	for len(pfstate.open) != 0 {
		// Find the node with the lowest value for f()
		// from the open list. As no heuristics are used,
		// f() effectively returns the value of g.
		node = pfstate.open[0]
		for i := 1; i < len(pfstate.open); i++ {
			if pfstate.open[i].f() < node.f() {
				node = pfstate.open[i]
			}
		}

		pfstate.addToClosed(node)

		for i := 0; i < 4; i++ {
			var dir env.Direction = env.Direction(i)
			var status Status = tilestate.GetTileStatus(node.tile.tile, dir)

			if status == goal {
				// We cannot use the undiscovered tile in pathfinding
				// because it hasn't been discovered yet. The link
				// between the TileWrapper and the env.ITile is nil.
				// However, if we started at a neighbouring tile, we
				// already know the direction.
				if start == node.tile {
					return dir
				}

				// Return A* to the closest neighbouring tile (node).
				return PathFind(start, node.tile, tilestate)
			} else if status == TILE_DISCOVERED {
				var wrapper *TileWrapper
				var neighbour *t_pathnode

				wrapper = tilestate.GetTile(node.tile, dir)
				neighbour = pfstate.getPathnode(wrapper)

				if pfstate.isOpen(neighbour) {
					neighbour.parent = node
					neighbour.g = node.g
				} else if !pfstate.isClosed(neighbour) {
					pfstate.addToOpen(neighbour)
					neighbour.parent = node
					neighbour.g = node.g
				}
			}
		}
	}

	return env.NONE
}
예제 #2
0
파일: agent.go 프로젝트: pimms/suckbot
func (a *Agent) performAction(action int, perf *util.SimPerf) {
	switch action {
	case NOOP:

	case SUCK:
		perf.AgentCleaned(a.currentTile.GetITile())
		a.vacuumCurrent()

	case int(env.UP):
		fallthrough

	case int(env.RIGHT):
		fallthrough

	case int(env.DOWN):
		fallthrough

	case int(env.LEFT):
		var moved bool
		moved = a.moveInDirection(env.Direction(action))

		// If the agent successfully moved in the direction,
		// notify the SimPerf of the dirt-status of the tile.
		if moved {
			tile := a.currentTile.GetITile()
			perf.AgentEnteredTile(tile.GetState() == env.DIRTY)
			perf.AgentMoved()
		}
	}
}
예제 #3
0
파일: pathfind.go 프로젝트: pimms/suckbot
/* Returns the direction the agent should take in order to
 * successfully arrive at the end-tile.
 */
func PathFind(start, end *TileWrapper, tilestate *TileState) env.Direction {
	var pfstate t_pf_state
	var node *t_pathnode
	var success bool

	pfstate.init(env.MAX_SIZE * env.MAX_SIZE)
	pfstate.setTilestate(tilestate)
	pfstate.setStart(start, true)

	node = pfstate.startNode

	for len(pfstate.open) != 0 {
		// Find the node with the lowest value for f()
		// from the open list
		node = pfstate.open[0]
		for i := 1; i < len(pfstate.open); i++ {
			if pfstate.open[i].f() < node.f() {
				node = pfstate.open[i]
			}
		}

		// Stop searching when we've added the destination
		// to the closed list
		pfstate.addToClosed(node)
		if node.tile == end {
			success = true
			break
		}

		for i := 0; i < 4; i++ {
			var dir env.Direction = env.Direction(i)
			var status Status = tilestate.GetTileStatus(node.tile.tile, dir)

			if status == TILE_DISCOVERED {
				var wrapper *TileWrapper
				var neighbour *t_pathnode

				wrapper = tilestate.GetTile(node.tile, dir)
				neighbour = pfstate.getPathnode(wrapper)

				if pfstate.isOpen(neighbour) {
					neighbour.parent = node
					neighbour.g = node.g
				} else if !pfstate.isClosed(neighbour) {
					pfstate.addToOpen(neighbour)
					neighbour.parent = node
					neighbour.g = node.g
				}
			}
		}
	}

	if success && node.parent != nil {
		for node.parent.parent != nil {
			node = node.parent
		}

		// Get the relative position
		x0, y0 := node.tile.tile.GetIndices()
		x1, y1 := node.parent.tile.tile.GetIndices()
		x := x0 - x1
		y := y0 - y1

		return env.GetDirection(x, y)
	}

	return env.NONE
}