Saturday, October 10, 2009

Setup for Succes

After nearly a decade of attempting to develop games, I have learned a few valuable lessons. Some of them are extremely basic, yet crucial, for anyone wanting to develop a video game, while some are more technical and for the more serious developer. Today I want to go over one a more technical lesson I have learned fairly recently.

From the very beginning, I was always a part of some game group project. Communication was hardly ever a problem; however, collaboration was almost always a problem. There was a continuous mess of making sure that everyone had the up-to-date map file, scripts ...ect. The problem grew exponentially with the size of the group. Anyone who has done a project in a group like this will know exactly what I am talking about. There is a solution to this though!

Source Control
(Subversion)
Source control is the key. I am sure that many developers have heard of this, but I imagine the more casual developer has not. I highly recommend this for anyone working on a project in a group. Subversion, aka SVN, is the most popular source control and is extremely useful. With it you can not only have a history of your revisions, but also be able to keep everything in one place, on the server, so that way it is easy for everyone to keep their project up-to-date.

I would write a tutorial on how to get this setup; however, there are lots of great tutorials out there that you can easily find via a google search. I know setting up a SVN server on Windows can be a little tricky if you don't know what you're doing. Ask if you have any questions and if enough people ask then I can write another post with some details.

Trac
Source control is a giant leap in setting up your project for success; however, it is only the start. Next on the list is something that will cover a gambit of potential hurdles. "Trac is an enhanced wiki and issue tracking system for software development projects." I am sure everyone has heard of a wiki before. They are immensely useful for documenting anything, even games that are being developed. I know I have seen several game projects that use a forum for keeping track of all of the game's details: storyline, characters, monsters, skills ...ect. With a wiki it is very simple to keep all of this data very organized and easily accessible by anyone on the team.

As mentioned, along with the wiki is an "issue tracking system" basically this system allows you to create "tickets" which can represent anything you want. Most commonly this is used for features and bugs. With a ticket created, lets say for a bug, you can assign it to someone and on that ticket have a discussion as well as keep track of the progress. When that bug is closed you can close the ticket. This goes along with Milestones you can create and attach tickets to. Tickets are very nice.

Trac can do much more than just this. It can be attached to a subversion repository and you can easily view the history of the changes as well as browse the source. You can easily add in new features and customize your Trac however you want. Trac Hacks is the best place to quickly to this. It is also easy to create your own since Trac is developed with Python.

Setting up Trac is easy thanks to the documentation. Here is a link to the different platforms and one directly to the windows since I'm sure most of you are on that.

Conclusion
I know that this is a lot to take in. I was there not too long ago. Getting Subversion and Trac setup will cost some overhead, especially if you have some difficulties like I did, but the time spent is nothing compared to what you gain.

The valuable lesson to take away from this is that having an environment that enables collaboration is not only going to make your life easier but may very well be the deciding factor in the completion of your project.

Thursday, October 8, 2009

DaB Gameplay

Following up my previous post, I wanted to give readers the general concept behind the gameplay for DaB. Here is an excerpt from the design document.

The main gameplay is playing a match. This is a 1v1 game of cards. Each player has 4 character cards, collectively known as a party, and a deck of other card types; Aer, Ability, and Item cards. An Aer card is played on a character (this is known as channeling), which enables the character to perform certain abilities. Such as the Aer of Health would give a character the ability to cast healing magic. Item cards are agnostic and consequently can be performed by any character at any time, but are generally weaker than their ability card counterparts. The objective of the game is to KO the opposing player's party.

DaB will follow the "always connected" methodology and require the player to always be connected to the online service that will be provided. Think of this online service as a mini battle.net. Through this service the player can match up on the ladder, with friends or take it solo in either practice (PvE) or story mode.

  • The story mode would consist of dialog scenes (2D backgrounds with character portraits). No actual character movement, everything is menu driven.
  • The online mode is where the major focus lies. With a matchmaking system in place the player is put in a match against another player with similar experience for competitive play. Players will be ranked but there are also unranked matches for playing with friends.
Hope you found this interesting. I will continue to provide more information about this project as development goes on.

Wednesday, October 7, 2009

The beginnings

It all began nearly 10 years ago. I was all so eager to begin making video games. With the trusty RPG Maker 2k (rm2k) program at my side I felt like I could take on the world! and I could... I just had to set up the scene...

Before too long I decided I was going to make an epic RPG. I planned to pull all of the stops with my game. The game was going to have an original mythology with at least a decent amount of history. To go along with the game's story, I designed several original gameplay systems (which I still think would be fun to play). Somewhere along the way I decided that I needed a card game inside my game. I figured why not, FF8 and FF9 were doing it. Also, subconsciously, I had to make sure I overwhelmed myself with as much work as possible - guaranteeing my game's demise.

I never completely fleshed out the card game concept, but I had a pretty rough idea of how it was going to work. Basically the player would have some sort of creature card they would have out in play. Then the player could use a card that would represent one of the Gods from the game's mythology. When played, this God card would modify the abilities of the creature. This is all I can really remember from it. I probably came up with more but in my old age I have a hard time remembering the days of my youth.

In May 2008 I decided I was going to develop a game. After some long and hard debating (that's what she said), I decided to revive my card game - at least what I could remember of it. In about a month and a half I came up with a good game design and even a very basic website. Things were going great and then came the avalanche of distractions; my wedding, FFXI and final year of college. FFXI was definitely the biggest one of them all. FFXI is to time as a Vampire is to blood. Needless to say, this project was put on the back burner.

Earlier this year I resumed game development, but on another game, Puni Puni Kingdom. After working on the game design for a few months we decided we needed a project that was more scalable. Puni Puni Kingdom required more overhead than we wanted for our first game. We wanted something we could get a basic build out before too long and build on top of it. That's when DaB(the card game) came back into the picture. Consequently we immediately switched projects and began working on DaB. This was all just a little over a month ago.

Stay tuned for followups!

*saved game*

Thursday, October 1, 2009

Belated update

Well, well, well, it looks like it has been awhile since I posted here. Two months to be precise. Much greatness has happened during this time. I have some catching up to do on here; however, I will take things one step at a time. For now I am going to just go over a few things that have been going on with my internship.

As I mentioned in my last post, I have been working at MokaFive for the last two months as an intern on the client team. During this time I have helped implement a few new features as well as help squash some little bugs - oh how they scurried. I have mostly been working with C++ and recently lots of WIN32 API, which I had managed to avoid all of these years. I have worked with so many different things it is not funny: drivers, services, GINA, credential providers, network stuff, cross-platform development, and the list goes on. I have also worked with some great tools like Boost, Doxygen (unfortunately minimal), Win32 (already mentioned...and maybe not so great) ...ect.

So far it has been a great experience at MokaFive. I have one month left, November 6th, there as an intern and then we'll see if I want to stay and if they will keep me. I think I know how things will go down but I wont say anything quite yet. Regardless, I am happy that I have been able to work with everyone there thus far.

Wednesday, July 29, 2009

Obtained: Job (Internship)

As most NPCs know by now, I recently began a new chapter in the story; my story. This chapter focuses on my recently obtained internship at MokaFive. To be completely honest when I first heard about MokaFive from a good friend that works there I was highly hesitant. My primary concern was that it was not a video game company. Sad news.

However, my interest in the position grew as I learned more about the company and the technologies I would be working with. As the interview process proceded I found myself more and more hopeful of being offered the job. This was all weeks ago.

Now, a week into the job, I am very pleased to say that it is a great place to work and for several reasons. The people are really friendly and are exceptionally intellegent with a large portion having a masters (or Ph.D.) from Stanford. One of the founders is even a CS professor from Stanford. The overall environment is relaxed and fairly casual but at the same time there is always something that needs to be done and it's seemingly crunch time often.

I am not clear on exactly all of the cool technologies that I am going to work with but to give you an idea. Last week I played around with a MSI file using Orca.exe and learned a great deal about the MokaFive product. This next week I am going to learn Python and SCons to help work on the build tools and I am also going to implement a Windows service into the product which is going to undoubted require me to use about five different things that I have never used before. Exciting!

The only downside to this internship is that I consequently have much less time. Project Euler problems are going to probably be fairly infrequent for now as well as my blog posts. I do want to continue to write about what I am doing at work as well as a juicy side project that I have yet to mention in this blog. Stay tuned!

*saved game*

Grind Report 30

Problem 30

Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits:
1634 = 1^(4) + 6^(4) + 3^(4) + 4^(4)
8208 = 8^(4) + 2^(4) + 0^(4) + 8^(4)
9474 = 9^(4) + 4^(4) + 7^(4) + 4^(4)

As 1 = 1^(4) is not a sum it is not included.

The sum of these numbers is 1634 + 8208 + 9474 = 19316.

Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.

*WARNING: This contains the solution!*

This was a fairly simple problem. My approach was extreme brute force using some recursion. I first consider every possible number with one digit, then two digits and so on. Every number I consider I check to see if the number matches the criteria for being a special number.

As I look back at my solution I think that recursion was probably not the best method but I'll let it stay as it is.

One important thing to do in this problem is precalculate the digits to the 5th power and store them in an array. This is somewhat obvious but still helps cut down the cost.

#include <iostream>
#include <vector>
#include <math.h>

using std::vector;
using std::cout;

const double N = 5;
const int MAXDIGITS = 6;

vector<int> nthpow;
int solution;

void CheckDigitCombinations(int digitCount, int digitTotal, int num, int sumOfDigits);

int main()
{
//precalculate the nth power of all single digits [0-9]
for (double i = 0; i < 10; ++i)
nthpow.push_back((int)pow(i, N));

for (int digitCount = 1; digitCount <= MAXDIGITS; ++digitCount)
CheckDigitCombinations(digitCount, digitCount, 0, 0);

cout << solution;
}

void CheckDigitCombinations(int digitCount, int digitTotal, int num, int sumOfDigits)
{

for (int digit = 0; digit < 10; ++digit)
{
int number = num;
int sum = sumOfDigits;
if (digitCount == digitTotal && !digit)
continue;
//add on the extra digit (doesn't change anything for digit #1)
number *= 10;
number += digit;
sum += nthpow[digit];
if (digitCount > 1)
CheckDigitCombinations(digitCount - 1, digitTotal, number, sum);
if (sum == number && sum != 1 && digitCount == 1)
solution += number;
}
}

*saved game*

Grind Report 29

Problem 29

Consider all integer combinations of a^(b) for 2 <= a <= 5 and 2 <= b <= 5:
2^(2)=4, 2^(3)=8, 2^(4)=16, 2^(5)=32
3^(2)=9, 3^(3)=27, 3^(4)=81, 3^(5)=243
4^(2)=16, 4^(3)=64, 4^(4)=256, 4^(5)=1024
5^(2)=25, 5^(3)=125, 5^(4)=625, 5^(5)=3125

If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by a^(b) for 2 <= a <= 100 and 2 <= b <= 100?

*WARNING: This contains the solution!*

While attempting this problem I came up with two solutions - but only one actually completely worked... As usual, using C++ runs into some problems here because of the limitation on integer size.

My first solution (the semifunctional one) placed the focus on the repeated terms. I used the fact that an exponent can be broken up such as

2^32 = (2^4)^8 = 16^8

With this it is possible to find which terms are repeated without ever actually calculating the value of a^b. So with this it is easy to simply keep a boolean collection of the different combinations and if one has been encountered before. Such as in the example above when 2^32 (a = 2, b = 32) is run it will see that this is equal to 4^16 and 16^8. Consequently [4][16] and [16][8] both need to be marked as repeats. At the end it is as easy as counting the repeats and subtracting them from the max number of possible terms (99x99).

Here is the code but keep in mind that this code does not return the correct answer. While attempting to debug the solution I came across another, much simplier, solution. That I'll discuss after this.

#include <iostream>
#include <vector>

using std::vector;
using std::cout;

int PowerWithinMAX(int a, int b);

int main()
{
vector<vector<bool>> encountered;
//create the list of encountered combinations - vector<vector<bool>>
for (int i = 0; i < MAX + 1; ++i)
encountered.push_back(vector<bool>(MAX + 1, false));

int repeatCount = 0;
for (int a = MIN; a <= MAX; ++a)
{
for (int b = MIN; b <= MAX; ++b)
{
//if a^b has previously been encountered before
//then increment repeat count and continue
if (encountered[a][b])
{
++repeatCount;
continue;
}
//check to see if b can be broken up into pieces
//ie. 2^32 = (2^4)^8 = 16^8
//if so then mark that as being encountered ([16][8])
for (int i = 2; i < b / 2; ++i)
{
//if i is a divisor of b
if (b % i == 0)
{
//check to see if the power is within the max
int c = PowerWithinMAX(a, i);
if (c)
encountered[c][b / i] = true;
}
}
}
}
int ans = 0;
for (int i = 0; i <= MAX; ++i)
for (int j = 0; j <= MAX; ++j)
if (encountered[i][j])
++ans;

int answer = (MAX - MIN + 1) * (MAX - MIN + 1) - ans;
cout << answer;
}

int PowerWithinMAX(int a, int b)
{
int solution = 1;
//calculates a^b until solution is > 100
while (solution <= MAX && b > 0)
{
solution *= a;
b--;
}
//if b > 0 (true) then the solution is greater than MAX
if (solution > MAX)
return 0;
else
return solution;
}

The working method using some more standard library goodness to take care of mostly everything. Every possible combination of a^b is calculated using pow(a, b) and then stored into a set. Once done the set.size() is the unique number of terms. The reason why this works is that when using double it is true that it is not precise enough to give the correct term, but it is precise enough that all terms are unique unless they are actually a repeated term.

Because this is so simple the code is pretty small.

#include <iostream>
#include <set>
#include <math.h>

using std::set;
using std::cout;

const int MIN = 2;
const int MAX = 100;

int main()
{
set<double> answer;
for (double a = MIN; a <= MAX; ++a)
for (double b = MIN; b <= MAX; ++b)
answer.insert(pow(a, b));
cout << answer.size();
}

I will probably go back and fix up the first solution and get it working eventually. I am curious what the problem with the algorithm is. In the meantime I'll continue to move onward.

*saved game*