package greymerk.roguelike.dungeon.segment;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import greymerk.roguelike.dungeon.IDungeonLevel;
import greymerk.roguelike.theme.ITheme;
import greymerk.roguelike.util.WeightedChoice;
import greymerk.roguelike.util.WeightedRandomizer;
import greymerk.roguelike.worldgen.Cardinal;
import greymerk.roguelike.worldgen.Coord;
import greymerk.roguelike.worldgen.IStair;
import greymerk.roguelike.worldgen.IWorldEditor;
public class SegmentGenerator implements ISegmentGenerator{
protected Segment arch;
protected WeightedRandomizer<Segment> segments;
public SegmentGenerator(Segment arch){
this.segments = new WeightedRandomizer<Segment>();
this.arch = arch;
}
public SegmentGenerator(SegmentGenerator toCopy){
this.arch = toCopy.arch;
this.segments = new WeightedRandomizer<Segment>(toCopy.segments);
}
public SegmentGenerator(JsonObject json){
String archType = json.get("arch").getAsString();
arch = Segment.valueOf(archType);
this.segments = new WeightedRandomizer<Segment>();
JsonArray segmentList = json.get("segments").getAsJsonArray();
for(JsonElement e : segmentList){
JsonObject segData = e.getAsJsonObject();
String segType = segData.get("type").getAsString();
int weight = segData.get("weight").getAsInt();
Segment type = Segment.valueOf(segType);
this.segments.add(new WeightedChoice<Segment>(type, weight));
}
}
public void add(Segment toAdd, int weight){
this.segments.add(new WeightedChoice<Segment>(toAdd, weight));
}
@Override
public List<ISegment> genSegment(IWorldEditor editor, Random rand, IDungeonLevel level, Cardinal dir, Coord pos) {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
List<ISegment> segs = new ArrayList<ISegment>();
for(Cardinal orth : Cardinal.orthogonal(dir)){
ISegment seg = pickSegment(editor, rand, level, dir, pos);
if(seg == null) return segs;
seg.generate(editor, rand, level, orth, level.getSettings().getTheme(), new Coord(pos));
segs.add(seg);
}
if(!level.hasNearbyNode(pos) && rand.nextInt(3) == 0) addSupport(editor, rand, level.getSettings().getTheme(), x, y, z);
return segs;
}
private ISegment pickSegment(IWorldEditor editor, Random rand, IDungeonLevel level, Cardinal dir, Coord pos){
int x = pos.getX();
int z = pos.getZ();
if((dir == Cardinal.NORTH || dir == Cardinal.SOUTH) && z % 3 == 0){
if(z % 6 == 0){
return Segment.getSegment(arch);
}
return Segment.getSegment(this.segments.get(rand));
}
if((dir == Cardinal.WEST || dir == Cardinal.EAST) && x % 3 == 0){
if(x % 6 == 0){
return Segment.getSegment(arch);
}
return Segment.getSegment(this.segments.get(rand));
}
return null;
}
private void addSupport(IWorldEditor editor, Random rand, ITheme theme, int x, int y, int z){
if(!editor.isAirBlock(new Coord(x, y - 2, z))) return;
editor.fillDown(rand, new Coord(x, y - 2, z), theme.getPrimary().getPillar());
IStair stair = theme.getPrimary().getStair();
stair.setOrientation(Cardinal.WEST, true);
stair.set(editor, new Coord(x - 1, y - 2, z));
stair.setOrientation(Cardinal.EAST, true);
stair.set(editor, new Coord(x + 1, y - 2, z));
stair.setOrientation(Cardinal.SOUTH, true);
stair.set(editor, new Coord(x, y - 2, z + 1));
stair.setOrientation(Cardinal.NORTH, true);
stair.set(editor, new Coord(x, y - 2, z - 1));
}
public static SegmentGenerator getRandom(Random rand, int count) {
SegmentGenerator segments = new SegmentGenerator(Segment.ARCH);
for(int i = 0; i < count; ++i){
segments.add(Segment.getRandom(rand), 1);
}
return segments;
}
}