Zovirl Industries

Mark Ivey’s weblog

Perplex City

Last month, TR bought a Perplex City starter kit for my wife and I. What a cool game! There are so many levels you can play at. You can solve puzzle cards by yourself. You can join up with others online and solve cards together (including some really hard cards requiring group efforts). The city itself has a lot of depth, with record companies, pharmaceutical companies, schools, blogs, and newspapers. Some of these “companies” run ads in London newspapers, and puzzles from the game have shown up in newspapers and magazines. Finally, you can hunt for the stolen cube and try to get the $200K reward.

Many of the puzzles make fun programming challenges. I’ve been doing them in python, since that is such a great language for rapid programming. Sweet Dreams (#85) makes an obvious candidate:

#!/usr/bin/env python

a = 1
b = 1
while a < 400000:
    c = a + b
    a = b
    b = c
    print c

My wife solved Rickety Old Bridge (#106) much faster than I was able to write the program (although the program found that there are two similar solutions, not just one). This was a good one to learn generators with:

#!/usr/bin/env python

class bridge:
    people = { "kurt":2, "scarlett":5, "violet":1, "sente":10 }
    states = [ {"near":people.keys(), "far":[], "moves":[]} ]

    def move(self, source, dest):
        """ yield all new states formed by moving
            a person from source -> dest """
        for state in self.states:
            for person in state[source]:
                yield {source:  [s for s in state[source] if s != person],
                       dest:    state[dest] + [person],
                       "moves": state["moves"] + [person] }

    def to_far(self):
        self.states = [s for s in self.move("near", "far")]

    def to_near(self):
        self.states = [s for s in self.move("far", "near")]

    def score(self, state):
        times = [self.people[name] for name in state["moves"]]
        total_time = max(times[0], times[1]) + times[2] + \\
                     max(times[3], times[4]) + times[5] + \\
                     max(times[6], times[7])
        return total_time, state["moves"]

    def print_scores(self):
        scores = [self.score(s) for s in self.states]
        scores.sort()
        scores.reverse()
        for s in scores:
            print s[0], s[1]

    def run(self):
        self.to_far()
        self.to_far()
        self.to_near()

        self.to_far()
        self.to_far()
        self.to_near()

        self.to_far()
        self.to_far()

        self.print_scores()

if __name__ == "__main__":
    b = bridge()
    b.run()

The program I came up with for solving Magic Square (98) takes a long time to run but eventually starts finding candidate solutions about 2.2 million squares into its search:

#!/usr/bin/env python

def comb(nums, n):
    if n == 0: yield [], nums
    else:
        for i in range(len(nums)):
            for tail, remaining in comb( nums[:i] + nums[i+1:], n-1):
                yield [nums[i]] + tail, remaining

def rows(nums):
    if not nums: yield []
    else:
        for row, remaining in comb(nums, 4):
            if sum(row) == 34:
                for other_rows in rows(remaining):
                    yield [row] + other_rows

def check(grid):
    magic = True
    for i in range(4):
        if sum([row[i] for row in grid]) != 34:
            magic = False
    if sum([grid[i][i] for i in range(4)]) != 34 or \\
       sum([grid[i][3-i] for i in range(4)]) != 34:
        magic = False
    return magic

count = 0
for grid in rows(range(1, 17)):
    count += 1
    if count % 100000 == 0:
        print count / 1000, "K"
    if check(grid):
        print grid

Changing Permissions in Subversion

It took me entirely too long to figure this today. Perhaps Google will pick this up and save someone else the effort.

I had a file in Subversion which should have been executable but wasn’t. I tried changing the file permissions and checking in the file, but Subversion refused to do anything since the file hadn’t changed. I poked around with Google but didn’t find anything helpful.

Finally the nice folks over in #svn on irc.freenode.net told me the command is svn propset svn:executable "*" filename. Sister commands include propdel and proplist.

Humble Beginnings: Your First OGRE Application (for linux)

Nicholas Green’s Humble Beginnings tutorial for the Ogre graphics engine says “Under construction” for the Linux section. This is an attempt to remedy that. I’m only going to cover setting up the project and getting to a basic program which compiles and runs, similar to the Mac OSX section. After that, you’re on your own…

To begin, make the Samples/Space directory for your project and copy these files into it:

Next we will set up a basic build system, for which we are going to use GNU automake and autoconf. If you want to learn more about these tools, I suggest reading the excellent tutorial at the autotools website. First we will write Samples/Space/configure.ac, which tells autoconf which programs and libraries we are going to use to compile our application:

AC_INIT([Ogre Space Tutorial],
        [0.0.1],
        [Mark Ivey zovirl@zovirl.com],
        [Space])
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE([dist-bzip2])

AC_PROG_CC
AC_PROG_CXX
AC_PROG_LIBTOOL

PKG_CHECK_MODULES(OGRE, OGRE >= 0.14.1,,AC_MSG_ERROR("OGRE not found!"))
AM_CXXFLAGS="$AM_CXXFLAGS $OGRE_CFLAGS"
AM_LDFLAGS="$AM_LDFLAGS $OGRE_LIBS"

AC_SUBST(AM_CXXFLAGS, "$AM_CXXFLAGS")
AC_SUBST(AM_LDFLAGS, "$AM_LDFLAGS")
AC_SUBST(PKGDATADIR, "${datadir}/${PACKAGE}")

AC_CONFIG_FILES([
   Makefile
])

AC_OUTPUT

Most of that is boiler-plate. The two important parts are “PKG_CHECK_MODULES(OGRE…)” which tells autoconf we will be using OGRE (and it should go find the correct compiler flags for us) library and “AC_CONFIG_FILES(…)” which tells autoconf which files we want it to generate.

Next we will write Samples/Space/Makefile.am, which tells automake how to compile our program:

bin_PROGRAMS = Space

noinst_HEADERs= ExampleApplication.h \
                ExampleFrameListener.h \
                SkyPlane.h

Space_SOURCES= SkyPlane.cpp

EXTRA_DIST = bootstrap configure

Ok, the last part of the build system is a short script to set everything up for us, Samples/Space/bootstrap:

#!/bin/sh

set -x
rm -f config.cache &&
libtoolize --force &&
aclocal &&
autoconf &&
autoheader &&
automake --foreign --add-missing

make that executable with “chmod +x bootstrap”

You are ready to compile (from the Samples/Space/ directory):

./bootstrap
./configure
make

Finally, you should be able to go into the data directory (Samples/Common/bin) and run ../../Space/Space.

Ok, the build system is done, now it is time to add the real source code. Remove SkyPlane.cpp and SkyPlane.h and edit Makefile.am to reflect the new files you are about to add:

bin_PROGRAMS = Space

noinst_HEADERs= ExampleApplication.h \
                ExampleFrameListener.h \
                SpaceApplication.h

Space_SOURCES= SpaceApplication.cpp

EXTRA_DIST = bootstrap configure

Finally, add the code for the application’s main loop in SpaceApplication.cpp:

#include "Ogre.h"
#include "SpaceApplication.h"

int main(int argc, char *argv[])
{
   // Create application object
   SpaceApplication  app;
   try {
      app.go();
   } catch( Ogre::Exception& e ) {

   std::cerr << "An exception has occured: " <<
   	e.getFullDescription().c_str() << std::endl;
   }

   return 0;
}

That won’t compile just yet because SpaceApplication.h hasn’t been added, but you are ready to continue on with the rest of the tutorial. Enjoy…

marbles 0.6

Just for fun in the evenings, my wife and I have been working on a simple marbles solitaire game. Yeah, we know, there are already hundreds of versions of this game. That isn’t the point. It is a way for us to learn SDL and keep our programming skills sharp. It isn’t finished yet so there are some rough edges, but we are posting it anyway. In the game, just click to move pieces around. ‘q’ quits and ‘r’ resets the board.

Download source code
win32 binaries