Fixed importer, added index for faster loading. Now runs on the IIgs. You can walk on open squares.

This commit is contained in:
Scott Duensing 2020-07-28 19:27:05 -05:00
parent 9d962fa564
commit ee85b19c0b
4 changed files with 266 additions and 73 deletions

View file

@ -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;

View file

@ -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=()

View file

@ -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();

View file

@ -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/.