World building
This commit is contained in:
parent
88ec2f43c0
commit
8fe0d0e323
14 changed files with 245 additions and 80 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
140
src/LinearSystem.java
Normal file
140
src/LinearSystem.java
Normal file
|
@ -0,0 +1,140 @@
|
|||
package it.arnaldo.unibs.tamagolem;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class LinearSystem {
|
||||
private final int n;
|
||||
private final int m;
|
||||
private final int[][] A;
|
||||
private final int[] b;
|
||||
|
||||
public LinearSystem(int n, int[][] A, int[] b) {
|
||||
this.n = n;
|
||||
this.m = (n * (n - 1)) / 2;
|
||||
this.A = A;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int[] resolve() {
|
||||
int[][] extendedMatrix = new int[n][m + 1];
|
||||
for (int i = 0; i < n; i++) {
|
||||
System.arraycopy(A[i], 0, extendedMatrix[i], 0, m);
|
||||
extendedMatrix[i][m] = b[i];
|
||||
}
|
||||
|
||||
int rank = gauss(extendedMatrix);
|
||||
int indipendentVariables = m - rank;
|
||||
if (indipendentVariables <= 0) {
|
||||
throw new IllegalStateException("Sistema determinato o sovradeterminato");
|
||||
}
|
||||
|
||||
int[] solutions;
|
||||
Random rand = new Random();
|
||||
int tries = 100000000;
|
||||
while (tries-- > 0) {
|
||||
int[] lambdaValues = new int[indipendentVariables];
|
||||
for (int i = 0; i < indipendentVariables; i++) {
|
||||
lambdaValues[i] = (rand.nextInt(n) + 1); // valori tra 1 e 9
|
||||
}
|
||||
|
||||
solutions = constructSolution(extendedMatrix, lambdaValues, rank);
|
||||
if (validNumbers(solutions)) return solutions;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Impossibile trovare una solutions intera senza zeri");
|
||||
}
|
||||
|
||||
private boolean validNumbers(int[] x) {
|
||||
boolean positive = false;
|
||||
boolean negative = false;
|
||||
for (int xi : x) {
|
||||
if (xi > 0) positive = true;
|
||||
else if (xi < 0) negative = true;
|
||||
if (xi == 0) return false;
|
||||
}
|
||||
return positive && negative;
|
||||
}
|
||||
|
||||
private int[] constructSolution(int[][] extendedMatrix, int[] parameters, int rank) {
|
||||
int[] x = new int[m];
|
||||
Arrays.fill(x, 0);
|
||||
|
||||
List<Integer> pivotCol = new ArrayList<>();
|
||||
boolean[] isFree = new boolean[m];
|
||||
Arrays.fill(isFree, true);
|
||||
|
||||
for (int i = 0; i < rank; i++) {
|
||||
int col = 0;
|
||||
while (col < m && extendedMatrix[i][col] == 0) col++;
|
||||
pivotCol.add(col);
|
||||
isFree[col] = false;
|
||||
}
|
||||
|
||||
int paramIndex = 0;
|
||||
for (int i = 0; i < m; i++) {
|
||||
if (isFree[i]) {
|
||||
x[i] = parameters[paramIndex++];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = rank - 1; i >= 0; i--) {
|
||||
int pivot = pivotCol.get(i);
|
||||
int val = extendedMatrix[i][m];
|
||||
for (int j = pivot + 1; j < m; j++) {
|
||||
val -= extendedMatrix[i][j] * x[j];
|
||||
}
|
||||
|
||||
if (val % extendedMatrix[i][pivot] != 0) {
|
||||
return new int[m]; // soluzione non intera -> rifiutiamo
|
||||
}
|
||||
|
||||
x[pivot] = val / extendedMatrix[i][pivot];
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private int gauss(int[][] mat) {
|
||||
int row = 0;
|
||||
for (int col = 0; col < m && row < n; col++) {
|
||||
int pivot = row;
|
||||
for (int i = row + 1; i < n; i++) {
|
||||
if (Math.abs(mat[i][col]) > Math.abs(mat[pivot][col])) {
|
||||
pivot = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (mat[pivot][col] == 0) continue;
|
||||
|
||||
int[] temp = mat[row];
|
||||
mat[row] = mat[pivot];
|
||||
mat[pivot] = temp;
|
||||
|
||||
for (int i = row + 1; i < n; i++) {
|
||||
int a = mat[i][col];
|
||||
int b = mat[row][col];
|
||||
if (a == 0) continue;
|
||||
|
||||
int lcm = lcm(Math.abs(a), Math.abs(b));
|
||||
int f1 = lcm / Math.abs(a);
|
||||
int f2 = lcm / Math.abs(b);
|
||||
if (a * b < 0) f2 = -f2;
|
||||
|
||||
for (int j = col; j <= m; j++) {
|
||||
mat[i][j] = mat[i][j] * f1 - mat[row][j] * f2;
|
||||
}
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
private int gcd(int a, int b) {
|
||||
return b == 0 ? a : gcd(b, a % b);
|
||||
}
|
||||
|
||||
private int lcm(int a, int b) {
|
||||
return a / gcd(a, b) * b;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
package it.arnaldo.unibs.tamagolem;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TamaGolemMain {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("TamaGolem");
|
||||
WorldBuilder.buildWorld();
|
||||
|
||||
}
|
||||
}
|
|
@ -7,104 +7,126 @@ public class WorldBuilder {
|
|||
Element[] allElements = Element.values();
|
||||
Random rand = new Random();
|
||||
// da cambiare il numero a 8
|
||||
int numElements = 3 + rand.nextInt(3);
|
||||
//int numElements = 3 + rand.nextInt(8);
|
||||
int numElements = 5;
|
||||
List<Element> selectedElements = new ArrayList<>(Arrays.asList(allElements));
|
||||
Collections.shuffle(selectedElements);
|
||||
selectedElements = selectedElements.subList(0, numElements);
|
||||
|
||||
ElementGraph world = new ElementGraph();
|
||||
|
||||
HashMap<Element, Integer> elementStrengthNumber = new HashMap<>();
|
||||
HashMap<Element, Integer> elementStrengthSum = new HashMap<>();
|
||||
HashMap<Element, Integer> elementWeaknessPointToAssign = new HashMap<>();
|
||||
HashMap<Element, Integer> elementWeaknessPoint = new HashMap<>();
|
||||
|
||||
int numMaxOfPossibleStrength = (numElements * (numElements - 1) / 2) - numElements;
|
||||
System.out.println(numMaxOfPossibleStrength);
|
||||
int index = 0;
|
||||
HashMap<Element, HashMap<Element, Integer>> linkDirections = new HashMap<>();
|
||||
for (Element element : selectedElements) {
|
||||
index++;
|
||||
int randomNumber = rand.nextInt(numElements - 2);
|
||||
if (numMaxOfPossibleStrength - randomNumber < 0) {
|
||||
randomNumber = numMaxOfPossibleStrength;
|
||||
numMaxOfPossibleStrength = 0;
|
||||
} else {
|
||||
numMaxOfPossibleStrength -= randomNumber;
|
||||
}
|
||||
|
||||
if (index == numElements) {
|
||||
randomNumber = numMaxOfPossibleStrength;
|
||||
}
|
||||
int strengthNumber = 1 + randomNumber;
|
||||
int weaknessNumber = numElements - 1 - strengthNumber;
|
||||
// int strengthSum = Math.max(strengthNumber, weaknessNumber) + rand.nextInt(10);
|
||||
elementStrengthNumber.put(element, strengthNumber);
|
||||
elementWeaknessPoint.put(element, weaknessNumber);
|
||||
}
|
||||
|
||||
|
||||
Map<Element, GraphElement> graphElementMap = new HashMap<>();
|
||||
for (Element el : selectedElements) {
|
||||
GraphElement ge = new GraphElement(el);
|
||||
world.addElement(ge);
|
||||
graphElementMap.put(el, ge);
|
||||
}
|
||||
|
||||
// Pairing e bilanciamento
|
||||
List<Element[]> possibleInteractions = new ArrayList<>();
|
||||
for (Element attacker : selectedElements) {
|
||||
for (Element defender : selectedElements) {
|
||||
if (!attacker.equals(defender)) {
|
||||
possibleInteractions.add(new Element[]{attacker, defender});
|
||||
HashMap<Element, Integer> links = new HashMap<>();
|
||||
Element followingElement = selectedElements.get((selectedElements.indexOf(element) + 1) % selectedElements.size());
|
||||
for (Element el : selectedElements) {
|
||||
if (el == followingElement) {
|
||||
links.put(el, 1);
|
||||
} else if (el != element) {
|
||||
links.put(el, 1);
|
||||
}
|
||||
}
|
||||
|
||||
linkDirections.put(element, links);
|
||||
}
|
||||
|
||||
Collections.shuffle(possibleInteractions);
|
||||
for (Element element : selectedElements) {
|
||||
HashMap<Element, Integer> elementLinks = linkDirections.get(element);
|
||||
for (Element el : selectedElements) {
|
||||
if (el == element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Set<String> alreadyUsed = new HashSet<>();
|
||||
|
||||
for (Element[] pair : possibleInteractions) {
|
||||
Element attacker = pair[0];
|
||||
Element defender = pair[1];
|
||||
|
||||
String key = attacker.name() + "-" + defender.name();
|
||||
String reverseKey = defender.name() + "-" + attacker.name();
|
||||
if (alreadyUsed.contains(key) || alreadyUsed.contains(reverseKey)) continue;
|
||||
|
||||
int attackerRemaining = elementStrengthNumber.get(attacker);
|
||||
int defenderRemaining = elementWeaknessPoint.get(defender);
|
||||
|
||||
int attackerPoints = elementStrengthSum.get(attacker);
|
||||
int defenderPoints = elementWeaknessPointToAssign.get(defender);
|
||||
|
||||
if (attackerRemaining <= 0 || defenderRemaining <= 0) continue;
|
||||
|
||||
// Calcolo potenza massima assegnabile
|
||||
int maxPower = Math.min(attackerPoints - (attackerRemaining - 1), defenderPoints - (defenderRemaining - 1));
|
||||
if (maxPower < 1) continue;
|
||||
|
||||
int power = 1 + rand.nextInt(maxPower);
|
||||
|
||||
// Assegna collegamenti
|
||||
graphElementMap.get(attacker).addLink(new ElementLink(power, defender));
|
||||
graphElementMap.get(defender).addLink(new ElementLink(-power, attacker));
|
||||
alreadyUsed.add(key);
|
||||
alreadyUsed.add(reverseKey);
|
||||
|
||||
// Aggiorna contatori
|
||||
elementStrengthNumber.put(attacker, attackerRemaining - 1);
|
||||
elementStrengthSum.put(attacker, attackerPoints - power);
|
||||
|
||||
elementWeaknessPoint.put(defender, defenderRemaining - 1);
|
||||
elementWeaknessPointToAssign.put(defender, defenderPoints - power);
|
||||
// // controllo anche prima per evitare che magari da un estrazione si vada a togliere
|
||||
// if (elementLinks.get(el) == 1){
|
||||
// linkDirections.get(el).put(element, -1);
|
||||
// }
|
||||
//
|
||||
// if (elementLinks.get(el) == 0) {
|
||||
// if (Math.random() < 0.5) {
|
||||
// linkDirections.get(el).put(element, 1);
|
||||
// } else {
|
||||
// linkDirections.get(el).put(element, -1);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (elementLinks.get(el) == 1){
|
||||
// linkDirections.get(el).put(element, -1);
|
||||
// } else {
|
||||
// linkDirections.get(el).put(element, 1);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(numElements);
|
||||
|
||||
System.out.println(linkDirections);
|
||||
|
||||
HashMap<Set<Element>, Integer> pairIndex = new HashMap<>();
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < selectedElements.size(); i++) {
|
||||
for (int j = i + 1; j < selectedElements.size(); j++) {
|
||||
Set<Element> pair = Set.of(selectedElements.get(i), selectedElements.get(j));
|
||||
|
||||
pairIndex.put(pair, index++);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(pairIndex);
|
||||
|
||||
int[][] A = new int[numElements][numElements * (numElements - 1) / 2];
|
||||
int[] b = new int[numElements];
|
||||
|
||||
int i = 0;
|
||||
for (Element element : selectedElements) {
|
||||
int[] line = new int[numElements * (numElements - 1) / 2];
|
||||
HashMap<Element, Integer> elementLinks = linkDirections.get(element);
|
||||
for (Element el : selectedElements) {
|
||||
if (el == element) {
|
||||
continue;
|
||||
} else {
|
||||
int idx = getIndex(element, el, pairIndex);
|
||||
line[idx] = elementLinks.get(el);
|
||||
}
|
||||
|
||||
}
|
||||
A[i] = line;
|
||||
b[i] = 0;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
LinearSystem system = new LinearSystem(numElements, A, b);
|
||||
|
||||
|
||||
int[] solution = system.resolve();
|
||||
System.out.println("Soluzione trovata:");
|
||||
for (int x : solution) {
|
||||
System.out.printf(String.format("%d ", x));
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
|
||||
|
||||
for (Element element : selectedElements) {
|
||||
GraphElement graphElement = new GraphElement(element);
|
||||
for (Element el : selectedElements) {
|
||||
if (el == element) {
|
||||
continue;
|
||||
}
|
||||
//int direction = linkDirections.get(element).get(el);
|
||||
graphElement.addLink(new ElementLink(solution[getIndex(element, el, pairIndex)], el));
|
||||
}
|
||||
world.addElement(graphElement);
|
||||
}
|
||||
world.printGraph();
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
private static int getIndex(Element e1, Element e2, HashMap<Set<Element>, Integer> pairIndex) {
|
||||
return pairIndex.get(Set.of(e1, e2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue