~ubuntu-branches/ubuntu/karmic/xpuzzles/karmic

« back to all changes in this revision

Viewing changes to xcubes/Cubes.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-22 16:29:42 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050822162942-tdtf178zkpd3xxdg
Tags: 7.1.3-1ubuntu1
Update {build-,}depends for xorg -> mesa transition.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
#
6
6
###
7
7
#
8
 
#  Copyright (c) 1994 - 2004    David Albert Bagley, bagleyd@tux.org
 
8
#  Copyright (c) 1994 - 2005    David Albert Bagley, bagleyd@tux.org
9
9
#
10
10
#                   All Rights Reserved
11
11
#
147
147
 <KeyPress>0x3E: Speed()\n\
148
148
 <KeyPress>0x3C: Slow()\n\
149
149
 <KeyPress>0x2C: Slow()\n\
150
 
 <KeyPress>2: Sound()\n\
151
150
 <KeyPress>@: Sound()\n\
152
151
 <EnterWindow>: Enter()\n\
153
152
 <LeaveWindow>: Leave()";
588
587
        return (pos / w->cubes.sizeRect);
589
588
}
590
589
 
591
 
static void
592
 
Cartesian(CubesWidget w, int pos, int * x, int * y)
 
590
static int
 
591
CartesianX(CubesWidget w, int pos)
593
592
{
594
 
        *x = Column(w, pos) * w->cubes.offset.x + w->cubes.delta.x +
 
593
        int x;
 
594
 
 
595
        x = Column(w, pos) * w->cubes.offset.x + w->cubes.delta.x +
595
596
                w->cubes.puzzleOffset.x;
596
 
        *y = Row(w, pos) * w->cubes.offset.y + w->cubes.delta.y +
 
597
        if (!w->cubes.vertical) {
 
598
                x += Stack(w, pos) * (w->cubes.sizeX * w->cubes.offset.x + 1);
 
599
        }
 
600
        return x;
 
601
}
 
602
 
 
603
static int
 
604
CartesianY(CubesWidget w, int pos)
 
605
{
 
606
        int y;
 
607
 
 
608
        y = Row(w, pos) * w->cubes.offset.y + w->cubes.delta.y +
597
609
                w->cubes.puzzleOffset.y;
598
610
        if (w->cubes.vertical) {
599
 
                *y += Stack(w, pos) * (w->cubes.sizeY * w->cubes.offset.y + 1);
600
 
        } else {
601
 
                *x += Stack(w, pos) * (w->cubes.sizeX * w->cubes.offset.x + 1);
 
611
                y += Stack(w, pos) * (w->cubes.sizeY * w->cubes.offset.y + 1);
602
612
        }
 
613
        return y;
603
614
}
604
615
 
605
616
static int
737
748
                w->cubes.sizeBlock;
738
749
        Pixmap dr = 0;
739
750
 
740
 
        Cartesian(w, pos, &dx, &dy);
741
 
        dx += offsetX + pressedOffset;
742
 
        dy += offsetY + pressedOffset;
743
 
        Cartesian(w, block, &sx, &sy);
 
751
        dx = CartesianX(w, pos) + offsetX + pressedOffset;
 
752
        dy = CartesianY(w, pos) + offsetY + pressedOffset;
 
753
        sx = CartesianX(w, block);
 
754
        sy = CartesianY(w, block);
744
755
        if (blank) {
745
756
                FILLRECTANGLE(w, dr,
746
757
                        (erase) ? w->cubes.inverseGC : w->cubes.blockGC,
780
791
                w->cubes.sizeBlock;
781
792
        Pixmap dr = 0;
782
793
 
783
 
        Cartesian(w, pos, &dx, &dy);
784
 
        dx += offsetX + pressedOffset;
785
 
        dy += offsetY + pressedOffset;
786
 
        Cartesian(w, block, &sx, &sy);
 
794
        dx = CartesianX(w, pos) + offsetX + pressedOffset;
 
795
        dy = CartesianY(w, pos) + offsetY + pressedOffset;
 
796
        sx = CartesianX(w, block);
 
797
        sy = CartesianY(w, block);
787
798
        if (blank) {
788
799
                FILLRECTANGLE(w, dr,
789
800
                        (erase) ? w->cubes.inverseGC : w->cubes.blockGC,
815
826
 
816
827
static void
817
828
DrawBufferedBlock(CubesWidget w, int pos, int pressedOffset)
818
 
 
819
829
{
820
830
        Pixmap *dr;
821
831
        GC blockGC, borderGC;
826
836
        dr = &(w->cubes.bufferBlocks[pressedOffset]);
827
837
        blockGC = w->cubes.blockGC;
828
838
        borderGC = w->cubes.borderGC;
829
 
        Cartesian(w, pos, &dx, &dy);
830
 
        dx += pressedOffset;
831
 
        dy += pressedOffset;
 
839
        dx = CartesianX(w, pos) + pressedOffset;
 
840
        dy = CartesianY(w, pos) + pressedOffset;
832
841
        if (pressedOffset != 0) {
833
842
                drawShadow(w, *dr, w->cubes.blockDarkerGC,
834
843
                        dx - pressedOffset, dy - pressedOffset,
850
859
                buf, i);
851
860
}
852
861
 
 
862
void
 
863
DrawAllBlocks(const CubesWidget w)
 
864
{
 
865
        int k;
 
866
 
 
867
        for (k = 0; k < w->cubes.sizeBlock; k++)
 
868
                DrawBlock(w, k, (w->cubes.blockOfPosition[k] <= 0),
 
869
                        (w->cubes.blockOfPosition[k] <= 0), FALSE, 0, 0);
 
870
}
 
871
 
853
872
static void
854
873
DrawAllBufferedBlocks(const CubesWidget w)
855
874
{
860
879
                        DrawBufferedBlock(w, k, l);
861
880
}
862
881
 
863
 
void
864
 
DrawAllBlocks(const CubesWidget w)
865
 
{
866
 
        int k;
867
 
 
868
 
        for (k = 0; k < w->cubes.sizeBlock; k++)
869
 
                DrawBlock(w, k, (w->cubes.blockOfPosition[k] <= 0),
870
 
                        (w->cubes.blockOfPosition[k] <= 0), FALSE, 0, 0);
871
 
}
872
 
 
873
882
static void
874
883
DrawBlockFrame(CubesWidget w, int xR, int yR, int wR, int hR, int incAt)
875
884
{
904
913
 
905
914
        fillBeginPos = BlockNFromSpace(w, numBlocks, dir);
906
915
        if ((dir == RIGHT) || (dir == LEFT)) {
907
 
                Cartesian(w, fillBeginPos, &fillBeginI, &dy);
 
916
                fillBeginI = CartesianX(w, fillBeginPos);
908
917
                gapI = w->cubes.blockSize.x * fast / w->cubes.numSlices;
909
918
                moveI = w->cubes.blockSize.x + w->cubes.delta.x;
910
919
        } else if ((dir == TOP) || (dir == BOTTOM)) {
911
 
                Cartesian(w, fillBeginPos, &dx, &fillBeginI);
 
920
                fillBeginI = CartesianY(w, fillBeginPos);
912
921
                gapI = w->cubes.blockSize.y * fast / w->cubes.numSlices;
913
922
                moveI = w->cubes.blockSize.y + w->cubes.delta.y;
914
923
        }
927
936
              PutMove(dir);
928
937
            }
929
938
            /* Calculate deltas */
930
 
            Cartesian(w, posNext, &dx, &dy);
 
939
            dx = CartesianX(w, posNext);
 
940
            dy = CartesianY(w, posNext);
931
941
            if ((dir == RIGHT) || (dir == LEFT)) {
932
942
              ix = ((dir == RIGHT) ? inc : -inc);
933
943
              iy = 0;
941
951
            iy += dy;
942
952
            if (aBlock < numBlocks - 1) {
943
953
              switch (dir) {
944
 
                case TOP:
945
 
                  FILLRECTANGLE(w, dr,
946
 
                    w->cubes.inverseGC,
947
 
                    ix, iy + w->cubes.blockSize.y,
948
 
                    w->cubes.blockSize.x, gapI);
949
 
                  break;
950
 
                case RIGHT:
951
 
                  FILLRECTANGLE(w, dr,
952
 
                    w->cubes.inverseGC,
953
 
                    ix - gapI, iy, gapI, w->cubes.blockSize.y);
954
 
                  break;
955
 
                case BOTTOM:
956
 
                  FILLRECTANGLE(w, dr,
957
 
                    w->cubes.inverseGC,
958
 
                    ix, iy - gapI, w->cubes.blockSize.x, gapI);
959
 
                  break;
960
 
                case LEFT:
961
 
                  FILLRECTANGLE(w, dr,
962
 
                    w->cubes.inverseGC,
963
 
                    ix + w->cubes.blockSize.x, iy,
964
 
                    gapI, w->cubes.blockSize.y);
965
 
                  break;
 
954
              case TOP:
 
955
                FILLRECTANGLE(w, dr,
 
956
                  w->cubes.inverseGC,
 
957
                  ix, iy + w->cubes.blockSize.y,
 
958
                  w->cubes.blockSize.x, gapI);
 
959
                break;
 
960
              case RIGHT:
 
961
                FILLRECTANGLE(w, dr,
 
962
                  w->cubes.inverseGC,
 
963
                  ix - gapI,
 
964
                  iy, gapI, w->cubes.blockSize.y);
 
965
                break;
 
966
              case BOTTOM:
 
967
                FILLRECTANGLE(w, dr,
 
968
                  w->cubes.inverseGC,
 
969
                  ix, iy - gapI,
 
970
                  w->cubes.blockSize.x, gapI);
 
971
                break;
 
972
              case LEFT:
 
973
                FILLRECTANGLE(w, dr,
 
974
                  w->cubes.inverseGC,
 
975
                  ix + w->cubes.blockSize.x, iy,
 
976
                  gapI, w->cubes.blockSize.y);
 
977
                break;
966
978
              }
967
979
            } else {
968
980
              switch (dir) {
969
 
                case TOP:
970
 
                  FILLRECTANGLE(w, dr,
971
 
                    w->cubes.inverseGC,
972
 
                    ix, iy + w->cubes.blockSize.y,
973
 
                    w->cubes.blockSize.x, fillBeginI - iy);
974
 
                  break;
975
 
                case RIGHT:
976
 
                  FILLRECTANGLE(w, dr,
977
 
                    w->cubes.inverseGC,
978
 
                    fillBeginI, iy,
979
 
                    ix - fillBeginI, w->cubes.blockSize.y);
980
 
                  break;
981
 
                case BOTTOM:
982
 
                  FILLRECTANGLE(w, dr,
983
 
                    w->cubes.inverseGC,
984
 
                    ix, fillBeginI,
985
 
                    w->cubes.blockSize.x, iy - fillBeginI);
986
 
                  break;
987
 
                case LEFT:
988
 
                  FILLRECTANGLE(w, dr,
989
 
                    w->cubes.inverseGC,
990
 
                    ix + w->cubes.blockSize.x, iy,
991
 
                    fillBeginI - ix, w->cubes.blockSize.y);
992
 
                 break;
 
981
              case TOP:
 
982
                FILLRECTANGLE(w, dr,
 
983
                  w->cubes.inverseGC,
 
984
                  ix, iy + w->cubes.blockSize.y,
 
985
                  w->cubes.blockSize.x, fillBeginI - iy);
 
986
                break;
 
987
              case RIGHT:
 
988
                FILLRECTANGLE(w, dr,
 
989
                  w->cubes.inverseGC,
 
990
                  fillBeginI, iy,
 
991
                  ix - fillBeginI, w->cubes.blockSize.y);
 
992
                break;
 
993
              case BOTTOM:
 
994
                FILLRECTANGLE(w, dr,
 
995
                  w->cubes.inverseGC,
 
996
                  ix, fillBeginI,
 
997
                  w->cubes.blockSize.x, iy - fillBeginI);
 
998
                break;
 
999
              case LEFT:
 
1000
                FILLRECTANGLE(w, dr,
 
1001
                  w->cubes.inverseGC,
 
1002
                  ix + w->cubes.blockSize.x, iy,
 
1003
                  fillBeginI - ix, w->cubes.blockSize.y);
 
1004
                break;
993
1005
              }
994
1006
            }
995
1007
          }
997
1009
        }
998
1010
        pos = w->cubes.spacePosition;
999
1011
        for (aBlock = 0; aBlock < numBlocks; aBlock++) {
1000
 
            posNext = BlockNFromSpace(w, aBlock + 1, dir);
1001
 
            w->cubes.blockOfPosition[pos] =
1002
 
              w->cubes.blockOfPosition[posNext];
1003
 
            pos = posNext;
 
1012
          posNext = BlockNFromSpace(w, aBlock + 1, dir);
 
1013
          w->cubes.blockOfPosition[pos] =
 
1014
            w->cubes.blockOfPosition[posNext];
 
1015
          pos = posNext;
1004
1016
        }
1005
1017
        w->cubes.spacePosition = fillBeginPos;
1006
1018
        w->cubes.blockOfPosition[fillBeginPos] = 0;
1010
1022
AnimateMove(CubesWidget w, int fromPos, int fast)
1011
1023
{
1012
1024
        int pos = w->cubes.spacePosition;
1013
 
        int dx, dy, fromdx, fromdy;
 
1025
        int dx, dy, fx, fy;
1014
1026
        int xToCenter, yToCenter;
1015
1027
        int incTo, incAt, inc;
1016
1028
        Pixmap dr = 0;
1017
1029
 
1018
 
        Cartesian(w, pos, &dx, &dy);
1019
 
        Cartesian(w, fromPos, &fromdx, &fromdy);
 
1030
        dx = CartesianX(w, pos);
 
1031
        dy = CartesianY(w, pos);
 
1032
        fx = CartesianX(w, fromPos);
 
1033
        fy = CartesianY(w, fromPos);
1020
1034
        xToCenter = w->cubes.blockSize.x / 2;
1021
1035
        yToCenter = w->cubes.blockSize.y / 2;
1022
1036
        incTo = MIN(w->cubes.blockSize.x, w->cubes.blockSize.y) / 2;
1024
1038
 
1025
1039
        FILLRECTANGLE(w, dr,
1026
1040
                w->cubes.inverseGC,
1027
 
                fromdx, fromdy, incAt, w->cubes.blockSize.y);
1028
 
        FILLRECTANGLE(w, dr,
1029
 
                w->cubes.inverseGC,
1030
 
                fromdx, fromdy, w->cubes.blockSize.x, incAt);
1031
 
        FILLRECTANGLE(w, dr,
1032
 
                w->cubes.inverseGC,
1033
 
                fromdx + w->cubes.blockSize.x - incAt, fromdy,
 
1041
                fx, fy, incAt, w->cubes.blockSize.y);
 
1042
        FILLRECTANGLE(w, dr,
 
1043
                w->cubes.inverseGC,
 
1044
                fx, fy, w->cubes.blockSize.x, incAt);
 
1045
        FILLRECTANGLE(w, dr,
 
1046
                w->cubes.inverseGC,
 
1047
                fx + w->cubes.blockSize.x - incAt, fy,
1034
1048
                incAt, w->cubes.blockSize.y);
1035
1049
        FILLRECTANGLE(w, dr,
1036
1050
                w->cubes.inverseGC,
1037
 
                fromdx, fromdy + w->cubes.blockSize.y - incAt,
 
1051
                fx, fy + w->cubes.blockSize.y - incAt,
1038
1052
                w->cubes.blockSize.x, incAt);
1039
1053
        initTimer(w);
1040
1054
        for (inc = incAt; inc < incTo; inc += incAt) {
1041
 
                int xR = fromdx + inc, yR = fromdy + inc;
 
1055
                int xR = fx + inc, yR = fy + inc;
1042
1056
                int wR = w->cubes.blockSize.x - 2 * inc;
1043
1057
                int hR = w->cubes.blockSize.y - 2 * inc;
1044
1058
 
1124
1138
}
1125
1139
 
1126
1140
static void
1127
 
ResetBlocks(CubesWidget w)
1128
 
{
1129
 
        int i;
1130
 
 
1131
 
        w->cubes.sizeRect = w->cubes.sizeX * w->cubes.sizeY;
1132
 
        w->cubes.sizeBlock = w->cubes.sizeRect * w->cubes.sizeZ;
1133
 
        if (w->cubes.blockOfPosition)
1134
 
                free((void *) w->cubes.blockOfPosition);
1135
 
        if (!(w->cubes.blockOfPosition = (int *)
1136
 
                        malloc(sizeof (int) * w->cubes.sizeBlock))) {
1137
 
                DISPLAY_ERROR("Not enough memory, exiting.");
1138
 
        }
1139
 
 
1140
 
        if (startPosition)
1141
 
                free((void *) startPosition);
1142
 
        if (!(startPosition = (int *)
1143
 
                        malloc(sizeof (int) * w->cubes.sizeBlock))) {
1144
 
                DISPLAY_ERROR("Not enough memory, exiting.");
1145
 
        }
1146
 
 
1147
 
        w->cubes.spacePosition = w->cubes.sizeBlock - 1;
1148
 
        w->cubes.blockOfPosition[w->cubes.sizeBlock - 1] = 0;
1149
 
        for (i = 1; i < w->cubes.sizeBlock; i++)
1150
 
                w->cubes.blockOfPosition[i - 1] = i;
1151
 
        FlushMoves(w);
1152
 
        w->cubes.currentPosition = -1;
1153
 
        w->cubes.started = False;
1154
 
}
1155
 
 
1156
 
static void
1157
1141
EraseFrame(const CubesWidget w, Pixmap dr)
1158
1142
{
1159
1143
        FILLRECTANGLE(w, dr, w->cubes.inverseGC,
1596
1580
}
1597
1581
 
1598
1582
static void
1599
 
RandomizeBlocks(CubesWidget w)
 
1583
ResetBlocks(CubesWidget w)
1600
1584
{
1601
 
        if (w->cubes.currentPosition >= 0)
1602
 
                return;
1603
 
        w->cubes.cheat = False;
1604
 
        /* First interchange blocks an even number of times */
1605
 
        /* Must be at least 3x2 or 2x2x2 */
1606
 
        if ((w->cubes.sizeX > 2 && (w->cubes.sizeY > 1 || w->cubes.sizeZ > 1)) ||
1607
 
                        (w->cubes.sizeY > 2 && (w->cubes.sizeX > 1 || w->cubes.sizeZ > 1)) ||
1608
 
                        (w->cubes.sizeZ > 2 && (w->cubes.sizeX > 1 || w->cubes.sizeY > 1)) ||
1609
 
                        (w->cubes.sizeX == 2 && w->cubes.sizeY == 2 && w->cubes.sizeZ == 2)) {
1610
 
                int pos, count = 0;
1611
 
 
1612
 
                for (pos = 0; pos < w->cubes.sizeBlock; pos++) {
1613
 
                        int randomPos = pos;
1614
 
 
1615
 
                        while (randomPos == pos) {
1616
 
                                randomPos = NRAND(w->cubes.sizeBlock);
1617
 
                        }
1618
 
                        count += ExchangeBlocks(w, pos, randomPos);
1619
 
                }
1620
 
                if ((count & 1) &&
1621
 
                                !ExchangeBlocks(w, 0, 1) &&
1622
 
                                !ExchangeBlocks(w, w->cubes.sizeBlock - 2,
1623
 
                                w->cubes.sizeBlock - 1)) {
1624
 
                        DISPLAY_WARNING("RandomizeBlocks: should not get here");
1625
 
                }
1626
 
                DrawAllBlocks(w);
1627
 
#ifndef WINVER
1628
 
                XFlush(XtDisplay(w));
1629
 
#endif
1630
 
        }
1631
 
        /* randomly position space */
1632
 
        /* Idea for this came from "puzzle" by Don Bennett, HP Labs */
1633
 
        {
1634
 
                int n, s, e;
1635
 
 
1636
 
                s = Column(w, w->cubes.spacePosition);
1637
 
                e = NRAND(w->cubes.sizeX);
1638
 
                for (n = 0; n < e - s; n++)
1639
 
                        (void) MoveCubesDir(w, LEFT, INSTANT);
1640
 
                for (n = 0; n < s - e; n++)
1641
 
                        (void) MoveCubesDir(w, RIGHT, INSTANT);
1642
 
                s = Row(w, w->cubes.spacePosition);
1643
 
                e = NRAND(w->cubes.sizeY);
1644
 
                for (n = 0; n < e - s; n++)
1645
 
                        (void) MoveCubesDir(w, TOP, INSTANT);
1646
 
                for (n = 0; n < s - e; n++)
1647
 
                        (void) MoveCubesDir(w, BOTTOM, INSTANT);
1648
 
                s = Stack(w, w->cubes.spacePosition);
1649
 
                e = NRAND(w->cubes.sizeZ);
1650
 
                for (n = 0; n < e - s; n++)
1651
 
                        (void) MoveCubesDir(w, OUTWARDS, INSTANT);
1652
 
                for (n = 0; n < s - e; n++)
1653
 
                        (void) MoveCubesDir(w, INWARDS, INSTANT);
1654
 
                FlushMoves(w);
1655
 
                SetCubes(w, CUBES_RANDOMIZE);
1656
 
        }
1657
 
#if 0
1658
 
        /* Now move the space around randomly */
1659
 
        if (w->cubes.sizeX > 1 || w->cubes.sizeY > 1 || w->cubes.sizeZ > 1) {
1660
 
                int big = w->cubes.sizeBlock + NRAND(2);
1661
 
                int lastDirection = -1;
1662
 
                int randomDirection;
1663
 
 
1664
 
                SetCubes(w, CUBES_RESET);
1665
 
#ifdef DEBUG
1666
 
                big = 3;
1667
 
#endif
1668
 
                if (big > 1000)
1669
 
                        big = 1000;
1670
 
                while (big--) {
1671
 
                        randomDirection = NRAND(COORD);
1672
 
#ifdef DEBUG
1673
 
                        Sleep(1);
1674
 
#endif
1675
 
                        if ((randomDirection < 4 && (randomDirection + 2) % 4 != lastDirection) ||
1676
 
                            (randomDirection >= 4 && randomDirection + ((randomDirection % 2) ? -1 : 1) != lastDirection) ||
1677
 
                            (w->cubes.sizeX == 1 && w->cubes.sizeY == 1) ||
1678
 
                            (w->cubes.sizeY == 1 && w->cubes.sizeZ == 1) ||
1679
 
                            (w->cubes.sizeZ == 1 && w->cubes.sizeX == 1)) {
1680
 
                                if (MoveCubesDir(w, randomDirection, INSTANT))
1681
 
                                        lastDirection = randomDirection;
1682
 
                                else
1683
 
                                        big++;
1684
 
                        }
1685
 
                }
1686
 
                FlushMoves(w);
1687
 
                SetCubes(w, CUBES_RANDOMIZE);
1688
 
        }
1689
 
#endif
1690
 
        if (CheckSolved(w)) {
1691
 
                SetCubes(w, CUBES_SOLVED);
1692
 
        }
 
1585
        int i;
 
1586
 
 
1587
        w->cubes.sizeRect = w->cubes.sizeX * w->cubes.sizeY;
 
1588
        w->cubes.sizeBlock = w->cubes.sizeRect * w->cubes.sizeZ;
 
1589
        if (w->cubes.blockOfPosition)
 
1590
                free((void *) w->cubes.blockOfPosition);
 
1591
        if (!(w->cubes.blockOfPosition = (int *)
 
1592
                        malloc(sizeof (int) * w->cubes.sizeBlock))) {
 
1593
                DISPLAY_ERROR("Not enough memory, exiting.");
 
1594
        }
 
1595
 
 
1596
        if (startPosition)
 
1597
                free((void *) startPosition);
 
1598
        if (!(startPosition = (int *)
 
1599
                        malloc(sizeof (int) * w->cubes.sizeBlock))) {
 
1600
                DISPLAY_ERROR("Not enough memory, exiting.");
 
1601
        }
 
1602
 
 
1603
        w->cubes.spacePosition = w->cubes.sizeBlock - 1;
 
1604
        w->cubes.blockOfPosition[w->cubes.sizeBlock - 1] = 0;
 
1605
        for (i = 1; i < w->cubes.sizeBlock; i++)
 
1606
                w->cubes.blockOfPosition[i - 1] = i;
 
1607
        FlushMoves(w);
 
1608
        w->cubes.currentPosition = -1;
 
1609
        w->cubes.started = False;
1693
1610
}
1694
1611
 
1695
1612
static void
1907
1824
}
1908
1825
 
1909
1826
static void
 
1827
RandomizeBlocks(CubesWidget w)
 
1828
{
 
1829
        if (w->cubes.currentPosition >= 0)
 
1830
                return;
 
1831
        w->cubes.cheat = False;
 
1832
        /* First interchange blocks an even number of times */
 
1833
        /* Must be at least 3x2 or 2x2x2 */
 
1834
        if ((w->cubes.sizeX > 2 && (w->cubes.sizeY > 1 || w->cubes.sizeZ > 1)) ||
 
1835
                        (w->cubes.sizeY > 2 && (w->cubes.sizeX > 1 || w->cubes.sizeZ > 1)) ||
 
1836
                        (w->cubes.sizeZ > 2 && (w->cubes.sizeX > 1 || w->cubes.sizeY > 1)) ||
 
1837
                        (w->cubes.sizeX == 2 && w->cubes.sizeY == 2 && w->cubes.sizeZ == 2)) {
 
1838
                int pos, count = 0;
 
1839
 
 
1840
                for (pos = 0; pos < w->cubes.sizeBlock; pos++) {
 
1841
                        int randomPos = pos;
 
1842
 
 
1843
                        while (randomPos == pos) {
 
1844
                                randomPos = NRAND(w->cubes.sizeBlock);
 
1845
                        }
 
1846
                        count += ExchangeBlocks(w, pos, randomPos);
 
1847
                }
 
1848
                if ((count & 1) &&
 
1849
                                !ExchangeBlocks(w, 0, 1) &&
 
1850
                                !ExchangeBlocks(w, w->cubes.sizeBlock - 2,
 
1851
                                w->cubes.sizeBlock - 1)) {
 
1852
                        DISPLAY_WARNING("RandomizeBlocks: should not get here");
 
1853
                }
 
1854
                DrawAllBlocks(w);
 
1855
#ifndef WINVER
 
1856
                XFlush(XtDisplay(w));
 
1857
#endif
 
1858
        }
 
1859
        /* randomly position space */
 
1860
        /* Idea for this came from "puzzle" by Don Bennett, HP Labs */
 
1861
        {
 
1862
                int n, s, e;
 
1863
 
 
1864
                s = Column(w, w->cubes.spacePosition);
 
1865
                e = NRAND(w->cubes.sizeX);
 
1866
                for (n = 0; n < e - s; n++)
 
1867
                        (void) MoveCubesDir(w, LEFT, INSTANT);
 
1868
                for (n = 0; n < s - e; n++)
 
1869
                        (void) MoveCubesDir(w, RIGHT, INSTANT);
 
1870
                s = Row(w, w->cubes.spacePosition);
 
1871
                e = NRAND(w->cubes.sizeY);
 
1872
                for (n = 0; n < e - s; n++)
 
1873
                        (void) MoveCubesDir(w, TOP, INSTANT);
 
1874
                for (n = 0; n < s - e; n++)
 
1875
                        (void) MoveCubesDir(w, BOTTOM, INSTANT);
 
1876
                s = Stack(w, w->cubes.spacePosition);
 
1877
                e = NRAND(w->cubes.sizeZ);
 
1878
                for (n = 0; n < e - s; n++)
 
1879
                        (void) MoveCubesDir(w, OUTWARDS, INSTANT);
 
1880
                for (n = 0; n < s - e; n++)
 
1881
                        (void) MoveCubesDir(w, INWARDS, INSTANT);
 
1882
                FlushMoves(w);
 
1883
                SetCubes(w, CUBES_RANDOMIZE);
 
1884
        }
 
1885
#if 0
 
1886
        /* Now move the space around randomly */
 
1887
        if (w->cubes.sizeX > 1 || w->cubes.sizeY > 1 || w->cubes.sizeZ > 1) {
 
1888
                int big = w->cubes.sizeBlock + NRAND(2);
 
1889
                int lastDirection = -1;
 
1890
                int randomDirection;
 
1891
 
 
1892
                SetCubes(w, CUBES_RESET);
 
1893
#ifdef DEBUG
 
1894
                big = 3;
 
1895
#endif
 
1896
                if (big > 1000)
 
1897
                        big = 1000;
 
1898
                while (big--) {
 
1899
                        randomDirection = NRAND(COORD);
 
1900
#ifdef DEBUG
 
1901
                        Sleep(1);
 
1902
#endif
 
1903
                        if ((randomDirection < 4 && (randomDirection + 2) % 4 != lastDirection) ||
 
1904
                            (randomDirection >= 4 && randomDirection + ((randomDirection % 2) ? -1 : 1) != lastDirection) ||
 
1905
                            (w->cubes.sizeX == 1 && w->cubes.sizeY == 1) ||
 
1906
                            (w->cubes.sizeY == 1 && w->cubes.sizeZ == 1) ||
 
1907
                            (w->cubes.sizeZ == 1 && w->cubes.sizeX == 1)) {
 
1908
                                if (MoveCubesDir(w, randomDirection, INSTANT))
 
1909
                                        lastDirection = randomDirection;
 
1910
                                else
 
1911
                                        big++;
 
1912
                        }
 
1913
                }
 
1914
                FlushMoves(w);
 
1915
                SetCubes(w, CUBES_RANDOMIZE);
 
1916
        }
 
1917
#endif
 
1918
        if (CheckSolved(w)) {
 
1919
                SetCubes(w, CUBES_SOLVED);
 
1920
        }
 
1921
}
 
1922
 
 
1923
static void
1910
1924
SolveBlocks(CubesWidget w)
1911
1925
{
1912
1926
        if (CheckSolved(w) || w->cubes.currentPosition >= 0)
2291
2305
        CubesWidget w = (CubesWidget) old;
2292
2306
 
2293
2307
        XtReleaseGC(old, w->cubes.blockGC);
 
2308
        XtReleaseGC(old, w->cubes.borderGC);
2294
2309
        XtReleaseGC(old, w->cubes.blockBrighterGC);
2295
2310
        XtReleaseGC(old, w->cubes.blockDarkerGC);
2296
 
        XtReleaseGC(old, w->cubes.borderGC);
2297
2311
        XtReleaseGC(old, w->cubes.frameGC);
2298
2312
        XtReleaseGC(old, w->cubes.inverseGC);
2299
2313
        XtRemoveCallbacks(old, XtNselectCallback, w->cubes.select);
2484
2498
        w->cubes.oldColormap = None;
2485
2499
        w->cubes.fontInfo = NULL;
2486
2500
        w->cubes.blockGC = NULL;
 
2501
        w->cubes.borderGC = NULL;
2487
2502
        w->cubes.blockBrighterGC = NULL;
2488
2503
        w->cubes.blockDarkerGC = NULL;
2489
 
        w->cubes.borderGC = NULL;
2490
2504
        w->cubes.frameGC = NULL;
2491
2505
        w->cubes.inverseGC = NULL;
2492
2506
#endif