//
//
//
//////////////////////////////////////////////////////////////////////////////////////
//
// 3600 grids, 60 ew, 60 ns = 3600 total. Each assigned location
// so grid x1 y37, would be first x-block(50ns) 37 blocks to the east.
// y37 = 1850 starting variable
// x1 = 0 starting variable
//
//////////////////////////////////////////////////////////////////////////////////////
// Personal-note, when world-map editing, all grids have to be loaded, which means loading
// every single grid, this is so when the map-saves, it saves everything, not just a small chunk
// of the massive map, which would = bad if it were to happen that way.
// Editor on live-port will be disabled when we have builders and a dev-port for building
// the new/improved world on. Though on the dev-port, we will probobly just keep the map always loaded
// so that we do not have to worry about constantly loading/closing, the worldmap.
//
//
// Additions: Adding GRID_DEBUGGING, to aid in logging of the grid system during testing phases.
// Fixed localtime glitch
// Added x/y stored ranges to the grid-data, for ease of grid locations.
//
// comment out if you don't want to debug
#define GRID_DEBUGGING 1
// step 0, assigning grid_list
Lexi::List<grid_data *>grid_list;
// global counter for memory checks
int grid_max;
//////////////////////////////////////////////////////////////////////////////////////
// the grid structure simply keeps track of a location array, when a segment of the
// map is loaded, it gets put into the grid, and then when moving/looking a local
// variable on the player points to the location of the x/y within the grid.
//
// This method keeps memory to an extreme minimum.
// destroyed world/restore timers do not exist, plainly they will be set to a list
class grid_data {
public:
grid_data() { extern int grid_max; extern time_t current_time; last_used = ¤t_time; grid_max++;
#ifdef GRID_DEBUGGING
extern void log_string(const char *, ...);
log_string("[WORLDMAP]: new grid_data created. grid_max now: %d.", grid_max);
#endif
}
~grid_data() { extern int grid_max; grid_max--;
#ifdef GRID_DEBUGGING
extern void log_string(const char *, ...);
log_string("[WORLDMAP]: deleted grid_data. grid_max now: %d.", grid_max);
#endif
}
private:
short location[50][50]; // a 50x50 array containing map information
short grid_x; // northsouth
short grid_y; // eastwest
// Insanity check here
short low_x_range;
short high_x_range;
short low_y_range;
short high_y_range;
// last used when?
time_t last_used; // last time the system used it.
// we will compare, and close after
// 1 hour of non-use.
// non popular zones will close every hour
// while popular ones will remain opened.
public:
short get_location(short x, short y) { return location[x][y];} // gets the map-type
void set_location(short x, short y, short type) { location[x][y] = type; } // sets the map-type
short get_x() { return grid_x; } // gets the overall-x location
short get_y() { return grid_y; } // gets the overall-y location
void set_x(int x) { grid_x = x; } // sets the overall-x location
void set_y(int y) { grid_y = y; } // sets the overall-y location
void set_x_range(int low, int high) { low_x_range = low; high_x_range = high; } // sets the low/high ranges for x
void set_y_range(int low, int high) { low_y_range = low; high_y_range = high; } // sets the low/high ranges for y
void get_x_range(int &low, int &high) { low = &low_x_range; high = &high_x_range; } // get the ranges
void get_y_range(int &low, int &high) { low = &low_y_range; high = &high_y_range; } // get the ranges
time_t &get_time() { return last_used; } // returns last time the grid was accessed(roughly)
void set_time() { extern time_t current_time; last_used = ¤t_time; } // sets the time the grid was used.
};
//////////////////////////////////////////////////////////////////////////////////////
// lets see if our grid is loaded!
bool grid_loaded(short x, short y) {
// grid matching and correction
// this is done so that our variables of +1/-1 work correctly.
if(x > MAX_GRID) x = 0;
if(y > MAX_GRID) y = 0;
if(x < 0) x = MAX_GRID;
if(y < 0) y = MAX_GRID;
FOREACH(Lexi::List<grid_data *>, grid_list, grid_iter) {
grid_data *g = (*grid_iter);
if(g->get_x() == x && g->get_y() == y)
return true;
}
// no grid found, we aren't loaded, return false.
return false;
}
//////////////////////////////////////////////////////////////////////////////////////
// remove a grid!
void close_grid(grid_data *g) {
if(InList(grid_list, g)) // are we in the list
grid_list.remove_one(g); // remove us from it
#ifdef GRID_DEBUGGING
// why do we log it? And why do we display memory free'd, well, this is
// allowing us to not only debug it, but keep track of the more frequented zones
// for opening/closing, plus we want to keep track of the memory allocation, which is
// why we made the grids, so its good to know.
log_string("[WORLDMAP]: Grid X%d : Y%d has been closed. Memory free'd (%s)", g->get_x(), g->get_y(), size_conversion(sizeof(g)))
#endif
delete g; // delete the grid
g = NULL; // null the variable.
}
//////////////////////////////////////////////////////////////////////////////////////
// close the grid
void check_close(grid_data *g) {
// hour not the same and the minute value matches.
if(localtime(&g->get_time())->tm_hour != localtime(¤t_time)->tm_hour
&& localtime(&g->get_time())->tm_min > localtime(&g->get_time())->tm_min+1) {
close_grid(g); // kill our grid
return;
}
// greater then 10 minutes, we close it out.
if(localtime(&g->get_time())->tm_min+10 < localtime(¤t_time)->tm_min) {
close_grid(g);
return;
}
return;
}
//////////////////////////////////////////////////////////////////////////////////////
// our updater, find the last time someone was within a grid.
// set it, and check to see if it is time to close an open grid.
// set this every 30 minutes or so.
Updater(grid_update) {
if(grid_list.empty())
return;
#ifdef GRID_DEBUGGING
log_string("[WORLDMAP]: Before: grid_update: grid_list contains %d grid(s). Approx mem used %s!", grid_list.size, (sizeof(grid_data *) * grid_list.size) );
#endif
FOREACH(Lexi::List<grid_data *>, grid_list, g_iter) {
grid_data *g = (*g_iter);
FOREACH(Lexi::List<CHAR_DATA *>, wild_list, w_iter) {
CHAR_DATA *c = (*w_iter);
// we are in the grid! Set our time!
if(c->grid_x == g->get_x() && c->grid_y == g->get_y()) {
g->set_time();
}
}
// check to see if we have to close our grid
check_close(g);
}
#ifdef GRID_DEBUGGING
log_string("[WORLDMAP]: After: grid_update: grid_list contains %d grid(s). Approx mem used %s!", grid_list.size, (sizeof(grid_data *) * grid_list.size) );
#endif
return;
}
//////////////////////////////////////////////////////////////////////////////////////
// we grab our grid-data, this is helpful
grid_data *get_grid(short x, short y) {
if(grid_list.empty()) return NULL;
FOREACH(Lexi::List<grid_data *>, grid_list, g_iter) {
grid_data *g = (*g_iter);
if(g->get_x() == x && g->get_y() == y)
return g;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////////////////
// What grid are we within. Greatly helpful, fast to process too.
// this will give us our grid-data, so we can pull any bits of information we need from
// that as required.
//
// This will most likely be-used in the draw_map code, as the worldmap can see into other
// ranges, and we will need the official grid-data's.
grid_data *within_range(short real_x, short real_y) {
FOREACH(Lexi::List<grid_data *>, grid_list, g_iter) {
grid_data *g = (*g_iter);
int low_x, high_x;
int low_y, high_y;
// lets grab our ranges. carefully!
g->get_x_range(&low_x, &high_x);
g->get_y_range(&low_y, &high_y);
// lets find out if we are within the ranges.
if(real_x >= low_x && real_x < high_x) // we are within the x-range
if(real_y >= low_y && real_y < high_y) // we are within the y-range
return g;
}
//////////////////////////////////////////////////////////
// obviously, the grid wasn't found above, this is a problem
// so to correct that, we know what grid we have to load
// so we load it. Plain, simple.
int f_x = find_grid_x(real_x);
int f_y = find_grid_y(real_y);
grid_data * g = load_grid(f_x, f_y);
// lets return g, even if g is null, we return here, hopefully save face.
return g;
}
//////////////////////////////////////////////////////////////////////////////////////
// Find out what the 'IN_X'/'IN_Y' values should be.
// This function is used when players are 'sent' to the worldmap.
void set_in_grid(CHAR_DATA *ch) {
grid_data *g = within_range(ch->coordinates[COORD_X], ch->coordinates[COORD_Y]);
// assume not on the map.
if(!g)
return;
int x_low, x_high;
int y_low, y_high;
// lets get our value's
g->get_x_range(&x_low, &x_high);
g->get_y_range(&y_low, &y_high);
int special_x = x_low;
int special_y = y_low;
int real_x = 0;
int real_y = 0;
//////////////////////////////////////////////////////////////////////
// Logic: 0-49 = possible locations, special_* is set to low-rating
// we sift through, if the special_x match's the coord_x, then we've
// found the right * location within the block.
// here we go
for(x = 0; x < 50; x++) {
if(special_x == ch->coordinates[COORD_X]) {
real_x = x;
break;
}
special_x++;
}
for(y = 0; y < 50; y++) {
if(special_y == ch->coordinates[COORD_Y]) {
real_y = x;
break;
}
special_y++;
}
// set the in_x/in_y variables
ch->coordinates[IN_X] = real_x;
ch->coordinates[IN_Y] = real_y;
return;
}
//////////////////////////////////////////////////////////////////////////////////////
// LOCATING THE ACTUAL GRID: Since the world-map code is now broken into grids, but
// our pre-existing linkage to the map doesn't know the grids, we have to be-able to
// work with them, what means, we have to find the existing grids based on the x/y
// value's, here we accomplish that, and attain our grids location
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// here we find out what the x-grid number will be
short find_grid_x(short real_x) {
return real_x/50; // short won't keep the remainder
}
//////////////////////////////////////////////////////////////////////////////////////
// here we find out what the y-grid number will be
short find_grid_y(short real_y) {
return real_y/50; // short won't keep the remainder
}
//////////////////////////////////////////////////////////////////////////////////////
// the math on this is easy, the grid is 50x50, the map is 3000x3000 (thats 3600 grids)
// we find our start location for x (up/down) and our y location (right/left).
// so, grid 2 37 would load at 100 1850 on the map.
// Based on the example above, ranges would be.
// 100->150 ud
// 1850->1900 lr
// however, we do not want to overlap our loaded tiles, so, to stop this from occuring
// we actualy only load to count -1., so 149, and 1899. technically its still valid :)
//
// The loading proceedure is fast, and simple. while it keeps track of the x/y variables, it
// ultimatly creates a 'internal' set of x/y so that we do not break the overall location
// within the grid. Crazy eh?
//
// If your math works properly with your grid alignment, you won't break any bounds
// within the reading of the x/y location. if you think your not going to balance
// out properly, add gdImageSX or gdImageSY checks within the loops, to ensure that
// you do not exceed bounds, but we feel it isn't needed.
//
grid_data *load_grid(short x, short y) {
int start_x = x * MAX_GRID_X;
int start_y = y * MAX_GRID_Y;
int end_x = start_x +50; // easy math :P stops at 49 thanks to alligators ;)
int end_y = start_y +50; // easy math ;)
FILE *jpgin = NULL;
grid_data *g = NULL;
// largest part on the memory is opening the file.
// but even then, its not enough to hiccup on a modern computer.
if((jpgin = fopen( WORLDMAP_FILE, "r" ) ) != NULL) {
gdImagePtr im = gdImageCreateFromPng( jpgin );
// our map-loading code goes here, with the ranges inputted.
g = new grid_data();
g->set_time();
// what is the overall grid x/y location (10x,37y)...
g->set_x(x);
g->set_y(y);
// what ranges is this grid responsible for!?
g->set_x_range(start_x, end_x);
g->set_y_range(start_y, end_y);
// on-to map loading.
int internal_y = 0; // internal variable
// we use set_location within the for-loop that will ensure here.
for( short yx = start_y; yx < end_x; ++yx ) {
int_internal_x = 0;
for( short xy = start_x; xy < end_x; ++xy ) {
internal_x++;
int pixel = gdImageGetPixel( im, xy, yx );
short terr = get_sector_colour( im, pixel );
g->set_location(internal_x,internal_y,terr);
}
internal_y++;
}
// done like this because stranger things have happened!
if(!InList(grid_list, g))
grid_list.push_front(g);
else
log_string("[WORLDMAP]: Grid X%d : Y%d already in the list! ODD!", g->get_x(), g->get_y());
fclose(jpgin);
jpgin = NULL;
gdImageDestroy( im ); // ensure the data is destroyed
#ifdef GRID_DEBUGGING
log_string("[WORLDMAP]: Grid X%d : Y%d has been opened. Memory Allocated (%s)", g->get_x(), g->get_y(), size_conversion(sizeof(g)))
#endif
}
// Here we deal with a safety issue, so that we do not have any overall problems, we try
// and ensuer that our maps are purged often if not being used, and when we load a new
// grid, we assume that people are wandering on the map, causing the rapid opening/closing
// of grids. if we have over <GRID_SAFETY> open, then we check and see if nobody is in
// the grids, and then close them if nobody is in them.
if(grid_max > GRID_SAFETY) {
FOREACH(Lexi::List<grid_data *>, grid_list, grid_iter) {
grid_data *g = (*grid_iter);
if(localtime(&g->get_time())->tm_min+10 > localtime(¤t_time)->tm_min
|| (localtime(&g->get_time())->tm_hour < localtime(¤t_time)->tm_hour
&& localtime(&g->get_time())->tm_min < local_time(¤t_time)->tm_min)) {
bool found = false;
FOREACH(Lexi::List<CHAR_DATA *>, wild_list, w_iter) {
CHAR_DATA *w = (*w_iter);
if(w->coordinates[GRID_X] == g->get_x() && w->coordinates[GRID_Y] == get_y())
found = true;
}
// was there someone within the grid? If not, lets close it!
// even if the last-used time is out, we don't want to obscure
// the map, so we protect ourselves, and ensure there are no outstanding issue's
if(!found) {
#ifdef GRID_DEBUGGING
log_string("[WORLDMAP]: Grid X%d : Y%d exceeding grid safety. Will close!", g->get_x(), g->get_y()))
#endif
close_grid(g);
}
}
}
}
return g;
}
//////////////////////////////////////////////////////////////////////////////////////
// movement: check coordinates for grid-loading changes.
// here we go doing the hard stuff. We find out if the grid is loaded
// if it isn't, we load it, since we are changing coordinates, we need
// to ensure that everything is good.
// set our global coordinates.
coordinates[COORD_X] = temp_x;
coordinates[COORD_Y] = temp_Y;
// change our in_x variable appropriatly.
switch(direction) {
case DIR_NORTH:
coordinates[IN_X]--; break;
case DIR_SOUTH:
coordinates[IN_X]++; break;
case DIR_EAST:
coordinates[IN_Y]++; break;
case DIR_WEST:
coordinates[IN_Y]--; break;
case DIR_NORTHEAST:
coordinates[IN_X]--;
coordinates[IN_Y]++; break;
case DIR_SOUTHWEST:
coordinates[IN_X]++;
coordinates[IN_Y]--; break;
case DIR_NORTHWEST:
coordinates[IN_X]--;
coordinates[IN_Y]--; break;
case DIR_SOUTHEAST:
coordinates[IN_X]++;
coordinates[IN_Y]++; break;
}
// Now we've changed our IN_X/IN_Y variables, lets see if
// we are changing grids? or atleast close enough to load a new grid.
// manage our local x/y coordinates
if(coordinates[IN_X] == MAX_GRID_X-1) {
if(!grid_loaded(coordinates[GRID_X+1], coordinates[GRID_Y]))
load_grid(coordinates[GRID_X+1], coordinates[GRID_Y]);
}
if(coordinates[IN_Y] == MAX_GRID_Y-1) {
if(!grid_loaded(coordinates[GRID_X], coordinates[GRID_Y+1]))
load_grid(coordinates[GRID_X], coordinates[GRID_Y+1);
}
if(coordinates[IN_X] == 0) {
if(!grid_loaded(coordinates[GRID_X-1], coordinates[GRID_Y]))
load_grid(coordinates[GRID_X-1], coordinates[GRID_Y]));
}
if(coordinates[IN_Y] == 0) {
if(!grid_loaded(coordinates[GRID_X], coordinates[GRID_Y-1]))
load_grid(coordinates[GRID_X], coordinates[GRID_Y-1));
}
// we change our standing within the world based on these coordinates
// that we have manipulated, and ensure all is well.
// world wrapping!
// this will be changed to a switch statement so we can change more values
// easily without any major issue's. such as the characters IN_X/IN_Y variables
// as they change when moving grid-to-grid. Entirely based on the direction
// are we moving off-the-grid!
if(coordinates[IN_X] > 49 || coordinates[IN_X] < 0
|| coordinates[IN_Y] > 49 || coordinates[IN_Y] < 0) {
// Okay, we're exceeding the value's, so we have to correct these
// because this is how we do it. So we do our grid-manipulation
// to the best of our ability, change our coordinates, and re-align
// our variables to match appropriatly.
switch(direction) {
case DIR_NORTH:
coordinates[GRID_X]--;
coordinates[IN_X] = 0;
break;
case DIR_SOUTH:
coordinates[GRID_X]++;
coordinates[IN_X] = 49; break;
case DIR_EAST: coordinates[GRID_Y]++;
coordinates[IN_Y] = 0;
break;
case DIR_WEST: coordinates[GRID_Y]--;
coordinates[IN_Y] = 49;
break;
case DIR_NORTHEAST:
coordinates[GRID_X]--; coordinates[GRID_Y]++;
coordinates[IN_X] = 0; coordinates[IN_Y] = 0;
break;
case DIR_NORTHWEST:
coordinates[GRID_X]--; coordinates[GRID_Y]--;
coordinates[IN_X] = 0; coordinates[IN_Y] = 49;
break;
case DIR_SOUTHEAST:
coordinates[GRID_X]++; coordinates[GRID_Y]++;
coordinates[IN_X] = 49; coordinates[IN_Y] = 0;
break;
case DIR_SOUTHWEST:
coordinates[GRID_X] +=1; coordinates[GRID_Y] -=1;
coordinates[IN_X] = 0; coordinates[IN_Y] = 49;
break;
}
}
// world wrapping correction, ensuer we are in the right place
// and not in an non-existant location.
if(coordinates[GRID_X] > MAX_GRID-1) coordinates[GRID_X] = 0;
if(coordinates[GRID_Y] > MAX_GRID-1) coordinates[GRID_Y] = 0;
if(coordinates[GRID_X] < 0) coordinates[GRID_X] = MAX_GRID-1;
if(coordinates[GRID_Y] < 0) coordinates[GRID_Y] = MAX_GRID-1;
// everytime we move, we find our grid, there shouldn't be too many grids open
// at any given time, so this should process really fast.
// if it becomes an issue, then we'll just have to adjust to a minute management
// of grids, so after minutes of non-use they close, apposed to hours.
grid_data *g = get_grid(coordinates[GRID_X], coordinates[GRID_Y]);
if(g) // we hope this isn't ever null
g->set_time();
else {
log_string("Character {{%s} moved in a NULL grid, safety required", IS_NPC(this) ? short_descr : name);
if(IS_NPC(this))
extract_char(this, true); // NPC not needed, extract.
else
extract_char(this, false); // returns to their hometown safely!
// just notify them with whats happened.
Sendf("You have been returned to your hometown mystically, maybe this was a good thing.!\n\r");
}
//////////////////////////////////////////////////////////////////////////////////////
// Give our immortals the ability to view our loaded grids and alittle bit of information
// about them, this will help with understanding of the overall grid-mapping magic
// that has been performed here today.
COMMAND(cmd_gridlist) {
BUFFER *output = new_buf();
char arg[MIL];
argument = one_argument(argument, arg);
if(arg[0] == '\0' || !str_cmp(arg, "list")) {
int cnt = 0;
FOREACH(Lexi::List<grid_data *>, grid_list, grid_iter) {
grid_data *g = (*grid_iter);
BufPrintf(output, "[%d]Grid: X%d Y%d: Last used: %s: Memory Used: %s.\n\r", cnt, g->get_x(), g->get_y(), grab_time_log(g->get_time(), size_conversion(sizeof(g)));
cnt++;
}
BufPrintf("%d grids with memory allocated.", grid_max);
page_to_char(buf_string(output), ch);
free_buf(output);
}
// close the selected grid, if nobody is in the grid.
if(!str_cmp(arg, "remove") || !str_cmp(arg, "delete") || !str_cmp(arg, "close")) {
if(!is_number(argument)) {
ch->Sendf("Syntax: gridlist close <number>\n\r");
return;
}
int cnt = 0;
FOREACH(Lexi::List<grid_data *>, grid_list, grid_iter) {
grid_data *g = (*grid_iter);
if(cnt == atoi(argument)) {
FOREACH(Lexi::List<CHAR_DATA *>, wild_list, wild_iter) {
CHAR_DATA *c = (*wild_iter);
if(g->get_x() == c->coordinates[GRID_X] && g->get_y() == c->coordinates[GRID_Y]) {
ch->Sendf(You cannot delete that grid, it is in use!"\n\r");
return;
}
}
// close the grid
close_grid(g);
ch->Sendf("You have closed a worldmap grid.\n\r");
return
}
cnt++;
}
return;
}
ch->Sendf("Syntax: gridlist list\n\r");
ch->Sendf("Syntax: gridlist close <number>\n\r");
return;
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// display changes, based on x/y range
short coordinates[7]; // to replace x/y and cord variable in char_data.
#define COORD_X 0 // global coords -- used to show the exact location on the worldmap
#define COORD_Y 1 // global coords -- used to show the exact location on the worldmap
#define GRID_X 2 // what x-grid -- our x-grid location
#define GRID_Y 3 // what y-grid -- our y-grid location
#define IN_X 4 // what x location within grid -- within the grid, what x location are we.
#define IN_Y 5 // what y location within grid -- within the grid, what y location are we
#define GRID_SAFETY 5 // how many grids can be open before we start to freak out and try to close them!
#define MAX_GRID 60 // how many grids there are(60x60)
#define MAX_GRID_X 50 // max X per grid (this ties into the MAX_GRID value)
#define MAX_GRID_Y 50 // max Y per grid (this ties into the MAX_GRID value)
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// We want to find out the size in KB, so we go the round-about way to determining the
// size, and returning it. under 1024, we return bytes, over, we return kb, and so on.
// this function is going to be used in many locations for memory management.
const char *size_conversion(size_t size) {
int math_controller = 1024;
int new_size = size/math_controller; // in KB! (solong as size was over 1024, thi will return a kb)
if(size <1024) {
String str = "" << size << " bytes.";
return str.c_str();
}
// over 1024 in originaly size!?
if(size >=1024) {
// whoah, whoah whoa! We are in the megabytes (don't think we need to go anyhigher)
if(new_size >= 1024) {
String s = "" << new_size/1024 << " megabytes.";
return s.c_str();
}
// not a megabyte, not a byte, must be a kilobyte!
String str = "" << new_size << " kilobytes.";
return str.c_str();
}
// if we ever reach this, I'll eat your hat!
return "Unknown size.... SCARY!";
}
//////////////////////////////////////////////////////////////////////////////////////
// Modified looking (test)
int orig_grid_x = ch->coordinates[GRID_X];
int orig_grid_y = ch->coordinates[GRID_Y];
int curr_grid_x = orig_grid_x;
int curr_grid_y = orig_grid_y;
grid *gd = get_grid(orig_grid_x, orig_grid_y);
for(start_x = ch->coordinates[IN_X]-10; start_x < ch->coordinates[IN_X]+10; start_x++) {
// modify our grid locations as required
if(start_x <0)
curr_grid_y--;
if(start_x>49)
curr_grid_x++;
// now we loop through our Y variable, and get our location
for(start_y = ch->coordinates[IN_Y]-7; start_y < ch->coordinates[IN_Y]+7; start_y++) {
if(start_y>49)
curr_grid_y++;
if(start_y <0)
curr_grid_y--;
// make sure the grids are loaded that are required to be loaded.
if(curr_grid_x == MAX_GRID_X-1) {
if(!grid_loaded(curr_grid_x+1, curr_grid_y))
load_grid(curr_grid_x+1, curr_grid_y);
}
if(curr_grid_y == MAX_GRID_Y-1) {
if(!grid_loaded(curr_grid_x, curr_grid_y+1))
load_grid(curr_grid_x, curr_grid_y+1);
}
if(curr_grid_x == 0) {
if(!grid_loaded(curr_grid_x-1, curr_grid_y))
load_grid(curr_grid_x-1, curr_grid_y);
}
if(curr_grid_y == 0) {
if(!grid_loaded(curr_grid_x, curr_grid_y-1))
load_grid(curr_grid_x, curr_grid_y-1);
}
// we draw our room (simple pleasures)
// start_x and and start_y will be manipulated in draw_room based on curr_grid vs orig_grid.
// if the grid's aren't the same, it will change based on how far beyond the limits.
// so -7 translates into 43, where as 57 turns into 6, simple mathmatics to display the appropriate
// information.
//
// gd is used to get the location and return its drawing point.
// if the orig_grid's dont' match the curr_grid, we switch to the appropriate grid
// but so-long as the orig_grid is the curr grid, we don't have to lookup the grid
// location, saving memory and cpu usage everytime we look. <-- important!
//
// this looks like it could verywell work, so-long as the modifications are made to
// draw_room that check the grids, and start_x/y variables and switch them around as
// required.
draw_room(ch, gd, orig_grid_x, orig_grid_y, curr_grid_x, curr_grid_y, start_x, start_y);
}
}