Retro Rocket ASCII Art Inspired by Nested for-loop ASCII art, I looked at building a more complicated ASCII art than just the normal 'diamond' and 'triangle' variations that crop up occasionally here.

The challenge: Produce the following rocket

     /**\
    //**\\
   ///**\\\
  ////**\\\\
 /////**\\\\\
+=*=*=*=*=*=*+
|../\..../\..|
|./\/\../\/\.|
|/\/\/\/\/\/\|
|\/\/\/\/\/\/|
|.\/\/..\/\/.|
|..\/....\/..|
+=*=*=*=*=*=*+
|\/\/\/\/\/\/|
|.\/\/..\/\/.|
|..\/....\/..|
|../\..../\..|
|./\/\../\/\.|
|/\/\/\/\/\/\|
+=*=*=*=*=*=*+
     /**\
    //**\\
   ///**\\\
  ////**\\\\
 /////**\\\\\


The question on Stack Overflow has issues, and those issues got answered before I could put a response together, but, the problem intrigued me, and I built the following code to solve it in a more compact way, using loops as much as possible, and parameterizing almost all aspects of the problem.

public class Rocket {

    private enum Direction {
        FORWARD, BACKWARD
    }

    private static final char NONE = (char) 0;

    private static final String buildSymmetrical(
            char[] chars, char mid, int from, int len) {

        StringBuilder sb = new StringBuilder(len * 2 + 2);
        for (int i = 0; i &lt; len; i++) {
            sb.append(chars[from + i]);
        }
        if (mid != NONE) {
            sb.append(mid).append(mid);
        }
        for (int i = 0; i &lt; len; i++) {
            sb.append(chars[chars.length - from - len + i]);
        }
        return sb.toString();
    }

    private static final String buildLines(
            char bracket, char[] source, int len, char midchar, int charfrom,
            Direction chardir, int linecount, int duplicates) {

        StringBuilder sb = new StringBuilder();
        for (int line = 0; line &lt; linecount; line++) {
            sb.append(bracket);
            int pos = charfrom + line * (chardir == Direction.FORWARD ? 1 : -1);
            String block = buildSymmetrical(source, midchar, pos, len);
            for (int d = 0; d &lt; duplicates; d++) {
                sb.append(block);
            }
            sb.append(bracket).append('\n');
        }
        return sb.toString();
    }

    public static final String buildRocket() {
        char[] wider = "../\\/\\/\\/\\..".toCharArray();
        char[] narrower = "..\\/\\/\\/\\/..".toCharArray();
        char[] cone = "    //////\\\\\\\\\\\\    ".toCharArray();
        char[] boundary = "+=*=*=*=*=*=*+\n".toCharArray();

        StringBuilder sb = new StringBuilder();
        sb.append(buildLines(' ', cone, 5, '*', 0, Direction.FORWARD, 5, 1));
        sb.append(boundary);
        sb.append(buildLines('|', wider, 3, NONE, 0, Direction.FORWARD, 3, 2));
        sb.append(buildLines('|', narrower, 3, NONE, 2, Direction.BACKWARD, 3, 2));
        sb.append(boundary);
        sb.append(buildLines('|', narrower, 3, NONE, 2, Direction.BACKWARD, 3, 2));
        sb.append(buildLines('|', wider, 3, NONE, 0, Direction.FORWARD, 3, 2));
        sb.append(boundary);
        sb.append(buildLines(' ', cone, 5, '*', 0, Direction.FORWARD, 5, 1));
        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println(buildRocket());
    }

}


My particular concerns are the number of parameters I have going to the inner methods. How can those be rationalized? Should they be? What mechanisms can be used to simplify the interfaces?
Wells, for the sake of loop-ifying everything, you may want to consider changing boundary as such:

final char[] boundary = "=*=*=*".toCharArray();
...
sb.append( buildLines( '+', boundary, 3, NONE, 0, Direction.CENTER, 1, 2 ) );


That will create =*=*=*, duplicate it once, and add the + character at both ends.

The ternary operator below looks like a good candidate for adding a helper method into the Direction enum:

int pos = charfrom + line * (chardir == Direction.FORWARD ? 1 : -1) 


My version is expanded as such:

private enum Direction {
    CENTER( 0 ), UPWARD( 1 ), DOWNWARD( -1 );

    private final int multiplier;

    Direction( final int multiplier ) {
        this.multiplier = multiplier;
    }

    int getMultiplier() {
        return multiplier;
    }
}


And calculating pos is just charfrom + line * chardir.getMultiplier();

One more minor suggestion: The usage of 5 and 3 seems to be repeated quite often, maybe refer to them as coneSize and blockSize? The main body will look something like:

sb.append( buildLines( ' ', cone, coneSize, '*', 0, Direction.UPWARD, coneSize, 1 ) );
sb.append( buildLines( '+', boundary, blockSize, NONE, 0, Direction.CENTER, 1, 2 ) );
sb.append( buildLines( '|', wider, blockSize, NONE, 0, Direction.UPWARD, blockSize, 2 ) );
sb.append( buildLines( '|', narrower, blockSize, NONE, 2, Direction.DOWNWARD, blockSize, 2 ) );
sb.append( buildLines( '+', boundary, blockSize, NONE, 0, Direction.CENTER, 1, 2 ) );
sb.append( buildLines( '|', narrower, blockSize, NONE, 2, Direction.DOWNWARD, blockSize, 2 ) );
sb.append( buildLines( '|', wider, blockSize, NONE, 0, Direction.UPWARD, blockSize, 2 ) );
sb.append( buildLines( '+', boundary, blockSize, NONE, 0, Direction.CENTER, 1, 2 ) );
sb.append( buildLines( ' ', cone, coneSize, '*', 0, Direction.UPWARD, coneSize, 1 ) );


Due to the fact that our sources are fixed lengths now, I don't see much of an improvement on the method signatures since it's not like the current code can be easily expanded to create rockets of different sizes. Maybe I'll attempt another stab at that when I have some more time...