Example #1
0
    def __init__(self, texture_info_list):
        self.walker = Walker()

        r = Resolver('name')

        id = 0

        self.root = TreeNode('Root', id)

        id += 1

        for info in texture_info_list:
            respath = info.respath

            cur_parent = self.root
            cur_parent.filesize.bytes += info.filesize.bytes
            cur_node = None
            for chunk in respath.chunks:
                try:
                    cur_node = r.get(cur_parent, chunk)
                    cur_parent = cur_node
                except ChildResolverError:
                    cur_node = TreeNode(chunk, id, cur_parent)
                    cur_parent = cur_node

                    id += 1

                    if chunk == respath.chunks[-1]:
                        cur_node.horizontal_desc = str(info)

                finally:
                    cur_node.filesize.bytes += info.filesize.bytes
Example #2
0
def get_type_similarity(root, cloth1, cloth2):

	cloth1_cat = cloth1.get_cat_label()
	cloth1_node = anytree.find(root, lambda node: node.name == cloth1_cat)

	cloth2_cat = cloth2.get_cat_label()
	cloth2_node = anytree.find(root, lambda node: node.name == cloth2_cat)

	# Walk from start node to end node
	# Returns:
	# upward is a list of nodes to go upward to.
	# common is common up node
	# downward is a list of nodes to go downward to
	
	w = Walker()
	upward, common, downward = w.walk(cloth1_node, cloth2_node)

	if(cloth1_node.name == cloth2_node.name):
		# Exact Match
		return 1
	elif((cloth1_node.name == cloth2_node.parent.name) or (cloth1_node.parent.name == cloth2_node.name) or (cloth1_node.parent.name == cloth2_node.parent.name)):
		# Cloth 1 type is an ancestor of cloth_2 or vise versa
		return 0.5
	elif(common.name == "Cloth"):
		return 0
	elif(common.name == "Tops" or common.name =="Bottoms" or common.name == "Fullbody"):
		return 0.25
	else:
		return 0
Example #3
0
def main():
    input_file_path = sys.argv[1]

    if not os.path.isfile(input_file_path):
        print(
            int("File path {} does not exist. Exiting...".format(
                input_file_path)))
        sys.exit()

    input_data = open(input_file_path, 'r').read().splitlines()

    node_list = {}

    for data in input_data:
        space_object_data = data.split(")")
        mass_object = Node(space_object_data[0])
        orbit_object = Node(space_object_data[1])

        if mass_object.name in node_list:
            mass_object = node_list[mass_object.name]
        else:
            node_list[mass_object.name] = mass_object

        if orbit_object.name in node_list:
            orbit_object = node_list[orbit_object.name]
        else:
            node_list[orbit_object.name] = orbit_object

        orbit_object.parent = mass_object

    w = Walker()
    walk_path = w.walk(node_list["YOU"].parent, node_list["SAN"].parent)
    print(len(flatten(walk_path)) - 1)
Example #4
0
def main():
    lines = readfile()
    nodes = {}

    for line in lines:
        p, c = line.split(")")
        if p not in nodes:
            nodes[p] = Node(p)

        if c in nodes:
            nodes[c].parent = nodes[p]
        else:
            nodes[c] = Node(c, parent=nodes[p])

    root = nodes[c].root

    if args.verbose:
        print(RenderTree(root))

    # Part 1
    orbits = 0
    for n in root.descendants:
        orbits += n.depth
    print("There are", orbits, "orbits")

    # Part 2
    w = Walker()
    result = w.walk(nodes["YOU"].parent, nodes["SAN"].parent)
    print("It takes",
          len(result[0]) + len(result[2]), "steps to get from YOU to SAN")
Example #5
0
def get_transfers(orbit_tree):
    you = orbit_tree['YOU']
    san = orbit_tree['SAN']

    w = Walker()
    route = w.walk(you, san)
    transfers = len(route[0]) + len(route[2]) - 2

    return transfers
Example #6
0
def count_transits(from_name, to_name, input):
    root = build_orbit_tree(input.split())

    # print(RenderTree(root, style=AsciiStyle()).by_attr())

    from_node = find(root, lambda node: node.name == from_name).parent
    to_node = find(root, lambda node: node.name == to_name).parent

    walker = Walker()
    (upwards, _, downwards) = walker.walk(from_node, to_node)
    return (len(upwards) + len(downwards))
Example #7
0
 def walk_to(self, node, verbose=False) -> Tuple[Any, Any, Any]:
     """Returns:
         (upwards, common, downwards): `upwards` is a list of nodes to go upward to.
         `common` top node. `downwards` is a list of nodes to go downward to.
     """
     w = Walker()
     rs = w.walk(self, node)
     if verbose:
         node_repr = lambda n: f"{n.text}({n.dependency_relation})"
         val_repr = lambda node: [node_repr(n) for n in node] if isinstance(
             node, tuple) else [node_repr(node)]
         print(' ._ '.join([','.join(val_repr(r)) for r in rs]))
     return rs
Example #8
0
def main():
    orbits = []
    with open('input/day6.txt') as temp_file:
        orbits = [line.rstrip('\n') for line in temp_file]
    count = countNodes(copy.deepcopy(orbits))
    process(orbits, count)
    # pprint.pprint(nodes)
    # for pre, fill, node in RenderTree(nodes.get('COM')):
    #     print("%s%s" % (pre, node.name))
    w = Walker()
    path = w.walk(nodes.get('YOU'), nodes.get('SAN'))
    upwards = path[0]
    common = path[1]
    downwards = path[2]
    totalSteps = len(upwards) + 1 + len(downwards) - 3
    print(totalSteps)
    def get_nodes_on_path(self, target_branch_id):
        branch_type = branchutil.parse_branch_type(target_branch_id)
        branch_num = branchutil.parse_branch_num(target_branch_id)

        target_node = None
        for node in PreOrderIter(self.root):
            if node.num == branch_num and node.type == branch_type:
                target_node = node

        w = Walker()
        nodes_on_path = [(node.num, node.type)
                         for node in w.walk(self.root, target_node)[2]]

        nodes_on_path.reverse()

        return nodes_on_path
 def path(self, src_token, tgt_token):
     src_node = self._get_node(src_token)
     tgt_node = self._get_node(tgt_token)
     if src_node == tgt_node:
         return ["@self"]
     up, lca, down = Walker().walk(src_node, tgt_node)
     return [f"-{u.rel}"
             for u in list(up)] + [f"+{d.rel}" for d in list(down)]
Example #11
0
def set_needs(tree):
    """For a recipe, needed is the number of times it must be run for 1 final output.

       For an item, needed is the number that must be produced for 1 final output.
    """
    w = Walker()
    for leaf in tree:
        if leaf.is_leaf:
            needed = tree[0].number
            try:
                for i, node in enumerate(w.walk(tree[0], leaf)[2]):
                    if i % 2 == 0:  # recipe node
                        needed /= node.number
                    else:  # item node
                        needed *= node.number
                    node.needed = needed
            except WalkError:
                pass
    def get_nodes_on_path(self, target_branch_id):
        branch_num = target_branch_id[0]
        branch_type = target_branch_id[1]

        if branch_num == 0:
            return []

        target_node = None
        for node in PreOrderIter(self.root):
            if node.num == branch_num and node.type == branch_type:
                target_node = node

        w = Walker()
        nodes_on_path = [(node.num, node.type)
                         for node in w.walk(self.root, target_node)[2]]

        nodes_on_path.reverse()

        return nodes_on_path
Example #13
0
    def __init__(self, exchange):
        self.exchange = exchange
        self.orderManager = OrderManager()
        self.logger.info("Initiate Price Arbitrage Algo")
        self._buildFxTree() # build fx tree for all possible conversions
        # build list of leaves
        root = self.tree.root  # get root
        w = Walker()  # tree walker
        # unwrap nested tuple returned by Walker to a flat list of FXPair
        def unwrapWalkerToFlatList(x):
            if isinstance(x, tuple):
                if len(x) == 0: return []
                s = []
                for t in x:
                    s.extend(unwrapWalkerToFlatList(t))
                return s
            else:
                if x.getFXPair() is None: return [] # skip root element
                else: return [x.getFXPair()]

        self.conversion_paths = {} # all conversion paths for the pair <pair: [pair1, pair2...]>
        # build list of all conversion paths
        for k in FXNode.treeNodesWithSamePair.keys():  # iterate all pairs
            alternative_list = FXNode.treeNodesWithSamePair[k]  # get list of leaves representing same pair but with different conversion path
            paths = []
            for c in alternative_list:  # iterate all leaves (same pair but different paths)
                if not c.is_leaf:
                    continue  # iterate only leaves
                path = unwrapWalkerToFlatList(w.walk(root, c))  # get path from root to this leaf
                paths.append(path) # list of lists

            if not k in self.conversion_paths.keys():
                self.conversion_paths[k] = list(paths)
            else:
                self.conversion_paths[k].append(list(paths))

        # set event triggers
        self.exchange.setEventHandler(tradeHandler=self.updateTradeHandler, orderHandler=self.updateOrderHandler)
Example #14
0
 def transformation_to(self, node: Node) -> np.ndarray:
     """ Transformation matrix from this node to another node.
     """
     if self == node:
         return np.identity(4)
     upwards, common, downwards = Walker().walk(self, node)
     transforms = tuple(map(lambda x: x.pose, upwards))
     transforms = transforms + tuple(
         map(lambda x: np.linalg.inv(x.pose), downwards))
     if len(transforms) == 1:
         transform = transforms[0]
     else:
         transform = np.linalg.multi_dot(transforms[::-1])
     return transform
Example #15
0
def test_walker():
    """walk test."""
    f = Node("f")
    b = Node("b", parent=f)
    a = Node("a", parent=b)
    d = Node("d", parent=b)
    c = Node("c", parent=d)
    e = Node("e", parent=d)
    g = Node("g", parent=f)
    i = Node("i", parent=g)
    h = Node("h", parent=i)
    w = Walker()
    print(w.walk(f, f))
    print(eq_(w.walk(f, f), ((), f, ())))
    eq_(w.walk(f, b), ((), f, (b, )))
    eq_(w.walk(b, f), ((b, ), f, ()))
    eq_(w.walk(a, f), ((a, b), f, ()))
    eq_(w.walk(h, e), ((h, i, g), f, (b, d, e)))
    eq_(w.walk(d, e), ((), d, (e, )))

    #with assert_raises(WalkError, "Node('/a') and Node('/b') are not part of the same tree."):
    w.walk(Node("a"), Node("b"))
Example #16
0
def calculate_path(start: Node, end: Node) -> List[Edge]:
    upwards, common, downwards = Walker().walk(start, end)
    edges = []

    if len(upwards) > 0:
        for i in range(0, len(upwards) - 1):
            edges.append(Edge(parent=upwards[i + 1], child=upwards[i]))

        edges.append(Edge(parent=common, child=upwards[-1]))

    if len(downwards) > 0:
        edges.append(Edge(parent=common, child=downwards[0]))

        for i in range(0, len(downwards) - 1):
            edges.append(Edge(parent=downwards[i], child=downwards[i + 1]))

    return edges
Example #17
0
class AssetInfoTree:
    def __init__(self, texture_info_list):
        self.walker = Walker()

        r = Resolver('name')

        id = 0

        self.root = TreeNode('Root', id)

        id += 1

        for info in texture_info_list:
            respath = info.respath

            cur_parent = self.root
            cur_parent.filesize.bytes += info.filesize.bytes
            cur_node = None
            for chunk in respath.chunks:
                try:
                    cur_node = r.get(cur_parent, chunk)
                    cur_parent = cur_node
                except ChildResolverError:
                    cur_node = TreeNode(chunk, id, cur_parent)
                    cur_parent = cur_node

                    id += 1

                    if chunk == respath.chunks[-1]:
                        cur_node.horizontal_desc = str(info)

                finally:
                    cur_node.filesize.bytes += info.filesize.bytes

    def build_node_path(self, node):
        path = self.walker.walk(self.root, node)
        return '/'.join([tn.name for tn in path[2]])
Example #18
0
 def path_to(self, node) -> Sequence[Node]:
     upwards, common, downwards = Walker().walk(self, node)
     path = upwards + (common,) + downwards
     return path
Example #19
0
    def __missing__(self, key):
        res = self[key] = Node(key)
        return res


if __name__ == "__main__":

    # with open("example_1") as f:
    with open("input_1") as f:
        input_m = [line.rstrip() for line in f]

    # print(f"input {input_m}")

    nodes = DefaultNodeDict()

    for input_orbit in input_m:
        center, satellite = input_orbit.split(")")
        nodes[satellite].parent = nodes[center]

    print(RenderTree(nodes["COM"]))
    w = Walker()
    # upward, common, downward = w.walk(nodes["YOU"], nodes["SAN"])
    # print(len(upward) + len(downward) - 2)

    # Part 1 below ###
    total = 0
    for node in nodes.values():
        upward, common, downward = w.walk(node, nodes["COM"])
        total += len(upward) + len(downward)
    print(total - len(nodes))
Example #20
0
def find_LCA_two_objects(node_object_1, node_object_2):
    w = Walker()
    LCA = w.walk(node_object_1, node_object_2)[1]
    return LCA
Example #21
0
# reference: https://stackoverflow.com/questions/2358045/how-can-i-implement-a-tree-in-python
# http://pydoc.net/anytree/2.4.3/anytree.node.nodemixin/

# reference: https://anytree.readthedocs.io/en/latest/

from anytree import Node, RenderTree, Walker
from anytree import Node, RenderTree, AsciiStyle

layer1 = Node(44)
layer2_1 = Node(6, parent=layer1)
layer2_2 = Node(9, parent=layer1)
layer3_1 = Node(34, parent=layer2_2)
layer3_2 = Node(5, parent=layer2_1)
layer3_3 = Node(4, parent=layer2_1)

print('\nShowing the entire tree:')
for pre, fill, node in RenderTree(layer1):
    print("%s%s" % (pre, node.name))
print('\n')

w = Walker()

print('\nWalking the tree, layers3_2, and layers3_3:')
print(w.walk(layer3_2, layer3_3))
print('\n')

print('Showing the tree AsciiStyle:')
print(RenderTree(layer1, style=AsciiStyle()))
print('\n')

# reference: https://anytree.readthedocs.io/en/latest/
Example #22
0
class bcolors:
    HEADER = '\033[95m'
    RED = '\033[31m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

INIT_REGEX = r'etc\/(init\.d\/|sysinit\.d\/|rc[\w\d]*\.d\/|rc[\w\d]*\.(sh|local)+)+[a-z\.\_]*'
PATH = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin', '/usr/local/sbin']
PROGRAMS = {}
TREE = []
w = Walker()

_TEXT_BOMS = (
    codecs.BOM_UTF16_BE,
    codecs.BOM_UTF16_LE,
    codecs.BOM_UTF32_BE,
    codecs.BOM_UTF32_LE,
    codecs.BOM_UTF8,
)



def print_node(node):
    for pre, fill, node in RenderTree(node, style=AsciiStyle()):
            print("%s%s" % (pre, node.name))
Example #23
0
def part2(node1, node2):
    w = Walker()
    upwards, common, downwards = w.walk(node1, node2)

    # minus 2 since you to parent and san to parent transfers ommited
    return len(upwards) + len(downwards) - 2
Example #24
0
 def __init__(self ):
     self.rootNode = Tree_Board_State( np.zeros((3,3)),0,0,0,   "theRootNode", 0,0, parent=None, children=None )
     self.theWalker = Walker()
     self.traversedPath = [self.rootNode]
Example #25
0
        cur = Node(orbiter, parent=root)
        nodes.append(cur)
        build_tree(cur, nodes, orbits)


root = Node('COM')
orbits = {}
with open('6.in') as f:
    for x in f.read().splitlines():
        # AAA)BBB = BBB is in orbit around AAA
        orbit = x.split(')')
        if orbit[0] not in orbits:
            orbits[orbit[0]] = [orbit[1]]
        else:
            orbits[orbit[0]].append(orbit[1])

nodes = []
build_tree(root, nodes, orbits)

length = 0
w = Walker()
for node in nodes:
    length += len(w.walk(node, root)[0])
print('part 1: {}'.format(length))

you = search.find(root, lambda node: node.name == 'YOU')
san = search.find(root, lambda node: node.name == 'SAN')

res = w.walk(you, san)
print('part 2: {}'.format(len(res[0]) + len(res[2]) - 2))
Example #26
0
        print(node)
#
print(RenderTree(nodes['COM'], style=AsciiStyle()))

##
# Part 1
##
direct = 0
indirect = 0
for node in PreOrderIter(nodes['COM']):
    ancestors = len(node.ancestors)
    if ancestors == 0:
        continue

    direct += 1
    indirect += ancestors - 1

print(direct + indirect)

##
# Part 2
##
san_parent = nodes['SAN'].parent
print(san_parent.name)
w = Walker()

walk = w.walk(nodes['YOU'].parent.parent, nodes['SAN'].parent)
print(walk)
full_path = (*walk[0], walk[1], *walk[2])
print(len(full_path))
Example #27
0
    def branch(self, origin, destination):
        """
        Description
        -----------
        
        Returns  the  path  in  the  tree  to go from the 'origin' node to the
        'destination' node.
        
        The result is returned as two lists :
            - upwards is a list of joint numbers to go upward to
            - downwards is a list of joint numbers to go downward to
            
        Every element of the list is the index of a joint from self.joints
        
        This  function  uses anytree Walker class, for more details, check the
        anytree documentation :
        https://anytree.readthedocs.io/en/latest/api/anytree.walker.html

        Parameters
        ----------
        origin : str
            Origin  element  of the tree. Is a string formatted like the nodes
            names of self.tree :
                type_number
                
                where type is 'joint' / 'link' and number is the number of the
                considered Joint / Link in self.joints / self.links.
                
                Example : origin='joint_2'
        destination : str
            Destination  element  of  the tree. Is a string formatted like the
            node names of self.tree :
                type_number
                
                where type is 'joint' / 'link' and number is the number of the
                considered Joint / Link in self.joints / self.links.
                
                Example : destination='link_0'

        Returns
        -------
        upwards : list of int
            List of  Joint index to go upward to. The transition matrix of the
            Joints is T()**(-1) to go from a Joint to the next in this list.
        downwards : list of int
            List  Joint index to go downward  to. The transition matrix of the
            Joints is T() to go from a Joint to the next in this list
            
        Examples
        --------
        
        TODO

        """

        # Upward List
        upwards = []

        # Downward List
        downwards = []

        # 1 - Finding the Node in the tree from origin and destination .......

        origin_node = None
        destination_node = None
        for _, _, node in self.tree:
            if node.name == origin:
                origin_node = node
            if node.name == destination:
                destination_node = node

        # 2 - Walk around the tree ...........................................

        # Tree Walker
        w = Walker()

        # Getting paths
        up_nodes, middle, down_nodes = w.walk(origin_node, destination_node)

        # As only Joints have transition matrices, we ignore link nodes

        # For upward nodes
        for node in up_nodes:
            # Getting the i & type from the node name "link_i" or "joint_i"
            node_type, node_nb = node.name.split('_')
            node_nb = int(node_nb)
            if node_type == 'joint':
                upwards.append(node_nb)

        # For downward nodes
        for node in down_nodes:
            # Getting the i & type from the node name "link_i" or "joint_i"
            node_type, node_nb = node.name.split('_')
            node_nb = int(node_nb)
            if node_type == 'joint':
                downwards.append(node_nb)

        return upwards, downwards
Example #28
0
    def findArbitrageOpportunity(self):
        # find spot arbitrage opportunity in the exchange
        # calculate conversion value
        # LONG position: from top to leaf

        #ierate tree from root to the leaves to calculate terminal conversion rate in the leaves
        def estimateRates(longVal, shortVal, root, longStr):
            r = root.getFXPair()
            # rates reflect current order book status and amt to exchange

            ex_rate1 = 0 # error signal
            v1 = 0
            if r.isBidAvailable():
                ex_rate1 = r.getAverageBidPrice(longVal)  # use bid price here
                v1 = longVal / ex_rate1  # convert val to Node base currency
            ex_rate2 = 0 # error signal
            v2 = 0
            if r.isAskAvailable():
                ex_rate2 = r.getAverageAskPrice(shortVal)  # use ask price
                v2 = shortVal * ex_rate2

            s1 = longStr + "-> " + str(v1) + " " + r.getBase() + "@" + str(ex_rate1)

            if root.is_leaf: # reached leaf - save accumulated long value
                root.longValue = v1  # value of 1 BTC expressed in terms of base value of this currency (base)
                root.longStr = s1
                root.shortValue = v2 # value of 1 unit of this base currency expressed in terms of quote currency of the tree root
            else:
                for n in root.children:
                    estimateRates(v1, v2, n, s1)

        # Combined LONG / SHORT LOOP: start with 1 BTC
        root = self.tree.root # get root
        for n in root.children:
            pair = n.getFXPair()
            x = self.exchange.getExchangeRate('BTC',pair.getQuote(), 'BID')
            # x = pair.get1BTCinQuote()
            # get value of 1 BTC expressed in quote currency of n
            #ex_rate1 = pair.getAverageBidPrice(x) # use bid price here
            #ex_rate2 = pair.getAverageAskPrice(1)
            v1 = x  # 1 * ex_rate1 # long local currency worth of 1 BTC
            v2 = 1  # short value
            s1 = "1 BTC -> " + str(x) + " " + pair.getQuote()
            estimateRates(v1, v2, n, s1)
        # print alternatives
        a = FXNode.m_alternatives.keys()
        w = Walker()
        for k in FXNode.m_alternatives.keys():
            alternative_list = FXNode.m_alternatives[k]
            print("------PAIR %s" % (k.getPairCode()))
            for c in alternative_list:
                if not c.is_leaf:
                    continue # iterate only leaves
                # unwrap nested tuples
                def unwrap(x):
                    if isinstance(x, tuple):
                        s = ""
                        for t in x:
                            s += unwrap(t)
                        return s
                    else:
                        return x.name + " "
                path = w.walk(root, c)
                print("LONG: %f : %s >> %s"  % (c.longValue, unwrap(path), c.longStr))


        print("FINISH")
Example #29
0
lines = []
d = {}
#with open("6test.txt") as f:
with open("6input.txt") as f:
    lines = [tuple(x.rstrip().split(")")) for x in f.readlines()]

for l in lines:
    if l[0] in d:
        d[l[0]].append(l[1])
    else:
        d[l[0]] = [l[1]]

root = Node("COM")
create_children(root)
sum = 0
you = None
santa = None
for n in root.descendants:
    sum += n.depth
    if n.name == "YOU":
        you = n
    if n.name == "SAN":
        santa = n

print(sum)

w = Walker()
up, common, down = w.walk(you, santa)
#assuming a single common node
print(len(up) - 2 + 1 + len(down) - 1)
Example #30
0
class MCTSalgo:
    """MCTS object
    -performs mcts algo on high level
    -required datamembers are as follows
        *walker obj to traverse gametree

        *rootNode to know the root, and switch root, when getting
        humanplayer's inputs into the system, and when changing the currentGameState

        *traversed path until including leafnode / or terminalnode, list of nodes
        is required for walker object to traverse one-depth at a time, into the leaf,
        and with traversedPath we can go straight back in rolloutMode, and update values,
        and visitedcounts

        *must be able to interact with getting inputs from the player,
        and gives outputs to the player after having played AI turn
        interaction can probably be tweaked at the last stage, because debugging and
        getting the mcts to work is the hard part"""

    """constructor"""
    def __init__(self ):
        self.rootNode = Tree_Board_State( np.zeros((3,3)),0,0,0,   "theRootNode", 0,0, parent=None, children=None )
        self.theWalker = Walker()
        self.traversedPath = [self.rootNode]

    """changeRootNode
    purpose is to change into new rootNode when curGameState changes (after AI has moved, or humanplayer has moved)"""
    def changeRootNode(self, newRootNode):
        self.rootNode = newRootNode
        self.rootNode.parent = None


    def getPlayerInput(self, curTreeBoard):
        self.changeRootNode( curTreeBoard )
        self.clearTraversed() ##IMPORTANT to clear the oldTraversed path because theOldTraversed points to a tree, whose root was different!
    """we can also say that the AI always takes second turn...
    hence we should always have possible gameState in the childNode, to place the marker into...
    hence, we can expand the rootNode into childNodes always"""
  #      listB, expandRes = self.rootNode.getPossibleActions()
   #     self.rootNode.expandCurrentNode(listB)


    """walkUntilLeaf (including LeafNode)
    traverses the tree from curRoot, until including leafNode, 
    meanwhile selecting the best childNodes along the path with UCB metrics
    saves the traversedPath list into memory for backpropagation purposes, 
    and also returns the leafNode itself"""

    def walkUntilLeaf(self):
        #curNode = self.rootNode
        self.traversedPath = [ node for node in PreOrderIter(self.rootNode, filter_=filterUCB1, stop=stopfilter2 ) ]
        lastNode = self.traversedPath[-1]
        self.traversedPath.append( lastNode.selectUCBFromChildren() )
        """##sadly the API was badly done, and it wasnt possible to
        ## easily walk until (including) the leafNode with stopfunction filter
        ## so we must have that "realLeafNode" append, in the end"""
        trueLeafNode = self.traversedPath[-1] #append it!
        return trueLeafNode

    def walkerFuncTraversal(self):
        destNode = self.rootNode.selectUCBFromChildren()
        if destNode == None:
            return self.rootNode
        else:
            curNode = self.rootNode
            while destNode != None:
                res = self.theWalker.walk( curNode, destNode  )
                res = res[2][0]
                self.traversedPath.append( res )
                curNode = destNode
                destNode = curNode.selectUCBFromChildren()
                ##if curNode selectUCBChildren returns None, it will have been
                ## leafNode itself
            return curNode


    def backpropagate(self, curReward):
        for x in self.traversedPath:
            x.visited_count += 1
            x.value += curReward
        kakka = 77 #for debug only



    """MAIN MCTS ALGORITHM"""
    def performMonteCarloTreeSearch(self, iterationsAmount):
        for j in range(1,iterationsAmount+1):
            leafNode = self.walkerFuncTraversal()
            if leafNode.getVisited() == 0:
                ##make Rolloout
                reward = self.playRollout(leafNode)
                self.backpropagate(reward)
            else:
                ##select childNode from expandedOnes
                ##make Rollout
                actionsList, res = leafNode.getPossibleActions()
                if  res == False: ##NotTerminalNode where game ends
                    leafNode.expandCurrentNode(actionsList)
                    childNode = leafNode.selectUCBFromChildren() ##select childNode
                    self.traversedPath.append(childNode)
                    reward = self.playRollout(childNode)
                    self.backpropagate(reward)
                else:   ##Game must have ended in this branch
                    kakka = 10 #for debug only!
                    reward = self.playRollout(leafNode)
                    self.backpropagate(reward)
            self.clearTraversed()
        print("gameTree after AI_mcts_deliberations:\n", RenderTree(self.rootNode).by_attr())

        childList = list(self.rootNode.children)
        visitsList=[]
        for child in childList:
            visitsList.append(child.getVisited())
        """mostVisited =  childList[visitsList.index(max(visitsList))  ]"""
        highVisitCount = max(visitsList)
        for child in childList:
            if child.getVisited() == highVisitCount:
                bestOpt = child
        bestOpt = copy.deepcopy(bestOpt)
        bestOpt.parent=None
        if bestOpt.current_turn == 1:
            bestOpt.current_turn = 0
        else:
            bestOpt.current_turn = 1
        return bestOpt




    """playRollout
    function is doing the mcts rollouts
    the key trick is to make the rollouts in a separateSimulatedCopy tree
    so it doesn't disturb the real mcts object's tree, then we simply 
    start from the copied gamestate simulatedRootNode, and expand the gameTree until game ends and we get
    reward.
    Other things to note about it: 
        *it will simply expand the simulatedRootNode into a gametree (until game ends) and hopefully
        garbagecollector will do something about it later...
        
        *actionPolicy for both players in rollout simulation will be equiprobable random, from the available
        actions that are left on the board"""
    def playRollout(self, originNode):
        #protip, use deepcopy instead of python shenanigans!!!
        simulatedRootNode = copy.deepcopy(originNode) ##hopefully copies the originNode into separate SimulatedRootNOde
        simulatedRootNode.parent = None
        curState = copy.deepcopy(simulatedRootNode)
        curReward = 0
        while True:
            game_res = curState.checkGameResult()
            if game_res != 2:
                if game_res == 1:
                    curReward = 50##AI has won, markers are 1s
                    break
                elif game_res == -1:
                    curReward = -50 ##human has won
                    break
                else:
                    curReward=25 ##draw
                    break
            else:
                action = curState.getRandomAction()
                if action != None:
                    curState = curState.makeLegalMove(action)
                else:
                    kakka = 90 #for debug only!

        return curReward


    def clearTraversed(self):
        self.traversedPath = [self.rootNode]

    def checkIfNoVisits(self, theNode):
        return theNode.getVisited()