long room_has_slab_adjacent(const struct Room *room, long slbkind) { long i; unsigned long k; k = 0; i = room->slabs_list; while (i > 0) { // Per room tile code long n; for (n=0; n < AROUND_SLAB_LENGTH; n++) { long slab_num; slab_num = i + around_slab[n]; struct SlabMap *slb; slb = get_slabmap_direct(slab_num); if (!slabmap_block_invalid(slb)) { if (slb->kind == slbkind) { return true; } } } // Per room tile code ends i = get_next_slab_number_in_room(i); k++; if (k > room->slabs_count) { ERRORLOG("Room slabs list length exceeded when sweeping"); break; } } return 0; }
TbBool jailbreak_possible(struct Room *room, long plyr_idx) { unsigned long i; unsigned long k; struct SlabMap *slb; if (room->owner == plyr_idx) { return false; } k = 0; i = room->slabs_list; while (i > 0) { slb = get_slabmap_direct(i); if (slabmap_block_invalid(slb)) { ERRORLOG("Jump to invalid room slab detected"); break; } if (slab_by_players_land(plyr_idx, slb_num_decode_x(i), slb_num_decode_y(i))) return true; i = get_next_slab_number_in_room(i); k++; if (k > map_tiles_x * map_tiles_y) { ERRORLOG("Infinite loop detected when sweeping room slabs"); break; } } return false; }
/** * Scans map for gold veins, and fills up gold_lookup array with veins found. */ void check_map_for_gold(void) { MapSlabCoord slb_x,slb_y; struct SlabMap *slb; SlabCodedCoords slb_num; unsigned char *treasure_map; unsigned short *vein_list; long gold_next_idx; long i; SYNCDBG(8,"Starting"); //_DK_check_map_for_gold(); for (i=0; i < GOLD_LOOKUP_COUNT; i++) { LbMemorySet(&game.gold_lookup[i], 0, sizeof(struct GoldLookup)); } // Make a map with treasure areas marked treasure_map = (unsigned char *)scratch; vein_list = (unsigned short *)&scratch[map_tiles_x*map_tiles_y]; for (slb_y = 0; slb_y < map_tiles_y; slb_y++) { for (slb_x = 0; slb_x < map_tiles_x; slb_x++) { slb_num = get_slab_number(slb_x, slb_y); slb = get_slabmap_direct(slb_num); treasure_map[slb_num] = 0; const struct SlabAttr *slbattr; slbattr = get_slab_attrs(slb); // Mark areas which are not valuable if ((slbattr->block_flags & (SlbAtFlg_Valuable)) == 0) { treasure_map[slb_num] |= 0x01; } } } // Add treasures to lookup as gold veins gold_next_idx = 0; for (slb_y = 0; slb_y < map_tiles_y; slb_y++) { for (slb_x = 0; slb_x < map_tiles_x; slb_x++) { slb_num = get_slab_number(slb_x, slb_y); if ( ((treasure_map[slb_num] & 0x01) == 0) && ((treasure_map[slb_num] & 0x02) == 0) ) { check_treasure_map(treasure_map, vein_list, &gold_next_idx, slb_x, slb_y); } } } SYNCDBG(8,"Found %ld possible digging locations",gold_next_idx); }
long calculate_effeciency_score_for_room_slab(SlabCodedCoords slab_num, PlayerNumber plyr_idx) { //return _DK_calculate_effeciency_score_for_room_slab(slab_num, plyr_idx); long eff_score; TbBool is_room_inside; is_room_inside = true; eff_score = 0; struct SlabMap *slb; slb = get_slabmap_direct(slab_num); long n; for (n=1; n < AROUND_SLAB_LENGTH; n+=2) { long round_slab_num; round_slab_num = slab_num + around_slab[n]; struct SlabMap *round_slb; round_slb = get_slabmap_direct(round_slab_num); if (!slabmap_block_invalid(round_slb)) { MapSlabCoord slb_x,slb_y; slb_x = slb_num_decode_x(round_slab_num); slb_y = slb_num_decode_y(round_slab_num); // Per slab code if ((slabmap_owner(round_slb) == slabmap_owner(slb)) && (round_slb->kind == slb->kind)) { eff_score += 2; } else { is_room_inside = false; switch (find_core_slab_type(slb_x, slb_y)) { case SlbT_ROCK: case SlbT_GOLD: case SlbT_EARTH: case SlbT_GEMS: eff_score++; break; case SlbT_WALLDRAPE: if (slabmap_owner(round_slb) == slabmap_owner(slb)) eff_score += 2; break; case SlbT_DOORWOOD1: if (slabmap_owner(round_slb) == slabmap_owner(slb)) eff_score += 2; break; default: break; } } // Per slab code ends } } // If we already know this is not an inside - finish if (!is_room_inside) { return eff_score; } // Make sure this is room inside by checking corners for (n=0; n < AROUND_SLAB_LENGTH; n+=2) { long round_slab_num; round_slab_num = slab_num + around_slab[n]; struct SlabMap *round_slb; round_slb = get_slabmap_direct(round_slab_num); if (!slabmap_block_invalid(round_slb)) { // Per slab code if ((slabmap_owner(round_slb) != slabmap_owner(slb)) || (round_slb->kind != slb->kind)) { is_room_inside = 0; break; } // Per slab code ends } } if (is_room_inside) { eff_score += 2; } return eff_score; }
void make_safe(struct PlayerInfo *player) { //_DK_make_safe(player); unsigned char *areamap; areamap = (unsigned char *)scratch; MapSlabCoord slb_x, slb_y; // Prepare the array to remember which slabs were already taken care of for (slb_y=0; slb_y < map_tiles_y; slb_y++) { for (slb_x=0; slb_x < map_tiles_x; slb_x++) { SlabCodedCoords slb_num; struct SlabMap *slb; slb_num = get_slab_number(slb_x, slb_y); slb = get_slabmap_direct(slb_num); struct SlabAttr *slbattr; slbattr = get_slab_attrs(slb); if ((slbattr->block_flags & (SlbAtFlg_Filled|SlbAtFlg_Digable|SlbAtFlg_Valuable)) != 0) areamap[slb_num] = 0x01; else areamap[slb_num] = 0x00; } } { const struct Coord3d *center_pos; center_pos = dungeon_get_essential_pos(player->id_number); slb_x = subtile_slab_fast(center_pos->x.stl.num); slb_y = subtile_slab_fast(center_pos->y.stl.num); SlabCodedCoords slb_num; slb_num = get_slab_number(slb_x, slb_y); areamap[slb_num] |= 0x02; } unsigned int list_cur, list_len; PlayerNumber plyr_idx; plyr_idx = player->id_number; SlabCodedCoords *slblist; slblist = (SlabCodedCoords *)(scratch + map_tiles_x*map_tiles_y); list_len = 0; list_cur = 0; while (list_cur <= list_len) { SlabCodedCoords slb_num; if (slb_x > 0) { slb_num = get_slab_number(slb_x-1, slb_y); if ((areamap[slb_num] & 0x01) != 0) { areamap[slb_num] |= 0x02; struct SlabMap *slb; slb = get_slabmap_direct(slb_num); struct SlabAttr *slbattr; slbattr = get_slab_attrs(slb); if ((slbattr->category == SlbAtCtg_FriableDirt) && slab_by_players_land(plyr_idx, slb_x-1, slb_y)) { unsigned char pretty_type; pretty_type = choose_pretty_type(plyr_idx, slb_x-1, slb_y); place_slab_type_on_map(pretty_type, slab_subtile(slb_x-1,0), slab_subtile(slb_y,0), plyr_idx, 1); do_slab_efficiency_alteration(slb_x-1, slb_y); fill_in_reinforced_corners(plyr_idx, slb_x-1, slb_y); } } else if ((areamap[slb_num] & 0x02) == 0) { areamap[slb_num] |= 0x02; slblist[list_len] = slb_num; list_len++; } } if (slb_x < map_tiles_x-1) { slb_num = get_slab_number(slb_x+1, slb_y); if ((areamap[slb_num] & 0x01) != 0) { areamap[slb_num] |= 0x02; struct SlabMap *slb; slb = get_slabmap_direct(slb_num); struct SlabAttr *slbattr; slbattr = get_slab_attrs(slb); if ((slbattr->category == SlbAtCtg_FriableDirt) && slab_by_players_land(plyr_idx, slb_x+1, slb_y)) { unsigned char pretty_type; pretty_type = choose_pretty_type(plyr_idx, slb_x+1, slb_y); place_slab_type_on_map(pretty_type, slab_subtile(slb_x+1,0), slab_subtile(slb_y,0), plyr_idx, 1u); do_slab_efficiency_alteration(slb_x+1, slb_y); fill_in_reinforced_corners(plyr_idx, slb_x+1, slb_y); } } else if ((areamap[slb_num] & 0x02) == 0) { areamap[slb_num] |= 0x02; slblist[list_len] = slb_num; list_len++; } } if (slb_y > 0) { slb_num = get_slab_number(slb_x, slb_y-1); if ((areamap[slb_num] & 0x01) != 0) { areamap[slb_num] |= 0x02; struct SlabMap *slb; slb = get_slabmap_direct(slb_num); struct SlabAttr *slbattr; slbattr = get_slab_attrs(slb); if ((slbattr->category == SlbAtCtg_FriableDirt) && slab_by_players_land(plyr_idx, slb_x, slb_y-1)) { unsigned char pretty_type; pretty_type = choose_pretty_type(plyr_idx, slb_x, slb_y-1); place_slab_type_on_map(pretty_type, slab_subtile(slb_x,0), slab_subtile(slb_y-1,0), plyr_idx, 1u); do_slab_efficiency_alteration(slb_x, slb_y-1); fill_in_reinforced_corners(plyr_idx, slb_x, slb_y-1); } } else if ((areamap[slb_num] & 0x02) == 0) { areamap[slb_num] |= 0x02; slblist[list_len] = slb_num; list_len++; } } if (slb_y < map_tiles_y-1) { slb_num = get_slab_number(slb_x, slb_y+1); if ((areamap[slb_num] & 0x01) != 0) { areamap[slb_num] |= 0x02; struct SlabMap *slb; slb = get_slabmap_direct(slb_num); struct SlabAttr *slbattr; slbattr = get_slab_attrs(slb); if ((slbattr->category == SlbAtCtg_FriableDirt) && slab_by_players_land(plyr_idx, slb_x, slb_y+1)) { unsigned char pretty_type; pretty_type = choose_pretty_type(plyr_idx, slb_x, slb_y+1); place_slab_type_on_map(pretty_type, slab_subtile(slb_x,0), slab_subtile(slb_y+1,0), plyr_idx, 1u); do_slab_efficiency_alteration(slb_x, slb_y+1); fill_in_reinforced_corners(plyr_idx, slb_x, slb_y+1); } } else if ((areamap[slb_num] & 0x02) == 0) { areamap[slb_num] |= 0x02; slblist[list_len] = slb_num; list_len++; } } slb_x = slb_num_decode_x(slblist[list_cur]); slb_y = slb_num_decode_y(slblist[list_cur]); list_cur++; } pannel_map_update(0, 0, map_subtiles_x+1, map_subtiles_y+1); }
void check_treasure_map(unsigned char *treasure_map, unsigned short *vein_list, long *gold_next_idx, MapSlabCoord veinslb_x, MapSlabCoord veinslb_y) { struct GoldLookup *gldlook; struct SlabMap *slb; SlabCodedCoords slb_num,slb_around; MapSlabCoord slb_x,slb_y; long gold_slabs,gem_slabs; long vein_total,vein_idx; long gld_v1,gld_v2,gld_v3; long gold_idx; // First, find a vein vein_total = 0; slb_x = veinslb_x; slb_y = veinslb_y; gld_v1 = 0; gld_v2 = 0; gld_v3 = 0; gem_slabs = 0; gold_slabs = 0; slb_num = get_slab_number(slb_x, slb_y); treasure_map[slb_num] |= 0x02; for (vein_idx=0; vein_idx <= vein_total; vein_idx++) { gld_v1 += slb_x; gld_v2 += slb_y; gld_v3++; slb_around = get_slab_number(slb_x, slb_y); slb = get_slabmap_direct(slb_around); if (slb->kind == SlbT_GEMS) { gem_slabs++; } else { gold_slabs++; slb_around = get_slab_number(slb_x-1, slb_y); if ((treasure_map[slb_around] & 0x03) == 0) { treasure_map[slb_around] |= 0x02; vein_list[vein_total] = slb_around; vein_total++; } slb_around = get_slab_number(slb_x+1, slb_y); if ((treasure_map[slb_around] & 0x03) == 0) { treasure_map[slb_around] |= 0x02; vein_list[vein_total] = slb_around; vein_total++; } slb_around = get_slab_number(slb_x, slb_y-1); if ((treasure_map[slb_around] & 0x03) == 0) { treasure_map[slb_around] |= 0x02; vein_list[vein_total] = slb_around; vein_total++; } slb_around = get_slab_number(slb_x, slb_y+1); if ((treasure_map[slb_around] & 0x03) == 0) { treasure_map[slb_around] |= 0x02; vein_list[vein_total] = slb_around; vein_total++; } } // Move to next slab in list slb_x = slb_num_decode_x(vein_list[vein_idx]); slb_y = slb_num_decode_y(vein_list[vein_idx]); } // Now get a GoldLookup struct to put the vein into if (*gold_next_idx < GOLD_LOOKUP_COUNT) { gold_idx = *gold_next_idx; (*gold_next_idx)++; } else { gold_idx = smaller_gold_vein_lookup_idx(gold_slabs, gem_slabs); } // Write the vein to GoldLookup item if (gold_idx != -1) { gldlook = get_gold_lookup(gold_idx); LbMemorySet(gldlook, 0, sizeof(struct GoldLookup)); gldlook->flags |= 0x01; gldlook->x_stl_num = slab_subtile_center(gld_v1 / gld_v3); gldlook->y_stl_num = slab_subtile_center(gld_v2 / gld_v3); gldlook->field_A = gold_slabs; gldlook->field_C = 0; gldlook->num_gold_slabs = gold_slabs; gldlook->num_gem_slabs = gem_slabs; SYNCDBG(8,"Added vein %d at (%d,%d)",(int)gold_idx,(int)gldlook->x_stl_num,(int)gldlook->y_stl_num); } }
/** * This function generates "expand room" action on a tile which is claimed ground and could have a room placed on. * It is used to fix vandalized or not fully built rooms, so that they will cover the whole area digged for them. * * @param comp * @param check Computer check data. * @param room The room to be checked for expand. * @param max_radius The max distance of the slab being put to the center of the room, in subtiles. * @param around_start Random value used for setting starting point of the check process. * @return */ TbBool computer_check_for_expand_specific_room(struct Computer2 *comp, struct ComputerCheck * check, struct Room *room, MapSubtlCoord max_radius, long around_start) { struct Dungeon *dungeon; dungeon = comp->dungeon; unsigned long i; unsigned long k; k = 0; i = room->slabs_list; while (i > 0) { MapSlabCoord slb_x,slb_y; struct SlabMap *slb; slb = get_slabmap_direct(i); slb_x = slb_num_decode_x(i); slb_y = slb_num_decode_y(i); i = get_next_slab_number_in_room(i); // Per-slab code int room_around, claimed_around; room_around = count_slabs_around_of_kind(slb_x, slb_y, slb->kind, dungeon->owner); claimed_around = 0; if (room_around < 8) { claimed_around = count_slabs_around_of_kind(slb_x, slb_y, SlbT_CLAIMED, dungeon->owner); } if (((room_around >= 3) && (claimed_around >= 2) && (room_around+claimed_around < 8)) // If there's something besides room and claimed, then grow more aggressively || ((room_around >= 4) && (claimed_around >= 2) && (room_around+claimed_around >= 8)) // If we're in open space, don't expand that much || ((room_around >= 6) && (claimed_around >= 1))) // Allow fixing one-slab holes inside rooms { unsigned long m,n; m = around_start % SMALL_AROUND_SLAB_LENGTH; for (n=0; n < SMALL_AROUND_SLAB_LENGTH; n++) { MapSlabCoord arslb_x, arslb_y; arslb_x = slb_x + small_around[m].delta_x; arslb_y = slb_y + small_around[m].delta_y; MapSubtlCoord arstl_x, arstl_y; arstl_x = slab_subtile_center(arslb_x); arstl_y = slab_subtile_center(arslb_y); long dist; dist = abs(room->central_stl_x - arstl_x) + abs(room->central_stl_y - arstl_y); if (dist <= max_radius) { if (can_build_room_at_slab(dungeon->owner, room->kind, arslb_x, arslb_y)) { if (try_game_action(comp, dungeon->owner, GA_PlaceRoom, 0, arstl_x, arstl_y, 1, room->kind) > Lb_OK) { return true; } } } m = (m+1) % SMALL_AROUND_SLAB_LENGTH; } } // Per-slab code ends k++; if (k > room->slabs_count) { ERRORLOG("Infinite loop detected when sweeping room slabs"); break; } } return false; }