diff --git a/MavenChess/MavenChess/src/main/java/controller/Game.java b/MavenChess/MavenChess/src/main/java/controller/Game.java
new file mode 100644
index 0000000000000000000000000000000000000000..f80862e912f52718317d0359daf9a7d09de74486
--- /dev/null
+++ b/MavenChess/MavenChess/src/main/java/controller/Game.java
@@ -0,0 +1,251 @@
+package controller;
+
+import model.*;
+import view.*;
+
+import java.util.ArrayList;
+
+public class Game {
+    private int status;
+    public static final int WHITE_TURN = 1, BLACK_TURN = 2, GAME_OVER = 3;
+
+    public Game() {
+        status = WHITE_TURN;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    public boolean isWhiteTurn() {
+        return status == WHITE_TURN;
+    }
+
+    public boolean isBlackTurn() {
+        return status == BLACK_TURN;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public void setVariant(boolean isVariant, Custom3dModel model, Board board, BoardView boardView) {
+        Position.setVariant(isVariant);
+        board.setVariant(isVariant);
+        boardView.refresh(board, model);
+    }
+
+    public void clickPiece(PieceView clickedPiece, Board board, BoardView boardView, CustomMaterial material, Custom3dModel model, Log log) {
+
+        // graveyard pieces should not do anything
+        if(clickedPiece.getPosition().getX() < 0) {
+            return;
+        }
+        // if piece is colored (aka targeted), we consider it an action to apply (tile click)
+        if(clickedPiece.isTargeted()) {
+            TileView tile = boardView.getTile(clickedPiece.getPosition().getID());
+            clickTile(tile, board, boardView, material, model, log);
+            return;
+        }
+        if(clickedPiece.isWhite() && isWhiteTurn() || clickedPiece.isBlack() && isBlackTurn()) {
+            // clicking a piece will ask her available moves
+            Position position = clickedPiece.getPosition();
+            board.setSelected(position);
+            boardView.resetColor(material);
+            boardView.setColor(material, position, CustomMaterial.SELECTED_TILE);
+            ArrayList<Position> moves = board.getPiece(position).getAvailableMoves(board);
+
+            // test if kamikaze, and shows the explosion range
+            if (board.isKamikaze(position)) {
+                ArrayList<Position> explosions = ((Kamikaze) board.getPiece(position)).getExplosion();
+                for (Position explosion : explosions) {
+                    boardView.setColor(material, explosion, CustomMaterial.EXPLOSION_TILE);
+                }
+                clickedPiece.setTargeted(material, CustomMaterial.EXPLOSION_TILE);
+            }
+
+            // shows all available moves on the tiles, with colors, each tile-color having a meaning
+            for (Position move : moves) {
+
+                if (board.isFree(move)) {
+                    boardView.setColor(material, move, CustomMaterial.MOVABLE_TILE);
+                    // test for "en passant"
+                    if (board.isPawn(position) || board.isNwap(position)) {
+                        Position enemy = new Position(move.getX(), position.getY());
+                        boolean isEnPassant = false;
+                        if (board.isEnemy(enemy, position)) {
+                            if (board.isPawn(enemy)) {
+                                if (((Pawn) board.getPiece(enemy)).isEnPassant()) {
+                                    isEnPassant = true;
+                                }
+                            }
+                            if (board.isNwap(enemy)) {
+                                if (((Nwap) board.getPiece(enemy)).isEnPassant()) {
+                                    isEnPassant = true;
+                                }
+                            }
+                        }
+                        if (isEnPassant) {
+                            boardView.setColor(material, move, CustomMaterial.SPECIAL_TILE);
+                            boardView.setColor(material, enemy, CustomMaterial.SPECIAL_TILE);
+                            boardView.getPiece(enemy.getID()).setTargeted(material, CustomMaterial.ATTACK_TILE);
+                        }
+                    }
+                } else if (board.isEnemy(move, position)) {
+                    boardView.setColor(material, move, CustomMaterial.ATTACK_TILE);
+                    boardView.getPiece(move.getID()).setTargeted(material, CustomMaterial.ATTACK_TILE);
+                } else {
+                    boardView.setColor(material, move, CustomMaterial.SPECIAL_TILE); // any special move
+                    boardView.getPiece(move.getID()).setTargeted(material, CustomMaterial.SPECIAL_TILE);
+                }
+                // PROMOTION (attacking or not)
+                if ((board.isPawn(position) || board.isNwap(position)) && (move.getY() == 8 || move.getY() == 1)) {
+                    boardView.setColor(material, move, CustomMaterial.SPECIAL_TILE);
+                }
+            }
+        }
+    }
+
+    public void clickTile(TileView clickedTile, Board board, BoardView boardView, CustomMaterial material, Custom3dModel model, Log log) {
+
+        boolean moved = false; // to tell if an action/movement was used or not
+
+        // --- Analyses the clicked tile type, and executes related actions ---
+        int state = clickedTile.getState();
+        Position selected = board.getSelected();
+        Position arrival = clickedTile.getPosition();
+        if(state != TileView.NORMAL && state != TileView.SELECTED) {
+            // --- Resets enPassant ---
+            for(int j = 1 ; j <= 8 ; j++) {
+                for(int i = 1 ; i <= 8 ; i++) {
+                    Position p = new Position(i, j);
+                    if (board.isPawn(p)) {
+                        ((Pawn) board.getPiece(p)).setEnPassant(false);
+                    }
+                    if (board.isNwap(p)) {
+                        ((Nwap) board.getPiece(p)).setEnPassant(false);
+                    }
+                }
+            }
+            // --- ALL SPECIAL MOVES ---
+            if(state == TileView.SPECIAL) {
+                if(board.isPawn(selected) || board.isNwap(selected)) {
+                    // --- PROMOTION ---
+                    if(arrival.getY() == 8 || arrival.getY() == 1) {
+                        // --- ATTACK (while doing promotion) ---
+                        if (!board.isFree(arrival)) {
+                            boardView.getPiece(arrival.getID()).resetTargeted(material); // reset color
+                            boardView.killPiece(arrival); // place piece on graveyard (visual)
+                        }
+                        // Promotion to Queen (by default, Queen for now)
+                        board.mutationOfSelectedPiece(Board.QUEEN); // (on model)
+                        boardView.mutationPiece(model, selected, Custom3dModel.QUEEN); // (on view)
+                        // --- MOVE (while doing promotion)  ---
+                        board.movePiece(selected, arrival); // move piece (on model)
+                        boardView.movePiece(selected, arrival); // move piece (on 3d view)
+                        moved = true;
+                    }
+                    // --- PRISE EN PASSANT ---
+                    else {
+                        // PRE : if it's not a promotion, then it's "prise en passant", because of pawn rules
+                        // we don't need to test y-position
+                        Position enemy = new Position(arrival.getX(), selected.getY());
+                        boardView.getPiece(enemy.getID()).resetTargeted(material); // reset color
+                        boardView.killPiece(enemy); // place piece on graveyard (visual)
+                        board.killPiece(enemy.getID()); // because we don't move "on it", we need to kill it manually (model)
+                        Position enPassantArrival = new Position(arrival.getX(), selected.getY()+1);
+                        if(board.getSelectedPiece().getColor() == Piece.BLACK) {
+                            enPassantArrival.setY(selected.getY()-1);
+                        }
+                        board.movePiece(selected, enPassantArrival); // move piece (on model)
+                        boardView.movePiece(selected, enPassantArrival); // move piece (on 3d view)
+                        moved = true;
+                    }
+                }
+                // --- CASTLING (from king) ---
+                if(board.isKing(selected)) {
+                    // PRE (1) : the arrival piece CAN ONLY BE ROOK, because of king rules
+                    // PRE (2) : we don't need to test if rook !hasBeenMoved(), because of king rules
+                    // PRE (3) : we don't need to test if king !hasBeenMoved(), because of king rules
+                    int x = Board.D; // king x arrival, for west-rook
+                    if(arrival.getX() == Board.H) {
+                        x = Board.F; // king x arrival, for east-rook
+                    }
+                    Position kingArrival = new Position(x, selected.getY());
+                    board.movePiece(selected, kingArrival); // move king (on model)
+                    boardView.movePiece(selected, kingArrival); // move king (on 3d view)
+                    board.movePiece(arrival, selected); // move rook (on model)
+                    boardView.movePiece(arrival, selected); // move rook (on 3d view)
+                    moved = true;
+                }
+                // --- CASTLING (from rook) ---
+                else if(board.isRook(selected)) {
+                    // PRE (1) : the arrival piece CAN ONLY BE KING, because of rook rules
+                    // PRE (2) : we don't need to test if king !hasBeenMoved(), because of rook rules
+                    // PRE (3) : we don't need to test if rook !hasBeenMoved(), because of rook rules
+                    int x = Board.D; // king x arrival, for west-rook
+                    if (selected.getX() == Board.H) {
+                        x = Board.F; // king x arrival, for east-rook
+                    }
+                    Position kingArrival = new Position(x, arrival.getY());
+                    board.movePiece(arrival, kingArrival); // move king (on model)
+                    boardView.movePiece(arrival, kingArrival); // move king (on 3d view)
+                    board.movePiece(selected, arrival); // move rook (on model)
+                    boardView.movePiece(selected, arrival); // move rook (on 3d view)
+                    moved = true;
+                }
+            }
+            // --- EXPLOSION MOVES ---
+            else if (state == TileView.EXPLOSION) {
+                for(int n = 0 ; n < 64 ; n++) {
+                    if(boardView.getTile(n).getState() == TileView.EXPLOSION) {
+                        if(boardView.getPiece(n) != null) {
+                            boardView.getPiece(n).resetTargeted(material); // reset color
+                            boardView.killPiece(boardView.getPiece(n).getPosition()); // place piece on graveyard (visual)
+                            board.killPiece(n);
+                        }
+                    }
+                }
+                moved = true;
+            }
+            // --- STANDARD MOVES ---
+            else {
+                // --- ATTACK ---
+                if(state == TileView.ATTACK) {
+                    boardView.getPiece(arrival.getID()).resetTargeted(material); // reset color
+                    boardView.killPiece(arrival); // place piece on graveyard (visual)
+                    // --- MAGICIAN CHANGE ---
+                    if(board.isMagician(selected)) {
+                        Magician magician = (Magician) board.getPiece(selected);
+                        Piece enemy = board.getPiece(arrival);
+                        magician.steal(enemy); // muahaha
+                    }
+                }
+                // --- EN PASSANT activation ---
+                if(Math.abs(selected.getY() - arrival.getY()) == 2) {
+                    if(board.isPawn(selected)) {
+                        ((Pawn) board.getPiece(selected)).setEnPassant(true);
+                    }
+                    if(board.isNwap(selected)) {
+                        ((Nwap) board.getPiece(selected)).setEnPassant(true);
+                    }
+                }
+                // --- MOVE ---
+                board.movePiece(selected, arrival); // move piece (on model)
+                boardView.movePiece(selected, arrival); // move piece (on 3d view)
+                moved = true;
+            }
+
+        }
+        // --- Resets board coloring, doing any action or not ---
+        boardView.resetColor(material);
+        // updates game status
+        if(moved) {
+            if(isWhiteTurn())
+                setStatus(Game.BLACK_TURN);
+            else if(isBlackTurn())
+                setStatus(Game.WHITE_TURN);
+            log.save(board, boardView);
+        }
+    }
+}
diff --git a/MavenChess/MavenChess/src/main/java/controller/Log.java b/MavenChess/MavenChess/src/main/java/controller/Log.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0fb207488667c921142c96e92f2f010174a20d5
--- /dev/null
+++ b/MavenChess/MavenChess/src/main/java/controller/Log.java
@@ -0,0 +1,20 @@
+package controller;
+
+import model.Board;
+import model.Piece;
+import view.BoardView;
+
+import java.util.ArrayList;
+
+public class Log {
+	// contains dynamic array of board, to be able to ctrl-Z equivalent
+    ArrayList<Piece[]> logPieces;
+
+    public Log() {
+        logPieces = new ArrayList<>();
+    }
+
+    public void save(Board board, BoardView boardView) {
+        logPieces.add(board.getAllPieces());
+    }
+}
diff --git a/MavenChess/MavenChess/src/main/java/controller/Main.java b/MavenChess/MavenChess/src/main/java/controller/Main.java
index 0bc61bb550ea68f6d2c3ee076f996840e60de5d7..a69f812c9a467d71e0b5aa8014e51193acf74f6c 100644
--- a/MavenChess/MavenChess/src/main/java/controller/Main.java
+++ b/MavenChess/MavenChess/src/main/java/controller/Main.java
@@ -1,9 +1,11 @@
 package controller;
 
 import javafx.application.Application;
+import javafx.beans.value.ChangeListener;
 import javafx.scene.*;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.input.ScrollEvent;
+import javafx.scene.layout.AnchorPane;
 import javafx.stage.Stage;
 import model.*;
 import view.*;
@@ -13,57 +15,82 @@ import java.util.ArrayList;
 public class Main extends Application {
 
 	private CustomCamera camera;
-	private Group group;
+	private Group group3d;
+	private AnchorPane group2d;
 	private CustomScene scene;
 	private CustomMaterial material;
 	private CustomLight light;
 	private Custom3dModel model;
 	private Desk desk;
+	private Room room;
 
 	private Board board;
 	private BoardView boardView;
 
+	private HUD hud;
+
+	private Game game;
+
+	private Log log;
+
+
 	@Override
 	public void start(Stage stage) {
 
 		// init --------------------------------------------------------------
 
 		// init - some window settings
-		stage.setMaximized(true); // maximized window
 		stage.setTitle("Chess3D - Tuna Acikbas & Olivier Pillods"); // title
 
 		// init - camera
-		camera = new CustomCamera(1, 1000, 70); // create a camera and some settings
+		camera = new CustomCamera(2, 1500, 70); // create a camera and some settings
+		camera.startAnimation(); // camera starts free rotating
 
 		// init - scene, main container
-		group = new Group(); // will contain all the elements "to show" on scene
-		scene = new CustomScene(group, camera.getCamera(), SceneAntialiasing.BALANCED);
+		group3d = new Group(); // will contain all the 3d elements
+		group2d = new AnchorPane(); // it's the root, will contain 2d elements and the 3d scene as a sub-scene
+		scene = new CustomScene(group2d, group3d, camera.getCamera(), SceneAntialiasing.BALANCED);
 
 		// init - materials and shaders
 		material = new CustomMaterial(); // prepare all the 3D materials (shaders)
 
 		// init - all lights
 		light = new CustomLight(); // setups different custom lights
-		light.addAllToScene(group); // adds all the lights to scene
+		light.addAllToScene(group3d); // adds all the lights to scene
 
 		// init - import all 3D models from .obj files
 		model = new Custom3dModel();
 
 		// init - creates a wooden desk
 		desk = new Desk(material);
-		desk.addAllToScene(group); // adds the desk to scene
+		desk.addAllToScene(group3d); // adds the desk to scene
+
+		// init - creates a room
+		room = new Room(material);
+		room.addAllToScene(group3d); // adds the desk to scene
 
 		// init - creates a (model) list of all pieces
 		board = new Board();
 
 		// init - creates a (visual) chessboard of 8x8, and all (visual) 3d pieces
 		boardView = new BoardView(model, material, board);
-		boardView.addAllToScene(group); // adds the board and the pieces to scene
+		boardView.addAllToScene(group3d); // adds the board and the pieces to scene
+
+		// init - 2d interface
+		hud = new HUD();
+		hud.resize(stage.getWidth(), stage.getHeight());
+		hud.addAllToScene(group2d);
+
+		// init - game controller
+		game = new Game();
+
+		// init - log manager
+		log = new Log();
 
 		// event --------------------------------------------------------------
 
 		// event - camera rotation (mouse dragging)
-		camera.initMouseControl(scene.get()); // allow user to move camera with mouse, with some constraints
+		camera.initMouseControl(scene.get3d()); // allow user to move camera with mouse, with some constraints
 
 		// event - camera zoom (mouse scroll)
 		stage.addEventHandler(ScrollEvent.SCROLL, event -> camera.scrollCamera(event.getDeltaY()));
@@ -72,230 +99,45 @@ public class Main extends Application {
 		for(int n = 0 ; n < 64 ; n++) {
 			PieceView piece = boardView.getPiece(n);
 			if(piece != null) {
-				piece.getObj().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> clickPiece(piece));
+				piece.getObj().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> game.clickPiece(piece, board, boardView, material, model, log));
 			}
 		}
 
 		// event - click on (visual) "colored tiles" to move the selected piece there
 		for(int n = 0 ; n < 64 ; n++) {
 			TileView tile = boardView.getTile(n);
-			tile.getObj().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> clickTile(tile));
+			tile.getObj().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> game.clickTile(tile, board, boardView, material, model, log));
 		}
 
+		// event - window resize
+		ChangeListener<Number> resizeWindow = (observable, oldValue, newValue) -> {
+			scene.get3d().setHeight(stage.getHeight());
+			scene.get3d().setWidth(stage.getWidth());
+			hud.resize(stage.getWidth(), stage.getHeight());
+		};
+		stage.widthProperty().addListener(resizeWindow);
+		stage.heightProperty().addListener(resizeWindow);
+
+		// event - click on menu : Standard / Variant
+		hud.getStandard().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
+			hud.removeMenu(group2d);
+			camera.stopAnimation();
+		});
+		hud.getVariant().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
+			hud.removeMenu(group2d);
+			camera.stopAnimation();
+			game.setVariant(true, model, board, boardView);
+		});
+
 		// start --------------------------------------------------------------
 
 		// start - links scene to application and shows application
-		stage.setScene(scene.get());
+		stage.setScene(scene.get2d());
 		stage.show();
+		stage.setMaximized(true); // maximized window
 	}
 
 	public static void main(String[] args) {
 		launch();
 	}
-
-	public void clickPiece(PieceView clickedPiece) {
-
-		// graveyard pieces should not do anything
-		if(clickedPiece.getPosition().getX() < 0) {
-			return;
-		}
-		// if piece is colored (aka targeted), we consider it an action to apply (tile click)
-		if(clickedPiece.isTargeted()) {
-			clickTile(boardView.getTile(clickedPiece.getPosition().getID()));
-		} else {
-			// clicking a piece will ask her available moves
-			Position position = clickedPiece.getPosition();
-			board.setSelected(position);
-			boardView.resetColor(material);
-			boardView.setColor(material, position, CustomMaterial.SELECTED_TILE);
-			ArrayList<Position> moves = board.getPiece(position).getAvailableMoves(board);
-
-			// test if kamikaze, and shows the explosion range
-			if(board.isKamikaze(position)) {
-				ArrayList<Position> explosions = ((Kamikaze) board.getPiece(position)).getExplosion();
-				for (Position explosion : explosions) {
-					boardView.setColor(material, explosion, CustomMaterial.EXPLOSION_TILE);
-				}
-				clickedPiece.setTargeted(material, CustomMaterial.EXPLOSION_TILE);
-			}
-
-			// shows all available moves on the tiles, with colors, each tile-color having a meaning
-			for (Position move : moves) {
-
-				if (board.isFree(move)) {
-					boardView.setColor(material, move, CustomMaterial.MOVABLE_TILE);
-					// test for "en passant"
-					if(board.isPawn(position) || board.isNwap(position)) {
-						Position enemy = new Position(move.getX(), position.getY());
-						boolean isEnPassant = false;
-						if(board.isEnemy(enemy, position)) {
-							if (board.isPawn(enemy)) {
-								if (((Pawn) board.getPiece(enemy)).isEnPassant()) {
-									isEnPassant = true;
-								}
-							}
-							if (board.isNwap(enemy)) {
-								if (((Nwap) board.getPiece(enemy)).isEnPassant()) {
-									isEnPassant = true;
-								}
-							}
-						}
-						if(isEnPassant) {
-							boardView.setColor(material, move, CustomMaterial.SPECIAL_TILE);
-							boardView.setColor(material, enemy, CustomMaterial.SPECIAL_TILE);
-							boardView.getPiece(enemy.getID()).setTargeted(material, CustomMaterial.ATTACK_TILE);
-						}
-					}
-				} else if (board.isEnemy(move, position)) {
-					boardView.setColor(material, move, CustomMaterial.ATTACK_TILE);
-					boardView.getPiece(move.getID()).setTargeted(material, CustomMaterial.ATTACK_TILE);
-				} else {
-					boardView.setColor(material, move, CustomMaterial.SPECIAL_TILE); // any special move
-					boardView.getPiece(move.getID()).setTargeted(material, CustomMaterial.SPECIAL_TILE);
-				}
-				// PROMOTION (attacking or not)
-				if ((board.isPawn(position) || board.isNwap(position)) && (move.getY() == 8 || move.getY() == 1)) {
-					boardView.setColor(material, move, CustomMaterial.SPECIAL_TILE);
-				}
-			}
-		}
-	}
-
-	public void clickTile(TileView clickedTile) {
-
-		// --- Analyses the clicked tile type, and executes related actions ---
-		int state = clickedTile.getState();
-		Position selected = board.getSelected();
-		Position arrival = clickedTile.getPosition();
-		if(state != TileView.NORMAL && state != TileView.SELECTED) {
-			// --- Resets enPassant ---
-			for(int j = 1 ; j <= 8 ; j++) {
-				for(int i = 1 ; i <= 8 ; i++) {
-					Position p = new Position(i, j);
-					if (board.isPawn(p)) {
-						((Pawn) board.getPiece(p)).setEnPassant(false);
-					}
-					if (board.isNwap(p)) {
-						((Nwap) board.getPiece(p)).setEnPassant(false);
-					}
-				}
-			}
-			// --- ALL SPECIAL MOVES ---
-			if(state == TileView.SPECIAL) {
-				if(board.isPawn(selected) || board.isNwap(selected)) {
-					// --- PROMOTION ---
-					if(arrival.getY() == 8 || arrival.getY() == 1) {
-						// --- ATTACK (while doing promotion) ---
-						if (!board.isFree(arrival)) {
-							boardView.getPiece(arrival.getID()).resetTargeted(material); // reset color
-							boardView.killPiece(arrival); // place piece on graveyard (visual)
-						}
-						// Promotion to Queen (by default, Queen for now)
-						board.mutationOfSelectedPiece(Board.QUEEN); // (on model)
-						boardView.mutationPiece(model, selected, Custom3dModel.QUEEN); // (on view)
-						// --- MOVE (while doing promotion)  ---
-						board.movePiece(selected, arrival); // move piece (on model)
-						boardView.movePiece(selected, arrival); // move piece (on 3d view)
-					}
-					// --- PRISE EN PASSANT ---
-					else {
-						// PRE : if it's not a promotion, then it's "prise en passant", because of pawn rules
-						// we don't need to test y-position
-						Position enemy = new Position(arrival.getX(), selected.getY());
-						boardView.getPiece(enemy.getID()).resetTargeted(material); // reset color
-						boardView.killPiece(enemy); // place piece on graveyard (visual)
-						board.killPiece(enemy.getID()); // because we don't move "on it", we need to kill it manually (model)
-						Position enPassantArrival = new Position(arrival.getX(), selected.getY()+1);
-						if(board.getSelectedPiece().getColor() == Piece.BLACK) {
-							enPassantArrival.setY(selected.getY()-1);
-						}
-						board.movePiece(selected, enPassantArrival); // move piece (on model)
-						boardView.movePiece(selected, enPassantArrival); // move piece (on 3d view)
-					}
-				}
-				// --- CASTLING (from king) ---
-				if(board.isKing(selected)) {
-					// PRE (1) : the arrival piece CAN ONLY BE ROOK, because of king rules
-					// PRE (2) : we don't need to test if rook !hasBeenMoved(), because of king rules
-					// PRE (3) : we don't need to test if king !hasBeenMoved(), because of king rules
-					int x = Board.D; // king x arrival, for west-rook
-					if(arrival.getX() == Board.H) {
-						x = Board.F; // king x arrival, for east-rook
-					}
-					Position kingArrival = new Position(x, selected.getY());
-					board.movePiece(selected, kingArrival); // move king (on model)
-					boardView.movePiece(selected, kingArrival); // move king (on 3d view)
-					board.movePiece(arrival, selected); // move rook (on model)
-					boardView.movePiece(arrival, selected); // move rook (on 3d view)
-				}
-				// --- CASTLING (from rook) ---
-				else if(board.isRook(selected)) {
-					// PRE (1) : the arrival piece CAN ONLY BE KING, because of rook rules
-					// PRE (2) : we don't need to test if king !hasBeenMoved(), because of rook rules
-					// PRE (3) : we don't need to test if rook !hasBeenMoved(), because of rook rules
-					int x = Board.D; // king x arrival, for west-rook
-					if (selected.getX() == Board.H) {
-						x = Board.F; // king x arrival, for east-rook
-					}
-					Position kingArrival = new Position(x, arrival.getY());
-					board.movePiece(arrival, kingArrival); // move king (on model)
-					boardView.movePiece(arrival, kingArrival); // move king (on 3d view)
-					board.movePiece(selected, arrival); // move rook (on model)
-					boardView.movePiece(selected, arrival); // move rook (on 3d view)
-				}
-			}
-			// --- EXPLOSION MOVES ---
-			else if (state == TileView.EXPLOSION) {
-				for(int n = 0 ; n < 64 ; n++) {
-					if(boardView.getTile(n).getState() == TileView.EXPLOSION) {
-						if(boardView.getPiece(n) != null) {
-							boardView.getPiece(n).resetTargeted(material); // reset color
-							boardView.killPiece(boardView.getPiece(n).getPosition()); // place piece on graveyard (visual)
-							board.killPiece(n);
-						}
-					}
-				}
-			}
-			// --- STANDARD MOVES ---
-			else {
-				// --- ATTACK ---
-				if(state == TileView.ATTACK) {
-					boardView.getPiece(arrival.getID()).resetTargeted(material); // reset color
-					boardView.killPiece(arrival); // place piece on graveyard (visual)
-					// --- MAGICIAN CHANGE ---
-					if(board.isMagician(selected)) {
-						// we can't do switch statement on ".getClass()"
-						Piece enemy = board.getPiece(arrival);
-						Magician magician = (Magician) board.getPiece(selected);
-						int color = magician.getColor();
-						if (enemy.getClass() == Pawn.class) { magician.setCopiedPiece(new Pawn(selected, color)); }
-						if (enemy.getClass() == Rook.class) { magician.setCopiedPiece(new Rook(selected, color)); }
-						if (enemy.getClass() == Knight.class) { magician.setCopiedPiece(new Knight(selected, color)); }
-						if (enemy.getClass() == Bishop.class) { magician.setCopiedPiece(new Bishop(selected, color)); }
-						if (enemy.getClass() == Queen.class) { magician.setCopiedPiece(new Queen(selected, color)); }
-						if (enemy.getClass() == King.class) { magician.setCopiedPiece(new King(selected, color)); }
-						if (enemy.getClass() == Nwap.class) { magician.setCopiedPiece(new Nwap(selected, color)); }
-						if (enemy.getClass() == Magician.class) { magician.setCopiedPiece(((Magician) enemy).getCopiedPiece()); } // lol, stealing the stealer
-						if (enemy.getClass() == Giant.class) { magician.setCopiedPiece(new Giant(selected, color)); }
-						if (enemy.getClass() == Kamikaze.class) { magician.setCopiedPiece(new Kamikaze(selected, color)); }
-					}
-				}
-				// --- EN PASSANT activation ---
-				if(Math.abs(selected.getY() - arrival.getY()) == 2) {
-					if(board.isPawn(selected)) {
-						((Pawn) board.getPiece(selected)).setEnPassant(true);
-					}
-					if(board.isNwap(selected)) {
-						((Nwap) board.getPiece(selected)).setEnPassant(true);
-					}
-				}
-				// --- MOVE ---
-				board.movePiece(selected, arrival); // move piece (on model)
-				boardView.movePiece(selected, arrival); // move piece (on 3d view)
-			}
-
-		}
-		// --- Resets board coloring, doing any action or not ---
-		boardView.resetColor(material);
-	}
 }
\ No newline at end of file
diff --git a/MavenChess/MavenChess/src/main/java/model/Board.java b/MavenChess/MavenChess/src/main/java/model/Board.java
index 1ba3182cfb691e5c7b3480ab6f3c34f673db4b11..93ae81231cf533207dce597fbbc16fc1165a3b2f 100644
--- a/MavenChess/MavenChess/src/main/java/model/Board.java
+++ b/MavenChess/MavenChess/src/main/java/model/Board.java
@@ -4,11 +4,13 @@ public class Board {
 
 	public static final int PAWN = 0, ROOK = 1, KNIGHT = 2, BISHOP = 3, QUEEN = 4, KING = 5, NWAP = 6, MAGICIAN = 7, GIANT = 8, KAMIKAZE =9;
 	public static final int A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, G = 7, H = 8;
+	private boolean isFeyPieces;
 
 	private final Piece[] pieces;
 	private Position selected;
 
 	public Board() {
+		isFeyPieces = false;
 		selected = null;
 		// initialisation of the list of pieces
 		pieces = new Piece[64];
@@ -20,18 +22,18 @@ public class Board {
 			// placement of pawns
 			if(color == Piece.WHITE) { y = 2; } else { y = 7; }
 			for(int x = A ; x <= H ; x++) {
-				createPiece(x, y, color, NWAP); // fills line 2 and line 7 with pawns
+				createPiece(x, y, color, PAWN); // fills line 2 and line 7 with pawns
 			}
 			// placement of rook, knight, bishop, queen, king - line 1 and line 8
 			if(color == Piece.WHITE) { y = 1; } else { y = 8; }
-			createPiece(A, y, color, GIANT);
-			createPiece(B, y, color, KAMIKAZE);
-			createPiece(C, y, color, MAGICIAN);
+			createPiece(A, y, color, ROOK);
+			createPiece(B, y, color, KNIGHT);
+			createPiece(C, y, color, BISHOP);
 			createPiece(D, y, color, QUEEN);
 			createPiece(E, y, color, KING);
-			createPiece(F, y, color, MAGICIAN);
-			createPiece(G, y, color, KAMIKAZE);
-			createPiece(H, y, color, GIANT);
+			createPiece(F, y, color, BISHOP);
+			createPiece(G, y, color, KNIGHT);
+			createPiece(H, y, color, ROOK);
 		}
 	}
 
@@ -47,6 +49,10 @@ public class Board {
 		return pieces[id];
 	}
 
+	public Piece[] getAllPieces() {
+		return pieces;
+	}
+
 	public void createPiece(int x, int y, int color, int type) {
 		Position p = new Position(x, y);
 		switch(type) {
@@ -113,6 +119,12 @@ public class Board {
 				&& getPiece(p).getClass() == King.class);
 	}
 
+	public boolean isGiant(Position p) {
+		return (p.isCorrect()
+				&& !isFree(p)
+				&& getPiece(p).getClass() == Giant.class);
+	}
+
 	public boolean isRook(Position p) {
 		return (p.isCorrect()
 				&& !isFree(p)
@@ -137,9 +149,51 @@ public class Board {
 				&& getPiece(p).getClass() == Kamikaze.class);
 	}
 
+	public boolean isKnight(Position p) {
+		return (p.isCorrect()
+				&& !isFree(p)
+				&& getPiece(p).getClass() == Knight.class);
+	}
+
 	public boolean isMagician(Position p) {
 		return (p.isCorrect()
 				&& !isFree(p)
 				&& getPiece(p).getClass() == Magician.class);
 	}
+	public boolean isBishop(Position p) {
+		return (p.isCorrect()
+				&& !isFree(p)
+				&& getPiece(p).getClass() == Bishop.class);
+	}
+
+	public void setVariant(boolean isVariant) {
+		isFeyPieces = isVariant;
+		for(int j = 1 ; j <= 8 ; j++) {
+			for (int i = 1; i <= 8; i++) {
+				Position p = new Position(i, j);
+				if(isFeyPieces) {
+					if (isPawn(p)) {
+						createPiece(i, j, getPiece(p).getColor(), NWAP);
+					} else if (isBishop(p)) {
+						createPiece(i, j, getPiece(p).getColor(), MAGICIAN);
+					} else if (isKnight(p)) {
+						createPiece(i, j, getPiece(p).getColor(), KAMIKAZE);
+					} else if (isRook(p)) {
+						createPiece(i, j, getPiece(p).getColor(), GIANT);
+					}
+				}
+				else {
+					if (isNwap(p)) {
+						createPiece(i, j, getPiece(p).getColor(), PAWN);
+					} else if (isMagician(p)) {
+						createPiece(i, j, getPiece(p).getColor(), BISHOP);
+					} else if (isKamikaze(p)) {
+						createPiece(i, j, getPiece(p).getColor(), KNIGHT);
+					} else if (isGiant(p)) {
+						createPiece(i, j, getPiece(p).getColor(), ROOK);
+					}
+				}
+			}
+		}
+	}
 }
diff --git a/MavenChess/MavenChess/src/main/java/model/Giant.java b/MavenChess/MavenChess/src/main/java/model/Giant.java
index f7f9d899315dbe08cf745ff005b441abbcd68290..d4f7d911a16e0929a32ffc0825420ac979faf50d 100644
--- a/MavenChess/MavenChess/src/main/java/model/Giant.java
+++ b/MavenChess/MavenChess/src/main/java/model/Giant.java
@@ -28,7 +28,7 @@ public class Giant extends Piece{
                 if (b.isEnemy(arrival, p) || b.isFree(arrival)) {
                     moves.add(arrival);
                 }
-                if (!b.isFree(arrival)) {
+                if (!arrival.isCorrect()) {
                     blocked = true;
                 }
                 i++;
diff --git a/MavenChess/MavenChess/src/main/java/model/Log.java b/MavenChess/MavenChess/src/main/java/model/Log.java
deleted file mode 100644
index bfa3ba2247254615b8d85fcc944ad10ca2b4313b..0000000000000000000000000000000000000000
--- a/MavenChess/MavenChess/src/main/java/model/Log.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package model;
-
-public class Log {
-	// contains dynamic array of board, to be able to ctrl-Z equivalent
-}
diff --git a/MavenChess/MavenChess/src/main/java/model/Magician.java b/MavenChess/MavenChess/src/main/java/model/Magician.java
index e43e4c502cdb675d20a30f055879ab2b2c42f340..4e3bc173998e9a69bc7813df8e2b2e94c1b106a5 100644
--- a/MavenChess/MavenChess/src/main/java/model/Magician.java
+++ b/MavenChess/MavenChess/src/main/java/model/Magician.java
@@ -14,11 +14,6 @@ public class Magician extends Piece{
         return copiedPiece.getAvailableMoves(b);
     }
 
-
-    public void setCopiedPiece(Piece copiedPiece) {
-        this.copiedPiece = copiedPiece;
-    }
-
     public Piece getCopiedPiece() {
         return copiedPiece;
     }
@@ -26,4 +21,22 @@ public class Magician extends Piece{
         this.p = p;
         copiedPiece.setPosition(p);
     }
+
+    public void setCopiedPiece(Piece copiedPiece) {
+        this.copiedPiece = copiedPiece;
+    }
+
+    public void steal(Piece enemy) {
+        // we can't do switch statement on ".getClass()"
+        if (enemy.getClass() == Pawn.class) { setCopiedPiece(new Pawn(p, color)); }
+        if (enemy.getClass() == Rook.class) { setCopiedPiece(new Rook(p, color)); }
+        if (enemy.getClass() == Knight.class) { setCopiedPiece(new Knight(p, color)); }
+        if (enemy.getClass() == Bishop.class) { setCopiedPiece(new Bishop(p, color)); }
+        if (enemy.getClass() == Queen.class) { setCopiedPiece(new Queen(p, color)); }
+        if (enemy.getClass() == King.class) { setCopiedPiece(new King(p, color)); }
+        if (enemy.getClass() == Nwap.class) { setCopiedPiece(new Nwap(p, color)); }
+        if (enemy.getClass() == Magician.class) { setCopiedPiece(((Magician) enemy).getCopiedPiece()); } // lol, stealing the stealer
+        if (enemy.getClass() == Giant.class) { setCopiedPiece(new Giant(p, color)); }
+        if (enemy.getClass() == Kamikaze.class) { setCopiedPiece(new Kamikaze(p, color)); }
+    }
 }
diff --git a/MavenChess/MavenChess/src/main/java/model/Piece.java b/MavenChess/MavenChess/src/main/java/model/Piece.java
index 4053281d513f4780e70d2318fc5cbc4ad517c3a8..03c1f3ede165d4309248bcae4262010bfdb4e9cb 100644
--- a/MavenChess/MavenChess/src/main/java/model/Piece.java
+++ b/MavenChess/MavenChess/src/main/java/model/Piece.java
@@ -25,6 +25,14 @@ public abstract class Piece {
 		return color;
 	}
 
+	public boolean isWhite() {
+		return color == WHITE;
+	}
+
+	public boolean isBlack() {
+		return color == BLACK;
+	}
+
 	public Position getPosition() {
 		return p;
 	}
diff --git a/MavenChess/MavenChess/src/main/java/model/Position.java b/MavenChess/MavenChess/src/main/java/model/Position.java
index 2eceaf8d503067c0dcbd9eee21bc718423e01907..5a47dab9dffb7074eb491b8c556363d629ec61ba 100644
--- a/MavenChess/MavenChess/src/main/java/model/Position.java
+++ b/MavenChess/MavenChess/src/main/java/model/Position.java
@@ -7,9 +7,17 @@ public class Position {
 	// PS : graveyards are specified as negative 'x', and we use 'y' to pile dead pieces from 1 to n
 	public static final int WHITE_GRAVEYARD = -1, BLACK_GRAVEYARD = -2;
 
+	private static boolean isSnake_mode = false;
+
 	public Position(int x, int y) {
-		while(x < 1) { x += 8; }
-		while(x > 8) { x -= 8; }
+		if(isSnake_mode) {
+			while (x < 1) {
+				x += 8;
+			}
+			while (x > 8) {
+				x -= 8;
+			}
+		}
 		this.x = x;
 		this.y = y;
 	}
@@ -48,4 +56,8 @@ public class Position {
 	public boolean equals(Position p) {
 		return (x == p.getX() && y == p.getY());
 	}
+
+	public static void setVariant(boolean isVariant) {
+		isSnake_mode = isVariant;
+	}
 }
diff --git a/MavenChess/MavenChess/src/main/java/view/BoardView.java b/MavenChess/MavenChess/src/main/java/view/BoardView.java
index 2608e65dadfb8341897a59b6c31bb3ebf05120fa..ba4d6a675e2a84acdac0de1d1a898904a299efcc 100644
--- a/MavenChess/MavenChess/src/main/java/view/BoardView.java
+++ b/MavenChess/MavenChess/src/main/java/view/BoardView.java
@@ -14,8 +14,12 @@ public class BoardView {
 	private final PieceView[] pieces; // contains all the 3d pieces (visual)
 	private int black_death_count, white_death_count; // graveyard counter
 
+	private final Box[] border; // visual border for the board
+
+
 
 	public BoardView(Custom3dModel model, CustomMaterial material, Board board) {
+
 		// creates the board squares, and position them properly
 		tiles = new TileView[64];
 		for(int j = 1 ; j <= 8 ; j++) {
@@ -30,17 +34,7 @@ public class BoardView {
 			pieces[n] = null;
 			Piece piece = board.getPiece(n);
 			if(piece != null) {
-				int type = Custom3dModel.PAWN; // we can't do switch statement on ".getClass()"
-				if (piece.getClass() == Rook.class) { type = Custom3dModel.ROOK; }
-				if (piece.getClass() == Knight.class) { type = Custom3dModel.KNIGHT; }
-				if (piece.getClass() == Bishop.class) { type = Custom3dModel.BISHOP; }
-				if (piece.getClass() == Queen.class) { type = Custom3dModel.QUEEN; }
-				if (piece.getClass() == King.class) { type = Custom3dModel.KING; }
-				if (piece.getClass() == Nwap.class) { type = Custom3dModel.NWAP; }
-				if (piece.getClass() == Magician.class) { type = Custom3dModel.MAGICIAN; }
-				if (piece.getClass() == Giant.class) { type = Custom3dModel.GIANT; }
-				if (piece.getClass() == Kamikaze.class) { type = Custom3dModel.KNIGHT; }
-				createPiece(piece.getPosition(), piece.getColor(), type, material, model);
+				createPiece(piece.getPosition(), piece.getColor(), getMeshType(piece), material, model);
 			}
 		}
 		// init graveyards as empty
@@ -48,6 +42,17 @@ public class BoardView {
 		white_death_count = 0;
 
 		resetColor(material); // init/reset the board squares with black and white
+
+		// creates the board visual border
+		border = new Box[4];
+		int[] all_x = {0, 1, 0, -1};
+		int[] all_y = {1, 0, -1, 0};
+		for(int n = 0 ; n < 4 ; n++) {
+				border[n] = new Box(BOARD_SIZE/4 + Math.abs(BOARD_SIZE*8.25*all_y[n]), BOARD_SIZE/2*1.3, BOARD_SIZE/4 + Math.abs(BOARD_SIZE*8.25*all_x[n]));
+				border[n].setMaterial(material.get(CustomMaterial.WHITE));
+				border[n].translateXProperty().set((double) all_x[n] * (BOARD_SIZE*4 + BOARD_SIZE/4/2));
+				border[n].translateZProperty().set((double) all_y[n] * (BOARD_SIZE*4 + BOARD_SIZE/4/2));
+		}
 	}
 
 	public TileView getTile(int id) {
@@ -74,6 +79,20 @@ public class BoardView {
 		pieces[piece.getPosition().getID()] = piece;
 	}
 
+	private int getMeshType(Piece piece) {
+		int type = Custom3dModel.PAWN; // we can't do switch statement on ".getClass()"
+		if (piece.getClass() == Rook.class) { type = Custom3dModel.ROOK; }
+		if (piece.getClass() == Knight.class) { type = Custom3dModel.KNIGHT; }
+		if (piece.getClass() == Bishop.class) { type = Custom3dModel.BISHOP; }
+		if (piece.getClass() == Queen.class) { type = Custom3dModel.QUEEN; }
+		if (piece.getClass() == King.class) { type = Custom3dModel.KING; }
+		if (piece.getClass() == Nwap.class) { type = Custom3dModel.NWAP; }
+		if (piece.getClass() == Magician.class) { type = Custom3dModel.MAGICIAN; }
+		if (piece.getClass() == Giant.class) { type = Custom3dModel.GIANT; }
+		if (piece.getClass() == Kamikaze.class) { type = Custom3dModel.KNIGHT; }
+		return type;
+	}
+
 	private void createTile(Position position) {
 		// creates a tile and with the right size and position
 		Box box = new Box(BOARD_SIZE, (double) BOARD_SIZE / 2, BOARD_SIZE);
@@ -209,10 +228,27 @@ public class BoardView {
 	public void addAllToScene(Group group) {
 		for(int n = 0 ; n < 64 ; n++) {
 			if(getTile(n) != null) {
-				group.getChildren().addAll(getTileObj(n));
+				group.getChildren().add(getTileObj(n));
 			}
 			if(getPiece(n) != null) {
-				group.getChildren().addAll(getPieceObj(n));
+				group.getChildren().add(getPieceObj(n));
+			}
+		}
+		for(int n = 0 ; n < 4 ; n++) {
+			group.getChildren().add(border[n]);
+		}
+	}
+
+	public void refresh(Board b, Custom3dModel model) {
+		for(int j = 1 ; j <= 8 ; j++) {
+			for (int i = 1; i <= 8; i++) {
+				Position p = new Position(i, j);
+				Piece piece = b.getPiece(p);
+				if (piece != null) {
+					MeshView obj = getPieceObj(p.getID());
+					TriangleMesh newMesh = model.get(getMeshType(piece)); // get the mesh to use
+					obj.setMesh(newMesh); // replaces old mesh by new mesh
+				}
 			}
 		}
 	}
diff --git a/MavenChess/MavenChess/src/main/java/view/CustomCamera.java b/MavenChess/MavenChess/src/main/java/view/CustomCamera.java
index 6aef910994eb6fd35706956a5d122a3ca670dcbf..e241d28c5115825fb0a5e7b7e647d94d71f6e4f4 100644
--- a/MavenChess/MavenChess/src/main/java/view/CustomCamera.java
+++ b/MavenChess/MavenChess/src/main/java/view/CustomCamera.java
@@ -1,12 +1,17 @@
 package view;
 
+import javafx.animation.RotateTransition;
+import javafx.animation.Timeline;
+import javafx.animation.TranslateTransition;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.SimpleDoubleProperty;
 import javafx.scene.Group;
 import javafx.scene.PerspectiveCamera;
 import javafx.scene.Scene;
+import javafx.scene.SubScene;
 import javafx.scene.transform.Rotate;
 import javafx.scene.transform.Translate;
+import javafx.util.Duration;
 
 public class CustomCamera {
 
@@ -14,6 +19,8 @@ public class CustomCamera {
 	private final Group group; // used to rotate camera from 0,0,0 and not from camera x,y,z
 	private double anchorX, anchorY, anchorAngleX, anchorAngleY;
 
+	private RotateTransition animation;
+
 	private final static double SCROLL_SPEED = 10;
 	private final DoubleProperty angleX, angleY;
 	public CustomCamera(int nearClip, int farClip, int fov) {
@@ -25,7 +32,7 @@ public class CustomCamera {
 		group = new Group(camera);
 		group.setTranslateY(20);
 		// camera controls for user (with mouse)
-		angleX = new SimpleDoubleProperty(-45);
+		angleX = new SimpleDoubleProperty(-25);  // -45
 		angleY = new SimpleDoubleProperty(8);
 	}
 
@@ -33,12 +40,32 @@ public class CustomCamera {
 		return camera;
 	}
 
-	public void initMouseControl(Scene scene) { // allows user to move camera with mouse, with some constraints
+	public void startAnimation() {
+		camera.setTranslateZ(-80);
+		animation = new RotateTransition();
+		animation.setDuration(Duration.millis(20000));
+		animation.setNode(group);
+		animation.setAxis(Rotate.Y_AXIS);
+		animation.setFromAngle(-30);
+		animation.setToAngle(30);
+		animation.setCycleCount(Timeline.INDEFINITE);
+		animation.setAutoReverse(true);
+		animation.play();
+	}
+
+	public void stopAnimation() {
+		camera.setTranslateZ(-20);
+		angleX.set(-45);
+		animation.jumpTo(Duration.millis(10000));
+		animation.pause();
+	}
+
+	public void initMouseControl(SubScene scene) { // allows user to move camera with mouse, with some constraints
 		Rotate xRotate;
 		Rotate yRotate;
 		group.getTransforms().addAll(
 				yRotate = new Rotate(0, Rotate.Y_AXIS),
-				xRotate = new Rotate(-25, Rotate.X_AXIS)
+				xRotate = new Rotate(0, Rotate.X_AXIS) // -25
 		);
 		xRotate.angleProperty().bind(angleX);
 		yRotate.angleProperty().bind(angleY);
@@ -77,7 +104,7 @@ public class CustomCamera {
 				camera.setTranslateZ(z + SCROLL_SPEED);
 		}
 		else {
-			if(z > -400)
+			if(z > -200)
 				camera.setTranslateZ(z - SCROLL_SPEED);
 		}
 	}
diff --git a/MavenChess/MavenChess/src/main/java/view/CustomLight.java b/MavenChess/MavenChess/src/main/java/view/CustomLight.java
index dddfbf4d30f282de56fffef9b864b59a42609828..32f8eec98e0d33e67f001f590e24e62692cfc900 100644
--- a/MavenChess/MavenChess/src/main/java/view/CustomLight.java
+++ b/MavenChess/MavenChess/src/main/java/view/CustomLight.java
@@ -15,9 +15,9 @@ public class CustomLight {
 		light[0] = new PointLight(Color.rgb(191, 174, 148));
 		light[1] = new PointLight(Color.rgb(191, 174, 148));
 		light[2] = new PointLight(Color.rgb(191, 174, 148));
-		light[0].getTransforms().add(new Translate(-100, -50, 100));
-		light[1].getTransforms().add(new Translate(0, -60, -100));
-		light[2].getTransforms().add(new Translate(100, -50, 100));
+		light[0].getTransforms().add(new Translate(-100, -50, -100));
+		light[1].getTransforms().add(new Translate(0, -60, 100));
+		light[2].getTransforms().add(new Translate(100, -50, -100));
 	}
 
 	public void addAllToScene(Group group) {
diff --git a/MavenChess/MavenChess/src/main/java/view/CustomMaterial.java b/MavenChess/MavenChess/src/main/java/view/CustomMaterial.java
index ede4a370eba286f4263b2767f92ca8fe82a83fc2..8565f8483b8278a2abb3ab6a55ea87246ead3312 100644
--- a/MavenChess/MavenChess/src/main/java/view/CustomMaterial.java
+++ b/MavenChess/MavenChess/src/main/java/view/CustomMaterial.java
@@ -9,8 +9,8 @@ public class CustomMaterial {
 	private static PhongMaterial[] material;
 	public static final int
 			BLACK = 0, WHITE = 1, SELECTED_TILE = 2, MOVABLE_TILE = 3,
-			ATTACK_TILE = 4, SPECIAL_TILE = 5, BLACK_TILE = 6, WHITE_TILE = 7, WOOD = 8, EXPLOSION_TILE = 9;
-	private static final int MATERIAL_LENGTH = 10;
+			ATTACK_TILE = 4, SPECIAL_TILE = 5, BLACK_TILE = 6, WHITE_TILE = 7, WOOD = 8, EXPLOSION_TILE = 9, CARPET = 10, STUDIO_WALL = 11;
+	private static final int MATERIAL_LENGTH = 12;
 
 	public CustomMaterial() {
 		material = new PhongMaterial[MATERIAL_LENGTH];
@@ -34,11 +34,17 @@ public class CustomMaterial {
 		material[WOOD].setDiffuseMap(new Image("/wood.jpg"));
 		material[EXPLOSION_TILE] = new PhongMaterial();
 		material[EXPLOSION_TILE].setDiffuseColor(Color.rgb(200, 80, 50));
+		material[CARPET] = new PhongMaterial();
+		material[CARPET].setDiffuseMap(new Image("/carpet.jpg"));
+		material[STUDIO_WALL] = new PhongMaterial();
+		material[STUDIO_WALL].setDiffuseMap(new Image("/studio_wall.jpg"));
 
 		for(int i = 0 ; i < MATERIAL_LENGTH ; i++) {
 			material[i].setSpecularColor(Color.rgb(100, 100, 100));
 		}
 		material[BLACK].setSpecularColor(Color.WHITE); // more intense reflection for black
+		material[CARPET].setSpecularColor(Color.BLACK);
+		material[STUDIO_WALL].setSpecularColor(Color.BLACK);
 	}
 
 	public PhongMaterial get(int type) {
diff --git a/MavenChess/MavenChess/src/main/java/view/CustomScene.java b/MavenChess/MavenChess/src/main/java/view/CustomScene.java
index 30def40d9e0978fd5638893fa86f73edd80dd0cb..53fafe4be0a814db501393bde35d6c6dde017aac 100644
--- a/MavenChess/MavenChess/src/main/java/view/CustomScene.java
+++ b/MavenChess/MavenChess/src/main/java/view/CustomScene.java
@@ -1,19 +1,23 @@
 package view;
 
-import javafx.scene.Group;
-import javafx.scene.PerspectiveCamera;
-import javafx.scene.Scene;
-import javafx.scene.SceneAntialiasing;
+import javafx.scene.*;
+import javafx.scene.layout.AnchorPane;
 import javafx.scene.paint.Color;
 
 public class CustomScene {
 	private final Scene scene;
-	public CustomScene(Group group, PerspectiveCamera camera, SceneAntialiasing antialiasing) {
-		scene = new Scene(group, 800, 500, true, antialiasing); // create scene
-		scene.setFill(Color.rgb(50, 50, 50)); // background default color
-		scene.setCamera(camera); // link camera to scene
+	private final SubScene subScene;
+	public CustomScene(AnchorPane group2d, Group group3d, PerspectiveCamera camera, SceneAntialiasing antialiasing) {
+		scene = new Scene(group2d, 1280, 720, true);
+		subScene = new SubScene(group3d, 1280, 720, true, antialiasing); // create scene
+		subScene.setFill(Color.rgb(50, 50, 50)); // background default color
+		subScene.setCamera(camera); // link camera to scene
+		group2d.getChildren().add(subScene);
 	}
-	public Scene get() {
+	public Scene get2d() {
 		return scene;
 	}
+	public SubScene get3d() {
+		return subScene;
+	}
 }
diff --git a/MavenChess/MavenChess/src/main/java/view/Desk.java b/MavenChess/MavenChess/src/main/java/view/Desk.java
index 06def99af1b9705fedf042e7f64e3daddb60a62d..7abbd462af4366c9e0d48f48ffae8dfb7cc2e61a 100644
--- a/MavenChess/MavenChess/src/main/java/view/Desk.java
+++ b/MavenChess/MavenChess/src/main/java/view/Desk.java
@@ -5,14 +5,33 @@ import javafx.scene.shape.Box;
 
 public class Desk {
 	private final Box desk;
+	private final Box[] desk_leg;
 	public Desk(CustomMaterial material) {
+		// desk board
 		int table_size = BoardView.BOARD_SIZE*12;
+		int leg_size = BoardView.BOARD_SIZE*8;
 		desk = new Box(table_size*2, BoardView.BOARD_SIZE, table_size);
 		desk.translateYProperty().set((double) BoardView.BOARD_SIZE /2);
 		desk.setMaterial(material.get(CustomMaterial.WOOD));
+		// desk legs
+		desk_leg = new Box[4];
+		for(int j = -1, n = 0; j <= 1 ; j+=2) {
+			for(int i = -1 ; i <= 1 ; i+=2 , n++) {
+				desk_leg[n] = new Box(BoardView.BOARD_SIZE, leg_size, BoardView.BOARD_SIZE);
+				desk_leg[n].setMaterial(material.get(CustomMaterial.WOOD));
+				desk_leg[n].translateYProperty().set((double) BoardView.BOARD_SIZE/2 + leg_size/2 + BoardView.BOARD_SIZE/2);
+				desk_leg[n].translateXProperty().set((double) i * (table_size - BoardView.BOARD_SIZE/2));
+				desk_leg[n].translateZProperty().set((double) j * (table_size/2 - BoardView.BOARD_SIZE/2));
+			}
+		}
+
+
 	}
 
 	public void addAllToScene(Group group) {
 		group.getChildren().add(desk);
+		for(int n = 0 ; n < 4 ; n++) {
+			group.getChildren().add(desk_leg[n]);
+		}
 	}
 }
diff --git a/MavenChess/MavenChess/src/main/java/view/HUD.java b/MavenChess/MavenChess/src/main/java/view/HUD.java
new file mode 100644
index 0000000000000000000000000000000000000000..43a024cb4bff17b5928c21c33a03ee272a431c8c
--- /dev/null
+++ b/MavenChess/MavenChess/src/main/java/view/HUD.java
@@ -0,0 +1,73 @@
+package view;
+
+import javafx.scene.effect.Glow;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.paint.Color;
+import javafx.scene.shape.Rectangle;
+
+public class HUD {
+
+    private Image standard_img, variant_img;
+    private ImageView standard_imgView, variant_imgView;
+    private Rectangle darkener;
+
+    public HUD() {
+        standard_img = new Image("/standard.jpg");
+        variant_img = new Image("/variant.jpg");
+        standard_imgView = new ImageView(standard_img);
+        variant_imgView = new ImageView(variant_img);
+        standard_imgView.setPreserveRatio(true);
+        variant_imgView.setPreserveRatio(true);
+        darkener = new Rectangle();
+        darkener.setX(0);
+        darkener.setY(0);
+        darkener.setFill(Color.BLACK);
+        darkener.setOpacity(0.5);
+        Glow glow = new Glow(0.2);
+        Glow none = new Glow(0);
+        standard_imgView.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> {
+            standard_imgView.setEffect(glow);
+            variant_imgView.setEffect(none);
+        });
+        standard_imgView.addEventHandler(MouseEvent.MOUSE_EXITED, event -> {
+            standard_imgView.setEffect(none);
+        });
+        variant_imgView.addEventHandler(MouseEvent.MOUSE_ENTERED, event -> {
+            variant_imgView.setEffect(glow);
+        });
+        variant_imgView.addEventHandler(MouseEvent.MOUSE_EXITED, event -> {
+            variant_imgView.setEffect(none);
+        });
+    }
+
+    public void resize(double width, double height) {
+        int weight = 2;
+        int total = weight*2 + 4;
+        standard_imgView.setX(width/total);
+        standard_imgView.setY(height/total/2);
+        standard_imgView.setFitWidth(width*weight/total);
+        variant_imgView.setX(width/total * (weight+3));
+        variant_imgView.setY(height/total/2);
+        variant_imgView.setFitWidth(width*weight/total);
+        darkener.setWidth(width);
+        darkener.setHeight(height);
+    }
+
+    public ImageView getStandard() {
+        return standard_imgView;
+    }
+
+    public ImageView getVariant() {
+        return variant_imgView;
+    }
+
+    public void removeMenu(AnchorPane group2d) {
+        group2d.getChildren().removeAll(darkener, standard_imgView, variant_imgView);
+    }
+    public void addAllToScene(AnchorPane group2d) {
+        group2d.getChildren().addAll(darkener, standard_imgView, variant_imgView);
+    }
+}
diff --git a/MavenChess/MavenChess/src/main/java/view/PieceView.java b/MavenChess/MavenChess/src/main/java/view/PieceView.java
index a67f77f6cb4d65786eca3543bf57dac335e0b51c..46c30a82361a7aab25a3367cb6e2584fa3965c43 100644
--- a/MavenChess/MavenChess/src/main/java/view/PieceView.java
+++ b/MavenChess/MavenChess/src/main/java/view/PieceView.java
@@ -37,6 +37,14 @@ public class PieceView {
 		return color;
 	}
 
+	public boolean isWhite() {
+		return color == Piece.WHITE;
+	}
+
+	public boolean isBlack() {
+		return color == Piece.BLACK;
+	}
+
 	public void setColor(int color) {
 		this.color = color;
 	}
diff --git a/MavenChess/MavenChess/src/main/java/view/Room.java b/MavenChess/MavenChess/src/main/java/view/Room.java
new file mode 100644
index 0000000000000000000000000000000000000000..79f7c032bb598ce32b2a0ef881f3c7d59fcabdc6
--- /dev/null
+++ b/MavenChess/MavenChess/src/main/java/view/Room.java
@@ -0,0 +1,50 @@
+package view;
+
+import javafx.scene.Group;
+import javafx.scene.shape.Box;
+import javafx.scene.shape.CullFace;
+
+public class Room {
+    private final Box[] walls;
+
+    public Room(CustomMaterial material) {
+
+        /*int size = BoardView.BOARD_SIZE*64;
+        int height = BoardView.BOARD_SIZE*32;
+        walls = new Box(size, height, size);
+        walls.setMaterial(material.get(CustomMaterial.BLACK_TILE));
+        walls.setCullFace(CullFace.BACK);*/
+
+        int size = BoardView.BOARD_SIZE*60;
+        double height = 0.5;
+        walls = new Box[6];
+        int[] pos_x = {0, 1, 0, -1, 0, 0};
+        int[] pos_y = {0, 0, 0, 0, 1, -1};
+        int[] pos_z = {1, 0, -1, 0, 0, 0};
+        int[] size_x = {1, 0, 1, 0, 1, 1};
+        int[] size_y = {1, 1, 1, 1, 0, 0};
+        int[] size_z = {0, 1, 0, 1, 1, 1};
+        for(int n = 0 ; n < 6 ; n++) {
+            walls[n] = new Box(1 + size_x[n]*size, 1 + size_y[n]*size*height, 1 + size_z[n]*size);
+            walls[n].translateXProperty().set((double) pos_x[n] * (size/2));
+            walls[n].translateYProperty().set((double) (pos_y[n] * (size/2) - (size/2)) * height + BoardView.BOARD_SIZE*9); // centered up, then down to table legs
+            walls[n].translateZProperty().set((double) pos_z[n] * (size/2));
+        }
+        // Ground
+        walls[4].setMaterial(material.get(CustomMaterial.CARPET));
+        // Ceiling
+        walls[5].setMaterial(material.get(CustomMaterial.WHITE));
+        // Walls
+        walls[0].setMaterial(material.get(CustomMaterial.STUDIO_WALL));
+        walls[1].setMaterial(material.get(CustomMaterial.STUDIO_WALL));
+        walls[2].setMaterial(material.get(CustomMaterial.STUDIO_WALL));
+        walls[3].setMaterial(material.get(CustomMaterial.STUDIO_WALL));
+    }
+
+    public void addAllToScene(Group group) {
+        //group.getChildren().add(walls);
+        for(int n = 0 ; n < 6 ; n++) {
+            group.getChildren().add(walls[n]);
+        }
+    }
+}
diff --git a/MavenChess/MavenChess/src/main/resources/carpet.jpg b/MavenChess/MavenChess/src/main/resources/carpet.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..9536e031b66400b03564da16b242121cc700ee01
Binary files /dev/null and b/MavenChess/MavenChess/src/main/resources/carpet.jpg differ
diff --git a/MavenChess/MavenChess/src/main/resources/icon_camera.png b/MavenChess/MavenChess/src/main/resources/icon_camera.png
new file mode 100644
index 0000000000000000000000000000000000000000..5c7c5c9a5539812f858aa1e83584256ee044ac42
Binary files /dev/null and b/MavenChess/MavenChess/src/main/resources/icon_camera.png differ
diff --git a/MavenChess/MavenChess/src/main/resources/standard.jpg b/MavenChess/MavenChess/src/main/resources/standard.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..80ab8bc158c7482c96f0e5f9d7fd649d5260d345
Binary files /dev/null and b/MavenChess/MavenChess/src/main/resources/standard.jpg differ
diff --git a/MavenChess/MavenChess/src/main/resources/studio_wall.jpg b/MavenChess/MavenChess/src/main/resources/studio_wall.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..21963150e325c6a8050e5dc248a39025b92f1f93
Binary files /dev/null and b/MavenChess/MavenChess/src/main/resources/studio_wall.jpg differ
diff --git a/MavenChess/MavenChess/src/main/resources/variant.jpg b/MavenChess/MavenChess/src/main/resources/variant.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..aa9b4c3c2aa2a908cc499df2c5f3b352d26c5d1d
Binary files /dev/null and b/MavenChess/MavenChess/src/main/resources/variant.jpg differ
diff --git a/MavenChess/MavenChess/target/classes/controller/Main.class b/MavenChess/MavenChess/target/classes/controller/Main.class
index b3df3d8666f86150ecee53900be5105cf57c6643..86e6c5508d2b7614d60f252634cf6e9ee5ce4704 100644
Binary files a/MavenChess/MavenChess/target/classes/controller/Main.class and b/MavenChess/MavenChess/target/classes/controller/Main.class differ
diff --git a/MavenChess/MavenChess/target/classes/model/Board.class b/MavenChess/MavenChess/target/classes/model/Board.class
index d7205579cb1b8491f6d63f543ac471e8ac5a086a..8451c0881bd6e5a99e303545b9889a28167d2f60 100644
Binary files a/MavenChess/MavenChess/target/classes/model/Board.class and b/MavenChess/MavenChess/target/classes/model/Board.class differ
diff --git a/MavenChess/MavenChess/target/classes/model/Giant.class b/MavenChess/MavenChess/target/classes/model/Giant.class
index 3585b01c7aac9a58774cfa823e3b6de25154838e..43177252b08e2c1fb809cd20ce087fe640b76db1 100644
Binary files a/MavenChess/MavenChess/target/classes/model/Giant.class and b/MavenChess/MavenChess/target/classes/model/Giant.class differ
diff --git a/MavenChess/MavenChess/target/classes/model/Log.class b/MavenChess/MavenChess/target/classes/model/Log.class
deleted file mode 100644
index 59bcb237934dd8d469f702c385593215ee0d5885..0000000000000000000000000000000000000000
Binary files a/MavenChess/MavenChess/target/classes/model/Log.class and /dev/null differ
diff --git a/MavenChess/MavenChess/target/classes/model/Magician.class b/MavenChess/MavenChess/target/classes/model/Magician.class
index a6c93ebe3cfc690fedc4ddf1307820b1a0664976..f801dce876007630df38376e796dfd993725c0f2 100644
Binary files a/MavenChess/MavenChess/target/classes/model/Magician.class and b/MavenChess/MavenChess/target/classes/model/Magician.class differ
diff --git a/MavenChess/MavenChess/target/classes/model/Piece.class b/MavenChess/MavenChess/target/classes/model/Piece.class
index 5ea10cd77ba3e51ecf0a9c9952be710ffc479667..ff3381d6210cc158f50aa92f3eddded279ec977d 100644
Binary files a/MavenChess/MavenChess/target/classes/model/Piece.class and b/MavenChess/MavenChess/target/classes/model/Piece.class differ
diff --git a/MavenChess/MavenChess/target/classes/model/Position.class b/MavenChess/MavenChess/target/classes/model/Position.class
index d08ee04d724822d2ca396ded99593f1d5aef9acc..52e0b27617cdee8062fedd8ba9704f57b73305d8 100644
Binary files a/MavenChess/MavenChess/target/classes/model/Position.class and b/MavenChess/MavenChess/target/classes/model/Position.class differ
diff --git a/MavenChess/MavenChess/target/classes/view/BoardView.class b/MavenChess/MavenChess/target/classes/view/BoardView.class
index dad9befd6db93d0d81adc0e81ba4275c84441a0e..a69cf882baf2ec66c24bb8dcb8fa7b8a97327849 100644
Binary files a/MavenChess/MavenChess/target/classes/view/BoardView.class and b/MavenChess/MavenChess/target/classes/view/BoardView.class differ
diff --git a/MavenChess/MavenChess/target/classes/view/CustomCamera.class b/MavenChess/MavenChess/target/classes/view/CustomCamera.class
index 26d3a8efec8aa8c0024ccc05fe267bc80ab29f96..a15d8e0789483c7fde04a89d6e69fed78e3be47e 100644
Binary files a/MavenChess/MavenChess/target/classes/view/CustomCamera.class and b/MavenChess/MavenChess/target/classes/view/CustomCamera.class differ
diff --git a/MavenChess/MavenChess/target/classes/view/CustomLight.class b/MavenChess/MavenChess/target/classes/view/CustomLight.class
index 5dca188028fe0f1b9563d42a38f325d9a1293066..9bdc08a814b8763eca9c064be9aab809c2f4a907 100644
Binary files a/MavenChess/MavenChess/target/classes/view/CustomLight.class and b/MavenChess/MavenChess/target/classes/view/CustomLight.class differ
diff --git a/MavenChess/MavenChess/target/classes/view/CustomMaterial.class b/MavenChess/MavenChess/target/classes/view/CustomMaterial.class
index 8dc8f459dec29d3bd79feacd9f5bfa14b963d72e..b48801cae6662a2273c1d21688ae64cf0e5e651e 100644
Binary files a/MavenChess/MavenChess/target/classes/view/CustomMaterial.class and b/MavenChess/MavenChess/target/classes/view/CustomMaterial.class differ
diff --git a/MavenChess/MavenChess/target/classes/view/CustomScene.class b/MavenChess/MavenChess/target/classes/view/CustomScene.class
index 6f961b88f066934065f9339e26e71c1f847402e7..94132b24ebab5f53a3db1d97c54339d3a661d09e 100644
Binary files a/MavenChess/MavenChess/target/classes/view/CustomScene.class and b/MavenChess/MavenChess/target/classes/view/CustomScene.class differ
diff --git a/MavenChess/MavenChess/target/classes/view/Desk.class b/MavenChess/MavenChess/target/classes/view/Desk.class
index 55a49cd16fcf1060e1a916541af1fe10e381ae50..4cccd6abf1fb4637c72fcbe5f98667b43e52f8fb 100644
Binary files a/MavenChess/MavenChess/target/classes/view/Desk.class and b/MavenChess/MavenChess/target/classes/view/Desk.class differ
diff --git a/MavenChess/MavenChess/target/classes/view/PieceView.class b/MavenChess/MavenChess/target/classes/view/PieceView.class
index 2cacf877973b8926ea0dae0b465634a7c1287266..a00472d7eddf3898636b0687e181c638e23b9eea 100644
Binary files a/MavenChess/MavenChess/target/classes/view/PieceView.class and b/MavenChess/MavenChess/target/classes/view/PieceView.class differ