Roguelike Aoc – part 12

In the twelfth lesson of roguelike game tutorial introduces monsters to the mix.

Structure changes and functions definitions

The author introduces Monster struct, which has sense. However, I had to sync it with my code – therefore making small amendment. Instead of separate Position and symbol in the struct I’ve just added Locations to represent a current monster’s location and a previous one (similar to the structure of Player).

typedef struct Monster {
      Location *currentLocation;
      Location *previousLocation;
      int health;
      int attack;
      int speed;
      int defence;
      bool pathfinding;
} Monster;

Along the way I’ve created monster.c file to comply with separation of concerns in the app (don’t forget to add this file to the CMakeLists.txt directives).

As we have to first create rooms, then we should assign monsters to them and later put everything into the Level. In order to do that a couple of additional changes had to be made. First of them was to modify createLevel function:

Level *createLevel(int levelNumber, int numberOfRooms, int numberOfMonsters);

Next, we had to assign rooms returned by roomsSetup function into an actual array (we did not do that up until now). A third thing to do was to write a different implementation for monsters’ creating functions – we do not want to hardcode the number of monsters in it. It will be passed as a level creating parameter. However, I’ve decided to keep (or at least try) to spread the number of monsters among the rooms. To sum everything up – below are the functions to do so.

#define GOBLIN_SIGN "g"
#define SPIDER_SIGN "S"

void createMonsters(Level *level,  Room **rooms)
    int monstersCreated = 0;
    level->monsters = malloc(sizeof(Monster *) * level->numberOfMonsters);

    do {
        for(int i = 0; i < level->numberOfRooms; i++) {
            if((rand() % 2) == 0) {

                Monster *monster = createMonster();
                placeMonsterInTheLevel(monster, *rooms[i]);
                level->monsters[monstersCreated] = monster;

                monstersCreated += 1;
    } while(monstersCreated < level->numberOfMonsters);


void placeMonsterInTheLevel(Monster *monster, Room room)
    Location *currentLocation = malloc(sizeof(struct Location));

    currentLocation->position.x = (rand() % (room.width - 2)) + room.position.x + 1;
    currentLocation->position.y = (rand() % (room.height - 2)) + room.position.y + 1;
    currentLocation->displaySign = FLOOR_SIGN;

    monster->currentLocation = currentLocation;
    monster->previousLocation = currentLocation;

Monster *createMonster(void) {
    if((rand() % 2)) {
        return createMonsterObject(GOBLIN_SIGN, 10, 1, 1, 2, FALSE);
    return createMonsterObject(SPIDER_SIGN, 15, 4, 3, 1, TRUE);

Monster *createMonsterObject(char *displaySign, int health, int attack, int speed, int defence, bool pathfinding) {
    Monster *newMonster = malloc(sizeof(Monster));
    newMonster->displaySign = displaySign;
    newMonster->health = health;
    newMonster->attack = attack;
    newMonster->speed = speed;
    newMonster->defence = defence;
    newMonster->pathfinding = pathfinding;

    return newMonster;

It’s less robust than the author’s code but here we’re not interested in very detailed monsters’ randomisation and creation. We create monsters to simulate movement and (I assume) – fighting. So I’ve just settled on two types of monsters. Actually there was nothing more done in this lesson – I’ve changed some initialization stuff (in level.c file) but that was minor stuff.


Here is the direct link to the GitHub repo.

You Might Also Like

Leave a Reply

Back to top