RPA Game History Available

You spoke, we listened.   Rock, Paper, Azure is going well, but one thing we’ve heard from many people is that they would like a history of their games.   The main reason for this is the “attack and retreat” approach  some people have taken – that is, they submit a bot with their main game playing skill, quickly observe/download the results, then resubmit a weak bot.   Because the MyBot page shows only the current results, odds are the other players won’t see the interim results.   We originally thought the current results would be all people would want to see, as game history (aside from taking a lot of space) could potentially be a lot of data to go through.  But, we’ve been proven wrong, so we decided to keep the history for players to go through.  We wanted to incorporate this in a non-breaking way, so it’s optional data to look at. On the MyBot page, you’ll still see the current games: Under that, you’ll see game history that shows all interim games: The filter allows you to select a single player to look at.  The number of games you see depends on the number of times your or your opponent’s bot was uploaded.  We haven’t quite decided how long we’ll keep history, but at the very least, it’s there to use!  Thanks for the feedback!

RPA Winners, Losers, and Eligibility

Over the past few weeks, we (the dev team of Rock, Paper, Azure) have gotten to be best friends with our internal legal department.  It’s been an educational experience, and this is where things stand with Rock, Paper, Azure. When one player wins a round, he or she is ineligible to win a future round.  If you don’t win, you are eligible to keep playing in subsequent weeks to try to win.  We’ve received a number of very good questions and concerns, so, I’ll try to summarize them here. 1. What if I win second or third place, and I want to keep playing to try to in the first place prize?  Can I do that? Players do have the option to refuse their prize.  If you come in second or third, you may reject it, forfeit your place, and continue playing.   Please note though that you assume the risk for doing this and the decision is final.  As weeks go by, I would expect the competition to get more difficult, so you may do worse and not win any prize at all, and also give up your place should there be a change in eligibility (see next paragraph). In addition to a player purposefully choosing to remove him or herself from claiming the prize, a player may also be found ineligible.   In either case, the prize goes to the next person in line.  So, hypothetically speaking, if the first place player was found ineligible, the second/third/fourth players become first/second/third.  Had player 2 already decided to refuse his place … yep, that’s right – the top three are now third/fourth/fifth from the leaderboard. It’s a bit confusing, but as you can imagine there are legalities involved here. 2. Why are previous winners still playing?  I thought they were ineligible!? Past winners are ineligible to win a prize again.  We’ll remove ineligible players as we can – as you might imagine, there’s a little delay because we’re sorting out the winners from week 1.   But rest assured, before we run the final round on Fridays, we vet all players and then rerun the entire round.  Remember that during the week, the “continuous integration” of your bot is primarily for fun and strategy – it’s only the final round that counts! 3. So, who won week 1? We had no idea it would be this volatile, but it turns out players 2 and 3 (Serplat and marsh) have been removed – one for his choice to keep playing, the other because of, unfortunately, eligibility.  (I wish that wasn’t the case, but laws are laws.)  That means that players 4 and 5 slide up to 2 and 3 – s7orm and AttnSystem now become 2nd and 3rd place, unless they too decide to keep playing and give up their place.  So just remember – you’re never out of it!

Can’t Lock() in RPA

For security and performance reasons, we often review what bots are doing and review any rejected bots to see how things are going.   When a bot is rejected, it is typically easy to spot the exact reason when looking at the code, but sometimes it’s not so apparent.  By far, the biggest case that I see is using the Lock keyword.  For example: 1: lock (someobject) 2: { 3: //synchronized code 4: } On the surface, it’s not apparent this would be a rules violation, and in the vast majority of cases, it is fine.  But under the covers, it calls Monitor.Enter() in the System.Threading namespace (known as compiler syntactical sugar), and we don’t allow anything in that namespace to be called.  The question we have internally is:  should we review the rule and make exceptions to specific calls? In this case, there’s no reason to use such code in a bot.  The only time you’d need to is if your bot has a static method/object reference, but that’s a bad idea in a bot because it will lead to unpredictable results.  Your bot should have only instance members.    So what’s the correct way?   Locking is a typical pattern (and a good habit) in object creation where there’s a risk of concurrency causing an issue.  Even if there is no risk, many developers are careful particularly with singletons to be sure of thread safety by using locks.  In the case of developing a bot, the best way to do this is in the bot’s constructor without any lock/monitor.   Questions or feedback?  Let us know!

Testing a RockPaperAzure Bot in a Winform

In Friday’s webcast, I showed a quick ‘n dirty utility for testing a RockPaperAzure bot outside of the game server and even the Bot Lab. When we ran some of these tournaments in person, it was very difficult to get a good feel for your bot before deploying it, and that’s why we introduced the idea of a Bot Lab. But even with the Bot Lab, if you’re working out a complex algorithm, it can be handy to have a simple test hardness. By pulling in the DLLs from the Bot Lab, it’s pretty easy to put together a little utility. To locate the DLLs, crack open the BotLabSite project and locate the ref directory, and grab the Compete.Bot, RockPaperScissorsPro, and RockPaperScissorsPro.RPA libraries: One thing to note: the RockPaperScissorsPro.RPA assembly, in the MyBot project, has an XML file that you can also include if you’d like intellisense – for example, we call out that GetRandomMove returns Rock/Paper/Scissors, not dynamite/water balloon: In our Windows Form app, we’ll create a few textboxes for the moves of each player, and the player’s log file: In our project, we’ll build a couple of bots – these can be your actual bots (because they use the same interface) or completely different – it’s up to you. MyBot will be the main bot we want to test, and Opponent will be, obviously, the opponent. In our form app, we’ll declare some of the player/game objects we need to test: 1: IRockPaperScissorsBot myBot; 2: IRockPaperScissorsBot opponentBot; 3: Player rpsPlayer1; 4: Player rpsPlayer2; 5: PlayerLog player1Log; 6: PlayerLog player2Log; 7: 8: private void Form1_Load(object sender, EventArgs e) 9: { 10: myBot = new MyBot(); 11: opponentBot = new OpponentBot(); 12: 13: rpsPlayer1 = new Player("you", myBot); 14: rpsPlayer2 = new Player("opponent", opponentBot); 15: 16: player1Log = new PlayerLog(rpsPlayer1, rpsPlayer1, rpsPlayer2); 17: player2Log = new PlayerLog(rpsPlayer2, rpsPlayer1, rpsPlayer2); 18: } When the form loads, we initialize our players. Each player has a bunch of methods and properties, but most importantly, also has the player’s bot. This can be a little confusing because bot is a property of the player. We’ll also create some player logs – normally the engine does this for us, but we’re running outside the engine so we need to do that ourselves. There are 2 ways we can have out bots move: Option 1: Simulate the game environment. This is a good option if you want to test timings against the game engine. I’m including this here really just for information sake – most people who want to test timings will be far better off testing in the bot lab. 1: int i = 0; 2: 3: private void button1_Click(object sender, EventArgs e) 4: { 5: i++; 6: 7: PlayerMove ourMove = rpsPlayer1.GetMoveToMake( 8: rpsPlayer2, GameRules.Default, player1Log); 9: 10: PlayerMove opponentMove = rpsPlayer2.GetMoveToMake( 11: rpsPlayer2, GameRules.Default, player1Log); By calling GetMoveToMake on the player, we’ll get back the Player’s move and this will be done just like it is in the real game – timeouts and all. Option 2: Take your time! This is really the best option – we’ll call into the bots MakeMove directly and this avoids threading/timeouts – the big advantage here is that it’s much easier to step through and debug. There is one tiny gotcha. The player log files are managed by the player, and in this case, we’re sidestepping that. In order to have a working log, we’ll need to inject that log via reflection. Reflection code won’t work on the real game server, but it comes in handy in our test app: 1: int i = 0; 2: 3: private void button1_Click(object sender, EventArgs e) 4: { 5: i++; 6: 7: Type t = typeof(Player); 8: FieldInfo fieldInfo = t.GetField( 9: "<Log>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance); 10: fieldInfo.SetValue(rpsPlayer1, player1Log); 11: fieldInfo.SetValue(rpsPlayer2, player2Log); 12: 13: Move ourMove = myBot.MakeMove(rpsPlayer1, rpsPlayer2, GameRules.Default); 14: Move opponentMove = opponentBot.MakeMove(rpsPlayer2, rpsPlayer1, GameRules.Default); What lines 7 – 11 do is use reflection to assign the player log. We need to use reflection because these are internal objects that we can’t typically access. Once we have the move, we call SetLastMove which gives bots the visibility into their last moves. 1: ... 2: rpsPlayer1.SetLastMove(new PlayerMove(rpsPlayer1, ourMove)); 3: rpsPlayer2.SetLastMove(new PlayerMove(rpsPlayer2, opponentMove)); 4: ... 5: 6: protected override void OnClosing(CancelEventArgs e) 7: { 8: rpsPlayer1.MatchOver(); 9: rpsPlayer2.MatchOver(); 10: 11: base.OnClosing(e); 12: } One other comment: in the form closing (or other location) you need to remember to close down the bots by calling MatchOver. This will make sure they shut down properly and the threads exit. With everything set up, we can run the app and see the output: So let’s return to the original question: Why do this? Suppose we want a simple way to track number and percentage of the moves thrown. We could keep simple counters (in fact, that would be the fastest way to do that), but consider this code block: 1: List<Move> opponentHistory = new List<Move>(); 2: 3: public Move MakeMove(IPlayer you, IPlayer opponent, GameRules rules) 4: { 5: gamenum++; 6: 7: if (gamenum == 1) { 8: you.Log.AppendLine("starting up."); 9: } else { 10: opponentHistory.Add(opponent.LastMove); 11: } 12: 13: if (opponentHistory.Count > 0) 14: { 15: var moveHistory = (from m in opponentHistory 16: group m by m.ToString() into g 17: select new { MoveName = g.Key, MoveCount = g.Count(), 18: Percentage = (Convert.ToDouble(g.Count()) / 19: Convert.ToDouble(opponentHistory.Count)*100) 20: } 21: ).ToList(); 22: } What we’re doing is keeping a log of the opponent’s moves into the opponentHistory list. We’ll then aggregate that into a moveHistory list, which is derived from the aggregated data. By looking at the opponentHistory, you can ask very specific questions of the data, such as move totals and percentages: 1: Rock - 3 - 27.27% 2: Paper - 6 - 54.55% 3: Scissors - 2 - 18.18% You could look at the past few moves, or the entire game – or adapt it to your project. I’ve uploaded the project, with a link below. You’ll need to pull the assemblies above into the project – I’ve left them out for licensing clarity. If you use or improve on this solution, let me know! It’s obviously not terribly advanced but should be enough to get you started. Download the solution

Rock, Paper, Azure Tournament Information

We had a couple of great questions on RPA tournaments over the first week – I thought I’d clarify a few things here. International Players As many of you know, the main tournament (with prizes) is limited the US residents. This is for legal reasons as I explained in this post. But, we wanted to get the framework in place to expand – and I’m thrilled to say that we’re there (how’s that for fast implementation?). Currently, when deploying bots, you’ll see other rounds that are open – for example, on the MyBot page: Currently, only US residents can enter the Tournament Round but everyone (including MSFT employees) can enter the Open Rounds. As other groups in varies locations put together tournaments, we are happy to support that effort. Resubmitting – not fair? One question received was from a player who thought he noticed several players resubmitting their bots rapidly without modification in order to force their bots to replay, and hopefully do better due to random elements they’ve built in their bot. Obviously, with random elements in your bot, you can win some games and lose others that will cause your bot to fluctuate position. To be clear, it doesn’t matter and this completely okay/fair to do. Here’s why: the games are played during the week in near real-time. On Friday at 2pm (for our main tournaments), we close submissions. At this time, we take a look at the players in the game for eligibility, and we start the final round at about 2:15pm. During this round at 2:15pm, all games are replayed – so the leaderboard before this is completely irrelevant – only the leaderboard created as a result of the final round is what matters. So why have the continuous integration during the week? Is it still important? You bet! It’s a chance to play and fine tune your strategy. To get ideas from other players and come up with your own. Your bot might play the same during the final, or it might not. Sandbagging Since the final leaderboard is generated as a result of the 2:15pm match, we’ve seen some interesting behavior – and this makes the game exciting! For example, suppose you’ve got a cool strategy – perhaps you wait to implement it because you don’t want your opponents to develop a counter play. This is all completely legit and part of the game. In some ways, it’s a double-edged sword – you need to test your ideas to see how good they are, but like in a poker game, you want to keep some cards close to your vest. One question we got was whether you could use time-based code in your bot. Absolutely! What I’d recommend, if coding specific for the Friday tournament, you do something like this: 1: if (DateTime.UtcNow > new DateTime(2011, 4, 15, 18, 0, 0)) 2: { 3: //begin super playing mode! 4: } In this case, we’re setting the bot to play differently after the 2pm close time on 4/15. Remember, all time is UTC on the game server (DateTime.UtcNow and DateTime.Now are the same in Windows Azure, but I use UTC for clarity). Because UTC is currently +4 hours from EDT, we add 4 hours to 2pm (1400 hours) so the cutoff time is 1800 hours UTC. I don’t recommend you set this to 2:15pm because the game may start slightly before 2:15pm. Additionally, I don’t recommend an end time because while the games should play at 2:15pm, it’s possible due to technical issues it might need to be delayed slightly. Ineligible Players We know some plays sneak in occasionally – past winners, employees … even we submit a test bot to demo the project or when trying to resolve an issue. We are usually pretty good at removing those bots. In the main tournament rounds, we’ll do our best to police the registrants to make sure they qualify, but we’ll apply a bit more scrutiny before the round at 2:15pm Friday (hence why we take a 15 minute break to give things a once-over).

Getting a Windows Azure account for Rock, Paper, Azure

If you’re interested in getting a Windows Azure account to play in Rock, Paper, Azure (RPA), there are a few options available to you, from least painful to most painful (in my opinion, anyway): Method 1 – Windows Azure Pass The way most people are getting an account is through the Windows Azure Pass program (using code PLAYRPA).  More details can be found on the Get Started page under step 1.    But, this certainly isn’t the only way to get an account, and – for a few of you – might not be possible.  The Azure Pass is limited to one Live ID, so if you got an account through the Azure Pass program say 6 months ago, you can’t get another one.  (I won’t say anything if you just sign up for another Live ID.) Method 2 – Windows Azure Trial Account Sign up for the Windows Azure Free Trial.   This gives you 750 hours of an extra small compute instance, and 25 hours of a small compute instance.  You do need a credit card to cover overages.  Note: the Bot Lab project by default is set up as a small compute instance.  If you go this route, I highly recommend you change the Bot Lab to be an Extra Small instance.  You can do this by double-clicking the role and changing the VM size: Method 3 – MSDN Subscriptions Have an MSDN Premium or Ultimate subscription?   You already have account hours you can use.  Log into your MSDN account for more information.   This step does require a credit card (or other billing arrangement) to handle overages, but you are not billed as long as you stay within plan.  As of the time of this writing, please note that Extra Small compute instances are beta and not included in the MSDN hours – so be sure to stick with a small instance.  As usual, we recommend taking down deployments once you’re done to avoid wasting compute time. Method 4: Pay as You Go Specials Check out the current offers.   There are few different options based on your needs (and some are available specifically for partners).  The introductory special is the best way to get started, but if you’re using Windows Azure consistently, the Windows Azure Core offers a great value.   If you’re just interested in playing the game and willing to pay or aren’t able to receive other offers for some reason, deploying the Bot Lab as an Extra Small instance costs $0.05 per hour.   If you were to play during the week, and leave the Bot Lab deployed 24 hours, you’d be looking at roughly $5.  (If you only code in the evenings for a few hours, pulling down the deployment overnight and not during use will bring that down substantially.) See you on the battlefield!

We’re Ready to Rock…

… but there are some changes to Rock, Paper, Azure we need to discuss based on our test week.   First things first:  I highly recommend you download the latest Bot Lab and MyBot project here.  For the most part, old bots bots will continue to work, but since this was a test round anyway, I highly recommend you upgrade – there are a few edge cases that might break bots, or cases where a bot doesn’t do what you think it would.  Let’s discuss all of these changes we’ve made.  I’ll save the best for last. CanBeat and LosesTo – Don’t Use We re-scoped the CanBeat and LosesTo methods from the Move class to internal (from public).   Most people weren’t using them, and they weren’t really intended for outside consumption and we received a couple of questions on behavior.  The reason for the change is this – and some of this is historical:  the way the engine works is that it goes through a series of steps to determine a winner.   It will first look if a move can beat another move: 1: internal bool CanBeat(Move move) 2: { 3: if (!ValidMoves.Contains(GetType().Name)) 4: return false; 5:  6: if (!ValidMoves.Contains(move.GetType().Name)) 7: return true; 8:  9: return CanBeatLegalMove(move); 10: } So the RockMove implementation returns true if the move is scissors which is implemented in the RockMove class.  The original game had moves in different assemblies for multiple rounds, so the win determination path had to waterfall through, and examine rules to the game – such as whether or not you have any dynamite remaining.   The short answer here is there are cases where this will return unexpected results, so it’s best to just not expose them.  Performance wise, it’s better to have your own implementation, anyway.  If your bot is currently using this, sorry to say this is a breaking change. Game Summary At the top of the log file, you’ll now see a game summary that is helpful for info-at-a-glance.  It looks like this: Game Summary bhitney JohnSmith Points 953 (L) 1000 (W) Dynamite Used 45 100 Time Deciding (s) 0.04885 0.06507 Time deciding shows how much time your bot has used for the entire round.   This is interesting to see how your bot compares to others, but, it’s also useful for timeouts which is below.   Timeout   The server has some strict timeouts – we’re always tweaking the exact logic and we’re hesitant to give too much information because, in a multithreaded environment, the time slice each bot has isn’t exclusive.   But, your bot has a maximum of 1 second (subject to change) per match.  Typically that is no problem, as you can see in the game summary.  Once your bot crosses the 1 second timeout, your bot will stop making moves (essentially forfeiting the rest of the moves).   Server Messaging   In the log file, you’ll now see more clear messaging if something happened – for example, if a player threw dynamite but was out of dynamite, the log will indicate this next to the score.    ExceptionMove   We standardized the error moves to “ExceptionMove.”  If a player times-out or throws an exception, their last move will be an ExceptionMove.  This is visible in the log, and detectable like so:   if (opponent.LastMove is ExceptionMove){ //player threw an exception or timeout} This is a good time to mention that the opponent’s LastMove is null on the first move.  Also, if a player throws “illegal dynamite” (that is, throws dynamite when he/she is out) their last move will be Dynamite.  It’s up to you to figure out they were out of dynamite!   Fresh Upgrade   One of Azure’s strengths is flexibility in deployment – when deploying, you have an option for an in-place upgrade, or can deploy to staging and do a VIP (virtual IP) swap that allows you to seamlessly move a new deployment into production.    Because of the significant changes to our Bot Lab and new features, we recommend deleting the old deployment first, and then deploying the new package and not doing an in-place upgrade.   Player Log   And now the best part!  There’s a private player log you can write to.  This information will be appended to the bottom of the game log – but it’s only visible to you.  We’re still testing this feature, but it should be helpful in isolating issues with your bot.  To write to your log, you can do something like:   1: if (!you.HasDynamite) 2: { 3: you.Log.AppendLine("I'm out of dynamite!"); 4:  5: //opponent's log is always null! 6: if (opponent.Log == null) { } 7: }   Note:  Your opponent’s log is always null, so don’t try it!  Also, logs are limited to a total of 300k – this should be more than enough, but once the log passes this mark, the engine won’t write to the log (but no exception is raised).

RPA: Why is my Bot Rejected?

We’ve had a few people ask about getting the following message when submitting bots: Bot contains invalid calls. Please review the official rules for more information. In short, this message means the bot didn’t pass the static analysis tests.  On the About the Challenge page, you’ll see this: While this list is subject to change, we do not allow any classes/methods from System.IO, System.Net, System.Reflection, System.Threading, System.Diagnostics, or System.GC. That list is subject to change, and there are a few other red flags like P/Invoke or unsafe code.  Sometimes, these are caused by what would otherwise seem innocuous, such as calling GetType on an object – but that’s a reflection call, so would trigger the static analysis. Another occurrence:  analysis will look for the presence of such code, not if it’s reachable.  In one case, the code was never called but still present in the bot. So, if you’re getting the above message, look for those items and if you have any questions, leave a comment here or send us an note through the www.rockpaperazure.com site!

Rock, Paper, Azure: Why US Only?

Over the past few days, we’ve gotten many requests from those outside the United States who would like to play Rock, Paper, Azure.  Some have even said, “I don’t care about the prizes, I just want to play!”   So what’s the deal? If we could simply enable the contest to be worldwide, that would be awesome!    But, when prizes are involved, it’s not a simple matter.   There isn’t an easy mechanism by which to say, “it’s ok to enter, you just can’t win.”  Just to provide a little transparency here, there are legal hurdles and frankly, the team that put this together is only a few people doing something part time.   Because we’re in the U.S. subsidiary, our main focus (naturally) is on U.S. – not that we want to exclude anyone, of course.  So what’s next?  First, we’re working with our colleagues in other subsidiaries to enable this in more countries, if at all possible.  It won’t happen on week 1, but hopefully we’ll get there over time.   If you know your local DPE evangelism team, be sure to contact him or her and let him know you’d like to play – if you don’t know who that is, leave a comment here in my blog. 

Rock, Paper, Azure Deep Dive: Part 1

If you’re not sure what Rock, Paper, Azure (RPA) is all about, check out the website or look over some of my recent posts.   In this series of posts, I want to go into some of the technical nuts and bolts regarding the project. First, you can download Aaron’s original project on github (here and here).   The first project is the Compete framework, which is an extensible framework design to host games like Rock, Paper, Scissors Pro! (the second project).    The idea, of course, is that other games can be created to work within the framework. Aaron and the other contributors to the project (I remember Aaron telling me some others had helped with various pieces, but I don’t recall who did what) did a great job in assembling the solution.   When moving it to Windows Azure, we had a number of issues – the bottom line is, our core requirements were a bit different than what was in the original solution.   When I describe some of these changes in this and other posts, don’t mistake it for me being critical of Aaron’s project.   Obviously, having used it at code camps and the basis for RPA shows I have a high regard for the concept, and the implementation, in many parts, were quite impressive. So, if you download those two projects on github, the first challenge is getting it up and running.  You’ll see in a few locations there are references to a local path – by default, I believe this is “c:\compete”.  This is the local scratch folder for bots, games, the db4o database, and the logfile.  Getting this to work in Windows Azure was actually pretty straightforward.   A Windows Azure project has several storage mechanisms.  When it comes to NTFS disk I/O, you have two options in Azure:  Local Storage, or Azure Drives.   Azure Drives are VHD files stored in Azure Blob Storage and can be mounted by a VM.   For our purposes, this was a little overkill because we only needed the disk space as a scratch medium: the players and results were being stored in SQL Azure.  The first thing we needed to do to get local storage configured is add a local storage resource: In this case, we just created a local storage area called compete, 4GB in size, set to clean itself if the role recycles. The next step was to remove any path references.  For example, in Compete.Site.Models, you’ll see directory references like this: Because there’s so much disk I/O going on, we created an AzureHelper project to ultimately help with the abstraction, and have a simple GetLocalScratchFolder method that resolves the right place to put files: Now, we inject that call wherever a directory is needed (about a half dozen or so places, if memory serves).   The next major change was deciding: to Spark, or not to Spark?  If you look at the project references (and in the views themselves, of course), you’ll see the Spark view engine is used: I’m no expert on Spark but having worked with it some, I grew to like its simplicity: The problem is, getting Spark to work in .NET 4.0 with MVC 2 was, at the time, difficult.  That doesn’t appear to be the case today as Spark has been revived a bit on their web page, but we started this a few weeks earlier (before this existed) and while we recompiled the engine and got it working, we ultimately decided to stick with what we knew best. The end result is the Bot Lab project.   While we’re using RPA with the idea that it can help others learn about Azure while having fun, it’s also a great example of why to use Windows Azure.  The Bot Lab project is around 1 MB in size, and the Bot Lab itself can be up and running in no time (open solution, hit F5). Imagine if you wanted to host an RPS style competition at a code camp.  If you have a deployment package, you could take the package and host it locally if you wanted, or upload it to Windows Azure – hosting an extra small instance for 6 hours at a code camp would cost $0.30.   Best of all, there’s no configuring that needs to be done (except for what the application dictates, like a username or password).  This, if you ask me, is one of the greatest strengths behind a platform as a service.

My Apps

Dark Skies Astrophotography Journal Vol 1 Explore The Moon
Mars Explorer Moons of Jupiter Messier Object Explorer
Brew Finder Earthquake Explorer Venus Explorer  

My Worldmap

Month List