001import java.util.HashMap;
002import java.util.Set;
003
004// Lecture de fichier
005import java.io.FileReader;
006import java.io.BufferedReader;
007import java.io.FileNotFoundException;
008import java.util.Scanner;
009
010public class GameEngine {
011    private Parser aParser;
012    private UserInterface aGui;
013    private HashMap<String, Room> aAllRooms;
014    private Player aPlayer;
015
016    public GameEngine() {
017        this.aParser = new Parser();
018        this.createRooms();
019    }
020
021    /**
022     * Crée toutes les salles du jeu avec leurs entrées et sorties, défini la salle
023     * actuelle (Bitcoin), et enfin, lis le clavier
024     */
025    private void createRooms() {
026
027        this.aAllRooms = new HashMap<String, Room>();
028        // ? Items
029        Item vCpu1 = new Item("cpu1", "a CPU that provide you calcul power for mining.", 500);
030        Item vCpu2 = new Item("cpu2", "a CPU that provide you calcul power for mining", 1000);
031
032        Item vKeyDefi = new Item("keyDEFI", "a key that aims you open the defi room.", 0);
033
034        Item vKeyBtc = new Item("keyBTC", "a key that aims you open the ETH room from the BTC room.", 50);
035        Item vShiba = new Item("shiba", "a shiba that helps you pump the Shiba INU", 300);
036        Item vDoge = new Item("doge", "a dog that helps youu pump the Doge Coin.", 300);
037
038        Item vCake = new Item("cake", "a magical cake.", 500);
039
040        Item vBollinger = new Item("bollinger", "the bollinger bands indicator", 50);
041
042        // ? Rooms
043        Room vBitcoin = new Room("outside the main entrance of the crypto world", "img/gifs/bitcoin.gif");
044        vBitcoin.addItem(vKeyBtc);
045        this.aAllRooms.put("Bitcoin", vBitcoin);
046
047        Room vEthereum = new Room("in the second greatest empire of the world of crypto", "img/gifs/ethereum.gif");
048        vEthereum.addItem(vCake);
049        vEthereum.addItem(vKeyDefi);
050        this.aAllRooms.put("Ethereum", vEthereum);
051
052        Room vShitCoin = new Room("in the shit coin hall", "img/gifs/shitcoin.gif");
053        vShitCoin.addItem(vShiba);
054        vShitCoin.addItem(vDoge);
055        this.aAllRooms.put("ShitCoin", vShitCoin);
056
057        Room vHackLab = new Room("in a computing lab", "img/hacking.jpg");
058        this.aAllRooms.put("HackLab", vHackLab);
059
060        Room vTrading = new Room("in a computing office", "img/trading.png");
061        vTrading.addItem(vBollinger);
062        this.aAllRooms.put("Trading", vTrading);
063
064        Room vICO = new Room("in the ICO paradize", "img/ico.png");
065        this.aAllRooms.put("ICO", vICO);
066
067        Room vDefiBSC = new Room("in the DEFI BSC department", "img/defi_bsc.png");
068        this.aAllRooms.put("DefiBSC", vDefiBSC);
069
070        Room vDefiETH = new Room("in the DEFI ETH department", "img/defi_eth.png");
071        this.aAllRooms.put("DefiETH", vDefiETH);
072
073        Room vMining = new Room("in the mining room", "img/gifs/mining.gif");
074        vMining.addItem(vCpu1);
075        vMining.addItem(vCpu2);
076        this.aAllRooms.put("Mining", vMining);
077
078        Room vNFT = new TransporterRoom("in the NFT hall", "img/gifs/nft.gif",this.aAllRooms);
079        this.aAllRooms.put("NFT", vNFT);
080
081        // ? Doors
082        Door vBtcEthDoor = new Door(true, vKeyBtc);
083        Door vBtcMiningDoor = new Door(false, null);
084
085        Door vEthTradingDoor = new Door(false, null);
086        Door vEthDefiDoor = new Door(true, vKeyDefi);
087        Door vEthShitcoinDoor = new Door(false, null);
088
089        Door vShitcoinHackDoor = new Door(false, null);
090        Door vShitcoinIcoDoor = new Door(false, null);
091
092        Door vHackTradingDoor = new Door(false, null);
093
094        Door vIcoDefiDoor = new Door(false, null);
095
096        Door vDefiMiningDoor = new Door(false, null);
097
098        Door vDefiNftDoor = new Door(false, null);
099
100        Door vDefiDoor = new Door(false, null);
101
102        vBitcoin.setExit("north", vEthereum, vBtcEthDoor);
103        vBitcoin.setExit("west", vMining, vBtcMiningDoor);
104
105        vEthereum.setExit("north", vShitCoin, vEthShitcoinDoor);
106        vEthereum.setExit("east", vTrading, vEthTradingDoor);
107        vEthereum.setExit("south", vBitcoin, vBtcEthDoor);
108        vEthereum.setExit("west", vDefiETH, vEthDefiDoor);
109
110        vShitCoin.setExit("east", vHackLab, vShitcoinHackDoor);
111        vShitCoin.setExit("south", vEthereum, vEthShitcoinDoor);
112        vShitCoin.setExit("west", vICO, vShitcoinIcoDoor);
113
114        vHackLab.setExit("south", vTrading, vHackTradingDoor);
115        vHackLab.setExit("west", vShitCoin, vShitcoinHackDoor);
116
117        vTrading.setExit("north", vHackLab, vHackTradingDoor);
118        vTrading.setExit("west", vEthereum, vEthTradingDoor);
119
120        vICO.setExit("east", vShitCoin, vShitcoinIcoDoor);
121        vICO.setExit("south", vDefiETH, vIcoDefiDoor);
122
123        vDefiETH.setExit("north", vICO, vIcoDefiDoor);
124        vDefiETH.setExit("up", vDefiBSC, vDefiDoor);
125        vDefiETH.setExit("east", vEthereum, vEthDefiDoor);
126        vDefiETH.setExit("south", vMining, vDefiMiningDoor);
127        vDefiETH.setExit("west", vNFT, vDefiNftDoor);
128
129        vDefiBSC.setExit("down", vDefiETH, vDefiDoor);
130
131        vMining.setExit("north", vDefiETH, vDefiMiningDoor);
132        vMining.setExit("east", vBitcoin, vBtcMiningDoor);
133
134        vNFT.setExit("east", vDefiETH, vDefiNftDoor);
135
136        this.aPlayer = new Player(vBitcoin, this);
137        this.aPlayer.setCurrentRoom(vBitcoin);
138
139        Beamer vBeamer = new Beamer("beamer",
140                "an object that memorize the room where it is charged and allow you to be teleported to this room in the future.",
141                50, this.aPlayer, this);
142        vBitcoin.addItem(vBeamer);
143    }
144    public HashMap<String,Room> getRooms() {
145        return this.aAllRooms;
146    }
147    public void setGUI(final UserInterface pUserInterface) {
148        this.aGui = pUserInterface;
149        this.printWelcome();
150    }
151
152    /**
153     * Affiche le message de bienvenue
154     */
155    private void printWelcome() {
156        this.aGui.println("Welcome to the Trade Infinity Game!");
157        this.aGui.println("World of Blockchains is a new, incredibly boring trading and investing game.");
158        String vAllRooms = "All rooms :";
159        Set<String> allKeys = this.aAllRooms.keySet();
160        for (String vKey : allKeys) {
161            vAllRooms += " " + vKey;
162        }
163        this.aGui.println(vAllRooms);
164        this.aGui.println("Type 'help' if you need help.");
165        this.printLocationInfo();
166        if (this.aPlayer.getCurrentRoom().getImageName() != null) {
167            this.aGui.showImage(this.aPlayer.getCurrentRoom().getImageName());
168        }
169    }
170
171    /**
172     * Check si la commande est valide, si oui return true sinon return false
173     * 
174     * @param pCommand la commande a check
175     * @return true ou false en fonction de si la commande est valide
176     */
177    public void interpretCommand(final String pCommandLine) {
178        this.aGui.println("> " + pCommandLine);
179        Command vCommand = this.aParser.getCommand(pCommandLine);
180
181        if (vCommand.isUnknown()) {
182            this.aGui.println("I don't know what you mean...");
183        } else {
184            if (vCommand.getCommandWord().equals("go")) {
185                this.goRoom(vCommand);
186            } else if (vCommand.getCommandWord().equals("help")) {
187                this.printHelp();
188            } else if (vCommand.getCommandWord().equals("look")) {
189                this.look(vCommand);
190            } else if (vCommand.getCommandWord().equals("buy")) {
191                this.buy(vCommand);
192            } else if (vCommand.getCommandWord().equals("back")) {
193                this.back(vCommand);
194            } else if (vCommand.getCommandWord().equals("test")) {
195                this.test(vCommand);
196            } else if (vCommand.getCommandWord().equals("take")) {
197                this.take(vCommand);
198            } else if (vCommand.getCommandWord().equals("drop")) {
199                this.drop(vCommand);
200            } else if (vCommand.getCommandWord().equals("items")) {
201                this.items(vCommand);
202            } else if (vCommand.getCommandWord().equals("eat")) {
203                this.eat(vCommand);
204            } else if (vCommand.getCommandWord().equals("use")) {
205                this.use(vCommand);
206            } else if (vCommand.getCommandWord().equals("charge")) {
207                this.charge(vCommand);
208            } else if (vCommand.getCommandWord().equals("open")) {
209                this.open(vCommand);
210            } else if (vCommand.getCommandWord().equals("close")) {
211                this.close(vCommand);
212            }
213            if (vCommand.getCommandWord().equals("quit")) {
214                this.quit(vCommand);
215            }
216        }
217    }
218
219    /**
220     * Permet de quitter le jeu
221     * 
222     * @param pQuit commande quit
223     * @return true si on quitte le jeu sinon false
224     */
225    private void quit(final Command pQuit) {
226        if (pQuit.hasSecondWord()) {
227            this.aGui.println("Quit what ??");
228        } else {
229            this.aGui.disableButtons();
230            this.endGame();
231        }
232    }
233
234    /**
235     * Défini l'action de la commande look :
236     * look : donne des informations sur la salle actuelle, les items présents à
237     * l'intérieur et les sorties.
238     * look wallet : affiche l'argent du joueur.
239     * 
240     * @param pCommand commande look
241     */
242    private void look(final Command pCommand) {
243        if (pCommand.hasSecondWord()) {
244            if (pCommand.getSecondWord().equals("wallet")) {
245                this.aGui.println(this.aPlayer.getBalanceString());
246            } else {
247                Boolean vTest = false;
248                Set<String> allKeys = this.aPlayer.getCurrentRoom().getItems().keySet();
249                for (String vKey : allKeys) {
250                    if (vKey.equals(pCommand.getSecondWord())) {
251                        vTest = true;
252                        this.aGui
253                                .println("This is "
254                                        + this.aPlayer.getCurrentRoom().getItems().get(vKey).getDescription());
255                    }
256                }
257                if (!vTest) {
258                    this.aGui.println("I don't know what you are looking for.");
259                }
260            }
261        } else {
262            this.aGui.println(this.aPlayer.getCurrentRoom().getLongDescription());
263        }
264    }
265
266    /**
267     * Permet au joueur de manger
268     * 
269     * @param pCommand commande
270     */
271    private void eat(final Command pCommand) {
272        this.aGui.println(this.aPlayer.eatCake(pCommand));
273    }
274
275    /**
276     * Liste des items
277     * 
278     * @param pCommand commande
279     */
280    private void items(final Command pCommand) {
281        this.aGui.println(this.aPlayer.lookItems());
282    }
283
284    /**
285     * Défini l'action de la commande buy
286     * 
287     * @param pCommand commande buy crypto
288     */
289    private void buy(final Command pCommand) {
290        if (pCommand.hasSecondWord()) {
291            this.aGui.println("You have bought " + pCommand.getSecondWord());
292        } else {
293            this.aGui.println("Please tell me wich crypto currency you want to buy.");
294        }
295    }
296
297    /**
298     * Affiche un message d'aide
299     */
300    private void printHelp() {
301        this.aGui.println("You are lost. You are alone.");
302        this.aGui.println("Your command words are:" + this.aParser.getCommandString());
303    }
304
305    /**
306     * Permet de se déplacer
307     * 
308     * @param pCommand commande pour se déplacer, par exemple "go south"
309     */
310    private void goRoom(final Command pCommand) {
311        if (!pCommand.hasSecondWord()) {
312            this.aGui.println("Go where ?");
313            return;
314        }
315
316        String vDirection = pCommand.getSecondWord();
317        Room vNextRoom = aPlayer.getCurrentRoom().getExit(vDirection);
318        if (vNextRoom == null) {
319            this.aGui.println("There is no door !");
320            return;
321        } else {
322            Door vDoor = this.aPlayer.getCurrentRoom().getDoors().get(vDirection);
323            if(vDoor==null) {
324                this.aGui.println("There is no door !");
325            } else if (vDoor.getLocked()) {
326                this.aGui.println("The door is locked.");
327            } else {
328                this.aPlayer.changeRoom(vNextRoom);
329                this.printLocationInfo();
330                if (this.aPlayer.getCurrentRoom().getImageName() != null) {
331                    this.aGui.showImage(this.aPlayer.getCurrentRoom().getImageName());
332                }
333            }
334        }
335    }
336
337    /**
338     * Permet de retourner dans les salles précédentes
339     * 
340     * @param pCommand commande tapée au clavier
341     */
342    private void back(final Command pCommand) {
343        if (pCommand.hasSecondWord()) {
344            this.aGui.println("I don't understand what you are saying.");
345        } else if (this.aPlayer.getPrevRooms().empty()) {
346            this.aGui.println("There are no previous room.");
347        } else if (this.aPlayer.getCurrentRoom().isExit(this.aPlayer.getPrevRooms().peek())) {
348            this.aPlayer.goBack();
349            this.printLocationInfo();
350            if (this.aPlayer.getCurrentRoom().getImageName() != null) {
351                this.aGui.showImage(this.aPlayer.getCurrentRoom().getImageName());
352            }
353        } else {
354            this.aGui.println("There are no door to go back.");
355        }
356    }
357
358    /**
359     * Test le jeu à partir d'un fichier texte contenant les commandes voulues.
360     * 
361     * @param pCommand commande test fichier pour tester le jeu avec les commandes
362     *                 dans fichier.txt
363     */
364    private void test(final Command pCommand) {
365        if (!pCommand.hasSecondWord()) {
366            this.aGui.println("What file do you want for the test ?");
367        } else {
368            Scanner myFile = null;
369            try {
370                myFile = new Scanner(new BufferedReader(new FileReader("tests/" + pCommand.getSecondWord() + ".txt")));
371                while (myFile.hasNext()) {
372                    String aLigne = myFile.nextLine();
373                    this.interpretCommand(aLigne);
374                }
375            } catch (final FileNotFoundException e) {
376                this.aGui.println("Error : " + e.getMessage());
377            } finally {
378                if (myFile != null) {
379                    myFile.close();
380                }
381            }
382        }
383    }
384
385    /**
386     * Permet au joueur de prendre un item dans son iventaire.
387     * 
388     * @param pCommand take item
389     */
390    public void take(final Command pCommand) {
391        if (pCommand.hasSecondWord()) {
392            String vOutput = this.aPlayer.takeItem(pCommand.getSecondWord());
393            this.aGui.println(vOutput);
394        } else {
395            this.aGui.println("Take what ?");
396        }
397    }
398
399    /**
400     * Permet au joueur de déposé un item dans la salle actuelle
401     * 
402     * @param pCommand drop item
403     */
404    public void drop(final Command pCommand) {
405        if (pCommand.hasSecondWord()) {
406            String vOutput = this.aPlayer.dropItem(pCommand.getSecondWord());
407            this.aGui.println(vOutput);
408        } else {
409            this.aGui.println("Take what ?");
410        }
411    }
412
413    /**
414     * permet d'utiliser des items
415     * 
416     * @param pCommand commande
417     */
418    private void use(final Command pCommand) {
419        if (pCommand.hasSecondWord()) {
420            Beamer vBeamer = (Beamer) this.aPlayer.getItems().get(pCommand.getSecondWord());
421            if (vBeamer.equals(null)) {
422                this.aGui.println("You don't have " + pCommand.getSecondWord());
423            } else {
424                this.aGui.println(vBeamer.fire());
425            }
426        } else {
427            this.aGui.println("Use what ?");
428        }
429    }
430
431    /**
432     * Permet de charger un beamer.
433     * 
434     * @param pCommand commande
435     */
436    public void charge(final Command pCommand) {
437        if (pCommand.hasSecondWord()) {
438            Beamer vBeamer = (Beamer) this.aPlayer.getItems().get(pCommand.getSecondWord());
439            if (vBeamer == null) {
440                this.aGui.println("You don't have a " + pCommand.getSecondWord());
441            } else {
442                this.aGui.println(vBeamer.charge(this.aPlayer.getCurrentRoom()));
443            }
444        } else {
445            this.aGui.println("Charge what ?");
446        }
447    }
448
449    /**
450     * Ouvre une porte
451     * 
452     * @param pCommand commande
453     */
454    public void open(final Command pCommand) {
455        if (!pCommand.hasSecondWord()) {
456            this.aGui.println("Open wich door ?");
457        } else {
458            String vDirection = pCommand.getSecondWord();
459            if (this.aPlayer.getCurrentRoom().getDoors().get(vDirection) == null) {
460                this.aGui.println("There is no door to open in that direction.");
461            } else {
462                Door vDoor = this.aPlayer.getCurrentRoom().getDoors().get(vDirection);
463                Item vKey = vDoor.getGoodKey(this.aPlayer.getItems());
464                if (!vDoor.getLocked()) {
465                    this.aGui.println("The door is already open.");
466                } else if (vKey == null) {
467                    this.aGui.println(
468                            "You don't have key in your inventory or you don't have the good key to open this door.");
469                } else {
470                    this.aPlayer.getCurrentRoom().getDoors().get(vDirection).openDoor();
471                    this.aGui.println("The door is now open.");
472                }
473            }
474        }
475    }
476
477    /**
478     * ferme une porte
479     * 
480     * @param pCommand commande
481     */
482    public void close(final Command pCommand) {
483        if (!pCommand.hasSecondWord()) {
484            this.aGui.println("Close wich door ?");
485        } else {
486            String vDirection = pCommand.getSecondWord();
487            if (this.aPlayer.getCurrentRoom().getDoors().get(vDirection) == null) {
488                this.aGui.println("There is no door to close in that direction.");
489            } else {
490                Door vDoor = this.aPlayer.getCurrentRoom().getDoors().get(vDirection);
491                Item vKey = vDoor.getGoodKey(this.aPlayer.getItems());
492                if (vDoor.getLocked()) {
493                    this.aGui.println("The door is already close.");
494                } else if (vKey == null) {
495                    this.aGui.println(
496                            "You don't have key in your inventory or you don't have the good key to close this door.");
497                } else {
498                    this.aPlayer.getCurrentRoom().getDoors().get(vDirection).closeDoor();
499                    this.aGui.println("The door is now close.");
500                }
501            }
502        }
503    }
504
505    private void endGame() {
506        this.aGui.println("Thank you for playing.  Good bye.");
507        this.aGui.enable(false);
508    }
509
510    /**
511     * Affiche un message pour nous informer de l'endroit où l'on se trouve.
512     */
513    private void printLocationInfo() {
514        this.aGui.println(this.aPlayer.getCurrentRoom().getLongDescription());
515    }
516
517    /**
518     * Retourne l'endroit où l'on se trouve actuellement
519     * 
520     * @return retourne la description de la salle actuelle
521     */
522    public String getCurrentRoom() {
523        return this.aPlayer.getCurrentRoom().getDescription();
524    }
525
526    public UserInterface getGui() {
527        return this.aGui;
528    }
529} // Game