Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

959 lines (833 sloc) 29.672 kB
/* $Id$
* MegaZeux
*
* Copyright (C) 2004 Gilead Kutnick
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "world.h"
#include "board.h"
#include "const.h"
int cmp_robots(const void *dest, const void *src)
{
Robot *rsrc = *((Robot **)src);
Robot *rdest = *((Robot **)dest);
return strcasecmp(rdest->robot_name, rsrc->robot_name);
}
void replace_current_board(World *mzx_world, char *name)
{
Board *src_board = mzx_world->current_board;
FILE *input_mzb = fopen(name, "rb");
int first_byte = fgetc(input_mzb);
char version_string[4];
int current_board_id = mzx_world->current_board_id;
fread(version_string, 3, 1, input_mzb);
version_string[3] = 0;
if((first_byte == 0xFF) &&
(!strcmp(version_string, world_version_string) ||
!strcmp(version_string, "MB2")))
{
clear_board(src_board);
src_board = load_board_allocate_direct(input_mzb, 0);
optimize_null_objects(src_board);
mzx_world->current_board = src_board;
mzx_world->board_list[current_board_id] = src_board;
}
}
Board *load_board_allocate(FILE *fp, int savegame)
{
Board *cur_board = (Board *)malloc(sizeof(Board));
load_board(cur_board, fp, savegame);
if(!cur_board->board_width)
{
free(cur_board);
return NULL;
}
return cur_board;
}
Board *load_board_allocate_direct(FILE *fp, int savegame)
{
Board *cur_board = (Board *)malloc(sizeof(Board));
load_board_direct(cur_board, fp, savegame);
fread(cur_board->board_name, 25, 1, fp);
return cur_board;
}
// The file given should point to a name/location combo. This will
// restore the file position to after the name/location.
void load_board(Board *cur_board, FILE *fp, int savegame)
{
int board_size = fgetd(fp);
if(board_size)
{
int board_location, last_location;
board_location = fgetd(fp);
last_location = ftell(fp);
fseek(fp, board_location, SEEK_SET);
load_board_direct(cur_board, fp, savegame);
fseek(fp, last_location, SEEK_SET);
}
else
{
cur_board->board_width = 0;
// And skip board location
fseek(fp, 4, SEEK_CUR);
}
}
void load_board_direct(Board *cur_board, FILE *fp, int savegame)
{
int num_robots, num_scrolls, num_sensors, num_robots_active;
int overlay_mode, board_mode;
int size, board_width, board_height;
int i;
Robot *cur_robot;
Scroll *cur_scroll;
Sensor *cur_sensor;
char *test_buffer;
board_mode = fgetc(fp);
overlay_mode = fgetc(fp);
if(!overlay_mode)
{
int overlay_width;
int overlay_height;
overlay_mode = fgetc(fp);
overlay_width = fgetw(fp);
overlay_height = fgetw(fp);
size = overlay_width * overlay_height;
cur_board->overlay = (char *)malloc(size);
cur_board->overlay_color = (char *)malloc(size);
load_RLE2_plane(cur_board->overlay, fp, size);
test_buffer = (char *)malloc(1024);
free(test_buffer);
// Skip sizes
fseek(fp, 4, SEEK_CUR);
load_RLE2_plane(cur_board->overlay_color, fp, size);
test_buffer = (char *)malloc(1024);
free(test_buffer);
}
else
{
overlay_mode = 0;
// Undo that last get
fseek(fp, -1, SEEK_CUR);
}
cur_board->overlay_mode = overlay_mode;
board_width = fgetw(fp);
board_height = fgetw(fp);
cur_board->board_width = board_width;
cur_board->board_height = board_height;
size = board_width * board_height;
cur_board->level_id = (char *)malloc(size);
cur_board->level_color = (char *)malloc(size);
cur_board->level_param = (char *)malloc(size);
cur_board->level_under_id = (char *)malloc(size);
cur_board->level_under_color = (char *)malloc(size);
cur_board->level_under_param = (char *)malloc(size);
load_RLE2_plane(cur_board->level_id, fp, size);
fseek(fp, 4, SEEK_CUR);
load_RLE2_plane(cur_board->level_color, fp, size);
fseek(fp, 4, SEEK_CUR);
load_RLE2_plane(cur_board->level_param, fp, size);
fseek(fp, 4, SEEK_CUR);
load_RLE2_plane(cur_board->level_under_id, fp, size);
fseek(fp, 4, SEEK_CUR);
load_RLE2_plane(cur_board->level_under_color, fp, size);
fseek(fp, 4, SEEK_CUR);
load_RLE2_plane(cur_board->level_under_param, fp, size);
// Load board parameters
fread(cur_board->mod_playing, FILENAME_SIZE, 1, fp);
cur_board->mod_playing[FILENAME_SIZE] = 0;
cur_board->viewport_x = fgetc(fp);
cur_board->viewport_y = fgetc(fp);
cur_board->viewport_width = fgetc(fp);
cur_board->viewport_height = fgetc(fp);
cur_board->can_shoot = fgetc(fp);
cur_board->can_bomb = fgetc(fp);
cur_board->fire_burn_brown = fgetc(fp);
cur_board->fire_burn_space = fgetc(fp);
cur_board->fire_burn_fakes = fgetc(fp);
cur_board->fire_burn_trees = fgetc(fp);
cur_board->explosions_leave = fgetc(fp);
cur_board->save_mode = fgetc(fp);
cur_board->forest_becomes = fgetc(fp);
cur_board->collect_bombs = fgetc(fp);
cur_board->fire_burns = fgetc(fp);
for(i = 0; i < 4; i++)
{
cur_board->board_dir[i] = fgetc(fp);
}
cur_board->restart_if_zapped = fgetc(fp);
cur_board->time_limit = fgetw(fp);
cur_board->last_key = fgetc(fp);
cur_board->num_input = fgetw(fp);
cur_board->input_size = fgetc(fp);
fread(cur_board->input_string, 81, 1, fp);
cur_board->player_last_dir = fgetc(fp);
fread(cur_board->bottom_mesg, 81, 1, fp);
cur_board->b_mesg_timer = fgetc(fp);
cur_board->lazwall_start = fgetc(fp);
cur_board->b_mesg_row = fgetc(fp);
cur_board->b_mesg_col = (signed char)fgetc(fp);
cur_board->scroll_x = (signed short)fgetw(fp);
cur_board->scroll_y = (signed short)fgetw(fp);
cur_board->locked_x = (signed short)fgetw(fp);
cur_board->locked_y = (signed short)fgetw(fp);
cur_board->player_ns_locked = fgetc(fp);
cur_board->player_ew_locked = fgetc(fp);
cur_board->player_attack_locked = fgetc(fp);
cur_board->volume = fgetc(fp);
cur_board->volume_inc = fgetc(fp);
cur_board->volume_target = fgetc(fp);
// Load robots
num_robots = fgetc(fp);
num_robots_active = 0;
cur_board->robot_list =
(Robot **)malloc(sizeof(Robot *) * (num_robots + 1));
// Also allocate for name sorted list
cur_board->robot_list_name_sorted =
(Robot **)malloc(sizeof(Robot *) * num_robots);
// Any null objects being placed will later be optimized out
if(num_robots)
{
for(i = 1; i <= num_robots; i++)
{
cur_robot = load_robot_allocate(fp, savegame);
if(cur_robot->used)
{
cur_board->robot_list[i] = cur_robot;
cur_board->robot_list_name_sorted[num_robots_active] = cur_robot;
num_robots_active++;
}
else
{
// We don't need no null robot
clear_robot(cur_robot);
cur_board->robot_list[i] = NULL;
}
}
}
if(num_robots_active)
{
if(num_robots_active != num_robots)
{
cur_board->robot_list_name_sorted =
(Robot **)realloc(cur_board->robot_list_name_sorted,
sizeof(Robot *) * num_robots_active);
}
qsort(cur_board->robot_list_name_sorted, num_robots_active,
sizeof(Robot *), cmp_robots);
}
else
{
free(cur_board->robot_list_name_sorted);
cur_board->robot_list_name_sorted = NULL;
}
cur_board->num_robots = num_robots;
cur_board->num_robots_allocated = num_robots;
cur_board->num_robots_active = num_robots_active;
// Load scrolls
num_scrolls = fgetc(fp);
cur_board->scroll_list =
(Scroll **)malloc(sizeof(Scroll *) * (num_scrolls + 1));
if(num_scrolls)
{
for(i = 1; i <= num_scrolls; i++)
{
cur_scroll = load_scroll_allocate(fp, savegame);
if(cur_scroll->used)
{
cur_board->scroll_list[i] = cur_scroll;
}
else
{
// We don't need no null scroll
clear_scroll(cur_scroll);
cur_board->scroll_list[i] = NULL;
}
}
}
cur_board->num_scrolls = num_scrolls;
// Load sensors
num_sensors = fgetc(fp);
cur_board->sensor_list =
(Sensor **)malloc(sizeof(Sensor *) * (num_sensors + 1));
if(num_sensors)
{
for(i = 1; i <= num_sensors; i++)
{
cur_sensor = load_sensor_allocate(fp, savegame);
if(cur_sensor->used)
{
cur_board->sensor_list[i] = cur_sensor;
}
else
{
// We don't need no null sensor
clear_sensor(cur_sensor);
cur_board->sensor_list[i] = NULL;
}
}
}
cur_board->num_sensors = num_sensors;
}
Board *create_blank_board()
{
Board *cur_board = (Board *)malloc(sizeof(Board));
int i;
cur_board->size = 0;
cur_board->board_name[0] = 0;
cur_board->board_width = 100;
cur_board->board_height = 100;
cur_board->overlay_mode = 1;
cur_board->level_id = (char *)malloc(100 * 100);
cur_board->level_param = (char *)malloc(100 * 100);
cur_board->level_color = (char *)malloc(100 * 100);
cur_board->level_under_id = (char *)malloc(100 * 100);
cur_board->level_under_param = (char *)malloc(100 * 100);
cur_board->level_under_color = (char *)malloc(100 * 100);
cur_board->overlay = (char *)malloc(100 * 100);
cur_board->overlay_color = (char *)malloc(100 * 100);
cur_board->mod_playing[0] = 0;
cur_board->viewport_x = 0;
cur_board->viewport_y = 0;
cur_board->viewport_width = 80;
cur_board->viewport_height = 25;
cur_board->can_shoot = 1;
cur_board->can_bomb = 1;
cur_board->fire_burn_brown = 0;
cur_board->fire_burn_space = 1;
cur_board->fire_burn_fakes = 1;
cur_board->fire_burn_trees = 1;
cur_board->explosions_leave = EXPL_LEAVE_ASH;
cur_board->save_mode = CAN_SAVE;
cur_board->forest_becomes = FOREST_TO_FLOOR;
cur_board->collect_bombs = 1;
cur_board->fire_burns = FIRE_BURNS_FOREVER;
for(i = 0; i < 4; i++)
{
cur_board->board_dir[i] = NO_BOARD;
}
cur_board->restart_if_zapped = 0;
cur_board->time_limit = 0;
cur_board->last_key = '?';
cur_board->num_input = 0;
cur_board->input_size = 0;
cur_board->input_string[0] = 0;
cur_board->player_last_dir = 0x10;
cur_board->bottom_mesg[0] = 0;
cur_board->b_mesg_timer = 0;
cur_board->lazwall_start = 7;
cur_board->b_mesg_row = 24;
cur_board->b_mesg_col = -1;
cur_board->scroll_x = 0;
cur_board->scroll_y = 0;
cur_board->locked_x = -1;
cur_board->locked_y = -1;
cur_board->player_ns_locked = 0;
cur_board->player_ew_locked = 0;
cur_board->player_attack_locked = 0;
cur_board->volume = 255;
cur_board->volume_inc = 0;
cur_board->volume_target = 255;
cur_board->num_robots = 0;
cur_board->num_robots_active = 0;
cur_board->num_robots_allocated = 0;
cur_board->robot_list = (Robot **)malloc(sizeof(Robot *));
cur_board->robot_list_name_sorted = NULL;
cur_board->num_scrolls = 0;
cur_board->num_scrolls_allocated = 0;
cur_board->scroll_list = (Scroll **)malloc(sizeof(Scroll *));
cur_board->num_sensors = 0;
cur_board->num_sensors_allocated = 0;
cur_board->sensor_list = (Sensor **)malloc(sizeof(Sensor *));
memset(cur_board->level_id, 0, 100 * 100);
memset(cur_board->level_color, 7, 100 * 100);
memset(cur_board->level_param, 0, 100 * 100);
memset(cur_board->level_under_id, 0, 100 * 100);
memset(cur_board->level_under_color, 7, 100 * 100);
memset(cur_board->level_under_param, 0, 100 * 100);
memset(cur_board->overlay, 32, 100 * 100);
memset(cur_board->overlay_color, 7, 100 * 100);
cur_board->level_id[0] = 127;
return cur_board;
}
void save_board_file(Board *cur_board, char *name)
{
FILE *board_file = fopen(name, "wb");
fputc(0xFF, board_file);
fputs(world_version_string, board_file);
optimize_null_objects(cur_board);
save_board(cur_board, board_file, 0);
// Write name
fwrite(cur_board->board_name, 25, 1, board_file);
fclose(board_file);
}
int save_board(Board *cur_board, FILE *fp, int savegame)
{
int num_robots, num_scrolls, num_sensors;
int start_location = ftell(fp);
int board_width = cur_board->board_width;
int board_height = cur_board->board_height;
int board_size = board_width * board_height;
int i;
// Board mode is now ignored, put 0
fputc(0, fp);
// Put overlay mode
if(cur_board->overlay_mode)
{
fputc(0, fp);
fputc(cur_board->overlay_mode, fp);
fputw(cur_board->board_width, fp);
fputw(cur_board->board_height, fp);
save_RLE2_plane(cur_board->overlay, fp, board_size);
fputw(cur_board->board_width, fp);
fputw(cur_board->board_height, fp);
save_RLE2_plane(cur_board->overlay_color, fp, board_size);
}
fputw(board_width, fp);
fputw(board_height, fp);
save_RLE2_plane(cur_board->level_id, fp, board_size);
fputw(board_width, fp);
fputw(board_height, fp);
save_RLE2_plane(cur_board->level_color, fp, board_size);
fputw(board_width, fp);
fputw(board_height, fp);
save_RLE2_plane(cur_board->level_param, fp, board_size);
fputw(board_width, fp);
fputw(board_height, fp);
save_RLE2_plane(cur_board->level_under_id, fp, board_size);
fputw(board_width, fp);
fputw(board_height, fp);
save_RLE2_plane(cur_board->level_under_color, fp, board_size);
fputw(board_width, fp);
fputw(board_height, fp);
save_RLE2_plane(cur_board->level_under_param, fp, board_size);
// Save board parameters
fwrite(cur_board->mod_playing, FILENAME_SIZE, 1, fp);
fputc(cur_board->viewport_x, fp);
fputc(cur_board->viewport_y, fp);
fputc(cur_board->viewport_width, fp);
fputc(cur_board->viewport_height, fp);
fputc(cur_board->can_shoot, fp);
fputc(cur_board->can_bomb, fp);
fputc(cur_board->fire_burn_brown, fp);
fputc(cur_board->fire_burn_space, fp);
fputc(cur_board->fire_burn_fakes, fp);
fputc(cur_board->fire_burn_trees, fp);
fputc(cur_board->explosions_leave, fp);
fputc(cur_board->save_mode, fp);
fputc(cur_board->forest_becomes, fp);
fputc(cur_board->collect_bombs, fp);
fputc(cur_board->fire_burns, fp);
for(i = 0; i < 4; i++)
{
fputc(cur_board->board_dir[i], fp);
}
fputc(cur_board->restart_if_zapped, fp);
fputw(cur_board->time_limit, fp);
fputc(cur_board->last_key, fp);
fputw(cur_board->num_input, fp);
fputc(cur_board->input_size, fp);
fwrite(cur_board->input_string, 81, 1, fp);
fputc(cur_board->player_last_dir, fp);
fwrite(cur_board->bottom_mesg, 81, 1, fp);
fputc(cur_board->b_mesg_timer, fp);
fputc(cur_board->lazwall_start, fp);
fputc(cur_board->b_mesg_row, fp);
fputc(cur_board->b_mesg_col, fp);
fputw(cur_board->scroll_x, fp);
fputw(cur_board->scroll_y, fp);
fputw(cur_board->locked_x, fp);
fputw(cur_board->locked_y, fp);
fputc(cur_board->player_ns_locked, fp);
fputc(cur_board->player_ew_locked, fp);
fputc(cur_board->player_attack_locked, fp);
fputc(cur_board->volume, fp);
fputc(cur_board->volume_inc, fp);
fputc(cur_board->volume_target, fp);
// Save robots
num_robots = cur_board->num_robots;
fputc(num_robots, fp);
if(num_robots)
{
Robot *cur_robot;
for(i = 1; i <= num_robots; i++)
{
cur_robot = cur_board->robot_list[i];
save_robot(cur_robot, fp, savegame);
}
}
// Save scrolls
num_scrolls = cur_board->num_scrolls;
putc(num_scrolls, fp);
if(num_scrolls)
{
Scroll *cur_scroll;
for(i = 1; i <= num_scrolls; i++)
{
cur_scroll = cur_board->scroll_list[i];
save_scroll(cur_scroll, fp, savegame);
}
}
// Save sensors
num_sensors = cur_board->num_sensors;
fputc(num_sensors, fp);
if(num_sensors)
{
Sensor *cur_sensor;
for(i = 1; i <= num_sensors; i++)
{
cur_sensor = cur_board->sensor_list[i];
save_sensor(cur_sensor, fp, savegame);
}
}
return (ftell(fp) - start_location);
}
void load_RLE2_plane(char *plane, FILE *fp, int size)
{
int i, runsize;
char current_char;
for(i = 0; i < size; i++)
{
current_char = fgetc(fp);
if(!(current_char & 0x80))
{
// Regular character
plane[i] = current_char;
}
else
{
// A run
runsize = current_char & 0x7F;
current_char = fgetc(fp);
memset(plane + i, current_char, runsize);
i += (runsize - 1);
}
}
}
void save_RLE2_plane(char *plane, FILE *fp, int size)
{
int i, runsize;
char current_char;
for(i = 0; i < size; i++)
{
current_char = plane[i];
runsize = 1;
while((i < (size - 1)) && (plane[i + 1] == current_char) &&
(runsize < 127))
{
i++;
runsize++;
}
// Put the runsize if necessary
if((runsize > 1) || current_char & 0x80)
{
fputc(runsize | 0x80, fp);
// Put the run character
fputc(current_char, fp);
}
else
{
fputc(current_char, fp);
}
}
}
void clear_board(Board *cur_board)
{
int i;
int num_robots_active = cur_board->num_robots_active;
int num_scrolls = cur_board->num_scrolls;
int num_sensors = cur_board->num_sensors;
Robot **robot_list = cur_board->robot_list;
Robot **robot_name_list = cur_board->robot_list_name_sorted;
Robot *cur_robot;
Scroll **scroll_list = cur_board->scroll_list;
Sensor **sensor_list = cur_board->sensor_list;
free(cur_board->level_id);
free(cur_board->level_param);
free(cur_board->level_color);
free(cur_board->level_under_id);
free(cur_board->level_under_param);
free(cur_board->level_under_color);
if(cur_board->overlay_mode)
{
free(cur_board->overlay);
free(cur_board->overlay_color);
}
for(i = 0; i < num_robots_active; i++)
{
cur_robot = robot_name_list[i];
clear_robot(cur_robot);
}
if(robot_name_list)
free(robot_name_list);
if(robot_list)
free(robot_list);
for(i = 1; i <= num_scrolls; i++)
{
if(scroll_list[i])
clear_scroll(scroll_list[i]);
}
if(scroll_list)
free(scroll_list);
for(i = 1; i <= num_sensors; i++)
{
if(sensor_list[i])
clear_sensor(sensor_list[i]);
}
if(sensor_list)
free(sensor_list);
free(cur_board);
}
// Just a linear search. Boards aren't addressed by name very often.
int find_board(World *mzx_world, char *name)
{
Board **board_list = mzx_world->board_list;
Board *current_board;
int num_boards = mzx_world->num_boards;
int i;
for(i = 0; i < num_boards; i++)
{
current_board = board_list[i];
if(current_board && !strcasecmp(name, current_board->board_name))
break;
}
if(i != num_boards)
{
return i;
}
else
{
return NO_BOARD;
}
}
void change_board_size(Board *src_board, int new_width, int new_height)
{
int board_width = src_board->board_width;
int board_height = src_board->board_height;
if((board_width != new_width) || (board_height != new_height))
{
char *level_id = src_board->level_id;
char *level_color = src_board->level_color;
char *level_param = src_board->level_param;
char *level_under_id = src_board->level_under_id;
char *level_under_color = src_board->level_under_color;
char *level_under_param = src_board->level_under_param;
char *overlay = src_board->overlay;
char *overlay_color = src_board->overlay_color;
int overlay_mode = src_board->overlay_mode;
int board_size = board_width * board_height;
int new_size = new_width * new_height;
int i;
// Shrinking height? Remove any robots/scrolls/sensors from excess lines
if(new_height < board_height)
{
int offset;
int check_id;
for(offset = new_size; offset < board_size - new_size; offset++)
{
check_id = level_id[offset];
if(check_id == 122)
clear_sensor_id(src_board, level_param[offset]);
else
if((check_id == 126) || (check_id == 125))
clear_scroll_id(src_board, level_param[offset]);
else
if((check_id == 123) || (check_id == 124))
clear_robot_id(src_board, level_param[offset]);
}
}
if(new_width < board_width)
{
// Take out pieces from each width, then reallocate.
// Only do this for the current height or the new height, whichever is
// less.
int src_offset, dest_offset;
int max_height = new_height;
int check_id, offset;
if(new_height > board_height)
max_height = board_height;
for(i = 0, src_offset = 0, dest_offset = 0; i < max_height;
i++, src_offset += board_width, dest_offset += new_width)
{
// First, remove any robots/scrolls/sensors from excess chunks
for(offset = src_offset + new_width; offset < src_offset + board_width;
offset++)
{
check_id = level_id[offset];
if(check_id == 122)
clear_sensor_id(src_board, level_param[offset]);
else
if((check_id == 126) || (check_id == 125))
clear_scroll_id(src_board, level_param[offset]);
else
if((check_id == 123) || (check_id == 124))
clear_robot_id(src_board, level_param[offset]);
}
memmove(level_id + dest_offset, level_id + src_offset, new_width);
memmove(level_param + dest_offset, level_param + src_offset, new_width);
memmove(level_color + dest_offset, level_color + src_offset, new_width);
memmove(level_under_id + dest_offset,
level_under_id + src_offset, new_width);
memmove(level_under_param + dest_offset,
level_under_param + src_offset, new_width);
memmove(level_under_color + dest_offset,
level_under_color + src_offset, new_width);
}
// Resize layers
src_board->level_id = (char *)realloc(level_id, new_size);
src_board->level_color = (char *)realloc(level_color, new_size);
src_board->level_param = (char *)realloc(level_param, new_size);
src_board->level_under_id = (char *)realloc(level_under_id, new_size);
src_board->level_under_color = (char *)realloc(level_under_color, new_size);
src_board->level_under_param = (char *)realloc(level_under_param, new_size);
level_id = src_board->level_id;
level_color = src_board->level_color;
level_param = src_board->level_param;
level_under_id = src_board->level_under_id;
level_under_color = src_board->level_under_color;
level_under_param = src_board->level_under_param;
overlay = src_board->overlay;
overlay_color = src_board->overlay_color;
// Do the overlay too, if it exists
if(overlay_mode)
{
for(i = 0, src_offset = 0, dest_offset = 0; i < max_height;
i++, src_offset += board_width, dest_offset += new_width)
{
memmove(overlay + dest_offset, overlay + src_offset, new_width);
memmove(overlay_color + dest_offset, overlay_color + src_offset, new_width);
}
src_board->overlay = (char *)realloc(overlay, new_size);
src_board->overlay_color = (char *)realloc(overlay_color, new_size);
}
}
else
if(new_width > board_width)
{
// Reallocate first, then copy over pieces, padding in widths
// Only do this for the current height or the new height, whichever is
// less.
int src_offset, dest_offset;
int max_height = new_height;
int width_difference = new_width - board_width;
if(new_height > board_height)
max_height = board_height;
// Resize first this time.
src_board->level_id = (char *)realloc(level_id, new_size);
src_board->level_color = (char *)realloc(level_color, new_size);
src_board->level_param = (char *)realloc(level_param, new_size);
src_board->level_under_id = (char *)realloc(level_under_id, new_size);
src_board->level_under_color = (char *)realloc(level_under_color, new_size);
src_board->level_under_param = (char *)realloc(level_under_param, new_size);
// Resize the overlay too, if it exists
if(overlay_mode)
{
src_board->overlay = (char *)realloc(overlay, new_size);
src_board->overlay_color = (char *)realloc(overlay_color, new_size);
overlay = src_board->overlay;
overlay_color = src_board->overlay_color;
}
level_id = src_board->level_id;
level_color = src_board->level_color;
level_param = src_board->level_param;
level_under_id = src_board->level_under_id;
level_under_color = src_board->level_under_color;
level_under_param = src_board->level_under_param;
// And start at the end instead of the beginning
src_offset = board_width * (max_height - 1);
dest_offset = new_width * (max_height - 1);
for(i = 0; i < max_height; i++, src_offset -= board_width, dest_offset -= new_width)
{
memmove(level_id + dest_offset, level_id + src_offset, board_width);
memmove(level_param + dest_offset, level_param + src_offset, board_width);
memmove(level_color + dest_offset, level_color + src_offset, board_width);
memmove(level_under_id + dest_offset,
level_under_id + src_offset, board_width);
memmove(level_under_param + dest_offset,
level_under_param + src_offset, board_width);
memmove(level_under_color + dest_offset,
level_under_color + src_offset, board_width);
// And fill in the remainder with blanks
memset(level_id + dest_offset + board_width, 0, width_difference);
memset(level_param + dest_offset + board_width, 0, width_difference);
memset(level_color + dest_offset + board_width, 7, width_difference);
memset(level_under_id + dest_offset + board_width, 0, width_difference);
memset(level_under_param + dest_offset + board_width, 0, width_difference);
memset(level_under_color + dest_offset + board_width, 7, width_difference);
}
src_offset = board_width * (max_height - 1);
dest_offset = new_width * (max_height - 1);
// Do the overlay too, if it exists
if(overlay_mode)
{
for(i = 0; i < max_height; i++, src_offset -= board_width, dest_offset -= new_width)
{
memmove(overlay + dest_offset, overlay + src_offset, board_width);
memmove(overlay_color + dest_offset, overlay_color + src_offset, board_width);
// And fill in the remainder with blanks
memset(overlay + dest_offset + board_width, 32, width_difference);
memset(overlay_color + dest_offset + board_width, 7, width_difference);
}
}
}
else
{
// Width remains the same, just a straight resize
src_board->level_id = (char *)realloc(level_id, new_size);
src_board->level_color = (char *)realloc(level_color, new_size);
src_board->level_param = (char *)realloc(level_param, new_size);
src_board->level_under_id = (char *)realloc(level_under_id, new_size);
src_board->level_under_color = (char *)realloc(level_under_color, new_size);
src_board->level_under_param = (char *)realloc(level_under_param, new_size);
// Resize the overlay too, if it exists
if(overlay_mode)
{
src_board->overlay = (char *)realloc(overlay, new_size);
src_board->overlay_color = (char *)realloc(overlay_color, new_size);
}
level_id = src_board->level_id;
level_color = src_board->level_color;
level_param = src_board->level_param;
level_under_id = src_board->level_under_id;
level_under_color = src_board->level_under_color;
level_under_param = src_board->level_under_param;
overlay = src_board->overlay;
overlay_color = src_board->overlay_color;
}
// Fill in any blanks
if(new_height > board_height)
{
int offset = new_width * board_height;
int size_difference = new_size - offset;
memset(level_id + offset, 0, size_difference);
memset(level_param + offset, 0, size_difference);
memset(level_color + offset, 7, size_difference);
memset(level_under_id + offset, 0, size_difference);
memset(level_under_param + offset, 0, size_difference);
memset(level_under_color + offset, 7, size_difference);
if(overlay_mode)
{
memset(overlay + board_size, 32, size_difference);
memset(overlay_color + board_size, 7, size_difference);
}
}
// Set the new sizes
src_board->board_width = new_width;
src_board->board_height = new_height;
}
}
Jump to Line
Something went wrong with that request. Please try again.