⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 Microwindows genesis was with the NanoGUI project, and is now the primary distribution for both th
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * NanoBreaker, a Nano-X Breakout clone by Alex Holden. * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. *  * The Original Code is NanoBreaker. *  * The Initial Developer of the Original Code is Alex Holden. * Portions created by Alex Holden are Copyright (C) 2002 * Alex Holden <alex@alexholden.net>. All Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the terms * of the GNU General Public license (the  "[GNU] License"), in which case the * provisions of [GNU] License are applicable instead of those * above.  If you wish to allow use of your version of this file only * under the terms of the [GNU] License and not to allow others to use * your version of this file under the MPL, indicate your decision by * deleting  the provisions above and replace  them with the notice and * other provisions required by the [GNU] License.  If you do not delete * the provisions above, a recipient may use your version of this file * under either the MPL or the [GNU] License. *//* loader.c mainly consists of routines for loading the game file. It also * contains the high score file loader and saver. */#include <stdio.h>#include <errno.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <nano-X.h>#include <nxcolors.h>#include "nbreaker.h"/* Print a warning indicating that a particular parameter has been defined * more than once, with the line number of the second definition. */static void redefinewarning(char *name, int line, char *gamefile){	fprintf(stderr, "Warning: redefining %s on line %d of game file "					"\"%s\"\n", name, line, gamefile);}/* Print a warning indicating that some parameter that is only allowed inside * a level block was encountered outside a level block. */static void notinlevblockerr(char *name, int line, char *gamefile){	fprintf(stderr, "Error: %s while not in a level block on "			"line %d of game file \"%s\"\n", name, line, gamefile);}/* Parse a Rows block by reading each line until it reaches a line containing * just EndRows, and convert each row into an appropriate line in the grid of * the specified level (and perform quite a bit of error checking along the * way). Returns 0 on success or 1 on encountering an error. */static int parse_rows(nbstate *state, level *lev, FILE *fp, int *line){	brick *b;	int x, y;	char buf[256], *p;	grid *g = lev->grid;	int startline = *line;	y = 0; /* Start on the first row. */	/* Read lines from the game file in a loop: */	while(fgets(buf, 256, fp)) {		x = 0; /* start the row in the first column. */		*line = *line + 1; /* increment the line number. */		/* Look for the newline at the end of the line. */		if(!(p = strchr(buf, '\n'))) {			/* There wasn't one, which probably means that the			 * line was longer than 255 characters. */			fprintf(stderr, "Too long line on line %d of game file "					"\"%s\"\n", *line, state->gamefile);			return 1;		}		*p = 0; /* Get rid of the newline. */		/* If this is the end of the rows block, return "success": */		if(!memcmp(buf, "EndRows", 7)) return 0;			/* If we've gone past the number of rows in the grid: */		if(y == state->height) {			/* Print an error and return "failure": */			fprintf(stderr, "Too many rows in level definition on"					"line %d of game file \"%s\"\n",					*line, state->gamefile);			return 1;		}		/* For each letter in the row: */		for(p = buf; *p; p++) {			/* Increment the column and if we go past the width of			 * the grid, print an error and return "failure": */			if(++x > state->width) {				fprintf(stderr, "Error: row too long on line "					"%d of game file \"%s\" (Width = %d)\n",					*line, state->gamefile,					state->width);				return 1;			}			if(*p == ' ') b = NULL; /* A space means "no brick". */			else {				/* Search through the global brick list for				 * one with a matching identifier: */				for(b = state->bricks; b && b->identifier != *p;								b = b->next);				/* If one wasn't found: */				if(!b) {					/* Search through the level specific					 * brick list for one with a matching					 * identifier: */					for(b = lev->bricks; b &&						b->identifier != *p;						b = b->next);				}				/* If one wasn't found: */				if(!b) {					/* Print an error message and return					 * "failure": */					fprintf(stderr, "Error: undefined brick"						" \"%c\" on line %d of game "						"file \"%s\"\n", *p, *line,						state->gamefile);					return 1;				}			}						/* A matching brick was found if we get to here.			 * Unless the brick is immutable (which don't count			 * because they're not normally destroyable), increment			 * the count of bricks in this level: */			if(b && !(b->flags & BRICK_FLAG_IMMUTABLE))				lev->numbricks++;						/* Set the current grid location brick pointer: */			g->b = b;			g++; /* Increment to the next grid location. */		}		g += state->width - x; /* skip past the rest of the row. */		y++; /* Increment to the next row. */	}	/* We shouldn't reach here unless the fgets() fails to get a new line	 * either because we reach the end of the file or because an I/O error	 * of some sort occurred. Print an appropriate error message and return	 * "failure" to the caller: */	if(feof(fp)) {		fprintf(stderr, "Error: premature end of file inside rows "				"block that started on line %d of game file "				"\"%s\"\n", startline, state->gamefile);	} else fprintf(stderr, "Error reading from game file \"%s\": %s\n",			state->gamefile, strerror(errno));	return 1;}static int parse_powers(nbstate *state, level *lev, FILE *fp, int *line){	int x, y, i;	char buf[256], *p;	grid *g = lev->grid;	int startline = *line;	char powers[] = " WSTPNF";	y = 0; /* Start on the first row. */	/* Read lines from the game file in a loop: */	while(fgets(buf, 256, fp)) {		x = 0; /* start the row in the first column. */		*line = *line + 1; /* increment the line number. */		/* Look for the newline at the end of the line. */		if(!(p = strchr(buf, '\n'))) {			/* There wasn't one, which probably means that the			 * line was longer than 255 characters. */			fprintf(stderr, "Too long line on line %d of game file "					"\"%s\"\n", *line, state->gamefile);			return 1;		}		*p = 0; /* Get rid of the newline. */		/* If this is the end of the powers block, return "success": */		if(!memcmp(buf, "EndPowers", 9))			return 0;		/* If we've gone past the number of rows in the grid: */		if(y == state->height) {			/* Print an error and return "failure": */			fprintf(stderr, "Too many rows in level definition on"					"line %d of game file \"%s\"\n",					*line, state->gamefile);			return 1;		}		/* For each letter in the row: */		for(p = buf; *p; p++) {			/* Increment the column and if we go past the width of			 * the grid, print an error and return "failure": */			if(++x > state->width) {				fprintf(stderr, "Error: row too long on line "					"%d of game file \"%s\" (Width = %d)\n",					*line, state->gamefile,					state->width);				return 1;			}			/* Search for a power with a matching identifier: */			for(i = 0; powers[i] && powers[i] != *p; i++);			/* If we didn't find one print an error message and			 * return "failure": */			if(!powers[i]) {				fprintf(stderr, "Error: invalid power \"%c\" "					"on line %d of game file \"%s\"\n",					*p, *line, state->gamefile);				return 1;			}			/* Set the power of the current grid location: */			g->power = i - 1;			g++; /* Increment to the next grid location. */		}		g += state->width - x; /* skip past the rest of the row. */		y++; /* Increment to the next row. */	}	/* We shouldn't reach here unless the fgets() fails to get a new line	 * either because we reach the end of the file or because an I/O error	 * of some sort occurred. Print an appropriate error message and return	 * "failure" to the caller: */	if(feof(fp)) {		fprintf(stderr, "Error: premature end of file inside powers "				"block that started on line %d of game file "				"\"%s\"\n", startline, state->gamefile);	} else fprintf(stderr, "Error reading from game file \"%s\": %s\n",			state->gamefile, strerror(errno));	return 1;}/* Parse a brick definition line. */static int parse_brick(nbstate *state, int inlevel, level *lev, int line,		char *buf){	int i;	char *flags, f;	brick *b = NULL;	/* Search for an existing brick with the same identifier in the global	 * brick list: */	for(b = state->bricks; b && b->identifier != *buf; b = b->next);		/* If we didn't find one and we're in a level definition, search for	 * a matching brick in the level specific brick list: */	if(!b && inlevel)		for(b = lev->bricks; b && b->identifier != *buf; b = b->next);		/* If we have found an existing brick with the same identifier, print	 * a warning and return: */	if(b) {		fprintf(stderr, "Warning: ignoring duplicate brick definition "				"on line %d of game file \"%s\"\n", line,				state->gamefile);		return 0;	}	/* Allocate the new brick structure: */	if(!(b = malloc(sizeof(brick)))) {		oom();		return 1;	}	b->identifier = *buf; /* Set the brick identifier. */	buf += 2; /* Skip past the identifier and the space after it. */	/* Look for a space after the filename, and if one is found set it to	 * 0 and set flags to the character after the space. After this, buf	 * points to a null terminated string which is the image filename, and	 * flags is either NULL if there was no space (and no flags) after the	 * filename, or a pointer to a null terminated list of flags. */	if((flags = strchr(buf, ' '))) *flags++ = 0;	b->flags = 0; /* Initialise the flags with all of them turned off. */	/* If there is a flags string: */	if(flags) {		/* For each flag in the string: */		while((f = *flags++)) {			/* Set the flag which matches this letter: */			if(f == 'I') b->flags |= BRICK_FLAG_IMMUTABLE;			else if(f == '2') b->flags |= BRICK_FLAG_2_HITS;			else if(f == '3') b->flags |= BRICK_FLAG_3_HITS;			else if(f == 'S') b->flags |= BRICK_FLAG_SMALL_BONUS;			else if(f == 'M') b->flags |= BRICK_FLAG_MEDIUM_BONUS;			else if(f == 'L') b->flags |= BRICK_FLAG_LARGE_BONUS;			else if(f == 'H') b->flags |= BRICK_FLAG_HUGE_BONUS;			else {				/* The letter wasn't one of the above, so print				 * a warning message and ignore the flag. */				fprintf(stderr, "Warning: ignoring invalid "						"flag \"%c\" specified for "						"brick \"%c\" on line %d "						"of game file \"%s\"\n", f,						b->identifier, line,						state->gamefile);			}		}	}	/* Count the number of flags which affect the number of times you have	 * to hit the brick to destroy it: */	i = 0;	if(b->flags & BRICK_FLAG_IMMUTABLE) i++;	if(b->flags & BRICK_FLAG_2_HITS) i++;	if(b->flags & BRICK_FLAG_3_HITS) i++;	/* If there was more than one of the above flags set, print a warning	 * and cancel all of them: */	if(i > 1) {		fprintf(stderr, "Warning: brick flags I, 2, and 3 are mutually "				"exclusive (see brick \"%c\" on line %d of "				"game file \"%s\")\n", b->identifier, line,				state->gamefile);		b->flags &= ~(BRICK_FLAG_IMMUTABLE | BRICK_FLAG_2_HITS |				BRICK_FLAG_3_HITS);	}	/* Count the number of flags which tell what bonus is associated with	 * this brick: */	i = 0;	if(b->flags & BRICK_FLAG_SMALL_BONUS) i++;	if(b->flags & BRICK_FLAG_MEDIUM_BONUS) i++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -