Added conquering and resource spending.

This commit is contained in:
Tim Schubert 2016-01-19 22:11:23 +01:00
parent 62cba726a8
commit 4f95ed3fc0
4 changed files with 155 additions and 30 deletions

View file

@ -9,11 +9,6 @@ Player *FieldMeta::get_owner()
return this->owner;
}
void FieldMeta::set_owner(Player *player)
{
this->owner = player;
}
Field FieldMeta::get_field() { return this->field; }
void FieldMeta::render(SDL_Renderer *renderer, Layout *layout)
@ -31,7 +26,9 @@ void FieldMeta::render(SDL_Renderer *renderer, Layout *layout)
vx[i] = (Sint16) polygon[i].x;
vy[i] = (Sint16) polygon[i].y;
}
filledPolygonRGBA(renderer, vx, vy, 6, color.r, color.g, color.b, 0x22);
if ((*this->owner) == Player::default_player)
color = {0x77, 0x77, 0x77, 0x77};
filledPolygonRGBA(renderer, vx, vy, 6, color.r, color.g, color.b, 0x33);
SDL_Color inverse;
inverse.r = (Uint8) (0xff - color.r);
inverse.g = (Uint8) (0xff - color.g);
@ -95,20 +92,23 @@ Resource FieldMeta::get_resources()
return this->resources;
}
Resource FieldMeta::get_resources_of_cluster()
Resource FieldMeta::get_resources_of_cluster(Cluster cluster)
{
Resource res = {0, 0, 0};
std::unordered_set<FieldMeta *> *cluster = new std::unordered_set<FieldMeta *>();
this->get_cluster(cluster);
for (FieldMeta *elem : *cluster)
for (FieldMeta *elem : cluster)
{
Resource r_plus = elem->get_resources();
res += r_plus;
}
delete cluster;
return res;
}
Resource FieldMeta::get_resources_of_cluster()
{
Cluster cluster = this->get_cluster();
return this->get_resources_of_cluster(cluster);
}
Uint32 FieldMeta::get_upgrades() { return this->upgrades; }
bool FieldMeta::upgrade(Upgrade upgrade)
@ -132,22 +132,22 @@ bool FieldMeta::upgrade(Upgrade upgrade)
std::cout << "Unknown update: " << upgrade;
break;
}
if (cluster_resources > costs)
Resource remaining_costs = this->consume_resources_of_cluster(costs);
Resource neutral = {0, 0, 0};
if (remaining_costs == neutral)
{
this->resources -= costs;
this->upgrades |= upgrade;
return true;
}
return false;
}
std::unordered_set<FieldMeta *> *FieldMeta::get_cluster(std::unordered_set<FieldMeta *> *visited)
Cluster FieldMeta::get_cluster(Cluster visited)
{
assert(visited != nullptr);
if (visited->find(this) != visited->end()) // already been here before
if (visited.find(this) != visited.end()) // already been here before
return visited;
visited->insert(this);
visited.insert(this);
for (Uint8 i = 0; i < 6; i++)
{
@ -160,3 +160,80 @@ std::unordered_set<FieldMeta *> *FieldMeta::get_cluster(std::unordered_set<Field
}
return visited;
}
Resource FieldMeta::consume_resources_of_cluster(Resource costs)
{
Cluster cluster = this->get_cluster();
Resource cluster_resources = this->get_resources_of_cluster(cluster);
for (FieldMeta *meta : cluster)
{
// mind the "special" definition of -=, only byte of what you can chew or leave nothing behind
Resource tmp = costs;
costs -= meta->resources;
meta->resources -= tmp;
}
return costs; // > {0, 0, 0} means there were not enough resources
}
void FieldMeta::set_owner(Player *player)
{
this->owner = player;
}
FieldMeta *FieldMeta::get_meta(Field field)
{
auto pair = fields.find(field);
if (pair != fields.end())
{
return pair->second;
}
return nullptr; // no meta-information (there is no field on the map at this location)
}
bool Player::fight(Field field)
{
FieldMeta *meta = FieldMeta::get_meta(field);
if (meta == nullptr || *this == *(meta->get_owner())) // attacked field outside of the map or friendly fire
{
return false;
}
if (*(meta->get_owner()) == this->default_player) // still to be had
{
meta->set_owner(this);
return true;
}
// defending player's defense against attacking player's offense
int power_level = meta->get_defense(); // it's over 9000
Field center = meta->get_field();
for (Uint8 i = 0; i < 6; i++)
{
Field neighbor = hex_neighbor(i, center);
FieldMeta *neighbor_meta = FieldMeta::get_meta(neighbor);
if (neighbor_meta == nullptr) // there is no neighbor in this direction
{
continue;
}
if (*(neighbor_meta->get_owner()) == *this) // comparison by UUID
power_level -= neighbor_meta->get_offense();
else if (*(neighbor_meta->get_owner()) == *(meta->get_owner()))
power_level += neighbor_meta->get_defense();
// else ignore, field / player not part of the fight (e.g. default player)
}
if (power_level < 0) // attacking player has won
{
meta->set_owner(this);
return true;
}
return false;
}
int FieldMeta::get_offense()
{
return this->offense;
}
int FieldMeta::get_defense()
{
return this->defense;
}

View file

@ -9,6 +9,8 @@
#include <SDL2/SDL_render.h>
#include "Grid.hpp"
#ifndef Upgrade
typedef enum
{
UPGRADE_FIRST_UPGRADE = 0,
@ -17,6 +19,7 @@ typedef enum
UPGRADE_REGENERATION_3,
UPGRADE_REPRODUCTION
} Upgrade;
#endif
#ifndef Tagged
@ -96,6 +99,8 @@ public:
return descriptor.str();
}
bool fight(Field field);
static Player default_player;
};
@ -125,9 +130,21 @@ struct Resource
Resource &operator-=(const Resource &rhs)
{
this->circle -= rhs.circle;
this->triangle -= rhs.triangle;
this->square -= rhs.square;
if (this->circle < rhs.circle)
this->circle = 0;
else
this->circle -= rhs.circle;
if (this->triangle < rhs.triangle)
this->triangle = 0;
else
this->triangle -= rhs.triangle;
if (this->square < rhs.square)
this->square = 0;
else
this->square -= rhs.square;
return *this;
}
@ -180,10 +197,18 @@ struct Resource
inline bool operator<=(const Resource &rhs) const { return !(*this > rhs); }
inline bool operator>=(const Resource &rhs) const { return !(*this < rhs); }
bool operator==(const Resource &rhs) const
{
return (this->circle == rhs.circle && this->triangle == rhs.triangle && this->square == rhs.square);
}
inline bool operator!=(const Resource &rhs) const { return !(*this == rhs); }
};
#endif
#ifndef FieldMeta
class FieldMeta
@ -201,21 +226,34 @@ public:
this->resources_base.square = distro(rng);
std::pair<Field, FieldMeta *> pair(field, this);
this->fields.insert(pair);
this->offense = 1;
this->defense = 1;
}
int get_offense();
int get_defense();
static FieldMeta *get_meta(Field field);
Field get_field();
Player *get_owner();
void set_owner(Player *player);
//void set_owner(Player *player);
void render(SDL_Renderer *renderer, Layout *layout);
Resource get_resources();
Resource get_resources_of_cluster();
std::unordered_set<FieldMeta *> *get_cluster(std::unordered_set<FieldMeta *> *visited);
Resource get_resources_of_cluster(std::unordered_set<FieldMeta *> cluster);
std::unordered_set<FieldMeta *> get_cluster(
std::unordered_set<FieldMeta *> visited = std::unordered_set<FieldMeta *>());
Uint32 get_upgrades();
@ -223,6 +261,8 @@ public:
bool upgrade(Upgrade upgrade);
Resource consume_resources_of_cluster(Resource costs);
private:
const Field field;
static std::unordered_map<Field, FieldMeta *> fields;
@ -230,6 +270,13 @@ private:
Uint32 upgrades;
Resource resources_base; // without upgrades applied, used as basis of regeneration
Resource resources; // actual current resources
int offense;
int defense;
};
#endif
#ifndef Cluster
typedef std::unordered_set<FieldMeta *> Cluster;
#endif

View file

@ -58,7 +58,7 @@ void Game::toggle_fullscreen()
this->full_screen = true;
SDL_SetWindowSize(this->window, dm.w, dm.h);
SDL_SetWindowFullscreen(this->window, SDL_WINDOW_FULLSCREEN);
this->grid->update_box(dm.w, dm.h);
this->grid->update_box(dm.w - SIDEBOX_WIDTH, dm.h);
}
else
{
@ -135,7 +135,7 @@ int Game::game_loop()
if (move_timer->get_timer() > 10)
{
move_timer->reset_timer();
SDL_Point move_by = {(this->move[1] - this->move[3]) * 10, (this->move[0] - this->move[2]) * 10};
SDL_Point move_by = {(this->move[1] - this->move[3]) * 20, (this->move[0] - this->move[2]) * 20};
this->grid->move(move_by);
}
if (frame_timer->get_timer() > 1000.0)
@ -155,7 +155,7 @@ int Game::game_loop()
{
quit = true;
}
if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEWHEEL)
if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEWHEEL || event.type == SDL_MOUSEBUTTONDOWN)
{
grid->handle_event(&event);
}
@ -205,8 +205,8 @@ int main(int, char **)
SDL_Quit();
return -1;
}
Layout *layout = new Layout(pointy_orientation, GRID_SIZE, {5 * SCREEN_WIDTH / 12, 5 * SCREEN_HEIGTH / 12},
{0, 0, 5 * SCREEN_WIDTH / 6, 5 * SCREEN_HEIGTH / 6});
Layout *layout = new Layout(pointy_orientation, 20, {SCREEN_WIDTH / 2, SCREEN_HEIGTH / 2},
{0, 0, SCREEN_WIDTH - SIDEBOX_WIDTH, SCREEN_HEIGTH});
Game *game = new Game(window, renderer, layout);
int exit_status = game->game_loop();
delete game;

View file

@ -10,7 +10,8 @@
const Sint16 GRID_SIZE = 4;
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGTH = 600;
char TITLE[] = "Bob - Battles of Bacteria";
const int SIDEBOX_WIDTH = 200;
const char TITLE[] = "Bob - Battles of Bacteria";
#endif
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
@ -49,7 +50,7 @@ private:
SDL_Renderer *renderer;
HexagonGrid *grid;
// only deal with meta information
std::unordered_set<FieldMeta *> fields_meta;
Cluster fields_meta;
Layout *layout;
bool move[4];
bool full_screen;