@@ -0,0 +1,242 @@
#include <string>
#include "area.h"

Area::Area(Direction* d) {
first = capacity/2;
last = first;
face = d;
}

void Area::swap_objects(unsigned int i, unsigned int j) {
Object* temp = vassals[i];
vassals[i] = vassals[j];
vassals[j] = temp;
}

/**
* Returns the index of the first found Object with Point p,
* or index of first Object with Point in front of p (if no such Object exists in vassals)
* Searches from start_i to end_i (exclusive)
*/
unsigned int Area::find_index(Point* p, unsigned int start_i, unsigned int end_i) {
unsigned int si = start_i, ei = end_i;
while (ei-si > 1) {
int c = compare(p, vassals[(si+ei)/2]->get_pos(), *face);
if (c == 0) { return (si+ei)/2; }
else if (c > 0) { si = (si+ei)/2; }
else { ei = (si+ei)/2; }
}
if (compare(p, vassals[si]->get_pos(), *face) >= 0) {
while (si >= start_i && compare(p, vassals[si]->get_pos(), *face) >= 0) {
si--;
}
return (si+1);
} else {
while (si < end_i && compare(p, vassals[si]->get_pos(), *face) < 0) {
si++;
}
return si;
}
}

/**
* Finds the specific place for the object and sorts it to that location
*/
void Area::resort_object(unsigned int index) {
unsigned int k = find_index(vassals[index]->get_pos(), first, index);
if (k < index) {
Object* temp = vassals[index];
for (unsigned int i = index; i > k; i--) {
vassals[i] = vassals[i-1];
}
vassals[k] = temp;
} else {
k = find_index(vassals[index]->get_pos(), index+1, last);
if (k > index) {
Object* temp = vassals[index];
for (unsigned int i = index; i < k-1; i++) {
vassals[i] = vassals[i+1];
}
vassals[k-1] = temp;
}
}
}

/**
* Sorts everything from si to ei, ei inclusive
* Uses quicksort, always choosing (si+ei)/2 as the pivot
*/
void Area::resort(unsigned int si, unsigned int ei) {
if (ei-si <= 1) { return; }
swap_objects((si+ei)/2, ei);
Point* pivot = vassals[ei]->get_pos();
unsigned int i = si;
for (unsigned int j = i; j < ei; j++) {
if (compare(vassals[j]->get_pos(), pivot, *face) <= 0) {
swap_objects(j, i++);
}
}
swap_objects(i, ei);
resort(si, i-1);
resort(i+1, ei);

/*
unsigned int mi = (si+ei)/2;
resort(si, mi);
resort(mi, ei);
unsigned int l = si;
unsigned int r = mi;
if (compare(vassals[l]->get_pos(), vassals[r]->get_pos(), wrapper->get_face()) <= 0) { return true; }
while (l < mi && r < ei) {
if (compare(vassals[l]->get_pos(), vassals[r]->get_pos(), wrapper->get_face()) > 0) {
Object* temp = vassals[r];
for (int i = r; i > l; i--) {
vassals[i] = vassals[i-1];
}
vassals[l] = temp;
mi++; r++;
}
l++;
}
return false;
*/
}

unsigned int Area::find_index(Point* p) {
return find_index(p, first, last);
}

bool Area::add(Object* o) {
return add(o, o->get_pos());
}

bool Area::add(Object* o, Point* p) {
bool add_before = (compare(p, vassals[(first+last)/2]->get_pos(), *face) <= 0);
if ((add_before && first == 0) || (!add_before && last == capacity)) {
unsigned int new_capacity = capacity*3/2;
if (new_capacity < capacity) { throw std::string("Too many objects in area."); }
Object** new_vassals = new Object*[new_capacity]();
unsigned int m = (add_before ? (capacity/2)-1 : 0);
for (unsigned int i = first+m; i < last; i++) {
if ((m == 0 || m == (capacity/2)-1) && compare(p, vassals[i-m]->get_pos(), *face) < 0) {
new_vassals[i] = o;
m++;
} else {
new_vassals[i] = vassals[i-m];
}
}
if (add_before) { first--; }
else { last++; }

delete[] vassals;
vassals = new_vassals;
capacity = new_capacity;
} else {
unsigned int index = (add_before ? (--first) : (last++));
vassals[index] = o;
resort_object(index);
}
return true;

/*
if (last == capacity) {
unsigned int new_capacity = capacity*7/4;
if (new_capacity < capacity) { throw std::string("Too many objects in area."); }
Object** new_vassals = new Object*[new_capacity];
bool added = false;
for (int i = 0; i < last; i++) {
if (added) {
new_vassals[i+1] = vassals[i];
} else if (compare(p, vassals[i]->get_pos(), face) < 0) {
new_vassals[i] = o;
new_vassals[i+1] = vassals[i];
added = true;
} else {
new_vassals[i] = vassals[i];
}
}
} else {
unsigned int index = find_index(p);
for (unsigned int i = last-1; i > index; i--) {
vassals[i] = vassals[i-1];
}
vassals[index] = o;
}
last++;
return true;
*/
}

Object* Area::discard(Object* o) {
unsigned int index = find_index(o->get_pos());
if (vassals[index] != o) {
for (unsigned int i = index; i < last; i++) {
if (vassals[i] == o) {
index = i;
break;
} else if (i == last-1 || compare(o->get_pos(), vassals[i]->get_pos(), *face) != 0) {
throw std::string("Attempted to delete Object not in Area.");
}
}
}

if (index <= (first+last)/2) {
for (unsigned int i = index; i > first; i--) {
vassals[i] = vassals[i-1];
}
vassals[first++] = NULL;
} else {
for (unsigned int i = index; i < last-1; i++) {
vassals[i] = vassals[i+1];
}
vassals[--last] = NULL;
}
return o;

/*
unsigned int i = index;
while (vassals[i] != o) {
if (i >= last-1 || compare(o->get_pos(), vassals[i]->get_pos(), wrapper->get_face()) != 0) {
break;
} else {
i++;
}
}
if (vassals[i] == o) {
index = i;
} else {
i = index;
while (vassals[i] != o) {
if (i <= first || compare(o->get_pos(), vassals[i]->get_pos(), wrapper->get_face()) != 0) {
break;
} else {
i--;
}
}
if (vassals[i] == o) {
index = i
} else {
throw std::string("Attempted to delete Object not in Area.");
}
}
}
bool del_before =
for (unsigned int i = last-1; i > index; i--) {
vassals[i-1] = vassals[i];
}
return o;
*/
}

Object* Area::get(Point* p) {
unsigned int index = find_index(p);
if (compare(p, vassals[index]->get_pos(), *face) != 0) {
throw 0;
} else {
return vassals[index];
}
}

@@ -0,0 +1,33 @@
#ifndef AREA_H
#define AREA_H

#include "lord.h"
#include "geometry.h"
#include "object.h"

class Area: public Lord<Object*, Point*> {
private:
unsigned int first;
unsigned int last;

Direction* face;

void swap_objects(unsigned int, unsigned int);
unsigned int find_index(Point*, unsigned int, unsigned int);
void resort_object(unsigned int);
void resort(unsigned int, unsigned int);
unsigned int find_index(Point*);

public:
Area(Direction*);

bool add(Object*);
bool add(Object*, Point*);
Object* discard(Object*);
Object* get(Point*);
void resort_all() { resort(0, last-1); }

void set_face(Direction* d) { face = d; }
};

#endif // AREA_H
BIN +1.04 MB (110%) adventure/bin/Debug/adventure.exe
Binary file not shown.
@@ -3,32 +3,61 @@

using namespace std;

void Parametrized::add_param(string key, void* value) {
params.insert( {{key, value}} );

Parametrized::Parametrized() {
add_param<shared_ptr<Parametrized> >(0, shared_ptr<Parametrized>(this));
add_param<shared_ptr<Parametrized> >(1, nullptr);
}

template <class T>
void Parametrized::add_param(unsigned int key, T value) {
shared_ptr<Param> p(new TypedParam<T>(value));
pair<unsigned int, shared_ptr<Param> > q(key, p);
params.insert(q);
// {{ key, new TypedParam<T>(value) }} );
}

void Parametrized::set_param(string key, void* value) {
unordered_map<string, void*>::iterator iter = params.find(key);
template <class T>
void Parametrized::set_param(unsigned int key, T value) {
unordered_map<unsigned int, shared_ptr<Param> >::iterator iter = params.find(key);
if (iter == params.end()) {
add_param(key, value);
} else {
iter->second = value;
iter->second = shared_ptr<Param>(new TypedParam<T>(value));
}
}

void* Parametrized::get_param(string key) {
unordered_map<string, void*>::iterator iter = params.find(key);
bool Parametrized::check_param(unsigned int key) {
unordered_map<unsigned int, shared_ptr<Param> >::iterator iter = params.find(key);
return (iter != params.end());
}

shared_ptr<Param> Parametrized::get_param(unsigned int key) {
unordered_map<unsigned int, shared_ptr<Param> >::iterator iter = params.find(key);
if (iter == params.end()) {
if (inherit == NULL) {
throw string("Attempted to access undefined parameter ").append(key).append(".");
if (shared_ptr<TypedParam<shared_ptr<Parametrized> > > inherit =
static_pointer_cast<TypedParam<shared_ptr<Parametrized> > >(get_param(1))) {
return inherit->data->get_param(key);
} else {
return inherit->get_param(key);
throw string("Attempted to access undefined parameter.");
}
} else {
return iter->second;
}
}

template <class T>
T Parametrized::get_param(unsigned int key) {
shared_ptr<Param> value = get_param(key);
if (value == nullptr) {
return nullptr;
} else if (shared_ptr<TypedParam<T> > typed_value = static_pointer_cast<TypedParam<T> >(value)) {
return typed_value->data;
} else {
throw string("Could not cast member to desired type.");
}
}

/*
void FormData::execute(string key) {
if (Script* value = dynamic_cast<Script*>(get_param(key))) {
@@ -56,16 +85,32 @@ Form* FormData::create() {
}
*/

void* Article::get_param(string key) {
smatch match;
if (regex_match(key, match, regex("(.*)\.(.*)"))) {
void* first = get_param(match.str(1));
if (Parametrized* prmtrs = static_cast<Parametrized*>(first)) {
return prmtrs->get_param(match.str(2));
Article::Article(Parametrized* p) {
set_param<shared_ptr<Parametrized> >(1, shared_ptr<Parametrized>(p));
}


shared_ptr<Param> Article::get_param_chain(vector<unsigned int>* keys) {
shared_ptr<Param> p = get_param(0);
for (vector<unsigned int>::iterator iter = keys->begin(); iter < keys->end(); ++iter) {
if (shared_ptr<TypedParam<shared_ptr<Parametrized> > > tp =
static_pointer_cast<TypedParam<shared_ptr<Parametrized> > >(p)) {
p = tp->data->get_param(*iter);
} else {
throw string(match.str(1)).append(" has no parameter ").append(match.str(2)).append(".");
throw string("Tried to access member which does not exist.");
}
}
return p;
}

template <class T>
T Article::get_param_chain(vector<unsigned int>* keys) {
shared_ptr<Param> value = get_param_chain(keys);
if (value == nullptr) {
return nullptr;
} else if (shared_ptr<TypedParam<T> > typed_value = static_pointer_cast<TypedParam<T> >(value)) {
return typed_value->data;
} else {
return Parametrized::get_param(key);
throw string("Could not cast member to desired type.");
}
}
@@ -1,8 +1,9 @@
#ifndef DATA_H
#define DATA_H

#include <memory>
#include <unordered_map>
#include <string>
#include <vector>
//#include "form.h"

/*
@@ -16,15 +17,26 @@ enum class UnderlyingClassData {
};
*/

struct Param {};

template <class T>
struct TypedParam: public Param {
T data;
TypedParam(T t) : data(t) {}
};


class Parametrized {
private:
Parametrized* inherit;
std::unordered_map<std::string, void*> params;
std::unordered_map< unsigned int, std::shared_ptr<Param> > params;
public:
Parametrized(Parametrized* p) : inherit(p) {}
void add_param(std::string, void*);
void set_param(std::string, void*);
virtual void* get_param(std::string);
Parametrized();

template <class T> void add_param(unsigned int, T);
template <class T> void set_param(unsigned int, T);
bool check_param(unsigned int);
std::shared_ptr<Param> get_param(unsigned int);
template <class T> T get_param(unsigned int);
};

/*
@@ -53,8 +65,11 @@ class FormData: public TypeData {

class Article: public Parametrized {
public:
Article(Parametrized* p) : Parametrized(p) {}
void* get_param(std::string);
Article() {}
Article(Parametrized*);

std::shared_ptr<Param> get_param_chain(std::vector<unsigned int>*);
template <class T> T get_param_chain(std::vector<unsigned int>*);
};

#endif // DATA_H
@@ -1,43 +1,133 @@
type Container: class Container {}
/**

def containerFormWidget: class Widget {
P R E D E F I N E D T Y P E S

VISIBLE OBJECTS
- Form the basic type for anything visible, can't be used on anything
* fixed flag: can the Form change position? (default = FALSE)
* x the x-coordinate of the Form
* y the y-coordinate of the Form
* sprite the sprite for the Form, as a path
* lord the thing that contains the Form
# INIT the Script for when the Form is created
# LEFT_CLICK the Script for when the Form is left-clicked
# RIGHT_CLICK the Script for when the Form is right-clicked
# DRAG_RELEASE the Script for when an Object is dragged onto the Form
- Menu(Form) container for Widgets
* vassals the Widgets in the Menu
# ADD the Script for when an outside call is made to add(Widget), returns TRUE if Widget should be added
- Widget(Form) buttons, labels, stuff in a Menu
- Object(Form) an actual object in the game
- Item(Object) an item of some sort
- Container(Item) an Item that can store other Items
* vassals the Items in the Container
# ADD the Script for when an outside call is made to add(Item), returns TRUE if Item should be added
- Entity(Object) an Object that has its own agency
* agent the Agent for the Entity
- Attired(Entity) an Entity that can put on Items
* vassals the Items on the Attired
# ADD the Script for when an outside call is made to add(Item), returns TRUE if Item should be added

OTHER TYPES
- Agent : the AI for an Entity


P R E D E F I N E D V A R S

this reference to the thing (specific to thing)
ui the UI, which holds all the Menus
*drag DRAG_RELEASE parameter, the Object dragged onto the Form
*addForm ADD parameter, the Form being added
*addX ADD parameter, the x-coordinate to add the Form at
*addY ADD parameter, the y-coordinate to add the Form at


D E F I N I T I O N S

type inherited type
params parameters for creating the thing
constraints constraints for parameters
scripts defined/overridden Scripts

**/

def Menu {
scripts {
ADD {
return TRUE;
}
}
}

def containerFormWidget {
type Widget
params {
contX
contX,
contY
}
DRAG_RELEASE {
lord.access.add(drag, i, j)
scripts {
DRAG_RELEASE {
lord.access.add( drag, contX, contY );
}
}
}

def containerWindow: class AccessMenu {
def containerWindow {
type Menu
params {
access
}
constraints {
access.type == Container
}
INIT {
range(i, 0, access.width) {
range(j, 0, access.height) {
add(containerFormWidget(contX=i, contY=j), 10*i, 10*j)
scripts {
INIT {
for (i = 0; i < access.width; i++) {
for (j = 0; j < access.height; j++) {
add( containerFormWidget( contX = i, contY = j ), 10*i, 10*j );
}
}
}
}
}

type Item: class Item {
RIGHT_CLICK {
// open a window to view description and actions
}
}

type Container: class Container {
def Item {
params {
width
width,
height
}
LEFT_CLICK {
// open a window to view items
scripts {
RIGHT_CLICK {
// open a window to view description and actions
}
}
DRAG_RELEASE {
// add dropped object to self
}

def Container {
scripts {
LEFT_CLICK {
ui.add(containerWindow( access = this ));
}
DRAG_RELEASE {
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
if (add(drag, i, j)) {
return;
}
}
}
}
ADD {
for (i = 0; i < vassals.length; i++) {
if (addX >= vassals[i].x+vassals[i].width ||
addX+addForm.width <= vassals[i].x ||
addY >= vassals[i].y+vassals[i].height ||
addY+addForm.height <= vassals[i].y) {
return FALSE;
}
}
return TRUE;
}
}
}

@@ -40,6 +40,8 @@ void show_error_message(const char* message) {

State* state;

State* get_state() { return state; }

void set_state(State* s) {
delete state;
state = s;
@@ -0,0 +1,15 @@
#include <memory>
#include "form.h"
#include "script.h"

Form::Form(Parametrized* p) : Article(p) {
shape.center = &pos;
}

void Form::execute(unsigned int key) {
std::shared_ptr<Script> s = nullptr;// this->get_param<std::shared_ptr<Script> >(key);
//get_param<std::shared_ptr<Script> >(key);
if (s != nullptr) {
s->execute();
}
}
@@ -0,0 +1,25 @@
#ifndef FORM_H
#define FORM_H

#include <string>
#include "data.h"
#include "lord.h"
#include "geometry.h"

class Form: public Article {
protected:
Lord<Form*, Point*>* lord;

Point pos;
Shape shape;

public:
Form() {}
Form(Parametrized*);

Point* get_pos() { return &pos; }

void execute(unsigned int);
};

#endif // FORM_H
@@ -0,0 +1,102 @@
#include <cmath>
#include "geometry.h"

/**
* Returns the relative direction of v with respect to d
*/
Direction rel_dir(Direction v, Direction d) {
return static_cast<Direction>(((int)d-(int)v+10)%8);
}

/**
* Converts Point p to Direction
*/
Direction point_to_dir(Point* p) {
int a = (int)round(atan2(-p->y, p->x)*4/3.1415926535);
return static_cast<Direction>((a+8)%8);
}

/**
* Converts Direction d to Point
*/
Point* dir_to_point(Direction d) {
Point* p = new Point();
if (d >= Direction::NORTHWEST && d <= Direction::SOUTHWEST) {
p->x = -1;
} else if ((d >= Direction::EAST && d <= Direction::NORTHEAST) || d == Direction::SOUTHEAST) {
p->x = 1;
}
if (d >= Direction::NORTHEAST && d <= Direction::NORTHWEST) {
p->y = -1;
} else if (d >= Direction::SOUTHWEST && d <= Direction::SOUTHEAST) {
p->y = 1;
}
return p;
}

/**
* Returns new Point translated in Direction d by distance dist
*/
Point* translate(Point* p, Direction d, int dist) {
Point* v = dir_to_point(d);
return new Point(p->x+(dist*v->x), p->y+(dist*v->y), p->z);
}

/**
* Returns 1 if p1 is in front of p2
* -1 if p1 is behind p2
* 0 if p1 equals p2 relative to dir
*/
int compare(Point* p1, Point* p2, Direction dir) {
if (p1->x == p2->x && p1->y == p2->y && p1->z == p2->z) { return 0; }
int x1 = p1->x;
int y1 = p1->y;
int x2 = p2->x;
int y2 = p2->y;
if (dir >= Direction::SOUTH || dir <= Direction::NORTHEAST) {
x1 = MAX_VALUE-x1;
x2 = MAX_VALUE-x2;
}
if (dir >= Direction::WEST) {
y1 = MAX_VALUE-y1;
y2 = MAX_VALUE-y2;
}
int v1 = x1+y1;
int v2 = x2+y2;
int d = static_cast<int>(dir);
if (d%2 == 0) {
if (d%4 == 0) {
v1 = x1;
v2 = x2;
} else {
v1 = y1;
v2 = y2;
}
}
if (v1 > v2) {
return 1;
} else if (v1 < v2) {
return -1;
} else {
if ((d/2)%2 == 0) {
v1 = y1;
v2 = y2;
} else {
v1 = x1;
v2 = x2;
}
if (v1 > v2) {
return 1;
} else if (v1 < v2) {
return -1;
} else {
if (p1->z > p2->z) {
return 1;
} else if (p1->z < p2->z) {
return -1;
} else {
return 0;
}
}
}
}
@@ -0,0 +1,40 @@
#ifndef GEOMETRY_H
#define GEOMETRY_H

const int MAX_VALUE = 2048;

enum class Direction : int {
EAST = 0,
NORTHEAST = 1,
NORTH = 2,
NORTHWEST = 3,
WEST = 4,
SOUTHWEST = 5,
SOUTH = 6,
SOUTHEAST = 7
};

struct Point {
int x;
int y;
int z;
Point() {}
Point(int a, int b) : x(a%MAX_VALUE), y(b%MAX_VALUE) {}
Point(int a, int b, int c) : x(a%MAX_VALUE), y(b%MAX_VALUE), z(c%MAX_VALUE) {}
};

struct Shape {
Point* center;
int dx;
int dy;
int dz;
};

Direction rel_dir(Direction, Direction);
Direction point_to_dir(Point*);
Point* dir_to_point(Direction);
Point* translate(Point*, Direction, int=1);

int compare(Point*, Point*, Direction=Direction::NORTH);

#endif // GEOMETRY_H
@@ -0,0 +1,25 @@
#ifndef INTELLIGENCE_H
#define INTELLIGENCE_H

enum class AIMode : int {
MANUAL = 0, // under manual control of player PC
ATTACK_SAME = 1, // attacks same target as PC ally
ATTACK_WEAK = 2, // attacks weakest threat
ATTACK_STRONG = 3, // attacks strongest threat
ATTACK_CLOSEST = 4, // attacks closest threat
PROTECT = 5, // attack anyone who attacks targeted ally
TARGET = 6, // target a specific enemy enemy
DISTANCE = 7, // attacks from distance, if possible
PACIFIST = 8, // don't attack, stay at distance
FLEE = 9 // don't attack, run away
};

class Agent {
private:
AIMode mode;
public:
AIMode get_mode() { return mode; }
void set_mode(AIMode m) { mode = m; }
};

#endif // INTELLIGENCE_H
@@ -5,6 +5,38 @@

using namespace std;


FileLoader::FileLoader(Module* m) {
module = m;
add_key(string("this"));
add_key(string("inherit"));
add_key(string("Form"));
add_key(string("Widget"));
add_key(string("Menu"));
add_key(string("Object"));
add_key(string("Item"));
add_key(string("Container"));
add_key(string("Entity"));
add_key(string("Attired"));
}

unsigned int FileLoader::add_key(string key) {
unsigned int ikey = (unsigned int)keymap.size();
keymap.insert( {{ key, ikey }} );
return ikey;
}

unsigned int FileLoader::get_key(string key) {
unordered_map<string, unsigned int>::iterator iter = keymap.find(key);
if (iter == keymap.end()) {
return add_key(key);
} else {
return iter->second;
}
}


/*
Script* FileLoader::load_script() {
load_script(string(""));
}
@@ -80,27 +112,205 @@ ConditionalScript* FileLoader::load_conditional_script(bool after) {
}
}
}
}*/

/*
void* FileLoader::load_value(string s, unordered_map<std::string, void*> local_vars) {
cmatch match;
if (s.empty() || s.compare("null") == 0) { return NULL; }
if (regex_match(s, match, regex("(.+)\.(([^\(\)]+)(\(.*\))?)"))) {
if (TypeData* d = dynamic_cast<TypeData*>(load_value(match.str(1)))) {
if (match.str(4).compare(string("")) != 0) {
// 5 = parameters for function
} else {
return d->get_param(match.str(3));
}
} else {
throw string(match.str(1)).append(" does not have member ").append(match.str(3)).append(".");
}
}
unordered_map<std::string, void*>::iterator it = local_vars.find(s);
if (it != local_vars.end()) {
return it->second;
}
it = global_vars.find(s);
if (it != global_vars.end()) {
return it->second;
}
}
unsigned int FileLoader::load_conditional(Script* s, string* str, string::iterator* iter) {
unsigned int r_value = 0;
regex or_c("\|\|");
regex and_c("&&");
unsigned int cnd = 0;
string input;
while (*iter < str->end()) {
if (**iter == '(') {
if (cnd > 0) { throw string("Unexpected token '('."); }
cnd = load_conditional(s, str, iter);
} else {
input.append(**iter);
++(*iter);
if (regex_match(*str, or_c)) {
r_value = s->append(ScriptType::OR);
if (cnd == 0) {
delete s;
throw string("No first clause for '||' token.");
}
s->append(cnd);
unsigned int second = s->append(ScriptType::END);
s->set_value(second, load_conditional(s, str, iter));
return second;
} else if (regex_match(*str, and_c)) {
r_value = s->append(ScriptType::AND);
if (cnd == 0) {
delete s;
throw string("No first clause for '&&' token.");
}
s->append(cnd);
unsigned int second = s->append(ScriptType::END);
s->set_value(second, load_conditional(s, str, iter));
return second;
}
}
}
}
unsigned int FileLoader::load_conditional(Script* s) {
}
unsigned int FileLoader::load_script(Script* s, unsigned int fsi) {
unsigned int first_index = s->last_index();
regex end_script("\}");
regex if_c("\bif\(");
regex else_c("\belse\{");
regex elseif_c("\belseif\(");
regex for_c("\bfor\((.*);(.*);(.*)\)\{");
string input;
while (add_char(&input) && !regex_match(input, end_script)) {
if (regex_match(input, if_c) || (regex_match(input, elseif_c) && fsi > 0)) {
if (fsi > 0) {
s->set_value(fsi, s->append(ScriptType::IF));
fsi = 0;
} else {
s->append(ScriptType::IF);
}
unsigned int eval = s->append(ScriptType::END);
unsigned int ts = s->append(ScriptType::END);
unsigned int fs = s->append(ScriptType::END);
unsigned int as = s->append(ScriptType::END);
input.clear();
s->set_value(eval, load_conditional(s));
if (add_char(&input) && regex_match(input, regex("\{")) {
s->set_value(ts, load_script(s));
} else {
delete s;
throw string("Expected '{', received '").append(input).append("'.");
}
s->set_value(as, load_script(s, fs));
} else if (regex_match(input, else_c) && fsi > 0) {
s->set_value(fsi, load_script(s));
fsi = 0;
first_index = s->last_index();
} else if regex_match(input, match, for_c) {
char FileLoader::get_char() {
if (buffer[b_index] == '\0' || l_no < 0) {
}
}
s->append(ScriptType::END);
return first_index;
}*/

regex whitespace("\s");
regex definition("(.*)\{");
regex line_end("(.*);");
regex var_def("(\w[^=]*)(=(.+))?");

void FileLoader::load(ALLEGRO_FILE* f) {
file = f;
l_no = -1;

try {
/*
smatch match;
regex type_def("type(\w.*)");
regex form_def("def(\w.*)");
regex script_def("(\w[^=]*)=(script)?");
string input;
while (add_char(&input)) {
if (regex_match(input, match, definition)) {
smatch def_match;
if (regex_match(match.str(1), def_match, type_def)) {
data.insert( {{ def_match.str(1), load_type() }} );
input.clear();
} else if (regex_match(match.str(1), def_match, form_def)) {
data.insert( {{ def_match.str(1), load_form() }} );
input.clear();
} else if (regex_match(match.str(1), def_match, script_def)) {
global_vars.insert( {{ def_match.str(1), load_script() }} );
} else {
throw string("Unrecognized qualifier before '{' token.");
}
} else if (regex_match(input, match, line_end)) {
cmatch def_match;
if (regex_match(match.str(1), def_match, var_def)) {
global_vars.insert( {{ def_match.str(1), load_value(def_match.str(3)) }} );
} else {
throw string("Unrecognized line format.");
}
}
}
*/
} catch (string s) {
// generate error message
}
}

bool FileLoader::add_char(string* s) {
if (b_index < 127 && buffer[b_index] == '/' && buffer[b_index+1] == '*') {
while (true) {
if (b_index < 127 && buffer[b_index] == '*' && buffer[b_index+1] == '/') {
b_index += 2;
break;
} else {
if (b_index >= 128 || buffer[b_index] == '\0'){
if (al_fgets(file, buffer, sizeof(buffer))) {
l_no++;
b_index = 0;
} else if (al_feof(file)) {
return false;
} else if (al_ferror(file)) {
throw string(al_ferrmsg(file));
}
} else {
b_index++;
}
}
}
}
if (b_index >= 128 || buffer[b_index] == '\0' || l_no < 0 || (b_index < 127 && buffer[b_index] == '/' && buffer[b_index+1] == '/')) {
if (al_fgets(file, buffer, sizeof(buffer))) {
l_no++;
b_index = 0;
return buffer[b_index++];
return add_char(s);
} else if (al_feof(file)) {
throw 0;
return false;
} else if (al_ferror(file)) {
throw string(al_ferrmsg(file));
}
} else {
return buffer[b_index++];
if (!regex_match(&buffer[b_index], whitespace)) {
s->append(&buffer[b_index++]);
return true;
} else {
b_index++;
return add_char(s);
}
}
}

void FileLoader::load(ALLEGRO_FILE* f) {
file = f;
l_no = -1;
line.clear();
}
@@ -3,42 +3,51 @@

#include <allegro5/allegro.h>
#include <string>
#include "script.h"

struct FormData {
unsigned int hashID;
std::string formID;
int classID;
int spriteID;

std::string name;
std::string desc;
int flags;

int* params;
};
#include <unordered_map>
// #include "script.h"
#include "data.h"
#include "module.h"

const int FILE_LOAD_BUFFER_SIZE = 128;

class FileLoader {
private:
Module* module;
ALLEGRO_FILE* file;

std::unordered_map<std::string, unsigned int> keymap;
// unordered_map<std::string, void*> global_vars;
unsigned int add_key(std::string);
unsigned int get_key(std::string);
void* get_value(std::string);

char buffer[FILE_LOAD_BUFFER_SIZE];
int b_index;
int l_no;

bool add_char(std::string*);
char* get_char();

public:
FileLoader(Module*);

void load(ALLEGRO_FILE*);

};

/*
Script* load_script();
Script* load_script(std::string);
BooleanScript* load_boolean_script();
ConditionalScript* load_conditional_script(bool);
*/

FormData* load_form();
/*unsigned int load_script(Script*);
unsigned int load_conditional(Script*);
void* load_var();
FormData* load_form();*/

public:
void load(ALLEGRO_FILE*);
};

#endif // LOADER_H
@@ -0,0 +1,23 @@
#ifndef LORD_H
#define LORD_H

template <class T, class P>
class Lord {
protected:
unsigned int capacity;
T* vassals;

public:
Lord() {
capacity = 8;
vassals = new T[capacity];
}

virtual bool add(T) = 0;
virtual bool add(T, P) = 0;
virtual T discard(T) = 0;
virtual T get(P) = 0;

};

#endif // LORD_H
@@ -1,73 +1,30 @@
#include <cmath>
#include "module.h"
#include "loader.h"

unsigned int data_hash(std::string formID, unsigned int value) {
unsigned int hashing = 0;
for (int i = 0; i < formID.length(); i++) {
hashing = (hashing + (int)((1 + (pow(value, 0.25)*i) + (pow(value, 0.33)*pow(i, 2)) + (pow(value, 0.5)*pow(i, 3))) *
pow((int)(formID[i]), 2))) % value;
}
return hashing;
}
using namespace std;


Module::Module() {
form_data = new FormData*[10]();
shared_ptr<Parametrized> Module::add_data(unsigned int key) {
shared_ptr<Parametrized> p(new Parametrized());
pair<unsigned int, shared_ptr<Parametrized> > q(key, p);
data.insert(q);
return p;
}

unsigned int Module::add(FormData* data) {
unsigned int index = data_hash(data->formID, length);
while (form_data[index] != NULL) {
index = (index+1)%length;
}
form_data[index] = data;
load++;
if (load > (unsigned int)(0.75*length)) {
return rehash(index);
shared_ptr<Parametrized> Module::get_data(unsigned int key) {
unordered_map<unsigned int, shared_ptr<Parametrized> >::iterator iter = data.find(key);
if (iter == data.end()) {
return add_data(key);
} else {
return index;
return iter->second;
}
}

unsigned int Module::rehash(unsigned int idx) {
unsigned int return_value;
unsigned int new_length = (unsigned int)(length * 1.75);
FormData** new_data = new FormData*[new_length]();
for (unsigned int i = 0; i < length; i++) {
unsigned int index = data_hash(form_data[i]->formID, new_length);
while (index != NULL) {
index = (index+1)%new_length;
}
new_data[index] = form_data[i];
new_data[index]->hashID = index;
if (i == idx) { return_value = index; }
void Module::load_modules(vector<ALLEGRO_FS_ENTRY*> files) {
FileLoader loader(this);
for (vector<ALLEGRO_FS_ENTRY*>::iterator iter = files.begin(); iter < files.end(); ++iter) {
ALLEGRO_FILE* file = al_open_fs_entry(*iter, "r");
loader.load(file);
// TODO close file
}
// reassign hash pointers
delete form_data;
form_data = new_data;
return return_value;
}

FormData* Module::get(std::string formID) {
unsigned int index = data_hash(formID, length);
unsigned int number = 0;
while (number < length && form_data[index] != NULL && form_data[index]->formID.compare(formID) != 0) {
index = (index + 1)%length;
number++;
}
if (form_data[index]->formID.compare(formID) == 0) {
return form_data[index];
} else {
return NULL;
}
}

FormData* Module::get(unsigned int index) {
return form_data[index];
}

void Module::load_form_data(ALLEGRO_FS_ENTRY* filepath) {
ALLEGRO_FILE* file = al_open_fs_entry(filepath, "r");
char buffer[128];

}
@@ -1,29 +1,21 @@
#ifndef MODULE_H
#define MODULE_H

#include <string>
#include <allegro5/allegro.h>
#include "loader.h"
#include <memory>
#include <vector>
#include <unordered_map>
#include "data.h"

class Module {
private:
unsigned int length;
unsigned int load;
FormData** form_data;
std::unordered_map<unsigned int, std::shared_ptr<Parametrized> > data;

unsigned int add(FormData*);
unsigned int rehash(unsigned int);
FormData* get(std::string);

void load_type(ALLEGRO_FILE*);
void load_form(ALLEGRO_FILE*);
Script* load_script(ALLEGRO_FILE*);
std::shared_ptr<Parametrized> add_data(unsigned int);
public:
Module();

FormData* get(unsigned int);
std::shared_ptr<Parametrized> get_data(unsigned int);

void load_form_data(ALLEGRO_FS_ENTRY*);
void load_modules(std::vector<ALLEGRO_FS_ENTRY*>);
};

#endif // MODULE_H
BIN +140 KB (1900%) adventure/obj/Debug/area.o
Binary file not shown.
Binary file not shown.
BIN +1.09 KB (110%) adventure/obj/Debug/engine.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN +946 Bytes (110%) adventure/obj/Debug/input.o
Binary file not shown.
BIN +942 Bytes (110%) adventure/obj/Debug/interface.o
Binary file not shown.
BIN -206 KB (94%) adventure/obj/Debug/loader.o
Binary file not shown.
BIN +500 KB (1200%) adventure/obj/Debug/module.o
Binary file not shown.
BIN +164 KB (460%) adventure/obj/Debug/options.o
Binary file not shown.
BIN +31.1 KB (120%) adventure/obj/Debug/script.o
Binary file not shown.
BIN +13.7 KB (150%) adventure/obj/Debug/state.o
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,43 @@
#ifndef OBJECT_H
#define OBJECT_H

#include "form.h"
#include "intelligence.h"

/**
* Basic physical object
*/
class Object: public Form {

};

/**
* An inanimate object
*/
class Item: public Object {

};

/**
* An Item that can store other items
*/
class Container: public Item, public Lord<Item*, Point*> {

};

/**
* An animate object with some sort of agency
*/
class Entity: public Object {
private:
Agent* ai;
};

/**
* An Entity which can equip items
*/
class Attired: public Entity, public Lord<Item*, int> {

};

#endif // OBJECT_H
@@ -4,17 +4,121 @@ void Script::execute() {
scope = 0;
vars.clear();
// try catch block
execute(0);
//// execute(0);
// end try catch
}
/*
void* Script::execute(unsigned int index) {
while (chain[index] != (unsigned int)ScriptType::END) {
switch ((ScriptType)chain[index]) {
case ScriptType::DECLARE:
vars.push_back({ scope, chain[index+1], valuate(chain[index+2]) });
index += 3;
break;
case ScriptType::ASSIGN:
set_var(chain[index+1], valuate(chain[index+2]));
index += 3;
break;
case ScriptType::IF:
if (evaluate(chain[index+1])%2 > 0) {
execute(chain[index+2]);
} else {
execute(chain[index+3]);
}
index = chain[index+4];
break;
case ScriptType::WHILE:
scope++;
while (evaluate(chain[index+1])%2 > 0) {
execute(chain[index+2]);
}
decrement_scope();
index = chain[index+3];
break;
case ScriptType::FOR:
scope++;
execute(chain[index+1]);
while (evaluate(chain[index+2])%2 > 0) {
execute(chain[index+4]);
execute(chain[index+3]);
}
decrement_scope();
index = chain[index+5];
break;
case ScriptType::ADD:
break;
}
}
}
void* Script::valuate(unsigned int index) {
switch ((ScriptType)chain[index]) {
case ScriptType::VALUE:
return consts[chain(index+1)];
case ScriptType::VARIABLE:
return var_get(chain[index+1]);
case ScriptType::DECLARE:
void* value = valuate(chain[index+2]);
vars.push_back({ scope, chain[index+1], value });
return value;
case ScriptType::ASSIGN:
return set_var(chain[index+1], valuate(chain[index+2]));
case ScriptType::CREATE:
return mod->create(chain[index+1]);
case ScriptType::ADD:
Form* value = dynamic_cast<Form*>(valuate(chain[index+2]));
if (value != NULL) {
}
return value;
default:
return NULL;
}
}
int Script::evaluate(unsigned int index) {
switch ((ScriptType)chain[index]) {
case ScriptType::VALUE:
return (int)chain[index+1];
case ScriptType::VARIABLE:
void* value = var_get(chain[index+1]);
if (int i = static_cast<int>(value)) {
return i;
} else {
return (int)(value != NULL);
}
case ScriptType::DECLARE:
case ScriptType::ASSIGN:
void* value = valuate(index);
return (int)(value != NULL);
case ScriptType::AND:
return (evaluate(chain[index+1]) & evaluate(chain[index+2]));
case ScriptType::OR:
return (evaluate(chain[index+1]) | evaluate(chain[index+2]));
case ScriptType::NOT:
return ~evaluate(chain[index+1]);
case ScriptType::EQUAL:
return (int)(evaluate(chain[index+1]) == evaluate(chain[index+2]));
case ScriptType::GREATER_THAN:
return (int)(evaluate(chain[index+1]) > evaluate(chain[index+2]));
case ScriptType::GREATER_EQUAL:
return (int)(evaluate(chain[index+1]) >= evaluate(chain[index+2]));
case ScriptType::LESS_THAN:
return (int)(evaluate(chain[index+1]) < evaluate(chain[index+2]));
case ScriptType::LESS_EQUAL:
return (int)(evaluate(chain[index+1]) <= evaluate(chain[index+2]));
default:
return 0;
}
}
unsigned int Script::execute(unsigned int index) {
while (chain[index] != (unsigned int)ScriptTypes::END) {
if (chain[index] >= (unsigned int)ScriptTypes::MAX) {
return var_get(chain[index]-(unsigned int)ScriptTypes::MAX);
while (chain[index] != (unsigned int)ScriptType::END) {
if (chain[index] >= (unsigned int)ScriptType::MAX) {
return var_get(chain[index]-(unsigned int)ScriptType::MAX);
} else {
switch ((ScriptTypes)chain[index]) {
case ScriptTypes::IF:
switch ((ScriptType)chain[index]) {
case ScriptType::IF:
if (execute(chain[index+1]) > 0) {
scope++;
execute(chain[index+2]);
@@ -25,31 +129,31 @@ unsigned int Script::execute(unsigned int index) {
decrement_scope();
index = chain[index+4];
break;
case ScriptTypes::AND:
case ScriptType::AND:
return (unsigned int)(execute(chain[index+1]) > 0 && execute(chain[index+2]) > 0);
case ScriptTypes::OR:
case ScriptType::OR:
return (unsigned int)(execute(chain[index+1]) > 0 || execute(chain[index+2]) > 0);
case ScriptTypes::NOT:
case ScriptType::NOT:
return (unsigned int)(execute(chain[index+1]) == 0);
case ScriptTypes::EQUAL:
case ScriptType::EQUAL:
return (unsigned int)(execute(chain[index+1]) == execute(chain[index+2]));
case ScriptTypes::GREATER_THAN:
case ScriptType::GREATER_THAN:
return (unsigned int)(execute(chain[index+1]) > execute(chain[index+2]));
case ScriptTypes::GREATER_EQUAL:
case ScriptType::GREATER_EQUAL:
return (unsigned int)(execute(chain[index+1]) >= execute(chain[index+2]));
case ScriptTypes::LESS_THAN:
case ScriptType::LESS_THAN:
return (unsigned int)(execute(chain[index+1]) < execute(chain[index+2]));
case ScriptTypes::LESS_EQUAL:
case ScriptType::LESS_EQUAL:
return (unsigned int)(execute(chain[index+1]) <= execute(chain[index+2]));
case ScriptTypes::WHILE:
case ScriptType::WHILE:
scope++;
while (execute(chain[index+1]) > 0) {
execute(chain[index+2]);
}
decrement_scope();
index = chain[index+3];
break;
case ScriptTypes::FOR:
case ScriptType::FOR:
scope++;
execute(chain[index+1]);
while (execute(chain[index+2]) > 0) {
@@ -59,13 +163,13 @@ unsigned int Script::execute(unsigned int index) {
decrement_scope();
index = chain[index+5];
break;
case ScriptTypes::VALUE:
case ScriptType::VALUE:
return chain[index+1];
case ScriptTypes::DECLARE:
case ScriptType::DECLARE:
vars.push_back({scope, chain[index+1]});
index += 2;
break;
case ScriptTypes::ASSIGN:
case ScriptType::ASSIGN:
var_set(chain[index+1], execute(chain[index+2]));
index += 3;
break;
@@ -85,7 +189,7 @@ void Script::decrement_scope() {
}
}
unsigned int Script::var_get(unsigned int key) {
void* Script::var_get(unsigned int key) {
for (std::vector<ScriptVariable>::reverse_iterator iter = vars.rbegin(); iter < vars.rend(); ++iter) {
if (key == (*iter).key) {
return (*iter).value;
@@ -94,21 +198,22 @@ unsigned int Script::var_get(unsigned int key) {
throw std::string("Tried to access undefined variable ").append(key).append(".");
}
void Script::var_set(unsigned int key, unsigned int value) {
void* Script::var_set(unsigned int key, void* value) {
for (std::vector<ScriptVariable>::reverse_iterator iter = vars.rbegin(); iter < vars.rend(); ++iter) {
if (key == (*iter).key) {
(*iter).value = value;
return;
return value;
}
}
throw std::string("Tried to access undefined variable ").append(key).append(".");
}
void Script::set_value(int index, unsigned int value) {
void Script::set_value(unsigned int index, unsigned int value) {
chain[index] = value;
}
int Script::append(unsigned int value) {
unsigned int Script::append(unsigned int value) {
chain.push_back(value);
return chain.size()-1;
return last_index()-1;
}
*/
@@ -2,83 +2,106 @@
#define SCRIPT_H

#include <string>
#include <vector>
#include <unordered_map>
#include "module.h"

enum class ScriptTypes : unsigned int {
MAX = 15,
END = 0,
IF = 1,
// +1 *condition
// +2 *true script
// +3 *false script
// +4 *next script
AND = 2,
// +1 *first condition
// +2 *second condition
OR = 3,
// +1 *first condition
// +2 *second condition
NOT = 4,
// +1 *condition
EQUAL = 5,
// +1 *first value
// +2 *second value
GREATER_THAN = 6,
// +1 *first value
// +2 *second value
GREATER_EQUAL = 7,
// +1 *first value
// +2 *second value
LESS_THAN = 8,
// +1 *first value
// +2 *second value
LESS_EQUAL = 9,
// +1 *first value
// +2 *second value
WHILE = 10,
// +1 *condition
// +2 *loop script
// +3 *next script
FOR = 11,
// +1 *declaration
// +2 *condition
// +3 *update
// +4 *loop script
// +5 *next script
VALUE = 12,
// +1 value
DECLARE = 13,
// +1 key
// +2 next script
ASSIGN = 14
// +1 var to assign to
// +2 value to assign
// +3 next script
enum class ScriptTrigger : int {
INIT = 0,
ON_LEFT_CLICK = 1,
ON_RIGHT_CLICK = 2,
ON_DRAG_RELEASE = 3
};

enum class ScriptType : unsigned int {
END = 0, // END of script
// OBJECTS
VALUE = 12, // get constant value
// +1 *value
VARIABLE = 13, // get value of variable
// +1 key
DECLARE = 14, // declare a variable
// +1 key
// +2 *valuation
ASSIGN = 15, // assign value to variable
// +1 key
// +2 *valuation
// CONTROL FLOW
IF = 1, // IF control flow
// +1 *evaluation
// +2 *true subscript
// +3 *false subscript
// +4 *next subscript
WHILE = 10, // WHILE control flow
// +1 *evaluation
// +2 *loop subscript
// +3 *next subscript
FOR = 11, // FOR control flow
// +1 declare key
// +2 *declare valuation
// +3 *evaluation
// +4 *update subscript
// +5 *loop subscript
// +6 *next subscript
// EVALUATIONS
AND = 2, // & bit operator
// +1 *first valuation
// +2 *second valuation
OR = 3, // | bit operator
// +1 *first valuation
// +2 *second valuation
NOT = 4, // ~ bit operator
// +1 *valuation
EQUAL = 5, // == boolean operator
// +1 *first valuation
// +2 *second valuation
GREATER_THAN = 6, // > boolean operator
// +1 *first valuation
// +2 *second valuation
GREATER_EQUAL = 7, // >= boolean operator
// +1 *first valuation
// +2 *second valuation
LESS_THAN = 8, // < boolean operator
// +1 *first valuation
// +2 *second valuation
LESS_EQUAL = 9, // <= boolean operator
// +1 *first valuation
// +2 *second valuation
// VALUATIONS
CREATE = 16, // create new Form
// +1 key to FormData
ADD = 17 // add Form to Lord
// +1 (WHERE TO ADD)
// +2 *valuation
};

struct ScriptVariable {
unsigned int scope;
unsigned int key;
unsigned int value;
void* value;
};

class Script {
private:
Module* mod;

std::vector<unsigned int> chain;

std::vector<void*> consts;
std::vector<ScriptVariable> vars;
unsigned int scope;

unsigned int var_get(unsigned int);
void var_set(unsigned int, unsigned int);
//void* var_get(unsigned int);
//void* var_set(unsigned int, void*);

unsigned int execute(unsigned int);
void decrement_scope();
//void* execute(unsigned int);
//void decrement_scope();
public:
Script();

void set_value(int, unsigned int);
int append(unsigned int);
//void set_value(unsigned int, unsigned int);
//unsigned int append(ScriptType t) { return append((unsigned int)t); }
//unsigned int append(unsigned int);
//unsigned int last_index() { return (unsigned int)chain.size(); }

void execute();
};
@@ -0,0 +1,130 @@
#include "wrapper.h"

Area* load_area(Area* a, Direction d) { return nullptr; }

/**
* Sets a as current Area
*/
bool Wrapper::add(Area* a) {
delete current;
current = a;
for (int i = 0; i < 8; i++) {
delete vassals[i];
vassals[i] = load_area(current, static_cast<Direction>(i));
}
}

/**
* Sets a as the Area in direction d
*/
bool Wrapper::add(Area* a, Direction d) {
delete vassals[(int)d];
vassals[(int)d] = a;
}

/**
* Sets the Area in direction d as current
*/
bool Wrapper::add(Direction dir) {
int d = (int)dir;
delete vassals[(d+4)%8];
vassals[(d+4)%8] = current;
current = vassals[d];
vassals[d] = load_area(current, static_cast<Direction>(d));
if (d%2 == 0) {
delete vassals[(d+3)%8];
vassals[(d+3)%8] = vassals[(d+2)%8];
vassals[(d+2)%8] = vassals[(d+1)%8];
vassals[(d+1)%8] = load_area(current, static_cast<Direction>((d+1)%8));
delete vassals[(d+5)%8];
vassals[(d+5)%8] = vassals[(d+6)%8];
vassals[(d+6)%8] = vassals[(d+7)%8];
vassals[(d+7)%8] = load_area(current, static_cast<Direction>((d+7)%8));
} else {
delete vassals[(d+2)%8];
vassals[(d+2)%8] = load_area(current, static_cast<Direction>((d+2)%8));
delete vassals[(d+3)%8];
vassals[(d+3)%8] = vassals[(d+1)%2];
vassals[(d+1)%8] = load_area(current, static_cast<Direction>((d+1)%8));
delete vassals[(d+5)%8];
vassals[(d+5)%8] = vassals[(d+7)%8];
vassals[(d+7)%8] = load_area(current, static_cast<Direction>((d+7)%8));
delete vassals[(d+6)%8];
vassals[(d+6)%8] = load_area(current, static_cast<Direction>((d+6)%8));
}
}

/**
* Deletes a
* Returns NULL
*/
Area* Wrapper::discard(Area* a) {
if (current == a) { delete a; }
else {
for (int i = 0; i < 8; i++) {
if (vassals[i] == a) {
delete vassals[i];
break;
}
}
}
return NULL;
}

/**
* Retrieves the Area in Direction d
*/
Area* Wrapper::get(Direction d) {
return vassals[(int)d];
}


bool Wrapper::add(Object* o) {
return add(o, o->get_pos());
}

bool Wrapper::add(Object* o, Point* p) {
if (p->x >= 0 && p->y >= 0 && p->x < MAX_VALUE && p->y < MAX_VALUE) {
return current->add(o, p);
}
int dx = -1;
int dy = -1;
if (p->x < 0) {
dx = (int)Direction::WEST;
p->x = (MAX_VALUE+p->x) % MAX_VALUE;
} else if (p->x >= MAX_VALUE) {
dx = (int)Direction::EAST;
p->x = p->x % MAX_VALUE;
}
if (p->y < 0) {
dy = (int)Direction::NORTH;
p->y = (MAX_VALUE+p->y) % MAX_VALUE;
} else if (p->y >= MAX_VALUE) {
dy = (int)Direction::SOUTH;
p->y = p->y % MAX_VALUE;
}
return vassals[((dx < 0) ? dy : ((dy < 0) ? dx : (dx+dy)/2))]->add(o, p);
}


/**
* Rotate view clockwise
*/
void Wrapper::c_rotate() {
face = static_cast<Direction>((6+(int)face)%8);
current->resort_all();
for (int i = 0; i < 8; i++) {
vassals[i]->resort_all();
}
}

/**
* Rotate view counter-clockwise
*/
void Wrapper::cc_rotate() {
face = static_cast<Direction>((2+(int)face)%8);
current->resort_all();
for (int i = 0; i < 8; i++) {
vassals[i]->resort_all();
}
}
@@ -0,0 +1,32 @@
#ifndef WRAPPER_H
#define WRAPPER_H

#include "lord.h"
#include "geometry.h"
#include "area.h"
#include "object.h"

class Wrapper: public Lord<Area*, Direction> {
private:
Area* current;
Point* center;
Direction face;

public:
Wrapper(Area*);

bool add(Area*);
bool add(Area*, Direction);
bool add(Direction);
Area* discard(Area*);
Area* get(Direction);

bool add(Object*);
bool add(Object*, Point*);

Direction get_face() { return face; }
void c_rotate();
void cc_rotate();
};

#endif // WRAPPER_H