/** * @brief Returns the json_doc used in the head log by exact_solver and ifes solvers. * * @param [in] call_level call level value * @param [in] gp the current game position * @return the newly constucted json string */ gchar * game_tree_log_data_h_json_doc (const int call_level, const GamePosition *const gp) { gchar *ret = NULL; GString *json_doc; json_doc = g_string_sized_new(256); const gboolean is_leaf = !game_position_has_any_player_any_legal_move(gp); const SquareSet legal_moves = game_position_legal_moves(gp); const int legal_move_count = bit_works_bitcount_64(legal_moves); const SquareSet empties = board_empties(gp->board); const int empty_count = bit_works_bitcount_64(empties); const int legal_move_count_adj = legal_move_count + ((legal_moves == 0 && !is_leaf) ? 1 : 0); gchar *legal_moves_pg_json_array = square_set_to_pg_json_array(legal_moves); /* * cl: call level * ec: empty count * il: is leaf * lmc: legal move count * lmca: legal move count adjusted * lma: legal move array ([""A1"", ""B4"", ""H8""]) */ g_string_append_printf(json_doc, "\"{ \"\"cl\"\": %2d, \"\"ec\"\": %2d, \"\"il\"\": %s, \"\"lmc\"\": %2d, \"\"lmca\"\": %2d, \"\"lma\"\": %s }\"", call_level, empty_count, is_leaf ? "true" : "false", legal_move_count, legal_move_count_adj, legal_moves_pg_json_array); g_free(legal_moves_pg_json_array); ret = json_doc->str; g_string_free(json_doc, FALSE); return ret; }
/** * @brief Recursive function used to traverse the game tree. * * @param [in] result a reference to the exact solution data structure * @param [in] gp the game position to traverse * @return a pointer to a new serch node structure */ static SearchNode * game_position_solve_impl ( ExactSolution * const result, const GamePosition * const gp_old) { SearchNode *node; SearchNode *node2; node = NULL; node2 = NULL; result->node_count++; NodeInfo * const node_info = &stack->nodes[++stack->fill_point]; //NodeInfo * const next_node_info = &stack->nodes[stack->fill_point]; LegalMoveList * const moves = &node_info->moves; const SquareSet move_set = game_position_legal_moves(gp_old); legal_move_list_from_set(move_set, moves); //GamePositionX * const gp = &node_info->gp; //GamePositionX * const next_gp = &next_node_info->gp; /* GamePosition gp; uint64 hash; */ if (move_set == empty_square_set) { GamePosition *flipped_players = game_position_pass(gp_old); const int previous_move_count = stack->nodes[stack->fill_point - 1].moves.move_count; const SquareSet empties = board_empties(gp_old->board); if (empties != empty_square_set && previous_move_count != 0) { node = search_node_negated(game_position_solve_impl(result, flipped_players)); } else { result->leaf_count++; node = search_node_new((Square) -1, game_position_final_value(gp_old)); } flipped_players = game_position_free(flipped_players); } else { node = search_node_new((Square) -1, -65); for (int i = 0; i < moves->move_count; i++) { const Square move = moves->squares[i]; GamePosition *gp2 = game_position_make_move(gp_old, move); node2 = search_node_negated(game_position_solve_impl(result, gp2)); gp2 = game_position_free(gp2); if (node2->value > node->value) { search_node_free(node); node = node2; node->move = move; node2 = NULL; } else { node2 = search_node_free(node2); } } } stack->fill_point--; return node; }