Temple of The Roguelike Forums

Development => Programming => Topic started by: tuturto on May 09, 2012, 11:28:26 AM

Title: Debugging and other helpful things
Post by: tuturto on May 09, 2012, 11:28:26 AM
What kind of systems/things are you using for helping in development? Things like profilers, debuggers, debuggin consoles within the game and so on? How do you like them and is there something that you feel could be done better?

Personally, I have two things that I use a lot. One is extensive debug log that is written if the game is started with specific command line switch. It uses aspects to log most of the method calls, their parameters and return values. In case of exception, exception is logged too. I like it because there usually is enough information to see how the program is running and where the problem might be. I also don't have to write separate calls to logging system, but it's handled more or less behind the scenes. Drawback is that the log can get big quite fast and finding information in it can be slow.

Second tool that I'm using is a debug server. There's small webserver running inside of the game and I can use it to inspect state of the game. Currently I can only view player character and map, but later I'm going to implement more functionality in it. Maybe things like spawning specific items or monsters to help in testing.

Very rarely I resort to debugging code. I think I have done that only in handful of cases, where I couldn't otherwise solve the problem. Profiling I haven't done much either, only to check occasionally that there isn't obvious bottlenecks where there shouldn't be any.
Title: Re: Debugging and other helpful things
Post by: kraflab on May 09, 2012, 05:20:36 PM
I don't often have a need to use a real debugger.  For me, I just carpet-bomb print statements around the problem to figure out what is going wrong.
Title: Re: Debugging and other helpful things
Post by: NON on May 09, 2012, 05:51:33 PM
I used to have a ton of console printouts in my code everywhere. Then I realized just running in debug mode in Code::blocks or similar does a better job. So I removed all the cout stuff for much neater code.

If the game crashes I just check the call stack. If the game is stuck in a loop, I can find out where by setting breakpoints.

For particularly frustrating things (like building the map generator), it's extremely helpful to be able to set breakpoints and look at function variable values.

Profilers are pretty much necessary for optimizing (but I haven't done that in a long time, since the game runs good enough).
Title: Re: Debugging and other helpful things
Post by: TheCreator on May 09, 2012, 07:05:30 PM
I don't use logs. I think I have enough of them in my job :). When the game crashes, it's the best when debugger breaks the execution, so you can debug immediately. Logs are only useful when someone else is testing and they accidentally find a bug (but crash dumps are still better). However, when you need to debug the initialization stage, a log (or a console window) is very helpful.

Profilers are piceless when you suddenly discover that your game slows down and you cannot find the cause. It's amazing that the results from a profiler are almost always totally different than your first guess.

I don't often have a need to use a real debugger.  For me, I just carpet-bomb print statements around the problem to figure out what is going wrong.

That's exactly what I've been doing in the old times when I had no real IDE with working debugger and I'm really glad that those old times are gone. Not many things are more frustrating than having to modify your code to see what's wrong with it :).
Title: Re: Debugging and other helpful things
Post by: Z on May 09, 2012, 08:00:37 PM
I have started more serious programming in an integrated debugging environment, and then started programming in gcc, without using IDEs. I had to learn how to effectively debug with print statements, and now I don't want to go back to using IDEs.

One good thing about this method is that it is always readily available. I develop in many different languages (some created by myself), for many different platforms (remote servers, mobile devices), and this method always works. After getting skilled in it, it is just faster to use it than to learn the debugger for each of these situations (in some cases the debugger might not even exist). It is hard for me to see how a debugger helps with some bugs (for example, when I have no idea about the precise condition in a function called 1000000 times which leads to some bad behavior which is also hard to describe, and when it happens, I would like to see the history which led to it), and the print method is more useful there.
Title: Re: Debugging and other helpful things
Post by: Ancient on May 10, 2012, 05:42:01 PM
Not using IDE here. A plain editor to color my code is enough. I use two things to help me catch bugs: log file and core dumps. First is just prinfs redirected to physical file. The other is really useful too. Whenever my program falls into infinite loop I can kill it provoking core dump and examine it to know which loop was it and what was the call stack and see state of variables at the time. It is very useful when for some reason game crashes during playing. I can examine the core dump and know why it happened. For errors that do not kill the program there is log file. On the other hand I litter the code with assertions to crash the thing when something goes wrong.
Title: Re: Debugging and other helpful things
Post by: Krice on May 11, 2012, 09:39:29 PM
I'm using in-game debug messages, not to track real bugs but to see what the game engine is doing at the moment. It's showing if something fails in dungeon generator etc.

I don't need debugger often, because I have learned how to write consistent code in C++ without producing the usual C/C++ bugs (buffer overruns, pointer problems). However should something happen it's usually quite easy to find with VC debugger.
Title: Re: Debugging and other helpful things
Post by: ant on May 12, 2012, 12:55:43 AM
hello,

  because i have rog-o-matic talking to rogue i use
gdb to attach to the running processes if i need to
see the stepping.

  as i am learning how to use gdb now there are things
i will get better at (like figuring out how to tell it i
really don't want to see system call stuff at the moment).

  other times it is by adding more print statements (
below line 24 :) ).  for debugging the message parsing
i used a few lines and then added a few more lines for
figuring out a pack corruption bug...  now i'm onto trying
to track down a screen artifact problem...  :)  great fun...
:)

  my C is rusty, but i can figure most things out given
enough time, patience and rainy days.
Title: Re: Debugging and other helpful things
Post by: XLambda on May 12, 2012, 09:53:31 AM
I mostly use jdb when debugging things that aren't obvious. If that doesn't help, print is your friend.

"The most effective debugging tool is still careful thought, coupled with judiciously placed print statements."
Brian Kernighan, "Unix for Beginners" (1979)
Title: Re: Debugging and other helpful things
Post by: purestrain on May 13, 2012, 12:05:08 PM
I'm mostly using logs and unit/integration-tests. Of course sometimes i have to change the tests since gameplay changes.
Title: Re: Debugging and other helpful things
Post by: Kyzrati on May 14, 2012, 02:01:45 AM
Mostly an abundance of assertions, even sometimes for conditions which seem impossible, since you can always turn them off.

Logging system with multiple levels of error messages (also controlled through assertions).

VS debugger breaks and watches for exploring values saves a lot of time.

If there's some repeatable but totally unexplainable hard crash that could be coming from anywhere (usually NULL ptr dereference) and the VS debugger is totally confused (it can't usually give you a reliable call stack trace for these) run a memory profiler.

Occasional code insertions to force special situations for testing when something's acting funny.

Most vital: An AI that can mimic the user and be run indefinitely to test the program automatically.

Speed profiling only much later when the program actually seems slow enough to require optimization.
Title: Re: Debugging and other helpful things
Post by: tuturto on May 14, 2012, 06:29:07 PM
Most vital: An AI that can mimic the user and be run indefinitely to test the program automatically.

Interesting. You have full game running and the AI is playing it? Or specific scenarios that it replays over and over again? How do you handle asserting that the game is behaving as it is expected?

I'm building my system with test driven development and recently started tinkering with doctest (sort of unit testing the documentation), but really high level stuff I'm lacking. Like move from room to room, while opening the door in between and falling into trap stuff. Would be interesting to try that too.
Title: Re: Debugging and other helpful things
Post by: Kyzrati on May 15, 2012, 01:17:24 AM
You have full game running and the AI is playing it?
Exactly. Program an AI to play the game like you would. It's useful not only because it catches bugs, but there's a lot of overlap between that AI and what you can use to run enemies. It takes a fair amount of extra time, but it's worth it because then you don't have to do as much playtesting yourself, and can find any strange errors that players/playtesters would find which you would then have to decipher (more easily done on the dev machine, obviously). Even rare errors, which may repeat only once in 1000, or even 10000, runs, aren't too much trouble for a computer to find. Just have it loop through plays, forever...

Plus it's fun ;)

How do you handle asserting that the game is behaving as it is expected?
Watch it play! If it does stupid things, well, that's a problem to fix, too!

When going for a huge number of runs, the ability to completely turn off rendering/animation is also useful to get the game running far faster, if you're just testing the logic.
Title: Re: Debugging and other helpful things
Post by: ant on May 16, 2012, 05:23:06 AM
Another very helpful feature is to be able to toggle the random number
generation to be simple or noisy.

For those situations where you get a rare event in combination that
only happens at deeper levels it can save a lot of time when trying
out a fix if you can replay the altered code with the starting
condition of the original version that errored...
Title: Re: Debugging and other helpful things
Post by: Krice on May 16, 2012, 06:45:14 AM
Most vital: An AI that can mimic the user and be run indefinitely to test the program automatically.

Isn't that kind of hard to do? Sounds like that, an AI close to human player.
Title: Re: Debugging and other helpful things
Post by: Kyzrati on May 16, 2012, 03:23:07 PM
Most vital: An AI that can mimic the user and be run indefinitely to test the program automatically.
Isn't that kind of hard to do?
Most certainly. I could've added that bit, but it seems obvious ;D It's only something to do if you love working with AI, and have lots and lots of free time... If anything, you can always write a simple AI that at least plays your own game using completely randomized decision-making, and run it in a loop. It works pretty well and isn't that hard; though the precise difficulty would be a function of the depth of your game, starting it early and expanding it as each new feature is added is actually quite trivial. Just have to be religious about updating it, otherwise it's not nearly as useful once the game reaches beyond its scope.

Another very helpful feature is to be able to toggle the random number
generation to be simple or noisy.
Or just reuse the same seed, if the system is automated to begin with. (Another advantage of AI-driven playtesting!)
Title: Re: Debugging and other helpful things
Post by: ant on May 16, 2012, 09:28:02 PM
Quote from: Kyzrati link=topic=2362.msg18423#msg18423 date=133718178
[quote author=ant link=topic=2362.msg18401#msg18401 date=1337145786
Another very helpful feature is to be able to toggle the random number
generation to be simple or noisy.
Or just reuse the same seed, if the system is automated to begin with. (Another advantage of AI-driven playtesting!)
[/quote]

  For the code I'm currently messing with I can do that, but it
still has enough things going on in the code to generate more
random numbers that it still will not reliably reproduce the
error/event I'm after.  What I need to do is to go in there and
find all the random noise making and put a flag around them
to turn them off for testing.

  Like it has been said though it is fun to watch even a weak
AI attempt to beat a game.  Running it in a loop, catching the
logs and looking for error messages is a great way to exercise
the code and it can also come up with combinations of events
that might not have been originally considered in the game
design.

  Another helpful feature on that front is a random command
sequence generator to feed as input so that you can test the
command interface to handle garbage input gracefully.
Title: Re: Debugging and other helpful things
Post by: tuturto on May 17, 2012, 11:30:31 AM
Really nice ideas there. I have to try that AI bot thing at somepoint and see what I need to get it up and running. What kind of interface do you have for it Kyzrati? Like, is the bot running inside the game and interfacing it directly or do you have it as an external program that connects to the game in order to play it?

I guess I could expand my debug server to serve json or something equally simple that could describe what the bot sees and then accepts commands from it that it executes. I think it should be fast enough for turn based game like this.

I'm mostly using the random number generator created in the beginning of the program, but I think there are still some places where a new one is instantiated. This makes the game non-deterministic, since current system time is used as seed. I'm slowly removing those from the code though, so after that I can try out running games with same seed.
Title: Re: Debugging and other helpful things
Post by: Kyzrati on May 17, 2012, 02:43:11 PM
What kind of interface do you have for it Kyzrati? Like, is the bot running inside the game and interfacing it directly or do you have it as an external program that connects to the game in order to play it?
I create them as part of the game, using the same class that the player controls, so the game doesn't necessarily have to even know the difference. In previous games I've gone so far as to have both the player and the AI use the exact same command system to interface with the logic, but in my current project they're not completely the same since I found that a bit cumbersome and limiting in some situations. Also, after spending years working on AI, I've more recently gotten a bit lazy about making sure it covers absolutely everything so I can put more effort into game design instead.

I'm mostly using the random number generator created in the beginning of the program, but I think there are still some places where a new one is instantiated. This makes the game non-deterministic, since current system time is used as seed. I'm slowly removing those from the code though, so after that I can try out running games with same seed.
Even after you make sure everything's centralized, you can still use the system time, of course; just make sure the save the seed it results in each time in case you need it/them again.
Title: Re: Debugging and other helpful things
Post by: purestrain on June 01, 2012, 10:29:28 AM
Um... is there really a reason to write a human-like AI instead of passing some predefined actions to the player controller in a specific a scenario?

Once you change a single part of the AI to match for a specific solution you can't guarantee that all other cases are not touched - but that is just my opinion.

i prefer the following:

Code: [Select]
@Test
public void shouldTriggerIfPlayerStartsThereButMovesBackAndForth() {
Game testGame = Game.newGame(database, new GameBuilderTestImplementation(false, 0));

Entity player = testGame.getPlayer();
CustomController controller = new CustomController();
controller.addAction(new IdleAction());
controller.addAction(new MoveAction(-1, 0));
controller.addAction(new MoveAction(1, 0));
                controller.addAction(new OpenDoorAction(1, 0));

player.setController(controller);

LocationTrigger toAdd = new LocationTrigger(testGame);
toAdd.setLocation(new Point(2, 1));
toAdd.setActivateCallback(new ActivateCallbackImplementation());
testGame.getCurrentZone().addTrigger(toAdd);

testGame.getLoop().rebuild();
while (testGame.step())
;

Assert.assertEquals(true, wasTriggered);
}
Title: Re: Debugging and other helpful things
Post by: Kyzrati on June 01, 2012, 11:57:07 AM
Other than the benefit of being able to use it as an opponent, using it to test and debug is going to give you a lot more coverage than feeding specific actions. I'm not referring simply to code coverage here, but situation coverage.

Testing basic actions like moving and opening doors is not what it's for--it's for highly complex games (like expansive RLs) with a huge array of interconnected systems where there are more or less an infinite number of possibilities, any of which could, under special circumstances, combine to create a unique situation that code was never intended to deal with. It could be very difficult to find some hypothetical emergent bug that only occurs when an entity under the effect of a certain spell is hit by the special effect caused by a certain weapon carried only by a certain enemy, or even some other situation which could require an even greater depth of specialization. Using an AI on this kind of game can save a lot of testing time. Obviously if you can foresee every possibility then an AI would be unnecessary, yes, but once you start adding system upon system to a complex game with development spanning over many years, I'd wager it's just about impossible to predict everything.
Title: Re: Debugging and other helpful things
Post by: tuturto on June 02, 2012, 07:37:55 AM
I think both ways have their merits. More than often it's good to have full control of what actions are taken during test, while sometimes (especially when testing how AI behaves), it is useful to give it a free reign.

Watching AI to play the game can be interesting, but I personally probably wouldn't use it to test the game. I like my tests small, fast and running continuously when I code. But I could probably use it to learn more about the game and how different AIs react to each other and observing if there are subtle bugs that tests don't cover yet (and then make sure that there is test for that subtle bug too when one is found).

I have been playing around on idea of writing some high level helpers for testing and especially for cases when I'm defining how things interact on a high level (ie. get hit by a monster, your hit points should go down, drop a fireball on top of potions, potions should boil and explode). Intent of following test is probably easy enough to understand, even if one reading it hasn't done much (if at all) programming:

Code: [Select]
def test_that_hitting_reduces_hit_points(self):
        """
        Getting hit should reduce hit points
        """
        Pete = strong(Adventurer())
        Uglak = weak(Goblin())
        level = Level()

        place(Uglak, middle_of(level))
        place(Pete, right_of(Uglak))

        make(Uglak, hit(Pete))

        assert_that(Pete, has_less_hit_points())

This is of course a lot simple case than what purestrain showed. I don't have game loop running (since I'm doing a single action). Eventually I need to figure out how to test those things too (making multiple actions and maybe having multiple characters to act even). Having queues of actions could be one solution for this.
Title: Re: Debugging and other helpful things
Post by: Kyzrati on June 02, 2012, 07:50:27 AM
I think both ways have their merits. More than often it's good to have full control of what actions are taken during test
Agreed, though personally I like to do the simple tests manually rather than automate them. This is made much easier by being able to take control of any entity at any time. So even if you're happily playing along in a normal game and something doesn't quite look right, just switch over control and check it out.
Title: Re: Debugging and other helpful things
Post by: tuturto on August 25, 2012, 07:21:45 AM
Returning to an old thread..

I have been playing around with some tools and libraries again and found two that I like.

First is behave, small tool/library for behaviour driven development. It allows me to write tests with almost natural language that is much easier for non-programmers to read. Below is two simple tests/specifications:

Code: [Select]
Feature: Combat
  as an character
  in order to kill enemies
  I want to damage my enemies

  Scenario: hit in unarmed combat
     Given Pete is Adventurer
       And Uglak is Goblin
       And Uglak is standing in room
       And Pete is standing next to Uglak     
      When Uglak hits Pete
      Then Pete should have less hitpoints

  Scenario: hit in melee combat
     Given Pete is Adventurer
       And Uglak is Goblin
       And Uglak wields dagger
       And Uglak is standing in room
       And Pete is standing next to Uglak     
      When Uglak hits Pete
      Then Pete should have less hitpoints

Output:

Code: [Select]
1 features passed, 0 failed, 0 skipped
2 scenarios passed, 0 failed, 0 skipped
13 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.0s

If I were to work with something more complex than roguelike and had a team of programmers and non-programmers, this could be really useful tool. Now it's fun tool to play around and experiment.

Another one I tried briefly is quickcheck. It allows me to wrap test functions and feed random test data into them:

Code: [Select]
    @forall(tries = 5,
            loc_x = integers(low = 1, high = 19),
            loc_y = integers(low = 1, high = 19))
    def test_dropped_item_added_to_correct_location(self, loc_x, loc_y):
        """
        Test that dropped item is added to correct location
        """
        self.character.location = (loc_x, loc_y)
        self.item.level = None
        self.item.location = (0, 0)
        self.character.inventory = [self.item]

        self.character.drop_item(self.item,
                                 self.action_factory)

        assert_that(self.item.location,
                    is_(equal_to(self.character.location)))

Nose (test framework I'm using) detects that function automatically based on its name and executes it. It doesn't know however, that it has been wrapped with @forall decorator that causes the test to be run 5 times, with random data for loc_x and loc_y parameters. This can be useful if you suspect that the function might be working differently with different parameters. Because of the way quickcheck is written, it can even made to generate random complex objects for testing purposes.
Title: Re: Debugging and other helpful things
Post by: purestrain on August 28, 2012, 06:11:05 PM
Woot; thanks. I'll try that out too (JBehave) - Already heard about BDD, but never took a further look at it until now.
Title: Re: Debugging and other helpful things
Post by: tuturto on September 01, 2012, 01:13:24 PM
What I like about using behave is that it lets met to separate things I'm working to two levels: long term goals and immediate goals. If I'm adding a new feature to the game, I usually try to express it as a behave specification/test. Then I can start working towards that and keep adding unit tests as I go. I don't mind if I have failing test written with behave, but I mind if I have a failing unit test (since it prevents me from commiting my changes to version control).

Let us know how you feel about using JBehave. I haven't used that one, but it looks really similar to behave (even more than SpecFlow for example).
Title: Re: Debugging and other helpful things
Post by: tuturto on November 18, 2012, 09:14:34 AM
I have been playing around with the interface and testing recently. I'm not doing any checks for layout or aesthetics, since those can be done by humans much more better than by computer (at least if I'm the one coding). But I figured out neat way to check if the correct information is shown to player and if basic functionality of a dialog is working.

Following snippet creates a character, who has cure minor wounds spell cast on him (that heals player slowly over couple of turns). It then creates a widget (control) that can show player's stats, spells being among them. Last two lines checks that there are two strings present at the dialog: name of the spell and short description.

It doesn't matter where those two strings are present, as long as they are there. This is just a quick check that the dialog can show the information to player. Human can then do the more complex testing if required.

Code: [Select]
def test_displaying_effects(self):
    """
    Displaying character should show effects
    """
    character = (CharacterBuilder()
                            .with_body(5)
                            .with_finesse(6)
                            .with_mind(7)
                            .with_effect(EffectBuilder()
                                                    .with_title('Cure minor wounds')
                                                    .with_description('Cures small amount of damage')
                                            )
                            .build())

    surface_manager = mock()
    when(surface_manager).get_icon(any()).thenReturn(QPixmap())

    widget = CharacterWidget(surface_manager = surface_manager,
                                         character = character,
                                         parent = None)

    assert_that(widget, has_label('Cure minor wounds'))
    assert_that(widget, has_label('Cures small amount of damage'))

Second test has a character standing in the same location with a dagger. Test creates inventory widget that shows the player's equipment, inventory and items laying on the ground. It then locates control which has dagger in it and clicks it. Final step is to check that the dagger is no longer laying on the ground.

What I like about the second example is how I don't have to tell exactly where to click, the test can figure it out by itself (within limits, of course). If I were to move things around on the screen, it should still work, as long as the basic idea stays the same.

Code: [Select]
def setup(self):
    """
    Setup test case
    """
    self.application = QApplication([])
    self.surface_manager = mock(SurfaceManager)
    when(self.surface_manager).get_icon(any()).thenReturn(QPixmap())

    self.action_factory = (ActionFactoryBuilder()
                                .with_inventory_factory()
                                .build())
    self.level = (LevelBuilder()
                        .build())
    self.character = (CharacterBuilder()
                            .with_level(self.level)
                            .with_location((5, 5))
                            .build())

def test_picking_up_item(self):
    """
    Test that item can be picked up
    """
    item = (ItemBuilder()
                .with_name('dagger')
                .build())
    self.level.add_item(item, (5, 5))

    dialog = InventoryDialog(surface_manager = self.surface_manager,
                             character = self.character,
                             action_factory = self.action_factory,
                             parent = None,
                             flags = Qt.Dialog)

    QTest.mouseClick(satin.widget(dialog,
                                  slot_with_item('dagger')),
                     Qt.LeftButton)

    assert_that(self.level, does_not_have_item(item.name))
Title: Re: Debugging and other helpful things
Post by: tuturto on December 12, 2012, 07:55:24 AM
Been playing with new toys again, this time with IPython, which is enchanced interactive Python shell. I have only scratched the surface, but already fell in love with the system.

IPython is really great for prototyping and experimenting with the data. Below I have dump of an interactive console, where I start up part of my game and generate a level. After generating one level, I change some of the parameters and generate a new level to see how they affect the end result. I also coded a whole new room generator interactively and checked while coding what kind of results it produces. Sadly I don't have logs from that at hand.

I didn't get rendering of my levels to work yet, but that shouldn't be too far anymore. Then I could display what the level actually looks in game with tiles and everything, instead of ascii representation.

I had fun playing briefly with this on a browser, which has the added benefit of leaving page that others can view and edit too. Might be interesting to use it for fast prototyping and collaborating with friends.

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.

IPython 0.13.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.
%guiref   -> A brief reference about the graphical user interface.

In [1]: import os.path
   ...: from herculeum.config import Configuration
   ...: from pyherc.data.model import Model
   ...: import sys
   ...: import logging
   ...: import herculeum.config.levels
   ...: import herculeum.gui.resources
   ...:
   ...: from herculeum.gui import MainWindow, HelpProvider
   ...: from PyQt4.QtGui import QApplication
   ...: from PyQt4.QtCore import QFile, QLatin1String, Qt
   ...:

In [2]: qt_app = QApplication([])

In [3]: world = Model()
   ...: config = Configuration('', world, herculeum.config.levels)
   ...: config.initialise()
   ...:
Initialising generators
Generators initialised
Initialising level generators
Level generators initialised
Initialising action sub system
Action sub system initialised

In [4]: level_generator_factory = config.level_generator_factory
   ...: level_generator = level_generator_factory.get_generator('upper crypt')
   ...:
   ...: level = level_generator.generate_level(None)
   ...:

In [5]: level
Out[5]:

#################################################################################
########################################################........#################
########################################################.######.#################
####............#########..*X..##############........*##.######.####.....########
####............#########...........######...............######..........########
####...X........#########......####........##.........##############.....########
#########.###############*.....##################.##################X....########
########..#################.##############........###############################
########.#############......##############.######################################
########.#############.###################.######################################
########.#############.###################.######################################
########....##########........############.........##############################
###########.#################.####################.##############################
########........#.......####...################..*....############.......X.######
########..........#####........################.......############...*.....######
########........############...################.......############........*######
###########.###################################.......################.##########
###########.######################################.##############......##########
###########.######################################.##############.###############
###########.######################################.##############.###############
###########.######################################.##############.###############
#########...###################################....##############.....###########
#########.#####################################.#####################.###########
########...####........##...........#########......##############.........#######
########........######..............#########.....*.....######............#######
########*..##############..X........#########......####........##...*.....#######
########...##################################......##############################
#################################################################################
#################################################################################
#################################################################################
#################################################################################

In [6]: from pyherc.generators.level.partitioners.grid import GridPartitioner
   ...: from random import Random
   ...:
   ...: new_partitioner = GridPartitioner('upper crypt', 2, 2, Random())
   ...:
   ...: level_generator.partitioner = new_partitioner
   ...: new_level = level_generator.generate_level(None)
   ...:

In [7]: new_level
Out[7]:

#################################################################################
#################################################################################
#################################################################################
###################################################........................######
###################################################......................*.######
###################################################........................######
############..........#############################........................######
############..........########..............................X........*.....######
############...................####################......*......X..........######
############..........#############################........................######
############..........#############################.....X..................######
############.....*....#############################........X............*..######
################.################################################################
################...##############################################################
##################.##############################################################
##################.##############################################################
##################...############################################################
####################.############################################################
################..........######...........######################################
################.....*....######.#########.###........................###########
################..........######.#########.###.....X..................###########
################..........######.#########..........................X.###########
################.................#############.....X..................###########
################..........####################*.......................###########
################..........####################........................###########
################..........#######################################################
################..........#######################################################
#################################################################################
#################################################################################
#################################################################################
#################################################################################

In [8]:
Title: Re: Debugging and other helpful things
Post by: MorleyDev on December 12, 2012, 05:27:37 PM
Tests glorious tests. The tricky part is figuring out where the problem is so I can put a unit test around it and fix. If it isn't obvious, Integration tests, debug logging and if all else fails step through. Then it's isolate the parameters that cause the erroneous behaviour with failing unit tests, then fix.

Though none of the existing unit testing or mocking libraries I found in C++ ever felt right or fit my needs and preferred testing style quite right. But I'm growing my own in my latest projects, taking advantage of C++11.
Title: Re: Debugging and other helpful things
Post by: tuturto on December 12, 2012, 09:27:32 PM
Though none of the existing unit testing or mocking libraries I found in C++ ever felt right or fit my needs and preferred testing style quite right. But I'm growing my own in my latest projects, taking advantage of C++11.

Have you had a look at Googletest http://code.google.com/p/googletest/ (http://code.google.com/p/googletest/)? I have heard many good things about it, but haven't personally tried it. It might give ideas if nothing else.

I'm really happy with the testing tools that I have currently in my disposal. I'm mostly using existing tools (nose, nosy, mockito, hamcrest and QTest) and had added just a little bit sugar coating here and there to make things easier to read. Testing C++ is a whole different beast than testing Python code though!
Title: Re: Debugging and other helpful things
Post by: MorleyDev on December 12, 2012, 10:08:12 PM
I tried Google Test, but I like to do a "Given X When Y Then Z" structure with Test Fixtures, where most logic is in the SetUp ("Given X When Y") and the Tests themselves only contain the Assertions ("Then Z"). Well, sometimes the Given is alone and the When and Then get combined, but not often. Not strict BDD, but more inspired by BDD but without the strict requirements.

Google Tests' lack of Suite support made organising that layout tricky and kept me with UnitTest++. I did use Google Mock, but I like to have "Weak" setups of functions with strong verifications after the calls are made and Google Mock didn't support that.

I use C# at work, where we do TDD in this manner using Nunit and Moq which work very well. But C++ doesn't have the kind of reflection that lets Moq work.
Title: Re: Debugging and other helpful things
Post by: tuturto on December 13, 2012, 05:31:17 AM
NUnit combined with Moq is a good toolset. Much nicer to specify mocks on the fly than to code them by hand. Do you happen to have any C++ code with tests online? I have zero experience with that stuff and it would be interesting to see how other languages do things. I might learn something new that way.

I was again playing with IPython and wrote rendering methods for my levels. Here's a console dump: http://tuturto.github.com/pyherc/sketch/ipython.html (http://tuturto.github.com/pyherc/sketch/ipython.html). I had to scale down the final image a bit in order it to fit better on screen.

I realised that since I have more or less the whole game running (save for UI currently), I can poke around the data and experiment with things. I can even add new monsters on the level and trigger their AI and make them to wander around and fight. Might be useful if I ever want to really tinker with AI.
Title: Re: Debugging and other helpful things
Post by: tuturto on January 01, 2013, 05:10:27 AM
Since I can get the program up and running without UI, I started tinkering again with Sphinx  (http://sphinx-doc.org/)and removing duplicate data. I have a page in manual that lists most of the weapons with their pictures. Same data is kept in the game too of course for the game to use. When I change the game, I have to change the manual, which I sometimes may forget.

So, I added two more directives that I can use while writing manual: itemimage and itemdescription. Those link directly back to game and pull some of the data from there, saving me from typing it.

If I type in manual's source:

Code: [Select]
Dagger
======
.. itemimage:: dagger

.. itemdescription:: dagger

I get

Code: [Select]
Dagger

XXX
Light and simple weapon that does not do much damage. Small size allows skilled wielder to do critical damage easily though.

Where XXX is a picture of dagger.

If I want to create a nice little table listing all the weapons that the manual mentions, it is as easy as typing:

Code: [Select]
Weapon tables
=============
.. itemtable::
   :type: weapon

That saves some typing and keeps the manual up to date regarding to items.

Full source of the items page of manual is here: source (http://tuturto.github.com/pyherc/manual/_sources/items.txt) and resulting html-page is here:
result (http://tuturto.github.com/pyherc/manual/items.html)