57 Commits

Author SHA1 Message Date
674ac14935 add dialog when game finish 2021-12-07 15:59:59 +01:00
ab6639f090 add dialog when game finish 2021-12-07 15:58:57 +01:00
7c00cd474b Add System.in as standard input 2021-12-07 15:13:27 +01:00
19dceafb7d Major improvement of windows (in terms of cpu, disk and ram performances), move ClientEventHandler.java to listener package 2021-12-07 12:19:31 +01:00
Valentin Lucas
1defc451aa Modification de putStatePlayerPane(), showStatePlayer(),showMoveText() (Reste à corriger certaines choses) 2021-12-07 10:07:38 +01:00
Valentin Lucas
bb44efd9fc Ajout de ShowMoveText() et showStatePlayers (à modifier) 2021-12-06 16:03:24 +01:00
e7740739d9 Add support to grid elements using a countdown like bomb 2021-12-06 13:02:55 +01:00
7dde04303c Move images, optimize imports, move GUI instructions to Window.java 2021-12-04 16:13:22 +01:00
Katchan
aea8ac654d Fix build function call 2021-12-04 15:36:47 +01:00
Katchan
87d4b6ca39 Fix Git add files 2021-12-04 15:20:12 +01:00
Katchan
f4477ac1e0 Add buildGrid Strategy Pattern 2021-12-04 15:17:41 +01:00
Katchan
daa07887f7 Deletion of the notion of cardinal for a wall 2021-12-03 15:45:09 +01:00
0a4e706e07 Fix images not loading 2021-12-03 15:30:38 +01:00
899f3ecebf Merge remote-tracking branch 'origin/master' 2021-12-03 15:25:13 +01:00
Katchan
3066ecf211 Fix critical bug 2021-12-03 15:22:00 +01:00
Katchan
7afd79b929 Conflict resolution 2021-12-02 20:11:23 +01:00
Katchan
e862e79a62 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	client/src/main/java/fr/lnl/game/client/App.java
#	server/src/main/java/fr/lnl/game/server/games/Game.java
#	server/src/test/java/fr/lnl/game/server/Mock.java
2021-12-02 20:06:53 +01:00
Katchan
a354d4fb21 Mock update and import optimization 2021-12-02 20:03:46 +01:00
Katchan
5201e73772 Add AbstractBox and lock case notion (to see if it is viable to keep it) 2021-12-02 20:01:49 +01:00
Katchan
c6f4dbffe3 Add random choose method in the Cardinal enum 2021-12-02 20:00:53 +01:00
Katchan
d40dedfc17 Add placement rules for walls, energyballs and players 2021-12-02 19:59:53 +01:00
Valentin Lucas
0876b4c773 Ajouts d'images et quelques modification de cell et Gui 2021-12-02 19:56:37 +01:00
b6cc8f24f9 Fix terminal view + fix dialog incorrect computer id 2021-12-02 18:44:57 +01:00
623e6b5fb3 Merge remote-tracking branch 'origin/master' 2021-12-02 18:33:36 +01:00
4c7017ff97 FINALLY fix the game with Window (currently not work with terminal) 2021-12-02 18:33:18 +01:00
Valentin Lucas
572a20bcf7 Modification de Cell et GUI, Affichage réussie de la grille mais image pas encore affichée 2021-12-02 16:12:30 +01:00
2ebd51f011 Move viewUpdate to ViewManager.java, renamed getPoint() to getPosition() in Player, View still not work 2021-12-01 23:31:51 +01:00
Valentin Valentin
1b8f9a2b30 Modification de cell et ajout d'un main temporaire + ajout d'images 2021-11-30 18:18:08 +01:00
de8c258322 Fix game not launching + add supprot to Computer Players (AI) + fix view not updating at each Game#play 's loop 2021-11-29 19:22:43 +01:00
f73dfc8bb9 Fix client only launching app on terminal view 2021-11-29 18:22:21 +01:00
b08139ebca Fix NullPointerException in App.java 2021-11-27 19:20:27 +01:00
9cfa56be8d implement Game#play 2021-11-27 17:47:05 +01:00
42b0c656f8 forgot to add module-info.java to last commit 2021-11-27 17:02:51 +01:00
21e571027f Move and updated listeners 2021-11-27 17:01:25 +01:00
b702a4030f Reworked dropBomb and DropMine + reordered tests 2021-11-26 16:04:27 +01:00
360a84c403 Fix ArrayOutOfBoundException when we didn't have a winner 2021-11-18 11:06:53 +01:00
e2bd1a8bf6 Improve Shot Action and shotActionTest 2021-11-18 10:58:46 +01:00
8ca2326c89 Added 1 test 2021-11-07 15:58:55 +01:00
cb4c020fe6 Improved actions consistency 2021-11-07 15:36:16 +01:00
4b5f9b719d Improved interaction with box 2021-11-07 15:15:27 +01:00
01d855435e Improved Move Action 2021-11-05 17:33:42 +01:00
Valentin Valentin
a2270d5de0 Ajout de la classe Cell et GUI, début d'implémentation de certaines de leurs méthodes. 2021-11-05 15:42:06 +01:00
Katchan
a7775f9c2a Optimize imports 2021-11-05 15:36:03 +01:00
Katchan
3ccc26592c Add differents ComputerPlayer class + refactor calls 2021-11-05 15:35:25 +01:00
a2ebb5195c Add players' classes (dps, tank and support) 2021-11-05 13:50:02 +01:00
Katchan
4ac571ad09 Optimize import 2021-10-28 23:23:10 +02:00
Katchan
8a35d22b58 Add basis Play test and Shot test 2021-10-28 23:21:53 +02:00
Katchan
2322462ab3 Add various changes on Pair toString, Firearm getter 2021-10-28 23:19:53 +02:00
Katchan
19e5f19b19 Add increment function 2021-10-28 23:18:31 +02:00
Katchan
785e28e6a9 Implement all action function 2021-10-28 23:17:12 +02:00
70439266e9 Fix encoding 2021-10-28 16:18:47 +02:00
5912b49356 Partially fix GridTest.java 2021-10-26 17:17:06 +02:00
3a31f8485d Merge branch 'testplay'
# Conflicts:
#	server/src/main/java/fr/lnl/game/server/games/Game.java
#	server/src/main/java/fr/lnl/game/server/games/action/DeployShield.java
#	server/src/main/java/fr/lnl/game/server/games/action/DropMine.java
2021-10-26 17:08:38 +02:00
2e86f71e94 Improved argument parser and fix a bug with grid not initialize on new instance 2021-10-26 16:04:12 +02:00
ad9ac682bb Create a view per player + improved arguments parser 2021-10-26 10:26:31 +02:00
4e2da3330a Added very basic view support + reworked players' fields in Game.java and Grid.java 2021-10-23 19:15:08 +02:00
Valentin Valentin
d6f2217554 Finalisation des classes DeployShield, DropBomb et DropMine 2021-10-22 08:17:50 +02:00
90 changed files with 1695 additions and 497 deletions

View File

@@ -21,7 +21,15 @@ javafx {
modules = [ 'javafx.controls', 'javafx.graphics' ]
}
compileJava {
options.encoding = 'UTF-8'
}
application {
// Define the main class for the application.
mainClassName = 'fr.lnl.game.client.App'
}
run {
standardInput = System.in
}

View File

@@ -1,4 +0,0 @@
package fr.lnl.game.client;
public abstract class AbstractView implements View {
}

View File

@@ -1,31 +1,147 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package fr.lnl.game.client;
import fr.lnl.game.client.listener.DisplayWinnerEvent;
import fr.lnl.game.client.view.AbstractView;
import fr.lnl.game.client.view.Terminal;
import fr.lnl.game.client.view.ViewManager;
import fr.lnl.game.client.view.Window;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.build.BuildStrategy;
import fr.lnl.game.server.games.grid.build.LockStrategy;
import fr.lnl.game.server.games.player.*;
import fr.lnl.game.server.listener.GameFinishEvent;
import fr.lnl.game.server.utils.CrashException;
import fr.lnl.game.server.utils.Point;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import static fr.lnl.game.server.MessageUtils.getMessage;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
public class App extends Application {
private static LinkedList<String> argsList;
public static HashMap<Player, ClientPlayer> playerList = new HashMap<>();
private static Game game;
private static ViewManager viewManager;
public static void main(String[] args) {
String result = getMessage();
System.out.println(result);
launch();
argsList = new LinkedList<>(Arrays.asList(args));
argsList.removeIf(s -> s.startsWith("-D") || s.equals("fr.lnl.game.client.App")); // remove given parameters from gradle
Class<? extends AbstractView> clazz;
try {
clazz = parseView();
} catch (IllegalArgumentException e) {
throw new CrashException(e.getMessage(), e);
}
if(clazz.equals(Terminal.class)) {
launchTerminal();
} else {
launch();
}
}
public static void startGame(ViewLambda lambda) throws IllegalArgumentException, InvocationTargetException, NoSuchMethodException,
InstantiationException, IllegalAccessException {
List<Player> players = parsePlayers();
Grid grid = new Grid(12, 12, players);
BuildStrategy buildStrategy = new LockStrategy(grid, 0.80F, 0.95F);
game = new Game(buildStrategy, players, new DisplayWinnerEvent());
for (Player player : game.getPlayers()) {
playerList.put(player, new ClientPlayer(player, lambda.createViewLambda(player)));
}
}
@Override
public void start(Stage stage) throws Exception {
System.out.println("Launching stage");
String javaVersion = System.getProperty("java.version");
String javafxVersion = System.getProperty("javafx.version");
Label l = new Label("Hello, JavaFX version " + javafxVersion + ", running on Java " + javaVersion + ".");
Scene scene = new Scene(new StackPane(l), 640, 480);
stage.setScene(scene);
stage.show();
public void start(Stage stage) {
try {
startGame(player -> new Window(stage, game, player));
} catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | InstantiationException
| IllegalAccessException e) {
throw new CrashException(e.getMessage(), e);
}
viewManager = new ViewManager(playerList, game, Window.class);
}
public static void launchTerminal() {
try {
startGame(player -> new Terminal(game, player));
} catch (IllegalArgumentException | InvocationTargetException | NoSuchMethodException | InstantiationException
| IllegalAccessException e) {
throw new CrashException(e.getMessage(), e);
}
viewManager = new ViewManager(playerList, game, Terminal.class);
}
public static List<Player> parsePlayers() throws IllegalArgumentException, NoSuchMethodException,
InvocationTargetException, InstantiationException, IllegalAccessException {
List<Player> playerList = new ArrayList<>();
Class<? extends AbstractPlayer> playerClass = null;
ClassPlayer classPlayer = null;
for(String str : argsList) {
switch (str) {
case "human" -> {
if(playerClass != null) {
playerList.add(createNewPlayer(playerClass,
classPlayer != null ? classPlayer : ClassPlayer.DEFAULT, playerList.size())
);
classPlayer = null;
}
playerClass = HumanPlayer.class;
}
case "computer" -> {
if(playerClass != null) {
playerList.add(createNewPlayer(playerClass,
classPlayer != null ? classPlayer : ClassPlayer.DEFAULT, playerList.size())
);
classPlayer = null;
}
playerClass = RandomComputerPlayer.class;
}
case "default" -> classPlayer = ClassPlayer.DEFAULT;
case "tank" -> classPlayer = ClassPlayer.TANK;
case "dps" -> classPlayer = ClassPlayer.DPS;
case "support" -> classPlayer = ClassPlayer.SUPPORT;
default -> throw new IllegalArgumentException("Unknown argument: " + str);
}
}
if(playerClass != null)
playerList.add(createNewPlayer(playerClass,
classPlayer != null ? classPlayer : ClassPlayer.DEFAULT, playerList.size())
);
return playerList;
}
private static Player createNewPlayer(Class<? extends AbstractPlayer> playerClass, ClassPlayer playerType,
int playerListSize) throws NoSuchMethodException, InvocationTargetException,
InstantiationException, IllegalAccessException {
return playerClass.getConstructor(Integer.class, Point.class, ClassPlayer.class)
.newInstance(playerListSize, null, playerType);
}
public static Class<? extends AbstractView> parseView() {
Class<? extends AbstractView> clazz;
if(!argsList.isEmpty()) {
if(argsList.get(0).equals("terminal")) {
clazz = Terminal.class;
} else if(argsList.get(0).equals("window")){
clazz = Window.class;
} else {
throw new IllegalArgumentException("Unknown argument: " + argsList.get(0));
}
argsList.removeFirst();
} else {
throw new IllegalArgumentException("No argument given");
}
return clazz;
}
public static ViewManager getViewManager() {
return viewManager;
}
public static Game getGame() {
return game;
}
}

View File

@@ -0,0 +1,15 @@
package fr.lnl.game.client;
import fr.lnl.game.client.view.View;
import fr.lnl.game.server.games.player.Player;
public record ClientPlayer(Player serverPlayer, View view) {
public Player getServerPlayer() {
return serverPlayer;
}
public View getView() {
return view;
}
}

View File

@@ -1,4 +0,0 @@
package fr.lnl.game.client;
public interface View {
}

View File

@@ -0,0 +1,11 @@
package fr.lnl.game.client;
import fr.lnl.game.client.view.View;
import fr.lnl.game.server.games.player.Player;
@FunctionalInterface
public interface ViewLambda {
View createViewLambda(Player player);
}

View File

@@ -1,4 +0,0 @@
package fr.lnl.game.client;
public class Window extends AbstractView {
}

View File

@@ -1,6 +0,0 @@
package fr.lnl.game.client.graphics;
import fr.lnl.game.client.AbstractView;
public class Terminal extends AbstractView {
}

View File

@@ -0,0 +1,41 @@
package fr.lnl.game.client.listener;
import fr.lnl.game.client.App;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.listener.AbstractModelListening;
import fr.lnl.game.server.listener.ModelListener;
import javafx.scene.control.Alert;
public class ButtonListener extends AbstractModelListening {
private final Game game;
public ButtonListener(Game game) {
this.game = game;
}
@Override
public void addListener(ModelListener e) {
this.listeners.add(e);
}
@Override
public void removalListener(ModelListener e) {
this.listeners.remove(e);
}
@Override
public void updateModel(Object event) {
Player player = game.getCurrentPlayer();
game.play();
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Un joueur ordinateur a joué");
alert.setHeaderText("Le joueur ordinateur numéro" + player.getId() + " a joué");
alert.setContentText("Il a joué l'action: " + game.getSelectedAction());
App.getViewManager().updateView();
alert.showAndWait();
}
}

View File

@@ -0,0 +1,19 @@
package fr.lnl.game.client.listener;
import fr.lnl.game.server.listener.ModelListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
public class ClientEventHandler implements EventHandler<ActionEvent> {
private final ModelListener listener;
public ClientEventHandler(ButtonListener listener) {
this.listener = listener;
}
@Override
public void handle(ActionEvent event) {
listener.updateModel(event);
}
}

View File

@@ -0,0 +1,12 @@
package fr.lnl.game.client.listener;
import fr.lnl.game.client.App;
import fr.lnl.game.server.listener.AbstractModelListening;
public class DisplayWinnerEvent extends AbstractModelListening {
@Override
public void updateModel(Object obj) {
App.getViewManager().displayWinner(App.getGame().getWinner());
}
}

View File

@@ -0,0 +1,15 @@
package fr.lnl.game.client.view;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.player.Player;
public abstract class AbstractView implements View {
protected final Player player;
protected Game game;
public AbstractView(Game game, Player player) {
this.game = game;
this.player = player;
}
}

View File

@@ -0,0 +1,57 @@
package fr.lnl.game.client.view;
import fr.lnl.game.server.games.grid.elements.Bomb;
import fr.lnl.game.server.games.grid.elements.EnergyBall;
import fr.lnl.game.server.games.grid.elements.Mine;
import fr.lnl.game.server.games.player.Player;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
/**
* classe qui a pour but de générer chaque case de la grid et de vérifier les entités présentes dessus
* (Mur, Joueur, Energie, Bombe, etc.)
*/
public class Cell extends Rectangle {
private static Image PLAYER_IMAGE = new Image("player.png");
private static Image ENERGY_BALL_IMAGE = new Image("energyBall.png");
private static Image BOMB_IMAGE = new Image("bomb.jpg");
private static Image MINE_IMAGE = new Image("mine.webp");
private static Image WALL_IMAGE = new Image("wall.jpg");
public Cell(int x, int y){
setWidth(Window.cellSize);
setHeight(Window.cellSize);
relocate(x*Window.cellSize,y*Window.cellSize);
setFill(Color.valueOf("#ffffff"));
setStroke(Color.DARKGRAY);
}
public static StackPane setImageObject(Object object){
StackPane sp = new StackPane();
Image in;
if(object instanceof Player){
in = PLAYER_IMAGE;
} else if(object instanceof EnergyBall){
in = ENERGY_BALL_IMAGE;
} else if(object instanceof Bomb){
in = BOMB_IMAGE;
} else if(object instanceof Mine){
in = MINE_IMAGE;
} else{
in = WALL_IMAGE;
}
ImageView iv = new ImageView(in);
iv.setFitHeight(40);
iv.setFitWidth(40);
sp.getChildren().add(iv);
return sp;
}
}

View File

@@ -0,0 +1,21 @@
package fr.lnl.game.client.view;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.player.Player;
public class Terminal extends AbstractView {
public Terminal(Game game, Player player) {
super(game, player);
}
public void show() {
System.out.println(game.getGrid().toString());
}
@Override
public void displayWinner(Player winner) {
System.out.println("Le joueur " + winner + " a gagné la partie");
}
}

View File

@@ -0,0 +1,10 @@
package fr.lnl.game.client.view;
import fr.lnl.game.server.games.player.Player;
public interface View {
void show();
void displayWinner(Player winner);
}

View File

@@ -0,0 +1,42 @@
package fr.lnl.game.client.view;
import fr.lnl.game.client.ClientPlayer;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.player.Player;
import java.util.HashMap;
public class ViewManager {
private final HashMap<Player, ClientPlayer> players;
private final Game game;
public ViewManager(HashMap<Player, ClientPlayer> players, Game game, Class<? extends View> viewType) {
this.players = players;
this.game = game;
if(viewType == Terminal.class) {
terminalView();
} else {
updateView();
}
}
public void updateView() {
players.get(game.getCurrentPlayer()).getView().show();
}
public void terminalView() {
while(true) {
Player player = game.getCurrentPlayer();
players.get(game.getCurrentPlayer()).getView().show();
game.play();
System.out.println("Le joueur ordinateur numéro " + player.getId() + " a joué");
System.out.println("Il a joué l'action: " + game.getSelectedAction());
}
}
public void displayWinner(Player winner) {
players.get(game.getCurrentPlayer()).getView().displayWinner(winner);
}
}

View File

@@ -0,0 +1,156 @@
package fr.lnl.game.client.view;
import fr.lnl.game.client.App;
import fr.lnl.game.client.listener.ButtonListener;
import fr.lnl.game.client.listener.ClientEventHandler;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.elements.*;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Pair;
import fr.lnl.game.server.utils.Point;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Window extends AbstractView {
public static final int cellSize = 40;
public static final int width = 24;
public static final int height = 16;
private final Stage stage;
public Window(Stage stage, Game game, Player player) {
super(game, player);
this.stage = stage;
}
public void show() {
Scene scene = new Scene(createContent());
stage.setScene(scene);
stage.setTitle("Game");
stage.setResizable(false);
stage.sizeToScene();
stage.show();
}
@Override
public void displayWinner(Player winner) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Fin du jeu");
alert.setHeaderText("La partie est terminé");
alert.setContentText("Un joueur " + winner + " a gagné");
App.getViewManager().updateView();
alert.showAndWait();
}
private Parent createContent() {
Pane principalPane = new Pane();
principalPane.setPrefSize(width * cellSize, height * cellSize); // TODO: 04/12/2021 A corriger -> doit plutôt s'adapter à la taille de la grid (grid.getRow() et grid.getColumn())
for (int i = 0; i < game.getGrid().getRow(); i++) {
for (int j = 0; j < game.getGrid().getColumn(); j++) {
Cell cell = new Cell(i, j);
principalPane.getChildren().add(cell);
}
}
Grid grid = game.getGrid();
for (int i = 0; i < grid.getRow(); i++) {
for (int j = 0; j < grid.getColumn(); j++) {
Pair<Player, Box> value = grid.getBoard().get(new Point(i, j));
if (value.getB() instanceof Wall || value.getB() instanceof EnergyBall || value.getB() instanceof Explosive) {
addToPrincipalPanel(value.getB(), principalPane, i, j);
}
if (value.getA() != null) {
addToPrincipalPanel(value.getA(), principalPane, i, j);
}
}
}
putStatePlayerPane(principalPane);
StackPane stateMoveTextPane = showMoveText();
stateMoveTextPane.setLayoutY(480);
principalPane.getChildren().add(stateMoveTextPane);
Button followingButton = new Button("SUIVANT");
followingButton.setOnAction(new ClientEventHandler(new ButtonListener(game)));
followingButton.setLayoutX(700);
followingButton.setLayoutY(600);
followingButton.setStyle("-fx-background-color: #a96806;");
followingButton.setTextFill(javafx.scene.paint.Color.WHITE);
principalPane.getChildren().add(followingButton);
return principalPane;
}
public void addToPrincipalPanel(Object object, Pane principalPane, int i, int j) {
StackPane sp = Cell.setImageObject(object);
sp.setLayoutY(i * cellSize);
sp.setLayoutX(j * cellSize);
principalPane.getChildren().add(sp);
}
// TODO: 07/12/2021 WARNING : générer autant de frames quil y a de joueurs,(à implémenter)
// TODO: 07/12/2021 Maintenant régler : Factorisation du code, Responsive
//à voir si on peut faire plus proprement les deux méthodes en dessous avec une List<StackPane> ?
public void putStatePlayerPane(Pane principalPane){
int Y = 0;
for(int i=0;i < game.getPlayers().size();i++){
StackPane sp = showStatePlayer(i);
sp.setLayoutX(480);
sp.setLayoutY(Y);
Y+=90;
principalPane.getChildren().add(sp);
}
}
public StackPane showStatePlayer(int playerNumber){
StackPane subSp = new StackPane();
String s = "Joueur " + (playerNumber+1) + "\n" +
"Energie : " + game.getPlayers().get(playerNumber).getEnergy() + "\n" +
"Arme : " + game.getPlayers().get(playerNumber).getWeapon() + "\n";
Text t = new Text(s);
Rectangle r = new Rectangle();
r.setWidth(500);
r.setHeight(90);
//à voir
if(game.getPlayers().get(playerNumber).getEnergy() <= 0){
r.setFill(Color.RED);
}else{
r.setFill(Color.GREEN);
}
r.setStrokeWidth(2);
r.setStroke(Color.BLACK);
subSp.getChildren().addAll(r,t);
return subSp;
}
//idem que au dessus
public StackPane showMoveText(){
StackPane subSp = new StackPane();
String s = "Joueur : " + (player.getId()+1) + "\n" +
"Vient de jouer : " + game.getSelectedAction() + "\n";
Text t = new Text(s);
Rectangle r = new Rectangle();
r.setWidth(478);
r.setHeight(165);
r.setStrokeWidth(2);
r.setStroke(Color.BLACK);
r.setFill(Color.WHITE);
subSp.getChildren().addAll(r,t);
return subSp;
}
}

View File

@@ -3,4 +3,6 @@ module client {
requires transitive javafx.graphics;
requires server;
exports fr.lnl.game.client;
exports fr.lnl.game.client.listener;
exports fr.lnl.game.client.view;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -1,16 +0,0 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package fr.lnl.game.client;
import fr.lnl.game.server.MessageUtils;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MessageUtilsTest {
@Test
public void testGetMessage() {
assertEquals("Hello World!", MessageUtils.getMessage());
}
}

1
gradle.properties Normal file
View File

@@ -0,0 +1 @@
org.gradle.jvmargs='-Dfile.encoding=utf-8'

View File

@@ -12,8 +12,12 @@ dependencies {
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
}
compileJava {
options.encoding = 'UTF-8'
}
application {
mainClassName = 'fr.lnl.game.server.games.grid.Grid'
mainClassName = 'fr.lnl.game.server.ServerMain'
}
test {

View File

@@ -1,10 +0,0 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package fr.lnl.game.server;
public class MessageUtils {
public static String getMessage() {
return "Hello World!";
}
}

View File

@@ -1,23 +1,9 @@
package fr.lnl.game.server;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.player.ComputerPlayer;
import fr.lnl.game.server.games.player.ClassPlayer;
import fr.lnl.game.server.games.player.Player;
public class ServerMain {
public static void main(String[] args) {
Player playerOne = new ComputerPlayer(1,null, ClassPlayer.DEFAULT);
Player playerTwo = new ComputerPlayer(2,null, ClassPlayer.DEFAULT);
Grid grid = new Grid(16,16,new Player[]{playerOne,playerTwo});
grid.initGrid();
grid.placePlayersBRUT();
grid.placeEnergyBallBRUT();
grid.placeInternWallBRUT();
Game game = new Game(grid,playerOne,playerTwo);
game.getGrid().printGrid();
throw new UnsupportedOperationException("Server standalone launch not supported, please use tests or launch the" +
" game from the client");
}
}

View File

@@ -1,57 +1,136 @@
package fr.lnl.game.server.games;
import fr.lnl.game.server.games.action.*;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.build.BuildStrategy;
import fr.lnl.game.server.games.grid.elements.CountdownBox;
import fr.lnl.game.server.games.player.ComputerPlayer;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.listener.AbstractModelListening;
import fr.lnl.game.server.listener.GameFinishEvent;
import fr.lnl.game.server.listener.ModelListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Game {
Grid grid;
Player player_One;
Player player_Two;
Player current_player;
ArrayList<Player> players;
private final BuildStrategy buildStrategy;
private final Grid grid;
private final List<Player> players;
private final ModelListener gameFinishEvent;
private final AbstractModelListening displayWinnerEvent;
private Player currentPlayer;
private Action selectedAction = null;
public Game(Grid grid, Player player_One, Player player_Two){
this.player_One = player_One;
this.player_Two = player_Two;
this.current_player = player_One;
this.grid = grid;
players = new ArrayList<Player>(Arrays.asList(player_One, player_Two));
}
public boolean isOver(){
return players.size() == 1;
}
public Player getWinner(){
// Quentin: simple avis: appel de isOver pas forcément nécessaire, puisqu'on appelera surement getWinner après
// un appel a isOver retournant true
if(isOver()){
return players.get(0);
public Game(BuildStrategy buildStrategy, List<Player> players, AbstractModelListening displayWinnerEvent) throws IllegalArgumentException {
this.grid = buildStrategy.getGrid();
if(players.size() < 2)
throw new IllegalArgumentException("The game need 2 or more player to start");
if(players.size() > grid.getNumberNeutralBox()){
throw new IllegalArgumentException("There are too many players for the number of box available");
}
return null;
this.buildStrategy = buildStrategy;
this.players = players;
this.currentPlayer = players.get(0);
this.gameFinishEvent = new GameFinishEvent(this);
this.displayWinnerEvent = displayWinnerEvent;
initGame();
}
public void initGame(){
buildStrategy.initPlacePlayers();
currentPlayer.setActions(generateAndGetPlayerActions(currentPlayer));
}
public void play() {
if (currentPlayer instanceof ComputerPlayer player) {
selectedAction = player.choseAction();
}
selectedAction.doAction();
countdownGridElementsUpdate();
nextCurrentPlayer();
currentPlayer.setActions(generateAndGetPlayerActions(currentPlayer));
if(isOver()) {
gameFinishEvent.updateModel(null);
}
}
private void countdownGridElementsUpdate() {
List<CountdownBox> countdownBoxes = this.getGrid().getAllCountdownElements();
countdownBoxes.forEach(CountdownBox::update);
}
public List<Action> generateAndGetPlayerActions(Player player) {
List<Action> actions = new ArrayList<>();
for(Direction direction : Direction.values()) {
try {
actions.add(new Move(this, player, direction));
} catch (NotValidDirectionException ignored){}
try {
new DropBomb(this, player, direction);
} catch (NotValidDirectionException ignored) {}
try {
new DropMine(this, player, direction);
} catch (NotValidDirectionException ignored) {}
try {
actions.add(new Shot(this, player, direction));
} catch (NotValidDirectionException | NoMoreBulletInWeaponException ignored) {}
}
actions.addAll(Arrays.asList(new Nothing(), new DeployShield(player)));
return actions;
}
public Stream<Player> getPlayersAlive() {
return players.parallelStream().filter(Player::isAlive);
}
public boolean isOver() {
return getPlayersAlive().count() <= 1;
}
public Player getWinner() {
// On part du principe que isOver est forcément appelé avant d'appeler getWinner
return getPlayersAlive().findFirst().orElse(null);
}
public Player getCurrentPlayer() {
return current_player;
return currentPlayer;
}
public void setCurrent_player(Player current_player) {
this.current_player = current_player;
/**
* Change player to the next available in the list
*/
public void nextCurrentPlayer() {
do {
int index = players.indexOf(currentPlayer) + 1;
if(index == players.size())
index = 0;
setCurrentPlayer(players.get(index));
} while(!currentPlayer.isAlive()); // On arrête la boucle dès qu'on trouve un joueur en vie
currentPlayer.setShieldDeploy(false); // on reset son état
}
public void decrementPlayers(Player player){
players.remove(player);
public void setCurrentPlayer(Player current_player) {
this.currentPlayer = current_player;
}
public Grid getGrid() {
return grid;
}
public ArrayList<Player> getPlayers() {
public List<Player> getPlayers() {
return players;
}
public Action getSelectedAction() {
return selectedAction;
}
public AbstractModelListening getDisplayWinnerEvent() {
return displayWinnerEvent;
}
}

View File

@@ -0,0 +1,8 @@
package fr.lnl.game.server.games;
public enum InterfaceAction {
SELECT_ACTION,
DIALOG_TO_CONTINUE_COMPUTER_IA
}

View File

@@ -1,15 +1,35 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
import java.util.List;
import java.util.Random;
public abstract class AbstractAction implements Action {
private Game game;
public AbstractAction(Game game){
protected final Game game;
protected final Player player;
public AbstractAction(Game game, Player player){
this.game = game;
this.player = player;
}
protected Game getGame() {
return game;
protected Point choseRandomPoint(List<Point> getValidPoint) {
Point point = null;
switch (getValidPoint.size()) {
case 0:
break;
case 1:
point = getValidPoint.get(0);
break;
default: {
Random random = new Random();
point = getValidPoint.get(random.nextInt(0, getValidPoint.size()));
}
}
return point;
}
}

View File

@@ -1,8 +1,13 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.utils.Point;
import java.util.List;
public interface Action {
void doAction();
boolean isPossible();
List<Point> getValidPoint();
}

View File

@@ -1,16 +1,20 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
import java.util.List;
public class DeployShield extends AbstractAction {
public DeployShield(Game game){
super(game);
public DeployShield(Player player){
super(null, player);
}
@Override
public void doAction(){
getGame().getCurrentPlayer().setShieldDeploy(true);
getGame().getCurrentPlayer().decrementEnergy(getGame().getCurrentPlayer().getClassPlayer().getShieldCost());
player.setShieldDeploy(true);
player.decrementEnergy(player.getClassPlayer().getShieldCost());
}
@Override
@@ -18,6 +22,11 @@ public class DeployShield extends AbstractAction {
return true;
}
@Override
public List<Point> getValidPoint() {
return null;
}
}

View File

@@ -0,0 +1,31 @@
package fr.lnl.game.server.games.action;
public enum Direction {
UP(-1, 0, true),
DOWN(1, 0, true),
LEFT(0, -1, false),
RIGHT(0, 1, false);
private final int deltaX;
private final int deltaY;
private final boolean isVertical;
Direction(int i, int i1, boolean isVertical) {
this.deltaX = i;
this.deltaY = i1;
this.isVertical = isVertical;
}
public int getDeltaX() {
return deltaX;
}
public int getDeltaY() {
return deltaY;
}
public boolean isVertical() {
return isVertical;
}
}

View File

@@ -1,29 +1,19 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.utils.Point;
import java.util.List;
import fr.lnl.game.server.games.grid.elements.Bomb;
import fr.lnl.game.server.games.player.Player;
public class DropBomb extends DropObject {
public DropBomb(Game game){
super(game);
public DropBomb(Game game, Player player, Direction direction) throws NotValidDirectionException {
super(game, player, direction);
}
@Override
public void doAction() {
}
@Override
public boolean isPossible() {
return super.isPossible();
}
@Override
public List<Point> getValidPoint() {
return super.getValidPoint();
game.getGrid().getBoard().get(point).setB(new Bomb(point, game));
player.decrementEnergy(player.getClassPlayer().getBombCost());
}
}

View File

@@ -1,34 +1,20 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.Mine;
import fr.lnl.game.server.utils.Point;
import java.util.List;
import java.util.Random;
import fr.lnl.game.server.games.grid.elements.Mine;
import fr.lnl.game.server.games.player.Player;
public class DropMine extends DropObject {
public DropMine(Game game){
super(game);
public DropMine(Game game, Player player, Direction direction) throws NotValidDirectionException {
super(game, player, direction);
}
@Override
public void doAction() {
List<Point> points = getValidPoint();
Random random = new Random();
Point point = points.get(random.nextInt(0,points.size()-1));
Mine mine = new Mine();
getGame().getGrid().getBoard().get(point).setB(mine);
getGame().getCurrentPlayer().decrementEnergy(getGame().getCurrentPlayer().getClassPlayer().getMineCost());
}
@Override
public boolean isPossible() {
return super.isPossible();
}
@Override
public List<Point> getValidPoint() {
return super.getValidPoint();
game.getGrid().getBoard().get(point).setB(new Mine());
game.getCurrentPlayer().decrementEnergy(player.getClassPlayer().getMineCost());
}
}

View File

@@ -1,42 +1,45 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.Box;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.Wall;
import fr.lnl.game.server.games.grid.elements.Box;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Pair;
import fr.lnl.game.server.utils.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
public abstract class DropObject extends AbstractAction {
public DropObject(Game game){
super(game);
}
protected final Point point;
@Override
public void doAction() {
public DropObject(Game game, Player player, Direction direction) throws NotValidDirectionException {
super(game, player);
List<Point> points = getValidPoint();
Point playerPosition = player.getPosition();
Point dropDirection = new Point(playerPosition.getA() + direction.getDeltaX(), playerPosition.getB() + direction.getDeltaY());
if(!points.contains(dropDirection)) {
throw new NotValidDirectionException(direction + " isn't a valid position");
}
this.point = dropDirection;
}
@Override
public boolean isPossible() {
return getValidPoint().isEmpty();
return !getValidPoint().isEmpty();
}
public List<Point> getValidPoint() {
List<Point> listMoves = new LinkedList<>();
HashMap<Point, Pair<Player, Box>> board = getGame().getGrid().getBoard();
Point position = getGame().getCurrentPlayer().getPoint();
List<Point> listMoves = new ArrayList<>();
HashMap<Point, Pair<Player, Box>> board = game.getGrid().getBoard();
Point position = player.getPosition();
for (int row = -1; row <= 1; row++) {
for (int column = -1; column <= 1; column++) {
if(Grid.caseisValid(position.getA(),row,position.getB(),column)){
if(game.getGrid().boardPositionIsValid(position.getA(),row,position.getB(),column)){
Point neighbour = new Point(position.getA() + row, position.getB() + column);
Pair<Player, Box> state = board.get(neighbour);
if(state.getA() == null || state.getB() instanceof Wall){
if(state.getA() == null && state.getB() == null){
listMoves.add(neighbour);
}
}

View File

@@ -1,32 +1,42 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.Box;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.Wall;
import fr.lnl.game.server.games.grid.elements.Box;
import fr.lnl.game.server.games.grid.elements.InteractiveBox;
import fr.lnl.game.server.games.grid.elements.Wall;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Pair;
import fr.lnl.game.server.utils.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class Move extends AbstractAction {
public Move(Game game) {
super(game);
private final Point point;
public Move(Game game, Player player, Direction direction) throws NotValidDirectionException {
super(game, player);
List<Point> points = getValidPoint();
Point playerPosition = player.getPosition();
Point newPosition = new Point(playerPosition.getA() + direction.getDeltaX(), playerPosition.getB() + direction.getDeltaY());
if(!points.contains(newPosition)) {
throw new NotValidDirectionException(direction + " isn't a valid position");
}
this.point = newPosition;
}
@Override
public void doAction() {
List<Point> points = getValidPoint();
Random random = new Random();
Point nextPositon = points.get(random.nextInt(0,points.size() - 1));
Player player = getGame().getCurrentPlayer();
getGame().getGrid().getBoard().get(player.getPoint()).setA(null);
getGame().getGrid().getBoard().get(nextPositon).setA(player);
game.getGrid().getBoard().get(player.getPosition()).setA(null);
game.getGrid().getBoard().get(this.point).setA(player);
player.setPosition(this.point);
player.decrementEnergy(player.getClassPlayer().getMoveCost());
Box box = game.getGrid().getBoard().get(this.point).getB();
if(box instanceof InteractiveBox interactiveBox) {
interactiveBox.interact(game.getGrid(), player, this.point);
}
}
@Override
@@ -34,17 +44,18 @@ public class Move extends AbstractAction {
return !getValidPoint().isEmpty();
}
@Override
public List<Point> getValidPoint() {
List<Point> listMoves = new LinkedList<>();
HashMap<Point, Pair<Player, Box>> board = getGame().getGrid().getBoard();
Point position = getGame().getCurrentPlayer().getPoint();
for (int row = -1; row <= 1; row++) {
for (int column = -1; column <= 1; column++) {
if(row == position.getA() + row || column == position.getB() + column){
if(Grid.caseisValid(position.getA(),row,position.getB(),column)){
Point neighbour = new Point(position.getA() + row, position.getB() + column);
List<Point> listMoves = new ArrayList<>();
HashMap<Point, Pair<Player, Box>> board = game.getGrid().getBoard();
Point position = player.getPosition();
for (int deltarow = -1; deltarow <= 1; deltarow++) {
for (int deltacolumn = -1; deltacolumn <= 1; deltacolumn++) {
if(deltarow == 0 || deltacolumn == 0){
if(game.getGrid().boardPositionIsValid(position.getA(),deltarow,position.getB(),deltacolumn)){
Point neighbour = new Point(position.getA() + deltarow, position.getB() + deltacolumn);
Pair<Player, Box> state = board.get(neighbour);
if(state.getA() == null || state.getB() instanceof Wall){
if(state.getA() == null && !(state.getB() instanceof Wall)){
listMoves.add(neighbour);
}
}
@@ -53,5 +64,4 @@ public class Move extends AbstractAction {
}
return listMoves;
}
}

View File

@@ -0,0 +1,9 @@
package fr.lnl.game.server.games.action;
public class NoMoreBulletInWeaponException extends Exception {
public NoMoreBulletInWeaponException() {
super();
}
}

View File

@@ -0,0 +1,9 @@
package fr.lnl.game.server.games.action;
public class NotValidDirectionException extends Exception {
public NotValidDirectionException(String message) {
super(message);
}
}

View File

@@ -1,12 +1,15 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.utils.Point;
import java.util.List;
public class Nothing extends AbstractAction {
public Nothing(Game game){
super(game);
public Nothing() {
super(null, null);
}
@Override
public void doAction(){
}
@@ -15,4 +18,9 @@ public class Nothing extends AbstractAction {
public boolean isPossible() {
return true;
}
@Override
public List<Point> getValidPoint() {
return null;
}
}

View File

@@ -1,19 +1,86 @@
package fr.lnl.game.server.games.action;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.elements.Wall;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.games.weapon.Weapon;
import fr.lnl.game.server.utils.Point;
import java.util.ArrayList;
import java.util.List;
public class Shot extends AbstractAction {
public Shot(Game game) {
super(game);
private final Point point;
private final Direction direction;
public Shot(Game game, Player player, Direction direction) throws NoMoreBulletInWeaponException, NotValidDirectionException {
super(game, player);
if(player.getWeapon().getBullet() == 0) {
throw new NoMoreBulletInWeaponException();
}
List<Point> points = getValidPoint();
Point playerPosition = player.getPosition();
Point shotDirection = new Point(playerPosition.getA() + direction.getDeltaX(), playerPosition.getB() + direction.getDeltaY());
if(!points.contains(shotDirection)) {
throw new NotValidDirectionException(direction + " isn't a valid position");
}
this.point = shotDirection;
this.direction = direction;
}
@Override
public void doAction() {
player.decrementEnergy(player.getClassPlayer().getShootCost());
int range = direction.isVertical() ? player.getWeapon().getVerticalDistance() : player.getWeapon().getHorizontalDistance();
for(int i=0; i < range; i++) {
Point point = new Point(this.point.getA() + (i * direction.getDeltaX()),
this.point.getB() + (i * direction.getDeltaY()));
Player player = game.getGrid().getBoard().get(point).getA();
if(player != null) {
player.decrementEnergy(player.getClassPlayer().getPenaltyShoot());
System.out.println("Not null: " + point);
} else {
System.out.println("null:" + point);
}
}
}
@Override
public boolean isPossible() {
return false;
return !getValidPoint().isEmpty();
}
@Override
public List<Point> getValidPoint() {
List<Point> listMoves = new ArrayList<>();
Point position = game.getCurrentPlayer().getPosition();
Weapon weapon = game.getCurrentPlayer().getWeapon();
for(Direction direction : Direction.values()) {
Point neighbour = seeNeighbour(position, direction.getDeltaX(), direction.getDeltaY(),
direction.isVertical() ? weapon.getVerticalDistance() : weapon.getHorizontalDistance());
if(neighbour != null)
listMoves.add(neighbour);
}
return listMoves;
}
public Point seeNeighbour(Point point, int deltaX, int deltaY, int range) {
if(range == 0)
return null;
for(int i = 0; i < range; i++) {
Point neighbour = new Point(point.getA() + deltaX + (i * deltaX), point.getB() + deltaY + (i * deltaY));
if(game.getGrid().boardPositionIsValid(point)) {
if(game.getGrid().getBoard().get(neighbour).getB() instanceof Wall) {
return null;
}
if(game.getGrid().getBoard().get(neighbour).getA() instanceof Player) {
System.out.println(game.getGrid().getBoard().get(neighbour).getA().getPosition());
return neighbour;
}
}
}
return null;
}
}

View File

@@ -1,4 +0,0 @@
package fr.lnl.game.server.games.grid;
public class Bomb extends Explosive{
}

View File

@@ -1,4 +0,0 @@
package fr.lnl.game.server.games.grid;
public interface Box {
}

View File

@@ -1,11 +0,0 @@
package fr.lnl.game.server.games.grid;
public class EnergyBall implements Box{
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return true; // no var to test
}
}

View File

@@ -1,4 +0,0 @@
package fr.lnl.game.server.games.grid;
public abstract class Explosive implements Box{
}

View File

@@ -1,77 +1,54 @@
package fr.lnl.game.server.games.grid;
import fr.lnl.game.server.games.grid.elements.*;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Cardinal;
import fr.lnl.game.server.utils.Pair;
import fr.lnl.game.server.utils.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Grid {
private HashMap<Point, Pair<Player, Box>> board;
private int row;
private int column;
private Player[] players;
private final HashMap<Point, Pair<Player, Box>> board;
private final int row;
private final int column;
private final List<Player> players;
public Grid(int row, int column, Player[] players){
public Grid(int row, int column, List<Player> players) {
this.row = row;
this.column = column;
this.players = players;
board = new HashMap<>();
}
public void initGrid(){
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
Box box;
if (i == 0 && j == 0) {
box = new Wall(Cardinal.NORTH_WEST, i, j);
} else if (i == 0 && j == column-1) {
box = new Wall(Cardinal.NORTH_EAST, i, j);
} else if (i == row-1 && j == 0) {
box = new Wall(Cardinal.SOUTH_WEST, i, j);
} else if (i == row-1 && j == column-1) {
box = new Wall(Cardinal.SOUTH_EAST, i, j);
} else if (i == 0) {
box = new Wall(Cardinal.NORTH, i, j);
} else if (i == row-1) {
box = new Wall(Cardinal.SOUTH, i, j);
} else if (j == 0) {
box = new Wall(Cardinal.WEST, i, j);
} else if (j == column-1) {
box = new Wall(Cardinal.EAST, i, j);
} else {
box = null;
public boolean boardPositionIsValid(int row, int deltaRow, int column, int deltaColumn){
return boardPositionIsValid(row + deltaRow, column + deltaColumn);
}
public boolean boardPositionIsValid(int row, int column) {
return row >= 0 && column >= 0 && row < this.row && column < this.column;
}
public boolean boardPositionIsValid(Point point) {
return boardPositionIsValid(point.getA(), point.getB());
}
public int getNumberNeutralBox(){
int countBox = 0;
for (int i = 1; i < row - 1; i++) {
for (int j = 1; j < column - 1; j++) {
Box box = board.get(new Point(i,j)).getB();
if(isNeutralBox(box)){
countBox++;
}
board.put(new Point(i,j), new Pair<>(null,box));
}
}
return countBox;
}
public void placePlayersBRUT(){
board.get(new Point(1,1)).setA(players[0]);
board.get(new Point(14,14)).setA(players[1]);
}
public void placeEnergyBallBRUT(){
board.get(new Point(2,3)).setB(new EnergyBall());
board.get(new Point(7,10)).setB(new EnergyBall());
}
public void placeInternWallBRUT(){
board.get(new Point(3,6)).setB(new Wall(Cardinal.NORTH,3,6));
board.get(new Point(7,14)).setB(new Wall(Cardinal.SOUTH,7,14));
board.get(new Point(10,7)).setB(new Wall(Cardinal.EAST,10,7));
board.get(new Point(14,2)).setB(new Wall(Cardinal.WEST,14,2));
}
public static boolean caseisValid(int row, int column, int deltaRow, int deltaColumn){
return row + deltaRow >= 0 && row + deltaRow < row && column + deltaColumn >= 0 && column + deltaColumn < column;
}
public HashMap<Point, Pair<Player, Box>> getBoard() {
return board;
public boolean isNeutralBox(Box box){
return !(box instanceof Wall) && !(box instanceof EnergyBall);
}
@Override
@@ -85,50 +62,30 @@ public class Grid {
str.append(" \033[0;34mP\033[0m");
}
else if (value.getB() instanceof Wall) {
if (((Wall) value.getB()).getCardinal() == Cardinal.NORTH) {
str.append(" \033[0;34m—\033[0m");
} else if (((Wall) value.getB()).getCardinal() == Cardinal.SOUTH) {
str.append(" \033[0;31m—\033[0m");
} else if (((Wall) value.getB()).getCardinal() == Cardinal.WEST) {
str.append(" \033[0;33m|\033[0m");
} else if (((Wall) value.getB()).getCardinal() == Cardinal.EAST) {
str.append(" \033[0;32m|\033[0m");
} else if (((Wall) value.getB()).getCardinal() == Cardinal.NORTH_EAST) {
str.append(" \033[0;32mN\033[0m");
} else if (((Wall) value.getB()).getCardinal() == Cardinal.NORTH_WEST) {
str.append(" \033[0;33mN\033[0m");
} else if (((Wall) value.getB()).getCardinal() == Cardinal.SOUTH_EAST) {
str.append(" \033[0;32mS\033[0m");
} else if (((Wall) value.getB()).getCardinal() == Cardinal.SOUTH_WEST) {
str.append(" \033[0;33mS\033[0m");
}
str.append(" \033[0;32m□\033[0m");
}
else if(value.getB() instanceof EnergyBall){
str.append(" \033[0;31mO\033[0m");
str.append(" \033[0;31mE\033[0m");
}
else if(value.getB() instanceof Mine){
str.append(" \033[0;31mX\033[0m");
str.append(" \033[0;35mM\033[0m");
}
else if(value.getB() instanceof Bomb){
str.append(" \033[0;31mI\033[0m");
str.append(" \033[0;36mB\033[0m");
}
else {
str.append(" \033[0;31m.\033[0m");
str.append(" \033[0;37m.\033[0m");
}
}
}
return str.toString();
}
/**
* @deprecated modèle mvc non respecté
*/
@Deprecated
public void printGrid() {
System.out.println(this);
public HashMap<Point, Pair<Player, Box>> getBoard() {
return board;
}
public Player[] getPlayers() {
public List<Player> getPlayers() {
return players;
}
@@ -139,4 +96,14 @@ public class Grid {
public int getColumn() {
return column;
}
public List<CountdownBox> getAllCountdownElements() {
List<CountdownBox> list = new ArrayList<>();
for(Pair<Player, Box> element : getBoard().values()) {
if(element.getB() instanceof CountdownBox box) {
list.add(box);
}
}
return list;
}
}

View File

@@ -1,4 +0,0 @@
package fr.lnl.game.server.games.grid;
public class Mine extends Explosive{
}

View File

@@ -1,38 +0,0 @@
package fr.lnl.game.server.games.grid;
import fr.lnl.game.server.utils.Cardinal;
import java.util.Objects;
public class Wall implements Box {
private Cardinal cardinal;
private int x;
private int y;
public Wall(Cardinal cardinal, int x, int y){
this.cardinal = cardinal;
this.x = x;
this.y = y;
}
public Cardinal getCardinal() {
return cardinal;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Wall other = (Wall) o;
return Objects.equals(cardinal, other.cardinal) && x == other.x && y == other.y;
}
}

View File

@@ -0,0 +1,41 @@
package fr.lnl.game.server.games.grid.build;
import fr.lnl.game.server.games.grid.Grid;
public abstract class AbstractBuildStrategy implements BuildStrategy{
private final float WALL_PROBABILITY, ENERGY_PROBABILITY;
private final Grid GRID;
public AbstractBuildStrategy(Grid grid, float wallProbability, float energyProbability){
this.GRID = grid;
this.WALL_PROBABILITY = wallProbability;
this.ENERGY_PROBABILITY = energyProbability;
build();
}
public void build() {
initGrid();
initPlaceInternWall(WALL_PROBABILITY);
initPlaceEnergyBall(ENERGY_PROBABILITY);
}
private float getEnergyProbability() {
return ENERGY_PROBABILITY;
}
private float getWallProbability() {
return WALL_PROBABILITY;
}
public Grid getGrid() {
return GRID;
}
abstract void initGrid();
abstract void initPlaceEnergyBall(float probability);
abstract void initPlaceInternWall(float probability);
}

View File

@@ -0,0 +1,10 @@
package fr.lnl.game.server.games.grid.build;
import fr.lnl.game.server.games.grid.Grid;
public interface BuildStrategy {
void initPlacePlayers();
Grid getGrid();
}

View File

@@ -0,0 +1,117 @@
package fr.lnl.game.server.games.grid.build;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.elements.AbstractBox;
import fr.lnl.game.server.games.grid.elements.Box;
import fr.lnl.game.server.games.grid.elements.EnergyBall;
import fr.lnl.game.server.games.grid.elements.Wall;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Pair;
import fr.lnl.game.server.utils.Point;
import java.util.Random;
public class LockStrategy extends AbstractBuildStrategy{
public LockStrategy(Grid grid, float wallProbability, float energyProbability) {
super(grid, wallProbability, energyProbability);
}
@Override
void initGrid() {
for (int i = 0; i < getGrid().getRow(); i++) {
for (int j = 0; j < getGrid().getColumn(); j++) {
Box box;
if (i == 0 && j == 0) {
box = new Wall(i, j);
} else if (i == 0 && j == getGrid().getColumn()-1) {
box = new Wall(i, j);
} else if (i == getGrid().getRow()-1 && j == 0) {
box = new Wall(i, j);
} else if (i == getGrid().getRow()-1 && j == getGrid().getColumn()-1) {
box = new Wall(i, j);
} else if (i == 0) {
box = new Wall(i, j);
} else if (i == getGrid().getRow()-1) {
box = new Wall(i, j);
} else if (j == 0) {
box = new Wall(i, j);
} else if (j == getGrid().getColumn()-1) {
box = new Wall(i, j);
} else {
box = null;
}
getGrid().getBoard().put(new Point(i,j), new Pair<>(null,box));
}
}
}
@Override
void initPlaceEnergyBall(float probability) {
for (int i = 1; i < getGrid().getRow() - 1; i++) {
for (int j = 1; j < getGrid().getColumn() - 1; j++) {
if(Math.random() >= probability){
Point point = new Point(i,j);
if(!(getGrid().getBoard().get(point).getB() instanceof Wall)){
getGrid().getBoard().get(point).setB(new EnergyBall());
}
}
}
}
}
@Override
void initPlaceInternWall(float probability) {
for (int i = 1; i < getGrid().getRow() - 1; i++) {
for (int j = 1; j < getGrid().getColumn() - 1; j++) {
if(Math.random() >= probability){
Point point = new Point(i,j);
if(getIllusionNumberWallNeighbour(point) <= 3){
getGrid().getBoard().get(point).setB(new Wall(i,j));
}
else{
getGrid().getBoard().get(point).setB(new AbstractBox());
getGrid().getBoard().get(point).getB().setLock(true);
}
}
}
}
}
@Override
public void initPlacePlayers() {
Random random = new Random();
Box boxTargeted;
Player playerTargeted;
Point point;
for (Player player: getGrid().getPlayers()) {
do{
int i = random.nextInt(1,getGrid().getRow() - 1);
int j = random.nextInt(1,getGrid().getColumn() - 1);
point = new Point(i,j);
Pair<Player,Box> pairTargeted = getGrid().getBoard().get(point);
boxTargeted = pairTargeted.getB();
playerTargeted = pairTargeted.getA();
}while(playerTargeted != null || !getGrid().isNeutralBox(boxTargeted));
getGrid().getBoard().get(point).setA(player);
player.setPosition(point);
}
}
public int getIllusionNumberWallNeighbour(Point point){
int countWall = 0;
for (int deltaRow = -1; deltaRow <= 1; deltaRow++){
for (int deltaColomn = -1; deltaColomn <= 1; deltaColomn++) {
Point neighbour = new Point(point.getA() + deltaRow, point.getB() + deltaColomn);
if (getGrid().boardPositionIsValid(neighbour)) {
Box box = getGrid().getBoard().get(neighbour).getB();
if (box != null) {
if (box instanceof Wall || box.isLock()) {
countWall++;
}
}
}
}
}
return countWall;
}
}

View File

@@ -0,0 +1,21 @@
package fr.lnl.game.server.games.grid.elements;
public class AbstractBox implements Box{
boolean lock;
public AbstractBox(){
lock = false;
}
@Override
public void setLock(boolean lock) {
this.lock = lock;
}
@Override
public boolean isLock() {
return lock;
}
}

View File

@@ -0,0 +1,50 @@
package fr.lnl.game.server.games.grid.elements;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
public class Bomb extends Explosive implements CountdownBox {
private final Point point;
private final Game game;
private int counter = 3;
private static int EXPLOSION_SIZE = 4;
public Bomb(Point point, Game game) {
this.point = point;
this.game = game;
counter = counter * game.getPlayers().size();
}
@Override
public void interact(Grid grid, /* Nullable */ Player player, Point position) {
if(player != null)
player.decrementEnergy(player.getClassPlayer().getPenaltyBomb());
super.interact(grid, player, position);
}
@Override
public void update() {
counter--;
if(counter == 0) {
for(int i = -EXPLOSION_SIZE; i < EXPLOSION_SIZE; i++) {
for(int j = -EXPLOSION_SIZE; j < EXPLOSION_SIZE; j++) {
if(pythagoras(i, j) <= EXPLOSION_SIZE) { // recherche en cercle, pas en carré
Grid grid = game.getGrid();
Point position = new Point(point.getA() + i, point.getB() + j);
if(position.getA() >= 0 && position.getA() < grid.getRow()
&& position.getB() >= 0 && position.getB() < grid.getColumn()) {
interact(grid, null, position);
}
}
}
}
}
}
public double pythagoras(double a, double b) {
return Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
}
}

View File

@@ -0,0 +1,7 @@
package fr.lnl.game.server.games.grid.elements;
public interface Box {
boolean isLock();
void setLock(boolean lock);
}

View File

@@ -0,0 +1,7 @@
package fr.lnl.game.server.games.grid.elements;
public interface CountdownBox {
void update();
}

View File

@@ -0,0 +1,20 @@
package fr.lnl.game.server.games.grid.elements;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
public class EnergyBall extends AbstractBox implements InteractiveBox{
@Override
public boolean equals(Object o) {
if (this == o) return true;
return o != null && getClass() == o.getClass();// no var to test
}
@Override
public void interact(Grid grid, Player player, Point position) {
player.incrementEnergy(player.getClassPlayer().getGainEnergy());
grid.getBoard().get(position).setB(null);
}
}

View File

@@ -0,0 +1,13 @@
package fr.lnl.game.server.games.grid.elements;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
public abstract class Explosive extends AbstractBox implements InteractiveBox {
@Override
public void interact(Grid grid, Player player, Point position) {
grid.getBoard().get(position).setB(null);
}
}

View File

@@ -0,0 +1,12 @@
package fr.lnl.game.server.games.grid.elements;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
public interface InteractiveBox {
void interact(Grid grid, Player player, Point position);
}

View File

@@ -0,0 +1,14 @@
package fr.lnl.game.server.games.grid.elements;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
public class Mine extends Explosive{
@Override
public void interact(Grid grid, Player player, Point position) {
player.decrementEnergy(player.getClassPlayer().getPenaltyMine());
super.interact(grid, player, position);
}
}

View File

@@ -0,0 +1,29 @@
package fr.lnl.game.server.games.grid.elements;
public class Wall extends AbstractBox {
private final int x;
private final int y;
public Wall(int x, int y){
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Wall other = (Wall) o;
return x == other.x && y == other.y;
}
}

View File

@@ -4,78 +4,102 @@ import fr.lnl.game.server.games.action.Action;
import fr.lnl.game.server.games.weapon.Weapon;
import fr.lnl.game.server.utils.Point;
import java.util.List;
public abstract class AbstractPlayer implements Player {
private int id;
private Point point;
private final int id;
private Point position;
private int energy;
private Weapon weapon;
private boolean shieldDeploy;
private Action[] actions;
private ClassPlayer classPlayer;
private List<Action> actions;
private final ClassPlayer classPlayer;
public AbstractPlayer(int id, Point point, boolean shieldDeploy, ClassPlayer classPlayer) {
public AbstractPlayer(Integer id, Point position, boolean shieldDeploy, ClassPlayer classPlayer) {
this.id = id;
this.classPlayer = classPlayer;
this.energy = classPlayer.getEnergy();
this.weapon = classPlayer.getWeapon();
this.shieldDeploy = shieldDeploy;
this.point = point;
this.position = position;
}
@Override
public boolean isAlive(){
return true;
return energy > 0;
}
@Override
public int getId() {
return id;
}
@Override
public int getEnergy() {
return energy;
}
@Override
public Weapon getWeapon() {
return weapon;
}
@Override
public boolean isShieldDeploy() {
return shieldDeploy;
}
@Override
public void setEnergy(int energy) {
this.energy = energy;
}
@Override
public void setShieldDeploy(boolean shieldDeploy) {
this.shieldDeploy = shieldDeploy;
}
@Override
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
public Action[] getActions() {
@Override
public List<Action> getActions() {
return actions;
}
public void setActions(Action[] actions){
@Override
public void setActions(List<Action> actions){
this.actions = actions;
}
@Override
public ClassPlayer getClassPlayer() {
return classPlayer;
}
public Point getPoint() {
return point;
@Override
public Point getPosition() {
return position;
}
public void setPoint(Point point){
this.point = point;
@Override
public void setPosition(Point position){
if(position == null){
throw new IllegalArgumentException("Position is null");
}
this.position = position;
}
@Override
public void decrementEnergy(int energy){
this.energy -= energy;
}
@Override
public void incrementEnergy(int energy){
this.energy += energy;
}
}

View File

@@ -5,15 +5,17 @@ import fr.lnl.game.server.games.weapon.Weapon;
public enum ClassPlayer {
DEFAULT(800, 25, 40, 30, 40, 10, 800, 20, 20, 15, new Firearm());
DEFAULT(800, 25, 20, 30, 40, 10, 80, 40, 20, 15, new Firearm()),
TANK(1000, 20, 20, 17, 23, 13, 80, 27, 30, 22, new Firearm()),
DPS(800, 25, 16, 15, 20, 10, 80, 40, 40, 30, new Firearm()),
SUPPORT(600, 25, 20, 11, 15, 7, 80, 45, 45, 35, new Firearm());
private final int energy;
private final int shieldCost;
private final int shootCost;
private final int mineCost;
private final int bombCost;
private final int moveCost;
private final int gainEnergyCost;
private final int gainEnergy;
private final int penaltyShoot;
private final int penaltyBomb;
private final int penaltyMine;
@@ -21,14 +23,14 @@ public enum ClassPlayer {
ClassPlayer(int energy, int shieldCost, int shootCost, int mineCost, int bombCost, int moveCost,
int gainEnergyCost, int penaltyShoot, int penaltyBomb, int penaltyMine, Weapon weapon){
int gainEnergy, int penaltyShoot, int penaltyBomb, int penaltyMine, Weapon weapon){
this.energy = energy;
this.shieldCost = shieldCost;
this.shootCost = shootCost;
this.mineCost = mineCost;
this.bombCost = bombCost;
this.moveCost = moveCost;
this.gainEnergyCost = gainEnergyCost;
this.gainEnergy = gainEnergy;
this.penaltyShoot = penaltyShoot;
this.penaltyBomb = penaltyBomb;
this.penaltyMine = penaltyMine;
@@ -59,8 +61,8 @@ public enum ClassPlayer {
return moveCost;
}
public int getGainEnergyCost() {
return gainEnergyCost;
public int getGainEnergy() {
return gainEnergy;
}
public int getPenaltyShoot() {

View File

@@ -1,10 +1,13 @@
package fr.lnl.game.server.games.player;
import fr.lnl.game.server.games.action.Action;
import fr.lnl.game.server.utils.Point;
public class ComputerPlayer extends AbstractPlayer{
public abstract class ComputerPlayer extends AbstractPlayer {
public ComputerPlayer(int id, Point point, ClassPlayer classPlayer) {
super(id,point,false, classPlayer);
public ComputerPlayer(Integer id, Point point, ClassPlayer classPlayer) {
super(id, point, false, classPlayer);
}
public abstract Action choseAction();
}

View File

@@ -1,11 +1,11 @@
package fr.lnl.game.server.games.player;
import fr.lnl.game.server.utils.Point;
public class HumanPlayer extends AbstractPlayer {
public HumanPlayer(int id, Point point, ClassPlayer classPlayer) {
public HumanPlayer(Integer id, Point point, ClassPlayer classPlayer) {
super(id, point,false, classPlayer);
}
}

View File

@@ -4,19 +4,38 @@ import fr.lnl.game.server.games.action.Action;
import fr.lnl.game.server.games.weapon.Weapon;
import fr.lnl.game.server.utils.Point;
import java.util.List;
public interface Player {
Point getPoint();
Point getPosition();
boolean isAlive();
int getId();
int getEnergy();
Weapon getWeapon();
boolean isShieldDeploy();
void setEnergy(int energy);
void setShieldDeploy(boolean shieldDeploy);
void setWeapon(Weapon weapon);
Action[] getActions();
void setActions(Action[] actions);
List<Action> getActions();
void setActions(List<Action> actions);
ClassPlayer getClassPlayer();
void setPoint(Point point);
void setPosition(Point position);
void decrementEnergy(int energy);
void incrementEnergy(int energy);
}

View File

@@ -0,0 +1,30 @@
package fr.lnl.game.server.games.player;
import fr.lnl.game.server.games.action.Action;
import fr.lnl.game.server.games.action.Nothing;
import fr.lnl.game.server.utils.Point;
import java.util.Random;
public class RandomComputerPlayer extends ComputerPlayer {
public RandomComputerPlayer(Integer id, Point point, ClassPlayer classPlayer) {
super(id,point, classPlayer);
}
@Override
public Action choseAction() {
Action action = null;
switch (getActions().size()){
case 0 -> action = new Nothing();
case 1 -> action = getActions().get(0);
default -> {
Random random = new Random();
while (action == null || !action.isPossible()) {
action = getActions().get(random.nextInt(0,getActions().size()));
}
}
}
return action;
}
}

View File

@@ -0,0 +1,16 @@
package fr.lnl.game.server.games.player;
import fr.lnl.game.server.games.action.Action;
import fr.lnl.game.server.utils.Point;
public class StrategyComputerPlayer extends ComputerPlayer {
public StrategyComputerPlayer(Integer id, Point point, ClassPlayer classPlayer) {
super(id,point, classPlayer);
}
@Override
public Action choseAction() {
return null;
}
}

View File

@@ -8,23 +8,23 @@ public class Firearm implements Weapon{
public Firearm(){
this.bullet = 10;
this.horizontalDistance = 2;
this.horizontalDistance = 3;
this.verticalDistance = 3;
}
@Override
public int getBullet() {
return 0;
return this.bullet;
}
@Override
public int getHorizontalDistance() {
return 0;
return this.horizontalDistance;
}
@Override
public int getVerticalDistance() {
return 0;
return this.verticalDistance;
}
}

View File

@@ -0,0 +1,22 @@
package fr.lnl.game.server.listener;
import java.util.List;
public abstract class AbstractModelListening implements ModelListener {
protected List<ModelListener> listeners;
public void addListener(ModelListener e) {
this.listeners.add(e);
}
public void removalListener(ModelListener e) {
this.listeners.remove(e);
}
public void fireChange(){
for(ModelListener e : listeners){
e.updateModel(this);
}
}
}

View File

@@ -0,0 +1,23 @@
package fr.lnl.game.server.listener;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.utils.CrashException;
import java.util.concurrent.TimeUnit;
public class GameFinishEvent extends AbstractModelListening {
private final Object lock = new Object();
private final Game game;
public GameFinishEvent(Game game) {
this.game = game;
}
// TODO: 02/12/2021 méthode a revoir, notamment surement mettre un dialog sur la view Window et fermer dès que l'utilisateur a cliqué sur ok
@Override
public void updateModel(Object obj) {
game.getDisplayWinnerEvent().updateModel(null);
System.exit(0);
}
}

View File

@@ -1,6 +1,6 @@
package fr.lnl.game.server.model;
package fr.lnl.game.server.listener;
public interface ModelListener {
//à peut-être revoir
void updateModel(Object obj);
}

View File

@@ -1,18 +0,0 @@
package fr.lnl.game.server.model;
import java.util.List;
public abstract class AbstractModelListening implements ModelListener {
List<ModelListener> listeners;
public abstract void addListener(ModelListener e);
public abstract void removalListener(ModelListener e);
public void fireChange(){
for(ModelListener e : listeners){
e.updateModel(this);
}
}
}

View File

@@ -1,21 +0,0 @@
package fr.lnl.game.server.model;
public class ModelListening extends AbstractModelListening{
@Override
public void addListener(ModelListener e) {
this.listeners.add(e);
}
@Override
public void removalListener(ModelListener e) {
this.listeners.remove(e);
}
@Override
public void updateModel(Object obj) {
}
}

View File

@@ -1,12 +0,0 @@
package fr.lnl.game.server.utils;
public enum Cardinal {
NORTH,
SOUTH,
EAST,
WEST,
NORTH_EAST,
NORTH_WEST,
SOUTH_EAST,
SOUTH_WEST
}

View File

@@ -0,0 +1,12 @@
package fr.lnl.game.server.utils;
public class CrashException extends RuntimeException {
public CrashException(String message, Throwable cause) {
super(message, cause);
System.exit(1);
}
}

View File

@@ -41,4 +41,9 @@ public class Pair<A,B> {
public int hashCode() {
return Objects.hash(a, b);
}
@Override
public String toString() {
return "Pair[" + a + "," + b + ']';
}
}

View File

@@ -1,3 +1,12 @@
module server {
exports fr.lnl.game.server;
exports fr.lnl.game.server.games;
exports fr.lnl.game.server.games.player;
exports fr.lnl.game.server.games.grid;
exports fr.lnl.game.server.games.weapon;
exports fr.lnl.game.server.games.action;
exports fr.lnl.game.server.utils;
exports fr.lnl.game.server.listener;
exports fr.lnl.game.server.games.grid.elements;
exports fr.lnl.game.server.games.grid.build;
}

View File

@@ -1,7 +1,11 @@
package fr.lnl.game.server;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.action.*;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.elements.Bomb;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Point;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -16,13 +20,74 @@ public class ActionPlayerTest {
Mock mock = new Mock();
this.grid = mock.grid;
this.game = mock.game;
}
// TODO: 21/10/2021 Vérifier sur Move effectue la bonne action en pensant a appeller isPossible() avant et
// en checkant son résultat
@Test
public void moveActionTest() {
Assertions.assertEquals(game.getPlayers().get(0), game.getCurrentPlayer());
}
@Test
public void moveActionTest() {
Action move = null;
Point oldPoint = game.getCurrentPlayer().getPosition();
Direction savedDirection = null;
for(Direction direction : Direction.values()) {
try {
move = new Move(game, game.getCurrentPlayer(), direction);
savedDirection = direction;
break;
} catch (NotValidDirectionException ignored) {}
}
Assertions.assertNotNull(move);
move.doAction();
Point newPoint = game.getCurrentPlayer().getPosition();
Assertions.assertEquals(newPoint,
new Point(oldPoint.getA() + savedDirection.getDeltaX(),
oldPoint.getA() + savedDirection.getDeltaY()
)
);
}
@Test
public void DeployShieldTest() {
Player player = game.getCurrentPlayer();
Assertions.assertFalse(player.isShieldDeploy());
Action action = new DeployShield(player);
action.doAction();
Assertions.assertTrue(player.isShieldDeploy());
}
@Test
public void shotActionTest(){
Action shot = null;
for(Direction direction : Direction.values()) {
try {
shot = new Shot(game, game.getCurrentPlayer(), direction);
break;
} catch (NoMoreBulletInWeaponException | NotValidDirectionException ignored) {}
}
Assertions.assertNotNull(shot);
Player otherPlayer = game.getPlayers().get(1);
int currentEnergyOtherPlayer = otherPlayer.getEnergy();
int currentEnergyCurrentPlayer = game.getCurrentPlayer().getEnergy();
shot.doAction();
Assertions.assertEquals(currentEnergyCurrentPlayer - game.getCurrentPlayer().getClassPlayer().getShootCost(), game.getCurrentPlayer().getEnergy());
Assertions.assertEquals(currentEnergyOtherPlayer - otherPlayer.getClassPlayer().getPenaltyShoot(), otherPlayer.getEnergy());
}
@Test
public void dropBombActionTest() {
Player player = game.getCurrentPlayer();
Action action = null;
Direction savedDirection = null;
for(Direction direction : Direction.values()) {
try {
action = new DropBomb(game, game.getCurrentPlayer(), direction);
savedDirection = direction;
break;
} catch (NotValidDirectionException ignored) {}
}
Assertions.assertNotNull(action);
action.doAction();
Point bombPosition = new Point(player.getPosition().getA() + savedDirection.getDeltaX(), player.getPosition().getB() + savedDirection.getDeltaY());
Assertions.assertTrue(game.getGrid().getBoard().get(bombPosition).getB() instanceof Bomb);
}
}

View File

@@ -1,19 +1,17 @@
package fr.lnl.game.server;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.action.*;
import fr.lnl.game.server.games.grid.EnergyBall;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.Wall;
import fr.lnl.game.server.games.grid.elements.Box;
import fr.lnl.game.server.games.grid.elements.EnergyBall;
import fr.lnl.game.server.games.grid.elements.Wall;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Cardinal;
import fr.lnl.game.server.utils.Pair;
import fr.lnl.game.server.utils.Point;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class GridTest {
@@ -30,45 +28,47 @@ public class GridTest {
@Test
public void testGrid() {
// test Grid#initGrid()
assertEquals(new Wall(Cardinal.NORTH_WEST, 0, 0), grid.getBoard().get(new Point(0,0)).getB());
assertEquals(new Wall(Cardinal.NORTH_EAST, 0, grid.getColumn() - 1), grid.getBoard().get(new Point(0, grid.getColumn() - 1)).getB());
assertEquals(new Wall(Cardinal.SOUTH_WEST, grid.getRow() - 1, 0), grid.getBoard().get(new Point(grid.getRow() - 1, 0)).getB());
assertEquals(new Wall(Cardinal.SOUTH_EAST, grid.getRow() - 1, grid.getColumn() - 1), grid.getBoard().get(new Point(grid.getRow() - 1, grid.getColumn() - 1)).getB());
assertEquals(new Wall(0, 0), grid.getBoard().get(new Point(0,0)).getB());
assertEquals(new Wall(0, grid.getColumn() - 1), grid.getBoard().get(new Point(0, grid.getColumn() - 1)).getB());
assertEquals(new Wall(grid.getRow() - 1, 0), grid.getBoard().get(new Point(grid.getRow() - 1, 0)).getB());
assertEquals(new Wall(grid.getRow() - 1, grid.getColumn() - 1), grid.getBoard().get(new Point(grid.getRow() - 1, grid.getColumn() - 1)).getB());
// test placePlayersBRUT (mocked)
assertEquals(grid.getPlayers()[0], grid.getBoard().get(new Point(1, 1)).getA());
assertEquals(grid.getPlayers()[1], grid.getBoard().get(new Point(14, 14)).getA());
assertEquals(grid.getPlayers().get(0), grid.getBoard().get(new Point(7, 7)).getA());
assertEquals(grid.getPlayers().get(1), grid.getBoard().get(new Point(7, 8)).getA());
// test placeEnergyBallBRUT (mocked)
assertEquals(new EnergyBall(), grid.getBoard().get(new Point(2, 3)).getB());
assertEquals(new EnergyBall(), grid.getBoard().get(new Point(7, 10)).getB());
assertEquals(new EnergyBall(), grid.getBoard().get(new Point(8, 10)).getB());
}
@Test
public void testPlay(){
for (Player player: game.getPlayers()) {
player.setActions(new Action[]{new Move(game)});
}
System.out.println(game.getGrid().toString());
while (!game.isOver()){
Random random = new Random();
Action action = null;
do {
action = game.getCurrentPlayer().getActions()[random.nextInt(0,game.getCurrentPlayer().getActions().length -1)];
}while (!action.isPossible());
action.doAction();
System.out.println(game.getGrid().toString());
if(game.getCurrentPlayer().getEnergy() <= 0){
game.decrementPlayers(game.getCurrentPlayer());
}
else{
if(game.getCurrentPlayer() == game.getPlayers().get(0)){
game.setCurrent_player(game.getPlayers().get(1));
public void testLock() {
System.out.println("=================== GRID COMPLETE ====================");
System.out.println(grid.toString());
System.out.println("=================== GRID AVEC LOCK ===================");
StringBuilder str = new StringBuilder();
for (int i = 0; i < grid.getRow(); i++) {
str.append("\n");
for (int j = 0; j < grid.getColumn(); j++) {
Pair<Player, Box> value = grid.getBoard().get(new Point(i, j));
if(value.getB() != null){
if(value.getB().isLock()){
str.append(" \033[0;35mL\033[0m");
}
if(value.getB() instanceof Wall){
str.append(" \033[0;32m□\033[0m");
}
if(value.getB() instanceof EnergyBall){
str.append(" \033[0;31mE\033[0m");
}
}
else{
game.setCurrent_player(game.getPlayers().get(0));
else if(value.getA() != null){
str.append(" \033[0;34mP\033[0m");
}
else {
str.append(" \033[0;37m.\033[0m");
}
}
}
System.out.println("Le joueur gagnant : " + game.getWinner().getId());
System.out.println(str);
}
}

View File

@@ -1,46 +1,51 @@
package fr.lnl.game.server;
import fr.lnl.game.server.games.Game;
import fr.lnl.game.server.games.grid.EnergyBall;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.grid.Wall;
import fr.lnl.game.server.games.grid.build.BuildStrategy;
import fr.lnl.game.server.games.grid.build.LockStrategy;
import fr.lnl.game.server.games.grid.elements.EnergyBall;
import fr.lnl.game.server.games.grid.elements.Wall;
import fr.lnl.game.server.games.player.ClassPlayer;
import fr.lnl.game.server.games.player.ComputerPlayer;
import fr.lnl.game.server.games.player.Player;
import fr.lnl.game.server.utils.Cardinal;
import fr.lnl.game.server.games.player.RandomComputerPlayer;
import fr.lnl.game.server.listener.GameFinishEvent;
import fr.lnl.game.server.utils.Point;
import java.util.Arrays;
import java.util.List;
public class Mock {
Grid grid;
Game game;
public BuildStrategy buildStrategy;
public Game game;
public Grid grid;
public Mock() {
Player playerOne = new ComputerPlayer(1,null, ClassPlayer.DEFAULT);
Player playerTwo = new ComputerPlayer(2,null, ClassPlayer.DEFAULT);
this.grid = new Grid(16,16,new Player[]{playerOne,playerTwo});
grid.initGrid();
placePlayersBRUT();
placeEnergyBallBRUT();
placeInternWallBRUT();
game = new Game(grid,playerOne,playerTwo);
List<Player> players = Arrays.asList(new RandomComputerPlayer(1,null, ClassPlayer.DEFAULT),
new RandomComputerPlayer(2,null, ClassPlayer.DEFAULT));
this.buildStrategy = new LockStrategy(new Grid(16,16, players),0.80F, 0.95F);
game = new Game(buildStrategy, players, new MockDisplayWinner());
this.grid = buildStrategy.getGrid();
}
public void placePlayersBRUT(){
grid.getBoard().get(new Point(1,1)).setA(grid.getPlayers()[0]);
grid.getBoard().get(new Point(14,14)).setA(grid.getPlayers()[1]);
grid.getBoard().get(new Point(7,7)).setA(grid.getPlayers().get(0));
grid.getPlayers().get(0).setPosition(new Point(7, 7));
grid.getBoard().get(new Point(7,8)).setA(grid.getPlayers().get(1));
grid.getPlayers().get(1).setPosition(new Point(7, 8));
}
public void placeEnergyBallBRUT(){
grid.getBoard().get(new Point(2,3)).setB(new EnergyBall());
grid.getBoard().get(new Point(7,10)).setB(new EnergyBall());
grid.getBoard().get(new Point(8,10)).setB(new EnergyBall());
}
public void placeInternWallBRUT(){
grid.getBoard().get(new Point(3,6)).setB(new Wall(Cardinal.NORTH,3,6));
grid.getBoard().get(new Point(7,14)).setB(new Wall(Cardinal.SOUTH,7,14));
grid.getBoard().get(new Point(10,7)).setB(new Wall(Cardinal.EAST,10,7));
grid.getBoard().get(new Point(14,2)).setB(new Wall(Cardinal.WEST,14,2));
grid.getBoard().get(new Point(3,6)).setB(new Wall(3,6));
grid.getBoard().get(new Point(7,14)).setB(new Wall(7,14));
grid.getBoard().get(new Point(10,7)).setB(new Wall(10,7));
grid.getBoard().get(new Point(14,2)).setB(new Wall(14,2));
}
}

View File

@@ -0,0 +1,10 @@
package fr.lnl.game.server;
import fr.lnl.game.server.listener.AbstractModelListening;
public class MockDisplayWinner extends AbstractModelListening {
@Override
public void updateModel(Object obj) {
}
}

View File

@@ -0,0 +1,55 @@
package fr.lnl.game.server.games;
import fr.lnl.game.server.Mock;
import fr.lnl.game.server.games.action.Action;
import fr.lnl.game.server.games.action.Nothing;
import fr.lnl.game.server.games.grid.Grid;
import fr.lnl.game.server.games.player.Player;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Random;
public class GameTest {
private Grid grid;
private Game game;
@BeforeEach
public void mock() {
Mock mock = new Mock();
grid = mock.grid;
game = mock.game;
}
@Test
public void testPlay(){
while (!game.isOver()){
System.out.println(" Tour du joueur " + game.getCurrentPlayer().getId() + " : " +
game.getCurrentPlayer().getEnergy() + " points de vies restants");
Player player = game.getCurrentPlayer();
player.setActions(game.generateAndGetPlayerActions(player));
System.out.println(game.getGrid().toString());
Action action = null;
switch (player.getActions().size()){
case 0 -> action = new Nothing();
case 1 -> action = game.getCurrentPlayer().getActions().get(0);
default -> {
Random random = new Random();
while (action == null || !action.isPossible()) {
action = game.getCurrentPlayer().getActions().get(
random.nextInt(0,game.getCurrentPlayer().getActions().size())
);
}
}
}
action.doAction();
System.out.println("Action " + action + " : " + game.getCurrentPlayer().getEnergy() +
" points de vies restants");
game.nextCurrentPlayer();
}
System.out.println(game.getGrid().toString());
Player winner = game.getWinner();
System.out.println(winner != null ? ("Le joueur gagnant : " + winner.getId()) : ("Partie nulle, aucun gagnant"));
}
}