Implement PastelChime2.AutoDungeonE_Create

This function is responsible for generating random dungeons for Pastel
Chime Continue.

The dgn_generate_drawfield() function implements the main logic. This
algorithm constructs the dungeon through a multi-step process involving
room creation, recursive expansion, wall placement, treasure room
generation, and corridor pruning/extension.

AutoDungeonE_Create() calls this function to create a layout based on
specified parameters, and then populates arrays with the proposed
coordinates of items, enemies, and traps.

This implementation strives to faithfully reproduce the behavior of
DrawField.dll, including its bugs, although it has not been strictly
verified.
This commit is contained in:
kichikuou
2025-09-11 12:53:09 +09:00
parent 037616f38d
commit ddf6ac5088
5 changed files with 1986 additions and 3 deletions
+1 -1
View File
@@ -128,7 +128,7 @@ struct dgn {
float sphere_color_top;
float sphere_color_bottom;
// DrawDungeon2
// for generated dungeons
int start_x, start_y;
int exit_x, exit_y;
+15
View File
@@ -18,7 +18,22 @@
struct dgn;
enum drawfield_cell_flag {
DF_FLAG_ITEM = 1 << 0,
DF_FLAG_ENEMY = 1 << 1,
DF_FLAG_TRAP = 1 << 2,
DF_FLAG_NO_TREASURE = 1 << 3,
DF_FLAG_NO_MONSTER = 1 << 4,
DF_FLAG_NO_TRAP = 1 << 5,
DF_FLAG_TREASURE_ROOM = 1 << 6
};
struct dgn *dgn_generate_drawdungeon2(int level);
void dgn_paint_step(struct dgn *dgn, int x, int y);
struct dgn *dgn_generate_drawfield(
int floor, int complexity, int wall_arrange_method, int floor_arrange_method,
int field_size_x, int field_size_y, int door_lock_percent, uint32_t seed,
uint8_t *cell_flags);
#endif /* SYSTEM4_DUNGEON_GENERATOR_H */
File diff suppressed because it is too large Load Diff
+5
View File
@@ -112,6 +112,11 @@ void dungeon_map_init(struct dungeon_context *ctx)
if (!map)
return;
if (map->textures) {
for (int i = 0; i < map->nr_textures; i++)
gfx_delete_texture(&map->textures[i]);
free(map->textures);
}
map->textures = xcalloc(dgn->size_y, sizeof(struct texture));
map->nr_textures = dgn->size_y;
+71 -2
View File
@@ -27,6 +27,8 @@
#include "hll.h"
#include "dungeon/dgn.h"
#include "dungeon/dungeon.h"
#include "dungeon/generator.h"
#include "dungeon/map.h"
#include "queue.h"
#include "sact.h"
#include "vm/heap.h"
@@ -1781,7 +1783,74 @@ static void PastelChime2_Field_UpdateDoors(
free(flags);
}
//void PastelChime2_AutoDungeonE_Create(int nFloor, int *nEntX, int *nEntY, int nComplex, int nWallArrangeMethod, int nFloorArrangeMethod, int nFieldSizeX, int nFieldSizeY, int nDoorLockPercent, struct page **dci);
static struct page *make_pos_t_array(struct dgn *dgn, uint8_t *cell_flags, int flag)
{
int struct_type = ain_get_struct(ain, "pos_t");
struct ain_struct *s = &ain->structures[struct_type];
int slot_x = find_struct_slot(s, "x");
int slot_y = find_struct_slot(s, "y");
int nr_points = 0;
for (int i = 0; i < dgn->size_z * dgn->size_x; i++) {
if (cell_flags[i] & flag) {
nr_points++;
}
}
struct page *array = alloc_page(ARRAY_PAGE, AIN_ARRAY_STRUCT, nr_points);
array->array.struct_type = struct_type;
array->array.rank = 1;
int out_index = 0;
for (int i = 0; i < dgn->size_z * dgn->size_x; i++) {
if (!(cell_flags[i] & flag))
continue;
struct page *elem = alloc_page(STRUCT_PAGE, struct_type, s->nr_members);
elem->values[slot_x].i = i % dgn->size_x;
elem->values[slot_y].i = i / dgn->size_x;
array->values[out_index++].i = heap_alloc_page(elem);
}
return array;
}
static void replace_object_slot(struct page *obj, const char *name, struct page *page)
{
int slot = struct_get_var(obj, name)->i;
delete_page(slot);
heap_set_page(slot, page);
}
static void PastelChime2_AutoDungeonE_Create(
int floor, int *ent_x, int *ent_y, int complex,
int wall_arrange_method, int floor_arrange_method,
int field_size_x, int field_size_y, int door_lock_percent, struct page **dci)
{
struct dungeon_context *ctx = dungeon_get_context(draw_field_sprite_number);
if (!ctx)
return;
uint8_t *cell_flags = xcalloc(field_size_y, field_size_x);
uint32_t seed = SDL_GetTicks();
NOTICE("PastelChime2.AutoDungeonE_Create: seed = %u, complexity = %d", seed, complex);
struct dgn *dgn = dgn_generate_drawfield(
floor, complex, wall_arrange_method, floor_arrange_method,
field_size_x, field_size_y, door_lock_percent, seed, cell_flags);
if (ctx->dgn)
dgn_free(ctx->dgn);
ctx->dgn = dgn;
dungeon_map_init(ctx);
replace_object_slot(*dci, "aposItem", make_pos_t_array(dgn, cell_flags, DF_FLAG_ITEM));
replace_object_slot(*dci, "aposEnemy", make_pos_t_array(dgn, cell_flags, DF_FLAG_ENEMY));
replace_object_slot(*dci, "aposTrap", make_pos_t_array(dgn, cell_flags, DF_FLAG_TRAP));
replace_object_slot(*dci, "aposNoTreasure", make_pos_t_array(dgn, cell_flags, DF_FLAG_NO_TREASURE));
replace_object_slot(*dci, "aposNoMonster", make_pos_t_array(dgn, cell_flags, DF_FLAG_NO_MONSTER));
replace_object_slot(*dci, "aposNoTrap", make_pos_t_array(dgn, cell_flags, DF_FLAG_NO_TRAP));
*ent_x = dgn->start_x;
*ent_y = dgn->start_y;
free(cell_flags);
}
//void PastelChime2_TestVMArray(struct page **a);
static void PastelChime2_str_erase_found(struct string **s, struct string **key)
@@ -1949,7 +2018,7 @@ HLL_LIBRARY(PastelChime2,
HLL_TODO_EXPORT(JudgeHitPointCircle, PastelChime2_JudgeHitPointCircle),
HLL_TODO_EXPORT(JudgeHitLineCircle, PastelChime2_JudgeHitLineCircle),
HLL_EXPORT(Field_UpdateDoors, PastelChime2_Field_UpdateDoors),
HLL_TODO_EXPORT(AutoDungeonE_Create, PastelChime2_AutoDungeonE_Create),
HLL_EXPORT(AutoDungeonE_Create, PastelChime2_AutoDungeonE_Create),
HLL_TODO_EXPORT(TestVMArray, PastelChime2_TestVMArray),
HLL_EXPORT(str_erase_found, PastelChime2_str_erase_found),
HLL_EXPORT(Field_PickUpRoadShape, PastelChime2_Field_PickUpRoadShape),