void bt_node_free ( bt_node_t *_node ) { // the array could be NULL; if ( _node->children ) { // free children nodes ex_array_each ( _node->children, bt_node_t *, child ) { bt_node_free ( child ); } ex_array_each_end // free array if ( _node->children ) { ex_array_free (_node->children); } }
/* clean bt_node tree while it's cleaning bt_node */ void clean_bin_tree(struct btree_node *node, int depth) { struct btree_node *parent; if (node->left || node->right || !depth) return; parent = node->parent; if (!parent) return; if (parent->left == node) parent->left = NULL; if (parent->right == node) parent->right = NULL; bt_node_free(node); clean_bin_tree(parent, --depth); }
static int gen_bin_tree_tail(unsigned char *maze, unsigned char *map, struct s_link **head) { struct btree_node *bt_new_node, *bt_node; struct s_link *sl_node; struct s_link *sl_new_node, *tail_new_list = NULL; unsigned char i, index, abs_dir; struct btree_node bt_node_backup; char dir, is_goal = 0, found_node; #ifdef CONFIG_PATH_LIMIT int path_limit = 0; #endif if (!maze || !map || !head || !*head) { print_error("NULL pointer error! %X %X %X %X\n", (unsigned int)maze, (unsigned int)map, (unsigned int)head, (unsigned int)*head); } print_dbg(DEBUG_S_LINK, "Check input linked list: %08X\n", (unsigned int)*head); debug_sl_node(*head); print_dbg(DEBUG_S_LINK, "Find next lower contour level\n"); /* Find next lower contour cube arond current location */ for (sl_node = *head; sl_node; sl_node = sl_node->node) { index = sl_node->bt_node->pos; abs_dir = sl_node->bt_node->abs_dir; bt_node = sl_node->bt_node; /* when it's set, found turn. on the unkonwn blocks, * there may be too many pathes to calculate. **/ found_node = 0; bt_node_backup.time = 0; /* use to check FD detection */ for (i = NI; i <= WI; i++) { if (!(maze[index] & wall_bit(i)) && (map[index] == map[index + maze_dxy[i]] + 1)) { dir = relative_direction(abs_dir, i); /* if block is unknown, then take turn prior * to straight path. It's to save memory * and calculation time. */ if (dir == FD && ((maze[index]&0xF0) != 0xF0)) { bt_node_backup.pos = index+maze_dxy[i]; bt_node_backup.dir = dir; bt_node_backup.abs_dir = i; /* to mark block has meaningful data */ bt_node_backup.time = 1; continue; } found_node = 1; /* create new bt_node and save next mouse index * and absolute direction of mouse at next block */ bt_new_node = bt_node_alloc(index+maze_dxy[i], i); /* Next bt_node->dir is to save how mouse made * a turn to come the block. */ bt_new_node->dir = dir; /* there can be 3rd child, only take 2 child at * a time */ if (!add_bt_node(bt_node, bt_new_node)) { sl_new_node = s_link_alloc(bt_new_node); add_sl_node(&tail_new_list, sl_new_node); #ifdef CONFIG_PATH_LIMIT path_limit++; #endif } else { bt_node_free(bt_new_node); } /* * debug_sl_node(tail_new_list); */ } } /* if forward is the only one in known block, * then use it */ if (!found_node && bt_node_backup.time) { bt_new_node = bt_node_alloc(bt_node_backup.pos, bt_node_backup.abs_dir); bt_new_node->dir = bt_node_backup.dir; add_bt_node(bt_node, bt_new_node); sl_new_node = s_link_alloc(bt_new_node); add_sl_node(&tail_new_list, sl_new_node); #ifdef CONFIG_PATH_LIMIT path_limit++; #endif } if (map[index] == 1 && !is_goal) is_goal = 1; /* Remove bt_node if there is no child, it'll search * parent node and remove the node if it had no child */ if (!is_goal) clean_bin_tree(bt_node, 80); #ifdef CONFIG_PATH_LIMIT /* 10 pathes : max 20KB * 20 pathes : max 30 KB * 40 pathes : max 57 KB */ if (path_limit >= 20) break; #endif } if (tail_new_list) debug_sl_node(tail_new_list); #ifdef DEBUG if (is_goal) { i = 0; print_dbg(DEBUG_BINTREE, "Found maze goal!!!\n"); print_dbg(DEBUG_BINTREE, "tail_new_list for tail: 0x%08X\n", (unsigned int)tail_new_list); print_dbg(DEBUG_BINTREE, "*head pointer: %08X\n", (unsigned int)*head); if (tail_new_list) print_error("tail_new_list must be NULL!\n"); for (sl_node = *head; sl_node; sl_node = sl_node->node) { index = sl_node->bt_node->pos; bt_node = sl_node->bt_node; i++; } print_dbg(DEBUG_BINTREE, "Total path: %d\n", i); } #endif /* critical error to find next contour maps */ if (!is_goal && tail_new_list == NULL) { printf("contour map\n"); print_full(map); printf("maze map\n"); print_map(maze); for (sl_node = *head; sl_node; sl_node = sl_node->node) { index = sl_node->bt_node->pos; abs_dir = sl_node->bt_node->abs_dir; bt_node = sl_node->bt_node; printf("mouse:(%d,%d),abs_dir:%d\n", pos_x(index), pos_y(index), abs_dir); } } /* free s_link nodes */ if (!is_goal) { sl_node_free(*head); *head = tail_new_list; } return is_goal; }