Overview




Welcome to the “Visual Analysis of a Multiplayer Game,” my final project for Harvard’s CS171 and an attempt to gain insights on player behavior in a virtual environment by taking an objective, third-person perspective on the otherwise subjective, first-person experience.

To begin using the Java applet, please click here. Instructions and feature explanations can be found in the Use section of this write-up.


Motivation


My motivation for this project was simple, but not, as you might have guessed, from any inherent love of video games; rather, as a joint-concentrator in Computer Science and the History of Science, I am most interested in the way that people and technology interact—a phenomenon essentially at the heart of the computer gaming industry. Partly out of my own curiosity, partly out of the idea of approaching cultural phenomena like videogames with a fairly scientific methodology, I would simply like to see what these visualizations can tell the layperson both about the game environment and the human player; moreover, I am interested in the value of these conclusions to more avid players, who might benefit from becoming more cognizant of their style of play or their surroundings.

Accordingly, the questions I sought to answer were “What are the types of trends exhibited players of a location-based multiplayer game?” and “How can these trends be used to identify problem areas and analyze the fairness of the environment or identify weaknesses and improve player performance?”


Data




At the heart of the data collection effort is the well-known first-person shooter called Counter-Strike: Source (CS:S). Released by video game developer Valve in October 2004, CS:S has since gained what could easily be described as a cult following, a group of avid players and at-home developers who have used Valve’s own SDK and the underlying Half-Life game engine to release hundreds of add-ons and mods. As not only a fun and popular game but also a powerful development platform, CS:S was an easy choice for this project.

The process from game to visualization involves three essential steps: playing the game, logging all in-game events, and overlaying these events on a map of the level.

In order to change the objective of the game from planting or disarming a bomb to simply eliminating as many players as possible on the opposing team (known as “team deathmatch”), I installed two plug-ins known as Metamod Source and Sourcemod, each of which provided a C++ API and hooks to intercept internal game functions. In addition to these, I installed an add-on known as CS:S Deathmatch, which required both APIs to create a custom deathmatch game for both human and CPU players.



In terms of logging the player events, I first installed EventScripts 2, a C++ and Python-capable server-side event handler, and wrote several scripts which handled events such as weapon_fire, player_footstep, and player_death. During each of these events, I would log all associated player and game data to a file on my computer. Though it fulfilled only a minor role, I also wrote a log parser in Python with the sole purpose of converting the server time format to a custom, time-based id for each event.

Finally, the Java-based Processing visualization loaded these events from the resulting comma-delimited file and dynamically created Player and Event objects to store and represent this data. The beauty of this data collection process is that you can go from playing a game in first-person to visualizing it third-person in less than a minute, which some mere parsing and copy-and-pasting of files.


Design


In designing the visualization, I was faced with the challenge of creating a simple yet intuitive design that would interest the layperson while also displaying all of the data that an avid gamer might want to know. Moreover, since I also wanted the visualization to be an investigative tool, I also needed to create something with a number of different possibilities for what to display and how to encode it. Overall, there are four basic components to the visualization:

CONTROL PANEL: Located to on the far right, the control panel provides a list of parameters (view, map, player, event, color, and timer) and corresponding values (lines, color, all players, footsteps, etc). Clicking on each of these will cycle between the available options and make the accompanying changes on the visualization. At the bottom of the control panel is also a play button that animates character behavior on top of the map.

MAP WINDOW: At the center of the visualization is a map of the level de_inferno, as it was one of the only high-quality map images I could find online. Using the control panel on the right, this map can be changed from color to grayscale, which makes the areas slightly less identifiable but makes the color data points or lines stand out more. Using the control panel, an overlay of lines or points can be statically displayed or dynamically animated over the map, with the locations on the map corresponding to the exact locations in the level. The control panel also allows the user to change the color encodings of the points or lines, from denoting player or team to showing their health at any given point. Finally, mousing over any data point or line will cause all data from other players to become fairly transparent and, using a data highlight, display all player and event information in the data window in the upper left.

DATA WINDOW: When a single point is not being selected, the data window displays the current team and player score at the current position in the game, providing information on kills, deaths, and the valuable kill-death spread (how many more kills than deaths each player has). On the other hand, when a single point is selected, the player’s name, team, health, weapon, and score will appear with next to the appropriate icon from the game. Below this, the type of the event, such as a footstep or fired weapon, and the event’s in-game coordinates are also shown.

TIMELINE: Last but certainly not least, the timeline at the bottom of the screen provides the current position of the animation when the game is being replayed while also defining a window of time to be viewed statically or played dynamically. At any point, the user can click and drag one of the two yellow triangles to define the start or end position, before or after which no data will be displayed. On the far right, a timer displays the in-game time, the time into the current window, or the remaining time, which can be changed from the control panel.

As for the design principles that governed my overall decisions, I wanted to minimize the non-data ink while still making the data exciting and “pop,” hence my choice of a black background. Above all, I wanted to respect the preferences of the user and thus provided numerous options; while I find that viewing data points over a grayscale map is one of the best visualizations in terms of understanding and color principles, I realize that users may want to view something else. Also, I realized that while watching an animated replay of the game was (to me) exciting, it was not necessarily as interesting as something interactive, so I included both. Overall, this visualization allows users to get an overall view of the game, filter by player or event, retrieve specific detail, identify outliers, make comparisons by player or team, and even change the encodings of different variables.



Use


To begin using the Java applet, please click here. First, simply change your preferences in the control panel by clicking on the parameter (such as view or map) or the value (such as points or color). Once you have a display that interests you, you may play an animation of the events using the “play” button or define a window of time to view by clicking and dragging the triangles on the timeline. To get specific details about a single point, simply mouse over it on the map and all related information will appear in the upper left of the screen.


Conclusions


Using this visualization, you can reach several interesting player- and environment-specific conclusions. For example, using the included data set from a real five-person game, you can tell that I (Aaron) have a tendency to double back and thus cover a lot of the same ground rather than reaching new areas of the map; from a player’s perspective, I am always worried about the things behind me that I can’t see, so it’s interesting to see how this tendency to watch my back can be viewed from the data points alone. Moreover, there are numerous areas on the map only frequented by certain players or teams, while others (such as the area at the very top of the map) are not visited at all. The implication that players tend to avoid corners of the level or places where there is only one exit would be of great importance to level designers, and I’d be curious to see if this holds true for other environments. If we view the jumps as data points, the small cluster in the bottom right of the map clearly stands out; from playing this game, I know this location as a place where players often jump from a balcony the ground, but also as a place where it is difficult to jump over the railing and under the roof at the same time. Therefore, it often takes players several attempts to reach the ground, which would sure interest developers, who might try to fix it, or other players, who might take advantage of the large amount of time spent stuck here by their opponents. Ultimately, the visualization reveals a large number of insights about player behavior and the effects of the environment, especially to those who have played the level; in the future, I would be interested to see how those unfamiliar with the level interpret the visualization.


Reflections


In the future, besides simply sharing this with a wider audience, there are several conceivable changes or additions I could make; for example, as the function I have to translate from in-game coordinates to map positions would theoretically work for any and all maps, I would like to dynamically load the map as well, so this visualization would work for theoretically any CS:S environment. In addition, a pause button might be more helpful than just “stop,” and not too difficult to create. I’d also be interested in displaying every player’s look direction during the animation, showing whether the run backwards or strafe for example. Finally, I didn’t really have enough data to display a density map or heat map of player events, but something like this might better explain where the most points are scored.

In retrospect, this was an incredibly enjoyable project. While I spun my wheels at the beginning when I tried to use a console game without an open SDK and was somewhat pressed for time at the end, I really enjoyed every challenge that I faced. Though I was not overly familiar with Counter-Strike before this project, there are few finals, especially at Harvard, for which playing an online video game is a necessary task. Even now, I am still amazed by the dynamism of this visualization, especially since I tend to think of such games as very static creations; that users are able to interface with it to view their performance is incredible to me. Furthermore, many companies charge top dollar for premium memberships that allow players to evaluate their actions and statistics, while this application is relatively powerful and, more importantly, free. The greatest challenges I faced were figuring out how to actually gather this data in the beginning, and, later, how to animate the events; in fact, I spent hours developing functions like animateDataLine() in addition to drawDataLine(), when I realized later that I could simply change the bounds of my time window and literally deleted half of my code. In the end, thank you to those who helped point me in the right direction, those who used and enjoyed this visualization, and those took the time to read this entire write-up.


Add-Ons


Metamod Source 1.7.1
Sourcemod 1.2.0
CS:S Deathmatch 2.1.0
EventScripts 2.0 Public Beta 2