~ubuntu-branches/ubuntu/maverick/sgt-puzzles/maverick

« back to all changes in this revision

Viewing changes to cube.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2009-05-03 14:54:23 UTC
  • mfrom: (1.1.7 upstream) (3.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090503145423-o4d0ubd8ocykbad8
Tags: 8446-1ubuntu1
* Merge from debian unstable, remaining changes:
  - typos in debian/desktop/netslide.desktop (Exec=netslide)
  - xpm icons files for the menus
  - debian/rules adapted to install desktop and icons files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
179
179
    float points[8];                   /* maximum */
180
180
    int directions[8];                 /* bit masks showing point pairs */
181
181
    int flip;
182
 
    int blue;
183
182
    int tetra_class;
184
183
};
185
184
 
195
194
    int d1, d2;
196
195
};
197
196
 
 
197
typedef struct game_grid game_grid;
 
198
struct game_grid {
 
199
    int refcount;
 
200
    struct grid_square *squares;
 
201
    int nsquares;
 
202
};
 
203
 
 
204
#define SET_SQUARE(state, i, val) \
 
205
    ((state)->bluemask[(i)/32] &= ~(1 << ((i)%32)), \
 
206
     (state)->bluemask[(i)/32] |= ((!!val) << ((i)%32)))
 
207
#define GET_SQUARE(state, i) \
 
208
    (((state)->bluemask[(i)/32] >> ((i)%32)) & 1)
 
209
 
198
210
struct game_state {
199
211
    struct game_params params;
200
212
    const struct solid *solid;
201
213
    int *facecolours;
202
 
    struct grid_square *squares;
203
 
    int nsquares;
 
214
    game_grid *grid;
 
215
    unsigned long *bluemask;
204
216
    int current;                       /* index of current grid square */
205
217
    int sgkey[2];                      /* key-point indices into grid sq */
206
218
    int dgkey[2];                      /* key-point indices into grid sq */
689
701
 
690
702
static void add_grid_square_callback(void *ctx, struct grid_square *sq)
691
703
{
692
 
    game_state *state = (game_state *)ctx;
 
704
    game_grid *grid = (game_grid *)ctx;
693
705
 
694
 
    state->squares[state->nsquares] = *sq;   /* structure copy */
695
 
    state->squares[state->nsquares].blue = FALSE;
696
 
    state->nsquares++;
 
706
    grid->squares[grid->nsquares++] = *sq;   /* structure copy */
697
707
}
698
708
 
699
709
static int lowest_face(const struct solid *solid)
865
875
 
866
876
static game_state *new_game(midend *me, game_params *params, char *desc)
867
877
{
 
878
    game_grid *grid = snew(game_grid);
868
879
    game_state *state = snew(game_state);
869
880
    int area;
870
881
 
872
883
    state->solid = solids[params->solid];
873
884
 
874
885
    area = grid_area(params->d1, params->d2, state->solid->order);
875
 
    state->squares = snewn(area, struct grid_square);
876
 
    state->nsquares = 0;
877
 
    enum_grid_squares(params, add_grid_square_callback, state);
878
 
    assert(state->nsquares == area);
 
886
    grid->squares = snewn(area, struct grid_square);
 
887
    grid->nsquares = 0;
 
888
    enum_grid_squares(params, add_grid_square_callback, grid);
 
889
    assert(grid->nsquares == area);
 
890
    state->grid = grid;
 
891
    grid->refcount = 1;
879
892
 
880
893
    state->facecolours = snewn(state->solid->nfaces, int);
881
894
    memset(state->facecolours, 0, state->solid->nfaces * sizeof(int));
882
895
 
 
896
    state->bluemask = snewn((state->grid->nsquares + 31) / 32, unsigned long);
 
897
    memset(state->bluemask, 0, (state->grid->nsquares + 31) / 32 *
 
898
           sizeof(unsigned long));
 
899
 
883
900
    /*
884
901
     * Set up the blue squares and polyhedron position according to
885
902
     * the game description.
890
907
 
891
908
        j = 8;
892
909
        v = 0;
893
 
        for (i = 0; i < state->nsquares; i++) {
 
910
        for (i = 0; i < state->grid->nsquares; i++) {
894
911
            if (j == 8) {
895
912
                v = *p++;
896
913
                if (v >= '0' && v <= '9')
903
920
                    break;
904
921
            }
905
922
            if (v & j)
906
 
                state->squares[i].blue = TRUE;
 
923
                SET_SQUARE(state, i, TRUE);
907
924
            j >>= 1;
908
925
            if (j == 0)
909
926
                j = 8;
913
930
            p++;
914
931
 
915
932
        state->current = atoi(p);
916
 
        if (state->current < 0 || state->current >= state->nsquares)
 
933
        if (state->current < 0 || state->current >= state->grid->nsquares)
917
934
            state->current = 0;        /* got to do _something_ */
918
935
    }
919
936
 
925
942
        int pkey[4];
926
943
        int ret;
927
944
 
928
 
        ret = align_poly(state->solid, &state->squares[state->current], pkey);
 
945
        ret = align_poly(state->solid, &state->grid->squares[state->current], pkey);
929
946
        assert(ret);
930
947
 
931
948
        state->dpkey[0] = state->spkey[0] = pkey[0];
951
968
    ret->facecolours = snewn(ret->solid->nfaces, int);
952
969
    memcpy(ret->facecolours, state->facecolours,
953
970
           ret->solid->nfaces * sizeof(int));
954
 
    ret->nsquares = state->nsquares;
955
971
    ret->current = state->current;
956
 
    ret->squares = snewn(ret->nsquares, struct grid_square);
957
 
    memcpy(ret->squares, state->squares,
958
 
           ret->nsquares * sizeof(struct grid_square));
 
972
    ret->grid = state->grid;
 
973
    ret->grid->refcount++;
 
974
    ret->bluemask = snewn((ret->grid->nsquares + 31) / 32, unsigned long);
 
975
    memcpy(ret->bluemask, state->bluemask, (ret->grid->nsquares + 31) / 32 *
 
976
           sizeof(unsigned long));
959
977
    ret->dpkey[0] = state->dpkey[0];
960
978
    ret->dpkey[1] = state->dpkey[1];
961
979
    ret->dgkey[0] = state->dgkey[0];
974
992
 
975
993
static void free_game(game_state *state)
976
994
{
977
 
    sfree(state->squares);
 
995
    if (--state->grid->refcount <= 0) {
 
996
        sfree(state->grid->squares);
 
997
        sfree(state->grid);
 
998
    }
978
999
    sfree(state->facecolours);
979
1000
    sfree(state);
980
1001
}
985
1006
    return NULL;
986
1007
}
987
1008
 
 
1009
static int game_can_format_as_text_now(game_params *params)
 
1010
{
 
1011
    return TRUE;
 
1012
}
 
1013
 
988
1014
static char *game_text_format(game_state *state)
989
1015
{
990
1016
    return NULL;
1031
1057
     * Find the two points in the current grid square which
1032
1058
     * correspond to this move.
1033
1059
     */
1034
 
    mask = from->squares[from->current].directions[direction];
 
1060
    mask = from->grid->squares[from->current].directions[direction];
1035
1061
    if (mask == 0)
1036
1062
        return -1;
1037
 
    for (i = j = 0; i < from->squares[from->current].npoints; i++)
 
1063
    for (i = j = 0; i < from->grid->squares[from->current].npoints; i++)
1038
1064
        if (mask & (1 << i)) {
1039
 
            points[j*2] = from->squares[from->current].points[i*2];
1040
 
            points[j*2+1] = from->squares[from->current].points[i*2+1];
 
1065
            points[j*2] = from->grid->squares[from->current].points[i*2];
 
1066
            points[j*2+1] = from->grid->squares[from->current].points[i*2+1];
1041
1067
            skey[j] = i;
1042
1068
            j++;
1043
1069
        }
1048
1074
     * This is our move destination.
1049
1075
     */
1050
1076
    dest = -1;
1051
 
    for (i = 0; i < from->nsquares; i++)
 
1077
    for (i = 0; i < from->grid->nsquares; i++)
1052
1078
        if (i != from->current) {
1053
1079
            int match = 0;
1054
1080
            float dist;
1055
1081
 
1056
 
            for (j = 0; j < from->squares[i].npoints; j++) {
1057
 
                dist = (SQ(from->squares[i].points[j*2] - points[0]) +
1058
 
                        SQ(from->squares[i].points[j*2+1] - points[1]));
 
1082
            for (j = 0; j < from->grid->squares[i].npoints; j++) {
 
1083
                dist = (SQ(from->grid->squares[i].points[j*2] - points[0]) +
 
1084
                        SQ(from->grid->squares[i].points[j*2+1] - points[1]));
1059
1085
                if (dist < 0.1)
1060
1086
                    dkey[match++] = j;
1061
 
                dist = (SQ(from->squares[i].points[j*2] - points[2]) +
1062
 
                        SQ(from->squares[i].points[j*2+1] - points[3]));
 
1087
                dist = (SQ(from->grid->squares[i].points[j*2] - points[2]) +
 
1088
                        SQ(from->grid->squares[i].points[j*2+1] - points[3]));
1063
1089
                if (dist < 0.1)
1064
1090
                    dkey[match++] = j;
1065
1091
            }
1110
1136
        int cx, cy;
1111
1137
        double angle;
1112
1138
 
1113
 
        cx = state->squares[state->current].x * GRID_SCALE + ds->ox;
1114
 
        cy = state->squares[state->current].y * GRID_SCALE + ds->oy;
 
1139
        cx = (int)(state->grid->squares[state->current].x * GRID_SCALE) + ds->ox;
 
1140
        cy = (int)(state->grid->squares[state->current].y * GRID_SCALE) + ds->oy;
1115
1141
 
1116
1142
        if (x == cx && y == cy)
1117
1143
            return NULL;               /* clicked in exact centre!  */
1136
1162
         * x-axis, not anticlockwise as most mathematicians would
1137
1163
         * instinctively assume.
1138
1164
         */
1139
 
        if (state->squares[state->current].npoints == 4) {
 
1165
        if (state->grid->squares[state->current].npoints == 4) {
1140
1166
            /* Square. */
1141
1167
            if (fabs(angle) > 3*PI/4)
1142
1168
                direction = LEFT;
1146
1172
                direction = DOWN;
1147
1173
            else
1148
1174
                direction = UP;
1149
 
        } else if (state->squares[state->current].directions[UP] == 0) {
 
1175
        } else if (state->grid->squares[state->current].directions[UP] == 0) {
1150
1176
            /* Up-pointing triangle. */
1151
1177
            if (angle < -PI/2 || angle > 5*PI/6)
1152
1178
                direction = LEFT;
1156
1182
                direction = RIGHT;
1157
1183
        } else {
1158
1184
            /* Down-pointing triangle. */
1159
 
            assert(state->squares[state->current].directions[DOWN] == 0);
 
1185
            assert(state->grid->squares[state->current].directions[DOWN] == 0);
1160
1186
            if (angle > PI/2 || angle < -5*PI/6)
1161
1187
                direction = LEFT;
1162
1188
            else if (angle < -PI/6)
1167
1193
    } else
1168
1194
        return NULL;
1169
1195
 
1170
 
    mask = state->squares[state->current].directions[direction];
 
1196
    mask = state->grid->squares[state->current].directions[direction];
1171
1197
    if (mask == 0)
1172
1198
        return NULL;
1173
1199
 
1176
1202
     */
1177
1203
    if (direction > DOWN) {
1178
1204
        for (i = LEFT; i <= DOWN; i++)
1179
 
            if (state->squares[state->current].directions[i] == mask) {
 
1205
            if (state->grid->squares[state->current].directions[i] == mask) {
1180
1206
                direction = i;
1181
1207
                break;
1182
1208
            }
1232
1258
     */
1233
1259
    {
1234
1260
        int all_pkey[4];
1235
 
        align_poly(from->solid, &from->squares[from->current], all_pkey);
 
1261
        align_poly(from->solid, &from->grid->squares[from->current], all_pkey);
1236
1262
        pkey[0] = all_pkey[skey[0]];
1237
1263
        pkey[1] = all_pkey[skey[1]];
1238
1264
        /*
1292
1318
            angle = -angle;            /* HACK */
1293
1319
 
1294
1320
        poly = transform_poly(from->solid,
1295
 
                              from->squares[from->current].flip,
 
1321
                              from->grid->squares[from->current].flip,
1296
1322
                              pkey[0], pkey[1], angle);
1297
 
        flip_poly(poly, from->squares[ret->current].flip);
1298
 
        success = align_poly(poly, &from->squares[ret->current], all_pkey);
 
1323
        flip_poly(poly, from->grid->squares[ret->current].flip);
 
1324
        success = align_poly(poly, &from->grid->squares[ret->current], all_pkey);
1299
1325
 
1300
1326
        if (!success) {
1301
1327
            sfree(poly);
1302
1328
            angle = -angle;
1303
1329
            poly = transform_poly(from->solid,
1304
 
                                  from->squares[from->current].flip,
 
1330
                                  from->grid->squares[from->current].flip,
1305
1331
                                  pkey[0], pkey[1], angle);
1306
 
            flip_poly(poly, from->squares[ret->current].flip);
1307
 
            success = align_poly(poly, &from->squares[ret->current], all_pkey);
 
1332
            flip_poly(poly, from->grid->squares[ret->current].flip);
 
1333
            success = align_poly(poly, &from->grid->squares[ret->current], all_pkey);
1308
1334
        }
1309
1335
 
1310
1336
        assert(success);
1370
1396
    if (!ret->completed) {
1371
1397
        i = lowest_face(from->solid);
1372
1398
        j = ret->facecolours[i];
1373
 
        ret->facecolours[i] = ret->squares[ret->current].blue;
1374
 
        ret->squares[ret->current].blue = j;
 
1399
        ret->facecolours[i] = GET_SQUARE(ret, ret->current);
 
1400
        SET_SQUARE(ret, ret->current, j);
1375
1401
 
1376
1402
        /*
1377
1403
         * Detect game completion.
1394
1420
        int pkey[4];
1395
1421
        int success;
1396
1422
 
1397
 
        success = align_poly(ret->solid, &ret->squares[ret->current], pkey);
 
1423
        success = align_poly(ret->solid, &ret->grid->squares[ret->current], pkey);
1398
1424
        assert(success);
1399
1425
 
1400
1426
        ret->dpkey[0] = pkey[0];
1471
1497
{
1472
1498
    struct bbox bb = find_bbox(params);
1473
1499
 
1474
 
    ds->gridscale = tilesize;
 
1500
    ds->gridscale = (float)tilesize;
1475
1501
    ds->ox = (int)(-(bb.l - solids[params->solid]->border) * ds->gridscale);
1476
1502
    ds->oy = (int)(-(bb.u - solids[params->solid]->border) * ds->gridscale);
1477
1503
}
1498
1524
{
1499
1525
    struct game_drawstate *ds = snew(struct game_drawstate);
1500
1526
 
1501
 
    ds->ox = ds->oy = ds->gridscale = 0.0F;/* not decided yet */
 
1527
    ds->ox = ds->oy = 0;
 
1528
    ds->gridscale = 0.0F; /* not decided yet */
1502
1529
 
1503
1530
    return ds;
1504
1531
}
1555
1582
    newstate = state;
1556
1583
    state = oldstate;
1557
1584
 
1558
 
    for (i = 0; i < state->nsquares; i++) {
 
1585
    for (i = 0; i < state->grid->nsquares; i++) {
1559
1586
        int coords[8];
1560
1587
 
1561
 
        for (j = 0; j < state->squares[i].npoints; j++) {
1562
 
            coords[2*j] = ((int)(state->squares[i].points[2*j] * GRID_SCALE)
 
1588
        for (j = 0; j < state->grid->squares[i].npoints; j++) {
 
1589
            coords[2*j] = ((int)(state->grid->squares[i].points[2*j] * GRID_SCALE)
1563
1590
                           + ds->ox);
1564
 
            coords[2*j+1] = ((int)(state->squares[i].points[2*j+1]*GRID_SCALE)
 
1591
            coords[2*j+1] = ((int)(state->grid->squares[i].points[2*j+1]*GRID_SCALE)
1565
1592
                             + ds->oy);
1566
1593
        }
1567
1594
 
1568
 
        draw_polygon(dr, coords, state->squares[i].npoints,
1569
 
                     state->squares[i].blue ? COL_BLUE : COL_BACKGROUND,
 
1595
        draw_polygon(dr, coords, state->grid->squares[i].npoints,
 
1596
                     GET_SQUARE(state, i) ? COL_BLUE : COL_BACKGROUND,
1570
1597
                     COL_BORDER);
1571
1598
    }
1572
1599
 
1573
1600
    /*
1574
1601
     * Now compute and draw the polyhedron.
1575
1602
     */
1576
 
    poly = transform_poly(state->solid, state->squares[square].flip,
 
1603
    poly = transform_poly(state->solid, state->grid->squares[square].flip,
1577
1604
                          pkey[0], pkey[1], angle);
1578
1605
 
1579
1606
    /*
1589
1616
 
1590
1617
            if (i < 2) {
1591
1618
                grid_coord =
1592
 
                    state->squares[square].points[gkey[j]*2+i];
 
1619
                    state->grid->squares[square].points[gkey[j]*2+i];
1593
1620
            } else {
1594
1621
                grid_coord = 0.0;
1595
1622
            }
1715
1742
    dup_game,
1716
1743
    free_game,
1717
1744
    FALSE, solve_game,
1718
 
    FALSE, game_text_format,
 
1745
    FALSE, game_can_format_as_text_now, game_text_format,
1719
1746
    new_ui,
1720
1747
    free_ui,
1721
1748
    encode_ui,