Game Development Journal 12: Checking for a Match

Generally speaking, a turn in Godori is quite simple. You have a hand of cards. On your turn, you play a card. The game board has a collection of cards on it. If the suit of the card you play matches the suit of one of the cards on the board, you capture it. Then a card is played from the draw pile. If that suit matches any on the board, you capture those as well.

From this simple explanation, you can either capture two, four, or zero cards. But there is an exception to this rule. What happens if you made a match on the card you played and then the same suit comes up from the draw pile?

In that situation, you do not capture any cards. All three cards remain on the board until another player or the deck plays the final card in the suit. At that point you capture all four cards.

I have to write programming logic to account for all of these scenarios. Because it’s possible for your cards to get stuck on the board, the way I am approaching this is that I am creating a temporary array of all the cards concerned in a turn.

These are all of the possible numbers of cards in play and how they would be distributed:

  • Two Cards: In this case, neither the card you played nor the card from the draw pile matched any suits currently in play. Both cards would be distributed to the game board.
  • Three Cards: There are two cases where you get three cards. You either made a match with either the card you played or the card that was drawn and the other card was not a match or all three cards are the same suit and they stay on the board.
  • Four Cards: The card you played and the drawn card each found another card on the board to pair with and you get all four cards.
  • Five Cards: You captured a set of three with one of your cards or one that was drawn, but the other card did not match.
  • Six Cards: Lucky you! You captured a complete suit and picked up another match from the board with the other card.
    • I can represent this logic in a method with a switch statement:

          func checkForMatch(cards:[Card]) {
              
              let numberOfCards = cards.count
              
              switch numberOfCards {
              case 2:
                  cardsInPlay += cards
              case 3:
                  let countCards = countSuits(cards: cards)
                  players[currentPlayer].capturedCards += countCards.playerCards
                  cardsInPlay += countCards.gameCards
              case 4:
                  players[currentPlayer].capturedCards += cards
              case 5:
                  let countCards = countSuits(cards: cards)
                  players[currentPlayer].capturedCards += countCards.playerCards
                  cardsInPlay += countCards.gameCards
              case 6:
                  players[currentPlayer].capturedCards += cards
              default:
                  break
              }
          }
      

      The two, four, and six options are easy. If there are two they go to the board. If there are four or six the player captures all of them.

      The hard cases to deal with are the sets of three or five. If there are three, then there is a case where the player gets no cards and a case where the player gets two cards and one goes back to the board. If there are five cards, then the player gets four cards and the board gets one, but which cards go where?

      As a person, this is easy to determine. I look at the cards all at once and I pick out the ones that don’t match. Trying to explain this to the computer is difficult.

      I have to check the suit property on each card and compare them to find the ones that match.

      This is made more difficult by the fact that I don’t know what suit I am dealing with. It’s easy to check to see if all the cards are from the .December suit, but to check a random blob of five cards where four will be one of twelve suits and the last one will be another means that I can’t simply loop through the array of cards checking to see if they’re a specific suit. I have to compare them to one another.

      The only think I have available to me to limit the amount of conditional logic is to know the order that the cards are entered into the array. I know that if I have three cards then either the card I played matched or the card from the draw stack matched. There would be no scenario where the first and third card would match without also matching the second card.

      A similar pattern exists with the five card option. If you capture a complete suit of cards, then there will be four cards in a row in the array with the same suit. Instead of having to check each card in the array for the mismatching card, I theoretically only have to check the first two cards and the last two cards. If the first two match, the last card will not. If the last two match, then the first one won’t.

      This is the current implementation I have:

          func countSuits(cards:[Card]) -> (playerCards:[Card], gameCards:[Card]) {
              
              if cards.count == 3 {
                  // I don't think there is a situation where the first and third card would match
                  // Either the first and second or second and third cards will match
                  if cards[0].cardSuit == cards[1].cardSuit && cards[0].cardSuit == cards[2].cardSuit {
                      return ([], cards)
                  } else if cards[0].cardSuit == cards[1].cardSuit {
                      return([cards[0], cards[1]], [cards[2]])
                  } else {
                      return([cards[1], cards[2]], [cards[0]])
                  }
              } else {
                  // Four cards will match and one will not. If arrays work the way I think they're supposed to, 
                  // in this case either the first four cards will match or the last four will.
                  if cards[0].cardSuit == cards[1].cardSuit {
                      return([cards[0], cards[1], cards[2], cards[3]], [cards[4]])
                  } else {
                      return([cards[1], cards[2], cards[3], cards[4]], [cards[0]])
                  }
              }
              
          }
      

      Again, I understand that this implementation is really ugly. Everything is hard coded. There are a lot of if/else statements and array positions. There are a lot of ways this can go wrong.

      Conclusions

      I know there is probably a better way to deal with this. It’s possible that there is a class in the Gameplay Kit framework that would handle this better.

      I am planning to explore better ways to deal with this. I also am planning to write unit tests for this when I move this stuff over to a project where I can include them.

      There is simply a lot of state and conditional logic in this application because it’s a game. I saw a bunch of people on Twitter recently talking about how embarrassed we’re going to be in ten years because we use if/else statements. I have not heard any suggestions about how to get around this.

      I know writing conditional logic is ugly and there are people reading this who want to completely rewrite my code. This is a question I deal with every day.

      There is a certain level of necessary complexity. There are a lot of conditions present in the rules of the game that need to be accommodated for. Simon Allardice talked about how when you’re teaching something there is a certain level of necessary complexity. I know myself and lot of people get frustrated when we do a tutorial for something like OpenGL and we have a spinning cube of death. It’s like, this is cool, but I can’t apply this knowledge to anything.

      There are certain circumstances that get chosen for teaching purposes because they’re easy and not messy. There is the world as it is and the world as we wish it would be.

      I see situations in here where it’s like “Oh this is simple! I can just set this up like this. Except it doesn’t work in this case, or this one, or this one…”

      I am trying to avoid setting up a bunch of spaghetti code or putting in a bunch of unnecessary objects to embed other object with even more objects.

      Programming is an iterative process. This code will change down the road. I would rather get something done now and go back and change it later when I get a better idea of what I need than spend all my time waxing poetic about how I could do this with a map() if I didn’t have to account for these edge cases. Bad code that actually gets written trumps perfect code that can only live in your head.

Game Development Journal 11: Dealing Cards

One thing I find fulfilling and frustrating about game development is that there are a lot of things we do in real life without thinking too much about it that are somewhat tricky to represent in code.

One of the big challenges with machine learning is figuring out how to explain to a computer that the blob of data it has represents a pug. A person can look at a picture of a pug and know it’s some kind of smush-faced dog. They might mistake it for a bulldog or something similar, but they won’t look at it and say it’s a table.

The thing I am dealing with right now is dealing a hand in my card game. The cards are dealt into five different collections: Three player hands, the cards currently in play on the table, and the cards in the draw pile.

In real life, a deck is basically a mutable array. You deal the top four cards to the first player, then the same to the next two, then deal three more to each collection and what’s left turns into the draw pile.

Swift doesn’t really think that way. Swift likes immutability. The game has a certain amount of state. The players will play their cards until there are no more, which means that the array will by necessity have to be mutable so that the cards that have been played can be removed from the hand and moved to the player’s captured cards.

It’s possible to make this work, but it’s not super pretty. It’s fighting against the way Swift wants to work.

I really did not want to have to go through and assign each card individually in this function. Since it follows a pattern, where the players each get four cards, then the table gets three, then everything gets three, it seems like it should be automatable.

I have some concerns about how to approach this. This is my first attempt:

    func dealCards(shuffledDeck:[Card]) {

        // Deal four cards to the first player and each one after that
        players[currentPlayer].hand[0...3] = shuffledDeck[0...3]
        nextPlayer()
        players[currentPlayer].hand[0...3] = shuffledDeck[4...7]
        nextPlayer()
        players[currentPlayer].hand[0...3] = shuffledDeck[8...11]
        nextPlayer()
        
        // Deal three cards to the table
        cardsInPlay[0...2] = shuffledDeck[12...14]
        
        // Deal three  more cards to each player
        players[currentPlayer].hand[4...6] = shuffledDeck[15...17]
        nextPlayer()
        players[currentPlayer].hand[4...6] = shuffledDeck[18...20]
        nextPlayer()
        players[currentPlayer].hand[4...6] = shuffledDeck[21...23]
        nextPlayer()
        
        
        // deal three cards to the table
        cardsInPlay[3...5] = shuffledDeck[24...26]
        
        // put the rest in the draw pile
        drawPile[0...21] = shuffledDeck[27...47]
    }

Yes, I know. This is reeking of Code Smell. I have two blocks of code that are nearly identical except for the indices on the shuffled deck. This depends on me keeping track of where I am in my array of cards. It also depends upon me knowing how many cards are in my array.

This makes me deeply uncomfortable. I am not entirely certain how to set up conditional logic for this. If this was before, I would use nested For loops, but those seem to be going the way of the dinosaur.

I suspect this is a situation where map() would probably be the best approach, but I feel like it’s complicated to express. I have to keep track of how many elements are being added to each array and where I am at in the shuffled deck. I even just noticed that I put the wrong terminating index at the end of this method that I went back and changed. There are a lot of ways this can go wrong.

I want to leave this here for the time being and try to think through a better approach to this. I don’t want to add a bunch of functional garbage that is less clear and more complicated than what I have now. I know there are better ways to do this, but I also know there are a lot worse ways to do this.

I do not want to over engineer this. Nothing in this function is going to change. There will never be more than 48 cards in the deck. There will always be three players. I know a lot of the reason we don’t hard code stuff is to add flexibility for changing requirements. But I know these requirements won’t change.

Also, I feel comfortable when I read this method about what it is that it does. It follows the same logical structure that you would if you were actually dealing a deck of cards. I know as a programmer this looks terrible, but me as a person it feels logical because this is the process I would go through if I was actually dealing a hand of Godori.

Conclusions

I will probably refactor this based on input from other people.

I think a lot about human versus computer. I know as a programmer there are more efficient ways for me to do things than I have in this code in particular. But I am also a human being. I have my own biases of how I personally process information.

I have to maintain this code. If I look at this in a year not only do I clearly understand how it works, but I also have an understanding of the game logic about how the cards are to be dealt.

I am probably justifying myself too much, but I am really struggling with this. The reason we have the abstraction of programming languages instead of writing everything in assembly language or machine language is to make programming more human friendly. Does writing more verbose code that is more clear to me but breaks best programming practices make me a hack? Or are we making things harder than they have to be in the name of trying to be 10x programmers?

Only time will tell.

Game Development Journal 10: Changing the Player Enum to an Array

Back when I created my Player class, I was trying to figure out how to organize players. I needed to have three players that I would keep in a specific order. My initial idea was to put them in an enum:

enum Players {
    case PlayerA
    case PlayerB
    case PlayerC
}

This was really bothering me. I knew I wanted some way to switch between players and we would always have a current player.

I was trying to figure out how to make this work and I realized I made a grievous error. I was misusing Enumerations.

Enumerations are good for things where you have options that result in you doing something. The example used in the Swift programming book from Apple does a really good job of showing what they mean by that:

enum Direction {
    case North
    case South
    case East
    case West
}

Having these directions in an enum allows you to create conditional logic where you have different actions based on what direction is currently selected.

It is not good at directly affecting and changing any of the case statements in the enum.

I need a data structure that holds three players. I need to know the order the players are in. I have to be able to affect the properties based on things that happen in the code.

I thought about putting these in a dictionary, but I realized that wasn’t really optimal. Dictionaries have orders, but they’re meant to correlate to keys and values. I just need to know what the current player is so I can set its properties and move on to the next one reliably.

I decided I needed an array of players. This array of players has to be initialized in the Game class and passed into the Hand class. The Player needs to be initialized with the initial amount of money that each player starts with.

I created a function that generates an array of players:

func createPlayers(startingMoney:Int) -> [Player] {
    let player = Player(money: startingMoney)
    return Array(repeatElement(player, count: 3))
}

I can then call this function in the Game class and set it to a variable that I can pass to the Hand class. The Hand plays through a round, determines the winner, and returns it to the Game so the Game can determine if another round should be played.

This means that I needed to add a few methods to the Player class to accommodate for these implementation details:

    init(money:Int) {
        currentMoney = money
        numberOfDeferrals = 0
        numberOfPoints = 0
    }
    
    // Reset Players
    mutating func resetPlayer() {
        hand.removeAll()
        capturedCards.removeAll()
        numberOfDeferrals = 0
        numberOfPoints = 0
    }

When the Player is initialized, it is created with the starting amount of money. When a Hand is completed, a Player’s properties need to be reset.

This clarifies a lot of what I need to do in the Hand Class. Now that I know I am using an array of players rather than an enum, I can create all of my properties that I need for a Hand:

    /*
      1. Players
      2. Current Player
      3. Shuffled Deck
      4. Cards on Board
      5. Draw Pile
    */

    var players:[Player]
    var currentPlayer:Player
    let shuffledDeck = shuffleDeck(deck: deck)
    var cardsInPlay = [Card]()
    var drawPile = [Card]()

As per my work in my previous post on figuring out what components I need, I have been able to figure out what type each of my properties are.

I made a mistake when creating my initializer. At first I made the current player a Player object. My initializer looked like this:

    init(playerArray:[Player], firstPlayer:Player) {
        players = playerArray
        currentPlayer = players[firstPlayer]
        dealCards(shuffledDeck: shuffledDeck)
    }

I thought that made a lot of sense, to make the currentPlayer an instance of the Player struct, but I realized that doing this divorced it from the player array.

The game logic basically requires a player to complete their turn and for the process to continue with the next player. By pulling out the current player from the array and making a copy of it in the current player, I have no way of knowing if that player is the first player or the hundredth. I need to persist where I am in my cycle of players because the current player keeps changing.

So I changed my currentPlayer property to:

var currentPlayer:Int = 0

and my initializer to:

    init(playerArray:[Player], firstPlayer:Int) {
        players = playerArray
        currentPlayer = firstPlayer
        dealCards(shuffledDeck: shuffledDeck)
    }

Now being able to go to the next player is fairly simple. I created a method to move to the next player in the array:

   func nextPlayer() {
        if currentPlayer == 2 {
            currentPlayer = 0
        } else {
            currentPlayer += 1
        }
    }

I made this a method on the Hand class. I had hoped to make this into a standalone function so it would be easier to test and be reusable within the application, but I decided against that for two reasons:

  • It makes the function a lot messier. I have to pass in the current index and pass back the return function. I would much rather just call nextPlayer() and not worry about it.
  • I don’t think I actually need this anywhere else in the code. There is no point in over engineering the app adding a bunch of stuff you won’t need.

Conclusions

I am in the process of building out the dealCards() method. I have to deal four cards to each player, then deal three to the table, then three more to each player, and then three to the table. I have to switch players several times and organize all the arrays properly.

I would like to be able to pinch off the first few elements of one array and give them to another array. I know I need to copy those elements and probably remove them from the shuffled deck array.

I can think of some really inefficient ways of doing this. I might write that method out inefficiently first so I can see where all the repeated code is. Writing bad code is an underestimated way to find your way to good code. Embrace bad code!!

Game Development Journal 9: Breaking out the Hand Logic

In my last journal, I talked about setting up the scoring system. I put that separate from the actual Hand because I don’t necessarily think it needs to be in there. I want to keep everything in the Hand that absolutely must be there.

GameNotesI find myself getting overwhelmed thinking about how all the pieces work together. I get confused and either over simplify things or overly confuse them.

I found that when this happens to me, it really helps to write things down on paper with pens like a savage.

For some reason, typing things out on my computer does not have the same cognitive resolution as physically writing things out and sketching them. I can use different colors for different things. It’s not super organized, but when I am trying to organize my thoughts, there is nothing better.

At first I was trying to figure out what properties I needed in my class. Then I realized that I was approaching things wrong. I had to think about what this class has to do rather than figuring out what I need first. If you want to cook, you figure out your recipe before you buy your ingredients.

The Hand class is basically a game loop. It plays out a hand of this game. It has to shuffle the cards and deal them to the players. It has to keep track of the current player and run a turn. If that turn does not end the game, it has to move to the next player and keep doing this until the hand ends.

This logic in pseudocode would look something like this:

    // Deal Cards/Initialize
    
    // Game Loop:
    /*
     
     Continue: Bool
     isWin: Bool
     
     Reset Players
     
     While continue is true and deck > 0. Return an optional player.
     
     1. Player plays a card
     2. Card from the stack gets played
     3. Computer checks for a match and distributes cards
     4. Computer checks for a win
     4a. If there is a win, the computer checks if someone else has called stop.
         If no, the computer asks the player if they want to go or stop. If yes,
         the loop ends.
     5a. If the player calls stop, the loop ends
     5b. If the player calls go, the computer moves to the next player and the game continues
     
    */

The loop needs to know if it continues or not. This is complicated by the game mechanic of the player being able to keep playing once they accumulate enough points to win. If a second player accumulates enough points to win after a first player has already called Go, the second player does not have the option to continue the game. This variable does not need to persist outside of the loop function, so I can make its scope confined to the loop.

The same is true with the isWin variable. We don’t care if someone has called Go after the hand is over.

It’s possible for no one to win the hand. If a player calls Go and accumulates no more points but the game plays to the end, then there could be no winner. The Game class that is going to create instances of this Hand class in its own game loop needs to know if there was a winner, and if so, who. The Player class (now) has a property that tracks how many points the player has. So when the hand is over if someone is a winner, that player gets passed back to the Game class that can check the property on the winner to distribute the chips. If a new hand is played, then these properties are reset and the game continues. This may not be the best way to organize things, so it may be refactored later.

Now that I know what the loop looks like, I can create my pseudocode of the methods that will be called by this loop:

    // Game Logic
    
    // Play a card (pass in an array)
    // Check for Match
    // Distribute cards
    // Check for win
    // Reset Players

I need to figure out what gets passed into these functions and what are mutable properties of the Hand class. However, this was far easier to figure out after I wrote out all the steps that the game loop needs to implement on each given turn.

Since I have a better understanding of what this class will do, figuring out what properties I need is simple:

    // Properties
    /*
      1. Players
      2. Current Player
      3. Shuffled Deck
      4. Cards on Board
      5. Draw Pile
    */

Conclusion

I know this doesn’t look super exciting. I haven’t written any “real” code, but I have made things a lot easier for myself whenever I pick this back up again. I can noodle around with this for 15 minutes every now and then and fill in all of these methods. I have broken this complicated piece of programming logic down into manageable tasks.

I might pull those methods called by the game loop out into functions like I did with the scoring to make it easier to test them. I can create non-random arrays to use for test data without having to create a whole instance of a Hand class where that property will always change.

Anyway, it always feels good to get anything done on this. An application is just an incredibly long series of small tasks. Doing a little every day results in progress. I’ll take it.

Game Development Journal 8: Scoring and Hand-Game Complexity

I am reaching a point in this project where I am trying to figure out how to proceed. I have my base deck and player functionality in place. After that, things get tricky.

Godori is a hand-based card game, similar to poker. In poker, you have multiple hands. If there were not multiple hands, then the betting would be irrelevant. There would be no point in betting on any specific hand because each hand would be all or nothing.

This means that I need to parse out how to separate the hand-based game logic from the overall game logic. This presents a tricky situation where it would be easy to try and place all of this in one massive class that has to deal with a lot of state. There will be a necessary amount of state, but I would prefer the state get handled by the right things.

Initially I was going to place most of the game logic into the Hand class, but I have realized that I don’t want everything in there. That class should simply be running the game. It should have a loop where it keeps track of the current player, ensures the player completes their turn, determines if a win condition has occurred, if the player has differed the win, then start over again with the next player. The scoring is a separate bit of functionality. It should be able to call functions that do the scoring for it rather than putting all of that into the Hand Class.

Yes, I realize this may not be the best way of handling things. I know that you should try to encapsulate functionality within data structures, but I also hate opening up a class to find a thousand lines of code. For me, conceptually, it’s easier for me to think of the scoring in terms of stand alone functions than trying to figure out how they fit within the Hand class.

Scoring Code

So I am creating a utility file of functions that take an array of cards as an input and return an integer that represents the score.

There are four types of cards, so I am going to write four functions to score the cards and one to call all of those functions.

The easiest one to score is the Brights. According to the rules of Godori, there are five Bright cards. You do not get any points until you collect three Brights. If you collect all five, you get a whopping fifteen points! Huzzah!

The stumbling block I came across with this was how to take advantage of a design decision I implemented earlier. I made a Card protocol that all of the card types conform to. Since the type isn’t a property on the struct, I was trying to figure out how to check the type and only count the ones that are of type BrightCard.

Some Googling brought me to a conditional logic statement I have not seen yet: if-is.

If-is allows you to check if something is a certain data type. Instead of having to add another property to each struct that represents its type, I can check it directly using that logic statement.

Here is my function to score my Bright Cards:

func brightScore(cards:[Card]) -> Int {
    
    var numberOfCards:Int = 0
    var score:Int = 0
    
    for card in cards {
        if card is BrightCard {
            numberOfCards += 1
        }
    }
    
    switch numberOfCards {
    case 3:
        score = 3
    case 4:
        score = 4
    case 5:
        score = 15
    default:
        score = 0
    }
    
    return score
}

This feels rather verbose. I am sure there is a better way to write this. I will revisit it later when I have a chance to think it over for a while.

Even though this is verbose, it’s very clear about what this function does. I like that it’s clear if you look this over about how this function works. Future Janie wants to look at code that will be clear to her about what it does.

If I decide to try and do something with Map() or whatever I want to make sure that it’s still perfectly clear to anyone what this does. I don’t care about cutting out lines of code as much as I care about clarity and performance. I understand that the vast amounts of conditional logic in the scoring functions might cause a performance hit, but I don’t want to prematurely optimize.

I am putting a pin in this to check later.

I am also going to share the Animal scoring function. This type is a little more complicated. There are three bird cards in the Animal set. If you capture all three bird cards, it scores you an extra five points.

I had to add a nested if statement to this function. After determining if a card is an Animal card or not, I additionally have to determine if it’s a bird or not. Since bird is not a property on the Card protocol, I have to cast the card as an Animal card when I know it will be an animal to check its bird property.

func animalScore(cards:[Card]) -> Int {
    var numberOfCards:Int = 0
    var numberOfBirds:Int = 0
    var score:Int = 0
    
    for card in cards {
        if card is AnimalCard {
            numberOfCards += 1
            
            let animalCard = card as! AnimalCard
            
            if animalCard.isBird == true {
                numberOfBirds += 1
            }
        }
    }
    
    switch numberOfCards {
    case 5:
        score = 1
    case 6:
        score = 2
    case 7:
        score = 3
    case 8:
        score = 4
    case 9:
        score = 5
    default:
        score = 0
    }
    
    if numberOfBirds == 3 {
        score += 5
    }
    
    return score
}

Refactoring the Switch Statement

After I went through and completed all of the scoring functions, I noticed there was a lot of repetition. This got really annoying with the Junk cards where the points start accumulating at ten cards and went all the way up to a possible 26 junk cards.

The Brights don’t follow a pattern, but all the other cards do. They have a lowest number of cards to be worth any points. Each additional card is worth a point. Instead of doing switch statements, I should be able to do this with less code.

I figured out that if I check if the number of cards is equal to or greater than this barrier to entry, I can subtract a certain amount from the number of cards to get the value.

With the ribbon and animal cards, if you have five cards, it’s worth one point. Each additional card is worth an additional point. This means that I can check to see if the number of cards is above five. If so, I can subtract four from the number of cards to get the number of points. If there are seven cards and you subtract four, you get three. This is scalable in the way the switch statement is not. I don’t have to worry that I miscounted the junk cards and that I will take away the player’s points after they exceed the number I thought there were.

This is the Junk scoring function, after the refactor:

func junkScore(cards:[Card]) -> Int {
    var numberOfCards:Int = 0
    var score:Int = 0
    
    for card in cards {
        if card is JunkCard {
            numberOfCards += 1
            
            let junkCard = card as! JunkCard
            
            if junkCard.isDouble == true {
                numberOfCards += 1
            }
        }
    }
    
    if numberOfCards >= 10 {
        score = numberOfCards - 9
    } else {
        score = 0
    }
    
    return score
}

Returning the Score

Now that all the scoring is encapsulated in each of these functions, I can write a short and sweet function checking the score for the entire hand:

func currentPlayerScore(cards:[Card]) -> Int {
    return brightScore(cards: cards) +
        animalScore(cards: cards) +
        ribbonScore(cards: cards) +
        junkScore(cards: cards)
}

Wrapping Up

One advantage to breaking this out as I have is that it is now a lot easier to unit test. I don’t have to make an instance of a hand just to check the scoring. I can create mock data that checks each of the conditions within all the functions.

One of my goals with this project was to figure out how to break down everything into small, doable chunks. If you look at the entire application as a whole, it’s overwhelming. By pulling out chunks that can be knocked off one by one and building upon those chunks, you can slowly build up a stable application based on a solid foundation without worrying too much about what goes on top.

Next up I am hoping to add more functionality to the Hand class. I need to create the properties and set up the game loop that will walk through how a turn works.

Ta ta for now!

Game Development Journal 7: Creating the Player Struct

When I started out this project, I tried to figure out what pieces needed to be in place to create a working prototype of this game without a user interface. I am planning to start off making this a command line application that can be played with text input and output.

I tentatively narrowed it down to these components:

  • A representation of the game “board” with all the player’s remaining money and the current state of the game. This will determine if any player has run out of money and if the game should continue after each hand.
  • A representation of a complete hand of the game. This is where the game logic for scoring and win conditions will be stored.
  • A representation of a player.
  • A representation of a deck of cards.

Since every part of this list is dependent upon the thing that comes after it, it made sense to start with the deck, which is at the bottom and is a dependency for everything else.

Now that the deck is completed, I can build up the next lowest section, which is the Player data structure.

The Player data structure will include logic that is both transient and persistent, which is unique to this structure. The game board is primarily concerned with items that persist from hand to hand, while the hand only cares about what happens during it’s lifecycle. The player has to know both things that are transient during a specific hand and persistent throughout the game.

If I am a player, the things that should know about myself are the following:

  • Amount of money I have
  • Current cards in my hand
  • What cards I have captured
  • Number of times I have chosen to continue the game after satisfying a win scenario

A player needs to have a persistent property that tells them how much money that have at any given point in time. If you run out of money, then you can no longer play. This amount will change at the end of each hand and will be used to determine the winner.

The rest of the things a player needs to know are transient and change after each turn. A player needs to know the current cards in their hand. They need to know what cards they have captured so that a win condition can be determined. A player also needs to know if they have achieved a win scenario but decided to defer the win to try and accumulate more points.

struct Player {
    
    // There are things that are persisted from hand to hand
    var currentMoney:Double
    
    // There are hand-specific properties
    var hand:[Card]
    var capturedCards:[Card]
    var numberOfDeferrals:Int
    
}

At this point in time, I do not think that the Player needs any methods placed upon it. The way I am conceptualizing it, the Player simply needs to encapsulate all of the properties the Player needs to be aware of. These can be changed and referenced based on game specific logic in both the Board and Hand classes.

I will revisit this later after I get the other classes filled out to see if I have made a fundamental mistake on this class.

I also need a way to switch between players. Each game will have three players in it, so I also need to create a data structure to hold all of my players. This seems a good place for an enum:

enum Players {
    case PlayerA
    case PlayerB
    case PlayerC
}

Today was rather busy and so I didn’t work much on this today. The next bit is going to be a lot more complicated. I am percolating on how to approach the next chunk of my programming application.

One exciting development on this project is that I created my prototype project and made my first commit to my private repository for this project. I would like to share as much of my logic on here as possible without just completely open sourcing the application.

Next on the docket is writing the Hand data structure. That is the most complicated part of the application so far, so this may constitute multiple posts as I figure out the best way to approach it. Stay tuned!

Game Development Journal 6: GKRandom

As of my last blog post, I now have a deck of flower cards. It is represented in an array of various struct instances that all conform to a Card protocol.

Games would not be very interesting if we didn’t have random elements. In order for me to proceed with my game, I need to implement a method to “shuffle” my deck of cards.

Initially, my plan was to do some research into various randomization algorithms. I was looking for an excuse to do more research into computerized randomization, but I don’t feel this application will fit the bill. My research yielded two results:

  1. iOS has a built in framework specifically for randomization
  2. Other languages have this functionality built directly into their Array class

One thing I am trying to avoid with this project is falling down rabbit holes. I thought it would be interesting to compare rolling my own randomization against the ones that are built into Gameplay Kit, but that is a waste of time. I am not rolling my own cryptography, so the built in randomization tools are fine.

Additionally, I feel that there are a lot of aspects of Gameplay Kit that people are completely unaware of. It seems to be something of a lost framework that I see very few people actually talk about or show in production. In the spirit of trying to figure out the best way to solve problems, I have decided that I would like to try and implement Gameplay Kit whenever possible so that awareness of this framework can improve.

GKRandom

Apple has a nice overview of the various options they have for their randomization components.

GKRandom is a protocol that has two classes that conform to it: GKRandomSource and GKRandomDistribution.

GKRandomDistribution is set up to generate random numbers based on a range. This would be ideal for doing something like rolling a dice. There are even built in functions based on both six-sided dice and twenty-sided dice. Good news if you are and Dungeons and Dragons fan!

I could write an algorithm to implement this to force it to suit my needs, but it’s worthwhile to see if the other class would work better.

Looking at GKRandomSource’s documentation shows that there is a built in method called arrayByShufflingObjects(in: [Any]). Since I decided to turn my deck into an array and not a dictionary, this seems ideal.

GKRandomSource is not meant to be used directly. It is a super class that has three different subclasses based on different random algorithms:

  • GKARC4RandomSource: This is the default randomization algorithm. This works well with just about any game scenario.
  • GKLinearCongruentialRandomSource: This is a more performant algorithm. It’s less random, but also less resource intensive. If you’re counting the milliseconds in your game loop and you don’t need something super random, you might want to consider this.
  • GKMersenneTwisterRandomSource: This is the most random of the random source classes, but it is also the slowest.

Since all three of these inherit from GKRandomSource, they all have the method to shuffle an array. It’s just a question of which one suits my purposes.

I think any of them would work. Shuffling a deck of cards tends to be less random than rolling a die by the nature of how difficult it is to get a genuinely random distribution, so having the most random distribution is probably overkill.

I am tentatively going to choose the fastest algorithm, the GKLinearCongruentialRandomSource. I don’t think that the performance aspect is an issue. The deck is only generated at the beginning of a hand, along with all other setup steps. If this were being run every single frame then performance would be an issue.

Instead, I am trying to mimic an actual game playing experience. If you are shuffling decks of cards, you’re not going to get super random distributions. Additionally, the way that I have initialized the deck by grouping the cards by class rather than suit, the initial deck layout is fairly mixed up anyway.

My final code to add shuffling functionality is as follows:

// Random Functions: Need to generate a "shuffled" deck of cards

func shuffleDeck(deck: [Card]) -> [Card] {
    let randomGenerator = GKLinearCongruentialRandomSource()
    return randomGenerator.arrayByShufflingObjects(in: deck) as! [Card]
}

let shuffledDeck = shuffleDeck(deck: deck)

By using Gameplay Kit, I was able to get the functionality I needed with one function that uses two lines of code.

Conclusions

It feels kind of anticlimactic to write a whole blog post to end saying I resolved the issue with two lines of code. But I feel like it’s important to emphasize the value of simple solutions.

I feel like we, as a community, feel the need to implement more complicated solutions. If I don’t write out my random algorithm in Swift, then I am not a real programmer. Except that’s not true.

First off, implementing my algorithm in Swift will result in me having more code that I have to maintain. Swift is still rapidly changing. Swift 2.2 is legacy code. More lines of pure Swift means more things that change that I have to go back and update a few times a year. No thank you.

Second, it would have taken up more lines of code. Right now the algorithm is abstracted away and I don’t have to have it in my code.

Third, there is no point in reinventing the wheel. My need to shuffle an array of objects is a common enough problem that Apple provided me a simple solution for it. They will maintain it and ensure that it keeps working. If it’s deprecated then it’s on me to go back and find what it changed to, but for all intents and purposes I never have to touch this again.

Fourth, I know that this algorithm is accurate because Apple gave it to me. They have people who know more about this stuff than I do who wrote and tested this so I don’t have to.

Fifth, if I ever for some reason bring on another person onto my project, it’s much simpler for that person to read that code snippet than it would be to walk through the programming logic associated with the algorithm. It’s plain what the function does and if they have questions they can read Apple’s documentation.

I have added this new playground here. It’s basically the same as the refactored playground but with the added random function and its call. Those lines are at the bottom.

Moral of the story is, if someone gives you the ability to do something in two lines of code, for the love of God just take it!!

god

Game Development Journal 5: Refactoring the Flower Cards for Protocols

After I posted my last blog post, my code was bothering me. It had code smell.

I wanted to get something started knowing I would go back and refactor things, but it still feels kind of bad to post what I now consider to be bad code, but that is kind of the point of this series of posts.

Good code, to quote a friend of mine, doesn’t spring from the mind fully formed like Athena from the head of Zeus. It is an iterative approach where you get something out there and you work with it and figure out what you didn’t consider when you were theoretically approaching the code as an abstract concept.

Separating the Responsibilities

Part of the issue I have with architecting this piece of software was figuring out how to represent things in code. I want to avoid spaghetti code. I also want to avoid making something overly complicated.

I feel that my initial foray stripped out some necessary complexity.

I was trying to keep my card class as simple as possible. Without looking at the rules too carefully, I initial felt that it was only necessary to track the suit and the type of card:

struct Card {
    let cardSuit:CardSuit
    let cardType:CardType
    
    init(suit:CardSuit, type:CardType) {
        cardSuit = suit
        cardType = type
    }
}

While I was going through the initialization process for these cards, I realized that there were a few edge cases I didn’t take into consideration:

  • Collecting all of the bird cards gives a bonus
  • The ribbons are different colors and collecting all three ribbons of the same color is worth more than three different colored ribbons
  • Some of the Junk cards are worth two cards instead of one

I tried to address that in the key I assigned each card. Every card is unique and needed a unique identifier, so I figured I would represent these edge cases in the key, but that was a really big mistake.

”Stringly”-Typed and Safety

I was making everything in my deck, as Justin Williams says, “stringly”-typed.

Stringly-typed occurs when you are using a key to correlate to something rather than a property that can be auto-completed. Core Image is (or at least used to be) stringly-typed.

I was basing all of my programming logic in this application upon the hope that I would remember my own naming scheme and not misspell anything. That is a bad assumption.

Additionally, I was separating out the responsibility in the wrong place. The card should know everything about itself. It should know its type. It should know its suit. If it is an edge case, it should know that too. It should not be the responsibility of the programming logic to know that a card has a blue ribbon or not. The card should know that about itself.

So how do I deal with that?

Optionals?

At first I thought optionals would be a good way to approach this. I want to know if an animal card is a bird or not. I also want to know what color the ribbon is and if the junk card is worth two or not. I can make these optional properties on my Card Struct:

struct Card {
    let cardSuit:CardSuit
    let cardType:CardTyped
    let ribbonColor:RibbonColor?
    let isBird:Bool?
    let isDouble:Bool?
    
    init(suit:CardSuit, type:CardType) {
        cardSuit = suit
        cardType = type
    }

    init(suit:CardSuit, type:CardType, ribbon:RibbonColor) {
        cardSuit = suit
        cardType = type
	 ribbonColor = ribbon
    }

    init(suit:CardSuit, type:CardType, bird:Bool) {
        cardSuit = suit
        cardType = type
	 isBird = bird
    }

    init(suit:CardSuit, type:CardType, double:Bool) {
        cardSuit = suit
        cardType = type
	 isDouble = double
    }
}

This creates a few different initializers to accommodate each of the edge cases. Great, right?

Not really.

As I figure out more and more edge cases, the larger and more complex this struct is going to get. Also, none of these edge cases overlap. There will never be a ribbon card that is worth double or will have a bird on it.

So what is a better approach?

Protocols

It makes more sense to, instead of having an enum of different card types, to create a Card protocol that includes only what every card will require and then create different structs for each type of card that can be tailored to its specific edge cases and requirements.

The simplest card type, the one that has no edge cases associated with it, is the Bright type. All a Bright card needs to know is that it is a Bright and what suit it is. Since I can make a Bright struct that knows it is a Bright card, the only thing the protocol needs (that I am aware of) is a suit. I can expand on that later if I figure out further into the project that this was too simple.

protocol Card {
    var cardSuit:CardSuit {get}
    var cardName:String {get}
}

I am adding a cardName property because I want to eventually incorporate these structures into a command line program and later add a user interface. I would like to have something to display in the command line and later have a key that I can use to assign the correct card in the UI. I had that in my previous implementation, but I want to move it into the class because a few cards will be duplicates and I want to not have to make unique identifiers for everything, especially when the cards are the same.

Now that I have a Card protocol, I can apply it to four different structs that are tailored for each card type and its own edge cases.

struct BrightCard:Card {
    
    internal var cardSuit: CardSuit
    internal var cardName: String

    init(suit: CardSuit, name: String) {
        cardSuit = suit
        cardName = name
    }
}

struct RibbonCard:Card {
    
    internal var cardSuit: CardSuit
    internal var cardName: String
    internal var ribbonColor: RibbonColor
    
    init(suit: CardSuit, name: String, ribbon: RibbonColor) {
        cardSuit = suit
        cardName = name
        ribbonColor = ribbon
    }
}

struct AnimalCard:Card {
    
    internal var cardSuit: CardSuit
    internal var cardName: String
    internal var isBird: Bool
    
    init(suit: CardSuit, name: String, bird:Bool) {
        cardSuit = suit
        cardName = name
        isBird = bird
    }
    
}

struct JunkCard:Card {
    
    internal var cardSuit: CardSuit
    internal var cardName: String
    internal var isDouble: Bool
    
    init(suit: CardSuit, name: String, double:Bool) {
        cardSuit = suit
        cardName = name
        isDouble = double
    }
}

If I am working on the game logic and find another edge case, I can easily apply it to its specific card type rather than making it a global optional or having to reflect it in the card’s name.

Since every one of these cards conforms to the same protocol, I can create an array of anything conforming to the Card protocol.

let deck:[Card] = [BrightCard(suit: .January, name:"JanuaryBright"),
                   BrightCard(suit: .March, name:"MarchBright"),
                   BrightCard(suit: .August, name: "AugustBright"),
                   BrightCard(suit: .November, name: "NovemberBright"),
                   BrightCard(suit: .December, name: "DecemberBright"),
                   RibbonCard(suit: .January, name: "JanuaryPurpleRibbon", ribbon: .Purple),
                   RibbonCard(suit: .February, name: "FebruaryPurpleRibbon", ribbon: .Purple),
                   RibbonCard(suit: .March, name: "MarchPurpleRibbon", ribbon: .Purple),
                   RibbonCard(suit: .April, name: "AprilRedRibbon", ribbon: .Red),
                   RibbonCard(suit: .May, name: "MayRedRibbon", ribbon: .Red),
                   RibbonCard(suit: .July, name: "JulyRedRibbon", ribbon: .Red),
                   RibbonCard(suit: .December, name: "DecemberRedRibbon", ribbon: .Red),
                   RibbonCard(suit: .June, name: "JuneBlueRibbon", ribbon: .Blue),
                   RibbonCard(suit: .September, name: "SeptemberBlueRibbon", ribbon: .Blue),
                   RibbonCard(suit: .October, name: "OctoberBlueRibbon", ribbon: .Blue),
                   AnimalCard(suit: .February, name: "FebruaryBird", bird: true),
                   AnimalCard(suit: .April, name: "AprilBird", bird: true),
                   AnimalCard(suit: .May, name: "MayAnimal", bird: false),
                   AnimalCard(suit: .June, name: "JuneAnimal", bird: false),
                   AnimalCard(suit: .July, name: "JulyAnimal", bird: false),
                   AnimalCard(suit: .August, name: "AugustBird", bird: true),
                   AnimalCard(suit: .September, name: "SeptemberAnimal", bird: false),
                   AnimalCard(suit: .October, name: "OctoberAnimal", bird: false),
                   AnimalCard(suit: .December, name: "DecemberAnimal", bird: false),
                   JunkCard(suit: .January, name: "JanuaryJunk", double: false),
                   JunkCard(suit: .January, name: "JanuaryJunk", double: false),
                   JunkCard(suit: .February, name: "FebruaryJunk", double: false),
                   JunkCard(suit: .February, name: "FebruaryJunk", double: false),
                   JunkCard(suit: .March, name: "MarchJunk", double: false),
                   JunkCard(suit: .March, name: "MarchJunk", double: false),
                   JunkCard(suit: .April, name: "AprilJunk", double: false),
                   JunkCard(suit: .April, name: "AprilJunk", double: false),
                   JunkCard(suit: .May, name: "MayJunk", double: false),
                   JunkCard(suit: .May, name: "MayJunk", double: false),
                   JunkCard(suit: .June, name: "JuneJunk", double: false),
                   JunkCard(suit: .June, name: "JuneJunk", double: false),
                   JunkCard(suit: .July, name: "JulyJunk", double: false),
                   JunkCard(suit: .July, name: "JulyJunk", double: false),
                   JunkCard(suit: .August, name: "AugustJunk", double: false),
                   JunkCard(suit: .August, name: "AugustJunk", double: false),
                   JunkCard(suit: .September, name: "SeptemberJunk", double: false),
                   JunkCard(suit: .September, name: "SeptemberJunk", double: false),
                   JunkCard(suit: .October, name: "OctoberJunk", double: false),
                   JunkCard(suit: .October, name: "OctoberJunk", double: false),
                   JunkCard(suit: .November, name: "NovemberJunk", double: false),
                   JunkCard(suit: .November, name: "NovemberJunk", double: false),
                   JunkCard(suit: .November, name: "NovemberJunkDouble", double: true),
                   JunkCard(suit: .December, name: "DecemberJunkDouble", double: true)]

I know that dictionaries are faster than arrays to deal with, but this isn’t a situation where the array is going to constantly increase in size. These cards have been stable for a few hundred years, they are not going to dramatically change in any way.

Approaching this in this way has made my code a lot easier to deal with. I can sort all of the cards in the array by their type so that when I get around to writing the scoring logic it will be easier to simply pull out every card by its type. Anything I want to track, such as if a junk card is worth two, can be added to this set of code that I never have to touch again. I don’t have to remember how I named anything because I can track everything through its type and its properties. I kept the names so that when I read what cards I have in my hand I know what they are without having to remember what they’re called while I am doing my programming logic.

Conclusions

My new playground with the refactored code is here.

I wasn’t planning to refactor this code this early in the process, but I feel like this is a good illustration of why I am writing this series of posts.

I have seen many projects where they were built upon faulty assumptions. Rather than going back and rewriting the code, work-arounds were implemented making the code increasingly more complex and fragile.

Had I continued on the path I was on, the code base would have been incredibly difficult to maintain. There are probably still better ways to approach this, but I feel a lot better about the code currently than I did earlier this week. I want to idiot proof this code as much as possible and I stripped out some necessary complexity without thinking about how much harder that would make things for me later.

My next goal with this code is to figure out the best way to shuffle the array containing the deck. After I get that squared away, I need to figure out how to represent a player, a hand, and the game board. I also need to start writing unit tests for my code, but I will wait until later. No, I am not doing TDD. Jump in a river.

Until next time!

Game Development Journal 4: Representing the Flower Cards in Code

One of the things that drives me completely crazy about reading programming books is that I feel like there is a huge base of knowledge that no one ever talks about.

Over the weekend at Indie DevStock, Simon Allardice spoke a bit about how a lot of teaching materials are terrible because they bombard you with a bunch of facts. If you’re watching an instructional video about Swift the presenter will start showing you every single little menu in Xcode because it’s there and by the time you get to code you’re already irreparably lost and don’t really care anymore.

I see this too and have been guilty of it myself. Whenever WWDC comes around, I and other conference speakers obsessively look for whatever is going to be the new hot thing from the new version of iOS that we can pitch a talk on. We latch onto one thing and learn just enough about it that we can present a talk on it. We come up with convoluted reasons to use the new shiny object so that we can use it as an example in our talk. We go in and talk knowledgeably about this new thing and people come to see us and because we know more than they do (which is usually not a whole lot) and think we’re like experts or geniuses or something.

I almost never come out of a talk or a tutorial thinking about how this new API/tool/whatever is going to completely change my workflow. I will think it’s cool and will try to find reasons to use it, but I almost never have an organic reason for doing so.

There is almost always an easier way to do something than the way we choose. We choose overly complex solutions for things because we feel pressure to show off how smart we are. We write unreadable Swift code because having it look too imperative makes us worry we’re going to look like noobs and not be on the cool functional train.

My attempt to save us from ourselves is going to be contain in this series of blog posts. I am going to present part of an issue I need to solve in order to implement my game. I am going to go over several possible solutions and then explain why I chose the solution I did.

Sometimes I will be comparing an implementation in just plain Swift to using a framework provided by Apple. I hope to make all of this available on GitHub.

I would like to open up our conversations in programming from just “What is the new cool thing out” to “How can using this solve my problems?”

Choosing a Starting Point

The first problem is figuring out where to start. My initial inclination is to think about the user interface because that is the thing that most of us see and interact with, but that is the last thing that should be implemented.

I read a book a while back called Systemantics: How Systems Work and Especially How They Fail. At the first startup I worked at, they had implemented several systems to try and facilitate communication among all the employees about deadlines and so forth. We had about a dozen employees at that point, but we had multiple layers of systems. In order to update anything, you had to update it in about five different places. The engineers would look at the issue tracker in the Git repository and the managers would look at the Post-it notes on the SCRUM board. Their solution to this problem was to add another layer of systems on top of everything else.

All of these systems we put into place work against us and make us slower. It’s really important to only implement the most simple system you can that will fulfill your needs. Yes, once you read the size of a place like Apple you must have systems in place or else nothing will get done. But if you’re a small team of people, you don’t need a system as complex as one that Apple needs. You’ll spend all of your time maintaining the system and nothing will get done.

Another aspect of this book talked about how to build a system. This works for application architecture as well as for teams. The best way to implement a system is to build it out. You have to figure out what your most basic component is and get that up and running first. Once that is stable and tested and you feel good about it, then you can build out from there.

Since the UI is not the foundation upon which you should build your application, it is not the right place to start.

The most vital component to my card game are the cards. Having a card object in place and correct is necessary for me to build out the board representation, game logic, and UI.

So I am starting out building my card objects.

Creating My Flower Deck Structures

Next I need to really think about what my card objects need to do and what pieces of information they need to be able to carry and convey.

Godori does not use a traditional Western deck. Western card decks were outlawed in Japan, and so they developed their own deck that is the basis of many card games that originated in Asia. There are a number of differences between Asian flower decks and traditional Western decks:

  • 48 cards instead of 52
  • 12 suits of four cards instead of four suits of 13 cards
  • Not numbered
  • No court cards (King, Queen, etc…)
  • Each card must be one of four types: bright, ribbon, animal, or junk

Traditional decks are somewhat easy because most of the cards are numbered one through ten. In most Western games, court cards count as ten, so it’s relatively easy to assign values to the cards.

Flower cards are slightly trickier. You need to keep track of not only what suit a card is, but what type it is.

The 48 cards in a flower deck have the following composition: five brights, nine animals, ten ribbons, and twenty-four junk cards. Every suit has at least one junk card and at least two special cards. These are pre-determined and you can use a lookup chart to see what suits have what composition of cards, so this is not going to be a random or automated task.

Enums

The first thing that I notice when looking over these requirements is that there are two pieces of information that a card must know about itself: its suit and what type of card it is. Both of these pieces of information have a limited number of options. There are twelve possible suits and only four possible types. This seems like a really good place to create a couple of enums.

enum CardType {
    case Bright
    case Ribbon
    case Animal
    case Junk
}

enum CardSuit {
    case January
    case February
    case March
    case April
    case May
    case June
    case July
    case August
    case September
    case October
    case November
    case December
}

This sets up the way to track what special characteristics a card has that we care about for the game mechanics. Now we need to apply those to our actual Card data structure.

Class vs Struct

This is part of the whole value vs reference debate. Initially, I thought that I needed to make this a class, but I realized I was remembering it wrong.

When you’re dealing with something where there will only be one thing, you use a class. For example, if you were going to describe a camera where there is only going to be one instance of that camera and it would be passed by reference through out the application, it should be a class. But in this case, I am creating multiple instances of my cards that are all going to be passed by value, so it should be a struct.

The struct should always be the default data structure you should use unless you have a really compelling reason to make something a class.

Each card needs to have two values associated with it: a suit and a type.

Knowing all of this, it’s now quite simple to put together the card structure:

struct Card {
    let cardSuit:CardSuit
    let cardType:CardType
    
    init(suit:CardSuit, type:CardType) {
        cardSuit = suit
        cardType = type
    }
}

Now that I have everything that I need to create a card, I now have to figure out how to create a deck of them.

Data Types: Representing A Deck

This is the most complicated part to represent from this initial foray into development. There are a lot of data structures that can contain a bunch of Card instances, but there are questions about what the best one is and additionally, what is the optimal way to populate that data structure with the card representations.

There are several collection types in Swift: Arrays, dictionaries, and sets.

Initially, I thought about making this into an array. That is kind of the default data structure when you have a lot of something that needs to be collected together.

A set would also work as well. Initially, the order of the cards in the deck really doesn’t matter, you just need to have a collection of all the cards. But I still thought there was a better way.

One issue I have with this game is that every card needs a unique identifier. I need to have an easy way to hook up each card to its graphical representation.

I thought about creating a name property for the card in the Card struct, but I realized that I could create this collection as a dictionary. I can assign a string name to each card as a key to access it rather than having to access its name property within the instance.

There are also several cards within the deck that have special rules associated with them. Rather than creating a bunch of optional properties within each card, it’s a lot easier for me conceptualize just using each card’s name.

The point I am trying to make is that there isn’t a right or a wrong answer for how to pick the collection type for the deck. I see many tutorials where people default to an array because that’s the first thing that comes to mind. There is no explanation about how the programmer decided to implement the programming logic and it seems like magic how the person figured it out. I want more people to think through what problem they are trying to solve rather than rote copying of code without any thought or context.

I have also spent a few days thinking through if there is any way to populate the deck using loops and conditionals. I was trying to figure out if there was a way to do this like you would if you were programming FizzBuzz, but the deck was not mathematically generated.

Initially I was going to create a function to generate the deck, but since the cards are not going to change, I realized that making the deck as a constant was a better way to proceed. It’s still a crap load of code, but it only needs to be done once and will not ever need to be changed.

I have, for the time being, set every card manually. I wanted to give each card a unique name and ensure that the cards are created properly.

let deck:[String:Card] = ["JanBright": Card(suit: .January, type: .Bright),
                          "JanRibbon": Card(suit: .January, type: .Ribbon),
                          "JanJunk1": Card(suit: .January, type: .Junk),
                          "JanJunk2": Card(suit: .January, type: .Junk),
                          "FebBird": Card(suit: .February, type: .Animal),
                          "FebRibbon": Card(suit: .February, type: .Ribbon),
                          "FebJunk1": Card(suit: .February, type: .Junk),
                          "FebJunk2": Card(suit: .February, type: .Junk),
                          "MarchBright": Card(suit: .March, type: .Bright),
                          "MarchRibbom": Card(suit: .March, type: .Ribbon),
                          "MarchJunk1": Card(suit: .March, type: .Junk),
                          "MarchJunk2": Card(suit: .March, type: .Junk),
                          "AprilBird": Card(suit: .April, type: .Animal),
                          "AprilRibbon": Card(suit: .April, type: .Ribbon),
                          "AprilJunk1": Card(suit: .April, type: .Junk),
                          "AprilJunk2": Card(suit: .April, type: .Junk),
                          "MayAnimal": Card(suit: .May, type: .Animal),
                          "MayRibbon": Card(suit: .May, type: .Ribbon),
                          "MayJunk1": Card(suit: .May, type: .Junk),
                          "MayJunk2": Card(suit: .May, type: .Junk),
                          "JuneAnimal": Card(suit: .June, type: .Animal),
                          "JuneRibbon": Card(suit: .June, type:.Ribbon),
                          "JuneJunk1": Card(suit: .June, type: .Junk),
                          "JuneJunk2": Card(suit: .June, type: .Junk),
                          "JulyAnimal": Card(suit: .July, type: .Animal),
                          "JulyRibbon": Card(suit: .July, type: .Ribbon),
                          "JulyJunk1": Card(suit: .July, type: .Junk),
                          "JulyJunk2": Card(suit: .July, type: .Junk),
                          "AugBright": Card(suit: .August, type: .Bright),
                          "AugBird": Card(suit: .August, type: .Animal),
                          "AugJunk1": Card(suit: .August, type: .Junk),
                          "AugJunk2": Card(suit: .August, type: .Junk),
                          "SepAnimal": Card(suit: .September, type: .Animal),
                          "SepRibbon": Card(suit: .September, type: .Ribbon),
                          "SepJunk1": Card(suit: .September, type: .Junk),
                          "SepJunk2": Card(suit: .September, type: .Junk),
                          "OctAnimal": Card(suit: .October, type: .Animal),
                          "OctRibbon": Card(suit: .October, type: .Ribbon),
                          "OctJunk1": Card(suit: .October, type: .Junk),
                          "OctJunk2": Card(suit: .October, type: .Junk),
                          "NovBright": Card(suit: .November, type: .Bright),
                          "NovAnimal": Card(suit: .November, type: .Animal),
                          "NovRibbon": Card(suit: .November, type: .Ribbon),
                          "NovJunkDouble": Card(suit: .November, type: .Junk),
                          "DecBright": Card(suit: .December, type:.Bright),
                          "DecJunkDouble": Card(suit: .December, type: .Junk),
                          "DecJunk1": Card(suit: .December, type: .Junk),
                          "DecJunk2": Card(suit: .December, type: .Junk),]

There are a few special rules in Godori where certain cards, such as the ones with birds on them, are worth a special bonus if you collect all of them. I did not want to put a bunch of optional properties on the card class for instances that affect only a few cards. I am tagging those cards in their name to try and handle those edge cases in the programming logic rather than hard coding it as a parameter. There are other edge cases I have not dealt with yet and I will go back and deal with that later.

This is part of the problem I see when people talk about the promise of Swift. Swift is really good at removing lines of code, but only in situations where you have certain kinds of programming logic.

If you are parsing a file or processing some kind of information or a few other situations, Swift’s pattern matching and protocols is fantastic and allows you to remove a lot of lines of code.

However, if you are interacting with the Cocoa frameworks or setting up something with a lot of customization, such as the user interface, there are a limited number of things you can pull out and automate.

Since the type of card in each suit does not have a pattern that I can detect, I don’t think I can automate this with loops and conditionals in any way that will be clear later.

I am planning to go through this project and refactor it periodically, so it’s possible I could figure out a better way to automate the deck generation than to manually create each card and add it to the collection. Until then, I am entering each card.

Wrap Up

I have pushed this playground to GitHub. I know that right now it doesn’t look like much, but big things come from small beginnings. This is the foundation upon which everything else will be built. I fully expect to expand on this and refactor it as I figure out better ways to do things.

Things don’t have to be perfect when you first create them. You should be going back and looking over code you wrote before and looking to see if you can make it better based on what you’ve learned since you wrote it.

I hope to post at least one blog post a week on what I have done on this project. I hope to make steady progress on this application and for people to be able to see it come together.

Thanks for reading.

Game Development Journal 3: Learning to Embrace Higher Level Abstractions

For the last few months I have been working on a project that required me to write a simple game and apply Gameplay Kit AI to the project. I chose a simple tic tac toe game because it’s simple. It’s tic tac toe. Three year olds play this game. It should be easy to implement, right?

Wrong.

I have been bashing my head against this stupid game for months because I was trying to figure out how to do it in Sprite Kit. (To be fair, I have also been rather burned out and little things have been incredibly difficult for me to deal with. Please do not judge me.)

Sprite Kit is good for a lot of things. It’s good if you are doing a platformer game like Super Mario Brothers or if you’re creating an endless runner. Sprite Kit is not as good at doing things like tic tac toe or card/board games. I was looking through my books and tutorials to try to figure out how to tell the app that a square area of the screen represented a specific square of a tic tac toe board. Most materials are glorified rewritten documentation or they focus on the easiest examples they can possibly figure out, which includes spawning enemies and having sprites removed from the screen when they collide with one.

This was driving me batty. I knew there had to be a way to do this, but I felt like I was fighting the framework because the framework wasn’t designed to do what I needed it to do.

This problem was completely roadblocking me. I couldn’t think about how to write the programming logic until I figured this out. I knew I should worry about the UI after I got the logic finished, but this thing was completely blocking my ability to conceptualize how to approach this problem. I was incredibly upset because I knew there should be an easy way to do this but I couldn’t find it in any Sprite Kit examples I was seeing.

My mental block finally crumbled a few days ago when I realized I should not be using Sprite Kit for this project. I should use UIKit. Instead of trying to figure out how to programmatically tell the app that a square area on the screen represents a square on a tic tac toe board, I should just create nine buttons.

In Paul Hudson’s Hacking with Swift book, he recreates the Four in a Row Gameplay Kit example with Swift. I looked at the Apple example and found it incomprehensible, so I was incredibly happy to find he walked through how to implement and design that example more clearly.

One thing he did in that example was he did his entire user interface in UIKit with stack views. One thing he showed that I didn’t know you could do was to create a tag for each button in the stack view and connect all of the buttons to the same outlet and action.

I have my name on books. I speak at conferences. I have worked for some fairly prestigious places. For the last year or so I have let my pride get in the way of me doing things I need to do to be a better developer.

I do not have a lot of experience. I was at Indie DevStock this weekend and I heard most of the other indie developers I look up to had 15-20 years of programming experience. I have three. I think I am a pretty good programmer for only having three years of experience, but I know that I could be a lot better than I am right now.

I have tried to find a normal job so that I can pay my dues and learn from people with more experience than I do, but with one exception, that has not happened. I encounter other people who are like me. We feel like we need to pretend like we know what we’re doing rather than acknowledge that we need to work on our fundamentals and that working on fundamentals honestly takes a lot of time. If you’re working at a company that expects you to work sixty hours a week and you have to spend all your time pretending like you know everything, you don’t have enough mental or emotional energy to go and learn stuff that you may have known at some point in the past but you don’t remember now.

Also, honestly, we feel intense amounts of pressure to convince everyone that we’re a programming ninja. No one can just be a good, solid developer. Everyone has to be a 10x engineer. Everyone has to be a ninja. We’re all competing with one another to prove that we’re hot shit and that attitude is actively stunting the growth of members of our engineering community.

When I first started out, no one knew who I was or anything about me. I knew I could not get a decent job if people didn’t know who I was. I went to a lot of effort to network and make connections. I wanted to attend a lot of conferences, but couldn’t afford to go. So I needed to find a job so that I could make enough money to attend conferences to find a job. That didn’t work. There was a work around, which was to be a speaker.

I didn’t want to be the dumb-ass pitching beginner talks to conferences on stuff I figured everyone already knew anyway. I decided to go big and started talking about GPU programming with Metal and GPUImage. I had some grasp of how these things worked, but I couldn’t think of anything I could do with them. I just wanted to know them.

I tried to learn these things without any real context for where they should be used. This is not a good way to learn something. It’s mentally exhausting and draining. You feel stupid and your mental state deteriorates. You feel like a failure but you can’t give up because you want to prove that you deserve to be around everyone else.

I recently had a conversation with Warren Moore where I told him I wanted to learn Metal better but I couldn’t think of a project to do in Metal that I couldn’t do in Scene Kit. He told me that was the point. They weren’t intending for everyone to jump into OpenGL or Metal. Scene Kit was designed to do almost everything you need to do and only once you exhaust what Scene Kit can do should you drop down to Metal.

I felt like this was the most obvious thing in the world and I have no idea why it took me two years and a few nervous breakdowns to finally figure that out.

I have been so obsessed with trying to convince everyone that I deserve to be here that I have been focusing on the wrong things. I make things more complicated than they have to be. I don’t look for the simplest solution. I jump into the most complicated thing I can so that I can find an excuse to learn something that may not be the right tool for what I want to do. I do that at the expense of getting comfortable and familiar with the easy solutions that allow me to get things done more quickly.

I have been on a path that leads me to places I don’t want to go. I want to be a great programmer. Knowing how to render a triangle to a screen in Metal does not make me a great programmer. It makes me a clever programmer. Writing clean code that anyone can read and understand at the highest abstraction level makes me a great programmer. Knowing the higher level abstractions well enough to know what they can and can’t do and when to drop to a lower abstraction makes me a great programmer.

Right now I am not a great programmer. I am a good programmer. I can do 90% of what most jobs need me to do, but I want to work towards being someone who is respected in the community for being able to solve problems.

I don’t want to keep seeking out really low levels of abstraction and create convoluted reasons regarding why I am using them when I could do things much easier in another way. That’s just stupid and I am not doing it any more. That path leads to mental ruin and despair.