Skip to content

Commit

Permalink
Pulled in Chen Shuang's skewb support! There's also more aggressive s…
Browse files Browse the repository at this point in the history
…q1 filtering in here.
  • Loading branch information
jfly committed Dec 28, 2013
1 parent 4236f1e commit c89b791
Show file tree
Hide file tree
Showing 9 changed files with 714 additions and 42 deletions.
6 changes: 4 additions & 2 deletions scrambler-interface/WebContent/scrambler-interface/js/ui.js
Expand Up @@ -359,7 +359,8 @@ var mark2 = {};
"777": {name: "7x7x7 Cube", default_round: {type: "mean", num_scrambles: 3, num_extra_scrambles: extraScrambles } },
"444bf": {name: "4x4x4 Cube: Blindfolded", default_round: {type: "best", num_scrambles: 3, num_extra_scrambles: extraScrambles } },
"555bf": {name: "5x5x5 Cube: Blindfolded", default_round: {type: "best", num_scrambles: 3, num_extra_scrambles: extraScrambles } },
"333mbf": {name: "3x3x3: Multiple Blindfolded", default_round: {type: "mbf", num_scrambles: 28 } }
"333mbf": {name: "3x3x3: Multiple Blindfolded", default_round: {type: "mbf", num_scrambles: 28 } },
"skewb": {name: "Skewb", default_round: {type: "avg", num_scrambles: 5, num_extra_scrambles: extraScrambles } }
};

// Javascript objects don't retain key order in all browsers, so we create this list for iteration.
Expand All @@ -380,7 +381,8 @@ var mark2 = {};
"clock",
"444bf",
"555bf",
"333mbf"
"333mbf",
"skewb"
];

function isFmc(eventID) {
Expand Down
270 changes: 270 additions & 0 deletions scrambles/src/puzzle/SkewbPuzzle.java
@@ -0,0 +1,270 @@
package puzzle;

import static net.gnehzr.tnoodle.utils.GwtSafeUtils.azzert;

import net.gnehzr.tnoodle.svglite.Color;
import net.gnehzr.tnoodle.svglite.Svg;
import net.gnehzr.tnoodle.svglite.Dimension;
import net.gnehzr.tnoodle.svglite.Path;
import net.gnehzr.tnoodle.svglite.Transform;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;
import java.util.logging.Logger;

import puzzle.SkewbSolver.SkewbSolverState;

import net.gnehzr.tnoodle.scrambles.InvalidScrambleException;
import net.gnehzr.tnoodle.scrambles.Puzzle;
import net.gnehzr.tnoodle.scrambles.PuzzleStateAndGenerator;
import net.gnehzr.tnoodle.utils.GwtSafeUtils;

import org.timepedia.exporter.client.Export;

@Export
public class SkewbPuzzle extends Puzzle {
private static final int MIN_SCRAMBLE_LENGTH = 9;
private static final Logger l = Logger.getLogger(SkewbPuzzle.class.getName());
private SkewbSolver skewbSolver = null;

private static final int pieceSize = 30;
private static final int gap = 3;

private static final double sq3d2 = Math.sqrt(3) / 2;

public SkewbPuzzle() {
skewbSolver = new SkewbSolver();
wcaMinScrambleDistance = 4;
}

@Override
public PuzzleStateAndGenerator generateRandomMoves(Random r) {
SkewbSolverState state = skewbSolver.randomState(r);
String scramble = skewbSolver.generateExactly(state, MIN_SCRAMBLE_LENGTH);

PuzzleState pState;
try {
pState = getSolvedState().applyAlgorithm(scramble);
} catch (InvalidScrambleException e) {
azzert(false, e);
return null;
}
return new PuzzleStateAndGenerator(pState, scramble);
}

/*************************************************************
* Functions to display the puzzle
*/


private static final HashMap<String, Color> defaultColorScheme = new HashMap<String, Color>();
static {
defaultColorScheme.put("U", Color.WHITE);
defaultColorScheme.put("R", Color.BLUE);
defaultColorScheme.put("F", Color.RED);
defaultColorScheme.put("D", Color.YELLOW);
defaultColorScheme.put("L", Color.GREEN);
defaultColorScheme.put("B", new Color(0xFF8000));
}

@Override
public HashMap<String, Color> getDefaultColorScheme() {
return new HashMap<String, Color>(defaultColorScheme);
}

private Transform[] getFaceTrans() {
Transform[] position = {
new Transform(pieceSize*sq3d2, -pieceSize/2, pieceSize*sq3d2, pieceSize/2, (pieceSize*4+gap*1.5)*sq3d2, pieceSize),
new Transform(pieceSize*sq3d2, -pieceSize/2, 0, pieceSize, (pieceSize*7+gap*3)*sq3d2, pieceSize * 1.5),
new Transform(pieceSize*sq3d2, -pieceSize/2, 0, pieceSize, (pieceSize*5+gap*2)*sq3d2, pieceSize * 2.5 + 0.5 * gap),
new Transform(0, pieceSize, -pieceSize*sq3d2, -pieceSize/2, (pieceSize*3+gap*1)*sq3d2, pieceSize * 4.5 + 1.5 * gap),
new Transform(pieceSize*sq3d2, pieceSize/2, 0, pieceSize, (pieceSize*3+gap*1)*sq3d2, pieceSize * 2.5 + 0.5 * gap),
new Transform(pieceSize*sq3d2, pieceSize/2, 0, pieceSize, pieceSize*sq3d2, pieceSize * 1.5),
};
return position;
}

@Override
public Dimension getPreferredSize() {
return new Dimension(
(int) Math.ceil((3 * gap + 8 * pieceSize + 1) * sq3d2),
(int) Math.ceil(2 * gap + 6 * pieceSize + 1));
}

@Override
public String getLongName() {
return "Skewb";
}

@Override
public String getShortName() {
return "skewb";
}

@Override
public PuzzleState getSolvedState() {
return new SkewbState();
}

@Override
protected int getRandomMoveCount() {
return 15;
}

public class SkewbState extends PuzzleState {

/**
* +---------+
* | 1 2 |
* U > | 0-0 |
* | 3 4 |
* +---------+---------+---------+---------+
* | 1 2 | 1 2 | 1 2 | 1 2 |
* | 4-0 | 2-0 | 1-0 | 5-0 |
* | 3 4 | 3 4 | 3 4 | 3 4 |
* +---------+---------+---------+---------+
* ^ | 1 2 |
* FL | 3-0 |
* | 3 4 |
* +---------+
*/
private int[][] image = new int[6][5];

SkewbState() {
for (int i=0; i<6; i++) {
for (int j=0; j<5; j++) {
image[i][j] = i;
}
}
}

SkewbState(int[][] _image) {
for (int i=0; i<6; i++) {
for (int j=0; j<5; j++) {
image[i][j] = _image[i][j];
}
}
}

private void turn(int axis, int pow, int[][] image) {
//axis:0-R 1-U 2-L 3-B
for (int p=0; p<pow; p++) {
switch (axis) {
case 0:
swap(2, 0, 3, 0, 1, 0, image);
swap(2, 4, 3, 2, 1, 3, image);
swap(2, 2, 3, 1, 1, 4, image);
swap(2, 3, 3, 4, 1, 1, image);
swap(4, 4, 5, 3, 0, 4, image);
break;
case 1:
swap(0, 0, 1, 0, 5, 0, image);
swap(0, 2, 1, 2, 5, 1, image);
swap(0, 4, 1, 4, 5, 2, image);
swap(0, 1, 1, 1, 5, 3, image);
swap(4, 1, 2, 2, 3, 4, image);
break;
case 2:
swap(4, 0, 5, 0, 3, 0, image);
swap(4, 3, 5, 4, 3, 3, image);
swap(4, 1, 5, 3, 3, 1, image);
swap(4, 4, 5, 2, 3, 4, image);
swap(2, 3, 0, 1, 1, 4, image);
break;
case 3:
swap(1, 0, 3, 0, 5, 0, image);
swap(1, 4, 3, 4, 5, 3, image);
swap(1, 3, 3, 3, 5, 1, image);
swap(1, 2, 3, 2, 5, 4, image);
swap(0, 2, 2, 4, 4, 3, image);
break;
default:
azzert(false);
}
}
}

private void swap(int f1, int s1, int f2, int s2, int f3, int s3, int[][] image) {
int temp = image[f1][s1];
image[f1][s1] = image[f2][s2];
image[f2][s2] = image[f3][s3];
image[f3][s3] = temp;
}

/**
* return a square skewb face. whose 4 corners are (-1, -1), (1, -1), (1, 1), (-1, 1). It will be transformed later.
*/
private Path[] getFacePaths() {
Path[] p = new Path[5];
for (int i=0; i<5; i++) {
p[i] = new Path();
// In svg, by default, borders are scaled along with shapes.
// Setting vector-effect to non-scaling-stroke disables that.
// Unfortunately, batik doesn't support it, so we have
// to do something hacky by explicitly setting the
// stroke-width to something teeny.
// If Batik ever changes to support vector-effect, we
// can clean this up.
//p[i].setAttribute("vector-effect", "non-scaling-stroke");
p[i].setAttribute("stroke-width", 1.0/pieceSize + "px");
}
p[0].moveTo(-1, 0); p[0].lineTo( 0, 1); p[0].lineTo( 1, 0); p[0].lineTo(0,-1); p[0].closePath();
p[1].moveTo(-1, 0); p[1].lineTo(-1,-1); p[1].lineTo( 0,-1); p[1].closePath();
p[2].moveTo( 0,-1); p[2].lineTo( 1,-1); p[2].lineTo( 1, 0); p[2].closePath();
p[3].moveTo(-1, 0); p[3].lineTo(-1, 1); p[3].lineTo( 0, 1); p[3].closePath();
p[4].moveTo( 0, 1); p[4].lineTo( 1, 1); p[4].lineTo( 1, 0); p[4].closePath();
return p;
}

protected Svg drawScramble(HashMap<String, Color> colorScheme) {
Svg g = new Svg(getPreferredSize());
Color[] scheme = new Color[6];
for(int i = 0; i < scheme.length; i++) {
scheme[i] = colorScheme.get("URFDLB".charAt(i)+"");
}
Transform[] position = getFaceTrans();
for (int face=0; face<6; face++) {
Path[] p = getFacePaths();
for (int i=0; i<5; i++) {
p[i].transform(position[face]);
p[i].setFill(scheme[image[face][i]]);
p[i].setStroke(Color.BLACK);
g.appendChild(p[i]);
}
}
return g;
}

public HashMap<String, PuzzleState> getSuccessors() {
HashMap<String, PuzzleState> successors = new HashMap<String, PuzzleState>();
String axes = "RULB";
for(int axis = 0; axis < axes.length(); axis++) {
char face = axes.charAt(axis);
for(int pow = 1; pow <= 2; pow++) {
String turn = "" + face;
if(pow == 2) {
turn += "'";
}
int[][] imageCopy = new int[image.length][image[0].length];
GwtSafeUtils.deepCopy(image, imageCopy);
turn(axis, pow, imageCopy);
successors.put(turn, new SkewbState(imageCopy));
}
}

return successors;
}

@Override
public boolean equals(Object other) {
// Sure this could blow up with a cast exception, but shouldn't it? =)
return Arrays.deepEquals(image, ((SkewbState) other).image);
}

@Override
public int hashCode() {
return Arrays.deepHashCode(image);
}
}

}

0 comments on commit c89b791

Please sign in to comment.