/** * Finds a safe and unused, adjacent position in room for a creature. * * @param pos Position of the creature to be moved. * @param owner Room owner to keep. * @return Coded subtiles of the new position, or 0 on failure. * @see person_get_somewhere_adjacent_in_room() */ SubtlCodedCoords find_unused_adjacent_position_in_workshop(const struct Coord3d *pos, long owner) { static const struct Around corners[] = { {1,2}, {0,1}, {1,0}, {2,1} }; long i; for (i=0; i < SMALL_AROUND_LENGTH; i++) { MapSlabCoord slb_x, slb_y; slb_x = subtile_slab_fast(pos->x.stl.num) + (long)small_around[i].delta_x; slb_y = subtile_slab_fast(pos->y.stl.num) + (long)small_around[i].delta_y; struct SlabMap *slb; slb = get_slabmap_block(slb_x, slb_y); if ((slb->kind == SlbT_WORKSHOP) && (slabmap_owner(slb) == owner)) { struct Thing *mnfc_creatng; MapSubtlCoord stl_x, stl_y; stl_x = slab_subtile(slb_x, corners[i].delta_x); stl_y = slab_subtile(slb_y, corners[i].delta_y); mnfc_creatng = get_other_creature_manufacturing_on_subtile(owner, stl_x, stl_y, INVALID_THING); if (!thing_is_invalid(mnfc_creatng)) { // Position used by another manufacturer continue; } struct Thing *objtng; objtng = get_workshop_equipment_to_work_with_on_subtile(owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y)); if (thing_is_invalid(objtng)) { // Position has no work equipment nearby continue; } // Found an acceptable position return get_subtile_number(stl_x, stl_y); } } return 0; }
TbBool update_trap_trigger_pressure(struct Thing *traptng) { MapSlabCoord slb_x, slb_y; slb_x = subtile_slab_fast(traptng->mappos.x.stl.num); slb_y = subtile_slab_fast(traptng->mappos.y.stl.num); MapSubtlCoord stl_x, stl_y; MapSubtlCoord end_stl_x, end_stl_y; end_stl_x = slab_subtile(slb_x,2); end_stl_y = slab_subtile(slb_y,2); for (stl_y=slab_subtile(slb_y,0); stl_y <= end_stl_y; stl_y++) { for (stl_x=slab_subtile(slb_x,0); stl_x <= end_stl_x; stl_x++) { struct Thing *creatng; creatng = INVALID_THING; if (find_pressure_trigger_trap_target_passing_by_subtile(traptng, stl_x, stl_y, &creatng)) { activate_trap(traptng, creatng); return true; } } } return false; }
TbBool tag_cursor_blocks_place_trap(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoord stl_y) { SYNCDBG(7,"Starting"); int floor_height; TbBool can_place; MapSlabCoord slb_x, slb_y; slb_x = subtile_slab_fast(stl_x); slb_y = subtile_slab_fast(stl_y); can_place = can_place_trap_on(plyr_idx, stl_x, stl_y); floor_height = floor_height_for_volume_box(plyr_idx, slb_x, slb_y); if (is_my_player_number(plyr_idx)) { if (!game_is_busy_doing_gui() && (game.small_map_state != 2)) { // Move to first subtile on a slab stl_x = slab_subtile(slb_x,0); stl_y = slab_subtile(slb_y,0); draw_map_volume_box(subtile_coord(stl_x,0), subtile_coord(stl_y,0), subtile_coord(stl_x+STL_PER_SLB,0), subtile_coord(stl_y+STL_PER_SLB,0), floor_height, can_place); } } return can_place; }
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; }
void process_creature_in_training_room(struct Thing *thing, struct Room *room) { static const struct Around corners[] = { {1, 2}, {0, 1}, {1, 0}, {2, 1}, }; struct CreatureControl *cctrl; struct CreatureStats *crstat; struct Thing *traintng; struct Thing *crtng; struct CreatureControl *cctrl2; struct Coord3d pos; long speed,dist; long i; cctrl = creature_control_get_from_thing(thing); SYNCDBG(8,"Starting %s mode %d",thing_model_name(thing),(int)cctrl->training.mode); //_DK_process_creature_in_training_room(thing, room); return; cctrl->field_4A = 0; switch (cctrl->training.mode) { case CrTrMd_SearchForTrainPost: // While we're in an instance, just wait if (cctrl->instance_id != CrInst_NULL) break; // On timeout, search for nearby training posts to start training ASAP if (cctrl->training.search_timeout < 1) { SYNCDBG(6,"Search timeout - selecting post nearest to (%d,%d)",(int)thing->mappos.x.stl.num, (int)thing->mappos.y.stl.num); setup_training_search_for_post(thing); cctrl->training.search_timeout = 100; break; } // Do a moving step cctrl->training.search_timeout--; speed = get_creature_speed(thing); i = creature_move_to(thing, &cctrl->moveto_pos, speed, 0, 0); if (i == 1) { // Move target is reached - find a training post which is supposed to be around here traintng = find_training_post_just_next_to_creature(thing); if (thing_is_invalid(traintng)) { SYNCDBG(6,"Reached (%d,%d) but there's no training post there",(int)thing->mappos.x.stl.num, (int)thing->mappos.y.stl.num); setup_move_to_new_training_position(thing, room, false); break; } // Found - go to next mode cctrl->training.mode = CrTrMd_SelectPositionNearTrainPost; cctrl->training.search_timeout = 50; } else if (i == -1) { ERRORLOG("Cannot get to (%d,%d) in the training room",(int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num); set_start_state(thing); } break; case CrTrMd_SelectPositionNearTrainPost: for (i=0; i < 4; i++) { long slb_x,slb_y; long stl_x,stl_y; struct SlabMap *slb; slb_x = subtile_slab_fast(thing->mappos.x.stl.num) + (long)small_around[i].delta_x; slb_y = subtile_slab_fast(thing->mappos.y.stl.num) + (long)small_around[i].delta_y; slb = get_slabmap_block(slb_x,slb_y); if ((slb->kind != SlbT_TRAINING) || (slabmap_owner(slb) != thing->owner)) continue; stl_x = slab_subtile(slb_x,corners[i].delta_x); stl_y = slab_subtile(slb_y,corners[i].delta_y); traintng = INVALID_THING; // Check if any other creature is using that post; allow only unused posts crtng = get_creature_of_model_training_at_subtile_and_owned_by(stl_x, stl_y, -1, thing->owner, thing->index); if (thing_is_invalid(crtng)) { traintng = get_object_at_subtile_of_model_and_owned_by(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 31, thing->owner); } if (!thing_is_invalid(traintng)) { cctrl->training.pole_stl_x = slab_subtile_center(subtile_slab_fast(thing->mappos.x.stl.num)); cctrl->training.pole_stl_y = slab_subtile_center(subtile_slab_fast(thing->mappos.y.stl.num)); cctrl->moveto_pos.x.stl.num = stl_x; cctrl->moveto_pos.y.stl.num = stl_y; cctrl->moveto_pos.x.stl.pos = 128; cctrl->moveto_pos.y.stl.pos = 128; cctrl->moveto_pos.z.val = get_thing_height_at(thing, &cctrl->moveto_pos); if (thing_in_wall_at(thing, &cctrl->moveto_pos)) { ERRORLOG("Illegal setup to (%d,%d)", (int)cctrl->moveto_pos.x.stl.num, (int)cctrl->moveto_pos.y.stl.num); break; } cctrl->training.mode = CrTrMd_MoveToTrainPost; break; } } if (cctrl->training.mode == CrTrMd_SelectPositionNearTrainPost) setup_move_to_new_training_position(thing, room, 1); break; case CrTrMd_MoveToTrainPost: speed = get_creature_speed(thing); i = creature_move_to(thing, &cctrl->moveto_pos, speed, 0, 0); if (i == 1) { // If there's already someone training at that position, go somewhere else crtng = get_creature_of_model_training_at_subtile_and_owned_by(thing->mappos.x.stl.num, thing->mappos.y.stl.num, -1, thing->owner, thing->index); if (!thing_is_invalid(crtng)) { setup_move_to_new_training_position(thing, room, 1); break; } // Otherwise, train at this position cctrl->training.mode = CrTrMd_TurnToTrainPost; } else if (i == -1) { ERRORLOG("Cannot get where we're going in the training room."); set_start_state(thing); } break; case CrTrMd_TurnToTrainPost: pos.x.val = subtile_coord_center(cctrl->training.pole_stl_x); pos.y.val = subtile_coord_center(cctrl->training.pole_stl_y); if (creature_turn_to_face(thing, &pos) < 56) { cctrl->training.mode = CrTrMd_DoTrainWithTrainPost; cctrl->training.train_timeout = 75; } break; case CrTrMd_PartnerTraining: if (cctrl->training.partner_idx == 0) { setup_move_to_new_training_position(thing, room, false); return; } crtng = thing_get(cctrl->training.partner_idx); TRACE_THING(crtng); if (!thing_exists(crtng) || (get_creature_state_besides_move(crtng) != CrSt_Training) || (crtng->creation_turn != cctrl->training.partner_creation)) { SYNCDBG(8,"The %s cannot start partner training - creature to train with is gone.",thing_model_name(thing)); setup_move_to_new_training_position(thing, room, false); return; } cctrl2 = creature_control_get_from_thing(crtng); if (cctrl2->training.partner_idx != thing->index) { SYNCDBG(6,"The %s cannot start partner training - %s changed the partner.",thing_model_name(thing),thing_model_name(crtng)); cctrl->training.partner_idx = 0; setup_move_to_new_training_position(thing, room, false); break; } if (get_room_thing_is_on(crtng) != room) { SYNCDBG(8,"The %s cannot start partner training - partner has left the room.",thing_model_name(thing)); cctrl->training.partner_idx = 0; cctrl2->training.partner_idx = 0; setup_move_to_new_training_position(thing, room, false); break; } crstat = creature_stats_get_from_thing(thing); dist = get_combat_distance(thing, crtng); if (dist > 284) { if (creature_move_to(thing, &crtng->mappos, get_creature_speed(thing), 0, 0) == -1) { WARNLOG("The %s cannot navigate to training partner",thing_model_name(thing)); setup_move_to_new_training_position(thing, room, false); cctrl->training.partner_idx = 0; } } else if (dist >= 156) { if (creature_turn_to_face(thing, &crtng->mappos) < 56) { cctrl->training.train_timeout--; if (cctrl->training.train_timeout > 0) { if ((cctrl->instance_id == CrInst_NULL) && ((cctrl->training.train_timeout % 8) == 0)) { set_creature_instance(thing, CrInst_SWING_WEAPON_SWORD, 1, 0, 0); } } else { if (cctrl->instance_id == CrInst_NULL) { setup_move_to_new_training_position(thing, room, false); cctrl->training.partner_idx = 0; } else { cctrl->training.train_timeout = 1; } cctrl->exp_points += (room->efficiency * crstat->training_value); } } } else { creature_retreat_from_combat(thing, crtng, 33, 0); } break; case CrTrMd_DoTrainWithTrainPost: if (cctrl->training.train_timeout > 0) { // While training timeout is positive, continue initiating the train instances cctrl->training.train_timeout--; if ((cctrl->instance_id == CrInst_NULL) && ((cctrl->training.train_timeout % 8) == 0)) { set_creature_instance(thing, CrInst_SWING_WEAPON_SWORD, 1, 0, 0); } } else { // Wait for the instance to end, then select new move position if (cctrl->instance_id != CrInst_NULL) { cctrl->training.train_timeout = 0; } else { cctrl->training.train_timeout = 0; setup_move_to_new_training_position(thing, room, true); } } break; default: WARNLOG("Invalid %s training mode %d; reset",thing_model_name(thing),(int)cctrl->training.mode); cctrl->training.mode = CrTrMd_SearchForTrainPost; cctrl->training.search_timeout = 0; break; } SYNCDBG(18,"End"); }
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); }