diff --git a/src/Graphwar/ComputerPlayer.java b/src/Graphwar/ComputerPlayer.java index 97e8d1d..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); //} - + } } diff --git a/src/Graphwar/Function.java b/src/Graphwar/Function.java index 30bddaf..0c06f8c 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;; - lastY = -Constants.PLANE_LENGTH*valuesY[numSteps-1]/Constants.PLANE_GAME_LENGTH + Constants.PLANE_HEIGHT/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 double getLastX() { return lastX; } - + public double getLastY() { return lastY; } - } diff --git a/src/Graphwar/GameData.java b/src/Graphwar/GameData.java index 9b59423..201b4c7 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, + gameMode, + player.getCurrentTurnSoldier().getAngle() + ); + soldiersHit = new ArrayList(); int numPlayersHit = function.getNumPlayersHit(); for(int i=0; i