Allow switching between outline and wfc map generators transitional_engine
authorunC0Rr
Thu, 29 Aug 2024 17:09:39 +0200
branchtransitional_engine
changeset 16026 ce4b50823a95
parent 16025 274a5afc2aec
child 16027 d4675c190fa5
Allow switching between outline and wfc map generators
QTfrontend/model/MapModel.h
QTfrontend/net/hwmap.h
QTfrontend/ui/widget/mapContainer.cpp
hedgewars/uLand.pas
hedgewars/uLandUtils.pas
hedgewars/uTypes.pas
rust/lib-hwengine-future/src/lib.rs
--- 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);
--- 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
--- 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
--- 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;
--- 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;
--- 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
--- 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::<OutlineTemplate>::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(&params, &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(&params, &mut random_numbers_gen);