Alphaios Blog

This is the official blog of Alphaios.net. When I feel like rambling I turn here.

7/30/08

Resource Management System Changed

The resource management system I posted before has been drastically changed. If you were using it and are expecting an updated version, expect the new version to be completely incompatible with your code!

Labels: , ,

Songs No. 74 and No. 75 Finished

I finished two new songs. (Actually I finished them over 2 weeks ago but I forgot to upload them with the rest of the other songs).

No. 74 - "If I Knew"
No. 75 - "Running on the Dance Track"

I'm also working on an alternate version of 74 that uses guitars and a piano instead of synth instruments, but I'm having trouble with the lead in the second half.

Labels: , , , ,

7/27/08

Mystery Solved

Yep, it's a battery. The panel on the bottom of the Wii is for the battery-backed memory. (Booooring...)

Labels:

7/23/08

Weird Panel on the Bottom of the Wii

I just took advantage of Nintendo's free Wiimote jacket deal. (Yeah, apparently that's still going on.) While looking for the serial number for the Wii, I noticed a small, inconspicuous, removable panel on the bottom below the eject button:



I'm not really sure what it's for, but the best I could get from various Google searches is that it holds some sort of button-cell battery for keeping the clock ticking when its unplugged. That would make sense; nearly every computer has one of these hidden in them somewhere.

I'm afraid to actually remove the panel to see what's inside. First of all, because it isn't my Wii. It's my brother's. ^_^ Second, because there's a small, small chance it would void the warranty...not likely, but not risking it. Third, because I don't have a Philip's head screwdriver small enough to get the screw out...

I'll bet this little mystery is solved by the manual. Of course, I don't know where the manual went, so that's no help. :P

Labels:

7/21/08

Resource Management System for Game Engine

I have just completed the resource management system for my upcoming game engine, "Scrollback". It hasn't been tested yet, but the syntax is, at least, correct.

If anyone would like to comment on the API or anything else, please do. I'm looking for some (inteligent) input.

Sorry about the sidebar on the right covering up the code...not much I can do about that right now, unfortunately. :( You should still be able to highlight and copy.

# sbak/resource.py
"""
This module defines the resource management system.

This version of the resoruce management system has been significantly
toned down from what I originally had it mind. This version does not have
any system of library hierarchies, names, or aliases, as did the original
plan. Instead, there is only the "registry," and all resources are
automatically registered with it when they are created, loaded, or stubbed.
(Incidentally, creating a resource is how a resource is stubbed!)

Complete but untested as of 2008-07-21. - The Music Guy
"""

import os.path
from error import ResourceError
import core._debug

__all__ = (
'init',
'register',
'unregister',
'get',
'get_exists',
'BaseResource'
)

# This maps the IDs of registered resources the actual resources.
_resource = {}

# Current "working directory" of the resource manager
_cwd = ''

def init():
""" Initializes the resource management system.
Must be called before using the resource management system
NOTE: This method doesn't actually do anything right now, but I'm fairly
sure I will need it later, so I'm defining it anyway.
"""
pass

def register(res):
""" Registers a resource with the manager.

You don't need to call this usually because resources will register
themselves automatically, provided they call the BaseResource
initializer on themselves.

Raises error.ResourceError if you attempt to register a resource with an
ID that is in use by another registered resource, or if you attempt to
register an object which does not appear to be a resource.
"""
global _resource
try:
theID = res.id
except AttributeError:
raise ResourceError,"Object being registered does not have a resource ID."
if theID in _resource:
raise ResourceError,'Duplicate registration of resource ID "%s".'%theID
_resource[theID] = res

def unregister(res):
""" Unregisters a resource from the resource manager.

Call this on a resource object or ID that has been registered to make
the system drop its reference to the resource. However, you will no
longer be able to get a reference to the resource by ID.

Raises error.ResourceError if you attempt to unregister a resource that
is not currently registered.
"""
pass # TODO: unregister

def get(id):
""" Returns the resource with the given ID.
Loads the resource explicitly if it has not already been loaded.
Returns None if there isn't a resource registered with the ID.
"""
global _resource
try:
res = _resource[id]
except KeyError:
return None
res.load()
return res

def _get_implicit(id):
""" Internal function.
Implicitly loads the resource with the given ID and returns it.
Returns None if there isn't a resource registered with the ID.
"""
global _resource
try:
res = _resource[id]
except KeyError:
return None
res.load(True)
return res

def get_exists(id):
' Returns whether or not there is a resource registered with the given ID. '
return id in _resource

def set_directory(*d):
""" Sets the "current working directory" of the resource manager.

You may pass a directory in "pieces" as a arbitrary number of arguments.
The pieces will be reassembled using the os.path.join() function.

This directory will be prefixed to the paths of filenames of resources
loaded or stubbed from the time of the calling till the end of the next
cycle.
"""
global _cwd
_cwd = join_paths(*d)

class BaseResource(object):
""" Base class for all resource types.

The following methods should be overwritten by subclasses:
__init__, load, unload

See the documentation for each of these methods for more info.

Additionally, subclasses should define a `save` method for allowing a
resource to save its data to a file. It should be defined as such:

class SomeResourceType(BaseResource):
...
def save(self,filename=None):
...

The `filename` argument is the file to which the resoruce data will be
saved relative to the "current working directory" of the resource
system, which can be determined by calling `resource.get_cwd()`.
If the filename is not present, the value of `self.filename` should be
assumed.
"""

__slots__ = (
'_id', # Unique keyword ID of the resource
'_filename', # Name of file from which this resource was last saved/loaded
'_loaded', # Loaded status (0=not loaded, 1=explicit, 2=implicit)
'_loads', # Number of times this resource has been loaded
'_depend', # List of the IDs of all dependencies
)

def __init__(self, ID=None, filepath=None, ext=None):
""" BaseResource initializer.

You may optionally omit either the ID or the filename, but not both.
The value present will be used in place of the value missing.

In the case of a missing ID but a present filename, the ID will be
the filename without any directory prefixes and without the
extension.

If the `ext` paramater is used, it will be added to the end of the
filename as its extension, but only if the filename was determined
from the ID.

Tip: When loading or stubbing many resources at a time from multiple
directories, it may be helpful to use the resource.chdir() function,
which adds a prefix to all filenames without changing the working
directory.

This should be called by subclasses.
"""
global _cwd

trueFName = filename
trueID = ID

# Subbing ID for filename
if ID is None:
# Fail if neither filename nor ID are present
if filename is None:
raise ValueError,'Must pass at least an ID or a filename.'
trueID = os.path.basename(filename)
trueID = trueID[0:trueID.find('.')]
# Subbing filename for ID
if filename is None:
if ext is None:
trueFName = ID
else:
trueFName = ID + '.' + ext
# Fill in the blanks
self._id = trueID
self._filename = os.path.join(_cwd,trueFName) # Add the cwd prefix
self._loaded = 0 # Not loaded
self._loads = 0 # Has been loaded 0 times
self._depend = [] # Default empty dependency table
# Attempt to register
register(self)

def add_depend(self, *deps):
""" Adds one or more dependencies to the resource's dependency list.
The dependencies should be resources or resource IDs. A duplicate ID
will raise error.ResourceError, as will attempting to use an object
which is not a dependency or string.
"""
for dep in deps:
if dep in self._depend:
raise ResourceError,'Duplicate dependency "%s" for resource "%s".'%(dep,self._id)
if isinstance(dep,str):
self._depend.append(dep)
else:
try:
self._depend.append(dep.id)
except AttributeError:
raise ResourceError,'Dependency %s is not a string and has no id property.'%dep

def remove_depend(self, dep):
""" Removes the given dependency from this resource.
Raises error.ResourceError if the resource does not depend on the
other resource.
"""
if dep not in self_depend:
raise ResourceError,'No dependency "%s" exists for resource "%s".'%(dep,self_id)
self._depend.remove(dep)

def depends_on(self, dep):
""" Returns whether or not this resource depends on the given resource. """
return dep in self._depends

def get_depends(self):
""" Returns a list of all resources this resource depends on. """
return self._depends[:]

def test_depends(self):
""" Make sure all dependencies exist.
Return True if all dependencies exist, otherwise False.
If recurse is true, also tests that dependencies of dependencies
are met, and so on.
TODO: Add recursive dependency checking capabilities
"""
for dep in self._depends:
if not get_exists(dep):
return False
return True

def load(self,implicit=False):
""" Loads the resource data explicitly (default) or implicitly.

Subclasses should overwrite this method to allow their data to be
loaded, but should also call this base method AFTER they do so.

Subclasses should not load data if it is already loaded.

If a resource depends on other resources it should load them
implicitly when this method is called.

Other resources depending on this resource should call this method
with implicit == True when they load it
"""
if implicit:
if self._loaded == 0:
self._loaded = 2
else:
if self._loaded != 1:
self._loaded = 1

def unload(self):
""" Unloads the resource data if it is loaded.

Also decrements the load count.

Subclasses should overwrite this method to allow their data to be
unloaded, but should also call this base method AFTER they do so.

In debug mode, a warning will be issued when this method is called
and there still seems to be other objects using it, or if the data
is not loaded.
"""
if self._loads > 0 and core._debug:
print "Warning: Resource '"+self._id+"' unloaded while still in use!"

self._loads -= 1

if self._loads < 0 or self._loaded==0:
if core._debug:
print "Debug Warning: Attempt to unload resource '"+self._id+"', but it is not loaded !"
self._loads = 0

self._loaded = 0

def unload_implicit(self):
""" Decrements the load count and calls self.unload() if it hits 0.

Returns whether or not the data was actually unloaded.

Does not unload data unless it was loaded implicitly!

In debug mode, a warning will be issued if this method is called
when the data does not seem to be loaded.
"""
self._loads -= 1

if self._loads==0 and self._loaded==2:
self._loads += 1 # This is to compensate for the decrement of the
# unload() method
self.unload()

# In subclasses, the `save` method would usually bed defined about here

def get_id(self):
return self._id

id = property(get_id, None, None,
""" (Read only.) The unique identifying string of the resource. """)

def get_filename(self):
return self._filename

def set_filename(self,v):
if not isinstance(v, str):
raise TypeError,'filename must be a string'
self._filename = v

filename = property(get_filename, set_filename, None,
""" The full path and name of the file to which this resource's data is
saved and from which it is loaded relative to the current working
directory of the program. Should be a string.
""")

def get_loaded(self):
return self._loaded

loaded = property(get_loaded, None, None,
""" (Read only.) The loaded status of this resoruce.
0 = Not loaded,
1 = Loaded explicitly,
2 = Loaded implicitly. The data of implicitly-loaded resources are
unloaded automatically when its load count hits 0.
""")

def get_loads(self):
return self._loads

loads = property(self._loads,None,None,
""" (Read-only.) Number of times the resource has been told to load,
minus the number of times it has been told to unload.
""")


Man, it would be nice if Blogger supported a code block feature...

Labels: , , , , , ,

7/18/08

Song Archive Uploaded

I have just uploaded my entire set of tracked modules, a whopping total of 73! I had no idea I had so many! I guess over the years they can really add up...

(Go to the Music section)

Anyway, because there were so many, I did not do a writeup for all of them. Instead, I added a simple script to the music page that will dynamically list all of the files in a certain directory.

Some of these songs are extremely old--I found a date stamp of 2003 on one of them. I have tried to sort them all in order of completion by using a 4-digit number in the filenames. However, I really don't know for sure what the order was; after all, some of these songs are over five years old.

Please check out some of these songs, at least the first few. I want to know what you think!

Labels: , ,

7/17/08

There Are No Dumb Questions

In my recent efforts at creating a data resource management system for my game engine I have entered #python several times to ask questions and get other's opinions. It has helped me so far, so I plan to continue.

The thing that most intrigues me about this experience is that even though I don't always get the answers that I was looking for I always seem to get what I really needed. Now, you may be thinking, "Well, duh, TMG! Those guys know Python--not to mention coding in general-- at least 1,000 times better than you do! " and that is almost always true. However, there is another thing that I have noticed, which has nothing to do with the experience of the experts: Simply talking about my problems helps me to solve them on my own, even when no one has an answer for me. I suppose its because putting enough mental effort to explain my code and ideas well enough that other people can understand them makes me see things from other angles, which in turn helps me to get a better grasp of the problem and therefore makes it much easier to see the solution.

I've known it for a while, but it seems that now that I've finally begun to utilize the social networking power of IRC the need for talking about my coding woes has become much more obvious. The key word in that statement is "begun." I've ONLY begun to really use IRC for practical purposes. I'm still fairly new to the world of IRC--and given my nonstandard perspective on practically everything at all, it will be a while until I really understand IRC. ^_^

That concludes my little rant. I hope you learned something useful that you can apply to your life, etc. etc. blah blah....

Labels: , ,

7/11/08

Heaven is Blue

AHHHHHHHHHHHHHHHHHHHHH!!!!!!! The impossible! The unthinkable! The mind-blowingly awesome! It can't be...yet it is!

All you folks out there who keep saying that Mega Man & Bass is the only "Mega Man 9" that exists...well, now there is UNDENIABLE PROOF TO THE CONTRARY!

I literally feel like jumping and screaming "WOOOOOOOOOOOOOOOOO!" at the top of my lungs. This got got to be the most insanely awesome thing that Capcom has ever done. It looks like they still love us after all...

Ok, here's what I've heard from other blogs, IGN, and the like...I'll probably mangle some of this information so go check it out yourself. Besides, for a lot of people, this is old news by now, but who cares, I'm posting it anyway. :P

First off, the Japan release in September. Speculators say that a US release should follow shortly after since there is obviously not going to be too much effort needed in translating. However, no official date has been set yet.

Next, the game is definitely coming out for WiiWare. Also, it looks like (according to the video) that it's also coming to Xbox Live and Playstation Network. I'm definitely getting the WiiWare version, even though there's a fresh new 360 in my house that just recently got online. Somehow it would just feel unnatural to play a game like this on anything but the Wii.

From what I hear, this game is based mostly on MM2, apparently because most fans said that was their favorite game in the original lineup. In fact, some of the lucky schmucks who got to play the unreleased game Personally, I thought 2 was okay, but not really my favorite. But then, I didn't actually play 2 until many years after conquering 3-8, with 3 being the first MM game I ever played...and fell in love with. :)

It looks like Dr. Light's shop is coming back. (Weird...but cool!) That means that many of the items that you had to "find" in the original series will be bought instead...but hopefully they will still have a few hidden items that you have to find in the stages.

The charge buster is only available from the shop as well--you don't actually start with the ability to charge. That's just cool. But from what I hear, you can't slide...darn. I liked the slide. However, GamesRadar (one of those lucky folk I mentioned) said that there are little tunnles strewn about that look like you should be able to slide through them, so who knows. Maybe it's a hidden ability, like the charge buster.

What amuses me the most is the range of responses that all the hype is getting. 4/5 people are like, "AWESOME!!! I can't believe they're actually doing this!" while the other 1/5 says "This is completely retarded. I can't believe they're actually doing this." All I can do is roll my eyes at the second group. Clearly you don't understand what this really is.

Anyway, W00T!! ^_^ ^_^ ^_^

Labels: , , , , , , ,

7/5/08

Using Pre-Fab Template for Blog

I realized that the Alphaios-resembling Blogger template that I wrote was severely lacking as a blog template. Rather than try to correct the many, many areas in which it falls short, I've decided to just use one of the existing Blogger templates instead. I picked a blue one because...well, I like blue.

You may notice that this new template isn't perfect, either. (For one thing, the sidebar covers up code blocks.) Well, I don't really care. So...there.

Labels: