Upload files to "WitchGame"

This commit is contained in:
gaven 2025-09-26 16:44:43 +00:00
parent 26d2e105b7
commit 988d211db6
5 changed files with 1017 additions and 0 deletions

View File

@ -0,0 +1,78 @@
package witchGame;
import java.util.ArrayList;
import java.util.Random;
@SuppressWarnings("unused")
public class EnemyAttack {
Random rand = new Random();
private String name;
private int toHit = 0;
private int die = 1;
private int sides = 1;
private int damage = 0;
private int damageType = 0;
private int numberHits = 1;
private int saveThrow = 1; // Str 1 | Dex 2 | Con 3 | Int 4 | Wis 5 | Chr 6
private Condition condition = null;
public EnemyAttack(int numberHits, String name, int toHit, int die, int sides, int damage, int damageType) {
this.name = name;
// this.speed = speed;
this.toHit = toHit;
this.die = die;
this.sides = sides;
this.damageType = damageType;
this.numberHits = numberHits;
}
public EnemyAttack(int numberHits, String name, int toHit, int die, int sides, int damage, int damageType, int saveThrow) {
this.name = name;
// this.speed = speed;
this.toHit = toHit;
this.die = die;
this.sides = sides;
this.damageType = damageType;
this.numberHits = numberHits;
this.saveThrow = saveThrow;
}
//TODO: pass conditions and consider advantage disadvantage
public int attack(ArrayList<Condition> conditions) {
int damageTotal = 0;
for (int a = 0; a < numberHits; a++) {
int rollToHit = rand.nextInt(21) + toHit;
int advantageOrDisadvantage = 0;
for (Condition condition : conditions) {
switch (condition.getConditionType()) {
default:
}
}
// for (Condition condition : witch.playerConditions) {
// switch (condition.getConditionType()) {
// default:
//
// }
// }
if (witch.playerAC < rollToHit) {
damageTotal += witch.dice(die, sides) + damage;
System.out.println(" " + name + ": " + damageTotal + " " + witch.damageTypes[damageType] + " damage!");
} else {
System.out.println(" " + name + ": Missed!");
}
}
return damageTotal;
}
public String toString() {
return (name + "\n+" + toHit + " to Hit\n" + die + "d" + sides + " + " + damage + " " + damageType + " damage");
// if (condition != null) {
//
// }
}
// damageTypes = {"acid", "bludgeoning", "cold", "fire", "force", "lightning", "necrotic", "piercing", "poison", "psychic", "radiant", "slashing", "thunder"};
}

87
WitchGame/Equipment.java Normal file
View File

@ -0,0 +1,87 @@
package witchGame;
import java.util.ArrayList;
import java.util.List;
public class Equipment extends Item {
// private String name;
// private int cost;
private ArrayList<Condition> constantEffects;
private ArrayList<Condition> abilityEffects;
// private TargetType abilityTarget;
// private int maxAbilityUses;
// private int abilityUses;
@Override
public String toString() {
String toString = "Equipment: " + name + "\nEquipslot: " + equipSlot + "\n";
if (constantEffects.size() > 0) {
toString += "Wearer has: \n";
for (Condition condition : constantEffects) {
toString += condition.toString();
}
}
if (abilityEffects.size() > 0) {
toString += "Ability:\n";
switch (abilityTarget) {
case Self: toString += "Apply to Self\n"; break;
case Enemy: toString += "Apply to Target Enemy\n"; break;
case AllEnemies: toString += "Apply to All Enemies\n"; break;
default: break;
}
for (Condition condition : abilityEffects) {
toString += condition.toString();
}
}
return toString;
}
public Equipment(String name, EquipmentType equipSlot, int cost, ArrayList<Condition> constantEffects,
ArrayList<Condition> abilityEffects, TargetType abilityTarget, int maxAbilityUses) {
super();
this.name = name;
this.equipSlot = equipSlot;
this.cost = cost;
this.constantEffects = constantEffects;
this.abilityEffects = abilityEffects;
this.abilityTarget = abilityTarget;
this.maxAbilityUses = maxAbilityUses;
this.abilityUses = this.maxAbilityUses;
}
public Equipment(String name, EquipmentType equipSlot, int cost, ArrayList<Condition> constantEffects) {
super();
this.name = name;
this.equipSlot = equipSlot;
this.cost = cost;
this.constantEffects = constantEffects;
this.abilityEffects = null;
this.abilityTarget = null;
this.maxAbilityUses = 0;
this.abilityUses = this.maxAbilityUses;
}
public Equipment(String name, EquipmentType equipSlot, int cost, ArrayList<Condition> abilityEffects,
TargetType abilityTarget, int maxAbilityUses) {
super();
this.name = name;
this.equipSlot = equipSlot;
this.cost = cost;
this.constantEffects = null;
this.abilityEffects = abilityEffects;
this.abilityTarget = abilityTarget;
this.maxAbilityUses = maxAbilityUses;
this.abilityUses = this.maxAbilityUses;
}
public static ArrayList<Equipment> equipmentList = new ArrayList<Equipment>();
static {
equipmentList.add(new Equipment("Breastplate", EquipmentType.Chest, 750, new ArrayList<Condition>(List.of(new Condition(ConditionType.ModifierOnAC, 999, 6), new Condition(ConditionType.DisadvantageOnAttacks, 999))))); //
}
}

View File

@ -0,0 +1,15 @@
package witchGame;
public enum EquipmentType {
Null,
Head,
Chest,
OneArm,
TwoArms,
Legs,
Trinket,
Consumable,
}

53
WitchGame/Item.java Normal file
View File

@ -0,0 +1,53 @@
package witchGame;
public abstract class Item implements Cloneable {
protected String name;
protected EquipmentType equipSlot;
protected int cost;
protected TargetType abilityTarget;
protected int abilityUses;
protected int maxAbilityUses;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public TargetType getAbilityTarget() {
return abilityTarget;
}
public int getAbilityUses() {
return abilityUses;
}
public void setAbilityUses(int abilityUses) {
this.abilityUses = abilityUses;
if (this.abilityUses > maxAbilityUses) {
this.abilityUses = maxAbilityUses;
}
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
public EquipmentType getEquipSlot() {
return equipSlot;
}
@Override
public String toString() {
return "Item: " + name + "\n";
}
}

784
WitchGame/MapSections.java Normal file
View File

@ -0,0 +1,784 @@
package witchGame;
import java.awt.color.*;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.DoubleStream;
import java.awt.Graphics;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import javax.swing.JPanel;
//@SuppressWarnings("unused")
public class MapSections extends JPanel {
private static final long serialVersionUID = 1L;
private int[][] regions;
private int[][] points;
private Color color;
private int e = 20;
private int offset = 25;
private Color[] regionColors = { Color.WHITE, Color.CYAN, Color.YELLOW, new Color(0, 64, 2) /* Forest Green */,
new Color(148, 200, 132) /* Mid Green */, new Color(107, 205, 0),
new Color(150, 150, 150) /* Darker Gray */, new Color(53, 74, 33) /* Aquamarine */, Color.DARK_GRAY,
Color.BLUE, Color.ORANGE };
Color myWhite = new Color(255, 255, 255);
private boolean debug = !true;
// final static String[] biomes = {"arctic", "coastal", "desert", "forest", "grassland", "hills", "mountains", "swampland", "underdark", "underwater", "urban"};
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
boolean[][] adjacent = new boolean[witchRunner.regions.length][witchRunner.regions.length];
ArrayList<Integer> adj = new ArrayList<>();
for (int r = 0; r < regions.length; r++) {
adj.clear();
for (int x = 0; x < witch.map_.length; x++) {
for (int y = 0; y < witch.map_[0].length; y++) {
if (witch.map_[x][y] == r) {
if (x != 0) {
if (y != witch.map_[0].length - 1)
adj.add(witch.map_[x - 1][y + 1]);
adj.add(witch.map_[x - 1][y]);
if (y != 0)
adj.add(witch.map_[x - 1][y - 1]);
}
if (x != witch.map_.length - 1) {
if (y != witch.map_[0].length - 1)
adj.add(witch.map_[x + 1][y + 1]);
adj.add(witch.map_[x + 1][y]);
if (y != 0)
adj.add(witch.map_[x + 1][y - 1]);
}
if (y != witch.map_[0].length - 1)
adj.add(witch.map_[x][y + 1]);
if (y != 0)
adj.add(witch.map_[x][y - 1]);
}
}
}
for (int i = 0; i < adjacent.length; i++) {
// adj.remove(i); // This removes one of each number from the adj array, meaning there has to be at least 2 places close to each region
if (adj.contains(i) && i != r) {
adjacent[r][i] = true;
} else {
adjacent[r][i] = false;
}
}
}
// for (int x = 0; x < adjacent.length; x++) {
// System.out.print("\n" + x + " is adjacent to: ");
// for (int y = 0; y < adjacent[x].length; y++) {
// if (adjacent[x][y]) {
// System.out.print(y + ", ");
// }
// }
// }
// System.out.println();
// g2.setColor(Color.BLUE); // TODO:?
// g2.setStroke(new BasicStroke(10));
Path2D linesBetween = new Path2D.Double();
// int[][] adjacentLines = new int[99999999][2];
int num = 0;
for (int i = 0; i < adjacent.length; i++) {
for (int j = i + 1; j < adjacent.length; j++) {
if (adjacent[i][j]) {
linesBetween.moveTo(offset + regions[i][1] * e, offset + regions[i][0] * e);
linesBetween.lineTo(offset + regions[j][1] * e, offset + regions[j][0] * e);
// adjacentLines[num][0] = i;
// adjacentLines[num++][1] = j;
}
}
}
g2.draw(linesBetween);
g2.setColor(Color.GREEN);
g2.setStroke(new BasicStroke(4));
num = 0;
double[][] possibleCircumcenters = new double[604800][6];
for (int a = 0; a < regions.length; a++) {
for (int b = a + 1; b < regions.length; b++) {
for (int c = b + 1; c < regions.length; c++) {
// System.arraycopy(array1, 0, array1and2, 0, array1.length);
// System.arraycopy(array2, 0, array1and2, array1.length, array2.length);
// System.out.println(a + "" + b + "" + c);
double[] x = Arrays.stream(regions[a]).asDoubleStream().toArray();
double[] y = Arrays.stream(regions[b]).asDoubleStream().toArray();
double[] z = Arrays.stream(regions[c]).asDoubleStream().toArray();
double[] circ = findCircumCenter(x, y, z);
System.arraycopy(circ, 0, possibleCircumcenters[num], 0, circ.length);
System.arraycopy(new double[] { a, b, c }, 0, possibleCircumcenters[num++], circ.length, 3);
// System.out.print("\t");
// for (int i : possibleCircumcenters[num-1])
// System.out.print(i + " ");
// System.out.println("\n\n");
// possibleCircumcenters[num] = new int[] {findCircumCenter(regions[a], regions[b], regions[c])};
}
}
}
ArrayList<double[]> realCircumcenters = new ArrayList<double[]>();
for (double[] x : possibleCircumcenters) {
// if (withinBorders(x)) {
if (adjacent[(int) x[2]][(int) x[3]] && adjacent[(int) x[2]][(int) x[4]] && adjacent[(int) x[3]][(int) x[4]]) {
int closest = 0;
for (int d = 0; d < regions.length; d++) {
int[] r = regions[d];
if (dist(new double[] {regions[closest][0], regions[closest][1]}, x) > dist(new double[] {r[0], r[1]}, x)) {
closest = d;
}
}
if ((int) x[2] == closest || (int) x[3] == closest || (int) x[4] == closest) {
System.out.println("Circumcenter @: " + x[2] + " " + x[3] + " " + x[4]);
realCircumcenters.add(x);
}
}
// }
}
Path2D circumcenterLines = new Path2D.Double();
Path2D borderCircumcenterLines = new Path2D.Double();
g2.setColor(Color.RED);
g2.setStroke(new BasicStroke(4));
for (int a = 0; a < realCircumcenters.size(); a++) {
for (int b = a + 1; b < realCircumcenters.size(); b++) {
int count = 0;
for (int i = 2; i < 5; i++) {
// if (connections.get(a)[i] == connections.get(b)[2] || connections.get(a)[i] == connections.get(b)[3] || connections.get(a)[i] == connections.get(b)[4]) {
if (realCircumcenters.get(a)[i] == realCircumcenters.get(b)[2]
|| realCircumcenters.get(a)[i] == realCircumcenters.get(b)[3]
|| realCircumcenters.get(a)[i] == realCircumcenters.get(b)[4])
count++;
}
if (count > 1) {
circumcenterLines.moveTo(offset + realCircumcenters.get(a)[1] * e,
offset + realCircumcenters.get(a)[0] * e);
circumcenterLines.lineTo(offset + realCircumcenters.get(b)[1] * e,
offset + realCircumcenters.get(b)[0] * e);
realCircumcenters.get(a)[5]++;
realCircumcenters.get(b)[5]++;
}
}
}
int[][] border = {
{0, 1, 0},
{1, 0, 0},
{0, 1, witch.map[0].length},
{1, 0, witch.map.length}
};
for (int a = 0; a < regions.length; a++) {
for (int b = a + 1; b < regions.length; b++) {
if (adjacent[a][b]) {
int[] count = {0,0,0};
num = 0;
for (int i = 0; i < realCircumcenters.size(); i++) {
double[] circ = realCircumcenters.get(i);
if ((circ[2] == a || circ[3] == a || circ[4] == a) && (circ[2] == b || circ[3] == b || circ[4] == b)) {
count[num++] = i;
}
}
// System.out.println("A:" + a + "B:" + b);
if (num == 0) { // If 0 indexes were used in the count check; AKA if there are no circumcenters associated with these adjacent regions
double[] aDouble = Arrays.stream(regions[a]).asDoubleStream().toArray();
double[] bDouble = Arrays.stream(regions[b]).asDoubleStream().toArray();
double[] line = lineFromPoints(aDouble, bDouble);
double[] perp = perpendicularBisectorFromLine(aDouble, bDouble, line);
double[][] borderPoints = {
lineLineIntersection(border[0][0], border[0][1], border[0][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[1][0], border[1][1], border[1][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[2][0], border[2][1], border[2][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[3][0], border[3][1], border[3][2], perp[0], perp[1], perp[2])
};
// for (int[] bor : borderPoints) { // Remove the 2 border points that are outside the borders
// if (bor[0] < 0 || bor[0] > witch.map.length || bor[1] < 0 || bor[1] > witch.map[0].length) {
// bor = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE};
// }
// }
int[] closest = {0,0}; // Initialize variable for the 2 closest points
double[] dMin = {Integer.MAX_VALUE, Integer.MAX_VALUE}; // Initialize variable for the distances of the 2 closest points
// int x1 = realCircumcenters.get(count[0])[0];
// int y1 = realCircumcenters.get(count[0])[1];
double x1 = regions[a][0];
double y1 = regions[a][1];
for (int i = 0; i < borderPoints.length; i++) {
double x2 = borderPoints[i][0];
double y2 = borderPoints[i][1];
double dist = Math.sqrt(Math.pow((x1-x2), 2) + Math.pow((y1-y2), 2));
dist = dist(aDouble, bDouble);
// double d = Math.sqrt(Math.pow(regions[r][0] - x, 2) + Math.pow(regions[r][1] - y, 2));
if (withinBorders(new double[] {x2, y2})) {
if (dist <= dMin[0]) {
closest[1] = closest[0];
dMin[1] = dMin[0];
closest[0] = i;
dMin[0] = dist;
} else if (dist <= dMin[1]) {
closest[1] = i;
dMin[1] = dist;
}
}
}
realCircumcenters.add(new double[] {borderPoints[closest[0]][0], borderPoints[closest[0]][1], a, b, -1});
realCircumcenters.add(new double[] {borderPoints[closest[1]][0], borderPoints[closest[1]][1], a, b, -1});
borderCircumcenterLines.moveTo(offset + borderPoints[closest[0]][1] * e, // First point on the line
offset + borderPoints[closest[0]][0] * e);
borderCircumcenterLines.lineTo(offset + borderPoints[closest[1]][1] * e, // Second point on the line
offset + borderPoints[closest[1]][0] * e);
// realCircumcenters.get(count[0])[5]++; // Unused for now; Indicator for whether the circumcenters are connected to 3 other points
} else if (num == 1) { // If 1 index were used in the count check; AKA if there is only one circumcenter associated with these adjacent regions
// System.out.println("NOTE");
// Make a perpendicular bisector
double[] cir = realCircumcenters.get(count[0]); // Finds the third region and calls it c. We now have 3 regions a, b, c that are all adjacent and have a circumcenter which is called cir. a and b do not have another circumcenter with each other.
int c = -1;
for (int z = 2; z < 5; z++) {
if (cir[z] != a && cir[z] != b) {
c = (int) cir[z];
}
}
// Seperate 2 border points from 1 border points and do each seperately
num = 0;
int[] count2 = {0,0,0};
for (int rC = 0; rC < realCircumcenters.size(); rC++) { // Find circumcenters next to this one
double[] circ = realCircumcenters.get(rC);
if ((circ[2] == c || circ[3] == c || circ[4] == c) && ((circ[2] == a || circ[3] == a || circ[4] == a) ^ (circ[2] == b || circ[3] == b || circ[4] == b))) {
// System.out.println("Sections: " + a + " " + b + " " + c);
// System.out.println("Circumcenter: " + circ[0] + ", " + circ[1] + ", " + circ[2] + ", " + circ[3] + ", " + circ[4]);
// outVectors[num] = new double[] {circ[0]-x1, circ[1]-y1};
if (circ[4] != -1)
count2[num++] = rC;
}
}
double[] x = Arrays.stream(regions[a]).asDoubleStream().toArray();
double[] y = Arrays.stream(regions[b]).asDoubleStream().toArray();
double[] z = Arrays.stream(regions[c]).asDoubleStream().toArray();
double x1 = cir[0]; // X-value of the circumcenter
double y1 = cir[1]; // Y-value of the circumcenter
if (num == 2) { // The circumcenter in question is connected to 2 other circumcenters: realCircumcenters.get(count2[0]) and realCircumcenters.get(count2[1])
double[] line = lineFromPoints(x, y); // Find the equation of a line between a and b
double[] perp = perpendicularBisectorFromLine(x, y, line); // Find the perpendicular bisector of a and b
double[][] borderPoints = { // Find the intersection points of each of the borders with the perpendicular bisector of a and b
lineLineIntersection(border[0][0], border[0][1], border[0][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[1][0], border[1][1], border[1][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[2][0], border[2][1], border[2][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[3][0], border[3][1], border[3][2], perp[0], perp[1], perp[2])
};
double[][] adjacentCircumcenters = new double[2][];
num = 0;
for (double[] circ : realCircumcenters) {
int countRegions = 0;
for (int i = 2; i <= 4; i++) {
// System.out.println(i);
// System.out.println("i = " + i + "\n " + circ[i] + "\na - " + a + "\tb - " + b + "\tc - " + c);
if (circ[i] == a || circ[i] == b || circ[i] == c) {
// System.out.println("i = " + i + "\n\ta - " + circ[i]);
// System.out.println(circ[i] == a);
// System.out.println(circ[i] == b);
// System.out.println(circ[i] == c);
countRegions++;
}
}
if (countRegions == 2 && circ[4] != -1) {
// System.out.println("Found Adjacent Circ: " + circ[0] + " " + circ[1] + " " + circ[2] + " " + circ[3] + " " + circ[4]);
adjacentCircumcenters[num++] = circ;
}
}
double[][] unitVectors = {unitVector(adjacentCircumcenters[0], cir), unitVector(adjacentCircumcenters[1], cir)};
double[] unitVectorsAdded = {unitVectors[0][0] + unitVectors[1][0], unitVectors[0][1] + unitVectors[1][1]};
// double[] outVectorsMagnitude = {Math.sqrt(Math.pow((outVectors[0][0]), 2) + Math.pow((outVectors[0][1]), 2)), Math.sqrt(Math.pow((outVectors[1][0]), 2) + Math.pow((outVectors[1][1]), 2))}; // TODO: change to use dist command
// outVectors[0] = new double[] {outVectors[0][0]/outVectorsMagnitude[0], outVectors[0][1]/outVectorsMagnitude[0]};
// outVectors[1] = new double[] {outVectors[1][0]/outVectorsMagnitude[1], outVectors[1][1]/outVectorsMagnitude[1]};
// double[] outVector = new double[] {outVectors[0][0] + outVectors[1][0], outVectors[0][1] + outVectors[1][1]};
int closest = -1; // Initialize a variable for the closest intersection point
double dMin = Integer.MAX_VALUE; // Initialize a variable for the distance to the closest intersection point
for (int bor = 0; bor < borderPoints.length; bor++) {
double x2 = borderPoints[bor][0];
double y2 = borderPoints[bor][1];
double dist = dist(cir, borderPoints[bor]);
// double d = Math.sqrt(Math.pow(regions[r][0] - x, 2) + Math.pow(regions[r][1] - y, 2));
double[] distVector = {x2-x1, y2-y1};
if (distVector[0] * unitVectorsAdded[0] + distVector[1] * unitVectorsAdded[1] > 0) { // Determine the direction of the vector projection between 2 lines: c to circumcenter and intersection point to circumcenter
// The line is in the same direction as the opposite vertex, which means reject this border point: it is in the wrong direction
} else if (dist <= dMin) { // If the distance of this point is closer, replace the old point and distance
closest = bor;
dMin = dist;
}
}
if (closest >= 0) {
if (withinBorders(new double[] {borderPoints[closest][0], borderPoints[closest][1]})) {
realCircumcenters.add(new double[] {borderPoints[closest][0], borderPoints[closest][1], a, b, -1});
borderCircumcenterLines.moveTo(offset + realCircumcenters.get(count[0])[1] * e, // First point on the line
offset + realCircumcenters.get(count[0])[0] * e);
borderCircumcenterLines.lineTo(offset + borderPoints[closest][1] * e, // Second point on the line
offset + borderPoints[closest][0] * e);
realCircumcenters.get(count[0])[5]++; // Currently unused
}
}
} else if (num == 1) { // The circumcenter in question is connected to only 1 circumcenter: realCircumcenters.get(count2[0])
//TODO:
double[][] unitVectors = new double[3][2];
double[][][] allBorderPoints = new double[2][4][];
double[][][] realBorderPoints = new double[2][4][];
unitVectors[2] = unitVector(cir, realCircumcenters.get(count2[0]));
double[][] lineComboRegions = new double[][] {
{a, b},
{a, c},
};
double[][][] lineCombos = new double[][][] {
{x, y},
{x, z},
};
if (realCircumcenters.get(count2[0])[2] == a || realCircumcenters.get(count2[0])[3] == a || realCircumcenters.get(count2[0])[4] == a) {
lineCombos[1][0] = y;
lineComboRegions[1][0] = b;
}
for (int iterate = 0; iterate <= 1; iterate++) {
int closest = 0;
double dMin = Integer.MAX_VALUE;
double[] line = lineFromPoints(lineCombos[iterate][0], lineCombos[iterate][1]); // Find the equation of a line between a and b
double[] perp = perpendicularBisectorFromLine(lineCombos[iterate][0], lineCombos[iterate][1], line); // Find the perpendicular bisector of a and b
allBorderPoints[iterate] = new double[][] { // Find the intersection points of each of the borders with the perpendicular bisector of a and b
lineLineIntersection(border[0][0], border[0][1], border[0][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[1][0], border[1][1], border[1][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[2][0], border[2][1], border[2][2], perp[0], perp[1], perp[2]),
lineLineIntersection(border[3][0], border[3][1], border[3][2], perp[0], perp[1], perp[2])
};
// double distMin = Integer.MAX_VALUE;
for (double[] borderPointsIteration : allBorderPoints[iterate]) {
// System.out.print(allBorderPoints[i][0]);
// double[] bP = borderPoints[iterate][i];
if (!withinBorders(borderPointsIteration)) {
// allBorderPoints[iterate][i] = new double[] {Integer.MAX_VALUE, Integer.MAX_VALUE};
} else {
// System.out.println("Enter- \n" + "Circumcenter: " + cir[0] + "," + cir[1] + "\nIterate: " + iterate + "; Border: " + borderPointsIteration[0] + "," + borderPointsIteration[1]);
if (dist(cir, borderPointsIteration) < dMin) {
realBorderPoints[iterate][1] = realBorderPoints[iterate][0];
realBorderPoints[iterate][0] = borderPointsIteration;
dMin = dist(cir, borderPointsIteration);
// System.out.println("True:" + dMin);
} else {
realBorderPoints[iterate][1] = borderPointsIteration;
}
}
}
unitVectors[iterate] = unitVector(cir, realBorderPoints[iterate][0]);
// System.out.println(dist(cir, realBorderPoints[iterate][0]));
if (dist(cir, realBorderPoints[iterate][0]) == 0) {
unitVectors[iterate] = new double[] {0,0};
// System.out.println("- 00");
}
}
double largestSmallAngle = Integer.MIN_VALUE;
int smallestAngleValue = -1;
// unitVectors are vectors to the 2 closest in-bounds borders and the circumcenter
for (int iterate = 0; iterate < 4; iterate++) {
/* iterate 0 = + unitvector[0], + unitvector[1]
* iterate 1 = + unitvector[0], - unitvector[1]
* iterate 2 = - unitvector[0], + unitvector[1]
* iterate 3 = - unitvector[0], - unitvector[1]
*/
// System.out.println("Vectors: \n" + unitVectors[0][0] + " " + unitVectors[0][1] + "\n" + unitVectors[1][0] + " " + unitVectors[1][1]);
double[] angle = {
Math.acos((iterate < 2 ? 1 : -1) * unitVectors[0][0] * (iterate % 2 == 0 ? 1 : -1) * unitVectors[1][0] + (iterate < 2 ? 1 : -1) * unitVectors[0][1] * (iterate % 2 == 0 ? 1 : -1) * unitVectors[1][1]),
Math.acos((iterate < 2 ? 1 : -1) * unitVectors[0][0] * unitVectors[2][0] + (iterate < 2 ? 1 : -1) * unitVectors[0][1] * unitVectors[2][1]),
Math.acos((iterate % 2 == 0 ? 1 : -1) * unitVectors[1][0] * unitVectors[2][0] + (iterate % 2 == 0 ? 1 : -1) * unitVectors[1][1] * unitVectors[2][1]),
};
Arrays.sort(angle);
// System.out.println("Angles: " + angle[0] + " " + angle[1] + " " + angle[2]);
// angle = Arrays.stream(angle)
// .map(radiansToDegrees -> radiansToDegrees * 180.0/Math.PI)
// .toArray();
// System.out.println("Angles: " + angle[0] + " " + angle[1] + " " + angle[2]);
if (angle[0] > largestSmallAngle) {
largestSmallAngle = angle[0];
smallestAngleValue = iterate;
}
}
// TODO: Circumcenters that are outside the borders
if (withinBorders(cir)) {
if (withinBorders(new double[] {realBorderPoints[0][smallestAngleValue/2][0], realBorderPoints[0][smallestAngleValue/2][1]})) {
realCircumcenters.add(new double[] {realBorderPoints[0][smallestAngleValue/2][0], realBorderPoints[0][smallestAngleValue/2][1], a, b, -1});
borderCircumcenterLines.moveTo(offset + cir[1] * e, // First point on the line; circumcenter
offset + cir[0] * e);
borderCircumcenterLines.lineTo(offset + realBorderPoints[0][smallestAngleValue/2][1] * e, // Second point on the line; border point
offset + realBorderPoints[0][smallestAngleValue/2][0] * e);
}
// System.out.println("smallestAngleValue = " + smallestAngleValue);
if (withinBorders(new double[] {realBorderPoints[1][smallestAngleValue%2][0], realBorderPoints[1][smallestAngleValue%2][1], lineComboRegions[1][0], c, -1})) {
realCircumcenters.add(new double[] {realBorderPoints[1][smallestAngleValue%2][0], realBorderPoints[1][smallestAngleValue%2][1], lineComboRegions[1][0], c, -1});
borderCircumcenterLines.moveTo(offset + realCircumcenters.get(count[0])[1] * e, // First point on the line; circumcenter
offset + realCircumcenters.get(count[0])[0] * e);
borderCircumcenterLines.lineTo(offset + realBorderPoints[1][smallestAngleValue%2][1] * e, // Second point on the line; border point
offset + realBorderPoints[1][smallestAngleValue%2][0] * e);
}
} else { // The circumcenter is outside the border
if (smallestAngleValue/2 == 0) { // if unit vector 1 went the right way
// Check which regions are closest to the borderpoints
// double[] doubles = Arrays.stream(ints).asDoubleStream().toArray();
double[][] distances = {
{dist(Arrays.stream(regions[a]).asDoubleStream().toArray(), realBorderPoints[0][1]), a},
{dist(Arrays.stream(regions[b]).asDoubleStream().toArray(), realBorderPoints[0][1]), b},
{dist(Arrays.stream(regions[c]).asDoubleStream().toArray(), realBorderPoints[0][1]), c},
};
System.out.println("D: \n" + distances[0][0] + "\n" + distances[1][0] + "\n" + distances[2][0] + "\n");
Arrays.sort(distances, (num1, num2) -> Double.compare(num1[0], num2[0]));
System.out.println("D: \n" + distances[0][0] + "\n" + distances[1][0] + "\n" + distances[2][0] + "\n");
// Add the correct border points to the realCircumcenters ArrayList
realCircumcenters.add(new double[] {realBorderPoints[0][0][0], realBorderPoints[0][0][1], distances[0][1], distances[1][1], -1});
realCircumcenters.add(new double[] {realBorderPoints[0][1][0], realBorderPoints[0][1][1], distances[0][1], distances[1][1], -1});
// Add the lines between the 2 closest borderlines
borderCircumcenterLines.moveTo(offset + realBorderPoints[0][0][1] * e, // Closest border point
offset + realBorderPoints[0][0][0] * e);
borderCircumcenterLines.lineTo(offset + realBorderPoints[0][1][1] * e, // Farthest border point
offset + realBorderPoints[0][1][0] * e);
}
if (smallestAngleValue%2 == 0) { // if unit vector 2 went the right way
double[][] distances = {
{dist(Arrays.stream(regions[a]).asDoubleStream().toArray(), realBorderPoints[1][1]), a},
{dist(Arrays.stream(regions[b]).asDoubleStream().toArray(), realBorderPoints[1][1]), b},
{dist(Arrays.stream(regions[c]).asDoubleStream().toArray(), realBorderPoints[1][1]), c},
};
System.out.println("D: \n" + distances[0][0] + "\n" + distances[1][0] + "\n" + distances[2][0] + "\n");
Arrays.sort(distances, (num1, num2) -> Double.compare(num1[0], num2[0]));
System.out.println("D: \n" + distances[0][0] + "\n" + distances[1][0] + "\n" + distances[2][0] + "\n");
realCircumcenters.add(new double[] {realBorderPoints[1][0][0], realBorderPoints[1][0][1], distances[0][1], distances[1][1], -1});
realCircumcenters.add(new double[] {realBorderPoints[1][1][0], realBorderPoints[1][1][1], distances[0][1], distances[1][1], -1});
borderCircumcenterLines.moveTo(offset + realBorderPoints[1][0][1] * e, // Closest border point
offset + realBorderPoints[1][0][0] * e);
borderCircumcenterLines.lineTo(offset + realBorderPoints[1][1][1] * e, // Farthest border point
offset + realBorderPoints[1][1][0] * e);
}
}
} else if (num == 0) { // There are no adjacent circumcenters to this circumcenter
/*
/* TODO: Find the region that makes the largest angle with the other regions
* Make a line from the circumcenter
*
*
double[][] regionVectors = {
unitVector(regions[a],regions[b]),
unitVector(a,b),
unitVector(a,b),
};
double[] angle = {
Math.acos(unitVectors[0][0] * unitVectors[1][0] + unitVectors[0][1] * unitVectors[1][1]),
Math.acos((iterate < 2 ? 1 : -1) * unitVectors[0][0] * unitVectors[2][0] + (iterate < 2 ? 1 : -1) * unitVectors[0][1] * unitVectors[2][1]),
Math.acos((iterate % 2 == 0 ? 1 : -1) * unitVectors[1][0] * unitVectors[2][0] + (iterate % 2 == 0 ? 1 : -1) * unitVectors[1][1] * unitVectors[2][1]),
};
*/
}
}
}
}
}
double[][] borderPoints = {
{0,0},
{0,witch.map[0].length},
{witch.map.length,witch.map[0].length},
{witch.map.length,0},
};
for (double[] bor : borderPoints) {
double dMin = Integer.MAX_VALUE;
int closest = -1;
for (int r = 0; r < regions.length; r++) {
double[] reg = new double[] {regions[r][0], regions[r][1]};
double d = dist(reg, bor);
if (d < dMin) {
closest = r;
dMin = d;
}
}
realCircumcenters.add(new double[] {bor[0], bor[1], closest, -1, -1});
}
for (int r = 0; r < regions.length; r++) {
// double rD = r;
Path2D newPath = new Path2D.Double();
ArrayList<double[]> regionCircumcenters = new ArrayList<double[]>();
for (double[] circ : realCircumcenters) {
int[] circPos = Arrays.stream(circ).mapToInt(d -> (int) d).toArray();
// for (int i : circPos) {
// System.out.print(i + " - ");
// }
// System.out.println(r);
// if (Arrays.asList(Arrays.copyOfRange(circPos,2,5)).contains(r)) {
// regionCircumcenters.add(circ);
// System.out.println("TRUE");
if (circ[2] == r || circ[3] == r || circ[4] == r) {
regionCircumcenters.add(circ);
// System.out.println("TRUE");
} else {
}
}
for (int a = 0; a < regionCircumcenters.size(); a++) {
for (int b = a+1; b < regionCircumcenters.size(); b++) {
newPath.moveTo(offset + regions[r][1] * e, offset + regions[r][0] * e);
newPath.lineTo(offset + regionCircumcenters.get(a)[1] * e, offset + regionCircumcenters.get(a)[0] * e);
newPath.lineTo(offset + regionCircumcenters.get(b)[1] * e, offset + regionCircumcenters.get(b)[0] * e);
newPath.closePath();
g2.setColor(regionColors[r%10]);
g2.fill(newPath);
}
}
}
if (debug) {
g2.setColor(Color.RED);
g2.setStroke(new BasicStroke(10));
for (int[] r : regions)
g2.drawOval(offset + r[1] * e - e / 2, offset + r[0] * e - e / 2, e, e);
g2.setColor(Color.MAGENTA);
g2.setStroke(new BasicStroke(4));
g2.draw(circumcenterLines);
g2.setColor(Color.ORANGE);
g2.draw(borderCircumcenterLines);
} else {
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(4));
g2.draw(circumcenterLines);
g2.draw(borderCircumcenterLines);
}
g2.setColor(this.color);
g2.setStroke(new BasicStroke(10));
Path2D path = new Path2D.Double();
path.moveTo(offset + points[0][1] * e, offset + points[0][0] * e);
for (int[] p : points) {
path.lineTo(offset + p[1] * e, offset + p[0] * e);
}
path.closePath();
// g2.fill(path);
g2.setColor(this.color);
g2.setStroke(new BasicStroke(1));
BufferedImage canvas = new BufferedImage(850, 600, BufferedImage.TYPE_INT_ARGB);
int c = this.color.getRGB();
for (int x = 0; x < canvas.getWidth(); x++) {
for (int y = 0; y < canvas.getHeight(); y++) {
canvas.setRGB(x, y, c);
}
}
Path2D borderLines = new Path2D.Double();
Path2D outsideLines = new Path2D.Double();
borderLines.moveTo(offset, offset);
borderLines.lineTo(offset + witch.map[0].length * e, offset);
borderLines.lineTo(offset + witch.map[0].length * e, offset + witch.map.length * e);
borderLines.lineTo(offset, offset + witch.map.length * e);
borderLines.lineTo(offset, offset);
outsideLines.moveTo(0, 0);
outsideLines.lineTo(offset * 2 + witch.map[0].length * e, 0);
outsideLines.lineTo(offset * 2 + witch.map[0].length * e, offset * 2 + witch.map.length * e);
outsideLines.lineTo(0, offset * 2 + witch.map.length * e);
outsideLines.lineTo(0, 0);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(4));
g2.draw(borderLines);
if (!debug) {
g2.setStroke(new BasicStroke(offset*2));
g2.draw(outsideLines);
}
}
public MapSections(int[][] regions, Color color) {
super();
this.regions = regions;
this.points = new int[][] { regions[0], regions[1], regions[2] };
this.color = color;
}
public static double dist(double[] a, double[] b) {
return (Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)));
}
public static boolean withinBorders(double[] p) {
if (p[0] < -0.001)
return false;
if (p[0] > witch.map.length + 000.1)
return false;
if (p[1] < -0.001)
return false;
if (p[1] > witch.map[0].length + 0.001)
return false;
return true;
}
// ----------------------------------------------------------------------------------------------
// Circumcenter finder functions
public static double[] unitVector(double[] a, double[] b) {
double dx = a[0] - b[0];
double dy = a[1] - b[1];
double length = Math.sqrt(Math.pow((dx), 2) + Math.pow((dy), 2));
return new double[] { dx / length, dy / length };
}
public static double[] lineFromPoints(double[] P, double[] Q) {
double[] a_b_c = { 0, 0, 0 };
a_b_c[0] = Q[1] - P[1];
a_b_c[1] = P[0] - Q[0];
a_b_c[2] = a_b_c[0] * (P[0]) + a_b_c[1] * (P[1]);
return a_b_c;
}
// Function which converts the input line to its
// perpendicular bisector. It also inputs the points
// whose mid-point lies on the bisector
public static double[] perpendicularBisectorFromLine(double[] P, double[] Q, double[] a_b_c) {
ArrayList<Double> mid_point = new ArrayList<Double>();
mid_point.add((P[0] + Q[0]) / 2);
mid_point.add((P[1] + Q[1]) / 2);
// c = -bx + ay
a_b_c[2] = -a_b_c[1] * (mid_point.get(0)) + a_b_c[0] * (mid_point.get(1));
double temp = a_b_c[0];
a_b_c[0] = -a_b_c[1];
a_b_c[1] = temp;
return a_b_c;
}
// Returns the intersection point of two lines
public static double[] lineLineIntersection(double a1, double b1, double c1, double a2, double b2, double c2) {
double[] ans = { 0, 0 };
double determinant = a1 * b2 - a2 * b1;
if (determinant == 0) {
// The lines are parallel. This is simplified
// by returning a pair of FLT_MAX
ans[0] = Integer.MAX_VALUE;
ans[1] = Integer.MAX_VALUE;
} else {
double x = (b2 * c1 - b1 * c2) / determinant;
double y = (a1 * c2 - a2 * c1) / determinant;
ans[0] = x;
ans[1] = y;
}
return ans;
}
public static double[] findCircumCenter(double[] P, double[] Q, double[] R) {
// Line PQ is represented as ax + by = c
double[] a_b_c = lineFromPoints(P, Q);
// Line QR is represented as ex + fy = g
double[] e_f_g = lineFromPoints(Q, R);
// Converting lines PQ and QR to perpendicular
// bisectors. After this, L = ax + by = c
// M = ex + fy = g
perpendicularBisectorFromLine(P, Q, a_b_c);
perpendicularBisectorFromLine(Q, R, e_f_g);
// The point of intersection of L and M gives
// the circumcenter
double[] circumcenter = lineLineIntersection(a_b_c[0], a_b_c[1], a_b_c[2], e_f_g[0], e_f_g[1], e_f_g[2]);
return circumcenter;
}
}