Previous 20

Jun. 19th, 2007

Japan

Struggling with Pickles

One of the great hopes I had when working on the design of my game was that a lot of other grunty, gritty feature implementation would be taken care of for me by writing things in a high level language.

Particularly, I was looking forward to not implementing save and restore, and instead using the builtin serialisation engine. This has definitely not been all I was hoping.

The first problem was when I reintroduced shadows in a more limited capacity ( they are no longer an object level implementation, but are turned on or off by individual getter functions ). A lot of the shadows would be represented by anonymous functions, generated by the lambda keyword.

Unfortunately, it turns out pickle only performs shallow persistence of instance variables - when it hits the code object generated by lambda, it dies. I managed to solve this by instead storing the function definition as a string and then using exec to generate a code object on the fly, but the shallow only nature of pickle has some other, more annoying consequences.

One is that, as only instance data is persisted ( and not e.g. the class definition ), if someone installs a module, grabs an item out of it at some point, and then uninstalls it, it invalidates their save file. This is not what I had wanted.

I have a terrible feeling I'm going to have to end up implementing save and load after all. Combined with the difficulties I am having writing decent AI, I am definitely feeling the mid-project doldrums.

I missed? )
Tags:

Jun. 12th, 2007

Japan

Research Request

Most of the engine is complete now, and I'm writing content for a while. Part of this involves writing up a lot of equipment to be bought and sold in the imaginatively named "Hub City".

One of the big problems facing me is that I don't know what a lot of these things would cost. How much do you pay for a Luger P08 in 1930? If I had my Call of Cthulhu rulebook in Japan, it would go some way towards getting some resolution on some of these mysteries ( at least for the 1920s ), but not all.

I am still worried about balancing this game correctly.
Tags:

Jun. 10th, 2007

Japan

Picking colours with AppleScript.

To colourise my glyphs in Bullwhip, I supply a tuple of four reals - representing red, green, blue and alpha. Each is a value from one to zero, but I rarely go beyond two decimal places.

Visualising colour is hard, so I like to use Apple's excellent colour picker widget. The following AppleScript uses the widget, converts the values into the range 0 - 1, puts them in a tuple, and stores them on the clipboard. It exits if you select true black ( 0, 0, 0 ).

on roundTrunc(n, numDecimals)
    set x to 10 ^ numDecimals
    (round (n * x)) / x
end roundTrunc

repeat while true
    set ourColour to choose color
    if ourColour is equal to {0, 0, 0} then exit repeat
    set ourMsg to "( " & roundTrunc((item 1 of ourColour) / 65535, 2) & ", " & roundTrunc((item 2 of ourColour) / 65535, 2) & ", " & roundTrunc((item 3 of ourColour) / 65535, 2) & " )"
    set the clipboard to ourMsg
end repeat
Tags:

Jun. 8th, 2007

Japan

Object oriented programming does not survive collision with shadows.

Subject says it all, I guess.

Because I can shadow ( define a set of recursive wrappers ) my accessor functions, and those shadowed values represent system "reality", I can no longer use direct access of underlying data structures even within the same class. It has turned into some kind of horrible "super OO" with no attributes, only setter and getter methods. Bleah!

I am doing another overhaul at the moment, unifying some classes and outright removing some others. I think I've finally made a decision on mechanics as well - at the moment ( after a brief flirtation with S.P.E.C.I.A.L. ) I am leaning towards something derived from Tristat dX.

updates: While I know that premature optimisation is generally a mistake, I had a look at some profiling data, and the amount of time spent handling shadows ( the interpreter has to basically start second guessing all object data / method references ) was just insane. I turned shadows into a mixin that would only be connected with certain objects, but that was still terrible. I've decided to dump them out for now.

Today also saw a lot of other optimisations and pruning with the introduction of the attributes system for marking objects as implementing various interfaces with each other. The beginnings of the implementation of the Tristat rules went in, and some redundant classes were combined or eliminated. Things generally went pretty well, although I appear to have picked up a small graphics bug in the works somewhere.
Tags:

May. 31st, 2007

Japan

Release: rezTunes 1.0

Source and binaries for Mactel are up at my homepage. If you are running iTunes on OSX, and want to watch beat patterns in the visualiser and optionally have it control n USB Rez vibrators, this is the plugin for you! License is Creative Commons Attribution-Share Alike 3.0.

edit: Wzdd has made a good argument, and I respect his judgement. Relicensed under CC-BY 3.0 effective immediately.

May. 30th, 2007

Japan

Grinding on.

Well, work on the plugin has almost finished now. After talking to Slashr for a bit, and then Wzdd, I ended up gutting all that math in the previous posts, and instead going for an exponentiated function. This was surprisingly easy to implement.

I still need to add support for multiple vibe units, but it's otherwise finished. The beat detection works reasonably well, after tweaking the parameters to more closely align with the kinds of music I expect to see it used with ( i.e. not noise rock, apologies Sonic Youth fans ).

The big problem is really down to response time on the unit itself. There is a spin up delay on the device which prevents it from catching some of the faster or less intense beats, which have already decayed away before the motor can reach speed ( or the user notice it, I guess ). I guess this is just a problem with the medium. It would probably work better for Electrostim / TENS applications, but that's not a road I'm going to go down just yet.

Release by Friday at the latest. Even if you don't have a Rez unit, you can have a look at the pretty flashing beat light if you're so inclined. It'll only work on a Mac though.
Tags:
Japan

Followup: Sectioning of Irregular Series

Because my case has certain fixed terms ( x = 512, width1 = 2 ), the earlier general math can be reduced to a much simpler equation:
z = ∑( x = 1 → n ) n
n * b + a * z = 512
b = 2 - a
n * ( 2 - a ) + a * z = 512
2 * n - n * a + z * a = 512
2 * n - a * ( n - z ) = 512
a = ( 2n - 512 ) / ( n - z )
a = ( 2n - 512 ) / ( n - n * ( n + 1 ) / 2 )
The goodness here stems from the useful identity that ∑( x = i → j ) x = ( j - i + 1 ) * ( i + j )/2.
Tags:

May. 28th, 2007

Japan

Irregular sectioning of arrays.

For an array of size x sectioned into n bands,
widthband = b + a * band
Σ( band = 1 → n ) widthband = x
Σ( band = 1 → n ) widthband = n * b + a * Σ( band = 1 → n ) band
∴ n * b + a * Σ( band = 1 → n ) band = x
In my example, sectioning a 512 element array of fft values into 64 bands, with an initial bandwidth of 2,
64b + a * Σ( band = 1 → 64 ) band = 512
64b + a * 2080 = 512
2b + 65a = 16
65a = 16 - 2b

width1 = b + a = 2
b = 2 - a

65a = 16 - 2( 2 - a )
65a = 16 - 4 + 2a
63a = 12

a = 12/63
b = 2 - 12/63
Results
 >>> a = 12.0 / 63.0
 >>> b = 2 - a
 >>> getwidth = lambda x: a * x + b
 >>> widths = [ getwidth( x ) for x in range( 1, 65 ) ]
 >>> sum( widths )
 511.99999999999994
Of course, many of these widths are fractional, so I'm going to have to play around with this a bit more.

Edit wrt earlier error: DURR 2080 / 64 = 32.5, not 32. Thanks python auto-int math. Why do I use this thing as a calculator again?
mechashiva mechashiva mechashiva
Tags:
Japan

Development Distractions

Well, I took some time off development on the roguelike this weekend to write an iTunes plugin. It's almost finished now, although I'm still yet to add "colour" to the beat detection code.

Here are some pocket observations on the iTunes plugin API:
  • It would be nice if the header files didn't generate compiler warnings.

  • ( I assume for compatibility with OS9 and Windows ) The graphic structures ( viewports / drawing rectangles ) provided by the plugin API are legacy (bitmapped) QuickDraw objects instead of (vectorised) Quartz ones. While you can re-derive the underlying Quartz surfaces from QuickDraw ones, QuickDraw has been deprecated since 10.4 and will stop working at some point.

    Also, QuickDraw has an inverted y-axis compared with Quartz, which can be a little annoying to correct for unless you can get the dimensions of the QuickDraw port.

  • iTunes will send your plugin two signals ( kVisualPluginEnableMessage and kVisualPluginDisableMessage ) at startup and shutdown. iTunes currently enables all plugins regardless of whether or not you've selected them, so the documentation advises you not to just ignore these messages. Note however that answering unimpErr to them will cause your plugin to be discarded by iTunes, causing you many hours of headscratching.
The plugin is revisiting somewhat old ground... it drives the Rez Trance Vibrator that you can see information about in my older posts. An iTunes plugin is wha I wanted to make originally, and I'm not quite sure why I got distracted and went off and wrote something else the first time around - maybe the complexity of doing USB with IOKit had scared me off. It's really not as bad as it looks.
Tags:

May. 22nd, 2007

Japan

First preview movie for Bullwhip.

Here is a little movie of me traipsing around the lobby level of episode 1, "Llovizna and Rockets".

Mpeg 4 .mov file - 727k.

Here are some things I think are interesting that are going behind the scenes but are not immediately apparent:

The message about the undergrowth slowing your progress is not entirely cosmetic - each action in the game ( apart from things like inspecting your inventory, etc ) has an attached time penalty, which you bleed off at ( speed ) per tick. You can't take actions while you have penalty outstanding. This allows you to catch up with things moving over rough ground, and vice versa.

I didn't show off the persistent macro or command queuing system for some reason. Eventually, when the keybinds stuff comes in, this will shorten the keypaths for those who don't like the idea of typing 'ii1e' to put on a hat or what-have-you ( e.g. you will be able to macro 'ii*e' to a character - the asterisk will prompt you for a keystroke ).

The "cursed hat" in inventory is the hat referred to in the previous update. It halves vision radius.

The combat system doesn't really get much of a showing off. We didn't even get to bonk it on the head with the flashlight!
Tags:
Japan

Implementing Shadows, II

As all in-world objects have a common ancestor, I ended up implementing this not as a proxy object, but as methods on that common ancestor object. It took a little juggling to dodge some recursion bugs, but it's all working pretty well! To test it, I coded up a cursed hat -

Code )

Pretty simple! I'm happy with how this has turned out. Now, if I could only solve the colour problem...
Tags:
Japan

Implementing Shadows

I had been a bit worried about this ahead of time, but it's come out alright. Shadows originate, as far as I am aware, from the LPC mud programming language, which I was exposed to during my tenure at Discworld MUD. They are a form of runtime function overloading.

While this is very easy to do in Python ( functions are first class objects and are hence first class overwrite-able ), I wanted to be able to chain them.

An example of an effect that is implemented with shadows are, say, statistic enhancing items. One in the default item catalog for Bullwhip is the "packrat harness" that allows you to carry additional loads. Conceptually, when the function to query the maximum carry weight for a player is called, the game will first determine the answer according to the players Class object, and then successively call the shadows registered against that function until a final answer is calculated, and return that.

After a bit of reading on the internet, and a chat with [info]wzdd who is an old hand at this kind of thing, I found that to trap function calls, I'd need to write a proxy object. Two problems sprang up right away - isinstance, which determines whether an object is of class X or its descendants would break, so I'd have to write a glue function. Second, is that method calls are done in two steps, a pointer to a bound instance of the method is retrieved from within the object, and then the arguments are called against it. This means that at the time when I can intercept the call, the function is not yet in execution, and the arguments are not interceptable.

Because of this last point, the shadows will have to instead take a function as an argument, and return a function with the same signature. Good news about that first-class functions thing!

Proxy class. )

Example. )

I've created a monster! *ragtime*
Tags:

May. 16th, 2007

warning

Frustration

So, for a little while now I have been writing a roguelike game, in that horrible "90's re-envisioning of 30's pulp" kind of style. It is object oriented and written in Python. So far, it all works very well, except for the fact that I'm not really good at designing game mechanics.

One thing that has not been going well has been computing fields of vision. I am now on day three of what feels like an endless deathmarch through algorithm space looking for a good solution.

At first, I used a recursive shadowcasting method as advocated in an old article by roguelike oldboy Björn Bergström. For some mysterious reason, I was unable to get it to behave in the same way as his reference implementation ( of which only 'screenshots' remain ).

I then reimplemented it as a gap hunting routine over the octant.

Finally I have gone to an angular shadowcasting method similar to that used by Hansjörg Malthaner in his crpg "H-World". I thought I'd finally come up with a winner here, only to be slapped in the face one last time. In short, over the first octant:

We have a list of tiles requiring inspection, and we have a list of "shadow angles", which are pairs of gradients. For each cell we are testing, we calculate the intersections of the shadow angles with the current line and test if the cell is inside it. If it's not, we check if it is a blocking cell. If it is, a shadow angle is added using the corners of the blocking square and the origin, where the player is. ( See cut. )

The problem?
@........       @........
.########       .#sssssss
.#.......  -->  .s.......
.#.......       .#....... 
.#.......       .s.......


That's right! On a vertical wall, each tile shadows the one next to it. A checkboard pattern is established because cells that are already shadowed do not contribute further shadowing.

Quickly consulting the math, with @ at (0,0) and x and y increasing left to right and top to bottom respectively, you can see the problem:

0,0 - No collisions.
0,1 - No collision.
1,1 - Collides. Bottom left corner is ( 0.5, 1.5 ), gradient is 1/3. Top right corner is at ( 1.5, 0.5 ), gradient is 3.

On the next line, these gradients produce shadow boundries of x = 2/3 and 6. Anything between these should be discarded. Of course, ( 1,2 ) obviously runs afoul.

There is nothing like an elegant, well thought out and correct solution that doesn't work.

Function for searching the octant, in python. )
Tags:

May. 11th, 2007

Japan

Japan's Best "Short Letters to Dad"

In 1996, the Maruoka-cho Cultural Foundation, with some help from the Sumitomo Group Public Affairs Committee and the postal service began a "A Brief Message from the Heart Letter Contest". Following a successful round of letters to people's mothers, there was then a successor competition for fathers - 73,933 letters were collected.

Down the line, a book was published containing the judges selections - 51 Japanese letters, and 13 English ones. It also contains translations into the opposing tongue for each.

Nearly every school I have taught in has a copy of this book, and I found it quite moving to read in parts, and an interesting insight into the character of the Japanese father. This is quite a feat for me as most of the Japanese I can read at my level tends to be quite dry. Anyway, I was lucky today to receive my own copy - it's a little ripped, and has been replaced. I am going to put the letters up here on LJ, on wednesdays and fridays, tagged with 'japandads'.

May. 2nd, 2007

Japan

Kantango Keys

I like to study vocabulary with Kantango. Unfortunately, I don't like using the mouse when I'm at the computer for long periods. In the olden days, the Flashcard interface on Kantango was passably navigable with the keyboard and a lot of tab mashing, but something changed in Firefox and broke it. So I've written a greasemonkey script to make it keyboardable - Kantango Keys.
Tags:

Mar. 15th, 2007

1337

blip.tv cutups

Sample ( resized/recompressed for web ).
Source.

Cuts creative commons and public domain videos from blip.tv into films in the style of The Cut-Ups. Needs feedparser ( included ) and ffmpeg ( not included as it's an endless moving target ).
Tags:

Feb. 8th, 2007

Japan

The Kabbalahmatic

Some of you might remember I wrote something to sit on the Livejournal "Recent Posts" feed, rip the mood tags out and then assemble statistics from the wreckage. At one point, I was going to make a mood lamp. Well, I'm too lazy to build something with my hands, so instead, I made a mood...desktop thing. It's somewhat influenced by the lovely colour schemes that were used in Alan Moore's "Promethea".

This python script quantizes the moods down into the basic sixteen moods as defined by the LJ Developers*. These are then amateurishly mapped to the Sephira of the Tree of Life**. The classical colours of these spheres are then combined in a weighting according to how many Livejournal users have declared their mood to fall in that sphere. The Finder desktop window is then set to that colour.

It seems that most of LJ is hanging out in Tiferet at the moment. That's as it should be.
Source. )
"Without going out of my door, I can know all things of Earth."
-- "The Inner Light", The Beatles
* Angry, Awake, Happy, Devious, Enthralled, Energetic, Bouncy, Working, Nerdy, OK, Indescribable, Confused, Sad, Scared, Determined, Thoughtful.

** Gevurah, Kether, Tiferet, Binah, Tiferet, Gevurah, Tiferet, Malkuth, Binah, Nezah, Malkuth, Chokmah, Hesed, Daath, Nezah and Chokmah, respectively. User defined moods are mapped to Kether, for at least displaying self awareness.
Tags:
Japan

Reloading the desktop image on OSX via AppleScript.

tell application "Finder"
	set the mood_graphic to (desktop picture as text)
	
	try
		set AppleScript's text item delimiters to ":"
		set mood_parent to text items 1 thru -2 of mood_graphic as text
		set AppleScript's text item delimiters to " "
	on error
		set AppleScript's text item delimiters to " "
	end try
	
	set the mood_alias to make new alias to file (desktop picture as text) at mood_parent
	set desktop picture to file (mood_alias as text)
	set desktop picture to file mood_graphic
	do shell script "rm " & quoted form of POSIX path of (mood_alias as text)
end tell
Part of an ongoing project. Why didn't they just put in a reload method on the Finder.app dictionary? :-(
Tags:

Feb. 7th, 2007

natsuko

Natsuko's Sake

I finally finished rewriting the engine that drives this page into using XML documents to store the translated strings. Now it will be easy to edit or add new translations for. Unfortunately, I haven't finished marking up all my paper notes into the new format yet. Link.

Dec. 13th, 2006

Japan

Livejournal Moods + Ambient Orb

So, I reworked my LJ mood reading code to talk to an Ambient Orb. The hardest part was quantizing the bazillion different livejournal moods. Unfortunately, Orbs won't work in Japan ( or Australia ), so I am hunting for a tester. Know anyone?

The Code )
I hope I didn't miss anything!

p.s. I missed the fact you need Feedparser, which is a module for parsing RSS feeds ( who knew ).

Previous 20

Japan

August 2007

S M T W T F S
   1234
567891011
12131415161718
19202122232425
262728293031 

Advertisement

Syndicate

RSS Atom
Powered by LiveJournal.com