John Bintz is a frontend Web developer living in Baltimore, MD. When he's not writing sweet Internet codes, he's drawing comics or playing some sort of game.

Where to find me...

  1. Blog rebuilt for the millionth time

    October 25th, 2015

    Yes, has been rebuilt. Now, instead of the huge-ass Rails app that did a bazillion things and was hard to work with after a while has been replaced with a much smaller Express server and with React for the frontend, and yes, I'm using universal JavaScript, so it's the same code on the frontend and backend. And it's super fast. I also deployed everything using Docker and Ansible, and it's way easy to deploy and update.

    We'll see how long this new version lasts.

  2. A Week with Docker on my Little Ol' Linux Server

    November 22nd, 2014

    Welcome to my server farm.

    On the right is my SheevaPlug, a 32 bit ARM v5 Linux server I've had for a few years now. It can run basic fileserving, minidlna, sshd, and other simple things like that. On the left is an Acer Aspire Revo HTPC that used to run XBMC until I replaced it with a Roku, which was way better. The SheevaPlug's been cranking away, the Revo's been in storage since last year.

    Lately, it's been much tougher to get upgrades and newer software for the SheevaPlug without going through a lot of headaches. I don't even think the Debian apt repo I was using before even works anymore! I've also hopped right on the Docker hype train, somewhere in the back by the food car where I can get hot dogs and expensive beers (you gotta do that when you're on a train). There's no way that Docker was going to run on there, let along anything really modern (I tried getting node.js to run there. Never again.), so I decided to break out the Revo and rebuild it so that, except for sshd, it only ran Docker containers for every useful service. That'll force me to learn real fast!

    The first thing was installing an OS I knew well. I put Kubuntu 14.04 on there, since configuring it initially via the GUI would be fast and easy. I then ran into my first problem: if the machine was left at the GUI login screen for too long, the on-board nVidia ION would lock up the machine. I changed my login to be text only via GRUB and made it so that tty1 logged me in and started htop on creation, since it's really neat and if you have physical access to the machine, I'm already compromised. No more lockups. I ordered a 7" monitor to use with the machine, because why not?

    Then it was on to Docker. I used the standard Ubuntu install method and was up and running in no time.

    Now to take all of the services that were important to me and start converting them to Dockerized services. The ones that I used the most were:

    • forked-daapd
    • minidlna
    • a cron job to update a DNS entry to point at my home's IP
    • a cron job to record a radio show from an MP3 stream every week

    And the new ones I wanted to run:

    • a Docker registry so I could host my own images
    • Docker UI
    • a Squid proxy for the local network

    I have my implementations of forked-daapd and minidlna up on GitHub. They're a little more configurable than the other images I've found, to better suit my setup of having a USB drive for serving the files. The cron containers use the approach outlined here for changing the container's time to the host machine's time. One thing I haven't done yet is use data-only containers. I still don't quite get them and I haven't had a need for one yet. Maybe I'll re-set up my Squid proxy to use one for the cache and see how it goes.

  3. A basic Capistrano recipe for deploying a simple Dockerized application

    November 17th, 2014

    I've been learning a few things at once right now: React.js for a different approach to front-end code, Express and the whole node.js ecosystem for simple back-end apps, and Docker for stupid-simple app deployment. I've gotten pretty far with all of these, to the point where I could write a simple little app that did its thing with just a few hundred lines of CoffeeScript and CJSX code. I put together a Dockerfile to bundle up the app, and could manually deploy it to the machine that was my media server until my Roku 3 took over. That server is now entirely for Dockerized daemons, including the little app I wrote.

    I really didn't want to deploy this app by hand every time I updated it while playing with new things, and there don't seem to be a lot of practical examples for bridging the local build to remote deploy gap in the Docker workflow, so I wrote this post. I reached for my old favorite Capistrano to handle the heavy lifting of coortinating tasks and running commands on my Docker server. Below is a simple deploy.rb file that you can drop into an app that you initialized with a Capfile that should get you most of the way.

  4. Search Engine Food: Applying Online for a Traders License in Maryland

    November 10th, 2014

    So much searching and a phone call to Baltimore County Circuit Court finally led me to this link, which lists the business license information you need for the state of Maryland, including traders licenses, and gives you online applications for the ones it can handle. A traders license is the one I may need to deal with in the future. Google barfed on trying to get me the best URL, and according to the clerk I talked to, this is the one. Index away!

  5. Game Design Journal: CDS game, post 2

    October 2nd, 2014

    So it's been a few weeks since I was able to do some solid work on the card-driven strategy game I've been putting together and hope to have ready for Unpub 5. The last version of it was very rough, with just written-on cards for what all of the individual card abilities were.

    During a slow time at Baltimore Comic-Con, I entered in all that textual data into the SVGGVS spreadsheet for the game and reworked the card template so that card effects and other information would show up properly:

    I played this version a few times by myself before subjecting my friend Gavin to the game, and I'm glad I did, becaue the experience of playing it with another person showed me just where all the flaws were, and most of them came down to complexity and inconsistency.

    One of the goals of this unnamed prototype is to bring in as much of the experience I enjoy from Twilight Struggle with much less overhead. The first things I found that made playing too complex were the following:

    • The text on the cards and all the different states I had to manage made it rough to keep track of what was going on. I even ended up making a ridiculously complex player aide that didn't do squat.
    • The method of invoking card powers that were "yours" was annoying.
    • The whole method for card power invocation was bad anyway.
    • Turn and year tracking was a pain.

    So, back to the drawing board. This time, I decided to switch out the card text with a series of simple icons:

    The icons allow you to do a number of resource/hand/discard pile manipulations, and in the Inkscape document, they're all clones, so when I polish up the icons, they'll all change at once. I make the generic Strength action (what would be an ops action in Twilight Struggle) a separate icon, so you didn't always have the option to do ops-y things. Finally, I decided to remove the dice for resolving certain events and use the dice card-like deck from Impulse to handle random chance things.

    By switching to dice cards, it opened up an opportunity to simplfy how all the dice-based actions work, which also provided this game's version of the "Space Race", allowing you to dump cards from your hand that you don't want to play. The original dice actions were:

    • Riots: Each player rolls 1 die. A player adds 1 to their roll if they have the most resources in the disputed location, and 1 for each adjacent location they own. Loser removes difference of resources from location. If still rioting, repeat.
    • Generate resources: Roll 1 die and add the Strength of the card you played. 6+ = 1 resource on your castle.
    • Remove cards from discard pile: Roll 1 die. If less than the Strength of the card, remove the diference between Strength and roll from your discard pile.

    Now, with dice cards:

    • Riots: Take 1 card, face down, for participating. Take an additional card if you have the most resources in the riot, or if you own an adjacent location. You may add 1 card from your hand to the riot pile. Flip all cards at once. Highest total card level wins and removes all opponent resources, and adds 1 card to their discard pile per resource removed this way. Silly player wins ties (since Serious player wins card reveal ties).
    • Generate resources: Using the Strength action on the card, flip that many cards from the deck. Total their levels and add that many resources to your castle.
    • Remove cards from discard pile: Same as generate resources, but remove discarded cards instead.

    This also eliminates the "All resources on board = you win" win condition, since it'd be too easy to dump all 45 resources on the board this way. Additionally, years and turns are not controlled by sliders. If a player has 1 or less cards in hand at the start of a turn, the year ends. 5 cards are set aside from the deck at the beginning of the game. At the end of the year, the winner of the "play War with your discarded cards" stage takes one of those cards into their hand and the loser removes 2 resources from the board.

    This second game went way faster, and was a lot smoother, and a lot more fun. We didn't finish a whole game, but we did move a lot faster through the game and had to deal with a lot fewer fiddly bits. The takeaway from this session was:

    • Removing the "all cards can be the board" mechanic. It's too much to worry about players purposely AP-ing if they have an idea of what's in the deck. I don't want that in this game. The less AP, the better. This means the board is now made out of a separate deck of cards, which will require coming up with some additional cards and bumping up the total card count to 126 to keep the costs in line, but that'll add 5 new game cards, which means I can have more generic Strength cards. Speaking of...
    • Gavin got a hand of cards that basically allowed him to do nothing of consequence. Several cards were "Opponent" or "Silly Lord" only (he was Serious) and he couldn't do anything with them, so he was boned. I don't want that to happen all the time, so I'm going to make sure each card has "You" as a target in some way.
    • The board is going to be smaller, 3x5 instead of 5x5. It should allow players to go more nuts on each other more quickly. This will mean I'll probably bump up the sizes of the locations, so you need more resources in there to butt heads. This would also allow me to easily design a 3 or 4 player expansion down the road.

    Finally, SVGGVS got some work done to it. I had a ton of clone in the Inkscape document I was working with, and the original code I used to decide if I neede to unclone an object (if it's text and there needs to be text replacement) decided to loop through every <svg:use> tag in the document, look at its type, and decide what to do, for every card that was build. With a document with around 500 <svg:use> tags, Nokogiri fell to its knees. I reworked that part of the code so that the type evaluation only happens during the first card, and the results are cached for all further cards. Took processing time down from about 5 minutes just to generate SVG files down to about 2. Nice.

  6. Scrum for One Week 17-18-19: Holy hand grenades, Batman, I've been busy!

    September 15th, 2014

    Sorry for the lack of updates. Things have been ridiculously busy. I've been falling behind on pretty much everything, so this week's sprint goal is Get Back on the Horse. This includes working on the CDS game (which I'll be playtesting with another human this week, neat), the mobile version rewrite of Can't Catch Me, Olivia! (which I'm now doing using Snap.svg, neat), and doing cleanup on the Can't Catch Me, Olivia! Kickstarter (I have cards to draw and people to track down, neat).

    My everything also exploded, so Keep Your Office Clean stays up as the kaizen.

  7. Scrum for One Week Sixteen: Intervention and How I Do It

    August 25th, 2014

    This was a busy week. I spent my time getting ready for Intervention in Rockville. The show went well, though I wished more people had stopeed by. I managed to sell my first copies of Can't Catch Me, Olivia! to non-Kickstarter backers at the show, and even did a custom character card! Sweet!

    Before the show I had the bright idea of rewriting the almost-complete Can't Catch Me, Olivia! app I had originally done in ClojureScript. I figured out I had done several things wrong when I first built it, things that became extremely evident after playing a lot of Star Realms and seeing how they put together a turn-based card game with remote sync:

    • The game was built as pass and play first. State was a thing to be manipulated directly, one step at a time, and would have been hard to retrofit so that actions could be replayed on another device after a player's turn was over.
    • For the same reason, plugging in an AI would have been equally tough. I figured out that remote, AI, and pass and play had to go through the same pipeline, which the original code was far from being designed to do.
    • ClojureScript abstracts away JavaScript entirely too much for my liking. I got it to work with AngularJS and other libraries I reach for in my web development, but it was very very painful. It feels like it's either ClojureScript's way or the highway. I decided to get back on the highway and rewrite it in CoffeeScript.

    So I decided to make this week's Sprint Goal Complete Game Logic Rewrite for Can't Catch Me, Olivia! Since I'm throwing one away (I really didn't plan to, honest!), development on this new version is going much much faster. I have 1/3 of the cards implemented, and should have the remaining ones done this week. Also this week is the big Kickstarter game dropoff at Brews & Board Games. So I'll be glad to have that over!

    This week's kaizen is the usual Keep Your Office Clean. I'm doing it, really!

    Finally, I have an article running over at Webcomic Alliance about this very process that I talk about here. It has cartoons! Go read it!


  8. Game Design Journal: CDS Game, entry #1

    August 16th, 2014

    I dropped out of the 5th Street Games contest because Mid-Life Chorus was taking over my life. I decided to pick up a much bigger project that had been back burnered for a while instead: a card-driven strategy game where the cards also form the board that players manage resources upon.

    The game will be a loose combination of some of the mechanics from the following games:

    • Twilight Struggle: 2 players, cards have unique actions which trigger under certain circumstances, insta-win/lose happens in certain game states, some cards are removed from the game as you play
    • Impulse: Cards form the board, pawns are generated and moved between cards and interact with each other
    • Innovation: Every card is unique, some cards are removed from the game first thing
    • Race for the Galaxy: Actions are selected simultaneously
    • Can't Catch Me, Olivia!, Love Letter: Personal discard piles that are used for something
    • War (seriously!): Compare cards from tops of personal decks, highest takes all cards

    I really like the "every card is unique" idea from Innovation and Twilight Struggle, but whereas Innovation and Twilight Struggle have a general progression upwards in the power of the cards, the game I'm working on won't have that luxury. Some cards may have some prerequisites, but that's about as far as I'll go. I also really like the simultaneous play option, and in my playtests, it's working quite well, making the gameplay go very fast. It does has a weird timing thing that TS doesn't have, which you'll see in a minute.

    The game is intended to be a prequel to a long-form webcomic I want to start in 2015. Anything with "serious lord" and "silly lord" mean the blue player and red player. Each player has a castle at one of the corners of the board. The rest of the board is built with cards from the deck. the map is always the same on the map side, but on the action side, it's always different. This means there are some cards that will never be accessible in each game, though there is a way to potentially get a handful of these cards back into the deck. Each Map card has a Size in the middle.

    The rest of the cards are shuffled and 9 are dealt to each player. The game itself is 9 "years" long, with a "year" consisting of 8 "turns" and an end of year resolution phase. Each player starts with Resources at and around their castle and more resources not on the board. These are real physical things in the game world, unlike the ephemeral "influence" in Twilight Struggle. At the start of the year, the player is dealt 9 cards.

    At the start of each turn, each player takes a card from their hand and places it, face down, in front of them. Both players reveal at the same time, and the player with the lowest Strength value on their card goes first (like Headlining in TS, but every turn!). If there's a tie, whoever has the lowest Strength card on the top of their personal discard pile goes first. If it's still tied, the Blue player goes first. At that point, the first player has one of three ways to use the card they played:

    • They can move resources from any one card on the board to any other one card on the board, as long as there is at least 0 or more cards with their resource on them in an unbroken line. Map cards are connected by lines to show how resources can move (basically, not diagonally and not wrapping around). If, for instance, your castle's surrounding cards have no resources on them, you can't move resources from your castle to a remote location -- you need to add a resource to one of those cards adjacent to your castle to create a road of sorts to move resources along.
    • They can use the Strength value of the card to attempt to add 1 resource to their castle. They roll 1 die and add the Strength, and if they get 6 or more, they create a resource. Yay!
    • If they own the map location (have as many resources on the card as the Size of the card and no opponent resources) that this card shares, they can perform a Public Works action. They remove all resources from the map card, take the card from the map and put it in their discard pile, then put the just-played action card on the board map-side up. This is good if you are holding a particularly devestating card of your opponent's that you don't want to play, ever!

    Each card has an event on it. Events always override game rules.

    • If you play a card that says "event happend automatically", it does!
    • If you play a card with an event of your color or a white card that doesn't happen automatically, you can choose to perform the event at this time. Put a card in your discard pile from the deck and follow the instructions.
    • If you play a card with an event of your opponent's color, the event triggers. You don't put a card in your discard pile.

    Basically, if you choose to make an event happen, you put a card in your discard pile.

    Once the first player is done, the other player then goes. After both players go, each map card is checked to see if any card has more resources than double the Size of the card on it. If so, the map card is Rioting. This is unlike Twilight Struggle, where the board (the world) was essentially the plaything of the two players (ah, the Cold War). In this game, the board doesn't want to be ruled over too strongly, and it fights back!

    Each player rolls a die for each Rioting card and adds the following to their roll:

    • If they have the most resources on that card, they add 1.
    • If they Control (have more resources than the Size of that card and more than their opponent), they add 1.

    If the modified rolls are tied, both players remove 1 resource and place 1 card in their discard piles. If not, the loser removes the difference in resources between the rolls, and the winner places a card in their discard pile. Continue until all Riots are resolved.

    If at the end of the year, any player has no resources in their castle, or the map cards surrounding their castle are owned by their opponent, they lose.

    After 8 turns, each player shuffles up their discard piles and, well, they play War. Not only do the towns fight against you, but the religious organization that gave you some leeway over governance (back story stuff) is watching you, and will step back into control if you push too far! Each player reveals the top card of their discard. The player who played the highest card takes both. If there's a tie, reveal another card until the tie is broken. The winner takes all of those cards. At then end, whoever has the most cards loses 2 resources of their choice. If they have 16 or more cards in their discard pile after this step, they lose the game. This means you can stuff a person's discard pile to DEFCON suicide them. :)

    Once this is done, each player counts up the number of map cards they own and puts a resource on their castle for each card they own. Then it repeats for 8 more years.

    So far I've completed several partial playthroughs and three complete playthroughs. The three complete playthroughs ended on discard pile detonation. With each playthrough I've been analyzing the strategy each player used and trying to come up with cards that will both help and hinder those strategies. I have about two dozen different approaches I'm compensating for in each direction now, and I have about 2/5 of the deck to still work through. So far it's super-promising. This will be the game I take to Unpub 5, I'm sure. If I can boil down the things I like about Twilight Struggle (and other CDS games like 1989, Labyrinth, and Hannibal: Rome vs. Carthage are on my "to play" list now) into a card game that takes half the time to play, I consider it a win. Impulse did it for 4X games for me (though the rules can be fiddly in places).

    More updates as progress continues!

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19