Category Archives: Technical

Povio: On its way to cool

An open letter to the developers of Povio including some hopefully constructive and totally unsolicited feedback about the user experience.

1. Povio is cool

I heard about Povio through Hacker News and immediately installed it. It’s new. It’s humble. It solves the problem of people sharing useless stuff about themselves. I can ping the people I’m interested in, and I feel good when people ping me for a photo of myself. As a member of their target demographic, I’m hooked.

Really – I like the app and I want to see it succeed. The rest of this article is my thoughts on how to accomplish that, mainly directed toward the developer(s) but also as a way to open up a conversation about modern app development, privacy, and heteronormativity.

It solves what I call the “broadcast problem”. Basically the idea that some forms of communication are “broadcast” (snapchat, facebook) and others are direct (texting, skype) and it’s sometimes easy to confuse the two. You can read my thoughts on the broadcast problem if you’re so inclined.

2. Povio needs to not be a dating app for straight white men

The video for Povio features mostly a good looking female who is Povio’d (new verb!) by a male friend and they end up getting ice cream together, or something. Whatever – sex sells, and especially to the coveted 18-24 year old male. But there’s also a problem here, which is that Povio needs to attract people of all genders and backgrounds if it wants to be successful.

In my opinion, if Povio tries to be a dating app like tinder, it’s going to fail. It will turn creepy and the vast majority of users will abandon it. I worry that it’s already on its way to this. Here are the users that are added automatically as friends:

2014-03-24 22.37.26

!!!???

All white, and seriously: Miss Hotty?!

Either Povio will change this, or they’ll lose a lot of users who aren’t heteronormative white males. Even if, at best, it’s based on your facebook gender, race, and “looking for”, which is almost a neat idea for user acquisition, but still gives me a bad feeling about the app.

3. Povio has a neat UI with unintuitive UX

Povio’s UI and graphic design: Clever.

Povio’s UX and command structure: Obtuse.

Let’s say I want to unfriend a user. (I actually had to reach out to the devs on twitter to figure this one out). Expected: I long-click on the user’s list item and get options. Nope – long click does nothing. I click on Best Buddy’s face. Nope – a close up of his profile pic.

2014-03-24 22.37.33

What is he so smug about?

Turns out it’s as simple as single-tapping the list item. But it took me a good 5 minutes and a twitter conversation to figure that out. And who wants to see a large version of their friend’s profile picture?

2014-03-24 22.38.19

Finally.

Suggestion: Use the standard long-press for options. Remove the click-to-open-profile-pic action. Get some user testing and work on having a really intuitive user experience.

4. Povio needs to have the ability to turn on strict privacy settings

Yep, just like I suspected. Been on there for 10 minutes, and already getting friend requests from creepy guys I’ve never heard of. I would only use this with close friends. —natasham25

Make sure people know each other on Facebook, Google Contacts, or something. Have an option for anonymous friend requests to require a three-digit password. Photo apps like snapchat already toe the “creepy” line and enabling users to lock down their profile is the best way of combating this.

Allowing “creepy guys” to anonymously ping people is only going to reinforce the “dating app” vibe.

 5. Povio shouldn’t show me who pinged my friends

A) I don’t want to see how popular they are compared to me.

B) Nobody wants to see all of the people pinging their S.O.

It’s rare that someone enjoys the feeling of “sharing” a friend. Especially a S.O. or more. I pinged my Fiancee and was surprised to see a list of all the other people who had also pinged her. I’m not a jealous guy – who she sends Povios to is not my business. But I know more jealous types probably wouldn’t be happy to see those names, especially if they’re potential rivals. It also creates the feeling that you didn’t just get a special picture created and shared just for you.

Who is this guy anyway?

Not making me feel unique, here.

6. Povio is awesome for shy and boring people

Not a criticism!

Povio makes it really easy to ask your friends to include you in their life. As long as it’s easy enough to ignore a ping (with plausible deniability for ignoring it) from someone you don’t want to share with, I think there’s great potential here for an app that allows people to ask “hey, what are you up to” without feeling inclusive.

Snapchat is for broadcasting cool events. I get snaps from some people a LOT more than I do from others. I only send snapchats when something interesting or exciting is going on. To send a snap, you have to feel like you’re doing something worthy of taking up someone else’s ten seconds.

Povio solves that by allowing me to request my friends’ presence when I’m bored and lonely, and therefore makes me feel more social and wanted. I can get pings from friends and be inspired to set up something cool to take a picture of.

Epilogue:

Povio is up-and-coming and I hope the best for it. Based on the reactions of my non-immersed-in-the-tech-world friends it has a lot of potential and I can’t imagine it’s userbase is less than viral already.

With a few tweaks and fixes, I think Povio will quickly become a household name.

From Brooklyn,

— Erty Seidel

Edit: Povio’s creator has responded to this post:

P.S. – Shameless self-promotion: If you liked my writeup, know that I’m currently looking for work!

Terminal_’s Rules of Game Development: A retrospective

Terminal_ is a game that Evan Conway , Max Feldkamp, Mike Gold, Julian Delfino, and myself worked on during the winter of 2012-2013. I’ve since left the project, but I believe that Evan and Max are carrying it forward despite having day jobs. That winter, I had the role of Product Manager, and came up with the following “helpful suggestions” to guide our development. I was chatting about game design with my friend Matt Davis, and decided to write up these rules so that they might be helpful to others.

The rules:

  1. This is not a workstation
  2. This is not a sim game
  3. Playtest Playtest Playtest
  4. Our drill is the drill that will pierce the heavens!
  5. Early optimization = death
  6. What is it really about?

1. This is not a workstation

Our early ideas for Terminal_ revolved around the player interacting with the game solely through a computer terminal. The problem with this is that we kept having ideas about implementing existing *nix tools and commands (like top, grep, etc.) in our game. I wrote rule #1 to remind us that the game was not a workstation, and that anything that didn’t contribute to the player having fun was just a distraction.

Takeaway: Focus on fun, not functionality.

2. This is not a Sim Game

We were constantly skirting Bottom-Up Game Design, basing the fun on the idea that the player was interacting with a terminal, instead of focusing on the challenges of level and puzzle design. Retrospectively, this is probably the biggest problem that we had. Our game was cool, it had a great atmosphere, but it didn’t have anything that was actually fun and engaging for the user.

Some games *are* sim games, in which case you can totally ignore this rule. But remember that sim games are only fun because they’re not exactly the thing that they’re trying to simulate. Otherwise they would be just as boring as that actual thing. If that makes sense.

Takeaway: Focus on fun puzzles and levels, not accurate simulation

3. Playtest Playtest Playtest

The Terminal_ team would get bogged down by arguments over the best way to implement a feature. When this happened – and I was usually one of the offenders – I would bring down the force of rule #3. Implement it one way, then playtest it. If it doesn’t work, try the other.

There’s A/B testing on websites, and really, data is an amazing way to make sure that your game is fun and playable. Valve knows this. They playtest each level over and over and over, making radical changes to the puzzle design until they get something that is fun and challenging, not frustrating or obvious. Portal 1 is a great example of this – listen to the developer commentary especially to see how many times they reference changing something because of playtests.

Takeaway: Data trumps opinion 99% of the time.

4. Our Drill is the Drill that will Pierce the Heavens!

If you don’t recognize this quote, you need more galaxy-sized robots in your life.

#4 was a reminder to not give up on the game, even when things were tough. We watched Gurren Lagann together as (mostly) a team at college, so whenever we were feeling down about the slow progress of our game, we would shout this at each other to remember that this game was achievable through hard work.

We obviously didn’t end up making the game, but I attribute that mainly to the fact that we only had 5 weeks to work, an ambitious schedule, and no clear person in charge to make final decisions about what went in the game.

Remember – you’re making something new, and even if the idea has been done before, you can do it better, or different in ways that are fun. Flappy bird is an idea that has been around forever, but Nguyen did things just right to make a worldwide sensation.

Another thought on this: Pare your game down to the minimum viable product. Get that done. Then expand on it until you have all the functionality you want. Whether you have a public beta is up to you, but despite your ability to pierce the heavens, you need to set realistic goals for the size and experience of your team. Once you’ve created something fully, you’ll be better prepared to embark on a larger project next time.

If you do fail, focus on the ways in which you’ve grown throughout the project, and the lessons learned for your next project. Then pierce the heavens next time.

Takeaway: Don’t give up on a game. If you run into trouble, see what you can cut. If you do fail, focus on the things you learned so that you can succeed with your next project.

5. Early Optimization = Death

I was chatting with Evan about one of his games recently – a dungeon crawler with a very innovative “sense” system. What you see, hear, smell, etc. in each room is passed through messages, and these messages also affect the wandering monsters. Nobody likes a room that reeks.

Evan was worried about the performance of iterating through all of the monsters and messages on each frame. He was beginning to consider alternate data structures and optimizations for the problem.

I fall prey to this all the time. The problem with this kind of thinking is that it quickly leads to spending more time working on the code than it does working on making the game fun. And really, there were no performance problems here, or in the similar problems we faced making Terminal_. This ties in to rule #3 – once playtesting has determined that something isn’t optimized enough is when it’s time to go back and rewrite it to be more efficient.

Or, if you have extra time and hands at the end of the project to make sure that your program will run on older PCs. Otherwise, just ship it, and work in the performance tweaks through patches later.

Takeaway: If you’re worried about performance, you’re probably wrong unless something actually isn’t performant.

6. What is it really about?

Especially in strongly-aesthetic games like Terminal_, knowing what your game is actually about is an important step toward putting reason behind your choices.

Even Flappy Bird has a “really about”: it’s about minimalist, fast gameplay. Nethack is really about exploring complex, programmatically generated dungeons. Amnesia: The Dark Descent is about atmosphere, memory, horror, and helplessness. Portal is about an insane AI testing you on puzzles which require you to think in a different topology.

What was Terminal_ about? I’m not sure. We kinda failed at this one because I think everyone on our team had a different idea.

Know the central themes of your game, whether you can describe that in a few words, a few sentences, or even an essay. Then, when someone proposes a new feature, you can really ask yourself and your team: does this fit into the theme?

Feel free to edit this theme as you go along, but when you do, check to make sure everything in your game still works toward creating something whole.

Takeaway: Have one idea about the themes of your game.

Breaking Rank: A Hacker’s Way of Defeating Stack Ranking

The Problem

Alarm has been raised in the developer community over stack-ranking of employees: managers are required to rank their employees and report the top and bottom performers, usually done by percentages (top 10%, bottom 10%, etc.). Among other serious problems, this creates an atmosphere of competition and sabotage, and destroys employee morale. Employees at Microsoft, infamous among developers for this system, call the stack-ranking system the “most destructive” process (source). Employees are often given raises – or fired – because they fell into certain brackets.

My dad, a manager for a certain aerospace corporation, mentioned to me over lunch today that his company also does this ranking system, although fortunately his company doesn’t give too much credit in the form of raises or punishments based on this system. As a hacker, my first thought was: how can I break this, and how can I break it in a way that benefits the employees, removes the toxicity of the system, and of course, casts the manager in a positive light?

A naïve solution

Let’s assume that a manager can deal out merits/demerits on their own terms, and that they have hired properly so that their team is full of good developers. As this manager, let’s go to our employees and say, “Hey, we’re going to draw straws instead of do stack ranking. The short straw gets the bottom 10% and the long straw gets the top 10%.” This means that on average, our employees will get an equal number of raises and demerits over time, and our entire team will get the average raise.

Our top performers might complain, but they’ll probably be happier to remove the toxic environment of stack ranking and work in an overall better environment. Plus, they’ll still draw the top 10% straw regularly. If an employee starts slacking off because they’re no longer motivated, it’s up to the manager to provide that incentive to keep working hard – just like in a company without stack-ranking.

But this doesn’t work for everyone: Some employees might draw the short straw too often and get fired by the powers-that-be. So how can we ensure that we give all our employees equal numbers of raises and demerits over the period of a couple of rankings? And how do we make sure that upper management never notices that we’re breaking their system?

Lava Lamp Algorithm

I’m calling this a Lava Lamp algorithm for lack of a better word – if there’s an official name for this kind of thing, please leave a comment. You can find the code for this on my github.

The basic idea is that we create a random list of employees. Let’s take some “random” names and put them in a random order for example purposes:

  • David
  • Zach
  • Tom
  • Nick
  • Mary
  • Allison
  • Alan
  • Sonali

Then we assign each employee a weight based on their position in their stack. Employees at the bottom get “lighter” and employees at the top get “heavier” (like the wax in a lava lamp). Here, I’m using a weight of 2 as a maximum, which worked well in my testing with the size of this list (8).

  • David [-2]
  • Zach [-1.43]
  • Tom [-0.86]
  • Nick [-0.29]
  • Mary [0.29]
  • Allison [0.86]
  • Alan [1.43]
  • Sonali [+2]

Here’s the tricky part – we use the absolute value of their weight to determine the order in which we move them – with smaller values going earlier. This keeps the list from getting stuck in loops where an employee moves up, only to be pushed back down by the next movement. There might be a better way to do this – this is definitely a first shot at the algorithm.

To keep things super deterministic, in the event of a tie of the absolute values, positive weights move first, and in the event of a real tie, the employee with the lexicographically first name goes first. This way the list will always move the same way no matter the implementation. The employees will move in this order:

  • Mary [0.29]
  • Nick [-0.29]
  • Allison [0.86]
  • Tom [-0.86]
  • Alan [+1.43]
  • Zach [-1.43]
  • Sonali [+2]
  • David [-2]

By “move”, I mean that the users will bubble through the list a number of positions determined by their weight as an integer. Our list above would become the following after one iteration:

  • Tom
  • Zach
  • David
  • Nick
  • Mary
  • Sonali
  • Alan
  • Allison

Then we re-add the weights for each spot (“heavier” top, “lighter” bottom):

  • Tom [-2.86]
  • Zach [-1.43]
  • David [-2.86]
  • Nick [-0.57]
  • Mary [0.57]
  • Sonali [2.86]
  • Alan [2.86]
  • Allison [2.86]

Nobody has jumped from the top to the bottom or vice versa, or any other kind of thing that might raise flags – it just looks like the list has shuffled somewhat. Allison has the bottom spot for now, but she also has a weight of +2.86, meaning she’ll move up quite a bit on the next iteration.

I’ve run the algorithm out to 100,000 steps, and as far as I can tell, the employees end up cycling nicely from top to bottom.

Problems

  • There’s always a to-do list with any code, and this is no exception. I wrote this in an afternoon, so there’s going to be some obvious bugs and weirdness. Python isn’t my main language, either, so any help making things more pythonic would be greatly appreciated (as long as the suggestions are put nicely, please!).
  • There’s also a lot of times where very small numbers (due to rounding errors) are introduced. I probably don’t need to remove these, but if there’s an easy way, I’d love to know.
  • There also needs to be more testing of both the code and the algorithm. Everything I’ve thrown at it seems to produce good results, but I’d love for people to come up with corner cases for this kind of thing. Even if this specific algorithm ends up not working, there’s no reason why someone shouldn’t write an edition that actually does work 🙂

Shout-Outs

  • My dad for helping me with some bugs and providing the inspiration for this problem
  • Eric van der Heide (my roommate) for helping me with the heart of the algorithm.
  • Hacker School (which I just attended) for being awesome and helping give me the skills to do something like this

What are Javascript, AJAX, jQuery, AngularJS, and Node.js?

This post is addressed toward people who have little to no experience with JavaScript, Node.js, or their associated libraries, but are interested in learning what they are and aren’t.

Another student at Hacker School asked me to explain the difference between Javascript, AJAX, jQuery, AngularJS, and Node.js.

Let’s start with the basics:

JavaScript

JavaScript is a programming language designed for use in a web browser. (It’s no longer a “scripting” language, nor does it have anything to do with Oracle’s “Java”, so the name is a bit misleading.)

You can code in JavaScript – it’s a full-featured language which (with one notable exception) runs in a web browser like Chrome, Firefox, or Internet Explorer. It’s usual use is to manipulate a thing called the “Document Object Model”, essentially elements on a webpage.

JavaScript executes on the client side: A website server sends the javascript to a user’s browser, and that browser interprets and runs the code. This happens inside a “sandbox”, which keeps the javascript from touching the internals of the system, which most of the time keeps malicious code from messing up the user’s computer.

A simple JavaScript program is alert("hello world!");, which on an HTML page would probably be put inside a <script> tag to tell the user’s web browser to interpret the following as JavaScript, like: <script> alert("hello world!"); </script>. This code makes a small alert box pop up on the user’s browser. To see this code execute, click here.

So, to recap: JavaScript is a programming language that operates in the browser, inside a security “sandbox”. It allows manipulation of elements on a webpage.

AJAX

AJAX stands for “Asynchronous JavaScript and XML“, and is a way that a webpage can use JavaScript to send and receive data from a server without refreshing a webpage. XML is a kind of markup language – like HTML, which people sometimes use for sending data across the internet. Recently, JSON (“JavaScript Object Notation”) is more popular and can be natively read by JavaScript. I know that’s a lot of 4-letter acronyms, so let’s recap:

AJAX: Asynchronous JavaScript and XML. A system for sending and receiving data from a server without a page refresh. (example below)
XML: eXtensible Markup Language. A language for organizing arbitrary data. Uses lots of angle brackets “<>”. (example)
HTML: HyperText Markup Language. A subset of XML specifically for describing and organizing web pages. (example)
JSON: JavaScript Object Notation. A more modern way of packaging data that’s often used with AJAX. Can be natively read by JavaScript. (example)

A sample AJAX call might work like this:

  1. Client requests page from server
  2. Server responds to request and sends page
  3. Client makes AJAX call to the server and requests more data
  4. Server sends that data.
  5. Client updates the page using that data without refreshing.

Facebook, Gmail, and Pinterest are examples of sites that use a lot of AJAX.

The “Asynchronous” part refers to the fact that when the JavaScript makes the AJAX call to the webserver, it continues to work until the response – it doesn’t “block” and stop while the data is being processed server-side.

jQuery

jQuery is a library built in JavaScript to automate and simplify common tasks. There are many libraries like it, but jQuery really took off because of its power and ability to make things work in older browsers. jQuery is used in the browser, alongside “normal” JavaScript. It is mainly used for animation and AJAX, which are difficult to do with vanilla JavaScript, but are just a few lines in jQuery.

jQuery is included in a web page using the <script> tag; for example: <script src="./path/to/jquery.js"></script>. There are also myriad jQuery plugins, which extend the functionality of jQuery in various ways.

A sample jQuery call, which hides a small box when clicked:

Live Example:

Click!


<script src="path/to/jquery.js">
<script>
    $("#box").click(function(){$("#box").slideUp()});
</script>

AngularJS

AngularJS is a full frontend MVC framework for JavaScript web applications. It was built at Google and provides a way to quickly build large, single-page web applications. Like jQuery, it is included into a page using the <script> tag, and is itself written in JavaScript. Unlike jQuery, it is meant to be a framework upon which an entire web application is built. It actually includes a minimal version of jQuery by default.

If you’re looking to learn AngularJS, I recommend EggHead’s video tutorials. You’ll need to have a very solid understanding of JavaScript first, since writing any Angular requires a deep understanding of prototyping, scope, and various other JavaScript aspects.

The AngularJS website has a page of example projects built with AngularJS, if you’re so inclined.

Node.js

Remember how I told you that JavaScript ran in the browser, but I mentioned that there was one big exception to that? Node.js is that exception. It’s a command-line tool that runs JavaScript on a machine without needing to run in a browser. It does this by using a version of Chrome’s V8 Engine, which is the JavaScript engine that runs inside Google Chrome.

Before Node.js, developers would have to use different languages for the backend and frontend of their application. For example, PHP, Java, ASP.Net would run on the server, and JavaScript would run in the client browser. Now with Node.js, developers can use JavaScript on the server as well as the client, meaning that developers can focus on learning one language. Whether this is a good thing is still up for debate (nsfw language).

Conclusion

JavaScript is a language written for websites to run in the client’s browser.

AJAX is a way for JavaScript to request data from a server without refreshing the page or blocking the application.

jQuery is a JavaScript library built to automate and simplify common web tasks like AJAX or animation.

Angular is a hip JavaScript framework which is made for building large, single-page web applications.

Node.js allows JavaScript to be run without a browser, and is commonly used to run web servers.

Please leave any questions or ideas for improving this article in the comments below!

From Manhattan,

–Erty

 

Free Linux Servers

Every once in a while, I find myself needing to quickly run linux or one of its derivatives. Here are some resources I’ve gathered that allow quick setup of a disposable linux server:

1. VirtualBox

Runs on your own machine as a VM. Internet connectivity. You’ll need to download an ISO and install it. You do get a GUI though.

2. Bellard’s JSLinux

Linux VM written in Javascript (how’s that for a project?). Free, terminal only, no networking. Pretty much good for playing around with the linux shell in a really disposable way.

3. Instant Server

Easily my favorite – hit a button and fill out a captcha for 35 minutes of Ubuntu 13.04. Or, pay a small fee and get the server for up to a week. Great customer service and good speeds. Terminal only, internet connectivity.

4. SimpleShell

Linited to 15 minutes, and doesn’t seem to have internet connectivity, despite what the site says. Still, for a free linux command line, it’s fast and has a very fast setup time.

5. And many more

A google search for “free shell” provides many links, dmoz being  one of the more trustworthy (run by Mozilla).

Enjoy!

From Manhattan,

–Erty

 

Installing VBFNLO

My friend Aaron has an internship with CERN or something like it, and he’s using a tool called VBFNLO for… something with particles.

Anyway, he was concerned about being able to install VBFNLO, so he called and asked me for help. After a bit of searching, we found by using cat /etc/issue that he was running Scientific Linux. I’ll be demonstrating on an Instant Server running Ubuntu 13.04. Both should work.

Downloads and installation instructions for VBFNLO are available on the VBFNLO website.

First, we need to make sure that we have the proper compilers. Make sure that you have a C compiler such as GCC, and a FORTRAN77 compiler such as g77 or gfortran. You can do this by running which gcc, which g77, and which gfortran. As long as the gcc and one of (g77|gfortran) return a value (e.g. /usr/bin/gcc), you’re fine. If running those commands returns no text, you’ll need to install the proper compilers, or ensure that you have another compiler that will work with VBFNLO (Ubuntu: sudo apt get install gcc, sudo apt-get install gfortran)

EDIT: You will also need g++ and make – I think this was a major hang-up in my installation process. You can test for g++ and make by running which g++ and which make – if the commands don’t print anything, you’ll have to install them (Ubuntu: sudo apt-get install g++, sudo apt-get install make)

The next thing to do is to move to a directory where you want to install VBFNLO. I’ll be working in my home directory, indicated by a tilde (~), but on my machine is /home/ubuntu/.

The VBFNLO source is available for download at http://www.itp.kit.edu/~vbfnloweb/wiki/lib/exe/fetch.php?media=download:vbfnlo-2.6.3.tgz, so we’ll run wget http://www.itp.kit.edu/~vbfnloweb/wiki/lib/exe/fetch.php?media=download:vbfnlo-2.6.3.tgz to download the file to our current directory.

If you run ls, you should see a file called fetch.php?media=download:vbfnlo-2.6.3.tgz. Let’s rename this to something more useful. Run mv fetch.php?media=download:vbfnlo-2.6.3.tgz vbfnlo-2.6.3.tgz to have a more workable name. Remember that you can hit tab to autocomplete the fetch.php... part.

The .tgz extension means that this is a tarballed, gzipped file. So let’s untar and unzip! Run tar -xzvf vbfnlo-2.6.2.tgz to extract all that delicious science from it’s compressed form.

If you run ls now, you should see a directory called VBFNLO-2.6.3. You’ll want to cd VBFNLO-2.6.3 to get into it. (If it says something about not being a directory, you’ve probably messed up or had insufficient privileges in this directory. Try running the tar command with higher privileges, i.e. sudo, or in a folder where you have directory creation permissions).

The next thing you’ll want to do is run sh ./configure --prefix=[path], where you replace [path] with the path to where you’ll be installing VBFNLO. In my case, I will run sh ./configure --prefix=/home/ubuntu. (You can see a full list of configuration flags on the VBFNLO installation instructions page, but odds are you want a default install for now.)

Now that configure has run, run make inside the VBFNLO-2.6.3 directory. This may take some time to complete. Go get some coffee or something. On my Micro-ec2 instance it took well over an hour; hopefully you’re running this on something a bit more powerful. You will need to have write permissions in the working directory. If you’re on a sketchy connection, you may want to run make &, which will decouple the make command from your terminal and keep running even if you disconnect. You can check if it’s still running by executing top, and looking for the process f951.

The next command you’ll need to run is  sudo make install, which will actually create the executables for you to run. You’ll need to be a sudoer or root to run make install.

If there are no errors, you should have your executables sitting in the path you provided earlier, in the bin folder.

From Manhattan,

–Erty

A Fix for Ultimate Tic-Tac-Toe?

A few days ago, Ben Orlin of mathwithbaddrawings.com posted Ultimate Tic-Tac-Toe, which described a nested game of Tic-Tac-Toe – In lieu of describing the game again, I’ll direct you to his post if you haven’t already read it.

The problem with UTTT is thus: the Orlin Gambit is too strong, and Ben admits it in his later edit. There, he says that sending a player to an already won board means that they can go anywhere.

This means that a game start goes like this. X takes the center, which forces O to take a non-center square:

uttt01

uttt02

Then X can take the center again, forcing O again to take a non-center square. Since the center square is more desirable than any other, by a longshot, the game almost deterministically ends up in this state:

uttt03

But with the new rules, O can now take any large square they like, but if they take a center small square, then X will be able to choose where to go. Assuming that center squares are the most desirable, the game will end up something like this. (Someone with more time should investigate if there is a better move for O when they get their first free move…)

uttt04

Notice that it is X’s move, and they already have the center square in 2/3 of the squares! That said, O does have the center square overall, so perhaps this is balanced? It just seems like a lot of moves forced by the game, since the player has otherwise made a “bad” move and worsened their position.

More analysis is needed to see if O taking a not-center-small-square for their fourth turn would turn out well.

So, to fix this, I have a rule change that should alleviate this problem: If a player chooses the center square of a small board, the other player can choose any large board to play in. For example, if X takes the center of the center square on their first move, then O can take the center of any other square.

So now we have a starting game that looks like,

X takes the center of the center:

uttt01

Since X took a center square, O can choose which large square to play in:

uttt05

Now X chooses which large square to play in:

uttt06

But this means O also gets to choose a square! By now, the game is already up to the players! So we don’t have a forced game past, perhaps, the first move or so. Eventually we will end up with some configuration of (assuming center squares are desirable):

uttt07

So here, O has at least one more square! And since our assumption that center squares are desirable probably doesn’t hold, either player could force the other to play in a side-large-square at any point up to this.

I hope this “fixes” the game of Ultimate Tic-Tac-Toe and makes it a fun and much deeper game for everyone! I’ll work on getting a javascript version here on the blog eventually. (I’m going to D.C. for the weekend so no promises).

From an Amtrak Train somewhere in New Jersey,

–Erty Seidel

 

 

 

LACE: Latency-Aware Collision Engine in Javascript

Code for this is at https://github.com/ertyseidel/collisions

Motivation

In a multiplayer game, it is useful to be able to do collision detection on the server, to ensure that your players aren’t cheating or moving incorrectly. When we take latency into account, and the other myriad problems that can come about when we deal with packets, this problem suddenly becomes very difficult.

Say we have three players (p1, p2, p3) and they each have a client that sends packets containing location data to the server. To keep things simple, we’ll say that these packets contain the player’s coordinates (x, y). So, mapping these players at t=0, we get:

fig-1

The server knows these positions, so we can assume that we have a fully updated representation. Then time begins to pass, and the players start to send updates with their new locations. At t = 10, let’s say we receive a packet from player 1. Thus we are in the following state:

fig-2

 

Player 1 has moved, but players 2 and 3 haven’t received any updates from their clients! If we have a collision here, there’s no way to check yet. There’s no guarantee that player 2 isn’t colliding with player 1 right now according to player 2. Let’s run a few more frames:

fig-3

 

Can you spot the collision? Answer: Right in the center, where 1 and 3 cross, at time 18 or so (assuming each snapshot took 10 time).

Algorithm

So obviously we need some sort of interpolation and time-checking for this! Let’s look at how the main update function works.

The first thing we need to do is figure out what “step” we’re on. We do this by setting a stepSize, something like 25; this is the “bucket size” for each time step on the server.

E.g., with a step size of 25, all the packets received between time 100 and time 124 inclusive will be in the time = 100 bucket.

Let’s get some packets! We start out with knowledge of all our players positions at time 0 (It’s actually more complex than that and handles players entering/leaving, but for now let’s say we know where everyone is at t=0).

Then we get a packet from player 1 at t= 56:

But let’s say the next time we get a packet is at time 105, from player 1:
fig-4

The next thing we do is interpolate player 1’s position for the missing row, t=25. We do this by linearly interpolating between P1’s x and y values, given the time between the updates (green values are interpolated):

fig-5

 

Now let’s get a packet from P2 and P3 in the T=100 bucket. Then we do collision detection on P2 and P3 at t=100, since there is more than one data point at that timestamp.

fig-6

And interpolate the values of P2 and P3 back to t=0:

fig-7

 

Right here, we perform collision detection between P2 and P3 at t=75, and between all three players at t=50 and t=25. Essentially, whenever we add data to a row, we do collision detection against the other existing data in that row. This means that we don’t have  to wait until all of the data for a row are in before we try collision detection across them. It also means we can detect collisions in the past, and the game can retroactively decide to act on that collision, or not.

There’s one last step at this point – we remove the rows at t=0 and t=25 since we’ve already collision checked all of the players at these points, and t=50 is the data from which every player will interpolate from this point forward. Thus our table ends up looking like:

fig-8

until we receive more data from the users.

There are functions dealing with adding and removing users, but you’ll have to explore the code to see that.

Todo

Setting a step-size that is much smaller (I use t=5ms) allows us to do very fast server-side collision checking. This is nice, since we don’t have to do collision detection AND rendering on any given computer.

The main problem facing this is that we currently only do collision detection against other players  – I have no idea how it will fare with more complex objects or things that don’t move.

I’d love to see if this library works for other people writing javascript multiplayer games, and since this is alpha-level development, forks and pull-requests are greatly appreciated!

From Manhattan,

–Erty

 

 

Keeping track of your competency as a programmer

Especially for Hacker School students, but really for anyone: If you’re looking for a way to discretely measure your progress through Hacker School, check out the following resources:

If you don’t really know what you want to work on, choose whatever is your lowest level in the Programmer Competency Matrix, or an example in the eight levels of programmer that you don’t understand, and ask someone more knowledgeable about it!

From Brooklyn,

–Erty

Integers and Strings in JavaScript

Joe and I just spent an hour or so debugging my Node.js application, a simple multiplayer tag game. The problem was that while a player was moving, they disappeared from every other player’s view. Not the greatest for playability.

So we dove in to the code, and figured out that on each loop, the x and y of each player object looked something like this (x,y):

(299, 445)

then

(2991.3423, 445)

then

(2991.34231.3423, 445)

etc.

So, each time the main game went along, “1.3423” got appended to the x and y variables. We were adding the velocityX and velocityY components to the x and y respectively, so they were somehow getting concatenated instead of added.

It turns out I was doing the following:

Client:

GET(
    'loop/' + currentPlayer.id + "/" + currentPlayer.x + "/" + currentPlayer.y + "/" + currentPlayer.vx + "/" + currentPlayer.vy + "/" + currentPlayer.keyx + "/" + currentPlayer.keyy, function(data){
    hasReturned = true;
    updateData = JSON.parse(data);
});

Server:

requrl = req.url.split('/');
requrl.shift();
currentPlayer.updateLocation(currentWorld, requrl[2], requrl[3], requrl[4], requrl[5], requrl[6], requrl[7]); //world, x, y, vx, vy, keyx, keyy

The problem with this is that each of the variables come back as strings, not integers. So when we call the updateLocation method, we’re passing in strings. Observe:

"1" + "1" // "11"
1 + "1" // "11"
"1" - "1" // 0
"30" * 1 //30
parseFloat("1.234") + 3 // 4.234

So: remember that your URL variables in node are going to come in as strings and not ints or floats, and that if you try to add them to anything, it’ll end up as a concatenation operation.

Hope this saves someone some time someday.

From Manhattan,
— Erty