Refactored Vertex and GameVertex classes into their own files, put some functions in GameVertex that made sense there

This commit is contained in:
Anna Rose 2011-07-03 16:37:07 -04:00
parent 8ad4ec0672
commit f90c60b6ac
10 changed files with 192 additions and 169 deletions

View File

@ -7,7 +7,7 @@ LDFLAGS=`sdl-config --libs` -lSDL_ttf
OBJECTS=\ OBJECTS=\
main.o \ main.o \
drawutils.o mathutils.o timer.o itos.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 \ menubutton.o \
mainevent.o gamestate.o game.o titlescreen.o mainevent.o gamestate.o game.o titlescreen.o

View File

@ -277,13 +277,13 @@ void Game::draw_stats(Vertex* v)
line_num++; line_num++;
adj_y = y + line_num * line_height; adj_y = y + line_num * line_height;
DrawUtils::draw_text(display, "atk:", x, adj_y, font); 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<GameVertex*>(v)->calculate_attack()),
x + 50, adj_y, font); x + 50, adj_y, font);
line_num++; line_num++;
adj_y = y + line_num * line_height; adj_y = y + line_num * line_height;
DrawUtils::draw_text(display, "armor:", x, adj_y, font); 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<GameVertex*>(v)->calculate_armor()),
x + 50, adj_y, font); x + 50, adj_y, font);
line_num++; line_num++;

View File

@ -2,9 +2,6 @@
#include "mathutils.h" #include "mathutils.h"
#include "debug.h" #include "debug.h"
#include <list> #include <list>
#include <algorithm>
#include <cassert>
using std::list; using std::list;
int GameData::PLAYER1_COLOUR = 0x4a483f; int GameData::PLAYER1_COLOUR = 0x4a483f;
@ -14,15 +11,6 @@ int GameData::BASE_BUILD_RADIUS = 75;
int GameData::NODE_RADIUS = 10; 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() GameData::GameData()
: Graph(true) : 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)) if (Graph::add_vertex(v))
{ {
#ifdef DEBUG
fprintf(stderr, "debug: GameData::add_vertex(): strength=%2.f\n", calculate_strength(*(vertices.rbegin())));
#endif
toggle_turn(); toggle_turn();
return true; 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)) if (Graph::add_vertex(v, current))
{ {
#ifdef DEBUG
fprintf(stderr, "debug: GameData::add_vertex(): strength=%.2f\n",
calculate_strength(*(vertices.rbegin())));
#endif
toggle_turn(); toggle_turn();
return true; 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<GameVertex*>(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<GameVertex*>(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<Vertex*> 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<Vertex*>& visited)
{
// Find which vertices we need to visit from here
list<Vertex*> neighbors = node->neighbors;
list<Vertex*> to_visit;
visited.push_back(node);
for (list<Vertex*>::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<Vertex*>::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 // This class contains logic checks to keep the mode aligned with
// what is reasonable. Special cases inside the GameData class should just // what is reasonable. Special cases inside the GameData class should just
// do mode = MODE_<whatever> // do mode = MODE_<whatever>
@ -330,8 +212,8 @@ int GameData::get_range(Vertex* node)
void GameData::attack_vertex(Vertex* target) void GameData::attack_vertex(Vertex* target)
{ {
float atk = calculate_attack(current); float atk = dynamic_cast<GameVertex*>(current)->calculate_attack();
float armor = calculate_armor(target); float armor = dynamic_cast<GameVertex*>(target)->calculate_armor();
int damage = (int)(atk / armor); int damage = (int)(atk / armor);
target->score -= damage; target->score -= damage;
if (target->score <= 0) remove_vertex(target); if (target->score <= 0) remove_vertex(target);

View File

@ -8,20 +8,9 @@
#include "graph.h" #include "graph.h"
#include "player.h" #include "player.h"
#include "gamevertex.h"
enum Mode {MODE_MOVE=0x1, MODE_ATTACK=0x2, MODE_BUILD=0x4, MODE_SELECT=0x8}; 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 class GameData : public Graph
{ {
@ -54,13 +43,8 @@ class GameData : public Graph
// check for (and set, if needed) winner // check for (and set, if needed) winner
bool endgame(); bool endgame();
Player* get_turn() const { return turn; } Player* get_turn() const { return turn; }
float calculate_attack(Vertex* node);
float calculate_strength(Vertex* node);
float calculate_armor(Vertex* node);
private: private:
float calculate_strength_r(Vertex* node, unsigned int depth, list<Vertex*>& visited);
Vertex* current; Vertex* current;
Player player1, player2; Player player1, player2;
Player* turn; Player* turn;

109
gamevertex.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "gamevertex.h"
#include <algorithm>
#include <cassert>
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<Vertex*> 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<Vertex*>& visited)
{
// Find which vertices we need to visit from here
list<Vertex*> neighbors = node->neighbors;
list<Vertex*> to_visit;
visited.push_back(node);
for (list<Vertex*>::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<Vertex*>::iterator cursor = to_visit.begin();
cursor != to_visit.end(); cursor++)
{
Vertex* v = *cursor;
modscore += calculate_strength_r(v, depth+1, visited);
}
return modscore;
}

36
gamevertex.h Normal file
View File

@ -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<Vertex*>& visited);
};
#endif

View File

@ -7,8 +7,6 @@
using std::list; using std::list;
Vertex::~Vertex() {}
Graph::Graph(bool planar) Graph::Graph(bool planar)
{ {
this->planar = planar; this->planar = planar;
@ -158,14 +156,3 @@ void Graph::remove_vertex(Vertex* target)
vertices.erase(cursor); vertices.erase(cursor);
delete target; 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;
}

17
graph.h
View File

@ -17,26 +17,11 @@
#ifndef _GRAPH_H_ #ifndef _GRAPH_H_
#define _GRAPH_H_ #define _GRAPH_H_
#include "vertex.h"
#include <list> #include <list>
using std::list; 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<Vertex*> neighbors;
};
class Graph class Graph
{ {

13
vertex.cpp Normal file
View File

@ -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() {}

27
vertex.h Normal file
View File

@ -0,0 +1,27 @@
/* A graph-theory style vertex with cartesian coordinates
*
*/
#ifndef _VERTEX_H_
#define _VERTEX_H_
#include <list>
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<Vertex*> neighbors;
};
#endif