package greymerk.roguelike.dungeon.towers;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import greymerk.roguelike.theme.ITheme;
import greymerk.roguelike.worldgen.Cardinal;
import greymerk.roguelike.worldgen.Coord;
import greymerk.roguelike.worldgen.IBlockFactory;
import greymerk.roguelike.worldgen.IStair;
import greymerk.roguelike.worldgen.IWorldEditor;
import greymerk.roguelike.worldgen.MetaBlock;
import greymerk.roguelike.worldgen.blocks.BlockType;
import greymerk.roguelike.worldgen.blocks.Leaves;
import greymerk.roguelike.worldgen.blocks.Log;
import greymerk.roguelike.worldgen.blocks.Vine;
import greymerk.roguelike.worldgen.blocks.Wood;
import greymerk.roguelike.worldgen.shapes.RectSolid;
public class JungleTower implements ITower{
@Override
public void generate(IWorldEditor editor, Random rand, ITheme theme, Coord dungeon) {
Coord origin = Tower.getBaseCoord(editor, dungeon);
origin.add(Cardinal.UP);
IBlockFactory pillar = theme.getPrimary().getPillar();
IBlockFactory walls = theme.getPrimary().getWall();
IStair stair = theme.getPrimary().getStair();
MetaBlock grass = BlockType.get(BlockType.GRASS);
Coord start;
Coord end;
Coord cursor;
// lower pillars
for(Cardinal dir : Cardinal.directions){
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 3);
cursor.add(dir, 7);
pillar(editor, rand, theme, cursor);
for(Cardinal o : Cardinal.orthogonal(dir)){
Coord c = new Coord(cursor);
c.add(o, 3);
pillar(editor, rand, theme, c);
c.add(dir);
c.add(Cardinal.UP);
walls.set(editor, rand, c);
c.add(Cardinal.UP);
walls.set(editor, rand, c);
c.add(Cardinal.UP);
stair.setOrientation(dir, false).set(editor, c);
c.add(Cardinal.reverse(dir));
walls.set(editor, rand, c);
}
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 4);
cursor.add(dir, 8);
walls.set(editor, rand, cursor);
cursor.add(Cardinal.UP);
walls.set(editor, rand, cursor);
cursor.add(Cardinal.UP);
stair.setOrientation(dir, false).set(editor, cursor);
cursor.add(Cardinal.reverse(dir));
walls.set(editor, rand, cursor);
start = new Coord(origin);
start.add(dir, 2);
start.add(Cardinal.left(dir), 2);
end = new Coord(start);
end.add(Cardinal.UP, 3);
pillar.fill(editor, rand, new RectSolid(start, end));
cursor = new Coord(end);
for(Cardinal d : new Cardinal[]{Cardinal.reverse(dir), Cardinal.right(dir)}){
Coord c = new Coord(cursor);
c.add(d);
stair.setOrientation(d, true).set(editor, c);
}
// corner pillar
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 6);
cursor.add(dir, 6);
cursor.add(Cardinal.left(dir), 6);
editor.fillDown(rand, new Coord(cursor), pillar);
for(Cardinal d : new Cardinal[]{dir, Cardinal.left(dir)}){
start = new Coord(cursor);
start.add(d);
stair.setOrientation(d, false).set(editor, start);
start.add(Cardinal.DOWN);
end = new Coord(start);
end.add(Cardinal.DOWN, 2);
walls.fill(editor, rand, new RectSolid(start, end));
end.add(Cardinal.DOWN);
stair.setOrientation(d, true).set(editor, end);
}
}
for(Cardinal dir : Cardinal.directions){
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 4);
cursor.add(dir, 7);
start = new Coord(cursor);
end = new Coord(cursor);
start.add(Cardinal.left(dir), 5);
end.add(Cardinal.right(dir), 5);
walls.fill(editor, rand, new RectSolid(start, end));
start.add(Cardinal.UP);
end.add(Cardinal.UP);
grass.fill(editor, rand, new RectSolid(start, end));
start.add(Cardinal.reverse(dir));
end.add(Cardinal.reverse(dir));
walls.fill(editor, rand, new RectSolid(start, end));
start.add(Cardinal.reverse(dir));
end.add(Cardinal.reverse(dir));
stair.setOrientation(Cardinal.reverse(dir), true).fill(editor, rand, new RectSolid(start, end));
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 4);
cursor.add(dir, 6);
pillar(editor, rand, theme, cursor);
for(Cardinal o : Cardinal.orthogonal(dir)){
Coord c = new Coord(cursor);
c.add(o, 3);
pillar(editor, rand, theme, c);
}
start = new Coord(origin);
start.add(Cardinal.UP, 5);
start.add(dir, 2);
end = new Coord(start);
end.add(dir, 3);
walls.fill(editor, rand, new RectSolid(start, end));
end.add(Cardinal.left(dir), 3);
start = new Coord(end);
start.add(Cardinal.reverse(dir), 10);
walls.fill(editor, rand, new RectSolid(start, end));
start = new Coord(origin);
start.add(Cardinal.UP, 6);
start.add(dir, 3);
start.add(Cardinal.left(dir), 2);
end = new Coord(start);
end.add(Cardinal.right(dir), 8);
end.add(dir, 3);
walls.fill(editor, rand, new RectSolid(start, end));
start = new Coord(origin);
start.add(Cardinal.UP, 4);
start.add(dir, 2);
end = new Coord(start);
start.add(Cardinal.left(dir), 2);
end.add(Cardinal.right(dir));
end.add(Cardinal.UP, 2);
walls.fill(editor, rand, new RectSolid(start, end));
start = new Coord(origin);
start.add(Cardinal.UP, 4);
start.add(dir, 3);
end = new Coord(start);
start.add(Cardinal.left(dir), 3);
end.add(Cardinal.right(dir), 2);
stair.setOrientation(dir, true).fill(editor, rand, new RectSolid(start, end));
}
// level 2 grass patches
for(Cardinal dir : Cardinal.directions){
for(Cardinal o : Cardinal.orthogonal(dir)){
start = new Coord(origin);
start.add(Cardinal.UP, 6);
start.add(dir, 5);
start.add(o);
end = new Coord(start);
end.add(o);
end.add(dir);
grass.fill(editor, rand, new RectSolid(start, end));
start.add(o, 3);
end.add(o, 3);
grass.fill(editor, rand, new RectSolid(start, end));
}
}
// second floor pillars
for(Cardinal dir : Cardinal.directions){
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 9);
cursor.add(dir, 5);
for(Cardinal o : Cardinal.orthogonal(dir)){
Coord c = new Coord(cursor);
c.add(o, 2);
pillar(editor, rand, theme, c);
c.add(dir);
c.add(Cardinal.UP);
walls.set(editor, rand, c);
c.add(Cardinal.UP);
stair.setOrientation(dir, false).set(editor, c);
c.add(Cardinal.reverse(dir));
walls.set(editor, rand, c);
c.add(Cardinal.UP);
stair.setOrientation(dir, false).set(editor, c);
}
cursor.add(Cardinal.left(dir), 5);
pillar(editor, rand, theme, cursor);
for(Cardinal d : new Cardinal[]{Cardinal.left(dir), dir}){
Coord c = new Coord(cursor);
c.add(d);
c.add(Cardinal.UP);
walls.set(editor, rand, c);
c.add(Cardinal.UP);
stair.setOrientation(d, false).set(editor, c);
}
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 10);
cursor.add(dir, 2);
cursor.add(Cardinal.left(dir), 2);
start = new Coord(cursor);
end = new Coord(start);
end.add(Cardinal.DOWN, 3);
pillar.fill(editor, rand, new RectSolid(start, end));
for(Cardinal d : new Cardinal[]{Cardinal.right(dir), Cardinal.reverse(dir)}){
Coord c = new Coord(cursor);
c.add(d);
stair.setOrientation(d, true).set(editor, c);
}
cursor.add(Cardinal.DOWN);
for(Cardinal d : new Cardinal[]{Cardinal.left(dir), dir}){
Coord c = new Coord(cursor);
c.add(d);
stair.setOrientation(d, true).set(editor, c);
c.add(Cardinal.UP);
walls.set(editor, rand, c);
c.add(d);
walls.set(editor, rand, c);
}
}
for(Cardinal dir : Cardinal.directions){
start = new Coord(origin);
start.add(Cardinal.UP, 10);
start.add(dir, 5);
end = new Coord(start);
start.add(Cardinal.left(dir), 5);
end.add(Cardinal.right(dir), 4);
walls.fill(editor, rand, new RectSolid(start, end));
start = new Coord(origin);
start.add(Cardinal.UP, 11);
start.add(dir, 2);
end = new Coord(start);
start.add(Cardinal.left(dir));
end.add(Cardinal.right(dir), 4);
end.add(dir, 2);
walls.fill(editor, rand, new RectSolid(start, end));
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 11);
cursor.add(dir, 5);
start = new Coord(cursor);
end = new Coord(start);
start.add(Cardinal.left(dir), 4);
end.add(Cardinal.right(dir), 4);
grass.fill(editor, rand, new RectSolid(start, end));
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 12);
cursor.add(dir, 3);
start = new Coord(cursor);
end = new Coord(start);
end.add(dir);
start.add(Cardinal.left(dir));
end.add(Cardinal.right(dir), 4);
grass.fill(editor, rand, new RectSolid(start, end));
}
for(Cardinal dir : Cardinal.directions){
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 12);
cursor.add(dir, 2);
start = new Coord(cursor);
end = new Coord(cursor);
start.add(Cardinal.left(dir), 4);
end.add(Cardinal.right(dir), 4);
walls.fill(editor, rand, new RectSolid(start, end));
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 11);
cursor.add(dir, 5);
cursor.add(Cardinal.left(dir), 5);
walls.set(editor, rand, cursor);
}
for(Cardinal dir : Cardinal.directions){
cursor = new Coord(origin);
cursor.add(dir, 2);
cursor.add(Cardinal.left(dir), 2);
cursor.add(Cardinal.UP, 15);
pillar(editor, rand, theme, cursor);
for(Cardinal d : new Cardinal[]{dir, Cardinal.left(dir)}){
Coord c = new Coord(cursor);
c.add(d);
c.add(Cardinal.UP);
walls.set(editor, rand, c);
c.add(Cardinal.UP);
stair.setOrientation(d, false).set(editor, c);
}
start = new Coord(origin);
start.add(Cardinal.UP, 16);
start.add(dir, 2);
end = new Coord(start);
start.add(Cardinal.left(dir));
end.add(Cardinal.right(dir), 2);
walls.fill(editor, rand, new RectSolid(start, end));
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 17);
cursor.add(dir, 2);
start = new Coord(cursor);
end = new Coord(cursor);
start.add(Cardinal.left(dir));
end.add(Cardinal.right(dir));
grass.fill(editor, rand, new RectSolid(start, end));
cursor.add(Cardinal.left(dir), 2);
walls.set(editor, rand, cursor);
start = new Coord(origin);
start.add(Cardinal.UP, 17);
end = new Coord(start);
start.add(dir);
start.add(Cardinal.left(dir));
end.add(Cardinal.reverse(dir));
end.add(Cardinal.right(dir));
walls.fill(editor, rand, new RectSolid(start, end));
start.add(Cardinal.UP);
end.add(Cardinal.UP);
grass.fill(editor, rand, new RectSolid(start, end));
}
start = new Coord(origin);
start.add(Cardinal.NORTH, 2);
start.add(Cardinal.EAST, 2);
end = new Coord(origin.getX(), dungeon.getY() + 10, origin.getZ());
end.add(Cardinal.SOUTH, 2);
end.add(Cardinal.WEST, 2);
walls.fill(editor, rand, new RectSolid(start, end), false, true);
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 12);
start = new Coord(cursor.getX(), dungeon.getY(), cursor.getZ());
end = new Coord(cursor);
for(Coord c : new RectSolid(start, end)){
editor.spiralStairStep(rand, c, stair, pillar);
}
decorate(editor, rand, theme, origin);
}
private void decorate(IWorldEditor editor, Random rand, ITheme theme, Coord origin){
List<Coord> spots = new ArrayList<Coord>();
for(Cardinal dir : Cardinal.directions){
Coord cursor = new Coord(origin);
cursor.add(Cardinal.UP, 6);
cursor.add(dir, 7);
for(Cardinal o : Cardinal.orthogonal(dir)){
Coord c = new Coord(cursor);
c.add(o);
spots.add(new Coord(c));
c.add(o);
spots.add(new Coord(c));
c.add(o, 2);
spots.add(new Coord(c));
c.add(o);
spots.add(new Coord(c));
}
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 12);
cursor.add(dir, 5);
spots.add(new Coord(cursor));
for(Cardinal o : Cardinal.orthogonal(dir)){
Coord c = new Coord(cursor);
c.add(o);
spots.add(new Coord(c));
c.add(o, 2);
spots.add(new Coord(c));
c.add(o);
spots.add(new Coord(c));
}
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 13);
cursor.add(dir, 4);
spots.add(new Coord(cursor));
for(Cardinal o : Cardinal.orthogonal(dir)){
Coord c = new Coord(cursor);
c.add(o);
spots.add(new Coord(c));
c.add(o, 2);
spots.add(new Coord(c));
c.add(o);
spots.add(new Coord(c));
}
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 18);
cursor.add(dir, 2);
spots.add(new Coord(cursor));
for(Cardinal o : Cardinal.orthogonal(dir)){
Coord c = new Coord(cursor);
c.add(o);
spots.add(new Coord(c));
}
cursor = new Coord(origin);
cursor.add(Cardinal.UP, 19);
Coord start = new Coord(cursor);
Coord end = new Coord(cursor);
start.add(dir);
end.add(Cardinal.reverse(dir));
start.add(Cardinal.left(dir));
end.add(Cardinal.right(dir));
spots.addAll(new RectSolid(start, end).get());
}
for(Coord c : spots){
if(rand.nextBoolean()){
tree(editor, rand, theme, c);
}
}
Coord start = new Coord(origin);
Coord end = new Coord(origin);
end.add(Cardinal.UP, 20);
start.add(Cardinal.NORTH, 8);
start.add(Cardinal.EAST, 8);
end.add(Cardinal.SOUTH, 8);
end.add(Cardinal.WEST, 8);
Vine.fill(editor, rand, start, end);
}
private void tree(IWorldEditor editor, Random rand, ITheme theme, Coord origin){
MetaBlock leaves = Leaves.get(Leaves.JUNGLE, false);
Coord cursor = new Coord(origin);
Log.getLog(Wood.JUNGLE).set(editor, cursor);
for(Cardinal dir : Cardinal.directions){
Coord c = new Coord(cursor);
c.add(dir);
leafSpill(editor, rand, theme, c, rand.nextInt(6));
}
if(rand.nextBoolean()){
cursor.add(Cardinal.UP);
Log.getLog(Wood.JUNGLE).set(editor, cursor);
for(Cardinal dir : Cardinal.directions){
Coord c = new Coord(cursor);
c.add(dir);
leaves.set(editor, rand, c, true, false);
}
}
if(rand.nextInt(3) == 0){
cursor.add(Cardinal.UP);
Log.getLog(Wood.JUNGLE).set(editor, cursor);
for(Cardinal dir : Cardinal.directions){
Coord c = new Coord(cursor);
c.add(dir);
leaves.set(editor, rand, c, true, false);
}
}
cursor.add(Cardinal.UP);
leaves.set(editor, cursor);
}
public void leafSpill(IWorldEditor editor, Random rand, ITheme theme, Coord origin, int count){
if(count < 0) return;
MetaBlock leaves = Leaves.get(Leaves.JUNGLE, false);
leaves.set(editor, origin);
Coord cursor = new Coord(origin);
cursor.add(Cardinal.DOWN);
if(!editor.getBlock(cursor).getMaterial().isOpaque()){
leaves.set(editor, origin);
if(rand.nextBoolean()) leafSpill(editor, rand, theme, cursor, count - 1);
return;
}
for(Cardinal dir : Cardinal.directions){
cursor = new Coord(origin);
cursor.add(dir);
if(editor.getBlock(cursor).getMaterial().isOpaque()) continue;
leaves.set(editor, origin);
cursor.add(Cardinal.DOWN);
if(editor.getBlock(cursor).getMaterial().isOpaque()) continue;
leafSpill(editor, rand, theme, cursor, count - 1);
}
}
private void pillar(IWorldEditor editor, Random rand, ITheme theme, Coord origin){
IBlockFactory pillar = theme.getPrimary().getPillar();
IStair stair = theme.getPrimary().getStair();
Coord cursor;
editor.fillDown(rand, new Coord(origin), pillar);
for(Cardinal dir : Cardinal.directions){
cursor = new Coord(origin);
cursor.add(dir);
stair.setOrientation(dir, true).set(editor, cursor);
}
}
}