noinst_HEADERS = conf_post.h src/version.h src/icon.h src/ewmhicon.h \
common/src/xtra.h
-rrace_curses_SOURCES = common/src/help.c src/game.c src/version.c
+rrace_curses_SOURCES = common/src/help.c src/game.c src/time.c src/version.c
rrace_curses_LDADD = $(libcursesmain_a_OBJECTS) $(CURSES_LIBS) $(GNULIB)
-rrace_motif_SOURCES = src/game.c src/x11.c src/game.h src/motif.h \
+rrace_motif_SOURCES = src/game.c src/time.c src/x11.c src/game.h src/motif.h \
src/colour.h src/ewmhicon.c src/icon.c \
src/version.c src/xcounter.c src/xcounter.h
rrace_motif_LDADD = $(libmotifmain_a_OBJECTS) $(libmotifui_a_OBJECTS) \
t/boardrect \
t/checkgoal \
t/ewmhicon \
+ t/initboard \
t/overlaygoal \
t/rng-test
-EXTRA_DIST += t/xos256ss.c
+EXTRA_DIST += t/game-notime.h t/xos256ss.c
$(t_boardbit_OBJECTS): $(gnulib_headers)
$(t_overlaygoal_OBJECTS): $(gnulib_headers)
t_ewmhicon_LDADD = $(MOTIF_LIBS) $(GNULIB)
$(t_ewmhicon_OBJECTS): $(gnulib_headers)
+t_initboard_SOURCES = t/initboard.c src/game.c
+$(t_initboard_OBJECTS): $(gnulib_headers)
+
XPMICONS_LOCOLOR = data/lo16x16.xpm data/lo32x32.xpm data/lo48x48.xpm
XPMICONS_HICOLOR = data/hi16x16.xpm data/hi24x24.xpm \
data/hi32x32.xpm data/hi48x48.xpm
/*
* Slide puzzle core game logic
- * Copyright © 2022 Nick Bowler
+ * Copyright © 2022-2023 Nick Bowler
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <config.h>
#include <limits.h>
#include <string.h>
+#include <unistd.h>
#include <time.h>
-#include <gethrxtime.h>
#include "game.h"
#define B64(x) ((x) & 0xffffffffffffffff)
if (!rng_is_seeded()) {
unsigned long long seed;
- seed = time(NULL);
- seed += gethrxtime();
+ /*
+ * Try to get a reasonable initial seed.
+ *
+ * Reasonable in this context means:
+ *
+ * - roughly even distribution of 1/0 bits, and
+ * - unlikely to generate the same seed twice in succession.
+ */
+ game_begin(board);
+
+ seed = time(NULL);
+ seed += board->time_start;
+ seed += (unsigned long long)getpid() << 16;
seed += seed << 32;
game_reseed(seed);
return mask & GOAL_MASK;
}
-void game_begin(struct board *board)
-{
- board->time_start = gethrxtime();
-}
-
-int_fast32_t game_elapsed(struct board *board)
-{
- return (gethrxtime() - board->time_start) / 1000000;
-}
-
int_fast32_t game_finish(struct board *board)
{
int_fast32_t t = game_elapsed(board);
--- /dev/null
+/*
+ * Slide puzzle game timer logic
+ * Copyright © 2022-2023 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdint.h>
+#include <gethrxtime.h>
+
+#include "game.h"
+
+void game_begin(struct board *board)
+{
+ board->time_start = gethrxtime();
+}
+
+int_fast32_t game_elapsed(struct board *board)
+{
+ return (gethrxtime() - board->time_start) / 1000000;
+}
/boardrect
/checkgoal
/ewmhicon
+/initboard
/overlaygoal
/rng-test
+/*
+ * Helper to test game_do_move function.
+ * Copyright © 2022-2023 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
-#include "game.h"
+#include "game-notime.h"
static const char *progname;
/*
* Helper to test game_check_goal function.
- * Copyright © 2022 Nick Bowler
+ * Copyright © 2022-2023 Nick Bowler
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <string.h>
#include <inttypes.h>
#include <errno.h>
-#include "game.h"
+#include "game-notime.h"
#define X3(x) x x x
--- /dev/null
+/*
+ * Test stubs to link in game logic without timers.
+ * Copyright © 2023 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "game.h"
+
+void game_begin(struct board *board) { }
+int_fast32_t game_elapsed(struct board *board) { return 0; }
--- /dev/null
+/*
+ * Call board_reset and print the resulting board.
+ * Copyright © 2023 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * This will stub out the high precision timer, which means this will not
+ * contribute to the initial seed (good for the tests we want to do).
+ */
+#include "game-notime.h"
+
+static int output_tile(unsigned tile, unsigned (*counts)[TILE_MAX], int goal)
+{
+ static const char chars[TILE_MAX] = ".ROYGBW";
+ unsigned wtf = tile ? 4 : !goal;
+
+ if (tile >= TILE_MAX) {
+ fprintf(stderr, "invalid tile value (%u)\n", tile);
+ return -1;
+ }
+
+ if (++counts[!goal][tile] > (tile ? 4 : !goal)) {
+ printf("WTF %u\n", wtf);
+ fprintf(stderr, "%s has too many (%u) %c tiles\n",
+ goal ? "goal" : "game", counts[!goal][tile], chars[tile]);
+ return -1;
+ }
+
+ putchar(chars[tile]);
+ return 0;
+}
+
+int main(void)
+{
+ unsigned counts[2][TILE_MAX] = {0};
+ struct board board;
+ int i, j;
+
+ game_reset(&board);
+
+ for (i = 0; i < 25; i++) {
+ int tile;
+
+ tile = board_tile(board.game, i);
+ if (output_tile(tile, counts, 0) < 0)
+ return EXIT_FAILURE;
+
+ if ((i+1) % 5)
+ continue;
+
+ if (i < 15) {
+ putchar(' ');
+
+ for (j = 0; j < 3; j++) {
+ tile = board_tile(board.goal, i-4 + j);
+ if (output_tile(tile, counts, 1) < 0)
+ return EXIT_FAILURE;
+ }
+ }
+ putchar('\n');
+ }
+}
/*
* Test case for xoshiro256** implementation.
- * Copyright © 2022 Nick Bowler
+ * Copyright © 2022-2023 Nick Bowler
*
* Directly compare the game RNG against the reference implementation.
*
#include <stdio.h>
#include <stdlib.h>
+#include "game-notime.h"
#include "game.c"
#include "xos256ss.c"
[0], [expout])
AT_CLEANUP
+
+# Basic check that we get different initial games if we run the program
+# multiple times in sequence.
+AT_SETUP([game_reset initial seed])
+
+AT_CHECK([initboard >a && initboard >b && initboard >c])
+AT_CHECK([diff a b || diff b c || diff a c || exit 42], [42], [ignore-nolog])
+
+AT_CLEANUP