nodehack : one day javascript minigame


The topic of the game jam organized at c-base.org was : hacking. A team of three including Iwan Gabovitch (artwork), Rico Possienka (server) and Loïc Dachary (client) implemented the nodehack multiplayer online game. The screen shows computer nodes that must be compromised. The player can click on a node to compromise it, one at a time. When the node falls under her/his influence, the player gets the points associated with the node. The first player reaching 200 points wins the game.

gameplay

In the mockup page it is possible to interact with a frozen game state that shows a simulated situation, there is no server behind it.

At any time the lower part of the screen shows the number of points the user has followed by the number of points he must collect to win the game (200p).

When the game is being played, the lower right part of the screen shows the status as playing. If the player reached 200 points first, it will show winner otherwise, it will show looser.

When a node shows with a white font, it means it is vulnerable and can be compromised. This is calculated by comparing the percentage with the number of points the user has.

When a node has a percentage that is above the number of points the player has, it shows with a gray font and cannot be compromised. The player has to gain more experience to try to compromise it. In the example above, the user has 30 points and the node is a 50% risk node that can only be compromised by players with more than 50 points.

When the player clicks on a node that can be compromised, the node progressively turns blue. It will take longer to compromise a node that awards many points. For instance, compromission of a 5 points node will be almost instant while a node with 80 points takes a few seconds to complete. During this time the user cannot do anything else.

When another player takes over a node, it shows in red. Such a node can be compromised and will turn blue : the other player will lose the node and the associated points.

While a node is being compromised, there is a percentage of chance of being detected by the other players. This is the percentage that shows next to the point in each node. When a player is detected, the other players know about the compromission and it becomes easier for them to take over the node. In other words, they can follow the same path and takeover the node quicker. Watch out for these easy preys that have a high reward value to beat your opponents.

playing

Assuming the game is available at http://dachary.org/loic/nodehack/hack.html creating a player to join the ongoing game is done by adding ?playername at the end of the URL. Each player who joined the game will show in the connected part of the screen (top left). There is no security model, one must chose a name that’s not already taken. Picking a name that’s already taken will allow the player to takeover the other player game, which is not part of the gameplay.

installation

During the development of the code, Rico ran the server on http://www.possienka.de/ while the client was available at http://dachary.org/loic/nodehack/hack.html. The JavaScript client could not send a request to a server different from dachary.org because that would violate the same origin policy. An apache reverse proxy was set on dachary.org to resolve this problem:

    ProxyPass           /state http://www.possienka.de/state retry=1
    ProxyPass           /action http://www.possienka.de/action retry=1

Installing the client can be done with :

git clone git@gitorious.org:nodehack/nodehack.git

for the developer or anonymously with

git clone https://git.gitorious.org/nodehack/nodehack.git

because it only consists of static files. A sample installation is attached to this document.

client server API

The client server protocol is made of two functions: action and state.

state

The state function can be called with /state and will return a JSON structure describing the full state of the game as in the following sample:

       { nodes: [ {x: 20, y: 30, id: 'N1', points: 5, risk: 10 },
         {x: 100, y: 150, id: 'N2', points: 44, risk: 11 },
         {x: 300, y: 150, id: 'N4', points: 10, risk: 5 },
         {x: 200, y: 200, id: 'N3', points: 88, risk: 50 }
       ] ,
       player: { 'DEFAULT':
                 { nodes: [ { id: 'N1', detected: false } ], points: 30 },
                 'P2':
                 { nodes: [ { id: 'N2', detected: true } ], points: 250 } }
       }

Which is rendered as demonstrated in the frozen game state.
The map being returned contains a nodes entry lists all the nodes and their associated property. It is used to lay out the screen when the game starts. It contains the coordinates of the top left corner of the div representing the node : x and y. They are the absolute coordinates within the div visible between the header and the footer. Each node has an identifier : id which is used to match it with the list of nodes a player owns. The points earned when a player compromises a node is in the points field and the percentage of chance that the compromission will be detected is in the risk field.
The player entry is a map where each key is the player name. It is associated to a map with two entries : nodes that lists all the nodes the player owns and points that is the total of points the player has. Each entry of the nodes array has two entries : id that is the name of the node, was found in the nodes list above and the detected boolean that is set if the last compromission was detected.

action

The action has two parameters : /action?name=PLAYER&id=ID where PLAYER is the name of the player and ID is the identifier of a node. It returns the same structure as the /state action. When the server receives this function, it assigns the node to the player. If the player did not exist before, it is created and will be listed as one of the active players. If the node was previously owned by another player, it is taken from her / him.

server / client responsibilities

The server is in charge of

  • placing the nodes randomly on the screen at startup
  • allocating the points and the risks to the nodes
  • determining if a node compromission was detected by randomly using the associated risk
  • calculating the number of points for each player
  • associating a node to the latest player who compromised it

The client is in charge of

  • blocking user interaction while a compromission is in progress
  • forbidding a user from attempting to take over a node for which there is not enough points
  • calculate the risk and the time required to compromised a node based on the risk information and the fact that the last node compromission has been detected (which makes it easier to compromise) or not.

There is no security model and it is trivial to make a client that will change the rules.