1 /* board.c	-- Board functions
2  * $Id: board.c,v 1.3 2005/06/29 03:20:34 kvance Exp $
3  * Copyright (C) 2001 Kev Vance <kvance@kvance.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place Suite 330; Boston, MA 02111-1307, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "zzt.h"
28 
29 /* zztParamCopyPtr(dest, src)
30  * Copies param onto pre-reserved memory
31  * Found in params.c
32  */
33 int zztParamCopyPtr(ZZTparam *dest, ZZTparam *src);
34 
35 /* Helper functions native to board.c */
36 
_zzt_rle_decode(u_int8_t * packed,ZZTblock * block)37 int _zzt_rle_decode(u_int8_t *packed, ZZTblock *block)
38 {
39 	int ofs = 0, count = 0;
40 	int maxcount = block->width * block->height;
41 	u_int8_t i;
42 
43 	/* NOTE: we assume that the decompressed rle string is not smaller than the
44 	 * size of the block. A larger rle string will safely generate an error */
45 
46 	do {
47 		for(i = 0; i < packed[ofs]; i++) {
48 			if (count >= maxcount)   /* Do not exceed the block size */
49 				return 0;
50 			block->tiles[count].type = packed[ofs+1];
51 			block->tiles[count++].color = packed[ofs+2];
52 		}
53 		ofs += 3;
54 	} while(count < maxcount);
55 	return 1;
56 }
57 
_zzt_rle_encoded_size(ZZTblock * block)58 int _zzt_rle_encoded_size(ZZTblock *block)
59 {
60 	int size = 0, ofs = 0;
61 	int maxcount = block->width * block->height;
62 	u_int8_t blocks;
63 	u_int8_t type;
64 	u_int8_t color;
65 
66 	/* Get size of RLE data */
67 	do {
68 		/* Start with one block */
69 		blocks = 1;
70 		type = block->tiles[ofs].type;
71 		color = block->tiles[ofs++].color;
72 
73 		while(ofs < maxcount && type == block->tiles[ofs].type && color == block->tiles[ofs].color && blocks < 255) {
74 			blocks++;
75 			ofs++;
76 		}
77 		size++;
78 	} while(ofs < maxcount);
79 
80 	return size;
81 }
82 
_zzt_rle_encode(ZZTblock * block)83 u_int8_t *_zzt_rle_encode(ZZTblock *block)
84 {
85 	int size = 0, ofs = 0, ofs2 = 0;
86 	int maxcount = block->width * block->height;
87 	u_int8_t blocks = 1;
88 	u_int8_t type;
89 	u_int8_t color;
90 
91 	u_int8_t *packed;
92 
93 	/* NOTE: the compressed string will only represent as many tiles as
94 	 * are in the given block. If the block is not ZZT size, the encoded
95 	 * string will not be ZZT size either. */
96 
97 	size = _zzt_rle_encoded_size(block);
98 
99 	/* Reallocate data */
100 	packed = malloc(size*3);
101 	/* RLE encode from unpacked */
102 	ofs = ofs2 = 0;
103 	do {
104 		blocks = 1;
105 		type = block->tiles[ofs].type;
106 		color = block->tiles[ofs++].color;
107 		if(ofs < maxcount) {
108 			while(type == block->tiles[ofs].type && color == block->tiles[ofs].color && blocks < 255) {
109 				blocks++;
110 				ofs++;
111 				if(ofs >= maxcount)
112 					break;
113 			}
114 		}
115 		packed[ofs2++] = blocks;
116 		packed[ofs2++] = type;
117 		packed[ofs2++] = color;
118 	} while (ofs < maxcount);
119 	return packed;
120 }
121 
_zzt_param_decode(ZZTparam * params,int paramcount,ZZTblock * block)122 int _zzt_param_decode(ZZTparam* params, int paramcount, ZZTblock *block)
123 {
124 	int i;
125 
126 	/* Store the number of params */
127 	block->paramcount = paramcount;
128 	/* Allocate an array of pointers */
129 	block->params = (ZZTparam **) malloc(sizeof(ZZTparam*) * paramcount);
130 
131 	for (i = 0; i < paramcount; i++) {
132 		/* Duplicate the compressed param */
133 		ZZTparam* param = zztParamDuplicate(params + i);
134 
135 		/* Store the param pointer in the ordered array */
136 		block->params[i] = param;
137 		param->index = i;
138 
139 		/* Store the param pointer in the tile array */
140 		if (params[i].x < block->width && params[i].y < block->height)
141 			zztTileAt(block, params[i].x, params[i].y).param = param;
142 	}
143 	return 1;
144 }
145 
_zzt_param_encode(int * paramsize,int playerx,int playery,ZZTblock * block)146 ZZTparam *_zzt_param_encode(int *paramsize, int playerx, int playery, ZZTblock *block)
147 {
148 	ZZTparam *params;
149 	int i;
150 
151 	if (block->paramcount == 0)
152 		return NULL;
153 
154 	/* Make room for the compressed list of params */
155 	params = (ZZTparam *) malloc(sizeof(ZZTparam) * block->paramcount);
156 
157 	/* Ensure that the first param points to the player */
158 	block->params[0]->x = playerx;
159 	block->params[0]->y = playery;
160 
161 	/* Copy each param onto the params array */
162 	for (i = 0; i < block->paramcount; i++)
163 	{
164 		zztParamCopyPtr(params + i, block->params[i]);
165 	}
166 
167 	*paramsize = block->paramcount;
168 	return params;
169 }
170 
_zztBoardFree(ZZTboard board)171 void _zztBoardFree(ZZTboard board)
172 {
173 	int i;
174 
175 	/* Delete the bigboard */
176 	if (board.bigboard != NULL)
177 		zztBlockFree(board.bigboard);
178 	/* Delete the packed board */
179 	if (board.packed != NULL)
180 		free(board.packed);
181 	/* Delete all params */
182 	if(board.params != NULL) {
183 		for(i = 0; i < board.info.paramcount; i++) {
184 			if(board.params[i].length != 0)
185 				free(board.params[i].program);
186 		}
187 		free(board.params);
188 	}
189 	board.bigboard = NULL;
190 	board.packed = NULL;
191 	board.params = NULL;
192 }
193 
zztBoardCopyPtr(ZZTboard * dest,ZZTboard * src)194 void zztBoardCopyPtr(ZZTboard *dest, ZZTboard *src)
195 {
196 	int tiles = 0, ofs = 0;
197 	int i;
198 
199 	/* Base board junk */
200 	memcpy(dest, src, sizeof(ZZTboard));
201 	/* Packed board */
202 	if (src->packed != NULL) {
203 		do {
204 			tiles += src->packed[ofs];
205 			ofs += 3;
206 		} while(tiles < ZZT_BOARD_MAX_SIZE);
207 		dest->packed = malloc(ofs);
208 		memcpy(dest->packed, src->packed, ofs);
209 	}
210 	/* Parameters */
211 	if(dest->params != NULL) {
212 		dest->params = malloc(sizeof(ZZTparam)*dest->info.paramcount);
213 		memcpy(dest->params, src->params, dest->info.paramcount*sizeof(ZZTparam));
214 		for(i = 0; i < src->info.paramcount; i++) {
215 			if(dest->params[i].length != 0) {
216 				dest->params[i].program = malloc(dest->params[i].length);
217 				memcpy(dest->params[i].program, src->params[i].program, dest->params[i].length);
218 			}
219 		}
220 	}
221 	/* Bigboard */
222 	if (src->bigboard != NULL) {
223 		dest->bigboard = zztBlockDuplicate(src->bigboard);
224 	}
225 }
226 
227 /* _zzt_board_relink(brd, offset, start, end movefrom, moveto)
228  * Add offset to all links in a board between start and end, except
229  * links to "movefrom" which become "moveto" instead
230  */
_zzt_board_relink(ZZTboard * brd,int offset,int start,int end,int movefrom,int moveto)231 int _zzt_board_relink(ZZTboard *brd, int offset, int start, int end, int movefrom, int moveto)
232 {
233 	int j, board_length;
234 
235 	/* Cool macro to save major space */
236 #define relink(link) if ((link) == movefrom) (link) = moveto; else if ((link) >= start && (link) <= end) (link) += offset;
237 
238 	/* Relink board connections */
239 	relink(brd->info.board_n);
240 	relink(brd->info.board_s);
241 	relink(brd->info.board_e);
242 	relink(brd->info.board_w);
243 
244 	/* Do the same for passages */
245 	if (!zztBoardDecompress(brd)) {
246 		fprintf(stderr, "Error decompressing board\n");
247 		return 0;
248 	}
249 	board_length = brd->bigboard->width * brd->bigboard->height;
250 	for (j = 0; j < board_length; j++) {
251 		if (brd->bigboard->tiles[j].type == ZZT_PASSAGE && brd->bigboard->tiles[j].param != NULL) {
252 			relink(brd->bigboard->tiles[j].param->data[2]);
253 		}
254 	}
255 
256 	return 1;
257 }
258 
_zzt_board_limit_links(ZZTboard * brd,int max)259 int _zzt_board_limit_links(ZZTboard *brd, int max)
260 {
261 	int j, board_length;
262 
263 	/* Fix link macro */
264 #define fixlink(link) if ((link) > max) (link) = 0;
265 
266 	/* Fix board connections */
267 	fixlink(brd->info.board_n);
268 	fixlink(brd->info.board_s);
269 	fixlink(brd->info.board_e);
270 	fixlink(brd->info.board_w);
271 
272 	/* Do the same for passages */
273 	if (!zztBoardDecompress(brd)) {
274 		fprintf(stderr, "Error decompressing board\n");
275 		return 0;
276 	}
277 
278 	board_length = brd->bigboard->width * brd->bigboard->height;
279 	for (j = 0; j < board_length; j++) {
280 		if (brd->bigboard->tiles[j].type == ZZT_PASSAGE && brd->bigboard->tiles[j].param != NULL) {
281 			fixlink(brd->bigboard->tiles[j].param->data[2]);
282 		}
283 	}
284 
285 	return 1;
286 }
287 
288 /* Functions present in zzt.h */
289 
zztBoardCreate(char * title)290 ZZTboard *zztBoardCreate(char *title)
291 {
292 	int blocks, remainder, ofs;
293 	int i;
294 
295 	/* Create new board */
296 	ZZTboard *board = malloc(sizeof(ZZTboard));
297 	memset(&board->info, 0, sizeof(ZZTboardinfo));
298 	strncpy(board->title, title, ZZT_BOARD_TITLE_SIZE);
299 	board->title[ZZT_BOARD_TITLE_SIZE] = '\0';
300 	board->info.maxshots = 255;
301 	board->bigboard = NULL;
302 	/* Make packed blank board */
303 	blocks = (ZZT_BOARD_MAX_SIZE-1)/255;
304 	remainder = (ZZT_BOARD_MAX_SIZE-1)%255;
305 	board->packed = malloc((blocks+2)*3);
306 	ofs = 0;
307 	board->packed[ofs++] = 1;
308 	board->packed[ofs++] = ZZT_PLAYER;
309 	board->packed[ofs++] = 0x1F;
310 	for(i = 0; i < blocks+1; i++) {
311 		board->packed[ofs++] = 255;
312 		board->packed[ofs++] = ZZT_EMPTY;
313 		board->packed[ofs++] = 0x0F;
314 	}
315 	board->packed[ofs-3] = remainder;
316 	/* Make player param */
317 	board->params = malloc(sizeof(ZZTparam));
318 	memset(board->params, 0, sizeof(ZZTparam));
319 	board->params->cycle = 1;
320 	board->info.paramcount = 1;
321 	/* Player position: (0, 0) */
322 	board->plx = board->ply = 0;
323 
324 	return board;
325 }
326 
zztBoardFree(ZZTboard * board)327 void zztBoardFree(ZZTboard *board)
328 {
329 	_zztBoardFree(*board);
330 	/* Delete the board pointer */
331 	free(board);
332 }
333 
zztBoardLoad(char * filename)334 ZZTboard *zztBoardLoad(char *filename)
335 {
336 	ZZTboard *board;
337 	FILE *fp;
338 
339 	/* Open file */
340 	fp = fopen(filename, "rb");
341 	if(fp == NULL)
342 		return NULL;
343 
344 	/* Read from file */
345 	board = zztBoardRead(fp);
346 	fclose(fp);
347 
348 	/* Done */
349 	return board;
350 }
351 
zztBoardSave(ZZTboard * board,char * filename)352 int zztBoardSave(ZZTboard *board, char *filename)
353 {
354 	int result;
355 	FILE *fp;
356 
357 	/* Open file */
358 	fp = fopen(filename, "wb");
359 	if(fp == NULL)
360 		return 0;
361 
362 	/* Compress the board before writing */
363 	zztBoardCompress(board);
364 
365 	/* Write to file */
366 	result = zztBoardWrite(board, fp);
367 	fclose(fp);
368 
369 	/* Done */
370 	return result;
371 }
372 
zztBoardCopy(ZZTboard * board)373 ZZTboard *zztBoardCopy(ZZTboard *board)
374 {
375 	ZZTboard *new = malloc(sizeof(ZZTboard));
376 	zztBoardCopyPtr(new, board);
377 	return new;
378 }
379 
zztBoardDecompress(ZZTboard * board)380 int zztBoardDecompress(ZZTboard *board)
381 {
382 	int i;
383 
384 	/* Do not decompress if already decompressed */
385 	if (board->bigboard != NULL || board->packed == NULL || board->params == NULL)
386 		/* Consider giving an error if one but not all of the above are true */
387 		return 1;
388 
389 	board->bigboard = zztBlockCreate(ZZT_BOARD_X_SIZE, ZZT_BOARD_Y_SIZE);
390 
391 	if (board->bigboard == NULL)
392 		return 0;
393 
394 	/* Decode packed & params onto bigboard */
395 	_zzt_rle_decode(board->packed, board->bigboard);
396 	_zzt_param_decode(board->params, board->info.paramcount, board->bigboard);
397 
398 	/* Free packed & params */
399 	free(board->packed);
400 	for(i = 0; i < board->info.paramcount; i++) {
401 		if(board->params[i].length != 0)
402 			free(board->params[i].program);
403 	}
404 	free(board->params);
405 
406 	board->packed = NULL;
407 	board->params = NULL;
408 
409 	return 1;
410 }
411 
zztBoardCompress(ZZTboard * board)412 int zztBoardCompress(ZZTboard *board)
413 {
414 	int paramcount;
415 
416 	/* Do not compress if alread compressed */
417 	if (board->packed != NULL || board->params != NULL || board->bigboard == NULL)
418 		/* Consider giving an error if one but not all of the above are true */
419 		return 1;
420 
421 	/* Pack the bigboard back into packed and params */
422 	board->packed = _zzt_rle_encode(board->bigboard);
423 	if (board->packed == NULL)
424 		return 0;
425 	board->params = _zzt_param_encode(&paramcount, board->plx, board->ply,
426 																		board->bigboard);
427 	if (board->params == NULL)
428 		return 0;
429 	board->info.paramcount = paramcount;
430 
431 	zztBlockFree(board->bigboard);
432 	board->bigboard = NULL;
433 
434 	return 1;
435 }
436 
zztBoardGetSize(ZZTboard * board)437 u_int16_t zztBoardGetSize(ZZTboard *board)
438 {
439 	u_int16_t size = 0;
440 	int i;
441 
442 	size += 0x34; /* Header */
443 	size += 0x58; /* Info */
444 	size += 1;    /* ? */
445 
446 	/* Size the bigboard */
447 	if (board->bigboard != NULL) {
448 		size += _zzt_rle_encoded_size(board->bigboard) * 3;
449 		size += board->bigboard->paramcount * 0x21;
450 		/* Find size of program data */
451 		for (i = 0; i < board->bigboard->width * board->bigboard->height; i++)
452 			if (board->bigboard->tiles[i].param != NULL)
453 				size += board->bigboard->tiles[i].param->length;
454 	} else if (board->packed != NULL) {
455 		/* TODO: find size of packed & params */
456 	}
457 
458 	return size;
459 }
460 
zztWorldAddBoard(ZZTworld * world,char * title)461 void zztWorldAddBoard(ZZTworld *world, char *title)
462 {
463 	ZZTboard *backup, *new;
464 	int bcount = zztWorldGetBoardcount(world);
465 
466 	if(bcount != 0) {
467 		/* Make backup of existing board list */
468 		backup = malloc(sizeof(ZZTboard)*bcount);
469 		memcpy(backup, world->boards, sizeof(ZZTboard)*bcount);
470 		free(world->boards);
471 	}
472 	/* Allocate bigger board list */
473 	zztWorldSetBoardcount(world, ++bcount);
474 	world->boards = malloc(sizeof(ZZTboard)*bcount);
475 	/* Restore existing board list */
476 	if(bcount != 1) {
477 		memcpy(world->boards, backup, sizeof(ZZTboard)*(bcount-1));
478 		free(backup);
479 	}
480 
481 	/* Create new board */
482 	new = zztBoardCreate(title);
483 	memcpy(&world->boards[bcount-1], new, sizeof(ZZTboard));
484 	free(new);	/* Don't ever free a board like this */
485 }
486 
zztWorldDeleteBoard(ZZTworld * world,int number,int relink)487 int zztWorldDeleteBoard(ZZTworld *world, int number, int relink)
488 {
489 	ZZTboard *backup;
490 	int bcount = zztWorldGetBoardcount(world);
491 	int i;
492 
493 	/* Check that it's in range */
494 	if(number < 0 || number >= bcount)
495 		return 0;
496 
497 	/* Clear the current board from memory */
498 	_zztBoardFree(world->boards[number]);
499 
500 	if(bcount != 1) {
501 		/* Remember where the old board array is */
502 		backup = world->boards;
503 
504 		/* Resize new array */
505 		zztWorldSetBoardcount(world, --bcount);
506 		world->boards = malloc(sizeof(ZZTboard)*bcount);
507 
508 		/* Copy boards before deleted one */
509 		for(i = 0; i < number; i++)
510 			memcpy(&world->boards[i], &backup[i], sizeof(ZZTboard));
511 
512 		/* Copy boards after deleted one */
513 		for(i = number+1; i < bcount+1; i++)
514 			memcpy(&world->boards[i-1], &backup[i], sizeof(ZZTboard));
515 
516 		/* Free the old board array */
517 		free(backup);
518 
519 		/* Move back one if we're over it */
520 		/* Do this before relinking so we know which board not to compress */
521 		if(world->cur_board > number) {
522 			world->cur_board--;
523 		}
524 
525 		/* Relink boards */
526 		if(relink) {
527 			for(i = 0; i < bcount; i++) {
528 				ZZTboard* brd = &(world->boards[i]);
529 				/* Relink links pointing to the next board up to
530 				 * where the boardcount ended _before_ we deleted this board!
531 				 * (that's one less that bcount + 1) */
532 				_zzt_board_relink(brd, -1, number + 1, bcount, number, 0);
533 
534 				/* Recompress the board unless it is the current board */
535 				if (i != world->cur_board)
536 					zztBoardCompress(brd);
537 			}
538 			if(world->header->startboard == number)
539 				world->header->startboard = 0;
540 			if(world->header->startboard > number)
541 				world->header->startboard--;
542 		}
543 	} else {
544 		/* Delete the last board */
545 		free(world->boards);
546 		world->boards = NULL;
547 		zztWorldSetBoardcount(world, 0);
548 	}
549 	return 1;
550 }
551 
zztWorldInsertBoard(ZZTworld * world,ZZTboard * board,int number,int relink)552 int zztWorldInsertBoard(ZZTworld *world, ZZTboard *board, int number, int relink)
553 {
554 	ZZTboard *backup;
555 	int bcount = zztWorldGetBoardcount(world);
556 	int i;
557 
558 	/* Check that it's in range */
559 	if(number < 0 || number > bcount)
560 		return 0;
561 
562 	/* Deleting the 0th board and relinking is impossible */
563 	if(relink && number == 0)
564 		return 0;
565 
566 	/* Remember where the original board array is */
567 	backup = world->boards;
568 
569 	/* Resize new array */
570 	zztWorldSetBoardcount(world, ++bcount);
571 	world->boards = malloc(sizeof(ZZTboard)*bcount);
572 
573 	/* Copy boards before new one */
574 	for(i = 0; i < number; i++)
575 		memcpy(&world->boards[i], &backup[i], sizeof(ZZTboard));
576 	/* Copy boards after new one */
577 	for(i = number+1; i < bcount; i++)
578 		memcpy(&world->boards[i], &backup[i-1], sizeof(ZZTboard));
579 
580 	/* Free the old array */
581 	free(backup);
582 	backup = NULL;
583 
584 	/* Move up one if we're over it */
585 	/* Must be done before relinking */
586 	if(world->cur_board >= number) {
587 		world->cur_board++;
588 	}
589 
590 	/* Relink boards */
591 	if(relink) {
592 		for(i = 0; i < bcount; i++) {
593 			ZZTboard* brd = &(world->boards[i]);
594 
595 			/* This board has yet to be inserted -- avoid */
596 			if(i == number)
597 				continue;
598 
599 			_zzt_board_relink(brd, 1, number, zztWorldGetBoardcount(world), 0, 0);
600 
601 			/* Recompress the board unless it is the current board */
602 			if (i != world->cur_board)
603 				zztBoardCompress(brd);
604 		}
605 		if(world->header->startboard >= number)
606 			world->header->startboard++;
607 	}
608 
609 	/* Insert the new board (finally!) */
610 	zztBoardCopyPtr(&world->boards[number], board);
611 
612 	/* Make sure curboard is decompressed */
613 	zztBoardDecompress(&world->boards[world->cur_board]);
614 
615 	return 1;
616 }
617 
618 /* This is blue magick */
zztWorldMoveBoard(ZZTworld * world,int src,int dest)619 int zztWorldMoveBoard(ZZTworld *world, int src, int dest)
620 {
621 	int bcount = zztWorldGetBoardcount(world);
622 	int high, low, offset;
623 	int i;
624 	ZZTboard* copy;
625 
626 	if(src == dest) {
627 		return 1; /* ;) */
628 	}
629 	if(src < 1 || src >= bcount) {
630 		return 0;
631 	}
632 	if(dest < 1 || dest >= bcount) {
633 		return 0;
634 	}
635 
636 	if(src < dest) {
637 		high = dest;
638 		low = src;
639 		offset = -1;
640 	} else {
641 		high = src;
642 		low = dest;
643 		offset = 1;
644 	}
645 
646 	/* Consider the current board */
647 	if (world->cur_board == src)
648 		world->cur_board = dest;
649 	else if (world->cur_board >= low && world->cur_board <= high)
650 		world->cur_board += offset;
651 
652 	/* Consider the starting board */
653 	if (world->header->startboard == src)
654 		world->header->startboard = dest;
655 	else if (world->header->startboard >= low && world->header->startboard <= high)
656 		world->header->startboard += offset;
657 
658 	/* Run thourgh all boards and relink them */
659 	for (i = 0; i < bcount; i++) {
660 		ZZTboard* brd = &(world->boards[i]);
661 		_zzt_board_relink(brd, offset, low, high, src, dest);
662 
663 		/* Recompress the board unless it is the current board */
664 		if (i != world->cur_board)
665 			zztBoardCompress(brd);
666 	}
667 
668 	/* MOVE IT */
669 
670 	/* Make a copy of the board-to-be-moved */
671 	if((copy = zztBoardCopy(&world->boards[src])) == NULL) {
672 		return 0;
673 	}
674 
675 	/* Delete the src board from it's current position */
676 	zztWorldDeleteBoard(world, src, 0);
677 
678 	/* Insert copy of src board at destination */
679 	zztWorldInsertBoard(world, copy, dest, 0);
680 
681 	/* Free the copy! */
682 	zztBoardFree(copy);
683 
684 	return 1;
685 }
686 
zztBoardSelect(ZZTworld * world,int number)687 int zztBoardSelect(ZZTworld *world, int number)
688 {
689 	/* Check range */
690 	if(number < 0 || number >= world->header->boardcount)
691 		return 0;
692 
693 	/* Commit old current board */
694 	zztBoardCommit(world);
695 
696 	/* Set new current board */
697 	world->cur_board = number;
698 	/* Uncompress to bigboard */
699 	zztBoardDecompress(&world->boards[number]);
700 
701 	return 1;
702 }
703 
zztBoardCommit(ZZTworld * world)704 void zztBoardCommit(ZZTworld *world)
705 {
706 	int curboard = zztBoardGetCurrent(world);
707 
708 	/* Compress the current board */
709 	zztBoardCompress(&(world->boards[curboard]));
710 }
711 
zztBoardClear(ZZTworld * world)712 int zztBoardClear(ZZTworld *world)
713 {
714 	ZZTboard * brd = zztBoardGetCurPtr(world);
715 	ZZTboard * newbrd;
716 
717 	/* Create a new board */
718 	newbrd = zztBoardCreate("");
719 	if (newbrd == NULL)
720 		return 0;
721 
722 	/* Free the old board data (not the board itself) */
723 	_zztBoardFree(*brd);
724 
725 	/* Who feels lazy? */
726 	memcpy(brd, newbrd, sizeof(ZZTboard));
727 
728 	/* FREE ONLY THE LOWEST LEVEL of the new board!
729 	 * Pointers to other memory locations are now copied
730 	 * into the board array via brd */
731 	free(newbrd);
732 
733 	/* Decompress the current board */
734 	zztBoardDecompress(brd);
735 
736 	return 1;
737 }
738 
zztBoardValidateLinks(ZZTworld * world)739 int zztBoardValidateLinks(ZZTworld *world)
740 {
741 	return _zzt_board_limit_links(zztBoardGetCurPtr(world), zztWorldGetBoardcount(world) - 1);
742 }
743 
zztBoardGetCurrent(ZZTworld * world)744 int zztBoardGetCurrent(ZZTworld *world)
745 {
746 	return world->cur_board;
747 }
748 
zztBoardGetCurPtr(ZZTworld * world)749 ZZTboard * zztBoardGetCurPtr(ZZTworld *world)
750 {
751 	return &(world->boards[world->cur_board]);
752 }
753 
zztBoardGetBlock(ZZTworld * world)754 ZZTblock * zztBoardGetBlock(ZZTworld *world)
755 {
756 	return world->boards[world->cur_board].bigboard;
757 }
758 
zztBoardSetTitle(ZZTworld * world,char * title)759 void zztBoardSetTitle(ZZTworld *world, char *title)
760 {
761 	strncpy(world->boards[world->cur_board].title, title, ZZT_BOARD_TITLE_SIZE);
762 	world->boards[world->cur_board].title[ZZT_BOARD_TITLE_SIZE] = '\0';
763 }
zztBoardSetMaxshots(ZZTworld * world,u_int8_t maxshots)764 void zztBoardSetMaxshots(ZZTworld *world, u_int8_t maxshots)
765 {
766 	world->boards[world->cur_board].info.maxshots = maxshots;
767 }
zztBoardSetDarkness(ZZTworld * world,u_int8_t darkness)768 void zztBoardSetDarkness(ZZTworld *world, u_int8_t darkness)
769 {
770 	world->boards[world->cur_board].info.darkness = darkness;
771 }
zztBoardSetBoard_n(ZZTworld * world,u_int8_t board_n)772 void zztBoardSetBoard_n(ZZTworld *world, u_int8_t board_n)
773 {
774 	world->boards[world->cur_board].info.board_n = board_n;
775 }
zztBoardSetBoard_s(ZZTworld * world,u_int8_t board_s)776 void zztBoardSetBoard_s(ZZTworld *world, u_int8_t board_s)
777 {
778 	world->boards[world->cur_board].info.board_s = board_s;
779 }
zztBoardSetBoard_w(ZZTworld * world,u_int8_t board_w)780 void zztBoardSetBoard_w(ZZTworld *world, u_int8_t board_w)
781 {
782 	world->boards[world->cur_board].info.board_w = board_w;
783 }
zztBoardSetBoard_e(ZZTworld * world,u_int8_t board_e)784 void zztBoardSetBoard_e(ZZTworld *world, u_int8_t board_e)
785 {
786 	world->boards[world->cur_board].info.board_e = board_e;
787 }
zztBoardSetReenter(ZZTworld * world,u_int8_t reenter)788 void zztBoardSetReenter(ZZTworld *world, u_int8_t reenter)
789 {
790 	world->boards[world->cur_board].info.reenter = reenter;
791 }
zztBoardSetReenter_x(ZZTworld * world,u_int8_t reenter_x)792 void zztBoardSetReenter_x(ZZTworld *world, u_int8_t reenter_x)
793 {
794 	world->boards[world->cur_board].info.reenter_x = reenter_x;
795 }
zztBoardSetReenter_y(ZZTworld * world,u_int8_t reenter_y)796 void zztBoardSetReenter_y(ZZTworld *world, u_int8_t reenter_y)
797 {
798 	world->boards[world->cur_board].info.reenter_y = reenter_y;
799 }
zztBoardSetMessage(ZZTworld * world,char * message)800 void zztBoardSetMessage(ZZTworld *world, char *message)
801 {
802 	strncpy(world->boards[world->cur_board].info.message, message, ZZT_MESSAGE_SIZE);
803 	world->boards[world->cur_board].info.message[ZZT_MESSAGE_SIZE] = '\0';
804 }
zztBoardSetTimelimit(ZZTworld * world,u_int16_t timelimit)805 void zztBoardSetTimelimit(ZZTworld *world, u_int16_t timelimit)
806 {
807 	world->boards[world->cur_board].info.timelimit = timelimit;
808 }
zztBoardSetParamcount(ZZTworld * world,u_int16_t paramcount)809 void zztBoardSetParamcount(ZZTworld *world, u_int16_t paramcount)
810 {
811 	// XXX Don't ever use this, it's just here for completeness
812 	world->boards[world->cur_board].info.paramcount = paramcount;
813 }
814 
zztBoardGetTitle(ZZTworld * world)815 u_int8_t *zztBoardGetTitle(ZZTworld *world)
816 {
817 	return world->boards[world->cur_board].title;
818 }
zztBoardGetMaxshots(ZZTworld * world)819 u_int8_t zztBoardGetMaxshots(ZZTworld *world)
820 {
821 	return world->boards[world->cur_board].info.maxshots;
822 }
zztBoardGetDarkness(ZZTworld * world)823 u_int8_t zztBoardGetDarkness(ZZTworld *world)
824 {
825 	return world->boards[world->cur_board].info.darkness;
826 }
zztBoardGetBoard_n(ZZTworld * world)827 u_int8_t zztBoardGetBoard_n(ZZTworld *world)
828 {
829 	return world->boards[world->cur_board].info.board_n;
830 }
zztBoardGetBoard_s(ZZTworld * world)831 u_int8_t zztBoardGetBoard_s(ZZTworld *world)
832 {
833 	return world->boards[world->cur_board].info.board_s;
834 }
zztBoardGetBoard_w(ZZTworld * world)835 u_int8_t zztBoardGetBoard_w(ZZTworld *world)
836 {
837 	return world->boards[world->cur_board].info.board_w;
838 }
zztBoardGetBoard_e(ZZTworld * world)839 u_int8_t zztBoardGetBoard_e(ZZTworld *world)
840 {
841 	return world->boards[world->cur_board].info.board_e;
842 }
zztBoardGetReenter(ZZTworld * world)843 u_int8_t zztBoardGetReenter(ZZTworld *world)
844 {
845 	return world->boards[world->cur_board].info.reenter;
846 }
zztBoardGetReenter_x(ZZTworld * world)847 u_int8_t zztBoardGetReenter_x(ZZTworld *world)
848 {
849 	return world->boards[world->cur_board].info.reenter_x;
850 }
zztBoardGetReenter_y(ZZTworld * world)851 u_int8_t zztBoardGetReenter_y(ZZTworld *world)
852 {
853 	return world->boards[world->cur_board].info.reenter_y;
854 }
zztBoardGetMessage(ZZTworld * world)855 u_int8_t *zztBoardGetMessage(ZZTworld *world)
856 {
857 	return world->boards[world->cur_board].info.message;
858 }
zztBoardGetTimelimit(ZZTworld * world)859 u_int16_t zztBoardGetTimelimit(ZZTworld *world)
860 {
861 	return world->boards[world->cur_board].info.timelimit;
862 }
zztBoardGetParamcount(ZZTworld * world)863 u_int16_t zztBoardGetParamcount(ZZTworld *world)
864 {
865 	return world->boards[world->cur_board].info.paramcount;
866 }
867