logik/game.cpp
2024-12-04 12:46:56 +01:00

137 lines
3.2 KiB
C++

#include <algorithm>
#include <chrono>
#include "global.hpp"
Game::Game(int _N, int _M) : N(_N), M(_M) {
possible = vector<vector<bool>>(N, vector<bool>(M, 1));
empty_colors = vector<bool>(M, 0);
final = vector<int>(N, -1);
unsigned int seed = std::chrono::system_clock::now().time_since_epoch().count();
random_engine = std::default_random_engine(seed);
}
// Getting known information
bool Game::can(int n, int col) {
return possible[n][col];
}
vector<vector<int>> Game::get_positions_of_colors(vector<int> guess) {
auto positions_of_colors = vector<vector<int>>(M, vector<int>(0));
for(int n = 0; n < N; n++)
if(guess[n] > -1)
positions_of_colors[guess[n]].push_back(n);
return positions_of_colors;
}
int Game::final_color(int n) {
if(final[n] > -1)
return final[n];
int final_col, count = 0;
for(int col = 0; col < M; col++)
if(possible[n][col]) {
final_col = col;
count++;
}
if(count == 1) {
final[n] = final_col;
return final_col;
}
return -1;
}
bool Game::is_empty(int col) {
if(empty_colors[col])
return true;
for(int n = 0; n < N; n++)
if(possible[n][col])
return false;
empty_colors[col] = true;
return true;
}
vector<vector<int>> Game::list_all_possibilities() {
auto r = vector<vector<int>>(N, vector<int>(0));
for(int col = 0; col < M; col++)
for(int n = 0; n < N; n++)
if(possible[n][col])
r[n].push_back(col);
for(int n = 0; n < N; n++)
std::shuffle(r[n].begin(), r[n].end(), random_engine);
return r;
}
void Game::print() {
cout << " ";
for(int col = 0; col < M; col++)
cout << col;
cout << '\n';
for(int i = 0; i < N; i++) {
cout << i;
for(auto col : possible[i])
cout << col;
cout << '\n';
}
cout << '\n';
}
// Learning functions
void Game::cannot_be(int n, int col) {
possible[n][col] = false;
}
void Game::must_be(int n, int must_col) {
for(int col = 0; col < M; col++)
if(col != must_col)
possible[n][col] = 0;
}
void Game::empty_color(int col) {
for(int n = 0; n < N; n++)
possible[n][col] = 0;
}
// Specific reactions
bool Game::if_not_here_then_nowhere(vector<int> guess) {
auto positions_of_colors = get_positions_of_colors(guess);
bool learned_something = false;
// If color isn't here, it can't be in the sequence
for(int col = 0; col < M; col++) {
int possible_count = 0;
for(int n : positions_of_colors[col])
if(possible[n][col])
possible_count++;
if(possible_count == 0 && positions_of_colors[col].size() > 0 && !is_empty(col)) {
empty_color(col);
learned_something = true;
}
}
return learned_something;
}
void Game::here(vector<int> guess) {
for(int n = 0; n < N; n++)
if(guess[n] > -1 && possible[n][guess[n]])
must_be(n, guess[n]);
}
void Game::not_here(vector<int> guess) {
for(int n = 0; n < N; n++)
if(guess[n] > -1)
cannot_be(n, guess[n]);
}
void Game::empty(vector<int> guess) {
for(int col : guess)
if(col > -1)
empty_color(col);
}
void Game::all_are_here(vector<int> guess) {
auto positions_of_colors = get_positions_of_colors(guess);
for(int col = 0; col < M; col++) {
if(positions_of_colors[col].size() == 0)
empty_color(col);
}
}
// For remembering guesses with their responses
Historic_guess::Historic_guess(vector<int> _guess, Response _response) {
guess = _guess;
response = _response;
}