short move_to_position(struct Thing *creatng)
{
    CreatureStateCheck callback;
    struct CreatureControl *cctrl;
    struct StateInfo *stati;
    long move_result;
    CrCheckRet state_check;
    long speed;
    TRACE_THING(creatng);
    cctrl = creature_control_get_from_thing(creatng);
    speed = get_creature_speed(creatng);
    SYNCDBG(18,"Starting to move %s index %d into (%d,%d)",thing_model_name(creatng),(int)creatng->index,(int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num);
    // Try teleporting the creature
    if (creature_move_to_using_teleport(creatng, &cctrl->moveto_pos, speed)) {
        SYNCDBG(8,"Teleporting %s index %d owner %d into (%d,%d) for %s",thing_model_name(creatng),(int)creatng->index,(int)creatng->owner,
            (int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num,creature_state_code_name(creatng->continue_state));
        return 1;
    }
    move_result = creature_move_to(creatng, &cctrl->moveto_pos, speed, cctrl->move_flags, 0);
    state_check = CrCkRet_Available;
    stati = get_thing_continue_state_info(creatng);
    if (!state_info_invalid(stati))
    {
        callback = stati->move_check;
        if (callback != NULL)
        {
            SYNCDBG(18,"Doing move check callback for continue state %s",creature_state_code_name(creatng->continue_state));
            state_check = callback(creatng);
        }
    }
    if (state_check == CrCkRet_Available)
    {
        // If moving was successful
        if (move_result == 1) {
            // Back to "main state"
            internal_set_thing_state(creatng, creatng->continue_state);
            return CrStRet_Modified;
        }
        // If moving failed, do a reset
        if (move_result == -1) {
            CrtrStateId cntstat;
            cntstat = creatng->continue_state;
            internal_set_thing_state(creatng, cntstat);
            set_start_state(creatng);
            SYNCDBG(8,"Couldn't move %s to place required for state %s; reset to state %s",thing_model_name(creatng),creature_state_code_name(cntstat),creatrtng_actstate_name(creatng));
            return CrStRet_ResetOk;
        }
        // If continuing the job, check for job stress
        process_job_stress_and_going_postal(creatng);
    }
    switch (state_check)
    {
    case CrCkRet_Deleted:
        return CrStRet_Deleted;
    case CrCkRet_Available:
        return CrStRet_Modified;
    default:
        return CrStRet_ResetOk;
    }
}
short tunneller_doing_nothing(struct Thing *creatng)
{
    //return _DK_tunneller_doing_nothing(creatng);
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    // Wait for some time
    if (game.play_gameturn - cctrl->last_mood_sound_turn <= 1) {
        return 1;
    }
    /* Sometimes we may have no target dungeon. In that case, destination dungeon
     * index is negative. */
    if (cctrl->party.target_plyr_idx == -1)
    {
        script_support_send_tunneller_to_appropriate_dungeon(creatng);
        return 0;
    }
    if (!player_cannot_win(cctrl->party.target_plyr_idx))
    {
        if (good_can_move_to_dungeon_heart(creatng, cctrl->party.target_plyr_idx))
        {
            internal_set_thing_state(creatng, CrSt_GoodDoingNothing);
            return 1;
        }
    }
    cctrl->party.target_plyr_idx = good_find_enemy_dungeon(creatng);
    if (cctrl->party.target_plyr_idx != -1)
    {
        internal_set_thing_state(creatng, CrSt_GoodDoingNothing);
        return 1;
    }

    int plyr_idx;
    plyr_idx = get_best_dungeon_to_tunnel_to(creatng);
    if (plyr_idx == -1) {
      return 1;
    }
    struct Dungeon *dungeon;
    dungeon = get_dungeon(plyr_idx);
    if ( dungeon->num_active_creatrs || dungeon->num_active_diggers )
    {
        struct Coord3d pos;
        get_random_position_in_dungeon_for_creature(plyr_idx, 1, creatng, &pos);
        send_tunneller_to_point_in_dungeon(creatng, plyr_idx, &pos);
    } else
    {
        good_setup_wander_to_dungeon_heart(creatng, plyr_idx);
    }
    return 1;
}
short at_scavenger_room(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    struct Dungeon *dungeon;
    struct Room *room;
    //return _DK_at_scavenger_room(thing);
    room = get_room_thing_is_on(thing);
    if (!room_initially_valid_as_type_for_thing(room, RoK_SCAVENGER, thing))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(thing),(int)thing->index);
        set_start_state(thing);
        return 0;
    }
    cctrl = creature_control_get_from_thing(thing);
    crstat = creature_stats_get_from_thing(thing);
    dungeon = get_dungeon(thing->owner);
    if (crstat->scavenger_cost >= dungeon->total_money_owned)
    {
        if (is_my_player_number(thing->owner))
            output_message(SMsg_NoGoldToScavenge, MESSAGE_DELAY_TREASURY, true);
        set_start_state(thing);
        return 0;
    }
    if (!add_creature_to_work_room(thing, room))
    {
        set_start_state(thing);
        return 0;
    }
    internal_set_thing_state(thing, CrSt_Scavengering);
    cctrl->field_82 = 0;
    return 1;
}
TbBool setup_person_move_to_position_f(struct Thing *thing, MapSubtlCoord stl_x, MapSubtlCoord stl_y, NaviRouteFlags flags, const char *func_name)
{
    struct CreatureControl *cctrl;
    struct Coord3d locpos;
    SYNCDBG(18,"%s: Moving %s index %d to (%d,%d)",func_name,thing_model_name(thing),(int)thing->index,(int)stl_x,(int)stl_y);
    TRACE_THING(thing);
    locpos.x.val = subtile_coord_center(stl_x);
    locpos.y.val = subtile_coord_center(stl_y);
    locpos.z.val = thing->mappos.z.val;
    locpos.z.val = get_thing_height_at(thing, &locpos);
    cctrl = creature_control_get_from_thing(thing);
    if (creature_control_invalid(cctrl))
    {
        WARNLOG("%s: Tried to move invalid creature to (%d,%d)",func_name,(int)stl_x,(int)stl_y);
        return false;
    }
    if (thing_in_wall_at(thing, &locpos))
    {
        SYNCDBG(16,"%s: The %s would be trapped in wall at (%d,%d)",func_name,thing_model_name(thing),(int)stl_x,(int)stl_y);
        return false;
    }
    if (!creature_can_navigate_to_with_storage_f(thing, &locpos, flags, func_name))
    {
        SYNCDBG(19,"%s: The %s cannot reach subtile (%d,%d)",func_name,thing_model_name(thing),(int)stl_x,(int)stl_y);
        return false;
    }
    cctrl->move_flags = flags;
    internal_set_thing_state(thing, CrSt_MoveToPosition);
    cctrl->moveto_pos.x.val = locpos.x.val;
    cctrl->moveto_pos.y.val = locpos.y.val;
    cctrl->moveto_pos.z.val = locpos.z.val;
    SYNCDBG(19,"%s: Done",func_name);
    return true;
}
TbBool setup_person_move_close_to_position(struct Thing *thing, MapSubtlCoord stl_x, MapSubtlCoord stl_y, NaviRouteFlags flags)
{
    struct CreatureControl *cctrl;
    struct Coord3d trgpos;
    struct Coord3d navpos;
    SYNCDBG(18,"Moving %s index %d to (%d,%d)",thing_model_name(thing),(int)thing->index,(int)stl_x,(int)stl_y);
    trgpos.x.val = subtile_coord_center(stl_x);
    trgpos.y.val = subtile_coord_center(stl_y);
    trgpos.z.val = thing->mappos.z.val;
    cctrl = creature_control_get_from_thing(thing);
    if (creature_control_invalid(cctrl))
    {
        WARNLOG("Tried to move invalid creature to (%d,%d)",(int)stl_x,(int)stl_y);
        return false;
    }
    get_nearest_navigable_point_for_thing(thing, &trgpos, &navpos, flags);
    if (!creature_can_navigate_to_with_storage(thing, &navpos, flags))
    {
        SYNCDBG(19,"The %s cannot reach subtile (%d,%d)",thing_model_name(thing),(int)stl_x,(int)stl_y);
        return false;
    }
    cctrl->move_flags = flags;
    internal_set_thing_state(thing, CrSt_MoveToPosition);
    cctrl->moveto_pos.x.val = navpos.x.val;
    cctrl->moveto_pos.y.val = navpos.y.val;
    cctrl->moveto_pos.z.val = navpos.z.val;
    return true;
}
CrStateRet creature_at_changed_lair(struct Thing *creatng)
{
    struct Room *room;
    TRACE_THING(creatng);
    //return _DK_creature_at_changed_lair(thing);
    if (!thing_is_on_own_room_tile(creatng))
    {
        set_start_state(creatng);
        return CrStRet_ResetFail;
    }
    room = get_room_thing_is_on(creatng);
    if (!room_initially_valid_as_type_for_thing(room, RoK_LAIR, creatng))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng));
        set_start_state(creatng);
        return CrStRet_ResetFail;
    }
    if (!creature_add_lair_to_room(creatng, room)) {
        internal_set_thing_state(creatng, CrSt_CreatureChooseRoomForLairSite);
        return CrStRet_Modified;
    }
    // All done - finish the state
    set_start_state(creatng);
    return CrStRet_ResetOk;
}
short at_guard_post_room(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Room *room;
    cctrl = creature_control_get_from_thing(thing);
    cctrl->target_room_id = 0;
    room = get_room_thing_is_on(thing);
    if (!room_initially_valid_as_type_for_thing(room, get_room_for_job(Job_GUARD), thing))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(thing),(int)thing->index);
        set_start_state(thing);
        return 0;
    }
    if (!add_creature_to_work_room(thing, room, Job_GUARD))
    {
        set_start_state(thing);
        return 0;
    }
    internal_set_thing_state(thing, get_continue_state_for_job(Job_GUARD));
    if (!person_get_somewhere_adjacent_in_room(thing, room, &cctrl->moveto_pos))
    {
        cctrl->moveto_pos.x.val = thing->mappos.x.val;
        cctrl->moveto_pos.y.val = thing->mappos.y.val;
        cctrl->moveto_pos.z.val = thing->mappos.z.val;
    }
    return 1;
}
Exemple #8
0
short at_workshop_room(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Room *room;
    //return _DK_at_workshop_room(thing);
    cctrl = creature_control_get_from_thing(thing);
    cctrl->target_room_id = 0;
    room = get_room_thing_is_on(thing);
    if (!room_initially_valid_as_type_for_thing(room, RoK_WORKSHOP, thing))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(thing));
        set_start_state(thing);
        return 0;
    }
    if (room->total_capacity <= room->used_capacity)
    {
        set_start_state(thing);
        return 0;
    }
    if ( !add_creature_to_work_room(thing, room) )
    {
        set_start_state(thing);
        return 0;
    }
    internal_set_thing_state(thing, CrSt_Manufacturing);
    setup_move_to_new_workshop_position(thing, room, 1);
    return 1;
}
short good_leave_through_exit_door(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Thing *tmptng;
    // Debug code to find incorrect states
    if (!is_hero_thing(thing))
    {
        ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner);
        set_start_state(thing);
        erstat_inc(ESE_BadCreatrState);
        return false;
    }
    //return _DK_good_leave_through_exit_door(thing);
    tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num);
    if (thing_is_invalid(tmptng))
    {
        return 0;
    }
    cctrl = creature_control_get_from_thing(thing);
    thing->creature.gold_carried = 0;
    cctrl->field_282 = game.hero_door_wait_time;
    cctrl->byte_8A = tmptng->creation_turn;
    place_thing_in_creature_controlled_limbo(thing);
    internal_set_thing_state(thing, CrSt_GoodWaitInExitDoor);
    return 1;
}
short good_drops_gold(struct Thing *thing)
{
    // Debug code to find incorrect states
    if (!is_hero_thing(thing))
    {
        ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner);
        set_start_state(thing);
        erstat_inc(ESE_BadCreatrState);
        return 0;
    }
    //return _DK_good_drops_gold(thing);
    GoldAmount amount;
    amount = game.pot_of_gold_holds;
    if (thing->creature.gold_carried <= game.pot_of_gold_holds)
        amount = thing->creature.gold_carried;
    struct Thing *gldtng;
    gldtng = create_object(&thing->mappos, 6, thing->owner, -1);
    if (thing_is_invalid(gldtng)) {
        return 0;
    }
    gldtng->valuable.gold_stored = amount;
    thing->creature.gold_carried -= amount;
    // Update size of the gold object
    add_gold_to_pile(gldtng, 0);
    internal_set_thing_state(thing, CrSt_GoodBackAtStart);
    return 1;
}
short tunnelling(struct Thing *creatng)
{
    struct SlabMap *slb;
    long speed;
    SYNCDBG(7,"Move %s from (%d,%d)",thing_model_name(creatng),(int)creatng->mappos.x.stl.num,(int)creatng->mappos.y.stl.num);
    //return _DK_tunnelling(creatng);
    speed = get_creature_speed(creatng);
    slb = get_slabmap_for_subtile(creatng->mappos.x.stl.num,creatng->mappos.y.stl.num);
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    struct Coord3d *pos;
    pos = &cctrl->moveto_pos;
    if (slabmap_owner(slb) == cctrl->party.target_plyr_idx)
    {
        internal_set_thing_state(creatng, CrSt_GoodDoingNothing);
        return 1;
    }
    long move_result;
    move_result = creature_tunnel_to(creatng, pos, speed);
    if (move_result == 1)
    {
        internal_set_thing_state(creatng, CrSt_TunnellerDoingNothing);
        return 1;
    }
    if (move_result == -1)
    {
        ERRORLOG("Bad place to tunnel to!");
        set_start_state(creatng);
        creatng->continue_state = CrSt_Unused;
        return 0;
    }
    // Once per 128 turns, check if we've done digging and can now walk to the place
    if (((game.play_gameturn + creatng->index) & 0x7F) == 0)
    {
        if (creature_can_navigate_to(creatng, pos, NavRtF_Default))
        {
            SYNCDBG(7,"The %s can now walk to (%d,%d), no need to tunnel",thing_model_name(creatng),(int)pos->x.stl.num,(int)pos->y.stl.num);
            return 1;
        }
    }
    SYNCDBG(7,"The %s cannot reach (%d,%d) by walk",thing_model_name(creatng),(int)pos->x.stl.num,(int)pos->y.stl.num);
    return 0;
}
Exemple #12
0
TbBool attempt_job_in_state_on_room_content_for_player(struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job)
{
    struct Room *room;
    RoomKind rkind;
    rkind = get_room_for_job(new_job);
    room = find_room_for_thing_with_used_capacity(creatng, creatng->owner, rkind, NavRtF_Default, 1);
    if (room_is_invalid(room)) {
        return false;
    }
    internal_set_thing_state(creatng, get_initial_state_for_job(new_job));
    return true;
}
short setup_person_tunnel_to_position(struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, unsigned char a4)
{
    struct CreatureControl *cctrl;
    if ( internal_set_thing_state(creatng, CrSt_Tunnelling) )
    {
        cctrl = creature_control_get_from_thing(creatng);
        cctrl->moveto_pos.x.val = subtile_coord_center(stl_x);
        cctrl->moveto_pos.y.val = subtile_coord_center(stl_y);
        cctrl->moveto_pos.z.val = get_thing_height_at(creatng, &cctrl->moveto_pos);
    }
    return 0;
}
Exemple #14
0
TbBool attempt_job_in_state_internal_for_player(struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job)
{
    struct CreatureControl *cctrl;
    CrtrStateId crstate;
    crstate = get_initial_state_for_job(new_job);
    cctrl = creature_control_get_from_thing(creatng);
    internal_set_thing_state(creatng, crstate);
    // Some states need additional initialization
    if (crstate == CrSt_SeekTheEnemy) {
        cctrl->word_9A = 0;
    }
    return true;
}
short creature_scavenged_disappear(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Dungeon *dungeon;
    struct Room *room;
    struct Coord3d pos;
    long stl_x, stl_y;
    long i;
    //return _DK_creature_scavenged_disappear(thing);
    cctrl = creature_control_get_from_thing(thing);
    cctrl->byte_9A--;
    if (cctrl->byte_9A > 0)
    {
      if ((cctrl->byte_9A == 7) && (cctrl->byte_9B < PLAYERS_COUNT))
      {
        create_effect(&thing->mappos, get_scavenge_effect_element(cctrl->byte_9B), thing->owner);
      }
      return 0;
    }
    // We don't really have to convert coordinates into numbers and back to XY.
    i = get_subtile_number(cctrl->scavenge.stl_9D_x, cctrl->scavenge.stl_9D_y);
    stl_x = stl_num_decode_x(i);
    stl_y = stl_num_decode_y(i);
    room = subtile_room_get(stl_x, stl_y);
    if (room_is_invalid(room) || (room->kind != RoK_SCAVENGER))
    {
        ERRORLOG("Room %s at (%d,%d) disappeared.",room_code_name(RoK_SCAVENGER),(int)stl_x,(int)stl_y);
        kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
        return -1;
    }
    if (find_random_valid_position_for_thing_in_room(thing, room, &pos))
    {
        move_thing_in_map(thing, &pos);
        anger_set_creature_anger_all_types(thing, 0);
        dungeon = get_dungeon(cctrl->byte_9B);
        dungeon->creatures_scavenge_gain++;
        if (is_my_player_number(thing->owner))
          output_message(SMsg_MinionScanvenged, 0, true);
        cctrl->byte_9C = thing->owner;
        change_creature_owner(thing, cctrl->byte_9B);
        internal_set_thing_state(thing, CrSt_CreatureScavengedReappear);
        return 0;
    } else
    {
        ERRORLOG("No valid position inside %s room for %s.",room_code_name(room->kind),thing_model_name(thing));
        kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
        return -1;
    }
}
short good_arrived_at_attack_room(struct Thing *thing)
{
    struct Room *room;
    room = get_room_thing_is_on(thing);
    // If the current tile can be destroyed
    if (room_exists(room) && (room->owner != thing->owner) && !room_cannot_vandalise(room->kind))
    {
        internal_set_thing_state(thing, CrSt_GoodAttackRoom1);
        MapCoord ev_coord_x,ev_coord_y;
        ev_coord_x = subtile_coord_center(room->central_stl_x);
        ev_coord_y = subtile_coord_center(room->central_stl_y);
        event_create_event_or_update_nearby_existing_event(ev_coord_x, ev_coord_y, EvKind_RoomUnderAttack, room->owner, 0);
        if (is_my_player_number(room->owner))
          output_message(SMsg_EnemyDestroyRooms, MESSAGE_DELAY_FIGHT, true);
        return 1;
    }
    set_start_state(thing);
    return 0;
}
short at_lair_to_sleep(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Thing *lairtng;
    struct Room *room;
    TRACE_THING(thing);
    //return _DK_at_lair_to_sleep(thing);
    cctrl = creature_control_get_from_thing(thing);
    lairtng = thing_get(cctrl->lairtng_idx);
    TRACE_THING(lairtng);
    cctrl->target_room_id = 0;
    if (thing_is_invalid(lairtng) || (cctrl->slap_turns != 0))
    {
        set_start_state(thing);
        return 0;
    }
    if (!creature_will_sleep(thing))
    {
        set_start_state(thing);
        return 0;
    }
    room = get_room_thing_is_on(thing);
    if (!room_initially_valid_as_type_for_thing(room, RoK_LAIR, thing))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(thing));
        set_start_state(thing);
        return 0;
    }
    if ((cctrl->lair_room_id != room->index))
    {
        set_start_state(thing);
        return 0;
    }
    if ( !creature_turn_to_face_angle(thing, lairtng->field_52) )
    {
        internal_set_thing_state(thing, CrSt_CreatureSleep);
        cctrl->field_82 = 200;
        thing->movement_flags &= ~TMvF_Flying;
    }
    process_lair_enemy(thing, room);
    return 1;
}
CrStateRet creature_at_new_lair(struct Thing *creatng)
{
    struct Room *room;
    TRACE_THING(creatng);
    //return _DK_creature_at_new_lair(thing);
    room = get_room_thing_is_on(creatng);
    if ( !room_still_valid_as_type_for_thing(room, RoK_LAIR, creatng) )
    {
        WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->owner);
        set_start_state(creatng);
        return CrStRet_ResetFail;
    }
    if (!creature_add_lair_to_room(creatng, room))
    {
        internal_set_thing_state(creatng, CrSt_CreatureChooseRoomForLairSite);
        return CrStRet_Modified;
    }
    set_start_state(creatng);
    return CrStRet_ResetOk;
}
Exemple #19
0
short at_training_room(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    struct Dungeon *dungeon;
    struct Room *room;
    //return _DK_at_training_room(thing);
    cctrl = creature_control_get_from_thing(thing);
    cctrl->target_room_id = 0;
    if (!creature_can_be_trained(thing))
    {
        SYNCDBG(9,"Ending training of %s level %d; creature is not trainable",thing_model_name(thing),(int)cctrl->explevel);
        set_start_state(thing);
        return 0;
    }
    crstat = creature_stats_get_from_thing(thing);
    dungeon = get_dungeon(thing->owner);
    if (dungeon->total_money_owned < crstat->training_cost)
    {
        if (is_my_player_number(thing->owner))
            output_message(SMsg_NoGoldToTrain, MESSAGE_DELAY_TREASURY, true);
        set_start_state(thing);
        return 0;
    }
    room = get_room_thing_is_on(thing);
    if (!room_initially_valid_as_type_for_thing(room, RoK_TRAINING, thing))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(thing));
        set_start_state(thing);
        return 0;
    }
    if ( !add_creature_to_work_room(thing, room) )
    {
        set_start_state(thing);
        return 0;
    }
    internal_set_thing_state(thing, CrSt_Training);
    setup_move_to_new_training_position(thing, room, 1);
    cctrl->field_82 = 0;
    return 1;
}
short at_barrack_room(struct Thing *creatng)
{
    struct Room *room;
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    cctrl->target_room_id = 0;
    room = get_room_thing_is_on(creatng);
    if (!room_initially_valid_as_type_for_thing(room, RoK_BARRACKS, creatng))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->index);
        set_start_state(creatng);
        return 0;
    }
    if (!add_creature_to_work_room(creatng, room))
    {
        set_start_state(creatng);
        return 0;
    }
    internal_set_thing_state(creatng, CrSt_Barracking);
    return 1;
}
short creature_arrived_at_prison(struct Thing *creatng)
{
    struct CreatureControl *cctrl;
    struct Room *room;
    TRACE_THING(creatng);
    cctrl = creature_control_get_from_thing(creatng);
    cctrl->target_room_id = 0;
    room = get_room_thing_is_on(creatng);
    if (!room_initially_valid_as_type_for_thing(room, RoK_PRISON, creatng))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->index);
        set_start_state(creatng);
        return 0;
    }
    if (!add_creature_to_work_room(creatng, room))
    {
        output_message_room_related_from_computer_or_player_action(room->owner, room->kind, OMsg_RoomTooSmall);
        cctrl->flgfield_1 &= ~CCFlg_NoCompControl;
        set_start_state(creatng);
        return 0;
    }
    cctrl->field_82 = game.play_gameturn;
    cctrl->flgfield_1 |= CCFlg_NoCompControl;
    internal_set_thing_state(creatng, CrSt_CreatureInPrison);
    if (creature_affected_by_spell(creatng, SplK_Speed)) {
        terminate_thing_spell_effect(creatng, SplK_Speed);
    }
    if (creature_affected_by_spell(creatng, SplK_Invisibility)) {
        terminate_thing_spell_effect(creatng, SplK_Invisibility);
    }
    if (creatng->light_id != 0) {
        light_delete_light(creatng->light_id);
        creatng->light_id = 0;
    }
    return 1;

}
TbBool creature_scavenge_from_creature_pool(struct Thing *calltng)
{
    struct Room *room;
    struct Coord3d pos;
    room = get_room_thing_is_on(calltng);
    if (!room_initially_valid_as_type_for_thing(room, RoK_SCAVENGER, calltng)) {
        WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d",room_code_name(room->kind),(int)room->owner,thing_model_name(calltng),(int)calltng->owner);
        return false;
    }
    if (game.pool.crtr_kind[calltng->model] <= 0) {
        ERRORLOG("Tried to generate %s but it is not in pool",thing_model_name(calltng));
        return false;
    }
    if ( !find_random_valid_position_for_thing_in_room(calltng, room, &pos) ) {
        ERRORLOG("Could not find valid position for thing to be generated");
        return false;
    }
    struct Thing *scavtng;
    scavtng = create_creature(&pos, calltng->model, calltng->owner);
    if (thing_is_invalid(scavtng)) {
        ERRORLOG("Tried to generate %s but creation failed",thing_model_name(calltng));
        return false;
    }
    if (!remove_creature_from_generate_pool(calltng->model))
    {
        ERRORLOG("Could not remove %s from pool",thing_model_name(calltng));
        return false;
    }
    {
        struct Dungeon *dungeon;
        dungeon = get_dungeon(calltng->owner);
        dungeon->creatures_scavenge_gain++;
    }
    internal_set_thing_state(scavtng, CrSt_CreatureScavengedReappear);
    return true;
}