/* Generate some ruins */ void generate_ruins(map_t *map) { /* Start off with a cave */ generate_cave(map); /* Special room wall tiles */ tile_t room_wall = tileset[TILE_WALL]; room_wall.glyph = '%'; room_wall.fg_lit = C_BROWN; /* Put some random rooms onto the map */ int room, rooms = rand() % 5 + 3; int room_x, room_y, room_width, room_height; /* Build each room */ for (room = 0; room < rooms; room++) { room_width = rand() % 8 + 4; room_height = rand() % 6 + 4; room_x = rand() % (map->width - room_width); room_y = rand() % (map->height - room_height); map_fill_rect(map, room_wall, room_x, room_y, room_width, room_height); map_fill_rect(map, tileset[TILE_FLOOR], room_x+1, room_y+1, room_width-2, room_height-2); } }
/* The main game loop */ void play(void) { int playing = 1; int x, y, vpx, vpy; /* A messy way to do the map, works for now */ map_t *map = map_new(50, 50); generate_cave(map); map_fov_build(map); /* Set up the offscreen consoles */ map_layer = TCOD_console_new(ui_viewport_width, ui_viewport_height); psion_layer = TCOD_console_new(ui_viewport_width, ui_viewport_height); TCOD_console_set_key_color(psion_layer, C_KEY); bgcolor(psion_layer, C_KEY); /* Set up the player */ init_player(); rename_player("Gu the Cabeboy"); blink_player(map); /* Initialize the inventory */ /* Enter the main game loop! */ while (playing) { /* Prepare the screen for drawing */ clear(NULL); /* Calculate the position of the viewport */ vpx = player->x - ui_viewport_width/2 > 0 ? player->x - ui_viewport_width/2 : 0; vpy = player->y - ui_viewport_height/2 > 0 ? player->y - ui_viewport_height/2 : 0; if ((vpx + ui_viewport_width) > map->width) { vpx = map->width - ui_viewport_width; } if ((vpy + ui_viewport_height) > map->height) { vpy = map->height - ui_viewport_height; } if (ui_viewport_width > map->width) { vpx = 0; } if (ui_viewport_height > map->height) { vpy = 0; } /* Calculate the field of view */ map_fov_do(map, player->x, player->y); /* Only display the part of the map inside the viewport */ for (y = 0; y < ui_viewport_height; y++) { for (x = 0; x < ui_viewport_width; x++) { if (((vpy+y) < map->height) && ((vpx+x) < map->width)) { tile_t *tile = tile_at(map, vpx+x, vpy+y); if (TCOD_map_is_in_fov(map->fov, vpx+x, vpy+y)) { fgcolor(map_layer, tile->fg_lit); } else { fgcolor(map_layer, tile->fg_dark); } putch(map_layer, x, y, tile->glyph); } } } TCOD_console_blit(map_layer, 0, 0, ui_viewport_width, ui_viewport_height, NULL, ui_viewport_x, ui_viewport_y, 255); /* Draw the player and status */ fgcolor(NULL, C_WHITE); putch(NULL, ui_viewport_x+player->x-vpx, ui_viewport_y+player->y-vpy, '@'); fgcolor(NULL, C_MSG); putstr(NULL, 1, 23, player->name); /* Redraw the screen */ update(); /* Handle keypress */ TCOD_key_t k = getkey(); if (k.c == 0) { switch (k.vk) { /* Move around */ case TCODK_KP7: /* up left */ attempt_move(map, player->x-1, player->y-1); break; case TCODK_KP8: /* up */ case TCODK_UP: attempt_move(map, player->x, player->y-1); break; case TCODK_KP9: /* up right */ attempt_move(map, player->x+1, player->y-1); break; case TCODK_KP1: /* down left */ attempt_move(map, player->x-1, player->y+1); break; case TCODK_KP2: /* down */ case TCODK_DOWN: attempt_move(map, player->x, player->y+1); break; case TCODK_KP3: /* down right */ attempt_move(map, player->x+1, player->y+1); break; case TCODK_KP4: /* left */ case TCODK_LEFT: attempt_move(map, player->x-1, player->y); break; case TCODK_KP6: /* right */ case TCODK_RIGHT: attempt_move(map, player->x+1, player->y); break; /* View character summary */ case TCODK_TAB: character(); break; default: printf("%d %d\n", TCODK_TAB, k.vk); break; } } else { switch (k.c) { /* Quit the game */ case 'Q': playing = quit(); break; /* Open up the inventory */ case 'i': inventory(); break; /* View character summary */ case 'c': character(); break; /* Use scan ability */ case 's': psion_scan(map); break; default: break; } } } /* Clean up, the game is over */ map_destroy(map); }
/*! * @brief フロアの切り替え処理 / Enter new floor. * @return なし * @details * If the floor is an old saved floor, it will be\n * restored from the temporal file. If the floor is new one, new cave\n * will be generated.\n */ void change_floor(void) { saved_floor_type *sf_ptr; bool loaded = FALSE; /* The dungeon is not ready */ character_dungeon = FALSE; /* No longer in the trap detecteded region */ p_ptr->dtrap = FALSE; /* Mega-Hack -- no panel yet */ panel_row_min = 0; panel_row_max = 0; panel_col_min = 0; panel_col_max = 0; /* Mega-Hack -- not ambushed on the wildness? */ ambush_flag = FALSE; /* No saved floors (On the surface etc.) */ if (!(change_floor_mode & CFM_SAVE_FLOORS) && !(change_floor_mode & CFM_FIRST_FLOOR)) { /* Create cave */ generate_cave(); /* Paranoia -- No new saved floor */ new_floor_id = 0; } /* In the dungeon */ else { /* No floor_id yet */ if (!new_floor_id) { /* Get new id */ new_floor_id = get_new_floor_id(); } /* Pointer for infomations of new floor */ sf_ptr = get_sf_ptr(new_floor_id); /* Try to restore old floor */ if (sf_ptr->last_visit) { /* Old saved floor is exist */ if (load_floor(sf_ptr, 0)) { loaded = TRUE; /* Forbid return stairs */ if (change_floor_mode & CFM_NO_RETURN) { cave_type *c_ptr = &cave[p_ptr->y][p_ptr->x]; if (!feat_uses_special(c_ptr->feat)) { if (change_floor_mode & (CFM_DOWN | CFM_UP)) { /* Reset to floor */ c_ptr->feat = floor_type[randint0(100)]; } c_ptr->special = 0; } } } } /* * Set lower/upper_floor_id of new floor when the new * floor is right-above/right-under the current floor. * * Stair creation/Teleport level/Trap door will take * you the same floor when you used it later again. */ if (p_ptr->floor_id) { saved_floor_type *cur_sf_ptr = get_sf_ptr(p_ptr->floor_id); if (change_floor_mode & CFM_UP) { /* New floor is right-above */ if (cur_sf_ptr->upper_floor_id == new_floor_id) sf_ptr->lower_floor_id = p_ptr->floor_id; } else if (change_floor_mode & CFM_DOWN) { /* New floor is right-under */ if (cur_sf_ptr->lower_floor_id == new_floor_id) sf_ptr->upper_floor_id = p_ptr->floor_id; } } /* Break connection to killed floor */ else { if (change_floor_mode & CFM_UP) sf_ptr->lower_floor_id = 0; else if (change_floor_mode & CFM_DOWN) sf_ptr->upper_floor_id = 0; } /* Maintain monsters and artifacts */ if (loaded) { IDX i; s32b tmp_last_visit = sf_ptr->last_visit; s32b absence_ticks; int alloc_chance = d_info[dungeon_type].max_m_alloc_chance; int alloc_times; while (tmp_last_visit > turn) tmp_last_visit -= TURNS_PER_TICK * TOWN_DAWN; absence_ticks = (turn - tmp_last_visit) / TURNS_PER_TICK; /* Maintain monsters */ for (i = 1; i < m_max; i++) { monster_race *r_ptr; monster_type *m_ptr = &m_list[i]; /* Skip dead monsters */ if (!m_ptr->r_idx) continue; if (!is_pet(m_ptr)) { /* Restore HP */ m_ptr->hp = m_ptr->maxhp = m_ptr->max_maxhp; /* Remove timed status (except MTIMED_CSLEEP) */ (void)set_monster_fast(i, 0); (void)set_monster_slow(i, 0); (void)set_monster_stunned(i, 0); (void)set_monster_confused(i, 0); (void)set_monster_monfear(i, 0); (void)set_monster_invulner(i, 0, FALSE); } /* Extract real monster race */ r_ptr = real_r_ptr(m_ptr); /* Ignore non-unique */ if (!(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_NAZGUL)) continue; /* Appear at a different floor? */ if (r_ptr->floor_id != new_floor_id) { /* Disapper from here */ delete_monster_idx(i); } } /* Maintain artifatcs */ for (i = 1; i < o_max; i++) { object_type *o_ptr = &o_list[i]; /* Skip dead objects */ if (!o_ptr->k_idx) continue; /* Ignore non-artifact */ if (!object_is_fixed_artifact(o_ptr)) continue; /* Appear at a different floor? */ if (a_info[o_ptr->name1].floor_id != new_floor_id) { /* Disappear from here */ delete_object_idx(i); } else { /* Cancel preserve */ a_info[o_ptr->name1].cur_num = 1; } } (void)place_quest_monsters(); /* Place some random monsters */ alloc_times = absence_ticks / alloc_chance; if (randint0(alloc_chance) < (absence_ticks % alloc_chance)) alloc_times++; for (i = 0; i < alloc_times; i++) { /* Make a (group of) new monster */ (void)alloc_monster(0, 0); } } /* New floor_id or failed to restore */ else /* if (!loaded) */ { if (sf_ptr->last_visit) { /* Temporal file is broken? */ #ifdef JP msg_print("階段は行き止まりだった。"); #else msg_print("The staircases come to a dead end..."); #endif /* Create simple dead end */ build_dead_end(); /* Break connection */ if (change_floor_mode & CFM_UP) { sf_ptr->upper_floor_id = 0; } else if (change_floor_mode & CFM_DOWN) { sf_ptr->lower_floor_id = 0; } } else { /* Newly create cave */ generate_cave(); } /* Record last visit turn */ sf_ptr->last_visit = turn; /* Set correct dun_level value */ sf_ptr->dun_level = dun_level; /* Create connected stairs */ if (!(change_floor_mode & CFM_NO_RETURN)) { /* Extract stair position */ cave_type *c_ptr = &cave[p_ptr->y][p_ptr->x]; /*** Create connected stairs ***/ /* No stairs down from Quest */ if ((change_floor_mode & CFM_UP) && !quest_number(dun_level)) { c_ptr->feat = (change_floor_mode & CFM_SHAFT) ? feat_state(feat_down_stair, FF_SHAFT) : feat_down_stair; } /* No stairs up when ironman_downward */ else if ((change_floor_mode & CFM_DOWN) && !ironman_downward) { c_ptr->feat = (change_floor_mode & CFM_SHAFT) ? feat_state(feat_up_stair, FF_SHAFT) : feat_up_stair; } /* Paranoia -- Clear mimic */ c_ptr->mimic = 0; /* Connect to previous floor */ c_ptr->special = p_ptr->floor_id; } } /* Arrive at random grid */ if (change_floor_mode & (CFM_RAND_PLACE)) { (void)new_player_spot(); } /* You see stairs blocked */ else if ((change_floor_mode & CFM_NO_RETURN) && (change_floor_mode & (CFM_DOWN | CFM_UP))) { if (!p_ptr->blind) { #ifdef JP msg_print("突然階段が塞がれてしまった。"); #else msg_print("Suddenly the stairs is blocked!"); #endif } else { #ifdef JP msg_print("ゴトゴトと何か音がした。"); #else msg_print("You hear some noises."); #endif } } /* * Update visit mark * * The "turn" is not always different number because * the level teleport doesn't take any turn. Use * visit mark instead of last visit turn to find the * oldest saved floor. */ sf_ptr->visit_mark = latest_visit_mark++; } /* Place preserved pet monsters */ place_pet(); /* Reset travel target place */ forget_travel_flow(); /* Hack -- maintain unique and artifacts */ update_unique_artifact(new_floor_id); /* Now the player is in new floor */ p_ptr->floor_id = new_floor_id; /* The dungeon is ready */ character_dungeon = TRUE; /* Hack -- Munchkin characters always get whole map */ if (p_ptr->pseikaku == SEIKAKU_MUNCHKIN) wiz_lite((bool)(p_ptr->pclass == CLASS_NINJA)); /* Remember when this level was "created" */ old_turn = turn; /* No dungeon feeling yet */ p_ptr->feeling_turn = old_turn; p_ptr->feeling = 0; /* Clear all flags */ change_floor_mode = 0L; select_floor_music(); }
/* * This is the entry point for generation statistics. */ static void stats_collect_level(void) { static bool first = TRUE; size_t i, x, y; memset(o_count, 0, sizeof(o_count)); memset(gold_count, 0, sizeof(gold_count)); mon_gold = 0.0; mon_drop = 0.0; results_reset(); result_add("level", format("%d", p_ptr->depth)); for (i = 0; i < TRIES; i++) { generate_cave(); /* Get stats on objects */ for (y = 1; y < DUNGEON_HGT - 1; y++) { for (x = 1; x < DUNGEON_WID - 1; x++) { const object_type *obj = get_first_object(y, x); if (obj) do { if (obj->tval == TV_GOLD) gold_count[i] += obj->pval; else o_count[i]++; } while ((obj = get_next_object(obj))); } } /* Get stats on monsters */ for (y = 1; y < DUNGEON_HGT - 1; y++) { for (x = 1; x < DUNGEON_WID - 1; x++) { if (cave_m_idx[y][x]) stats_monster(&mon_list[cave_m_idx[y][x]]); } } } stats_print_o(); stats_print_m(); if (first) { /* printf("level,mon-drops"); */ results_print_csv_titles(); first = FALSE; } /* results_print_csv_pair("level", "mon-drops"); */ results_print_csv(); do_cmd_redraw(); }