diff --git a/assets/soko/levels/SK_LEVEL_LIST.txt b/assets/soko/levels/SK_LEVEL_LIST.txt index a82eb3fe3..6c5ed87e1 100644 --- a/assets/soko/levels/SK_LEVEL_LIST.txt +++ b/assets/soko/levels/SK_LEVEL_LIST.txt @@ -10,11 +10,12 @@ 31:sk_e_harmonica.bin: 32:sk_e_spine.bin: 33:sk_e_a-frame.bin: -34:sk_e_curlingiron.bin: -35:sk_e_copymachine.bin: +34:sk_e_curling_iron.bin: +35:sk_e_copy_machine.bin: 36:sk_e_spiral.bin: -37:sk_e_steeringwheel.bin: +37:sk_e_steering_wheel.bin: 38:sk_e_casette.bin: +100:sk_e_spywork.bin: 101:sk_e_apollo.bin: 102:sk_e_waterwheel.bin: 103:sk_e_feint.bin: diff --git a/assets/soko/levels/euler/sk_e_copy_machine.tmx b/assets/soko/levels/euler/sk_e_copy_machine.tmx new file mode 100644 index 000000000..3299ae6d7 --- /dev/null +++ b/assets/soko/levels/euler/sk_e_copy_machine.tmx @@ -0,0 +1,50 @@ + + + + + + +0,0,0,0,0,0,2,2,0,0, +0,0,0,2,2,2,2,2,2,2, +0,0,0,2,2,2,2,1,2,2, +0,0,2,2,2,2,2,1,2,2, +0,0,2,2,2,2,2,2,2,2, +0,0,2,2,2,1,1,1,1,2, +0,0,0,0,2,2,2,2,2,2, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/soko/levels/euler/sk_e_curling_iron.tmx b/assets/soko/levels/euler/sk_e_curling_iron.tmx new file mode 100644 index 000000000..17285aeba --- /dev/null +++ b/assets/soko/levels/euler/sk_e_curling_iron.tmx @@ -0,0 +1,26 @@ + + + + + + +0,2,2,2,0,0,2,2,0,0,2,2,0, +2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2, +0,2,2,2,0,0,2,2,0,0,2,2,0 + + + + + + + + + + + + + + + + diff --git a/assets/soko/levels/euler/sk_e_spywork.tmx b/assets/soko/levels/euler/sk_e_spywork.tmx new file mode 100644 index 000000000..2d229aa8d --- /dev/null +++ b/assets/soko/levels/euler/sk_e_spywork.tmx @@ -0,0 +1,26 @@ + + + + + + +2,2,2,2,2,2, +2,2,1,1,1,2, +2,2,2,2,2,2, +2,1,2,2,1,2, +2,1,2,2,2,2, +2,2,2,2,2,2, +2,2,2,2,1,2, +2,2,2,2,2,2 + + + + + + + + + + + + diff --git a/assets/soko/levels/euler/sk_e_steering_wheel.tmx b/assets/soko/levels/euler/sk_e_steering_wheel.tmx new file mode 100644 index 000000000..306a556ef --- /dev/null +++ b/assets/soko/levels/euler/sk_e_steering_wheel.tmx @@ -0,0 +1,21 @@ + + + + + + +0,2,2,2,0,2,2,2,0, +2,2,0,2,2,2,0,2,2, +2,0,0,2,2,2,2,0,2, +2,2,0,2,2,2,0,2,2, +0,2,2,2,2,2,2,2,0 + + + + + + + + + + diff --git a/assets/soko/levels/euler/sk_e_threestep.tmx b/assets/soko/levels/euler/sk_e_threestep.tmx index 1354cb252..87341fd34 100644 --- a/assets/soko/levels/euler/sk_e_threestep.tmx +++ b/assets/soko/levels/euler/sk_e_threestep.tmx @@ -1,17 +1,18 @@ - + - + -2,2,2,2,2, -2,2,2,2,2, -2,2,2,2,2, -2,2,2,2,2, -2,2,2,2,2, -2,2,2,2,2, -0,0,0,0,2, -0,0,0,0,0 +2,2,2,2,2,2, +2,2,2,2,2,2, +2,2,2,2,2,2, +2,2,2,2,2,2, +2,2,2,2,2,2, +2,2,2,2,2,2, +0,0,2,0,2,2, +0,0,2,2,2,2, +0,0,0,0,0,0 @@ -20,22 +21,28 @@ - + - - + + - + - - + + - + - + + + + + + + diff --git a/assets/soko/levels/euler/sk_e_tunnels.tmx b/assets/soko/levels/euler/sk_e_tunnels.tmx index 100325e86..477b93502 100644 --- a/assets/soko/levels/euler/sk_e_tunnels.tmx +++ b/assets/soko/levels/euler/sk_e_tunnels.tmx @@ -1,9 +1,10 @@ - + - + +1,1,1,1,1, 2,2,2,2,2, 2,2,1,1,1, 2,2,2,2,2, @@ -12,12 +13,12 @@ - + - - + + diff --git a/assets/soko/levels/sk_e_overworld.tmx b/assets/soko/levels/sk_e_overworld.tmx index 056463744..2fa592df6 100644 --- a/assets/soko/levels/sk_e_overworld.tmx +++ b/assets/soko/levels/sk_e_overworld.tmx @@ -15,7 +15,7 @@ 0,12,12,12,12,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -12,76,13,13,13,76,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +12,76,13,13,0,76,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 12,13,13,13,77,77,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 12,13,13,13,77,77,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 12,13,13,13,77,77,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/assets/soko/sprites/block/sk_player1.png b/assets/soko/sprites/block/sk_player1.png new file mode 100644 index 000000000..4666a6275 Binary files /dev/null and b/assets/soko/sprites/block/sk_player1.png differ diff --git a/assets/soko/sprites/block/sk_player2.png b/assets/soko/sprites/block/sk_player2.png new file mode 100644 index 000000000..54ea5d573 Binary files /dev/null and b/assets/soko/sprites/block/sk_player2.png differ diff --git a/assets/soko/sprites/block/sk_player3.png b/assets/soko/sprites/block/sk_player3.png new file mode 100644 index 000000000..329c3db3f Binary files /dev/null and b/assets/soko/sprites/block/sk_player3.png differ diff --git a/assets/soko/sprites/block/sk_player4.png b/assets/soko/sprites/block/sk_player4.png new file mode 100644 index 000000000..9f938ff92 Binary files /dev/null and b/assets/soko/sprites/block/sk_player4.png differ diff --git a/assets/soko/sprites/block/sk_player5.png b/assets/soko/sprites/block/sk_player5.png new file mode 100644 index 000000000..9484b31d6 Binary files /dev/null and b/assets/soko/sprites/block/sk_player5.png differ diff --git a/assets/soko/sprites/sk_sticky_trail_crate.png b/assets/soko/sprites/sk_sticky_trail_crate.png index f31c5459d..d7deb2912 100644 Binary files a/assets/soko/sprites/sk_sticky_trail_crate.png and b/assets/soko/sprites/sk_sticky_trail_crate.png differ diff --git a/docs/soko/soko_levels.md b/docs/soko/soko_levels.md index 4814a6436..2f740225d 100644 --- a/docs/soko/soko_levels.md +++ b/docs/soko/soko_levels.md @@ -19,7 +19,6 @@ The player entity should contain a 'gamemode' custom property, set to one of the - SOKO_OVERWORLD - SOKO_CLASSIC - SOKO_EULER -- SOKO_LASERBOUNCE #### Configuring the Overworld The overworld level is where we will add connections between levels. The structure of the game is flat: the player must return to the overworld after they complete a level. There are not multiple overworlds (zones, world 2-2, etc). diff --git a/main/modes/games/soko/soko.c b/main/modes/games/soko/soko.c index 0e54f57fa..95ce681c1 100644 --- a/main/modes/games/soko/soko.c +++ b/main/modes/games/soko/soko.c @@ -13,9 +13,11 @@ static void sokoBackgroundDrawCallback(int16_t x, int16_t y, int16_t w, int16_t static void sokoExtractLevelNamesAndIndices(soko_abs_t* self); // strings -static const char sokoModeName[] = "Sokobanabokabon"; -static const char sokoResumeGameLabel[] = "returnitytoit"; -static const char sokoNewGameLabel[] = "startsyfreshy"; +const char sokoModeName[] = "Hunter's Puzzles"; +static const char sokoPlayGameLabel[] = "Play"; +const char SOKO_TAG[] = "SB"; + +extern const char key_sk_overworldPos[]; // create the mode swadgeMode_t sokoMode = { @@ -40,23 +42,26 @@ soko_abs_t* soko = NULL; static void sokoEnterMode(void) { - soko = calloc(1, sizeof(soko_abs_t)); + soko = heap_caps_calloc(1, sizeof(soko_abs_t), MALLOC_CAP_SPIRAM); // Load a font loadFont("ibm_vga8.font", &soko->ibm, false); + soko->allSolved = false; + // load sprite assets // set pointer soko->currentTheme = &soko->sokoDefaultTheme; soko->sokoDefaultTheme.wallColor = c111; soko->sokoDefaultTheme.floorColor = c444; soko->sokoDefaultTheme.altFloorColor = c444; - soko->background = SKBG_FORREST; + soko->background = SKBG_BLACK; // load or set themes... // Default Theme - loadWsg("sk_pixel_front.wsg", &soko->sokoDefaultTheme.playerDownWSG, false); - loadWsg("sk_pixel_back.wsg", &soko->sokoDefaultTheme.playerUpWSG, false); - loadWsg("sk_pixel_left.wsg", &soko->sokoDefaultTheme.playerLeftWSG, false); - loadWsg("sk_pixel_right.wsg", &soko->sokoDefaultTheme.playerRightWSG, false); + loadWsg("sk_player1.wsg", &soko->sokoDefaultTheme.playerDownWSG, false); + loadWsg("sk_player2.wsg", &soko->sokoDefaultTheme.playerUpWSG, false); + loadWsg("sk_player3.wsg", &soko->sokoDefaultTheme.playerLeftWSG, false); + loadWsg("sk_player4.wsg", &soko->sokoDefaultTheme.playerRightWSG, false); + loadWsg("sk_player5.wsg", &soko->sokoDefaultTheme.playerCenterWSG, false); loadWsg("sk_crate_2.wsg", &soko->sokoDefaultTheme.crateWSG, false); loadWsg("sk_crate_ongoal.wsg", &soko->sokoDefaultTheme.crateOnGoalWSG, false); loadWsg("sk_sticky_crate.wsg", &soko->sokoDefaultTheme.stickyCrateWSG, false); @@ -73,6 +78,7 @@ static void sokoEnterMode(void) soko->overworldTheme.playerUpWSG = soko->sokoDefaultTheme.playerUpWSG; soko->overworldTheme.playerLeftWSG = soko->sokoDefaultTheme.playerLeftWSG; soko->overworldTheme.playerRightWSG = soko->sokoDefaultTheme.playerRightWSG; + soko->overworldTheme.playerCenterWSG = soko->sokoDefaultTheme.playerCenterWSG; soko->overworldTheme.crateWSG = soko->sokoDefaultTheme.crateWSG; soko->overworldTheme.goalWSG = soko->sokoDefaultTheme.goalWSG; soko->overworldTheme.crateOnGoalWSG = soko->sokoDefaultTheme.crateOnGoalWSG; @@ -83,11 +89,12 @@ static void sokoEnterMode(void) soko->overworldTheme.floorColor = c444; // Euler Theme - soko->eulerTheme.playerDownWSG = soko->sokoDefaultTheme.playerDownWSG; - soko->eulerTheme.playerUpWSG = soko->sokoDefaultTheme.playerUpWSG; - soko->eulerTheme.playerLeftWSG = soko->sokoDefaultTheme.playerLeftWSG; - soko->eulerTheme.playerRightWSG = soko->sokoDefaultTheme.playerRightWSG; - soko->eulerTheme.goalWSG = soko->sokoDefaultTheme.goalWSG; + soko->eulerTheme.playerDownWSG = soko->sokoDefaultTheme.playerDownWSG; + soko->eulerTheme.playerUpWSG = soko->sokoDefaultTheme.playerUpWSG; + soko->eulerTheme.playerLeftWSG = soko->sokoDefaultTheme.playerLeftWSG; + soko->eulerTheme.playerRightWSG = soko->sokoDefaultTheme.playerRightWSG; + soko->eulerTheme.playerCenterWSG = soko->sokoDefaultTheme.playerCenterWSG; + soko->eulerTheme.goalWSG = soko->sokoDefaultTheme.goalWSG; loadWsg("sk_e_crate.wsg", &soko->eulerTheme.crateWSG, false); loadWsg("sk_sticky_trail_crate.wsg", &soko->eulerTheme.crateOnGoalWSG, false); @@ -100,10 +107,10 @@ static void sokoEnterMode(void) // Initialize the menu soko->menu = initMenu(sokoModeName, sokoMenuCb); - soko->menuManiaRenderer = initMenuManiaRenderer(&soko->ibm, NULL, NULL); + soko->menuManiaRenderer = initMenuManiaRenderer(NULL, NULL, NULL); - addSingleItemToMenu(soko->menu, sokoResumeGameLabel); - addSingleItemToMenu(soko->menu, sokoNewGameLabel); + // addSingleItemToMenu(soko->menu, sokoResumeGameLabel); + addSingleItemToMenu(soko->menu, sokoPlayGameLabel); // Set the mode to menu mode soko->screen = SOKO_MENU; @@ -119,6 +126,13 @@ static void sokoEnterMode(void) static void sokoExitMode(void) { + for (int32_t lIdx = 0; lIdx < ARRAY_SIZE(soko->levelTitles); lIdx++) + { + if (soko->levelTitles[lIdx]) + { + free(soko->levelTitles[lIdx]); + } + } // Deinitialize the menu deinitMenu(soko->menu); deinitMenuManiaRenderer(soko->menuManiaRenderer); @@ -135,6 +149,7 @@ static void sokoExitMode(void) freeWsg(&soko->sokoDefaultTheme.playerDownWSG); freeWsg(&soko->sokoDefaultTheme.playerLeftWSG); freeWsg(&soko->sokoDefaultTheme.playerRightWSG); + freeWsg(&soko->sokoDefaultTheme.playerCenterWSG); freeWsg(&soko->sokoDefaultTheme.crateWSG); freeWsg(&soko->sokoDefaultTheme.crateOnGoalWSG); freeWsg(&soko->sokoDefaultTheme.stickyCrateWSG); @@ -154,21 +169,27 @@ static void sokoMenuCb(const char* label, bool selected, uint32_t settingVal) if (selected) { // placeholder. - if (label == sokoResumeGameLabel) + if (label == sokoPlayGameLabel) { - int32_t data; - readNvs32("sk_data", &data); - // bitshift, etc, as needed. - uint16_t lastSaved = (uint16_t)data; - sokoLoadGameplay(soko, lastSaved, false); - sokoInitGameBin(soko); - soko->screen = SOKO_LEVELPLAY; - } - else if (label == sokoNewGameLabel) - { - // load level. - // we probably shouldn't have a new game option; just an overworld option. - sokoLoadGameplay(soko, 0, true); + int32_t overworld_player; + if (readNvs32(key_sk_overworldPos, &overworld_player)) + { + soko->overworld_playerX + = (uint16_t)(overworld_player + & 0b1111111111111111); // okay so the cast to uint16 just does this right? + soko->overworld_playerY = (uint16_t)(overworld_player >> 16); + } + else + { + soko->overworld_playerX = 0; + soko->overworld_playerY = 0; + } + ESP_LOGD(SOKO_TAG, "Load Overworld: %" PRIu16 ",%" PRIu16 " - {%" PRId32 "}", soko->overworld_playerX, + soko->overworld_playerY, overworld_player); + + // if x == 0 && y == 0, then put the player somewhere else. + + sokoLoadGameplay(soko, 0, false); sokoInitGameBin(soko); soko->screen = SOKO_LEVELPLAY; } @@ -217,29 +238,13 @@ static void sokoMainLoop(int64_t elapsedUs) { sokoLoadGameplay(soko, soko->loadNewLevelIndex, soko->loadNewLevelFlag); sokoInitNewLevel(soko, soko->currentLevel.gameMode); - printf("Go to gameplay\n"); + ESP_LOGD(SOKO_TAG, "Go to gameplay"); soko->loadNewLevelFlag = false; // reset flag. soko->screen = SOKO_LEVELPLAY; } } } -// void freeEntity(soko_abs_t* self, sokoEntity_t* entity) // Free internal entity structures -// { -// if (entity->propFlag) -// { -// if (entity->properties->targetCount) -// { -// free(entity->properties->targetX); -// free(entity->properties->targetY); -// } -// free(entity->properties); -// entity->propFlag = false; -// } -// self->currentLevel.entityCount -= 1; -// } - -// placeholder. static void sokoBackgroundDrawCallback(int16_t x, int16_t y, int16_t w, int16_t h, int16_t up, int16_t upNum) { // Use TURBO drawing mode to draw individual pixels fast @@ -316,16 +321,9 @@ static void sokoBackgroundDrawCallback(int16_t x, int16_t y, int16_t w, int16_t // todo: move to soko_save static void sokoExtractLevelNamesAndIndices(soko_abs_t* self) { - printf("Loading Level List...!\n"); - // printf("%s\n", self->levelFileText); - // printf("%d\n", (int)strlen(self->levelFileText)); - // char* a = strstr(self->levelFileText,":"); - // char* b = strstr(a,".bin:"); - // printf("%d",(int)((int)b-(int)a)); - // char* stringPtrs[30]; - // memset(stringPtrs,0,30*sizeof(char*)); char** stringPtrs = soko->levelNames; memset(stringPtrs, 0, sizeof(soko->levelNames)); + memset(soko->levelTitles, 0, sizeof(soko->levelTitles)); memset(soko->levelIndices, 0, sizeof(soko->levelIndices)); int intInd = 0; int ind = 0; @@ -336,29 +334,37 @@ static void sokoExtractLevelNamesAndIndices(soko_abs_t* self) if (!(strstr(storageStr, ".bin"))) // Make sure you're not accidentally reading a number from a filename { soko->levelIndices[intInd] = (int)strtol(storageStr, NULL, 10); - // printf("NumberThing: %s :: %d\n",storageStr,(int)strtol(storageStr,NULL,10)); + // ESP_LOGD(SOKO_TAG, "NumberThing: %s :: %d",storageStr,(int)strtol(storageStr,NULL,10)); intInd++; } else { if (!strpbrk(storageStr, "\n\t\r ") && (strstr(storageStr, ".bin"))) { - // int tokLen = strlen(storageStr); - // char* tempPtr = calloc((tokLen + 1), sizeof(char)); // Length plus null teminator - // strcpy(tempPtr,storageStr); - // stringPtrs[ind] = tempPtr; + int tokLen = strlen(storageStr); + // char* tempPtr = heap_caps_malloc((tokLen + 1), sizeof(char), MALLOC_CAP_SPIRAM) ; // Length plus null + // teminator strcpy(tempPtr,storageStr); stringPtrs[ind] = tempPtr; + + // remove the sk_e_ and .bin from the filename and copy to title. stringPtrs[ind] = storageStr; - // printf("%s\n",storageStr); + char* title = heap_caps_calloc(tokLen - 8, sizeof(char), MALLOC_CAP_SPIRAM); + strncpy(title, storageStr + 5, tokLen - 9); + + // change _ to spaces + for (int i = 0; i < strlen(title); i++) + { + if (title[i] == '_') + { + title[i] = ' '; + } + } + // set title + soko->levelTitles[ind] = title; + ind++; } } - // printf("This guy!\n"); + // ESP_LOGD(SOKO_TAG, "This guy!"); storageStr = strtok(NULL, ":"); } - printf("Strings: %d, Ints: %d\n", ind, intInd); - printf("Levels and indices:\n"); - for (int i = ind - 1; i > -1; i--) - { - printf("Index: %d : %d : %s\n", i, soko->levelIndices[i], stringPtrs[i]); - } } diff --git a/main/modes/games/soko/soko.h b/main/modes/games/soko/soko.h index e073be957..bec9ab849 100644 --- a/main/modes/games/soko/soko.h +++ b/main/modes/games/soko/soko.h @@ -1,6 +1,8 @@ #ifndef _SOKO_MODE_H_ #define _SOKO_MODE_H_ +#include +#include #include "swadge2024.h" #include "soko_input.h" #include "soko_consts.h" @@ -9,10 +11,9 @@ extern swadgeMode_t sokoMode; typedef enum { - SOKO_OVERWORLD = 0, - SOKO_CLASSIC = 1, - SOKO_EULER = 2, - SOKO_LASERBOUNCE = 3 + SOKO_OVERWORLD = 0, + SOKO_CLASSIC = 1, + SOKO_EULER = 2, } soko_var_t; typedef enum @@ -31,25 +32,21 @@ typedef enum typedef enum { - SKB_EMPTY = 0, - SKB_WALL = 1, - SKB_FLOOR = 2, - SKB_GOAL = 3, - SKB_NO_WALK = 4, - SKB_OBJSTART = 201, // Object and Signal Bytes are over 200 - SKB_COMPRESS = 202, - SKB_PLAYER = 203, - SKB_CRATE = 204, - SKB_WARPINTERNAL = 205, - SKB_WARPINTERNALEXIT = 206, - SKB_WARPEXTERNAL = 207, - SKB_BUTTON = 208, - SKB_LASEREMITTER = 209, - SKB_LASERRECEIVEROMNI = 210, - SKB_LASERRECEIVER = 211, - SKB_LASER90ROTATE = 212, - SKB_GHOSTBLOCK = 213, - SKB_OBJEND = 230 + SKB_EMPTY = 0, + SKB_WALL = 1, + SKB_FLOOR = 2, + SKB_GOAL = 3, + SKB_NO_WALK = 4, + SKB_OBJSTART = 201, // Object and Signal Bytes are over 200 + SKB_COMPRESS = 202, + SKB_PLAYER = 203, + SKB_CRATE = 204, + SKB_WARPINTERNAL = 205, + SKB_WARPINTERNALEXIT = 206, + SKB_WARPEXTERNAL = 207, + SKB_BUTTON = 208, + SKB_GHOSTBLOCK = 213, + SKB_OBJEND = 230 } soko_bin_t; // Binary file byte value decode list typedef struct soko_portal_s { @@ -72,15 +69,6 @@ typedef enum SKS_VICTORY, } sokoGameState_t; -/* -typedef enum -{ - SOKO_OVERWORLD = 0, - SOKO_CLASSIC = 1, - SOKO_EULER = 2 -} soko_var_t; -*/ - typedef enum { SKE_NONE = 0, @@ -91,23 +79,18 @@ typedef enum SKE_STICKY_TRAIL_CRATE = 5, SKE_WARP = 11, SKE_BUTTON = 6, - SKE_LASER_EMIT_UP = 7, - SKE_LASER_RECEIVE_OMNI = 8, - SKE_LASER_RECEIVE = 9, SKE_GHOST = 10 } sokoEntityType_t; typedef enum { - SKT_EMPTY = 0, - SKT_FLOOR = 1, - SKT_WALL = 2, - SKT_GOAL = 3, - SKT_NO_WALK = 4, - SKT_PORTAL = 5, - SKT_LASER_EMIT = 6, // To Be Removed - SKT_LASER_RECEIVE = 7, // To Be Removed - SKT_FLOOR_WALKED = 8 + SKT_EMPTY = 0, + SKT_FLOOR = 1, + SKT_WALL = 2, + SKT_GOAL = 3, + SKT_NO_WALK = 4, + SKT_PORTAL = 5, + SKT_FLOOR_WALKED = 8 } sokoTile_t; typedef struct @@ -168,6 +151,7 @@ typedef struct wsg_t playerRightWSG; wsg_t playerLeftWSG; wsg_t playerDownWSG; + wsg_t playerCenterWSG; wsg_t goalWSG; wsg_t crateWSG; wsg_t crateOnGoalWSG; @@ -203,6 +187,7 @@ typedef struct soko_abs_s char* levelFileText; char* levelNames[SOKO_LEVEL_COUNT]; + char* levelTitles[SOKO_LEVEL_COUNT]; uint16_t levelIndices[SOKO_LEVEL_COUNT]; bool levelSolved[SOKO_LEVEL_COUNT]; @@ -220,6 +205,7 @@ typedef struct soko_abs_s // level char* levels[SOKO_LEVEL_COUNT]; ///< List of wsg filenames. not comitted to storing level data like this, but idk if ///< I need level names like picross. + bool allSolved; // wsg_t levelWSG; ///< Current level uint8_t* levelBinaryData; @@ -274,6 +260,9 @@ typedef struct soko_abs_s uint8_t loadNewLevelIndex; soko_var_t loadNewLevelVariant; + int chosen_victory_message; } soko_abs_t; +extern const char SOKO_TAG[]; +extern const char sokoModeName[]; #endif diff --git a/main/modes/games/soko/soko_game.c b/main/modes/games/soko/soko_game.c index a93022eb2..e627f4ddd 100644 --- a/main/modes/games/soko/soko_game.c +++ b/main/modes/games/soko/soko_game.c @@ -18,7 +18,7 @@ soko_abs_t* soko_s; void sokoInitGameBin(soko_abs_t* soko) { - printf("init sokoban game from bin file"); + ESP_LOGD(SOKO_TAG, "init sokoban game from bin file"); soko_s = soko; soko_s->soko_player = &soko_s->currentLevel.entities[soko_s->currentLevel.playerIndex]; @@ -35,7 +35,7 @@ void sokoInitGameBin(soko_abs_t* soko) void sokoInitGame(soko_abs_t* soko) { - printf("init sokobon game.\n"); + ESP_LOGD(SOKO_TAG, "init sokobon game."); // Configure conveninence pointers. soko_s = soko; @@ -56,7 +56,7 @@ void sokoInitGame(soko_abs_t* soko) void sokoInitNewLevel(soko_abs_t* soko, soko_var_t variant) { - printf("Init New Level.\n"); + ESP_LOGD(SOKO_TAG, "Init New Level."); soko_s = soko; soko_s->soko_player = &soko_s->currentLevel.entities[soko_s->currentLevel.playerIndex]; @@ -246,8 +246,10 @@ void drawTiles(sokoLevel_t* level) drawWsg(&s->playerLeftWSG,ox+level->entities[i].x*scale,oy+level->entities[i].y*scale,false,false,0); break; case SKD_DOWN: - default: drawWsg(&s->playerDownWSG,ox+level->entities[i].x*scale,oy+level->entities[i].y*scale,false,false,0); + case SKD_NONE: + default: + drawWsg(&s->playerCenterWSG,ox+level->entities[i].x*scale,oy+level->entities[i].y*scale,false,false,0); break; } diff --git a/main/modes/games/soko/soko_gamerules.c b/main/modes/games/soko/soko_gamerules.c index 4a4237e05..f7cce23f0 100644 --- a/main/modes/games/soko/soko_gamerules.c +++ b/main/modes/games/soko/soko_gamerules.c @@ -7,7 +7,7 @@ // clang-format off // True if the entity CANNOT go on the tile -const bool sokoEntityTileCollision[6][9] = { +bool sokoEntityTileCollision[6][9] = { // Empty, //floor//wall//goal//noWalk//portal //l-emit //l-receive //walked {true, false, true, false, true,false, false, false, false}, // SKE_NONE {true, false, true, false, true,false, false, false, true}, // PLAYER @@ -16,10 +16,15 @@ const bool sokoEntityTileCollision[6][9] = { {true, false, true, false, true,false, false, false, false}, // STICKY CRATE {true, false, true, false, true,false, false, false, true} // STICKY_TRAIL_CRATE }; + +static const char *victorym[] ={"nice", "good job", "well done", "solved it", "high five!","hooray","brilliant","victory","incredible", "awesome!","superb work","success!"}; +const size_t victorym_count = sizeof(victorym) / sizeof(victorym[0]); // clang-format on uint64_t victoryDanceTimer; +const char key_sk_overworldPos[] = "sk_ovwPos"; + void sokoConfigGamemode( soko_abs_t* soko, soko_var_t variant) // This should be called when you reload a level to make sure game rules are correct @@ -29,7 +34,7 @@ void sokoConfigGamemode( if (variant == SOKO_CLASSIC) // standard gamemode. Check 'variant' variable { - printf("Config Soko to Classic\n"); + ESP_LOGD(SOKO_TAG, "Config Soko to Classic"); soko->maxPush = 1; // set to 1 for "traditional" sokoban. soko->gameLoopFunc = absSokoGameLoop; soko->sokoTryPlayerMovementFunc = absSokoTryPlayerMovement; @@ -40,7 +45,7 @@ void sokoConfigGamemode( } else if (variant == SOKO_EULER) // standard gamemode. Check 'variant' variable { - printf("Config Soko to Euler\n"); + ESP_LOGD(SOKO_TAG, "Config Soko to Euler"); soko->maxPush = 0; // set to 0 for infinite push. soko->gameLoopFunc = absSokoGameLoop; soko->sokoTryPlayerMovementFunc = eulerSokoTryPlayerMovement; @@ -63,7 +68,7 @@ void sokoConfigGamemode( } else if (variant == SOKO_OVERWORLD) { - printf("Config Soko to Overworld\n"); + ESP_LOGD(SOKO_TAG, "Config Soko to Overworld"); soko->maxPush = 0; // set to 0 for infinite push. soko->gameLoopFunc = overworldSokoGameLoop; soko->sokoTryPlayerMovementFunc = absSokoTryPlayerMovement; @@ -74,9 +79,10 @@ void sokoConfigGamemode( soko->currentTheme = &soko->overworldTheme; // set position to previous overworld positon when re-entering the overworld // but like... not an infinite loop? + soko->soko_player->x = soko->overworld_playerX; soko->soko_player->y = soko->overworld_playerY; - soko->background = SKBG_FORREST; + soko->background = SKBG_BLACK; for (size_t i = 0; i < soko->portalCount; i++) { @@ -86,81 +92,20 @@ void sokoConfigGamemode( } } } - else if (variant == SOKO_LASERBOUNCE) - { - printf("Config Soko to Laser Bounce\n"); - soko->maxPush = 0; // set to 0 for infinite push. - soko->gameLoopFunc = laserBounceSokoGameLoop; - soko->sokoTryPlayerMovementFunc = absSokoTryPlayerMovement; - soko->sokoTryMoveEntityInDirectionFunc = absSokoTryMoveEntityInDirection; - soko->drawTilesFunc = absSokoDrawTiles; - soko->isVictoryConditionFunc = absSokoAllCratesOnGoal; - soko->sokoGetTileFunc = absSokoGetTile; - } else { - printf("invalid gamemode."); + ESP_LOGD(SOKO_TAG, "invalid gamemode."); } + // save overworld position. + uint32_t overworldData = (soko->overworld_playerY << 16) | soko->overworld_playerX; + writeNvs32(key_sk_overworldPos, overworldData); + // add conditional for alternative variants sokoInitHistory(soko); -} - -void laserBounceSokoGameLoop(soko_abs_t* self, int64_t elapsedUs) -{ - if (self->state == SKS_GAMEPLAY) - { - // logic - self->sokoTryPlayerMovementFunc(self); - - // victory status. stored separate from gamestate because of future gameplay ideas/remixes. - // todo: rename to isVictory or such. - self->allCratesOnGoal = self->isVictoryConditionFunc(self); - if (self->allCratesOnGoal) - { - self->state = SKS_VICTORY; - victoryDanceTimer = 0; - } - // draw level - self->drawTilesFunc(self, &self->currentLevel); - drawLaserFromEntity(self, self->soko_player); - } - else if (self->state == SKS_VICTORY) - { - // check for input for exit/next level. - self->drawTilesFunc(self, &self->currentLevel); - victoryDanceTimer += elapsedUs; - if (victoryDanceTimer > SOKO_VICTORY_TIMER_US) - { - sokoSolveCurrentLevel(self); - self->loadNewLevelIndex = 0; - self->loadNewLevelFlag = true; - self->screen = SOKO_LOADNEWLEVEL; - } - } - // DEBUG PLACEHOLDER: - // Render the time to a string - char str[16] = {0}; - int16_t tWidth; - if (!self->allCratesOnGoal) - { - // snprintf(buffer, buflen - 1, "%s%s", item->label, item->options[item->currentOpt]); - snprintf(str, sizeof(str) - 1, "%s", self->levelNames[self->currentLevelIndex]); - // Measure the width of the time string - tWidth = textWidth(&self->ibm, str); - // Draw the time string to the display, centered at (TFT_WIDTH / 2) - drawText(&self->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 0); - } - else - { - snprintf(str, sizeof(str) - 1, "sokasuccess"); - // Measure the width of the time string - tWidth = textWidth(&self->ibm, str); - // Draw the time string to the display, centered at (TFT_WIDTH / 2) - drawText(&self->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 0); - } - sharedGameLoop(self); + // pick a single random victory message. We can't pick during the loop or it will be random every frame. + soko->chosen_victory_message = rand() % victorym_count; } void absSokoGameLoop(soko_abs_t* soko, int64_t elapsedUs) @@ -201,24 +146,23 @@ void absSokoGameLoop(soko_abs_t* soko, int64_t elapsedUs) } } - // DEBUG PLACEHOLDER: - char str[16] = {0}; + char str[20] = {0}; int16_t tWidth; if (!soko->allCratesOnGoal) { - snprintf(str, sizeof(str) - 1, "%s", soko->levelNames[soko->currentLevelIndex]); + snprintf(str, sizeof(str) - 1, "%s", soko->levelTitles[soko->currentLevelIndex]); // Measure the width of the time string tWidth = textWidth(&soko->ibm, str); // Draw the time string to the display, centered at (TFT_WIDTH / 2) - drawText(&soko->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 0); + drawText(&soko->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 2); } else { - snprintf(str, sizeof(str) - 1, "sokasuccess"); + snprintf(str, sizeof(str) - 1, "%s", victorym[soko->chosen_victory_message]); // Measure the width of the time string tWidth = textWidth(&soko->ibm, str); // Draw the time string to the display, centered at (TFT_WIDTH / 2) - drawText(&soko->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 0); + drawText(&soko->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 2); } sharedGameLoop(soko); } @@ -347,7 +291,6 @@ bool absSokoTryMoveEntityInDirection(soko_abs_t* self, sokoEntity_t* entity, int return false; } - // draw the tiles (and entities, for now) of the level. void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) { @@ -394,6 +337,7 @@ void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) { screenMaxX = level->width; } + screenMinY = self->camY - self->camHeight / 2 - 1; if (screenMinY < 0) { @@ -418,8 +362,6 @@ void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) screenMaxY = level->height; } - SETUP_FOR_TURBO(); - // Tile Drawing (bg layer) for (size_t x = screenMinX; x < screenMaxX; x++) { @@ -469,18 +411,14 @@ void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) // none of this matters it's all getting replaced with drawwsg later. if (color != cTransparent) { - for (size_t xd = ox + x * scale; xd < ox + x * scale + scale; xd++) - { - for (size_t yd = oy + y * scale; yd < oy + y * scale + scale; yd++) - { - TURBO_SET_PIXEL(xd, yd, color); - } - } + int32_t xd = ox + x * scale; + int32_t yd = oy + y * scale; + fillDisplayArea(xd, yd, xd + scale, yd + scale, color); } if (level->tiles[x][y] == SKT_GOAL) { - drawWsg(&self->currentTheme->goalWSG, ox + x * scale, oy + y * scale, false, false, 0); + drawWsgSimple(&self->currentTheme->goalWSG, ox + x * scale, oy + y * scale); } // DEBUG_DRAW_COUNT++; @@ -491,9 +429,9 @@ void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) // draw portal in overworld before entities. // hypothetically, we can get rid of the overworld check, and there just won't be other portals? but there could be? - // sprint("a\n"); if (self->currentLevel.gameMode == SOKO_OVERWORLD) { + self->allSolved = true; for (int i = 0; i < self->portalCount; i++) { if (self->portals[i].x >= screenMinX && self->portals[i].x <= screenMaxX && self->portals[i].y >= screenMinY @@ -508,6 +446,7 @@ void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) { drawWsg(&self->currentTheme->portal_incompleteWSG, ox + self->portals[i].x * scale, oy + self->portals[i].y * scale, false, false, 0); + self->allSolved = false; } } } @@ -524,6 +463,16 @@ void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) { case SKE_PLAYER: { + // for (size_t xd = ox + level->entities[i].x * scale; xd < ox + level->entities[i].x * scale + + // scale; xd++) + // { + // for (size_t yd = oy +level->entities[i]. y * scale; yd < oy + level->entities[i].y * scale + + // scale; yd++) + // { + // TURBO_SET_PIXEL(xd, yd, c211); + // } + // } + // continue; switch (level->entities[i].facing) { case SKD_UP: @@ -545,12 +494,18 @@ void absSokoDrawTiles(soko_abs_t* self, sokoLevel_t* level) break; } case SKD_DOWN: - default: { drawWsg(&self->currentTheme->playerDownWSG, ox + level->entities[i].x * scale, oy + level->entities[i].y * scale, false, false, 0); break; } + case SKD_NONE: + default: + { + drawWsg(&self->currentTheme->playerCenterWSG, ox + level->entities[i].x * scale, + oy + level->entities[i].y * scale, false, false, 0); + break; + } } break; @@ -657,397 +612,6 @@ sokoVec_t sokoGridToPix(soko_abs_t* self, sokoVec_t grid) // Convert grid positi return retVec; } -void drawLaserFromEntity(soko_abs_t* self, sokoEntity_t* emitter) -{ - sokoCollision_t impactSpot = sokoBeamImpact(self, self->soko_player); - // printf("Player Pos: x:%d,y:%d Facing:%d Impact Result: x:%d,y:%d, Flag:%d - // Index:%d\n",self->soko_player->x,self->soko_player->y,self->soko_player->facing,impactSpot.x,impactSpot.y,impactSpot.entityFlag,impactSpot.entityIndex); - sokoVec_t playerGrid, impactGrid; - playerGrid.x = emitter->x; - playerGrid.y = emitter->y; - impactGrid.x = impactSpot.x; - impactGrid.y = impactSpot.y; - sokoVec_t playerPix = sokoGridToPix(self, playerGrid); - sokoVec_t impactPix = sokoGridToPix(self, impactGrid); - drawLine(playerPix.x, playerPix.y, impactPix.x, impactPix.y, c500, 0); -} - -// void sokoDoBeam(soko_abs_t* self) -// { -// // bool receiverImpact; -// // for (int entInd = 0; entInd < self->currentLevel.entityCount; entInd++) -// // { -// // if (self->currentLevel.entities[entInd].type == SKE_LASER_EMIT_UP) -// // { -// // self->currentLevel.entities[entInd].properties->targetCount = 0; -// // receiverImpact = sokoBeamImpactRecursive( -// // self, self->currentLevel.entities[entInd].x, self->currentLevel.entities[entInd].y, -// // self->currentLevel.entities[entInd].type, &self->currentLevel.entities[entInd]); -// // } -// // } -// } - -bool sokoLaserTileCollision(sokoTile_t testTile) -{ - switch (testTile) - { - case SKT_EMPTY: - { - return false; - } - case SKT_FLOOR: - { - return false; - } - case SKT_WALL: - { - return true; - } - case SKT_GOAL: - { - return false; - } - case SKT_PORTAL: - { - return false; - } - case SKT_FLOOR_WALKED: - { - return false; - } - case SKT_NO_WALK: - { - return false; - } - default: - { - return false; - } - } -} - -bool sokoLaserEntityCollision(sokoEntityType_t testEntity) -{ - switch (testEntity) // Anything that doesn't unconditionally pass should return true - { - case SKE_NONE: - { - return false; - } - case SKE_PLAYER: - { - return false; - } - case SKE_CRATE: - { - return true; - } - case SKE_LASER_90: - { - return true; - } - case SKE_STICKY_CRATE: - { - return true; - } - case SKE_WARP: - { - return false; - } - case SKE_BUTTON: - { - return false; - } - case SKE_LASER_EMIT_UP: - { - return true; - } - case SKE_LASER_RECEIVE_OMNI: - { - return true; - } - case SKE_LASER_RECEIVE: - { - return true; - } - case SKE_GHOST: - { - return true; - } - default: - { - return false; - } - } -} - -sokoDirection_t sokoRedirectDir(sokoDirection_t emitterDir, bool inverted) -{ - switch (emitterDir) - { - case SKD_UP: - { - return inverted ? SKD_LEFT : SKD_RIGHT; - } - case SKD_DOWN: - { - return inverted ? SKD_RIGHT : SKD_LEFT; - } - case SKD_RIGHT: - { - return inverted ? SKD_DOWN : SKD_UP; - } - case SKD_LEFT: - { - return inverted ? SKD_UP : SKD_DOWN; - } - default: - { - return SKD_NONE; - } - } -} - -int sokoBeamImpactRecursive(soko_abs_t* self, int emitter_x, int emitter_y, sokoDirection_t emitterDir, - sokoEntity_t* rootEmitter) -{ - sokoDirection_t dir = emitterDir; - sokoVec_t projVec = {0, 0}; - sokoVec_t emitVec = {emitter_x, emitter_y}; - switch (dir) - { - case SKD_DOWN: - { - projVec.y = 1; - break; - } - case SKD_UP: - { - projVec.y = -1; - break; - } - case SKD_LEFT: - { - projVec.x = -1; - break; - } - case SKD_RIGHT: - { - projVec.x = 1; - break; - } - default: - { - projVec.y = -1; - break; - // return base entity position - } - } - - // Iterate over tiles in ray to edge of level - sokoVec_t testPos = sokoAddCoord(emitVec, projVec); - int entityCount = self->currentLevel.entityCount; - // todo: make first pass pack a statically allocated array with only the entities in the path of the laser. - - int16_t possibleSquares = 0; - if (dir == SKD_RIGHT) // move these checks into the switch statement - { - possibleSquares = self->currentLevel.width - emitVec.x; // Up to and including far wall - } - if (dir == SKD_LEFT) - { - possibleSquares = emitVec.x + 1; - } - if (dir == SKD_UP) - { - possibleSquares = emitVec.y + 1; - } - if (dir == SKD_DOWN) - { - possibleSquares = self->currentLevel.height - emitVec.y; - } - - int tileCollFlag, entCollFlag, entCollInd; - tileCollFlag = entCollFlag = entCollInd = 0; - - bool retVal; - // printf("emitVec(%d,%d)",emitVec.x,emitVec.y); - // printf("projVec:(%d,%d) possibleSquares:%d ",projVec.x,projVec.y,possibleSquares); - - for (int n = 0; n < possibleSquares; n++) - { - sokoTile_t posTile = absSokoGetTile(self, testPos.x, testPos.y); - // printf("|n:%d,posTile:(%d,%d):%d|",n,testPos.x,testPos.y,posTile); - if (sokoLaserTileCollision(posTile)) - { - tileCollFlag = 1; - break; - } - for (int m = 0; m < entityCount; m++) // iterate over tiles/entities to check for laser collision. First pass - // finds everything in the path of the - { - sokoEntity_t candidateEntity = self->currentLevel.entities[m]; - // printf("|m:%d;CE:(%d,%d)%d",m,candidateEntity.x,candidateEntity.y,candidateEntity.type); - if (candidateEntity.x == testPos.x && candidateEntity.y == testPos.y) - { - // printf(";POSMATCH;Coll:%d",entityCollision[candidateEntity.type]); - if (sokoLaserEntityCollision(candidateEntity.type)) - { - entCollFlag = 1; - entCollInd = m; - // printf("|"); - break; - } - } - // printf("|"); - } - sokoEntityProperties_t* entProps = &rootEmitter->properties; - if (tileCollFlag) - { - entProps->targetX[entProps->targetCount] = testPos.x; // Pack target properties with every impacted - // position. - entProps->targetY[entProps->targetCount] = testPos.y; - entProps->targetCount++; - } - if (entCollFlag) - { - sokoEntityType_t entType = self->currentLevel.entities[entCollInd].type; - - entProps->targetX[entProps->targetCount] = testPos.x; // Pack target properties with every impacted entity. - entProps->targetY[entProps->targetCount] - = testPos.y; // If there's a redirect, it will be added after this one. - entProps->targetCount++; - if (entType == SKE_LASER_90) - { - sokoDirection_t redirectDir - = sokoRedirectDir(emitterDir, self->currentLevel.entities[entCollInd].facing); // SKD_UP or SKD_DOWN - sokoBeamImpactRecursive(self, testPos.x, testPos.y, redirectDir, rootEmitter); - } - - break; - } - testPos = sokoAddCoord(testPos, projVec); - } - retVal = self->currentLevel.entities[entCollInd].properties.targetCount; - // printf("\n"); - // retVal.x = testPos.x; - // retVal.y = testPos.y; - // retVal.entityIndex = entCollInd; - // retVal.entityFlag = entCollFlag; - // printf("impactPoint:(%d,%d)\n",testPos.x,testPos.y); - return retVal; -} - -sokoCollision_t sokoBeamImpact(soko_abs_t* self, sokoEntity_t* emitter) -{ - sokoDirection_t dir = emitter->facing; - sokoVec_t projVec = {0, 0}; - sokoVec_t emitVec = {emitter->x, emitter->y}; - switch (dir) - { - case SKD_DOWN: - { - projVec.y = 1; - break; - } - case SKD_UP: - { - projVec.y = -1; - break; - } - case SKD_LEFT: - { - projVec.x = -1; - break; - } - case SKD_RIGHT: - { - projVec.x = 1; - break; - } - default: - { // return base entity position - } - } - - // Iterate over tiles in ray to edge of level - sokoVec_t testPos = sokoAddCoord(emitVec, projVec); - int entityCount = self->currentLevel.entityCount; - // todo: make first pass pack a statically allocated array with only the entities in the path of the laser. - - uint8_t tileCollision[] - = {0, 0, 1, 0, 0, 1, 1}; // There should be a pointer internal to the game state so this can vary with game mode - uint8_t entityCollision[] = {0, 0, 1, 1}; - - int16_t possibleSquares = 0; - if (dir == SKD_RIGHT) // move these checks into the switch statement - { - possibleSquares = self->currentLevel.width - emitVec.x; // Up to and including far wall - } - if (dir == SKD_LEFT) - { - possibleSquares = emitVec.x + 1; - } - if (dir == SKD_UP) - { - possibleSquares = emitVec.y + 1; - } - if (dir == SKD_DOWN) - { - possibleSquares = self->currentLevel.height - emitVec.y; - } - - // int tileCollFlag = 0; - int entCollFlag = 0; - int entCollInd = 0; - - sokoCollision_t retVal; - // printf("emitVec(%d,%d)",emitVec.x,emitVec.y); - // printf("projVec:(%d,%d) possibleSquares:%d ",projVec.x,projVec.y,possibleSquares); - - for (int n = 0; n < possibleSquares; n++) - { - sokoTile_t posTile = absSokoGetTile(self, testPos.x, testPos.y); - // printf("|n:%d,posTile:(%d,%d):%d|",n,testPos.x,testPos.y,posTile); - if (tileCollision[posTile]) - { - // tileCollFlag = 1; - break; - } - for (int m = 0; m < entityCount; m++) // iterate over tiles/entities to check for laser collision. First pass - // finds everything in the path of the - { - sokoEntity_t candidateEntity = self->currentLevel.entities[m]; - // printf("|m:%d;CE:(%d,%d)%d",m,candidateEntity.x,candidateEntity.y,candidateEntity.type); - if (candidateEntity.x == testPos.x && candidateEntity.y == testPos.y) - { - // printf(";POSMATCH;Coll:%d",entityCollision[candidateEntity.type]); - if (entityCollision[candidateEntity.type]) - { - entCollFlag = 1; - entCollInd = m; - // printf("|"); - break; - } - } - // printf("|"); - } - - if (entCollFlag) - { - break; - } - testPos = sokoAddCoord(testPos, projVec); - } - // printf("\n"); - retVal.x = testPos.x; - retVal.y = testPos.y; - retVal.entityIndex = entCollInd; - retVal.entityFlag = entCollFlag; - // printf("impactPoint:(%d,%d)\n",testPos.x,testPos.y); - return retVal; -} - sokoVec_t sokoAddCoord(sokoVec_t op1, sokoVec_t op2) { sokoVec_t retVal; @@ -1151,9 +715,7 @@ void overworldSokoGameLoop(soko_abs_t* self, int64_t elapsedUs) self->allCratesOnGoal = self->isVictoryConditionFunc(self); if (self->allCratesOnGoal) { - self->state = SKS_VICTORY; - - printf("Player at %d,%d\n", self->soko_player->x, self->soko_player->y); + self->state = SKS_VICTORY; victoryDanceTimer = 0; } // draw level @@ -1174,6 +736,10 @@ void overworldSokoGameLoop(soko_abs_t* self, int64_t elapsedUs) } } + // int32_t data = self->overworld_playerY << 16; + // data = data | self->overworld_playerX; + // writeNvs32("sk_over_pos",data); + self->loadNewLevelIndex = targetWorldIndex; self->loadNewLevelFlag = false; // load saved data. self->screen = SOKO_LOADNEWLEVEL; @@ -1181,23 +747,23 @@ void overworldSokoGameLoop(soko_abs_t* self, int64_t elapsedUs) // DEBUG PLACEHOLDER: // Render the time to a string - char str[16] = {0}; + char str[31] = {0}; int16_t tWidth; - if (!self->allCratesOnGoal) + if (!self->allSolved) { - snprintf(str, sizeof(str) - 1, "sokoban"); + snprintf(str, sizeof(str) - 1, "%s", sokoModeName); // Measure the width of the time string tWidth = textWidth(&self->ibm, str); // Draw the time string to the display, centered at (TFT_WIDTH / 2) - drawText(&self->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 0); + drawText(&self->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 3); } else { - snprintf(str, sizeof(str) - 1, "sokasuccess"); + snprintf(str, sizeof(str) - 1, "'oh, nice, You won' - Hunter"); // Measure the width of the time string tWidth = textWidth(&self->ibm, str); // Draw the time string to the display, centered at (TFT_WIDTH / 2) - drawText(&self->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 0); + drawText(&self->ibm, c555, str, ((TFT_WIDTH - tWidth) / 2), 3); } } @@ -1225,7 +791,7 @@ void restartCurrentLevel(soko_abs_t* self) void exitToOverworld(soko_abs_t* soko) { - printf("Exit to Overworld\n"); + ESP_LOGD(SOKO_TAG, "Exit to Overworld"); // save. todo: skip if victory. if (soko->currentLevel.gameMode == SOKO_EULER) { diff --git a/main/modes/games/soko/soko_gamerules.h b/main/modes/games/soko/soko_gamerules.h index 4588d201a..4ea7fb818 100644 --- a/main/modes/games/soko/soko_gamerules.h +++ b/main/modes/games/soko/soko_gamerules.h @@ -28,16 +28,7 @@ bool allCratesOnGoal(void); void eulerSokoTryPlayerMovement(soko_abs_t* self); bool eulerNoUnwalkedFloors(soko_abs_t* self); -// lasers -sokoCollision_t sokoBeamImpact(soko_abs_t* self, sokoEntity_t* emitter); -int sokoBeamImpactRecursive(soko_abs_t* self, int emitter_x, int emitter_y, sokoDirection_t emitterDir, - sokoEntity_t* rootEmitter); -sokoDirection_t sokoRedirectDir(sokoDirection_t emitterDir, bool inverted); -bool sokoLaserEntityCollision(sokoEntityType_t testEntity); -bool sokoLaserTileCollision(sokoTile_t testTile); -void laserBounceSokoGameLoop(soko_abs_t* self, int64_t elapsedUs); sokoVec_t sokoGridToPix(soko_abs_t* self, sokoVec_t grid); -void drawLaserFromEntity(soko_abs_t* self, sokoEntity_t* emitter); sokoVec_t sokoAddCoord(sokoVec_t op1, sokoVec_t op2); // overworld diff --git a/main/modes/games/soko/soko_input.h b/main/modes/games/soko/soko_input.h index 0ed23478c..f9c5fdcd9 100644 --- a/main/modes/games/soko/soko_input.h +++ b/main/modes/games/soko/soko_input.h @@ -4,11 +4,11 @@ // it through eventually. typedef enum { + SKD_NONE, SKD_UP, SKD_DOWN, SKD_RIGHT, SKD_LEFT, - SKD_NONE } sokoDirection_t; typedef struct diff --git a/main/modes/games/soko/soko_save.c b/main/modes/games/soko/soko_save.c index 0df4d9c10..e4247e58e 100644 --- a/main/modes/games/soko/soko_save.c +++ b/main/modes/games/soko/soko_save.c @@ -9,6 +9,13 @@ void sokoSaveEulerTiles(soko_abs_t* soko); void sokoLoadEulerTiles(soko_abs_t* soko); void sokoSaveCurrentLevelEntities(soko_abs_t* soko); +const char key_sk_data[] = "sk_data"; +const char key_sklv1[] = "sklv1"; +const char key_sklv2[] = "sklv2"; +const char key_sk_ents[] = "sk_ents"; +const char key_sk_e_t_c[] = "sk_e_t_c"; +const char key_sk_e_ts[] = "sk_e_ts"; + /// @brief Called on 'resume' from the menu. /// @param soko void sokoLoadGameplay(soko_abs_t* soko, uint16_t levelIndex, bool loadNew) @@ -17,15 +24,18 @@ void sokoLoadGameplay(soko_abs_t* soko, uint16_t levelIndex, bool loadNew) sokoSaveGameplay(soko); // load current level - int32_t data = 0; - readNvs32("sk_data", &data); - // bitshift, etc, as needed. - uint16_t lastSaved = (uint16_t)data; + int32_t data = 0; + uint16_t lastSaved = 0xFFFF; + if (readNvs32(key_sk_data, &data)) + { + // bitshift, etc, as needed. + lastSaved = (uint16_t)data; + } sokoLoadBinLevel(soko, levelIndex); if (levelIndex == lastSaved && !loadNew) { - printf("Load Saved Data for level %i\n", lastSaved); + ESP_LOGD(SOKO_TAG, "Load Saved Data for level %i", lastSaved); // current level entity positions sokoLoadCurrentLevelEntities(soko); @@ -38,7 +48,7 @@ void sokoLoadGameplay(soko_abs_t* soko, uint16_t levelIndex, bool loadNew) void sokoSaveGameplay(soko_abs_t* soko) { - printf("Save Gameplay\n"); + ESP_LOGD(SOKO_TAG, "Save Gameplay"); // save current level if (soko->currentLevelIndex == 0) @@ -50,7 +60,7 @@ void sokoSaveGameplay(soko_abs_t* soko) // current level entity positions uint32_t data = current; // what other data gets encoded? we can also save the sk_tiles count. - writeNvs32("sk_data", data); + writeNvs32(key_sk_data, data); sokoSaveCurrentLevelEntities(soko); @@ -65,18 +75,22 @@ void sokoLoadLevelSolvedState(soko_abs_t* soko) // todo: automatically split for >32, >64 levels using 2 loops. int32_t lvs = 0; - readNvs32("sklv1", &lvs); - // i<32... - for (size_t i = 0; i < SOKO_LEVEL_COUNT; i++) + if (readNvs32(key_sklv1, &lvs)) { - soko->levelSolved[i] = (1 & lvs >> i) == 1; + // i<32... + for (size_t i = 0; i < SOKO_LEVEL_COUNT; i++) + { + soko->levelSolved[i] = (1 & lvs >> i) == 1; + } } // now the next 32 bytes! - // readNvs32("sklv2",&lvs); - // for (size_t i = 32; i < SOKO_LEVEL_COUNT || i < 64; i++) - // { - // soko->levelSolved[i] = (1 & lvs>>i) == 1; - // } + // if (readNvs32(key_sklv2, &lvs)) + // { + // for (size_t i = 32; i < SOKO_LEVEL_COUNT || i < 64; i++) + // { + // soko->levelSolved[i] = (1 & lvs >> i) == 1; + // } + // } // etc. Probably won't bother cleaning it into nested loop until over 32*4 levels... // so .. never? @@ -84,7 +98,7 @@ void sokoLoadLevelSolvedState(soko_abs_t* soko) void sokoSetLevelSolvedState(soko_abs_t* soko, uint16_t levelIndex, bool solved) { - printf("save level solved status %d\n", levelIndex); + ESP_LOGD(SOKO_TAG, "save level solved status %" PRIu16 "", levelIndex); // todo: changes a single levels bool in the sokoSolved array, soko->levelSolved[levelIndex] = true; @@ -94,11 +108,17 @@ void sokoSetLevelSolvedState(soko_abs_t* soko, uint16_t levelIndex, bool solved) if (section == 0) { - readNvs32("sklv1", &lvs); + if (!readNvs32(key_sklv1, &lvs)) + { + lvs = 0; + } } else if (section == 1) { - readNvs32("sklv2", &lvs); + if (!readNvs32(key_sklv2, &lvs)) + { + lvs = 0; + } index -= 32; } // else, 64, @@ -117,11 +137,11 @@ void sokoSetLevelSolvedState(soko_abs_t* soko, uint16_t levelIndex, bool solved) // write the bit out to data. if (section == 0) { - writeNvs32("sklv1", lvs); + writeNvs32(key_sklv1, lvs); } else if (section == 1) { - writeNvs32("sklv2", lvs); + writeNvs32(key_sklv2, lvs); } } @@ -164,7 +184,7 @@ void sokoSaveCurrentLevelEntities(soko_abs_t* soko) // if each entity is 4 bytes, then we can save (adjust) all entities as a single blob, always, since it's a // pre-allocated array. - char* entities = calloc(soko->currentLevel.entityCount * 4, sizeof(char)); + char* entities = heap_caps_calloc(soko->currentLevel.entityCount * 4, sizeof(char), MALLOC_CAP_SPIRAM); for (int i = 0; i < soko->currentLevel.entityCount; i++) { @@ -177,7 +197,7 @@ void sokoSaveCurrentLevelEntities(soko_abs_t* soko) entities[i * 4 + 3] = soko->currentLevel.entities[i].facing; } size_t size = sizeof(char) * (soko->currentLevel.entityCount) * 4; - writeNvsBlob("sk_ents", entities, size); + writeNvsBlob(key_sk_ents, entities, size); free(entities); } // todo: there is no clean place to return to the main menu right now, so gotta write that function/flow so this can get @@ -187,30 +207,31 @@ void sokoSaveCurrentLevelEntities(soko_abs_t* soko) /// @param soko void sokoLoadCurrentLevelEntities(soko_abs_t* soko) { - printf("loading current level entities.\n"); + ESP_LOGD(SOKO_TAG, "loading current level entities."); - char* entities = calloc(soko->currentLevel.entityCount * 4, sizeof(char)); + char* entities = heap_caps_calloc(soko->currentLevel.entityCount * 4, sizeof(char), MALLOC_CAP_SPIRAM); size_t size = sizeof(char) * (soko->currentLevel.entityCount * 4); - readNvsBlob("sk_ents", entities, &size); - - for (int i = 0; i < soko->currentLevel.entityCount; i++) + if (readNvsBlob(key_sk_ents, entities, &size)) { - // todo: wait, if all entities are the same length, we don't actually need to save the index... - soko->currentLevel.entities[i].x = entities[i * 4 + 1]; - soko->currentLevel.entities[i].y = entities[i * 4 + 2]; - soko->currentLevel.entities[i].facing = entities[i * 4 + 3]; + for (int i = 0; i < soko->currentLevel.entityCount; i++) + { + // todo: wait, if all entities are the same length, we don't actually need to save the index... + soko->currentLevel.entities[i].x = entities[i * 4 + 1]; + soko->currentLevel.entities[i].y = entities[i * 4 + 2]; + soko->currentLevel.entities[i].facing = entities[i * 4 + 3]; + } } free(entities); } void sokoSaveEulerTiles(soko_abs_t* soko) { - printf("encoding euler tiles.\n"); + ESP_LOGD(SOKO_TAG, "encoding euler tiles."); sokoTile_t prevTile = SKT_FLOOR; int w = soko->currentLevel.width; uint16_t i = 0; - char* blops = (char*)calloc(255, sizeof(char)); + char* blops = (char*)heap_caps_calloc(255, sizeof(char), MALLOC_CAP_SPIRAM); for (uint16_t y = 0; y < soko->currentLevel.height; y++) { for (uint16_t x = 0; x < w; x++) @@ -229,7 +250,7 @@ void sokoSaveEulerTiles(soko_abs_t* soko) blops[i] = blops[i] + 1; if (i > 255) { - printf("ERROR This level is too big to save for euler???\n"); + ESP_LOGD(SOKO_TAG, "ERROR This level is too big to save for euler???"); break; } } @@ -237,67 +258,69 @@ void sokoSaveEulerTiles(soko_abs_t* soko) } } i++; - writeNvsBlob("sk_e_t_c", &i, sizeof(uint16_t)); - writeNvsBlob("sk_e_ts", blops, sizeof(char) * i); + writeNvsBlob(key_sk_e_t_c, &i, sizeof(uint16_t)); + writeNvsBlob(key_sk_e_ts, blops, sizeof(char) * i); free(blops); } void sokoLoadEulerTiles(soko_abs_t* soko) { - printf("Load Euler Tiles\n"); + ESP_LOGD(SOKO_TAG, "Load Euler Tiles"); sokoTile_t runningTile = SKT_FLOOR; uint16_t w = soko->currentLevel.width; uint16_t total = 0; // i don't think i need to calloc before reading the blob? size_t size = sizeof(uint16_t); - readNvsBlob("sk_e_t_c", &total, &size); - - char* blops = calloc(total, sizeof(char)); - size = sizeof(char) * total; - readNvsBlob("sk_e_ts", blops, &size); - - uint16_t bi = 0; - if (blops[0] == 0) + if (readNvsBlob(key_sk_e_t_c, &total, &size)) { - // pre-flip, basically... - runningTile = SKT_FLOOR_WALKED; - bi = 1; // doesn't mess up our count, because 0 counts for 0 tiles. - } - for (size_t y = 0; y < soko->currentLevel.height; y++) - { - for (size_t x = 0; x < w; x++) + char* blops = heap_caps_calloc(total, sizeof(char), MALLOC_CAP_SPIRAM); + size = sizeof(char) * total; + if (readNvsBlob(key_sk_e_ts, blops, &size)) { - sokoTile_t t = soko->currentLevel.tiles[x][y]; - if (t == SKT_FLOOR || t == SKT_FLOOR_WALKED) + uint16_t bi = 0; + if (blops[0] == 0) { - soko->currentLevel.tiles[x][y] = runningTile; - blops[bi] = blops[bi] - 1; - - if (blops[bi] == 0) + // pre-flip, basically... + runningTile = SKT_FLOOR_WALKED; + bi = 1; // doesn't mess up our count, because 0 counts for 0 tiles. + } + for (size_t y = 0; y < soko->currentLevel.height; y++) + { + for (size_t x = 0; x < w; x++) { - bi++; - // flop - if (runningTile == SKT_FLOOR) - { - runningTile = SKT_FLOOR_WALKED; - } - else if (runningTile == SKT_FLOOR_WALKED) + sokoTile_t t = soko->currentLevel.tiles[x][y]; + if (t == SKT_FLOOR || t == SKT_FLOOR_WALKED) { - runningTile = SKT_FLOOR; + soko->currentLevel.tiles[x][y] = runningTile; + blops[bi] = blops[bi] - 1; + + if (blops[bi] == 0) + { + bi++; + // flop + if (runningTile == SKT_FLOOR) + { + runningTile = SKT_FLOOR_WALKED; + } + else if (runningTile == SKT_FLOOR_WALKED) + { + runningTile = SKT_FLOOR; + } + } } } } } + free(blops); } - free(blops); } // Level loading void sokoLoadBinLevel(soko_abs_t* soko, uint16_t levelIndex) { - printf("load bin level %d, %s\n", levelIndex, soko->levelNames[levelIndex]); + ESP_LOGD(SOKO_TAG, "load bin level %" PRIu16 ", %s", levelIndex, soko->levelNames[levelIndex]); soko->state = SKS_INIT; size_t fileSize; if (soko->levelBinaryData) @@ -315,9 +338,8 @@ void sokoLoadBinLevel(soko_abs_t* soko, uint16_t levelIndex) soko->currentLevel.gameMode = (soko_var_t)soko->levelBinaryData[2]; // for(int i = 0; i < fileSize; i++) //{ - // printf("%d, ",soko->levelBinaryData[i]); + // ESP_LOGD(SOKO_TAG, "%"PRIu8", ",soko->levelBinaryData[i]); // } - // printf("\n"); soko->currentLevelIndex = levelIndex; soko->currentLevel.levelScale = 16; soko->camWidth = TFT_WIDTH / (soko->currentLevel.levelScale); @@ -336,14 +358,14 @@ void sokoLoadBinLevel(soko_abs_t* soko, uint16_t levelIndex) { if (soko->overworld_playerX == 0 && soko->overworld_playerY == 0) { - printf("resetting player position from loaded entity\n"); + ESP_LOGD(SOKO_TAG, "resetting player position from loaded entity"); soko->overworld_playerX = soko->soko_player->x; soko->overworld_playerY = soko->soko_player->y; } } - printf("Loaded level w: %i, h %i, entities: %i\n", soko->currentLevel.width, soko->currentLevel.height, - soko->currentLevel.entityCount); + ESP_LOGD(SOKO_TAG, "Loaded level w: %i, h %i, entities: %i", soko->currentLevel.width, soko->currentLevel.height, + soko->currentLevel.entityCount); } // todo: rename self to soko @@ -364,10 +386,10 @@ void sokoLoadBinTiles(soko_abs_t* self, int byteCount) { int objX = (tileIndex - 1) % (self->currentLevel.width); // Look at the previous int objY = (tileIndex - 1) / (self->currentLevel.width); - uint8_t flagByte, direction; + uint8_t flagByte; bool players, crates, sticky, trail, inverted; int hp; //, targetX, targetY; - // printf("reading object byte after start: %i,%i:%i\n",objX,objY,self->levelBinaryData[i+1]); + // ESP_LOGD(SOKO_TAG, "reading object byte after start: %i,%i:%i",objX,objY,self->levelBinaryData[i+1]); switch (self->levelBinaryData[i + 1]) // On creating entities, index should be advanced to the SKB_OBJEND // byte so the post-increment moves to the next tile. @@ -431,9 +453,9 @@ void sokoLoadBinTiles(soko_abs_t* self, int byteCount) self->currentLevel.entities[self->currentLevel.entityCount].properties.crates = crates; self->currentLevel.entities[self->currentLevel.entityCount].properties.hp = hp; self->currentLevel.entities[self->currentLevel.entityCount].properties.targetX - = malloc(sizeof(uint8_t)); + = heap_caps_malloc(sizeof(uint8_t), MALLOC_CAP_SPIRAM); self->currentLevel.entities[self->currentLevel.entityCount].properties.targetY - = malloc(sizeof(uint8_t)); + = heap_caps_malloc(sizeof(uint8_t), MALLOC_CAP_SPIRAM); self->currentLevel.entities[self->currentLevel.entityCount].properties.targetCount = 1; self->currentLevel.entityCount += 1; i += 6; @@ -473,9 +495,9 @@ void sokoLoadBinTiles(soko_abs_t* self, int byteCount) self->currentLevel.entities[self->currentLevel.entityCount].y = objY; self->currentLevel.entities[self->currentLevel.entityCount].propFlag = true; self->currentLevel.entities[self->currentLevel.entityCount].properties.targetX - = malloc(sizeof(uint8_t) * hp); + = heap_caps_malloc(sizeof(uint8_t) * hp, MALLOC_CAP_SPIRAM); self->currentLevel.entities[self->currentLevel.entityCount].properties.targetY - = malloc(sizeof(uint8_t) * hp); + = heap_caps_malloc(sizeof(uint8_t) * hp, MALLOC_CAP_SPIRAM); self->currentLevel.entities[self->currentLevel.entityCount].properties.targetCount = true; self->currentLevel.entities[self->currentLevel.entityCount].properties.crates = crates; self->currentLevel.entities[self->currentLevel.entityCount].properties.players = players; @@ -497,68 +519,6 @@ void sokoLoadBinTiles(soko_abs_t* self, int byteCount) i += (4 + 2 * hp); break; } - case SKB_LASEREMITTER: //[type][flag] - { - flagByte = self->levelBinaryData[i + 2]; - direction = (flagByte & (0x3 << 6)) >> 6; // flagbyte stores direction in 0bDD0000P0 Where D is - // direction bits and P is player push - players = !!(flagByte & (0x1 < 1)); - - self->currentLevel.entities[self->currentLevel.entityCount].type = SKE_LASER_EMIT_UP; - self->currentLevel.entities[self->currentLevel.entityCount].x = objX; - self->currentLevel.entities[self->currentLevel.entityCount].y = objY; - self->currentLevel.entities[self->currentLevel.entityCount].facing = direction; - self->currentLevel.entities[self->currentLevel.entityCount].propFlag = true; - self->currentLevel.entities[self->currentLevel.entityCount].properties.players = players; - self->currentLevel.entities[self->currentLevel.entityCount].properties.targetX - = calloc(SOKO_MAX_ENTITY_COUNT, sizeof(uint8_t)); - self->currentLevel.entities[self->currentLevel.entityCount].properties.targetX - = calloc(SOKO_MAX_ENTITY_COUNT, sizeof(uint8_t)); - self->currentLevel.entities[self->currentLevel.entityCount].properties.targetCount = 0; - self->currentLevel.entityCount += 1; - i += 3; - break; - } - case SKB_LASERRECEIVEROMNI: - { - self->currentLevel.entities[self->currentLevel.entityCount].type = SKE_LASER_RECEIVE_OMNI; - self->currentLevel.entities[self->currentLevel.entityCount].x = objX; - self->currentLevel.entities[self->currentLevel.entityCount].y = objY; - self->currentLevel.entityCount += 1; - i += 2; - break; - } - case SKB_LASERRECEIVER: - { - flagByte = self->levelBinaryData[i + 2]; - direction = (flagByte & (0x3 << 6)) >> 6; // flagbyte stores direction in 0bDD0000P0 Where D is - // direction bits and P is player push - players = !!(flagByte & (0x1 < 1)); - - self->currentLevel.entities[self->currentLevel.entityCount].type = SKE_LASER_RECEIVE; - self->currentLevel.entities[self->currentLevel.entityCount].x = objX; - self->currentLevel.entities[self->currentLevel.entityCount].y = objY; - self->currentLevel.entities[self->currentLevel.entityCount].facing = direction; - self->currentLevel.entityCount += 1; - i += 3; - break; - } - case SKB_LASER90ROTATE: - { - flagByte = self->levelBinaryData[i + 2]; - direction = !!(flagByte & (0x1 < 0)); - players = !!(flagByte & (0x1 < 1)); - - self->currentLevel.entities[self->currentLevel.entityCount].type = SKE_LASER_90; - self->currentLevel.entities[self->currentLevel.entityCount].x = objX; - self->currentLevel.entities[self->currentLevel.entityCount].y = objY; - self->currentLevel.entities[self->currentLevel.entityCount].facing = direction; - self->currentLevel.entities[self->currentLevel.entityCount].propFlag = true; - self->currentLevel.entities[self->currentLevel.entityCount].properties.players = players; - self->currentLevel.entityCount += 1; - i += 3; - break; - } case SKB_GHOSTBLOCK: { flagByte = self->levelBinaryData[i + 2]; @@ -657,8 +617,13 @@ void sokoLoadBinTiles(soko_abs_t* self, int byteCount) } self->currentLevel.tiles[tileX][tileY] = tileType; prevTileType = tileType; - // printf("BinData@%d: %d Tile: %d at (%d,%d) - // index:%d\n",i,self->levelBinaryData[i],tileType,tileX,tileY,tileIndex); + // ESP_LOGD(SOKO_TAG, "BinData@%d: %"PRIu8" Tile: %d at (%d,%d) index:%d", + // i, + // self->levelBinaryData[i], + // tileType, + // tileX, + // tileY, + // tileIndex); tileIndex++; } } diff --git a/main/modes/games/soko/soko_undo.c b/main/modes/games/soko/soko_undo.c index 2bb262874..d8cf3f8e3 100644 --- a/main/modes/games/soko/soko_undo.c +++ b/main/modes/games/soko/soko_undo.c @@ -54,7 +54,7 @@ void sokoAddEntityMoveToHistory(soko_abs_t* soko, sokoEntity_t* entity, uint16_t { moveID += 1; soko->historyNewMove = false; - // printf("first invalid move (oldest) %i\n",soko->historyOldestValidMoveID); + // ESP_LOGD(SOKO_TAG, "first invalid move (oldest) %i",soko->historyOldestValidMoveID); } soko->historyCurrent++; diff --git a/tools/soko/tmx_to_binary.py b/tools/soko/tmx_to_binary.py index 6141fb703..b23b5d217 100644 --- a/tools/soko/tmx_to_binary.py +++ b/tools/soko/tmx_to_binary.py @@ -121,8 +121,9 @@ def convertTMX(file_path): # output now is a list of tiles. - output2 = compress(output) - #output2 = output + #output2 = compress(output) + output2 = output + rawsize = len(output) compsize = len(output2) rawBytesc = bytearray(output2)