diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/laby.iml b/.idea/laby.iml
new file mode 100644
index 0000000..216b054
--- /dev/null
+++ b/.idea/laby.iml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/artgaphics_0_1_0.xml b/.idea/libraries/artgaphics_0_1_0.xml
new file mode 100644
index 0000000..f00ac9e
--- /dev/null
+++ b/.idea/libraries/artgaphics_0_1_0.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..bcd4766
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..b142ba3
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LISEZMOI b/LISEZMOI
index ea87c6e..1f87cb0 100644
--- a/LISEZMOI
+++ b/LISEZMOI
@@ -5,6 +5,14 @@ Il s'agit d'un générateur de labyrinthes écrit en langage java.
Pour le lancer vous devez avoir installé un environnement java 8 ( avec javafx (*) )
+racourçi :
+
+sous linux ./laby.sh
+
+sous windows lancez le laby.bat
+
+il s'gait d'un porgramme java qui peut aussi être lancé avec l'interpréteur java ainsi :
+
java -jar artloglaby-1.0.jar
mail pl@artisanlogiciel.net
@@ -14,5 +22,6 @@ vous pouvez le distribuer ou bien même le vendre
ses sources sont sur https://github.com/artlog/labystl
( et utilise aussi https://github.com/artlog/sharedrawweb )
+Les labyrinthes que vous sauvegardez le sont dans le répertoire lab.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..e413b6a
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = c
+dist_doc_DATA = README
diff --git a/README b/README
index c1423d6..b7e1822 100644
--- a/README
+++ b/README
@@ -3,7 +3,8 @@ This is a personal project to generate a 2D maze using in depth path generation.
Download the 'latest' laby.zip containing java jar from my blog http://blog.artisanlogiciel.net/public/tech/laby.zip
-this can generate a stl file, overall goal was to print it with a 3D printer, i didn't test it yet ( even if i actualy have a 3D printer ).
+this can generate a stl file, overall goal was to print it with a 3D printer.
+After years i finaly printed one maze, find it at https://www.thingiverse.com/thing:2814655
This is the very first usable part.
It was developped under debian 7/8 but since it is java based it might be very easily recompiled or even just copied on other platform.
@@ -25,6 +26,8 @@ cd labystl
./init.sh
# will create build scripts from artlog_toolbox
# ./doit.sh
+# depends on sharedrawweb for stl export
+./fetch_dependencies.sh
ant dist
source ./specificdoit.sh; create_zip_package
unzip laby.zip; cd artloglaby ; ./laby.sh
diff --git a/bootstrapbuild.sh b/bootstrapbuild.sh
new file mode 100755
index 0000000..c7957c4
--- /dev/null
+++ b/bootstrapbuild.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+if [[ ! -f configure.ac ]]
+then
+ echo "[ERROR] Missing configure.ac . Please create one " >&2
+ exit 1
+fi
+
+if which autoreconf
+then
+
+ echo "bootstrap using automake tools"
+ echo "from configure.ac will generate configure"
+
+ autoreconf --install
+
+ echo "lauch ./configure && make"
+
+else
+
+ echo "[ERROR] Missing autoreconf script from autotools. Please install autotools ( package autotools-dev and autoreconf" >&2
+
+fi
diff --git a/build.xml b/build.xml
index 973e799..d99e9ad 100644
--- a/build.xml
+++ b/build.xml
@@ -10,10 +10,10 @@
-
+
-
-
+
+
@@ -26,6 +26,7 @@
+
@@ -37,8 +38,8 @@
-
-
+
+
@@ -50,5 +51,4 @@
-
diff --git a/c/Makefile.am b/c/Makefile.am
new file mode 100644
index 0000000..fe8ba1c
--- /dev/null
+++ b/c/Makefile.am
@@ -0,0 +1,12 @@
+# Makefile.am is REALLY where changes should be done
+# Makefile.in and Makefile are generated from this.
+
+bin_PROGRAMS = laby
+
+laby_SOURCES = allaby_reader.c allaby_main.c
+
+laby_CPPFLAGS = $(ARTLOG_CPPFLAGS) $(ALEXPANDER_CPPFLAGS)
+
+# in LDADD and not in LDFLAGS to be linked AFTER
+laby_LDADD = $(ARTLOG_LDFLAGS) $(ALEXPANDER_LDFLAGS)
+
diff --git a/c/allaby_main.c b/c/allaby_main.c
new file mode 100644
index 0000000..6284847
--- /dev/null
+++ b/c/allaby_main.c
@@ -0,0 +1,17 @@
+#include "al_options.h"
+
+// NOT YET IMPLEMENTED
+int main(int argc, char ** argv)
+{
+ int exitcode = 1;
+ struct al_options * options = al_options_create(argc,argv);
+ al_options_set_debug(options,0);
+ struct alhash_datablock * debugdata = al_option_get(options,"debug");
+ if ( debugdata != NULL )
+ {
+ exitcode = 0;
+ }
+ al_options_release(options);
+
+ return exitcode;
+}
diff --git a/c/allaby_reader.c b/c/allaby_reader.c
new file mode 100644
index 0000000..feefc82
--- /dev/null
+++ b/c/allaby_reader.c
@@ -0,0 +1,2 @@
+#include "allaby_reader.h"
+
diff --git a/c/allaby_reader.h b/c/allaby_reader.h
new file mode 100644
index 0000000..92f85e0
--- /dev/null
+++ b/c/allaby_reader.h
@@ -0,0 +1,9 @@
+#ifndef __ALLABY_READER_H__
+#define __ALLABY_READER_H__
+
+/** goal : read a labyrinth/maze created
+by java laby project
+**/
+
+
+#endif // __ALLABY_READER_H__
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..01758a0
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,37 @@
+# written manually, this is root entry files for automake together with Makefile.am
+# inspired from
+# http://www.gnu.org/software/automake/manual/html_node/Creating-amhello.html#Creating-amhello
+
+AC_INIT([allaby], [0.1], [pl@artisanlogiciel.net])
+
+# set ARTLOG_TOOLBOX where artlog_toolbox is to use it.
+[ARTLOG_TOOLBOX=`pwd`/`./locate_artlog_toolbox.sh`]
+
+# non need to propagate it in .h ...
+# AC_DEFINE_UNQUOTED([ARTLOG_TOOLBOX],["$ARTLOG_TOOLBOX"],[where artog toolbox is])
+
+ARTLOG_CPPFLAGS="-I${ARTLOG_TOOLBOX}/build/include"
+ARTLOG_LDFLAGS="-Wl,-Bstatic -L${ARTLOG_TOOLBOX}/build/lib -lalsave -laltest -laljson -lalstack -lalhash -laldev -Wl,-Bdynamic"
+
+AC_SUBST(ARTLOG_CPPFLAGS)
+AC_SUBST(ARTLOG_LDFLAGS)
+
+[if [ "$ALEXPANDER_DIR" = "" ]]
+[then]
+[ALEXPANDER_DIR=`pwd`/../sharedrawweb]
+[fi]
+ALEXPANDER_CPPFLAGS="-I${ALEXPANDER_DIR}/build/include -D CHARSPERRECORD=80"
+ALEXPANDER_LDFLAGS="-Wl,-Bstatic -L${ALEXPANDER_DIR}/build/lib -lalima -lalcommon -Wl,-Bdynamic"
+
+AC_SUBST(ALEXPANDER_CPPFLAGS)
+AC_SUBST(ALEXPANDER_LDFLAGS)
+
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AC_PROG_CC
+AC_CONFIG_HEADERS([config.h])
+AC_DEFINE([MAX_FLAT_VIEWS],[20],[maximum number of view])
+AC_CONFIG_FILES([
+ Makefile
+ c/Makefile
+])
+AC_OUTPUT
diff --git a/fetch_dependencies.sh b/fetch_dependencies.sh
new file mode 100755
index 0000000..0eeff37
--- /dev/null
+++ b/fetch_dependencies.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+if [[ ! -d ../sharedrawweb ]]
+then
+ echo "[ERROR] expected a sharedrawweb project parent ( for exports )" >&2
+fi
+
+if [[ ! -d libs ]]
+then
+ mkdir libs
+fi
+
+if [[ ! -e libs/artgaphics-0.1.0.jar ]]
+then
+ ln -s ../../sharedrawweb/dist/lib/artgaphics-0.1.0.jar libs/
+fi
diff --git a/java/Makefile b/java/Makefile
index 90904b5..1b58e23 100644
--- a/java/Makefile
+++ b/java/Makefile
@@ -11,8 +11,8 @@ $(OUT):
# mkdir -p $(OUT)
clean:
- @find $(PACKAGE_DIR) -name "*.class" -type f -print0|xargs -0 rm 2>/dev/null && echo "cleaned classes in source"
- @find $(OUT) -name "*.class" -type f -print0|xargs -0 rm 2>/dev/null || echo "nothing to clean"
+ @find $(PACKAGE_DIR) -name "*.class" -type f -print0|xargs -0 --no-run-if-empty rm 2>/dev/null
+ @find $(OUT) -name "*.class" -type f -print0|xargs -0 --no-run-if-empty rm 2>/dev/null
test:
echo "$(pwd)/$(PACKAGE_DIR)"
diff --git a/java/org/artisanlogiciel/games/DirectionPosition.java b/java/org/artisanlogiciel/games/DirectionPosition.java
index 96567ac..f11f88a 100644
--- a/java/org/artisanlogiciel/games/DirectionPosition.java
+++ b/java/org/artisanlogiciel/games/DirectionPosition.java
@@ -1,77 +1,60 @@
package org.artisanlogiciel.games;
/**
- DirectionPosition
-
-record direction and position ( direction as defined in LabyModel ).
+ * DirectionPosition
+ *
+ * record direction and position ( direction as defined in LabyModel ).
**/
-public class DirectionPosition
-{
+public class DirectionPosition {
private short direction;
private Position position;
// (direction,position)
- DirectionPosition(short d, Position p)
- {
- direction=d;
- position=p;
+ public DirectionPosition(short d, Position p) {
+ direction = d;
+ position = p;
}
- short getDirection()
- {
- return direction;
+ public short getDirection() {
+ return direction;
}
- void setDirection(short d)
- {
- direction = d;
+ public void setDirection(short d) {
+ direction = d;
}
- Position getPosition()
- {
- return position;
+ public Position getPosition() {
+ return position;
}
- public String toString()
- {
- if (position != null)
- {
- return position.toString();
- }
- return "?";
+ public String toString() {
+ if (position != null) {
+ return position.toString();
+ }
+ return "?";
}
// create a new DirectionPosition from this using one possible direction.
- DirectionPosition moveToAdjacentDirection()
- {
- short pointingdirection = 0;
- Position p = null;
- if (LabyModel.isFlagSet(direction,LabyModel.RIGHT))
- {
- p = new Position(position.getX() + 1, position.getY());
- pointingdirection |= LabyModel.LEFT;
- }
- else if (LabyModel.isFlagSet(direction,LabyModel.LEFT))
- {
- p = new Position(position.getX() -1 ,position.getY());
- pointingdirection |= LabyModel.RIGHT;
- }
- else if (LabyModel.isFlagSet(direction,LabyModel.UP))
- {
- p = new Position(position.getX(),position.getY() -1);
- pointingdirection |= LabyModel.DOWN;
- }
- else if (LabyModel.isFlagSet(direction,LabyModel.DOWN))
- {
- p = new Position(position.getX(),position.getY() + 1);
- pointingdirection |= LabyModel.UP;
- }
- else
- {
- p = position;
- }
+ public DirectionPosition moveToAdjacentDirection() {
+ short pointingdirection = 0;
+ Position p = null;
+ if (LabyModel.isFlagSet(direction, LabyModel.RIGHT)) {
+ p = new Position(position.getX() + 1, position.getY());
+ pointingdirection |= LabyModel.LEFT;
+ } else if (LabyModel.isFlagSet(direction, LabyModel.LEFT)) {
+ p = new Position(position.getX() - 1, position.getY());
+ pointingdirection |= LabyModel.RIGHT;
+ } else if (LabyModel.isFlagSet(direction, LabyModel.UP)) {
+ p = new Position(position.getX(), position.getY() - 1);
+ pointingdirection |= LabyModel.DOWN;
+ } else if (LabyModel.isFlagSet(direction, LabyModel.DOWN)) {
+ p = new Position(position.getX(), position.getY() + 1);
+ pointingdirection |= LabyModel.UP;
+ } else {
+ p = position;
+ }
- return new DirectionPosition((short) pointingdirection, p);
+ return new DirectionPosition((short) pointingdirection, p);
}
}
diff --git a/java/org/artisanlogiciel/games/Display.java b/java/org/artisanlogiciel/games/Display.java
deleted file mode 100644
index b83903d..0000000
--- a/java/org/artisanlogiciel/games/Display.java
+++ /dev/null
@@ -1,1375 +0,0 @@
-package org.artisanlogiciel.games;
-
-import java.awt.BorderLayout;
-import java.awt.image.BufferedImage;
-import java.awt.Color;
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.Graphics;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import java.awt.event.InputEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseMotionListener;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.Locale;
-import java.util.Scanner;
-import java.util.ResourceBundle;
-
-import javax.imageio.ImageIO;
-
-import javax.swing.AbstractAction;
-import javax.swing.Action;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JCheckBox;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSlider;
-import javax.swing.JTextField;
-import javax.swing.KeyStroke;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-
-import org.artisanlogiciel.games.stl.Wall3d;
-import org.artisanlogiciel.util.UTF8Control;
-
-import org.artisanlogiciel.graphics.Drawing;
-import org.artisanlogiciel.graphics.DrawingLine;
-import org.artisanlogiciel.graphics.SvgWriter;
-
-/**
- * Display is Main JFrame for this tool
- **/
-public class Display extends JFrame
-{
- // to please eclipse, not supposed to be serialized
- private static final long serialVersionUID = 8500214871372184418L;
-
- final static ResourceBundle labels = ResourceBundle.getBundle("LabelsBundle", Locale.getDefault(), Display.class.getClassLoader(), new UTF8Control());
-
- MazeComponent maze;
- MazeControler controler;
- LabyModel model;
- JPanel controlPanel;
- boolean autoSize;
-
- MazeParams params = null;
-
- Drawing drawing = new Drawing();
-
- Display(LabyModel model,int W, int H, MazeParams params)
- {
- super(labels.getString("title"));
- if (params != null)
- {
- // fixedParams = new MazeParamsFixed(params.getSaveDir(),params.getWidth(),params.getHeight(),params.getMaxDepth());
- this.params = params;
- }
- this.model = model;
- maze = createMazeComponent(model,W,H);
-
- Container con = this.getContentPane();
- JScrollPane scrollableMaze = new JScrollPane(maze);
- scrollableMaze.addMouseMotionListener(maze);
- con.add(scrollableMaze, BorderLayout.CENTER);
- controler = new MazeControler(params);
- con.add(controler.getMoveControl(), BorderLayout.NORTH);
- con.add(controler.getGenerationControl(), BorderLayout.SOUTH);
-
- addComponentListener(new ComponentAdapter() {
- @Override
- public void componentResized(ComponentEvent e) {
- if ( autoSize )
- {
- maze.getAutoSize();
- }
- }
- });
-
- model.setMazeListener(maze);
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- setBounds(W, H, W, H);
- setVisible(true);
- }
-
- private static MazeComponent createMazeComponent(LabyModel model, int W, int H)
- {
- MazeCellParameters cp = new MazeCellParameters(model.getWidth(),model.getHeight(), W, H, 3, 3);
- MazeComponent comp = new MazeComponent(model, cp);
- return comp;
- }
-
- void recreateModel()
- {
- // recreate labyrinth
- if (params != null)
- {
- params = controler.getSettings().getParams();
- // keep current model...
- // model = new LabyModel(params, new java.util.Random());
- maze.resetWallsProvider(model);
- model.setMazeListener(maze);
-
- model.reset();
-
- // we are in GUI event thread, need to release it and do it outside.
- new Thread() {
- public void run() {
- model.generateWithEntry(0, 0);
- model.addEntryOrExit(-1, 0);
- model.addEntryOrExit(params.getWidth(), params.getHeight() - 1);
- }
- }.start();
- }
- }
-
- void resetModel()
- {
- // recreate labyrinth
- if (params != null)
- {
- params = controler.getSettings().getParams();
- model = new LabyModel(params, new java.util.Random());
- maze.resetWallsProvider(model);
- model.setMazeListener(maze);
-
-
- // we are in GUI event thread, need to release it and do it outside.
- new Thread() {
- public void run() {
- maze.changed(null,null,model);
- }
- }.start();
-
-
- }
- }
-
- void resolve()
- {
- model.reset();
- model.resolve(model.getWidth() - 1, model.getHeight() - 1, maze);
- }
-
- void goNorth()
- {
- maze.goNorth();
- }
-
- void goSouth()
- {
- maze.goSouth();
- }
-
- void goEast()
- {
- maze.goEast();
- }
-
- void goWest()
- {
- maze.goWest();
- }
-
- void setWallSize(int size)
- {
- maze.setWallSize(size);
- }
-
- void setAutoSize(boolean autoSize)
- {
- this.autoSize = autoSize;
- if ( autoSize )
- {
- maze.getAutoSize();
- }
- }
-
- void addWallInDrawing(int pX, int pY, Drawing d)
- {
- short walls = model.getWalls(pX,pY);
- short wdrawn = 0;
- // todo
- int w = 2;
- int h = 2;
- int ox=0;
- int oy=0;
-
- int x = ox + (int) (pX * w);
- int y = oy + (int) (pY * h);
- DrawingLine dl = new DrawingLine();
- // order matters since all points are linked
- if ( (pY == 0) && LabyModel.isFlagSet(walls,Brick.UP) )
- {
- dl.addPoint(new Point(x, y));
- dl.addPoint(new Point(x + (int) w, y));
- wdrawn |= Brick.UP;
- }
- if (LabyModel.isFlagSet(walls,Brick.RIGHT))
- {
- if ( ! LabyModel.isFlagSet(wdrawn,Brick.UP) )
- {
- dl.addPoint(new Point(x + (int) w, y));
- }
- dl.addPoint(new Point(x + (int) w, y + (int) h));
- wdrawn |= Brick.RIGHT;
- }
- if (LabyModel.isFlagSet(walls,Brick.DOWN))
- {
- if ( ! LabyModel.isFlagSet(wdrawn,Brick.RIGHT) )
- {
- if (wdrawn != 0)
- {
- d.addLine(dl);
- dl = new DrawingLine();
- }
- dl.addPoint(new Point(x + (int) w, y + (int) h));
- }
- dl.addPoint(new Point(x, y + (int) h));
- wdrawn |= Brick.DOWN;
- }
- if ( (pX == 0 ) && LabyModel.isFlagSet(walls,Brick.LEFT))
- {
- if ( ! LabyModel.isFlagSet(wdrawn,Brick.DOWN) )
- {
- if (wdrawn != 0)
- {
- d.addLine(dl);
- dl = new DrawingLine();
- }
- dl.addPoint(new Point(x, y + (int) h));
- }
- dl.addPoint(new Point(x, y));
- wdrawn |= Brick.LEFT;
- }
- if (wdrawn != 0)
- {
- d.addLine(dl);
- }
- }
-
- Drawing createDrawing()
- {
- Drawing d = new Drawing();
- {
- short walls;
-
- // draw all walls within clip bounds horiz first then lines
- for (int y = 0; y < model.getHeight(); y++)
- {
- for (int x = 0; x < model.getWidth(); x ++)
- {
- addWallInDrawing(x,y,d);
- }
- }
- }
- return d;
- }
-
- // to allow to log / write somewher into screen...
- void writeSentence(String pSentence)
- {
- // TODO
- System.out.println( pSentence);
- }
-
- void writeError(String pError)
- {
- System.err.println(pError);
- }
-
- void saveImc()
- {
- Drawing d = createDrawing();
-
- if ( d != null )
- {
- File outfile = new File(params.getSaveDir(), params.getName() + ".imc");
- writeSentence("Saving to " + outfile + " ...");
- try
- {
- DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile));
- d.saveLinesKompressed(out);
- out.flush();
- out.close();
- writeSentence("... Done.");
- }
- catch (IOException io)
- {
- io.printStackTrace(System.err);
- }
- }
- }
-
- void saveSvg()
- {
- Drawing d = createDrawing();
-
- if ( d != null )
- {
- File outfile = new File(params.getSaveDir(), params.getName() + ".svg");
- writeSentence("Saving to " + outfile + " ...");
- try
- {
- DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile));
- SvgWriter writer = new SvgWriter(d.getInternLines());
- writer.writeTo(out);
- out.flush();
- out.close();
- writeSentence("... Done.");
- }
- catch (IOException io)
- {
- io.printStackTrace(System.err);
- }
- }
- else
- {
- writeError("drawing creation failed");
- }
- }
-
-
-
- void savePng()
- {
- File file = new File("snapshot.png");
- // BufferedImage bi = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_ARGB);
- BufferedImage bi = new BufferedImage(maze.getSize().width, maze.getSize().height, BufferedImage.TYPE_INT_ARGB);
- Graphics g = bi.createGraphics();
- // this.paint(g);
- maze.paint(g);
- g.dispose();
- try{
- ImageIO.write(bi,"png",file);
- }catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private class MazeSettings extends JPanel
- {
- MazeParams params;
-
- JTextField textWidth = null;
- JTextField textHeight = null;
- JTextField textDepth = null;
-
- // TODO set width and height and depth of maze with gui
- public MazeSettings(MazeParams params)
- {
- super();
- this.params = params;
- createSettingsGui();
- }
-
- void createSettingsGui()
- {
- if ( params != null )
- {
- JButton buttonCreate = new JButton(labels.getString("create"));
- buttonCreate.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent evt)
- {
- recreateModel();
- }
- });
- add(buttonCreate);
-
- JButton buttonReset = new JButton("reset");//labels.getString("reset"));
- buttonReset.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent evt)
- {
- resetModel();
- }
- });
- add(buttonReset);
-
- }
- if ( params != null )
- {
- JLabel widthLabel = new JLabel(labels.getString("width"));
- textWidth = new JTextField("0" + params.getWidth());
- add(widthLabel);
- add(textWidth);
- JLabel heightLabel = new JLabel(labels.getString("height"));
- textHeight = new JTextField("0" + params.getHeight());
- add(heightLabel);
- add(textHeight);
- JLabel depthLabel = new JLabel(labels.getString("depth"));
- textDepth = new JTextField("0" + params.getMaxDepth());
- add(depthLabel);
- add(textDepth);
- }
- }
-
- public MazeParams getParams()
- {
- return new MazeParamsFixed(params.getSaveDir(),
- Integer.parseInt(textWidth.getText()),
- Integer.parseInt(textHeight.getText()),
- Integer.parseInt(textDepth.getText()));
- }
-
- }
-
- private static class MazeParamsFixed implements MazeParams
- {
- int width;
- int height;
- int maxdepth;
- File labdir;
- String name;
-
- public MazeParamsFixed()
- {
- }
-
- public MazeParamsFixed(MazeParams params)
- {
- setParams(params.getSaveDir(),params.getWidth(),params.getHeight(),params.getMaxDepth());
- }
-
- public void setParams(File saveDir, int W, int H, int MD)
- {
- labdir = saveDir;
- width=W;
- height=H;
- maxdepth=MD;
- }
-
- public MazeParamsFixed(File saveDir, int W, int H, int MD)
- {
- name = null;
- setParams(saveDir,W,H,MD);
- }
-
- public int getWidth()
- {
- return width;
- }
-
- public int getHeight()
- {
- return height;
- }
-
- public int getMaxDepth()
- {
- return maxdepth;
- }
-
- public void setName(String n)
- {
- name = n;
- }
-
- public String getName()
- {
- if (name == null)
- {
- name = "lab" + width + "x" + height;
- }
- return name;
- }
-
- public File getSaveDir()
- {
- return labdir;
- }
- }
-
-
- private class MazeControler extends JPanel
- {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- private MazeSettings settings = null;
-
- private JPanel resizecontrol = null;
-
- private void setMazeName(String pName)
- {
- MazeParamsFixed p = (MazeParamsFixed) params;
- p.setName(pName);
- }
-
- private JPanel createSavingBar()
- {
- final JTextField saveName = new JTextField("newlaby ");
- final JButton savePngButton = new JButton(labels.getString("save") +" png");
- Action savePngAction = new AbstractAction() {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("save png");
- setMazeName(saveName.getText());
- savePng();
- }
- };
- savePngButton.addActionListener(savePngAction);
- final JButton saveSvgButton = new JButton(labels.getString("save") +" svg");
- Action saveSvgAction = new AbstractAction() {
- public void actionPerformed(ActionEvent evt)
- {
- writeSentence("save png");
- setMazeName(saveName.getText());
- saveSvg();
- }
- };
- saveSvgButton.addActionListener(saveSvgAction);
- final JButton saveButton = new JButton(labels.getString("save") +" raw");
- Action saveAction = new AbstractAction() {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("save");
- setMazeName(saveName.getText());
- MazeParamsFixed p = (MazeParamsFixed) params;
- save(p,model);
- }
- };
- saveButton.addActionListener(saveAction);
- final JButton saveImcButton = new JButton(labels.getString("save") +" imc");
- Action saveImcAction = new AbstractAction() {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("save imc");
- setMazeName(saveName.getText());
- saveImc();
- }
- };
- saveImcButton.addActionListener(saveImcAction);
-
- JPanel savePanel = new JPanel(new FlowLayout());
- savePanel.add(saveName);
- savePanel.add(saveSvgButton);
- savePanel.add(savePngButton);
- savePanel.add(saveButton);
- savePanel.add(saveImcButton);
-
- return savePanel;
-
- }
-
- private JPanel createResolveQuitBar()
- {
- JPanel resolveQuitBar = new JPanel(new FlowLayout());
- JButton resolveButton = new JButton(labels.getString("resolve"));
- resolveButton.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("Resolving");
- resolve();
- }
- });
-
- resolveQuitBar.add(resolveButton);
-
- final JButton quitButton = new JButton(labels.getString("quit"));
- Action quitAction = new AbstractAction() {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("quit");
- System.exit(0);
- }
- };
- quitButton.addActionListener(quitAction);
-
- resolveQuitBar.add(quitButton);
-
- return resolveQuitBar;
-
- }
-
- public MazeControler(MazeParams params)
- {
- // super(new BorderLayout());
- super();
- BoxLayout layout = new BoxLayout(this,BoxLayout.Y_AXIS);
- setLayout(layout);
-
- add(createSavingBar());
-
- add(createResolveQuitBar());
-
- controlPanel = new JPanel(new BorderLayout());
- settings = new MazeSettings(params);
- @SuppressWarnings("serial")
- Action goNorth = new AbstractAction()
- {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("go North");
- goNorth();
- }
- };
- JButton north = addDirection(this, labels.getString("north"), "UP", goNorth);
-
- @SuppressWarnings("serial")
- Action goEast = new AbstractAction()
- {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("go East");
- goEast();
- }
- };
-
- JButton east = addDirection(this, labels.getString("east"), "RIGHT", goEast);
-
- @SuppressWarnings("serial")
- Action goWest = new AbstractAction()
- {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("go West");
- goWest();
- }
- };
- JButton west = addDirection(this, labels.getString("west"), "LEFT", goWest);
-
- @SuppressWarnings("serial")
- Action goSouth = new AbstractAction()
- {
- public void actionPerformed(ActionEvent evt)
- {
- //
- System.out.println("go South");
- goSouth();
- }
- };
- JButton south = addDirection(this, labels.getString("south"), "DOWN", goSouth);
-
- controlPanel.add(north, BorderLayout.NORTH);
- controlPanel.add(west, BorderLayout.WEST);
- controlPanel.add(east, BorderLayout.EAST);
- controlPanel.add(south, BorderLayout.SOUTH);
- add(controlPanel, BorderLayout.NORTH);
-
- // control display panel contains controls for display
- // zoom , autozoom.
- final JPanel controlDisplayPanel = new JPanel(new BorderLayout());
- final JCheckBox showAll = new JCheckBox("show all");
- showAll.addChangeListener(new ChangeListener()
- {
- public void stateChanged(ChangeEvent e)
- {
- maze.setShowAll( showAll.isSelected());
- }
- });
-
- final JSlider slider = new JSlider(2, 40);
- slider.addChangeListener(new ChangeListener()
- {
- public void stateChanged(ChangeEvent e)
- {
- setWallSize(slider.getValue());
- }
- });
- final JCheckBox autoSlide = new JCheckBox("autoslide");
- autoSlide.addChangeListener(new ChangeListener()
- {
- public void stateChanged(ChangeEvent e)
- {
- setAutoSize( autoSlide.isSelected());
- }
- });
-
- resizecontrol = new JPanel(new FlowLayout());
- resizecontrol.add(showAll);
- resizecontrol.add(slider);
- resizecontrol.add(autoSlide);
-
- add(controlDisplayPanel, BorderLayout.SOUTH);
- add(resizecontrol,BorderLayout.WEST);
- add(settings,BorderLayout.EAST);
-
- }
-
- private JPanel getMoveControl()
- {
- return this;
- }
-
- private JPanel getResizeControl()
- {
- return resizecontrol;
- }
-
- private JPanel getGenerationControl()
- {
- return settings;
- }
-
- public MazeSettings getSettings()
- {
- return settings;
- }
-
- }
-
- private JButton addDirection(final JPanel panel, final String direction, String key, Action goAction)
- {
- String actionName = "go" + direction;
- JButton button = new JButton(direction);
- button.addActionListener(goAction);
- KeyStroke keystroke = KeyStroke.getKeyStroke(key);
- // attach keys to maze
- maze.getInputMap().put(keystroke, actionName);
- maze.getActionMap().put(actionName, goAction);
- return button;
- }
-
- private static class MazeCellParameters
- {
- double width = 10; // width of one cell
- double height = 10; // height of one cell
- int offsetX = 5; // x offset of upper corner left
- int offsetY = 5; // y offset of upper corner left
-
- int mapWidth = 0;
- int mapHeight = 0;
-
- public MazeCellParameters(int mapw, int maph, int W, int H, int x, int y)
- {
- double w = ( W - x )/ mapw;
- double h = ( H - y )/ maph;
- mapWidth = mapw;
- mapHeight = maph;
- if (w < 5)
- w = 5;
- if (h < 5)
- h = 5;
- setCellSize(w,h);
- offsetX = x;
- offsetY = y;
- }
-
- public void resetMazeWidthHeight(int mapw, int maph)
- {
- mapWidth = mapw;
- mapHeight = maph;
- }
-
- public void adaptTo(double W, double H)
- {
- double w = ( W - offsetX ) / mapWidth;
- double h = ( H - offsetY ) / mapHeight;
- mapWidth = mapWidth;
- mapHeight = mapHeight;
- if (w < 5)
- w = 5;
- if (h < 5)
- h = 5;
- setCellSize(w,h);
- }
-
- public void setCellSize(double w, double h)
- {
- width = w;
- height = h;
- }
-
- public double getWidth()
- {
- return width;
- }
-
- public double getHeight()
- {
- return height;
- }
-
- public int getOffsetX()
- {
- return offsetX;
- }
-
- public int getOffsetY()
- {
- return offsetY;
- }
-
- public Dimension getDimension()
- {
- return new Dimension(offsetX + (int) (mapWidth * width),
- offsetY + (int) (mapHeight * height));
- }
-
- public void drawWalls(Graphics g, int pX, int pY, short walls)
- {
- int x = offsetX + (int) (pX * width);
- int y = offsetY + (int) (pY * height);
- if ( (pY == 0) && ((walls & Brick.UP) == Brick.UP))
- g.drawLine(x, y, x + (int) width, y);
- if ((walls & Brick.DOWN) == Brick.DOWN)
- g.drawLine(x, y + (int) height, x + (int) width, y + (int) height);
- if ((walls & Brick.RIGHT) == Brick.RIGHT)
- g.drawLine(x + (int) width, y, x + (int) width, y + (int) height);
- if ( (pX == 0 ) && ((walls & Brick.LEFT) == Brick.LEFT))
- g.drawLine(x, y, x, y + (int) height);
- }
-
- public void drawPath(Graphics g, DirectionPosition dp, int pX, int pY, int mX, int mY)
- {
- if ( dp != null )
- {
- Position dot = dp.getPosition();
- if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY))
- {
- int x = offsetX + (int) (dot.getX() * width);
- int y = offsetY + (int) (dot.getY() * height);
- short path = dp.getDirection();
- int xm = x+ (int) (width / 2);
- int ym = y+ (int) (height / 2);
- if ( (path & LabyModel.HORIZONTAL) == LabyModel.HORIZONTAL)
- {
- if ( (path & LabyModel.POSITIVE) == LabyModel.POSITIVE )
- {
- g.drawLine(xm, ym, x + (int) width, ym);
- g.drawLine(xm, ym + (int) (height / 4), x + (int) width, ym);
- }
- // LEFT /_
- if ( (path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE )
- {
- g.drawLine(x, ym, xm, ym);
- g.drawLine(x, ym, xm, ym - (int) (height / 4));
- }
- }
- if ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL)
- {
- if ( (path & LabyModel.POSITIVE) == LabyModel.POSITIVE )
- {
- g.drawLine(xm, ym, xm , y + (int) height);
- g.drawLine(xm - (int) (width / 4), ym , xm, y + (int) height);
- }
- // UP |\
- if ( (path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE )
- {
- g.drawLine(xm, ym, xm , y);
- g.drawLine(xm + (int) (width /4), ym , xm , y);
- }
- }
- }
- }
- }
-
- public void drawDot(Graphics g, Position dot, int pX, int pY, int mX, int mY)
- {
- double radius = (height > width) ? width : height;
- int a = (int) ( radius / 4 );
- if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY))
- {
- int x = offsetX + (int) (dot.getX() * width);
- int y = offsetY + (int) (dot.getY() * height);
- int r2 = (int) ( (radius * 3)/4 );
- g.drawOval(x + 1, y + 1, r2, r2);
- // g.drawLine(x+a,y+a,x+width-a,y+height-a);
- // g.drawLine(x+a,y+height-a,x+width-a,y+a);
-
- }
- else
- {
- int x = offsetX + (int) (pX * width);
- int y = offsetY + (int) (pY * height);
- g.drawLine(x + 1, y + 1, x + (int) width - 1, y + (int) height - 1);
- }
- }
-
- }
-
- private static class MazeComponent
- extends JComponent
- implements MazeCreationListener,
- MazeResolutionListener,
- MouseMotionListener
- {
- private static final long serialVersionUID = 3163272907991176390L;
-
- // WallsProvider map;
- LabyModel map;
- final MazeCellParameters cp;
- Position current = null;
- LinkedList solvedPath = null;
- LinkedList drawingPath = null;
- final Object lockChange = new Object();
- // current postion of human resolving
- int sX = 0;
- int sY = 0;
- // goal exit
- int gX = -1;
- int gY = -1;
-
- // not set by default for debug, will show any path
- boolean showAll = false;
-
- // for a given (x,y) pixel return cell position.
- Position getPosition(int x, int y)
- {
- int pX = (int) ((double) (x - cp.getOffsetX()) / cp.getWidth());
- int pY = (int) ((double) (y - cp.getOffsetY()) / cp.getHeight());
- return new Position(pX,pY);
- }
-
- @Override
- public void mouseDragged(MouseEvent e) {
- // should find the cell ...
- DirectionPosition last = null;
- short path = 0;
- Position newPosition = getPosition(e.getX(),e.getY());
- if (drawingPath == null )
- {
- drawingPath = new LinkedList<>();
- last = new DirectionPosition((short) 0,newPosition);
- System.out.println("Mouse dragged Cell " + newPosition + " Button " + e.getModifiersEx() + " " + InputEvent.BUTTON1_DOWN_MASK);
- drawingPath.addLast(last);
- }
- else
- {
- // setShowAll(true);
- DirectionPosition first = drawingPath.getLast();
- last = first;
- // construct as many move form last to new position as needed.
- while ( ! last.getPosition().equals(newPosition))
- {
- path=LabyModel.getDirection(last.getPosition(),newPosition);
- last.setDirection(path);
- // button 1 : add direction; button 2 : replace with direction.
- if ( ( e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK ) != 0 )
- {
- map.addDirection(last.getPosition().getX(),last.getPosition().getY(),path);
- }
- else
- {
- map.setDirection(last.getPosition().getX(),last.getPosition().getY(),path);
- }
- last = last.moveToAdjacentDirection();
- drawingPath.addLast(last);
- }
- System.out.println("Mouse dragged from Cell " + first.getPosition() + "To" + newPosition + " Button " + e.getModifiersEx() + " " + InputEvent.BUTTON1_DOWN_MASK);
- }
- changed(null,null,map);
- }
-
- @Override
- public void mouseMoved(MouseEvent e) {
- // System.out.println("Mouse moved (" + e.getX() + ',' + e.getY() + ')');
- Position newPosition = getPosition(e.getX(),e.getY());
- if ( ( newPosition.getX() >= 0 ) && ( newPosition.getY() >= 0 ) )
- {
- requestFocus();
- }
- }
-
- public void setShowAll(boolean showall )
- {
- this.showAll = showall;
- System.out.println(showAll ? "show all" : "X");
- }
-
- void checkExit()
- {
- if ((sX == gX) && (sY == gY))
- {
- System.out.println("Exit found by human !");
- }
- }
-
- void goNorth()
- {
- resetResolution();
- if ((map.getWalls(sX, sY) & Brick.UP) == 0)
- {
- sY = sY - 1;
- // should redraw ...
- invalidate();
- repaint();
-
- checkExit();
- }
-
- }
-
- void goSouth()
- {
- resetResolution();
- if ((map.getWalls(sX, sY) & Brick.DOWN) == 0)
- {
- sY = sY + 1;
- // should redraw ...
- invalidate();
- repaint();
-
- checkExit();
- }
-
- }
-
- void goEast()
- {
- resetResolution();
- if ((map.getWalls(sX, sY) & Brick.RIGHT) == 0)
- {
- sX = sX + 1;
- // should redraw ...
- invalidate();
- repaint();
-
- checkExit();
- }
- }
-
- void goWest()
- {
- resetResolution();
- if ((map.getWalls(sX, sY) & Brick.LEFT) == 0)
- {
- sX = sX - 1;
- // should redraw ...
- invalidate();
- repaint();
-
- checkExit();
- }
-
- }
-
- /**
- width, height of one cell,
- offsetX, offsetY of upper left corner
- **/
- // public MazeComponent(WallsProvider map, MazeCellParameters cp)
- public MazeComponent(LabyModel map, MazeCellParameters cp)
- {
- super();
- this.cp = cp;
- this.map = map;
- setPreferredSize(cp.getDimension());
- gX = map.getWidth() - 1;
- gY = map.getHeight() - 1;
- }
-
- // public void resetWallsProvider(WallsProvider map)
- public void resetWallsProvider(LabyModel map)
- {
- this.map = map;
- solvedPath=null;
- // could be kept
- drawingPath=null;
- sX=0;
- sY=0;
- cp.resetMazeWidthHeight(map.getWidth(),map.getHeight());
- setPreferredSize(cp.getDimension());
- }
-
- public void setWallSize(int size)
- {
- cp.setCellSize((double) size,(double) size);
- // should redraw ...
- invalidate();
- repaint();
- }
-
- public int getAutoSize()
- {
- Rectangle r = getBounds();
- cp.adaptTo((int) r.getWidth(),(int) r.getHeight());
- // should redraw ...
- invalidate();
- repaint();
- return 50;
- }
-
- public void changed(Position cl, Position cr, WallsProvider map)
- {
- // should redraw ...
- invalidate();
- repaint();
- Object waiter = new Object();
- synchronized (waiter)
- {
- try
- {
- waiter.wait(10);
- }
- catch (InterruptedException e)
- {
- System.err.println("Interrupted !");
- }
- }
- }
-
- @Override
- protected void paintComponent(Graphics g)
- {
- super.paintComponent(g);
- int x = 0;
- int y = 0;
- short walls = 0;
- short path = 0;
-
- // try to display only visible part...
- // should compute pX, pY, mX, mY based on clip...
- // Shape s=g.getClip();
- Rectangle r = g.getClipBounds();
-
- int mX = (int) ((double) r.getWidth() / cp.getWidth());
- int mY = (int) ((double) r.getHeight() / cp.getHeight());
- int pX = (int) ((double) (r.getX() - cp.getOffsetX()) / cp.getWidth());
- int pY = (int) ((double) (r.getY() - cp.getOffsetY()) / cp.getHeight());
-
- if (pX < 0)
- pX = 0;
- if (pY < 0)
- pY = 0;
- if (pX >= map.getWidth())
- return;
- if (pY >= map.getHeight())
- return;
-
- mX = mX + pX;
- mY = mY + pY;
-
- if (mX > map.getWidth())
- {
- mX = map.getWidth();
- }
- if (mY > map.getHeight())
- {
- mY = map.getHeight();
- }
-
- if ((sX == gX) && (sY == gY))
- {
- g.setColor(Color.red);
- }
- else
- {
- g.setColor(Color.green);
- cp.drawDot(g, new Position(gX, gY), pX, pY, mX, mY);
- g.setColor(Color.blue);
- }
- cp.drawDot(g, new Position(sX, sY), pX, pY, mX, mY);
-
- synchronized (lockChange)
- {
- g.setColor(Color.red);
- if (current != null)
- {
- cp.drawDot(g, current, pX, pY, mX, mY);
- }
- if (solvedPath != null)
- {
- for (DirectionPosition resolved : solvedPath)
- {
- // cp.drawDot(g, resolved.getPosition(), pX, pY, mX, mY);
- cp.drawPath(g,resolved, pX, pY, mX, mY);
- }
- }
- }
-
- int aX = pX;
- int aY = pY;
-
- g.setColor(Color.black);
-
- // draw all walls within clip bounds horiz first then lines
- for (; pY < mY; pY++)
- {
- for (pX = 0; pX < mX; pX++)
- {
- walls = map.getWalls(pX, pY);
- cp.drawWalls(g, pX, pY, walls);
- }
- }
-
- if (this.showAll)
- {
- System.out.println("*");
- pX = aX;
- pY = aY;
-
- // draw all path within clip bounds horiz first then lines
- for (; pY < mY; pY++)
- {
- for (pX = 0; pX < mX; pX++)
- {
- path = map.getPath(pX,pY);
- if ( ( path & LabyModel.SOLVED ) == LabyModel.SOLVED )
- {
- g.setColor(Color.green);
- }
- else
- {
- g.setColor(Color.blue);
- }
- if ( path != 0 )
- {
- DirectionPosition dp = new DirectionPosition(path,new Position(pX,pY));
- cp.drawPath(g,dp,pX,pY,pX+1,pY+1);
- }
- }
- }
- }
- }
-
-
- public boolean notifySearch(DirectionPosition pPosition)
- {
- synchronized (lockChange)
- {
- current = pPosition.getPosition();
- }
- // should redraw ...
- invalidate();
- repaint();
- return true;
-
- }
-
- public void notifySearchError(String error)
- {
- System.err.println(error);
- }
-
- public void notifyCompletion(LinkedList solvedPath)
- {
- LinkedList newPath = new LinkedList<>(solvedPath);
- System.out.println("resolution completed");
- synchronized (lockChange)
- {
- this.solvedPath = newPath;
- }
- // should redraw ...
- invalidate();
- repaint();
- }
-
- public void resetResolution()
- {
- solvedPath = null;
- }
- }
-
- private static void setupDisplay(LabyModel model, int W, int H, MazeParams params)
- {
- Display display = new Display(model, W,H,params);
- }
-
- public static void save(MazeParamsFixed params,LabyModel model)
- {
- File outfile = new File(params.getSaveDir(), params.getName() + ".raw");
- if (!outfile.exists())
- {
- System.out.println("Saving to " + outfile + " ...");
- try
- {
- FileOutputStream out = new FileOutputStream(outfile);
- model.streamOut("raw", out);
- out.flush();
- out.close();
- System.out.println("... Done.");
- }
- catch (IOException io)
- {
- io.printStackTrace(System.err);
- }
- }
- else
- {
- System.out.println("" + outfile + " already exists");
- }
- outfile = new File(params.getSaveDir(), params.getName() + ".stl");
- if (!outfile.exists())
- {
- System.out.println("Saving to " + outfile + " ...");
- try
- {
- FileOutputStream out = new FileOutputStream(outfile);
- Wall3d.streamWallsOut(params.getName(), model, out);
- out.flush();
- out.close();
- System.out.println("... Done.");
- }
- catch (IOException io)
- {
- io.printStackTrace(System.err);
- }
- }
- else
- {
- System.out.println("" + outfile + " already exists");
- }
-
- }
-
- public static void main(String pArgs[])
- {
- LabyModel model = null;
- int W = 600;
- int H = 400;
-
- System.out.println("Default Locale " + Locale.getDefault());
-
- if ( (pArgs.length > 0) && (pArgs[0].length() > 0))
- {
- try
- {
- model = new LabyModel("raw", new FileInputStream(pArgs[0]));
- }
- catch (IOException io)
- {
- io.printStackTrace(System.err);
- System.exit(1);
- }
-
- setupDisplay(model, W,H,null);
- }
- else
- {
- MazeParamsFixed params = new MazeParamsFixed(new File("lab"),20,20,12);
- model = new LabyModel(params, new java.util.Random());
-
- setupDisplay(model,W,H,params);
-
- /*
- model.generateWithEntry(0, 0);
-
- model.addEntryOrExit(-1, 0);
- model.addEntryOrExit(params.getWidth(), params.getHeight() - 1);
-
- System.out.println("Generation completed");
- */
- /*
- */
- }
-
- }
-}
diff --git a/java/org/artisanlogiciel/games/LabyModel.java b/java/org/artisanlogiciel/games/LabyModel.java
index 9e2da37..56e22b9 100644
--- a/java/org/artisanlogiciel/games/LabyModel.java
+++ b/java/org/artisanlogiciel/games/LabyModel.java
@@ -1,16 +1,10 @@
package org.artisanlogiciel.games;
+import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
-import java.util.Collections;
import java.util.Random;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.DataOutputStream;
-import java.io.DataInputStream;
-
/**
* Model of labyrinth storing only paths not walls. wall are regenerated later
* on based on adjacent paths. each position (x,y) stores what move can be done
@@ -18,8 +12,7 @@ import java.io.DataInputStream;
* openList if all moves from its position have not been resolved a node is
* tagged CLOSED when fully processed
**/
-public class LabyModel implements WallsProvider
-{
+public class LabyModel implements WallsProvider {
/**
* WARNING don't change those values, they are used as it is for
@@ -27,42 +20,42 @@ public class LabyModel implements WallsProvider
*/
private final static short FLAGLENGTH = 7;
private final static short CLEAR = 0; // mandatory 0 since array creation is
- // initialized with 0.
+ // initialized with 0.
public final static short HORIZONTAL = 1;
public final static short VERTICAL = 2;
public final static short DIRECTION = 4; // could we get rid of that to
- // free one bit for other purpose
- // ?
+ // free one bit for other purpose
+ // ?
+ // can be both POSITIVE and NEGATIVE, it means that you can move in positive direction and in negative direction.
public final static short POSITIVE = 8;
public final static short NEGATIVE = 16;
-
+
+ // can it be both OPEN and CLOSED ?
private final static short OPEN = 32; // can be reused once generation is
- // completed
+ // completed
private final static short CLOSED = 64; // can be reused once generation is
- // completed
+ // completed
public final static short LEFT = Brick.LEFT << FLAGLENGTH | DIRECTION | HORIZONTAL | NEGATIVE;
public final static short DOWN = Brick.DOWN << FLAGLENGTH | DIRECTION | VERTICAL | POSITIVE;
public final static short RIGHT = Brick.RIGHT << FLAGLENGTH | DIRECTION | HORIZONTAL | POSITIVE;
public final static short UP = Brick.UP << FLAGLENGTH | DIRECTION | VERTICAL | NEGATIVE;
- public final static short ENTRY = Brick.ENTRY << FLAGLENGTH; // flag when a
- // wall should
- // be open to
- // access
- // this.
- private final static short GOAL = Brick.GOAL << FLAGLENGTH; // flag when a
- // wall should
- // be open to
- // access this.
- public final static short SOLVED = 64 << FLAGLENGTH; // flag when solution
- // is on this path.
- private final static short FREE = 128 << FLAGLENGTH; // free flag
+
+ // flag when a wall should be open to access this for entry
+ public final static short ENTRY = Brick.ENTRY << FLAGLENGTH;
+ // flag when a wall should be open to access this for exit
+ private final static short GOAL = Brick.GOAL << FLAGLENGTH;
+ // flag when solution is on this path.
+ public final static short SOLVED = 64 << FLAGLENGTH;
+ // free flag
+ private final static short FREE = 128 << FLAGLENGTH;
// remains 2 free bits ( keep one out for sign )
- private static final short[] AllDirections = { LEFT, DOWN, RIGHT, UP };
+ // orders matters see getReverseDirection
+ private static final short[] AllDirections = {LEFT, DOWN, RIGHT, UP};
private int width;
private int height;
- // wall flags + status flags for each position (x,y)
+ // wall flags Brick.(LEFT,DOWN,RIGHT,UP,ENTRY,GOAL) + status flags for each position (x,y)
private short[][] t;
private int depth = 0;
/**
@@ -71,45 +64,27 @@ public class LabyModel implements WallsProvider
* that to shorter maxdepth is the harder the labyrinth is ...
**/
private int maxdepth = 0;
- private int deepest = 0; // longest path found
+ // longest path found
+ private int deepest = 0;
+ // each move is a linearwork step
private int linearwork = 0;
+
private Position deepestEnd = null;
boolean maxreached = false;
java.util.Random random;
+ // list of positions not fully walked
private final LinkedList openList = new LinkedList();
// list of entries and exits.
private final LinkedList entryExits = new LinkedList();
private final Object coherentLock = new Object(); // before getting the lock
- // and after lock release
- // all is coherent ( ie
- // check() is ok ),
+ // and after lock release
+ // all is coherent ( ie
+ // check() is ok ),
MazeCreationListener listener = null;
- /**
-TODO
- private static MyLinkedList
- {
- MyLinkedList
next;
- P content
-
- MyLinkedList
( P object)
- {
- content=object;
- next=null;
- }
-
- MyLinkedList
addLast(P object)
- {
- next = new MyLinkedList(object);
- return next;
- }
- }
- */
-
- public LabyModel(int width, int height, int maxdepth, Random random)
- {
+ private LabyModel(int width, int height, int maxdepth, Random random) {
this.width = width;
this.height = height;
this.maxdepth = maxdepth;
@@ -118,218 +93,183 @@ TODO
t = new short[width][height];
}
- public LabyModel(MazeParams params, Random random)
- {
- this.width = params.getWidth();
- this.height = params.getHeight();
- this.maxdepth = params.getMaxDepth();
- this.random = random;
- // CLEAR == 0 and array is initialized with 0s
- t = new short[width][height];
+ public LabyModel(MazeParams params) {
+ this(params.getWidth(), params.getHeight(), params.getMaxDepth(), new java.util.Random(params.getSeed()));
}
- public LabyModel(String pFormat, InputStream pIn) throws IOException
- {
+ /**
+ * construct LabyModel from an InputStream, yet only "raw" is supported
+ **/
+ public LabyModel(String pFormat, InputStream pIn) throws IOException {
parseInputStream(pFormat, pIn);
}
- public void setMazeListener(MazeCreationListener listener)
- {
+ public void setMazeListener(MazeCreationListener listener) {
this.listener = listener;
}
// FIXME FULLY BREAK RESOLVING...
- public void noWalls(int x, int y)
- {
- if ((x >= 0) && (x < width) && (y >= 0) && (y < height))
- {
- // t[x][y] |= DIRECTION | VERTICAL | POSITIVE | HORIZONTAL | NEGATIVE | LEFT | RIGHT | UP | DOWN;
- t[x][y] |= DIRECTION | VERTICAL | POSITIVE | HORIZONTAL | NEGATIVE;
- t[x][y] |= LEFT | RIGHT | UP | DOWN;
- }
+ public void noWalls(int x, int y) {
+ if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
+ // t[x][y] |= DIRECTION | VERTICAL | POSITIVE | HORIZONTAL | NEGATIVE | LEFT | RIGHT | UP | DOWN;
+ t[x][y] |= LEFT | RIGHT | UP | DOWN;
+ }
}
/* set direction existing onee are lost */
// FIXME FULLY BREAK RESOLVING...
- public void setDirection(int x, int y, short path)
- {
- if ((x >= 0) && (x < width) && (y >= 0) && (y < height))
- {
- t[x][y]= (short) (path | OPEN);
- }
+ public void setDirection(int x, int y, short path) {
+ if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
+ t[x][y] = (short) (path | OPEN);
+ }
}
- /** add a new direction, exiting ones are kept */
+ /**
+ * add a new direction, exiting ones are kept
+ */
// FIXME FULLY BREAK RESOLVING...
- public void addDirection(int x, int y, short path)
- {
- if ((x >= 0) && (x < width) && (y >= 0) && (y < height))
- {
- t[x][y]|= (short) (path | OPEN);
- }
+ public void addDirection(int x, int y, short path) {
+ if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
+ t[x][y] |= (short) (path | OPEN);
+ }
}
// entry and exit can be outside the model boundaries a one x or one y out.
- public boolean addEntryOrExit(int x, int y)
- {
+ public boolean addEntryOrExit(int x, int y) {
entryExits.add(new Position(x, y));
- if ((x > 0) && (x < width) && (y > 0) && (y < height))
- {
+ if ((x > 0) && (x < width) && (y > 0) && (y < height)) {
t[x][y] |= ENTRY;
}
return true;
}
- public void debugOut()
- {
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
+ public void debugOut() {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
out4XY(x, y);
}
System.out.print('\n');
}
}
- public void out4XY(int x, int y)
- {
+ public void out4XY(int x, int y) {
int direction = t[x][y];
- if ((direction & OPEN) == OPEN)
- {
+ if ((direction & OPEN) == OPEN) {
System.out.print("?");
- }
- else if ((direction & CLOSED) == CLOSED)
- {
+ } else if ((direction & CLOSED) == CLOSED) {
System.out.print(".");
- }
- else
- {
+ } else {
System.out.print(" ");
}
// don't display information about short.
direction &= ~OPEN;
direction &= ~GOAL;
direction &= ~CLOSED;
- switch (direction)
- {
- case LEFT: // left
- System.out.print("<-");
- break;
- case DOWN: // down
- System.out.print("vv");
- break;
- case RIGHT: // right
- System.out.print("->");
- break;
- case UP: // up
- System.out.print("^^");
- break;
- case HORIZONTAL: // -
- System.out.print("--");
- break;
- case VERTICAL: // |
- System.out.print("||");
- break;
- case CLEAR:
- System.out.print(" ");
- break;
- case CLOSED:
- System.out.print("00");
- break;
- case RIGHT | LEFT:
- System.out.print("--");
- break;
- case UP | DOWN:
- System.out.print("||");
- break;
- case RIGHT | UP:
- System.out.print("^>");
- break;
- case RIGHT | DOWN:
- System.out.print("v>");
- break;
- case LEFT | DOWN:
- System.out.print("");
- break;
- case LEFT | RIGHT | UP | DOWN:
- System.out.print("++");
- break;
- case OPEN:
- System.out.print("??");
- break;
- case GOAL:
- System.out.print("**");
- break;
- default:
- System.out.print("..");
+ switch (direction) {
+ case LEFT: // left
+ System.out.print("<-");
+ break;
+ case DOWN: // down
+ System.out.print("vv");
+ break;
+ case RIGHT: // right
+ System.out.print("->");
+ break;
+ case UP: // up
+ System.out.print("^^");
+ break;
+ case HORIZONTAL: // -
+ System.out.print("--");
+ break;
+ case VERTICAL: // |
+ System.out.print("||");
+ break;
+ case CLEAR:
+ System.out.print(" ");
+ break;
+ case CLOSED:
+ System.out.print("00");
+ break;
+ case RIGHT | LEFT:
+ System.out.print("--");
+ break;
+ case UP | DOWN:
+ System.out.print("||");
+ break;
+ case RIGHT | UP:
+ System.out.print("^>");
+ break;
+ case RIGHT | DOWN:
+ System.out.print("v>");
+ break;
+ case LEFT | DOWN:
+ System.out.print("");
+ break;
+ case LEFT | RIGHT | UP | DOWN:
+ System.out.print("++");
+ break;
+ case OPEN:
+ System.out.print("??");
+ break;
+ case GOAL:
+ System.out.print("**");
+ break;
+ default:
+ System.out.print("..");
}
- if (((t[x][y] & RIGHT) == RIGHT) || ((x + 1 < width) && ((t[x + 1][y] & LEFT) == LEFT)))
- {
+ if (((t[x][y] & RIGHT) == RIGHT) || ((x + 1 < width) && ((t[x + 1][y] & LEFT) == LEFT))) {
System.out.print("-");
- }
- else
- {
+ } else {
System.out.print("H");
}
}
- public String outHorizWall2XY(int x, int y)
- {
+ public String outHorizWall2XY(int x, int y) {
String freeway = " ";
- if ((t[x][y] & SOLVED) == SOLVED)
- {
+ if ((t[x][y] & SOLVED) == SOLVED) {
freeway = "*";
}
- if ((x < 0) || (x > width))
- {
+ if ((x < 0) || (x > width)) {
return " H";
}
- if ((y < 0) || (y >= height))
- {
+ if ((y < 0) || (y >= height)) {
return "HH";
}
- if (((t[x][y] & DOWN) == DOWN) || ((y + 1 < height) && ((t[x][y + 1] & UP) == UP)))
- {
+ if (((t[x][y] & DOWN) == DOWN) || ((y + 1 < height) && ((t[x][y + 1] & UP) == UP))) {
return freeway + "H";
- }
- else
- {
+ } else {
return "HH";
}
}
- public String out2XY(int x, int y)
- {
+ public String out2XY(int x, int y) {
// can check for entry exits.
- if ((y < 0) || (y >= height) || (x < 0) || (x > width))
- {
+ if ((y < 0) || (y >= height) || (x < 0) || (x > width)) {
return " H";
}
String low = "";
int direction = t[x][y];
String freeway = " ";
- if ((t[x][y] & SOLVED) == SOLVED)
- {
+ if ((t[x][y] & SOLVED) == SOLVED) {
freeway = "*";
}
// don't display information about short.
@@ -337,136 +277,115 @@ TODO
direction &= ~GOAL;
direction &= ~CLOSED;
direction &= ~SOLVED;
- switch (direction)
- {
- case LEFT:
- case DOWN:
- case RIGHT:
- case UP:
- low = freeway;
- break;
- case HORIZONTAL: // -
- low = " ";
- break;
- case VERTICAL: // |
- low = " ";
- break;
- case CLEAR:
- low = " ";
- break;
- case CLOSED:
- low = "0";
- break;
- case RIGHT | LEFT:
- case UP | DOWN:
- case RIGHT | UP:
- case RIGHT | DOWN:
- case LEFT | DOWN:
- case LEFT | UP:
- case LEFT | RIGHT | UP:
- case LEFT | RIGHT | DOWN:
- case LEFT | DOWN | UP:
- case RIGHT | DOWN | UP:
- case LEFT | RIGHT | UP | DOWN:
- low = ".";
- break;
- case OPEN:
- low = "?";
- break;
- case GOAL:
- low = "*";
- break;
- default:
- low = ".";
+ switch (direction) {
+ case LEFT:
+ case DOWN:
+ case RIGHT:
+ case UP:
+ low = freeway;
+ break;
+ case HORIZONTAL: // -
+ low = " ";
+ break;
+ case VERTICAL: // |
+ low = " ";
+ break;
+ case CLEAR:
+ low = " ";
+ break;
+ case CLOSED:
+ low = "0";
+ break;
+ case RIGHT | LEFT:
+ case UP | DOWN:
+ case RIGHT | UP:
+ case RIGHT | DOWN:
+ case LEFT | DOWN:
+ case LEFT | UP:
+ case LEFT | RIGHT | UP:
+ case LEFT | RIGHT | DOWN:
+ case LEFT | DOWN | UP:
+ case RIGHT | DOWN | UP:
+ case LEFT | RIGHT | UP | DOWN:
+ low = ".";
+ break;
+ case OPEN:
+ low = "?";
+ break;
+ case GOAL:
+ low = "*";
+ break;
+ default:
+ low = ".";
}
- for (Position exit : entryExits)
- {
- if ((exit.getX() == x + 1) && (exit.getY() == y))
- {
+ for (Position exit : entryExits) {
+ if ((exit.getX() == x + 1) && (exit.getY() == y)) {
low = low + ">";
return low;
}
}
- if (((t[x][y] & RIGHT) == RIGHT) || ((x + 1 < width) && ((t[x + 1][y] & LEFT) == LEFT)))
- {
+ if (((t[x][y] & RIGHT) == RIGHT) || ((x + 1 < width) && ((t[x + 1][y] & LEFT) == LEFT))) {
low = low + freeway;
- }
- else
- {
+ } else {
low = low + "H";
}
return low;
}
- public LabyMap toLabyMap()
- {
- synchronized (coherentLock)
- {
+ public LabyMap toLabyMap() {
+ synchronized (coherentLock) {
Brick[][] brickMap = new Brick[width][height];
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
brickMap[x][y] = new Brick(out2XY(x, y), outHorizWall2XY(x, y), getWalls(x, y));
}
}
- return new LabyMap(brickMap, (LinkedList) entryExits.clone());
+ return new LabyMap(brickMap, new LinkedList(entryExits));
}
}
- public int getWidth()
- {
+ public int getWidth() {
return this.width;
}
- public int getHeight()
- {
+ public int getHeight() {
return this.height;
}
- public LinkedList getOpenList()
- {
+ public LinkedList getOpenList() {
return openList;
}
- public void reset()
- {
+ public void reset() {
depth = 0;
computeOpenList();
- resetResolving();
+ resetResolving();
}
- public void resetResolving()
- {
- // don't keep solved path
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- t[x][y] &= ~(SOLVED);
+ public void resetResolving() {
+ // don't keep solved path
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ t[x][y] &= ~(SOLVED);
}
}
}
- public void fullReset()
- {
+ public void fullReset() {
depth = 0;
openList.clear();
maxreached = false;
deepest = 0;
deepestEnd = null;
// clear open
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- // resetCell(x,y);
- t[x][y] &= ~( OPEN | SOLVED);
-
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ // resetCell(x,y);
+ t[x][y] &= ~(OPEN | SOLVED);
}
}
@@ -475,26 +394,21 @@ TODO
/**
* check model coherency and fix if model needed a fix it means that
* algorithm has a problem
- *
+ *
* @return true if model is ok and no fix was applied.
**/
- public boolean check()
- {
+ public boolean check() {
boolean check = true;
- synchronized (coherentLock)
- {
+ synchronized (coherentLock) {
// node in OPEN should be tagged OPEN and not CLOSED.
- for (Position p : openList)
- {
+ for (Position p : openList) {
int x = p.getX();
int y = p.getY();
- if (isFlagSet(t[x][y],OPEN))
- {
+ if (isFlagSet(t[x][y], OPEN)) {
check = false;
t[x][y] |= OPEN;
}
- if (isFlagSet(t[x][y],CLOSED))
- {
+ if (isFlagSet(t[x][y], CLOSED)) {
check = false;
t[x][y] &= ~CLOSED;
}
@@ -506,47 +420,43 @@ TODO
return check;
}
- public void computeOpenList()
- {
+ // coherency : if CLOSED then not OPEN
+ public void computeOpenList() {
openList.clear();
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- if (isFlagSet(t[x][y],CLOSED))
- {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ if (isFlagSet(t[x][y], CLOSED)) {
t[x][y] &= ~OPEN;
}
- if (isFlagSet(t[x][y],OPEN) || (t[x][y] == CLEAR))
- {
+ if (isFlagSet(t[x][y], OPEN) || (t[x][y] == CLEAR)) {
openList.add(new Position(x, y));
}
}
}
}
- public void generateWithEntry(int x, int y)
- {
+ /**
+ * This is core of generator.
+ *
+ * generate a maze with an entry set at (x,y) with a maxdepth
+ **/
+ public void generateWithEntry(int x, int y) {
openList.add(new Position(x, y));
- while (!openList.isEmpty())
- {
- step(0); // fixme depth not set
+ while (!openList.isEmpty()) {
+ // this is where magic happens
+ step();
- synchronized (coherentLock)
- {
+ synchronized (coherentLock) {
linearwork++;
- if (linearwork % maxdepth == 0)
- {
+ if (linearwork % maxdepth == 0) {
coherentLock.notifyAll();
- if (listener != null)
- {
+ if (listener != null) {
listener.changed(null, null, this);
}
// should not continue in depth first...
- if (!openList.isEmpty())
- {
+ if (!openList.isEmpty()) {
// insert head as next position to pick up.
Position current = openList.removeFirst();
openList.add(current);
@@ -556,43 +466,35 @@ TODO
}
- if (deepestEnd != null)
- {
+ if (deepestEnd != null) {
t[deepestEnd.getX()][deepestEnd.getY()] |= GOAL;
}
}
- public int getDepth()
- {
+ public int getDepth() {
return depth;
}
- public Position getDeepestEnd()
- {
+ public Position getDeepestEnd() {
return deepestEnd;
}
- public int getDeepestPath()
- {
+ public int getDeepestPath() {
return deepest;
}
- public boolean maxReached()
- {
+ public boolean maxReached() {
return maxreached;
}
/**
- * @param p
- * Position
+ * @param p Position
* @return true if newly added , false if already open.
**/
- private boolean open(boolean first, Position p)
- {
+ private boolean open(boolean first, Position p) {
int x = p.getX();
int y = p.getY();
- if ((t[x][y] & OPEN) != OPEN)
- {
+ if ((t[x][y] & OPEN) != OPEN) {
t[x][y] |= OPEN;
openList.addLast(p);
return true;
@@ -600,318 +502,257 @@ TODO
return false;
}
- public final static boolean isFlagSet(short check, short flag)
- {
- return ((check & flag) == flag);
+ public final static boolean isFlagSet(short check, short flag) {
+ return ((check & flag) == flag);
}
- public final short getCell(Position p)
- {
- return t[p.getX()][p.getY()];
+ public final short getCell(Position p) {
+ return t[p.getX()][p.getY()];
}
- public final void updateCell(Position p, short flags)
- {
- t[p.getX()][p.getY()] |= flags;
+ public final void updateCell(Position p, short flags) {
+ t[p.getX()][p.getY()] |= flags;
}
- public final static short getReverseDirection(int index)
- {
- return AllDirections[(index + 2) % 4];
+ public final static short getReverseDirection(int index) {
+ return AllDirections[(index + 2) % 4];
}
- /** return direction to use to be closer to 'to' from 'from' */
- public final static short getDirection(Position from, Position to)
- {
- short pointingdirection = DIRECTION;
- if ( from.equals(to) )
- {
- return pointingdirection;
- }
- if ( from.getX() < to.getX() )
- {
- pointingdirection |= RIGHT;
- }
- else
- if ( from.getX() > to.getX() )
- {
- pointingdirection |= LEFT;
- }
- if ( from.getY() < to.getY() )
- {
- pointingdirection |= DOWN;
- }
- else
- if ( from.getY() > to.getY() )
- {
- pointingdirection |= UP;
- }
- return pointingdirection;
+ /**
+ * return direction to use to be closer to 'to' from 'from'
+ */
+ public final static short getDirection(Position from, Position to) {
+ short pointingdirection = DIRECTION;
+ if (from.equals(to)) {
+ return pointingdirection;
+ }
+ if (from.getX() < to.getX()) {
+ pointingdirection |= RIGHT;
+ } else if (from.getX() > to.getX()) {
+ pointingdirection |= LEFT;
+ }
+ if (from.getY() < to.getY()) {
+ pointingdirection |= DOWN;
+ } else if (from.getY() > to.getY()) {
+ pointingdirection |= UP;
+ }
+ return pointingdirection;
}
-
+
/**
* resolve this labrynth using internal representation
* initial (x,y) is exit, will return list of positions from start (0,0) to end (x,y)
**/
- public LinkedList resolve(int x, int y, MazeResolutionListener rlistener)
- {
- long safeguard = width * height;
+ public LinkedList resolve(int x, int y, MazeResolutionListener rlistener) {
+ long safeguard = width * height;
int newx = 0;
int newy = 0;
- resetResolving();
+ resetResolving();
- // list of alternate paths
+ // list of alternate paths
LinkedList> altpath = new LinkedList<>();
- // list of positions from start to end
+ // list of positions from start to end
LinkedList backpath = new LinkedList();
- // position that point to (x,y).
- DirectionPosition found = new DirectionPosition((short) 0,new Position(x, y));
- // entry
- Position entry = new Position(0, 0);
+ // position that point to (x,y).
+ DirectionPosition found = new DirectionPosition((short) 0, new Position(x, y));
+ // entry
+ Position entry = new Position(0, 0);
- while (! found.getPosition().equals(entry) )
- {
- Position last = found.getPosition();
+ while (!found.getPosition().equals(entry)) {
+ Position last = found.getPosition();
backpath.addFirst(found);
- found = null;
+ found = null;
// should find from all adjacent cells (directions) one that point to this.
- {
- // didx is index of four cell adjacent to this (x,y)
- for (int didx = 0; didx < 4; didx++)
- {
- int delta = 0;
- short direction = AllDirections[didx];
- short reversedirection = getReverseDirection(didx);
- short pointingdirection = DIRECTION;
+ {
+ // didx is index of four cell adjacent to this (x,y)
+ for (int didx = 0; didx < 4; didx++) {
+ int delta = 0;
+ short direction = AllDirections[didx];
+ short reversedirection = getReverseDirection(didx);
+ short pointingdirection = DIRECTION;
- if (isFlagSet(direction,POSITIVE))
- {
- delta = 1;
- pointingdirection |= NEGATIVE;
- }
- else
- {
- delta = -1;
- pointingdirection |= POSITIVE;
- }
+ if (isFlagSet(direction, POSITIVE)) {
+ delta = 1;
+ pointingdirection |= NEGATIVE;
+ } else {
+ delta = -1;
+ pointingdirection |= POSITIVE;
+ }
- if (isFlagSet(direction,HORIZONTAL))
- {
- newx = last.getX() + delta;
- newy = last.getY();
- pointingdirection |= HORIZONTAL;
- }
- else
- {
- newy = last.getY() + delta;
- newx = last.getX();
- pointingdirection |= VERTICAL;
- }
+ if (isFlagSet(direction, HORIZONTAL)) {
+ newx = last.getX() + delta;
+ newy = last.getY();
+ pointingdirection |= HORIZONTAL;
+ } else {
+ newy = last.getY() + delta;
+ newx = last.getX();
+ pointingdirection |= VERTICAL;
+ }
- // internal GUARD.
- if (! isFlagSet(reversedirection,pointingdirection))
- {
- System.out.println("Internal ERROR. Please check AllDirections order "
- + (reversedirection & pointingdirection) + " " + pointingdirection);
- return backpath;
- }
+ // internal GUARD.
+ if (!isFlagSet(reversedirection, pointingdirection)) {
+ System.out.println("[FATAL] Internal ERROR. Please check AllDirections order "
+ + (reversedirection & pointingdirection) + " " + pointingdirection);
+ return backpath;
+ }
- Position p = new Position(newx,newy);
- if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height))
- {
- if (isFlagSet(getCell(p),reversedirection))
- {
- if (found != null)
- {
- // there is already a potential solution in adjacent cell of last.
- System.out.println("alternate " + p + " from " + last + "/" + safeguard);
- // could be a unique parent of two paths...
- // but search from other entry/exits than generated
- // from
- // ie entry(0,0) exit(width-1,height-1) not yet
- // implemented.
- {
- if (! isFlagSet(getCell(p), SOLVED ))
- {
- LinkedList cp = (LinkedList) backpath.clone();
- DirectionPosition altfound = new DirectionPosition(reversedirection,p);
- cp.addFirst(altfound);
- altpath.addLast(cp);
- rlistener.notifySearchError("record alternate path " + p.toString());
- }
- else
- {
- // this was already solved, might be a loop.
- if (rlistener != null)
- {
- rlistener.notifySearchError("Loop " + last.toString() + " has two parents " + found.toString() + " "
- + p.toString());
- }
- // continue;
- }
- }
- }
- else
- {
- if (! isFlagSet(getCell(p), SOLVED ))
- {
- // this is first potential solution in adjacent cell of last.
- System.out.println("check " + p + " from " + last + "/" + safeguard);
-
- found = new DirectionPosition(reversedirection,p);
- if (rlistener != null)
- {
- rlistener.notifySearch(found);
- }
- }
- else
- {
- // was already solved.
- System.out.println("already solved " + p + " from " + last + "/" + safeguard);
- }
- }
- // support multiple pathes
- }
- else
- {
- System.out.println("not reachable " + p + " from " + last + "/" + safeguard);
- }
- }
- else
- {
- System.out.println("p outofbounds " + p + "/" + safeguard);
- }
- }
- if (found == null)
- {
- if ( ! altpath.isEmpty() )
- {
- // new possible backpath
- backpath = altpath.removeFirst();
- found = backpath.removeFirst();
- if (rlistener != null)
- {
- rlistener.notifySearchError("try alternate path " + found.toString());
- rlistener.notifySearch(found);
- }
- }
- }
- }
- if (found == null)
- {
- if ( ! altpath.isEmpty() )
- {
- rlistener.notifySearchError("No path found BUT ALTPATH !" );
- }
- rlistener.notifySearchError("No path found !");
- break;
- }
+ Position p = new Position(newx, newy);
+ if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height)) {
+ if (isFlagSet(getCell(p), reversedirection)) {
+ if (found != null) {
+ // there is already a potential solution in adjacent cell of last.
+ System.out.println("alternate " + p + " from " + last + "/" + safeguard);
+ // could be a unique parent of two paths...
+ // but search from other entry/exits than generated
+ // from
+ // ie entry(0,0) exit(width-1,height-1) not yet
+ // implemented.
+ {
+ if (!isFlagSet(getCell(p), SOLVED)) {
+ LinkedList cp = new LinkedList(backpath);
+ DirectionPosition altfound = new DirectionPosition(reversedirection, p);
+ cp.addFirst(altfound);
+ altpath.addLast(cp);
+ rlistener.notifySearchError("record alternate path " + p.toString());
+ } else {
+ // this was already solved, might be a loop.
+ if (rlistener != null) {
+ rlistener.notifySearchError("Loop " + last.toString() + " has two parents " + found.toString() + " "
+ + p.toString());
+ }
+ // continue;
+ }
+ }
+ } else {
+ if (!isFlagSet(getCell(p), SOLVED)) {
+ // this is first potential solution in adjacent cell of last.
+ System.out.println("check " + p + " from " + last + "/" + safeguard);
+
+ found = new DirectionPosition(reversedirection, p);
+ if (rlistener != null) {
+ rlistener.notifySearch(found);
+ }
+ } else {
+ // was already solved.
+ System.out.println("already solved " + p + " from " + last + "/" + safeguard);
+ }
+ }
+ // support multiple pathes
+ } else {
+ System.out.println("not reachable " + p + " from " + last + "/" + safeguard);
+ }
+ } else {
+ System.out.println("p outofbounds " + p + "/" + safeguard);
+ }
+ }
+ if (found == null) {
+ if (!altpath.isEmpty()) {
+ // new possible backpath
+ backpath = altpath.removeFirst();
+ found = backpath.removeFirst();
+ if (rlistener != null) {
+ rlistener.notifySearchError("try alternate path " + found.toString());
+ rlistener.notifySearch(found);
+ }
+ }
+ }
+ }
+ if (found == null) {
+ if (!altpath.isEmpty()) {
+ rlistener.notifySearchError("No path found BUT ALTPATH !");
+ }
+ rlistener.notifySearchError("No path found !");
+ break;
+ }
// System.out.println(found);
- if (isFlagSet(getCell(found.getPosition()), SOLVED ))
- {
- System.out.println("[INFO] position already solved" + found.toString() + " *length:" + backpath.size());
- }
- else
- {
- updateCell(found.getPosition(),SOLVED);
- }
+ if (isFlagSet(getCell(found.getPosition()), SOLVED)) {
+ System.out.println("[INFO] position already solved" + found.toString() + " *length:" + backpath.size());
+ } else {
+ updateCell(found.getPosition(), SOLVED);
+ }
-
- safeguard --;
- if ( safeguard < 0 )
- {
- rlistener.notifySearchError("Path too long ( or long overflow ) for width*height:" + (width*height) + " length:" + backpath.size());
- break;
- }
+
+ safeguard--;
+ if (safeguard < 0) {
+ rlistener.notifySearchError("Path too long ( or long overflow ) for width*height:" + (width * height) + " length:" + backpath.size());
+ break;
+ }
}
- if (rlistener != null)
- {
+ if (rlistener != null) {
rlistener.notifyCompletion(backpath);
}
return backpath;
}
+ private final void closePosition(int x, int y) {
+ t[x][y] &= ~OPEN;
+ t[x][y] |= CLOSED;
+ }
+
/**
- * @returns wheter process closed current node.
+ * One step in Maze generation process
+ * get last element in open list and explore one random direction with it.
+ *
+ * @returns whether process closed current node.
**/
- public boolean step(int depth)
- {
+ public boolean step() {
boolean complete = false;
Position current = null;
- synchronized (coherentLock)
- {
+ synchronized (coherentLock) {
- if (!openList.isEmpty())
- {
+ if (!openList.isEmpty()) {
// last : in depth before.
current = openList.getLast();
- }
- else
- {
+ } else {
return true;
}
- if (current != null)
- {
+ if (current != null) {
int x = current.getX();
int y = current.getY();
// should find all free positions...
ArrayList freeDirection = new ArrayList();
- for (short direction : AllDirections)
- {
+ for (short direction : AllDirections) {
int delta = 0;
int newx = -1;
int newy = -1;
- if ((direction & POSITIVE) == POSITIVE)
- {
+ if ((direction & POSITIVE) == POSITIVE) {
delta = 1;
- }
- else
- {
+ } else {
delta = -1;
}
- if ((direction & HORIZONTAL) == HORIZONTAL)
- {
+ if ((direction & HORIZONTAL) == HORIZONTAL) {
newx = x + delta;
newy = y;
- }
- else
- {
+ } else {
newy = y + delta;
newx = x;
}
- if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height))
- {
- if ((t[newx][newy]) == CLEAR)
- {
- freeDirection.add(new Short(direction));
+ if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height)) {
+ if ((t[newx][newy]) == CLEAR) {
+ freeDirection.add(Short.valueOf(direction));
}
}
}
- if (!freeDirection.isEmpty())
- {
+ if (!freeDirection.isEmpty()) {
// control random using our own pseudorandom
short direction = 0;
- if (freeDirection.size() > 1)
- {
+ if (freeDirection.size() > 1) {
direction = freeDirection.get(random.nextInt(freeDirection.size()));
- }
- else
- {
+ } else {
direction = freeDirection.get(0);
Position last = openList.removeLast();
- if (last != current)
- {
+ if (last != current) {
// GUARD, should not happen ( or multi-thread access
// to model error )
System.err.println("INTERNAL ERROR 3");
@@ -923,38 +764,28 @@ TODO
int newx = -1;
int newy = -1;
- if ((direction & POSITIVE) == POSITIVE)
- {
+ if ((direction & POSITIVE) == POSITIVE) {
delta = 1;
- }
- else
- {
+ } else {
delta = -1;
}
- if ((direction & HORIZONTAL) == HORIZONTAL)
- {
+ if ((direction & HORIZONTAL) == HORIZONTAL) {
newx = x + delta;
newy = y;
- }
- else
- {
+ } else {
newy = y + delta;
newx = x;
}
Position target = new Position(newx, newy, current.getDepth() + 1);
open(false, target);
- if ((t[x][y] & DIRECTION) == DIRECTION)
- {
+ if ((t[x][y] & DIRECTION) == DIRECTION) {
t[x][y] |= direction;
- }
- else
- {
+ } else {
t[x][y] = direction;
} // not a 'direction' ... is it necessary to check ?
- if (freeDirection.size() > 1)
- {
+ if (freeDirection.size() > 1) {
// keep it open at the very same place, previous open
// did add another node to inspect.
return false;
@@ -964,24 +795,21 @@ TODO
// last )
// can proceed to close
- }
- else
- {
+ } else {
// no free direction remaining => closing
Position last = openList.removeLast();
- if (last != current)
- {
+ if (last != current) {
// GUARD, should not happen.
System.err.println("INTERNAL ERROR 3");
return false;
}
}
complete = true;
- t[x][y] &= ~OPEN;
- t[x][y] |= CLOSED;
- if (current.getDepth() > deepest)
- {
- deepest = depth;
+ closePosition(x, y);
+
+ final int currentdepth = current.getDepth();
+ if (currentdepth > deepest) {
+ deepest = currentdepth;
deepestEnd = current;
}
} // current != null;
@@ -989,34 +817,28 @@ TODO
return complete;
}
- public short getWalls(int x, int y)
- {
+ public short getWalls(int x, int y) {
short walls = 0;
- for (short direction : AllDirections)
- {
- if (hasWallInDirection(x, y, direction))
- {
+ for (short direction : AllDirections) {
+ if (hasWallInDirection(x, y, direction)) {
walls |= (direction >> FLAGLENGTH);
}
}
return walls;
}
- public short getPath(int x, int y)
- {
+ public short getPath(int x, int y) {
short path = 0;
- if (( x < width ) && ( y < height ))
- {
- path = t[x][y];
- }
- return path;
+ if ((x < width) && (y < height)) {
+ path = t[x][y];
+ }
+ return path;
}
/**
* is there a wall in that direction ?
**/
- public boolean hasWallInDirection(int x, int y, short direction)
- {
+ public boolean hasWallInDirection(int x, int y, short direction) {
int newx = 0;
int newy = 0;
int delta = 0;
@@ -1024,106 +846,87 @@ TODO
int reversedirection = 0;
// is this direction on the path ? yes => no wall
- if ((t[x][y] & direction) == direction)
- {
+ if ((t[x][y] & direction) == direction) {
return false;
}
// is adjacent tile in direction pointing in reverse direction ? yes =>
// no wall
- if ((direction & POSITIVE) == POSITIVE)
- {
+ if ((direction & POSITIVE) == POSITIVE) {
delta = 1;
- }
- else
- {
+ } else {
delta = -1;
}
- if ((direction & HORIZONTAL) == HORIZONTAL)
- {
+ if ((direction & HORIZONTAL) == HORIZONTAL) {
newx = x + delta;
newy = y;
reversedirection = (direction == RIGHT) ? LEFT : RIGHT;
- }
- else
- {
+ } else {
newy = y + delta;
newx = x;
reversedirection = (direction == UP) ? DOWN : UP;
}
- if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height))
- {
- return !isFlagSet(t[newx][newy],(short)reversedirection);
- }
- else
- {
+ if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height)) {
+ return !isFlagSet(t[newx][newy], (short) reversedirection);
+ } else {
// outside boundaries.
// TODO CHECK exits.
return true;
}
}
- public void streamOut(String pFormat, OutputStream pOut) throws IOException
- {
- if ((pFormat == null) || (pFormat.equals("raw")))
- {
+ public void streamOut(String pFormat, OutputStream pOut) throws IOException {
+ if ((pFormat == null) || (pFormat.equals("raw"))) {
// first raw format, not smart.
DataOutputStream dataOut = new DataOutputStream(pOut);
// should dump this to stream.
- dataOut.write(new byte[] { (byte) 'L', (byte) 'A', (byte) 'B', (byte) '0' });
+ dataOut.write(new byte[]{(byte) 'L', (byte) 'A', (byte) 'B', (byte) '0'});
dataOut.writeInt(getWidth());
dataOut.writeInt(getHeight());
dataOut.flush();
- for (int y = 0; y < getHeight(); y++)
- {
- for (int x = 0; x < getWidth(); x++)
- {
+ for (int y = 0; y < getHeight(); y++) {
+ for (int x = 0; x < getWidth(); x++) {
dataOut.writeShort(t[x][y]);
}
}
dataOut.flush();
- }
- else
- {
+ } else {
throw new IOException("Format " + pFormat + " Not yet implemented.");
}
}
- private void streamIn(String pFormat, InputStream pIn) throws IOException
- {
+ private void streamIn(String pFormat, InputStream pIn) throws IOException {
throw new IOException("Use correct constructor.");
}
- private void parseInputStream(String pFormat, InputStream pIn) throws IOException
- {
- if ((pFormat == null) || (pFormat.equals("raw")))
- {
+ private void parseInputStream(String pFormat, InputStream pIn) throws IOException {
+ if ((pFormat == null) || (pFormat.equals("raw"))) {
+ // maxdepth is unset then unmodified
byte[] header = new byte[4];
DataInputStream in = new DataInputStream(pIn);
in.read(header);
int rwidth = in.readInt();
int rheight = in.readInt();
- width = rwidth;
- height = rheight;
- maxdepth = maxdepth;
- random = null;
- // SHOULD CHECK max width and max height...
- // CLEAR == 0 and array is initialized with 0s
- t = new short[width][height];
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- t[x][y] = in.readShort();
+ if ((rwidth > 0) && (rheight > 0)) {
+ width = rwidth;
+ height = rheight;
+ random = null;
+ // SHOULD CHECK max width and max height...
+ // CLEAR == 0 and array is initialized with 0s
+ t = new short[width][height];
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ t[x][y] = in.readShort();
+ }
}
+ } else {
+ throw new IOException("Invalid header for width and height");
}
// should be at end of stream ? Not necessary can stream multiple
// labs ( or tiling ).
- }
- else
- {
+ } else {
throw new IOException("Format " + pFormat + " Not yet implemented.");
}
diff --git a/java/org/artisanlogiciel/games/Main.java b/java/org/artisanlogiciel/games/Main.java
index 0aa7afd..4b19244 100644
--- a/java/org/artisanlogiciel/games/Main.java
+++ b/java/org/artisanlogiciel/games/Main.java
@@ -14,25 +14,14 @@ public class Main
return editor;
}
- public WallsProvider generate(int width, int height, int maxdepth, MazeResolutionListener listener)
+ public LabyMap generate2(MazeParamEditor params)
{
- LabyModel model = new LabyModel(width, height, maxdepth, new java.util.Random());
+ params.setSeed(1024L);
+ LabyModel model = new LabyModel(params);
model.generateWithEntry(0, 0);
- LinkedList exits = new LinkedList();
- model.addEntryOrExit(-1, 0);
- model.addEntryOrExit(width, height - 1);
- if (!model.check())
- {
- System.out.println("Check failed");
- }
- model.resolve(width - 1, height - 1, listener);
- return model;
- }
- public LabyMap generate2(int width, int height, int maxdepth)
- {
- LabyModel model = new LabyModel(width, height, maxdepth, new java.util.Random(1024L));
- model.generateWithEntry(0, 0);
+ final int width = params.getWidth();
+ final int height = params.getHeight();
LinkedList exits = new LinkedList();
model.addEntryOrExit(-1, 0);
model.addEntryOrExit(width, height - 1);
@@ -51,7 +40,7 @@ public class Main
{
Main m = new Main();
MazeParamEditor editor = m.editor();
- LabyMap map = m.generate2(editor.width, editor.height, editor.maxdepth);
+ LabyMap map = m.generate2(editor);
System.out.println(map.toShortString());
System.out.println(map.toString());
System.out.println(Brick.getDirLine());
diff --git a/java/org/artisanlogiciel/games/MazeCreationListener.java b/java/org/artisanlogiciel/games/MazeCreationListener.java
index d425a70..633ecac 100644
--- a/java/org/artisanlogiciel/games/MazeCreationListener.java
+++ b/java/org/artisanlogiciel/games/MazeCreationListener.java
@@ -3,7 +3,7 @@ package org.artisanlogiciel.games;
/**
* MazeCreationListener
**/
-interface MazeCreationListener
+public interface MazeCreationListener
{
void changed(Position cornerleft, Position cornerright, WallsProvider provider);
}
diff --git a/java/org/artisanlogiciel/games/MazeParamEditor.java b/java/org/artisanlogiciel/games/MazeParamEditor.java
index 664e1b2..003723b 100644
--- a/java/org/artisanlogiciel/games/MazeParamEditor.java
+++ b/java/org/artisanlogiciel/games/MazeParamEditor.java
@@ -8,6 +8,7 @@ import java.util.Scanner;
**/
class MazeParamEditor implements MazeParams
{
+ long seed;
int width;
int height;
int maxdepth;
@@ -27,6 +28,11 @@ class MazeParamEditor implements MazeParams
maxdepth = console.nextInt();
}
+ public long getSeed()
+ {
+ return seed;
+ }
+
public int getWidth()
{
return width;
@@ -51,6 +57,11 @@ class MazeParamEditor implements MazeParams
return name;
}
+ public void setSeed(long seed)
+ {
+ this.seed = seed;
+ }
+
public File getSaveDir()
{
return labdir;
diff --git a/java/org/artisanlogiciel/games/MazeParams.java b/java/org/artisanlogiciel/games/MazeParams.java
index 77f5753..e2020a8 100644
--- a/java/org/artisanlogiciel/games/MazeParams.java
+++ b/java/org/artisanlogiciel/games/MazeParams.java
@@ -7,6 +7,9 @@ import java.io.File;
**/
public interface MazeParams
{
+ /** currently seed of java.util.random **/
+ public long getSeed();
+
public int getWidth();
public int getHeight();
diff --git a/java/org/artisanlogiciel/games/MazeParamsFixed.java b/java/org/artisanlogiciel/games/MazeParamsFixed.java
new file mode 100644
index 0000000..6f9e505
--- /dev/null
+++ b/java/org/artisanlogiciel/games/MazeParamsFixed.java
@@ -0,0 +1,76 @@
+package org.artisanlogiciel.games;
+
+import java.io.File;
+
+public class MazeParamsFixed implements MazeParams
+{
+ long seed;
+ int width;
+ int height;
+ int maxdepth;
+ File labdir;
+ String name;
+
+ public MazeParamsFixed()
+ {
+ }
+
+ public MazeParamsFixed(MazeParams params)
+ {
+ setParams(params.getSaveDir(),params.getWidth(),params.getHeight(),params.getMaxDepth());
+ }
+
+ public void setParams(File saveDir, int W, int H, int MD)
+ {
+ labdir = saveDir;
+ width=W;
+ height=H;
+ maxdepth=MD;
+ }
+
+ public MazeParamsFixed(File saveDir, int W, int H, int MD, long seed)
+ {
+ name = null;
+ setParams(saveDir,W,H,MD);
+ this.seed=seed;
+ }
+
+ public long getSeed()
+ {
+ return seed;
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+
+ public int getHeight()
+ {
+ return height;
+ }
+
+ public int getMaxDepth()
+ {
+ return maxdepth;
+ }
+
+ public void setName(String n)
+ {
+ name = n;
+ }
+
+ public String getName()
+ {
+ if (name == null)
+ {
+ name = "lab" + width + "x" + height;
+ }
+ return name;
+ }
+
+ public File getSaveDir()
+ {
+ return labdir;
+ }
+}
diff --git a/java/org/artisanlogiciel/games/WallsProvider.java b/java/org/artisanlogiciel/games/WallsProvider.java
index 6e61b4a..6c96c10 100644
--- a/java/org/artisanlogiciel/games/WallsProvider.java
+++ b/java/org/artisanlogiciel/games/WallsProvider.java
@@ -13,7 +13,12 @@ public interface WallsProvider
/**
* See Brick
*
- * Will set bits : 3 2 1 0 (8)(4)(2)(1) ^ > v < U R D L p i o e g w f h n t
+ * Will set bits :
+ * 3 2 1 0
+ * (8)(4)(2)(1)
+ * ^ > v <
+ * U R D L
+ * p i o e g w f h n t
* t
**/
public short getWalls(int x, int y);
diff --git a/java/org/artisanlogiciel/games/maze/gui/Display.java b/java/org/artisanlogiciel/games/maze/gui/Display.java
new file mode 100644
index 0000000..79893e5
--- /dev/null
+++ b/java/org/artisanlogiciel/games/maze/gui/Display.java
@@ -0,0 +1,1164 @@
+package org.artisanlogiciel.games.maze.gui;
+
+import java.awt.BorderLayout;
+import java.awt.image.BufferedImage;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.io.*;
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import javax.imageio.ImageIO;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.artisanlogiciel.games.*;
+import org.artisanlogiciel.games.stl.Maze3dParams;
+import org.artisanlogiciel.games.stl.Wall3d;
+import org.artisanlogiciel.games.stl.Wall3dStream;
+import org.artisanlogiciel.util.UTF8Control;
+
+import org.artisanlogiciel.graphics.Drawing;
+import org.artisanlogiciel.graphics.DrawingLine;
+import org.artisanlogiciel.graphics.SvgWriter;
+
+/**
+ * Display is Main JFrame for this tool
+ **/
+public class Display extends JFrame {
+ // to please eclipse, not supposed to be serialized
+ private static final long serialVersionUID = 8500214871372184418L;
+
+ public final static ResourceBundle labels = ResourceBundle.getBundle("LabelsBundle", Locale.getDefault(), Display.class.getClassLoader(), new UTF8Control());
+
+ MazeComponent maze;
+ MazeControler controler;
+ LabyModel model;
+ boolean autoSize;
+
+ MazeParams params = null;
+ JTextField statusField = null;
+
+ Maze3dSettings stlsettings;
+
+ Display(LabyModel model, int W, int H, MazeParams params) {
+ super(labels.getString("title"));
+ if (params != null) {
+ // fixedParams = new MazeParamsFixed(params.getSaveDir(),params.getWidth(),params.getHeight(),params.getMaxDepth());
+ this.params = params;
+ }
+ this.model = model;
+ maze = createMazeComponent(model, W, H);
+
+ Container con = this.getContentPane();
+ JScrollPane scrollableMaze = new JScrollPane(maze);
+ scrollableMaze.addMouseMotionListener(maze);
+ con.add(scrollableMaze, BorderLayout.CENTER);
+ controler = new MazeControler(params);
+ con.add(controler.getMoveControl(), BorderLayout.NORTH);
+ con.add(controler.getGenerationControl(), BorderLayout.SOUTH);
+
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ if (autoSize) {
+ maze.getAutoSize();
+ }
+ }
+ });
+
+ model.setMazeListener(maze);
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setBounds(W, H, W, H);
+ setVisible(true);
+ }
+
+ private MazeComponent createMazeComponent(LabyModel model, int W, int H) {
+ MazeCellParameters cp = new MazeCellParameters(model.getWidth(), model.getHeight(), W, H, 3, 3);
+ MazeComponent comp = new MazeComponent(model, cp);
+ return comp;
+ }
+
+ void recreateModel() {
+ // recreate labyrinth
+ if (params != null) {
+
+ // Keep current model to be able to complete a manualy edited one
+ maze.resetWallsProvider(model);
+ model.setMazeListener(maze);
+
+ model.reset();
+
+ // we are in GUI event thread, need to release it and do it outside.
+ new Thread() {
+ public void run() {
+ model.generateWithEntry(0, 0);
+ model.addEntryOrExit(-1, 0);
+ model.addEntryOrExit(params.getWidth(), params.getHeight() - 1);
+ }
+ }.start();
+ }
+ }
+
+ void resetModel() {
+ // recreate labyrinth
+ if (params != null) {
+ params = controler.getSettings().resetParams();
+ model = new LabyModel(params);
+
+ refresh();
+ }
+ }
+
+ void refresh()
+ {
+ // reinit labyrinth view
+ if (params != null) {
+ maze.resetWallsProvider(model);
+ model.setMazeListener(maze);
+
+ // we are in GUI event thread, need to release it and do it outside.
+ new Thread() {
+ public void run() {
+ maze.changed(null, null, model);
+ }
+ }.start();
+
+ }
+ }
+
+ void resolve() {
+ model.reset();
+ model.resolve(model.getWidth() - 1, model.getHeight() - 1, maze);
+ }
+
+ void goNorth() {
+ maze.goNorth();
+ }
+
+ void goSouth() {
+ maze.goSouth();
+ }
+
+ void goEast() {
+ maze.goEast();
+ }
+
+ void goWest() {
+ maze.goWest();
+ }
+
+ void setWallSize(int size) {
+ maze.setWallSize(size);
+ }
+
+ void setAutoSize(boolean autoSize) {
+ this.autoSize = autoSize;
+ if (autoSize) {
+ maze.getAutoSize();
+ }
+ }
+
+ void addWallInDrawing(int pX, int pY, Drawing d) {
+ short walls = model.getWalls(pX, pY);
+ short wdrawn = 0;
+ // todo
+ int w = 2;
+ int h = 2;
+ int ox = 0;
+ int oy = 0;
+
+ int x = ox + (int) (pX * w);
+ int y = oy + (int) (pY * h);
+ DrawingLine dl = new DrawingLine();
+ // order matters since all points are linked
+ if ((pY == 0) && LabyModel.isFlagSet(walls, Brick.UP)) {
+ dl.addPoint(new Point(x, y));
+ dl.addPoint(new Point(x + (int) w, y));
+ wdrawn |= Brick.UP;
+ }
+ if (LabyModel.isFlagSet(walls, Brick.RIGHT)) {
+ if (!LabyModel.isFlagSet(wdrawn, Brick.UP)) {
+ dl.addPoint(new Point(x + (int) w, y));
+ }
+ dl.addPoint(new Point(x + (int) w, y + (int) h));
+ wdrawn |= Brick.RIGHT;
+ }
+ if (LabyModel.isFlagSet(walls, Brick.DOWN)) {
+ if (!LabyModel.isFlagSet(wdrawn, Brick.RIGHT)) {
+ if (wdrawn != 0) {
+ d.addLine(dl);
+ dl = new DrawingLine();
+ }
+ dl.addPoint(new Point(x + (int) w, y + (int) h));
+ }
+ dl.addPoint(new Point(x, y + (int) h));
+ wdrawn |= Brick.DOWN;
+ }
+ if ((pX == 0) && LabyModel.isFlagSet(walls, Brick.LEFT)) {
+ if (!LabyModel.isFlagSet(wdrawn, Brick.DOWN)) {
+ if (wdrawn != 0) {
+ d.addLine(dl);
+ dl = new DrawingLine();
+ }
+ dl.addPoint(new Point(x, y + (int) h));
+ }
+ dl.addPoint(new Point(x, y));
+ wdrawn |= Brick.LEFT;
+ }
+ if (wdrawn != 0) {
+ d.addLine(dl);
+ }
+ }
+
+ Drawing createDrawing() {
+ Drawing d = new Drawing();
+ {
+ short walls;
+
+ // draw all walls within clip bounds horiz first then lines
+ for (int y = 0; y < model.getHeight(); y++) {
+ for (int x = 0; x < model.getWidth(); x++) {
+ addWallInDrawing(x, y, d);
+ }
+ }
+ }
+ return d;
+ }
+
+ // to allow to log / write somewher into screen...
+ void writeSentence(String pSentence) {
+ // TODO
+ addStatus(pSentence);
+ }
+
+ void writeError(String pError) {
+ System.err.println(pError);
+ }
+
+ void saveImc() {
+ Drawing d = createDrawing();
+
+ if (d != null) {
+ File outfile = getFileForExtension("imc");
+ writeSentence("Saving to " + outfile + " ...");
+ try {
+ DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile));
+ d.saveLinesKompressed(out);
+ out.flush();
+ out.close();
+ writeSentence("... Done.");
+ } catch (IOException io) {
+ io.printStackTrace(System.err);
+ }
+ }
+ }
+
+ File getFileForExtension(final String extension)
+ {
+ return new File(params.getSaveDir(), params.getName() + "." + extension);
+ }
+
+ void saveSvg() {
+ Drawing d = createDrawing();
+
+ if (d != null) {
+ File outfile = getFileForExtension("svg");
+ writeSentence("Saving to " + outfile + " ...");
+ try {
+ DataOutputStream out = new DataOutputStream(new FileOutputStream(outfile));
+ SvgWriter writer = new SvgWriter(d.getInternLines());
+ writer.writeTo(out);
+ out.flush();
+ out.close();
+ writeSentence("... Done.");
+ } catch (IOException io) {
+ io.printStackTrace(System.err);
+ }
+ } else {
+ writeError("drawing creation failed");
+ }
+ }
+
+
+ void savePng() {
+ File file = getFileForExtension("png");
+ // BufferedImage bi = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_ARGB);
+ BufferedImage bi = new BufferedImage(maze.getSize().width, maze.getSize().height, BufferedImage.TYPE_INT_ARGB);
+ Graphics g = bi.createGraphics();
+ // this.paint(g);
+ maze.paint(g);
+ g.dispose();
+ try {
+ ImageIO.write(bi, "png", file);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ void addStatus(String pStatus)
+ {
+ statusField.setText(pStatus);
+ }
+
+
+ private class MazeControler extends JPanel {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ private MazeSettings settings = null;
+
+ private JPanel resizecontrol = null;
+
+ private void setMazeName(String pName) {
+ MazeParamsFixed p = (MazeParamsFixed) params;
+ p.setName(pName);
+ }
+
+ private JMenu createLoadingMenu() {
+ JMenu loadMenu = new JMenu(labels.getString("load") );
+
+ final JTextField loadName = new JTextField("newlaby");
+
+ loadMenu.add(loadName);
+
+ Action loadRawAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("load raw");
+
+ String filename = loadName.getText();
+
+ if ((filename.length() > 0)) {
+ setMazeName(filename);
+ loadRaw();
+ refresh();
+ }
+
+ }
+ };
+ JButton loadRawButton = new JButton(labels.getString("load" ) + " raw");
+ loadRawButton.addActionListener(loadRawAction);
+
+ loadMenu.add(loadRawButton);
+ return loadMenu;
+ }
+
+ private JMenu createSavingMenu() {
+ final JTextField saveName = new JTextField("newlaby");
+ final JButton savePngButton = new JButton(labels.getString("save") + " png");
+ Action savePngAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("save png");
+ setMazeName(saveName.getText());
+ savePng();
+ }
+ };
+ savePngButton.addActionListener(savePngAction);
+ final JButton saveSvgButton = new JButton(labels.getString("save") + " svg");
+ Action saveSvgAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ writeSentence("save svg");
+ setMazeName(saveName.getText());
+ saveSvg();
+ }
+ };
+ saveSvgButton.addActionListener(saveSvgAction);
+ final JButton saveButton = new JButton(labels.getString("save") + " raw");
+ Action saveAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("save");
+ setMazeName(saveName.getText());
+ MazeParamsFixed p = (MazeParamsFixed) params;
+ save(p, model);
+ }
+ };
+ saveButton.addActionListener(saveAction);
+ final JButton saveImcButton = new JButton(labels.getString("save") + " imc");
+ Action saveImcAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("save imc");
+ setMazeName(saveName.getText());
+ saveImc();
+ }
+ };
+ saveImcButton.addActionListener(saveImcAction);
+ final JButton saveStlButton = new JButton(labels.getString("save") + " stl");
+ Action saveStlAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("save stl");
+ setMazeName(saveName.getText());
+ MazeParamsFixed p = (MazeParamsFixed) params;
+ saveStl(p, model,stlsettings.createParams());
+ }
+ };
+ saveStlButton.addActionListener(saveStlAction);
+
+ stlsettings = new Maze3dSettings(new Maze3dParams());
+
+ JMenu saveMenu = new JMenu(labels.getString("save") );
+ saveMenu.add(saveName);
+ saveMenu.add(saveSvgButton);
+ saveMenu.add(savePngButton);
+ saveMenu.add(saveButton);
+ saveMenu.add(stlsettings);
+ saveMenu.add(saveStlButton);
+ saveMenu.add(saveImcButton);
+
+ return saveMenu;
+
+ }
+
+ private JPanel createResolveQuitBar() {
+ JPanel resolveQuitBar = new JPanel(new FlowLayout());
+
+ JButton buttonCreate = new JButton(labels.getString("create"));
+ buttonCreate.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ recreateModel();
+ }
+ });
+ resolveQuitBar.add(buttonCreate);
+
+ JButton resolveButton = new JButton(labels.getString("resolve"));
+ resolveButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("Resolving");
+ resolve();
+ }
+ });
+
+ resolveQuitBar.add(resolveButton);
+
+ final JButton quitButton = new JButton(labels.getString("quit"));
+ Action quitAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("quit");
+ System.exit(0);
+ }
+ };
+ quitButton.addActionListener(quitAction);
+
+ resolveQuitBar.add(quitButton);
+
+ JButton buttonReset = new JButton("reset");//labels.getString("reset"));
+ buttonReset.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ resetModel();
+ }
+ });
+ resolveQuitBar.add(buttonReset);
+
+ return resolveQuitBar;
+
+ }
+
+ public MazeControler(MazeParams params) {
+ // super(new BorderLayout());
+ super();
+ BoxLayout layout = new BoxLayout(this, BoxLayout.Y_AXIS);
+ setLayout(layout);
+
+ JMenuBar menuBar = new JMenuBar();
+ menuBar.add(createSavingMenu());
+ menuBar.add(createLoadingMenu());
+ add(menuBar);
+
+ add(createResolveQuitBar());
+
+ JPanel controlMovesPanel = new JPanel(new BorderLayout());
+ settings = new MazeSettings(params);
+ @SuppressWarnings("serial")
+ Action goNorth = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("go North");
+ goNorth();
+ }
+ };
+ JButton north = addDirection(this, labels.getString("north"), "UP", goNorth);
+
+ @SuppressWarnings("serial")
+ Action goEast = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("go East");
+ goEast();
+ }
+ };
+
+ JButton east = addDirection(this, labels.getString("east"), "RIGHT", goEast);
+
+ @SuppressWarnings("serial")
+ Action goWest = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("go West");
+ goWest();
+ }
+ };
+ JButton west = addDirection(this, labels.getString("west"), "LEFT", goWest);
+
+ @SuppressWarnings("serial")
+ Action goSouth = new AbstractAction() {
+ public void actionPerformed(ActionEvent evt) {
+ //
+ addStatus("go South");
+ goSouth();
+ }
+ };
+ JButton south = addDirection(this, labels.getString("south"), "DOWN", goSouth);
+
+ controlMovesPanel.add(north, BorderLayout.NORTH);
+ controlMovesPanel.add(west, BorderLayout.WEST);
+ controlMovesPanel.add(east, BorderLayout.EAST);
+ controlMovesPanel.add(south, BorderLayout.SOUTH);
+
+ JPanel controlPanel = new JPanel();
+
+ controlPanel.add(controlMovesPanel,BorderLayout.LINE_START);
+ statusField = new JTextField("",20);
+ controlPanel.add(statusField, BorderLayout.CENTER);
+ add(controlPanel, BorderLayout.NORTH);
+
+ // control display panel contains controls for display
+ // zoom , autozoom.
+ final JPanel controlDisplayPanel = new JPanel(new BorderLayout());
+ final JCheckBox showAll = new JCheckBox("show all");
+ showAll.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ maze.setShowAll(showAll.isSelected());
+ }
+ });
+
+ final JSlider slider = new JSlider(2, 40);
+ slider.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ setWallSize(slider.getValue());
+ }
+ });
+ final JCheckBox autoSlide = new JCheckBox("autoslide");
+ autoSlide.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ setAutoSize(autoSlide.isSelected());
+ }
+ });
+
+ resizecontrol = new JPanel(new FlowLayout());
+ resizecontrol.add(showAll);
+ resizecontrol.add(slider);
+ resizecontrol.add(autoSlide);
+
+ add(controlDisplayPanel, BorderLayout.SOUTH);
+ add(resizecontrol, BorderLayout.WEST);
+ add(settings, BorderLayout.EAST);
+
+ }
+
+ private JPanel getMoveControl() {
+ return this;
+ }
+
+ private JPanel getResizeControl() {
+ return resizecontrol;
+ }
+
+ private JPanel getGenerationControl() {
+ return settings;
+ }
+
+ public MazeSettings getSettings() {
+ return settings;
+ }
+
+ }
+
+ private void loadRaw() {
+ File infile = new File(params.getSaveDir(), params.getName() + ".raw");
+ FileInputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(infile);
+ model = new LabyModel("raw", inputStream);
+ } catch (IOException io) {
+ io.printStackTrace(System.err);
+ statusField.setText("[ERROR] Can't load " + infile.getAbsolutePath());
+ }
+ finally
+ {
+ if (inputStream != null )
+ {
+ // cleanup
+ try {
+ inputStream.close();
+ }
+ catch (Exception any)
+ {
+ // don't care really
+ }
+ }
+ }
+ }
+
+ private JButton addDirection(final JPanel panel, final String direction, String key, Action goAction) {
+ String actionName = "go" + direction;
+ JButton button = new JButton(direction);
+ button.addActionListener(goAction);
+ KeyStroke keystroke = KeyStroke.getKeyStroke(key);
+ // attach keys to maze
+ maze.getInputMap().put(keystroke, actionName);
+ maze.getActionMap().put(actionName, goAction);
+ return button;
+ }
+
+ private static class MazeCellParameters {
+ double width = 10; // width of one cell
+ double height = 10; // height of one cell
+ int offsetX = 5; // x offset of upper corner left
+ int offsetY = 5; // y offset of upper corner left
+
+ int mapWidth = 0;
+ int mapHeight = 0;
+
+ public MazeCellParameters(int mapw, int maph, int W, int H, int x, int y) {
+ double w = (W - x) / mapw;
+ double h = (H - y) / maph;
+ mapWidth = mapw;
+ mapHeight = maph;
+ if (w < 5)
+ w = 5;
+ if (h < 5)
+ h = 5;
+ setCellSize(w, h);
+ offsetX = x;
+ offsetY = y;
+ }
+
+ public void resetMazeWidthHeight(int mapw, int maph) {
+ mapWidth = mapw;
+ mapHeight = maph;
+ }
+
+ public void adaptTo(double W, double H) {
+ double w = (W - offsetX) / mapWidth;
+ double h = (H - offsetY) / mapHeight;
+ mapWidth = mapWidth;
+ mapHeight = mapHeight;
+ if (w < 5)
+ w = 5;
+ if (h < 5)
+ h = 5;
+ setCellSize(w, h);
+ }
+
+ public void setCellSize(double w, double h) {
+ width = w;
+ height = h;
+ }
+
+ public double getWidth() {
+ return width;
+ }
+
+ public double getHeight() {
+ return height;
+ }
+
+ public int getOffsetX() {
+ return offsetX;
+ }
+
+ public int getOffsetY() {
+ return offsetY;
+ }
+
+ public Dimension getDimension() {
+ return new Dimension(offsetX + (int) (mapWidth * width),
+ offsetY + (int) (mapHeight * height));
+ }
+
+ public void drawWalls(Graphics g, int pX, int pY, short walls) {
+ int x = offsetX + (int) (pX * width);
+ int y = offsetY + (int) (pY * height);
+ if ((pY == 0) && ((walls & Brick.UP) == Brick.UP))
+ g.drawLine(x, y, x + (int) width, y);
+ if ((walls & Brick.DOWN) == Brick.DOWN)
+ g.drawLine(x, y + (int) height, x + (int) width, y + (int) height);
+ if ((walls & Brick.RIGHT) == Brick.RIGHT)
+ g.drawLine(x + (int) width, y, x + (int) width, y + (int) height);
+ if ((pX == 0) && ((walls & Brick.LEFT) == Brick.LEFT))
+ g.drawLine(x, y, x, y + (int) height);
+ }
+
+ public void drawPath(Graphics g, DirectionPosition dp, int pX, int pY, int mX, int mY) {
+ if (dp != null) {
+ Position dot = dp.getPosition();
+ if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
+ int x = offsetX + (int) (dot.getX() * width);
+ int y = offsetY + (int) (dot.getY() * height);
+ short path = dp.getDirection();
+ int xm = x + (int) (width / 2);
+ int ym = y + (int) (height / 2);
+ if ((path & LabyModel.HORIZONTAL) == LabyModel.HORIZONTAL) {
+ if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
+ g.drawLine(xm, ym, x + (int) width, ym);
+ g.drawLine(xm, ym + (int) (height / 4), x + (int) width, ym);
+ }
+ // LEFT /_
+ if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
+ g.drawLine(x, ym, xm, ym);
+ g.drawLine(x, ym, xm, ym - (int) (height / 4));
+ }
+ }
+ if ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL) {
+ if ((path & LabyModel.POSITIVE) == LabyModel.POSITIVE) {
+ g.drawLine(xm, ym, xm, y + (int) height);
+ g.drawLine(xm - (int) (width / 4), ym, xm, y + (int) height);
+ }
+ // UP |\
+ if ((path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE) {
+ g.drawLine(xm, ym, xm, y);
+ g.drawLine(xm + (int) (width / 4), ym, xm, y);
+ }
+ }
+ }
+ }
+ }
+
+ public void drawDot(Graphics g, Position dot, int pX, int pY, int mX, int mY) {
+ double radius = (height > width) ? width : height;
+ int a = (int) (radius / 4);
+ if ((dot.getX() >= pX) && (dot.getY() >= pY) && (dot.getX() < mX) && (dot.getY() < mY)) {
+ int x = offsetX + (int) (dot.getX() * width);
+ int y = offsetY + (int) (dot.getY() * height);
+ int r2 = (int) ((radius * 3) / 4);
+ g.drawOval(x + 1, y + 1, r2, r2);
+ // g.drawLine(x+a,y+a,x+width-a,y+height-a);
+ // g.drawLine(x+a,y+height-a,x+width-a,y+a);
+
+ } else {
+ int x = offsetX + (int) (pX * width);
+ int y = offsetY + (int) (pY * height);
+ g.drawLine(x + 1, y + 1, x + (int) width - 1, y + (int) height - 1);
+ }
+ }
+
+ }
+
+ private class MazeComponent
+ extends JComponent
+ implements MazeCreationListener,
+ MazeResolutionListener,
+ MouseMotionListener {
+ private static final long serialVersionUID = 3163272907991176390L;
+
+ // WallsProvider map;
+ LabyModel map;
+ final MazeCellParameters cp;
+ Position current = null;
+ LinkedList solvedPath = null;
+ LinkedList drawingPath = null;
+ final Object lockChange = new Object();
+ // current postion of human resolving
+ int sX = 0;
+ int sY = 0;
+ // goal exit
+ int gX = -1;
+ int gY = -1;
+
+ // not set by default for debug, will show any path
+ boolean showAll = false;
+
+ // for a given (x,y) pixel return cell position.
+ Position getPosition(int x, int y) {
+ int pX = (int) ((double) (x - cp.getOffsetX()) / cp.getWidth());
+ int pY = (int) ((double) (y - cp.getOffsetY()) / cp.getHeight());
+ return new Position(pX, pY);
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ // should find the cell ...
+ DirectionPosition last = null;
+ short path = 0;
+ Position newPosition = getPosition(e.getX(), e.getY());
+ if (drawingPath == null) {
+ drawingPath = new LinkedList<>();
+ last = new DirectionPosition((short) 0, newPosition);
+ addStatus("Mouse dragged Cell " + newPosition + " Button " + e.getModifiersEx() + " " + InputEvent.BUTTON1_DOWN_MASK);
+ drawingPath.addLast(last);
+ } else {
+ // setShowAll(true);
+ DirectionPosition first = drawingPath.getLast();
+ last = first;
+ // construct as many move form last to new position as needed.
+ while (!last.getPosition().equals(newPosition)) {
+ path = LabyModel.getDirection(last.getPosition(), newPosition);
+ last.setDirection(path);
+ // button 1 : add direction; button 2 : replace with direction.
+ if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0) {
+ map.addDirection(last.getPosition().getX(), last.getPosition().getY(), path);
+ } else {
+ map.setDirection(last.getPosition().getX(), last.getPosition().getY(), path);
+ }
+ last = last.moveToAdjacentDirection();
+ drawingPath.addLast(last);
+ }
+ addStatus("Mouse dragged from Cell " + first.getPosition() + "To" + newPosition + " Button " + e.getModifiersEx() + " " + InputEvent.BUTTON1_DOWN_MASK);
+ }
+ changed(null, null, map);
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ // addStatus("Mouse moved (" + e.getX() + ',' + e.getY() + ')');
+ Position newPosition = getPosition(e.getX(), e.getY());
+ if ((newPosition.getX() >= 0) && (newPosition.getY() >= 0)) {
+ requestFocus();
+ }
+ }
+
+ public void setShowAll(boolean showall) {
+ this.showAll = showall;
+ addStatus(showAll ? "show all" : "X");
+ }
+
+ void checkExit() {
+ if ((sX == gX) && (sY == gY)) {
+ addStatus("Exit found by human !");
+ }
+ }
+
+ void goNorth() {
+ resetResolution();
+ if ((map.getWalls(sX, sY) & Brick.UP) == 0) {
+ sY = sY - 1;
+ // should redraw ...
+ invalidate();
+ repaint();
+
+ checkExit();
+ }
+
+ }
+
+ void goSouth() {
+ resetResolution();
+ if ((map.getWalls(sX, sY) & Brick.DOWN) == 0) {
+ sY = sY + 1;
+ // should redraw ...
+ invalidate();
+ repaint();
+
+ checkExit();
+ }
+
+ }
+
+ void goEast() {
+ resetResolution();
+ if ((map.getWalls(sX, sY) & Brick.RIGHT) == 0) {
+ sX = sX + 1;
+ // should redraw ...
+ invalidate();
+ repaint();
+
+ checkExit();
+ }
+ }
+
+ void goWest() {
+ resetResolution();
+ if ((map.getWalls(sX, sY) & Brick.LEFT) == 0) {
+ sX = sX - 1;
+ // should redraw ...
+ invalidate();
+ repaint();
+
+ checkExit();
+ }
+
+ }
+
+ /**
+ * width, height of one cell,
+ * offsetX, offsetY of upper left corner
+ **/
+ // public MazeComponent(WallsProvider map, MazeCellParameters cp)
+ public MazeComponent(LabyModel map, MazeCellParameters cp) {
+ super();
+ this.cp = cp;
+ this.map = map;
+ setPreferredSize(cp.getDimension());
+ gX = map.getWidth() - 1;
+ gY = map.getHeight() - 1;
+ }
+
+ // public void resetWallsProvider(WallsProvider map)
+ public void resetWallsProvider(LabyModel map) {
+ this.map = map;
+ solvedPath = null;
+ // could be kept
+ drawingPath = null;
+ sX = 0;
+ sY = 0;
+ cp.resetMazeWidthHeight(map.getWidth(), map.getHeight());
+ setPreferredSize(cp.getDimension());
+ }
+
+ public void setWallSize(int size) {
+ cp.setCellSize((double) size, (double) size);
+ // should redraw ...
+ invalidate();
+ repaint();
+ }
+
+ public int getAutoSize() {
+ Rectangle r = getBounds();
+ cp.adaptTo((int) r.getWidth(), (int) r.getHeight());
+ // should redraw ...
+ invalidate();
+ repaint();
+ return 50;
+ }
+
+ public void changed(Position cl, Position cr, WallsProvider map) {
+ // should redraw ...
+ invalidate();
+ repaint();
+ Object waiter = new Object();
+ synchronized (waiter) {
+ try {
+ waiter.wait(10);
+ } catch (InterruptedException e) {
+ System.err.println("Interrupted !");
+ }
+ }
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ int x = 0;
+ int y = 0;
+ short walls = 0;
+ short path = 0;
+
+ // try to display only visible part...
+ // should compute pX, pY, mX, mY based on clip...
+ // Shape s=g.getClip();
+ Rectangle r = g.getClipBounds();
+
+ int mX = (int) ((double) r.getWidth() / cp.getWidth());
+ int mY = (int) ((double) r.getHeight() / cp.getHeight());
+ int pX = (int) ((double) (r.getX() - cp.getOffsetX()) / cp.getWidth());
+ int pY = (int) ((double) (r.getY() - cp.getOffsetY()) / cp.getHeight());
+
+ if (pX < 0)
+ pX = 0;
+ if (pY < 0)
+ pY = 0;
+ if (pX >= map.getWidth())
+ return;
+ if (pY >= map.getHeight())
+ return;
+
+ mX = mX + pX;
+ mY = mY + pY;
+
+ if (mX > map.getWidth()) {
+ mX = map.getWidth();
+ }
+ if (mY > map.getHeight()) {
+ mY = map.getHeight();
+ }
+
+ if ((sX == gX) && (sY == gY)) {
+ g.setColor(Color.red);
+ } else {
+ g.setColor(Color.green);
+ cp.drawDot(g, new Position(gX, gY), pX, pY, mX, mY);
+ g.setColor(Color.blue);
+ }
+ cp.drawDot(g, new Position(sX, sY), pX, pY, mX, mY);
+
+ synchronized (lockChange) {
+ g.setColor(Color.red);
+ if (current != null) {
+ cp.drawDot(g, current, pX, pY, mX, mY);
+ }
+ if (solvedPath != null) {
+ for (DirectionPosition resolved : solvedPath) {
+ // cp.drawDot(g, resolved.getPosition(), pX, pY, mX, mY);
+ cp.drawPath(g, resolved, pX, pY, mX, mY);
+ }
+ }
+ }
+
+ int aX = pX;
+ int aY = pY;
+
+ g.setColor(Color.black);
+
+ // draw all walls within clip bounds horiz first then lines
+ for (; pY < mY; pY++) {
+ for (pX = 0; pX < mX; pX++) {
+ walls = map.getWalls(pX, pY);
+ cp.drawWalls(g, pX, pY, walls);
+ }
+ }
+
+ if (this.showAll) {
+ addStatus("*");
+ pX = aX;
+ pY = aY;
+
+ // draw all path within clip bounds horiz first then lines
+ for (; pY < mY; pY++) {
+ for (pX = 0; pX < mX; pX++) {
+ path = map.getPath(pX, pY);
+ if ((path & LabyModel.SOLVED) == LabyModel.SOLVED) {
+ g.setColor(Color.green);
+ } else {
+ g.setColor(Color.blue);
+ }
+ if (path != 0) {
+ DirectionPosition dp = new DirectionPosition(path, new Position(pX, pY));
+ cp.drawPath(g, dp, pX, pY, pX + 1, pY + 1);
+ }
+ }
+ }
+ }
+ }
+
+
+ public boolean notifySearch(DirectionPosition pPosition) {
+ synchronized (lockChange) {
+ current = pPosition.getPosition();
+ }
+ // should redraw ...
+ invalidate();
+ repaint();
+ return true;
+
+ }
+
+ public void notifySearchError(String error) {
+ System.err.println(error);
+ }
+
+ public void notifyCompletion(LinkedList solvedPath) {
+ LinkedList newPath = new LinkedList<>(solvedPath);
+ addStatus("resolution completed");
+ synchronized (lockChange) {
+ this.solvedPath = newPath;
+ }
+ // should redraw ...
+ invalidate();
+ repaint();
+ }
+
+ public void resetResolution() {
+ solvedPath = null;
+ }
+ }
+
+ private static void setupDisplay(LabyModel model, int W, int H, MazeParams params) {
+ Display display = new Display(model, W, H, params);
+ }
+
+ public void saveStl(MazeParamsFixed params, LabyModel model, Maze3dParams wallparams) {
+ File outfile = getFileForExtension("stl");
+ if (!outfile.exists()) {
+ addStatus("Saving to " + outfile + " ...");
+ try {
+ FileOutputStream out = new FileOutputStream(outfile);
+ new Wall3dStream(params.getName(), model, out, wallparams).stream();
+ out.close();
+ addStatus("... Done.");
+ } catch (IOException io) {
+ io.printStackTrace(System.err);
+ }
+ } else {
+ addStatus("" + outfile + " already exists");
+ }
+
+ }
+
+ public void save(MazeParamsFixed params, LabyModel model) {
+ File outfile = getFileForExtension("raw");
+ if (!outfile.exists()) {
+ addStatus("Saving to " + outfile + " ...");
+ try {
+ FileOutputStream out = new FileOutputStream(outfile);
+ model.streamOut("raw", out);
+ out.flush();
+ out.close();
+ addStatus("... Done.");
+ } catch (IOException io) {
+ io.printStackTrace(System.err);
+ }
+ } else {
+ addStatus("" + outfile + " already exists");
+ }
+ }
+
+
+ public static void main(String pArgs[]) {
+ LabyModel model = null;
+ int W = 600;
+ int H = 400;
+
+ System.out.println("Default Locale " + Locale.getDefault());
+
+ if ((pArgs.length > 0) && (pArgs[0].length() > 0)) {
+ try {
+ model = new LabyModel("raw", new FileInputStream(pArgs[0]));
+ } catch (IOException io) {
+ io.printStackTrace(System.err);
+ System.exit(1);
+ }
+
+ setupDisplay(model, W, H, null);
+ } else {
+ MazeParamsFixed params = new MazeParamsFixed(new File("lab"), 20, 20, 12,1024L);
+ model = new LabyModel(params);
+
+ setupDisplay(model, W, H, params);
+
+ /*
+ model.generateWithEntry(0, 0);
+
+ model.addEntryOrExit(-1, 0);
+ model.addEntryOrExit(params.getWidth(), params.getHeight() - 1);
+
+ addStatus("Generation completed");
+ */
+ /*
+ */
+ }
+
+ }
+}
diff --git a/java/org/artisanlogiciel/games/maze/gui/Maze3dSettings.java b/java/org/artisanlogiciel/games/maze/gui/Maze3dSettings.java
new file mode 100644
index 0000000..601e396
--- /dev/null
+++ b/java/org/artisanlogiciel/games/maze/gui/Maze3dSettings.java
@@ -0,0 +1,72 @@
+package org.artisanlogiciel.games.maze.gui;
+
+import org.artisanlogiciel.games.MazeParams;
+import org.artisanlogiciel.games.stl.Maze3dParams;
+import org.artisanlogiciel.games.stl.Wall3d;
+
+import javax.swing.*;
+
+public class Maze3dSettings
+ extends JPanel
+{
+ // grid size
+ JTextField xl;
+ JTextField yl;
+ JTextField zl;
+
+ JTextField w;
+ JTextField lg;
+ JTextField hg;
+
+ JCheckBox reverse;
+
+ Maze3dParams params;
+
+ public Maze3dSettings(Maze3dParams params) {
+ super();
+ this.params = params;
+ createSettingsGui();
+ }
+
+ void createSettingsGui() {
+ if (params != null) {
+ JLabel widthLabel = new JLabel(Display.labels.getString("width"));
+ xl = new JTextField("0" + params.getXl());
+ add(widthLabel);
+ add(xl);
+ JLabel heightLabel = new JLabel(Display.labels.getString("height"));
+ zl = new JTextField("0" + params.getZl());
+ add(heightLabel);
+ add(zl);
+ JLabel depthLabel = new JLabel(Display.labels.getString("depth"));
+ yl = new JTextField("0" + params.getYl());
+ add(depthLabel);
+ add(yl);
+
+ reverse = new JCheckBox("reverse",params.isReverse());
+ add(reverse);
+
+ w = new JTextField("0" + params.getW());
+ add(w);
+
+ // lowground hightground
+ lg = new JTextField("0" + params.getLg());
+ add(lg);
+ hg = new JTextField("0" + params.getHg());
+ add(hg);
+ }
+ }
+
+ Maze3dParams createParams()
+ {
+ return new Maze3dParams(
+ Integer.parseInt(xl.getText()),
+ Integer.parseInt(yl.getText()),
+ Integer.parseInt(zl.getText()),
+ Integer.parseInt(w.getText()),
+ Integer.parseInt(lg.getText()),
+ Integer.parseInt(hg.getText()),
+ reverse.isSelected());
+ }
+
+}
diff --git a/java/org/artisanlogiciel/games/maze/gui/MazeSettings.java b/java/org/artisanlogiciel/games/maze/gui/MazeSettings.java
new file mode 100644
index 0000000..3feca25
--- /dev/null
+++ b/java/org/artisanlogiciel/games/maze/gui/MazeSettings.java
@@ -0,0 +1,56 @@
+package org.artisanlogiciel.games.maze.gui;
+
+import org.artisanlogiciel.games.MazeParams;
+import org.artisanlogiciel.games.MazeParamsFixed;
+
+import javax.swing.*;
+import java.util.Random;
+
+public class MazeSettings extends JPanel {
+ MazeParams params;
+
+ JTextField textWidth = null;
+ JTextField textHeight = null;
+ JTextField textDepth = null;
+ JTextField textSeed = null;
+
+ // TODO set width and height and depth of maze with gui
+ public MazeSettings(MazeParams params) {
+ super();
+ this.params = params;
+ createSettingsGui();
+ }
+
+ void createSettingsGui() {
+ if (params != null) {
+ JLabel widthLabel = new JLabel(Display.labels.getString("width"));
+ textWidth = new JTextField("0" + params.getWidth());
+ add(widthLabel);
+ add(textWidth);
+ JLabel heightLabel = new JLabel(Display.labels.getString("height"));
+ textHeight = new JTextField("0" + params.getHeight());
+ add(heightLabel);
+ add(textHeight);
+ JLabel depthLabel = new JLabel(Display.labels.getString("depth"));
+ textDepth = new JTextField("0" + params.getMaxDepth());
+ add(depthLabel);
+ add(textDepth);
+ JLabel seedLabel = new JLabel(Display.labels.getString("seed"));
+ textSeed = new JTextField( "" + params.getSeed(),16);
+ add(seedLabel);
+ add(textSeed);
+ }
+ }
+
+ public MazeParams resetParams() {
+ params = new MazeParamsFixed(params.getSaveDir(),
+ Integer.parseInt(textWidth.getText()),
+ Integer.parseInt(textHeight.getText()),
+ Integer.parseInt(textDepth.getText()),
+ new Random().nextLong()
+ );
+ textSeed.setText("" + params.getSeed());
+ return params;
+ }
+
+}
diff --git a/java/org/artisanlogiciel/games/stl/Maze3dParams.java b/java/org/artisanlogiciel/games/stl/Maze3dParams.java
new file mode 100644
index 0000000..c8c34f3
--- /dev/null
+++ b/java/org/artisanlogiciel/games/stl/Maze3dParams.java
@@ -0,0 +1,104 @@
+package org.artisanlogiciel.games.stl;
+
+public class Maze3dParams {
+
+ // grid size
+ int xl;
+ int yl;
+ int zl;
+
+ int w;
+ int lg;
+ int hg;
+
+ Wall3d south;
+ Wall3d west;
+ Wall3d north;
+ Wall3d east;
+ Wall3d highGround;
+ Wall3d lowGround;
+
+ // reverse : means that resolved path will be HighGround actual making maze more difficult to play with
+ boolean reverse;
+
+ // default
+ public Maze3dParams()
+ {
+ this(10,10,10, 1 , 1, 3, false);
+ }
+
+ // w width is wall thickness
+ public Maze3dParams(int xl, int yl, int zl, int w, int lg, int hg, boolean reverse)
+ {
+ this.xl = xl;
+ this.yl = yl;
+ this.zl = zl;
+ this.reverse = reverse;
+ int h = zl;
+
+ this.w = w;
+ this.lg = lg;
+ this.hg = hg;
+
+ south = new Wall3d(xl, w, h, 0, 0, 0);
+ west = new Wall3d(w, yl, h, 0, 0, 0);
+ north = new Wall3d(xl, w, h, 0, yl, 0);
+ east = new Wall3d(w, yl, h, xl, 0, 0);
+ highGround = new Wall3d(xl, yl, hg, 0, 0, 0);
+ lowGround = new Wall3d(xl, yl, lg, 0, 0, 0);
+ }
+
+ public boolean isReverse() {
+ return reverse;
+ }
+
+ public int getXl() {
+ return xl;
+ }
+
+ public int getYl() {
+ return yl;
+ }
+
+ public int getZl() {
+ return zl;
+ }
+
+ public Wall3d getSouth() {
+ return south;
+ }
+
+ public Wall3d getWest() {
+ return west;
+ }
+
+ public Wall3d getNorth() {
+ return north;
+ }
+
+ public Wall3d getEast() {
+ return east;
+ }
+
+ public Wall3d getHighGround() {
+ return highGround;
+ }
+
+ public Wall3d getLowGround() {
+ return lowGround;
+ }
+
+ public int getLg() {
+ return lg;
+ }
+
+ public int getHg() {
+ return hg;
+ }
+
+ public int getW() {
+ return w;
+ }
+
+
+}
diff --git a/java/org/artisanlogiciel/games/stl/Wall3d.java b/java/org/artisanlogiciel/games/stl/Wall3d.java
index cb0a582..7f77f3d 100644
--- a/java/org/artisanlogiciel/games/stl/Wall3d.java
+++ b/java/org/artisanlogiciel/games/stl/Wall3d.java
@@ -11,114 +11,134 @@ import java.io.IOException;
/**
* Wall3d to create walls in 3d for stl conversion South, West North East...
+ *
+ * wall3D will create a rectangular cuboid with 2 triangle vertex for each face
**/
-public class Wall3d
-{
+public class Wall3d {
+
// 4 triangles in 2 dim space reused 3 times
- final static int BASE[][][] = { { { 0, 0 }, { 1, 0 }, { 0, 1 } }, { { 1, 0 }, { 1, 1 }, { 0, 1 } },
- { { 0, 0 }, { 1, 0 }, { 1, 1 } }, { { 0, 0 }, { 1, 1 }, { 0, 1 } } };
+ // in facts order matters...
+ final static int BASE[][][] = {
+ // lower left
+ {{0, 0}, {1, 0}, {0, 1}},
+ // higher right
+ {{1, 0}, {1, 1}, {0, 1}},
+ // lower right
+ {{0, 0}, {1, 0}, {1, 1}},
+ // higher left
+ {{0, 0}, {1, 1}, {0, 1}}};
final static short X = 1;
final static short Y = 2;
final static short Z = 4;
// final static short AXIS[][]= {{X,Y},{-Z,Y},{X,Y},{Z,Y},{X,-Z},{X,-Z}};
- final static short AXIS[][] = { { X, Y, 0 }, { Z, Y, 0 }, { X, Y, 1 }, { Z, Y, 1 }, { X, Z, 0 }, { X, Z, 1 } };
- public final static Wall3d South = new Wall3d(10, 1, 10, 0, 0, 0);
- public final static Wall3d West = new Wall3d(1, 10, 10, 0, 0, 0);
- public final static Wall3d North = new Wall3d(10, 1, 10, 0, 10, 0);
- public final static Wall3d East = new Wall3d(1, 10, 10, 10, 0, 0);
- public final static Wall3d HighGround = new Wall3d(10, 10, 3, 0, 0, 0);
- public final static Wall3d LowGround = new Wall3d(10, 10, 2, 0, 0, 0);
+ // [face][axis]
+ final static short AXIS[][] = {
+ // face 0 (x,y) back
+ {X, Y, 0},
+ // face 1 (z,y) left
+ {Z, Y, 0},
+ // face 2 (x,y,1)
+ {X, Y, 1},
+ // face 3
+ {Z, Y, 1},
+ // face 4
+ {X, Z, 0},
+ // face 5
+ {X, Z, 1}};
+
+ final static String normalx = "1.0 0.0 0.0";
+ final static String normaly = "0.0 1.0 0.0";
+ final static String normalz = "0.0 0.0 1.0";
+ final static String normalmx = "-1.0 0.0 0.0";
+ final static String normalmy = "0.0 -1.0 0.0";
+ final static String normalmz = "0.0 0.0 -1.0";
+
+ // final static short NORMAL[] = {Z,X,Z,X,Y,Y};
+
+ final static String normalstr[] =
+ { normalmz, normalx,
+ normalz, normalmx,
+ normaly, normalmy
+ };
+
+ boolean reverse_vertex[] = {
+ true,false,false,true,false,true
+ };
int triangle[][][] = null;
- public Wall3d(int t[][][])
- {
+ public Wall3d(int t[][][]) {
triangle = t;
}
- public Wall3d(Wall3d origin, int dx, int dy, int dz)
- {
+ public Wall3d(Wall3d origin, int dx, int dy, int dz) {
triangle = origin.translate(dx, dy, dz);
}
- Wall3d(int xl, int yl, int zl, int dx, int dy, int dz)
- {
+ Wall3d(int xl, int yl, int zl, int dx, int dy, int dz) {
int f = 0;
triangle = new int[12][3][3];
- int[] factor = { xl, yl, zl };
- int[] translate = { dx, dy, dz };
- for (int i = 0; i < 12; i++)
- {
- // point in a triangle
- for (int p = 0; p < 3; p++)
- {
+ int[] factor = {xl, yl, zl};
+ int[] translate = {dx, dy, dz};
+ for (int facet = 0; facet < 12; facet++) {
+ // point in a triangle / facet
+ for (int p = 0; p < 3; p++) {
short uaxis = 0;
- for (int axis = 0; axis < 2; axis++)
- {
- short caxis = AXIS[i / 2][axis];
- if (caxis > 0)
- {
+ // a square face is two facets.
+ int face = facet / 2;
+ // first two axis ( projected on x,y,z depending on AXIS[face][] )
+ for (int axis = 0; axis < 2; axis++) {
+ short caxis = AXIS[face][axis];
+ if (caxis > 0) {
f = 1;
- }
- else if (caxis < 0)
- {
+ } else if (caxis < 0) {
+ // wait wait in AXIS there is no negative value ...
+ // so we never enter here, what was the purpose ? might be history.
f = -1;
caxis = (short) -caxis;
}
+ // what if caxis == 0 ? f is kept as its previous value ?
+ // which is 1 in facts due to AXIS[..][0] > 0
+
+ // uaxis keep track of used axes for this face to find last missing axis
uaxis |= caxis;
- if (caxis == X)
- {
+ if (caxis == X) {
caxis = 0;
- }
- else if (caxis == Y)
- {
+ } else if (caxis == Y) {
caxis = 1;
- }
- else
- {
+ } else {
caxis = 2;
}
- // if ( f == 0 )
- // {
- // System.out.println("ERROR");
- // }
- // System.out.println("i " + i + " p " + p + " a " + caxis +
- // " , " + BASE[i%4][p][axis] );
- triangle[i][p][caxis] = translate[caxis] + BASE[i % 4][p][axis] * f * factor[caxis];
+ triangle[facet][p][caxis] = translate[caxis] + BASE[facet % 4][p][axis] * f * factor[caxis];
}
- if ((uaxis & X) == 0)
- {
+ // last remaining axis
+ if ((uaxis & X) == 0) {
+ // no X was used => X
uaxis = 0;
- }
- else if ((uaxis & Y) == 0)
- {
+ } else if ((uaxis & Y) == 0) {
+ // X was used byt not Y => Y
uaxis = 1;
- }
- else
- {
+ } else {
+ // default X, and Y were used => Z
uaxis = 2;
}
- triangle[i][p][uaxis] = translate[uaxis] + AXIS[i / 2][2] * factor[uaxis];
+ triangle[facet][p][uaxis] = translate[uaxis] + AXIS[facet / 2][2] * factor[uaxis];
}
}
}
- public int[][][] translate(int dx, int dy, int dz)
- {
- int[] translate = { dx, dy, dz };
+ public int[][][] translate(int dx, int dy, int dz) {
+ int[] translate = {dx, dy, dz};
int t[][][] = new int[12][3][3];
- for (int i = 0; i < 12; i++)
- {
+ for (int facet = 0; facet < 12; facet ++) {
// point in a triangle
- for (int p = 0; p < 3; p++)
- {
- for (int axis = 0; axis < 3; axis++)
- {
- t[i][p][axis] = translate[axis] + triangle[i][p][axis];
+ for (int p = 0; p < 3; p++) {
+ for (int axis = 0; axis < 3; axis++) {
+ t[facet][p][axis] = translate[axis] + triangle[facet][p][axis];
}
}
}
@@ -127,22 +147,27 @@ public class Wall3d
}
/**
- write triangles as stl text
+ * write triangles as stl text
**/
- public String toString()
- {
+ public String toString() {
String s = "";
- for (int t = 0; t < 12; t++)
- {
- s += "facet normal 0 0 0\nouter loop\n";
- for (int p = 0; p < 3; p++)
- {
+ for (int facet = 0; facet < 12; facet++) {
+ int face = facet / 2;
+ // most software don't care normal but just rely on vertex order ( right hand ).
+ String normal = normalstr[face];
+ s += "facet normal " + normal + "\nouter loop\n";
+ boolean reverse = reverse_vertex[face];
+ for (int p = 0; p < 3; p++) {
s += "vertex";
- for (int a = 0; a < 3; a++)
+ // p that accept right hand
+ int rhp = p;
+ if ( reverse )
{
- // s+=" t "+ t + " p " + p + " a " + a + "=" +
- // triangle[t][p][a];
- s += " " + triangle[t][p][a];
+ // reverse 2 and 1 ; 0 => 0, 1 => 2 , 2 => 1
+ rhp = ( p * 5 ) % 3;
+ }
+ for (int a = 0; a < 3; a++) {
+ s += " " + triangle[facet][rhp][a];
}
s += "\n";
}
@@ -151,94 +176,4 @@ public class Wall3d
return s;
}
- public static void prepare()
- {
- System.out.println(South.toString());
- System.out.println(East.toString());
- System.out.println(North.toString());
- System.out.println(West.toString());
- }
-
- public static void streamWallsOut(String name, LabyModel provider, OutputStream stream) throws IOException
- {
- int width = provider.getWidth();
- int height = provider.getHeight();
- int xl = 10;
- int yl = 10;
- int zl = 10;
-
- // WARNING DOWN - UP reversed ( in 2D Y is oriented to lower, in 3D it
- // is to upper ).
- stream.write(("solid " + name + "\n").getBytes());
- for (int x = 0; x < width; x++)
- {
- short walls = provider.getWalls(x, 0);
- if ((walls & Brick.UP) != 0)
- {
- stream.write(new Wall3d(South, x * xl, 0, 0).toString().getBytes());
- }
- if ((walls & Brick.LEFT) != 0)
- {
- stream.write(new Wall3d(West, x * xl, 0, 0).toString().getBytes());
- }
- }
-
- for (int y = 0; y < height; y++)
- {
- short walls = provider.getWalls(0, y);
- if ((walls & Brick.LEFT) != 0)
- {
- stream.write(new Wall3d(West, 0, y * yl, 0).toString().getBytes());
- }
- for (int x = 0; x < width; x++)
- {
- // south and east
- walls = provider.getWalls(x, y);
- if ((walls & Brick.DOWN) != 0)
- {
- stream.write(new Wall3d(North, x * xl, y * yl, 0).toString().getBytes());
- }
- if ((walls & Brick.RIGHT) != 0)
- {
- stream.write(new Wall3d(East, x * xl, y * yl, 0).toString().getBytes());
- }
- short path = provider.getPath(x,y);
- if ( ( path & LabyModel.SOLVED ) == LabyModel.SOLVED )
- // if ( (walls & ( Brick.GOAL | Brick.ENTRY ) ) == 0 )
- {
- // if ( ( (x+y) % 2) == 0 )
-
- stream.write(new Wall3d(LowGround, x * xl, y * yl, 0).toString().getBytes());
- }
- else
- {
- stream.write(new Wall3d(HighGround, x * xl, y * yl, 0).toString().getBytes());
- }
- }
- }
-
- stream.write("endsolid wall\n\n".getBytes());
- }
-
- public static void main(String args[])
- {
-
- Scanner console = new Scanner(System.in);
- int xl = console.nextInt();
- int yl = console.nextInt();
- int zl = console.nextInt();
-
- int dx = console.nextInt();
- int dy = console.nextInt();
- int dz = console.nextInt();
-
- String s = "solid wall\n";
-
- Wall3d instance = new Wall3d(xl, yl, zl, dx, dy, dz);
-
- prepare();
-
- s += "endsolid wall\n\n";
- System.out.println(s);
- }
}
diff --git a/java/org/artisanlogiciel/games/stl/Wall3dStream.java b/java/org/artisanlogiciel/games/stl/Wall3dStream.java
new file mode 100644
index 0000000..f2ed4d6
--- /dev/null
+++ b/java/org/artisanlogiciel/games/stl/Wall3dStream.java
@@ -0,0 +1,93 @@
+package org.artisanlogiciel.games.stl;
+
+import org.artisanlogiciel.games.Brick;
+import org.artisanlogiciel.games.LabyModel;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class Wall3dStream
+{
+
+ String name;
+ LabyModel provider;
+ OutputStream stream;
+
+ Maze3dParams params;
+
+ /**
+ *
+ * @param name
+ * @param provider
+ * @param stream
+ * @param params
+ */
+ public Wall3dStream(String name, LabyModel provider, OutputStream stream, Maze3dParams params)
+ {
+ this.name = name;
+ this.provider = provider;
+ this.stream = stream;
+ this.params = params;
+ }
+
+ private void writeWall3D(Wall3d wall3d)
+ throws IOException
+ {
+ stream.write(wall3d.toString().getBytes());
+ }
+
+ public void stream() throws IOException {
+ int width = provider.getWidth();
+ int height = provider.getHeight();
+
+ int xl = params.getXl();
+ int yl = params.getYl();
+ int zl = params.getZl();
+ boolean reverse = params.isReverse();
+
+ // WARNING DOWN - UP reversed ( in 2D Y is oriented to lower, in 3D it
+ // is to upper ).
+ stream.write(("solid " + name + "\n").getBytes());
+ for (int x = 0; x < width; x++) {
+ short walls = provider.getWalls(x, 0);
+ if ((walls & Brick.UP) != 0) {
+ writeWall3D(new Wall3d(params.getSouth(), x * xl, 0, 0));
+ }
+ if ((walls & Brick.LEFT) != 0) {
+ writeWall3D(new Wall3d(params.getWest(), x * xl, 0, 0));
+ }
+ }
+
+ for (int y = 0; y < height; y++) {
+ short walls = provider.getWalls(0, y);
+ if ((walls & Brick.LEFT) != 0) {
+ writeWall3D(new Wall3d(params.getWest(), 0, y * yl, 0));
+ }
+ for (int x = 0; x < width; x++) {
+ // south and east
+ walls = provider.getWalls(x, y);
+ if ((walls & Brick.DOWN) != 0) {
+ writeWall3D(new Wall3d(params.getNorth(), x * xl, y * yl, 0));
+ }
+ if ((walls & Brick.RIGHT) != 0) {
+ writeWall3D(new Wall3d(params.getEast(), x * xl, y * yl, 0));
+ }
+ short path = provider.getPath(x, y);
+
+ // where resolved path is leaked to stl model.
+ Wall3d ground = reverse ? params.getLowGround() : params.getHighGround();
+ if ((path & LabyModel.SOLVED) == LabyModel.SOLVED)
+ // if ( (walls & ( Brick.GOAL | Brick.ENTRY ) ) == 0 )
+ {
+ // if ( ( (x+y) % 2) == 0 )
+ ground = reverse ? params.getHighGround() : params.getLowGround();
+ }
+ writeWall3D(new Wall3d(ground, x * xl, y * yl, 0));
+ }
+ }
+
+ stream.write("endsolid wall\n\n".getBytes());
+
+ stream.flush();
+ }
+}
diff --git a/lang/LabelsBundle.properties b/lang/LabelsBundle.properties
index c1691a5..de03b04 100644
--- a/lang/LabelsBundle.properties
+++ b/lang/LabelsBundle.properties
@@ -9,4 +9,6 @@ resolve = Resolve
create = Create
save = Save
quit = Quit
-title = A Maz ing
\ No newline at end of file
+title = A Maz ing
+seed = seed
+load = Load
\ No newline at end of file
diff --git a/lang/LabelsBundle_fr.properties b/lang/LabelsBundle_fr.properties
index a85b857..cd279bf 100644
--- a/lang/LabelsBundle_fr.properties
+++ b/lang/LabelsBundle_fr.properties
@@ -9,4 +9,6 @@ resolve = Résoudre
create = Créer
save = Sauver
quit = Quitter
-title = La Bireinte
\ No newline at end of file
+title = La Bireinte
+seed = graine
+load = Charger
\ No newline at end of file
diff --git a/mybuild.xml b/mybuild.xml
index 973e799..d99e9ad 100644
--- a/mybuild.xml
+++ b/mybuild.xml
@@ -10,10 +10,10 @@
-
+
-
-
+
+
@@ -26,6 +26,7 @@
+
@@ -37,8 +38,8 @@
-
-
+
+
@@ -50,5 +51,4 @@
-
diff --git a/project_params b/project_params
index 182ff1a..8041926 100644
--- a/project_params
+++ b/project_params
@@ -2,6 +2,6 @@ project_name=artloglaby
project_default=dist
project_basedir=$(pwd)
project_mainpackage=org.artisanlogiciel.games
-project_mainclass=$project_mainpackage.Display
-project_version=1.0
+project_mainclass=$project_mainpackage.maze.gui.Display
+project_version=1.1
default_args='lab/lab30x30.raw'
diff --git a/renamelabindir.sh b/renamelabindir.sh
new file mode 100755
index 0000000..5e8bc1d
--- /dev/null
+++ b/renamelabindir.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+labdir=$1
+newprefix=$2
+
+if [[ -z $labdir ]]
+then
+ echo "[ERROR] expect a lab directory"
+ echo "will rename all labxxx.* within this directory to directory name labdirxxx.*"
+ exit 1
+fi
+
+if [[ -z $newprefix ]]
+then
+ newprefix=$labdir
+fi
+
+{
+ echo "[INFO] changing lab prefix to $newprefix"
+
+ declare -i index=1
+
+ pushd $labdir
+ for f in $(find . -regextype egrep -regex "./lab[0-9]+x[0-9]+\..*")
+ do
+ if [[ $f =~ ./lab([0-9]+)x([0-9]+)\.(.+) ]]
+ then
+ width=${BASH_REMATCH[1]}
+ height=${BASH_REMATCH[2]}
+ extension=${BASH_REMATCH[3]}
+ newname="${newprefix}_${index}_${width}x${height}.$extension"
+ if [[ ! -e ./$newname ]]
+ then
+ mv $f ./$newname
+ else
+ echo "[ERROR] skip $f -> ./$newname since new name already used" >&2
+ fi
+ fi
+ index=index+1
+ done
+ popd
+}
diff --git a/scripts/laby.sh b/scripts/laby.sh
new file mode 100755
index 0000000..9255fab
--- /dev/null
+++ b/scripts/laby.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+findmainjar()
+{
+ for MJ in $(find . -name "*.jar")
+ do
+ echo "$MJ"
+ if [[ $MJ =~ artloglaby-(.*)\.jar ]]
+ then
+ VERSION=${BASH_REMATCH[1]}
+ echo "found $MJ version $VERSION"
+ MAINJAR=$MJ
+ fi
+ done
+
+}
+
+echo "Ce script a été conçu pour une distribution linux"
+echo "This script was created for linux"
+
+findmainjar
+
+if [[ -z $MAINJAR ]]
+then
+ echo "[ERREUR] aucun jar artloglaby-xxx.jar dans ce répertoire"
+ exit 1
+fi
+
+if which java
+then
+ java -jar $MAINJAR
+else
+ echo "Aucun java/jre de trouvé"
+ echo
+ echo "Pour ubuntu :"
+ echo "sudo apt install openjdk-8-jre"
+fi
diff --git a/specificdoit.sh b/specificdoit.sh
index 3fca2ef..6966d04 100644
--- a/specificdoit.sh
+++ b/specificdoit.sh
@@ -1,5 +1,19 @@
#!/bin/bash
+function findmainjar()
+{
+ for MJ in $(find . -name "*.jar")
+ do
+ echo "$MJ"
+ if [[ $MJ =~ (artloglaby-.*\.jar) ]]
+ then
+ MAINJAR=${BASH_REMATCH[1]}
+ echo "found $MJ jar $MAINJAR"
+ fi
+ done
+
+}
+
specific_run()
{
local action=$1
@@ -33,9 +47,25 @@ create_zip_package()
mkdir $dest
# will be used at run time to save mazes
mkdir $dest/lab
+ mkdir $dest/libs
cp scripts/laby.sh $dest
+
+ MAINJAR=""
+ pushd dist/lib
+ findmainjar
+ popd
+
+ if [[ -n $MAINJAR ]]
+ then
+ printf '%b\n' "java -jar $MAINJAR"
+ printf '%b\r\n' "java -jar $MAINJAR" >$dest/laby.bat
+ else
+ echo "[ERROR] can't find main jar"
+ fi
+
+
cp LISEZMOI $dest
- cp libs/* $dest
+ cp libs/* $dest/libs/
cp dist/lib/* $dest
zip -r $zip_package $dest
diff --git a/toolbox.param b/toolbox.param
new file mode 100644
index 0000000..5b6f920
--- /dev/null
+++ b/toolbox.param
@@ -0,0 +1 @@
+ARTLOG_TOOLBOX=../artlog_toolbox