package com.planet_ink.coffee_mud.Libraries.layouts; import java.util.Enumeration; import java.util.Hashtable; import java.util.Random; import java.util.Vector; import com.planet_ink.coffee_mud.Libraries.interfaces.AreaGenerationLibrary.LayoutFlags; import com.planet_ink.coffee_mud.Libraries.interfaces.AreaGenerationLibrary.LayoutNode; import com.planet_ink.coffee_mud.Libraries.interfaces.AreaGenerationLibrary.LayoutRuns; import com.planet_ink.coffee_mud.Libraries.interfaces.AreaGenerationLibrary.LayoutTypes; import com.planet_ink.coffee_mud.core.Directions; public class LayoutSet { Random r = new Random(); private long total = 0; private final Hashtable<Long, LayoutNode> used = new Hashtable<Long, LayoutNode>(); private Vector<LayoutNode> set = null; public LayoutSet(Vector<LayoutNode> V, long total) { this.total = total; this.set = V; } public Vector<LayoutNode> set() { return set;} public Long getHashCode(long x, long y){ return (Long.valueOf((x * total)+y));} public boolean isUsed(long[] xy) { return isUsed(xy[0],xy[1]); } public boolean isUsed(long x, long y) { return used.containsKey(getHashCode(x,y)); } public boolean isUsed(LayoutNode n) { return isUsed(n.coord())&&set.contains(n); } public void unUse(LayoutNode n) { used.remove(getHashCode(n.coord()[0],n.coord()[1])); set.remove(n); } public boolean use(LayoutNode n, LayoutTypes nodeType) { if(isUsed(n.coord())) return false; used.put(getHashCode(n.coord()[0],n.coord()[1]),n); set.add(n); if(nodeType != null) n.reType(nodeType); return true; } public LayoutNode getNode(long[] xy) { return getNode(xy[0],xy[1]);} public LayoutNode getNode(long x, long y) { return used.get(getHashCode(x,y));} public boolean spaceAvailable() { return set.size() < total; } public long[] makeNextCoord(long[] n, int dir) { switch(dir) { case Directions.NORTH: return new long[]{n[0],n[1]-1}; case Directions.SOUTH: return new long[]{n[0],n[1]+1}; case Directions.EAST: return new long[]{n[0]+1,n[1]}; case Directions.WEST: return new long[]{n[0]-1,n[1]}; } return null; } public LayoutNode makeNextNode(LayoutNode n, int dir) { long[] l = makeNextCoord(n.coord(),dir); if(l!=null) return new DefaultLayoutNode(l); return null; } public LayoutNode getNextNode(LayoutNode n, int dir) { LayoutNode next = makeNextNode(n,dir); return getNode(next.coord()); } public void drawABox(int width, int height) { LayoutNode n = new DefaultLayoutNode(new long[]{0,0}); n.flag(LayoutFlags.corner); for(int y=0;y<height-1;y++) { use(n,LayoutTypes.surround); LayoutNode nn = getNextNode(n, Directions.NORTH); if(nn==null) nn=makeNextNode(n, Directions.NORTH); n.crossLink(nn); nn.flagRun(LayoutRuns.ns); n=nn; } n.flag(LayoutFlags.corner); use(n,LayoutTypes.surround); n = new DefaultLayoutNode(new long[]{width-1,0}); n.flag(LayoutFlags.corner); for(int y=0;y<height-1;y++) { use(n,LayoutTypes.surround); LayoutNode nn = getNextNode(n, Directions.NORTH); if(nn==null) nn=makeNextNode(n, Directions.NORTH); n.crossLink(nn); nn.flagRun(LayoutRuns.ns); n=nn; } n.flag(LayoutFlags.corner); use(n,LayoutTypes.surround); n = getNode(new long[]{0,0}); n.flag(LayoutFlags.corner); for(int x=0;x<width-1;x++) { use(n,LayoutTypes.surround); LayoutNode nn = getNextNode(n, Directions.EAST); if(nn==null) nn=makeNextNode(n, Directions.EAST); n.crossLink(nn); nn.flagRun(LayoutRuns.ns); n=nn; } n.flag(LayoutFlags.corner); use(n,LayoutTypes.surround); n = getNode(new long[]{0,-height+1}); n.flag(LayoutFlags.corner); for(int x=0;x<width-1;x++) { use(n,LayoutTypes.surround); LayoutNode nn = getNextNode(n, Directions.EAST); if(nn==null) nn=makeNextNode(n, Directions.EAST); n.crossLink(nn); nn.flagRun(LayoutRuns.ns); n=nn; } n.flag(LayoutFlags.corner); use(n,LayoutTypes.surround); } public boolean fillMaze(LayoutNode p) { Vector<Integer> dirs = new Vector<Integer>(); for(int i=0;i<4;i++) dirs.add(Integer.valueOf(i)); Vector<Integer> rdirs = new Vector<Integer>(); while(dirs.size()>0) { int x = r.nextInt(dirs.size()); Integer dir = dirs.elementAt(x); dirs.removeElementAt(x); rdirs.addElement(dir); } for(int r=0;r<rdirs.size();r++) { Integer dir = rdirs.elementAt(r); LayoutNode p2 = getNextNode(p, dir.intValue()); if(p2 == null) { p2 = makeNextNode(p, dir.intValue()); p.crossLink(p2); use(p2,LayoutTypes.interior); fillMaze(p2); } } return true; } public void clipLongStreets() { @SuppressWarnings("unchecked") Vector<LayoutNode> set2=(Vector<LayoutNode>)set().clone(); for(Enumeration<LayoutNode> e=set2.elements();e.hasMoreElements();) { LayoutNode p=e.nextElement(); if(isUsed(p) && p.isStreetLike()) for(int d=0;d<4;d++) if(p.getLink(d)==null) { LayoutNode p2 =getNextNode(p, d); if((p2!=null) &&(!p.links().containsValue(p2))) { Enumeration<LayoutNode> nodes=p.links().elements(); LayoutNode p_1=(LayoutNode)nodes.nextElement(); LayoutNode p_2=(LayoutNode)nodes.nextElement(); p.deLink(); p_1.crossLink(p_2); unUse(p); LayoutNode p3 = makeNextNode(p2, Directions.getOpDirectionCode(d)); p2.crossLink(p3); use(p3, LayoutTypes.leaf); break; } } } } public void fillInFlags() { for(Enumeration<LayoutNode> e=set().elements();e.hasMoreElements();) { LayoutNode n = (LayoutNode)e.nextElement(); int[] dirs=new int[n.links().size()]; int x=0; for(Integer dirLink : n.links().keySet()) dirs[x++]=dirLink.intValue(); n.setExits(dirs); if((dirs.length==1)&&(!n.isFlagged(LayoutFlags.gate))) n.reType(LayoutTypes.leaf); } for(Enumeration<LayoutNode> e=set().elements();e.hasMoreElements();) { LayoutNode n = (LayoutNode)e.nextElement(); if(n.links().size()==2) { LayoutFlags flag = null; if(n.type()==LayoutTypes.interior) for(Integer dirLink : n.links().keySet()) { LayoutNode n2=n.links().get(dirLink); if((n2!=null)&&(n2.type()==LayoutTypes.leaf)) flag=LayoutFlags.offleaf; } if(flag!=null) n.flag(flag); else { Enumeration<Integer> dirs=n.links().keys(); Integer lN1=dirs.nextElement(); Integer lN2=dirs.nextElement(); if(lN1.intValue() != Directions.getOpDirectionCode(lN2.intValue())) n.flag(LayoutFlags.corner); } } else if((n.links().size()==3) &&(((n.type()==LayoutTypes.street) ||(n.type()!=LayoutTypes.surround)))) { boolean allStreet = true; for(Integer dirLink : n.links().keySet()) { LayoutNode n2=n.links().get(dirLink); if((n2==null) ||((n2.type()!=LayoutTypes.street) &&(n2.type()!=LayoutTypes.surround))) allStreet = false; } if(allStreet) n.flag(LayoutFlags.tee); } else if((n.links().size()==4) &&(((n.type()==LayoutTypes.street) ||(n.type()!=LayoutTypes.surround)))) { boolean allStreet = true; for(Integer dirLink : n.links().keySet()) { LayoutNode n2=n.links().get(dirLink); if((n2==null) ||((n2.type()!=LayoutTypes.street) &&(n2.type()!=LayoutTypes.surround))) allStreet = false; } if(allStreet) n.flag(LayoutFlags.intersection); } } } }