std::string Room::get_description_with_doors() { std::string direction_names[] = {"North", "East", "South", "West", "Up", "Down", "Secret0", "Secret1", "Secret2", "Invalid"}; std::string retval = description; for (std::size_t i = 0; i < static_cast<std::size_t>(Exit::INVALID); ++i) { //if we have a door description, add it in if (door_descriptions[i] != "") { std::string c = "green>open"; if (get_exit(static_cast<Exit>(i)) == Exit_Status::Locked) { c = "red>locked"; } #ifdef DEBUG else if (get_exit(static_cast<Exit>(i)) == Exit_Status::Wall) { Log::write("Warning: The room '" + StringUtils::to_string(static_cast<int>(my_handle)) + "' has a door but the door is neither locked nor open. Just counting it as 'open'."); } #endif retval += "<fg=white><bg=black>\nTo the " + direction_names[i] + " is " + door_descriptions[i] + "<fg=white><bg=black>. It is <fg=" + c + "<fg=white>."; } //if there is no door description but the way is still locked, just say there's a generic door else if (exits[i] == Exit_Status::Locked) { retval += "<fg=white><bg=black>\nTo the " + direction_names[i] + " is an unremarkable door. It is <fg=red>locked<fg=white>."; } } return retval; }
void hunt_victim( CHAR_DATA * ch ) { bool found; CHAR_DATA *tmp; EXIT_DATA *pexit; short ret; if( !ch || !ch->hunting || ch->position < 5 ) return; /* * make sure the char still exists */ for( found = FALSE, tmp = first_char; tmp && !found; tmp = tmp->next ) if( ch->hunting->who == tmp ) found = TRUE; if( !found ) { do_say( ch, "Damn! My prey is gone!!" ); stop_hunting( ch ); return; } if( ch->in_room == ch->hunting->who->in_room ) { if( ch->fighting ) return; found_prey( ch, ch->hunting->who ); return; } ret = find_first_step( ch->in_room, ch->hunting->who->in_room, 500 + ch->level * 25 ); if( ret < 0 ) { do_say( ch, "Damn! Lost my prey!" ); stop_hunting( ch ); return; } else { if( ( pexit = get_exit( ch->in_room, ret ) ) == NULL ) { bug( "%s", "Hunt_victim: lost exit?" ); return; } move_char( ch, pexit, FALSE ); /* * Crash bug fix by Shaddai */ if( char_died( ch ) ) return; if( !ch->hunting ) { if( !ch->in_room ) { bug( "Hunt_victim: no ch->in_room! Mob #%d, name: %s. Placing mob in limbo.", ch->pIndexData->vnum, ch->name ); char_to_room( ch, get_room_index( ROOM_VNUM_LIMBO ) ); return; } do_say( ch, "Damn! Lost my prey!" ); return; } if( ch->in_room == ch->hunting->who->in_room ) found_prey( ch, ch->hunting->who ); else { CHAR_DATA *vch; /* * perform a ranged attack if possible */ /* * Changed who to name as scan_for_victim expects the name and * * Not the char struct. --Shaddai */ if( ( vch = scan_for_victim( ch, pexit, ch->hunting->name ) ) != NULL ) { if( !mob_fire( ch, ch->hunting->who->name ) ) { /* * ranged spell attacks go here */ } } } return; } }
SPEC_RET spec_mayor( CHAR_DATA *ch ) { static const char open_path[] = "W3a3003b33000c111d0d111Oe333333Oe22c222112212111a1S."; static const char close_path[] = "W3a3003b33000c111d0d111CE333333CE22c222112212111a1S."; static const char *path; static int pos; static bool move; if ( !move ) { if ( calendar.hour == 6 ) { path = open_path; move = TRUE; pos = 0; } if ( calendar.hour == 20 ) { path = close_path; move = TRUE; pos = 0; } } if ( ch->fighting ) return spec_cast_cleric( ch ); if ( !move || ch->position < POSITION_SLEEP ) return FALSE; /* (TR) */ switch ( path[pos] ) { case '0': case '1': case '2': case '3': move_char( ch, get_exit(ch->in_room, path[pos] - '0'), 0, FALSE ); break; case 'W': ch->position = POSITION_STAND; act( AT_ACTION, "$n awakens and groans loudly.", ch, NULL, NULL, TO_ROOM ); break; case 'S': ch->position = POSITION_SLEEP; act( AT_ACTION, "$n lies down and falls asleep.", ch, NULL, NULL, TO_ROOM ); break; case 'a': act( AT_SAY, "$n says 'Hello Honey!'", ch, NULL, NULL, TO_ROOM ); break; case 'b': act( AT_SAY, "$n says 'What a view! I must do something about that dump!'", ch, NULL, NULL, TO_ROOM ); break; case 'c': act( AT_SAY, "$n says 'Vandals! Youngsters have no respect for anything!'", ch, NULL, NULL, TO_ROOM ); break; case 'd': act( AT_SAY, "$n says 'Good day, citizens!'", ch, NULL, NULL, TO_ROOM ); break; case 'e': act( AT_SAY, "$n says 'I hereby declare the town of Darkhaven open!'", ch, NULL, NULL, TO_ROOM ); break; case 'E': act( AT_SAY, "$n says 'I hereby declare the town of Darkhaven closed!'", ch, NULL, NULL, TO_ROOM ); break; case 'O': send_command( ch, "unlock gate", CO ); send_command( ch, "open gate", CO ); break; case 'C': send_command( ch, "close gate", CO ); send_command( ch, "lock gate", CO ); break; case '.' : move = FALSE; break; } pos++; return FALSE; }
/* This function is recursive, ie it calls itself */ void map_exits( CHAR_DATA * ch, ROOM_INDEX_DATA * pRoom, int x, int y, int depth ) { static char map_chars[11] = "|-|-UD/\\\\/"; int door; int exitx = 0, exity = 0; int roomx = 0, roomy = 0; EXIT_DATA *pExit; /* * Setup this coord as a room - Change any symbols that can't be displayed here */ dmap[x][y].sector = pRoom->sector_type; switch ( pRoom->sector_type ) { case SECT_INSIDE: dmap[x][y].tegn = 'O'; dmap[x][y].sector = -1; break; case SECT_CITY: dmap[x][y].tegn = ':'; break; case SECT_FIELD: case SECT_FOREST: case SECT_HILLS: dmap[x][y].tegn = '*'; break; case SECT_MOUNTAIN: dmap[x][y].tegn = '@'; break; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: dmap[x][y].tegn = '='; break; case SECT_AIR: dmap[x][y].tegn = '~'; break; case SECT_DESERT: dmap[x][y].tegn = '+'; break; default: dmap[x][y].tegn = 'O'; dmap[x][y].sector = -1; bug( "%s: Bad sector type (%d) in room %d.", __FUNCTION__, pRoom->sector_type, pRoom->vnum ); break; } dmap[x][y].vnum = pRoom->vnum; dmap[x][y].depth = depth; // dmap[x][y].info = pRoom->room_flags; dmap[x][y].can_see = room_is_dark( pRoom ); /* * Limit recursion */ if ( depth > MAXDEPTH ) return; /* * This room is done, deal with it's exits */ for ( door = 0; door < 10; ++door ) { /* * Skip if there is no exit in this direction */ if ( !( pExit = get_exit( pRoom, door ) ) ) continue; /* * Skip up and down until I can figure out a good way to display it */ if ( door == 4 || door == 5 ) continue; /* * Get the coords for the next exit and room in this direction */ get_exit_dir( door, &exitx, &exity, x, y ); get_exit_dir( door, &roomx, &roomy, exitx, exity ); /* * Skip if coords fall outside map */ if ( BOUNDARY( exitx, exity ) || BOUNDARY( roomx, roomy ) ) continue; /* * Skip if there is no room beyond this exit */ if ( !pExit->to_room ) continue; /* * Ensure there are no clashes with previously defined rooms */ if ( ( dmap[roomx][roomy].vnum != 0 ) && ( dmap[roomx][roomy].vnum != pExit->to_room->vnum ) ) { /* * Use the new room if the depth is higher */ if ( dmap[roomx][roomy].depth <= depth ) continue; /* * It is so clear the old room */ clear_room( roomx, roomy ); } /* * No exits at MAXDEPTH */ if ( depth == MAXDEPTH ) continue; /* * No need for exits that are already mapped */ if ( dmap[exitx][exity].depth > 0 ) continue; /* * Fill in exit */ dmap[exitx][exity].depth = depth; dmap[exitx][exity].vnum = pExit->to_room->vnum; // dmap[exitx][exity].info = pExit->exit_info; dmap[exitx][exity].tegn = map_chars[door]; dmap[exitx][exity].sector = -1; /* * More to do? If so we recurse */ if ( depth < MAXDEPTH && ( ( dmap[roomx][roomy].vnum == pExit->to_room->vnum ) || ( dmap[roomx][roomy].vnum == 0 ) ) ) { /* * Depth increases by one each time */ map_exits( ch, pExit->to_room, roomx, roomy, depth + 1 ); } } }
char *sprint_reset( RESET_DATA * pReset, short *num ) { RESET_DATA *tReset, *gReset; static char buf[MAX_STRING_LENGTH]; char mobname[MAX_STRING_LENGTH], roomname[MAX_STRING_LENGTH], objname[MAX_STRING_LENGTH]; static ROOM_INDEX_DATA *room; static OBJ_INDEX_DATA *obj, *obj2; static MOB_INDEX_DATA *mob; switch ( pReset->command ) { default: snprintf( buf, MAX_STRING_LENGTH, "%2d) *** BAD RESET: %c %d %d %d %d ***\r\n", *num, pReset->command, pReset->extra, pReset->arg1, pReset->arg2, pReset->arg3 ); break; case 'M': mob = get_mob_index( pReset->arg1 ); room = get_room_index( pReset->arg3 ); if ( mob ) strncpy( mobname, mob->player_name, MAX_STRING_LENGTH ); else strncpy( mobname, "Mobile: *BAD VNUM*", MAX_STRING_LENGTH ); if ( room ) strncpy( roomname, room->name, MAX_STRING_LENGTH ); else strncpy( roomname, "Room: *BAD VNUM*", MAX_STRING_LENGTH ); snprintf( buf, MAX_STRING_LENGTH, "%2d) %s (%d) -> %s Room: %d [%d] %s\r\n", *num, mobname, pReset->arg1, roomname, pReset->arg3, pReset->arg2, pReset->sreset ? "[Not Reset]" : "[Reset]" ); for ( tReset = pReset->first_reset; tReset; tReset = tReset->next_reset ) { ( *num )++; switch ( tReset->command ) { case 'E': if ( !mob ) strncpy( mobname, "* ERROR: NO MOBILE! *", MAX_STRING_LENGTH ); if ( !( obj = get_obj_index( tReset->arg1 ) ) ) strncpy( objname, "Object: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( objname, obj->name, MAX_STRING_LENGTH ); snprintf( buf + strlen( buf ), MAX_STRING_LENGTH - strlen( buf ), "%2d) (equip) %s (%d) -> %s (%s) [%d]\r\n", *num, objname, tReset->arg1, mobname, wear_locs[tReset->arg3], tReset->arg2 ); break; case 'G': if ( !mob ) strncpy( mobname, "* ERROR: NO MOBILE! *", MAX_STRING_LENGTH ); if ( !( obj = get_obj_index( tReset->arg1 ) ) ) strncpy( objname, "Object: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( objname, obj->name, MAX_STRING_LENGTH ); snprintf( buf + strlen( buf ), MAX_STRING_LENGTH - strlen( buf ), "%2d) (carry) %s (%d) -> %s [%d]\r\n", *num, objname, tReset->arg1, mobname, tReset->arg2 ); break; } if ( tReset->first_reset ) { for ( gReset = tReset->first_reset; gReset; gReset = gReset->next_reset ) { ( *num )++; switch ( gReset->command ) { case 'P': if ( !( obj2 = get_obj_index( gReset->arg1 ) ) ) strncpy( objname, "Object1: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( objname, obj2->name, MAX_STRING_LENGTH ); if ( gReset->arg3 > 0 && ( obj = get_obj_index( gReset->arg3 ) ) == NULL ) strncpy( roomname, "Object2: *BAD VNUM*", MAX_STRING_LENGTH ); else if ( !obj ) strncpy( roomname, "Object2: *NULL obj*", MAX_STRING_LENGTH ); else strncpy( roomname, obj->name, MAX_STRING_LENGTH ); snprintf( buf + strlen( buf ), MAX_STRING_LENGTH - strlen( buf ), "%2d) (put) %s (%d) -> %s (%d) [%d]\r\n", *num, objname, gReset->arg1, roomname, obj ? obj->vnum : gReset->arg3, gReset->arg2 ); break; } } } } break; case 'O': if ( !( obj = get_obj_index( pReset->arg1 ) ) ) strncpy( objname, "Object: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( objname, obj->name, MAX_STRING_LENGTH ); room = get_room_index( pReset->arg3 ); if ( !room ) strncpy( roomname, "Room: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( roomname, room->name, MAX_STRING_LENGTH ); snprintf( buf, MAX_STRING_LENGTH, "%2d) (object) %s (%d) -> %s Room: %d [%d]\r\n", *num, objname, pReset->arg1, roomname, pReset->arg3, pReset->arg2 ); for ( tReset = pReset->first_reset; tReset; tReset = tReset->next_reset ) { ( *num )++; switch ( tReset->command ) { case 'P': if ( !( obj2 = get_obj_index( tReset->arg1 ) ) ) strncpy( objname, "Object1: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( objname, obj2->name, MAX_STRING_LENGTH ); if ( tReset->arg3 > 0 && ( obj = get_obj_index( tReset->arg3 ) ) == NULL ) strncpy( roomname, "Object2: *BAD VNUM*", MAX_STRING_LENGTH ); else if ( !obj ) strncpy( roomname, "Object2: *NULL obj*", MAX_STRING_LENGTH ); else strncpy( roomname, obj->name, MAX_STRING_LENGTH ); snprintf( buf + strlen( buf ), MAX_STRING_LENGTH - strlen( buf ), "%2d) (put) %s (%d) -> %s (%d) [%d]\r\n", *num, objname, tReset->arg1, roomname, obj ? obj->vnum : tReset->arg3, tReset->arg2 ); break; case 'T': snprintf( buf + strlen( buf ), MAX_STRING_LENGTH - strlen( buf ), "%2d) (trap) %d %d %d %d (%s) -> %s (%d)\r\n", *num, tReset->extra, tReset->arg1, tReset->arg2, tReset->arg3, flag_string( tReset->extra, trap_flags ), objname, obj ? obj->vnum : 0 ); break; case 'H': snprintf( buf + strlen( buf ), MAX_STRING_LENGTH - strlen( buf ), "%2d) (hide) -> %s\r\n", *num, objname ); break; } } break; case 'D': if ( pReset->arg2 < 0 || pReset->arg2 > MAX_DIR + 1 ) pReset->arg2 = 0; if ( !( room = get_room_index( pReset->arg1 ) ) ) { strncpy( roomname, "Room: *BAD VNUM*", MAX_STRING_LENGTH ); snprintf( objname, MAX_STRING_LENGTH, "%s (no exit)", dir_name[pReset->arg2] ); } else { strncpy( roomname, room->name, MAX_STRING_LENGTH ); snprintf( objname, MAX_STRING_LENGTH, "%s%s", dir_name[pReset->arg2], get_exit( room, pReset->arg2 ) ? "" : " (NO EXIT!)" ); } switch ( pReset->arg3 ) { default: strncpy( mobname, "(* ERROR *)", MAX_STRING_LENGTH ); break; case 0: strncpy( mobname, "Open", MAX_STRING_LENGTH ); break; case 1: strncpy( mobname, "Close", MAX_STRING_LENGTH ); break; case 2: strncpy( mobname, "Close and lock", MAX_STRING_LENGTH ); break; } snprintf( buf, MAX_STRING_LENGTH, "%2d) %s [%d] the %s [%d] door %s (%d)\r\n", *num, mobname, pReset->arg3, objname, pReset->arg2, roomname, pReset->arg1 ); break; case 'R': if ( !( room = get_room_index( pReset->arg1 ) ) ) strncpy( roomname, "Room: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( roomname, room->name, MAX_STRING_LENGTH ); snprintf( buf, MAX_STRING_LENGTH, "%2d) Randomize exits 0 to %d -> %s (%d)\r\n", *num, pReset->arg2, roomname, pReset->arg1 ); break; case 'T': if ( !( room = get_room_index( pReset->arg3 ) ) ) strncpy( roomname, "Room: *BAD VNUM*", MAX_STRING_LENGTH ); else strncpy( roomname, room->name, MAX_STRING_LENGTH ); snprintf( buf, MAX_STRING_LENGTH, "%2d) Trap: %d %d %d %d (%s) -> %s (%d)\r\n", *num, pReset->extra, pReset->arg1, pReset->arg2, pReset->arg3, flag_string( pReset->extra, trap_flags ), roomname, room ? room->vnum : 0 ); break; } return buf; }
/* * Reset one room. */ void reset_room( ROOM_INDEX_DATA * room ) { RESET_DATA *pReset, *tReset, *gReset; OBJ_DATA *nestmap[MAX_NEST]; CHAR_DATA *mob; OBJ_DATA *obj, *lastobj, *to_obj; ROOM_INDEX_DATA *pRoomIndex = NULL; MOB_INDEX_DATA *pMobIndex = NULL; OBJ_INDEX_DATA *pObjIndex = NULL, *pObjToIndex; EXIT_DATA *pexit; const char *filename = room->area->filename; int level = 0, n, num = 0, lastnest, onreset = 0; mob = NULL; obj = NULL; lastobj = NULL; if ( !room->first_reset ) return; level = 0; for ( pReset = room->first_reset; pReset; pReset = pReset->next ) { ++onreset; switch ( pReset->command ) { default: bug( "%s: %s: bad command %c.", __FUNCTION__, filename, pReset->command ); break; case 'M': if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) ) { bug( "%s: %s: 'M': bad mob vnum %d.", __FUNCTION__, filename, pReset->arg1 ); continue; } if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) ) { bug( "%s: %s: 'M': bad room vnum %d.", __FUNCTION__, filename, pReset->arg3 ); continue; } if ( !pReset->sreset ) { mob = NULL; break; } mob = create_mobile( pMobIndex ); { ROOM_INDEX_DATA *pRoomPrev = get_room_index( pReset->arg3 - 1 ); if ( pRoomPrev && xIS_SET( pRoomPrev->room_flags, ROOM_PET_SHOP ) ) xSET_BIT( mob->act, ACT_PET ); } if ( room_is_dark( pRoomIndex ) ) xSET_BIT( mob->affected_by, AFF_INFRARED ); mob->resetvnum = pRoomIndex->vnum; mob->resetnum = onreset; pReset->sreset = false; char_to_room( mob, pRoomIndex ); level = URANGE( 0, mob->level - 2, LEVEL_AVATAR ); if ( pReset->first_reset ) { for ( tReset = pReset->first_reset; tReset; tReset = tReset->next_reset ) { ++onreset; switch ( tReset->command ) { case 'G': case 'E': if ( !( pObjIndex = get_obj_index( tReset->arg1 ) ) ) { bug( "%s: %s: 'E' or 'G': bad obj vnum %d.", __FUNCTION__, filename, tReset->arg1 ); continue; } if ( !mob ) { lastobj = NULL; break; } if ( mob->pIndexData->pShop ) { int olevel = generate_itemlevel( room->area, pObjIndex ); obj = create_object( pObjIndex, olevel ); xSET_BIT( obj->extra_flags, ITEM_INVENTORY ); } else obj = create_object( pObjIndex, number_fuzzy( level ) ); obj->level = URANGE( 0, obj->level, LEVEL_AVATAR ); obj = obj_to_char( obj, mob ); if ( tReset->command == 'E' ) { if ( obj->carried_by != mob ) { bug( "'E' reset: can't give object %d to mob %d.", obj->pIndexData->vnum, mob->pIndexData->vnum ); break; } equip_char( mob, obj, tReset->arg3 ); } for ( n = 0; n < MAX_NEST; n++ ) nestmap[n] = NULL; nestmap[0] = obj; lastobj = nestmap[0]; lastnest = 0; if ( tReset->first_reset ) { for ( gReset = tReset->first_reset; gReset; gReset = gReset->next_reset ) { int iNest; to_obj = lastobj; ++onreset; switch ( gReset->command ) { case 'H': if ( !lastobj ) break; xSET_BIT( lastobj->extra_flags, ITEM_HIDDEN ); break; case 'P': if ( !( pObjIndex = get_obj_index( gReset->arg1 ) ) ) { bug( "%s: %s: 'P': bad obj vnum %d.", __FUNCTION__, filename, gReset->arg1 ); continue; } iNest = gReset->extra; if ( !( pObjToIndex = get_obj_index( gReset->arg3 ) ) ) { bug( "%s: %s: 'P': bad objto vnum %d.", __FUNCTION__, filename, gReset->arg3 ); continue; } if ( iNest >= MAX_NEST ) { bug( "%s: %s: 'P': Exceeded nesting limit of %d", __FUNCTION__, filename, MAX_NEST ); obj = NULL; break; } if ( count_obj_list( pObjIndex, to_obj->first_content ) > 0 ) { obj = NULL; break; } if ( iNest < lastnest ) to_obj = nestmap[iNest]; else if ( iNest == lastnest ) to_obj = nestmap[lastnest]; else to_obj = lastobj; obj = create_object( pObjIndex, number_fuzzy( UMAX( generate_itemlevel( room->area, pObjIndex ), to_obj->level ) ) ); if ( num > 1 ) pObjIndex->count += ( num - 1 ); obj->count = gReset->arg2; obj->level = UMIN( obj->level, LEVEL_AVATAR ); obj->count = gReset->arg2; obj_to_obj( obj, to_obj ); if ( iNest > lastnest ) { nestmap[iNest] = to_obj; lastnest = iNest; } lastobj = obj; /* * Hackish fix for nested puts */ if ( gReset->arg3 == OBJ_VNUM_MONEY_ONE ) gReset->arg3 = to_obj->pIndexData->vnum; break; } } } break; } } } break; case 'O': if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) ) { bug( "%s: %s: 'O': bad obj vnum %d.", __FUNCTION__, filename, pReset->arg1 ); continue; } if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) ) { bug( "%s: %s: 'O': bad room vnum %d.", __FUNCTION__, filename, pReset->arg3 ); continue; } if ( count_obj_list( pObjIndex, pRoomIndex->first_content ) < 1 ) { obj = create_object( pObjIndex, number_fuzzy( generate_itemlevel( room->area, pObjIndex ) ) ); if ( num > 1 ) pObjIndex->count += ( num - 1 ); obj->count = pReset->arg2; obj->level = UMIN( obj->level, LEVEL_AVATAR ); obj->cost = 0; obj_to_room( obj, pRoomIndex ); } else { int x; if ( !( obj = get_obj_room( pObjIndex, pRoomIndex ) ) ) { obj = NULL; lastobj = NULL; break; } obj->extra_flags = pObjIndex->extra_flags; for ( x = 0; x < 6; ++x ) obj->value[x] = pObjIndex->value[x]; } for ( n = 0; n < MAX_NEST; n++ ) nestmap[n] = NULL; nestmap[0] = obj; lastobj = nestmap[0]; lastnest = 0; if ( pReset->first_reset ) { for ( tReset = pReset->first_reset; tReset; tReset = tReset->next_reset ) { int iNest; to_obj = lastobj; ++onreset; switch ( tReset->command ) { case 'H': if ( !lastobj ) break; xSET_BIT( lastobj->extra_flags, ITEM_HIDDEN ); break; case 'T': if ( !IS_SET( tReset->extra, TRAP_OBJ ) ) { bug( "%s: Room reset found on object reset list", __FUNCTION__ ); break; } else { /* * We need to preserve obj for future 'T' checks */ OBJ_DATA *pobj; if ( tReset->arg3 > 0 ) { if ( !( pObjToIndex = get_obj_index( tReset->arg3 ) ) ) { bug( "%s: %s: 'T': bad objto vnum %d.", __FUNCTION__, filename, tReset->arg3 ); continue; } if ( room->area->nplayer > 0 || !( to_obj = get_obj_type( pObjToIndex ) ) || ( to_obj->carried_by && !IS_NPC( to_obj->carried_by ) ) || is_trapped( to_obj ) ) break; } else { if ( !lastobj || !obj ) break; to_obj = obj; } pobj = make_trap( tReset->arg2, tReset->arg1, number_fuzzy( to_obj->level ), tReset->extra ); obj_to_obj( pobj, to_obj ); } break; case 'P': if ( !( pObjIndex = get_obj_index( tReset->arg1 ) ) ) { bug( "%s: %s: 'P': bad obj vnum %d.", __FUNCTION__, filename, tReset->arg1 ); continue; } iNest = tReset->extra; if ( !( pObjToIndex = get_obj_index( tReset->arg3 ) ) ) { bug( "%s: %s: 'P': bad objto vnum %d.", __FUNCTION__, filename, tReset->arg3 ); continue; } if ( iNest >= MAX_NEST ) { bug( "%s: %s: 'P': Exceeded nesting limit of %d. Room %d.", __FUNCTION__, filename, MAX_NEST, room->vnum ); obj = NULL; break; } if ( count_obj_list( pObjIndex, to_obj->first_content ) > 0 ) { obj = NULL; break; } if ( iNest < lastnest ) to_obj = nestmap[iNest]; else if ( iNest == lastnest ) to_obj = nestmap[lastnest]; else to_obj = lastobj; obj = create_object( pObjIndex, number_fuzzy( UMAX( generate_itemlevel( room->area, pObjIndex ), to_obj->level ) ) ); if ( num > 1 ) pObjIndex->count += ( num - 1 ); obj->count = tReset->arg2; obj->level = UMIN( obj->level, LEVEL_AVATAR ); obj->count = tReset->arg2; obj_to_obj( obj, to_obj ); if ( iNest > lastnest ) { nestmap[iNest] = to_obj; lastnest = iNest; } lastobj = obj; /* * Hackish fix for nested puts */ if ( tReset->arg3 == OBJ_VNUM_MONEY_ONE ) tReset->arg3 = to_obj->pIndexData->vnum; break; } } } break; case 'T': if ( IS_SET( pReset->extra, TRAP_OBJ ) ) { bug( "%s: Object trap found in room %d reset list", __FUNCTION__, room->vnum ); break; } else { if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) ) { bug( "%s: %s: 'T': bad room %d.", __FUNCTION__, filename, pReset->arg3 ); continue; } if ( room->area->nplayer > 0 || count_obj_list( get_obj_index( OBJ_VNUM_TRAP ), pRoomIndex->first_content ) > 0 ) break; to_obj = make_trap( pReset->arg1, pReset->arg1, 10, pReset->extra ); obj_to_room( to_obj, pRoomIndex ); } break; case 'D': if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) ) { bug( "%s: %s: 'D': bad room vnum %d.", __FUNCTION__, filename, pReset->arg1 ); continue; } if ( !( pexit = get_exit( pRoomIndex, pReset->arg2 ) ) ) break; switch ( pReset->arg3 ) { case 0: REMOVE_BIT( pexit->exit_info, EX_CLOSED ); REMOVE_BIT( pexit->exit_info, EX_LOCKED ); break; case 1: SET_BIT( pexit->exit_info, EX_CLOSED ); REMOVE_BIT( pexit->exit_info, EX_LOCKED ); if ( IS_SET( pexit->exit_info, EX_xSEARCHABLE ) ) SET_BIT( pexit->exit_info, EX_SECRET ); break; case 2: SET_BIT( pexit->exit_info, EX_CLOSED ); SET_BIT( pexit->exit_info, EX_LOCKED ); if ( IS_SET( pexit->exit_info, EX_xSEARCHABLE ) ) SET_BIT( pexit->exit_info, EX_SECRET ); break; } break; case 'R': if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) ) { bug( "%s: %s: 'R': bad room vnum %d.", __FUNCTION__, filename, pReset->arg1 ); continue; } randomize_exits( pRoomIndex, pReset->arg2 - 1 ); break; } } }
void redit_parse( DESCRIPTOR_DATA *d , char *arg ) { ROOM_DATA *room = d->character->dest_buf; ROOM_DATA *tmp; EXIT_DATA *pexit = d->character->spare_ptr; EXTRA_DESCR_DATA *ed = d->character->spare_ptr; char arg1[MIL]; char buf[MSL]; int number = 0; switch ( OLC_MODE(d) ) { case REDIT_CONFIRM_SAVESTRING: switch ( *arg ) { case 'y': case 'Y': /* redit_save_internally(d); */ send_log( NULL, LOG_OLC, "OLC: %s edits room %d", d->character->name, OLC_NUM(d) ); cleanup_olc( d ); send_to_char( d->character, "Room saved to memory.\r\n" ); break; case 'n': case 'N': cleanup_olc( d ); break; default: send_to_char( d->character, "Invalid choice!\r\n" ); send_to_char( d->character, "Do you wish to save this room internally? : " ); break; } return; case REDIT_MAIN_MENU: switch ( *arg ) { case 'q': case 'Q': /* if ( OLC_CHANGE(d) ) { *. Something has been modified .* send_to_char( d->character, "Do you wish to save this room internally? : " ); OLC_MODE(d) = REDIT_CONFIRM_SAVESTRING; } else */ cleanup_olc( d ); return; case '1': send_to_char( d->character, "Enter room name:-\r\n| " ); OLC_MODE(d) = REDIT_NAME; break; case '2': OLC_MODE(d) = REDIT_DESC; d->character->substate = SUB_ROOM_DESCR; d->character->last_cmd = do_redit_reset; send_to_char( d->character, "Enter room description:-\r\n" ); if ( !room->description ) room->description = str_dup( "" ); start_editing( d->character, room->description ); break; case '3': redit_disp_flag_menu(d); break; case '4': redit_disp_sector_menu(d); break; case '5': send_to_char( d->character, "How many people can fit in the room? " ); OLC_MODE(d) = REDIT_TUNNEL; break; case '6': send_to_char( d->character, "How long before people are teleported out? " ); OLC_MODE(d) = REDIT_TELEDELAY; break; case '7': send_to_char( d->character, "Where are they teleported to? " ); OLC_MODE(d) = REDIT_TELEVNUM; break; case 'a': case 'A': redit_disp_exit_menu(d); break; case 'b': case 'B': redit_disp_extradesc_menu(d); break; default: send_to_char( d->character, "Invalid choice!" ); redit_disp_menu(d); break; } return; case REDIT_NAME: DISPOSE( room->name ); room->name = str_dup( arg ); olc_log( d, "Changed name to %s", room->name ); break; case REDIT_DESC: /* we will NEVER get here */ send_log( NULL, LOG_OLC, "redit_parse: reached REDIT_DESC case in redit_parse" ); break; case REDIT_FLAGS: if ( is_number(arg) ) { number = atoi( arg ); if ( number == 0 ) break; else if ( number < 0 || number >= MAX_ROOM ) { send_to_char( d->character, "Invalid flag, try again: " ); return; } else { number--; /* Offset for 0 */ TOGGLE_BIT( room->flags, number ); olc_log( d, "%s the room flag %s", HAS_BIT( room->flags, number ) ? "Added" : "Removed", code_name(NULL, number, CODE_ROOM) ); } } else { while ( VALID_STR(arg) ) { arg = one_argument( arg, arg1 ); number = code_num( NULL, arg1, CODE_ROOM ); if ( number > 0 ) { TOGGLE_BIT( room->flags, number ); olc_log( d, "%s the room flag %s", HAS_BIT( room->flags, number ) ? "Added" : "Removed", code_name( NULL, number, CODE_ROOM) ); } } } redit_disp_flag_menu(d); return; case REDIT_SECTOR: number = atoi( arg ); if ( number < 0 || number >= MAX_SECTOR ) { send_to_char( d->character, "Invalid choice!" ); redit_disp_sector_menu(d); return; } else room->sector = number; olc_log( d, "Changed sector to %s", code_name(NULL, number, CODE_SECTOR) ); break; case REDIT_TUNNEL: number = atoi( arg ); room->tunnel = URANGE( 0, number, 1000 ); olc_log( d, "Changed tunnel amount to %d", room->tunnel ); break; case REDIT_TELEDELAY: number = atoi( arg ); room->tele_delay = number; olc_log( d, "Changed teleportation delay to %d", room->tele_delay ); break; case REDIT_TELEVNUM: number = atoi( arg ); room->tele_vnum = URANGE( 1, number, MAX_VNUM-1 ); olc_log( d, "Changed teleportation vnum to %d", room->tele_vnum ); break; case REDIT_EXIT_MENU: switch ( toupper(arg[0]) ) { default: if ( is_number(arg) ) { number = atoi( arg ); pexit = get_exit_num( room, number ); d->character->spare_ptr = pexit; redit_disp_exit_edit(d); return; } redit_disp_exit_menu( d ); return; case 'A': OLC_MODE(d) = REDIT_EXIT_ADD; redit_disp_exit_dirs( d ); return; case 'R': OLC_MODE(d) = REDIT_EXIT_DELETE; send_to_char( d->character, "Delete which exit? " ); return; case 'Q': d->character->spare_ptr = NULL; break; } break; case REDIT_EXIT_EDIT: switch ( toupper(arg[0]) ) { case 'Q': d->character->spare_ptr = NULL; redit_disp_exit_menu(d); return; case '1': /* OLC_MODE(d) = REDIT_EXIT_DIR; redit_disp_exit_dirs(d); */ send_to_char( d->character, "This option can only be changed by remaking the exit.\r\n" ); break; case '2': OLC_MODE(d) = REDIT_EXIT_VNUM; send_to_char( d->character, "Which room does this exit go to? " ); return; case '3': OLC_MODE(d) = REDIT_EXIT_KEY; send_to_char( d->character, "What is the vnum of the key to this exit? " ); return; case '4': OLC_MODE(d) = REDIT_EXIT_KEYWORD; send_to_char( d->character, "What is the keyword to this exit? " ); return; case '5': OLC_MODE(d) = REDIT_EXIT_FLAGS; redit_disp_exit_flag_menu(d); return; case '6': OLC_MODE(d) = REDIT_EXIT_DESC; send_to_char( d->character, "Description:\r\n] " ); return; } redit_disp_exit_edit(d); return; case REDIT_EXIT_DESC: if ( !VALID_STR(arg) ) { DISPOSE( pexit->description ); pexit->description = str_dup( "" ); } else { sprintf( buf, "%s\r\n", arg ); DISPOSE( pexit->description ); pexit->description = str_dup( buf ); } olc_log( d, "Changed %s description to %s", code_name( NULL, pexit->vdir, CODE_DIR), arg ? arg : "none" ); redit_disp_exit_edit(d); return; case REDIT_EXIT_ADD: if ( is_number( arg ) ) { number = atoi( arg ); if ( number < 0 || number >= MAX_DIR ) { send_to_char( d->character, "Invalid direction, try again: " ); return; } d->character->tempnum = number; } else { number = get_dir(arg); pexit = get_exit( room, number ); if ( pexit ) { send_to_char( d->character, "An exit in that direction already exists.\r\n" ); redit_disp_exit_menu(d); return; } d->character->tempnum = number; } OLC_MODE(d) = REDIT_EXIT_ADD_VNUM; send_to_char( d->character, "Which room does this exit go to? " ); return; case REDIT_EXIT_ADD_VNUM: number = atoi( arg ); if ( (tmp = get_room_index(NULL, number)) == NULL ) { send_to_char( d->character, "Non-existant room.\r\n" ); OLC_MODE(d) = REDIT_EXIT_MENU; redit_disp_exit_menu(d); return; } pexit = make_exit( room, tmp, d->character->tempnum ); DISPOSE( pexit->keyword ); DISPOSE( pexit->description ); pexit->keyword = str_dup( "" ); pexit->description = str_dup( "" ); pexit->key = -1; pexit->flags = 0; act( AT_ADMIN, "$n reveals a hidden passage!", d->character, NULL, NULL, TO_ROOM ); d->character->spare_ptr = pexit; olc_log( d, "Added %s exit to %d", code_name( NULL, pexit->vdir, CODE_DIR), pexit->vnum ); OLC_MODE(d) = REDIT_EXIT_EDIT; redit_disp_exit_edit(d); return; case REDIT_EXIT_DELETE: if ( !is_number( arg ) ) { send_to_char( d->character, "Exit must be specified in a number.\r\n" ); redit_disp_exit_menu(d); } number = atoi( arg ); pexit = get_exit_num( room, number ); if ( !pexit ) { send_to_char( d->character, "That exit does not exist.\r\n" ); redit_disp_exit_menu(d); } olc_log( d, "Removed %s exit", code_name( NULL, pexit->vdir, CODE_DIR) ); extract_exit( room, pexit ); redit_disp_exit_menu( d ); return; case REDIT_EXIT_VNUM: number = atoi( arg ); if ( number < 1 || number >= MAX_VNUM ) { send_to_char( d->character, "Invalid room number, try again : " ); return; } if ( get_room_index(NULL, number) == NULL ) { send_to_char( d->character, "That room does not exist, try again: " ); return; } pexit->vnum = number; olc_log( d, "%s exit vnum changed to %d", code_name( NULL, pexit->vdir, CODE_DIR), pexit->vnum ); redit_disp_exit_menu( d ); return; case REDIT_EXIT_KEYWORD: DISPOSE( pexit->keyword ); pexit->keyword = str_dup( arg ); olc_log( d, "Changed %s keyword to %s", code_name( NULL, pexit->vdir, CODE_DIR), pexit->keyword ); redit_disp_exit_edit( d ); return; case REDIT_EXIT_KEY: number = atoi( arg ); if ( number < 1 || number >= MAX_VNUM ) send_to_char( d->character, "Invalid vnum, try again: " ); else { pexit->key = number; redit_disp_exit_edit( d ); } olc_log( d, "%s key vnum is now %d", code_name( NULL, pexit->vdir, CODE_DIR), pexit->key ); return; case REDIT_EXIT_FLAGS: number = atoi( arg ); if ( number == 0 ) { redit_disp_exit_edit( d ); return; } if ( number < 0 || number >= MAX_EXIT || ((number-1) == EXIT_RES1) || ((number-1) == EXIT_RES2) || ((number-1) == EXIT_PORTAL) ) { send_to_char( d->character, "That's not a valid choice!\r\n" ); redit_disp_exit_flag_menu( d ); } number -= 1; TOGGLE_BIT( pexit->flags, number ); olc_log( d, "%s %s to %s exit", HAS_BIT(pexit->flags, number) ? "Added" : "Removed", code_name(NULL, number, CODE_EXIT), code_name(NULL, pexit->vdir, CODE_DIR) ); redit_disp_exit_flag_menu( d ); return; case REDIT_EXTRADESC_DELETE: ed = redit_find_extradesc( room, atoi(arg) ); if ( !ed ) { send_to_char( d->character, "Not found, try again: " ); return; } olc_log( d, "Deleted exdesc %s", ed->keyword ); UNLINK( ed, room->first_extradescr, room->last_extradescr, next, prev ); DISPOSE( ed->keyword ); DISPOSE( ed->description ); DISPOSE( ed ); top_ed--; redit_disp_extradesc_menu(d); return; case REDIT_EXTRADESC_CHOICE: switch ( toupper( arg[0] ) ) { case 'Q': if ( !ed->keyword || !ed->description ) { send_to_char( d->character, "No keyword and/or description, junking..." ); UNLINK( ed, room->first_extradescr, room->last_extradescr, next, prev ); DISPOSE( ed->keyword ); DISPOSE( ed->keyword ); DISPOSE( ed ); top_ed--; } d->character->spare_ptr = NULL; redit_disp_extradesc_menu(d); return; case '1': OLC_MODE(d) = REDIT_EXTRADESC_KEY; send_to_char( d->character, "Keywords, seperated by spaces: " ); return; case '2': OLC_MODE(d) = REDIT_EXTRADESC_DESCRIPTION; d->character->substate = SUB_ROOM_EXTRA; d->character->last_cmd = do_redit_reset; send_to_char( d->character, "Enter new extradesc description: \r\n" ); start_editing( d->character, ed->description ); return; } break; case REDIT_EXTRADESC_KEY: /* if ( SetRExtra( room, arg ) ) { send_to_char( d->character, "A extradesc with that keyword already exists.\r\n" ); redit_disp_extradesc_menu(d); return; } */ olc_log( d, "Changed exkey %s to %s", ed->keyword, arg ); DISPOSE( ed->keyword ); ed->keyword = str_dup( arg ); oedit_disp_extra_choice(d); OLC_MODE(d) = REDIT_EXTRADESC_CHOICE; return; case REDIT_EXTRADESC_MENU: switch ( toupper( arg[0] ) ) { case 'Q': break; case 'A': CREATE( ed, EXTRA_DESCR_DATA, 1 ); LINK( ed, room->first_extradescr, room->last_extradescr, next, prev ); ed->keyword = str_dup( "" ); ed->description = str_dup( "" ); top_ed++; d->character->spare_ptr = ed; olc_log( d, "Added new exdesc" ); oedit_disp_extra_choice(d); OLC_MODE(d) = REDIT_EXTRADESC_CHOICE; return; case 'R': OLC_MODE(d) = REDIT_EXTRADESC_DELETE; send_to_char( d->character, "Delete which extra description? " ); return; default: if ( is_number(arg) ) { ed = redit_find_extradesc( room, atoi(arg) ); if ( !ed ) { send_to_char( d->character, "Not found, try again: " ); return; } d->character->spare_ptr = ed; oedit_disp_extra_choice(d); OLC_MODE(d) = REDIT_EXTRADESC_CHOICE; } else redit_disp_extradesc_menu(d); return; } break; default: /* we should never get here */ send_log( NULL, LOG_OLC, "redit_parse: reached default case in parse_redit" ); break; } /* chiude lo switch */ /* Log the changes, so we can keep track of those sneaky bastards */ /* Don't log on the flags cause it does that above */ /* if ( OLC_MODE(d) != REDIT_FLAGS ) olc_log( d, arg ); */ /*. If we get this far, something has be changed .*/ OLC_CHANGE(d) = TRUE; redit_disp_menu(d); }
bool spec_wanderer( CHAR_DATA *ch ) { OBJ_DATA *trash; OBJ_DATA *trash_next; OBJ_DATA *obj2; ROOM_INDEX_DATA *was_in_room; EXIT_DATA *pexit = NULL; CHAR_DATA *vch; int door; int chance=50; bool found = FALSE; /* Valid direction */ bool thrown = FALSE;/* Whether to be thrown or not */ bool noexit = TRUE; /* Assume there is no valid exits */ was_in_room = ch->in_room; if ( !IS_AWAKE(ch) ) return FALSE; if((pexit = ch->in_room->first_exit) !=NULL) noexit=FALSE; if(chance>number_percent()){ /**** * Look for objects on the ground and pick it up ****/ for ( trash = ch->in_room->first_content; trash; trash = trash_next ) { trash_next = trash->next_content; if ( !IS_SET( trash->wear_flags, ITEM_TAKE ) || IS_OBJ_STAT( trash, ITEM_BURIED ) ) continue; if ( trash->item_type == ITEM_WEAPON || trash->item_type == ITEM_ARMOR || trash->item_type == ITEM_LIGHT ) { separate_obj( trash ); /* So there is no 'sword <6>' gets only one object off ground */ act( AT_ACTION, "$n leans over and gets $p.", ch, trash, NULL, TO_ROOM ); obj_from_room( trash ); trash = obj_to_char( trash, ch ); /***** * If object is too high a level throw it away. *****/ if ( ch->level < trash->level ) { act( AT_ACTION, "$n tries to use $p, but is too inexperienced.",ch, trash, NULL, TO_ROOM ); thrown = TRUE; } /***** * Wear the object if it is not to be thrown. The FALSE is passed * so that the mob wont remove a piece of armor already there * if it is not worn it is assumed that they can't use it or * they already are wearing something. *****/ if(!thrown) wear_obj( ch, trash, FALSE, -1 ); /***** * Look for an object in the inventory that is not being worn * then throw it away... *****/ found=FALSE; if(!thrown) for ( obj2 = ch->first_carrying; obj2; obj2 = obj2->next_content ){ if (obj2->wear_loc == WEAR_NONE){ do_say(ch,"Hmm, I can't use this."); trash=obj2; thrown=TRUE; } } /***** * Ugly bit of code.. * Checks if the object is to be thrown & there is a valid exit, * randomly pick a direction to throw it, and check to make sure no other * spec_wanderer mobs are in that room. *****/ if(thrown && !noexit) while(!found && !noexit){ door=number_door(); if((pexit = get_exit(ch->in_room,door) ) != NULL && pexit->to_room && !IS_SET(pexit->exit_info, EX_CLOSED) && !xIS_SET(pexit->to_room->room_flags, ROOM_NODROP)){ if( (vch = pexit->to_room->first_person) !=NULL) for( vch = pexit->to_room->first_person; vch; vch = vch->next_in_room){ if (!str_cmp(lookup_spec(vch->spec_fun), "spec_wanderer")){ noexit = TRUE; /*act( AT_CYAN,"$n spec_wanderer inroom $T", ch, NULL,dir_name[pexit->vdir], TO_ROOM);*/ return FALSE; } } found = TRUE; } } if (!noexit && thrown){ /*if (trash->value*/ set_cur_obj( trash ); if( damage_obj( trash ) != rOBJ_SCRAPPED){ separate_obj(trash); act( AT_ACTION, "$n growls and throws $p $T.", ch, trash, dir_name[pexit->vdir], TO_ROOM ); obj_from_char( trash ); obj_to_room( trash, pexit->to_room ); char_from_room(ch); char_to_room(ch, pexit->to_room); act( AT_CYAN,"$p thrown by $n lands in the room.",ch, trash, ch, TO_ROOM); char_from_room(ch); char_to_room(ch, was_in_room); } else{ do_say(ch,"This thing is junk!"); act( AT_ACTION, "$n growls and breaks $p.",ch, trash, NULL, TO_ROOM); } return TRUE; } return TRUE; } } /* get next obj */ return FALSE; /* No objects :< */ } return FALSE; }
struct commandResult execute_command(struct player * me, char * cmd_buffer, char * cmd_param) { World *w = me->world; struct commandResult result; int ret = 0; int moved = 0; if(strlen(cmd_buffer) == 0) { printf("What?\n"); } else if(has_exit(me->currentRoom, cmd_buffer)) { printf("You go: %s\n", cmd_buffer); char room_file[30]; memset(&room_file, '\0', sizeof(char)*30); get_exit(&room_file, me->currentRoom, cmd_buffer); //free currentRoom.. struct room * nextRoom = cached_read_room(w, room_file); if(nextRoom != NULL) { // Also free links, items etc //free(me->currentRoom); me->currentRoom=NULL; me->currentRoom = nextRoom; moved = 1; } else { printf("You didn't move.\n"); } } else if(strcmp(cmd_buffer, "examine") == 0) { if((me->currentRoom)->items == NULL) { printf("You do not notice anything.\n"); } else { printf("You notice:-\n"); struct item * itemPtr = (me->currentRoom)->items; do { printf("%s\n", itemPtr->name); itemPtr = itemPtr->link; } while(itemPtr != NULL); } } else if(strcmp(cmd_buffer, "look") == 0) { if(cmd_param != NULL && strlen(cmd_param) > 0) { // printf("%s\n", cmd_param); if(strcmp(cmd_param, "me") == 0) { time_t now; time(&now); int seconds = (int)difftime(now, me->connectionTime); printf( "================================================================================\n" "Player: %s\n" "================================================================================\n" "Current room: %s\n" "Connected for: %d seconds\n", me->name, (me->currentRoom)->name, seconds); } else { printf("You do not notice anything special about: '%s'.\n", cmd_param); } } else { look_player(me); } } else if(strcmp(cmd_buffer, "mem") == 0) { printf("World: %s\n\n", w->name); LoadedRoom *head = w->rooms; printf("Loaded rooms:\n"); do { printf("- %s\n", (head->current)->fileName); head = head->next; } while(head != NULL); // && head->next!=NULL); } else if(strcmp(cmd_buffer, "help") == 0) { showHelp(); } else if(strcmp(cmd_buffer, "quit")==0) { ret = 1; } else { char expanded[30]; if(find_alias(&expanded, cmd_buffer, me)) { printf("Using alias %s.\n", expanded); struct commandResult childResult = execute_command(me, &expanded, cmd_param); ret = childResult.exit; moved = childResult.moved; } else { printf("I do not understand: '%s'.. ?\n", cmd_buffer); } } result.exit = ret; result.moved = moved; return result; }
void plot_course(struct plane *p, int row, int col, int alt) { const bool trace = (p->id == 'i' && frame_no == 575); struct frame *frstart = malloc(sizeof *frstart); struct frame *frend = frstart; frstart->prev = frstart->next = NULL; frstart->opc_start = NULL; struct op_courses *opc_end = NULL; assert(alt == 7 || alt == 0); int bearing = alt ? calc_bearing(row, col) : get_airport_xy(row, col)->bearing; bool cleared_exit = false; struct xyz target; for (struct plane *pi = plstart; pi; pi = pi->next) { if (pi == p) continue; new_op_course(pi->current, &frstart->opc_start, &opc_end, pi->isjet); } incr_opc(frstart->opc_start); if (p->target_airport) { struct airport *a = get_airport(p->target_num); if (a == NULL) { errexit('u', "Plane '%c' headed to unknown airport %d.", p->id, p->target_num); } target.alt = 1; target.row = a->trow; target.col = a->tcol; } else { struct exitspec *e = get_exit(p->target_num); if (e == NULL) { errexit('u', "Plane '%c' headed to unknown exit %d.", p->id, p->target_num); } target.alt = 9; target.row = e->row; target.col = e->col; } tracelog(trace, "Tracing plane %c's course from %d:(%d, %d, %d)@%d to " "(%d, %d, %d)\n", p->id, frame_no, row, col, alt, bearings[bearing].degree, target.row, target.col, target.alt); p->start = p->current = p->end = NULL; add_course_elem(p, row, col, alt, bearing, false, trace ? frame_no : 0); p->start_tm = p->current_tm = frame_no; int tick = frame_no+1; int steps = 0, moves = 0; /* Operation of the "plotting course" machine: * (A) Get a frame for the current pos'n. * (B) If frame has cands, step ahead to the best cand and return to (A). * (C) If not, step back to parent frame and remove the cand and * return to (B). */ for (;;) { if (++steps > 200) { log_course(p); errexit('8', "Plane %c stuck in an infinite loop.", p->id); } // Plane doesn't move if it's a prop and the tick is odd... // ...except that a prop plane in an exit will pop out of it. if (!p->isjet && tick%2 == 1 && row != 0 && col != 0 && row != board_height-1 && col != board_width-1) { add_course_elem(p, row, col, alt, bearing, cleared_exit, trace ? tick : 0); tick++; frend->n_cand = -3; make_new_fr(&frend); continue; } moves++; calc_next_move(p, row, col, &alt, target, &bearing, cleared_exit, frend); assert((alt < 0) == (frend->n_cand <= 0)); while (frend->n_cand <= 0) { tracelog(trace, "Backtracking at step %d move %d tick %d\n", steps, moves, tick); struct xyz bt_pos = backtrack(&tick, &cleared_exit, &p->end, &frend); moves--; // Check for a prop. plane's non-move. // TODO: Do we have to worry about the "pop out of an exit" move // that props get at their first tick? if (frend->n_cand == -3) { tracelog(trace, "Backtracking over prop's non-move at tick %d\n", tick); assert(!p->isjet); bt_pos = backtrack(&tick, &cleared_exit, &p->end, &frend); assert(frend->n_cand != -3); } row = bt_pos.row; col = bt_pos.col; tracelog(trace, "After backtracking: %d: pos(%d, %d, %d) and %d " "remaining candidates\n", tick, bt_pos.row, bt_pos.col, bt_pos.alt, frend->n_cand - 1); if (--frend->n_cand > 0) { // We've found a new candidate that's available after // backtracking, so stop backtracing and get on with it. alt = frend->cand[frend->n_cand-1].alt; bearing = frend->cand[frend->n_cand-1].bearing; break; } tracelog(trace, "No new candidates found at tick %d. Backtracking " "again.\n", tick); } if (alt) { row += bearings[bearing].drow; col += bearings[bearing].dcol; } add_course_elem(p, row, col, alt, bearing, cleared_exit, trace ? tick : 0); tick++; if (row == target.row && col == target.col && alt == target.alt) { // We've reached the target. Clean-up and return. if (p->target_airport) { if (!p->isjet) { add_course_elem(p, row, col, alt, bearing, cleared_exit, trace ? tick : 0); tick++; } add_course_elem(p, -1, -1, -2, -1, cleared_exit, trace ? tick : 0); p->end_tm = tick; } else { // For an exit, the plane disappears at reaching it. p->end_tm = tick-1; p->end->at_exit = true; } free_framelist(frstart); if (!quiet) { struct record *rec = p->isjet ? &rec_jet : &rec_prop; if (steps > rec->steps || moves > rec->moves) { if (steps > rec->steps) rec->steps = steps; if (moves > rec->moves) rec->moves = moves; fprintf(logff, "New record long route: plane '%c' at time " "%d in %d steps/%d moves.\n", p->id, frame_no, steps, moves); log_course(p); log_all_courses(); } } return; } if (!cleared_exit && alt > 1 && ((row > 2 && row < board_height-3 && col > 2 && col < board_width-3) || alt < 6 || alt == 9)) { cleared_exit = true; } make_new_fr(&frend); } }