Program Listing for File game_meteor.c

Return to documentation for file (server/game_events/game_meteor.c)

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "names.h"
#include "handler.h"

static constexpr const float DENSITIES[RES_COUNT] = {
    0.5F, 0.3F, 0.15F, 0.1F, 0.1F, 0.08F, 0.05F,
};

DEBUG_USED
static const char *RES_NAMES[RES_COUNT] = {
    "food", "linemate", "deraumere", "sibur", "mendiane", "phiras", "thystame"
};

static constexpr const double METEOR_PERIODICITY_SEC = 20.0F;

[[gnu::unused]] static
void log_map(server_t *srv)
{
    DEBUG_USED size_t y = 0;
    DEBUG_USED size_t x = 0;

    DEBUG_MSG("=======================MAP========================");
    DEBUG_MSG("Map contents:");
    for (size_t i = 0; i < (uint64_t)(srv->map_height * srv->map_width); i++) {
        y = i / srv->map_width;
        x = i % srv->map_width;
        DEBUG_RAW("(%zu, %zu): ", x, y);
        for (size_t n = 0; n < RES_COUNT; n++)
            DEBUG_RAW("%s: %u%s", RES_NAMES[n], srv->map[y][x].qnts[n],
                (n < RES_COUNT - 1) ? ", " : "");
        DEBUG_RAW_MSG("\n");
    }
    DEBUG_MSG("==================================================");
    DEBUG_MSG("Total items in map:");
    for (size_t n = 0; n < RES_COUNT; n++)
        DEBUG_RAW("%s: %u%s", RES_NAMES[n], srv->total_item_in_map.qnts[n],
            (n < RES_COUNT - 1) ? ", " : "");
    DEBUG_RAW_MSG("\n");
}

static bool meteor_rescedule(server_t *srv, const event_t *event)
{
    uint64_t interval_sec =
        (METEOR_PERIODICITY_SEC * MICROSEC_IN_SEC) / srv->frequency;
    event_t new = {
        .client_idx = event->client_idx,
        .command = { METEOR },
        .timestamp = event->timestamp + interval_sec,
    };

    DEBUG("Meteor incoming in %ld ms",
        (new.timestamp - get_timestamp()) / MILISEC_IN_SEC);
    if (!event_heap_push(&srv->events, &new)) {
        perror("Failed to reschedule meteor event");
        return false;
    }
    return true;
}

bool game_meteor_handler(server_t *srv, const event_t *event)
{
    ssize_t qty_needed = 0;
    size_t x = 0;
    size_t y = 0;

    for (size_t n = 0; n < RES_COUNT; n++) {
        qty_needed = (ssize_t)(srv->map_height * srv->map_width * DENSITIES[n])
            - srv->total_item_in_map.qnts[n];
        DEBUG("meteor: %u %s, missing %ld",
            srv->total_item_in_map.qnts[n], RES_NAMES[n], qty_needed);
        for (ssize_t i = 0; i < qty_needed; i++) {
            x = rand() % srv->map_width;
            y = rand() % srv->map_height;
            srv->map[y][x].qnts[n]++;
            srv->total_item_in_map.qnts[n]++;
        }
    }
    return meteor_rescedule(srv, event);
}