Sample Solving Program

remzi
Posts: 1
Joined: Sat Apr 18, 2009 1:21 pm

Post by remzi »

im new at this to how should i start with
kenan
Posts: 1
Joined: Sat Oct 17, 2009 4:52 pm
Location: china
Contact:

Post by kenan »

I COME FROM CHINA
中国人
User avatar
laz0r
Posts: 290
Joined: Thu Feb 04, 2010 4:18 pm
Location: Within the depths of Unix

Post by laz0r »

Sorry if I'm being stupid, but surely since boardX is initialised to -1, then in findSolutionPath, the line

Code: Select all

startX = r.nextInt(boardX);
is going to throw an error? (trying to get the next random number with a negative seed)
There is no spoon.
User avatar
CodeX
Posts: 350
Joined: Fri Oct 17, 2008 5:28 pm

Post by CodeX »

The initial value of boardX is 0 (by default), -1 is assigned to StartX & StartY. boardX is also assigned before it gets to it's first use so it doesn't have to rely on the default unless a bad username/pass is used as the flow goes main->go->input2level<assignment here>->solve, with an invalid username or password the result of the query to the website is "invalid user" or "invalid password" so the loop that looks through the response wont find the key line which it assigns the values by so if it were to get to a random.nextInt(int) the worst you can get is r.nextInt(0) which I think returns 0.
User avatar
laz0r
Posts: 290
Joined: Thu Feb 04, 2010 4:18 pm
Location: Within the depths of Unix

Post by laz0r »

Ah, thanks!
There is no spoon.
Bliss
Posts: 10
Joined: Sat Oct 02, 2010 8:23 pm

Re: Sample Solving Program

Post by Bliss »

adum wrote:i have written a small and simple Java program to demonstrate how an automatic solver works for the Mortal Coil game. this also features automatic puzzle retrieval and submission (just enter name and pw as command line params). of course, the algorithm isn't the fastest! =)

Code: Select all

import java.io.*;
import java.net.URL;
import java.util.Random;

// program to solve the puzzle at http://www.hacker.org/coil/
public class MortalCoilSolver {
    private static int[][] offsets = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    private static char[] offNames = {'L', 'D', 'R', 'U'};
    private Random r = new Random();
    private static String name, pw;
    private int targetFill, boardX, boardY, startX = -1, startY = -1, board[][];
    private String boardString;

    public static void main(String[] args) throws Exception {
        if (args.length != 2) {
            System.out.println("usage:\nMortalCoilSolver name pw\n");
            return;
        }
        name = args[0]; pw = args[1];
        MortalCoilSolver mcs = new MortalCoilSolver();
        while (true) {
            mcs.go();
            Thread.sleep(2000);
        }
    }

    private void go() throws Exception {
        URL u;
        u = new URL("http://www.hacker.org/coil/index.php?name=" + name + "&password=" + pw);
        InputStream is = u.openStream();
        input2level(is);
        System.out.println(this);
        solve();
    }

    public String toString() {
        String s = "";
        for (int j = 0; j < boardY; j++) {
            for (int i = 0; i < boardX; i++) {
                s += board[i][j] > 0 ? 'X' : '.';
            }
            if (j < boardY - 1) s += '\n';
        }
        return s;
    }

    public boolean solve() throws Exception {
        String path = findSolutionPath();
        System.out.println("solved at (" + startX + ", " + startY + ") : " + path);
        URL u;
        u = new URL("http://www.hacker.org/coil/index.php?name=" + name + 
                "&password=" + pw + "&path=" + path + "&x=" + startX + "&y=" + startY);
        InputStream is = u.openStream();
        BufferedReader in = new BufferedReader(new InputStreamReader(is));
        while ((in.readLine()) != null) { }
        is.close();
        return false;
    }
    
    private String findSolutionPath() {
        while (true) { // search until done
            parseBoardString(); // reset board
            startX = r.nextInt(boardX); startY = r.nextInt(boardY); // random start
            if (!goodSquare(startX, startY)) continue;
            int x = startX, y = startY, fill = 1;
            String path = ""; // remember our path
            loop: while (true) {
                int tdir = r.nextInt(4); // choose random direction
                for (int dloop = 0; dloop < 3; dloop++) {
                    int dir = (dloop + tdir) % 4;
                    int offx = offsets[dir][0];
                    int offy = offsets[dir][1];
                    if (!goodSquare(x + offx, y + offy)) continue; // blocked
                    path += offNames[dir];
                    while (true) { // move until we hit something
                        board[x][y] = 2;
                        x += offx; y += offy;
                        if (!goodSquare(x, y)) break;
                        if (++fill == targetFill) return path; // got it
                    }
                    x -= offx; y -= offy; // we went one too far!
                    continue loop;
                }
                break;
            }
        }
    }
    
    private boolean goodSquare(int x, int y) {
        if (x < 0 || y < 0 || x >= boardX || y >= boardY) return false;
        return (board[x][y] == 0);
    }
    
    private void input2level(InputStream is) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(is));
        String line;
        while ((line = in.readLine()) != null) {
            if (!line.startsWith("    <param name="FlashVars"")) continue;
            line = line.split(""")[3]; // get just the value
            String[] ss = line.split("(=|&)"); // split up the name value pairs
            boardX = Integer.parseInt(ss[1]); boardY = Integer.parseInt(ss[3]);
            board = new int[boardX][boardY];
            boardString = ss[5];
            parseBoardString();
        }
        in.close();
    }

    private void parseBoardString() {
        int cnt = 0;
        for (int x = 0; x < boardX; x++)
            for (int y = 0; y < boardY; y++) {
                int a = boardString.charAt(x + y * boardX) == 'X' ? 1 : 0;
                board[x][y] = a;
                cnt += a;
            }
        targetFill = (boardX * boardY) - cnt; // how many squares we need to fill
    }
}
Just wanted to ask in which line do we put the params name and password ?? I am confused :S
Shoud we make another class and run mcs from it ?
Truly yours
User avatar
CodeX
Posts: 350
Joined: Fri Oct 17, 2008 5:28 pm

Post by CodeX »

The username and password aren't hardcoded, they are passed via the command line (inside the main method, line 19) into the class' name and pw variables (defined on line 10), these are then used in the solve and go methods which in turn pass data to the server via GET.
Hooray for having a quick look at the code
Post Reply