#include "gamedata.h" #include "mathutils.h" #include "debug.h" #include #include #include using std::list; int GameData::PLAYER1_COLOUR = 0x4a483f; int GameData::PLAYER2_COLOUR = 0x090c7a; GameData::GameData() : Graph(true) { current = NULL; player = PLAYER1; mode = MODE_MOVE; } GameData::~GameData() { } void GameData::toggle_turn() { if (player == PLAYER1) player = PLAYER2; else if (player == PLAYER2) player = PLAYER1; mode = MODE_MOVE; } void GameData::do_vertex(int x, int y, int r) { if (current != NULL && (MathUtils::distance(current->x, current->y, x, y) > get_range())) { select_vertex(x, y); return; } if (mode == MODE_MOVE) { int colour; if (player == PLAYER1) colour = PLAYER1_COLOUR; if (player == PLAYER2) colour = PLAYER2_COLOUR; if (point_in_vertex(x, y, r)) select_vertex(x, y); else add_vertex(x, y, r, colour); } } void GameData::select_vertex(int x, int y) { for (list::iterator cursor = vertices.begin(); cursor != vertices.end(); cursor++) { Vertex* v = *cursor; if ((MathUtils::distance(v->x, v->y, x, y) <= v->r) && (v->colour == PLAYER1_COLOUR && player == PLAYER1 || v->colour == PLAYER2_COLOUR && player == PLAYER2)) { current = v; return; } } } bool GameData::add_vertex(int x, int y, int r, int colour) { if (mode == MODE_ATTACK) return false; // this is the special case for adding the first vertex for each player if (current == NULL) { if ((player == PLAYER1 && !player1_played) || (player == PLAYER2 && !player2_played)) { Graph::add_vertex(x, y, r, colour, 10); #ifdef DEBUG fprintf(stderr, "debug: GameData::add_vertex(): strength=%f\n", calculate_strength(*(vertices.rbegin()))); #endif if (player == PLAYER1) player1_played = true; if (player == PLAYER2) player2_played = true; toggle_turn(); return true; } return false; } if (Graph::add_vertex(x, y, r, colour, 10, current)) { #ifdef DEBUG fprintf(stderr, "debug: GameData::add_vertex(): strength=%f\n", calculate_strength(*(vertices.rbegin()))); #endif clear_current_vertex(); toggle_turn(); return true; } return false; } float GameData::calculate_strength(Vertex* node) { list visited; // Special case - a one-node tree just returns its own score! list all_nodes = get_colour(node->colour); if (all_nodes.size() == 1) return (float)node->score; return calculate_strength_r(node, 0, visited); } // Oh the recursive recursion! float GameData::calculate_strength_r(Vertex* node, unsigned int depth, list& visited) { // Find which vertices we need to visit from here list neighbors = get_neighbors(node); list to_visit; visited.push_back(node); for (list::iterator cursor = neighbors.begin(); cursor != neighbors.end(); cursor++) { Vertex* v = *cursor; // if this is true, we haven't visited the vertex on the other end of // this edge yet if (find(visited.begin(), visited.end(), v) == visited.end()) { to_visit.push_back(v); } } // This is the base case - this node has no unvisited neighbors if (to_visit.empty()) { assert(depth > 0); return (float)(node->score) / depth; } // Else, iterate through to_visit and visit them all, summing their // effective strengths adjusted for depth. // Since our trees are acyclic, this can't loop. float modscore = (float)node->score; if (depth > 0) modscore /= depth; for (list::iterator cursor = to_visit.begin(); cursor != to_visit.end(); cursor++) { Vertex* v = *cursor; modscore += calculate_strength_r(v, depth+1, visited); } return modscore; } int GameData::get_range(Vertex* node) { if (node == NULL) node = current; if (node == NULL) return 0; else if (mode == MODE_MOVE) return 100; else if (mode == MODE_ATTACK) { } } void GameData::attack_vertex(Vertex* target) { }