The Bitwise Challenge Post-Mortem, Part 4

This is part 4 of the post-mortem I’m doing for the Bitwise Challenge, in which I made a Tetris-like game called Loftis as an Addon in WildStar in four hours. Here are links to parts onetwo, and three.

Okay, so by the end of part 3 we had written the logic for creating new blocks, testing whether a position is valid, rotating blocks, and moving blocks side to side as they rise through the field.

If when a block is rising it cannot move into the position above, it is time to place it. The code for placing a block is straightforward:

 local tGame = self.tGame
 local tBlock = self.tGame.tBlock
 for y = 1,4 do 
   for x = 1,4 do
     if tBlock[y][x] then
       tGame.arField[tGame.iRow + y - 1][tGame.iColumn + x - 1] = true
       local tPixie = tGame.arPixies[tGame.iRow + y - 1][tGame.iColumn + x - 1]
       local nLeft = (tGame.iColumn + x - 2) * 32
       local nTop = -128 + (tGame.iRow + y) * 32 - 32

       tPixie.loc.nOffsets = {nLeft, nTop, nLeft + 32, nTop + 32}
       tPixie.id = self.wndGame:AddPixie(tPixie)
       tGame.arPixies[tGame.iRow + y - 1][tGame.iColumn + x - 1] = tPixie
     end
   end
 end
 self.tGame.tBlock = nil

Aaaaaaaack! More magic numbers. Bad Bitwise. I’m not going to talk too much about the Pixies API calls here because that is WildStar-specific, and these post-mortems are more about the logic behind Loftis. All that we are really doing here is setting the tGame.arField[y][x] to true for any corresponding true value in our rising block. After doing that we reset the tGame.tBlock member to nil. We’ll see why later.

After placing a new block, we check to see if we have completed any rows. This is done in two steps. First, we make a list of all rows in which all 10 blocks are filled.

 -- check for scoring
 nRowCount = 0
 arRowsToRemove = {}
 for y = 4,21 do
   local nBlocks = 0
   for x = 1,10 do
     if tGame.arField[y][x] then
       nBlocks = nBlocks + 1
     end
   end

   if nBlocks == 10 then
     nRowCount = nRowCount + 1
     arRowsToRemove[nRowCount] = y
   end
 end

Note: the arRowsToRemove variable should be local! I’m really not sure why it wasn’t flagged as local; might have been an edit or just an oversight. Also note that we start our checking at row 4 because rows 1-3 are dummy rows that are always on. But we only go to 21! Another bug! That should be 24. Whenever we find a row that is completely on, we store its index and continue.

After compiling our list of completed rows, we remove them in reverse order, so as to preserve the correct indices of preceding rows.

 if nRowCount == 0 then
   return
 end

 local nScore = 50
 for i = nRowCount,1,-1 do
   nScore = nScore * 2
   self:RemoveRow(arRowsToRemove[i])
 end

 self.tGame.nScore = self.tGame.nScore + nScore

We also double the score for each row and add that temporary value to the game score. Since we started at 50, the scores for completing 1-4 rows will be 100, 200, 400, 800.

Removing a row is simple:

 for y = nRow, 27 do
   for x = 1,10 do
     tGame.arField[y][x] = tGame.arField[y + 1][x]
   end
 end

 for x = 1,10 do
   tGame.arField[28][x] = false
 end

The magic numbers… they burn. You can hopefully see why removing the rows in reverse order is necessary here. Note that this method of counting the rows and then calling RemoveRow for each of the rows is really really inefficient. Because of the way I do this, if I were to remove the first 4 rows due to a particularly well placed I-piece, nearly the entirely field is moved 4 entire times. There are two reasons I did it this way: one, it was very very fast to write it this way. Two, even though it is about as inefficient as possible, it’s still plenty fast enough to get all the work done without a hiccup. Again, in a production environment or with a larger dataset, we wouldn’t do it this way.

Along those same lines, if you look at the code dealing with pixies surrounding the removal code, you can see that I destroy all the blocks in the field and re-create them with every single row removal. Extremely inefficient! I started to do this in a better way but by this point I was really sweating the clock and ended up just hacking this code because I knew performance wasn’t a concern.

That brings us to the last part of this Addon, the update function. Here the function is called OnTimer, because I implemented through the use of an Apollo timer. Normally I would respond every frame and calculate how much time had elapsed for the simulation. Here, however, I just decided to set a 20 Hz timer and always assume that 50 ms had elapsed. Again, a coding speed decision. The result of this is that if WildStar slows down to less than 20 FPS, Loftis will slow down, making it easier to play.

Here’s the OnTimer function:

function Loftis:OnTimer()
 if self.tGame == nil then
   return
 end
 local tGame = self.tGame
 if tGame.bGameOver then
   return
 end
 if tGame.tBlock == nil then
   -- we need to make a new block and put it in the world
   -- if we can't place the block, game over man
   local iBlock = math.random(1, 7)
   local tBlock = InitBlock(karBlocks[iBlock])
   local nRotate = math.random(1, 4)
   for i = 1,nRotate do
     tBlock = RotateBlockRight(tBlock)
   end
   if not self:IsPositionValid(tBlock, 24, 5) then
     self:DoGameOver()
   end
   tGame.tBlock = tBlock
   tGame.iColumn = 4
   tGame.iRow = 24
   tGame.fProgress = 0
   return
 end

 tGame.fProgress = tGame.fProgress + 0.10
 if tGame.fProgress >= 1.0 then
   if tGame.iRow > 1 and self:IsPositionValid(tGame.tBlock, tGame.iRow - 1, tGame.iColumn) then
     tGame.fProgress = 0
     tGame.iRow = tGame.iRow - 1
   else
     self:PlaceBlock()
     return
   end
 end

 -- Update Block pixies
 self:UpdateBlockPixies()
end

Now you can see why I initialized the tGame.tBlock member to nil when starting a new game, and why we reset it to nil when it is placed. Every update, we check to see if it is nil, and if it is, we create a new one from the 7 variations, rotate it 1-4 times, and then place it if we can, or call DoGameOver if we cannot.

Rising is controlled through the fProgress member, as noted previously. Here’s another magic number, 0.10, which determines how fast the blocks are rising. This equates to one block every half a second. If we had used an elapsed time model, we would have used a constant for speed (2.0) and multiplied it by elapsed time. Whenever fProgress gets to 1, we check to see if the block can keep rising and reset progress to 0, or place the block.

Finally, we call UpdateBlockPixies to modify the sprites that are used to draw the block. I won’t go into much detail there (again, WildStar specific) but the method I used does allow for “smooth movement” of the blocks as they rise, using fProgress to determine the relative y-value of the sprites drawn.

That’s pretty much it for Loftis. I’ve gone over all the major logic in the game and hopefully showed my thought process as I wrote the game. Not bad for a 4-hour challenge, though your mileage may vary. Obviously there were bugs that I found as I did this post-mortem, and there might be others as well. If you are in the WildStar beta, please feel free to install Loftis, modify it, etc. I myself will be updating a version with a little more polish and a few less bugs eventually, probably next week, depending on the weather here.

If you are not in the WildStar beta, you can probably follow along with the Apollo API calls and get a pretty good feel for what they do based on their names. I hope to see you in the game eventually!

Bitwise out.

Posted in Videogames, WildStar | Tagged , , | 2 Comments

The Bitwise Challenge Post-Mortem, Part 3

This is part 3 of the post-mortem I’m doing for the Bitwise Challenge, in which I made a Tetris-like game called Loftis as an Addon in WildStar in four hours. Here are links to parts one and two.

Just a quick aside: I’ve now spent more time writing the post-mortem than the challenge itself, and I’m only about halfway done. Okay, moving on.

By the end of part two, we had an object representing the game field, a way to make new blocks and to rotate them, and I had described the process by which I would simulate rising blocks. Now let’s look at the logic for whether a proposed position of a block is a valid location. This is essentially the meat of Loftis, right here:

function Loftis:IsPositionValid(tBlock, iRow, iColumn)
 local tGame = self.tGame
 for y = 1,4 do
   for x = 1,4 do
     if tBlock[y][x] then
       if iRow + y - 1 < 1 or iRow + y - 1 > 28 or iColumn + x - 1 < 1 or iColumn + x - 1 > 10 then
         return false
       end
       if tGame.arField[iRow + y - 1][iColumn + x - 1] then
         return false
       end
    end
   end
 end
 return true
end

This is pretty straightforward, but it is made a little less clear because of Lua’s one-based nature, which is something that I curse on an almost-daily basis. Let’s look at what’s going on, because this is the function that really determines what happens next at any given point.

Basically what I’m doing here is testing the passed block (tBlock), which is represented by a 4×4 array of boolean values, and testing whether the position passed in (iRow, iColumn) is valid. The way to test that is simple: for each of those sixteen booleans that are true, if the corresponding block in the game’s field of blocks is also true, the block cannot be placed there. Also, if the corresponding “on” block would be outside the game field, (x < 1 or x > 10) then the block cannot be placed in the proposed position.

IsPositionValid is called 6 times in Loftis. The first one I wrote is right after creating a new block:

if not self:IsPositionValid(tBlock, 24, 5) then
  self:DoGameOver()
end
tGame.tBlock = tBlock
tGame.iColumn = 4
tGame.iRow = 24

If it is time to create a new block, and a new block cannot be placed, it’s because the field has been filled up with blocks, so in that case, the game is over. And hey look! Remember when I talked about magic numbers before? For those who aren’t familiar with the programmer lingo, a “magic number” is a hard-coded literal constant. In this case 24, 5, 24, and…. 4! If you are understanding the code I am writing here, you may have just realized I have a bug in Loftis, a bug I just found in this post-mortem!

Even during the challenge I knew I shouldn’t have been using magic numbers. I tweeted this at the 2:25 mark:

This rather conveniently illustrates the exact danger in writing magic numbers. Obviously I had started the new block in column 5, and then realized it needs to be in column 4 instead, but since I used literal 5s when writing the code, changing it required me to change all the instances of 5 when I was referring to the starting column. But I clearly forgot to do that in the call to IsPositionValid. If I had taken the time to create a constant like this:

local kStartCol = 4
local kStartRow = 24

and written the code like this:

if not self:IsPositionValid(tBlock, kStartRow, kStartCol) then
  self:DoGameOver()
end
tGame.tBlock = tBlock
tGame.iColumn = kStartCol
tGame.iRow = kStartRow

There would have been no bug when I decided that starting column needed to be 4 instead of 5. I really couldn’t have found a better illustration as to why magic numbers are so bad. Don’t use them! Even in 4-hour coding challenges, in case you are ever in one…

Let’s move on to the next usage.

if tGame.fProgress >= 1.0 then
 if tGame.iRow > 1 and self:IsPositionValid(tGame.tBlock, tGame.iRow - 1, tGame.iColumn) then
   tGame.fProgress = 0
   tGame.iRow = tGame.iRow - 1
 else
   self:PlaceBlock()
   return
 end
end

This second use of IsPositionValid is called after the progress for the current block has exceeded 1.0. When it does so, we check to see if it is still possible to fall or if it has come to rest on another (higher) block. If the new position check fails, it’s time to place the block. If it succeeds, we update our new row (subtracting one) and reset progress to be 0.0.

After I had written this code it was possible for me to start a game and watch blocks rise to the top, collide, and get placed. I sent out this tweet:

After that there were two calls to handle attempts to move left and right. These were very straightforward:

if self:IsPositionValid(tGame.tBlock, tGame.iRow, tGame.iColumn - 1) then
  tGame.iColumn = tGame.iColumn - 1
end
if self:IsPositionValid(tGame.tBlock, tGame.iRow, tGame.iColumn + 1) then
  tGame.iColumn = tGame.iColumn + 1
end

Check the space on your left or right. Can we move there? If so, cool, do it. If not, do nothing. In a more polished game, we might play a buzz sound here when we fail, but not in a 4-hour challenge.

Finally the last two calls to IsPositionValid are used when attempting to rotate the current block. Remember how I said I rewrote RotateBlockLeft and RotateBlockRight to return a new block instead of changing the current block in place? This is why. In Tetris Loftis, it’s possible that your block could be in a position where attempting to rotate would cause the block to collide with the field. This is how I handle it:

function Loftis:OnRotateLeft( wndHandler, wndControl, eMouseButton )
 local tGame = self.tGame
 local tNewBlock = RotateBlockLeft(tGame.tBlock)
 if self:IsPositionValid(tNewBlock, tGame.iRow, tGame.iColumn) then
   tGame.tBlock = tNewBlock
 end
 self:UpdateBlockPixies()
end

I call my rotate function which returns a rotated copy of my current block. I then check to see if that new block’s position/orientation is valid. If it is, I assign it to be the current block. (The old current block loses its reference and is collected here. Thanks garbage collector!) If the new block is not valid, I do nothing and it is collected when I exit the function.

Okay, that does it for today. I should be able to finish this thing up tomorrow.

Bitwise out.

Posted in Videogames, WildStar | Tagged , , , | 2 Comments

The Bitwise Challenge Post-Mortem, Part 2

Hello again.

This is the second post in a series about the Bitwise Challenge, wherein I wrote a Tetris clone as an Addon in the upcoming MMO WildStar. Part 1 is here.

When I ended the last post, I had just written the code to create a new block, randomly selected from the 7 different Tetris blocks that we had defined. The next code I wrote was the code to rotate one of these blocks as it was falling rising.

function RotateBlockLeft(tOldBlock)
 local tBlock = {}
 for i = 1,4 do
   tBlock[i] = {}
 end

 -- 1 2 3 4     4 8 C G
 -- 5 6 7 8 --> 3 7 B F
 -- 9 A B C     2 6 A E
 -- D E F G     1 5 9 D

 tBlock[4][1] = tOldBlock[1][1]
 tBlock[3][1] = tOldBlock[1][2]
 tBlock[2][1] = tOldBlock[1][3]
 tBlock[1][1] = tOldBlock[1][4]
 tBlock[4][2] = tOldBlock[2][1]
 tBlock[3][2] = tOldBlock[2][2]
 tBlock[2][2] = tOldBlock[2][3]
 tBlock[1][2] = tOldBlock[2][4]
 tBlock[4][3] = tOldBlock[3][1]
 tBlock[3][3] = tOldBlock[3][2]
 tBlock[2][3] = tOldBlock[3][3]
 tBlock[1][3] = tOldBlock[3][4]
 tBlock[4][4] = tOldBlock[4][1]
 tBlock[3][4] = tOldBlock[4][2]
 tBlock[2][4] = tOldBlock[4][3]
 tBlock[1][4] = tOldBlock[4][4]

 return tBlock
end
function RotateBlockRight(tOldBlock)

 local tBlock = {}
 for i = 1,4 do
   tBlock[i] = {}
 end
 -- 1 2 3 4     D 9 5 1
 -- 5 6 7 8 --> E A 6 2
 -- 9 A B C     F B 7 3
 -- D E F G     G C 7 4

 tBlock[1][4] = tOldBlock[1][1]
 tBlock[2][4] = tOldBlock[1][2]
 tBlock[3][4] = tOldBlock[1][3]
 tBlock[4][4] = tOldBlock[1][4]
 tBlock[1][3] = tOldBlock[2][1]
 tBlock[2][3] = tOldBlock[2][2]
 tBlock[3][3] = tOldBlock[2][3]
 tBlock[4][3] = tOldBlock[2][4]
 tBlock[1][2] = tOldBlock[3][1]
 tBlock[2][2] = tOldBlock[3][2]
 tBlock[3][2] = tOldBlock[3][3]
 tBlock[4][2] = tOldBlock[3][4]
 tBlock[1][1] = tOldBlock[4][1]
 tBlock[2][1] = tOldBlock[4][2]
 tBlock[3][1] = tOldBlock[4][3]
 tBlock[4][1] = tOldBlock[4][4]

 return tBlock
end

This code evolved during the challenge a bit. When I first wrote it, it received a block as a parameter and did the transformation on the block passed in. (All Lua tables are passed by reference.) I changed it so that instead I create a new block from the passed block, transform it, and then return it as a new object. I’ll explain why when I show the code that calls this.

The code for rotation is pretty straightforward. You can see that I included some comments (in green) to show exactly what a rotated 4×4 block should look like before and after the transformation. I wrote those comments before I coded the logic so that I could refer to them as I was doing the assignments.

After writing those utility functions, it was time to think about the actual game object. I created a table called tGame and filled it with the information needed to keep track of a game.

local tGame = {}
 tGame.arField = {}
 tGame.arPixies = {}
 for y = 1,28 do
   tGame.arField[y] = {}
   tGame.arPixies[y] = {}
   for x = 1,10 do
     tGame.arField[y][x] = (y <= 3)
     tGame.arPixies[y][x] = {
       id = 0,
       strSprite = "WhiteFill",
       loc = {fPoints = {0, 0, 0, 0}, nOffsets = {0, 0, 32, 32}},
       cr = ApolloColor.new("xkcdAquaMarine")
     }
   end
 end
 tGame.nScore = 0
 tGame.fProgress = 0
 tGame.iColumn = 5
 tGame.iRow = 21
 tGame.tBlock = nil
 tGame.bGameOver = false
 tGame.arBlockPixies = {}
 for i = 1,16 do
   local tBlockPixie = {id = 0}
   tBlockPixie.strSprite = "WhiteFill"
   tBlockPixie.cr = ApolloColor.new("blue")
   tBlockPixie.loc = {}
   tBlockPixie.loc.fPoints = {0, 0, 0, 0}
   tBlockPixie.loc.nOffsets = {0, 0, 32, 32}
   tGame.arBlockPixies[i] = tBlockPixie
 end

Some of these, like nScore and bGameOver, are self-explanatory. The arField member is a 2D-array of boolean variables that represent where blocks have been placed in the game. If you can follow the logic there you’ll notice that I made it 28×10. This is also the first of the (way too many) magic variables I would add to the code. Even as I was typing them out, I knew it was wrong, but I was under a time constraint so I did it anyway. Sigh.

You may also wonder why the array has 28 rows, instead of just 21 as in a standard Tetris board. This is another thing that evolved as I was writing the code. Because of the way I would eventually write the logic to check whether a block could be placed, it was a lot easier to have 3 “dummy” rows of filled in blocks at the top of the board, and 4 “dummy” rows of empty blocks at the bottom. This explains the assignment of:

tGame.arField[y][x] = (y <= 3)

The arPixies member holds the actual pixies (an Apollo object for drawing sprites) that will draw the placed blocks. tBlock is set to nil but this will eventually hold the block that is rising. iColumn and iRow represent the position of the upper-left corner of the rising block. Finally fProgress represents the “progress” of the rising block, from 0 to 1. Whenever fProgress reaches 1, we will check to see if the block can be moved up; if it can, we do so and reset progress to 0. If it cannot, we will place the block and generate a new one.

I’ll talk about the logic for checking whether a block can be moved in the next post, hopefully tomorrow as sun and sand permit.

Bitwise out.

Posted in Videogames, WildStar | Tagged , , , , | 2 Comments

The Bitwise Challenge Post Mortem, Part 1

Hello!

If you are reading this, it’s probably because you either a) were directed here by a tweet about the Bitwise Challenge, or b) you used to read a political blog called SomeDisagree and you decided to see what’s up with it. If you are in that second group, I’ve got bad news for you. I haven’t been doing much political blogging lately (in case you hadn’t noticed) and I’m not really starting up again now. I’m using this blog to post some stuff about a game I work on called WildStar. On the Carbine forums (fora?) I am called Bitwise, hence the name of the challenge I’ll be talking about.

Okay, if you are in that first group, good news! You’re in the right place for information about the Bitwise Challenge, where I made a Tetris clone using the WildStar user interface engine in 4 hours on a dare. As the first paragraph alluded to, this site used to be a political blog, but after the 2012 election I lost all interest in political blogging and my fellow bloggers here pretty much did too, so this site has been almost entirely unused for the last 10 months. So I decided to use it to write up what I did with the challenge for those who expressed interest in it.

Now for the awesome disclaimers that everyone loves so much: THIS IS MY PERSONAL SITE. It is not associated with Carbine Studios and all the opinions expressed here are mine. I’m going to be talking about programming, not politics, but if you look through the previous postings you will see all sorts of things written by me and some of my friends which are very political. If that kind of thing might upset you, then don’t read the archives. If you’d rather stick with reading about this stuff via Carbine-approved sites, that’s cool, and some of this will probably get put on there eventually. I don’t apologize for anything I’ve posted on here, but it’s not going to be the focus moving forward. Probably. I dunno.

If you are here hoping to find out some new game information about WildStar, you (probably) won’t find much. All of that stuff is under tight control by our community relations peeps, and I won’t be (deliberately!) divulging any secrets here. In fact, this isn’t even going to be mostly about Apollo (the WildStar Addon Application Programming Interface) and Houston (an Addon Studio that will ship with the game) but the existence of those are already public knowledge. If you are curious about these aspects of WildStar and what it will be like to develop Addons for WildStar, you might find this interesting, but I won’t be revealing much new here about them. All of that stuff (Apollo, Houston, WildStar) is property of Carbine and we have an entire staff of people in charge of telling you all about it.

What this post (and others) WILL be about is the approach I take to programming a problem such as the one I tackled in the Bitwise Challenge. While the code here will be using the Apollo API, I won’t be going into any detail about that aspect of the code. Instead, I’ll be talking about reasons why I tackled certain logic problems in the way that I did, pointing out where I could have done things better, and stuff like that. Yes, you will see some of the Apollo API, and you may be able to glean some interesting info about it, but nothing that is a huge secret or anything. Most of the logic I will be talking about is API-agnostic, although not really language-agnostic, since Lua is so weird that it really affects the way you think about solving a problem.

Okay, on to the reason you are probably here, if you are still here: The Bitwise Challenge. For those who don’t remember, about 6-8 weeks ago someone tweeted a joke about Matt Krause spending all his time writing Tetris and I, in my usual humble manner, tweeted:

So… yeah, me and my big mouth. Anyway, that tweet got me to thinking. Could I really do it? So, the Bitwise Challenge was born. I talked to Troy at Carbine and he talked to the guys at Curse and we did this… thing… where I wrote a post about the challenge, and then I started at 5 PM and just started programming like a… something that programs… and tweeted about it and stuff and after 4 hours… I had a decent working version of Tetris:

So… success! Of course the challenge wasn’t ever about proving how awesome of a programmer I am (that’s just an added side benefit) but about how easy it is to create Addons for WildStar using Houston. With that in mind, I wanted to write up a post-mortem about the event that would illustrate some of the ways I went about solving the problem, along with the code. As some of you may remember, I had intended to do that over a weekend but was foiled when my younger son Jack decided to spill water all over my laptop, frying it. While the story of my poor laptop eventually had a happy ending thanks to Carbine IT, things were (and still are) pretty hectic at Carbine and I never did find time to write a post-mortem before my vacation.

So, yes, now I’m on vacation, and I’m choosing to spend at least some of that vacation on writing about programming games. Why? Because I love you guys, that’s why, assuming anyone is reading this. Also, I’m a huge nerd. Also, I like to point out that I wrote a Tetris clone in Houston in only 4 hours. Also… that’s enough alsos. Let’s get to the Addon.

First of all, I decided to make a Tetris clone with a WildStar theme, hence Loftis. For those who don’t know, on Nexus there are these weird crystals that float because [REDACTED] and they have some other cool properties like [REDACTED]. They’re called Loftite. So I decided my version of Tetris would be called Loftis and the blocks would float up rather than fall down. Also, coincidentally, a lot of the look of WildStar was created by a concept artist named Cory Loftis, who has since moved on to Disney, so it was kind of cool for that reason as well. Anyway, here’s a zip file that is Loftis as it was when the challenge ended:

Loftis Post Challenge source.

For those of you currently in beta, you can just copy the contents of that zip file into a folder named “Loftis” in your Addons (%appdata%\ncsoft\wildstar\Addons) folder. Login to the game and type “/loftis” on the chat entry line to invoke Loftis. It works pretty well, there are some bugs, but it keeps score and ends the game when you can’t place a new block anymore. I didn’t get the “Next Block” feature working.

I spent the first 25 minutes or so of the challenge just editing the form that would eventually be the Loftis UI. This included making all the controls for the game, and registering/creating the event handlers to handle the game controls. The scheme I came up with was “A” and “D” to move blocks left and right, and “Q” and “E” to rotate them. “W” can be used to quickly force a rising block to go immediately to its next position. Once I had finished the form, I ran the game and invoked Loftis, and sent this tweet with a screenshot:

As the tweet says, that’s Loftis running in game, without a single line of new Lua code. Once I did start writing code, here’s what I wrote first:

-- block definitions
local karBlocks = {
 {'    ', 
  '    ', 
  '****', 
  '    '},

 {'    ', 
  '   *', 
  ' ***', 
  '    '},

 {'    ', 
  ' *  ', 
  ' ***', 
  '    '},

 {'    ',
  ' ** ',
  ' ** ',
  '    '},

 {'    ',
  '**  ',
  ' ** ',
  '    '},

 {'    ',
  ' ** ',
  ' ** ',
  '    '},

 {'    ',
  '  * ',
  ' ***',
  '    '},
}

These represent the 7 different kinds of blocks that are used in Tetris, er, Loftis. I chose to represent the definitions as strings for the sole purpose that it made it much easier to enter them into the source code. It was purely a coding-speed decision, which is very different than a performance-speed decision. If I was purely interested in performance, I’d probably take the coding time to represent these blocks as booleans rather than strings that need to be parsed. However, the other thing to consider is readability, and the strings are much easier to read than a table of booleans; you can look at those blocks of text and sort of see the Tetris blocks. Since the conversion time from a string to boolean is not a concern (see below) I’d probably still use strings to define these blocks, even if I wasn’t under a 4-hour time constraint.

Anyway, in the game simulation, I represented the current block as an array of boolean variables, so I also had to write a converter:

function InitBlock(tBlockDef)
 local tBlock = {}

 for i = 1,4 do
   tBlock[i] = {}
   for x = 1,4 do 
     tBlock[i][x] = false
     if string.sub(tBlockDef[i], x, x) == '*' then
       tBlock[i][x] = true
     end
   end
 end
 return tBlock
end

This function takes one of those block definitions and returns a new 4×4 table of booleans with true representing a block and false representing empty space. Whenever it is time to place a new block, I first use math.random(1, 7) to choose which element of karBlocks to send to InitBlock:

local iBlock = math.random(1, 7)
local tBlock = InitBlock(karBlocks[iBlock])

Now I have a tBlock object that represents one of the seven Tetris blocks. What will I do with it? You’ll have to wait until tomorrow(ish) to find out! Hey, I’m on vacation.

Bitwise out.

UPDATE: In case this wasn’t obvious, NONE of this code is production-quality code. This was a speed programming challenge. There are all sorts of things (magic numbers, inefficient algorithms) that I would absolutely NOT do if I were writing this code to last. I’ll be pointing these things out as I write about them, with examples of what I might do instead in a production environment. Showing someone else your bad code is an act of trust; don’t get hung up on the ugliness.

Posted in Videogames, WildStar | 6 Comments

This place is dead anyway!

I needed a bit to re-charge my political batteries.  To be frank, in mid-2012 I just got sick of ranting about politics and was more frightened than amused by the tea party types and the Romney campaign. 

So here I am in 2013 with a political blog that has been dormant since 2012 and I’m ready to party once again.  Why the hell should I wait until 2014 anyhow?  With crazy eye’d Michelle Bachman stepping down (good riddance), The Governor of New Jersey getting the lap band (or was it merely a stapled stomach?) to cure his Cheetos addiction (as well as deflating so he looks more like a US President and less like the Michelin Man), and the anti-tax Tea Party getting their panties in a collective bunch over an IRS quasi-scandal brought to you by Fox News, there is still lots to rant about. 

 

Posted in Uncategorized | 1 Comment

MERS

A great article appeared in California Lawyer a few months back about MERS.  If you hate reading, take a look at John Stewart’s rant here.

Several of my colleagues and I are actively trying to fight against MERS in California but when I tell people about MERS and why it sucks, I get blank stares.  So here is the article about MERS and why it sucks (and if the good folks at callawyer.com think I suck for sharing the link and article here, I will take it down at their request). 

http://www.callawyer.com/clstory.cfm?eid=927421&wteid=927421_In_MERS_We_Trust

In MERS We Trust

by Thomas Brom

March 2013

When you get your pocket picked by a real pro, sometimes all you can do is appreciate the artistry. Such, apparently, is the case with MERS, a national electronic database of home mortgages that effectively swiped millions of dollars from local governments just when they could have used the revenue most.

By now homeowners across the country are familiar with Mortgage Electronic Registration Systems Inc. (MERS) and MERSCORP Holdings Inc., its corporate shell based in Reston, Virginia. Launched in 1997 by the Mortgage Bankers Association, Fannie Mae, and Freddie Mac, MERS was created to bypass perceived logjams at county recording offices, speeding the flow of notes to Wall Street for bundling, securitizing, and sale to investors. The casino needed more chips. According to boilerplate on its security agreements, MERS owns all the mortgages in the registry, “acting solely as a nominee for Lender and Lender’s successors and assigns.” MERS also claims to be “the beneficiary under this Security Instrument” and “a common agent for the mortgage industry” – admitting to no contradiction in assuming multiple roles. MERS Inc. is listed as mortgagee on an estimated 70 percent of all home mortgages. Member banks, however, may or may not track assignments, and they do not reveal the chain of title that extends from the loan originator to the securitized trusts controlled by pooling and servicing agreements. The registry operates with a handful of employees, relying on a small army of designated “vice-presidents” at loan servicing offices to process assignments and foreclosures. On its website MERS states that it is “not a system of public record nor a replacement for the public land records.” Nonetheless, designating MERS Inc. as the mortgagee for all subsequent transfers between members has saved mortgage bankers more than $2 billion in recording fees, according to a 2009 deposition by former MERSCORP president and CEO R. K. Arnold. MERS neither sought nor received permission to sidestep the public system. By using “a hollow placeholder as the grantee of their property interests,” writes Christopher L. Peterson of the University of Utah College of Law, “mortgage bankers have attempted to create a completely fungible mortgage in which the true owner of the lien, or the land itself in title-theory states, becomes whomever the … loan servicers say it is.” Peterson laments, “For the first time in the nation’s history there is no longer an authoritative, public record of who owns land in each county.” (53 WM. & MARY L. REV. 111, 117 (2011).) You’d think someone would have noticed. At first, the National Association of County Recorders, Election Officials and Clerks protested that there was no need for MERS to create a federal land-titling system, but to no avail. Most counties simply took the revenue loss on the chin – until the housing bust of 2007 produced a flood of foreclosures that exposed gaps in tracking assignments. Homeowners in many states sued MERS alleging wrongful foreclosure. Those filings continue in many states, but they are now rare in California. In 2011 a state appellate court ruled that MERS has no obligation to disclose documents prior to initiating a nonjudicial foreclosure, and that a homeowner has no private right of action to determine the identity of the beneficiary. (Gomes v. Countrywide Home Loans, Inc., 192 Cal. App. 4th 1149 (2011).) A spate of contrary rulings in federal bankruptcy court gave some California homeowners relief. But last year a federal district court – citing a state appellate ruling that deeds of trust in California need not be recorded (Calvo v. HSBC Bank USA N.A., 199 Cal. App. 4th 118 (2011)) – reversed a plaintiff’s bankruptcy court judgment. The district judge held that MERS had a statutory right to foreclose under the express language of the deed of trust. (In re Salazar, 470 B.R. 557, 562 (S.D. Cal. 2012).) Attorneys general in dozens of other states have sued MERS for deceptive trade practices, but very few complaints include claims for lost recording fees. The barriers to recovery are formidable: Depending on state law, recording title assignments may be mandatory or permissive; a private right of action must exist; county recorders must have standing to sue, and also be able to collect damages for failing to record. To date, lost-fee cases filed by county recorders have survived motions to dismiss in only three states – Alabama, Texas, and Pennsylvania. In October a trial court ruled that Pennsylvania’s mandatory recording statute allows “any person in any manner interested in a conveyance” to bring a quiet title action. The judge permitted a claim for unjust enrichment but threw out a civil conspiracy claim. (Montgomery County Recorder v. MERSCORP, Inc., 2012 WL 5199361 (E.D. Pa. 2012).) MERS, however, has appeals pending in all three cases. In a 2010 article, former Ginnie Mae CEO Joe Murin asserted, “[A]voiding these fees in no way constitutes any type of tax avoidance or fraud. Fees are paid in exchange for a service. If the service is not needed … then there is no ‘lost’ revenue.” In November a Massachusetts state court agreed, finding that MERS’s failure to register mortgage transfers was not unlawful. (Commonwealth v. Bank of America, 2012 WL 6062747.) California officials have been noticeably quiet on the lost-fee issue. In February 2011 Phil Ting – then San Francisco’s Assessor-Recorder – issued an audit of about 400 recent foreclosures that concluded about 84 percent of the files contained what appeared to be clear violations of law, and two-thirds had at least four violations or irregularities. But the Gomes ruling denied homeowners a private right of action. That same year, Ting coauthored AB 1321, a bill introduced by Assemblyman Bob Wieckowski (D-Fremont) requiring that any deed of trust assignment be recorded in the county where the property is located. But the measure died in committee, and wasn’t reintroduced. “It was seen as too burdensome on the industry, and also on county recorder offices,” says Heather Falkenthal in Wieckowski’s office. “They said we were addressing a problem that had already passed, and the bill fizzled.” Last November, Ting and former Orange County Clerk-Recorder Tom Daly – both critics of MERS – were elected to the Legislature. But so far, no bills addressing lost recording fees have been introduced. With little case law to support a complaint, state Attorney General Kamala Harris’s office also has done nothing on the recording issue. “We aren’t aware of recording fee-type cases in California,” says Jason Lobo, MERS communications director. Nor does Congress appear interested. In 2010 Rep. Marcy Kaptur (D-Ohio) introduced a bill to prohibit Fannie Mae, Freddie Mac, and Ginnie Mae from owning or guaranteeing any mortgage assigned to MERS or for which MERS is the mortgagee of record. It died in committee in 2011 and again last year; in January, Kaptur reintroduced the bill as H.R. 189. Whether MERS Inc. can sustain a private, members-only registry of home mortgages remains to be seen. “There can be no national solution – each state governs its own recording system,” maintains David E. Woolley, principal of Harbinger Analytics Group in Tustin and a licensed land surveyor. In a 2011 report – later published as a law review article – Woolley predicted that a wave of boundary suits would eventually hit title insurers. “[T]ens of thousands of titles have been lost or diluted in a sea of MERS transactions, and may take a hundred years to fix,” he and Manhattan Beach lawyer Lisa D. Herzog lament. (8 HASTINGS BUS. L.J. 365, 367 (2012).) But Roger Bernhardt, professor of real estate law at Golden Gate University in San Francisco, says Woolley’s contentions are nonsense. “If the endorsement is done right, the only question is who’s got the note,” he says. “In California there are no title recording questions – all the rest is smoke.” Still, Bernhardt concedes that a “deed of trust disconnected from its supporting promissory note is an odd creature.” Title insurers show no signs of concern. In fact, the American Land Title Association, their trade group, was a founding MERS shareholder. Kurt Pfotenhauer, its chief executive at the time, called MERS “an elegant solution” to the inefficiencies of state recording systems. In 2009 Pfotenhauer became a MERS director and two years later he was elected its chairman. You have to at least admire the audacity of this scheme. Under our very noses, the banking industry created a private registry of mortgages that offers homeowners little accountability, slashes millions of dollars from county revenue, and skates over hundreds of years of state property laws. Anybody have a problem with that?

 

 

 

Posted in Uncategorized | Leave a comment

Sometimes I am rude on Facebook

So, um, hi.

Yeah, I haven’t posted since the election. Sorry about that. I don’t even have a really good excuse for that; I just haven’t felt compelled at all to post. That kind of changed today, as the world went insane, and I ended up spewing forth with a rant on a friend’s Facebook wall today.

It started because he quoted that famous Ronald Reagan quote which says,

We must reject the idea that every time a law’s broken, society is guilty rather than the lawbreaker. It is time to restore the American precept that each individual is accountable for his actions.

That got a lot of thumbs up from his fellow conservatives, and another friend suggested that this is the kind of crisis that would be used to implement authoritarianism, and then I decided to reply and, well, just look:

FacebookRant_GunsReagan

Yeah, so not very polite, but oh well. I’ve written before about this specific Reagan quote and how much it bothers me.

If you’re having a hard time reading the image in that small font, here’s what I wrote:

There’s never been a bigger abdication of responsibility in the history of our country than Reagan’s words here. Every one is responsible for their own actions, but we are also collectively responsible for the society we create. 

Conservatives claim to believe in personal responsibility but whenever something like this happens they refuse to look at how their own actions may have in any way contributed to this tragedy. Are we adequately funding mental health facilities? Are we willing to have a serious discussion on how to protect society within the bounds of the 2nd amendment, how to fulfill the “well-regulated” portion of the text, or do we instead demagogue any attempt to address these issues, accusing anyone who would seek to ban certain types of weapons or create waiting periods of being authoritarians, accusing people trying to find solutions within the framework of the constitution of just wanting to take away our guns, lying about their motives to win the next election?

Whenever something like this happens conservatives refuse to hear even the most benign ideas for prevention. Could we limit the size of clips? No, authoritarianism. Could we have a waiting period for buying guns? Tyranny! Could we do background checks on people when they buy a gun? Big brother! Can we better identify people who are mentally ill, and treat them before they hurt other people? Nanny state! We can’t afford it!

Each individual is accountable for his actions. Absolutely true. And each conservative who refuses to even discuss this issue in a helpful way or without accusing the other side of opportunistically using a crisis “to implement authoritarianism” is accountable for impeding any useful prevention.

Instead of looking inward at what the policies that have been pushed by the ghouls at the NRA, you guys want to fall back on the comforting words of Ronald Reagan, and tell yourselves that you share no blame whatsoever for what has happened. That’s what that quote is all about. It’s about covering your own sorry asses. Because deep down, you know. You know that your actions and the people you choose to support and all the stupid posts attacking Bob Costas for even daring to talk about gun culture is part of why no politician would even dare to bring up meaningful legislation that could have prevented this. 

Have fun on congratulating yourselves for not actually pulling the trigger. The man who pulled the trigger deserved to be held fully accountable for his actions, absolutely. He is 100% responsible for his own actions. You’re right about that. But blame is not a zero-sum game. There’s plenty to go around.

I’m just so angry about today. I’m simply not in the mood for bullshit from these people. Not today.

Posted in Crime, Guns | Tagged , , , , , | Leave a comment