]> git.draconx.ca Git - rrace.git/commitdiff
Improve game_check_goal implementation slightly.
authorNick Bowler <nbowler@draconx.ca>
Wed, 7 Dec 2022 03:40:10 +0000 (22:40 -0500)
committerNick Bowler <nbowler@draconx.ca>
Wed, 7 Dec 2022 04:37:00 +0000 (23:37 -0500)
It seems that, at least on x86, GCC can generate very slightly more
compact code by "expanding" the goal bitmap to match the game format,
rather what is currently done ("shrinking" the game bitmap to match
the goal format).

Add a sanity test case that checks the result of this function, which
makes such a change straightforward to do.

Makefile.am
src/game.c
t/.gitignore
t/checkgoal.c [new file with mode: 0644]
tests/game.at

index b475a79e8215a8b1f213fa9a8249cee19941d8e6..1d55ab7f9159d3878ff7e23664e5da1075013a17 100644 (file)
@@ -87,7 +87,7 @@ EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-tree.awk
 DISTCLEANFILES += $(TREEFILES:.dat=.h)
 EXTRA_DIST += $(TREEFILES)
 
-check_PROGRAMS = t/boardmove t/boardbit t/ewmhicon t/rng-test
+check_PROGRAMS = t/boardmove t/boardbit t/checkgoal t/ewmhicon t/rng-test
 EXTRA_DIST += t/xos256ss.c
 
 t_boardmove_SOURCES = t/boardmove.c src/game.c
@@ -102,6 +102,10 @@ t_ewmhicon_SOURCES = t/ewmhicon.c src/ewmhicon.c src/icon.c common/src/help.c
 t_ewmhicon_LDADD = libgnu.a $(MOTIF_LIBS)
 $(t_ewmhicon_OBJECTS): $(gnulib_headers)
 
+t_checkgoal_SOURCES = t/checkgoal.c src/game.c
+t_checkgoal_LDADD = libgnu.a
+$(t_checkgoal_OBJECTS): $(gnulib_headers)
+
 t_rng_test_LDADD = libgnu.a
 $(t_rng_test_OBJECTS): $(gnulib_headers)
 
index 4946f8d137bd3679316025ba1890864de01ed508..47adc9ffe37cb01a90d88647d25246fb2be53332 100644 (file)
@@ -236,8 +236,8 @@ uint_fast32_t game_check_goal(struct board *board)
        int i;
 
        for (i = 0; i < 3; i++)
-               mask |= goal[i] ^ (game[i] >> GOAL_SHIFT);
-       return (mask << GOAL_SHIFT) & GOAL_MASK;
+               mask |= game[i] ^ ((0ul+goal[i]) << GOAL_SHIFT);
+       return mask & GOAL_MASK;
 }
 
 void game_begin(struct board *board)
index 52f3776bfa460058f37ce75bbefc7de270db2bce..9ecb9754932dbdb6ee2eb67e7fd23a75727ecaf4 100644 (file)
@@ -1,4 +1,5 @@
 /boardbit
 /boardmove
+/checkgoal
 /ewmhicon
 /rng-test
diff --git a/t/checkgoal.c b/t/checkgoal.c
new file mode 100644 (file)
index 0000000..0941e91
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Helper to test game_check_goal function.
+ * Copyright © 2022 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 <inttypes.h>
+#include <errno.h>
+#include "game.h"
+
+#define X3(x) x x x
+
+static const char *progname = "checkgoal";
+
+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)
+       {
+               printf("%.5" PRIxFAST32 "\n", game_check_goal(&board));
+       }
+
+       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 b607cf67e39d695de2b0d7ca5e39fc4c4187f5ce..76c802a5beb9072783c092cf1cc604f38d266eb6 100644 (file)
@@ -597,3 +597,33 @@ grep -v '^ok' out], [0], [1..200
 ])
 
 AT_CLEANUP
+
+AT_SETUP([game_check_goal])
+
+AT_DATA([boards.dat],
+[[0 0 0 0 0 0
+1f8c63f 1f8c63f 1f8c63f 0000 0000 0000
+1f8c63f 1f8c63f 1f8c63f ffff 0000 0000
+1f8c63f 1f8c63f 1f8c63f 0000 ffff 0000
+1f8c63f 1f8c63f 1f8c63f 0000 0000 ffff
+00739c0 1f8c63f 1f8c63f ffff 0000 0000
+1f8c63f 00739c0 1f8c63f 0000 ffff 0000
+1f8c63f 1f8c63f 00739c0 0000 0000 ffff
+0000000 0000000 0000000 0001 0020 0400
+]])
+
+AT_DATA([expout],
+[[00000
+00000
+739c0
+739c0
+739c0
+00000
+00000
+00000
+10840
+]])
+
+AT_CHECK([checkgoal <boards.dat >result.dat && cat result.dat], [0], [expout])
+
+AT_CLEANUP