/** * Computes the next level from src according to the strategy in result. */ static inline void compute_strategy_level(vset_t strategy_level, const int* src, const int player, const recursive_result* strategy) { // Initialise strategy level to the empty set vset_clear(strategy_level); // Find the right strategy level. For each level that contains src, there is either a transition // to the same level, or (preferrably) to a lower level. for (int i=0; i < strategy->strategy_boundary_count[player]; i++) { int begin = (i==0) ? 0 : strategy->strategy_boundaries[player][i-1]; int end = strategy->strategy_boundaries[player][i]; //printf("considering segment %d (begin=%d, end=%d).\n", i, begin, end); //assert(first <= last); assert(strategy->strategy_boundaries[player][i]<=strategy->strategy_levels_count[player]); bool src_found = false; for (int j = begin; j < end && !src_found; j++) { if (vset_member(strategy->strategy_levels[player][j], src)) { if (j==begin) { vset_union(strategy_level, strategy->strategy_levels[player][j]); //printf("choosing move from segment %d, moving from level %d to level %d.\n", i, j, j); } else { vset_union(strategy_level, strategy->strategy_levels[player][j-1]); //printf("choosing move from segment %d, moving from level %d to level %d.\n", i, j, j-1); } assert(!vset_is_empty(strategy_level)); src_found = true; } } } // strategy_level now contains any target states that can be reached from src // in one step and are conform the strategy. }
/** * \brief Computes the subset of v that belongs to player <tt>player</tt>. * \param vars the indices of variables of player <tt>player</tt>. */ static inline void add_variable_subset(vset_t dst, vset_t src, vdom_t domain, int var_index) { //Warning(info, "add_variable_subset: var_index=%d", var_index); int p_len = 1; int proj[1] = {var_pos}; // position 0 encodes the variable int match[1] = {var_index}; // the variable vset_t u = vset_create(domain, -1, NULL); vset_copy_match_proj(u, src, p_len, proj, variable_projection, match); if (debug_output_enabled && log_active(infoLong)) { double e_count; vset_count(u, NULL, &e_count); if (e_count > 0) Print(infoLong, "add_variable_subset: %d: %.*g states", var_index, DBL_DIG, e_count); } vset_union(dst, u); vset_destroy(u); }
int choose_strategy_move(const parity_game* g, const recursive_result* strategy, const int player, const int* src, int* current_player, bool* strategy_play, bool* result, bool* deadlock, int* dst) { int group = -1; vset_t level = vset_create(g->domain, -1, NULL); vset_t tmp = vset_create(g->domain, -1, NULL); vset_t singleton = vset_create(g->domain, -1, NULL); vset_add(singleton, src); // Do a random run through the game, conforming to // the strategy in result. *current_player = (vset_member(g->v_player[player], src) ? player : 1-player); Print(hre_debug, "Using strategy of player %d. The position is owned by player %d.", player, *current_player); if (*current_player==player && vset_member(strategy->win[player], src)) { //printf("Player %d chooses according to his/her winning strategy.\n", player); // Choose a transition according to the strategy of player *strategy_play = true; vset_t strategy_level = vset_create(g->domain, -1, NULL); compute_strategy_level(strategy_level, src, player, strategy); vset_clear(level); for (int i=0; i < g->num_groups; i++) { vset_next(tmp, singleton, g->e[i]); vset_intersect(tmp, strategy_level); if (!vset_is_empty(tmp)) { vset_copy(level, tmp); // Choose a random element: //printf("Choosing a transition from transition group %d.\n", i); group = i; vset_random(level, dst); break; } } // Check for deadlocks if (vset_is_empty(level)) { *deadlock = true; *result = (*current_player != player); Print(infoLong, "Deadlock for player %d, player %s has won, result is %s.", *current_player, (*current_player==1) ? "0 (even / or)" : "1 (odd / and)", *result ? "true" : "false"); } } else { //Print(info, "Not player %d's turn or player %d has no winning strategy. Choosing an arbitrary move for player %d.", // player, player, *current_player); // this states belongs to (1-player) or player does not have a winning strategy *strategy_play = false; vset_t strategy_level = vset_create(g->domain, -1, NULL); /* if (vset_member(result.win[current_player], src)) { // winning move after all compute_strategy_level(strategy_level, src, current_player, result); if (vset_is_empty(strategy_level)) { Print(info, "Unexpected: src is in win[%d], but strategy_level is empty.", current_player); } else { strategy_play = true; } } */ // choose a random move vset_clear(level); for (int i=0; i < g->num_groups; i++) { vset_next(tmp, singleton, g->e[i]); if (*strategy_play && !vset_is_empty(tmp)) { vset_intersect(tmp, strategy_level); if (!vset_is_empty(tmp)) { vset_copy(level, tmp); // Choose a random element: //printf("Choosing a transition from transition group %d.\n", i); group = i; vset_random(level, dst); break; } } else { vset_union(level, tmp); } } // Check for deadlocks if (vset_is_empty(level)) { *deadlock = true; *result = (*current_player != player); Print(infoLong, "Deadlock for player %d, player %s has won, result is %s.", *current_player, (*current_player==1) ? "0 (even / or)" : "1 (odd / and)", *result ? "true" : "false"); } else if (!*strategy_play) { //Print(info, "choose randomly"); vset_random(level, dst); } } return group; }