Java 4k competition 2011

Finally the time a year when you are encouraged to write really dirty code, Java 4k competition! Well, maybe not dirty but certainly ugly.

The Java 4K competition is a game programmer competition. The goal of the competition is to create the best game possible in Java. But what's the catch? Well, it wouldn't be fun if there wasn't any catch! There are limitations, and these limitations are: The maximum allowed size of a game is only 4K

This year i forgot to exclude the manifest before i started with the size optimizations. I felt like a child on christmas when i discovered it! Good times :) Anyway, my game is a classic puzzle game where you control a rolling cube. The objective is to clear all colored bricks on the playfield by rolling over the bricks with the a side of the cube which have the same color as the brick. The game can be found on the Java 4k site and I encourage you to try all submitted games, some of them are really good.

Because Riven's excellent Compile 'n Shrink service seems to be down, probably due to the hacking of, I'll post my own compression scripts here.

This is the script I use for this tedious task:

if [ $# -ne 1 ]
  echo "Usage: `basename $0` "
  exit 65

function printSize() {
   SIZE=$(ls -l $1 | awk '//{print $5}')
   printf "+ %-15s %s bytes [%d]\\n" $1 ${SIZE} $((SIZE-4096))


PRO_FLAGS="-libraryjars /lib/rt.jar -basedirectory ."


pushd .
cd $BIN


#echo Generating manifest file
#echo -e Main-Class: $1\\n > $1.manifest

echo Running jar on $CLASS
jar cfM $JAR $CLASS

echo Running Proguard on $JAR
proguard $PRO_FLAGS -injars $JAR -outjars $PRO -keep public class $1

echo Running pack200 on $JAR
pack200 -G $PACK $JAR

echo Running pack200 on $PRO
pack200 -G $PRO_PACK $PRO
pack200 --no-gzip $PRO_PACK_RAW $PRO

echo Compressing $PRO_PACK_RAW with 7zip
7z a -mx=9 -tgzip $PRO_PACK_7ZIP $PRO_PACK_RAW > /dev/null

echo Compressing $PRO_PACK_RAW with Kzip
kzip /q /y /s0 /rn /b64 $PRO_PACK_K $PRO_PACK_RAW 

echo File size summary:
printSize $CLASS
printSize $JAR
printSize $PRO
printSize $PACK
printSize $PRO_PACK
printSize $PRO_PACK_7ZIP
printSize $PRO_PACK_K_GZ

# Write to the log file
echo "----------------------------------" >> $LOG
date +"%Y-%m-%d %H:%M:%S" >> $LOG
echo "----------------------------------" >> $LOG
echo "File size summary:" >> $LOG
printSize $CLASS >> $LOG
printSize $JAR >> $LOG
printSize $PRO >> $LOG
printSize $PACK >> $LOG
printSize $PRO_PACK >> $LOG
printSize $PRO_PACK_7ZIP >> $LOG
printSize $PRO_PACK_K_GZ >> $LOG
echo >> $LOG

popd >> /dev/null
For even smaller files, replace the kzip command with a script that runs kzip 10-100 times and takes the smallest resulting file. You will also need pjt33's Zip2Gzip converter to convert the KZip files to GZip:

// Based on
// and
public class Zip2Gzip {
 // Usage: java Zip2Gzip [ [file.gzip]]
 public static void main(final String[] args) throws IOException {
  InputStream in = new FileInputStream(args[0]);
  in = new BufferedInputStream(in);
  OutputStream out = new FileOutputStream(args[1]);
  out = new BufferedOutputStream(out);

  // Start by writing a gzip header.
  // Magic.
  // Compression method: inflate.
  // Flags: we include no optional extras.
  // Timestamp: unavailable.
  // Extra flags: none.
  // OS: unknown.

  // The next block of output is the compressed data. We need to process
  // the zip file header to find it and know how long it is.
  // local file header signature 4 bytes (0x04034b50)
  // version needed to extract 2 bytes
  // general purpose bit flag 2 bytes
  // compression method 2 bytes
  // last mod file time 2 bytes
  // last mod file date 2 bytes
  // Total so far: 14 bytes
  for (int i = 0; i < 14; i++) {;
  // crc-32 4 bytes
  final int crc1 =;
  final int crc2 =;
  final int crc3 =;
  final int crc4 =;
  // compressed size 4 bytes
  int cmpSz = ( & 0xff) + (( & 0xff) << 8) + (( & 0xff) << 16)
    + (( & 0xff) << 24);
  // uncompressed size 4 bytes
  final int ucmpSz1 =;
  final int ucmpSz2 =;
  final int ucmpSz3 =;
  final int ucmpSz4 =;
  // file name length 2 bytes
  final int nameLen = ( & 0xff) + (( & 0xff) << 8);
  // extra field length 2 bytes
  final int xfLen = ( & 0xff) + (( & 0xff) << 8);
  // file name (variable size)
  for (int i = 0; i < nameLen; i++) {;
  // extra field (variable size)
  for (int i = 0; i < xfLen; i++) {;

  // Data follows, so we can copy it to the output.
  final byte[] buf = new byte[4096];
  while (cmpSz > 0) {
   final int desired = cmpSz > buf.length ? buf.length : cmpSz;
   final int len =, 0, desired);
   if (len == 0) {
    throw new EOFException();
   out.write(buf, 0, len);
   cmpSz -= len;

  // The output still needs the CRC32 and the uncompressed size.

  // Done. Be tidy.

Cubing for charity

The last couple of months I've been traveling in Asia and come face to face with the extreme poverty here. Of course I've heard the news, seen the pictures and read the facts but it's not the same as actually seeing it with your own eyes. I felt like I had to do something. So I've decided that until the profit from the ads in Rubik's Cube Algorithms (and other apps) reaches a substantial part of my normal income, it will be donated to charity. I know this is kind of a feel-good-move on my part since the amount of money spent by me for the sole purpose of traveling is infinitely more than the profit from the ads. But at least it's something and I will continue with the donations on each payment from admob.

The first donation goes to Hand in Hand whose objective is:
Our objective is to eliminate poverty by creating jobs. We do this through our unique holistic approach that tackles the areas that matter the most to poor communities – microfinance, education, health, information, and environment.
The amount donated is £17.00 GBP ($26 USD). It's not much, but according to Hand in Hand it will at least "Provide one woman with entrepreneurial training to start her own business".

Floating header plugin v1.4.0

Due to a very nice patch submitted by Jason Axley i've release a new version of the plugin. The changes are a lot of performance optimizations including lazy creation of the floating-clones.
Look at my old post or the jQuery project page for more information about the plugin.