package main; import java.util.*; import org.jibble.pircbot.*; public class CyberBot extends PircBot { boolean noGame = true, prep, inGame; String chan = "#cyberzone"; ArrayList players = new ArrayList(); ArrayList ops = new ArrayList(); int[][] board = null; // 2-15 represent items int cur = 0; int round = 0; int itemUse = 0; int deadLoop = -1; int multiTrojan = 0; String mbHack = ""; String gameStarter = ""; int config = 0; int numItems = 0; ArrayList pickedItems = new ArrayList(); boolean handPicked; int spawnInterval = 0; int roundsUntilSpawn = 0; int boardSize = 0; // Set itemsForDesc = new TreeSet(); Timer turnTimer; String[] itemNames = new String[] { "", "", "Trojan (Godhammer)", "ICE", "Backdoor", "Query", "Scan", "Overclock", "Cloak", "Phone phreak", "Reboot", "Sector kill", "Invert", "Deadloop", "Defrag", "Magic Bullet", "White Knight", "tangerine.exe", "Magic Bullet ][", "Silver Cord", "Trojan (Masquerade)", "Trojan (Monday Morning Massacre)", "Minesweeper", "dir.", "Torchbearer", "Magic Bullet ]|[", "Flying Carpet" }; int[] itemProbs = new int[] { 0,0,8,5,5,6,5,3,6,3,3, // 0 - 10 4,4,6,3,8,4,1,6, // 11 - 18 3,7,7,2,5,3, // 19 - 24 3,2 // 25 - }; int itemProbsLen = 0; public static void main(String[] args) { @SuppressWarnings("unused") CyberBot bot = new CyberBot(); } public CyberBot() { ops.add("thecalcgenius"); ops.add("blue_tetris"); for(int pr : itemProbs) itemProbsLen += pr; setMessageDelay(500); setVerbose(true); setName("CyberBot"); setLogin("Cyberzone"); setVersion("CyberBot by Calcy, v0.95; Game idea by blue_tetris"); try { connect("irc.waypasteleven.com"); identify("pa55w0rd"); setMode(getNick(), "+B"); joinChannel(chan); Thread.sleep(1000); setTopic(chan, "Cyberzone | Type !start to begin. If the preparation for the game seems to be frozen, type !end. | About the game: http://metanet.2.forumer.com/index.php?showtopic=16812"); } catch (Exception ex) { ex.printStackTrace(); } } private void msg(String m) { sendMessage(chan, m); } public void onMessage(String channel, String sender, String login, String hostname, String message) { if(sender.equals("thecalcgenius")) { if(message.equals("!verboseoff")) { setVerbose(false); } else if(message.equals("!verboseon")) { setVerbose(true); } else if(message.equals("!testprobs") && noGame) { int[] times = new int[itemProbs.length]; Random rnd = new Random(); for(int i = 0; i < 1000; i++) { int rndNum = rnd.nextInt(itemProbsLen); int n, sum; for(n = 2, sum = 0; n < itemProbs.length; n++) { sum += itemProbs[n]; if(rndNum < sum) break; } times[n]++; } msg("After 1000 iterations: "); for(int i = 0; i < times.length; i++) { msg(itemNames[i] + ": " + times[i]); } } } if(noGame && message.equals("!start")) { noGame = false; prep = true; players = new ArrayList(); // itemsForDesc = new TreeSet(); board = null; cur = 0; round = 0; itemUse = 0; deadLoop = -1; gameStarter = sender; turnTimer = new Timer("Prep timer"); turnTimer.schedule(new TimerTask() { public void run() { endGame(); } }, 300000); setMode(chan, "+N"); msg(Colors.BLUE + "Grid active. Type \'jack\' to log into the mainframe. " + bold(sender) + ", once all hackers have " + "jacked into the mainframe, type \'!load\' to boot the interface."); } else if((prep || config > 0) && (sender.equals(gameStarter) || ops.contains(sender)) && message.equals("!end")) { endGame(); } else if(prep && message.equals("jack")) { for(Player p : players) { if(p.name.equals(sender)) { sendNotice(sender, "You are already playing!"); return; } } if(players.size() == 12) { msg(Colors.RED + "Sorry, 12 players maximum."); return; } players.add(new Player(sender)); voice(chan, sender); msg(Colors.BLUE + bold(sender) + " jacks into the mainframe."); } else if(prep && message.equals("unjack")) { int ind = findIndex(sender); if(ind != -1) { players.remove(ind); deVoice(chan, sender); msg(Colors.RED + bold(sender) + " unjacks himself from the mainframe."); } } else if(prep && (sender.equals(gameStarter) || ops.contains(sender)) && message.equals("!config")) { if(players.size() < 2) { msg(Colors.RED + "2 or more hackers required to configure and load interface."); return; } turnTimer.cancel(); config = 1; prep = false; // DELETE msg(Colors.DARK_GREEN + bold(gameStarter) + " edits \"config.ini\"."); msg(Colors.DARK_GREEN + bold(gameStarter) + ", enter the length of the board you wish to play on. The length can be " + "any number from " + (players.size()+1) + " to 20, inclusive. Type \"default\" to select the default value."); //config = 0; } else if((sender.equals(gameStarter) || ops.contains(sender)) && config > 0 && config != 100) { configure(message); return; } else if((prep || config == 100) && (sender.equals(gameStarter) || ops.contains(sender)) && message.equals("!load")) { //msg("config finished, loading interface..."); if(players.size() < 2) { msg(Colors.RED + "2 or more hackers required to load interface."); return; } prep = false; inGame = true; turnTimer.cancel(); //numItems = 0; //pickedItems = new ArrayList(); //handpicked //spawnInterval = 0; //boardSize = 0; if(config == 0) { boardSize = 4+players.size()+(players.size()/3); numItems = boardSize - players.size(); spawnInterval = 2 + players.size(); // msg("if statement on line 182 reached, shouldn\'t happen"); } roundsUntilSpawn = spawnInterval; config = 0; setTopic(chan, "Cyberzone | Game in progress. | About the game: http://metanet.2.forumer.com/index.php?showtopic=16812"); board = new int[boardSize][boardSize]; ArrayList rows = new ArrayList(), cols = new ArrayList(); ArrayList names = new ArrayList(); for(int i = 0; i < board.length; i++) { rows.add(i); cols.add(i); } Random rnd = new Random(); for(Player p : players) { int r = rows.remove(rnd.nextInt(rows.size())); int c = cols.remove(rnd.nextInt(cols.size())); board[r][c] = 1; p.r = r; p.c = c; } boolean calcPlay = false; for(Player p : players) if(p.name.equals("thecalcgenius")) calcPlay = true; for(int i = 0; i < numItems; i++) { int r = rows.remove(rnd.nextInt(rows.size())); int c = cols.remove(rnd.nextInt(cols.size())); int rndNum = rnd.nextInt(itemProbsLen); int n, sum; for(n = 2, sum = 0; n < itemProbs.length; n++) { sum += itemProbs[n]; if(rndNum < sum) break; } board[r][c] = n; names.add(itemNames[n]); //if(!calcPlay) sendMessage("thecalcgenius", itemNames[n] + " is at " + ((char)(r+65)) + "" + (c+1)); } for(int i = 0; i < 7; i++) Collections.shuffle(players); msg(Colors.BLUE + "Interface online. Hacker avatars have been uploaded to the mainframe."); String temp = ""; for(Player p : players) { temp += " " + p.name; } msg(Colors.BLUE + "Grid size is " + board.length + "x" + board.length + "."); msg(Colors.BLUE + "The hacker order will be:" + temp); Collections.sort(names); if(!names.isEmpty()) msg(Colors.DARK_GREEN + "Programs loaded: " + names.toString()); //msg(Colors.BLUE + "PM \"!desc\" to me for detailed descriptions of the programs in the mainframe."); giveInfo(); } else if(inGame && ops.contains(sender) && message.startsWith("!eject ") && itemUse == 0) { String name = message.split(" ")[1]; int ind; if((ind = findIndex(name)) != -1) { if(ind == cur) { players.remove(ind); deVoice(chan, name); msg(Colors.RED + bold(name) + " has been forcibly ejected from the mainframe. His space will not be holed."); if(players.size() == 1) { win(players.get(0).name); return; } giveInfo(); } else { players.remove(ind); deVoice(chan, name); msg(Colors.RED + bold(name) + " has been forcibly ejected from the mainframe. His space will not be holed."); if(players.size() == 1) { win(players.get(0).name); return; } if(ind < cur) cur--; } } else { msg(Colors.RED + bold(name) + " is not a part of this game."); } } else if(inGame && sender.equals(players.get(cur).name) && itemUse != 4 && itemUse != 20 && itemUse != 21) { if(itemUse == 2) { if(!validSpace(message,1)) { msg(Colors.DARK_GREEN + "FAT32 error. Node inaccessible. Input a different move."); return; } int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; if(board[rr][cc] == 1) { board[rr][cc] = -1; itemUse = 0; testHack(rr, cc, sender); return; } board[rr][cc] = -1; } else if(itemUse == 5) { if(sender.equalsIgnoreCase("message")) { msg(Colors.DARK_GREEN + "Probable recursion has forced a program abort. Query a non-host avatar."); return; } Player p; if((p = nameExists(message)) == null) { msg(Colors.DARK_GREEN + "Avatar not found. Query an avatar within the database."); return; } sendMessage(sender, p.name + " is located at " + p.loc() + "."); } else if(itemUse == 6) { if(!validSpace(message,0)) { msg(Colors.DARK_GREEN + "FAT32 error. Node inaccessible. Input a different move."); return; } int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; sendMessage(sender, "At " + message + ": " + giveInfo2(rr, cc, 1)); } else if(itemUse == 9) { if(!validSpace(message,0)) { msg(Colors.DARK_GREEN + "FAT32 error. Node inaccessible. Input a different move."); return; } int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; if(board[rr][cc] == 0) board[rr][cc] = -1; multiTrojan--; if(multiTrojan > 0) { msg(Colors.DARK_GREEN + multiTrojan + " left."); return; } } else if(itemUse == 10) { if(!validRC(message)) { msg(Colors.DARK_GREEN + "Target sector does not meet core criterion. Select a different row or column."); return; } if(Character.isUpperCase(message.charAt(0))) { int rr = message.charAt(0)-65; for(int c = 0; c < board.length; c++) { if(board[rr][c] == -1) board[rr][c] = 0; } } else { int cc = Integer.parseInt(message) - 1; for(int r = 0; r < board.length; r++) { if(board[r][cc] == -1) board[r][cc] = 0; } } } else if(itemUse == 11) { if(!validRC(message)) { msg(Colors.DARK_GREEN + "Target sector does not meet core criterion. Select a different row or column."); return; } if(Character.isUpperCase(message.charAt(0))) { int rr = message.charAt(0)-65; for(int c = 0; c < board.length; c++) { if(board[rr][c] != 1) board[rr][c] = -1; } } else { int cc = Integer.parseInt(message) - 1; for(int r = 0; r < board.length; r++) { if(board[r][cc] != 1) board[r][cc] = -1; } } } else if(itemUse == 12) { if(!validRC(message)) { msg(Colors.DARK_GREEN + "Target sector does not meet core criterion. Select a different row or column."); return; } if(Character.isUpperCase(message.charAt(0))) { int rr = message.charAt(0)-65; for(int c = 0; c < board.length; c++) { if(board[rr][c] == -1) board[rr][c] = 0; else if(board[rr][c] == 0) board[rr][c] = -1; } } else { int cc = Integer.parseInt(message) - 1; for(int r = 0; r < board.length; r++) { if(board[r][cc] == -1) board[r][cc] = 0; else if(board[r][cc] == 0) board[r][cc] = -1; } } } else if(itemUse == 15) { if(!(message.equalsIgnoreCase("r") || message.equalsIgnoreCase("c") || message.equalsIgnoreCase("row") || message.equalsIgnoreCase("column"))) { msg(Colors.DARK_GREEN + "Invalid input string. State row " + bold("(R)") + " or column " + bold("(C)") + "."); return; } Player p = players.get(cur); if(message.equalsIgnoreCase("r") || message.equalsIgnoreCase("row")) { int rr = p.r; for(int c = 0; c < board.length; c++) { if(c == p.c) continue; if(board[rr][c] == 1) { board[rr][c] = -1; int ind = findIndex(rr, c); Player np = players.get(ind); msg(Colors.RED + bold(p.name) + " uploads magic bullet program to " + bold(np.name) + "\'s avatar. " + bold(np.name) + " is forced to hard reboot, and drops from the mainframe!"); deVoice(chan, np.name); players.remove(ind); if(players.size() == 1) { win(players.get(0).name); return; } if(ind < cur) cur--; } } } else { int cc = p.c; for(int r = 0; r < board.length; r++) { if(r == p.r) continue; if(board[r][cc] == 1) { board[r][cc] = -1; int ind = findIndex(r, cc); Player np = players.get(ind); msg(Colors.RED + bold(p.name) + " uploads magic bullet program to " + bold(np.name) + "\'s avatar. " + bold(np.name) + " is forced to hard reboot, and drops from the mainframe!"); deVoice(chan, np.name); players.remove(ind); if(players.size() == 1) { win(players.get(0).name); return; } if(ind < cur) cur--; } } } if(cur < 0) cur += players.size(); } else if(itemUse == 18) { if(mbHack.equals("")) { if(sender.equalsIgnoreCase(message)) { msg(Colors.DARK_GREEN + "Probable recursion has forced a program abort. Query a non-host avatar."); return; } if(nameExists(message) == null) { msg(Colors.DARK_GREEN + "Avatar not found. Query an avatar within the database."); return; } mbHack = message; msg(Colors.DARK_GREEN + "Now, enter a specific name of a row (A-" + ((char)(board.length+64)) + ") or a column " + "(1-" + (board.length) + "). If the hacker\'s avatar is located within that row or column, he will " + "be ejected from the mainframe."); return; } else { if(!validRC(message)) { msg(Colors.DARK_GREEN + "Target sector does not meet core criterion. Select a different row or column."); return; } int ind = findIndex(mbHack); Player np = players.get(ind); mbHack = ""; if(Character.isUpperCase(message.charAt(0))) { int rr = message.charAt(0)-65; if(np.r == rr) { Player p = players.get(cur); msg(Colors.RED + bold(p.name) + " uploads \"Jade Lightning\" to " + bold(np.name) + "\'s avatar. " + bold(np.name) + " is forced to hard reboot, and drops from the mainframe!"); deVoice(chan, np.name); players.remove(ind); if(players.size() == 1) { win(players.get(0).name); return; } if(ind < cur) cur--; } } else { int cc = Integer.parseInt(message) - 1; //msg(bold("cc = " + cc)); if(np.c == cc) { Player p = players.get(cur); msg(Colors.RED + bold(p.name) + " uploads \"Jade Lightning\" to " + bold(np.name) + "\'s avatar. " + bold(np.name) + " is forced to hard reboot, and drops from the mainframe!"); deVoice(chan, np.name); players.remove(ind); if(players.size() == 1) { win(players.get(0).name); return; } if(ind < cur) cur--; } } } } else if(itemUse == 22) { if(!validSpace(message,0)) { msg(Colors.DARK_GREEN + "FAT32 error. Node inaccessible. Input a different move."); return; } int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; if(board[rr][cc] == -1) board[rr][cc] = 0; multiTrojan--; if(multiTrojan > 0) { msg(Colors.DARK_GREEN + multiTrojan + " left."); return; } } else if(itemUse == 23) { if(!validRC(message)) { msg(Colors.DARK_GREEN + "Target sector does not meet core criterion. Select a different row or column."); return; } if(Character.isUpperCase(message.charAt(0))) { int rr = message.charAt(0)-65; String s = "Holes in row " + message.charAt(0) + ":"; for(int c = 0; c < board.length; c++) if(board[rr][c] == -1) s += " " + ((char)(rr+65)) + (c+1) + ","; if(s.endsWith(":")) sendMessage(sender, "No holes in row " + message.charAt(0) + "."); else sendMessage(sender, s.substring(0, s.length() - 1) + "."); } else { int cc = Integer.parseInt(message) - 1; String s = "Holes in column " + (cc+1) + ":"; for(int r = 0; r < board.length; r++) if(board[r][cc] == -1) s += " " + ((char)(r+65)) + (cc+1) + ","; if(s.endsWith(":")) sendMessage(sender, "No holes in column " + (cc+1) + "."); else sendMessage(sender, s.substring(0, s.length() - 1) + "."); } } else if(itemUse == 24) { if(!(message.equalsIgnoreCase("r") || message.equalsIgnoreCase("c") || message.equalsIgnoreCase("row") || message.equalsIgnoreCase("column"))) { msg(Colors.DARK_GREEN + "Invalid input string. State row " + bold("(R)") + " or column " + bold("(C)") + "."); return; } msg(Colors.DARK_GREEN + "Uploading info..."); if(message.equalsIgnoreCase("r") || message.equalsIgnoreCase("row")) { for(int r = 0; r < board.length; r++) sendMessage(sender, giveInfoR(r, 0, 1)); } else { for(int c = 0; c < board.length; c++) sendMessage(sender, giveInfoC(0, c, 1)); } } else if(itemUse == 25) { if(!validSpace(message,0)) { msg(Colors.DARK_GREEN + "FAT32 error. Node inaccessible. Input a different move."); return; } //msg("25. input accepted. cur = " + cur); boolean found = false; int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; Player p = players.get(cur); for(int c = 0; c < board.length; c++) { if(board[rr][c] == 1) { int ind = findIndex(rr, c); if(cur == ind) continue; //msg("victim found in 1. cur = " + cur); found = true; board[rr][c] = 0; Player np = players.get(ind); msg(Colors.RED + bold(p.name) + " rides the bomb onto " + bold(np.name) + "\'s avatar. " + bold(np.name) + " stops worrying and hard reboots."); msg(Colors.RED + bold(np.name) + " drops from the mainframe!"); deVoice(chan, np.name); players.remove(ind); if(players.size() == 1) { win(players.get(0).name); return; } if(ind < cur) cur--; //msg("victim dead, player removed. cur = " + cur); } } for(int r = 0; r < board.length; r++) { if(board[r][cc] == 1) { int ind = findIndex(r,cc); if(cur == ind) continue; //msg("victim found in 2. cur = " + cur); found = true; board[r][cc] = 0; Player np = players.get(ind); msg(Colors.RED + bold(p.name) + " rides the bomb onto " + bold(np.name) + "\'s avatar. " + bold(np.name) + " stops worrying and hard reboots."); msg(Colors.RED + bold(np.name) + " drops from the mainframe!"); deVoice(chan, np.name); players.remove(ind); if(players.size() == 1) { win(players.get(0).name); return; } if(ind < cur) cur--; //msg("victim dead, player removed. cur = " + cur); } } //msg("all victims dead. now moving player. cur = " + cur); if(found) { board[p.r][p.c] = 0; p.r = rr; p.c = cc; itemUse = 0; if(board[rr][cc] == 1) { testHack(rr, cc, sender); return; } if(board[rr][cc] > 1) { informItem(p, rr, cc, sender); return; } board[p.r][p.c] = 1; cur++; cur = cur % players.size(); giveInfo(); return; } else { board[p.r][p.c] = 0; msg(Colors.RED + bold(sender) + " is reported to SysOps, and drops from the mainframe."); deVoice(chan, sender); players.remove(cur); if(players.size() == 1) { win(players.get(0).name); return; } cur--; } //msg("25 done. cur = " + cur); } if(itemUse != 0) { itemUse = 0; cur++; cur = cur % players.size(); giveInfo(); } } } private void endGame() { prep = false; config = 0; noGame = true; msg(Colors.RED + "Grid deactivated."); for(Player p : players) { deVoice(chan, p.name); } setMode(chan, "-N"); } private void configure(String message) { if(config == 1) { try { int n = Integer.parseInt(message); if(n <= players.size() || n > 20) { msg(Colors.DARK_GREEN + "Invalid board size."); return; } boardSize = n; msg(Colors.DARK_GREEN + "Now, enter the number of programs to initially place on the board. You can have between " + "0 and " + (boardSize-players.size()) + " programs, inclusive. Type \"default\" for the default setting."); config = 2; } catch(Exception ex) { if(message.equalsIgnoreCase("default")) { boardSize = 4 + players.size() + (players.size()/3); msg(Colors.DARK_GREEN + "Now, enter the number of programs to initially place on the board. You can have between " + "0 and " + (boardSize-players.size()) + " programs, inclusive. Type \"default\" for the default setting."); config = 2; } else msg(Colors.DARK_GREEN + "Invalid entry."); return; } } else if(config == 2) { try { int n = Integer.parseInt(message); if(n < 0 || (n > boardSize-players.size())) { msg(Colors.DARK_GREEN + "Invalid amount."); return; } numItems = n; if(numItems > 0) { msg(Colors.DARK_GREEN + "Do you want to pick what programs show up on the board yourself? Answer \"yes\" or " + "\"no\". If you choose not to pick, random programs will be loaded."); config = 3; } else { msg(Colors.DARK_GREEN + "Enter the number of rounds to wait before loading a new program into the mainframe. " + "Minimum is 2. Type \"none\" to eliminate spawning of items. Type \"default\" for the default setting."); config = 5; } } catch(Exception ex) { if(message.equalsIgnoreCase("default")) { numItems = boardSize - players.size(); msg(Colors.DARK_GREEN + "Do you want to pick what programs show up on the board yourself? Answer \"yes\" or " + "\"no\". If you choose not to pick, random programs will be loaded."); config = 3; } else msg(Colors.DARK_GREEN + "Invalid entry."); return; } // msg(Colors.DARK_GREEN + "Congratulations! The mainframe has been succesfully configured. Type \"!load\" to activate " + // "the grid."); // config = 100; } else if(config == 3) { if(message.equalsIgnoreCase("y") || message.equalsIgnoreCase("yes")) { msg(Colors.DARK_GREEN + "It\'s not implemented yet. Type no."); } else if(message.equalsIgnoreCase("n") || message.equalsIgnoreCase("no")) { msg(Colors.DARK_GREEN + "Enter the number of rounds to wait before loading a new program into the mainframe. " + "Minimum is 2. Type \"none\" to eliminate spawning of items. Type \"default\" for the default setting."); config = 5; } } else if(config == 4) { } else if(config == 5) { try { int n = Integer.parseInt(message); if(n < 2) { msg(Colors.DARK_GREEN + "Invalid amount."); return; } spawnInterval = n; msg(Colors.DARK_GREEN + "Enter any permanent items you wish to have at the start of the game. Choices are \"ICE\", " + "\"Cloak\", \"WK\" (White Knight), \"SC\" (Silver Cord), \"FC\" (Flying Carpet), or any combination of " + "these (enter each one separately). Once you are finished entering the combination of items, or if you " + "do not want any initial items, type \"done\"."); config = 6; } catch(Exception ex) { if(message.equalsIgnoreCase("default")) { spawnInterval = 2 + players.size(); msg(Colors.DARK_GREEN + "Enter any permanent items you wish to have at the start of the game. Choices are \"ICE\", " + "\"Cloak\", \"WK\" (White Knight), \"SC\" (Silver Cord), \"FC\" (Flying Carpet), or any combination of " + "these (enter each one separately). Once you are finished entering the combination of items, or if you " + "do not want any initial items, type \"done\"."); config = 6; } else if(message.equalsIgnoreCase("none")) { spawnInterval = -1; msg(Colors.DARK_GREEN + "Enter any permanent items you wish to have at the start of the game. Choices are \"ICE\", " + "\"Cloak\", \"WK\" (White Knight), \"SC\" (Silver Cord), \"FC\" (Flying Carpet), or any combination of " + "these (enter each one separately). Once you are finished entering the combination of items, or if you " + "do not want any initial items, type \"done\"."); config = 6; } else msg(Colors.DARK_GREEN + "Invalid entry."); return; } } else if(config == 6) { if(message.equalsIgnoreCase("ice")) { for(Player p : players) p.ice = true; msg(Colors.DARK_GREEN + "ICE has been loaded."); } else if(message.equalsIgnoreCase("cloak")) { for(Player p : players) p.cloak = true; msg(Colors.DARK_GREEN + "The Cloak program has been loaded."); } else if(message.equalsIgnoreCase("wk")) { for(Player p : players) p.knight = true; msg(Colors.DARK_GREEN + "The White Knight (tm) program has been loaded."); } else if(message.equalsIgnoreCase("sc")) { for(Player p : players) p.cord = true; msg(Colors.DARK_GREEN + "The Silver Cord has been loaded."); } else if(message.equalsIgnoreCase("fc")) { for(Player p : players) p.carpet = true; msg(Colors.DARK_GREEN + "The Flying Carpet has been loaded."); } else if(message.equalsIgnoreCase("done")) { msg(Colors.DARK_GREEN + "Congratulations! The mainframe has been succesfully configured. Type \"!load\" to activate " + "the grid."); config = 100; // msg("boardSize = " + boardSize); // msg("numItems = " + numItems); // msg("spawnInt = " + spawnInterval); } } } private void win(String name) { turnTimer.cancel(); msg(Colors.BLUE + bold(name) + " now has uncontested domain over the mainframe!"); msg(Colors.BLUE + "Good game."); setMode(chan, "-N"); setTopic(chan, "Cyberzone | Type !start to begin. If the preparation for the game seems to be frozen, type !end. | About the game: http://metanet.2.forumer.com/index.php?showtopic=16812"); deVoice(chan, name); noGame = true; inGame = false; config = 0; return; } private String bold(String n) { return Colors.BOLD + n + Colors.BOLD; } private boolean validRC(String message) { try { int c = Integer.parseInt(message) - 1; return c >= 0 && c < board.length; } catch(Exception ex) { if(message.length() != 1 || !Character.isUpperCase(message.charAt(0))) return false; char r = message.charAt(0); return r >= 'A' && r < board.length + 65; } } private int findIndex(int r, int c) { for(int i = 0; i < players.size(); i++) { Player pl = players.get(i); if(pl.r == r && pl.c == c) return i; } return -1; } private int findIndex(String message) { for(int i = 0; i < players.size(); i++) { if(players.get(i).name.equalsIgnoreCase(message)) return i; } return -1; } private Player nameExists(String message) { for(Player p : players) { if(p.name.equalsIgnoreCase(message)) return p; } return null; } private boolean validSpace(String msg, int eq) { // EQ = 1 IF CHECKING IS REQUIRED if(msg.length() < 2 || !Character.isUpperCase(msg.charAt(0))) { return false; } int rr, cc; try { cc = Integer.parseInt(msg.substring(1))-1; }catch(Exception ex) { return false; } rr = msg.charAt(0) - 65; Player p = players.get(cur); if(rr < 0 || rr >= board.length || cc < 0 || cc >= board.length) { return false; } if(eq == 1 && p.r == rr && p.c == cc) return false; return true; } public void onPrivateMessage(String sender, String login, String hostname, String message) { turnTimer.cancel(); if(inGame && sender.equals(players.get(cur).name)) { if(itemUse == 4 || itemUse == 20 || itemUse == 21) { if(itemUse == 4) { if(!validSpace(message,0)) { sendMessage(sender, Colors.DARK_GREEN + bold(sender) + " Invalid location. Please choose " + "another space."); return; } Player p = players.get(cur); int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; p.r = rr; p.c = cc; itemUse = 0; if(board[rr][cc] == 1) { testHack(rr, cc, sender); return; } if(board[rr][cc] > 1) { informItem(p, rr, cc, sender); return; } board[p.r][p.c] = 1; } else if(itemUse == 20) { if(!validSpace(message,1)) { sendMessage(sender, "Invalid location. Please choose another space."); return; } Player p = players.get(cur); int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; if(p.r != rr && p.c != cc) { sendMessage(sender, "The location must be in your row or column!"); return; } if(board[rr][cc] == 1) { board[rr][cc] = -1; itemUse = 0; testHack(rr, cc, sender); return; } board[rr][cc] = -1; } else if(itemUse == 21) { if(!validSpace(message,1)) { sendMessage(sender, "Invalid location. Please choose another space."); return; } int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; if(board[rr][cc] == 1) { board[rr][cc] = -1; itemUse = 0; testHack(rr, cc, sender); return; } board[rr][cc] = -1; } itemUse = 0; cur++; cur = cur % players.size(); giveInfo(); } else if(itemUse == 0){ if(!validSpace(message,1)) { sendMessage(sender, "Invalid location. Please enter another space."); return; } Player p = players.get(cur); int rr = message.charAt(0) - 65, cc = Integer.parseInt(message.substring(1))-1; if(p.r != rr && p.c != cc && !p.knight) { sendMessage(sender, "The location must be in your row or column!"); return; } board[p.r][p.c] = -1; if(board[rr][cc] == -1) { p.r = rr; p.c = cc; if(p.cord) { msg(Colors.DARK_GREEN + bold(sender) + " slips through a hole in the mainframe, but is lifted out by The " + "Silver Cord. The Silver Cord is broken."); board[rr][cc] = 1; p.cord = false; cur++; } else if(p.carpet) { msg(Colors.DARK_GREEN + bold(sender) + " invokes the power of the Flying Carpet to soar over a hole at " + p.loc() + "."); board[rr][cc] = 1; cur++; } else { msg(Colors.RED + bold(sender) + " slips through the hole " + p.loc() + ", and loses all user access. " + bold(sender) + " drops from the mainframe!"); deVoice(chan, sender); players.remove(cur); if(players.size() == 1) { win(players.get(0).name); return; } } cur = cur % players.size(); giveInfo(); return; } p.r = rr; p.c = cc; if(board[rr][cc] == 1) { testHack(rr, cc, sender); return; } if(board[rr][cc] > 1) { informItem(p, rr, cc, sender); return; } board[p.r][p.c] = 1; cur++; cur = cur % players.size(); giveInfo(); } } } /*private void testHack2(int rr, int cc, int ind) { Player p = players.get(ind); for(int i = 0; i < players.size(); i++) { if(i == cur) continue; Player np = players.get(i); if(np.r == rr && np.c == cc) { if(np.ice) { msg(Colors.RED + bold(p.name) + " hacks " + bold(np.name) + "\'s avatar. " + bold(np.name) + " executes ICE, " + "preventing the hack. " + bold(p.name) + " is revealed to SysOps and is forcibly ejected from the " + "mainframe!"); deVoice(chan, p.name); players.remove(cur); if(players.size() == 1) { win(players.get(0).name); return; } cur = cur % players.size(); giveInfo(); return; } else { msg(Colors.RED + bold(p.name) + " hacks " + bold(np.name) + "\'s avatar. " + bold(np.name) + " drops from the " + "mainframe!"); deVoice(chan, np.name); players.remove(i); if(players.size() == 1) { win(players.get(0).name); return; } if(i > cur) cur++; cur = cur % players.size(); giveInfo(); return; } } } msg("Something failed when " + p.name + " tried to take over the spot at " + rr + " " + cc); } */ private void testHack(int rr, int cc, String sender) { for(int i = 0; i < players.size(); i++) { if(i == cur) continue; Player np = players.get(i); if(np.r == rr && np.c == cc) { if(np.ice) { msg(Colors.RED + bold(sender) + " hacks " + bold(np.name) + "\'s avatar at " + np.loc() + ". " + bold(np.name) + " executes ICE, preventing the hack. " + bold(sender) + " is revealed to SysOps and is forcibly ejected " + "from the mainframe!"); deVoice(chan, sender); players.remove(cur); if(players.size() == 1) { win(players.get(0).name); return; } cur = cur % players.size(); giveInfo(); return; } else { msg(Colors.RED + bold(sender) + " hacks " + bold(np.name) + "\'s avatar at " + np.loc() + ". " + bold(np.name) + " drops from the mainframe!"); deVoice(chan, np.name); players.remove(i); if(players.size() == 1) { win(players.get(0).name); return; } if(i > cur) cur++; cur = cur % players.size(); giveInfo(); return; } } } //msg("Something failed when " + sender + " tried to take over the spot at " + rr + " " + cc); } private void informItem(Player p, int rr, int cc, String sender) { if(board[rr][cc] == 2) { itemUse = 2; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes the Trojan virus, GodHammer Edition."); msg(Colors.DARK_GREEN + bold(sender) + ", input the name of a space publically. The space you name will be holed. If " + "an avatar or item is in that space, it slips from the mainframe."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 3) { msg(Colors.DARK_GREEN + bold(sender) + " downloads and installs Intrustion Counter-Electronics. " + bold(sender) + " cannot be hacked. Avatars hacking " + bold(sender) + " will instead be revealed to system operators and " + "ejected from the mainframe."); p.ice = true; } else if(board[rr][cc] == 4) { itemUse = 4; msg(Colors.DARK_GREEN + bold(sender) + " locates a backdoor in the mainframe."); msg(Colors.DARK_GREEN + bold(sender) + ", using PM, input the name of a space. Your avatar will be relocated to the " + "space you input. If this space is holed, the hole will be removed and your avatar will land safely. If this " + "space contains an avatar, you hack them. If this space contains a program, you instantly run that program. The " + "space where you originated from will be holed."); board[p.r][p.c] = -1; return; } else if(board[rr][cc] == 5) { itemUse = 5; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes a query relay."); msg(Colors.DARK_GREEN + bold(sender) + ", input the name of a hacker publically. The query will privately reveal the " + "exact location of that hacker's avatar. " + Colors.BOLD + "Hacker names are case-sensitive."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 6) { itemUse = 6; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes a scan relay."); msg(Colors.DARK_GREEN + bold(sender) + ", input the name of a space publically. The scan will retrieve information for " + "you as if you were in that space. The information will arrive privately."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 7) { msg(Colors.DARK_GREEN + bold(sender) + " overclocks the deck, and immediately takes another turn."); board[p.r][p.c] = 1; giveInfo3(); return; } else if(board[rr][cc] == 8) { msg(Colors.DARK_GREEN + bold(sender) + " downloads and installs a cloaking program, and is now invisible to normal " + "detection."); p.cloak = true; } else if(board[rr][cc] == 9) { itemUse = 9; multiTrojan = board.length; msg(Colors.DARK_GREEN + bold(sender) + " finds an insecure port to phone phreak the mainframe."); msg(Colors.DARK_GREEN + bold(sender) + ", enter " + board.length + " spaces, one by one. Each space you type will be " + "holed unless there is an avatar or an item in that space."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 10) { itemUse = 10; msg(Colors.DARK_GREEN + bold(sender) + " finds a gap in code, allowing for a safe reboot."); msg(Colors.DARK_GREEN + bold(sender) + ", publically input the name of a row (A-" + ((char)(board.length+64)) + ") or a column (1-" + (board.length) + "). The holes in that sector will become " + "free grid spaces again."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 11) { itemUse = 11; msg(Colors.DARK_GREEN + bold(sender) + " finds a gap in code, allowing for a potent sector kill."); msg(Colors.DARK_GREEN + bold(sender) + ", publically input the name of a row (A-" + ((char)(board.length+64)) + ") or a column (1-" + (board.length) + "). The free spaces in this sector become " + "holes. Any program on a space in this sector is dropped from the mainframe. Avatar spaces are not " + "affected."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 12) { itemUse = 12; msg(Colors.DARK_GREEN + bold(sender) + " finds a gap in code, allowing for a strategic inversion."); msg(Colors.DARK_GREEN + bold(sender) + ", publically input the name of a row (A-" + ((char)(board.length+64)) + ") or a column (1-" + (board.length) + "). The free spaces in this sector become " + "holes, while holed spaces become free spaces. Spaces containing items or avatars are not affected."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 13) { deadLoop = cur; msg(Colors.DARK_GREEN + bold(sender) + " discovers a dormant deadloop within the mainframe and executes it. As a result, " + "other hackers will not receive information about their surroundings for one full round."); } else if(board[rr][cc] == 14) { ArrayList holes = new ArrayList(); for(int r = 0; r < board.length; r++) for(int c = 0; c < board.length; c++) if(board[r][c] == -1) holes.add(new int[] {r,c}); int n = (int)(Math.round(holes.size()/2.0)); for(int i = 0; i < 7; i++) Collections.shuffle(holes); for(int i = 0; i < n; i++) { int[] loc = holes.remove(0); board[loc[0]][loc[1]] = 0; } msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes a defrag program. A random set of half of the holed " + "grid spaces are reconfigured, becoming free spaces again."); } else if(board[rr][cc] == 15) { itemUse = 15; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes the magic bullet program."); msg(Colors.DARK_GREEN + bold(sender) + ", publically declare \"column\" or \"row\". Any avatars in the same column or " + "row (whichever was declared) as you are forced to hard reboot, removing them from the mainframe. Remember " + "that your column is a number and your row is a letter."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 16) { p.knight = true; msg(Colors.DARK_GREEN + bold(sender) + " downloads and installs White Knight (tm). You can now move to any location " + "during your turn, instead of a location within the same row or column."); } else if(board[rr][cc] == 17) { for(int r = 0; r < board.length; r++) for(int c = 0; c < board.length; c++) if(board[r][c] == 0) board[r][c] = -1; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes a silhouette copy of the lengendary virus " + "\"tangerine.exe\". Every space on the mainframe has been holed, except spaces containing avatars or items. " + "A single cryptic message arrives in the program's readme text file: \"Never forget her. Never forget her. The " + "Tangerine."); } else if(board[rr][cc] == 18) { itemUse = 18; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes the magic bullet ][ program."); msg(Colors.DARK_GREEN + bold(sender) + ", first name a hacker. " + bold("Names are case-sensitive.")); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 19) { p.cord = true; msg(Colors.DARK_GREEN + bold(sender) + " downloads and installs The Silver Cord. " + bold(sender) + " is now immune " + "to slipping through a hole. After slipping through a hole once, The Silver Cord will break."); } else if(board[rr][cc] == 20) { itemUse = 20; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes the Trojan virus, Masquerade Edition. "); msg(Colors.DARK_GREEN + bold(sender) + ", PM me the name of a space that is in your same row or column. This space " + "will be holed. If an avatar or program is on that space, they will be dropped from the mainframe."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 21) { itemUse = 21; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes the Trojan virus, triple-M edition. "); msg(Colors.DARK_GREEN + bold(sender) + ", PM me the name of a space. This space will be holed. If an avatar or program " + "is on that space, they will be dropped from the mainframe."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 22) { itemUse = 22; multiTrojan = board.length; msg(Colors.DARK_GREEN + bold(sender) + " finds a minesweeper."); msg(Colors.DARK_GREEN + bold(sender) + ", enter " + board.length + " spaces, one by one. If that space is a hole, " + "it will be turned into a free space."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 23) { itemUse = 23; msg(Colors.DARK_GREEN + bold(sender) + " gains access to the parent directory, allowing for the execution of a " + "\"dir.\" command."); msg(Colors.DARK_GREEN + bold(sender) + ", publically input the name of a row (A-" + ((char)(board.length+64)) + ") or a column (1-" + (board.length) + "). You will privately receive exact locations" + " of any holes in that row or column."); board[p.r][p.c] = 1; return; } else if (board[rr][cc] == 24) { itemUse = 24; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes Torchbearer (tm) by JourneymanWorks, who provide the " + "latest in deckrunning technology at affordable prices!"); msg(Colors.DARK_GREEN + bold(sender) + ", publically declare \"column\" or \"row\". The Torchbearer will retrieve " + "information about every column or every row (whichever was selected) as if you were viewing those sectors. " + "This information will arrive privately."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 25) { itemUse = 25; msg(Colors.DARK_GREEN + bold(sender) + " downloads and executes \"Strangelove\", the third magic bullet virus."); msg(Colors.DARK_GREEN + bold(sender) + ", enter the name of a space. If any avatar is on the same column or row, they " + "will be ejected from the mainframe, and you will backdoor onto that space. However, if there are no avatars " + "on that column or row, you will be reported to SysOps and will be ejected from the mainframe."); board[p.r][p.c] = 1; return; } else if(board[rr][cc] == 26) { p.carpet = true; msg(Colors.DARK_GREEN + bold(sender) + " downloads and installs The Flying Carpet. " + bold(sender) + " is now immune " + "to slipping through a hole for the rest of the game. However, if he is rescued from a hole, the mainframe " + "will publically say what square he is in."); } board[p.r][p.c] = 1; cur++; cur = cur % players.size(); giveInfo(); } private String giveInfoR(int rr, int cc, int sc) { String pl = "", i = ""; int h = 0; for(int c = 0; c < board.length; c++) { if(sc == 0 && c == cc) continue; if(board[rr][c] == -1) h++; else if(board[rr][c] == 1) { Player pp = findPlayer(rr,c); if(!pp.cloak) pl += pp.name + ", "; } else if(board[rr][c] > 1) i += itemNames[board[rr][c]] + ", "; } StringBuffer s = new StringBuffer(); if(pl.length() > 0) s.append(pl.substring(0, pl.length() - 2)); if(i.length() > 0) { if(pl.length() > 0) s.append(", "); s.append(i.substring(0, i.length() - 2)); } if(h > 0) { if(pl.length() > 0 || i.length() > 0) s.append(" and "); s.append("" + h + (h == 1? " hole": " holes")); } if(!pl.equals("") || h > 0 || !i.equals("")) s.append(" in row " + ((char)(rr+65)) + ". "); return s.toString(); } private String giveInfoC(int rr, int cc, int sc) { String pl = "", i = ""; int h = 0; for(int r = 0; r < board.length; r++) { if(sc == 0 && r == rr) continue; if(board[r][cc] == -1) h++; else if(board[r][cc] == 1) { Player pp = findPlayer(r, cc); if(!pp.cloak) pl += pp.name + ", "; } else if(board[r][cc] > 1) i += itemNames[board[r][cc]] + ", "; } StringBuffer s = new StringBuffer(); if(pl.length() > 0) s.append(pl.substring(0, pl.length() - 2)); if(i.length() > 0) { if(pl.length() > 0) s.append(", "); s.append(i.substring(0, i.length() - 2)); } if(h > 0) { if(pl.length() > 0 || i.length() > 0) s.append(" and "); s.append("" + h + (h == 1? " hole": " holes")); } if(!pl.equals("") || h > 0 || !i.equals("")) s.append(" in column " + (cc+1) + ". "); return s.toString(); } private String giveInfo2(int rr, int cc, int sc) { return giveInfoR(rr, cc, sc) + giveInfoC(rr, cc, sc); } private void notify30() { turnTimer.cancel(); msg(Colors.BLUE + bold(players.get(cur).name) + ", you have 30 seconds to make your move. You will be ejected from the " + "mainframe if you do not make one."); turnTimer = new Timer("Final timer"); turnTimer.schedule(new TimerTask() { public void run() { noMoveTaken(); } }, 30000); } private void noMoveTaken() { turnTimer.cancel(); Player p = players.get(cur); msg(Colors.RED + "The mainframe was unable to receive a PING acknowledgement from " + bold(p.name) + ". As a result, " + bold(p.name) + " has been gracefully unjacked from the mainframe. His space will not be holed."); board[p.r][p.c] = 0; deVoice(chan, p.name); players.remove(cur); if(players.size() == 1) { win(players.get(0).name); return; } cur = cur % players.size(); giveInfo(); } private void giveInfo() { if(cur == 0) { msg(Colors.BLUE + Colors.BOLD + "Round " + (++round) + "."); if(roundsUntilSpawn == 0 && spawnInterval != -1) { if(spawnInterval > 3) spawnInterval--; roundsUntilSpawn = spawnInterval; int r, c; Random rnd = new Random(); int rndNum = rnd.nextInt(itemProbsLen); int n, sum; for(n = 2, sum = 0; n < itemProbs.length; n++) { sum += itemProbs[n]; if(rndNum < sum || n == itemProbs.length - 1) break; } r = rnd.nextInt(board.length); c = rnd.nextInt(board.length); while(board[r][c] == 1) { r = rnd.nextInt(board.length); c = rnd.nextInt(board.length); } board[r][c] = n; msg(Colors.DARK_GREEN + "Program loaded: " + itemNames[n] + "."); } else roundsUntilSpawn--; } msg(Colors.BLUE + bold(players.get(cur).name) + "\'s turn."); giveInfo3(); } private void giveInfo3() { turnTimer = new Timer("Initial timer"); turnTimer.schedule(new TimerTask() { public void run() { notify30(); } }, 60000); Player p = players.get(cur); String s = "You are at " + p.loc() + ". "; if(deadLoop == cur) deadLoop = -1; if(deadLoop == -1) s += giveInfo2(p.r, p.c, 0); else s += "You are adrift in a maelstrom of useless code. "; s += "Where to?"; sendMessage(p.name, s); } private Player findPlayer(int r, int c) { for(Player p : players) { if(p.r == r && p.c == c) return p; } return null; } public class Player { int r; int c; String name; boolean cloak; boolean ice; boolean knight; boolean cord; boolean carpet; //ArrayList cookie = new ArrayList(); public Player(String n) { name = n; } public String loc() { return "" + ((char)(r+65)) + (c+1); } public String toString() { return name; } } }