int find_first_step(sh_int src, sh_int target, int stay_zone) { int curr_dir; sh_int curr_room; int src_zone = ((src - (src % 100)) / 100); int target_zone = ((target - (target % 100)) / 100); if (src < 0 || src > top_of_world || target < 0 || target > top_of_world) { stderr_log("Illegal value passed to find_first_step (graph.c)"); return BFS_ERROR; } /* dez 19980805 if ((src_zone != target_zone && stay_zone == 1) || stay_zone == 2) { return BFS_NO_PATH; } */ if (src_zone != target_zone && stay_zone == 1) { return BFS_NO_PATH; } if (src == target) { return BFS_ALREADY_THERE; } /* clear marks first */ for (curr_room = 0; curr_room <= top_of_world; curr_room++) { UNMARK(curr_room); } MARK(src); /* first, enqueue the first steps, saving which direction we're going. */ for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) { if (VALID_EDGE(src, curr_dir)) { MARK(TOROOM(src, curr_dir)); bfs_enqueue(TOROOM(src, curr_dir), curr_dir); } } /* now, do the classic BFS. */ while (queue_head) { if (queue_head->room == target) { curr_dir = queue_head->dir; bfs_clear_queue(); return curr_dir; } else { for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) { if (VALID_EDGE(queue_head->room, curr_dir)) { MARK(TOROOM(queue_head->room, curr_dir)); bfs_enqueue(TOROOM(queue_head->room, curr_dir), queue_head->dir); } } bfs_dequeue(); } } return BFS_NO_PATH; }
int VALID_EDGE(room_rnum x, int y) { if (world[x].dir_option[y] == NULL || TOROOM(x, y) == NOWHERE) return 0; if (track_through_doors == FALSE && IS_CLOSED(x, y)) return 0; if (ROOM_FLAGGED(TOROOM(x, y), ROOM_NOTRACK) || IS_MARKED(TOROOM(x, y))) return 0; return 1; }
static int VALID_EDGE(room_rnum x, int y) { if (world[x].dir_option[y] == NULL || TOROOM(x, y) == NOWHERE) return 0; if (CONFIG_TRACK_T_DOORS == FALSE && IS_CLOSED(x, y)) return 0; if (ROOM_FLAGGED(TOROOM(x, y), ROOM_NOTRACK) || IS_MARKED(TOROOM(x, y))) return 0; return 1; }
int VALID_EDGE(room_rnum x, int y, int edge_range, int through_doors) { if (world[x]->dir_option[y] == NULL || TOROOM(x, y) == NOWHERE) return 0; // Попытка уползти в другую зону if (edge_range == EDGE_ZONE && (world[x]->zone != world[TOROOM(x, y)]->zone)) return 0; if (through_doors == FALSE && IS_CLOSED(x, y)) return 0; if (ROOM_FLAGGED(TOROOM(x, y), ROOM_NOTRACK) || IS_MARKED(TOROOM(x, y))) return 0; return 1; }
/* * find_first_step: given a source room and a target room, find the first * step on the shortest path from the source to the target. * * Intended usage: in mobile_activity, give a mob a dir to go if they're * tracking another mob or a PC. Or, a 'track' skill for PCs. */ int find_first_step(room_rnum src, room_rnum target) { int curr_dir; room_rnum curr_room; if (src == NOWHERE || target == NOWHERE || src > top_of_world || target > top_of_world) { extended_mudlog(NRM, SYSL_BUGS, TRUE, "Illegal value %d or %d passed to find_first_step. (%s)", src, target, __FILE__); return (BFS_ERROR); } if (src == target) return (BFS_ALREADY_THERE); /* clear marks first, some OLC systems will save the mark. */ for (curr_room = 0; curr_room <= top_of_world; curr_room++) UNMARK(curr_room); MARK(src); /* first, enqueue the first steps, saving which direction we're going. */ for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) if (VALID_EDGE(src, curr_dir)) { MARK(TOROOM(src, curr_dir)); bfs_enqueue(TOROOM(src, curr_dir), curr_dir); } /* now, do the classic BFS. */ while (queue_head) { if (queue_head->room == target) { curr_dir = queue_head->dir; bfs_clear_queue(); return (curr_dir); } else { for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) if (VALID_EDGE(queue_head->room, curr_dir)) { MARK(TOROOM(queue_head->room, curr_dir)); bfs_enqueue(TOROOM(queue_head->room, curr_dir), queue_head->dir); } bfs_dequeue(); } } return (BFS_NO_PATH); }
/* should do sanity checks on vnums & remove invalid records */ void House_boot(void) { struct house_control_rec temp_house; int real_house, real_atrium; FILE *fl; memset((char *)house_control,0,sizeof(struct house_control_rec)*MAX_HOUSES); if (!(fl = fopen(HCONTROL_FILE, "rb"))) { log("House control file does not exist."); return; } while (!feof(fl) && num_of_houses < MAX_HOUSES) { fread(&temp_house, sizeof(struct house_control_rec), 1, fl); if (feof(fl)) break; if (get_name_by_id(temp_house.owner) == NULL) continue; /* owner no longer exists -- skip */ if ((real_house = real_room(temp_house.vnum)) < 0) continue; /* this vnum doesn't exist -- skip */ if ((find_house(temp_house.vnum)) >= 0) continue; /* this vnum is already a hosue -- skip */ if ((real_atrium = real_room(temp_house.atrium)) < 0) continue; /* house doesn't have an atrium -- skip */ if (temp_house.exit_num < 0 || temp_house.exit_num >= NUM_OF_DIRS) continue; /* invalid exit num -- skip */ if (TOROOM(real_house, temp_house.exit_num) != real_atrium) continue; /* exit num mismatch -- skip */ house_control[num_of_houses++] = temp_house; SET_BIT_AR(ROOM_FLAGS(real_house), ROOM_HOUSE); SET_BIT_AR(ROOM_FLAGS(real_house), ROOM_PRIVATE); SET_BIT_AR(ROOM_FLAGS(real_atrium), ROOM_ATRIUM); House_load(temp_house.vnum); } fclose(fl); House_save_control(); }
/* * find_first_step: given a source room and a target room, find the first * step on the shortest path from the source to the target. * * Intended usage: in mobile_activity, give a mob a dir to go if they're * tracking another mob or a PC. Or, a 'track' skill for PCs. */ int find_first_step(room_rnum src, room_rnum target, CHAR_DATA * ch) { int curr_dir, edge, through_doors; room_rnum curr_room, rnum_start = FIRST_ROOM, rnum_stop = top_of_world; if (src < FIRST_ROOM || src > top_of_world || target < FIRST_ROOM || target > top_of_world) { log("SYSERR: Illegal value %d or %d passed to find_first_step. (%s)", src, target, __FILE__); return (BFS_ERROR); } if (src == target) return (BFS_ALREADY_THERE); // clear marks first, some OLC systems will save the mark. if (IS_NPC(ch)) { // Запрещаем искать мобам в другой зоне ... if (world[src]->zone != world[target]->zone) return (BFS_ERROR); get_zone_rooms(world[src]->zone, &rnum_start, &rnum_stop); // Запрещаем мобам искать через двери ... through_doors = FALSE; edge = EDGE_ZONE; } else { // Игроки полноценно ищут в мире. through_doors = TRUE; edge = EDGE_WORLD; } for (curr_room = rnum_start; curr_room <= rnum_stop; curr_room++) UNMARK(curr_room); MARK(src); // переписано на вектор без реального очищения, чтобы не заниматься сотнями аллокаций памяти в секунду зря -- Krodo static std::vector<bfs_queue_struct> bfs_queue; static struct bfs_queue_struct temp_queue; // first, enqueue the first steps, saving which direction we're going. for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) if (VALID_EDGE(src, curr_dir, edge, through_doors)) { MARK(TOROOM(src, curr_dir)); temp_queue.room = TOROOM(src, curr_dir); temp_queue.dir = curr_dir; bfs_queue.push_back(temp_queue); } // now, do the classic BFS. for (unsigned int i = 0; i < bfs_queue.size(); ++i) { if (bfs_queue[i].room == target) { curr_dir = bfs_queue[i].dir; bfs_queue.clear(); return curr_dir; } else { for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) { if (VALID_EDGE(bfs_queue[i].room, curr_dir, edge, through_doors)) { MARK(TOROOM(bfs_queue[i].room, curr_dir)); temp_queue.room = TOROOM(bfs_queue[i].room, curr_dir); temp_queue.dir = bfs_queue[i].dir; bfs_queue.push_back(temp_queue); } } } } bfs_queue.clear(); sprintf(buf, "Mob (mob: %s vnum: %d) can't find path.", GET_NAME(ch), GET_MOB_VNUM(ch)); mudlog(buf, NRM, -1, ERRLOG, TRUE); return (BFS_NO_PATH); }
void hedit_parse(struct descriptor_data *d, char *arg) { int i, j; if (OLC_MODE(d) > HEDIT_NUMERICAL_RESPONSE) { if (!isdigit(arg[0]) && ((*arg == '-') && (!isdigit(arg[1])))) { write_to_output(d, TRUE, "Field must be numerical, try again : "); return; } } switch (OLC_MODE(d)) { /*-------------------------------------------------------------------*/ case SEDIT_CONFIRM_SAVESTRING: switch (*arg) { case 'y': case 'Y': write_to_output(d, TRUE, "Saving house to memory.\r\n"); hedit_save_internally(d); hedit_save_to_disk(); extended_mudlog(BRF, SYSL_OLC, TRUE, "%s edits house %d.", GET_NAME(d->character), OLC_NUM(d)); cleanup_olc(d, CLEANUP_STRUCTS); return; case 'n': case 'N': cleanup_olc(d, CLEANUP_ALL); return; default: write_to_output(d, TRUE, "Invalid choice!\r\nDo you wish to save the house? : "); return; } break; /*-------------------------------------------------------------------*/ case HEDIT_MAIN_MENU: i = 0; switch (*arg) { case 'q': case 'Q': if (OLC_VAL(d)) { /* Anything been changed? */ write_to_output(d, TRUE, "Do you wish to save the changes to the house? (y/n) : "); OLC_MODE(d) = HEDIT_CONFIRM_SAVESTRING; } else cleanup_olc(d, CLEANUP_ALL); return; case '0': OLC_MODE(d) = HEDIT_OWNER; write_to_output(d, TRUE, "Enter the name of the house owner : "); i--; return; case '1': OLC_MODE(d) = HEDIT_ATRIUM; write_to_output(d, TRUE, "Enter the room number of the atrium : "); i++; return; case '2': OLC_MODE(d) = HEDIT_EXIT; hedit_exits_menu(d); return; case '3': OLC_MODE(d) = HEDIT_MODE; hedit_modes_menu(d); return; case '4': OLC_MODE(d) = HEDIT_PRUNE_SAFE; hedit_prune_safe_menu(d); return; case '5': OLC_MODE(d) = HEDIT_COST; write_to_output(d, TRUE, "Enter the house cost : "); i++; return; case '6': OLC_MODE(d) = HEDIT_MAX_SECURE; write_to_output(d, TRUE, "Enter maximum number of secure containers : "); i++; return; case '7': OLC_MODE(d) = HEDIT_MAX_LOCKED; write_to_output(d, TRUE, "Enter maximum number of locked-down items : "); i++; return; case 'c': case 'C': hedit_owners_menu(d); return; case 'g': case 'G': hedit_guests_menu(d); return; case 'r': case 'R': hedit_rooms_menu(d); return; case 'd': case 'D': delete_house(d, OLC_NUM(d)); cleanup_olc(d, CLEANUP_ALL); return; default: hedit_disp_menu(d); return; } if (i == 0) break; else if (i == 1) write_to_output(d, TRUE, "\r\nEnter new value : "); else if (i == -1) write_to_output(d, TRUE, "\r\nEnter new text :\r\n] "); else write_to_output(d, TRUE, "Oops...\r\n"); return; /*-------------------------------------------------------------------*/ case HEDIT_ROOMS_MENU: switch (*arg) { case 'a': case 'A': write_to_output(d, TRUE, "\r\nEnter new room vnum number : "); OLC_MODE(d) = HEDIT_NEW_ROOM; return; case 'c': case 'C': hedit_compact_rooms_menu(d); return; case 'l': case 'L': hedit_rooms_menu(d); return; case 'd': case 'D': write_to_output(d, TRUE, "\r\nDelete which room? : "); OLC_MODE(d) = HEDIT_DELETE_ROOM; return; case 'q': case 'Q': break; } break; /*-------------------------------------------------------------------*/ case HEDIT_COWNERS_MENU: switch (*arg) { case 'a': case 'A': write_to_output(d, TRUE, "\r\nEnter player name : "); OLC_MODE(d) = HEDIT_NEW_COWNER; return; case 'l': case 'L': hedit_owners_menu(d); return; case 'd': case 'D': write_to_output(d, TRUE, "\r\nDelete which co-owner? : "); OLC_MODE(d) = HEDIT_DELETE_COWNER; return; case 'q': case 'Q': break; } break; /*-------------------------------------------------------------------*/ case HEDIT_GUESTS_MENU: switch (*arg) { case 'a': case 'A': write_to_output(d, TRUE, "\r\nEnter player name : "); OLC_MODE(d) = HEDIT_NEW_GUEST; return; case 'l': case 'L': hedit_guests_menu(d); return; case 'd': case 'D': write_to_output(d, TRUE, "\r\nDelete which guest? : "); OLC_MODE(d) = HEDIT_DELETE_GUEST; return; case 'q': case 'Q': break; } break; /*-------------------------------------------------------------------*/ /* * Numerical responses. */ /*-------------------------------------------------------------------*/ case HEDIT_OWNER: if ((i = get_id_by_name(arg)) == NOBODY) { write_to_output(d, TRUE, "No such player, try again : "); return; } H_OWNER(OLC_HOUSE(d)) = i; break; /*-------------------------------------------------------------------*/ case HEDIT_ATRIUM: if ((i = real_room(atoi(arg))) == NOWHERE) { write_to_output(d, TRUE, "No such room, try again : "); return; } if ((find_house(atoi(arg))) != NOWHERE) { write_to_output(d, TRUE, "That's a house room, try again : "); return; } H_ATRIUM(OLC_HOUSE(d)) = atoi(arg); break; /*-------------------------------------------------------------------*/ case HEDIT_EXIT: /* Check for a valid exit. */ if (atoi(arg) < 0 || atoi(arg) >= NUM_OF_DIRS) { write_to_output(d, TRUE, "\r\n&RThat's not a valid exit.&n\r\n\r\n"); hedit_exits_menu(d); return; } /* Make sure we have a start room (first in list). */ if ((i = real_room(H_ROOM(OLC_HOUSE(d), 0))) == NOWHERE) { write_to_output(d, TRUE, "\r\n&RYou have to define the starting room first.&n\r\n\r\n"); break; } /* Make sure we have an atrium. */ if ((j = real_room(H_ATRIUM(OLC_HOUSE(d)))) == NOWHERE) { write_to_output(d, TRUE, "\r\n&RYou have to define the atrium room first.&n\r\n\r\n"); break; } /* Check for a valid exit leading out from start room. */ if (TOROOM(i, atoi(arg)) == NOWHERE) { write_to_output(d, TRUE, "\r\n&RThere is no exit %s from room %d.&n\r\n\r\n", dirs[atoi(arg)], H_ROOM(OLC_HOUSE(d), 0)); hedit_exits_menu(d); return; } /* Check for a valid return exit from the atrium. */ if (TOROOM(j, rev_dir[atoi(arg)]) != i) { write_to_output(d, TRUE, "\r\n&RThe returning exit %s does not come from the atrium %d.&n\r\n\r\n", dirs[rev_dir[atoi(arg)]], H_ATRIUM(OLC_HOUSE(d))); hedit_exits_menu(d); return; } H_EXIT(OLC_HOUSE(d)) = atoi(arg); break; /*-------------------------------------------------------------------*/ case HEDIT_MODE: i = atoi(arg); if (i < 0 || i >= NUM_HOUSE_FLAGS) { write_to_output(d, TRUE, "\r\n&RThat's not a valid house type.&n\r\n\r\n"); hedit_modes_menu(d); return; } H_MODE(OLC_HOUSE(d)) = i; break; /*-------------------------------------------------------------------*/ case HEDIT_PRUNE_SAFE: i = atoi(arg); if (i < 0 || i > 1) { write_to_output(d, TRUE, "\r\n&RValid choices are 0 or 1.&n\r\n\r\n"); hedit_prune_safe_menu(d); return; } H_PRUNE_SAFE(OLC_HOUSE(d)) = i; break; /*-------------------------------------------------------------------*/ case HEDIT_COST: H_COST(OLC_HOUSE(d)) = atoi(arg); break; /*-------------------------------------------------------------------*/ case HEDIT_MAX_SECURE: if ((i = atoi(arg)) > HOUSE_MAX_SECURES) { write_to_output(d, TRUE, "Valid ranges are 0-%d : ", HOUSE_MAX_SECURES); return; } H_MAX_SECURE(OLC_HOUSE(d)) = i; break; /*-------------------------------------------------------------------*/ case HEDIT_MAX_LOCKED: if ((i = atoi(arg)) > HOUSE_MAX_LOCKS) { write_to_output(d, TRUE, "Valid ranges are 0-%d : ", HOUSE_MAX_LOCKS); return; } H_MAX_LOCKED(OLC_HOUSE(d)) = i; break; /*-------------------------------------------------------------------*/ case HEDIT_NEW_ROOM: if ((i = atoi(arg)) != -1) if ((i = real_room(i)) < 0) { write_to_output(d, TRUE, "That room does not exist, try again : "); return; } if (i >= 0) add_to_house_list(&(H_ROOMS(OLC_HOUSE(d))), atoi(arg)); hedit_rooms_menu(d); return; case HEDIT_DELETE_ROOM: remove_from_house_list(&(H_ROOMS(OLC_HOUSE(d))), atoi(arg)); hedit_rooms_menu(d); return; /*-------------------------------------------------------------------*/ case HEDIT_NEW_COWNER: if ((i = get_id_by_name(arg)) == NOBODY) { write_to_output(d, TRUE, "No such player, try again : "); return; } if (i == H_OWNER(OLC_HOUSE(d))) { write_to_output(d, TRUE, "That player already owns the house, try again : "); return; } for (j = 0; H_COWNER(OLC_HOUSE(d), j) != NOBODY; j++) { if (i == H_COWNER(OLC_HOUSE(d), j)) { write_to_output(d, TRUE, "That player has already been added, try again : "); return; } } for (j = 0; H_GUEST(OLC_HOUSE(d), j) != NOBODY; j++) { if (i == H_GUEST(OLC_HOUSE(d), j)) { write_to_output(d, TRUE, "That player is listed as a guest, try again : "); return; } } if (i >= 0) add_to_house_list(&(H_COWNERS(OLC_HOUSE(d))), i); hedit_owners_menu(d); return; case HEDIT_DELETE_COWNER: remove_from_house_list(&(H_COWNERS(OLC_HOUSE(d))), atoi(arg)); hedit_owners_menu(d); return; /*-------------------------------------------------------------------*/ case HEDIT_NEW_GUEST: if ((i = get_id_by_name(arg)) == NOBODY) { write_to_output(d, TRUE, "No such player, try again : "); return; } if (i == H_OWNER(OLC_HOUSE(d))) { write_to_output(d, TRUE, "That player already owns the house, try again : "); return; } for (j = 0; H_COWNER(OLC_HOUSE(d), j) != NOBODY; j++) { if (i == H_COWNER(OLC_HOUSE(d), j)) { write_to_output(d, TRUE, "That player is a co-owner, try again : "); return; } } for (j = 0; H_GUEST(OLC_HOUSE(d), j) != NOBODY; j++) { if (i == H_GUEST(OLC_HOUSE(d), j)) { write_to_output(d, TRUE, "That player has already been added, try again : "); return; } } if (i >= 0) add_to_house_list(&(H_GUESTS(OLC_HOUSE(d))), i); hedit_guests_menu(d); return; case HEDIT_DELETE_GUEST: remove_from_house_list(&(H_GUESTS(OLC_HOUSE(d))), atoi(arg)); hedit_guests_menu(d); return; /*-------------------------------------------------------------------*/ default: /* * We should never get here. */ cleanup_olc(d, CLEANUP_ALL); extended_mudlog(NRM, SYSL_BUGS, TRUE, "OLC: hedit_parse(): Reached default case!"); write_to_output(d, TRUE, "Oops...\r\n"); break; } /*-------------------------------------------------------------------*/ /* * END OF CASE * If we get here, we have probably changed something, and now want to * return to main menu. Use OLC_VAL as a 'has changed' flag. */ OLC_VAL(d) = 1; hedit_disp_menu(d); }
void hcontrol_build_house(struct char_data * ch, char *arg) { char arg1[MAX_INPUT_LENGTH]; struct house_control_rec temp_house; int virt_house, real_house, real_atrium, virt_atrium, exit_num; long owner; if (num_of_houses >= MAX_HOUSES) { send_to_char("Max houses already defined.\r\n", ch); return; } /* first arg: house's vnum */ arg = one_argument(arg, arg1); if (!*arg1) { send_to_char(HCONTROL_FORMAT, ch); return; } virt_house = atoi(arg1); if ((real_house = real_room(virt_house)) < 0) { send_to_char("No such room exists.\r\n", ch); return; } if ((find_house(virt_house)) >= 0) { send_to_char("House already exists.\r\n", ch); return; } /* second arg: direction of house's exit */ arg = one_argument(arg, arg1); if (!*arg1) { send_to_char(HCONTROL_FORMAT, ch); return; } if ((exit_num = search_block(arg1, dirs, FALSE)) < 0) { sprintf(buf, "'%s' is not a valid direction.\r\n", arg1); send_to_char(buf, ch); return; } if (TOROOM(real_house, exit_num) == NOWHERE) { sprintf(buf, "There is no exit %s from room %d.\r\n", dirs[exit_num], virt_house); send_to_char(buf, ch); return; } real_atrium = TOROOM(real_house, exit_num); virt_atrium = world[real_atrium].number; if (TOROOM(real_atrium, rev_dir[exit_num]) != real_house) { send_to_char("A house's exit must be a two-way door.\r\n", ch); return; } /* third arg: player's name */ arg = one_argument(arg, arg1); if (!*arg1) { send_to_char(HCONTROL_FORMAT, ch); return; } if ((owner = get_id_by_name(arg1)) < 0) { sprintf(buf, "Unknown player '%s'.\r\n", arg1); send_to_char(buf, ch); return; } temp_house.mode = HOUSE_PRIVATE; temp_house.vnum = virt_house; temp_house.atrium = virt_atrium; temp_house.exit_num = exit_num; temp_house.built_on = time(0); temp_house.last_payment = 0; temp_house.owner = owner; temp_house.num_of_guests = 0; house_control[num_of_houses++] = temp_house; SET_BIT_AR(ROOM_FLAGS(real_house), ROOM_HOUSE); SET_BIT_AR(ROOM_FLAGS(real_house), ROOM_PRIVATE); SET_BIT_AR(ROOM_FLAGS(real_atrium), ROOM_ATRIUM); House_crashsave(virt_house); send_to_char("House built. Mazel tov!\r\n", ch); House_save_control(); }