Fixed importer, added index for faster loading. Now runs on the IIgs. You can walk on open squares.
This commit is contained in:
parent
9d962fa564
commit
ee85b19c0b
4 changed files with 266 additions and 73 deletions
|
@ -57,13 +57,14 @@ int main(int argc, char *argv[]) {
|
|||
unsigned char b2;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t count = 0;
|
||||
int32_t bytes = 0;
|
||||
int16_t count;
|
||||
int32_t bytes;
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
FILE *puzzles;
|
||||
FILE *index;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("%s: [letslogic.txt] [puzzles.dat]\n", argv[0]);
|
||||
if (argc != 4) {
|
||||
printf("%s: [letslogic.txt] [puzzles.dat] [index.dat]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -73,18 +74,26 @@ int main(int argc, char *argv[]) {
|
|||
return 2;
|
||||
}
|
||||
|
||||
out = fopen(argv[2], "wb");
|
||||
if (!out) {
|
||||
puzzles = fopen(argv[2], "wb");
|
||||
if (!puzzles) {
|
||||
fclose(in);
|
||||
printf("Unable to write %s\n", argv[2]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Skip two bytes at the front of the file to later write the puzzle count into.
|
||||
fputc(0, out);
|
||||
fputc(0, out);
|
||||
bytes = 2;
|
||||
index = fopen(argv[3], "wb");
|
||||
if (!index) {
|
||||
fclose(puzzles);
|
||||
fclose(in);
|
||||
printf("Unable to write %s\n", argv[3]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Skip two bytes at the front of the index file to later write the puzzle count into.
|
||||
fputc(0, index);
|
||||
fputc(0, index);
|
||||
|
||||
bytes = 0;
|
||||
count = 0;
|
||||
height = -1;
|
||||
width = 0;
|
||||
|
@ -101,7 +110,7 @@ int main(int argc, char *argv[]) {
|
|||
// Got it. Read this line.
|
||||
if (width < strlen(line)) {
|
||||
width = strlen(line);
|
||||
printf("Width %d\n", width);
|
||||
//printf("Width %d\n", width);
|
||||
}
|
||||
height++;
|
||||
for (x=0; x<width; x++) {
|
||||
|
@ -113,45 +122,48 @@ int main(int argc, char *argv[]) {
|
|||
// Yep! Output it!
|
||||
height++; // Make it 1 based ('width' has been 1 based the whole time)
|
||||
if ((width & 1) == 1) {
|
||||
// Width must be even - fill new column with 1, which will become zero below.
|
||||
// Width must be even - fill new column with empty space
|
||||
for (y=0; y<height; y++) {
|
||||
puzzle[width][y] = 1;
|
||||
puzzle[width][y] = '_';
|
||||
}
|
||||
width++;
|
||||
printf("Increased width to %d\n", width);
|
||||
//printf("Increased width to %d\n", width);
|
||||
}
|
||||
fputc(width, out);
|
||||
fputc(height, out);
|
||||
// Save to index
|
||||
fwrite(&bytes, sizeof(int32_t), 1, index);
|
||||
// Save puzzle
|
||||
fputc(width, puzzles);
|
||||
fputc(height, puzzles);
|
||||
bytes += 2;
|
||||
// Write out the puzzle data, two tiles to a byte.
|
||||
printf("%dx%d\n", width, height);
|
||||
//printf("%dx%d\n", width, height);
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x+=2) {
|
||||
b1 = isLegal(puzzle[x][y]) - 1;
|
||||
b2 = isLegal(puzzle[x + 1][y]) - 1;
|
||||
printf("%c%c", puzzleChars[b1], puzzleChars[b2]);
|
||||
fputc((b1 << 4) + b2, out);
|
||||
//printf("%c%c", puzzleChars[b1], puzzleChars[b2]);
|
||||
fputc((b1 << 4) + b2, puzzles);
|
||||
bytes++;
|
||||
}
|
||||
printf("\n");
|
||||
//printf("\n");
|
||||
}
|
||||
// Reset for next pass.
|
||||
count++;
|
||||
width = 0;
|
||||
height = -1;
|
||||
printf("Puzzle %d imported, %d total bytes written.\n", count, bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Seek back to the top and write the number of puzzles found.
|
||||
fflush(out);
|
||||
fseek(out, 0, SEEK_SET);
|
||||
fwrite(&count, sizeof(int16_t), 1, out);
|
||||
fflush(index);
|
||||
fseek(index, 0, SEEK_SET);
|
||||
fwrite(&count, sizeof(int16_t), 1, index);
|
||||
|
||||
fclose(out);
|
||||
fclose(index);
|
||||
fclose(puzzles);
|
||||
fclose(in);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
PROJECT=warehouse
|
||||
DATA=(font.img font.stn kanga.img tiles.img ../puzzles.dat)
|
||||
DATA=(font.img font.stn kanga.img tiles.img ../puzzles.dat ../index.dat)
|
||||
#SOURCE=(*.c *.h)
|
||||
SOURCE=()
|
||||
|
||||
|
|
272
warehouse/main.c
272
warehouse/main.c
|
@ -42,11 +42,14 @@ segment "warehouse";
|
|||
#define TILE_GOAL 3
|
||||
#define TILE_CRATE 4
|
||||
#define TILE_PLAYER 5
|
||||
#define TILE_CRATE_ON_GOAL 6
|
||||
#define TILE_PLAYER_ON_GOAL 7
|
||||
#define TILE_PLAYER_ON_GOAL 6
|
||||
#define TILE_CRATE_ON_GOAL 7
|
||||
#define TILE_COUNT 8
|
||||
|
||||
|
||||
typedef struct PuzzleS {
|
||||
byte offsetX;
|
||||
byte offsetY;
|
||||
byte width;
|
||||
byte height;
|
||||
byte puzzle[MAX_WIDTH][MAX_HEIGHT];
|
||||
|
@ -58,62 +61,161 @@ typedef struct SaveS {
|
|||
byte *solved;
|
||||
} SaveT;
|
||||
|
||||
typedef struct CoordS {
|
||||
byte x;
|
||||
byte y;
|
||||
} CoordT;
|
||||
|
||||
static jlImgT *fontI = NULL;
|
||||
|
||||
static jlImgT *fontI = NULL;
|
||||
static jlImgT *tilesI = NULL;
|
||||
|
||||
static jint16 puzzleCount = 0;
|
||||
static jint16 puzzleCount;
|
||||
|
||||
static jint32 *puzzleIndex = NULL;
|
||||
|
||||
static PuzzleT puzzle;
|
||||
static SaveT saveGame;
|
||||
|
||||
static byte puzzleNow[MAX_WIDTH][MAX_HEIGHT];
|
||||
static byte puzzleBefore[MAX_WIDTH][MAX_HEIGHT];
|
||||
|
||||
static byte avatarX;
|
||||
static byte avatarY;
|
||||
static byte avatarXLast;
|
||||
static byte avatarYLast;
|
||||
|
||||
static char puzzleChars[] = { "_# .$@+*" };
|
||||
|
||||
static CoordT tileLookup[TILE_COUNT] = {
|
||||
{ 10 * 8, 0 },
|
||||
{ 0 * 8, 0 },
|
||||
{ 2 * 8, 0 },
|
||||
{ 4 * 8, 0 },
|
||||
{ 6 * 8, 0 },
|
||||
{ 8 * 8, 0 },
|
||||
{ 8 * 8, 0 },
|
||||
{ 6 * 8, 0 }
|
||||
};
|
||||
|
||||
|
||||
void drawAvatar(void);
|
||||
void drawPuzzle(void);
|
||||
void loadPuzzle(jint16 number);
|
||||
void printPuzzle(char *message, byte which[MAX_WIDTH][MAX_HEIGHT]);
|
||||
void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...);
|
||||
|
||||
|
||||
void drawAvatar(void) {
|
||||
jint16 x = 0; // Screen (tile) coordinates.
|
||||
jint16 y = 0;
|
||||
CoordT t;
|
||||
|
||||
x = ((avatarX << 1) + puzzle.offsetX) << 3;
|
||||
y = ((avatarY << 1) + puzzle.offsetY) << 3;
|
||||
t = tileLookup[TILE_PLAYER];
|
||||
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x, t.y, x, y );
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x + 8, t.y, x + 8, y );
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x, t.y + 8, x, y + 8);
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x + 8, t.y + 8, x + 8, y + 8);
|
||||
}
|
||||
|
||||
|
||||
void drawPuzzle(void) {
|
||||
byte bx = 0; // Board coordinates.
|
||||
byte by = 0;
|
||||
jint16 x = 0; // Screen (tile) coordinates.
|
||||
jint16 y = 0;
|
||||
CoordT t;
|
||||
|
||||
for (by=0; by<puzzle.height; by++) {
|
||||
y = ((by << 1) + puzzle.offsetY) << 3;
|
||||
for (bx=0; bx<puzzle.width; bx++) {
|
||||
// Is this tile "dirty" on the display?
|
||||
if (puzzleNow[bx][by] != puzzleBefore[bx][by]) {
|
||||
puzzleBefore[bx][by] = puzzleNow[bx][by];
|
||||
x = ((bx << 1) + puzzle.offsetX) << 3;
|
||||
t = tileLookup[puzzleNow[bx][by]];
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x, t.y, x, y );
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x + 8, t.y, x + 8, y );
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x, t.y + 8, x, y + 8);
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x + 8, t.y + 8, x + 8, y + 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loadPuzzle(jint16 number) {
|
||||
FILE *in = NULL;
|
||||
jint16 count = 0;
|
||||
byte x = 0;
|
||||
byte y = 0;
|
||||
|
||||
// NOTE: We don't use fgetc() because it's borked in ORCA/C.
|
||||
|
||||
in = fopen("data/puzzles.dat", "rb");
|
||||
if (!in) jlUtilDie("Unable to open puzzle database!");
|
||||
|
||||
// Skip over puzzle count bytes.
|
||||
fread(&puzzleCount, sizeof(jint16), 1, in);
|
||||
|
||||
// Iterate until we find the puzzle we need.
|
||||
while (count < number) {
|
||||
// Load width of puzzle
|
||||
puzzle.width = fgetc(in);
|
||||
// Load height of puzzle
|
||||
puzzle.height = fgetc(in);
|
||||
// Load the puzzle itself
|
||||
for (y=0; y<puzzle.height; y++) {
|
||||
for (x=0; x<puzzle.width; x+=2) {
|
||||
puzzle.puzzle[x][y] = fgetc(in);
|
||||
// Split single byte into two tiles
|
||||
puzzle.puzzle[x + 1][y] = puzzle.puzzle[x][y] & 0x0f;
|
||||
puzzle.puzzle[x][y] = puzzle.puzzle[x][y] >> 4;
|
||||
// Skip to requested puzzle.
|
||||
fseek(in, puzzleIndex[number - 1], SEEK_SET);
|
||||
// Load width of puzzle
|
||||
fread(&puzzle.width, sizeof(byte), 1, in);
|
||||
// Load height of puzzle
|
||||
fread(&puzzle.height, sizeof(byte), 1, in);
|
||||
// Load the puzzle itself
|
||||
for (y=0; y<puzzle.height; y++) {
|
||||
for (x=0; x<puzzle.width; x+=2) {
|
||||
fread(&puzzle.puzzle[x][y], sizeof(byte), 1, in);
|
||||
// Split single byte into two tiles.
|
||||
puzzle.puzzle[x + 1][y] = puzzle.puzzle[x][y] & 0x0f;
|
||||
puzzle.puzzle[x][y] = puzzle.puzzle[x][y] >> 4;
|
||||
// Is this our start location? If so, replace with proper tile and remember where we are.
|
||||
if (puzzle.puzzle[x][y] == TILE_PLAYER) {
|
||||
puzzle.puzzle[x][y] = TILE_FLOOR;
|
||||
avatarX = x;
|
||||
avatarY = y;
|
||||
}
|
||||
if (puzzle.puzzle[x][y] == TILE_PLAYER_ON_GOAL) {
|
||||
puzzle.puzzle[x][y] = TILE_GOAL;
|
||||
avatarX = x;
|
||||
avatarY = y;
|
||||
}
|
||||
if (puzzle.puzzle[x + 1][y] == TILE_PLAYER) {
|
||||
puzzle.puzzle[x + 1][y] = TILE_FLOOR;
|
||||
avatarX = x + 1;
|
||||
avatarY = y;
|
||||
}
|
||||
if (puzzle.puzzle[x + 1][y] == TILE_PLAYER_ON_GOAL) {
|
||||
puzzle.puzzle[x + 1][y] = TILE_GOAL;
|
||||
avatarX = x + 1;
|
||||
avatarY = y;
|
||||
}
|
||||
}
|
||||
// Count it.
|
||||
count++;
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
|
||||
//***DEBUG***
|
||||
printf("Puzzles found: %d\n", puzzleCount);
|
||||
printf("Puzzle %d - %dx%d\n", count, puzzle.width, puzzle.height);
|
||||
for (y=0; y<puzzle.height; y++) {
|
||||
for (x=0; x<puzzle.width; x++) {
|
||||
printf("%c", puzzleChars[puzzle.puzzle[x][y]]);
|
||||
// Center puzzle on display.
|
||||
puzzle.offsetX = (10 - puzzle.width / 2) * 2;
|
||||
puzzle.offsetY = (6 - puzzle.height / 2) * 2;
|
||||
|
||||
// Make copie for our rendering array.
|
||||
memcpy(&puzzleNow, puzzle.puzzle, sizeof(byte) * MAX_WIDTH * MAX_HEIGHT);
|
||||
|
||||
// Clear "displayed" board so it has to redraw.
|
||||
memset(&puzzleBefore, TILE_NOTHING, sizeof(byte) * MAX_WIDTH * MAX_HEIGHT);
|
||||
}
|
||||
|
||||
|
||||
void printPuzzle(char *message, byte which[MAX_WIDTH][MAX_HEIGHT]) {
|
||||
byte bx = 0; // Board coordinates.
|
||||
byte by = 0;
|
||||
|
||||
printf("%s\n", message);
|
||||
for (by=0; by<puzzle.height; by++) {
|
||||
for (bx=0; bx<puzzle.width; bx++) {
|
||||
printf("%c", puzzleChars[which[bx][by]]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -135,12 +237,12 @@ void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...) {
|
|||
vsprintf(msg, what, va);
|
||||
va_end(va);
|
||||
|
||||
tx = cx * 8;
|
||||
ty = cy * 8;
|
||||
tx = cx << 3;
|
||||
ty = cy << 3;
|
||||
|
||||
for (counter=0; counter<(int)strlen(msg); counter++) {
|
||||
x = (msg[counter] % 40) * 8;
|
||||
y = (msg[counter] / 40) * 8;
|
||||
x = (msg[counter] % 40) << 3;
|
||||
y = (msg[counter] / 40) << 3;
|
||||
jlDrawBlit8x8(jlImgSurfaceGet(font), x, y, tx, ty);
|
||||
tx += 8;
|
||||
}
|
||||
|
@ -148,7 +250,11 @@ void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...) {
|
|||
|
||||
|
||||
int main(void) {
|
||||
FILE *in = NULL;
|
||||
FILE *in = NULL;
|
||||
jint16 current = 1;
|
||||
jint16 last = 0;
|
||||
char key = 0;
|
||||
bool playing = true;
|
||||
|
||||
jlUtilStartup("Warehouse");
|
||||
|
||||
|
@ -160,8 +266,8 @@ int main(void) {
|
|||
// For splash screens, reuse tilesI to save memory.
|
||||
jlImgLoad(tilesI, "kanga");
|
||||
if (!tilesI) jlUtilDie("Unable to load kanga!");
|
||||
// jlImgDisplay(tilesI);
|
||||
// jlDisplayPresent();
|
||||
jlImgDisplay(tilesI);
|
||||
jlDisplayPresent();
|
||||
|
||||
// Load the rest of our data.
|
||||
jlImgLoad(tilesI, "tiles");
|
||||
|
@ -169,10 +275,13 @@ int main(void) {
|
|||
jlImgLoad(fontI, "font");
|
||||
if (!fontI) jlUtilDie("Unable to load font!");
|
||||
|
||||
// Load the index.
|
||||
in = fopen("data/index.dat", "rb");
|
||||
if (!in) jlUtilDie("Unable to open puzzle index!");
|
||||
// How many puzzles?
|
||||
in = fopen("data/puzzles.dat", "rb");
|
||||
if (!in) jlUtilDie("Unable to open puzzle database!");
|
||||
fread(&puzzleCount, sizeof(jint16), 1, in);
|
||||
puzzleIndex = (jint32 *)jlMalloc(sizeof(jint32) * puzzleCount);
|
||||
fread(puzzleIndex, sizeof(jint32), puzzleCount, in);
|
||||
fclose(in);
|
||||
|
||||
// Create bit array of possible games for save file.
|
||||
|
@ -194,18 +303,89 @@ int main(void) {
|
|||
memset(saveGame.solved, 0, saveGame.solvedSize);
|
||||
}
|
||||
|
||||
loadPuzzle(1);
|
||||
// Force tile palette
|
||||
jlImgDisplay(tilesI);
|
||||
|
||||
jlDrawClear();
|
||||
jlDrawColorSet(15);
|
||||
printAt(fontI, 0, 0, "%d puzzles found", puzzleCount);
|
||||
jlDisplayPresent();
|
||||
jlKeyWaitForAny();
|
||||
while (playing && !jlUtilMustExit()) {
|
||||
if (jlKeyPressed()) {
|
||||
while (jlKeyPressed()) {
|
||||
key = jlKeyRead();
|
||||
}
|
||||
avatarXLast = avatarX;
|
||||
avatarYLast = avatarY;
|
||||
switch (key) {
|
||||
case 27:
|
||||
playing = false;
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
case 'q':
|
||||
current--;
|
||||
if (current < 1) {
|
||||
current = puzzleCount;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
case 'w':
|
||||
current++;
|
||||
if (current >= puzzleCount) {
|
||||
current = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
case 'i':
|
||||
if (puzzleNow[avatarX][avatarY - 1] == TILE_FLOOR) {
|
||||
avatarY--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
case 'j':
|
||||
if (puzzleNow[avatarX - 1][avatarY] == TILE_FLOOR) {
|
||||
avatarX--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'K':
|
||||
case 'k':
|
||||
if (puzzleNow[avatarX + 1][avatarY] == TILE_FLOOR) {
|
||||
avatarX++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (puzzleNow[avatarX][avatarY + 1] == TILE_FLOOR) {
|
||||
avatarY++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Load new level?
|
||||
if (last != current) {
|
||||
last = current;
|
||||
loadPuzzle(current);
|
||||
avatarXLast = -1;
|
||||
avatarYLast = -1;
|
||||
jlDrawClear();
|
||||
printAt(fontI, 0, 24, "%d puzzles found. Showing #%d", puzzleCount, current);
|
||||
}
|
||||
// Redraw?
|
||||
if ((avatarX != avatarXLast) || (avatarY != avatarYLast)) {
|
||||
puzzleBefore[avatarXLast][avatarYLast] = TILE_NOTHING;
|
||||
//printPuzzle("Now", puzzleNow);
|
||||
//printPuzzle("Before", puzzleBefore);
|
||||
drawPuzzle();
|
||||
drawAvatar();
|
||||
jlDisplayPresent();
|
||||
}
|
||||
}
|
||||
|
||||
jlFree(saveGame.solved);
|
||||
|
||||
jlFree(puzzleIndex);
|
||||
jlImgFree(tilesI);
|
||||
|
||||
jlImgFree(fontI);
|
||||
|
||||
jlUtilShutdown();
|
||||
|
|
|
@ -5,5 +5,6 @@ export JOEY=$2
|
|||
|
||||
mkdir -p data
|
||||
cp -f "${GAME}"/../puzzles.dat data/.
|
||||
cp -f "${GAME}"/../index.dat data/.
|
||||
cp -f "${GAME}"/*.img data/.
|
||||
cp -f "${GAME}"/*.stn data/.
|
||||
|
|
Loading…
Add table
Reference in a new issue