treewars/gamevertex.cpp

174 lines
3.8 KiB
C++
Raw Permalink Normal View History

#include "debug.h"
#include "gamevertex.h"
#include "itos.h"
#include "drawutils.h"
#include <algorithm>
#include <cassert>
TTF_Font* GameVertex::font = NULL;
SDL_Surface* GameVertex::attacker_icon = NULL;
SDL_Surface* GameVertex::defender_icon = NULL;
SDL_Surface* GameVertex::producer_icon = NULL;
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;
if (font == NULL || attacker_icon == NULL || defender_icon == NULL ||
producer_icon == NULL)
init();
}
float GameVertex::calculate_armor()
{
2011-07-06 02:28:46 +00:00
float armor = calculate_strength();
switch(type)
{
case VERTEX_ATTACKER:
2011-07-06 02:28:46 +00:00
armor *= 0.2;
break;
case VERTEX_DEFENDER:
2011-07-06 02:28:46 +00:00
armor *= 0.5;
break;
case VERTEX_PRODUCER:
2011-07-06 02:28:46 +00:00
armor *= 0.1;
break;
}
if (armor < 1) armor = 1;
return armor;
}
float GameVertex::calculate_attack()
{
float attack = calculate_strength();
switch (type)
{
case VERTEX_ATTACKER:
2011-07-06 02:28:46 +00:00
attack *= 1.25;
break;
case VERTEX_DEFENDER:
2011-07-06 02:28:46 +00:00
attack *= 0.1;
break;
case VERTEX_PRODUCER:
attack = 0;
break;
}
return attack;
}
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;
}
bool GameVertex::init()
{
font = TTF_OpenFont("res/LiberationSans-Regular.ttf", 12);
attacker_icon = DrawUtils::load("attacker_icon.bmp");
defender_icon = DrawUtils::load("defender_icon.bmp");
producer_icon = DrawUtils::load("producer_icon.bmp");
if (font == NULL || attacker_icon == NULL ||
defender_icon == NULL || producer_icon == NULL)
{
debug("GameVertex::init(): error: Couldn't load some resource(s)");
return false;
}
DrawUtils::transpare(attacker_icon);
DrawUtils::transpare(defender_icon);
DrawUtils::transpare(producer_icon);
return true;
}
void GameVertex::render(SDL_Surface* display)
{
SDL_Surface* icon;
switch (type)
{
case VERTEX_ATTACKER:
icon = attacker_icon;
break;
case VERTEX_DEFENDER:
icon = defender_icon;
break;
case VERTEX_PRODUCER:
icon = producer_icon;
break;
default:
icon = NULL;
}
DrawUtils::draw_circle_filled(display, x, y, r, colour);
if (score > 0) DrawUtils::draw_text(display, itos(score), x, y, font,
0x00ff00, true, true);
if (icon != NULL) DrawUtils::draw(display, icon, x + 5, y + 5);
}