Thursday, May 17, 2012

Symmetric Pandemic

Pandemic is a very popular board game around the office, but there are a couple things about it that bug me.
First, I'm pretty competitive so even though this co-op game can be a real challenge I really wanted to find a way to pit players against each other (other than using the bio-terrorist role). The other thing that has always bothered me a bit about pandemic is that one or two vocal (hopefully experienced) players can often drown out the other players. I've occasionally considered granting each player a certain amount of time per round/game and using timers to limit an individual's vocal contributions but this kind of takes away from one of the most fun parts of a good game of pandemic, the interaction and debate.

A colleague of mine, Mike McGraw, proposed an interesting twist on the game that seemed like it might solve both of the above issues. We had multiple copies of the game, what if we could sync up the decks so that we could have 2 teams simultaneously playing the same game? Because of the way that pandemic works it would be relatively easy to have both teams get the exact same player and virus cards in the same order. This means that the decisions made by the teams would be the sole difference in the results of the games. A nice even playing field. We decided that the winning team would be the team that cured the most viruses, if both teams won, then the team that won first (real time, not turns) would be the victor. This incentivised both teams to play at a quick pace, but not a reckless one.

A nice side effect of having both teams play on the same (large) table and use the same card order is that at least at the start of the game you don't want to talk too loudly or too much about the cards you draw or the good ideas you have because your opposing team can also hear them and use that information. While I don't think either team used this advantage to any great degree in our game it's an interesting dynamic.

Once we decided to give this variation a try we didn't want to have to require an extra person on hand to do the initial deck sync and make sure the post-infection shuffles also resulted in the same ordering. Fortunately I work in an office full of talented programmers, one of whom (Luke Dewitt @whatadewitt) spent a couple hours building a web-app that takes a seed and generates a shuffled deck of pandemic cards, has buttons for drawing from both the player and virus decks and manages the actions required for infection events. We had 2 computers load up this app and input the same seed and the resulting play through is symmetrical (in terms of cards drawn).

Luke's Pandemic Card-Sync-app


To make it a little easier to get the app running in the limited time we had before playing we decided to remove a couple special event cards that can affect card drawing which could potentially break the drawing symmetry. Since you only play with a subset of the special event cards anyway this shouldn't be a problem.

The game itself went really well, my team had to restart after a missed turn early in the game, but this was easily accomplished using the app and the same seed and we quickly caught back up to where we were before. The game ended with one team curing the last virus and winning by being the first to do so. I'm confident that both teams would have won the game (we were playing with 4 infection cards for this initial play test) so the real-time aspect of the variation made the difference.

The 2 Teams and Boards


We plan on playing another game like this sometime soon, if it turns out I'll record it and post it here. I think everyone enjoyed the game and the new angle that the 2-team variation brought. One thing we've considered for future iterations is finding a way to track (or perhaps record) which moves each team made so we could review it post-game and find the turning points.

In particular I like the idea of picking a seed at random, generating a unique game and playing it either with a group or solitaire (Pandemic is a great solitaire game) and then sending the seed to a friend to see how they did with the same card sequence.

Thanks to Luke, Mike, Shawn, TJ, and Jamie for the great game,

Brent

UPDATE:

Luke has posted the source for the web-app on github and it's also available on his site:
source: https://github.com/whatadewitt/symmetric-pandemic
online: http://whatadewitt.ca/pandemic/

I'd recommend playing (or at least starting) a solo game before trying a multi-team setup just to make sure you understand how the app works.


Wednesday, April 11, 2012

Super Mario Kart Cycle



I love Super Mario Kart and the SNES in general.


When I was young I used to think about how much fun it would be to play SMK with a real bike. Now, many years later, we finally have the ability to create such a thing without a lot of very specific knowledge and tools.

Some of the things I used:
Arduino microcontroller (UNO)
A few transistors
Some pushbutton switches
A few resistors
A 2$ photo interrupter
An SNES controller
A very old stationary bike
A breadboard


Nothing there is overly expensive and none of it should require more then a little time and googling to figure out how to use. That said I'm not particularly experienced with electronics so there may very well be better ways to do some of this. (Actually I've found a few things I'd like to correct myself quite recently)

This was my 2nd Arduino project, the first being an n-back test game which I'll make a post about in the future (https://github.com/statuswoe/nBackGame).

There are two separate parts to this project, the first is finding an easy way to output from Arduino into the SNES and the second is having the Arduino recognize when the bike is being pedaled and when the buttons are being pressed.

Arduino to SNES

The SNES controller isn't particularly complicated, there looks to be a multiplexer and a couple resistors but little else. I wasn't able to find a really good diagram though. There is a description of the pinouts here: http://www.gamesx.com/controldata/snesdat.htm but I wasn't really interested in playing with a clocked signal when I didn't have to since I had an old SNES controller that I wasn't using. All I needed to do was put an NPN transistor across the points that the buttons contacted and I can fake a button press by applying voltage to the base pin, this was pretty simple.

My soldering is getting a little better, couldn't get much worse.


What I ended up with is a series of input pins that I plugged into my Arduino board and when I set them high the associated SNES button is triggered.

I mounted the project board and the modified controller into a small toolbox which was the cheapest container I could find that fit them both. The SNES connector comes out of one end and the Arduino connector comes out of the other. One of my goals was to make the SNES controller adapter entirely separate so that I can use it for other games/peripherals.




Bike to Arduino

The Handlebar buttons are pretty self explanatory. I used momentary push button switches that are on unless pressed just because I had some on hand. Because I'm running them into the Arduino I was able to invert the state in software.

The fun part was finding a simple way to track pedaling. I found a few caveats:
- Because the wheel doesn't stop when you stop pedaling and there are no real breaks I didn't want to use the wheel to track speed. I need to know when the user stopped pedaling.
- Running wire onto the pedal would be a pain because the pedal rotates relative to the bike so I'd need to set up brushes or something that wouldn't twist up when you pedal.

Because of these issues I decided to mount a photo interrupter next to the sprocket and have something attached to the sprocket at regular intervals that can pass through the interrupter and trigger the state-change. I ended up using 6 small pieces of playing card to do this.


Once the photo interrupter and buttons were hooked up to the Arduino I wrote some quick code to read the inputs and set the appropriate outputs to the SNES Controller adapter. The code is available here(and could use some polish).

I have the code and SNES Controller adapter set up to accept up, down, left, right, A and B, but I don't have the up/down hooked up to the bike yet because I'm not satisfied with the toggle switch I was going to use for it.

So in the end we have The Bike pushing data into Arduino, which does a little logic and sets some appropriate outputs which saturate the transistors to press the appropriate button.





EDIT:
Maicol asked for some more info on using transistors to control digital buttons, so here's a better image of that part of it, click on it for full size. The common ground is the red blocks, the blue side is the per-button input from the arduino (high to simulate the push).  The NPN transistors bridge the path from the (green block) SNES controller wires to ground which the SNES reads as a button having been pressed.
The SNES is a bit odd in this sense, what you really want to do if you're using this for any other sort of input is put one side of the NPN transistor on the wire leading into one side of the button and the other side of the NPN transistor on the wire coming from the other side of the NPN transistor. You can then apply a charge to the middle pin of the transistor and it will act as though the button had been physically bridged. Hope this helps.


Friday, April 29, 2011

The value of a drop in a bucket

I frequently listen to the ESPN podcast "Baseball Today" with Eric Karabell and guests. It's not my favorite podcast, but the guy knows his baseball and his co-hosts are usually really good.
On a recent podcast Eric mentioned that the current decline in attendance at Dodgers games being partially blamed on fans wanting to protest the ownership was silly. He stated that a fan not going to a game to protest the ownership situation wouldn't even be noticed and that no real fan would want to do that.
This reminded me of something else that's been getting a lot of attention this (and every) election season, the value of one vote. On a larger scale the concept is often likened to a drop in a bucket, an idea worth looking at.

The price of a coffee:

If I asked you right now the exact maximum price you would pay for a coffee, to the penny, what would you say? Do you think you're guess is accurate? In my case I'd have to say no, it's just a ball-park of what I would expect, rather than an instantaneous reflection of how much I would actually pay. It's really hard to prove the exact price you would pay for something at any given time since any initial offer or haggling would likely change your perspective.
However, If I had 1000 clones of you, all of whom are exactly like you in every way and offered them all a different price for a cup of coffee then I could find out exactly what your maximum price would be. Consider the following example

Clone 1 is offered the coffee for $.01 and accepts
Clone 2 is offered the coffee for $.02 and accepts
...
Clone 143 is offered the coffee for $1.43 and accepts
Clone 144 is offered the coffee for $1.44 and declines
...

We can expect that since clone 144 declined to pay $1.44 for the coffee that all subsequent clones, being the same person effectively, would decline to pay more. At this point we know that the maximum price you (being the one who was cloned) would pay for a coffee at this time.

This kind of accuracy is impossible to get simply by offering a person the same coffee consecutive times since as I mentioned earlier previous offers can bias their perceived value of the coffee. It also doesn't last, ask me 5 minutes from now and I'd bet the number would have changed, particularly if I was still growing thirsty.

Now you might be thinking "Wow Brent you've wasted like 3 minutes of my day, thanks! Who cares how much I'd have payed for a coffee at a specific time, other than perhaps the man running the coffee shop at that time. Also, since this is a theoretical experiment I can't even find that price in the real world rendering this whole post useless. I hate you." Ouch. Well, maybe we can use this idea to help increase our perception on the value of one penny/vote/drop?

Consider that not every person would have the same "instantaneous maximum" for a given offer or question. The "Would you pay $1.73 for a cup of coffee." question could easily translate into "Do you consider Party X, who got 10,173 votes to be a valid party worthy of consideration in the next election?" or "173 people complained about a decision I made, is that number high enough to make me take their perspective into consideration?" All of these numbers could easily fall into the instantaneous maximums of people looking at them. For example:

Party A received 10,417 votes
Party B received 9,567 votes
Party X received 4,351 votes


Party A wins the seat, Party B supporters are disappointed about losing such a close race, but know they have a shot next election. Party X however didn't really come all that close, so they might be asking themselves a big question.

Did my vote count for anything?

One way to look at it is that in such a close race both of the top parties will be looking to gain votes in the following election, one way to do this is to make sufficient concessions toward an outside party's platform to woo some of their voters. For instance if Party X was really pro-environment then Party A or B might alter their platform a little to be more environmental in order to get a few of Party X's votes. This is at least a partial success since you are going to see some of your desires fulfilled.
Another view is that with any smaller party there is likely to be people who support the platform but don't want to "waste their vote" and vote strategically for whomever would be their choice of the front-runners. This seems to be a very popular way to vote, most people feel very strongly either in favor of or opposed to the incumbent and want to make sure "he/she does('nt) get back in". What can get lost in this is the idea that a third party that loses a lot of votes to strategic voting can end up looking much further out of the running than their actual support would be. Each vote for party X adds increased likelihood that when the results come out that party would look like they have a legitimate chance in a future election.

This is where the instantaneous maximum concept I mentioned above comes in. In the sense of voting, where everyone can see the resulting vote totals and decide for themselves if a party had enough to be considered a viable choice in future elections that's a lot of potential voters using their own maximums to make that call subconsciously.

As an example if I was a party X supporter, but voted A strategically and tuned in to see the vote totals I have a number, albeit a number I don't consciously know, where I would realize that party X might have a shot next election. Say that number was 4,352 then in the above example I wouldn't yet be convinced and would likely vote strategically next election, but I wouldn't know exactly how close I came to being convinced. Now consider there are a large number of people like me, but who's number is slightly (or significantly) different than mine. This means that instead of having one solid number (to win the election) that if you miss you feel like you've wasted your vote you actually have hundreds or even thousands of numbers where your single vote could influence the next election in a much more dramatic way.

This kind of thing can snowball too. If my vote this election catalyzes additional people to consider party X and maybe vote for them in the following election then their votes can do the same in subsequent elections.

In conclusion even though third party vote totals might not win them an election, the value of the actual vote count (or penny charged, or drop added) can have direct impact on results even if the number seems arbitrary.

I didn't really intend for this to become so much about voting, but it seemed a decent example, and I think it's important that people consider not only the short term outcomes of elections but use their votes as a path to the future that they want.

Thanks,
Brent

Thursday, March 3, 2011

Maven Release and Directory Locations

A co-worker of mine ran into a strange error while running a maven release:prepare goal on a new project we were setting up, and the issue is kind of odd.

When he ran the prepare goal he would quickly get (on the first module) this error:
[INFO] ------------------------------------------------------------------------
[ERROR] FATAL ERROR
[INFO] ------------------------------------------------------------------------
[INFO] null
[INFO] ------------------------------------------------------------------------
[INFO] Trace
java.lang.NullPointerException
at org.apache.maven.shared.release.util.ReleaseUtil.getBaseWorkingDirect
oryParentCount(ReleaseUtil.java:233)
at org.apache.maven.shared.release.phase.RewritePomsForReleasePhase.tran
slateScm(RewritePomsForReleasePhase.java:109)
at org.apache.maven.shared.release.phase.RewritePomsForReleasePhase.tran
sformScm(RewritePomsForReleasePhase.java:62)

Google didn't really help much so I had a look at source for those classes and tried to figure out where the null was coming from. While I was looking around I remembered that he had checked out the project into his root directory, so the working directory was directly inside "C:\".

That is:
C:\project\pom.xml was the top level pom getting built.

Since the release plugin looks for some base and parent directories I wondered if this made a difference, if asking for the base directory and just getting "C:\" was an issue. I tried to run the same goal on my machine, with a more nested working directory and it finished successfully. We tried adding one level of directories between his root and his workspace (C:\blah\project\pom.xml) and that seemed to do the trick.

I've logged a bug report with the maven release plugin about this: http://jira.codehaus.org/browse/MRELEASE-663, but in the interm if anyone runs into it just make sure you aren't doing your dev too close to root.

Thanks,
Brent

Thursday, February 24, 2011

Hudson/Jenkins and the missing key

A while back we began moving from one old hudson server to a new box with a newer version of hudson on it that could better handle the ever increasing load it was being given. For a while things were working fine, I do mostly AS3/Flex builds using flex-mojos and I moved a couple project to the new server with no issues. At some point (still unsure why) our flex jobs started failing. The error given was as follows:

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] key can't be empty

[INFO] ------------------------------------------------------------------------
[INFO] Trace
org.apache.maven.lifecycle.LifecycleExecutionException: key can't be empty
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:719)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
at org.apache.maven.lifecycle.LifecycleExecutorInterceptor.execute(LifecycleExecutorInterceptor.java:65)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)

I found a couple references online to "missing key in Hudson" but none seemed to fit my situation.

Eventually I ended up creating a new test project as a multi-configuration project instead of my standard Maven 2 project, adding an empty shell script and the Maven 2 build step. This ended up solving the missing key issue, though I'm at a loss as to why.

Since I struggled with this for so long I figured I'd post it and hopefully save someone else some pain. It's quite possibly a flex-mojos bug since it didn't seem to affect the Java jobs on the server. If anyone can explain why this seems to happen I'd love to hear about it.

This occurred in a version of Hudson just before the start of the Jenkins project, so it would likely occur there as well and I thought it's worth mentioning.

Thanks,
Brent

Thursday, November 18, 2010

Pidgin MSN Cert update

This morning pidgin was complaining about my MSN accounts and the cert coming from omega.contacts.msn.com. I seems that the cert was changed.

The fix:

Using Firefox visit: https://omega.contacts.msn.com/

Right-click on the page (an error page) and select page-info

Select the Security tab and click "View Certificate"

In the Details tab click export and save it in the certs dir in your .purple folder
ex:(Win XP) C:\Documents and Settings\{username}\Application Data\.purple\certificates\x509\tls_peers

(if you can's find this on your machine a simple search for tls_peers should point you in the right dir)

In Pidgin disable then enable any MSN accounts and it should connect.

For people who don't want to grab the cert themselves a helpful blogger has a link to a copy of the cert (and similar instructions) here: http://blog.andreineculau.com/2010/11/pidgin-and-msn-certificate-error-for-omega-contacts-msn-com/ BUT BE WARNED that certs are the sort of things you should get from the site itself if you care about security.

Hope This Helps,
Brent

Thursday, June 17, 2010

AS3 Boolean Assignment

I came across a situation where I had a series of function calls that could alter an array of objects and I wanted to know at the end if any of them had actually made any changes. I decided to have each function return true if it had made a change and false otherwise. Then I created a boolean variable before running through the set of functions and assigned the result of each of the function calls to that variable using the following:

b = foo() || b;


I did it this way because boolean logic operators work left to right and had I done either of these:

b = b || foo();
b ||= foo();


then if b was true foo() would never have been called.

I found myself wishing that there was a way to explicitly set which direction the expressions would be checked in ( =|| instead of ||= for right to left) or even a means of indicating that you want ALL of the expressions to be validated (efficiency be damned!).

Fortunately there is a (less optimized?) way to do something similar using numerical operators. When a boolean is used in a numerical operator it gets treated as a 1 or 0. This allow you do do the following

var b:Boolean = true;
var c:Boolean; //defaults to false
var d:Boolean;

trace(b+b+c+b)// 3
trace(b+c+c+c)// 1

d = c+b+b
trace(d)// true;
d = c+c+c+b;
trace(d)// true;
d = c+c;
trace(d)// false;

d = false;
d += b // true;


This means I can do the following in my example situation:

var b:Boolean;
b += foo();
b += boo();
b += who();
b += do();


and if any of the functions return true b will become true.