Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Testing, tracing and debugging in Project Hoshimi

0.00/5 (No votes)
11 May 2007 1  
Learn how to trace and debug your Project Hoshimi program with Visual Studio
Testing, tracing and debugging in Project Hoshimi

Introduction

Project Hoshimi is a part of the Imagine Cup challenge. Imagine Cup is the world's premier technical competition for students. In 2006, more than 65,000 students from 100 countries participated, leading the competition to be dubbed the "software development Olympics".

In Project Hoshimi, you will have to create a strategy for a team of virtual "nano bots". They move inside a map (representing a part of the human body) and they score points by doing some actions (such as collecting AZN molecules). Then, your team will have to fight against other teams, on given maps. Like in a video game, you can watch the games using a 2D or 3D viewer. The difference is that you cannot interact with your bots during a game. You have to develop the whole behavior of your bots before you launch the game.

You can download the Project Hoshimi SDK here: http://www.project-hoshimi.com/downloads.aspx.

Abstract

In Project Hoshimi, debugging is very important. First of all, if your program throws any uncaught exception, your nanobots will stop taking orders, and will automatically get stuck. So you have to be very meticulous about null references, index out of bounds...

Secondly, you may use very complex algorithms in your AI program. Since the only output of Project Hoshimi is a viewer program, it is very hard to check that everything is going well in your program.

In this article, I will give you some advices to make debugging and tracing much more easy with Project Hoshimi.

Setting up Visual Studio

The first thing to do is to set up Visual Studio to launch automatically Project Hoshimi after building your DLL.

Setting up Visual Studio

Open the properties dialog of your project. Then, set the output directory to the players folder of the Project Hoshimi directory. Thus, the DLL file will automatically be copied in the players folder after being built.

Next, you have to setup Visual Studio to launch Project Hoshimi. If you are not using Visual Studio Express Edition, the following will work:

Setting up Visual Studio

In the project properties, go to the Debug tab, and select "Start external program" as the start action, and select the path of the ProjectHoshimi.exe file. Then set the "start working directory" to the Project Hoshimi folder (the one that contains ProjectHoshimi.exe). This will prevent you from being asked for your user name each time you launch the Project Hoshimi application.

If you are using Visual Studio Express Edition, you have to edit the *.csproj.usr file and paste this inside:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <StartAction>Program</StartAction>
    <StartProgram>Path to ProjectHoshimi.exe</StartProgram>
    <StartWorkingDirectory>ProjectHoshimi directory</StartWorkingDirectory>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <StartAction>Program</StartAction>
    <StartProgram>Path to ProjectHoshimi.exe</StartProgram>
    <StartWorkingDirectory>ProjectHoshimi directory</StartWorkingDirectory>
  </PropertyGroup>
</Project>

Replace "Path to ProjectHoshimi.exe" by the ProjectHoshimi.exe path, and "ProjectHoshimi directory" by the directory where ProjectHoshimi.exe is.

Tracing

It is very important to know what is happening during the execution of your AI program. Project Hoshimi features a log system but it is not very convenient. I will now explain how to create a log system easier to use.

First, add this using directive:

using System.Diagnostics;

Then, add this InitLogger static function :

[Conditional("DEBUG")]
public void InitLogger()
{
  Debug.Listeners.Clear();
  Debug.Listeners.Add(new DefaultTraceListener());
  Debug.Listeners.Add(new TextWriterTraceListener("log " +
    DateTime.Now.ToString().Replace(':', '.').Replace('/', '-') + ".txt"));
  Debug.AutoFlush = true;
}

Call it in the constructor of your Player class. Now, you can use the Debug.WriteLine static method to log text in the defined trace listeners. Here, I have 2 listeners:

  • DefaultTraceListener write the text logged in the Output Window of Visual Studio
  • TextWriterTraceListener write the text logged inside a text file

Try from anywhere in your program:

Debug.WriteLine("Hello world");

Look for a file in the directory of Project Hoshimi with the format "log 30-04-2007 15.31.25.txt". Open it, you should see "Hello world".

You can choose the trace listeners you want to use. The DefaultTraceListener can slow down you program when running with Visual Studio. The TextWriterTraceListener involves few performances loss, and allow you to keep your logs.

The calls of the methods of the Debug class will only be included in the compiled file if the DEBUG compilation flag is set. It is set by default in the Debug configuration, and not set in the Release configuration. So when you will compile the final version of your DLL, just set the current configuration to Release and there will remain no File IO access.

Now, let's add a small function that automatically adds the turn number to the log file:

[Conditional("DEBUG")]
public void LogData(string text)
{
  Debug.WriteLine("[" + this.CurrentTurn.ToString() + "] " + text);
}

This method cannot be static because it uses the CurrentTurn property of the Player object. So you need an instance of the Player object to call it.

This is an example of the output window if you use this function:

Output window

Debugging

Sometimes, in you program, you may have to check that everything is running well. In order to notify an incorrect execution of your program, you have several options. You can return an incorrect value from a function or throw an exception. In this article, we are going to use Debugger.Break(). This will cause the execution of the program to break, like if there were a breakpoint. Of course, when running outside of Visual Studio, your DLL will not break.

Let's write the next functions:

[DebuggerHidden]
[Conditional("DEBUG")]
public static void Assert(bool condition, string description)
{
  if (!condition)
  {
    Debug.WriteLine("Assertion has failed");
    if (description != null && description != "")
      Debug.WriteLine(description);
    Debugger.Break();
  }
}
[DebuggerHidden]
[Conditional("DEBUG")]
public static void Assert(bool condition)
{
  Assert(condition, "");
}

Let's assume that in some part of your program, an integer variable must be positive or null. You can use this Assert function to ensure it is not:

Assert(i >= 0, "i should not be negative");

In Debug mode, when i is positive, this line will be transparent and when i is negative, the debugger will stop, and you will have access to the values of all local variables through Visual Studio, facilitating debugging. Besides, you will be able to check the call stack.

Assertion failing

In Release mode, this line of code won't even be compiled (because of the [Conditional("DEBUG")] attribute), so you won't have any performance loss. Additionally, this function can write a message in the log.

Exceptions

If your program raises an uncaught exception, the remaining code will not be executed and you bots won't do anything during this turn. It is very important to avoid raising uncaught exceptions.

First, open in the Debugging / Exceptions dialog of Visual Studio. Make sure to check all the CLR Exceptions.

Exceptions configuration

During development, I advice you not to use try / catch statements, because your program will stop on any exception risen, and you will be able to debug. For the final version of your program, it can be a good idea to add some try / catch statements to protect your program. But remember that this can slow down your program.

Conclusion

Now, you should be able to debug properly your program. A good way to test your program is to use PHAutomate to play automatically several games on several maps. Then you can study scores and log files to search for an abnormal behavior.

Good luck!

History

This article was published on May 11th, 2007.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here