long count_player_rooms_entrances(PlayerNumber plyr_idx) { struct Room *room; long i; unsigned long k; long count; count = 0; i = game.entrance_room_id; 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_kind; // Per-room code if ((plyr_idx < 0) || (room->owner == plyr_idx)) count++; // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return count; }
long computer_check_for_place_door(struct Computer2 *comp, struct ComputerCheck * check) { if (is_newdig_enabled(comp)) return 4; SYNCDBG(8,"Starting"); ThingModel doorkind; struct Dungeon *dungeon; dungeon = comp->dungeon; //TODO COMPUTER_PLAYER Computer prefers to put wooden doors, and uses other types only if wooden are depleted. That should be changed. for (doorkind = 1; doorkind < DOOR_TYPES_COUNT; doorkind++) { if (dungeon->door_amount_stored[doorkind] <= 0) { continue; } long rkind; rkind = check->param1; if (rkind == 0) { rkind = (check->param2 + 1) % ROOM_TYPES_COUNT; check->param2 = rkind; } unsigned long k; k = 0; long i; i = dungeon->room_kind[rkind]; while (i != 0) { struct Room *room; room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code struct Coord3d pos; pos.x.val = 0; pos.y.val = 0; pos.z.val = 0; if (find_place_to_put_door_around_room(room, &pos)) { if (try_game_action(comp, dungeon->owner, GA_PlaceDoor, 0, pos.x.stl.num, pos.y.stl.num, doorkind, 0) > Lb_OK) { return CTaskRet_Unk1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } } return CTaskRet_Unk4; }
long creature_add_lair_to_room(struct Thing *creatng, struct Room *room) { struct Thing *lairtng; if (!room_has_enough_free_capacity_for_creature(room, creatng)) return 0; //return _DK_creature_add_lair_to_room(thing, room); // Make sure we don't already have a lair on that position lairtng = find_creature_lair_at_subtile(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, 0); if (!thing_is_invalid(lairtng)) return 0; struct CreatureStats *crstat; struct CreatureControl *cctrl; crstat = creature_stats_get_from_thing(creatng); cctrl = creature_control_get_from_thing(creatng); room->content_per_model[creatng->model]++; room->used_capacity += crstat->lair_size; if ((cctrl->lair_room_id > 0) && (cctrl->lairtng_idx > 0)) { struct Room *room; room = room_get(cctrl->lair_room_id); creature_remove_lair_from_room(creatng, room); } cctrl->lair_room_id = room->index; // Create the lair thing struct CreatureData *crdata; struct Coord3d pos; pos.x.val = creatng->mappos.x.val; pos.y.val = creatng->mappos.y.val; pos.z.val = creatng->mappos.z.val; crdata = creature_data_get_from_thing(creatng); lairtng = create_object(&pos, crdata->field_1, creatng->owner, -1); if (thing_is_invalid(lairtng)) { ERRORLOG("Could not create lair totem"); remove_thing_from_mapwho(creatng); place_thing_in_mapwho(creatng); return 1; // Return that so we won't try to redo the action over and over } lairtng->mappos.z.val = get_thing_height_at(lairtng, &lairtng->mappos); // Associate creature with the lair cctrl->lairtng_idx = lairtng->index; lairtng->word_13 = creatng->index; lairtng->word_15 = 1; // Lair size depends on creature level lairtng->word_17 = 300 * cctrl->explevel / 20 + 300; lairtng->field_52 = ACTION_RANDOM(0x800); struct Objects *objdat; unsigned long i; objdat = get_objects_data_for_thing(lairtng); i = convert_td_iso(objdat->field_5); set_thing_draw(lairtng, i, objdat->field_7, lairtng->word_15, 0, -1, objdat->field_11); thing_play_sample(creatng, 158, NORMAL_PITCH, 0, 3, 1, 2, FULL_LOUDNESS); create_effect(&pos, imp_spangle_effects[creatng->owner], creatng->owner); anger_set_creature_anger(creatng, 0, AngR_NoLair); remove_thing_from_mapwho(creatng); place_thing_in_mapwho(creatng); return 1; }
struct Room *player_has_room_of_type(PlayerNumber plyr_idx, RoomKind rkind) { //return _DK_player_has_room_of_type(plyr_idx, rkind); struct Dungeon *dungeon; if (plyr_idx == game.neutral_player_num) return false; dungeon = get_players_num_dungeon(plyr_idx); return room_get(dungeon->room_kind[rkind]); }
long instf_destroy(struct Thing *creatng, long *param) { struct Dungeon *dungeon; struct Room *room; struct SlabMap *slb; MapSlabCoord slb_x,slb_y; long prev_owner; TRACE_THING(creatng); slb_x = subtile_slab_fast(creatng->mappos.x.stl.num); slb_y = subtile_slab_fast(creatng->mappos.y.stl.num); dungeon = get_dungeon(creatng->owner); slb = get_slabmap_block(slb_x, slb_y); room = room_get(slb->room_index); prev_owner = slabmap_owner(slb); if ( !room_is_invalid(room) && (prev_owner != creatng->owner) ) { if (room->health > 1) { room->health--; return 0; } clear_dig_on_room_slabs(room, creatng->owner); if (room->owner == game.neutral_player_num) { claim_room(room, creatng); } else { MapCoord ccor_x,ccor_y; ccor_x = subtile_coord_center(room->central_stl_x); ccor_y = subtile_coord_center(room->central_stl_y); event_create_event_or_update_nearby_existing_event(ccor_x, ccor_y, EvKind_RoomLost, room->owner, 0); claim_enemy_room(room, creatng); } thing_play_sample(creatng, 76, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); create_effects_on_room_slabs(room, imp_spangle_effects[creatng->owner], 0, creatng->owner); return 0; } if (slb->health > 1) { slb->health--; return 0; } if (prev_owner != game.neutral_player_num) { struct Dungeon *prev_dungeon; prev_dungeon = get_dungeon(prev_owner); prev_dungeon->lvstats.territory_lost++; } decrease_dungeon_area(prev_owner, 1); neutralise_enemy_block(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, creatng->owner); remove_traps_around_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), NULL); switch_owned_objects_on_destoyed_slab_to_neutral(slb_x, slb_y, prev_owner); dungeon->lvstats.territory_destroyed++; return 1; }
struct Room * find_next_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, int prev_room_idx, unsigned char nav_flags, long used, long *neardistance) { long distance; struct Coord3d pos; struct Room *room; unsigned long k; int i; k = 0; i = prev_room_idx; 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 // Compute simplified distance - without use of mul or div distance = abs(thing->mappos.x.stl.num - (int)room->central_stl_x) + abs(thing->mappos.y.stl.num - (int)room->central_stl_y); if ((*neardistance > distance) && (room->used_capacity >= used)) { if (find_first_valid_position_for_thing_anywhere_in_room(thing, room, &pos)) { TbBool is_connected; switch (thing->class_id) { case TCls_Creature: is_connected = creature_can_navigate_to(thing, &pos, nav_flags); break; default: is_connected = navigation_points_connected(&thing->mappos, &pos); break; } if (is_connected) { *neardistance = distance; return room; } } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return INVALID_ROOM; }
void init_dungeon_essential_position(struct Dungeon *dungeon) { struct Room *room; room = room_get(dungeon->room_kind[RoK_DUNGHEART]); RoomKind rkind; for (rkind = 1; rkind < ROOM_TYPES_COUNT; rkind++) { if (!room_is_invalid(room)) break; room = room_get(dungeon->room_kind[rkind]); } if (room_is_invalid(room)) { dungeon->essential_pos.x.val = subtile_coord_center(map_subtiles_x/2); dungeon->essential_pos.y.val = subtile_coord_center(map_subtiles_y/2); dungeon->essential_pos.z.val = subtile_coord(0,1); return; } dungeon->essential_pos.x.val = subtile_coord_center(room->central_stl_x); dungeon->essential_pos.y.val = subtile_coord_center(room->central_stl_y); dungeon->essential_pos.z.val = subtile_coord(0,1); }
long computer_check_move_creatures_to_room(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; struct Room *room; dungeon = comp->dungeon; SYNCDBG(8,"Checking player %d for move to %s", (int)dungeon->owner, room_code_name(check->param2)); int num_to_move; num_to_move = check->param1 * dungeon->num_active_creatrs / 100; if (num_to_move <= 0) { SYNCDBG(8,"No creatures to move, active %d percentage %d", (int)dungeon->num_active_creatrs, (int)check->param1); return CTaskRet_Unk4; } if (computer_able_to_use_magic(comp, PwrK_HAND, 1, num_to_move) != 1) { return CTaskRet_Unk4; } // If there's already task in progress which uses hand, then don't add more // content of the hand could be used by wrong task by mistake if (is_task_in_progress_using_hand(comp)) { return CTaskRet_Unk4; } unsigned long k; long i; k = 0; i = dungeon->room_kind[check->param2]; 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 if (room->total_capacity > room->used_capacity) { int num_to_move_fit; num_to_move_fit = min(num_to_move, room->total_capacity - room->used_capacity); if (create_task_move_creatures_to_room(comp, room->index, num_to_move_fit)) { SYNCDBG(8,"Added task to move %d creatures to %s index %d", (int)num_to_move_fit,room_code_name(room->kind),(int)room->index); return CTaskRet_Unk1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return CTaskRet_Unk4; }
long computer_check_move_creatures_to_room(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; struct Room *room; dungeon = comp->dungeon; SYNCDBG(8,"Checking player %d for move to %s", (int)dungeon->owner, room_code_name(check->param2)); //return _DK_computer_check_move_creatures_to_room(comp, check); //TODO check if should be changed to computer_able_to_use_magic() if (!is_power_available(dungeon->owner, PwrK_HAND)) { return 4; } int num_to_move; num_to_move = check->param1 * dungeon->num_active_creatrs / 100; if (num_to_move <= 0) { SYNCDBG(8,"No creatures to move, active %d percentage %d", (int)dungeon->num_active_creatrs, (int)check->param1); return 4; } if (is_task_in_progress(comp, CTT_MoveCreatureToRoom)) { return 4; } unsigned long k; long i; k = 0; i = dungeon->room_kind[check->param2]; 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 if (room->total_capacity > room->used_capacity) { if (create_task_move_creatures_to_room(comp, room->index, num_to_move)) { SYNCDBG(8,"Added task to move %d creatures to %s index %d", (int)num_to_move,room_code_name(room->kind),(int)room->index); return 1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return 4; }
struct Room * find_nearest_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, PlayerNumber owner, RoomKind rkind, unsigned char nav_flags, long used, long *neardistance) { struct Dungeon *dungeon; struct Room *nearoom; long distance; struct Coord3d pos; struct Room *room; unsigned long k; int i; SYNCDBG(18,"Searching for %s navigable by %s index %d",room_code_name(rkind),thing_model_name(thing),(int)thing->index); dungeon = get_dungeon(owner); nearoom = INVALID_ROOM; k = 0; i = dungeon->room_kind[rkind]; 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 // Compute simplified distance - without use of mul or div distance = abs(thing->mappos.x.stl.num - (int)room->central_stl_x) + abs(thing->mappos.y.stl.num - (int)room->central_stl_y); if ((*neardistance > distance) && (room->used_capacity >= used)) { if (find_first_valid_position_for_thing_anywhere_in_room(thing, room, &pos)) { if ((thing->class_id != TCls_Creature) || creature_can_navigate_to(thing, &pos, nav_flags)) { *neardistance = distance; nearoom = room; } } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return nearoom; }
long computer_check_for_expand_room_kind(struct Computer2 *comp, struct ComputerCheck * check, RoomKind rkind, long max_slabs, long around_start) { struct Dungeon *dungeon; dungeon = comp->dungeon; { struct RoomStats *rstat; rstat = room_stats_get_for_kind(rkind); // If we don't have money for the room - don't even try // Check price for two slabs - after all, we don't want to end up having nothing if (2*rstat->cost >= dungeon->total_money_owned) { return 0; } } MapSubtlCoord max_radius; // Don't allow the room to be made into long, narrow shape max_radius = 3 * slab_subtile(LbSqrL(max_slabs),2) / 4; struct Room *room; long i; unsigned long k; 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 if ((room->slabs_count > 0) && (room->slabs_count < max_slabs)) { if (computer_check_for_expand_specific_room(comp, check, room, max_radius, around_start)) { SYNCDBG(6,"The %s index %d will be expanded",room_code_name(room->kind),(int)room->index); return 1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return 0; }
struct Room *get_player_room_of_kind_nearest_to(PlayerNumber plyr_idx, RoomKind rkind, MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *retdist) { struct Dungeon *dungeon; struct Room *room; long i; unsigned long k; dungeon = get_dungeon(plyr_idx); struct Room *nearest_room; long nearest_dist; nearest_dist = LONG_MAX; nearest_room = INVALID_ROOM; 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 long dist; dist = abs(room->central_stl_y - stl_y) + abs(room->central_stl_x - stl_x); if (dist < nearest_dist) { nearest_dist = dist; nearest_room = room; } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } if (retdist != NULL) *retdist = nearest_dist; return nearest_room; }
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; }
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; }
/** * 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; }
/** * User thread responsible for handling individual clients * @param arg Structure to use to process the thread */ void *user_thread( void *arg ) { User user = new_user( ((Environment)arg)->client ); Management manager = ((Environment)arg)->manager; // increase thread count manager_up_thread( manager, pthread_self() ); // lock user for now user_lock( user ); // add the user to the list of users manager_add_user( manager, user ); // turn client on client_ok( user->client ); // ready user for commo user_unlock( user ); /* --------------------------------------------- * Login screen */ Room login_room = room_get( manager->rooms, 0 ); if( login_room == NULL ){ printf("Error getting login room\n"); //return 0; } char_set_room( user->parent->character, login_room ); // have a look action_look( NULL, user, manager ); // client_prompt( ) // accept input // initialize int buff_len = 256; char *buff = (char *) malloc( buff_len ); memset( buff, 0, 256 ); if( buff == NULL ){ perror("client thread recv buffer malloc"); return NULL; } // user response loop while( manager->cease != 1 && (user->flags & USER_FLAG_EXIT) == 0 ){ // receive response from client int length = client_recv( user->client, &buff, &buff_len ); // handle response if( buff != NULL && length > 0 ){ // parse the response for actionable text action_parse_response( buff, // buffer with response length, // length of response user, // user making response manager ); // manager // reset response memset(buff,0,length); } else { // nothing going on, yield sched_yield(); } } free( buff ); // remove from manager list manager_remove_user( manager, user ); // lock user for this user_lock( user ); // close and destory all structs // manually manage this part close_client( user->client ); destroy_client( user->client ); // user gone from manager so safe to unlock a head user_unlock( user ); // now destroy destroy_user( user ); free( ((Environment)arg) ); // decrease thread count manager_down_thread( manager, pthread_self() ); pthread_exit( 0 ); return NULL; }
long computer_check_enemy_entrances(struct Computer2 *comp, struct ComputerCheck * check) { SYNCDBG(8,"Starting"); //return _DK_computer_check_enemy_entrances(comp, check); long result; result = 4; PlayerNumber plyr_idx; for (plyr_idx=0; plyr_idx < PLAYERS_COUNT; plyr_idx++) { if (comp->dungeon->owner == plyr_idx) { continue; } if (players_are_mutual_allies(comp->dungeon->owner, plyr_idx)) { continue; } struct PlayerInfo *player; struct Dungeon *dungeon; player = get_player(plyr_idx); dungeon = get_players_dungeon(player); long i; unsigned long k; i = dungeon->room_kind[RoK_ENTRANCE]; k = 0; while (i != 0) { struct Room *room; room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code struct Comp2_UnkStr1 *unkptr; unkptr = &comp->unkarr_A10[(int)plyr_idx]; long n; for (n = 0; n < 64; n++) { struct Coord3d *pos; pos = &unkptr->pos_A[n]; if ((pos->x.val == subtile_coord(room->central_stl_x,0)) && (pos->y.val == subtile_coord(room->central_stl_y,0))) { break; } } if (n == 64) { struct Coord3d *pos; n = unkptr->field_4; unkptr->field_4 = (n + 1) % 64; unkptr->field_0 = game.play_gameturn; pos = &unkptr->pos_A[n]; pos->x.val = subtile_coord(room->central_stl_x,0); pos->y.val = subtile_coord(room->central_stl_y,0); pos->z.val = subtile_coord(1,0); result = 2; } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } } return result; }