+2010-03-27
+ * added support for native Sokoban solution files in pure 'udlrUDLR'
+ format with extension ".sln" instead of ".tape" for solution tapes
+
2010-03-26
* added image config suffix ".class" to be able to define classes of
crumbled elements which are then separated against each others when
drawing crumbled borders (class names can freely be defined)
+ (Example: "sand.CRUMBLED.class: sand" and "emc_grass.CRUMBLED.class:
+ emc_grass" results in sand and emc_grass being crumbled separately,
+ even if directly adjacent on the playfield.)
* added image config suffix ".style" to use two new features for
crumbled graphics:
- - "accurate_borders": try to draw correctly crumbled corners
- - "inner_corners": also draw inner corners -- this is a big kludge:
+ - "accurate_borders": try to draw correctly crumbled corners (which
+ means that a row of crumbled elements does not have two crumbled
+ corners for each element in the row, but only at the "real" corners
+ at the start and the end of the row of elements)
+ - "inner_corners": also draw inner corners in concave constructions
+ of several crumbled elements -- this is currently a big kludge: the
number of frames for crumbled graphic must be "2", with the first
frame as usual (crumbled graphic), while the second frame contains
- the inner corners for the crumbled graphic
+ the graphic with inner (crumbled) corners for the crumbled graphic
(These two features are mainly intended for bevelled walls, not for
- diggable elements like sand; "inner_corners" only reliably works for
- static walls, not for dynamically changing walls using CEs.)
+ diggable elements like sand; "inner_corners" only works reliably for
+ static walls, not for in-game dynamically changing walls using CEs.)
2010-03-16
* continued code cleanup of native Supaplex game engine
-#define COMPILE_DATE_STRING "2010-03-26 21:45"
+#define COMPILE_DATE_STRING "2010-03-27 20:44"
return chunk_size;
}
+void LoadTape_SokobanSolution(char *filename)
+{
+ FILE *file;
+ int move_delay = TILESIZE / level.initial_player_stepsize[0];
+
+ if (!(file = fopen(filename, MODE_READ)))
+ {
+ tape.no_valid_file = TRUE;
+
+ return;
+ }
+
+ while (!feof(file))
+ {
+ unsigned char c = fgetc(file);
+
+ if (feof(file))
+ break;
+
+ switch (c)
+ {
+ case 'u':
+ case 'U':
+ tape.pos[tape.length].action[0] = MV_UP;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case 'd':
+ case 'D':
+ tape.pos[tape.length].action[0] = MV_DOWN;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case 'l':
+ case 'L':
+ tape.pos[tape.length].action[0] = MV_LEFT;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case 'r':
+ case 'R':
+ tape.pos[tape.length].action[0] = MV_RIGHT;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case '\n':
+ case '\r':
+ case '\t':
+ case ' ':
+ /* ignore white-space characters */
+ break;
+
+ default:
+ tape.no_valid_file = TRUE;
+
+ Error(ERR_WARN, "unsupported Sokoban solution file '%s' ['%d']", filename, c);
+
+ break;
+ }
+ }
+
+ fclose(file);
+
+ if (tape.no_valid_file)
+ return;
+
+ tape.length_seconds = GetTapeLength();
+}
+
void LoadTapeFromFilename(char *filename)
{
char cookie[MAX_LINE_LEN];
/* always start with reliable default values */
setTapeInfoToDefaults();
+ if (strSuffix(filename, ".sln"))
+ {
+ LoadTape_SokobanSolution(filename);
+
+ return;
+ }
+
if (!(file = fopen(filename, MODE_READ)))
{
tape.no_valid_file = TRUE;
Error(ERR_WARN, "unsupported version of tape file '%s'", filename);
fclose(file);
+
return;
}
sprintf(basename, "%03d.%s", nr, TAPEFILE_EXTENSION);
filename = getPath2(getSolutionTapeDir(), basename);
+ if (!fileExists(filename))
+ {
+ static char *filename_sln = NULL;
+
+ checked_free(filename_sln);
+
+ sprintf(basename, "%03d.sln", nr);
+ filename_sln = getPath2(getSolutionTapeDir(), basename);
+
+ if (fileExists(filename_sln))
+ return filename_sln;
+ }
+
return filename;
}