Skip to content
Snippets Groups Projects
Commit d4727c23 authored by MasterPyo's avatar MasterPyo
Browse files

variants fully functionnal + enpassant pawn AND nwap

parent 4ef0f70c
No related merge requests found
Showing
with 236 additions and 57 deletions
......@@ -5,8 +5,7 @@ import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.stage.Stage;
import model.Board;
import model.Position;
import model.*;
import view.*;
import java.util.ArrayList;
......@@ -23,6 +22,7 @@ public class Main extends Application {
private Board board;
private BoardView boardView;
@Override
public void start(Stage stage) {
......@@ -99,11 +99,10 @@ public class Main extends Application {
if(clickedPiece.getPosition().getX() < 0) {
return;
}
// if piece is an "attack" or "special" target, we consider it an action to apply (tile click)
// 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 {
} else {
// clicking a piece will ask her available moves
Position position = clickedPiece.getPosition();
board.setSelected(position);
......@@ -111,10 +110,42 @@ public class Main extends Application {
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);
......@@ -123,7 +154,7 @@ public class Main extends Application {
boardView.getPiece(move.getID()).setTargeted(material, CustomMaterial.SPECIAL_TILE);
}
// PROMOTION (attacking or not)
if (board.isPawn(position) && (move.getY() == 8 || move.getY() == 1)) {
if ((board.isPawn(position) || board.isNwap(position)) && (move.getY() == 8 || move.getY() == 1)) {
boardView.setColor(material, move, CustomMaterial.SPECIAL_TILE);
}
}
......@@ -131,13 +162,27 @@ public class Main extends Application {
}
public void clickTile(TileView clickedTile) {
// --- 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);
}
}
}
// --- 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) {
// --- ALL SPECIAL MOVES ---
if(state == TileView.SPECIAL) {
if(board.isPawn(selected)) {
if(board.isPawn(selected) || board.isNwap(selected)) {
// --- PROMOTION ---
if(arrival.getY() == 8 || arrival.getY() == 1) {
// --- ATTACK (while doing promotion) ---
......@@ -156,6 +201,16 @@ public class Main extends Application {
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) ---
......@@ -189,12 +244,50 @@ public class Main extends Application {
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)
......
......@@ -79,7 +79,11 @@ public class Board {
Piece piece = getPiece(origin);
piece.setPosition(arrival); // changes position to arrival
setPiece(piece); // copies the piece (from origin ID) to arrival ID on the pieces list
pieces[origin.getID()] = null; // removes the origin ID piece on the pieces list
killPiece(origin.getID()); // removes the origin ID piece on the pieces list
}
public void killPiece(int id) {
pieces[id] = null;
}
public void mutationOfSelectedPiece(int type) {
......@@ -120,4 +124,22 @@ public class Board {
&& !isFree(p)
&& getPiece(p).getClass() == Pawn.class);
}
public boolean isNwap(Position p) {
return (p.isCorrect()
&& !isFree(p)
&& getPiece(p).getClass() == Nwap.class);
}
public boolean isKamikaze(Position p) {
return (p.isCorrect()
&& !isFree(p)
&& getPiece(p).getClass() == Kamikaze.class);
}
public boolean isMagician(Position p) {
return (p.isCorrect()
&& !isFree(p)
&& getPiece(p).getClass() == Magician.class);
}
}
......@@ -3,7 +3,7 @@ package model;
import java.util.ArrayList;
public class Giant extends Piece{
protected Giant(Position p, int color) {
public Giant(Position p, int color) {
super(p, color);
}
......@@ -12,8 +12,31 @@ public class Giant extends Piece{
public ArrayList<Position> getAvailableMoves(Board b) {
ArrayList<Position> moves = new ArrayList<>();
Position arrival;
// list of the 4 giant directions
int[] all_x = {0, 2, 0, -2};
int[] all_y = {2, 0, -2, 0};
for(int n = 0 ; n < all_x.length ; n++) { // for each direction
int x = all_x[n];
int y = all_y[n];
boolean blocked = false;
int i = 1;
while (i < 4 && !blocked) { // continues "as a ray" in that direction until blocked
arrival = new Position(p.getX() + (x * i), p.getY() + (y * i));
if (b.isEnemy(arrival, p) || b.isFree(arrival)) {
moves.add(arrival);
}
if (!b.isFree(arrival)) {
blocked = true;
}
i++;
}
}
// Full explicit directions version : ----------------------------
/*
int i = 1;
boolean left = false;
boolean right = false;
......@@ -21,26 +44,21 @@ public class Giant extends Piece{
boolean down = false;
while (i < 4) {
//left
arrival = new Position(p.getX() + (i*2), p.getY());
if (arrival.isCorrect()) {
if (!left) {
if (b.isEnemy(arrival, p) || b.isFree(arrival)) {
moves.add(arrival);
}
if (b.isKing(arrival)) {
moves.add(arrival);
}
}
if (!b.isFree(arrival)) {
left = true;
}
}
//right
arrival = new Position(p.getX() - (i*2), p.getY());
if (arrival.isCorrect()) {
......@@ -52,14 +70,11 @@ public class Giant extends Piece{
moves.add(arrival);
}
}
if (!b.isFree(arrival)) {
right = true;
}
}
arrival = new Position(p.getX(), p.getY() + (i*2));
if (arrival.isCorrect()) {
if (!top) {
......@@ -67,15 +82,11 @@ public class Giant extends Piece{
moves.add(arrival);
}
}
if (!b.isFree(arrival)) {
top = true;
}
}
arrival = new Position(p.getX(), p.getY() - (i*2));
if (arrival.isCorrect()) {
if (!down) {
......@@ -83,15 +94,13 @@ public class Giant extends Piece{
moves.add(arrival);
}
}
if (!b.isFree(arrival)) {
top = true;
}
}
i++;
}
}*/
// ------------------------------------------------------------
return moves;
......
......@@ -2,7 +2,7 @@ package model;
import java.util.ArrayList;
public class Kamikaze extends Pawn {
public class Kamikaze extends Pawn { // aka Trojan knight :P
public Kamikaze(Position p, int color) {
super(p, color);
}
......@@ -10,42 +10,56 @@ public class Kamikaze extends Pawn {
@Override
public ArrayList<Position> getAvailableMoves(Board b) {
ArrayList<Position> moves = new ArrayList<Position>();
ArrayList<Position> moves = new ArrayList<>();
Position arrival;
// Self-Detonation Position no need for checks as the Kamikaze is already in place
arrival = new Position(p.getX(),p.getY());
moves.add(arrival);
if(color == Piece.WHITE) { // black and white have an opposite direction behavior
/*if(color == Piece.WHITE) { // black and white have an opposite direction behavior
if(!hasBeenMoved){
arrival = new Position(p.getX(),p.getY()+2);
if(arrival.isCorrect() && b.isFree(arrival)) {moves.add(arrival);}
}
arrival = new Position(p.getX(),p.getY()+1);
if(arrival.isCorrect() && b.isFree(arrival)) {moves.add(arrival);}
}
else {
if(!hasBeenMoved){
arrival = new Position(p.getX(),p.getY()-2);
if(arrival.isCorrect() && b.isFree(arrival)) {moves.add(arrival);}
}
arrival = new Position(p.getX(),p.getY()-1);
if(arrival.isCorrect() && b.isFree(arrival)) {moves.add(arrival);}
}*/
// list of the 8 kamikaze-knight specific movements
int[] all_x = {1, 2, 2, 1, -1, -2, -2, -1};
int[] all_y = {2, 1, -1, -2, -2, -1, 1, 2};
for(int n = 0 ; n < all_x.length ; n++) { // for each direction
int x = all_x[n];
int y = all_y[n];
arrival = new Position(p.getX() + x, p.getY() + y);
if (b.isEnemy(arrival, p) || b.isFree(arrival)) {
moves.add(arrival);
}
}
return moves;
}
public ArrayList<Position> getExplosion() {
ArrayList<Position> moves = new ArrayList<>();
Position target;
for(int x = -1 ; x <= 1 ; x++) {
for(int y = -1 ; y <= 1 ; y++) {
target = new Position(p.getX() + x, p.getY() + y);
if (target.isCorrect()) {
moves.add(target);
}
}
}
return moves;
}
}
......@@ -18,6 +18,10 @@ public class Magician extends Piece{
public void setCopiedPiece(Piece copiedPiece) {
this.copiedPiece = copiedPiece;
}
public Piece getCopiedPiece() {
return copiedPiece;
}
public void setPosition(Position p) {
this.p = p;
copiedPiece.setPosition(p);
......
......@@ -3,8 +3,11 @@ package model;
import java.util.ArrayList;
public class Nwap extends Pawn {
private boolean enPassant;
public Nwap(Position p, int color) {
super(p, color);
enPassant = false;
}
@Override
......@@ -73,4 +76,11 @@ public class Nwap extends Pawn {
}
return moves;
}
public boolean isEnPassant() {
return enPassant;
}
public void setEnPassant(boolean enPassant) {
this.enPassant = enPassant;
}
}
......@@ -4,9 +4,10 @@ import java.util.ArrayList;
public class Pawn extends Piece {
private boolean enPassant = true; // temporarily given true but has to be changed in the controller
private boolean enPassant;
public Pawn(Position p, int color) {
super(p, color);
enPassant = false;
}
public ArrayList<Position> getAvailableMoves(Board b) {
......
......@@ -8,6 +8,8 @@ public class Position {
public static final int WHITE_GRAVEYARD = -1, BLACK_GRAVEYARD = -2;
public Position(int x, int y) {
while(x < 1) { x += 8; }
while(x > 8) { x -= 8; }
this.x = x;
this.y = y;
}
......
......@@ -3,7 +3,7 @@ package model;
import java.util.ArrayList;
public class Queen extends Piece{
protected Queen(Position p, int color) {
public Queen(Position p, int color) {
super(p, color);
}
......
package view;
import javafx.animation.TranslateTransition;
import javafx.scene.Group;
import javafx.scene.shape.*;
import model.*;
import javafx.util.Duration;
public class BoardView {
......@@ -113,15 +115,30 @@ public class BoardView {
}
}
private void updatePieceWithAnimation(Position position) { // updates the piece(i, j), visually, to the right position
int id = position.getID();
MeshView obj = getPieceObj(id);
if(getPiece(id) != null) {
TranslateTransition animation = new TranslateTransition();
animation.setDuration(Duration.millis(300));
animation.setNode(obj);
animation.setFromX(obj.getTranslateX());
animation.setFromZ(obj.getTranslateZ());
animation.setToX((position.getX()-1) * BOARD_SIZE + CENTERED_ORIGIN);
animation.setToZ((position.getY()-1) * BOARD_SIZE + CENTERED_ORIGIN);
animation.play();
}
}
private void updateGraveyardPiece(PieceView piece) { // updates position (visual) of a dead piece
int x = piece.getPosition().getX();
int y = piece.getPosition().getY();
if(x == Position.WHITE_GRAVEYARD) {
piece.getObj().setTranslateX(-2 * BOARD_SIZE + CENTERED_ORIGIN);
piece.getObj().setTranslateZ(y * BOARD_SIZE*0.65f - BOARD_SIZE*4);
piece.getObj().setTranslateZ(y * BOARD_SIZE*0.65f - BOARD_SIZE*5);
} else { // x == Position.BLACK_GRAVEYARD
piece.getObj().setTranslateX(9 * BOARD_SIZE + CENTERED_ORIGIN);
piece.getObj().setTranslateZ(-y * BOARD_SIZE*0.65f + BOARD_SIZE*4);
piece.getObj().setTranslateZ(-y * BOARD_SIZE*0.65f + BOARD_SIZE*5);
}
piece.getObj().setTranslateY(GRAVEYARD_HEIGHT); // place at right height (Y axis) on table
}
......@@ -149,6 +166,7 @@ public class BoardView {
getTileObj(id).setMaterial(material.get(type));
// save color-type in the "state" attribute of that tile
switch(type) {
case CustomMaterial.EXPLOSION_TILE -> getTile(id).setState(TileView.EXPLOSION);
case CustomMaterial.SELECTED_TILE -> getTile(id).setState(TileView.SELECTED);
case CustomMaterial.MOVABLE_TILE -> getTile(id).setState(TileView.MOVABLE);
case CustomMaterial.ATTACK_TILE -> getTile(id).setState(TileView.ATTACK);
......@@ -162,19 +180,23 @@ public class BoardView {
piece.setPosition(arrival); // changes position to arrival
setPiece(piece); // copies the piece from origin ID to arrival ID
pieces[origin.getID()] = null; // removes the origin ID piece
updatePiece(arrival); // updates 3d model position (visual)
// updatePiece(arrival); // updates 3d model position (visual)
updatePieceWithAnimation(arrival); // updates 3d model position (visual) but animated
}
public void killPiece(Position p) { // graveyards are specified as negative x
PieceView piece = getPiece(p.getID());
if(piece.getColor() == Piece.WHITE){
white_death_count++;
piece.setPosition(new Position(Position.WHITE_GRAVEYARD, white_death_count));
piece.setPosition(new Position(1, white_death_count));
piece.getPosition().setX(Position.WHITE_GRAVEYARD);
} else {
black_death_count++;
piece.setPosition(new Position(Position.BLACK_GRAVEYARD, black_death_count));
piece.setPosition(new Position(1, black_death_count));
piece.getPosition().setX(Position.BLACK_GRAVEYARD);
}
updateGraveyardPiece(piece);
pieces[p.getID()] = null;
}
public void mutationPiece(Custom3dModel model, Position selected, int type) {
......
......@@ -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;
private static final int MATERIAL_LENGTH = 9;
ATTACK_TILE = 4, SPECIAL_TILE = 5, BLACK_TILE = 6, WHITE_TILE = 7, WOOD = 8, EXPLOSION_TILE = 9;
private static final int MATERIAL_LENGTH = 10;
public CustomMaterial() {
material = new PhongMaterial[MATERIAL_LENGTH];
......@@ -19,9 +19,9 @@ public class CustomMaterial {
material[WHITE] = new PhongMaterial();
material[WHITE].setDiffuseColor(Color.rgb(240,240,240));
material[SELECTED_TILE] = new PhongMaterial();
material[SELECTED_TILE].setDiffuseColor(Color.rgb(50,200,100));
material[SELECTED_TILE].setDiffuseColor(Color.rgb(40,150,60));
material[MOVABLE_TILE] = new PhongMaterial();
material[MOVABLE_TILE].setDiffuseColor(Color.rgb(50,240,0));
material[MOVABLE_TILE].setDiffuseColor(Color.rgb(50,200,80));
material[ATTACK_TILE] = new PhongMaterial();
material[ATTACK_TILE].setDiffuseColor(Color.rgb(200,50,50));
material[SPECIAL_TILE] = new PhongMaterial();
......@@ -32,6 +32,8 @@ public class CustomMaterial {
material[WHITE_TILE].setDiffuseColor(Color.grayRgb(200));
material[WOOD] = new PhongMaterial();
material[WOOD].setDiffuseMap(new Image("/wood.jpg"));
material[EXPLOSION_TILE] = new PhongMaterial();
material[EXPLOSION_TILE].setDiffuseColor(Color.rgb(200, 80, 50));
for(int i = 0 ; i < MATERIAL_LENGTH ; i++) {
material[i].setSpecularColor(Color.rgb(100, 100, 100));
......
......@@ -9,7 +9,7 @@ public class TileView {
private final Position position;
private int state;
public static final int NORMAL = 0, SELECTED = 1, MOVABLE = 2, ATTACK = 3, SPECIAL = 4;
public static final int NORMAL = 0, SELECTED = 1, MOVABLE = 2, ATTACK = 3, SPECIAL = 4, EXPLOSION = 5;
public TileView(Box obj, Position position) {
this.obj = obj;
this.position = position;
......
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment