package de.ctdo.crashtest.game; import de.ctdo.crashtest.domotics.*; import de.ctdo.crashtest.gui.*; import de.ctdo.crashtest.irc.*; import de.ctdo.crashtest.mpd.IMPDController; import de.ctdo.crashtest.mpd.MPDController; public class TheGame implements StatemachineListener, GuiEventListener, IRCEventListener { private IGuiControl guiControl; private IIrcClient ircClient; private IStatemachine machine; private IBuntiClient bunti; private IMPDController mpdController; private IRelaisboard relaisboard; private int gamerRating = 3; private Thread discoThread; private boolean shouldStopDisco; private boolean gemActivated = false; public TheGame(IGuiControl guiControl) { this.guiControl = guiControl; this.ircClient = new IrcClient("crashtest", "#crashtest","irc.ctdo.de"); this.bunti = new BuntiClient("bunti.ctdo.de", 8080); this.mpdController = new MPDController("dampfradio.raum.ctdo.de"); this.relaisboard = new Relaisboard("/dev/ttyUSB0"); this.machine = new Statemachine(); initGame(); } private void initGame() { guiControl.addListener(this); ircClient.addListener(this); machine.addListener(this); machine.reset(); relaisboard.open(); resetDomotics(); } private void rate(int rating, String text) { gamerRating += rating; ircClient.say("rated: " + rating + " (" + gamerRating + ") " + text); if(gamerRating > 5) gamerRating = 5; if(gamerRating < 1) gamerRating = 1; } /** * Event listener for state change events from statemachine * @param newState the new game state from statemachine */ @Override public void stateChanged(Statemachine.state newState) { ircClient.say("New State: " + newState); switch (newState) { case NEUTRAL: discoStop(); bunti.setPar56(255,255,255); bunti.setLampel(false,false,false); machine.stopTimer(); break; case IDLE: gamerRating = 3; machine.stopTimer(); resetDomotics(); discoStop(); guiControl.setExtra(""); guiControl.setWall(""); mpdController.setVolume(50); mpdController.playSong("start", "mix"); bunti.setPar56(0,0,0); bunti.setLampel(false,false,false); guiControl.showCountDown(false); break; case ENTERED_ROOM: relaisboard.setRelais(7, false); // disable light barrier over relais mpdController.setVolume(70); mpdController.playSong("tidirium", "welcome"); bunti.setLampel(false,false,false); bunti.setPar56(20,0,100); guiControl.showCountDown(true); machine.startTimer(60*8); break; case TABLE_GAME_ONE: relaisboard.setRelais(6, true); // enable third green circle //guiControl.setWall("64K RAM SYSTEM 38911 BASIC BYTES FREE. **** COMMODORE 64 BASIC V2 ****"); mpdController.setVolume(70); mpdController.playSong("K2", "Der Berg Ruft"); bunti.setLampel(true,false,false); bunti.setPar56(20,0,100); guiControl.showCountDown(true); break; case TABLE_GAME_TWO: bunti.setLampel(false,true,false); bunti.setPar56(100,0,100); guiControl.showCountDown(true); break; case TABLE_GAME_THREE: bunti.setLampel(false,true,false); bunti.setPar56(255,35,0); guiControl.showCountDown(true); break; case TABLE_GAME_FOUR: mpdController.setVolume(60); mpdController.playSong("Mo-Do","9 Eins Zwei Polizei"); bunti.setLampel(false,true,false); bunti.setPar56(200,100,0); guiControl.showCountDown(true); break; case TABLE_GAME_FIVE: bunti.setLampel(false,true,false); bunti.setPar56(150,150,0); guiControl.showCountDown(true); break; case TABLE_GAME_SIX: //mpdController.setVolume(60); //mpdController.playSong("Zlatko & Jürgen","Großer Bruder"); bunti.setLampel(false,true,false); bunti.setPar56(100,200,0); guiControl.showCountDown(true); break; case TABLE_GAME_DONE: bunti.setLampel(false,false,true); bunti.setPar56(100,255,0); guiControl.showCountDown(true); machine.pauseTimer(true); // spieler haben 8 Minuten, wenn sie es in weniger als 4 minuten schaffen // gibts +1, in weniger als 2 minuten gibts +2 if(machine.getTimerSecondsLast() >= 6*60 ) { rate(2, "table game faster than 2 minutes"); } else if(machine.getTimerSecondsLast() > 4*60) { rate(1, "table game faster than 4 minutes"); } if(machine.getStateChangeCounter() > 100) { rate(-1, "more than 100 tries"); } sayScore(); relaisboard.setRelais(6, false); // disable third green circle relaisboard.blinkRelais(2, 700); // hint Button break; case ROKET_STARTED: mpdController.setVolume(50); mpdController.playSong("The Underdog Project", "Summer Jam"); mpdController.addToPlayList("Maximo Park", "Books of Boxes"); bunti.setLampel(false,true,false); bunti.setPar56(0, 255, 0); relaisboard.toggleRelais(0, 300); // r0kets toogle relaisboard.toggleRelais(3, 10000); // oven relaisboard.blinkRelaisStop(2); // stop hint button lamp guiControl.setWall("Pizza ist fertig!"); guiControl.showCountDown(true); machine.startTimer(7*60); break; case ROKET_DONE: mpdController.setVolume(50); mpdController.playSong("CTDO", "finish"); bunti.setLampel(false,false,true); bunti.setPar56(255, 255, 255); guiControl.setWall("willkommen im chaostreff dortmund"); guiControl.showCountDown(true); machine.pauseTimer(true); // spieler haben 7 Minuten, wenn sie es in weniger als 4 minuten schaffen // gibts +1, in weniger als 2 minuten gibts +2 if(machine.getTimerSecondsLast() >= 5*60 ) { rate(2, "r0kets faster than 2 minutes"); } else if(machine.getTimerSecondsLast() > 3*60) { rate(1, "r0kets faster than 4 minutes"); } sayScore(); disco(); break; } } /** * Event listener for timer ticks from statemachine. * @param tsecondsLeft the seconds left on the current game */ @Override public void timerTick(int tsecondsLeft) { guiControl.setCountDown(tsecondsLeft); if(tsecondsLeft == 0) { ircClient.say("timer expired"); Statemachine.state bla = machine.getCurrentState(); if( bla != Statemachine.state.TABLE_GAME_DONE && bla != Statemachine.state.ROKET_DONE ) { rate(-2, "game not done in time"); sayScore(); } } } /** * Event listener for keyPress events from the GUI * @param key the pressed key */ @Override public void keyPress(char key) { machine.handleInput(key); //guiControl.setExtra("btn: " + key); } /** * Event lister for window closing event from the GUI */ @Override public void windowClosing() { machine.reset(); bunti.setPar56(0xff,0xff,0xff); ircClient.say("bye"); relaisboard.close(); } /** * Event listener for IRC Messages * @param message the message from the IRC user */ @Override public void handleMessage(final String message) { if(message.startsWith("help")) { handleHelpCommand(message); } else if(message.equals("reset")) { machine.reset(); } else if(message.startsWith("state")) { handleStateCommand(message); } else if(message.startsWith("timer")) { handleTimerCommand(message); } else if(message.startsWith("score")) { sayScore(); } else if(message.startsWith("wall")) { guiControl.setWall(message.substring("wall".length()).trim()); } else if(message.startsWith("extra")) { guiControl.setExtra(message.substring("extra".length()).trim()); } else if(message.startsWith("relais")) { handleRelaisCommand(message); } else if(message.startsWith("disco start")) { disco(); } else if(message.startsWith("disco stop")) { discoStop(); } else if(message.startsWith("gem")) { handleGem(); } else { ircClient.say("y u no use valid command?"); } } private void handleTimerCommand(final String message) { String params = message.substring("timer".length()).trim().toLowerCase(); if(params.startsWith("start")) { String timeStr = params.substring("start".length()).trim(); if(timeStr.length() > 0) { try { int time = Integer.parseInt(timeStr); guiControl.showCountDown(true); machine.startTimer(time); ircClient.say("got it, starting with " + time + " seconds"); } catch (NumberFormatException e) { ircClient.say("your number looks a bit odd..."); } } else { ircClient.say("invalid parameter"); } } else if(params.startsWith("stop")) { machine.stopTimer(); guiControl.showCountDown(false); ircClient.say("timer stopped"); } else if(params.startsWith("pause")) { machine.pauseTimer(true); } else if(params.startsWith("resume")) { machine.pauseTimer(false); } } private void handleStateCommand(final String message) { if(message.equals("state")) { ircClient.say(machine.getCurrentState().name()); } else { String params = message.substring("state".length()).trim().toLowerCase(); Boolean ok = false; for(Statemachine.state st: Statemachine.state.values()) { String stateName = st.name().toLowerCase(); if(stateName.equals(params)) { ok = true; machine.setNewState(st); break; } } if(!ok) ircClient.say("ehm, impossibruu!"); } } // Yes, it makes no sense, but I want have it anyway. For more Spass am Geraet! private void handleGem() { if (!gemActivated) { java.util.Random random = new java.util.Random(); int scry = random.nextInt(100); if (scry >= 99) { ircClient.say("Perfect Gem Activated"); } else if (scry >= 90) { ircClient.say("Moooooooo!"); } else { ircClient.say("Gem Activated"); } } else { ircClient.say("Gem Deactivated"); } gemActivated = !gemActivated; } private void handleRelaisCommand(final String message) { String params = message.substring("relais".length()).trim().toLowerCase(); if(params.startsWith("lamp on")) { relaisboard.setRelais(2, true); } else if(params.startsWith("lamp off")) { relaisboard.setRelais(2, false); } else if(params.startsWith("oven on")) { relaisboard.setRelais(3, true); } else if(params.startsWith("oven off")) { relaisboard.setRelais(3, false); } else if(params.startsWith("rokets")) { relaisboard.toggleRelais(0, 300); } else if(params.startsWith("lamp blink")) { relaisboard.blinkRelais(2, 700); } else if(params.startsWith("lamp stop")) { relaisboard.blinkRelaisStop(2); } } private void handleHelpCommand(final String message) { if(message.equals("help")) { ircClient.say("commands: help, reset, state, timer, wall, extra, score"); } else if(message.contains("reset")) { ircClient.say("resets the game to IDLE"); } else if(message.contains("state")) { ircClient.say("get or set game state"); ircClient.say("> state "); ircClient.say("valid states: "); int counter = 0; StringBuilder sb = new StringBuilder(); for(Statemachine.state st: Statemachine.state.values()) { sb.append(st.name()); sb.append(" "); if(++counter == 4) { counter = 0; ircClient.say(sb.toString()); sb.setLength(0); } } if(sb.length() > 0) { ircClient.say(sb.toString()); } } else if(message.contains("timer")) { ircClient.say("control timer. commands are: start, stop, pause, resume."); ircClient.say("for start give lenght in seconds as parameter"); ircClient.say("e.g.: timer start 120"); } else if(message.contains("wall")) { ircClient.say("set text message on the screen"); } else if(message.contains("extra")) { ircClient.say("set small extra message on the screen"); } else if(message.contains("score")) { ircClient.say("i will tell you the current game score"); } else if(message.contains("relais")) { ircClient.say("control the relais board"); ircClient.say("valid commands: lamp on, lamp off, lamp blink, lamp stop, oven on, oven off, rokets"); } else if(message.contains("disco")) { ircClient.say("party! use: disco {on,off}"); } else if(params.contains("gem")) { ircClient.say("you don't say?"); } else { ircClient.say("dafuq?"); } } private void sayScore() { ircClient.say("stateChangeCounter: " + machine.getStateChangeCounter()); int seconds = machine.getTimerSecondsLast(); int seconds1 = machine.getTimerSeconds(); int seconds2 = seconds-seconds1; int mins = seconds / 60; int secs = seconds % 60; int mins1 = seconds1 / 60; int secs1 = seconds1 % 60; int mins2 = seconds2 / 60; int secs2 = seconds2 % 60; ircClient.say("time " + mins1 + ":" + secs1 + " last: " + mins + ":" + secs + " left: " + mins2 + ":" + secs2); ircClient.say("gamerRating: " + gamerRating); } private void resetDomotics() { relaisboard.toggleRelais(2, 2000); relaisboard.setRelais(7, true); // enable light barrier over relais relaisboard.setRelais(6, true); // enable third green circle mpdController.clearPlaylist(); } private void discoStop() { if(discoThread != null) { shouldStopDisco = true; discoThread.interrupt(); try { discoThread.join(500); } catch (InterruptedException e) { } } } private void disco() { discoStop(); Runnable r = new Runnable() { @Override public void run() { try { while(true) { if(shouldStopDisco) return; bunti.setPar56(0, 255, 0, 0); bunti.setPar56(1, 0, 255, 0); bunti.setPar56(2, 0, 255, 0); bunti.setPar56(3, 255, 0, 0); if(shouldStopDisco) return; Thread.sleep(500); bunti.setPar56(0, 0, 0, 255); bunti.setPar56(1, 255, 255, 0); bunti.setPar56(2, 255, 255, 0); bunti.setPar56(3, 0, 0, 255); if(shouldStopDisco) return; Thread.sleep(500); bunti.setPar56(0, 255, 128, 0); bunti.setPar56(1, 0, 255, 255); bunti.setPar56(2, 0, 255, 255); bunti.setPar56(3, 255, 128, 0); if(shouldStopDisco) return; Thread.sleep(500); bunti.setPar56(0, 0, 255, 255); bunti.setPar56(1, 0, 255, 0); bunti.setPar56(2, 0, 255, 0); bunti.setPar56(3, 0, 255, 255); if(shouldStopDisco) return; Thread.sleep(500); } } catch (InterruptedException e) { } } }; discoThread = new Thread(r); shouldStopDisco = false; discoThread.start(); } }