private static double[][] genMatrix(int diceSides) {
        double[][] matrix = new double[BOARD_SIZE][BOARD_SIZE];

        double[] roleProb = getRoleProb(diceSides);
        for (int i = 0;i< BOARD_SIZE;i++) {
            for (int j = 0;j< roleProb.length;j++)
                matrix[i][(i + j + 1) % BOARD_SIZE] = roleProb[j];

            //Fix 3 doubles
            matrix[i][JAIL] += (1.0/diceSides)*(1.0/diceSides)*(1.0/diceSides);
            for (int j = 1;j< roleProb.length;j+=2) {
                // 1 - (1/ (#sides^2 * prob(j)) * (1/ #sides)^2
                matrix[i][(i + j + 1) % BOARD_SIZE] *= 1.0 - (1.0/ (diceSides * diceSides * roleProb[j]) * (1.0/diceSides) * (1.0/diceSides));
            }


            //Fix Goto Jail
            matrix[i][JAIL] += matrix[i][GOTO_JAIL];
            matrix[i][GOTO_JAIL] = 0;

            //Fix Community Chest
            for (int cc : COMM_CHEST) {
                if (matrix[i][cc] > 0) {
                    matrix[i][GO] += matrix[i][cc] * 1.0/16;
                    matrix[i][JAIL] += matrix[i][cc] * 1.0/16;
                    matrix[i][cc] = matrix[i][cc] * 14.0/16; //Stay where we are.
                }
            }

            for (int ch : CHANCE) {
                if (matrix[i][ch] > 0) {
                    matrix[i][GO] += matrix[i][ch] * 1.0/16;
                    matrix[i][JAIL] += matrix[i][ch] * 1.0/16;
                    matrix[i][11] += matrix[i][ch] * 1.0/16;
                    matrix[i][24] += matrix[i][ch] * 1.0/16;
                    matrix[i][39] += matrix[i][ch] * 1.0/16;
                    matrix[i][5] += matrix[i][ch] * 1.0/16;
                    matrix[i][nextRR(ch)] += matrix[i][ch] * 2.0/16;
                    matrix[i][nextUtil(ch)] += matrix[i][ch] * 1.0/16;
                    matrix[i][ch-3] += matrix[i][ch] * 1.0/16;
                    matrix[i][ch] = matrix[i][ch] * 6.0/16; //Stay where we are.
                }
            }
        }

        return matrix;
    }