Categories
Personal Development

It’s My Fault I Bought A Bad Product

I talked previously about how I enjoyed listening to the audio book “100 Ways to Motivate Yourself” by Steve Chandler. I really liked how much I learned from listening to a tape while driving. So I recently bought another audio book called “Develop a Super Memory Auto-matically”. I didn’t know about it previously, but I saw it when I was at Barnes & Noble. I’m interested in learning how to remember things more consistently and clearly.

This audio book, however, was not one I should have bought. Here is a break down on how the tape runs:

  • “Hi, welcome to the tape. First, to increase your memory, stop saying you have a bad memory. You need to believe you can have a good memory.”
  • Lame music with positive affirmations you’re supposed to repeat to yourself.
  • “Forgetting someone’s name isn’t because of bad memory but because you weren’t paying attention or focused.”
  • Lame music with positive affirmations you’re supposed to repeat to yourself.
  • Fake conversation with other host: “I can remember student names within the first hour of a new class.” “Wait a minute, Bob, are you blah blah blah blah seriously?” “Why, yes, Diedre, blah blah blah I’ll give you the secret but first let’s have more positive affirmation time.” “Ok!”
  • Lame music with positive affirmations you’re supposed to repeat to yourself.
  • “The secret…No, wait, just a description of the secret’s results. Let’s take an affirmation break.”
  • Lame music with positive affirmations you’re supposed to repeat to yourself.

And so on. I plan on finishing the tape, even though the big secret isn’t really a secret. I’ve read about associating a number with a specific item, such as 1=T/Tea, 2=N/Noah, 3=M,May, etc. And I’ve read that making absurd images and using other senses help you to remember. If anything redeems itself, it is the fact that the tape talks about this “memorizing lists” technique in a more natural pace than what I’ve read. I can actually see myself making use of this technique.

Still, it’s an audio tape. If I feel the need to reaffirm that I have the ability to remember things, I’ll rewind to listen to an “affirmation break” from the beginning. I don’t need it strewn throughout the tape, interrupting the flow of learning. What really ticked me off was hearing the author say something like, “We usually use 30 items, but due to time constraints, we’ll only use 16.” Time constraints?! Maybe if you didn’t waste most of the tape with affirmations, you would have more time!

I’m fairly upset about it, but I have to realize that it is my fault that I wasn’t informed. In an age where reviews of any product by anyone in the world are easily available, I made a reckless purchasing decision. I would have seen that other people were also turned off by the repeated and mostly unnecessary affirmation breaks. I say mostly because I can see why the affirmations would be useful. Believing you can remember things well is necessary to learn how to remember things well. Still, did we really need to go through the affirmation breaks so many times?

I will no longer make impulse purchases without knowing something about the product first. I will probably pick up Mega Memory next time.

Categories
Geek / Technical

Stupid Hypotheticals While in Line for Star Wars

While I was waiting in line for the new Star Wars movie last night, I posed this joke of a question: who would win in a fight, Voldemort or Vader?

Funny, right?

Well my girlfriend and our friend started discussing it. Seriously discussing it. They concluded that Voldemort would win since he only had to say something to kill Vader. I protested that Vader would do his patented choke-from-across-the-room Force move, rendering Voldemort speechless.

How did I get sucked into arguing about this?! It was a joke! I was poking fun at the die-hard fans who would ask such questions! After a few calls, we had three people for Voldemort and two for Vader. Whatever.

So then I said, “Dumbledore or Yoda?” That one I left alone, and I don’t know if they concluded anything. But “Luke Skywalker and Harry Potter? No, they’d fight on the same side!”

Oh, and the movie was great.

Categories
Geek / Technical Linux Game Development

Wine Talk

This Thursday I am giving a talk on using Wine to run Windows applications on Linux. Wine stands for Wine Is Not an Emulator. It is an implementation of the Win32 API, which means applications run at a normal speed compared to running them in actual emulators like VMWare.

That is, if they run properly. Wine is still not at version 1.0, which means that nothing is expected to work. Still, a great many apps are available as can be seen in the Application Database.

My first test was to install Starcraft. I found a few how-tos, but they aren’t terribly consistent, and it seems that the authoritative document is years old. Fortunately it wasn’t hard to install and run. The only problem I’ve found is that Battle.net isn’t usable. I get a black screen and the mouse cursor disappears so I can’t join in games. Cedega is a fork of the Wine code that was made into a closed source app. It was previously called WineX. It’s database lists Starcraft as highly rated and doesn’t mention the Battle.net problem. Still, I am not ready to shell out $5/month just to have Windows games I’ve already paid for running on my Gnu/Linux system, especially when some months I don’t get to play said games, and especially when there are plenty of native apps already. Also, it seems that newer versions of Wine tend to break the feature whenever it is available. I’ll wait.

My next test was Wizardry 8. I love the Wizardry series, and I feel bad that I haven’t played 8 very much. It works perfectly according to the Wine application database, so I set out to install it. I had forgotten how long it took to install this game! This is one of those 3 CD games which take up a lot of space on my hard drive. At 50% I had already added 1GB to my home directory (well, including Starcraft and the rest of Wine, but still).

Unfortunately when I try to run it, Wizardry 8 thinks I am running a debugger and wants me to stop doing so. I ended up having to find a no-cd crack in order to play this game, which goes to show you how annoying copy protection can be for legitimate owners of games. In the end, I managed to get it to play and aside from a few sound cracks during the opening video, it ran flawlessly. I am very pleased but I wish I didn’t have to go looking for a No-CD crack to play. Still, it shows a legitimate use of what would otherwise be considered illegal under the DMCA.

And Total Annihilation’s setup program wouldn’t even run on the version of Wine that I was using (20050310).

Wine just isn’t ready yet, but then no one pretends it is. Still, I have the ability to play one game as it was meant to be played, and another one works fine in single-player mode. Total Annihilation was possible at one time, so I can look forward to it in the future, I’m sure. Not bad for an incomplete project.

I’ve updated the Wine-Wiki for Wizardry 8, Starcraft, and Total Annihilation. Someone else already added their own comments about Starcraft. Wikis rule.

Categories
General

Day[24]; // off by one errors

When I was really young, I remember the first time I learned that the first hour of the day started at midnight. It was weird realizing that time moved in this sequence: 10PM, 11PM, 12 AM, 1AM, etc. Thinking about it for awhile, I realized it made sense.

To this day, the border between one day and the next throws people off. I like to think of it as an array of hours.

hours Day[24];

So now I have an array of hours called Day. The first hour is hour 0, and the last hour is hour 23. Translated into actual time: if it is after 12AM, you have entered into the next day.

Why am I bringing this up? Because I recently bought tickets for the latest Star Wars movie, and I bought them for opening night. My ticket says very clearly “Wednesday 12:01AM 5/18/2005”. I haven’t been paying attention to when opening night was supposed to be for the world, but I thought that I could trust my ticket. I received a call from my girlfriend today. She informed me that the movie is tomorrow night and not tonight. I think it is absurd, but she worked in a movie theater before and insists it is true.

So I walk to the theater. I ask a few of the desk workers if it is true that the movie isn’t playing tonight but is instead playing tomorrow.

“Yes.”
Why?
“Because it is Wednesday.”
But TONIGHT is Wednesday. TONIGHT is when it is 12:01AM on Wednesday.

At that point, one of them claims to have warned some manager about people getting confused about this issue. The other workers just apologize and say that it is meant to be Thursday morning, Wednesday night. As if them telling me that makes it alright now. One apologizes because that’s how the computer printed them out. As if some person didn’t make the computer do that. One reassures me that I’ll be able to get in tomorrow, as if that was my concern.

The ticket says one thing, but they “meant” another. I’ve been fairly upset about it all afternoon. I drove in today instead of taking the train since I knew I wouldn’t be back at a reasonable hour. I planned on using tomorrow to work on my presentation. Now because I was supposed to just know what they meant, I can’t work on the presentation tomorrow, and I didn’t get started on the presentation today until I got home hours later than I normally would have.

So tomorrow I will be going to a movie a day after what the ticket says. Imagine if the bank or your job worked this way. Direct deposit goes through on Friday? Nope. It’s actually Saturday. Father says to daughter, “Be home by midnight” only to find out that she is gone for a day longer than he thought she should be.

If the movie is 12:01AM on a Wednesday, it means I need to leave my house on Tuesday to make it in time. Unless you’re the movie theater, in which case it means you need to leave on Wednesday night, almost a full day after 12:01AM. GAH!

Categories
Geek / Technical General

DePaul Linux Community Install Fest

May 14th, this Saturday, will be the DePaul Linux Community Install Fest. It’s open to everyone, so if you’re in the Chicagoland area, check out the information on DLC’s website. Here’s a handy map to the event.

Categories
General

Learning Kyra: Hit Detection

The Learning Kyra series to date:

  1. Learning Kyra
  2. Learning More Kyra
  3. Learning Kyra: Attack of the Clones
  4. Learning Kyra: Tiles and Z-Ordering

I covered collision detection already, but it was in a limited capacity in Attack of the Clones. Basically, I checked if a sprite was colliding with a specific object. But what happens when I want to check for collisions with objects that have been added dynamically and prevent me from anticipating them at compile time?

The code below creates a number of sprites from the same resource. Kyra comes with the Grinning Lizard Utilities, so those are prefaced with Gl. I think that it makes it confusing if you want to mix your code with OpenGL, but whatever. One of the utilities is GlDynArray, which acts very much like the C++ Standard Library’s vector class. While it is in the provided demo code, I couldn’t find any mention of it in the documentation. I simply followed along with the demo in shooter.cpp. I created an array and added 10 ghost sprites to it. In the code below, MAX_GHOSTS is equal to 10. I also add those sprites to the tree.

KrSpriteResource* ghostRes = engine->Vault()->GetSpriteResource(GHOST_ghost);
GLASSERT( ghostRes );

KrSprite* ghost = new KrSprite( ghostRes );
ghost->SetPos( GHOST_START_X, GHOST_START_Y - 64);
engine->Tree()->AddNode( midgroundTree, ghost );

GlDynArray< KrImage* > otherGhost;
for (int i = 0; i < MAX_GHOSTS; ++i)
otherGhost.PushBack( new KrSprite( ghostRes ));
for (int i = 0; i < (int)otherGhost.Count(); ++i) {
otherGhost[i]->SetPos( GHOST_START_X, GHOST_START_Y );
engine->Tree()->AddNode( midgroundTree, otherGhost[i] );
}

So now I have a bunch of ghosts bunched up in the center, which is where GHOST_START_X, GHOST_START_Y sets them. I placed the player’s ghost about two tiles higher. Since I was going for simplicity, and I mostly hacked out this code without designing it first, I just made the sprites in otherGhost move around randomly. Another utility is GlRandom, which provides random number generators that are superior to rand() provided by C++. The following code demonstrates how I used it:

GlRandom random;

...
//the following is in the main loop
for (int i = 0; i < otherGhost.Count(); ++i) {

...
otherGhost[i]->SetPos( otherGhost[i]->X() + (random.Rand(3) - 1) * moveSpeed , otherGhost[i]->Y() + ( random.Rand(3) - 1) * moveSpeed);

...
}

So now each of the sprites in otherGhost move in random directions. I move the original ghost much the same way as I moved my clone sprite in previous Learning Kyra entry. Well, there is movement for the player and other objects, but what about collision?

if (engine->Tree()->CheckSiblingCollision(ghost, &hit, 0) ) {
for (int i = 0; i < (int)hit.Count(); ++i) {
engine->Tree()->DeleteNode(hit[i]);
int j = otherGhost.Find(hit[i]);
otherGhost.Remove(j);
}
if (otherGhost.Count() < 1 )
done = true;
}

Very simply, if the main ghost collides with any of the other ghosts, those ghosts disappear. When the last one disappears, the main loop ends, and since I hacked this out instead of designing it, so does the program. Still, it is game-like. I experimented with other options to see what else I could do.

Instead of removing the ghosts from the tree, you could make them stationary, sort of like in Freeze Tag. As they get hit, I remove them from the otherGhost vector to keep them from moving about, but I also added the following to fade them a bit:

KrColorTransform color = hit[i]->CTransform( 0 );
color.SetAlpha( 50 );
hit[i]->SetColor(color, 0);

While it isn’t fun or polished in any way, I don’t think I can expect too much more from this specific project, at least not without struggling through painful changes. I didn’t set specific goals so the project simply evolved. I’ll consider this project complete and move on to a new project that will benefit from my new experience and some better design. You can download the project as it stands from one of the links below:


KyraGame-r1.tar.gz
KyraGame-r1.zip
Kyra Source in .tar.gz format
Kyra Source in .zip format

NOTE: You will need Kyra v2.0.7 to use this code. Also, the comments in the code weren’t all updated to reflect the fact that I’ve changed it. It is licensed under the GPL or LGPL as specified.

Categories
Geek / Technical

Snapback2 How-To

Not too long ago I created my own automated backup script. Shortly afterwards, helpful people sent me links to other, more robust scripts that have been written. One of those was called Snapback2.

Snapback2 is a backup script based on rsync and hard-links. I could explain what that means, but why reinvent an already well invented wheel? Again?

My original script was alright, but it worked by making an exact copy of everything each time it ran. For my 4 GB home directory, backing it up weekly over the course of a month would result in a backup directory that is 16-20 GB in size! That’s a lot of wasted space, especially when some files don’t change at all.

Snapback2 uses hard links and only stores changes between one backup to the next, which means that if I only changed files that were 30MB in size, then the next backup will be 30MB as well. If no changes were made, then no space is wasted at all. Clearly this method is superior to what I have written.

Setting up Snapback2 is supposed to be very simple, but I found that the documentation assumes you know what you’re doing. The following is my Snapback2 How-To:

You can download Snapback2 at http://search.cpan.org/~mikeh/Snapback2-0.5/ for the latest version as of this writing. Technically you should be able to use Perl to download it from CPAN, but I didn’t. Most of the prerequisites should be on your Linux-based system already. According to the documentation, you’ll need:

Gnu toolset, including cp, rm, and mv
rsync 2.5.7 or higher
ssh
Perl 5.8 or higher
Perl module Config::ApacheFormat

On my Debian Sarge system, I have rsync 2.6.4, so your distribution will likely have at least 2.5.7. Similarly, I have Perl 5.8.4. The one thing that you need to do is get and install Config::ApacheFormat. To do so, make sure you have root privileges and run:

# perl -MCPAN -e 'install Config::ApacheFormat'

If it is the first time you’ve used CPAN through Perl, you will be prompted to configure it. If you aren’t sure, you can simply cancel the configuration step and it apparently grabs some defaults just fine. Any and all dependencies will also be installed.

Once you have all of the prerequisites, you can install Snapback2. Again, you could probably do the same thing above to grab it from CPAN, and it will probably grab Config::ApacheFormat for you, but as I didn’t do that, I won’t cover it here.

If you grabbed the tar.gz file from the link I provided above, you should run the following:

# tar xzf Snapback2-0.5.tar.gz

It will create a directory called Snapback2-0.5. The README tells you what to do, but for completeness, here are the next steps:

# cd Snapback2-0.5
# perl Makefile.PL
# make
# make test
# make install

Snapback2 should now be installed on your system. If it isn’t, you should double-check that you have all the prerequisites. The fourth line in the previous list runs tests before installing. If something failed, you should know why from the test results. Even if you did install it successfully, it isn’t going to do anything yet. You now need to make a configuration file.

You can read the documentation setting up the configuration file in the man page for snapback2, but you can also view it online.

Here is my file, snapback.conf:

Hourlies 4
Dailies 7
Weeklies 4
Monthlies 12
AutoTime Yes

AdminEmail gberardi

LogFile /var/log/snapback.log
ChargeFile /var/log/snapback.charges

Exclude core.*

SnapbackRoot /etc/snapback

DestinationList /home/gberardi/LauraGB

<Backup 192.168.2.41>
Directory /home
</Backup>

I didn’t change it much from what was in Snapback2-0.5/examples. I installed Snapback2 on the machine called MariaGB. MariaGB will connect to 192.168.2.41, which is the IP address of my main machine called LauraGB. This is why the DestinationList refers to LauraGB. If I wanted to backup another system, say BobGB, I would keep those backups separate in their own directory called BobGB. Normally, the ssh/rsync request would ask for a password. When I setup the backups to run automatically, it won’t be useful to me if I need to be present to login. You can do the following to create a secure public/private key pair:

$ ssh-keygen -t rsa

The above line will create keys based on RSA encryption, although you could alternatively use DSA. You will be prompted for a passphrase, which is optional. Still, a good passphrase is much better than no phrase at all. Using the defaults, you should now have two files in your .ssh directory: id_rsa and id_rsa.pub. The first one is your private key. DO NOT give it to anyone. The second one is your public key, which you could give to anyone. When setting up key-based authentication, you will append the contents of this file to the server’s .ssh/authorized_keys file. Next time you login, instead of being prompted for a password, you will find yourself at a prompt, ready to work. For more detailed information, read this document about using key-based authentication with SSH.

So now, if I run the following command on MariaGB:

# snapback2

It will backup any changes from LauraGB’s /home directory to MariaGB. If, however, it hasn’t been an hour since the last backup, it won’t do anything.

Still, manually running this command isn’t very useful, and while I could install a cron job to run snapback2, I will instead make sure that snapback_loop is running. It acts as a daemon, checking to see if a file gets created in /tmp/backups. Now I can create the following entry in my crontab:

# Create file for snapback_loop to run
0,30 * * * * touch /tmp/backups/snapback

So now, every 30 minutes, I create the file /tmp/backups/snapback, which snapback_loop will take as its cue to delete that file and run snapback2. Then snapback2 will make a backup if there has been enough time since the last backup was made.

Now, I have automated backups that run regularly. Some caveats:

  • Verify that snapback2 is in /usr/local/bin. On my system, snapback2 would run manually, but snapback_loop would output errors to /tmp/backups/errors that weren’t too clear. I had to create a symlink to /usr/bin/snapback2 in /usr/local/bin in order to get it to run.
  • Make sure snapback_loop is running with root privileges. It has to call snapback2, which will need access to files in /var/log and other directories which will have restricted access. If you run it as a regular user, you may get errors. You could also change the location of the log file, but /var/log is a standard spot to keep such output.
  • Because you are running it with root privileges, you’ll need to make sure root is the one with the public key in authorized keys rather than your user account. Otherwise, you’ll get errors like “permission denied” when rsync tries to connect to the other machine.

If you don’t use a second computer, you can always use a second hard drive instead. Either way, you now have an effortless system for automating your backups!

Categories
General

Learning Kyra: Tiles and Z-Ordering

Another entry in the Learning Kyra series. The series to date:

  1. Learning Kyra
  2. Learning More Kyra
  3. Learning Kyra: Attack of the Clones

The first three entries in the series documented my attempts at learning about the engine. I had a goal to become more familiar with the engine by the end of the month, so those articles were more focused. While that month has since passed, I am still learning plenty about the engine.

Recently I learned how to create tiles. Originally I was creating sprites, and they are sufficient for making games. However, I can also use tiles, but the documentation warns:

A Tile — in contrast to a sprite — is always square (width == height.) It can be rotated and flipped, however. You should always use Sprites unless you need to rotate and flip the image.

Making sprite images and making tile images are similar activities. When I use the Kyra Sprite Editor, I need to specify tile instead of sprite. Tiles are simpler since I do not need to mark hotspots and verify that they are aligned correctly. I was able to get three tiles very quickly, and saving created the .xml file to use. Then I used the Kyra Encoder and created the appropriate .dat and .h files. I copied those over to my source code directory.

The code to load a tile is different from the code to load a sprite, and the tutorial doesn’t cover it. I had to look at the Bug-Eyed Monster (BEM) demo code to find an example that I could use. To load a sprite, you have to do a few steps:

  1. Load the .dat file
  2. Get the KrSpriteResource as specified in the header file you created
  3. Create the KrSprite from the KrSpriteResource

Loading a tile is a little more complex:

  1. Load the .dat file
  2. Get the KrResource
  3. Get the KrTileResource by using KrResource::ToTileResource()
  4. Create the KrSprite from the KrTileResource

Ok, so there is only one more step, but it took me some time to find how to retrieve a KrTileResource. For instance, to get the KrSpriteResource, there is a function: GetSpriteResource(name_of_resource). To get a KrTileResource, however, you first need a generic resource by using GetResource(ALLCAPS_TAG, name_of_resource), and I couldn’t find the documentation on what that tag should be. It turned out that they were defined in kyraresource.h, and the one I needed was KYRATAG_TILE. Again, it was not in the tutorial so it took some work for me to learn what was needed. Here is the relevant code, keeping in mind that when I used the encoder, I prefaced everything with Tiles2_ (I already had a previous attempt with Tiles_) :

KrResource* res = engine->Vault()->GetResource( KYRATAG_TILE, Tiles2_tile2 );
GLASSERT( res );
KrTileResource* tileRes = res->ToTileResource();
GLASSERT( tileRes );
KrTile* tile = new KrTile( tileRes );
GLASSERT( tile );

tile->SetPos( 130, 98 );
tile->SetRotation(1);
engine->Tree()->AddNode(0, tile);

Anyway, I imagined that the tiles I created would be pretty cool to work with since they have alpha transparency. I could make clouds or chain-link fences, for instance. As I moved a sprite to the tile, I expected that the sprite would show through the tile’s transparent spots; however, when adding an image to the engine’s tree, the order matters. Since I added the sprite after the tile, the sprite image overlapped the tile image. I switched the order in the code, and it worked perfectly fine.

But then I was concerned. In a game, elements will get added dynamically. I wouldn’t want to find that a new enemy can walk over tunnels, or that the hero walks under floor tiles! Then I learned how the BEM demo handled Z-Ordering.

Everything that can be in the engine’s tree inherents from the base class KrImNode. KrSprite and KrTile are both KrImage classes, and KrImage is a KrImNode. KrImNode isn’t an abstract class, and it is the key to handling Z-Ordering.

Usually when I add a sprite or tile to the engine, I use the following code:

engine->Tree()->AddNode(0, tile);

AddNode()’s first parameter in this case is 0, which means that in the tree, it is a child of the root. If I add a second child, it will be drawn over the first child when the following code gets run:

engine->Draw()

BEM handles Z-Ordering by creating subtrees. Background images should be added to the backgroundTree while foreground images should be added to the foregroundTree. You create those trees in the following way:

KrImNode* backgroundTree = new KrImNode;
KrImNode* foregroundTree = new KrImNode;

engine->Tree()->AddNode(0, backgroundTree);
engine->Tree()->AddNode(0, foregroundTree);

Now, when I create a tile that goes in the background, I use AddNode(backgroundTree, tile1). Naturally I would have a separate subtree or two for entities I want to always be between the background and the foreground. If I need to create tiles for the foreground, I can add them to the foregroundTree:

engine->Tree()->AddNode(foregroundTree, tile2);

And tile2 will always be drawn on top of any images that are siblings to tile1, even if I add an image to backgroundTree after adding tile2.

Now that tiles and the Z-Ordering methods are added to my toolbox, I’m becoming much more dangerous with the Kyra Sprite Engine. Using just what I know now, I can probably make a fairly simple game without struggling with an unfamiliar library. There are still a few features to learn, however, including:

  • Fonts
  • Alpha blending and color transformations
  • Scaling
  • Canvases
  • Sub-window views

I may tackle one or two of these in the next Learning Kyra post.

Categories
General

Reading in 2005

Earlier this year, I noticed some developers are making book lists on their blogs. Sillytech and Joost Ronkes Agerbeek’s lists are two of them. I have been keeping a private list of books I am reading and have read, but I think it will be useful to post the list online as well.

I plan on having a sidebar similar to what is on Games From Within. In the meantime, you can see a listing in this blog post.

Books I Am Currently Reading

  • On Writing by Stephen King

Books I Have Read in 2005

  • 100 Ways to Motivate Yourself by Steve Chandler (Audio Book)
  • Alice’s Adventures in Wonderland by Lewis Carroll (ebook)
  • C++ Coding Standards by Herb Sutter
  • The Curious Incident of the Dog in the Night-Time by Mark Haddon
  • First Things First by Stephen Covey
  • Getting Things Done by David Allen
  • Live Without a Net by Lou Anders (Editor)
  • The Object-Oriented Thought Process by Matt Weisfeld
  • Ready for Anything by David Allen
  • The Seven Habits of Effective People by Stephen Covey
  • Through the Looking Glass by Lewis Carroll (ebook)

Some people try to read at least one book a week. It’s the 18th week or so for the year, so I am about six books behind. I never actually set such a goal, of course, but I should. I’ve found that I can have much more intelligent conversations and tell much funnier jokes (at least to me) since I’ve started reading regularly. I have learned so much more than I would have if I had neglected the literature, and some of it, such as Getting Things Done, has changed my life in amazing ways.

I’ve found that I’ve been focusing on personal productivity a bit too much, so I’ve tried to add works of fiction to the mix. Besides science fiction, I’m interested in mystery novels as well, but I am not familiar with what is good outside of Sherlock Holmes and Hercules Poirot. Anyone have any suggestions?

Categories
Game Development Personal Development

Goals and Habits: Program for 5 hrs/week

Since I think coding practice should be a higher priority in my life, I’ve scheduled two days out of the week to program. Monday and Tuesday evenings after work, I will spend at least two hours programming. Four hours of the week can easily be accounted for there, and I could always do more on those days and others.

Previously I assumed I could squeeze time out of my week to program, but since I didn’t have any hard rules about it, I never did it. The thinking was that I could always program “tomorrow”, and of course tomorrow always had its own excuses.

Eventually procrastination became a habit. If I did have time in front of my computer, I ended up checking email or configuring something that I didn’t need to configure at that moment. Even now I catch myself getting distracted too easily during my programming time. I find myself trying to check my email or reading blog entries and have to force myself to continue programming.

Breaking old habits is hard, as everyone knows. I recently bought Steve Chandler’s 100 Ways to Motivate Yourself audio book. I listen to it in the car and am amazed at how much education you can get in a 30 minute drive. One of the things he talks about is breaking bad habits. He says we can’t simply drop bad habits. We must replace them with better habits. In my situation, I simply need to get my mind to think that it is time to program whenever I am in front of my computer instead of having it think that it is time for recreational web browsing. He also talks about will power and the need to exercise it. The more we practice control, the stronger our will becomes. The two tips go hand in hand.

Each time I refuse to check my email during my designated programming times, I get that much closer to replacing habitual time wasters like useless email and web browsing with habitual productive activities. Building will power in this way applies elsewhere. For instance, each time I make myself check my calendar before making a committment, the more useful and powerful my calendar becomes. Each time I check my lists when I am deciding on my next action, the more important my lists become to me, which means I’ll use them more.

Creating good habits and getting rid of old ones is great for accomplishing goals. If I make a regular habit of programming each day, I simply have to hit my goal for the week, and therefore I can’t NOT hit my goals for the month. As Chandler says, “It’s mathematical.”