World building

This commit is contained in:
L3o15 2025-05-12 19:12:33 +02:00
parent 88ec2f43c0
commit 8fe0d0e323
14 changed files with 245 additions and 80 deletions

140
src/LinearSystem.java Normal file
View 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;
}
}

View file

@ -1,8 +1,11 @@
package it.arnaldo.unibs.tamagolem; package it.arnaldo.unibs.tamagolem;
import java.util.*; import java.util.*;
public class TamaGolemMain { public class TamaGolemMain {
public static void main(String[] args) { public static void main(String[] args) {
System.out.println("TamaGolem"); System.out.println("TamaGolem");
WorldBuilder.buildWorld(); WorldBuilder.buildWorld();
} }
} }

View file

@ -7,104 +7,126 @@ public class WorldBuilder {
Element[] allElements = Element.values(); Element[] allElements = Element.values();
Random rand = new Random(); Random rand = new Random();
// da cambiare il numero a 8 // 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)); List<Element> selectedElements = new ArrayList<>(Arrays.asList(allElements));
Collections.shuffle(selectedElements); Collections.shuffle(selectedElements);
selectedElements = selectedElements.subList(0, numElements); selectedElements = selectedElements.subList(0, numElements);
ElementGraph world = new ElementGraph(); ElementGraph world = new ElementGraph();
HashMap<Element, Integer> elementStrengthNumber = new HashMap<>(); HashMap<Element, HashMap<Element, Integer>> linkDirections = 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;
for (Element element : selectedElements) { for (Element element : selectedElements) {
index++; HashMap<Element, Integer> links = new HashMap<>();
int randomNumber = rand.nextInt(numElements - 2); Element followingElement = selectedElements.get((selectedElements.indexOf(element) + 1) % selectedElements.size());
if (numMaxOfPossibleStrength - randomNumber < 0) { for (Element el : selectedElements) {
randomNumber = numMaxOfPossibleStrength; if (el == followingElement) {
numMaxOfPossibleStrength = 0; links.put(el, 1);
} else { } else if (el != element) {
numMaxOfPossibleStrength -= randomNumber; links.put(el, 1);
}
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});
} }
} }
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<>(); // // controllo anche prima per evitare che magari da un estrazione si vada a togliere
// if (elementLinks.get(el) == 1){
for (Element[] pair : possibleInteractions) { // linkDirections.get(el).put(element, -1);
Element attacker = pair[0]; // }
Element defender = pair[1]; //
// if (elementLinks.get(el) == 0) {
String key = attacker.name() + "-" + defender.name(); // if (Math.random() < 0.5) {
String reverseKey = defender.name() + "-" + attacker.name(); // linkDirections.get(el).put(element, 1);
if (alreadyUsed.contains(key) || alreadyUsed.contains(reverseKey)) continue; // } else {
// linkDirections.get(el).put(element, -1);
int attackerRemaining = elementStrengthNumber.get(attacker); // }
int defenderRemaining = elementWeaknessPoint.get(defender); // }
//
int attackerPoints = elementStrengthSum.get(attacker); // if (elementLinks.get(el) == 1){
int defenderPoints = elementWeaknessPointToAssign.get(defender); // linkDirections.get(el).put(element, -1);
// } else {
if (attackerRemaining <= 0 || defenderRemaining <= 0) continue; // linkDirections.get(el).put(element, 1);
// }
// 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);
} }
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(); world.printGraph();
return world; return world;
} }
private static int getIndex(Element e1, Element e2, HashMap<Set<Element>, Integer> pairIndex) {
return pairIndex.get(Set.of(e1, e2));
}
} }