From 957a22477ba88fe6f97b345f7e8195b7867a21af Mon Sep 17 00:00:00 2001 From: Cmd-GZ Date: Sat, 4 Jul 2026 07:01:50 +0800 Subject: [PATCH 1/4] Reorganize: src/Graphwar/Function.java Integrate many repeative codes and nested codes --- src/Graphwar/Function.java | 735 ++++++++++++------------------------- 1 file changed, 229 insertions(+), 506 deletions(-) diff --git a/src/Graphwar/Function.java b/src/Graphwar/Function.java index 30bddaf..7919db5 100644 --- a/src/Graphwar/Function.java +++ b/src/Graphwar/Function.java @@ -1,5 +1,5 @@ // Copyright (C) 2011 Lucas Catabriga Rocha -// +// // This file is part of Graphwar. // // Graphwar is free software: you can redistribute it and/or modify @@ -23,295 +23,146 @@ public class Function private String strFunc; private PolishNotationFunction polishFunc; private double offSet; - + private double fireAngle; private double[] valuesX; private double[] valuesY; private double[] valuesDY; private int numSteps; - + private int[] playersHit; private int[] soldiersHit; private int[] soldierHitPosition; private int numPlayersHit; - + private double lastX; private double lastY; - - Function(String str) throws MalformedFunction - { - strFunc = str; - - polishFunc = new PolishNotationFunction(strFunc); - + + private void init() + { offSet = 0; - + fireAngle = 0; valuesX = null; valuesY = null; valuesDY = null; numSteps = 0; - + playersHit = null; soldiersHit = null; + soldierHitPosition = null; numPlayersHit = 0; - + lastX = 0; lastY = 0; - } - + + Function(String str) throws MalformedFunction + { + strFunc = str; + polishFunc = new PolishNotationFunction(strFunc); + + init(); + + } + Function(PolishNotationFunction polishNotationFunction) { strFunc = ""; - polishFunc = polishNotationFunction; - - offSet = 0; - - fireAngle = 0; - valuesX = null; - valuesY = null; - valuesDY = null; - numSteps = 0; - - playersHit = null; - soldiersHit = null; - soldierHitPosition = null; - numPlayersHit = 0; - - lastX = 0; - lastY = 0; - + + init(); + } - + public int getNumPlayersHit() { return numPlayersHit; } - + public int getPlayerHit(int index) { return playersHit[index]; } - + public int getSoldierHit(int index) { return soldiersHit[index]; } - + public int getSoldierHitPosition(int index) { return soldierHitPosition[index]; } - + public double getFireAngle() { return fireAngle; - } - + } + public double getX(int index) { return valuesX[index]; } - + public double getY(int index) { return valuesY[index]; } - + public int getNumSteps() { return numSteps; } - + public String getStringFunc() { return strFunc; } - + private double getStartAngle(double x, double radius) { double angle = 0; - + double startAngleTangent = (polishFunc.evaluateFunction(x+Constants.STEP_SIZE,0,0) - polishFunc.evaluateFunction(x,0,0))/Constants.STEP_SIZE; angle = Math.atan(startAngleTangent); - + double finalX; double error = 10000; for(int i=0; error > Constants.ANGLE_ERROR && i Constants.FUNC_MAX_STEP_DISTANCE_SQUARED;j++) - { - if(valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE) - { - tempStepSize = tempStepSize/2; - - valuesX[i] = valuesX[i-1] + tempStepSize; - valuesY[i] = polishFunc.evaluateFunction(valuesX[i],0,0)+offSet; - } - else - { - endFunc = true; - break; - } - } - - if(endFunc) - { - numSteps = i; - break; - } - - double x = Constants.PLANE_LENGTH*valuesX[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; - double y = -Constants.PLANE_LENGTH*valuesY[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; - - - if(inverted) - { - x = Constants.PLANE_LENGTH - x; - } - - for(int j=0; j Constants.FUNC_MAX_STEP_DISTANCE_SQUARED && valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE;j++) - { - if(valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE) - { - tempStepSize = tempStepSize/2; - - k1 = polishFunc.evaluateFunction( valuesX[i-1], valuesY[i-1], 0); - k2 = polishFunc.evaluateFunction( valuesX[i-1] + 0.5*tempStepSize, valuesY[i-1] + 0.5*tempStepSize*k1, 0); - k3 = polishFunc.evaluateFunction( valuesX[i-1] + 0.5*tempStepSize, valuesY[i-1] + 0.5*tempStepSize*k2, 0); - k4 = polishFunc.evaluateFunction( valuesX[i-1] + tempStepSize, valuesY[i-1] + tempStepSize*k3, 0); - - valuesY[i] = valuesY[i-1] + (tempStepSize/6)*(k1 + 2*k2 + 2*k3 + k4); - valuesX[i] = valuesX[i-1] + tempStepSize; - } - else - { - endFunc = true; - break; - } - } - - if(endFunc) - { - numSteps = i; - break; - } - - double x = Constants.PLANE_LENGTH*valuesX[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; - double y = -Constants.PLANE_LENGTH*valuesY[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; - - - if(inverted) - { - x = Constants.PLANE_LENGTH - x; - } - - for(int j=0; j Constants.FUNC_MAX_STEP_DISTANCE_SQUARED && valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE;j++) + + for(int j = 0; Math.pow(valuesX[i]-valuesX[i-1], 2) + Math.pow(valuesY[i]-valuesY[i-1], 2) > Constants.FUNC_MAX_STEP_DISTANCE_SQUARED; j++) { - if(valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE) - { - - tempStepSize = tempStepSize/2; - - x1 = valuesX[i-1]; - y1 = valuesY[i-1]; - y2 = valuesDY[i-1]; - - k11 = y2; - k12 = polishFunc.evaluateFunction( x1, y1, y2); - - x1 = valuesX[i-1] + tempStepSize/2; - y1 = valuesY[i-1] + (tempStepSize/2)*k11; - y2 = valuesDY[i-1] + (tempStepSize/2)*k12; - - k21 = y2; - k22 = polishFunc.evaluateFunction( x1, y1, y2); - - y1 = valuesY[i-1] + (tempStepSize/2)*k21; - y2 = valuesDY[i-1] + (tempStepSize/2)*k22; - - k31 = y2; - k32 = polishFunc.evaluateFunction( x1, y1, y2); - - x1 = valuesX[i-1] + tempStepSize; - y1 = valuesY[i-1] + (tempStepSize)*k31; - y2 = valuesDY[i-1] + (tempStepSize)*k32; - - k41 = y2; - k42 = polishFunc.evaluateFunction( x1, y1, y2); - - - valuesX[i] = valuesX[i-1] + tempStepSize; - valuesY[i] = valuesY[i-1] + (tempStepSize/6)*(k11 + 2*k21 + 2*k31 + k41); - valuesDY[i] = valuesDY[i-1] + (tempStepSize/6)*(k12 + 2*k22 + 2*k32 + k42); - } - else + if (valuesX[i] - valuesX[i-1] <= Constants.FUNC_MIN_X_STEP_DISTANCE) { endFunc = true; break; } - + tempStepSize = tempStepSize/2; + + valuesX[i] = valuesX[i-1]; + valuesY[i] = valuesY[i-1]; + valuesDY[i] = valuesDY[i-1]; + + if (mode == Constants.NORMAL_FUNC) + valuesY[i] = polishFunc.evaluateFunction(valuesX[i],0,0) + offSet; + if (mode == Constants.FST_ODE) + valuesY[i] = getRK4(valuesX[i], valuesY[i], tempStepSize); + if (mode == Constants.SND_ODE) + { + double[] vecY = getRK42(valuesX[i], valuesY[i], valuesDY[i], tempStepSize); + valuesY[i] = vecY[0]; + valuesDY[i] = vecY[1]; + } + valuesX[i] = valuesX[i-1] + tempStepSize; } - if(endFunc) { numSteps = i; break; } - - + double x = Constants.PLANE_LENGTH*valuesX[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; double y = -Constants.PLANE_LENGTH*valuesY[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; - - - if(inverted) - { - x = Constants.PLANE_LENGTH - x; - } - - for(int j=0; j= Constants.SOLDIER_RADIUS*Constants.SOLDIER_RADIUS) + continue; + if(playerAlreadyHit(j,k)) + continue; + + playersHit[numPlayersHit] = j; + soldiersHit[numPlayersHit] = k; + soldierHitPosition[numPlayersHit] = i; + numPlayersHit++; } } - - - if(obstacle.collidePoint((int)x, (int)y)) - { - numSteps = i; - break; - } - - if(Double.isNaN(y) || Double.isInfinite(y)) + + + if(obstacle.collidePoint((int)x, (int)y) || Double.isNaN(y) || Double.isInfinite(y)) { numSteps = i; break; } - - } - - lastX = Constants.PLANE_LENGTH*valuesX[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2;; + + lastX = Constants.PLANE_LENGTH*valuesX[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; lastY = -Constants.PLANE_LENGTH*valuesY[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; + } + + public void processFunctionRange(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted) + { + processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.NORMAL_FUNC, 0); + } - + public void processRK4Range(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted) + { + processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.FST_ODE, 0); + } + + public void processRK42Range(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, double angle ,boolean inverted) + { + processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.SND_ODE, angle); } - + public double getLastX() { return lastX; } - + public double getLastY() { return lastY; } - } From 0357108fe2204e843eceadf60f6f4ea5516dc966 Mon Sep 17 00:00:00 2001 From: Cmd-GZ Date: Sat, 4 Jul 2026 20:51:08 +0800 Subject: [PATCH 2/4] Reoriganize: process(Function/RK4/RK42)Range -> processRange --- src/Graphwar/ComputerPlayer.java | 16 +++--------- src/Graphwar/Function.java | 17 +----------- src/Graphwar/GameData.java | 44 ++++++++------------------------ 3 files changed, 15 insertions(+), 62 deletions(-) diff --git a/src/Graphwar/ComputerPlayer.java b/src/Graphwar/ComputerPlayer.java index 97e8d1d..95fcea1 100644 --- a/src/Graphwar/ComputerPlayer.java +++ b/src/Graphwar/ComputerPlayer.java @@ -169,19 +169,9 @@ private double evaluateFunction(PolishNotationFunction ft, double angle) { inverted = true; } - - switch(graphwar.getGameData().getGameMode()) - { - case Constants.NORMAL_FUNC: - func.processFunctionRange(graphwar.getGameData().getObstacle(), players, numPlayers, graphwar.getGameData().getCurrentTurnIndex(), inverted); - break; - case Constants.FST_ODE: - func.processRK4Range(graphwar.getGameData().getObstacle(), players, numPlayers, graphwar.getGameData().getCurrentTurnIndex(), inverted); - break; - case Constants.SND_ODE: - func.processRK42Range(graphwar.getGameData().getObstacle(), players, numPlayers, graphwar.getGameData().getCurrentTurnIndex(), angle, inverted); - break; - } + + func.processRange(graphwar.getGameData().getObstacle(), players, numPlayers, graphwar.getGameData().getCurrentTurnIndex(), inverted, graphwar.getGameData().getGameMode(), angle); + double minDistSquared = 1000000; diff --git a/src/Graphwar/Function.java b/src/Graphwar/Function.java index 7919db5..3b19e37 100644 --- a/src/Graphwar/Function.java +++ b/src/Graphwar/Function.java @@ -236,7 +236,7 @@ private boolean playerAlreadyHit(int player, int soldier) return false; } - private void processRange(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted, int mode, double angle) + public void processRange(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted, int mode, double angle) { playersHit = new int[numPlayers*Constants.MAX_SOLDIERS_PER_PLAYER]; soldiersHit = new int[numPlayers*Constants.MAX_SOLDIERS_PER_PLAYER]; @@ -383,21 +383,6 @@ private void processRange(Obstacle obstacle, Player players[], int numPlayers, i lastY = -Constants.PLANE_LENGTH*valuesY[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; } - public void processFunctionRange(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted) - { - processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.NORMAL_FUNC, 0); - } - - public void processRK4Range(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted) - { - processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.FST_ODE, 0); - } - - public void processRK42Range(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, double angle ,boolean inverted) - { - processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.SND_ODE, angle); - } - public double getLastX() { return lastX; diff --git a/src/Graphwar/GameData.java b/src/Graphwar/GameData.java index 9b59423..a214700 100644 --- a/src/Graphwar/GameData.java +++ b/src/Graphwar/GameData.java @@ -1061,44 +1061,22 @@ else if(numDrawSteps > soldier.getKillPosition()) } private void processFunction(Player player, String functionString) throws MalformedFunction - { + { function = new Function(functionString); - + player.getCurrentTurnSoldier().setFunction(functionString); //If player is in team 2 the function must go in the other direction //and the obstacles are inverted - if(player.getTeam()==Constants.TEAM1) - { - switch(gameMode) - { - case Constants.NORMAL_FUNC: - function.processFunctionRange(obstacle, players.toArray(new Player[0]), players.size(), currentTurn, false); - break; - case Constants.FST_ODE: - function.processRK4Range(obstacle, players.toArray(new Player[0]), players.size(), currentTurn, false); - break; - case Constants.SND_ODE: - function.processRK42Range(obstacle, players.toArray(new Player[0]), players.size(), currentTurn, player.getCurrentTurnSoldier().getAngle(),false); - break; - } - } - else - { - switch(gameMode) - { - case Constants.NORMAL_FUNC: - function.processFunctionRange(obstacle, players.toArray(new Player[0]), players.size(), currentTurn, true); - break; - case Constants.FST_ODE: - function.processRK4Range(obstacle, players.toArray(new Player[0]), players.size(), currentTurn, true); - break; - case Constants.SND_ODE: - function.processRK42Range(obstacle, players.toArray(new Player[0]), players.size(), currentTurn, player.getCurrentTurnSoldier().getAngle(),true); - break; - } - } - + function.processRange( + obstacle, + players.toArray(new Player[0]), + players.size(), currentTurn, + player.getTeam()==Constants.TEAM2, + Constants.NORMAL_FUNC, + player.getCurrentTurnSoldier().getAngle() + ); + soldiersHit = new ArrayList(); int numPlayersHit = function.getNumPlayersHit(); for(int i=0; i Date: Wed, 8 Jul 2026 02:35:41 +0800 Subject: [PATCH 3/4] Fix: The bullet with undefined function will explode on the the top-left corner in y' mode In y' mode, if you send a function that is undefined, such as `log(x)`, `sqrt(x)`, `ln(x)`, at the starting point, instead of exploding at the starting point, the bullet will explode on the top-left corner. I have no idea that what stuff exactly causes it, but it's suprise that I fixed it when I try reorganising the `Function.java` unconsciously. Just like I said, the code in `src/Graphwar/Function.java` is organized to make it more readable, which fixes the bug somehow. --- src/Graphwar/Function.java | 731 +++++++++++-------------------------- 1 file changed, 223 insertions(+), 508 deletions(-) diff --git a/src/Graphwar/Function.java b/src/Graphwar/Function.java index 30bddaf..b6e8354 100644 --- a/src/Graphwar/Function.java +++ b/src/Graphwar/Function.java @@ -1,5 +1,5 @@ // Copyright (C) 2011 Lucas Catabriga Rocha -// +// // This file is part of Graphwar. // // Graphwar is free software: you can redistribute it and/or modify @@ -23,295 +23,146 @@ public class Function private String strFunc; private PolishNotationFunction polishFunc; private double offSet; - + private double fireAngle; private double[] valuesX; private double[] valuesY; private double[] valuesDY; private int numSteps; - + private int[] playersHit; private int[] soldiersHit; private int[] soldierHitPosition; private int numPlayersHit; - + private double lastX; private double lastY; - - Function(String str) throws MalformedFunction - { - strFunc = str; - - polishFunc = new PolishNotationFunction(strFunc); - + + private void init() + { offSet = 0; - + fireAngle = 0; valuesX = null; valuesY = null; valuesDY = null; numSteps = 0; - + playersHit = null; soldiersHit = null; + soldierHitPosition = null; numPlayersHit = 0; - + lastX = 0; lastY = 0; - } - + + Function(String str) throws MalformedFunction + { + strFunc = str; + polishFunc = new PolishNotationFunction(strFunc); + + init(); + + } + Function(PolishNotationFunction polishNotationFunction) { strFunc = ""; - polishFunc = polishNotationFunction; - - offSet = 0; - - fireAngle = 0; - valuesX = null; - valuesY = null; - valuesDY = null; - numSteps = 0; - - playersHit = null; - soldiersHit = null; - soldierHitPosition = null; - numPlayersHit = 0; - - lastX = 0; - lastY = 0; - + + init(); + } - + public int getNumPlayersHit() { return numPlayersHit; } - + public int getPlayerHit(int index) { return playersHit[index]; } - + public int getSoldierHit(int index) { return soldiersHit[index]; } - + public int getSoldierHitPosition(int index) { return soldierHitPosition[index]; } - + public double getFireAngle() { return fireAngle; - } - + } + public double getX(int index) { return valuesX[index]; } - + public double getY(int index) { return valuesY[index]; } - + public int getNumSteps() { return numSteps; } - + public String getStringFunc() { return strFunc; } - + private double getStartAngle(double x, double radius) { double angle = 0; - + double startAngleTangent = (polishFunc.evaluateFunction(x+Constants.STEP_SIZE,0,0) - polishFunc.evaluateFunction(x,0,0))/Constants.STEP_SIZE; angle = Math.atan(startAngleTangent); - + double finalX; double error = 10000; for(int i=0; error > Constants.ANGLE_ERROR && i Constants.FUNC_MAX_STEP_DISTANCE_SQUARED;j++) - { - if(valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE) - { - tempStepSize = tempStepSize/2; - - valuesX[i] = valuesX[i-1] + tempStepSize; - valuesY[i] = polishFunc.evaluateFunction(valuesX[i],0,0)+offSet; - } - else - { - endFunc = true; - break; - } - } - - if(endFunc) - { - numSteps = i; - break; - } - - double x = Constants.PLANE_LENGTH*valuesX[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; - double y = -Constants.PLANE_LENGTH*valuesY[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; - - - if(inverted) - { - x = Constants.PLANE_LENGTH - x; - } - - for(int j=0; j Constants.FUNC_MAX_STEP_DISTANCE_SQUARED && valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE;j++) - { - if(valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE) - { - tempStepSize = tempStepSize/2; - - k1 = polishFunc.evaluateFunction( valuesX[i-1], valuesY[i-1], 0); - k2 = polishFunc.evaluateFunction( valuesX[i-1] + 0.5*tempStepSize, valuesY[i-1] + 0.5*tempStepSize*k1, 0); - k3 = polishFunc.evaluateFunction( valuesX[i-1] + 0.5*tempStepSize, valuesY[i-1] + 0.5*tempStepSize*k2, 0); - k4 = polishFunc.evaluateFunction( valuesX[i-1] + tempStepSize, valuesY[i-1] + tempStepSize*k3, 0); - - valuesY[i] = valuesY[i-1] + (tempStepSize/6)*(k1 + 2*k2 + 2*k3 + k4); - valuesX[i] = valuesX[i-1] + tempStepSize; - } - else - { - endFunc = true; - break; - } - } - - if(endFunc) - { - numSteps = i; - break; - } - - double x = Constants.PLANE_LENGTH*valuesX[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; - double y = -Constants.PLANE_LENGTH*valuesY[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; - - - if(inverted) - { - x = Constants.PLANE_LENGTH - x; - } - - for(int j=0; j Constants.FUNC_MAX_STEP_DISTANCE_SQUARED && valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE;j++) - { - if(valuesX[i]-valuesX[i-1]>Constants.FUNC_MIN_X_STEP_DISTANCE) - { - - tempStepSize = tempStepSize/2; - - x1 = valuesX[i-1]; - y1 = valuesY[i-1]; - y2 = valuesDY[i-1]; - - k11 = y2; - k12 = polishFunc.evaluateFunction( x1, y1, y2); - - x1 = valuesX[i-1] + tempStepSize/2; - y1 = valuesY[i-1] + (tempStepSize/2)*k11; - y2 = valuesDY[i-1] + (tempStepSize/2)*k12; - - k21 = y2; - k22 = polishFunc.evaluateFunction( x1, y1, y2); - - y1 = valuesY[i-1] + (tempStepSize/2)*k21; - y2 = valuesDY[i-1] + (tempStepSize/2)*k22; - - k31 = y2; - k32 = polishFunc.evaluateFunction( x1, y1, y2); - - x1 = valuesX[i-1] + tempStepSize; - y1 = valuesY[i-1] + (tempStepSize)*k31; - y2 = valuesDY[i-1] + (tempStepSize)*k32; - - k41 = y2; - k42 = polishFunc.evaluateFunction( x1, y1, y2); - - - valuesX[i] = valuesX[i-1] + tempStepSize; - valuesY[i] = valuesY[i-1] + (tempStepSize/6)*(k11 + 2*k21 + 2*k31 + k41); - valuesDY[i] = valuesDY[i-1] + (tempStepSize/6)*(k12 + 2*k22 + 2*k32 + k42); - } - else + + for(int j = 0; Math.pow(valuesX[i]-valuesX[i-1], 2) + Math.pow(valuesY[i]-valuesY[i-1], 2) > Constants.FUNC_MAX_STEP_DISTANCE_SQUARED; j++) + { // If the step is too big, halve it + if (valuesX[i] - valuesX[i-1] <= Constants.FUNC_MIN_X_STEP_DISTANCE) { - endFunc = true; + if (gameMode == Constants.NORMAL_FUNC) + endFunc = true; break; } - + tempStepSize = tempStepSize/2; + + setNextValues(valuesX, valuesY, valuesDY, tempStepSize, i, gameMode); } - if(endFunc) { numSteps = i; break; } - - + double x = Constants.PLANE_LENGTH*valuesX[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; double y = -Constants.PLANE_LENGTH*valuesY[i]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; - - - if(inverted) - { - x = Constants.PLANE_LENGTH - x; - } - - for(int j=0; j= Constants.SOLDIER_RADIUS*Constants.SOLDIER_RADIUS) // The soldier is too far + continue; + if(Double.isNaN(distSquared)) // The illegal case + continue; + if(playerAlreadyHit(j,k)) // The player has already been hit + continue; + + playersHit[numPlayersHit] = j; + soldiersHit[numPlayersHit] = k; + soldierHitPosition[numPlayersHit] = i; + numPlayersHit++; } } - - - if(obstacle.collidePoint((int)x, (int)y)) - { - numSteps = i; - break; - } - - if(Double.isNaN(y) || Double.isInfinite(y)) + + + if(obstacle.collidePoint((int)x, (int)y) || Double.isNaN(y) || Double.isInfinite(y)) { numSteps = i; break; } - - } - - lastX = Constants.PLANE_LENGTH*valuesX[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2;; + + lastX = Constants.PLANE_LENGTH*valuesX[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_LENGTH/2; lastY = -Constants.PLANE_LENGTH*valuesY[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/2; + } + + public void processFunctionRange(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted) + { + processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.NORMAL_FUNC, 0); + } - + public void processRK4Range(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, boolean inverted) + { + processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.FST_ODE, 0); + } + + public void processRK42Range(Obstacle obstacle, Player players[], int numPlayers, int currentTurn, double angle ,boolean inverted) + { + processRange(obstacle, players, numPlayers, currentTurn, inverted, Constants.SND_ODE, angle); } - + public double getLastX() { return lastX; } - + public double getLastY() { return lastY; } - } From 295109b3cc1f4745dcfd2a655ba94d858c68b5d4 Mon Sep 17 00:00:00 2001 From: Cmd-GZ Date: Wed, 8 Jul 2026 04:48:42 +0800 Subject: [PATCH 4/4] Organize&Fix: src/Graphwar/ComputerPlayer.java 1. Organize ComputerPlayer.java to make it more readable 2. Fix a bug in `run()`, which makes the program mutate the old function angle (functions[i].angle) instead of the new one (newFunctions[i].angle) 3. Remove unused initialize about bestFunction --- src/Graphwar/ComputerPlayer.java | 534 +++++++++++++------------------ 1 file changed, 218 insertions(+), 316 deletions(-) diff --git a/src/Graphwar/ComputerPlayer.java b/src/Graphwar/ComputerPlayer.java index 0b7e3d1..3619dc5 100644 --- a/src/Graphwar/ComputerPlayer.java +++ b/src/Graphwar/ComputerPlayer.java @@ -1,5 +1,5 @@ // Copyright (C) 2011 Lucas Catabriga Rocha -// +// // This file is part of Graphwar. // // Graphwar is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ public class ComputerPlayer extends Player implements Runnable -{ +{ private int numGenerations; private int numFunctions; private EvolvableFunction[] bestFunction; @@ -33,13 +33,13 @@ public class ComputerPlayer extends Player implements Runnable private boolean over9000; //private boolean sayFunc; private boolean myTurn; - + private class EvolvableFunction implements Comparator { public PolishNotationFunction function; public double angle; public double points; - + EvolvableFunction() { function = new PolishNotationFunction(); @@ -47,62 +47,43 @@ private class EvolvableFunction implements Comparator points = 0; } - public int compare(EvolvableFunction arg0, EvolvableFunction arg1) + public int compare(EvolvableFunction arg0, EvolvableFunction arg1) { if(arg0.points < arg1.points) - { return 1; - } if(arg0.points > arg1.points) - { return -1; - } - else - { - return 0; - } + return 0; } - + } - - + + private double bestAngle; private String function; - - + + private boolean processingFunction; - + private Graphwar graphwar; - + private static Random random = new Random(); - + public ComputerPlayer(String name, int playerID, int team, boolean localPlayer, int numSoldiers, boolean ready, int level, Graphwar graphwar) { super(name, playerID, team, localPlayer, numSoldiers, ready); - + this.graphwar = graphwar; - + this.numGenerations = level; - if(level > 9000) - { - over9000 = true; - } - else - { - over9000 = false; - } + + over9000 = level > 9000; this.numFunctions = Constants.NUM_FUNCTIONS_AI; - + bestFunction = new EvolvableFunction[Constants.MAX_SOLDIERS_PER_PLAYER]; - for(int i=0; i 0) - continue; - } - - double tempDistSquared = Math.pow(distX,2) + Math.pow(distY,2); - - if(tempDistSquared < soldierMinDist) - { - soldierMinDist = tempDistSquared; - } - } - - if(soldierMinDist < minDistSquared) - { - minDistSquared = soldierMinDist; - } - } - } - } - } - - totalPoints += 1000000-minDistSquared; - - return totalPoints; + } + + if(players[i].getTeam() == this.team) + continue; + + double soldierMinDist = Double.MAX_VALUE; + + for(int k=0; k 0)) + continue; + + double tempDistSquared = Math.pow(distX,2) + Math.pow(distY,2); + + if(tempDistSquared < soldierMinDist) + soldierMinDist = tempDistSquared; + + } + + if(soldierMinDist < minDistSquared) + minDistSquared = soldierMinDist; + } + } + + totalPoints += 1000000-minDistSquared; + + return totalPoints; } private int getFunctionToReproduce(EvolvableFunction[] functions, double totalPoints) { - double randomPoints = totalPoints*random.nextDouble(); - - for(int i=0; i randomPoints) - { - totalPoints -= functions[i].points; - } - else - { - return i; - } - } - - return 0; + double randomPoints = totalPoints*random.nextDouble(); + + for(int i=0; i 5000) || (over9000)); k++) { - - if(graphwar.getGameData().getCurrentTurnPlayer() == this) - { - functions = this.functions[this.currentTurnSoldier]; - } - else + + functions = this.functions[this.currentTurnSoldier]; + if (graphwar.getGameData().getCurrentTurnPlayer() != this) { int nextTurnSoldier = this.getCurrentTurnSoldierIndex(); - - if(nextTurnSoldier == -1) - { + if (nextTurnSoldier == -1) return; - } - else - { - functions = this.functions[nextTurnSoldier]; - } + functions = this.functions[nextTurnSoldier]; } - - EvolvableFunction[] newFunctions = new EvolvableFunction[numFunctions]; - - totalPoints = getTotalPoints(functions); - - for(int i=0; i= 3000 || over9000) + continue; + functions = oldFunctions; + this.functions[this.currentTurnSoldier] = oldFunctions; + break generationLoop; + } + //System.out.println(); - - Arrays.sort(functions, functions[0]); - - - if(over9000) - { - if(myTurn && (graphwar.getGameData().getRemainingTime()) < 5000) - { - bestFunction[this.currentTurnSoldier] = functions[0]; - sendFunction(); - - myTurn = false; - } - } - - + + Arrays.sort(functions, functions[0]); + + + if(!over9000 || !myTurn || (graphwar.getGameData().getRemainingTime()) >= 5000) + continue; + + bestFunction[this.currentTurnSoldier] = functions[0]; + sendFunction(); + + myTurn = false; } - - //bestFunction[this.currentSoldierTurn] = functions[getFunctionToReproduce(functions, totalPoints)]; - if(processingFunction) - { - if(over9000 == false) - { - bestFunction[this.currentTurnSoldier] = functions[0]; - sendFunction(); - } - } - + + //bestFunction[this.currentSoldierTurn] = functions[getFunctionToReproduce(functions, totalPoints)]; + if(processingFunction && !over9000) + { + bestFunction[this.currentTurnSoldier] = functions[0]; + sendFunction(); + } + processingFunction = false; - + //gameInfo.sendChatMessage(gameInfo.getCurrentTurn(), function + " " + functions[0].points); } - + private void sendFunction() - { + { function = bestFunction[this.currentTurnSoldier].function.simplifyFunction().getStringFunction(); bestAngle = bestFunction[this.currentTurnSoldier].angle; - + //System.out.println(this.getName()+":"); //System.out.println(bestFunction[this.currentTurnSoldier].function.getStringFunction()); //System.out.println(function); - + graphwar.getGameData().setAngle(bestAngle); graphwar.getGameData().sendFunction(function); - + //if(sayFunc) //{ // graphwar.getGameData().sendChatMessage(this, function); //} - + } }