1
0
Fork 0

Experimental statistic room generation implemented

master
MrMcX vor 8 Jahren
Ursprung 6dee36a6d1
Commit 6eea01482c

@ -3,8 +3,17 @@
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/dungeon/Room.java</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/dungeon/Exit.java</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/.gitignore</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/dungeon/Dungeon.java</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/build.xml</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/nbproject/build-impl.xml</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/main/DungeonGeneratorUI.java</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/util/Counter.java</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/dungeon/Enemy.java</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/util/Dice.java</file>
<file>file:/C:/Users/MrMcX/ownCloud/Rollenspiel/DSA/Meister/DungeonGenerator/src/dungeon/Trap.java</file>
</group>
</open-files>
</project-private>

@ -24,8 +24,12 @@
package dungeon;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import util.Counter;
import util.Dice;
import org.jgraph.graph.DefaultEdge;
@ -34,31 +38,48 @@ import org.jgrapht.graph.SimpleGraph;
/**
* Stores all information about the dungeon
*
* @author MrMcX
*/
public class Dungeon {
private final List<Room> rooms;
private final LinkedList<Room> toGenerate;
private final Counter counter;
private final HashMap greedyMap;
/**
* Stanard constructor, creates a new dungeon and then generates the contens
* Standard constructor, creates a new dungeon
*
* @param size maximum number of rooms
* @param type how the rooms are to construct
* @param mode determines room generation sequence
*/
public Dungeon(int size, Type type, Mode mode){
public Dungeon(int size, Type type) {
rooms = new ArrayList<>();
toGenerate = new LinkedList<>();
counter = new Counter();
generate(size, type, mode);
greedyMap = GreedyMap(size, type);
}
/**
* Returns the greedy map
* @return
*/
public HashMap GetGreedyMap(){
return greedyMap;
}
private void generate(int size, Type type, Mode mode){
toGenerate.add(Room.RandomRoom(true, Exit.Start(), counter, type));
while(!toGenerate.isEmpty() && rooms.size() < size){
/**
* Generates the dungeons contents
* @param size Size of the dungeon
* @param type type of environment
* @param mode generation mode
*/
public void generate(int size, Type type, Mode mode) {
toGenerate.add(Room.RandomRoom(true, Exit.Start(), counter, type, greedyMap));
while (!toGenerate.isEmpty() && (rooms.size() < size || Experimental(type))) {
Room next;
switch(mode){
switch (mode) {
case STRAIGHT:
next = toGenerate.getLast();
break;
@ -66,37 +87,38 @@ public class Dungeon {
next = toGenerate.getFirst();
break;
case RANDOM:
next = toGenerate.get(Dice.Roll(toGenerate.size(), 1)-1);
next = toGenerate.get(Dice.Roll(toGenerate.size(), 1) - 1);
break;
default:
next = toGenerate.getFirst();
break;
}
next.generate(counter, type).stream().forEach((r) -> {
toGenerate.add(r);
next.generate(counter, type, greedyMap).stream().forEach((r) -> {
toGenerate.add((Room) r);
});
toGenerate.remove(next);
rooms.add(next);
rooms.add(next);
}
}
@Override
public String toString(){
public String toString() {
return rooms.stream().map((r) -> r.toLongString() + "\n").reduce("", String::concat);
}
/**
* Creates a graph from the dungeon
*
* @return UndirectedGraph from JGraphT
*/
public UndirectedGraph toGraph(){
UndirectedGraph g = new SimpleGraph(DefaultEdge.class);
public UndirectedGraph toGraph() {
UndirectedGraph g = new SimpleGraph(DefaultEdge.class);
rooms.stream().forEach((r) -> {
g.addVertex(r);
});
rooms.stream().forEach((r) -> {
for(Exit e : r.exits){
if(e.isStart || e.room.number == 0 || g.containsEdge(r, e.room)){
for (Exit e : r.exits) {
if (e.isStart || e.room.number == 0 || g.containsEdge(r, e.room)) {
continue;
}
g.addEdge(r, e.room, e);
@ -104,60 +126,131 @@ public class Dungeon {
});
return g;
}
/**
* Checks whether a type is natural
*
* @param n type to check
* @return is natural
*/
public static boolean Natural(Type n){
public static boolean Natural(Type n) {
return (n == Type.NATURAL || n == Type.EXP_NATURAL);
}
/**
* Checks whether a type is experimental
*
* @param n type to check
* @return is experimental
*/
public static boolean Experimental(Type n) {
return (n == Type.EXP_ARTIFICIAL || n == Type.EXP_NATURAL);
}
/**
* Different room generation sequence modes
*/
public static enum Mode{
public static enum Mode {
/**
* FILO - straight dungeon
*/
STRAIGHT,
/**
* FIFO - branched dungeon
*/
BRANCHED,
/**
* Random - balanced dungeon
*/
RANDOM,
}
/**
* The type of rooms to generate
*/
public static enum Type{
public static enum Type {
/**
* Nature-made rooms
*/
NATURAL,
/**
* "Human"-made rooms
*/
ARTIFICIAL,
/**
* Nature-made rooms in experimental mode
*/
EXP_NATURAL,
/**
* "Human"-made rooms in experimental mode
*/
EXP_ARTIFICIAL
}
private static HashMap GreedyMap(int size, Type type) {
HashMap expMap = new HashMap();
if (Experimental(type)) {
double expVal = 1.0 - (1.0 / size);
expMap.put(0, expVal);
int i = 1;
boolean a = true;
int b = 0;
while (expVal >= 1.0 / 20.0 && i <= 20) {
if (expVal >= (3.0 / 20.0)) {
expMap.put(i, 19);
expVal -= (3.0 / 20.0);
} else if (expVal >= 1.0 / 8.0) {
expMap.put(i, a ? 8 : 11);
expVal -= 1.0 / 8.0;
a = !a;
} else if (expVal >= 1.0 / 10.0) {
switch (b) {
case 1:
expMap.put(i, 1);
break;
case 2:
expMap.put(i, 5);
break;
default:
expMap.put(i, 18);
b = 0;
break;
}
expVal -= 1.0 / 10.0;
b++;
} else if (expVal >= 3.0 / 40.0) {
expMap.put(i, 13);
expVal -= 3.0 / 40.0;
} else {
expMap.put(i, 15);
expVal -= 1.0 / 20.0;
}
i++;
}
int c = 0;
while (i <= 20) {
switch (c) {
case 1:
expMap.put(i, 7);
break;
case 2:
expMap.put(i, 10);
break;
default:
expMap.put(i, 20);
c = 0;
break;
}
c++;
i++;
}
} else {
for (int i = 1; i <= 20; i++) {
expMap.put(i, i);
}
}
return expMap;
}
}

@ -23,6 +23,7 @@
*/
package dungeon;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import util.Counter;
@ -129,15 +130,16 @@ public class Room {
* Generates the content of the room
* @param c Room counter
* @param type Environment type
* @param map Experimental map
* @return Returns more rooms to generate
*/
public List<Room> generate(Counter c, Dungeon.Type type){
public List<Room> generate(Counter c, Dungeon.Type type, HashMap<Integer, Integer> map){
number = c.Next();
List<Room> list = new LinkedList();
for(int i = 0; i < exits.length; i++){
if(exits[i] == null){
Exit predecessor = new Exit(this);
Room newRoom = RandomRoom(false, predecessor, c, type);
Room newRoom = RandomRoom(false, predecessor, c, type, map);
exits[i] = new Exit(newRoom, predecessor.type);
list.add(newRoom);
}
@ -335,16 +337,8 @@ public class Room {
}
}
private static Room CorridorStraight(Exit predecessor, Counter c){
return new Room(predecessor, 2, false, "gerader Gang", c);
}
private static Room CorridorRight(Exit predecessor, Counter c){
return new Room(predecessor, 2, false, "rechts abbiegender Gang", c);
}
private static Room CorridorLeft(Exit predecessor, Counter c){
return new Room(predecessor, 2, false, "links abbiegender Gang", c);
private static Room Corridor(Exit predecessor, Counter c){
return new Room(predecessor, 2, false, "Gang", c);
}
private static Room CrossingT(Exit predecessor, Counter c){
@ -365,16 +359,17 @@ public class Room {
* @param predecessor Predecessor room
* @param c Room counter
* @param type Environment type
* @param map The map for experimental mode
* @return random room
*/
public static Room RandomRoom(boolean first, Exit predecessor, Counter c, Dungeon.Type type){
public static Room RandomRoom(boolean first, Exit predecessor, Counter c, Dungeon.Type type, HashMap<Integer, Integer> map){
int number;
if(first){
number = Dice.Roll(6, 1);
} else {
number = Dice.Roll(20, 1);
}
switch(number){
switch(map.get(number)){
case 1:
case 2:
case 3: return RoomBigExits(predecessor, c, type);
@ -389,9 +384,9 @@ public class Room {
case 12: return RoomSmallExitsStair(predecessor, c, type);
case 13:
case 14: return RoomGiant(predecessor, c, type);
case 15: return CorridorStraight(predecessor, c);
case 16: return CorridorRight(predecessor, c);
case 17: return CorridorLeft(predecessor, c);
case 15:
case 16:
case 17: return Corridor(predecessor, c);
case 18: return CrossingT(predecessor, c);
case 19: return Crossing(predecessor, c);
case 20: return DeadEnd(predecessor, c);

@ -75,13 +75,32 @@
<Property name="text" type="java.lang.String" value="Hilfe"/>
</Properties>
<SubComponents>
<MenuItem class="javax.swing.JMenuItem" name="jMenuItem1">
<MenuItem class="javax.swing.JMenuItem" name="jMenuItemHelp">
<Properties>
<Property name="accelerator" type="javax.swing.KeyStroke" editor="org.netbeans.modules.form.editors.KeyStrokeEditor">
<KeyStroke key="F1"/>
</Property>
<Property name="text" type="java.lang.String" value="Hilfe"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jMenuItemHelpActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="jMenuItemContact">
<Properties>
<Property name="text" type="java.lang.String" value="Kontakt"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jMenuItemContactActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="jMenuItemGithub">
<Properties>
<Property name="text" type="java.lang.String" value="Github"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jMenuItemGithubActionPerformed"/>
</Events>
</MenuItem>
<MenuItem class="javax.swing.JPopupMenu$Separator" name="jSeparator1">
</MenuItem>
@ -174,7 +193,7 @@
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="Raummaximum"/>
<Property name="text" type="java.lang.String" value="Raumanzahl"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="jSpinSize">
@ -208,7 +227,7 @@
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckBoxExp">
<Properties>
<Property name="text" type="java.lang.String" value="Experimenteller Modus"/>
<Property name="text" type="java.lang.String" value="&lt;html&gt;&#xa;&lt;b&gt;Experimenteller Modus&lt;/b&gt;&lt;br/&gt;&#xa;schr&#xe4;nkt Raumzahl nicht direkt ein, sondern &#xe4;ndert die Zufallsfunktion so, dass ihr Erwartungswert der Raumanzahl entspricht"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBoxExpActionPerformed"/>

@ -29,8 +29,10 @@ import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxCellRenderer;
import com.mxgraph.util.mxConstants;
import dungeon.Dungeon;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileWriter;
@ -51,7 +53,11 @@ import org.jgrapht.ext.GmlExporter;
import org.jgrapht.ext.JGraphXAdapter;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.Label;
import java.net.URI;
import java.net.URISyntaxException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
/**
*
@ -113,7 +119,9 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
jMenuImage = new javax.swing.JMenuItem();
jMenuClose = new javax.swing.JMenuItem();
jMenuHelp = new javax.swing.JMenu();
jMenuItem1 = new javax.swing.JMenuItem();
jMenuItemHelp = new javax.swing.JMenuItem();
jMenuItemContact = new javax.swing.JMenuItem();
jMenuItemGithub = new javax.swing.JMenuItem();
jSeparator1 = new javax.swing.JPopupMenu.Separator();
jMenuItemAbout = new javax.swing.JMenuItem();
@ -137,7 +145,7 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
jPanelSettings.setLayout(new java.awt.GridLayout(4, 2));
jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel4.setText("Raummaximum");
jLabel4.setText("Raumanzahl");
jPanelSettings.add(jLabel4);
jSpinSize.setModel(new javax.swing.SpinnerNumberModel(1, 1, null, 1));
@ -146,7 +154,7 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
jPanelSettings.add(jSpinSize);
jPanelSettings.add(filler1);
jCheckBoxExp.setText("Experimenteller Modus");
jCheckBoxExp.setText("<html>\n<b>Experimenteller Modus</b><br/>\nschränkt Raumzahl nicht direkt ein, sondern ändert die Zufallsfunktion so, dass ihr Erwartungswert der Raumanzahl entspricht");
jCheckBoxExp.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jCheckBoxExpActionPerformed(evt);
@ -265,9 +273,30 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
jMenuHelp.setText("Hilfe");
jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F1, 0));
jMenuItem1.setText("Hilfe");
jMenuHelp.add(jMenuItem1);
jMenuItemHelp.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F1, 0));
jMenuItemHelp.setText("Hilfe");
jMenuItemHelp.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemHelpActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemHelp);
jMenuItemContact.setText("Kontakt");
jMenuItemContact.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemContactActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemContact);
jMenuItemGithub.setText("Github");
jMenuItemGithub.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jMenuItemGithubActionPerformed(evt);
}
});
jMenuHelp.add(jMenuItemGithub);
jMenuHelp.add(jSeparator1);
jMenuItemAbout.setText("Über/Lizenz");
@ -290,8 +319,20 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
}//GEN-LAST:event_jMenuCloseActionPerformed
private void jButtonGenerateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonGenerateActionPerformed
mDungeon = new Dungeon((int) jSpinSize.getValue(), SelectedNatural(), SelectedMode());
Dungeon.Mode mode = SelectedMode();
Dungeon.Type type = SelectedNatural();
int size = (int) jSpinSize.getValue();
mDungeon = new Dungeon(size, type);
if (false && Dungeon.Experimental(type)) {
JFrame frame = new JFrame("Debug");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Label lab = new Label();
lab.setText(mDungeon.GetGreedyMap().toString());
frame.getContentPane().add(lab, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
mDungeon.generate(size, type, mode);
mGraph = mDungeon.toGraph();
JGraphXAdapter graphAdapter = new JGraphXAdapter(mGraph);
mGraphComponent = new mxGraphComponent(graphAdapter);
@ -304,9 +345,9 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
jPanelDraw.add(mGraphComponent);
jTextDescription.setText(mDungeon.toString());
jLabelStatus1.setText("Max: " + jSpinSize.getValue());
jLabelStatus2.setText("Type: " + SelectedNatural().toString());
jLabelStatus3.setText("Mode: " + SelectedMode().toString());
jLabelStatus1.setText("Max: " + size);
jLabelStatus2.setText("Type: " + type.toString());
jLabelStatus3.setText("Mode: " + mode.toString());
jMenuSave.setEnabled(true);
jMenuNew.setEnabled(true);
@ -420,12 +461,12 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
String number = vprops.getString("BUILDNUMBER");
String date = vprops.getString("BUILDDATE");
JOptionPane.showMessageDialog(this, "DungeonGenerator Version " + number + "\n"
+ "(compiled on " + date + ")\n"
JOptionPane.showMessageDialog(this, "<html><b>DungeonGenerator Version " + number + "</b>\n"
+ "<html><i>(compiled on " + date + ")</i>\n"
+ "\n"
+ "The MIT License (MIT)\n"
+ "<html><b>The MIT License (MIT)</b>\n"
+ "\n"
+ "Copyright (c) 2016 Simon Moser IT\n"
+ "<html>Copyright &copy; 2016 <a href='https://smoser.eu/'>Simon Moser IT</a>\n"
+ "\n"
+ "Permission is hereby granted, free of charge, to any person\n"
+ "obtaining a copy of this software and associated documentation\n"
@ -448,13 +489,40 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
+ "ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n"
+ "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
+ "\n"
+ "Icons made by Revicon from www.flaticon.com", "Über", JOptionPane.QUESTION_MESSAGE);
+ "<html>Icons made by <a href='http://www.flaticon.com/authors/revicon'>Revicon</a>", "Über", JOptionPane.QUESTION_MESSAGE);
}//GEN-LAST:event_jMenuItemAboutActionPerformed
private void jCheckBoxExpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxExpActionPerformed
// TODO add your handling code here:
int a = JOptionPane.showConfirmDialog(this, "Diese Option kann zu einer Endlosschleife führen", "Achtung", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
if (a == JOptionPane.CANCEL_OPTION) {
jCheckBoxExp.setSelected(false);
}
}//GEN-LAST:event_jCheckBoxExpActionPerformed
private void jMenuItemContactActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemContactActionPerformed
try {
Desktop.getDesktop().mail(new URI("mailto:info@smoser.eu?subject=DungeonGenerator"));
} catch (URISyntaxException | IOException ex) {
Logger.getLogger(DungeonGeneratorUI.class.getName()).log(Level.SEVERE, null, ex);
}
}//GEN-LAST:event_jMenuItemContactActionPerformed
private void jMenuItemHelpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemHelpActionPerformed
try {
Desktop.getDesktop().browse(new URI("https://github.com/MrMcX/DungeonGenerator/issues"));
} catch (URISyntaxException | IOException ex) {
Logger.getLogger(DungeonGeneratorUI.class.getName()).log(Level.SEVERE, null, ex);
}
}//GEN-LAST:event_jMenuItemHelpActionPerformed
private void jMenuItemGithubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemGithubActionPerformed
try {
Desktop.getDesktop().browse(new URI("https://github.com/MrMcX/DungeonGenerator/"));
} catch (URISyntaxException | IOException ex) {
Logger.getLogger(DungeonGeneratorUI.class.getName()).log(Level.SEVERE, null, ex);
}
}//GEN-LAST:event_jMenuItemGithubActionPerformed
/**
* @param args the command line arguments
*/
@ -503,13 +571,13 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
}
private Dungeon.Type SelectedNatural() {
if(jComboBoxNatural.getSelectedItem().equals("Künstlich")){
if(jCheckBoxExp.isSelected()){
if (jComboBoxNatural.getSelectedItem().equals("Künstlich")) {
if (jCheckBoxExp.isSelected()) {
return Dungeon.Type.EXP_ARTIFICIAL;
}
return Dungeon.Type.ARTIFICIAL;
} else {
if(jCheckBoxExp.isSelected()){
if (jCheckBoxExp.isSelected()) {
return Dungeon.Type.EXP_NATURAL;
}
return Dungeon.Type.NATURAL;
@ -535,8 +603,10 @@ public class DungeonGeneratorUI extends javax.swing.JFrame {
private javax.swing.JMenu jMenuGraph;
private javax.swing.JMenu jMenuHelp;
private javax.swing.JMenuItem jMenuImage;
private javax.swing.JMenuItem jMenuItem1;
private javax.swing.JMenuItem jMenuItemAbout;
private javax.swing.JMenuItem jMenuItemContact;
private javax.swing.JMenuItem jMenuItemGithub;
private javax.swing.JMenuItem jMenuItemHelp;
private javax.swing.JMenuItem jMenuNew;
private javax.swing.JMenuItem jMenuSave;
private javax.swing.JPanel jPanelCardDraw;

Laden…
Abbrechen
Speichern