# HG changeset patch # User unC0Rr # Date 1724944179 -7200 # Node ID ce4b50823a95e5b40ea2ebf1c1452d6a7e2c99cf # Parent 274a5afc2aec3dd89daddf8b6baf7509d0eeb770 Allow switching between outline and wfc map generators diff -r 274a5afc2aec -r ce4b50823a95 QTfrontend/model/MapModel.h --- a/QTfrontend/model/MapModel.h Thu Aug 29 15:28:20 2024 +0200 +++ b/QTfrontend/model/MapModel.h Thu Aug 29 17:09:39 2024 +0200 @@ -46,28 +46,30 @@ Q_OBJECT public: - enum MapType { - Invalid, - GeneratedMap, - GeneratedMaze, - GeneratedPerlin, - HandDrawnMap, - MissionMap, - StaticMap, - FortsMap - }; + enum MapType { + Invalid, + GeneratedMap, + GeneratedMaze, + GeneratedPerlin, + HandDrawnMap, + MissionMap, + StaticMap, + FortsMap, + WfcMap + }; - /// a struct for holding the attributes of a map. - struct MapInfo - { - MapType type; ///< The map-type - QString name; ///< The internal name. - QString theme; ///< The theme to be used. (can be empty) - quint32 limit; ///< The maximum allowed number of hedgehogs. - QString scheme; ///< Default scheme name or "locked", for mission-maps. - QString weapons; ///< Default weaponset name or "locked", for missions-maps. - QString desc; ///< The brief 1-2 sentence description of the mission, for mission-maps. - bool dlc; ///< True if this map was not packaged with the game + /// a struct for holding the attributes of a map. + struct MapInfo { + MapType type; ///< The map-type + QString name; ///< The internal name. + QString theme; ///< The theme to be used. (can be empty) + quint32 limit; ///< The maximum allowed number of hedgehogs. + QString scheme; ///< Default scheme name or "locked", for mission-maps. + QString + weapons; ///< Default weaponset name or "locked", for missions-maps. + QString desc; ///< The brief 1-2 sentence description of the mission, + ///< for mission-maps. + bool dlc; ///< True if this map was not packaged with the game }; MapModel(MapType maptype, QObject *parent = 0); diff -r 274a5afc2aec -r ce4b50823a95 QTfrontend/net/hwmap.h --- a/QTfrontend/net/hwmap.h Thu Aug 29 15:28:20 2024 +0200 +++ b/QTfrontend/net/hwmap.h Thu Aug 29 17:09:39 2024 +0200 @@ -26,14 +26,14 @@ #include "tcpBase.h" -enum MapGenerator -{ - MAPGEN_REGULAR = 0, - MAPGEN_MAZE = 1, - MAPGEN_PERLIN = 2, - MAPGEN_DRAWN = 3, - MAPGEN_FORTS = 4, - MAPGEN_MAP = 5 +enum MapGenerator { + MAPGEN_REGULAR = 0, + MAPGEN_MAZE = 1, + MAPGEN_PERLIN = 2, + MAPGEN_DRAWN = 3, + MAPGEN_FORTS = 4, + MAPGEN_WFC = 5, + MAPGEN_MAP = 6, }; class HWMap : public TCPBase diff -r 274a5afc2aec -r ce4b50823a95 QTfrontend/ui/widget/mapContainer.cpp --- a/QTfrontend/ui/widget/mapContainer.cpp Thu Aug 29 15:28:20 2024 +0200 +++ b/QTfrontend/ui/widget/mapContainer.cpp Thu Aug 29 17:09:39 2024 +0200 @@ -129,7 +129,9 @@ cType->insertItem(4, tr("Random maze"), MapModel::GeneratedMaze); cType->insertItem(5, tr("Random perlin"), MapModel::GeneratedPerlin); cType->insertItem(6, tr("Forts"), MapModel::FortsMap); - connect(cType, SIGNAL(currentIndexChanged(int)), this, SLOT(mapTypeChanged(int))); + cType->insertItem(7, tr("WFC"), MapModel::WfcMap); + connect(cType, SIGNAL(currentIndexChanged(int)), this, + SLOT(mapTypeChanged(int))); m_childWidgets << cType; /* Randomize button */ @@ -760,19 +762,23 @@ m_mapInfo.type = MapModel::FortsMap; f = true; break; + case MAPGEN_WFC: + m_mapInfo.type = MapModel::WfcMap; + f = true; + break; case MAPGEN_MAP: - switch (m_mapInfo.type) - { - case MapModel::GeneratedMap: - case MapModel::GeneratedMaze: - case MapModel::GeneratedPerlin: - case MapModel::HandDrawnMap: - case MapModel::FortsMap: - m_mapInfo.type = MapModel::Invalid; - default: - break; - } - break; + switch (m_mapInfo.type) { + case MapModel::GeneratedMap: + case MapModel::GeneratedMaze: + case MapModel::GeneratedPerlin: + case MapModel::HandDrawnMap: + case MapModel::FortsMap: + case MapModel::WfcMap: + m_mapInfo.type = MapModel::Invalid; + default: + break; + } + break; } if(f) @@ -948,10 +954,11 @@ case MapModel::GeneratedMap: case MapModel::GeneratedPerlin: case MapModel::GeneratedMaze: - mapPreview->setWhatsThis(randomAllPrev); - mapFeatureSize->setWhatsThis(mfsComplex); - btnRandomize->setWhatsThis(randomAll); - break; + case MapModel::WfcMap: + mapPreview->setWhatsThis(randomAllPrev); + mapFeatureSize->setWhatsThis(mfsComplex); + btnRandomize->setWhatsThis(randomAll); + break; case MapModel::MissionMap: case MapModel::StaticMap: mapPreview->setWhatsThis(randomAllPrev); @@ -1059,8 +1066,15 @@ setMapInfo(MapModel::MapInfoForts); lblMapList->hide(); break; + case MapModel::WfcMap: + mapgen = MAPGEN_WFC; + setMapInfo(MapModel::MapInfoRandom); + lblMapList->setText(tr("Map size:")); + lblMapList->show(); + generationStyles->show(); + break; default: - break; + break; } // Update theme button size diff -r 274a5afc2aec -r ce4b50823a95 hedgewars/uLand.pas --- a/hedgewars/uLand.pas Thu Aug 29 15:28:20 2024 +0200 +++ b/hedgewars/uLand.pas Thu Aug 29 17:09:39 2024 +0200 @@ -793,11 +793,12 @@ begin WriteLnToConsole('Generating land...'); case cMapGen of - mgRandom: GenerateTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); + mgRandom: GenerateOutlineTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); mgMaze : begin ResizeLand(4096,2048); GenMaze; end; mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; mgDrawn : GenDrawnMap; mgForts : begin GameFlags:= (GameFlags or gfDivideTeams); MakeFortsMap(); end; + mgWfc: GenerateWfcTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); else OutError('Unknown mapgen', true); end; @@ -948,11 +949,12 @@ begin WriteLnToConsole('Generating preview...'); case cMapGen of - mgRandom: GenerateTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); + mgRandom: GenerateOutlineTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); mgMaze: begin ResizeLand(4096,2048); GenMaze; end; mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; mgDrawn: begin GenDrawnMap; end; mgForts: MakeFortsPreview(); + mgWfc: GenerateWfcTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); else OutError('Unknown mapgen', true); end; @@ -1007,11 +1009,12 @@ begin WriteLnToConsole('Generating preview...'); case cMapGen of - mgRandom: GenerateTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); + mgRandom: GenerateOutlineTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); mgMaze: begin ResizeLand(4096,2048); GenMaze; end; mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; mgDrawn: begin GenDrawnMap; end; mgForts: MakeFortsPreview; + mgWfc: GenerateWfcTemplatedLand(cFeatureSize, cSeed, SelectTemplate, PathPrefix); else OutError('Unknown mapgen', true); end; diff -r 274a5afc2aec -r ce4b50823a95 hedgewars/uLandUtils.pas --- a/hedgewars/uLandUtils.pas Thu Aug 29 15:28:20 2024 +0200 +++ b/hedgewars/uLandUtils.pas Thu Aug 29 17:09:39 2024 +0200 @@ -2,7 +2,8 @@ interface uses SDLh; -procedure GenerateTemplatedLand(featureSize: Longword; seed, templateType: shortstring; dataPath: ansistring); +procedure GenerateOutlineTemplatedLand(featureSize: Longword; seed, templateType: shortstring; dataPath: ansistring); +procedure GenerateWfcTemplatedLand(featureSize: Longword; seed, templateType: shortstring; dataPath: ansistring); procedure ResizeLand(width, height: LongWord); procedure DisposeLand(); procedure InitWorldEdges(); @@ -35,7 +36,8 @@ procedure land_pixel_set(game_field: pointer; x, y: LongInt; value: Longword); cdecl; external; function land_pixel_row(game_field: pointer; row: LongInt): PLongwordArray; cdecl; external; -function generate_templated_game_field(feature_size: Longword; seed, template_type, data_path: PChar): pointer; cdecl; external; +function generate_outline_templated_game_field(feature_size: Longword; seed, template_type, data_path: PChar): pointer; cdecl; external; +function generate_wfc_templated_game_field(feature_size: Longword; seed, template_type, data_path: PChar): pointer; cdecl; external; procedure apply_theme(game_field: pointer; data_path, theme_name: PChar); cdecl; external; var gameField: pointer; @@ -75,12 +77,37 @@ LandPixelRow:= land_pixel_row(gameField, row) end; -procedure GenerateTemplatedLand(featureSize: Longword; seed, templateType: shortstring; dataPath: ansistring); +procedure GenerateOutlineTemplatedLand(featureSize: Longword; seed, templateType: shortstring; dataPath: ansistring); begin seed[byte(seed[0]) + 1]:= #0; templateType[byte(templateType[0]) + 1]:= #0; - gameField:= generate_templated_game_field(featureSize, @seed[1], @templateType[1], PChar(dataPath)); + gameField:= generate_outline_templated_game_field(featureSize, @seed[1], @templateType[1], PChar(dataPath)); + get_game_field_parameters(gameField, LAND_WIDTH, LAND_HEIGHT, playWidth, playHeight); + + MaxHedgehogs:= 32; + hasGirders:= true; + + leftX:= (LAND_WIDTH - playWidth) div 2; + rightX:= Pred(leftX + playWidth); + topY:= LAND_HEIGHT - playHeight; + cWaterLine:= LAND_HEIGHT; + + // let's assume those are powers of two + LAND_WIDTH_MASK:= not(LAND_WIDTH-1); + LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); + + SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); + + initScreenSpaceVars(); +end; + +procedure GenerateWfcTemplatedLand(featureSize: Longword; seed, templateType: shortstring; dataPath: ansistring); +begin + seed[byte(seed[0]) + 1]:= #0; + templateType[byte(templateType[0]) + 1]:= #0; + + gameField:= generate_wfc_templated_game_field(featureSize, @seed[1], @templateType[1], PChar(dataPath)); get_game_field_parameters(gameField, LAND_WIDTH, LAND_HEIGHT, playWidth, playHeight); MaxHedgehogs:= 32; diff -r 274a5afc2aec -r ce4b50823a95 hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Thu Aug 29 15:28:20 2024 +0200 +++ b/hedgewars/uTypes.pas Thu Aug 29 17:09:39 2024 +0200 @@ -196,7 +196,7 @@ TStereoMode = (smNone, smRedCyan, smCyanRed, smRedBlue, smBlueRed, smRedGreen, smGreenRed, smHorizontal, smVertical); TWorldEdge = (weNone, weWrap, weBounce, weSea, weSky); TUIDisplay = (uiAll, uiNoTeams, uiNone); - TMapGen = (mgRandom, mgMaze, mgPerlin, mgDrawn, mgForts); + TMapGen = (mgRandom, mgMaze, mgPerlin, mgDrawn, mgForts, mgWFC); THHFont = record diff -r 274a5afc2aec -r ce4b50823a95 rust/lib-hwengine-future/src/lib.rs --- a/rust/lib-hwengine-future/src/lib.rs Thu Aug 29 15:28:20 2024 +0200 +++ b/rust/lib-hwengine-future/src/lib.rs Thu Aug 29 17:09:39 2024 +0200 @@ -4,6 +4,7 @@ wavefront_collapse::generator::{ TemplateDescription as WfcTemplate, }, + outline_template_based::outline_template::OutlineTemplate, LandGenerationParameters, LandGenerator, }; use lfprng::LaggedFibonacciPRNG; @@ -47,7 +48,47 @@ } #[no_mangle] -pub extern "C" fn generate_templated_game_field( +pub extern "C" fn generate_outline_templated_game_field( + feature_size: u32, + seed: *const i8, + template_type: *const i8, + data_path: *const i8, +) -> *mut GameField { + let data_path: &str = unsafe { CStr::from_ptr(data_path) }.to_str().unwrap(); + let data_path = Path::new(&data_path); + + let seed: &str = unsafe { CStr::from_ptr(seed) }.to_str().unwrap(); + let template_type: &str = unsafe { CStr::from_ptr(template_type) }.to_str().unwrap(); + + let mut random_numbers_gen = LaggedFibonacciPRNG::new(seed.as_bytes()); + + let yaml_templates = + fs::read_to_string(data_path.join(Path::new("map_templates.yaml")).as_path()) + .expect("Error reading map templates file"); + let mut map_gen = MapGenerator::::new(data_path); + map_gen.import_yaml_templates(&yaml_templates); + + let distance_divisor = feature_size.pow(2) / 8 + 10; + let params = LandGenerationParameters::new(0u16, 0x8000u16, distance_divisor, false, false); + let template = map_gen + .get_template(template_type, &mut random_numbers_gen) + .expect("Error reading outline templates file") + .clone(); + let landgen = map_gen.build_generator(template); + let collision = landgen.generate_land(¶ms, &mut random_numbers_gen); + let size = collision.size().size(); + + let game_field = Box::new(GameField { + collision, + pixels: land2d::Land2D::new(&size, 0), + landgen_parameters: Some(params), + }); + + Box::leak(game_field) +} + +#[no_mangle] +pub extern "C" fn generate_wfc_templated_game_field( feature_size: u32, seed: *const i8, template_type: *const i8, @@ -71,7 +112,7 @@ let params = LandGenerationParameters::new(0u16, 0x8000u16, distance_divisor, false, false); let template = map_gen .get_template(template_type, &mut random_numbers_gen) - .expect("Error reading templates file") + .expect("Error reading wfc templates file") .clone(); let landgen = map_gen.build_generator(template); let collision = landgen.generate_land(¶ms, &mut random_numbers_gen);