Exemplo n.º 1
0
TbBool prison_convert_creature_to_skeleton(struct Room *room, struct Thing *thing)
{
    struct Dungeon *dungeon;
    struct CreatureControl *cctrl;
    struct Thing *crthing;
    long crmodel;
    cctrl = creature_control_get_from_thing(thing);
    crmodel = get_room_create_creature_model(room->kind); // That normally returns skeleton breed
    crthing = create_creature(&thing->mappos, crmodel, room->owner);
    if (thing_is_invalid(crthing))
    {
        ERRORLOG("Couldn't create creature %s in prison", creature_code_name(crmodel));
        return false;
    }
    init_creature_level(crthing, cctrl->explevel);
    set_start_state(crthing);
    if (creature_model_bleeds(thing->model))
      create_effect_around_thing(thing, TngEff_Unknown10);
    kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
    dungeon = get_dungeon(room->owner);
    if (!dungeon_invalid(dungeon)) {
        dungeon->lvstats.skeletons_raised++;
    }
    return true;
}
Exemplo n.º 2
0
PerPlayerFlags action_point_get_players_within(long apt_idx)
{
    //return _DK_action_point_get_players_within(apt_idx);
    struct ActionPoint *apt;
    apt = action_point_get(apt_idx);
    PerPlayerFlags activated;
    activated = apt->activated;
    PlayerNumber plyr_idx;
    for (plyr_idx=0; plyr_idx < PLAYERS_COUNT; plyr_idx++)
    {
        struct PlayerInfo *player;
        player = get_player(plyr_idx);
        if (player_exists(player))
        {
            if ((activated & (1 << plyr_idx)) == 0)
            {
                struct Dungeon *dungeon;
                dungeon = get_players_dungeon(player);
                if (dungeon_invalid(dungeon)) {
                    continue;
                }
                SYNCDBG(16,"Checking player %d",(int)plyr_idx);
                if (action_point_is_creature_from_list_within(apt, dungeon->digger_list_start)) {
                    activated |= (1 << plyr_idx);
                    continue;
                }
                if (action_point_is_creature_from_list_within(apt, dungeon->creatr_list_start)) {
                    activated |= (1 << plyr_idx);
                    continue;
                }
            }
        }
    }
    return activated;
}
Exemplo n.º 3
0
long computer_check_for_expand_room(struct Computer2 *comp, struct ComputerCheck * check)
{
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_for_expand_room(comp, check);
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon))
    {
        ERRORLOG("Invalid computer players dungeon");
        return 0;
    }
    long around_start;
    around_start = ACTION_RANDOM(119);
    // Don't work when placing rooms; we could place in an area for room by mistake
    if (is_task_in_progress(comp, CTT_PlaceRoom) || is_task_in_progress(comp, CTT_CheckRoomDug)) {
        SYNCDBG(8,"No rooms expansion - colliding task already in progress");
        return 0;
    }
    if (4 * dungeon->creatures_total_pay / 3 >= dungeon->total_money_owned) {
        SYNCDBG(8,"No rooms expansion - we don't even have money for payday");
        return 0;
    }
    const struct ExpandRooms *expndroom;
    for (expndroom = &expand_rooms[0]; expndroom->rkind != RoK_NONE; expndroom++)
    {
        if (computer_check_for_expand_room_kind(comp, check, expndroom->rkind, expndroom->max_slabs, around_start)) {
            return 1;
        }
    }
    SYNCDBG(8,"No rooms found for expansion");
    return 0;
}
Exemplo n.º 4
0
TbBool placing_offmap_workshop_item(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel)
{
    SYNCDBG(18,"Starting");
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon)) {
        // Player with no dungeon has only on-map items
        // But this shouldn't really happen
        return true;
    }
    switch (tngclass)
    {
    case TCls_Trap:
        if (dungeon->trap_amount_stored[tngmodel] > 0) {
            return false;
        }
        if (dungeon->trap_amount_offmap[tngmodel] > 0) {
            return true;
        }
        break;
    case TCls_Door:
        if (dungeon->door_amount_stored[tngmodel] > 0) {
            return false;
        }
        if (dungeon->door_amount_offmap[tngmodel] > 0) {
            return true;
        }
        break;
    }
    return false;
}
Exemplo n.º 5
0
/**
 * Removes item from the amount of crates stored in workshops.
 * @param owner
 * @param tngclass
 * @param tngmodel
 * @return Gives WrkCrtS_None if no crate was found, WrkCrtS_Offmap if offmap crate was used, WrkCrtS_Stored if crate from workshop was used.
 * @note was named remove_workshop_item()
 */
int remove_workshop_item_from_amount_stored_f(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel, unsigned short flags, const char *func_name)
{
    SYNCDBG(18,"%s: Starting",func_name);
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon_f(plyr_idx,func_name);
    if (dungeon_invalid(dungeon)) {
        ERRORLOG("%s: Can't remove item; player %d has no dungeon.",func_name,(int)plyr_idx);
        return WrkCrtS_None;
    }
    long amount;
    amount = 0;
    switch (tngclass)
    {
    case TCls_Trap:
        if ((flags & WrkCrtF_NoStored) == 0) {
            amount = dungeon->trap_amount_stored[tngmodel];
        }
        if (amount > 0) {
            SYNCDBG(8,"%s: Removing stored trap %s",func_name,trap_code_name(tngmodel));
            dungeon->trap_amount_stored[tngmodel] = amount - 1;
            return WrkCrtS_Stored;
        }
        if ((flags & WrkCrtF_NoOffmap) == 0) {
            amount = dungeon->trap_amount_offmap[tngmodel];
        }
        if (amount > 0) {
            SYNCDBG(8,"%s: Removing offmap trap %s",func_name,trap_code_name(tngmodel));
            dungeon->trap_amount_offmap[tngmodel] = amount - 1;
            return WrkCrtS_Offmap;
        }
        ERRORLOG("%s: Trap %s not available",func_name,trap_code_name(tngmodel));
        break;
    case TCls_Door:
        if ((flags & WrkCrtF_NoStored) == 0) {
            amount = dungeon->door_amount_stored[tngmodel];
        }
        if (amount > 0) {
            SYNCDBG(8,"%s: Removing stored door %s",func_name,door_code_name(tngmodel));
            dungeon->door_amount_stored[tngmodel] = amount - 1;
            return WrkCrtS_Stored;
        }
        if ((flags & WrkCrtF_NoOffmap) == 0) {
            amount = dungeon->door_amount_offmap[tngmodel];
        }
        if (amount > 0) {
            SYNCDBG(8,"%s: Removing offmap door %s",func_name,door_code_name(tngmodel));
            dungeon->door_amount_offmap[tngmodel] = amount - 1;
            return WrkCrtS_Offmap;
        }
        ERRORLOG("%s: Door %s not available",func_name,door_code_name(tngmodel));
        break;
    default:
        ERRORLOG("%s: Can't remove item; illegal item class %d",func_name,(int)tngclass);
        break;
    }
    return WrkCrtS_None;
}
Exemplo n.º 6
0
/** Returns if given dungeon contains a room of given kind.
 *
 * @param dungeon Target dungeon.
 * @param rkind Room kind being checked.
 * @return
 */
TbBool dungeon_has_room(const struct Dungeon *dungeon, RoomKind rkind)
{
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    if ((rkind < 1) || (rkind >= ROOM_TYPES_COUNT)) {
        return false;
    }
    return (dungeon->room_kind[rkind] > 0);
}
Exemplo n.º 7
0
TbBool check_workshop_item_limit_reached(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon))
        return true;
    switch (tngclass)
    {
    case TCls_Trap:
        return (dungeon->trap_amount_stored[tngmodel] >= MANUFACTURED_ITEMS_LIMIT);
    case TCls_Door:
        return (dungeon->door_amount_stored[tngmodel] >= MANUFACTURED_ITEMS_LIMIT);
    }
    return true;
}
Exemplo n.º 8
0
TbBool set_script_flag(PlayerNumber plyr_idx, long flag_id, long value)
{
    struct Dungeon *dungeon;
    if ( (flag_id < 0) || (flag_id >= SCRIPT_FLAGS_COUNT) ) {
        ERRORLOG("Can't set flag; invalid flag id %d.",(int)flag_id);
        return false;
    }
    dungeon = get_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon)) {
        ERRORLOG("Can't set flag; player %d has no dungeon",(int)plyr_idx);
        return false;
    }
    dungeon->script_flags[flag_id] = value;
    return true;
}
Exemplo n.º 9
0
TbBool restart_script_timer(PlayerNumber plyr_idx, long timer_id)
{
    struct Dungeon *dungeon;
    if ( (timer_id < 0) || (timer_id >= TURN_TIMERS_COUNT) ) {
        ERRORLOG("Can't restart timer; invalid timer id %d.",(int)timer_id);
        return false;
    }
    dungeon = get_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon)) {
        ERRORLOG("Can't restart timer; player %d has no dungeon.",(int)plyr_idx);
        return false;
    }
    dungeon->turn_timers[timer_id].state = 1;
    dungeon->turn_timers[timer_id].count = game.play_gameturn;
    return true;
}
Exemplo n.º 10
0
/**
 * Adds item to the amount of crates in workshops, but also to the amount available to be placed.
 * @param owner
 * @param tngclass
 * @param tngmodel
 * @return
 * @note was named add_workshop_item()
 */
TbBool add_workshop_item_to_amounts_f(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel, const char *func_name)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon_f(plyr_idx,func_name);
    if (dungeon_invalid(dungeon)) {
        ERRORLOG("%s: Can't add item; player %d has no dungeon.",func_name,(int)plyr_idx);
        return false;
    }
    switch (tngclass)
    {
    case TCls_Trap:
        SYNCDBG(8,"%s: Adding Trap %s",func_name,trap_code_name(tngmodel));
        dungeon->trap_amount_stored[tngmodel]++;
        dungeon->trap_amount_placeable[tngmodel]++;
        dungeon->trap_build_flags[tngmodel] |= MnfBldF_Built;
        // In case the placeable amount lost it, do a fix
        if (dungeon->trap_amount_placeable[tngmodel] > dungeon->trap_amount_stored[tngmodel]+dungeon->trap_amount_offmap[tngmodel]) {
            WARNLOG("%s: Placeable %s traps amount for player %d was too large; fixed",func_name,trap_code_name(tngmodel),(int)plyr_idx);
            dungeon->trap_amount_placeable[tngmodel] = dungeon->trap_amount_stored[tngmodel]+dungeon->trap_amount_offmap[tngmodel];
        }
        if (dungeon->trap_amount_placeable[tngmodel] < dungeon->trap_amount_offmap[tngmodel]) {
            WARNLOG("%s: Placeable %s traps amount for player %d was too small; fixed",func_name,trap_code_name(tngmodel),(int)plyr_idx);
            dungeon->trap_amount_placeable[tngmodel] = dungeon->trap_amount_offmap[tngmodel];
        }
        break;
    case TCls_Door:
        SYNCDBG(8,"%s: Adding Door %s",func_name,door_code_name(tngmodel));
        dungeon->door_amount_stored[tngmodel]++;
        dungeon->door_amount_placeable[tngmodel]++;
        dungeon->door_build_flags[tngmodel] |= MnfBldF_Built;
        // In case the placeable amount lost it, do a fix
        if (dungeon->door_amount_placeable[tngmodel] > dungeon->door_amount_stored[tngmodel]+dungeon->door_amount_offmap[tngmodel]) {
            WARNLOG("%s: Placeable %s doors amount for player %d was too large; fixed",func_name,door_code_name(tngmodel),(int)plyr_idx);
            dungeon->door_amount_placeable[tngmodel] = dungeon->door_amount_stored[tngmodel]+dungeon->door_amount_offmap[tngmodel];
        }
        if (dungeon->door_amount_placeable[tngmodel] < dungeon->door_amount_offmap[tngmodel]) {
            WARNLOG("%s: Placeable %s doors amount for player %d was too small; fixed",func_name,door_code_name(tngmodel),(int)plyr_idx);
            dungeon->door_amount_placeable[tngmodel] = dungeon->door_amount_offmap[tngmodel];
        }
        break;
    default:
        ERRORLOG("%s: Can't add item; illegal item class %d",func_name,(int)tngclass);
        return false;
    }
    return true;
}
Exemplo n.º 11
0
/**
 * Returns if the trap was at least one built by a player.
 */
TbBool is_trap_built(PlayerNumber plyr_idx, long tngmodel)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    // Check if the player even have a dungeon
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) {
        ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx);
        return false;
    }
    if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Built) != 0) {
        return true;
    }
    return false;
}
Exemplo n.º 12
0
struct Thing *computer_check_creatures_in_dungeon_rooms_of_kind_for_accelerate(struct Computer2 *comp, RoomKind rkind)
{
    struct Dungeon *dungeon;
    struct Room *room;
    struct Thing *thing;
    long i;
    unsigned long k;
    if ((rkind < 1) || (rkind > ROOM_TYPES_COUNT))
    {
        ERRORLOG("Invalid room kind %d",(int)rkind);
        return INVALID_THING;
    }
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon))
    {
        ERRORLOG("Invalid computer players dungeon");
        return INVALID_THING;
    }
    i = dungeon->room_kind[rkind];
    k = 0;
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
          ERRORLOG("Jump to invalid room detected");
          break;
        }
        i = room->next_of_owner;
        // Per-room code
        thing = computer_check_creatures_in_room_for_accelerate(comp, room);
        if (!thing_is_invalid(thing))
            return thing;
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
          ERRORLOG("Infinite loop detected when sweeping rooms list");
          break;
        }
    }
    return INVALID_THING;
}
Exemplo n.º 13
0
TbBool set_door_buildable_and_add_to_amount(PlayerNumber plyr_idx, ThingModel tngmodel, long buildable, long amount)
{
    struct Dungeon *dungeon;
    if ( (tngmodel <= 0) || (tngmodel >= DOOR_TYPES_COUNT) ) {
        ERRORDBG(1,"Can't set door availability; invalid door kind %d.",(int)tngmodel);
        return false;
    }
    dungeon = get_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon)) {
        ERRORDBG(11,"Can't set door availability; player %d has no dungeon.",(int)plyr_idx);
        return false;
    }
    if (buildable)
        dungeon->door_build_flags[tngmodel] |= MnfBldF_Manufacturable;
    dungeon->door_amount_offmap[tngmodel] += amount;
    dungeon->door_amount_placeable[tngmodel] += amount;
    if (amount > 0)
      dungeon->door_build_flags[tngmodel] |= MnfBldF_Built;
    return true;
}
Exemplo n.º 14
0
TbBool set_creature_tendencies(struct PlayerInfo *player, unsigned short tend_type, TbBool val)
{
    struct Dungeon *dungeon;
    dungeon = get_dungeon(player->id_number);
    if (dungeon_invalid(dungeon)) {
        ERRORLOG("Can't set tendency; player %d has no dungeon.",(int)player->id_number);
        return false;
    }
    switch (tend_type)
    {
    case CrTend_Imprison:
        set_flag_byte(&dungeon->creature_tendencies, 0x01, val);
        return true;
    case CrTend_Flee:
        set_flag_byte(&dungeon->creature_tendencies, 0x02, val);
        return true;
    default:
        ERRORLOG("Can't set tendency; bad tendency type %d",(int)tend_type);
        return false;
    }
}
Exemplo n.º 15
0
/**
 * Returns if the trap can be manufactured by a player.
 * Checks only if it's set as buildable in level script.
 * Doesn't check if player has workshop or workforce for the task.
 */
TbBool is_trap_buildable(PlayerNumber plyr_idx, long tngmodel)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    // Check if the player even have a dungeon
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    // Player must have dungeon heart to build anything
    if (!player_has_heart(plyr_idx)) {
        return false;
    }
    if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) {
        ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx);
        return false;
    }
    if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Manufacturable) != 0) {
        return true;
    }
    return false;
}
Exemplo n.º 16
0
/**
 * Returns if the trap can be placed by a player.
 * Checks only if it's available and if the player is 'alive'.
 * Doesn't check if map position is on correct spot.
 */
TbBool is_trap_placeable(PlayerNumber plyr_idx, long tngmodel)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    // Check if the player even have a dungeon
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    // Player must have dungeon heart to place traps
    if (!player_has_heart(plyr_idx)) {
        return false;
    }
    if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) {
        ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx);
        return false;
    }
    if (dungeon->trap_amount_placeable[tngmodel] > 0) {
        return true;
    }
    return false;
}
Exemplo n.º 17
0
/**
 * Returns if the door was at least one built by a player.
 */
TbBool is_door_built(PlayerNumber plyr_idx, long door_idx)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    // Check if the player even have a dungeon
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    // Player must have dungeon heart to build anything
    if (!player_has_heart(plyr_idx)) {
        return false;
    }
    if ((door_idx <= 0) || (door_idx >= DOOR_TYPES_COUNT)) {
        ERRORLOG("Incorrect door %d (player %d)",(int)door_idx, (int)plyr_idx);
        return false;
    }
    if ((dungeon->door_build_flags[door_idx] & MnfBldF_Built) != 0) {
        return true;
    }
    return false;
}
Exemplo n.º 18
0
struct Room *get_opponent_room(struct Computer2 *comp, PlayerNumber plyr_idx)
{
    static const RoomKind opponent_room_kinds[] = {RoK_DUNGHEART, RoK_PRISON, RoK_LIBRARY, RoK_TREASURE};
    struct Dungeon *dungeon;
    struct Room *room;
    dungeon = get_players_num_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon) || (slab_conf.room_types_count < 1)) {
        return INVALID_ROOM;
    }
    int i,n;
    n = opponent_room_kinds[ACTION_RANDOM(sizeof(opponent_room_kinds)/sizeof(opponent_room_kinds[0]))];
    for (i=0; i < slab_conf.room_types_count; i++)
    {
        room = room_get(dungeon->room_kind[n]);
        if (room_exists(room)) {
            return room;
        }
        n = (n + 1) % slab_conf.room_types_count;
    }
    return INVALID_ROOM;
}
Exemplo n.º 19
0
void player_add_offmap_gold(PlayerNumber plyr_idx, GoldAmount value)
{
    if (plyr_idx == game.neutral_player_num) {
        WARNLOG("Cannot give gold to neutral player %d",(int)plyr_idx);
        return;
    }
    struct Dungeon *dungeon;
    // note that we can't get_players_num_dungeon() because players
    // may be uninitialized yet when this is called.
    dungeon = get_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon)) {
        WARNLOG("Cannot give gold player %d with no dungeon",(int)plyr_idx);
        return;
    }
    // If we're removing gold instead of adding, make sure we won't remove too much
    if ((value < 0) && (dungeon->offmap_money_owned < -value)) {
        value = -dungeon->offmap_money_owned;
    }
    dungeon->offmap_money_owned += value;
    dungeon->total_money_owned += value;
}
Exemplo n.º 20
0
/**
 * Removes item from the amount available to be placed on map.
 * @param owner
 * @param tngclass
 * @param tngmodel
 * @return
 */
TbBool remove_workshop_item_from_amount_placeable_f(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel, const char *func_name)
{
    SYNCDBG(18,"%s: Starting",func_name);
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon_f(plyr_idx,func_name);
    if (dungeon_invalid(dungeon)) {
        ERRORLOG("%s: Can't remove item; player %d has no dungeon.",func_name,(int)plyr_idx);
        return false;
    }
    long amount;
    switch (tngclass)
    {
    case TCls_Trap:
        amount = dungeon->trap_amount_placeable[tngmodel];
        if (amount <= 0) {
            ERRORLOG("%s: Trap %s not available",func_name,trap_code_name(tngmodel));
            break;
        }
        SYNCDBG(8,"%s: Removing Trap %s",func_name,trap_code_name(tngmodel));
        dungeon->trap_amount_placeable[tngmodel] = amount - 1;
        dungeon->trap_build_flags[tngmodel] |= MnfBldF_Used;
        dungeon->lvstats.traps_used++;
        return true;
    case TCls_Door:
        amount = dungeon->door_amount_placeable[tngmodel];
        if (amount <= 0) {
            ERRORLOG("%s: Door %s not available",func_name,door_code_name(tngmodel));
            break;
        }
        SYNCDBG(8,"%s: Removing Door %s",func_name,door_code_name(tngmodel));
        dungeon->door_amount_placeable[tngmodel] = amount - 1;
        dungeon->door_build_flags[tngmodel] |= MnfBldF_Used;
        dungeon->lvstats.doors_used++;
        return true;
    default:
        ERRORLOG("%s: Can't remove item; illegal item class %d",func_name,(int)tngclass);
        break;
    }
    return false;
}
Exemplo n.º 21
0
TbBool mark_creature_joined_dungeon(struct Thing *creatng)
{
    if (creatng->owner == game.neutral_player_num) {
        // Neutral player has no dungeon
        return false;
    }
    struct Dungeon *dungeon;
    dungeon = get_dungeon(creatng->owner);
    if (dungeon_invalid(dungeon)) {
        ERRORLOG("Can't mark; player %d has no dungeon",(int)creatng->owner);
        return false;
    }
    if ((dungeon->owned_creatures_of_model[creatng->model] <= 1) && (dungeon->creature_models_joined[creatng->model] <= 0))
    {
        event_create_event(creatng->mappos.x.val, creatng->mappos.y.val, EvKind_NewCreature, creatng->owner, creatng->index);
    }
    if (dungeon->creature_models_joined[creatng->model] < 255)
    {
        dungeon->creature_models_joined[creatng->model]++;
    }
    return true;
}
Exemplo n.º 22
0
/**
 * Counts amount of rooms of specific type owned by specific player.
 * @param plyr_idx The player number. Only specific player number is accepted.
 * @param rkind Room kind to count. Only specific kind is accepted.
 */
long count_player_rooms_of_type(PlayerNumber plyr_idx, RoomKind rkind)
{
    struct Dungeon *dungeon;
    struct Room *room;
    long i;
    unsigned long k;
    // note that we can't get_players_num_dungeon() because players
    // may be uninitialized yet when this is called.
    dungeon = get_dungeon(plyr_idx);
    if (dungeon_invalid(dungeon))
        return 0;
    i = dungeon->room_kind[rkind];
    k = 0;
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
            ERRORLOG("Jump to invalid room detected");
            break;
        }
        i = room->next_of_owner;
        // No Per-room code - we only want count
        SYNCDBG(19,"Player %d has %s at (%d,%d)",(int)plyr_idx, room_code_name(room->kind), (int)room->central_stl_x, (int)room->central_stl_y);
        if (room->owner != plyr_idx) {
            ERRORDBG(3,"Player %d has bad room in %s list; it's really %s index %d owned by player %d",(int)plyr_idx, room_code_name(rkind), room_code_name(room->kind), (int)room->index, (int)room->owner);
            break;
        }
        k++;
        if (k > ROOMS_COUNT)
        {
            ERRORLOG("Infinite loop detected when sweeping rooms list");
            break;
        }
    }
    return k;
}
Exemplo n.º 23
0
long computer_check_for_expand_room(struct Computer2 *comp, struct ComputerCheck * check)
{
	if (is_newdig_enabled(comp))
		return 4;

    SYNCDBG(8,"Starting");
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon) || !player_has_heart(dungeon->owner)) {
        SYNCDBG(7,"Computer players %d dungeon in invalid or has no heart",(int)dungeon->owner);
        return CTaskRet_Unk4;
    }
    long around_start;
    around_start = ACTION_RANDOM(119);
    // Don't work when placing rooms; we could place in an area for room by mistake
    if (is_task_in_progress(comp, CTT_PlaceRoom) || is_task_in_progress(comp, CTT_CheckRoomDug)) {
        SYNCDBG(8,"No rooms expansion - colliding task already in progress");
        return CTaskRet_Unk0;
    }
    if (computer_player_in_emergency_state(comp)) {
        SYNCDBG(8,"No rooms expansion - emergency state");
        return CTaskRet_Unk0;
    }
    if (get_computer_money_less_cost(comp) < dungeon->creatures_total_pay / 3) {
        SYNCDBG(8,"No rooms expansion - not enough money buffer");
        return CTaskRet_Unk0;
    }
    const struct ExpandRooms *expndroom;
    for (expndroom = &expand_rooms[0]; expndroom->rkind != RoK_NONE; expndroom++)
    {
        if (computer_check_for_expand_room_kind(comp, check, expndroom->rkind, expndroom->max_slabs, around_start)) {
            return CTaskRet_Unk1;
        }
    }
    SYNCDBG(8,"No rooms found for expansion");
    return CTaskRet_Unk0;
}
Exemplo n.º 24
0
/**
 * Does a step of researching.
 * Informs if the research cycle should end.
 * @param thing
 */
CrCheckRet process_research_function(struct Thing *creatng)
{
    struct Dungeon *dungeon;
    struct Room *room;
    dungeon = get_dungeon(creatng->owner);
    if (dungeon_invalid(dungeon)) {
        SYNCDBG(9,"The %s index %d cannot work as player %d has no dungeon",
            thing_model_name(creatng), (int)creatng->index, (int)creatng->owner);
        set_start_state(creatng);
        return CrCkRet_Continue;
    }
    if (!creature_can_do_research(creatng)) {
        set_start_state(creatng);
        return CrCkRet_Continue;
    }
    room = get_room_creature_works_in(creatng);
    if ( !room_still_valid_as_type_for_thing(room, RoK_LIBRARY, creatng) ) {
        WARNLOG("Room %s owned by player %d is bad work place for %s index %d owner %d",
            room_code_name(room->kind), (int)room->owner, thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        set_start_state(creatng);
        return CrCkRet_Continue;
    }
    long work_value;
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    work_value = compute_creature_work_value(crstat->research_value*256, room->efficiency, cctrl->explevel);
    work_value = process_work_speed_on_work_value(creatng, work_value);
    SYNCDBG(19,"The %s index %d produced %d research points",thing_model_name(creatng),(int)creatng->index,(int)work_value);
    dungeon->total_research_points += work_value;
    dungeon->research_progress += work_value;
    //TODO CREATURE_JOBS going postal should be possible for all jobs, not only research
    process_job_stress_and_going_postal(creatng, room);
    return CrCkRet_Available;
}
Exemplo n.º 25
0
long computer_check_neutral_places(struct Computer2 *comp, struct ComputerCheck * check)
{
	if (is_newdig_enabled(comp))
		return 4;

    SYNCDBG(8,"Starting");
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon) || !player_has_heart(dungeon->owner)) {
        SYNCDBG(7,"Computer players %d dungeon in invalid or has no heart",(int)dungeon->owner);
        return CTaskRet_Unk4;
    }
    struct OpponentRelation *oprel;
    oprel = &comp->opponent_relations[game.neutral_player_num];
    struct Room *near_room;
    struct Coord3d *near_pos;
    int near_dist;
    near_room = INVALID_ROOM;
    near_dist = LONG_MAX;
    near_pos = &oprel->pos_A[0];
    int i;
    for (i=0; i < COMPUTER_SPARK_POSITIONS_COUNT; i++)
    {
        struct Coord3d *place;
        place = &oprel->pos_A[i];
        if ((place->x.val == 0) || (place->y.val == 0)) {
            continue;
        }
        struct Room *room;
        room = INVALID_ROOM;
        if (computer_finds_nearest_room_to_pos(comp, &room, place))
        {
            MapSubtlDelta dx,dy;
            dx = abs((int)room->central_stl_x - (MapSubtlDelta)place->x.stl.num);
            dy = abs((int)room->central_stl_y - (MapSubtlDelta)place->y.stl.num);
            if (near_dist > dx+dy)
            {
                near_room = room;
                near_pos = place;
                near_dist = dx+dy;
            }
        }
    }
    if (room_is_invalid(near_room)) {
        return CTaskRet_Unk4;
    }
    struct Coord3d endpos;
    struct Coord3d startpos;
    endpos.x.val = near_pos->x.val;
    endpos.y.val = near_pos->y.val;
    endpos.z.val = near_pos->z.val;
    startpos.x.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_x));
    startpos.y.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_y));
    startpos.z.val = subtile_coord(1,0);
    if (!create_task_dig_to_neutral(comp, startpos, endpos)) {
        return CTaskRet_Unk4;
    }
    near_pos->x.val = 0;
    near_pos->y.val = 0;
    near_pos->z.val = 0;
    return CTaskRet_Unk1;
}
Exemplo n.º 26
0
/**
 * Checks if a computer player has not enough imps.
 * @param comp
 * @param check The check structure; param1 is preferred amount of imps, param2 is minimal amount.
 */
long computer_check_no_imps(struct Computer2 *comp, struct ComputerCheck * check)
{
	if (is_newdig_enabled(comp))
	{
		//workaround for interval seeming to be ignored by from my reconfiguration.
		//modern computers can handle interval 1 and interval 200 is awfully passive and easy to kill
		//interval 20 means player-like imp swarms will form while not being excessive
		//consider making configurable again if *properly* reconfiguring to 20 for all levels except easy beginner levels

		if (check->turns_interval > 20)
			check->turns_interval = 20;
		if (check->param2 < 8)
			check->param2 = 8;
	}

    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon) || !player_has_heart(dungeon->owner)) {
        SYNCDBG(7,"Computer players %d dungeon in invalid or has no heart",(int)dungeon->owner);
        return CTaskRet_Unk4;
    }

	long power_price, lowest_price;
	TbBool diggers_are_cheap;
	power_price = compute_power_price(dungeon->owner, PwrK_MKDIGGER, 0);
	lowest_price = compute_lowest_digger_price(dungeon->owner);
	diggers_are_cheap = power_price <= lowest_price;

	//see if we can sacrifice imps to reduce price
	if (gameadd.sacrifice_info.classic_imp_sacrifice)
	{
		SYNCDBG(18, "Imp creation power price: %d, lowest: %d", power_price, lowest_price);

		if (!diggers_are_cheap
			&& dungeon->total_money_owned > power_price //TODO: might need to multiply for safety factor
			&& dungeon_has_room(dungeon, RoK_TEMPLE))
		{
			struct Thing* imp;
			imp = find_imp_for_sacrifice(comp->dungeon);
			if (!thing_is_invalid(imp))
			{
				long dist;
				struct Room* room;
				room = find_room_nearest_to_position(dungeon->owner, RoK_TEMPLE, &imp->mappos, &dist);
				if (!room_is_invalid(room))
				{
					if (create_task_move_creature_to_subtile(comp, imp, room->central_stl_x, room->central_stl_y, CrSt_CreatureSacrifice))
						return CTaskRet_Unk4;
				}
			}
		}
	}

	//regular old imp check after this point
    long controlled_diggers;
	TbBool digging_gems;
	long limit;
	digging_gems = is_digging_any_gems(dungeon);
    controlled_diggers = dungeon->num_active_diggers - count_player_diggers_not_counting_to_total(dungeon->owner);
	//SYNCLOG("controlled diggers of %d = %d, params = %d %d", (int)dungeon->owner, controlled_diggers, check->param1, check->param2);
	limit = check->param1;
	if (digging_gems)
	{
		if (diggers_are_cheap)
			limit = max(limit, 50);
		else
			limit = max(limit, 20);
	}
    if (controlled_diggers >= limit) {
        return CTaskRet_Unk4;
    }
    long able;
	if ((controlled_diggers == 0 || (controlled_diggers < 3 && (digging_gems || diggers_are_cheap))) && is_power_available(dungeon->owner, PwrK_MKDIGGER))
	{
		//ignore payday and everything else, we need at least 3 imp to play the game
		able = dungeon->total_money_owned >= compute_power_price(dungeon->owner, PwrK_MKDIGGER, 0);
		//TODO: recovery could be improved further by looking at length to payday and time it takes to get more money to increase lower bound
	} else if (controlled_diggers >= check->param2 && !digging_gems) {
        // We have less than preferred amount, but higher than minimal; allow building if we've got spare money
        able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 3 + (controlled_diggers - check->param2)/4);
    } else {
        able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 1);
    }
    if (able == CTaskRet_Unk1)
    {
        struct Thing *heartng;
        MapSubtlCoord stl_x, stl_y;
        heartng = get_player_soul_container(dungeon->owner);
        stl_x = heartng->mappos.x.stl.num;
        stl_y = heartng->mappos.y.stl.num;
        if (xy_walkable(stl_x, stl_y, dungeon->owner))
        {
            if (try_game_action(comp, dungeon->owner, GA_UseMkDigger, 0, stl_x, stl_y, 1, 1) > Lb_OK) {
                return CTaskRet_Unk1;
            }
        }
        return CTaskRet_Unk1;
    }
    return CTaskRet_Unk0;
}
Exemplo n.º 27
0
TbBool process_scavenge_creature_from_level(struct Thing *scavtng, struct Thing *calltng, long work_value)
{
    struct Dungeon *calldngn;
    long num_prayers;
    calldngn = get_dungeon(calltng->owner);
    if (dungeon_invalid(calldngn)) {
        ERRORLOG("The %s owner %d can't do scavenging - has no dungeon",thing_model_name(calltng),(int)calltng->owner);
        return false;
    }
    // Compute amount of creatures praying against the scavenge
    if (!is_neutral_thing(scavtng)) {
        struct Dungeon *scavdngn;
        scavdngn = get_dungeon(scavtng->owner);
        num_prayers = scavdngn->creatures_praying[scavtng->model];
    } else {
        num_prayers = 0;
    }
    // Increase scavenging counter, used to break the prayers counter
    calldngn->creatures_scavenging[scavtng->model]++;
    // If scavenge is blocked by prayers, return
    if (calldngn->creatures_scavenging[calltng->model] < 2 * num_prayers) {
        SYNCDBG(8, "Player %d prayers (%d) are blocking player %d scavenging (%d) of %s", (int)scavtng->owner,
            (int)num_prayers, (int)calltng->owner, (int)calldngn->creatures_scavenging[calltng->model], thing_model_name(calltng));
        return false;
    }
    SYNCDBG(18,"The %s index %d scavenges %s index %d",thing_model_name(calltng),(int)calltng->index,thing_model_name(scavtng),(int)scavtng->index);
    // If we're starting to scavenge a new creature, do the switch
    if (calldngn->scavenge_targets[calltng->model] != scavtng->index)
    {
        calldngn->scavenge_turn_points[calltng->model] = work_value;
        if (calldngn->scavenge_targets[calltng->model] > 0)
        {
            // Stop scavenging old creature
            struct Thing *thing;
            thing = thing_get(calldngn->scavenge_targets[calltng->model]);
            if (thing_is_creature(thing) && (thing->model == calltng->model))
            {
                if (creature_is_being_scavenged(thing)) {
                    set_start_state(thing);
                }
            }
        }
        // Start the new scavenging
        calldngn->scavenge_targets[calltng->model] = scavtng->index;
        if (is_my_player_number(scavtng->owner)) {
            output_message(SMsg_CreatureScanvenged, 500, 1);
        }
        event_create_event(scavtng->mappos.x.val, scavtng->mappos.y.val, EvKind_CreatrScavenged, scavtng->owner, scavtng->index);
    } else
    {
        calldngn->scavenge_turn_points[calltng->model] += work_value;
    }
    // Make sure the scavenged creature is in correct state
    if (!creature_is_being_scavenged(scavtng))
    {
        if (!is_neutral_thing(scavtng)) {
            external_set_thing_state(scavtng, CrSt_CreatureBeingScavenged);
        }
    }
    long scavpts;
    scavpts = calculate_correct_creature_scavenge_required(scavtng, calltng->owner);
    if ((scavpts << 8) < calldngn->scavenge_turn_points[calltng->model])
    {
        SYNCDBG(8,"The %s index %d owner %d accumulated enough points to turn to scavenger",thing_model_name(scavtng),(int)scavtng->index,(int)scavtng->owner);
        turn_creature_to_scavenger(scavtng, calltng);
        calldngn->scavenge_turn_points[calltng->model] -= (scavpts << 8);
        return true;
    }
    return false;
}
Exemplo n.º 28
0
/**
 * Updates gameplay score for a dungeon belonging to given player.
 * @return
 */
TbBool update_dungeon_scores_for_player(struct PlayerInfo *player)
{
    struct Dungeon *dungeon;
    int i,k;
    dungeon = get_players_dungeon(player);
    unsigned long manage_efficiency,max_manage_efficiency;
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    manage_efficiency = 0;
    max_manage_efficiency = 0;
    {
        manage_efficiency += 40 * compute_dungeon_rooms_attraction_score(dungeon->room_slabs_count[RoK_ENTRANCE],
            dungeon->field_949, dungeon->field_1485);
        max_manage_efficiency += 40 * compute_dungeon_rooms_attraction_score(LONG_MAX, LONG_MAX, LONG_MAX);
    }
    {
        manage_efficiency += 40 * compute_dungeon_creature_tactics_score(dungeon->battles_won, dungeon->battles_lost,
            dungeon->creatures_scavenge_gain, dungeon->creatures_scavenge_lost);
        max_manage_efficiency += 40 * compute_dungeon_creature_tactics_score(LONG_MAX, LONG_MAX, LONG_MAX, LONG_MAX);
    }
    {
        // Compute amount of different types of rooms built
        unsigned long room_types;
        room_types = 0;
        for (i=0; i < ROOM_TYPES_COUNT; i++)
        {
            if (dungeon->room_slabs_count[i] > 0)
                room_types++;
        }
        manage_efficiency += 40 * compute_dungeon_rooms_variety_score(room_types, dungeon->total_area);
        max_manage_efficiency += 40 * compute_dungeon_rooms_variety_score(ROOM_TYPES_COUNT, LONG_MAX);
    }
    {
        manage_efficiency += compute_dungeon_train_research_manufctr_wealth_score(dungeon->total_experience_creatures_gained,
            dungeon->total_research_points, dungeon->field_1181, dungeon->total_money_owned);
        max_manage_efficiency += compute_dungeon_train_research_manufctr_wealth_score(LONG_MAX, LONG_MAX, LONG_MAX, LONG_MAX);
    }
    unsigned long creatures_efficiency, creatures_mood;
    unsigned long max_creatures_efficiency, max_creatures_mood;
    {
        creatures_efficiency = compute_dungeon_creature_amount_score(dungeon->num_active_creatrs);
        max_creatures_efficiency = compute_dungeon_creature_amount_score(LONG_MAX);
        creatures_mood = compute_dungeon_creature_mood_score(dungeon->num_active_creatrs,dungeon->creatures_annoyed);
        max_creatures_mood = compute_dungeon_creature_mood_score(LONG_MAX,LONG_MAX);
    }
    { // Compute total score for this turn
        i = manage_efficiency + creatures_efficiency;
        k = max_manage_efficiency + max_creatures_efficiency;
        dungeon->field_AE9[1] = 1000 * i / k;
    }
    { // Compute managing efficiency score
        i = manage_efficiency - creatures_efficiency;
        k = max_manage_efficiency - max_creatures_efficiency;
        if (i < 0)
            i = 0;
        long raw_score;
        raw_score = 1000 * i / k;
        // Angry creatures may degrade the score by up to 50%
        raw_score = raw_score / 2 + raw_score * (max_creatures_mood - creatures_mood) / (2*max_creatures_mood);
        dungeon->field_AE9[0] = raw_score;
    }
    {
        unsigned long gameplay_score;
        gameplay_score = dungeon->field_AE9[1];
        if (gameplay_score <= 1) {
            WARNLOG("Total score for turn is too low!");
            gameplay_score = 1;
        }
        dungeon->field_AE9[1] = gameplay_score;
    }
    {
        unsigned long gameplay_score;
        gameplay_score = dungeon->field_AE9[0];
        if (gameplay_score <= 1) {
            WARNLOG("Managing score for turn is too low!");
            gameplay_score = 1;
        }
        dungeon->field_AE9[0] = gameplay_score;
    }
    { // Check to update max score
        unsigned long gameplay_score;
        gameplay_score = dungeon->field_AE9[1];
        if (dungeon->max_gameplay_score < gameplay_score)
            dungeon->max_gameplay_score = gameplay_score;
    }
    return true;
}