diff --git a/core/.gitignore b/core/.gitignore index 1cf25c0..fbd5135 100644 --- a/core/.gitignore +++ b/core/.gitignore @@ -19,3 +19,4 @@ /texture.class /vector.class /playerCommander.class +/sideBarManager.class diff --git a/core/AssetManager.java b/core/AssetManager.java index bbea7fe..936b508 100644 --- a/core/AssetManager.java +++ b/core/AssetManager.java @@ -183,14 +183,14 @@ public class AssetManager { gunTurrets = new gunTurret[512]; missileTurrets = new missileTurret[256]; - goldMines[0].goldDeposite = 45000; - goldMines[1].goldDeposite = 45000; - goldMines[2].goldDeposite = 50000; - goldMines[3].goldDeposite = 50000; - goldMines[4].goldDeposite = 45000; - goldMines[5].goldDeposite = 45000; - goldMines[6].goldDeposite = 55000; - goldMines[7].goldDeposite = 55000; + goldMines[0].goldDeposite = goldMines[0].maxDeposite; + goldMines[1].goldDeposite = goldMines[1].maxDeposite; + goldMines[2].goldDeposite = goldMines[2].maxDeposite; + goldMines[3].goldDeposite = goldMines[3].maxDeposite; + goldMines[4].goldDeposite = goldMines[4].maxDeposite; + goldMines[5].goldDeposite = goldMines[5].maxDeposite; + goldMines[6].goldDeposite = goldMines[6].maxDeposite; + goldMines[7].goldDeposite = goldMines[7].maxDeposite; bullets = new bullet[200]; for(int i = 0; i < 200; i ++){ @@ -305,14 +305,14 @@ public class AssetManager { gunTurrets = null; missileTurrets = null; - goldMines[0].goldDeposite = 45000; - goldMines[1].goldDeposite = 45000; - goldMines[2].goldDeposite = 50000; - goldMines[3].goldDeposite = 50000; - goldMines[4].goldDeposite = 45000; - goldMines[5].goldDeposite = 45000; - goldMines[6].goldDeposite = 55000; - goldMines[7].goldDeposite = 55000; + goldMines[0].goldDeposite = goldMines[0].maxDeposite; + goldMines[1].goldDeposite = goldMines[1].maxDeposite; + goldMines[2].goldDeposite = goldMines[2].maxDeposite; + goldMines[3].goldDeposite = goldMines[3].maxDeposite; + goldMines[4].goldDeposite = goldMines[4].maxDeposite; + goldMines[5].goldDeposite = goldMines[5].maxDeposite; + goldMines[6].goldDeposite = goldMines[6].maxDeposite; + goldMines[7].goldDeposite = goldMines[7].maxDeposite; bullets = null; rockets = null; diff --git a/core/playerCommander.java b/core/playerCommander.java index 2bc6306..12b6270 100644 --- a/core/playerCommander.java +++ b/core/playerCommander.java @@ -6,7 +6,6 @@ import entity.constructionYard; import entity.factory; import entity.solidObject; import gui.inputHandler; -import gui.sideBarManager; //this class interprets player's inputs and turns them into commands that can be issued to game units public class playerCommander { diff --git a/gui/sideBarManager.java b/core/sideBarManager.java similarity index 96% rename from gui/sideBarManager.java rename to core/sideBarManager.java index ac6a340..b8557af 100644 --- a/gui/sideBarManager.java +++ b/core/sideBarManager.java @@ -1,8 +1,7 @@ -package gui; +package core; -import core.mainThread; -import core.playerCommander; import entity.*; +import gui.inputHandler; //this class handles player's interaction with the sidebar public class sideBarManager { diff --git a/enemyAI/.gitignore b/enemyAI/.gitignore index 4d78972..04aaf1b 100644 --- a/enemyAI/.gitignore +++ b/enemyAI/.gitignore @@ -8,3 +8,4 @@ /microManagementAI.class /scoutingManagerAI.class /unitProductionAI.class +/harassmentAI.class diff --git a/enemyAI/baseExpensionAI.java b/enemyAI/baseExpensionAI.java index 9719177..0740fc1 100644 --- a/enemyAI/baseExpensionAI.java +++ b/enemyAI/baseExpensionAI.java @@ -23,8 +23,8 @@ public class baseExpensionAI { public boolean allExpansionOccupied; public int lastExpansionLocation; - public baseExpensionAI(baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + public baseExpensionAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; frameAI = 0; temp = new vector(0,0,0); @@ -144,7 +144,7 @@ public class baseExpensionAI { boolean playerHasLessUnits = mainThread.ec.theCombatManagerAI.checkIfAIHasBiggerForce(1f); - int lowGoldmineThreshold = 20000; + int lowGoldmineThreshold = 22500; if(playerHasLessUnits) { @@ -172,14 +172,13 @@ public class baseExpensionAI { if(numberOfMCVOnQueue == 0 && theBaseInfo.canBuildMCV){ for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){ if(mainThread.theAssetManager.factories[i] != null && mainThread.theAssetManager.factories[i].teamNo != 0){ - //if(main.theAssetManager.factories[i].lightTankProgress < 240 || main.theAssetManager.factories[i].isIdle()){ + mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.lightTankType); mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.rocketTankType); mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.stealthTankType); mainThread.theAssetManager.factories[i].cancelItemFromProductionQueue(factory.heavyTankType); mainThread.theAssetManager.factories[i].buildMCV(); - break; - //} + break; } } } diff --git a/enemyAI/buildingManagerAI.java b/enemyAI/buildingManagerAI.java index 00ce113..d7d3625 100644 --- a/enemyAI/buildingManagerAI.java +++ b/enemyAI/buildingManagerAI.java @@ -20,8 +20,8 @@ public class buildingManagerAI { public int frameIndex; - public buildingManagerAI (baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + public buildingManagerAI (){ + this.theBaseInfo = mainThread.ec.theBaseInfo; buildingPlacementCheckTiles = solidObject.generateTileCheckList(13); buildingPlacementCheckTiles_2x2 = new int[buildingPlacementCheckTiles.length]; diff --git a/enemyAI/combatManagerAI.java b/enemyAI/combatManagerAI.java index 0a05b42..24d8816 100644 --- a/enemyAI/combatManagerAI.java +++ b/enemyAI/combatManagerAI.java @@ -61,10 +61,15 @@ public class combatManagerAI { public boolean unitCountLow; + public int standardAttackTime, rushAttackTime; - public combatManagerAI(baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + + public combatManagerAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; + + standardAttackTime = 600; + rushAttackTime = 300; goldMines = mainThread.theAssetManager.goldMines; @@ -152,15 +157,18 @@ public class combatManagerAI { if(currentState == booming){ //enemy AI compares its own force with player's force, then make a decision whether it should attack or not - int attackTime = 540; + int attackTime = standardAttackTime; if(mainThread.ec.theMapAwarenessAI.canRushPlayer) - attackTime = 300; + attackTime = rushAttackTime; int targetPlayerExpension = mainThread.ec.theMapAwarenessAI.targetPlayerExpension; if(frameAI > attackTime) { if(targetPlayerExpension == 0 || targetPlayerExpension == 1 || targetPlayerExpension == 6 || targetPlayerExpension == 7) - shouldAttack = checkIfAIHasBiggerForce(0.9f); + if(frameAI < 700) + shouldAttack = checkIfAIHasBiggerForce(0.5f); + else + shouldAttack = checkIfAIHasBiggerForce(0.75f); else shouldAttack = checkIfAIHasBiggerForce(1.2f); } @@ -305,6 +313,11 @@ public class combatManagerAI { } } + //if a rush tactics is denied by the player (e.g player builds static defenses around natural), then change status to booming + if(frameAI < standardAttackTime && !mainThread.ec.theMapAwarenessAI.canRushPlayer){ + currentState = booming; + return; + } attackDirection.set(attackPosition.x - combatCenterX, 0, attackPosition.z - combatCenterZ); distanceToTarget = attackDirection.getLength(); @@ -364,7 +377,7 @@ public class combatManagerAI { //check if the player force has become stronger than the AI during the marching towards attack position //System.out.println("distanceToTarget: " + distanceToTarget); - if(checkIfAIHasBiggerForce(1.5f) == false && distanceToTarget > 5){ + if(checkIfAIHasBiggerForce(1.5f) == false && distanceToTarget > 6){ playerHasBecomeStrongerThanAIDuringMarching = true; } diff --git a/enemyAI/defenseManagerAI.java b/enemyAI/defenseManagerAI.java index dcb6a5e..32e6492 100644 --- a/enemyAI/defenseManagerAI.java +++ b/enemyAI/defenseManagerAI.java @@ -44,8 +44,8 @@ public class defenseManagerAI { public vector missileTurretDeployLocation; - public defenseManagerAI(baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + public defenseManagerAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; observers = new solidObject[4]; @@ -95,7 +95,7 @@ public class defenseManagerAI { } - if(gameTime > 880) { + if(gameTime > 980) { xPos = 0.25f; zPos = 20.5f; @@ -133,7 +133,7 @@ public class defenseManagerAI { zPos = 24.5f; } - if(gameTime > 880) { + if(gameTime > 980) { if(gameTime%18 < 9) { xPos = 0.25f; zPos = 20.5f; @@ -155,7 +155,7 @@ public class defenseManagerAI { zPos = 20f; } - if(gameTime > 880) { + if(gameTime > 980) { if(gameTime%14 < 7) { xPos = 18.75f; zPos = 5f; @@ -350,9 +350,9 @@ public class defenseManagerAI { float d = (float)Math.sqrt((minorThreatLocation.x-AIStructures[i].centre.x)*(minorThreatLocation.x-AIStructures[i].centre.x) + (minorThreatLocation.z-AIStructures[i].centre.z)*(minorThreatLocation.z-AIStructures[i].centre.z)); - if(AIStructures[i].type == 200 && d <= 2) + if(AIStructures[i].type == 200 && d <= 2.5) numOfGunTurretNearThreat++; - if(AIStructures[i].type == 199 && d <= 2.4) + if(AIStructures[i].type == 199 && d <= 2.9) numOfMissileTurretNearThreat++; } } @@ -367,15 +367,17 @@ public class defenseManagerAI { float d = (float)Math.sqrt((majorThreatLocation.x-AIStructures[i].centre.x)*(majorThreatLocation.x-AIStructures[i].centre.x) + (majorThreatLocation.z-AIStructures[i].centre.z)*(majorThreatLocation.z-AIStructures[i].centre.z)); - if(AIStructures[i].type == 200 && d <= 2) + if(AIStructures[i].type == 200 && d <= 2.5) numOfGunTurretNearThreat++; - if(AIStructures[i].type == 199 && d <= 2.4) + if(AIStructures[i].type == 199 && d <= 2.9) numOfMissileTurretNearThreat++; } } } + //System.out.println("mainPlayerForceSize: " + mainPlayerForceSize + " " + "numOfGunTurretNearThreat: " +numOfGunTurretNearThreat + " " + "numOfMissileTurretNearThreat: " + numOfMissileTurretNearThreat); + for(int i = 0; i < constructionYards.length; i++){ if(constructionYards[i] != null && constructionYards[i].teamNo != 0 && constructionYards[i].currentHP >0) { @@ -414,7 +416,7 @@ public class defenseManagerAI { } //find deploy location of missile turret - if(threatX != 0 && distanceToThreat < 5.15 && (numOfMissileTurretNearThreat < mainPlayerForceSize/6 || !gunTurretAlreadyInQueue)) { + if(threatX != 0 && distanceToThreat < 5.15 && (numOfMissileTurretNearThreat < mainPlayerForceSize/6 )) { float d = 1.65f; //minimum deploy distance from conyard if(distanceToThreat > d + missileTurret.attackRange) diff --git a/enemyAI/economyManagerAI.java b/enemyAI/economyManagerAI.java index 01e3348..7aab876 100644 --- a/enemyAI/economyManagerAI.java +++ b/enemyAI/economyManagerAI.java @@ -19,8 +19,8 @@ public class economyManagerAI { public vector evadeDirection; public int numberOfFunctionalRefinery; - public economyManagerAI(baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + public economyManagerAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo;; evadeDirection = new vector(0,0,0); diff --git a/enemyAI/enemyCommander.java b/enemyAI/enemyCommander.java index 56de5da..61b6ac3 100644 --- a/enemyAI/enemyCommander.java +++ b/enemyAI/enemyCommander.java @@ -21,6 +21,7 @@ public class enemyCommander { public defenseManagerAI theDefenseManagerAI; public combatManagerAI theCombatManagerAI; public microManagementAI theMicroManagementAI; + public harassmentAI theHarassmentAI; public int difficulty; @@ -33,15 +34,16 @@ public class enemyCommander { theBaseInfo = new baseInfo(); - theBuildingManagerAI = new buildingManagerAI(theBaseInfo); - theEconomyManagerAI = new economyManagerAI(theBaseInfo); - theMapAwarenessAI = new mapAwarenessAI(theBaseInfo, visionMap); - theUnitProductionAI = new unitProductionAI(theBaseInfo); - theBaseExpentionAI = new baseExpensionAI(theBaseInfo); - theScoutingManagerAI = new scoutingManagerAI(theBaseInfo); - theDefenseManagerAI = new defenseManagerAI(theBaseInfo); - theCombatManagerAI = new combatManagerAI(theBaseInfo); - theMicroManagementAI = new microManagementAI(theBaseInfo); + theBuildingManagerAI = new buildingManagerAI(); + theEconomyManagerAI = new economyManagerAI(); + theMapAwarenessAI = new mapAwarenessAI(); + theUnitProductionAI = new unitProductionAI(); + theBaseExpentionAI = new baseExpensionAI(); + theScoutingManagerAI = new scoutingManagerAI(); + theDefenseManagerAI = new defenseManagerAI(); + theCombatManagerAI = new combatManagerAI(); + theMicroManagementAI = new microManagementAI(); + theHarassmentAI = new harassmentAI(); } @@ -119,6 +121,10 @@ public class enemyCommander { theDefenseManagerAI.processAI(); } + if(mainThread.gameFrame % 30 == 8) { + theHarassmentAI.processAI(); + } + //if(mainThread.frameIndex % 5 == 0){ theMicroManagementAI.processAI(); //} diff --git a/enemyAI/harassmentAI.java b/enemyAI/harassmentAI.java new file mode 100644 index 0000000..d8a6192 --- /dev/null +++ b/enemyAI/harassmentAI.java @@ -0,0 +1,31 @@ +//This AI agent will perform hit and run tactics against the player. +//It will try to harass plahyer's mineral line, and destroy player's building from a distance. +//It will most likely act at the same time when the AI's main attack force is launching an attack, + +package enemyAI; + +import core.baseInfo; +import core.mainThread; + +public class harassmentAI { + + public baseInfo theBaseInfo; + + public int gameTime; + + + public harassmentAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; + + + } + + public void processAI(){ + + gameTime++; + + + } + + +} diff --git a/enemyAI/mapAwarenessAI.java b/enemyAI/mapAwarenessAI.java index 7776c50..8374bf8 100644 --- a/enemyAI/mapAwarenessAI.java +++ b/enemyAI/mapAwarenessAI.java @@ -79,9 +79,9 @@ public class mapAwarenessAI { public int[] playerStaticDefenseSize; public int[] playerStaticDefenseStrength; - public mapAwarenessAI(baseInfo theBaseInfo, boolean[] visionMap){ - this.theBaseInfo = theBaseInfo; - this.visionMap = visionMap; + public mapAwarenessAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; + this.visionMap = mainThread.ec.visionMap; mapAsset = new solidObject[1024]; playerUnitInMinimap = new solidObject[128]; @@ -463,7 +463,7 @@ public class mapAwarenessAI { playerIsRushingLightTank = mainThread.gameFrame/30 > 300 && mainThread.gameFrame/30 < 600 && ((playerLikelyCanNotProduceHighTierUnits && numberOfStealthTanks_player < 3) || playerHasMostlyLightTanks); - playerHasMostlyHeavyAndStealthTanks = (maxNumberOfStealthTanks_playerInLastFiveMinutes >=2 ) && (float)(numberOfHeavyTanks_player + numberOfStealthTanks_player)/totalNumberOfPlayerUnits > 0.8f; + playerHasMostlyHeavyAndStealthTanks = (maxNumberOfStealthTanks_playerInLastFiveMinutes >=3 ) && (float)(numberOfHeavyTanks_player + numberOfStealthTanks_player)/totalNumberOfPlayerUnits > 0.8f; //advanced counting of player units @@ -515,7 +515,26 @@ public class mapAwarenessAI { } if(playerIsFastExpanding) { - canRushPlayer = true; + + //check if there is any static defense around player's natural + boolean staticDefenceNearPlayerExpansion = false; + solidObject[] playerStaticDefence = mainThread.ec.theMapAwarenessAI.playerStaticDefenceInMinimap; + for(int i = 0; i < playerStaticDefence.length; i++) { + if(playerStaticDefence[i] != null && playerStaticDefence[i].currentHP > 0) { + float x1 = playerStaticDefence[i].centre.x; + float z1 = playerStaticDefence[i].centre.z; + float x2 = playerNaturalLocation.x; + float z2 = playerNaturalLocation.z; + + if(Math.sqrt((x1-x2)*(x1-x2) + (z1-z2)*(z1-z2)) < 3f) { + staticDefenceNearPlayerExpansion = true; + break; + } + } + } + + if(!staticDefenceNearPlayerExpansion) + canRushPlayer = true; } diff --git a/enemyAI/microManagementAI.java b/enemyAI/microManagementAI.java index b791172..5f1dcfb 100644 --- a/enemyAI/microManagementAI.java +++ b/enemyAI/microManagementAI.java @@ -28,8 +28,8 @@ public class microManagementAI { public int numberOfPlayerUnitsOnMinimap; - public microManagementAI(baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + public microManagementAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; } public void processAI(){ diff --git a/enemyAI/scoutingManagerAI.java b/enemyAI/scoutingManagerAI.java index 7dab22b..3c317d4 100644 --- a/enemyAI/scoutingManagerAI.java +++ b/enemyAI/scoutingManagerAI.java @@ -32,8 +32,8 @@ public class scoutingManagerAI { //scout unit consists a sole light tank public solidObject scout; - public scoutingManagerAI(baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + public scoutingManagerAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; patrolNodes = new float[][]{ {16, 30}, {2, 29}, {15, 17}, {16, 14}, {27f, 1}, {30, 16}, {16, 14}, {15, 17} @@ -56,12 +56,12 @@ public class scoutingManagerAI { public void processAI(){ gameTime++; - + if(avoidingIncomingPlayerUnitCooldown > 0) avoidingIncomingPlayerUnitCooldown--; boolean scoutIsLightTank = scout != null && scout.type == 0; - if((gameTime%275 > 235 && gameTime%275 < 275 && !scoutIsLightTank) && gameTime < 600 && scoutingMode == patrolling || (scoutIsLightTank && gameTime < 240)){ + if((gameTime%275 > 235 && gameTime%275 < 275 && !scoutIsLightTank) && gameTime < 900 && scoutingMode == patrolling || (scoutIsLightTank && gameTime < 240)){ scoutingMode = exploring; destinationNode = 0; movementOrderIssued = false; diff --git a/enemyAI/unitProductionAI.java b/enemyAI/unitProductionAI.java index 800ff01..4fc8853 100644 --- a/enemyAI/unitProductionAI.java +++ b/enemyAI/unitProductionAI.java @@ -47,8 +47,8 @@ public class unitProductionAI { public int frameAI; - public unitProductionAI(baseInfo theBaseInfo){ - this.theBaseInfo = theBaseInfo; + public unitProductionAI(){ + this.theBaseInfo = mainThread.ec.theBaseInfo; rallyPoint = new vector(0,0,0); @@ -166,15 +166,18 @@ public class unitProductionAI { boolean playerHasManyLightTanksButNoHeavyTank = mainThread.ec.theMapAwarenessAI.playerHasManyLightTanksButNoHeavyTank; boolean playerHasMostlyHeavyAndStealthTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyHeavyAndStealthTanks; - if((numberOfRocketTanks_AI < 2 && (frameAI > 400 || frameAI > 170 && frameAI < 240 && mainThread.ec.theMapAwarenessAI.numberOfConstructionYard_player > 0) && !playerHasMostlyLightTanks) || numberOfRocketTanks_AI < numberOfPlayerGunTurrets + numberOfPlayerMissileTurrets*1.5 || (gameData.getRandom() > 925 && !playerHasMostlyLightTanks)){ + + boolean b1 = (numberOfRocketTanks_AI < 2 && (frameAI > 400 || frameAI > 170 && frameAI < 240 && mainThread.ec.theMapAwarenessAI.numberOfConstructionYard_player > 0) && !playerHasMostlyLightTanks); + boolean b2 = (numberOfRocketTanks_AI < numberOfPlayerGunTurrets + numberOfPlayerMissileTurrets*1.5); + if( b1 || b2){ currentProductionOrder = produceRocketTank; }else if(theBaseInfo.canBuildHeavyTank && - playerHasMostlyHeavyAndStealthTanks || - (!playerHasManyLightTanksButNoHeavyTank + (playerHasMostlyHeavyAndStealthTanks || + !playerHasManyLightTanksButNoHeavyTank && !playerHasMostlyLightTanks && !(numberOfHeavyTanks_player == 0 && maxNumberOfStealthTanks_playerInLastFiveMinutes < 3 && mainThread.gameFrame/30 > 600) && !(playerHasMostlyHeavyTanks && numberOfStealthTanks_player < numberOfHeavyTanks_AI*2) - && (playIsRushingHighTierUnits || gameData.getRandom() > 985 || maxNumberOfStealthTanks_playerInLastFiveMinutes*4 > numberOfHeavyTanks_AI || (mainThread.gameFrame/30 > 400 && mainThread.gameFrame/30 < 600 && numberOfPlayerGunTurrets + numberOfPlayerMissileTurrets+ numberOfLightTanks_player + numberOfRocketTanks_player + numberOfHeavyTanks_player*5 < 5)))){ + && (playIsRushingHighTierUnits || maxNumberOfStealthTanks_playerInLastFiveMinutes*4 > numberOfHeavyTanks_AI || (mainThread.gameFrame/30 > 400 && mainThread.gameFrame/30 < 600 && numberOfPlayerGunTurrets + numberOfPlayerMissileTurrets+ numberOfLightTanks_player + numberOfRocketTanks_player + numberOfHeavyTanks_player*5 < 5)))){ currentProductionOrder = produceHeavyTank; }else if(theBaseInfo.canBuildStealthTank && (playerHasMostlyLightTanks || playerLikelyCanNotProduceHighTierUnits || playerDoesntHaveMassHeavyTanks) && !playerHasMostlyHeavyTanks){ currentProductionOrder = produceStealthTank; @@ -182,7 +185,7 @@ public class unitProductionAI { currentProductionOrder = produceLightTank; } - + //make decision on what tech to research if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfCommunicationCenter > 0) { if(mainThread.ec.theDefenseManagerAI.needMissileTurret || theBaseInfo.currentCredit > 1500) { diff --git a/entity/lightPole.java b/entity/lightPole.java index b50fa64..6cca403 100644 --- a/entity/lightPole.java +++ b/entity/lightPole.java @@ -35,6 +35,7 @@ public class lightPole extends solidObject{ //uncontrollable unit, but act as a small sized static collidable agent ID = -1; type = 100; + teamNo = -1; this.angle = angle;