From f90c60b6ac082d01756fc78c7c6e6700bd933a52 Mon Sep 17 00:00:00 2001 From: Anna Wiggins Date: Sun, 3 Jul 2011 16:37:07 -0400 Subject: [PATCH] Refactored Vertex and GameVertex classes into their own files, put some functions in GameVertex that made sense there --- Makefile | 2 +- game.cpp | 4 +- gamedata.cpp | 122 +------------------------------------------------ gamedata.h | 18 +------- gamevertex.cpp | 109 +++++++++++++++++++++++++++++++++++++++++++ gamevertex.h | 36 +++++++++++++++ graph.cpp | 13 ------ graph.h | 17 +------ vertex.cpp | 13 ++++++ vertex.h | 27 +++++++++++ 10 files changed, 192 insertions(+), 169 deletions(-) create mode 100644 gamevertex.cpp create mode 100644 gamevertex.h create mode 100644 vertex.cpp create mode 100644 vertex.h diff --git a/Makefile b/Makefile index 3ab429e..acad14a 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ LDFLAGS=`sdl-config --libs` -lSDL_ttf OBJECTS=\ main.o \ drawutils.o mathutils.o timer.o itos.o \ -graph.o gamedata.o player.o \ +graph.o gamedata.o player.o vertex.o gamevertex.o \ menubutton.o \ mainevent.o gamestate.o game.o titlescreen.o diff --git a/game.cpp b/game.cpp index 7093212..ce38d8c 100644 --- a/game.cpp +++ b/game.cpp @@ -277,13 +277,13 @@ void Game::draw_stats(Vertex* v) line_num++; adj_y = y + line_num * line_height; DrawUtils::draw_text(display, "atk:", x, adj_y, font); - DrawUtils::draw_text(display, itos(data.calculate_attack(v)), + DrawUtils::draw_text(display, itos(dynamic_cast(v)->calculate_attack()), x + 50, adj_y, font); line_num++; adj_y = y + line_num * line_height; DrawUtils::draw_text(display, "armor:", x, adj_y, font); - DrawUtils::draw_text(display, itos(data.calculate_armor(v)), + DrawUtils::draw_text(display, itos(dynamic_cast(v)->calculate_armor()), x + 50, adj_y, font); line_num++; diff --git a/gamedata.cpp b/gamedata.cpp index ddb9159..64e0b0d 100644 --- a/gamedata.cpp +++ b/gamedata.cpp @@ -2,9 +2,6 @@ #include "mathutils.h" #include "debug.h" #include -#include -#include - using std::list; int GameData::PLAYER1_COLOUR = 0x4a483f; @@ -14,15 +11,6 @@ int GameData::BASE_BUILD_RADIUS = 75; int GameData::NODE_RADIUS = 10; -GameVertex::GameVertex(int x, int y, int z, int r, int colour, int score, - VertexType type, Player* player) - : Vertex(x, y, z, r, colour, score) -{ - this->type = type; - this->player = player; -} - - GameData::GameData() : Graph(true) { @@ -144,9 +132,6 @@ bool GameData::add_vertex(int x, int y, int z, int r, int colour) { if (Graph::add_vertex(v)) { -#ifdef DEBUG - fprintf(stderr, "debug: GameData::add_vertex(): strength=%2.f\n", calculate_strength(*(vertices.rbegin()))); -#endif toggle_turn(); return true; } @@ -174,11 +159,6 @@ bool GameData::add_vertex(int x, int y, int z, int r, int colour) if (Graph::add_vertex(v, current)) { -#ifdef DEBUG - fprintf(stderr, "debug: GameData::add_vertex(): strength=%.2f\n", - calculate_strength(*(vertices.rbegin()))); -#endif - toggle_turn(); return true; } @@ -188,104 +168,6 @@ bool GameData::add_vertex(int x, int y, int z, int r, int colour) } -float GameData::calculate_armor(Vertex* node) -{ - float str = calculate_strength(node); - float armor; - - switch(dynamic_cast(node)->type) - { - case VERTEX_ATTACKER: - armor = str / 10; - break; - case VERTEX_DEFENDER: - armor = str / 5; - break; - case VERTEX_PRODUCER: - armor = str / 40; - break; - } - - if (armor < 1) armor = 1; - return armor; -} - - -float GameData::calculate_attack(Vertex* node) -{ - float attack = calculate_strength(node); - - switch (dynamic_cast(node)->type) - { - case VERTEX_ATTACKER: - attack *= 1.5; - break; - case VERTEX_DEFENDER: - attack /= 0.75; - break; - case VERTEX_PRODUCER: - attack = 0; - break; - } -} - - -float GameData::calculate_strength(Vertex* node) -{ - list visited; - - // Special case - a one-node tree just returns its own score! - if (node->neighbors.empty()) 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 = node->neighbors; - 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; -} - - // This class contains logic checks to keep the mode aligned with // what is reasonable. Special cases inside the GameData class should just // do mode = MODE_ @@ -330,8 +212,8 @@ int GameData::get_range(Vertex* node) void GameData::attack_vertex(Vertex* target) { - float atk = calculate_attack(current); - float armor = calculate_armor(target); + float atk = dynamic_cast(current)->calculate_attack(); + float armor = dynamic_cast(target)->calculate_armor(); int damage = (int)(atk / armor); target->score -= damage; if (target->score <= 0) remove_vertex(target); diff --git a/gamedata.h b/gamedata.h index 0ea9dda..45bc448 100644 --- a/gamedata.h +++ b/gamedata.h @@ -8,20 +8,9 @@ #include "graph.h" #include "player.h" +#include "gamevertex.h" enum Mode {MODE_MOVE=0x1, MODE_ATTACK=0x2, MODE_BUILD=0x4, MODE_SELECT=0x8}; -enum VertexType {VERTEX_NONE=0x1, VERTEX_ATTACKER=0x2, VERTEX_DEFENDER=0x4, - VERTEX_PRODUCER=0x8}; - -class GameVertex : public Vertex -{ - public: - GameVertex(int x, int y, int z, int r, int colour = 0, int score = 0, - VertexType type = VERTEX_NONE, Player* player = NULL); - - VertexType type; - Player* player; -}; class GameData : public Graph { @@ -54,13 +43,8 @@ class GameData : public Graph // check for (and set, if needed) winner bool endgame(); Player* get_turn() const { return turn; } - float calculate_attack(Vertex* node); - float calculate_strength(Vertex* node); - float calculate_armor(Vertex* node); private: - float calculate_strength_r(Vertex* node, unsigned int depth, list& visited); - Vertex* current; Player player1, player2; Player* turn; diff --git a/gamevertex.cpp b/gamevertex.cpp new file mode 100644 index 0000000..3b5025f --- /dev/null +++ b/gamevertex.cpp @@ -0,0 +1,109 @@ +#include "gamevertex.h" +#include +#include + +GameVertex::GameVertex(int x, int y, int z, int r, int colour, int score, + VertexType type, Player* player) + : Vertex(x, y, z, r, colour, score) +{ + this->type = type; + this->player = player; +} + + +float GameVertex::calculate_armor() +{ + float str = calculate_strength(); + float armor; + + switch(type) + { + case VERTEX_ATTACKER: + armor = str / 10; + break; + case VERTEX_DEFENDER: + armor = str / 5; + break; + case VERTEX_PRODUCER: + armor = str / 40; + break; + } + + if (armor < 1) armor = 1; + return armor; +} + + +float GameVertex::calculate_attack() +{ + float attack = calculate_strength(); + + switch (type) + { + case VERTEX_ATTACKER: + attack *= 1.5; + break; + case VERTEX_DEFENDER: + attack /= 0.75; + break; + case VERTEX_PRODUCER: + attack = 0; + break; + } +} + + +float GameVertex::calculate_strength() +{ + list visited; + + // Special case - a one-node tree just returns its own score! + if (neighbors.empty()) return (float)score; + + return calculate_strength_r(this, 0, visited); +} + + +// Oh the recursive recursion! +float GameVertex::calculate_strength_r(Vertex* node, unsigned int depth, list& visited) +{ + // Find which vertices we need to visit from here + list neighbors = node->neighbors; + 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; +} diff --git a/gamevertex.h b/gamevertex.h new file mode 100644 index 0000000..314f9d4 --- /dev/null +++ b/gamevertex.h @@ -0,0 +1,36 @@ +/* This extends a normal vertex to do a bunch of game-specific stuff, + * including handling attack and defense strengths. It is used by the + * GameData class. + * + * Following the lead of the Vertex class (which is more of a glorified struct) + * this will have public data members. Don't judge me. + */ + +#ifndef _GAMEVERTEX_H_ +#define _GAMEVERTEX_H_ + +#include "vertex.h" +#include "player.h" + +enum VertexType {VERTEX_NONE=0x1, VERTEX_ATTACKER=0x2, VERTEX_DEFENDER=0x4, + VERTEX_PRODUCER=0x8}; + +class GameVertex : public Vertex +{ + public: + GameVertex(int x, int y, int z, int r, int colour = 0, int score = 0, + VertexType type = VERTEX_NONE, Player* player = NULL); + + VertexType type; + Player* player; + + float calculate_attack(); + float calculate_armor(); + + private: + float calculate_strength(); + float calculate_strength_r(Vertex* node, unsigned int depth, list& visited); + +}; + +#endif diff --git a/graph.cpp b/graph.cpp index 25b2dda..ca12678 100644 --- a/graph.cpp +++ b/graph.cpp @@ -7,8 +7,6 @@ using std::list; -Vertex::~Vertex() {} - Graph::Graph(bool planar) { this->planar = planar; @@ -158,14 +156,3 @@ void Graph::remove_vertex(Vertex* target) vertices.erase(cursor); delete target; } - - -Vertex::Vertex(int x, int y, int z, int r, int colour, int score) -{ - this->x = x; - this->y = y; - this->z = z; - this->r = r; - this->colour = colour; - this->score = score; -} diff --git a/graph.h b/graph.h index 59a7da3..6755451 100644 --- a/graph.h +++ b/graph.h @@ -17,26 +17,11 @@ #ifndef _GRAPH_H_ #define _GRAPH_H_ +#include "vertex.h" #include using std::list; -class Vertex -{ - public: - Vertex(int x, int y, int z, int r, int colour = 0, int score = 0); - virtual ~Vertex(); - - int x; - int y; - int z; - int r; - int colour; - int score; - - list neighbors; -}; - class Graph { diff --git a/vertex.cpp b/vertex.cpp new file mode 100644 index 0000000..eaccc7e --- /dev/null +++ b/vertex.cpp @@ -0,0 +1,13 @@ +#include "vertex.h" + +Vertex::Vertex(int x, int y, int z, int r, int colour, int score) +{ + this->x = x; + this->y = y; + this->z = z; + this->r = r; + this->colour = colour; + this->score = score; +} + +Vertex::~Vertex() {} diff --git a/vertex.h b/vertex.h new file mode 100644 index 0000000..cd0fe73 --- /dev/null +++ b/vertex.h @@ -0,0 +1,27 @@ +/* A graph-theory style vertex with cartesian coordinates + * + */ + +#ifndef _VERTEX_H_ +#define _VERTEX_H_ + +#include +using std::list; + +class Vertex +{ + public: + Vertex(int x, int y, int z, int r, int colour = 0, int score = 0); + virtual ~Vertex(); + + int x; + int y; + int z; + int r; + int colour; + int score; + + list neighbors; +}; + +#endif