]> git.draconx.ca Git - rrace.git/commitdiff
Fix bitmap generation in goal overlay feature.
authorNick Bowler <nbowler@draconx.ca>
Wed, 4 Jan 2023 07:20:16 +0000 (02:20 -0500)
committerNick Bowler <nbowler@draconx.ca>
Sat, 7 Jan 2023 16:43:13 +0000 (11:43 -0500)
The board initialization procedure no longer ensures that unused bits of
the goal bitmap are zeroed.  When these are ORed with the game bitmaps,
it can result in bogus values for the outer tiles, which will either
render incorrectly or trip the assertion if the tile value is 7.

Normally only the objective area tiles get redrawn when the feature
is toggled on or off, which hides the problem most of the time, as
something else needs to trigger redraw of the outer tiles.  One way
to make this happen is to use the keyboard to start a new game while
holding down the right mouse button.

The best solution seems to be to just mask the goal bitmaps where
they are used.  As the same fix is needed in both the curses and
motif UIs, implement this new logic into a common function and add
a new test case to check for this bug.

Makefile.am
src/curses.c
src/game.h
src/x11.c
t/.gitignore
t/overlaygoal.c [new file with mode: 0644]
tests/game.at
testsuite.at

index c0d0c273a1cc4eb4e5547a5cfc4dab1732df9ba4..88fde3c718a5872bef7f4bf7b662bd8578b91c18 100644 (file)
@@ -94,11 +94,13 @@ check_PROGRAMS = t/boardbit \
                  t/boardrect \
                  t/checkgoal \
                  t/ewmhicon \
+                 t/overlaygoal \
                  t/rng-test
 EXTRA_DIST += t/xos256ss.c
 
-t_boardbit_SOURCES = t/boardbit.c
 $(t_boardbit_OBJECTS): $(gnulib_headers)
+$(t_overlaygoal_OBJECTS): $(gnulib_headers)
+$(t_rng_test_OBJECTS): $(gnulib_headers)
 
 t_boardmove_SOURCES = t/boardmove.c src/game.c
 $(t_boardmove_OBJECTS): $(gnulib_headers)
@@ -113,8 +115,6 @@ t_ewmhicon_SOURCES = t/ewmhicon.c src/ewmhicon.c src/icon.c common/src/help.c
 t_ewmhicon_LDADD = $(MOTIF_LIBS) $(GNULIB)
 $(t_ewmhicon_OBJECTS): $(gnulib_headers)
 
-$(t_rng_test_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
index f66589eab3dac2fac9ae85f993eded99259f375f..c0f4265e25fc98054f947cce25290b227e941ab6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Curses UI for slide puzzle game
- * 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
@@ -156,13 +156,8 @@ static void curs_redraw_game(struct app_state *state, uint_fast32_t mask)
        if (mask == -1)
                redraw_area_border(state->gamewin, 2, 5);
 
-       if (state->view_goal_on_game) {
-               for (i = 0; i < 3; i++) {
-                       buf[i] = state->board.goal[i];
-                       buf[i] = (gp[i] & ~GOAL_MASK) | (buf[i] << GOAL_SHIFT);
-               }
-               gp = buf;
-       }
+       if (state->view_goal_on_game)
+               gp = game_overlay_goal(&state->board, buf);
 
        for (i = 0; i < 25; i++) {
                if (mask & 1) {
index efa7ef0fc95d229d1d045bde9ab45dce19348db4..56fb4427fcc18abb2b3d99abdfe98006b7143fbd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -221,4 +221,21 @@ int_fast32_t game_elapsed(struct board *board);
  */
 int_fast32_t game_finish(struct board *board);
 
+/*
+ * Constructs a new set of game bitmaps into buf, with tiles in the
+ * objective area replaced by the goal tile colours, and returns buf.
+ */
+static inline uint_least32_t *
+game_overlay_goal(struct board *board, uint_least32_t *buf)
+{
+       int i;
+
+       for (i = 0; i < 3; i++) {
+               buf[i] = (unsigned long)board->goal[i] << GOAL_SHIFT;
+               buf[i] = (buf[i] & GOAL_MASK) | (board->game[i] & ~GOAL_MASK);
+       }
+
+       return buf;
+}
+
 #endif
index c8ef3353d8be28c04b2a26a5f75d61ff448d5422..b4b0a2cd2db82c1a0c96addd291d362841e5e216 100644 (file)
--- a/src/x11.c
+++ b/src/x11.c
@@ -281,13 +281,8 @@ void x11_redraw_game(struct app_state *state, uint_fast32_t mask)
        unsigned sz = state->game_tile_sz;
        int i;
 
-       if (state->flags & FLAG_VIEW_GOAL_ON_GAME) {
-               for (i = 0; i < 3; i++) {
-                       buf[i] = state->board.goal[i];
-                       buf[i] = (gp[i] & ~GOAL_MASK) | (buf[i] << GOAL_SHIFT);
-               }
-               gp = buf;
-       }
+       if (state->flags & FLAG_VIEW_GOAL_ON_GAME)
+               gp = game_overlay_goal(&state->board, buf);
 
        /* Optimize the game end case where the outer frame is cleared */
        if (mask & GAME_MASK & ~GOAL_MASK) {
index b8c0b58af5b47f083157e5ad563dba7c3799e70b..54f6466c4bff545db21e5ca3cb5bc6d8e7d0af1f 100644 (file)
@@ -3,4 +3,5 @@
 /boardrect
 /checkgoal
 /ewmhicon
+/overlaygoal
 /rng-test
diff --git a/t/overlaygoal.c b/t/overlaygoal.c
new file mode 100644 (file)
index 0000000..059e835
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Helper to test game_overlay_goal function.
+ * 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>
+#include <string.h>
+#include <errno.h>
+#include "game.h"
+
+#define X3(x) x x x
+
+static const char *progname = "overlaygoal";
+
+int main(int argc, char **argv)
+{
+       struct board board;
+       int rc;
+
+       if (argc > 0)
+               progname = argv[0];
+
+       while ((rc = scanf(X3("%" SCNxLEAST32) X3("%" SCNxLEAST16),
+                             &board.game[0], &board.game[1],
+                             &board.game[2], &board.goal[0],
+                             &board.goal[1], &board.goal[2])) == 6)
+       {
+               uint_least32_t buf[3];
+
+               game_overlay_goal(&board, buf);
+               printf(X3(" %.7" PRIxLEAST32)"\n"+1, buf[0], buf[1], buf[2]);
+       }
+
+       if (rc == EOF) {
+               if (ferror(stdin)) {
+                       fprintf(stderr, "%s: read error: %s\n", progname,
+                                       strerror(errno));
+                       return EXIT_FAILURE;
+               }
+
+               return EXIT_SUCCESS;
+       }
+
+       fprintf(stderr, "%s: invalid input sequence\n", progname);
+       return EXIT_FAILURE;
+}
index 4d367afd9a1e3f4ced0cb0f650fb52a97681158b..610b066817f0b0170cef98f7f8a21c9e6f9ad2a3 100644 (file)
@@ -1,4 +1,4 @@
-# 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
@@ -629,3 +629,26 @@ AT_DATA([expout],
 AT_CHECK([checkgoal <boards.dat >result.dat && cat result.dat], [0], [expout])
 
 AT_CLEANUP
+
+AT_SETUP([game_overlay_goal])
+
+AT_DATA([boards.dat], [dnl
+0 0 0  0  0  0
+0 0 0 -1  0  0
+0 0 0  0 -1  0
+0 0 0  0  0 -1
+1ffffff 1ffffff 1ffffff 0 0 0
+])
+
+AT_DATA([expout], [dnl
+0000000 0000000 0000000
+00739c0 0000000 0000000
+0000000 00739c0 0000000
+0000000 0000000 00739c0
+1f8c63f 1f8c63f 1f8c63f
+])
+
+AT_CHECK([overlaygoal <boards.dat >result.dat && cat result.dat],
+  [0], [expout])
+
+AT_CLEANUP
index f76b15a834d71a17aa317c28a7e3b5a5fc312ffd..09efc3a6862c05b1a653698aab5b4e5f5cebb17e 100644 (file)
@@ -1,4 +1,4 @@
-AT_COPYRIGHT([Copyright © 2022 Nick Bowler])
+AT_COPYRIGHT([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