private Node<A> select(Node<A> node) {
		if (node.state.isTerminal() || node.numVisits < EXPAND_THRESHOLD) {
			return node;
		}
		
		ArrayList<Node<A>> candidates = new ArrayList<Node<A>>();
		for (Node<A> n : node.children.values()) {
			if (n.numVisits < EXPAND_THRESHOLD) {
				candidates.add(n);
			}
		}
		int size = candidates.size();
		if (size != 0) {
			return candidates.get(rand.nextInt(size));
		}
		
		Node<A> ret = null;
		double bestScore = -100.0;
		for (Node<A> n : node.children.values()) {
			double score = n.value/n.numVisits + C * Math.sqrt(Math.log(n.parent.numVisits)/n.numVisits);
			if (ret == null || score > bestScore) {
				bestScore = score;
				ret = n;
			}
		}

		return select(ret);
	}