Galactic Fire FREE – Advertising networks on Windows Phone 7

[cross-posted from my blog!]

While researching ad networks on Windows Phone 7 for Galactic Fire FREE, it became clear that ad network support for Windows Phone 7 is a bit fragmented depending on which tech stack an application is written in. Silverlight-based applications have several options for ad networks, and XNA-based applications have… well, fewer options.

The first (and last!) ad network I implemented was PubCenter advertisements. During evaluation of PubCenter, I was unhappy with the format of the ads being served (480×80 banners for a full-screen ad?), the relevance of ads (trucker jobs in England? srs?), and the fact that the portal doesn’t support WebKit-based browsers.

I also evaluated AdMob, which seemed to be an incredibly clear winner. Unfortunately, AdMob didn’t have support XNA titles, so I was out of luck there.

An interesting ad exchange network that did have support for XNA was AdDuplex, in which developers exchange advertisements in their game for advertisements in your game. The monetization model is different in that there is no indirect ad revenue. A developer in the program show 10 ads for someone else in their game, and the developer’s game is shown 8 times in someone else’s game. I’ve seen this recommended a number of times, and may yet experiment with this model, but direct sales of a non-established brand appear to be pretty abysmal, and this model drives only direct sales.

PubCenter, being a Microsoft ad network, had client binaries for WP7 XNA titles and had a monetization strategy that was more in-line with my goals. In the end, the advertisements seen in-game come from PubCenter.

Galactic Fire – Leaderboards, analytics and more for Windows Phone 7 games

[crossposted from my blog]

Hi all! Hijacking a bit of your time to discuss leader boards and analytics in the indie game space.

Throughout casual play testing, one of the recurring feature requests for Galactic Fire (now available on the Windows Phone 7 Marketplace!) was leaderboards. Initially, one could only compete with themselves for a high score on the local device and, while appealing, it doesn’t necessarily capture the same competitive edge as seeing how one ranked world-wide. Leaderboards sounded like fun, and folks wanted to see how they compared to other players in the office.

Being overzealously protective of my spare time, I dismissed the idea of leaderboards. The game was more or less feature complete, was already for sale in the WP7 Marketplace, and I didn’t want to build or maintain a leaderboard service. Even once it was built, I’d have to cover hosting costs, troubleshoot uptime and availability issues, and it sounded like a bunch of problems I ultimately didn’t have time for.

One of the key differentiating features between Galactic Fire and its free/trial counterparts ended up being work that I didn’t have to do at all, and that’s largely thanks to a service called Mogade. Mogade advertises “free solutions for casual game developers“, and one of the free solutions happens to be leaderboard support with corresponding Windows Phone 7 client source and binaries.

As far as I can tell, Mogade is a small handful of folks learning and building services for an area that they are passionate about, and monetization is currently on the back burner. From the Mogade FAQ:

Why build mogade? Why make it for free? Why open source it? Ultimately, we believe in gaming, and we believing in the casual gaming revolution brought about by new devices. We grew up on video games and we want to do our little part to make sure others get the same benefit. It currently costs roughly $100/month to run mogade on redundant hardware. It’s a manageable expense.

I ended up using the free Mogade-hosted leaderboard service, but if the idea of someone else hosting your app’s functionality makes you uncomfortable, then you have the option of forking the Mogade source on Github and hosting it on your own servers.

In addition to leaderboard support, I took advantage of some other Mogade-provided features to add some basic instrumentation to track game launches and unique users. This has the net effect of tracking downloads, unique users and game launches in a way that is far more immediate than the App Hub tools. In fact, I could see the build with instrumentation going through certification as the number of unique users spiked in advance of the game’s marketplace launch.

Mogade offers great functionality at a cost that I can’t argue with. For indie developers and small studios, it’s hard not to recommend taking a look.

New Theme Twenty Eleven!

I’ve pulled the trigger and upgraded to the Twenty Eleven theme to keep things looking fresh and tasty. I’m still hoping to move on over to self-hosting and using WordPress.org so we can have Javascript (Then I can host Tableau Visualizations! W00t!) and so much more, but until then, I hope you guys like the new digs.

Galactic Fire v1.5 now available on the Windows Phone 7 App Marketplace!

Hi all! Diverting a bit of your attention for the shameless self-promotion of my first game, which is available now on the WP7 App Marketplace!

[crossposted from my blog!]

Galactic Fire v1.5 is now live on the Windows Phone 7 App Marketplace, and includes the following updates!

  • Leaderboards! Owners of the game will now be able to participate in global leader boards for overall score.
  • Fancy art! The app icon and splash screen have received a major overhaul.
  • Game duration has been increased, from 90 seconds to 180 seconds.
  • Game difficulty has been tweaked, and death should no longer reset difficulty.
  • Fancy score and multiplier modifiers now show on enemy death and gem pickup, respectively.
  • Minor UI tweaks.
Additionally, Galactic Fire now has an ad-supported trial, and Galactic Fire FREE has been submitted to the WP7 app marketplace! The trial and free versions are ad supported and lack leaderboard support, but are otherwise identical to the full version of the game!
 
Tell your friends and rate the game! It’s actually quite fun!

Image

Project in Review, Part 3: 2D or not 2D?

[cross-posted from my blog here!]

This is a continuation of a multi-part blog series focusing on the development of Archimedean Assault. Go read part 1 and part 2. It’s good!

Once the scope of our game was reasonably well defined, we set forth like good little game jammers and started hammering out code, 2D art assets and music.

Not far into this process, we realized the multiplicative nature our scope had on our art assets. A robot. Alright, he has to walk around and shoot. But, also, he has to transform! A transforming robot. Okay, that doubles the number of art assets for our robot’s actions. We need assets for both versions of the robot. And, we also need a transition animation going from one form to another. Okay, fine. A free-roaming game world in which the player can move 8 directions.

So, we need at least number of actions * number of forms * number of directions (x * 32 for those keeping score at home!) frames for any given action, and that’s before we get into animation. That means, if we want the robot to fire a gun and have muzzle flash, we need to get the muzzle flash from each direction in each form. When we start talking about animation and number of frames per animation, hand-drawn art assets quickly balloon out of control.

That’s before we start talking about the environment assets in which the game will actually take place.

Being the newbs that we are, we don’t have a dedicated pixel artist. We’ve got nguyenn1, who is by my estimation, about 10% of a dedicated artist. It takes us a few weekends to discover that we wrote a check for art assets that our group couldn’t cash. At least, not within a reasonable timeframe, and not within a reasonable quality.

We mitigated our dependency on pixel art by borrowing heavily from anywhere we could. danc’s sprite sheets on Lost Garden quickly became an invaluable asset that we leaned on.

Of course, this restricts us to assets that fit into the kind of game we’re trying to build, and art decisions became something to the effect of “Well, what’ve we got that kind of works?” That strategy doesn’t work when you have very specific demands, like “floating citadel” or “a robot that transforms from 8 different angles.”

After realizing that there was no way we’d effectively deliver on our artistic demands, I started looking at alternatives. 3D models are readily accessible at comparably low costs from sites like TurboSquid. After several months, the art assets for the player weren’t yet complete, and environmental art assets were still quirky and buggy. But, we could buy a 3D model that matched up pretty well with our vision for $5.

If $5 can save months of artist time, it certainly seems like money well spent. However, working with 3D assets requires time elsewhere. It requires non-trivial developer time and ramp-up time on tools and techniques across the team. Once I have a $5 model for the player, then what? The landscape of 3D modeling software isn’t terribly friendly (importers for fixed content, exporters to proprietary formats that either didn’t support our content pipeline or munged content beyond recognition, rigging models and animating them in-game…), and animation seems to be a mess across the board.

So, $5 doesn’t seem to save us time, but does distribute the load across the team a bit more evenly. But, how can we be sure that we aren’t wasting our time chasing something because we think it’s fun?

Project in Review, Part 2: Archimedean Assault

[cross-posted from my blog. Click here to read the original.]

In this episode, we’ll focus on the team makeup going into the development of the currently-stalled Archimedean Assault. For a general overview of the project, go read Part 1 in this series.

I mentioned we had about a half a dozen people that thought this was a great idea for some reason. For a hobbyist, “Hey, who else wants to go get stuff done this weekend?” project, we ended up with an all-star cast of game development awesome.

The Game Designer

nguyenn1 leveraged some awesome connections from a local Soul Calibur Game Night and roped in an honest-to-goodness, gainfully employed game designer from a local game studio.

This was awesome, and we were quickly shaping up to be a legit operation (!!!).

Having a designer on-board for the first time, one thing we quickly learned was that an hour of game designer time could quickly translate to hundreds of hours of development time.

Even though we settled on a general design early on in the project, gameplay evolved as soon as people got their hands on something playable. Evolving design meant more requirements during development, which equated to more time producing art/audio assets and development.

On the plus side, having a game designer allowed others to focus on their work. I could fire up a build of the game, enthusiastically shout “This isn’t fun! Who cares, not my job!” and then toss it over the wall like a good and/or bad engineer is prone to do. Being able to lean on the game designer was certainly handy for maintaining focus in the face of a game that wasn’t immediately fun.

Of course, in order to be able to toss it over the wall, we had to expose a bunch of levers to allow the game designer to tweak core gameplay mechanics. Keep in mind that we started with the game jam format, which roughly translates to producing code that only looks like it works by Sunday.

Letting the designer muck with game mechanics is a data-driven concept, and the game jam schedule is on the opposite end of that particular spectrum. That got us in a bind where virtually everything was hard coded and needed to… not be.

Exposing gameplay mechanics for the game designer ended up taking just as long as the original game jam schedule. Whoops.

Lesson learned. All roads lead to data-driven content. Got it.

Project in Review, Part 1: Archimedean Assault

[Crossposted from my blog. See the original here.]

As nguyenn1 alluded to, we’ve been working on a game (!). What started as a weekend long GameJam entry into October’s LudumDare competition is… well, still going. We’re clearly over every imaginable budget at this point, so let’s take some time to look back and see what went well and what could have gone better. But, before that, let’s set some context!

Archimedean Assault is a single-player, arcade-inspired shooter featuring a transforming protagonist. Development efforts were borne out of a love for games and a coinciding LudumDare competition.

The player pilots a Gundam-style mech that can switch between a maneuverable aerial form and a heavy-hitting ground assault tank. While airborne, the player has exceptional maneuverability through a constant speed bonus and afterburners for an extra boost. In contrast, the player’s ground form is a slow-moving, armored behemoth with much more firepower. Expert players will strike a balance between air superiority and ground assault modes to destroy opposing forces and complete objectives scattered through a free-roaming game world.

In retrospect, I’m not sure how any sane individual could read that last paragraph and say, “Hey, we can totally hammer that out in a weekend!” Yet, we had about a half a dozen people on-board with the idea that we could.

Stay tuned for the gory technical details!

Game Theory: Making the Game

Does anything ever work the first time?

I have always loved video games. I can’t think of a time where there wasn’t a video game in my life when I was growing up. I remember looking through catalogs (remember those?) to Witmark (!!!) wishing I could buy the Turbographix 16 or the original Nintendo Entertainment System (NES). Point of fact though, I think a lot of guys my age had similar experiences, but most of them never do it. I don’t know why that is; it’s probably just like most things we dream of as children – wonderful fantasies we cherish that we don’t have the time, or opportunity, or the ambition to ever accomplish. So naturally, when I was presented a chance to make a game with some friends from work, we never did anything beyond basic talk.

OK, this time is for realz guys

Fast forward just about 1 year, and the some of the same guys, some new guys, and you know what? We started talking about making a game, and this time we actually started working on something! What follows is a little snapshot and history of our game. Right now it looks pretty crappy, and it IS pretty crappy. But it works, and it uses assets that are not cribbed (well, entirely cribbed) from other sources. It even has box art and an official story!

Now, before I go any further, sometime after we started making the game Gabe and I talked about documenting our experiences making (still making as of the writing of this post!) our 2nd game together. That’s right, I said Gabe and I! Gabe will be a guest blogger who will be contributing his own thoughts and insights into what we’ve been working on. Some of the material will be the same, but he’s going to focus on the things he likes aka coding, and I’ll focus on a few pieces that I know well. I hope you guys enjoy what we have to say. But that’s getting ahead of things. Let’s go back to the 2nd beginning…

So in the beginning there was Gabe. And Gabe had this idea that we could do an unofficial “game jam”. A game jam is a weekend dedicated to conceiving, designing, programming, creating, testing and releasing a game. It’s meant to encapsulate the entire experience of game creating into a single weekend. By this time, I’d felt like I learned some lessons from the first time we tried to make a game, and when he asked me, I jumped at the chance.

Now around this time, it became pretty apparent to us that we needed more skills than just what Gabe and I could bring to bear. Sure, we had the help of 2 of the previous participants (Brett and Michael), but that was pretty much the same group of guys who failed the first time. Fortunately for us, I’d managed to make a few new friends who would prove very helpful to us. My friend Bryan was/is a game designer, and his brother Bruce (or Brewski as I like to call him Smile ) studied sound design at school. I felt with Bryan’s previous experience, he could help us design a better game and Bruce filled in a much need gap in our skill set. We still lacked an artist, but having realized this from the last time we tried to make a game, I decided to bit the bullet and make the art for the game.

The Usual Suspects

Friday after work, we all gathered at Gabe’s house and started to powow. The original gang consisted of Gabe, Jaison, Bryan, Bruce, and myself. Brett and Michael had agreed to work as guns for hire and bang out the code we needed once the game design had been settled down. The game I 🙂 had in my mind looked a lot like an old arcade shooter called Cybattler

Cybattler google images:

I wasn’t able to articulate this at first since I had forgotten the name of the game, but eventually everyone got the idea. At this point, each person had some input, but Bryan really took a large role here. From the initial game concept (i.e. clone cybattler) he envisioned a much more free-form concept that involved the same pieces: transforming robot, space, waves of enemies but instead revolved around exploring the map searching for those enemies. We all agreed to this concept and started working! The whole process definitely took a bit of time, and Bryan was to spend A LOT more time fleshing out many of the specifics that we never even got to.

At this point, the 4 of us split apart and starting playing around with each of our assigned roles. Gabe is a much stronger coder than I, with more experience, so I started working on the concept art and actual art of the game. I don’t have a Wacom tablet or anything, so when we started doing the initial conceptual art of the robot, we did it with paper and pencil first. As a child of the 80’s, all things anime had a big influence on me, but Robotech and Battle Tech in particular had a really strong grip on my imagination as a child. Below are the sketches I did to get an initial idea of what kind of aesthetic we wanted the robot to have:

Archimedean Assault Robot concept art 1Archimedean Assault Robot concept art 2

The robot had to be able to transform from plane to robot and back again, so you can see the elements of the plane in the robot design. The feet were meant to contain the primary thrusters. The shield in the second picture formed the wings of the plane and the backpack looking thing was the plasma thruster unit which was meant to be the afterburner in plane mode, and a kind of beam weapon in robot form. The pictured gun was originally a kind of machine gun in my own head, and was also the primary attack cannon of the plane mode. The primary thrusters of the jet mount onto the back of the robot and provide the movement and flight capability in space. There are no hardpoints for missiles – in typical anime style they are internally stored. Smile In our robot’s case, they are stored within the legs so that means the robot is actually more heavily armed in robot mode than in plane mode! The tradeoff is that the plane is much faster.

My next post will talk about the tools we used to create the art assets and hopefully the source control software. But the next post you should see will be from Gabe!

Designing and implementing a Simpletron using C#

The last problem in Chapter 8 of Deitel’s Visual C# 2005: How to Program 2/e is to design and implement a simple machine-language processor called a Simpletron. I won’t go into the basics of the machine in great detail, since the book does so at great length. It is a really interesting problem, but there isn’t a great deal of information regarding C# implementations on the web, so hopefully this post will serve to fill part of that void. There are 2 parts to the problem:

1) Implement the Simpletron class in an extensible manner – This teaches you how to use Arrays in yet another way. Essentially in this problem, the Arrays are used both as RAM ( memory ) and as registers to hold changing values.

2) Enhance the Simpletron by adding the capability to perform additional operations – This portion of the problem forces the student to understand the nuances of low-level CPU operation.

I’ll only be posting code for part 1. Since this problem is often used in academic settings, I won’t be posting the other code, but what I’ll do instead is post errata I’ve found in the advanced problem, and my own interpretations of the enhancement requests. I found the wording in the book to be quite vague regarding how far to go with the modifications, so I hope this proves helpful. I searched fruitlessly for many hours with finding anything, so maybe someone else will be spared my pain. 🙂

Code outline for the Simpletron:

namespace Exercise8._32 {
    class Simpletron {
        // Input/output operations
        private const int READ = 10;
        private const int WRITE = 11;

        // Load/store operations
        private const int LOAD = 20;
        private const int STORE = 21;

        // Arithmetic operations
        private const int ADD = 30;
        private const int SUBTRACT = 31;
        private const int DIVIDE = 32;
        private const int MULTIPLY = 33;

        // Transfer of control operations
        private const int BRANCH = 40;
        private const int BRANCHNEG = 41;
        private const int BRANCHZERO = 42;
        private const int HALT = 43;

        private const int SIZE_OF_MEMORY = 100;
        private const int MIN_MEMORY_RANGE = -9999;
        private const int MAX_MEMORY_RANGE = +9999;
        private const int STOP_PROGRAM = -99999;

        private int accumulator;
        private int instructionCounter;
        private int operationCode;
        private int operand;
        private int instructionRegister;

        private int[] memory;

        public Simpletron() {
            memory = new int[SIZE_OF_MEMORY];
            accumulator = 0;
            instructionCounter = 0;
            operationCode = 0;
            operand = 0;
            instructionRegister = 0;
        }

        public void Run() {
            DisplayWelcomeMessage();
            UserDialogue();
            ExecuteProgram();
            DisplayMemoryDump();
        }

        private void DisplayWelcomeMessage() {

        }

        private void DisplayMemoryDump() {

        }

        private void UserDialogue() {

        }

        private int ValidateUserInput(int currentUserInput) {

        }


        private void ExecuteProgram() {

        }

        private int EvaluateOperationCode(int currentOperationCode,
                                          int currentOperand) {

        }

        private int AccumulatorOverflowValidation(int currentOperationResult) {

        }
    }
}

You can see that I have a Run method that is the primary execution method inside the class. There are also various validation methods that are called inside of some of the major methods. This code could have been placed inside of the main methods, but since it is called by many times, I thought it was wise to separate this code out. I would like to say that the particulars of the implementation aren’t super important – in this part of the problem, the main issue is the design. Another important thing to remember is to consistently use Test Driven Development. After each piece of code was created, I would run a few programs stressing those functions to ensure that the program was working correctly. It’s important that you test at least 3-4 variations of data to make sure that you are not designing only for a subset of your data.

I could have automated the testing by creating an overload of the run method that bypassed the userinput method, but for the scale of this project, performing the testing manually wasn’t time intensive. I would like to stress that had we wanted to continue modifying the program, we would have wanted to create automation at that point.

Okay, part 2 – the advanced section. I’d like to point out an errata on page 407: “In Exercises 25.10 and 25.11, we propose building a compiler that converts programs written in a high-level programming language (a variation of Basic) to Simpletron Machine Language. Some of the following modifications and enhancements may be required to execute the programs produced by the compiler: “ Well, I looked these problems up hoping for some clarification, but they don’t exist. 🙂

I believe requests a), b), c), and e) to be pretty self-explanatory. Below is some additional information that I believe will help with the remaining modifications.

d) Modify the simulator to use hexadecimal values rather than integer values to represent SML instructions – This modification is kind of weird, because if you followed the book, you almost certainly used an integer Array as your memory structure. It’s also kind of redundant to ask us to store things as Hex, since the computer is doing that anyway, but to shoehorn hex into your existing memory array would be a nightmare. And to what end? So I ended up interpreting this request to mean that on output, you should display all memory registers as Hex. I also added a section to the beginning asking the user which format: Decimal or Hex they would prefer. I know for troubleshooting I wanted Decimal since that is how I wrote the programs!

f) Modify the simulator to process floating-point values in addition to integer values – This one is a doozy. There are 2 possible ways to interpret this – Add a double memory array, accumulator, and a whole new set of instructions. The other is to continue to use integer memory and registers and instead encode the floating point data to fit within an integer field. I used the latter interpretation, since the former is kind of cheesy. One point in favor of the latter is that it will teach you an important lesson about CPU’s. Hint: Up until Intel’s 386 DX processors, all CPUs only had a single accumulator register. I really enjoyed this modification.

g) and h) Modify the simulator to handle string input – The only thing I need to mention is pay attention to this sentence in the clue the book gives you: Each two-digit integer represents the ASCII decimal equivalent of a character. That is the most important sentence in the clue. If you look up an ASCII table, you’ll see that they all have decimal representations, but that there are some with more than 2 digit representations. For instance, “h” or lower case h, is 104, so it’s impossible to fit into a 2 decimal bit memory location. If you did part f as I did, this problem might be easier for you, since similar thinking ( i.e. encoding/shifting ) is required.

Hope this helps! I had loads of fun solving this problem, and I hope that these hints help you focus on the important parts of the problem.

Things I learned about comparing two poker hands in C#

I’ve been going through Visual C# 2005: How to Program, 2/e and I recently got stuck on problem 30 in chapter 8. Chapter 8 deals with arrays and problem 30 is an innocent thing asking you to compare 2 hands of poker. Well, I spend a good month fucking around with this problem thinking to myself, there is NO WAY it should be this convoluted and hard. After finishing it yesterday, it turns out it is. The Coding the Wheel site has an entire page devoted to poker hand evaluations and my code looks remarkably like the naive implementation. My implementation is more difficult because beyond the initial hand evaluation, it tries to compare the hands and account for ties all the way down to a perfect tie, which in poker results in a pot split. I always thought suits would be used to break ties, but that isn’t an official rule according to Wikipedia. I found a few things significantly hampered me in my particular implementation.

  1. I should have developed using TDD. I developed the test code below AFTER I had written a significant portion of code, which killed me since I had to scrap a lot of that poorly tested code and rewrite my algorithms. I’ve posted a portion of the test code below. The only thing of note here is that I created an Enumeration called Hands which contained all of all the poker hands which I passed into this method.

    BuildHand method of DeckOfCardsTest class

     private void BuildHand(Card[] pokerHand, Hands typeOfHand) {
                int counter;
    
                string[] suits = { "Hearts", "Diamonds", "Clubs", "Spades" };
                string[] faces = { "Ace", "Deuce", "Three", "Four", "Five", "Six",
     "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
    
                // designate default suit 
    for cards as Hearts and default face as deuce
                string testSuit = suits[0];
                string testFace = faces[1];
    
                Card card;
    
                switch (Convert.ToInt32(typeOfHand)) {
                    // Create high card hand
                    case 0:
                        testSuit = suits[0];
                        for (counter = 0; counter < pokerHand.Length; ++counter) {
                            switch (counter) {
                                case 0:
                                    testFace = faces[2];
                                    testSuit = suits[3];
                                    break;
                                case 1:
                                    testFace = faces[9];
                                    testSuit = suits[1];
                                    break;
                                case 2:
                                    testFace = faces[12];
                                    testSuit = suits[2];
                                    break;
                                case 3:
                                    testFace = faces[4];
                                    testSuit = suits[3];
                                    break;
                                case 4:
                                    testFace = faces[random.Next(4,9)];
                                    testSuit = suits[1];
                                    break;
                            }
                            card = new Card(testFace, testSuit);
                            pokerHand[counter] = card;
                        }
                        break;
                    // Create pair hand
                    case 1:
                        int pair = random.Next(0, 7);
                        for (counter = 0; counter < pokerHand.Length; ++counter) {
                            switch (counter) {
                                case 0:
                                    testFace = faces[pair];
                                    testSuit = suits[0];
                                    break;
                                case 1:
                                    testFace = faces[pair];
                                    testSuit = suits[1];
                                    break;
                                case 2:
                                    testFace = faces[7];
                                    testSuit = suits[2];
                                    break;
                                case 3:
                                    testFace = faces[9];
                                    testSuit = suits[3];
                                    break;
                                case 4:
                                    testFace = faces[10];
                                    testSuit = suits[1];
                                    break;
                            }
                            card = new Card(testFace, testSuit);
                            pokerHand[counter] = card;
                        }
                        break;                
  2. I REALLY should have implemented a HandOfPoker class instead of using a Card array directly. This would have cleaned up my code quite a bit because each HandOfPoker object could have contained the frequency arrays I was using to store my face and suit counts. I also could have stored the hand results directly as properties instead of having to immediately compare after evaluation. See some of my ugly code below. Notice the massive redundancy as I compare the two hands. Sorry about some of the code getting cut off, but I can’t make it appear without ruining the formatting which will make it impossible to read. It’s not really for analysis, but to demonstrate what I could have improved.
    CompareTwoHands method from DeckOfCards class
    public void CompareTwoHands(Card[] firstHand, Card[] secondHand) {
                Hands firstHandResult;
                Hands secondHandResult;
    
                int counter;
                int cardCounter;
                int highestCardCount;
    
                int firstHandHighCard = faceValues.Length;
                int secondHandHighCard = faceValues.Length;
    
                // for each hand we will create 
    a frequency array for the faces (13) and suits (4)
                int[] faceCountsFirstHand;
                int[] suitCountsFirstHand;
    
                int[] faceCountsSecondHand;
                int[] suitCountsSecondHand;
    
                faceCountsFirstHand = CountFaceCards(firstHand);
                suitCountsFirstHand = CountSuitCards(firstHand);
    
                faceCountsSecondHand = CountFaceCards(secondHand);
                suitCountsSecondHand = CountSuitCards(secondHand);
    
                firstHandResult = 
    		AssessHand(faceCountsFirstHand, suitCountsFirstHand);
                secondHandResult = 
    		AssessHand(faceCountsSecondHand, suitCountsSecondHand);
    
                if (firstHandResult > secondHandResult) {
                    Console.WriteLine("The first hand won with "
     + DisplayHand(firstHandResult,faceCountsFirstHand,suitCountsFirstHand) + 
    " beating " +
     DisplayHand(secondHandResult,faceCountsSecondHand,suitCountsSecondHand));
                }
                else if (firstHandResult < secondHandResult) {
                    Console.WriteLine("The second hand won with " + 
    DisplayHand(secondHandResult,faceCountsSecondHand,suitCountsSecondHand) + " beating " +
     DisplayHand(firstHandResult,faceCountsFirstHand,suitCountsFirstHand));
                }
                else if (firstHandResult == secondHandResult) {
                    switch (Convert.ToInt32(firstHandResult)) {
                        case 1:
                            highestCardCount = 2;
                            for (cardCounter = highestCardCount; cardCounter > 0; --cardCounter) {
                                for (counter = faceCountsFirstHand.Length - 1; counter > 0; --counter) {
                                    if (faceCountsFirstHand[0] == highestCardCount || faceCountsSecondHand[0] == highestCardCount) {
                                        if (faceCountsFirstHand[counter] != faceCountsSecondHand[counter]) {
                                            firstHandHighCard = faceCountsFirstHand[counter];
                                            secondHandHighCard = faceCountsSecondHand[counter];
                                            cardCounter = 0;
                                            break;
                                        }
                                    }
                                    else if (faceCountsFirstHand[counter] == highestCardCount || faceCountsSecondHand[counter] == highestCardCount) {
                                        if (faceCountsFirstHand[counter] != faceCountsSecondHand[counter]) {
                                            firstHandHighCard = faceCountsFirstHand[counter];
                                            secondHandHighCard = faceCountsSecondHand[counter];
                                            cardCounter = 0;
                                            break;
                                        }
                                    }
                                }
                                if (counter == 1 && firstHandHighCard == secondHandHighCard) {
                                    highestCardCount = highestCardCount - 1;
                                }
                            }
                            break;

 

But you  know what? After doing all this, I’m pretty content with finishing it. I’m really fired up about what I learned, and after looking over some of the better solutions on Coding the Wheel, I realize that my solution is hampered by my tools, in this case my tool being the data structure Array which I’m being asked to use exclusively ( and I don’t really know anything else either. 🙂 ).

Hope this helps someone else trying to learn about this problem!