summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/divvy.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/divvy.c')
-rw-r--r--apps/plugins/puzzles/src/divvy.c141
1 files changed, 13 insertions, 128 deletions
diff --git a/apps/plugins/puzzles/src/divvy.c b/apps/plugins/puzzles/src/divvy.c
index ea018010cf..61b04eb80d 100644
--- a/apps/plugins/puzzles/src/divvy.c
+++ b/apps/plugins/puzzles/src/divvy.c
@@ -260,9 +260,10 @@ static bool addremcommon(int w, int h, int x, int y, int *own, int val)
260 * In both of the above suggested use cases, the user would 260 * In both of the above suggested use cases, the user would
261 * probably want w==h==k, but that isn't a requirement. 261 * probably want w==h==k, but that isn't a requirement.
262 */ 262 */
263static int *divvy_internal(int w, int h, int k, random_state *rs) 263DSF *divvy_rectangle_attempt(int w, int h, int k, random_state *rs)
264{ 264{
265 int *order, *queue, *tmp, *own, *sizes, *addable, *retdsf; 265 int *order, *queue, *tmp, *own, *sizes, *addable;
266 DSF *retdsf, *tmpdsf;
266 bool *removable; 267 bool *removable;
267 int wh = w*h; 268 int wh = w*h;
268 int i, j, n, x, y, qhead, qtail; 269 int i, j, n, x, y, qhead, qtail;
@@ -277,6 +278,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs)
277 queue = snewn(n, int); 278 queue = snewn(n, int);
278 addable = snewn(wh*4, int); 279 addable = snewn(wh*4, int);
279 removable = snewn(wh, bool); 280 removable = snewn(wh, bool);
281 retdsf = tmpdsf = NULL;
280 282
281 /* 283 /*
282 * Permute the grid squares into a random order, which will be 284 * Permute the grid squares into a random order, which will be
@@ -609,7 +611,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs)
609 assert(own[i] >= 0 && own[i] < n); 611 assert(own[i] >= 0 && own[i] < n);
610 tmp[own[i]] = i; 612 tmp[own[i]] = i;
611 } 613 }
612 retdsf = snew_dsf(wh); 614 retdsf = dsf_new(wh);
613 for (i = 0; i < wh; i++) { 615 for (i = 0; i < wh; i++) {
614 dsf_merge(retdsf, i, tmp[own[i]]); 616 dsf_merge(retdsf, i, tmp[own[i]]);
615 } 617 }
@@ -619,18 +621,18 @@ static int *divvy_internal(int w, int h, int k, random_state *rs)
619 * the ominoes really are k-ominoes and we haven't 621 * the ominoes really are k-ominoes and we haven't
620 * accidentally split one into two disconnected pieces. 622 * accidentally split one into two disconnected pieces.
621 */ 623 */
622 dsf_init(tmp, wh); 624 tmpdsf = dsf_new(wh);
623 for (y = 0; y < h; y++) 625 for (y = 0; y < h; y++)
624 for (x = 0; x+1 < w; x++) 626 for (x = 0; x+1 < w; x++)
625 if (own[y*w+x] == own[y*w+(x+1)]) 627 if (own[y*w+x] == own[y*w+(x+1)])
626 dsf_merge(tmp, y*w+x, y*w+(x+1)); 628 dsf_merge(tmpdsf, y*w+x, y*w+(x+1));
627 for (x = 0; x < w; x++) 629 for (x = 0; x < w; x++)
628 for (y = 0; y+1 < h; y++) 630 for (y = 0; y+1 < h; y++)
629 if (own[y*w+x] == own[(y+1)*w+x]) 631 if (own[y*w+x] == own[(y+1)*w+x])
630 dsf_merge(tmp, y*w+x, (y+1)*w+x); 632 dsf_merge(tmpdsf, y*w+x, (y+1)*w+x);
631 for (i = 0; i < wh; i++) { 633 for (i = 0; i < wh; i++) {
632 j = dsf_canonify(retdsf, i); 634 j = dsf_canonify(retdsf, i);
633 assert(dsf_canonify(tmp, j) == dsf_canonify(tmp, i)); 635 assert(dsf_equivalent(tmpdsf, j, i));
634 } 636 }
635 637
636 cleanup: 638 cleanup:
@@ -640,6 +642,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs)
640 */ 642 */
641 sfree(order); 643 sfree(order);
642 sfree(tmp); 644 sfree(tmp);
645 dsf_free(tmpdsf);
643 sfree(own); 646 sfree(own);
644 sfree(sizes); 647 sfree(sizes);
645 sfree(queue); 648 sfree(queue);
@@ -652,131 +655,13 @@ static int *divvy_internal(int w, int h, int k, random_state *rs)
652 return retdsf; 655 return retdsf;
653} 656}
654 657
655#ifdef TESTMODE 658DSF *divvy_rectangle(int w, int h, int k, random_state *rs)
656static int fail_counter = 0;
657#endif
658
659int *divvy_rectangle(int w, int h, int k, random_state *rs)
660{ 659{
661 int *ret; 660 DSF *ret;
662 661
663 do { 662 do {
664 ret = divvy_internal(w, h, k, rs); 663 ret = divvy_rectangle_attempt(w, h, k, rs);
665
666#ifdef TESTMODE
667 if (!ret)
668 fail_counter++;
669#endif
670
671 } while (!ret); 664 } while (!ret);
672 665
673 return ret; 666 return ret;
674} 667}
675
676#ifdef TESTMODE
677
678/*
679 * gcc -g -O0 -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c
680 *
681 * or to debug
682 *
683 * gcc -g -O0 -DDIVVY_DIAGNOSTICS -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c
684 */
685
686int main(int argc, char **argv)
687{
688 int *dsf;
689 int i;
690 int w = 9, h = 4, k = 6, tries = 100;
691 random_state *rs;
692
693 rs = random_new("123456", 6);
694
695 if (argc > 1)
696 w = atoi(argv[1]);
697 if (argc > 2)
698 h = atoi(argv[2]);
699 if (argc > 3)
700 k = atoi(argv[3]);
701 if (argc > 4)
702 tries = atoi(argv[4]);
703
704 for (i = 0; i < tries; i++) {
705 int x, y;
706
707 dsf = divvy_rectangle(w, h, k, rs);
708 assert(dsf);
709
710 for (y = 0; y <= 2*h; y++) {
711 for (x = 0; x <= 2*w; x++) {
712 int miny = y/2 - 1, maxy = y/2;
713 int minx = x/2 - 1, maxx = x/2;
714 int classes[4], tx, ty;
715 for (ty = 0; ty < 2; ty++)
716 for (tx = 0; tx < 2; tx++) {
717 int cx = minx+tx, cy = miny+ty;
718 if (cx < 0 || cx >= w || cy < 0 || cy >= h)
719 classes[ty*2+tx] = -1;
720 else
721 classes[ty*2+tx] = dsf_canonify(dsf, cy*w+cx);
722 }
723 switch (y%2 * 2 + x%2) {
724 case 0: /* corner */
725 /*
726 * Cases for the corner:
727 *
728 * - if all four surrounding squares belong
729 * to the same omino, we print a space.
730 *
731 * - if the top two are the same and the
732 * bottom two are the same, we print a
733 * horizontal line.
734 *
735 * - if the left two are the same and the
736 * right two are the same, we print a
737 * vertical line.
738 *
739 * - otherwise, we print a cross.
740 */
741 if (classes[0] == classes[1] &&
742 classes[1] == classes[2] &&
743 classes[2] == classes[3])
744 printf(" ");
745 else if (classes[0] == classes[1] &&
746 classes[2] == classes[3])
747 printf("-");
748 else if (classes[0] == classes[2] &&
749 classes[1] == classes[3])
750 printf("|");
751 else
752 printf("+");
753 break;
754 case 1: /* horiz edge */
755 if (classes[1] == classes[3])
756 printf(" ");
757 else
758 printf("--");
759 break;
760 case 2: /* vert edge */
761 if (classes[2] == classes[3])
762 printf(" ");
763 else
764 printf("|");
765 break;
766 case 3: /* square centre */
767 printf(" ");
768 break;
769 }
770 }
771 printf("\n");
772 }
773 printf("\n");
774 sfree(dsf);
775 }
776
777 printf("%d retries needed for %d successes\n", fail_counter, tries);
778
779 return 0;
780}
781
782#endif