package th; /* This class contains various thing pretaining to making * and fixing the map. * */ import java.util.Vector; import java.lang.reflect.InvocationTargetException; public class Map { public static final String[] random_names = { "Doug", "Jeremy", "Stephen", "Ken", "John", "Lauren", "Catherine", "Katz", "Yuko", "Hosea", "Upinder", "Schroeder", "Jason", "Schroeder", "Syda", "Gallagher", "Jorden", "Alexia", "Kevin", "Andrew", "Josh", "J Kennedy", "M Tohya", "J L Picard", "Foothark McGee", "Arizona Amy", "Columbia Jones", "J Koizumi", "Clinton", "Bush", "Carter", "Kofi Annan", "Seijik", "Bart", "S Mario", "Luigi", "S Hedgehog" }; public static final String[] rsize_adjectives = { "tiny", "cramped", "bitty", "big", "average-sized", "huge", "large", "small", "spacious" }; public static final String[] radjectives = { "strange-smelling", "odorous", "happy", "unhappy", "clean", "dirty", "filthy", "dusty", "sterile", "boring", "interesting", "awesome", "yet another stupid", "totally elite", "narrow", "long", "machine", "unused", "abandoned", "messy", "barren" }; // True advice // public static final String[] rtips_true = { "Stupid people should not play with hats.", "Even weak creatures are dangerous if they have Rubber Wands.", "They say that the yolk of a Pikachu's egg can have strange effects on items.", "It is said that vegetarians get bonus points.", "Rumor has it that there is a cavern made of chocolate in the tunnels.", "Lesson from Physics 4B: You can recharge a wand by rubbing it with the right material.", "Be careful not to overcharge wands.", "Cookies are good for you.", "They say that the Programmer may help you, if you're a good person.", "Science Fiction Convention Today!", "Lab coats can protect you from chemical spills.", "They say that the universe runs on hobos and Vectors, mostly hobos.", "Some people say that the galvanic currents in a pikachu egg can raise the dead.", "This statement is false.", "Rumor has it that some people wearing costumes have been lurking in the tunnels.", "If you have pointed ears like Mr. Spock, no-one will think that you're a jock.", "Reading books can make you smarter.", "Sometimes walls will lie to you.", "A big book can pack a whallop!", "Fetid blobs often contain items in their slimy goo.", "Good deeds are often rewarded." }; // False advice public static final String[] rtips_false = { "Eating a spider corpse will cure lost DX.", "They say that wearing a top hat makes you immune to a mind-flayer's attacks.", "Rumor has it that there is a bonus for killing all hamsters.", "It's said that a parrot corpse is the ultimate weapon.", "They say that blue gum totally restores a person's HP.", "Pets aren't harmed by tainted corpses.", "Eating toads builds character.", "Suzie is not really evil.", "This statement is false.", "Eating Suzie gives extra points.", "It is said that graffiti is always true.", "According to rumor, polymorphing into a hamster is the ultimate strategy!", "The random number generator hates all that live.", "They say that gnomes are totally harmless, even if you attack them.", "The book ``Java in a Nutshell'' is good, accessible reading.", "Food found in cesspools tastes the best.", "The most powerful enemies will die instantly if you attack them with a stick." }; // specific pregenerated graffiti public static final String[] rgraffiti = { "I know what you did last semester", "I'll get you, and your little pikachu too! - Suzie", "I hope you die - The RNG", "I write, therefore I am", "Arm yourself before the gerbils get you!", "GNOMES: WE ARE THE FOUNT OF AWESOME", "Won't someone think of the children?", "(C) 1956 Omniwall, inc. All rights reserved.", "Wall of Blocking +3", "This is not a wall", "I am a wall. I hate you.", "I was murdered by --", "This wall contains no lead.", "contains asbestos: do not eat" }; private static String graffiti() { switch (Utl.rn(8)) { case 0: return Utl.rn(random_names)+" "+Utl.rn(1,12)+"/"+Utl.rn(75,99); case 1: return "???? ???"; case 2: return "call "+Utl.rn(random_names)+" ???-"+Utl.rn(10)+"?"+Utl.rn(10)+"?"; case 3: return Utl.rn(rtips_true); case 4: return Utl.rn(rtips_false); case 5: return Utl.rn(random_names)+" was here!"; default: return Utl.rn(rgraffiti); // specific graffiti } } // Create a random room name ------------------------------------- public static String random_room_desc(boolean tunnel) { switch (Utl.rn(10)) { case 0: return "This "+(tunnel? "tunnel" : "room")+" is "+Utl.rn(rsize_adjectives)+"."; case 1: return "This "+(tunnel? "tunnel" : "room")+" is rather "+Utl.rn(rsize_adjectives)+"."; case 2: return "The "+(tunnel? "tunnel" : "room")+" is "+Utl.rn(radjectives)+"."; case 3: return "Some graffiti on the wall says: `"+graffiti()+"'"; default: return "This is a "+(tunnel? "tunnel" : "room")+" like many others."; } } /* This function "fixes" nodes, building reciporical links. */ public static void fix (Node[][] m) { Node cur = null; for (int i = 1; i < m.length; ++i) for (int j = 0; j < m.length; ++j) { cur = m[i][j]; if (cur == null) continue; if (cur.north != null) cur.north.south = cur; if (cur.south != null) cur.south.north = cur; if (cur.east != null) cur.east.west = cur; if (cur.west != null) cur.west.east = cur; /* if (m[i][j].north == null && m[i][j-1] != null && m[i][j-1].south == null) { m[i][j].north = m[i][j-1]; m[i][j-1].south = m[i][j]; } if (m[i][j].south == null && m[i][j+1] != null && m[i][j+1].north == null) { m[i][j].south = m[i][j+1]; m[i][j+1].north = m[i][j]; } if (m[i][j].east == null && m[i-1][j] != null && m[i-1][j].west == null) { m[i][j].east = m[i-1][j]; m[i-1][j].west = m[i][j]; } if (m[i][j].west == null && m[i+1][j] != null && m[i+1][j].east == null) { m[i][j].west = m[i+1][j]; m[i+1][j].east = m[i][j]; } */ } } private static int[] nswe2nesw = {0, 2, 3, 1}; private static int[] nesw2nswe = {0, 3, 1, 2}; public static int rotate (int odir, int steps) { int cache = (nswe2nesw[odir] + steps) % 4; if (cache < 0) cache += 4; return nesw2nswe[cache]; } private static boolean in (Node n, int x, int y, int w, int h) { return (n.x >= x && n.x < x + w && n.y >= y && n.y < y + h); } public static void show(Node center, int w, int h, boolean omni, int maxlen) { String[][] matrix = new String[h][w]; for (String [] row: matrix) for (int i = 0; i < w; ++i) row[i] = " "; Vector traversed = new Vector(); show(center, w/2, h/2, w, h, center.trav, matrix, omni, true, 1, '*', maxlen, center.region, traversed); if (Tunnels.gmode != Tunnels.DOS) System.out.println("\033(0"); for (String[] row: matrix) { for (int i = 0; i < w; ++i) System.out.print(row[i]); System.out.println(""); } if (Tunnels.gmode != Tunnels.DOS) System.out.println("\033(B"); for (int i = 0; i < traversed.size(); ++i) { ((Node)traversed.elementAt(i)).trav = false; } } public static void show (Node center, int x, int y, int w, int h, boolean phase, String[][] matrix, boolean omni, boolean pv, int travlen, char direc, int maxlen, int region, Vector traversed) { if (travlen == maxlen) return; center.trav = !phase; center.seen = true; traversed.addElement((Object)center); //System.out.printf("XX %d %d %d %d\n", x, y, w, h); if (matrix[y][x] == " ") if (center == g.here && (Tunnels.gmode != Tunnels.DOS)) matrix[y][x] = Ifc.color(Ifc.INVERSE) + center.unbiased_character() + Ifc.color(); else if (center == g.here) matrix[y][x] = "@"; else if (omni || center.visited) matrix[y][x] = Ifc.color(center.color) + center.character() + Ifc.color(); else matrix[y][x] = (Tunnels.gmode != Tunnels.DOS? "a" : "\260"); boolean visited = center.visited; if (center.north != null && center.north.trav == phase && y > 0 && (direc == 'n' || direc == '*' || omni || center.north.seen) && (center.north.region == region || center.north.bridge)) { show(center.north, x, y-1, w, h, phase, matrix, omni, visited, travlen + (center.north.visited? 0 : 1), 'n', maxlen, region, traversed ); } if (center.south != null && center.south.trav == phase && y < h-1 && (direc == 's' || direc == '*' || omni || center.south.seen) && (center.south.region == region || center.south.bridge)) { show(center.south, x, y+1, w, h, phase, matrix, omni, visited, travlen + (center.south.visited? 0 : 1), 's', maxlen, region, traversed ); } if (center.west != null && center.west.trav == phase && x > 0 && (direc == 'w' || direc == '*' || omni || center.west.seen) && (center.west.region == region || center.west.bridge)) { show(center.west, x-1, y, w, h, phase, matrix, omni, visited, travlen + (center.west.visited? 0 : 1), 'w', maxlen, region, traversed ); } if (center.east != null && center.east.trav == phase && x < w-1 && (direc == 'e' || direc == '*' || omni || center.east.seen) && (center.east.region == region || center.east.bridge)) { show(center.east, x+1, y, w, h, phase, matrix, omni, visited, travlen + (center.east.visited? 0 : 1), 'e', maxlen, region, traversed ); } } private static int change_dir(int current) { if (current < 2) return 2+Utl.rn(2); else return Utl.rn(2); } public final static int NORTH = 0, SOUTH = 1, EAST = 2, WEST = 3; public static Node make_map(Node center, MoleParameterSet p, MoleParameterSet r) { boolean phase; Node lab; Node hall; Node tower; Node en; Node [][] matrix; int regnum = 0; while (true) { en = new Entrance(); lab = new Node(); lab = new Region_Bridge(lab); hall = new Champion_Hall(); tower = new Programmer_Tower(); try { matrix = new Node[(p.life + p.vlife) * 2][(p.life + p.vlife) * 2]; int c = (p.life + p.vlife); matrix[c][c] = center; mole(matrix, c, c, p, 0, SOUTH, lab, 0); mole(matrix, c, c, p, 0, EAST, hall, 0); mole(matrix, c, c, p, 0, WEST, tower, 0); mole(matrix, c, c, r, 0, NORTH, en, 0); fix(matrix); phase = !en.trav; traverse(en, phase); if (lab.trav == phase && hall.trav == phase && tower.trav == phase && en.trav == phase && center.trav == phase) break; else { for (int i = 0; i < g.nodes.size(); ++i) { ((Node)g.nodes.elementAt(i)).finalize(); } g.nodes.removeAllElements(); g.deadends.removeAllElements(); } } catch (InstantiationException e) { System.out.println("Error making map. Probably really bad."); } catch (IllegalAccessException e) { System.out.println("Error making map. Probably really bad."); } } ZeiusRegion labreg = new ZeiusRegion(lab, ++regnum); for (Class re: Region.regions_to_make) { try { Node start = (Node)Utl.rn(g.deadends); g.deadends.remove((Object)start); start = new Region_Bridge(start); Region reg = (Region)(re.getConstructors()[0].newInstance(start, ++regnum)); } catch (InstantiationException e) { System.out.println("Error making map. Probably really bad. " + e); } catch (IllegalAccessException e) { System.out.println("Error making map. Probably really bad. " + e); } catch (InvocationTargetException e) { System.out.println("Error making map. Probably really bad. " + e); } } for (int i = 0; i < g.nodes.size(); ++i) { ((Node)g.nodes.elementAt(i)).trav = false; } return en; } private static void traverse (Node start, boolean phase) { start.trav = phase; if (countlinks(start) == 1 && start.tunnel) g.deadends.add((Object)start); if (start.north != null && start.north.trav != phase) traverse(start.north, phase); if (start.south != null && start.south.trav != phase) traverse(start.south, phase); if (start.east != null && start.east.trav != phase) traverse(start.east, phase); if (start.west != null && start.west.trav != phase) traverse(start.west, phase); } public static int countlinks (Node n) { int ret = (n.north != null? 1:0); ret += (n.south != null? 1:0); ret += (n.east != null? 1:0); ret += (n.west != null? 1:0); return ret; } private static int[][] DIR = {{0,-1},{0,1},{-1,0},{1,0}}; public static void makelink(Node newnode, Node oldnode, int direction) { if (direction == 0) { if (oldnode != null) oldnode.north = newnode; newnode.south = oldnode; } else if (direction == 1) { if (oldnode != null) oldnode.south = newnode; newnode.north = oldnode; } else if (direction == 2) { if (oldnode != null) oldnode.west = newnode; newnode.east = oldnode; } else if (direction == 3) { if (oldnode != null) oldnode.east = newnode; newnode.west = oldnode; } else System.out.println("This should never happen."); } private static void mole(Node[][] m, int x, int y, MoleParameterSet p, int i, int direction, Node terminal, int region) throws InstantiationException, IllegalAccessException { int life = p.life + Utl.rn(-p.vlife); int ox = 0; int oy = 0; int hold = 0; int count = p.switch_len; int freq = p.corr_chance; while (i < life) { ox = x; oy = y; x += DIR[direction][0]; y += DIR[direction][1]; hold = 2; if (x == 0) direction = 1; if (y == 0) direction = 0; if (x == m.length - 1) direction = 2; if (y == m.length - 1) direction = 3; else hold = 0; // square matrix assumed. //if (x >= m.length - 5 || x < 5 || y >= m.length - 5 || y < 5) break; --hold; if (hold <= 0) { if (m[x][y] != null) { if (Utl.rn(1000) < p.grid_chance) makelink(m[x][y], m[ox][oy], direction); } else { if (i + 1== life) m[x][y] = terminal; else if (Utl.rn(1000) < p.special_chance) m[x][y] = (Node)Utl.rn(Node.non_unique_special_nodes).newInstance(); else { m[x][y] = new Node(); m[x][y].tunnel = Utl.rn(1000) < p.tunnel_chance; m[x][y].description = Map.random_room_desc(m[x][y].tunnel); //"This is a " + (m[x][y].tunnel? "tunnel" : "room") + " like many others."; m[x][y].name = (m[x][y].tunnel? "Tunnel" : "Room"); if (Utl.rn(1000) < p.item_chance) { m[x][y].add(Utl.rn(Items.all_items).make()); } if (Utl.rn(1000) < p.monster_chance) { m[x][y].add(Species.good_mon((int)(i*p.difficulty_slope + p.inital_difficulty))); } m[x][y].spawn_chance = p.spawn_chance; } m[x][y].region = region; m[x][y].x = x; m[x][y].y = y; makelink(m[x][y], m[ox][oy], direction); ++i; } --count; if (count <= 0) { count = p.switch_len; freq = (p.rand_chance + p.corr_chance) - freq; } if (Utl.rn(1000) < freq) direction = Utl.rn(4); //if (i > p.safety_zone && Utl.rn(1000) < p.branch) //mole(m, x, y, p, i+20, Utl.rn(4), (Node)Utl.rn(Node.non_unique_special_nodes).newInstance()); } } //ox = x; oy = y; //x += DIR[direction][0]; y += DIR[direction][1]; // if (m[x][y] != null && m[x][y].unique) // System.out.println("WARNING! PATHOLOGICAL RANDOM MAP; YOUR GAME MAY BE UNWINNABLE."); //m[x][y] = terminal; //makelink(m[x][y], m[ox][oy], direction); } }