forked from brownan/Rubiks-Cube-Solver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.c
173 lines (163 loc) · 5.93 KB
/
common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
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 <http://www.gnu.org/licenses/>.
Copyright © 2009 Andrew Brown <[email protected]>
*/
#include <stdio.h>
#include "common.h"
#include "cube.h"
/*
* common.c has methods used by more than one function
*/
/*
* Whichpos takes a 6 character string from the old 120 byte cube
* representation and determines which of the twenty cubies it is by looking at
* the signature of 'n's it has
*
* This method is costly, the huge number of tiny branches probably kill the
* processor pipeline.
*
* This method used to be used in the main loop, called from the hashing
* functions, but has since been obsoleted by adding a position byte to each
* cubie in the cube representation string.
* This method is still useful to convert the old 120 byte strings to the newer
* format.
*
*/
int whichpos(const char *cubie)
{
/* Takes a 6 character cubie string and returns which cubie it is,
* one through twenty. cubie is NOT null terminated (this func only
* touches the first 6 chars)
* */
int ns[4] = {-1,-1,-1,-1};
int i, j=0;
for (i=0; i<6; i++) {
if (cubie[i] == 'n')
ns[j++] = i;
}
/* Just a big if statement will suffice: */
if (ns[0]==0 && ns[1]==1 && ns[2]==5 && ns[3]==-1)
return 0;
else if (ns[0]==0 && ns[1]==1 && ns[2]==2 && ns[3]==5)
return 1;
else if (ns[0]==0 && ns[1]==1 && ns[2]==2 && ns[3]==-1)
return 2;
else if (ns[0]==0 && ns[1]==1 && ns[2]==4 && ns[3]==5)
return 3;
else if (ns[0]==0 && ns[1]==1 && ns[2]==2 && ns[3]==4)
return 4;
else if (ns[0]==0 && ns[1]==4 && ns[2]==5 && ns[3]==-1)
return 5;
else if (ns[0]==0 && ns[1]==2 && ns[2]==4 && ns[3]==5)
return 6;
else if (ns[0]==0 && ns[1]==2 && ns[2]==4 && ns[3]==-1)
return 7;
else if (ns[0]==0 && ns[1]==1 && ns[2]==3 && ns[3]==5)
return 8;
else if (ns[0]==0 && ns[1]==1 && ns[2]==2 && ns[3]==3)
return 9;
else if (ns[0]==0 && ns[1]==3 && ns[2]==4 && ns[3]==5)
return 10;
else if (ns[0]==0 && ns[1]==2 && ns[2]==3 && ns[3]==4)
return 11;
else if (ns[0]==1 && ns[1]==3 && ns[2]==5 && ns[3]==-1)
return 12;
else if (ns[0]==1 && ns[1]==2 && ns[2]==3 && ns[3]==5)
return 13;
else if (ns[0]==1 && ns[1]==2 && ns[2]==3 && ns[3]==-1)
return 14;
else if (ns[0]==1 && ns[1]==3 && ns[2]==4 && ns[3]==5)
return 15;
else if (ns[0]==1 && ns[1]==2 && ns[2]==3 && ns[3]==4)
return 16;
else if (ns[0]==3 && ns[1]==4 && ns[2]==5 && ns[3]==-1)
return 17;
else if (ns[0]==2 && ns[1]==3 && ns[2]==4 && ns[3]==5)
return 18;
else if (ns[0]==2 && ns[1]==3 && ns[2]==4 && ns[3]==-1)
return 19;
fprintf(stderr, "WARNING, SOMETHING HAS GONE TERRIBLLY WRONG IN WHICHPOS %d\n", __LINE__);
fprintf(stderr, "%.6s\n", cubie);
fprintf(stderr, "%d, %d, %d, %d\n", ns[0], ns[1], ns[2], ns[3]);
return -1;
}
/*
* Whichrot takes a 6 character string and determines what its rotation is.
* See cube.h for information on how cubie rotations are defined
*
* This is also expensive, should not be called in main loop
*/
int whichrot(const char *cubie)
{
char cols[2]; /* used for edge cubies */
char tmp;
int i, j;
int pos = whichpos(cubie);
if (pos == 0 || pos == 2 || pos == 5 || pos == 7 ||
pos == 12 || pos == 14 || pos == 17 || pos == 19) {
/* Corner cubie */
if (cubie[FRONT] == 'w' || cubie[FRONT] == 'y' ||
cubie[BACK] == 'w' || cubie[BACK] == 'y') {
return 0;
} else if (cubie[LEFT] == 'w' || cubie[LEFT] == 'y' ||
cubie[RIGHT] == 'w' || cubie[RIGHT] == 'y') {
return 1;
} else if (cubie[TOP] == 'w' || cubie[TOP] == 'y' ||
cubie[DOWN] == 'w' || cubie[DOWN] == 'y') {
return 2;
} else {
fprintf(stderr, "Caution: whichrot error %d\n", __LINE__);
return -1;
}
} else {
/* Edge cubie */
j=0;
for (i=0; i<6; ++i){
if (cubie[i] != 'n') {
cols[j++] = cubie[i];
}
}
/*
* Put white or yellow in the first col.
* If there's no white or yellow, put blue or green first
*/
if (cols[1] == 'w' || cols[1] == 'y') {
tmp = cols[1];
cols[1] = cols[0];
cols[0] = tmp;
} else if ((cols[0] != 'w' && cols[0] != 'y') &&
(cols[1] == 'b' || cols[1] == 'g')) {
tmp = cols[1];
cols[1] = cols[0];
cols[0] = tmp;
}
/*
* white/yellow case
* if white/yellow is on the front or back, or if the other color is
* on the top or bottom, we know it's oriented 0
* otherwise, 1
*
* For the last four edge cubies (the four that don't have white or
* yellow on them) we check to see if green/blue is on the front or
* back, or if the other color is on the top or bottom. Then it's
* 0.
*
* Thanks to the re-ordering done above, it's the same check:
*/
if (cubie[TOP] == cols[1] || cubie[DOWN] == cols[1] ||
cubie[FRONT] == cols[0] || cubie[BACK] == cols[0]) {
return 0;
} else {
return 1;
}
}
}