1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-18 17:40:48 +02:00

Generate random maps from map editor

This commit is contained in:
nordsoft 2022-08-30 17:08:33 +04:00
parent 4afa8eb463
commit 68b106fdc1
15 changed files with 1097 additions and 35 deletions

View File

@ -203,7 +203,7 @@ void CMapGenOptions::setMapTemplate(const CRmgTemplate * value)
{
mapTemplate = value;
//TODO validate & adapt options according to template
assert(0);
//assert(0);
}
void CMapGenOptions::finalize(CRandomGenerator & rand)
@ -401,7 +401,7 @@ bool CMapGenOptions::checkOptions() const
}
}
const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const
std::vector<const CRmgTemplate *> CMapGenOptions::getPossibleTemplates() const
{
int3 tplSize(width, height, (hasTwoLevels ? 2 : 1));
auto humanPlayers = countHumanPlayers();
@ -437,7 +437,13 @@ const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand
return false;
});
// Select tpl
return templates;
}
const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const
{
auto templates = getPossibleTemplates();
if(templates.empty())
return nullptr;

View File

@ -142,6 +142,8 @@ public:
const CRmgTemplate * getMapTemplate() const;
void setMapTemplate(const CRmgTemplate * value);
std::vector<const CRmgTemplate *> getPossibleTemplates() const;
/// Finalizes the options. All random sizes for various properties will be overwritten by numbers from
/// a random number generator by keeping the options in a valid state. Check options should return true, otherwise
/// this function fails.

View File

@ -118,12 +118,15 @@ void CMapGenerator::initQuestArtsRemaining()
}
}
std::unique_ptr<CMap> CMapGenerator::generate()
std::unique_ptr<CMap> CMapGenerator::generate(bool empty)
{
try
{
addHeaderInfo();
map->initTiles(*this);
if(empty)
return std::move(map->mapInstance);
initPrisonsRemaining();
initQuestArtsRemaining();
genZones();

View File

@ -55,7 +55,7 @@ public:
const CMapGenOptions& getMapGenOptions() const;
std::unique_ptr<CMap> generate();
std::unique_ptr<CMap> generate(bool emptyMap = false);
void findZonesForQuestArts();

View File

@ -9,6 +9,8 @@ set(editor_SRCS
maphandler.cpp
Animation.cpp
graphics.cpp
spoiler.cpp
windownewmap.cpp
)
set(editor_HEADERS
@ -21,10 +23,13 @@ set(editor_HEADERS
maphandler.h
Animation.h
graphics.h
spoiler.h
windownewmap.h
)
set(editor_FORMS
mainwindow.ui
windownewmap.ui
)
assign_source_group(${editor_SRCS} ${editor_HEADERS} VCMI_launcher.rc)

View File

@ -15,6 +15,5 @@ int main(int argc, char * argv[])
{
QApplication vcmieditor(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return vcmieditor.exec();
}

View File

@ -20,6 +20,7 @@
#include "CGameInfo.h"
#include "maphandler.h"
#include "graphics.h"
#include "windownewmap.h"
static CBasicLogConfigurator * logConfig;
@ -87,9 +88,13 @@ MainWindow::MainWindow(QWidget *parent) :
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
sceneMini = new QGraphicsScene(this);
ui->minimapView->setScene(sceneMini);
scene->addPixmap(QPixmap(QString::fromStdString(resPath.native())));
show();
}
MainWindow::~MainWindow()
@ -97,14 +102,50 @@ MainWindow::~MainWindow()
delete ui;
}
void MainWindow::reloadMap()
{
MapHandler mapHandler(map.get());
for(int j = 0; j < map->height; ++j)
{
for(int i = 0; i < map->width; ++i)
{
mapHandler.drawTerrainTile(i, j, 0);
mapHandler.drawObjects(i, j, 0);
}
}
auto mapSizePx = mapHandler.surface.rect();
float ratio = std::fmin(mapSizePx.width() / 256., mapSizePx.height() / 256.);
minimap = mapHandler.surface;
minimap.setDevicePixelRatio(ratio);
scene->clear();
scene->addPixmap(mapHandler.surface);
//ui->graphicsView->setSceneRect(mapHandler.surface.rect());
sceneMini->clear();
sceneMini->addPixmap(minimap);
}
void MainWindow::setMap(std::unique_ptr<CMap> cmap)
{
map = std::move(cmap);
unsaved = true;
filename.clear();
setWindowTitle(filename + " - VCMI Map Editor");
reloadMap();
}
void MainWindow::on_actionOpen_triggered()
{
auto filename = QFileDialog::getOpenFileName(this, tr("Open Image"), QString::fromStdString(VCMIDirs::get().userCachePath().native()), tr("Homm3 Files (*.vmap *.h3m)"));
auto filenameSelect = QFileDialog::getOpenFileName(this, tr("Open Image"), QString::fromStdString(VCMIDirs::get().userCachePath().native()), tr("Homm3 Files (*.vmap *.h3m)"));
if(filename.isNull())
if(filenameSelect.isNull())
return;
QFileInfo fi(filename);
QFileInfo fi(filenameSelect);
std::string fname = fi.fileName().toStdString();
std::string fdir = fi.dir().path().toStdString();
ResourceID resId("MAPS/" + fname, EResType::MAP);
@ -126,19 +167,45 @@ void MainWindow::on_actionOpen_triggered()
QMessageBox::critical(this, "Failed to open map", e.what());
}
MapHandler mapHandler(map.get());
unsaved = false;
filename = filenameSelect;
setWindowTitle(filename + " - VCMI Map Editor");
for(int j = 0; j < map->height; ++j)
{
for(int i = 0; i < map->width; ++i)
{
mapHandler.drawTerrainTile(i, j, 0);
mapHandler.drawObjects(i, j, 0);
}
}
scene->clear();
scene->addPixmap(mapHandler.surface);
ui->graphicsView->setSceneRect(mapHandler.surface.rect());
reloadMap();
}
void MainWindow::on_actionSave_as_triggered()
{
if(!map)
return;
auto filenameSelect = QFileDialog::getSaveFileName(this, tr("Save map"), "", tr("VCMI maps (*.vmap)"));
if(filenameSelect.isNull())
return;
if(!unsaved && filenameSelect == filename)
return;
CMapService mapService;
try
{
mapService.saveMap(map, filenameSelect.toStdString());
}
catch(const std::exception & e)
{
QMessageBox::critical(this, "Failed to save map", e.what());
}
filename = filenameSelect;
unsaved = false;
setWindowTitle(filename + " - VCMI Map Editor");
}
void MainWindow::on_actionNew_triggered()
{
auto newMapDialog = new WindowNewMap(this);
}

View File

@ -20,15 +20,26 @@ public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void setMap(std::unique_ptr<CMap> cmap);
void reloadMap();
private slots:
void on_actionOpen_triggered();
void on_actionSave_as_triggered();
void on_actionNew_triggered();
private:
Ui::MainWindow *ui;
QGraphicsScene * scene;
QGraphicsScene * sceneMini;
QPixmap minimap;
std::unique_ptr<CMap> map;
QString filename;
bool unsaved = false;
};
#endif // MAINWINDOW_H

View File

@ -11,12 +11,38 @@
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
<string>VCMI Map Editor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGraphicsView" name="graphicsView"/>
<item row="0" column="1">
<widget class="QGraphicsView" name="minimapView">
<property name="minimumSize">
<size>
<width>256</width>
<height>256</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>256</width>
<height>256</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QGraphicsView" name="graphicsView">
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
</widget>
</item>
</layout>
</widget>
@ -33,7 +59,10 @@
<property name="title">
<string>File</string>
</property>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
<addaction name="actionSave_as"/>
</widget>
<addaction name="menuFile"/>
</widget>
@ -48,13 +77,30 @@
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
</widget>
<action name="actionOpen">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="actionSave">
<property name="text">
<string>Save</string>
</property>
</action>
<action name="actionNew">
<property name="text">
<string>New</string>
</property>
</action>
<action name="actionSave_as">
<property name="text">
<string>Save as</string>
</property>
</action>
</widget>
<resources/>
<connections/>

View File

@ -11,7 +11,7 @@
class CGObjectInstance;
class CGBoat;
struct PlayerColor;
class PlayerColor;
struct TerrainTileObject
{

58
mapeditor/spoiler.cpp Normal file
View File

@ -0,0 +1,58 @@
#include <QPropertyAnimation>
#include "Spoiler.h"
Spoiler::Spoiler(const QString & title, const int animationDuration, QWidget *parent) : QWidget(parent), animationDuration(animationDuration)
{
toggleButton.setStyleSheet("QToolButton { border: none; }");
toggleButton.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toggleButton.setArrowType(Qt::ArrowType::RightArrow);
toggleButton.setText(title);
toggleButton.setCheckable(true);
toggleButton.setChecked(false);
headerLine.setFrameShape(QFrame::HLine);
headerLine.setFrameShadow(QFrame::Sunken);
headerLine.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
contentArea.setStyleSheet("QScrollArea { background-color: white; border: none; }");
contentArea.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
// start out collapsed
contentArea.setMaximumHeight(0);
contentArea.setMinimumHeight(0);
// let the entire widget grow and shrink with its content
toggleAnimation.addAnimation(new QPropertyAnimation(this, "minimumHeight"));
toggleAnimation.addAnimation(new QPropertyAnimation(this, "maximumHeight"));
toggleAnimation.addAnimation(new QPropertyAnimation(&contentArea, "maximumHeight"));
// don't waste space
mainLayout.setVerticalSpacing(0);
mainLayout.setContentsMargins(0, 0, 0, 0);
int row = 0;
mainLayout.addWidget(&toggleButton, row, 0, 1, 1, Qt::AlignLeft);
mainLayout.addWidget(&headerLine, row++, 2, 1, 1);
mainLayout.addWidget(&contentArea, row, 0, 1, 3);
setLayout(&mainLayout);
QObject::connect(&toggleButton, &QToolButton::clicked, [this](const bool checked) {
toggleButton.setArrowType(checked ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow);
toggleAnimation.setDirection(checked ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
toggleAnimation.start();
});
}
void Spoiler::setContentLayout(QLayout & contentLayout)
{
delete contentArea.layout();
contentArea.setLayout(&contentLayout);
const auto collapsedHeight = sizeHint().height() - contentArea.maximumHeight();
auto contentHeight = contentLayout.sizeHint().height();
for (int i = 0; i < toggleAnimation.animationCount() - 1; ++i) {
QPropertyAnimation * spoilerAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(i));
spoilerAnimation->setDuration(animationDuration);
spoilerAnimation->setStartValue(collapsedHeight);
spoilerAnimation->setEndValue(collapsedHeight + contentHeight);
}
QPropertyAnimation * contentAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(toggleAnimation.animationCount() - 1));
contentAnimation->setDuration(animationDuration);
contentAnimation->setStartValue(0);
contentAnimation->setEndValue(contentHeight);
}

27
mapeditor/spoiler.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef SPOILER_H
#define SPOILER_H
#include <QFrame>
#include <QGridLayout>
#include <QParallelAnimationGroup>
#include <QScrollArea>
#include <QToolButton>
#include <QWidget>
class Spoiler : public QWidget {
Q_OBJECT
private:
QGridLayout mainLayout;
QToolButton toggleButton;
QFrame headerLine;
QParallelAnimationGroup toggleAnimation;
QScrollArea contentArea;
int animationDuration{300};
public:
explicit Spoiler(const QString & title = "", const int animationDuration = 300, QWidget *parent = 0);
void setContentLayout(QLayout & contentLayout);
};
#endif // SPOILER_H

234
mapeditor/windownewmap.cpp Normal file
View File

@ -0,0 +1,234 @@
#include "../lib/mapping/CMap.h"
#include "../lib/rmg/CRmgTemplateStorage.h"
#include "../lib/rmg/CRmgTemplate.h"
#include "../lib/rmg/CMapGenerator.h"
#include "../lib/VCMI_Lib.h"
#include "windownewmap.h"
#include "ui_windownewmap.h"
#include "mainwindow.h"
WindowNewMap::WindowNewMap(QWidget *parent) :
QDialog(parent),
ui(new Ui::WindowNewMap)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setWindowModality(Qt::ApplicationModal);
show();
}
WindowNewMap::~WindowNewMap()
{
delete ui;
}
void WindowNewMap::on_cancelButton_clicked()
{
close();
}
void WindowNewMap::on_okButtong_clicked()
{
EWaterContent::EWaterContent water = EWaterContent::RANDOM;
EMonsterStrength::EMonsterStrength monster = EMonsterStrength::RANDOM;
if(ui->waterOpt1->isChecked())
water = EWaterContent::RANDOM;
if(ui->waterOpt2->isChecked())
water = EWaterContent::NONE;
if(ui->waterOpt3->isChecked())
water = EWaterContent::NORMAL;
if(ui->waterOpt4->isChecked())
water = EWaterContent::ISLANDS;
if(ui->monsterOpt1->isChecked())
monster = EMonsterStrength::RANDOM;
if(ui->monsterOpt2->isChecked())
monster = EMonsterStrength::GLOBAL_WEAK;
if(ui->monsterOpt3->isChecked())
monster = EMonsterStrength::GLOBAL_NORMAL;
if(ui->monsterOpt4->isChecked())
monster = EMonsterStrength::GLOBAL_STRONG;
mapGenOptions.setWaterContent(water);
mapGenOptions.setMonsterStrength(monster);
CMapGenerator generator(mapGenOptions);
static_cast<MainWindow*>(parent())->setMap(generator.generate(!ui->randomMapCheck->isChecked()));
close();
}
void WindowNewMap::generateEmptyMap()
{
}
void WindowNewMap::generateRandomMap()
{
}
void WindowNewMap::on_sizeCombo_activated(int index)
{
std::map<int, std::pair<int, int>> sizes
{
{0, {36, 36}},
{1, {72, 72}},
{2, {108, 108}},
{3, {144, 144}},
};
ui->widthTxt->setText(QString::number(sizes[index].first));
ui->heightTxt->setText(QString::number(sizes[index].second));
}
void WindowNewMap::on_twoLevelCheck_stateChanged(int arg1)
{
bool twoLevel = ui->twoLevelCheck->isChecked();
mapGenOptions.setHasTwoLevels(twoLevel);
updateTemplateList();
}
void WindowNewMap::on_humanCombo_activated(int index)
{
const int playerLimit = 8;
std::map<int, int> players
{
{0, CMapGenOptions::RANDOM_SIZE},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{6, 6},
{7, 7},
{8, 8}
};
int humans = players[index];
if(humans > playerLimit)
{
humans = playerLimit;
ui->humanCombo->setCurrentIndex(humans);
return;
}
mapGenOptions.setPlayerCount(humans);
int teams = mapGenOptions.getTeamCount();
if(teams > humans - 1)
{
teams = humans - 1;
//TBD
}
int cpu = mapGenOptions.getCompOnlyPlayerCount();
if(cpu > playerLimit - humans)
{
cpu = playerLimit - humans;
ui->cpuCombo->setCurrentIndex(cpu + 1);
}
int cpuTeams = mapGenOptions.getCompOnlyTeamCount(); //comp only players - 1
if(cpuTeams > cpu - 1)
{
cpuTeams = cpu - 1;
//TBD
}
//void setMapTemplate(const CRmgTemplate * value);
updateTemplateList();
}
void WindowNewMap::on_cpuCombo_activated(int index)
{
const int playerLimit = 8;
std::map<int, int> players
{
{0, CMapGenOptions::RANDOM_SIZE},
{1, 0},
{2, 1},
{3, 2},
{4, 3},
{5, 4},
{6, 5},
{7, 6},
{8, 7}
};
int humans = mapGenOptions.getPlayerCount();
int cpu = players[index];
if(cpu > playerLimit - humans)
{
cpu = playerLimit - humans;
ui->cpuCombo->setCurrentIndex(cpu + 1);
return;
}
mapGenOptions.setCompOnlyPlayerCount(cpu);
updateTemplateList();
}
void WindowNewMap::on_randomMapCheck_stateChanged(int arg1)
{
randomMap = ui->randomMapCheck->isChecked();
ui->templateCombo->setEnabled(randomMap);
updateTemplateList();
}
void WindowNewMap::on_templateCombo_activated(int index)
{
if(index == 0)
{
mapGenOptions.setMapTemplate(nullptr);
return;
}
auto * templ = VLC->tplh->getTemplate(ui->templateCombo->currentText().toStdString());
mapGenOptions.setMapTemplate(templ);
}
void WindowNewMap::on_widthTxt_textChanged(const QString &arg1)
{
mapGenOptions.setWidth(arg1.toInt());
updateTemplateList();
}
void WindowNewMap::on_heightTxt_textChanged(const QString &arg1)
{
mapGenOptions.setHeight(arg1.toInt());
updateTemplateList();
}
void WindowNewMap::updateTemplateList()
{
ui->templateCombo->clear();
ui->templateCombo->setCurrentIndex(-1);
if(!randomMap)
return;
mapGenOptions.setMapTemplate(nullptr);
auto templates = mapGenOptions.getPossibleTemplates();
if(templates.empty())
return;
ui->templateCombo->addItem("[default]");
for(auto * templ : templates)
{
ui->templateCombo->addItem(QString::fromStdString(templ->getName()));
}
ui->templateCombo->setCurrentIndex(0);
}

54
mapeditor/windownewmap.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef WINDOWNEWMAP_H
#define WINDOWNEWMAP_H
#include <QDialog>
#include "../lib/rmg/CMapGenOptions.h"
namespace Ui {
class WindowNewMap;
}
class WindowNewMap : public QDialog
{
Q_OBJECT
public:
explicit WindowNewMap(QWidget *parent = nullptr);
~WindowNewMap();
private slots:
void on_cancelButton_clicked();
void on_okButtong_clicked();
void on_sizeCombo_activated(int index);
void on_twoLevelCheck_stateChanged(int arg1);
void on_humanCombo_activated(int index);
void on_cpuCombo_activated(int index);
void on_randomMapCheck_stateChanged(int arg1);
void on_templateCombo_activated(int index);
void on_widthTxt_textChanged(const QString &arg1);
void on_heightTxt_textChanged(const QString &arg1);
private:
void generateEmptyMap();
void generateRandomMap();
void updateTemplateList();
private:
Ui::WindowNewMap *ui;
CMapGenOptions mapGenOptions;
bool randomMap = false;
};
#endif // WINDOWNEWMAP_H

550
mapeditor/windownewmap.ui Normal file
View File

@ -0,0 +1,550 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WindowNewMap</class>
<widget class="QDialog" name="WindowNewMap">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>447</width>
<height>385</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>390</width>
<height>351</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>9999</width>
<height>9999</height>
</size>
</property>
<property name="windowTitle">
<string>Create new map</string>
</property>
<property name="modal">
<bool>false</bool>
</property>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>271</width>
<height>81</height>
</rect>
</property>
<property name="title">
<string>Map size</string>
</property>
<widget class="QComboBox" name="sizeCombo">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>141</width>
<height>32</height>
</rect>
</property>
<item>
<property name="text">
<string>S (36x36)</string>
</property>
</item>
<item>
<property name="text">
<string>M (72x72)</string>
</property>
</item>
<item>
<property name="text">
<string>L (108x108)</string>
</property>
</item>
<item>
<property name="text">
<string>XL (144x144)</string>
</property>
</item>
</widget>
<widget class="QLineEdit" name="heightTxt">
<property name="geometry">
<rect>
<x>210</x>
<y>50</y>
<width>51</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>36</string>
</property>
<property name="maxLength">
<number>3</number>
</property>
</widget>
<widget class="QLineEdit" name="widthTxt">
<property name="geometry">
<rect>
<x>210</x>
<y>20</y>
<width>51</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>36</string>
</property>
<property name="maxLength">
<number>3</number>
</property>
</widget>
<widget class="QCheckBox" name="twoLevelCheck">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>121</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Two level map</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>140</x>
<y>20</y>
<width>58</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Width</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>140</x>
<y>50</y>
<width>58</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Height</string>
</property>
</widget>
</widget>
<widget class="QPushButton" name="okButtong">
<property name="geometry">
<rect>
<x>310</x>
<y>20</y>
<width>111</width>
<height>32</height>
</rect>
</property>
<property name="text">
<string>Ok</string>
</property>
</widget>
<widget class="QPushButton" name="cancelButton">
<property name="geometry">
<rect>
<x>310</x>
<y>50</y>
<width>111</width>
<height>32</height>
</rect>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
<widget class="QGroupBox" name="groupBox_5">
<property name="geometry">
<rect>
<x>10</x>
<y>120</y>
<width>431</width>
<height>251</height>
</rect>
</property>
<property name="title">
<string>Random map</string>
</property>
<widget class="QComboBox" name="templateCombo">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>90</x>
<y>220</y>
<width>331</width>
<height>32</height>
</rect>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
</widget>
<widget class="QLabel" name="label_5">
<property name="geometry">
<rect>
<x>20</x>
<y>220</y>
<width>58</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Template</string>
</property>
</widget>
<widget class="QGroupBox" name="groupBox_2">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>411</width>
<height>91</height>
</rect>
</property>
<property name="title">
<string>Players</string>
</property>
<widget class="QComboBox" name="humanCombo">
<property name="geometry">
<rect>
<x>120</x>
<y>20</y>
<width>91</width>
<height>32</height>
</rect>
</property>
<item>
<property name="text">
<string>Random</string>
</property>
</item>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="cpuCombo">
<property name="geometry">
<rect>
<x>120</x>
<y>50</y>
<width>91</width>
<height>32</height>
</rect>
</property>
<item>
<property name="text">
<string>Random</string>
</property>
</item>
<item>
<property name="text">
<string>0</string>
</property>
</item>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="humanTeamsCombo">
<property name="geometry">
<rect>
<x>320</x>
<y>20</y>
<width>91</width>
<height>32</height>
</rect>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="cpuTeamsCombo">
<property name="geometry">
<rect>
<x>320</x>
<y>50</y>
<width>91</width>
<height>32</height>
</rect>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Human/Computer</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Computer only</string>
</property>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox_4">
<property name="geometry">
<rect>
<x>10</x>
<y>170</y>
<width>411</width>
<height>41</height>
</rect>
</property>
<property name="title">
<string>Monster strength</string>
</property>
<widget class="QRadioButton" name="monsterOpt1">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Random</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QRadioButton" name="monsterOpt2">
<property name="geometry">
<rect>
<x>90</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Weak</string>
</property>
</widget>
<widget class="QRadioButton" name="monsterOpt3">
<property name="geometry">
<rect>
<x>170</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Normal</string>
</property>
</widget>
<widget class="QRadioButton" name="monsterOpt4">
<property name="geometry">
<rect>
<x>260</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Strong</string>
</property>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox_3">
<property name="geometry">
<rect>
<x>10</x>
<y>120</y>
<width>411</width>
<height>41</height>
</rect>
</property>
<property name="title">
<string>Water content</string>
</property>
<widget class="QRadioButton" name="waterOpt1">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Random</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QRadioButton" name="waterOpt2">
<property name="geometry">
<rect>
<x>90</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>None</string>
</property>
</widget>
<widget class="QRadioButton" name="waterOpt3">
<property name="geometry">
<rect>
<x>170</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Normal</string>
</property>
</widget>
<widget class="QRadioButton" name="waterOpt4">
<property name="geometry">
<rect>
<x>260</x>
<y>20</y>
<width>99</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Islands</string>
</property>
</widget>
</widget>
</widget>
<widget class="QCheckBox" name="randomMapCheck">
<property name="geometry">
<rect>
<x>10</x>
<y>100</y>
<width>331</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Generate random map</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>