public static Vector getFeatures(Game game, int nodeIndex, MOVE move) {
		LinkedList<Integer> normalGhosts = new LinkedList<Integer>();
		LinkedList<Integer> edibleGhosts = new LinkedList<Integer>();

		for (GHOST ghost : GHOST.values()) {
			if (game.getGhostLairTime(ghost) == 0) {
				int ghostNodeIndex = game.getGhostCurrentNodeIndex(ghost);
				if (game.getGhostEdibleTime(ghost) == 0)
					normalGhosts.add(ghostNodeIndex);
				else
					edibleGhosts.add(ghostNodeIndex);
			}
		}

		double[] features = new double[14];
		int i = 0;
		features[i++] = getSavePathLength(game, nodeIndex, move, 110);
		features[i++] = getNumberOfSavePaths(game, nodeIndex, move, 50);
		features[i++] = getJunctionDistance(game, nodeIndex, move);
		features[i++] = getShortestPathDifference(game, nodeIndex, move);
		features[i++] = getPillsInDirection(game, nodeIndex, move);
		features[i++] = getMinimumDistance(game, nodeIndex, move, game.getActivePillsIndices());
		features[i++] = getMinimumDistance(game, nodeIndex, move, game.getActivePowerPillsIndices());
		features[i++] = getRemainingPills(game);
		features[i++] = completable(game, nodeIndex, move);
		features[i++] = getMinimumDistance(game, nodeIndex, move, toArray(edibleGhosts));
		features[i++] = getRemainingEdibleTime(game);
		features[i++] = getMinimumDistance(game, nodeIndex, move, toArray(normalGhosts));
		features[i++] = getMinimumDistance(game, game.getNeighbour(nodeIndex, move), move.opposite(), toArray(normalGhosts));
		features[i++] = move == game.getPacmanLastMoveMade().opposite() ? 1 : 0;

		return new Vector(features);
	}