├── META-INF ├── native-image │ └── native-image.properties └── MANIFEST.MF ├── configs ├── BWAPI.dll ├── run32.bat ├── run64.bat ├── run_proxy.bat ├── PurpleWaveLocalMetal.config.json ├── PurpleWaveLocalDocker.config.json ├── PurpleWaveAIIDE.config.json ├── PurpleWaveSCHNAIL.config.json ├── launch4jPurpleSimViz.xml └── PurpleWaveBASIL.config.json ├── install ├── instructions1.png ├── instructions2.png ├── instructions3.png ├── instructions4.png └── instructions5.png ├── src ├── Macro │ ├── Facts │ │ └── MacroFacts.scala │ ├── Requests │ │ ├── RequestTech.scala │ │ ├── RequestUpgrade.scala │ │ └── RequestAutosupply.scala │ ├── Scheduling │ │ ├── ScheduleItem.scala │ │ ├── MacroProducer.scala │ │ ├── MacroStep.scala │ │ └── Scheduler.scala │ ├── Actions │ │ ├── BuildOnce.scala │ │ ├── SneakyCitadel.scala │ │ └── PumpShuttleAndReavers.scala │ └── Allocation │ │ └── Priorities.scala ├── Gameplans │ ├── Zerg │ │ ├── ZvZ │ │ │ └── ZergVsZerg.scala │ │ ├── ZvP │ │ │ └── ZergVsProtoss.scala │ │ ├── ZvT │ │ │ └── ZergVsTerran.scala │ │ ├── ZvR │ │ │ └── ZergVsRandom.scala │ │ └── ZergStandardGameplan.scala │ ├── Terran │ │ ├── TvP │ │ │ ├── TerranVsProtoss.scala │ │ │ └── TvPRaxExpand.scala │ │ ├── TvT │ │ │ └── TerranVsTerran.scala │ │ ├── TvZ │ │ │ └── TerranVsZerg.scala │ │ ├── TerranStandardGameplan.scala │ │ └── TvE │ │ │ └── BunkerRush.scala │ ├── All │ │ ├── Modal.scala │ │ ├── ModalGameplan.scala │ │ └── StandardGameplan.scala │ └── Protoss │ │ ├── FFA │ │ └── ProtossFFAMoney.scala │ │ ├── PvR │ │ └── ProtossVsRandom.scala │ │ ├── PvZ │ │ └── ProtossVsZerg.scala │ │ ├── PvP │ │ └── ProtossVsProtoss.scala │ │ ├── PvT │ │ └── ProtossVsTerran.scala │ │ └── ProtossStandardGameplan.scala ├── Planning │ ├── Plans │ │ ├── NoPlan.scala │ │ └── Plan.scala │ ├── ResourceLocks │ │ ├── LockCurrencyFor.scala │ │ ├── LockCurrency.scala │ │ └── LockTiles.scala │ └── Proxy │ │ └── ProxyRequest.scala ├── Utilities │ ├── Time │ │ ├── Frames.scala │ │ ├── Seconds.scala │ │ ├── Hours.scala │ │ ├── Minutes.scala │ │ ├── GameTime.scala │ │ ├── Forever.scala │ │ └── FrameCount.scala │ ├── UnitCounters │ │ ├── CountOne.scala │ │ ├── CountEverything.scala │ │ ├── CountUpTo.scala │ │ ├── CountBetween.scala │ │ ├── CountExactly.scala │ │ ├── UnitCounter.scala │ │ └── CountExcept.scala │ ├── LightYear.scala │ ├── UnitFilters │ │ ├── IsFlyingBuilding.scala │ │ ├── IsFlyingWarrior.scala │ │ ├── IsGroundWarrior.scala │ │ ├── IsMechWarrior.scala │ │ ├── IsAnything.scala │ │ ├── IsBioWarrior.scala │ │ ├── IsEnemy.scala │ │ ├── IsProxied.scala │ │ ├── UnitFilter.scala │ │ ├── IsTank.scala │ │ ├── IsVisible.scala │ │ ├── IsBuilding.scala │ │ ├── IsComplete.scala │ │ ├── IsTownHall.scala │ │ ├── IsWorker.scala │ │ ├── IsDetector.scala │ │ ├── IsHatchlike.scala │ │ ├── IsLairlike.scala │ │ ├── IsAntiAir.scala │ │ ├── Is.scala │ │ ├── IsAntiGround.scala │ │ ├── IsWarrior.scala │ │ ├── IsAny.scala │ │ ├── IsMobileDetector.scala │ │ ├── IsLandedBuilding.scala │ │ ├── IsAll.scala │ │ ├── IsBurrowedLurker.scala │ │ ├── IsSpeedling.scala │ │ ├── IsSpeedlot.scala │ │ ├── IsSlowling.scala │ │ ├── IsSlowlot.scala │ │ ├── IsCompleteFor.scala │ │ ├── IsSpeedScout.scala │ │ ├── IsRangedGoon.scala │ │ ├── IsSpeedVulture.scala │ │ ├── IsCombatSpellcaster.scala │ │ └── IsRecruitableForCombat.scala │ ├── In.scala │ ├── SomeIf.scala │ ├── SomeIfO.scala │ ├── AsJava.scala │ ├── AsScala.scala │ ├── UnitPreferences │ │ ├── UnitPreference.scala │ │ ├── PreferAnything.scala │ │ ├── PreferLowEnergy.scala │ │ ├── PreferBaseWithMoreWorkers.scala │ │ ├── PreferBaseWithFewerWorkers.scala │ │ ├── PreferIf.scala │ │ ├── PreferIdle.scala │ │ ├── PreferAll.scala │ │ ├── PreferTiers.scala │ │ ├── PreferHatcheryWithThreeLarva.scala │ │ └── PreferScout.scala │ ├── Ternary.scala │ ├── SwapIf.scala │ ├── DoQueue.scala │ └── SpinWait.scala ├── ProxyBwapi │ ├── Techs │ │ └── None.scala │ ├── Size.scala │ ├── Players │ │ └── Players.scala │ ├── UnitTracking │ │ ├── Visibility.scala │ │ └── IndexedSet.scala │ ├── Bullets │ │ └── Bullets.scala │ ├── Races │ │ └── Neutral.scala │ ├── Upgrades │ │ └── Upgrades.scala │ ├── UnitClasses │ │ └── UnitClasses.scala │ ├── UnitInfo │ │ └── Targeter.scala │ ├── Buildable.scala │ └── Readme.md ├── Debugging │ ├── SimpleString.scala │ ├── Asciify.scala │ ├── Decimal.scala │ ├── English.scala │ ├── Visualizations │ │ ├── Rendering │ │ │ └── TextWidth.scala │ │ ├── Views │ │ │ ├── Micro │ │ │ │ ├── ShowUnitPaths.scala │ │ │ │ ├── ShowPathfinding.scala │ │ │ │ └── ShowFormations.scala │ │ │ ├── Geography │ │ │ │ └── ShowBWEB.scala │ │ │ ├── Planning │ │ │ │ ├── ShowPlacement.scala │ │ │ │ ├── ShowWall.scala │ │ │ │ ├── ShowHistory.scala │ │ │ │ └── ShowFingerprints.scala │ │ │ ├── Fun │ │ │ │ ├── ShowBlackScreen.scala │ │ │ │ └── ShowHappyVision.scala │ │ │ ├── ShowStoryteller.scala │ │ │ ├── DebugView.scala │ │ │ └── Battles │ │ │ │ └── ShowTeams.scala │ │ ├── ForceLabel.scala │ │ ├── Hues.scala │ │ └── Animation.scala │ ├── ToString.scala │ └── EnumerateUnits.scala ├── Mathematics │ ├── Physics │ │ ├── Forces.scala │ │ ├── Gravity.scala │ │ └── ForceMap.scala │ ├── Shapes │ │ ├── Square.scala │ │ ├── Rectangle.scala │ │ ├── Corners.scala │ │ ├── Circle.scala │ │ ├── Box.scala │ │ ├── RoundedBox.scala │ │ └── Ring.scala │ ├── Points │ │ ├── Directions.scala │ │ ├── Points.scala │ │ ├── WalkTile.scala │ │ ├── AbstractPoint.scala │ │ └── Point.scala │ └── Maff.scala ├── Information │ ├── Geography │ │ ├── Pathfinding │ │ │ ├── Types │ │ │ │ ├── TileState.scala │ │ │ │ ├── NoPath.scala │ │ │ │ └── ZonePathNode.scala │ │ │ ├── Paths.scala │ │ │ └── PathfindRepulsor.scala │ │ ├── NeoGeo │ │ │ ├── NeoEdge.scala │ │ │ ├── NeoMetro.scala │ │ │ ├── NeoRegion.scala │ │ │ ├── NeoPixel.scala │ │ │ ├── NeoTile.scala │ │ │ ├── NeoWalk.scala │ │ │ ├── NeoContinent.scala │ │ │ ├── NeoCountry.scala │ │ │ ├── Internal │ │ │ │ └── NeoContinentBackend.scala │ │ │ ├── NeoBase.scala │ │ │ └── MapIdentifier.scala │ │ ├── Calculations │ │ │ ├── ZonesConnecting.scala │ │ │ └── GetExits.scala │ │ └── Types │ │ │ └── LabelGenerator.scala │ ├── Grids │ │ ├── Floody │ │ │ ├── FloodyUnitDepth.scala │ │ │ ├── FloodyUnit.scala │ │ │ ├── GridEnemyVision.scala │ │ │ ├── GridEnemyRangeAir.scala │ │ │ ├── GridEnemyRangeAirGround.scala │ │ │ ├── GridEnemyRangeGround.scala │ │ │ ├── GridFriendlyDetection.scala │ │ │ └── GridEnemyDetection.scala │ │ ├── Grid.scala │ │ ├── GridUpdateUnit.scala │ │ ├── Construction │ │ │ ├── GridPsi2Height.scala │ │ │ ├── GridPsi3Height.scala │ │ │ ├── GridBuildable.scala │ │ │ ├── GridBuildableTerrain.scala │ │ │ └── GridBuildableTownHall.scala │ │ ├── ArrayTypes │ │ │ ├── AbstractGridFramestamp.scala │ │ │ └── AbstractGridArrayBoolean.scala │ │ ├── Versioned │ │ │ ├── GridVersionedInt.scala │ │ │ ├── GridVersionedDouble.scala │ │ │ └── GridVersionedBoolean.scala │ │ ├── Movement │ │ │ ├── GridWalkable.scala │ │ │ ├── GridFlowField.scala │ │ │ ├── GridUnwalkableUnits.scala │ │ │ └── GridWalkableTerrain.scala │ │ └── Vision │ │ │ ├── GridScoutingPathsBases.scala │ │ │ ├── GridScoutingPathsStartLocations.scala │ │ │ └── GridLastSeen.scala │ ├── Battles │ │ ├── Prediction │ │ │ ├── Simulation │ │ │ │ ├── Occupancy.scala │ │ │ │ ├── BehaviorIdle.scala │ │ │ │ ├── BehaviorHeal.scala │ │ │ │ ├── BehaviorStorm.scala │ │ │ │ ├── SimulacrumBehavior.scala │ │ │ │ ├── BehaviorAssemble.scala │ │ │ │ ├── SimulationEventDeath.scala │ │ │ │ ├── BehaviorDetect.scala │ │ │ │ ├── BehaviorFlee.scala │ │ │ │ ├── SimulationEventBehavior.scala │ │ │ │ ├── BehaviorRepair.scala │ │ │ │ ├── SimulationEventSleep.scala │ │ │ │ ├── ReportCard.scala │ │ │ │ ├── SimulationEventMove.scala │ │ │ │ └── BehaviorGather.scala │ │ │ ├── Skimulation │ │ │ │ ├── SkimulationTeam.scala │ │ │ │ └── SkimulationUnit.scala │ │ │ └── CPCount.scala │ │ ├── Types │ │ │ ├── DivisionRadius.scala │ │ │ ├── EnemyTeam.scala │ │ │ ├── FriendlyTeam.scala │ │ │ ├── JudgmentModifier.scala │ │ │ └── GroupCentroid.scala │ │ └── ProcessingStates │ │ │ ├── BattleProcessInitial.scala │ │ │ ├── BattleProcessComplete.scala │ │ │ ├── BattleProcessCluster.scala │ │ │ ├── BattleProcessState.scala │ │ │ ├── BattleProcessJudge.scala │ │ │ └── BattleProcessMatchupAnalysis.scala │ ├── GameSense │ │ ├── Budgets.scala │ │ ├── GameSense.scala │ │ └── GameSenses.scala │ ├── Fingerprinting │ │ ├── TerranStrategies │ │ │ ├── TerranTimings.scala │ │ │ ├── Fingerprint1RaxGas.scala │ │ │ ├── Fingerprint2Fac.scala │ │ │ ├── Fingerprint3Fac.scala │ │ │ ├── FingerprintWallIn.scala │ │ │ ├── Fingerprint2FacVultures.scala │ │ │ ├── Fingerprint14CC.scala │ │ │ ├── FingerprintFD.scala │ │ │ ├── Fingerprint1BaseBioMech.scala │ │ │ ├── Fingerprint3FacVultures.scala │ │ │ ├── Fingerprint1RaxFE.scala │ │ │ └── Fingerprint2PortWraith.scala │ │ ├── Generic │ │ │ ├── FingerprintLambda.scala │ │ │ ├── FingerprintRace.scala │ │ │ ├── FingerprintNot.scala │ │ │ ├── FingerprintOr.scala │ │ │ ├── FingerprintAnd.scala │ │ │ ├── FingerprintTechBy.scala │ │ │ ├── FingerprintUpgradeBy.scala │ │ │ ├── FingerprintGasSteal.scala │ │ │ ├── FingerprintExistsBy.scala │ │ │ ├── FingerprintHasExpanded.scala │ │ │ └── FingerprintGasEmptyUntil.scala │ │ ├── ZergStrategies │ │ │ ├── Fingerprint9PoolGas.scala │ │ │ ├── Fingerprint10Hatch.scala │ │ │ ├── Fingerprint12HatchHatch.scala │ │ │ ├── Fingerprint12Pool11Gas.scala │ │ │ ├── FingerprintOverpoolGas.scala │ │ │ ├── Fingerprint3HatchSpeedling.scala │ │ │ ├── Fingerprint10Hatch9Pool8Gas.scala │ │ │ ├── Fingerprint1HatchGas.scala │ │ │ ├── Fingerprint12Hatch11Pool10Gas.scala │ │ │ ├── Fingerprint2HatchGas.scala │ │ │ ├── Fingerprint12Hatch11Pool.scala │ │ │ ├── Fingerprint2HatchMain.scala │ │ │ ├── Fingerprint3HatchHydra.scala │ │ │ ├── Fingerprint3HatchMuta.scala │ │ │ ├── Fingerprint9PoolHatch.scala │ │ │ ├── Fingerprint12Pool.scala │ │ │ ├── Fingerprint4Pool.scala │ │ │ └── Fingerprint3HatchGas.scala │ │ └── ProtossStrategies │ │ │ ├── FingerprintBunkerRush.scala │ │ │ ├── FingerprintCannonRush.scala │ │ │ ├── FingerprintCoreBeforeZealot.scala │ │ │ ├── FingerprintEarlyForge.scala │ │ │ ├── FingerprintNexusFirst.scala │ │ │ └── FingerprintGatewayFirst.scala │ ├── Counting │ │ └── MacroCounts.scala │ └── Scouting │ │ └── Scouting.scala ├── Lifecycle │ └── PurpleBWClient.scala ├── Performance │ ├── TaskQueue │ │ └── Task.scala │ ├── CacheForever.scala │ ├── GameCache.scala │ ├── Tasks │ │ ├── SimpleTask.scala │ │ ├── DummyTask.scala │ │ └── StateTasks.scala │ ├── Cache.scala │ └── Timer.scala ├── Placement │ ├── Walls │ │ ├── WallMetrics.scala │ │ ├── WallFillers.scala │ │ ├── WallConstraint.scala │ │ └── WallSpans.scala │ ├── Templating │ │ ├── PointGas.scala │ │ ├── PointNothing.scala │ │ ├── PointAnything.scala │ │ ├── PointWalkable.scala │ │ ├── RequireAnything.scala │ │ ├── RequireNothing.scala │ │ ├── RequireWalkable.scala │ │ └── RequireGas.scala │ ├── Generation │ │ ├── TileGenerator.scala │ │ ├── TemplatesGeneric.scala │ │ └── TileGeneratorProximity.scala │ ├── Access │ │ └── Foundation.scala │ ├── Architecture │ │ ├── BuildingPlacement.scala │ │ ├── Exclusion.scala │ │ ├── ArchitecturalAssessment.scala │ │ └── GridExclusion.scala │ └── FoundationSources.scala ├── Micro │ ├── Coordination │ │ ├── TargetMap.scala │ │ ├── Pushing │ │ │ ├── ExplosionNuke.scala │ │ │ ├── TrafficPriority.scala │ │ │ ├── ExplosionInfestedTerran.scala │ │ │ ├── ExplosionEMP.scala │ │ │ ├── ExplosionPsionicStorm.scala │ │ │ ├── ExplosionIrradiateSplash.scala │ │ │ ├── ExplosionLurkerNow.scala │ │ │ └── UnitLinearGroundPush.scala │ │ └── Coordinator.scala │ ├── Agency │ │ ├── BuildIntent.scala │ │ ├── LocalSimOverrides.scala │ │ └── LocalSim.scala │ ├── Formation │ │ ├── FormationSimple.scala │ │ ├── FormationEmpty.scala │ │ └── FormationZone.scala │ ├── Actions │ │ ├── ActionPerformance.scala │ │ ├── Combat │ │ │ ├── Tactics │ │ │ │ ├── FewShot.scala │ │ │ │ └── Potshot.scala │ │ │ └── Spells │ │ │ │ └── WraithUncloak.scala │ │ ├── Basic │ │ │ ├── DoNothing.scala │ │ │ ├── Addon.scala │ │ │ ├── Unstick.scala │ │ │ └── Bunk.scala │ │ ├── Commands │ │ │ ├── Attack.scala │ │ │ └── Travel.scala │ │ ├── Terran │ │ │ ├── Liftoff.scala │ │ │ ├── FinishConstruction.scala │ │ │ ├── Scan.scala │ │ │ └── GetRepairedBuilding.scala │ │ ├── Scouting │ │ │ ├── DroneWarfare.scala │ │ │ ├── Scout.scala │ │ │ └── PreserveScout.scala │ │ └── Protoss │ │ │ └── Shuttle │ │ │ └── Shuttling.scala │ ├── Targeting │ │ ├── TargetFilter.scala │ │ ├── FiltersRequired │ │ │ ├── TargetFilterEnemy.scala │ │ │ ├── TargetFilterMissing.scala │ │ │ ├── TargetFilterCanAttack.scala │ │ │ ├── TargetFilterType.scala │ │ │ ├── TargetFilterExposed.scala │ │ │ ├── TargetFilterScourge.scala │ │ │ └── TargetFilterVulture.scala │ │ └── FiltersSituational │ │ │ ├── TargetFilterVisibleInRange.scala │ │ │ ├── TargetFilterWhitelist.scala │ │ │ ├── TargetFilterPotshot.scala │ │ │ └── TargetFilterCombatants.scala │ └── Heuristics │ │ └── SpellTargets.scala ├── Strategery │ ├── History │ │ └── ContextualHistory.scala │ ├── Strategies │ │ ├── AllRaces │ │ │ └── Sandbox.scala │ │ ├── AllChoices.scala │ │ └── Protoss │ │ │ ├── PvRStrategies.scala │ │ │ └── ProtossFPM.scala │ ├── Selection │ │ ├── StrategySelectionPolicy.scala │ │ ├── WeightedGame.scala │ │ ├── StrategySelectionFixed.scala │ │ ├── StrategySelectionRandom.scala │ │ └── StrategySelectionDynamic.scala │ └── Rolling.scala └── Tactic │ ├── Squads │ ├── FriendlyUnitGroup.scala │ ├── Qualities │ │ └── Quality.scala │ ├── GenericUnitGroup.scala │ └── GenericFriendlyUnitGroup.scala │ ├── GetDefenseBase.scala │ └── Tactics │ ├── TacticFloatBuildings.scala │ ├── TacticGather.scala │ ├── Tactic.scala │ └── TacticMeldDarchons.scala ├── 3rdparty └── apache │ ├── jna-5.1.0.jar │ ├── jna-platform-5.1.0.jar │ ├── commons-lang3-3.8.1.jar │ ├── commons-lang3-3.8.1-javadoc.jar │ └── commons-lang3-3.8.1-sources.jar ├── PurpleWave.bat ├── .idea ├── modules.xml ├── encodings.xml ├── codeStyleSettings.xml └── vcs.xml ├── .gitignore ├── PurpleWaveWithJMX.bat ├── .gitmodules └── scripts └── performance.sh /META-INF/native-image/native-image.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: Lifecycle.Main 3 | 4 | -------------------------------------------------------------------------------- /configs/BWAPI.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/configs/BWAPI.dll -------------------------------------------------------------------------------- /install/instructions1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/install/instructions1.png -------------------------------------------------------------------------------- /install/instructions2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/install/instructions2.png -------------------------------------------------------------------------------- /install/instructions3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/install/instructions3.png -------------------------------------------------------------------------------- /install/instructions4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/install/instructions4.png -------------------------------------------------------------------------------- /install/instructions5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/install/instructions5.png -------------------------------------------------------------------------------- /src/Macro/Facts/MacroFacts.scala: -------------------------------------------------------------------------------- 1 | package Macro.Facts 2 | 3 | object MacroFacts extends MacroCounting 4 | -------------------------------------------------------------------------------- /3rdparty/apache/jna-5.1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/3rdparty/apache/jna-5.1.0.jar -------------------------------------------------------------------------------- /PurpleWave.bat: -------------------------------------------------------------------------------- 1 | "C:\Program Files (x86)\Java\jre1.8.0_121\bin\java.exe" -jar ./out/artifacts/PurpleWave.jar 2 | -------------------------------------------------------------------------------- /src/Gameplans/Zerg/ZvZ/ZergVsZerg.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Zerg.ZvZ 2 | 3 | class ZergVsZerg extends ZvZ10Hatch -------------------------------------------------------------------------------- /src/Planning/Plans/NoPlan.scala: -------------------------------------------------------------------------------- 1 | package Planning.Plans 2 | 3 | object NoPlan { def apply(): Plan = new Plan } 4 | -------------------------------------------------------------------------------- /src/Utilities/Time/Frames.scala: -------------------------------------------------------------------------------- 1 | package Utilities.Time 2 | 3 | case class Frames(f: Int) extends FrameCount(f) 4 | -------------------------------------------------------------------------------- /src/Gameplans/Terran/TvP/TerranVsProtoss.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Terran.TvP 2 | 3 | class TerranVsProtoss extends TvP2Fac -------------------------------------------------------------------------------- /src/Gameplans/Terran/TvT/TerranVsTerran.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Terran.TvT 2 | 3 | class TerranVsTerran extends TvT1Port -------------------------------------------------------------------------------- /src/Gameplans/Terran/TvZ/TerranVsZerg.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Terran.TvZ 2 | 3 | class TerranVsZerg extends TvZ8RaxSK -------------------------------------------------------------------------------- /src/Gameplans/Zerg/ZvP/ZergVsProtoss.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Zerg.ZvP 2 | 3 | class ZergVsProtoss extends ZvPHydraLurker -------------------------------------------------------------------------------- /src/Gameplans/Zerg/ZvT/ZergVsTerran.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Zerg.ZvT 2 | 3 | class ZergVsTerran extends ZvTEffortBust -------------------------------------------------------------------------------- /src/Utilities/UnitCounters/CountOne.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitCounters 2 | 3 | object CountOne extends CountUpTo(1) -------------------------------------------------------------------------------- /3rdparty/apache/jna-platform-5.1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/3rdparty/apache/jna-platform-5.1.0.jar -------------------------------------------------------------------------------- /src/Utilities/LightYear.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | object LightYear { 4 | def apply(): Int = 256 * 256 5 | } 6 | -------------------------------------------------------------------------------- /src/Utilities/Time/Seconds.scala: -------------------------------------------------------------------------------- 1 | package Utilities.Time 2 | 3 | case class Seconds(s: Int) extends FrameCount(s * 24) 4 | -------------------------------------------------------------------------------- /3rdparty/apache/commons-lang3-3.8.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/3rdparty/apache/commons-lang3-3.8.1.jar -------------------------------------------------------------------------------- /src/Utilities/Time/Hours.scala: -------------------------------------------------------------------------------- 1 | package Utilities.Time 2 | 3 | case class Hours(h: Int) extends FrameCount(h * 60 * 60 * 24) 4 | -------------------------------------------------------------------------------- /src/Utilities/Time/Minutes.scala: -------------------------------------------------------------------------------- 1 | package Utilities.Time 2 | 3 | case class Minutes(m: Int) extends FrameCount(m * 60 * 24) 4 | -------------------------------------------------------------------------------- /src/Utilities/UnitCounters/CountEverything.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitCounters 2 | 3 | object CountEverything extends CountUpTo(10000) -------------------------------------------------------------------------------- /src/Utilities/UnitCounters/CountUpTo.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitCounters 2 | 3 | case class CountUpTo(maximum: Int) extends UnitCounter -------------------------------------------------------------------------------- /src/ProxyBwapi/Techs/None.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.Techs 2 | 3 | import bwapi.TechType 4 | 5 | object None extends Tech(TechType.None) -------------------------------------------------------------------------------- /src/Utilities/Time/GameTime.scala: -------------------------------------------------------------------------------- 1 | package Utilities.Time 2 | 3 | case class GameTime(m: Int, s: Int) extends FrameCount(24 * (60 * m + s)) -------------------------------------------------------------------------------- /3rdparty/apache/commons-lang3-3.8.1-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/3rdparty/apache/commons-lang3-3.8.1-javadoc.jar -------------------------------------------------------------------------------- /3rdparty/apache/commons-lang3-3.8.1-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dgant/PurpleWave/HEAD/3rdparty/apache/commons-lang3-3.8.1-sources.jar -------------------------------------------------------------------------------- /src/Debugging/SimpleString.scala: -------------------------------------------------------------------------------- 1 | package Debugging 2 | 3 | trait SimpleString { 4 | override def toString: String = ToString(this) 5 | } 6 | -------------------------------------------------------------------------------- /src/Gameplans/All/Modal.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.All 2 | 3 | trait Modal { 4 | def isComplete: Boolean 5 | def update(): Unit 6 | } 7 | -------------------------------------------------------------------------------- /src/Mathematics/Physics/Forces.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Physics 2 | 3 | object Forces { 4 | val None: Force = Force(0.0, 0.0) 5 | } 6 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsFlyingBuilding.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | object IsFlyingBuilding extends IsAll(IsBuilding, _.flying) -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsFlyingWarrior.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | object IsFlyingWarrior extends IsAll(IsWarrior, _.flying) -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsGroundWarrior.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | object IsGroundWarrior extends IsAll(IsWarrior, ! _.flying) 4 | -------------------------------------------------------------------------------- /src/Debugging/Asciify.scala: -------------------------------------------------------------------------------- 1 | package Debugging 2 | 3 | object Asciify { 4 | def apply(v: String): String = v.replaceAll("[^\\x00-\\x7F]", "") 5 | } 6 | -------------------------------------------------------------------------------- /src/Information/Geography/Pathfinding/Types/TileState.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Pathfinding.Types 2 | 3 | class TileState { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/Information/Grids/Floody/FloodyUnitDepth.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | case class FloodyUnitDepth(unit: FloodyUnit, value: Int) 4 | -------------------------------------------------------------------------------- /src/Gameplans/Zerg/ZvR/ZergVsRandom.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Zerg.ZvR 2 | 3 | import Gameplans.Zerg.ZvE.ZvE4Pool 4 | 5 | class ZergVsRandom extends ZvE4Pool -------------------------------------------------------------------------------- /src/Lifecycle/PurpleBWClient.scala: -------------------------------------------------------------------------------- 1 | package Lifecycle 2 | 3 | import bwapi.BWClient 4 | 5 | object PurpleBWClient extends BWClient(PurpleEventListener) 6 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsMechWarrior.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | object IsMechWarrior extends IsAll(IsWarrior, _.unitClass.isMechanical) 4 | -------------------------------------------------------------------------------- /src/Utilities/In.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | object In { 4 | @inline final def apply[T](element: T, among: T*): Boolean = among.contains(element) 5 | } 6 | -------------------------------------------------------------------------------- /configs/run32.bat: -------------------------------------------------------------------------------- 1 | echo "Running with default JRE (Presumably 32-bit Java 8)." 2 | java.exe -jar -XX:MaxGCPauseMillis=15 -Xms768m -Xmx768m ./bwapi-data/AI/PurpleWave.jar 3 | -------------------------------------------------------------------------------- /src/Performance/TaskQueue/Task.scala: -------------------------------------------------------------------------------- 1 | package Performance.TaskQueue 2 | 3 | trait Task { 4 | def canRun: Boolean 5 | def run(): Unit 6 | def skip(): Unit 7 | } 8 | -------------------------------------------------------------------------------- /src/Placement/Walls/WallMetrics.scala: -------------------------------------------------------------------------------- 1 | package Placement.Walls 2 | 3 | class WallMetrics { 4 | var permutations = 0 5 | var tilesConsidered = 0 6 | } 7 | -------------------------------------------------------------------------------- /src/Utilities/Time/Forever.scala: -------------------------------------------------------------------------------- 1 | package Utilities.Time 2 | 3 | object Forever extends Frames(345678) // Almost exactly 4 hours, but also a recognizable sentinel value 4 | -------------------------------------------------------------------------------- /src/Debugging/Decimal.scala: -------------------------------------------------------------------------------- 1 | package Debugging 2 | 3 | object Decimal { 4 | def apply(value: Double, decimals: Int = 2): String = s"%1.${decimals}f".format(value) 5 | } 6 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/Occupancy.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object Occupancy { 4 | val Resolution = 12 5 | } 6 | -------------------------------------------------------------------------------- /src/Information/Geography/Pathfinding/Paths.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Pathfinding 2 | 3 | final class Paths extends TilePathfinder with ZonePathfinder with GroundDistance -------------------------------------------------------------------------------- /src/Micro/Coordination/TargetMap.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination 2 | 3 | class TargetMap { 4 | val targets: Array[Array[Double]] = Array.ofDim[Double](10000, 10000) 5 | } 6 | -------------------------------------------------------------------------------- /src/Placement/Templating/PointGas.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | import Mathematics.Points.Point 4 | 5 | class PointGas extends TemplatePoint(Point(0, 0), new RequireGas) -------------------------------------------------------------------------------- /src/Utilities/UnitCounters/CountBetween.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitCounters 2 | 3 | case class CountBetween(override val minimum: Int, override val maximum: Int) extends UnitCounter -------------------------------------------------------------------------------- /src/Gameplans/Protoss/FFA/ProtossFFAMoney.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Protoss.FFA 2 | 3 | class ProtossFFAMoney extends ProtossFFA { 4 | override val expandEver: Boolean = false 5 | } 6 | -------------------------------------------------------------------------------- /src/Macro/Requests/RequestTech.scala: -------------------------------------------------------------------------------- 1 | package Macro.Requests 2 | 3 | import ProxyBwapi.Techs.Tech 4 | 5 | case class RequestTech(techType: Tech) extends RequestBuildable(techType, 1) 6 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoEdge.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | /** 4 | * Describes a boundary between two Regions. 5 | */ 6 | class NeoEdge { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/Information/Grids/Grid.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids 2 | 3 | trait Grid { 4 | def update(): Unit = {} 5 | var code: String = "uncoded" 6 | def reprAt(i: Int): String 7 | } 8 | -------------------------------------------------------------------------------- /src/Performance/CacheForever.scala: -------------------------------------------------------------------------------- 1 | package Performance 2 | 3 | import Utilities.Time.Forever 4 | 5 | class CacheForever[T](recalculator: () => T) extends Cache[T](recalculator, Forever()) 6 | -------------------------------------------------------------------------------- /src/Utilities/SomeIf.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | object SomeIf { 4 | @inline final def apply[T](predicate: Boolean, value: => T): Option[T] = ?(predicate, Some(value), None) 5 | } 6 | -------------------------------------------------------------------------------- /src/Debugging/English.scala: -------------------------------------------------------------------------------- 1 | package Debugging 2 | 3 | object English { 4 | def pluralize(word: String, count: Int): String = { 5 | if (count == 1) word else word + "s" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Information/Battles/Types/DivisionRadius.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Types 2 | 3 | object DivisionRadius { 4 | val inner: Int = 32 * 32 5 | val outer: Int = 32 * 20 + inner 6 | } 7 | -------------------------------------------------------------------------------- /src/Performance/GameCache.scala: -------------------------------------------------------------------------------- 1 | package Performance 2 | 3 | import Lifecycle.With 4 | 5 | class GameCache[TValue](getValue: () => TValue) extends KeyedCache[TValue, Long](getValue, () => With.id) -------------------------------------------------------------------------------- /src/Placement/Templating/PointNothing.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | import Mathematics.Points.Point 4 | 5 | class PointNothing extends TemplatePoint(Point(0, 0), new RequireNothing) 6 | -------------------------------------------------------------------------------- /src/ProxyBwapi/Size.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi 2 | 3 | object Size { 4 | trait Type 5 | object Small extends Type 6 | object Medium extends Type 7 | object Large extends Type 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/SomeIfO.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | object SomeIfO { 4 | @inline final def apply[T](predicate: Boolean, value: => Option[T]): Option[T] = ?(predicate, value, None) 5 | } 6 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Rendering/TextWidth.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Rendering 2 | 3 | object TextWidth { 4 | def apply(s: String): Int = { 5 | 9 * s.length 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoMetro.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | /** 4 | * A Metro is a collection of one or more closely- 5 | */ 6 | class NeoMetro { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/Information/Grids/GridUpdateUnit.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | trait GridUpdateUnit { 6 | def updateUnit(unit: UnitInfo): Unit 7 | } 8 | -------------------------------------------------------------------------------- /src/Placement/Templating/PointAnything.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | import Mathematics.Points.Point 4 | 5 | class PointAnything extends TemplatePoint(Point(0, 0), new RequireAnything) 6 | -------------------------------------------------------------------------------- /src/Placement/Templating/PointWalkable.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | import Mathematics.Points.Point 4 | 5 | class PointWalkable extends TemplatePoint(Point(0, 0), new RequireWalkable) 6 | -------------------------------------------------------------------------------- /src/Utilities/AsJava.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | import scala.collection.JavaConverters._ 4 | 5 | object AsJava { 6 | def apply[T](x: Iterable[T]): java.lang.Iterable[T] = x.asJava 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/AsScala.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | import scala.collection.JavaConverters._ 4 | 5 | object AsScala { 6 | def apply[T](x: java.lang.Iterable[T]): Iterable[T] = x.asScala 7 | } 8 | -------------------------------------------------------------------------------- /src/Gameplans/Protoss/PvR/ProtossVsRandom.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Protoss.PvR 2 | 3 | import Gameplans.All.ModalGameplan 4 | 5 | class ProtossVsRandom extends ModalGameplan( 6 | new PvR2Gate4Gate 7 | ) -------------------------------------------------------------------------------- /src/Mathematics/Shapes/Square.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Shapes 2 | 3 | import Mathematics.Points.Point 4 | 5 | object Square { 6 | def apply(width: Int): IndexedSeq[Point] = Rectangle(width, width) 7 | } 8 | -------------------------------------------------------------------------------- /src/Placement/Generation/TileGenerator.scala: -------------------------------------------------------------------------------- 1 | package Placement.Generation 2 | 3 | import Mathematics.Points.Tile 4 | 5 | trait TileGenerator { 6 | def next(): Tile 7 | def hasNext: Boolean 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitCounters/CountExactly.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitCounters 2 | 3 | case class CountExactly(override val minimum: Int) extends UnitCounter { 4 | override val maximum: Int = minimum 5 | } -------------------------------------------------------------------------------- /configs/run64.bat: -------------------------------------------------------------------------------- 1 | echo "Running with bundled JRE." 2 | ./bwapi-data/AI/jre/bin/java.exe -jar -XX:MaxGCPauseMillis=15 -Xms1536m -Xmx2048m --add-opens=java.base/java.nio=ALL-UNNAMED ./bwapi-data/AI/PurpleWave.jar 3 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Micro/ShowUnitPaths.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Micro 2 | 3 | import Debugging.Visualizations.Views.DebugView 4 | 5 | object ShowUnitPaths extends DebugView 6 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/UnitPreference.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | 5 | trait UnitPreference extends Function[FriendlyUnitInfo, Double] 6 | -------------------------------------------------------------------------------- /src/Macro/Requests/RequestUpgrade.scala: -------------------------------------------------------------------------------- 1 | package Macro.Requests 2 | 3 | import ProxyBwapi.Upgrades.Upgrade 4 | 5 | case class RequestUpgrade(upgradeType: Upgrade, level: Int = 1) extends RequestBuildable(upgradeType, level) -------------------------------------------------------------------------------- /src/Placement/Access/Foundation.scala: -------------------------------------------------------------------------------- 1 | package Placement.Access 2 | 3 | import Mathematics.Points.Tile 4 | import Placement.Templating.TemplatePoint 5 | 6 | case class Foundation(tile: Tile, point: TemplatePoint, order: Int = 0) -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsAnything.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import ProxyBwapi.UnitInfo.UnitInfo 3 | 4 | object IsAnything extends UnitFilter { 5 | override def apply(unit: UnitInfo): Boolean = true 6 | } 7 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoRegion.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | /** 4 | * A Region is an open piece of walkable territory. 5 | */ 6 | class NeoRegion { 7 | var isChoke: Boolean = _ 8 | } 9 | -------------------------------------------------------------------------------- /src/Information/Grids/Floody/FloodyUnit.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | import Mathematics.Points.Tile 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | case class FloodyUnit(unit: UnitInfo, radius: Int, tile: Tile) -------------------------------------------------------------------------------- /src/Micro/Agency/BuildIntent.scala: -------------------------------------------------------------------------------- 1 | package Micro.Agency 2 | 3 | import Mathematics.Points.Tile 4 | import ProxyBwapi.UnitClasses.UnitClass 5 | 6 | case class BuildIntent(unitClass: UnitClass, tile: Tile, startNow: Boolean = true) -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/ExplosionNuke.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import Mathematics.Points.Pixel 4 | 5 | class ExplosionNuke(pixel: Pixel) extends CircularPush(TrafficPriorities.Dive, pixel, 256) 6 | -------------------------------------------------------------------------------- /src/Placement/Architecture/BuildingPlacement.scala: -------------------------------------------------------------------------------- 1 | package Placement.Architecture 2 | 3 | import Mathematics.Points.Tile 4 | import ProxyBwapi.UnitClasses.UnitClass 5 | 6 | case class BuildingPlacement(tile: Tile, unit: UnitClass) -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsBioWarrior.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.Terran 4 | 5 | object IsBioWarrior extends IsAll(IsAny(Terran.Marine, Terran.Firebat), _.aliveAndComplete, _.canMove) 6 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/ForceLabel.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations 2 | 3 | import bwapi.Color 4 | 5 | case class ForceLabel(name: String, color: Color) { 6 | override def toString: String = "Force: " + name 7 | } 8 | -------------------------------------------------------------------------------- /src/Macro/Requests/RequestAutosupply.scala: -------------------------------------------------------------------------------- 1 | package Macro.Requests 2 | 3 | import ProxyBwapi.Races.Neutral 4 | 5 | object RequestAutosupply extends RequestBuildable(Neutral.Autosupply) { 6 | override val toString = "Autosupply" 7 | } -------------------------------------------------------------------------------- /src/Micro/Agency/LocalSimOverrides.scala: -------------------------------------------------------------------------------- 1 | package Micro.Agency 2 | 3 | trait LocalSimOverrides { 4 | 5 | 6 | 7 | private def add(outcome: Boolean, name: String, test: () => Boolean): Unit = { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Strategery/History/ContextualHistory.scala: -------------------------------------------------------------------------------- 1 | package Strategery.History 2 | 3 | import Utilities.CountMap 4 | 5 | case class ContextualHistory( 6 | winsByStrategy : CountMap[String], 7 | lossesByStrategy : CountMap[String]) 8 | -------------------------------------------------------------------------------- /src/Utilities/Ternary.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | //noinspection ScalaFileName 4 | object ? { 5 | @inline final def apply[T](predicate: Boolean, yes: => T, no: => T): T = { 6 | if (predicate) yes else no 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsEnemy.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsEnemy extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.isEnemy 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsProxied.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsProxied extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.proxied 7 | } -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/UnitFilter.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import Debugging.SimpleString 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | trait UnitFilter extends Function[UnitInfo, Boolean] with SimpleString 7 | -------------------------------------------------------------------------------- /src/Gameplans/Protoss/PvZ/ProtossVsZerg.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Protoss.PvZ 2 | 3 | import Gameplans.All.ModalGameplan 4 | 5 | class ProtossVsZerg extends ModalGameplan( 6 | new PvZFE, 7 | new PvZ1BaseReactive, 8 | new PvZ2022 9 | ) -------------------------------------------------------------------------------- /src/Information/Geography/Pathfinding/PathfindRepulsor.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Pathfinding 2 | 3 | import Mathematics.Points.Pixel 4 | 5 | final case class PathfindRepulsor(source: Pixel, magnitude: Double, rangePixels: Double) -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsTank.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsTank extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isTank 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsVisible.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsVisible extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.visible 7 | } 8 | -------------------------------------------------------------------------------- /src/Information/Geography/Pathfinding/Types/NoPath.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Pathfinding.Types 2 | 3 | import Mathematics.Points.Tile 4 | 5 | object NoPath { 6 | val value = TilePath(Tile(0, 0), Tile(0, 0), 0, None) 7 | } 8 | 9 | -------------------------------------------------------------------------------- /src/Placement/Architecture/Exclusion.scala: -------------------------------------------------------------------------------- 1 | package Placement.Architecture 2 | 3 | import Mathematics.Points.TileRectangle 4 | 5 | case class Exclusion(description: String, areaExcluded: TileRectangle, request: Option[BuildingPlacement] = None) 6 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsBuilding.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import ProxyBwapi.UnitInfo.UnitInfo 3 | 4 | object IsBuilding extends UnitFilter { 5 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isBuilding 6 | } 7 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsComplete.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsComplete extends UnitFilter { 6 | 7 | override def apply(unit: UnitInfo): Boolean = unit.complete 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsTownHall.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import ProxyBwapi.UnitInfo.UnitInfo 3 | 4 | object IsTownHall extends UnitFilter { 5 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isTownHall 6 | } 7 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsWorker.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsWorker extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isWorker 7 | } 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Gameplans/Protoss/PvP/ProtossVsProtoss.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Protoss.PvP 2 | 3 | import Gameplans.All.ModalGameplan 4 | 5 | class ProtossVsProtoss extends ModalGameplan( 6 | new PvPNexusFirst, 7 | new PvPOpening, 8 | new PvPLateGame, 9 | ) -------------------------------------------------------------------------------- /src/Gameplans/Protoss/PvT/ProtossVsTerran.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Protoss.PvT 2 | 3 | import Gameplans.All.ModalGameplan 4 | 5 | class ProtossVsTerran extends ModalGameplan( 6 | new PvTFastCarrier, 7 | new PvTArbiter, 8 | new PvTDoubleRobo 9 | ) -------------------------------------------------------------------------------- /src/Tactic/Squads/FriendlyUnitGroup.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Squads 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | trait FriendlyUnitGroup extends UnitGroup with TFriendlyUnitGroup { 6 | def groupUnits: Seq[UnitInfo] = groupFriendlyUnits 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsDetector.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsDetector extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isDetector 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsHatchlike.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsHatchlike extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isHatchlike 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsLairlike.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsLairlike extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isLairlike 7 | } 8 | -------------------------------------------------------------------------------- /src/Macro/Scheduling/ScheduleItem.scala: -------------------------------------------------------------------------------- 1 | package Macro.Scheduling 2 | 3 | import Macro.Requests.RequestBuildable 4 | 5 | case class ScheduleItem(requester: Any, request: RequestBuildable) { 6 | override def toString = f"$request -- for $requester" 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsAntiAir.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsAntiAir extends UnitFilter { 6 | 7 | override def apply(unit: UnitInfo): Boolean = unit.damageOnHitAir > 0 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferAnything.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 3 | 4 | object PreferAnything extends UnitPreference { 5 | override def apply(unit: FriendlyUnitInfo): Double = 0 6 | } 7 | -------------------------------------------------------------------------------- /src/Tactic/Squads/Qualities/Quality.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Squads.Qualities 2 | 3 | import Utilities.UnitFilters.UnitFilter 4 | 5 | trait Quality extends UnitFilter { 6 | val counteredBy: Array[Quality] = Array.empty 7 | def counterScaling: Double = 1.0 8 | } -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/Is.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | case class Is(predicate: UnitInfo => Boolean) extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = predicate(unit) 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsAntiGround.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsAntiGround extends UnitFilter { 6 | 7 | override def apply(unit: UnitInfo): Boolean = unit.damageOnHitGround > 0 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/SwapIf.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | object SwapIf { 4 | def apply[T](predicate: Boolean, a: => T, b: => T): T = { 5 | if (predicate) { 6 | b 7 | a 8 | } else { 9 | a 10 | b 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorIdle.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object BehaviorIdle extends SimulacrumBehavior { 4 | val fighting: Boolean = false 5 | override def act(simulacrum: Simulacrum): Unit = {} 6 | } 7 | -------------------------------------------------------------------------------- /src/Information/GameSense/Budgets.scala: -------------------------------------------------------------------------------- 1 | package Information.GameSense 2 | 3 | object Budgets extends Enumeration { 4 | val 5 | Worker, 6 | Base, 7 | Supply, 8 | Production, 9 | Science, 10 | Defense, 11 | War = Value 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoPixel.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | import bwapi.Position 4 | 5 | case class NeoPixel(x: Int, y: Int) { 6 | def this(position: Position) { 7 | this(position.getX, position.getY) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Micro/Formation/FormationSimple.scala: -------------------------------------------------------------------------------- 1 | package Micro.Formation 2 | 3 | import Mathematics.Points.Pixel 4 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 5 | 6 | case class FormationSimple(style: FormationStyle, placements: Map[FriendlyUnitInfo, Pixel]) extends Formation 7 | -------------------------------------------------------------------------------- /src/Placement/FoundationSources.scala: -------------------------------------------------------------------------------- 1 | package Placement 2 | 3 | object FoundationSources { 4 | trait FoundationSource 5 | object Default extends FoundationSource 6 | object TownHall extends FoundationSource 7 | object Gas extends FoundationSource 8 | } 9 | -------------------------------------------------------------------------------- /src/Tactic/Squads/GenericUnitGroup.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Squads 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | case class GenericUnitGroup(override val groupUnits: Seq[UnitInfo]) extends UnitGroup { 6 | def this(unit: UnitInfo) { 7 | this(Seq(unit)) 8 | } 9 | } -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsWarrior.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsWarrior extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.aliveAndComplete && unit.unitClass.isWarrior 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferLowEnergy.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | 5 | object PreferLowEnergy extends UnitPreference { 6 | override def apply(unit: FriendlyUnitInfo): Double = unit.energy 7 | } 8 | -------------------------------------------------------------------------------- /src/Information/Battles/ProcessingStates/BattleProcessInitial.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.ProcessingStates 2 | 3 | class BattleProcessInitial extends BattleProcessState { 4 | override def step(): Unit = { 5 | transitionTo(new BattleProcessCluster) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Information/Geography/Pathfinding/Types/ZonePathNode.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Pathfinding.Types 2 | 3 | import Information.Geography.Types.{Edge, Zone} 4 | 5 | case class ZonePathNode(from: Zone, edge: Edge) { 6 | def to: Zone = edge.otherSideof(from) 7 | } 8 | -------------------------------------------------------------------------------- /src/Micro/Actions/ActionPerformance.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions 2 | 3 | class ActionPerformance { 4 | var invocations: Int = 0 5 | var durationNanos: Long = 0 6 | def totalMs: Double = durationNanos / 1e6 7 | def meanMs: Double = totalMs / invocations.toDouble 8 | } 9 | -------------------------------------------------------------------------------- /src/Tactic/GetDefenseBase.scala: -------------------------------------------------------------------------------- 1 | package Tactic 2 | 3 | import Information.Geography.Types.Base 4 | 5 | object GetDefenseBase { 6 | def apply(base: Base): Base = { 7 | base.natural.filter(b => b.isOurs || b.plannedExpoRecently).getOrElse(base) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsAny.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | case class IsAny(matches: UnitFilter*) extends UnitFilter { 6 | @inline final override def apply(unit: UnitInfo): Boolean = matches.exists(_(unit)) 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsMobileDetector.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsMobileDetector extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isDetector && unit.canMove 7 | } 8 | -------------------------------------------------------------------------------- /src/Information/Battles/Types/EnemyTeam.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Types 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | import Tactic.Squads.UnitGroup 5 | 6 | class EnemyTeam(battle: Battle, units: Seq[UnitInfo]) extends Team(battle, units) with UnitGroup { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsLandedBuilding.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsLandedBuilding extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.unitClass.isBuilding && ! unit.flying 7 | } 8 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoTile.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | import bwapi.TilePosition 4 | 5 | case class NeoTile(x: Int, y: Int) { 6 | def this(tilePosition: TilePosition) { 7 | this(tilePosition.getX, tilePosition.getY) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoWalk.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | import bwapi.WalkPosition 4 | 5 | case class NeoWalk(x: Int, y: Int) { 6 | def this(walkPosition: WalkPosition) { 7 | this(walkPosition.getX, walkPosition.getY) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Grids/Construction/GridPsi2Height.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Construction 2 | 3 | import Mathematics.Points.Point 4 | import Mathematics.Shapes.Pylons 5 | 6 | class GridPsi2Height extends AbstractGridPsi { 7 | override val psiPoints: Array[Point] = Pylons.points2 8 | } 9 | -------------------------------------------------------------------------------- /src/Information/Grids/Construction/GridPsi3Height.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Construction 2 | 3 | import Mathematics.Points.Point 4 | import Mathematics.Shapes.Pylons 5 | 6 | class GridPsi3Height extends AbstractGridPsi { 7 | override val psiPoints: Array[Point] = Pylons.points3 8 | } 9 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Placement/Walls/WallFillers.scala: -------------------------------------------------------------------------------- 1 | package Placement.Walls 2 | 3 | import Debugging.SimpleString 4 | 5 | object WallFillers { 6 | trait WallFiller extends SimpleString 7 | object NoFiller extends WallFiller 8 | object PylonsCannons extends WallFiller 9 | } 10 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Hues.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations 2 | 3 | object Hues { 4 | val Red = 0 5 | val Orange = 24 6 | val Yellow = 64 7 | val Green = 96 8 | val Teal = 128 9 | val Blue = 160 10 | val Indigo = 192 11 | val Violet = 224 12 | } 13 | -------------------------------------------------------------------------------- /src/Micro/Targeting/TargetFilter.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting 2 | 3 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 4 | 5 | trait TargetFilter { 6 | def appliesTo(actor: FriendlyUnitInfo): Boolean = true 7 | def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache-main 2 | *.log.txt 3 | *.log 4 | *.class 5 | *.zip 6 | .idea/workspace.xml 7 | .idea/codeStyles 8 | .idea/hydra.xml 9 | .idea/libraries/scala_sdk_2_12_6.xml 10 | .idea/scala_settings.xml 11 | .gradle/ 12 | /out/ 13 | /target/ 14 | /images/ 15 | dependency-reduced-pom.xml -------------------------------------------------------------------------------- /src/ProxyBwapi/Players/Players.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.Players 2 | 3 | import Lifecycle.With 4 | import bwapi.Player 5 | 6 | object Players { 7 | def all: Iterable[PlayerInfo] = With.proxy.players 8 | def get(player: Player): PlayerInfo = With.proxy.playersById(player.getID) 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Grids/ArrayTypes/AbstractGridFramestamp.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.ArrayTypes 2 | 3 | import Lifecycle.With 4 | 5 | abstract class AbstractGridFramestamp extends AbstractGridVersioned { 6 | override def updateVersion() { version = With.frame } 7 | def frameUpdated: Int = version 8 | } -------------------------------------------------------------------------------- /src/ProxyBwapi/UnitTracking/Visibility.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.UnitTracking 2 | 3 | object Visibility extends Enumeration { 4 | val 5 | Visible, 6 | InvisibleBurrowed, 7 | InvisibleNearby, 8 | InvisibleMissing, 9 | Hypothetical, 10 | Dead 11 | = Value 12 | } 13 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsAll.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import ProxyBwapi.UnitInfo.UnitInfo 3 | 4 | case class IsAll(matchers: UnitFilter*) extends UnitFilter { 5 | 6 | override def apply(unit: UnitInfo): Boolean = { 7 | matchers.forall(_(unit)) 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsBurrowedLurker.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.Zerg 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | object IsBurrowedLurker extends UnitFilter { 7 | override def apply(unit: UnitInfo): Boolean = unit.burrowed && Zerg.Lurker(unit) 8 | } 9 | -------------------------------------------------------------------------------- /src/Performance/Tasks/SimpleTask.scala: -------------------------------------------------------------------------------- 1 | package Performance.Tasks 2 | 3 | class SimpleTask(lambda: () => Unit) extends TimedTask { 4 | def this(name: String, lambda: () => Unit) { 5 | this(lambda) 6 | withName(name) 7 | } 8 | override def onRun(budgetMs: Long): Unit = lambda() 9 | } 10 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsSpeedling.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import ProxyBwapi.Races.Zerg 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsSpeedling extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = Zerg.Zergling(unit) && Zerg.ZerglingSpeed(unit.player) 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsSpeedlot.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import ProxyBwapi.Races.Protoss 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsSpeedlot extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = Protoss.Zealot(unit) && Protoss.ZealotSpeed(unit.player) 7 | } 8 | -------------------------------------------------------------------------------- /src/Debugging/ToString.scala: -------------------------------------------------------------------------------- 1 | package Debugging 2 | 3 | object ToString { 4 | def apply(value: Object): String = { 5 | var name = value.getClass.getSimpleName 6 | if (name.contains("anon")) name = value.getClass.getSuperclass.getSimpleName 7 | name.replaceAllLiterally("$", "") 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoContinent.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | /** 4 | * A Continent is a fully-walkable area. 5 | * Every tile adjacent to a Continent is unwalkable or off the map entirely. 6 | */ 7 | abstract class NeoContinent { 8 | def walkable: Seq[Int] 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoCountry.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | /** 4 | * A map contains one Country for each start location. 5 | * A Country comprises the Metros and Regions associated most closely with that start location. 6 | */ 7 | class NeoCountry { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsSlowling.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.Zerg 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | object IsSlowling extends UnitFilter { 7 | override def apply(unit: UnitInfo): Boolean = Zerg.Zergling(unit) && ! Zerg.ZerglingSpeed(unit.player) 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsSlowlot.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.Protoss 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | object IsSlowlot extends UnitFilter { 7 | override def apply(unit: UnitInfo): Boolean = Protoss.Zealot(unit) && ! Protoss.ZealotSpeed(unit.player) 8 | } 9 | -------------------------------------------------------------------------------- /PurpleWaveWithJMX.bat: -------------------------------------------------------------------------------- 1 | "C:\Program Files (x86)\Java\jre1.8.0_121\bin\java.exe" -cp $SCALA_HOME/lib/scala-library.jar -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=20000 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar ./out/artifacts/PurpleWave.jar Startup.Main -------------------------------------------------------------------------------- /src/Mathematics/Shapes/Rectangle.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Shapes 2 | 3 | import Mathematics.Points.Point 4 | 5 | object Rectangle { 6 | def apply(width: Int, height: Int): IndexedSeq[Point] = 7 | (0 until height).flatten(dy => 8 | (0 until width).map(dx => 9 | Point(dx, dy))) 10 | } 11 | -------------------------------------------------------------------------------- /src/Placement/Walls/WallConstraint.scala: -------------------------------------------------------------------------------- 1 | package Placement.Walls 2 | 3 | import Placement.Walls.WallSpans.WallSpan 4 | import ProxyBwapi.UnitClasses.UnitClass 5 | 6 | case class WallConstraint( 7 | gapTiles : Int, 8 | blocksUnit : UnitClass, 9 | span : WallSpan, 10 | buildings : UnitClass*) -------------------------------------------------------------------------------- /src/Strategery/Strategies/AllRaces/Sandbox.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Strategies.AllRaces 2 | 3 | import Gameplans.All.Sandbox 4 | import Planning.Plans.Plan 5 | import Strategery.Strategies.Strategy 6 | 7 | object Sandbox extends Strategy { 8 | override def gameplan: Option[Plan] = Some(new Sandbox) 9 | } 10 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsCompleteFor.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import Lifecycle.With 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | case class IsCompleteFor(ageFrames: Int) extends UnitFilter{ 6 | override def apply(unit: UnitInfo): Boolean = With.framesSince(unit.completionFrame) >= ageFrames 7 | } 8 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsSpeedScout.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.Protoss 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | object IsSpeedScout extends UnitFilter { 7 | override def apply(unit: UnitInfo): Boolean = Protoss.Scout(unit) && Protoss.ScoutSpeed(unit.player) 8 | } 9 | -------------------------------------------------------------------------------- /src/Tactic/Squads/GenericFriendlyUnitGroup.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Squads 2 | 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | 5 | case class GenericFriendlyUnitGroup(override val groupFriendlyUnits: Seq[FriendlyUnitInfo]) extends FriendlyUnitGroup { 6 | def this(unit: FriendlyUnitInfo) { 7 | this(Seq(unit)) 8 | } 9 | } -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsRangedGoon.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.Protoss 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | object IsRangedGoon extends UnitFilter { 7 | override def apply(unit: UnitInfo): Boolean = Protoss.Dragoon(unit) && Protoss.DragoonRange(unit.player) 8 | } 9 | -------------------------------------------------------------------------------- /.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 9 | -------------------------------------------------------------------------------- /src/Gameplans/Terran/TvP/TvPRaxExpand.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Terran.TvP 2 | 3 | import Gameplans.Terran.TvE.TerranGameplan 4 | 5 | class TvPRaxExpand extends TerranGameplan { 6 | 7 | override def executeBuild(): Unit = { 8 | 9 | } 10 | 11 | override def executeMain(): Unit = { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/TerranTimings.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Utilities.Time.GameTime 4 | 5 | object TerranTimings { 6 | object ElevenRax_BarracksCompleteBy extends GameTime(2, 13) 7 | object ElevenRax_MarineCompleteBy extends GameTime(2, 28) 8 | } 9 | -------------------------------------------------------------------------------- /src/Placement/Walls/WallSpans.scala: -------------------------------------------------------------------------------- 1 | package Placement.Walls 2 | 3 | import Debugging.SimpleString 4 | 5 | object WallSpans { 6 | trait WallSpan extends SimpleString 7 | object TerrainTerrain extends WallSpan 8 | object TerrainGas extends WallSpan 9 | object TerrainHall extends WallSpan 10 | } 11 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferBaseWithMoreWorkers.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | 5 | object PreferBaseWithMoreWorkers extends UnitPreference { 6 | 7 | override def apply(unit: FriendlyUnitInfo): Double = 1000 - PreferBaseWithFewerWorkers(unit) 8 | } 9 | -------------------------------------------------------------------------------- /src/Micro/Actions/Combat/Tactics/FewShot.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Combat.Tactics 2 | 3 | import ProxyBwapi.UnitClasses.UnitClass 4 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 5 | 6 | object FewShot { 7 | 8 | def apply(unit: FriendlyUnitInfo, targetType: UnitClass, maxShots: Int): Unit = { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsSpeedVulture.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.{Protoss, Terran} 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | object IsSpeedVulture extends UnitFilter { 7 | override def apply(unit: UnitInfo): Boolean = Terran.Vulture(unit) && Terran.VultureSpeed(unit.player) 8 | } 9 | -------------------------------------------------------------------------------- /src/Information/Battles/ProcessingStates/BattleProcessComplete.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.ProcessingStates 2 | 3 | class BattleProcessComplete extends BattleProcessState { 4 | override def step(): Unit = { 5 | transitionTo(new BattleProcessInitial) 6 | } 7 | 8 | override val isFinalStep: Boolean = true 9 | } 10 | -------------------------------------------------------------------------------- /src/Macro/Scheduling/MacroProducer.scala: -------------------------------------------------------------------------------- 1 | package Macro.Scheduling 2 | 3 | import ProxyBwapi.UnitClasses.UnitClass 4 | import Utilities.? 5 | 6 | case class MacroProducer(producer: UnitClass, product: UnitClass) { 7 | val supplyUsePerFrame: Float = product.supplyRequired.toFloat / ?(producer.isHatchlike, 342, product.buildFrames) 8 | } 9 | -------------------------------------------------------------------------------- /src/Micro/Formation/FormationEmpty.scala: -------------------------------------------------------------------------------- 1 | package Micro.Formation 2 | import Mathematics.Points.Pixel 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | 5 | object FormationEmpty extends Formation { 6 | def style: FormationStyle = FormationStyleEmpty 7 | def placements: Map[FriendlyUnitInfo, Pixel] = Map.empty 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferBaseWithFewerWorkers.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | 5 | object PreferBaseWithFewerWorkers extends UnitPreference { 6 | 7 | override def apply(unit: FriendlyUnitInfo): Double = unit.base.map(_.workerCount).getOrElse(0).toDouble 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferIf.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | import Utilities.? 5 | 6 | case class PreferIf(predicate: FriendlyUnitInfo => Boolean) extends UnitPreference { 7 | override def apply(unit: FriendlyUnitInfo): Double = ?(predicate(unit), 1, 2) 8 | } 9 | -------------------------------------------------------------------------------- /src/Micro/Actions/Basic/DoNothing.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Basic 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object DoNothing extends Action { 8 | override protected def perform(unit: FriendlyUnitInfo): Unit = { Commander.sleep(unit, 1) } 9 | } 10 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Geography/ShowBWEB.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Geography 2 | 3 | import Debugging.Visualizations.Views.DebugView 4 | import Placement.JBWEBWrapper 5 | 6 | object ShowBWEB extends DebugView { 7 | 8 | override def renderMap(): Unit = { 9 | JBWEBWrapper.draw() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Gameplans/All/ModalGameplan.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.All 2 | 3 | import Planning.Plans.Plan 4 | 5 | class ModalGameplan(modes: Modal*) extends Plan with Modal { 6 | override def isComplete: Boolean = modes.forall(_.isComplete) 7 | override def onUpdate(): Unit = { 8 | modes.find( ! _.isComplete).foreach(_.update()) 9 | } 10 | } -------------------------------------------------------------------------------- /src/Mathematics/Points/Directions.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Points 2 | 3 | object Directions { 4 | object Up extends Direction(0, -1) 5 | object Down extends Direction(0, 1) 6 | object Left extends Direction(-1, 0) 7 | object Right extends Direction(1, 0) 8 | val All: Seq[Direction] = Seq(Up, Down, Left, Right) 9 | } 10 | -------------------------------------------------------------------------------- /src/Placement/Generation/TemplatesGeneric.scala: -------------------------------------------------------------------------------- 1 | package Placement.Generation 2 | 3 | import Placement.Templating.Template 4 | 5 | object TemplatesGeneric { 6 | 7 | val walkway: Template = new Template().from("-") 8 | 9 | val townhall: Template = new Template().from( 10 | "Hxxx", 11 | "xxxx", 12 | "xxxx") 13 | } 14 | -------------------------------------------------------------------------------- /src/Mathematics/Shapes/Corners.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Shapes 2 | 3 | import Mathematics.Points.Point 4 | 5 | object Corners { 6 | def apply(width: Int, height: Int): IndexedSeq[Point] = Vector( 7 | Point(0, 0), 8 | Point(width - 1, 0), 9 | Point(width - 1, height - 1), 10 | Point(0, height - 1)) 11 | } 12 | -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/TrafficPriority.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import bwapi.Color 4 | 5 | case class TrafficPriority(value: Int, color: Color, name: String) extends Ordered[TrafficPriority] { 6 | def compare(other: TrafficPriority): Int = value.compareTo(other.value) 7 | override val toString: String = name 8 | } 9 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorHeal.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object BehaviorHeal extends SimulacrumBehavior { 4 | val fighting: Boolean = true 5 | @inline override def act(simulacrum: Simulacrum): Unit = { 6 | // TODO 7 | simulacrum.doBehavior(BehaviorFlee) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorStorm.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object BehaviorStorm extends SimulacrumBehavior { 4 | override val fighting: Boolean = true 5 | override def act(simulacrum: Simulacrum): Unit = { 6 | // TODO 7 | simulacrum.doBehavior(BehaviorFlee) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/SimulacrumBehavior.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | import Debugging.ToString 4 | 5 | trait SimulacrumBehavior { 6 | val fighting: Boolean 7 | def act(simulacrum: Simulacrum): Unit 8 | override val toString: String = ToString(this).replace("Behavior", "") 9 | } 10 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersRequired/TargetFilterEnemy.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersRequired 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | object TargetFilterEnemy extends TargetFilter { 7 | override def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = target.isEnemy 8 | } 9 | -------------------------------------------------------------------------------- /src/Utilities/UnitCounters/UnitCounter.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitCounters 2 | 3 | trait UnitCounter { 4 | def minimum: Int = 1 5 | def maximum: Int 6 | final def continue[T](iterable: Iterable[T]): Boolean = iterable.size < maximum 7 | final def accept[T](iterable: Iterable[T]): Boolean = iterable.size >= minimum && iterable.size <= maximum 8 | } 9 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Animation.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations 2 | 3 | import Lifecycle.With 4 | 5 | class Animation { 6 | def durationFrames: Int = 96 7 | def drawScreen(): Unit = {} 8 | def drawMap(): Unit = {} 9 | 10 | final val frameCreated = With.frame 11 | final def age: Int = With.framesSince(frameCreated) 12 | } 13 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Micro/ShowPathfinding.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Micro 2 | 3 | import Debugging.Visualizations.Views.DebugView 4 | import Lifecycle.With 5 | 6 | object ShowPathfinding extends DebugView { 7 | 8 | override def renderMap(): Unit = { 9 | With.grids.debugPathfinding.drawMap() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Information/Battles/ProcessingStates/BattleProcessCluster.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.ProcessingStates 2 | 3 | import Lifecycle.With 4 | 5 | class BattleProcessCluster extends BattleProcessState { 6 | override def step(): Unit = { 7 | With.battles.clustering.recalculate() 8 | transitionTo(new BattleProcessDivisions) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Information/Grids/Versioned/GridVersionedInt.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Versioned 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridVersionedValue 4 | 5 | class GridVersionedInt extends AbstractGridVersionedValue[Int] { 6 | override val defaultValue: Int = 0 7 | override protected val values: Array[Int] = Array.fill(length)(defaultValue) 8 | } 9 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Planning/ShowPlacement.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Planning 2 | 3 | import Debugging.Visualizations.Views.DebugView 4 | import Lifecycle.With 5 | 6 | object ShowPlacement extends DebugView { 7 | 8 | override def renderMap(): Unit = { 9 | With.placement.fits.foreach(_.drawMap()) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferIdle.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 5 | 6 | object PreferIdle extends UnitPreference { 7 | 8 | override def apply(unit: FriendlyUnitInfo): Double = unit.remainingOccupationFrames + 240 * Maff.fromBoolean(unit.carrying) 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Geography/Calculations/ZonesConnecting.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Calculations 2 | 3 | import Information.Geography.Types.{Geo, Zone} 4 | import Lifecycle.With 5 | 6 | object ZonesConnecting { 7 | def apply(a: Geo, b: Geo): Seq[Zone] = { 8 | With.paths.aStar(a.heart, b.heart).tiles.getOrElse(Seq.empty).map(_.zone) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersRequired/TargetFilterMissing.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersRequired 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | object TargetFilterMissing extends TargetFilter { 7 | override def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = target.likelyStillThere 8 | } 9 | -------------------------------------------------------------------------------- /src/ProxyBwapi/Bullets/Bullets.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.Bullets 2 | 3 | import Lifecycle.With 4 | import Performance.Cache 5 | 6 | import scala.collection.JavaConverters._ 7 | 8 | class Bullets { 9 | def all: Seq[BulletInfo] = cachedBullets() 10 | 11 | private val cachedBullets = new Cache(() => With.game.getBullets.asScala.map(BulletInfo)) 12 | } 13 | -------------------------------------------------------------------------------- /src/Strategery/Selection/StrategySelectionPolicy.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Selection 2 | 3 | import Debugging.SimpleString 4 | import Strategery.Strategies.StrategyBranch 5 | 6 | trait StrategySelectionPolicy extends SimpleString { 7 | def chooseBranch: StrategyBranch 8 | def respectMap : Boolean = true 9 | def respectHistory : Boolean = true 10 | } 11 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersRequired/TargetFilterCanAttack.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersRequired 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | object TargetFilterCanAttack extends TargetFilter { 7 | override def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = actor.canAttack(target) 8 | } 9 | -------------------------------------------------------------------------------- /src/Performance/Tasks/DummyTask.scala: -------------------------------------------------------------------------------- 1 | package Performance.Tasks 2 | 3 | class DummyTask(classType: Class[_]) extends TimedTask { 4 | withName(if (classType.getSimpleName.contains("anon")) classType.getSuperclass.getSimpleName else classType.getSimpleName) 5 | var runFunction: () => Unit = () => {} 6 | override protected def onRun(budgetMs: Long): Unit = runFunction() 7 | } 8 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Micro/ShowFormations.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Micro 2 | 3 | import Debugging.Visualizations.Views.DebugView 4 | import Lifecycle.With 5 | 6 | object ShowFormations extends DebugView { 7 | 8 | override def renderMap(): Unit = { 9 | With.squads.all.foreach(_.formations.foreach(_.renderMap())) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Information/Battles/Types/FriendlyTeam.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Types 2 | 3 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 4 | import Tactic.Squads.TFriendlyUnitGroup 5 | 6 | class FriendlyTeam(battle: Battle, override val groupFriendlyUnits: Seq[FriendlyUnitInfo]) extends Team(battle, groupFriendlyUnits.map(_.asInstanceOf[UnitInfo])) with TFriendlyUnitGroup 7 | -------------------------------------------------------------------------------- /src/Information/GameSense/GameSense.scala: -------------------------------------------------------------------------------- 1 | package Information.GameSense 2 | 3 | import Debugging.SimpleString 4 | 5 | trait GameSense extends SimpleString { 6 | private var _opposite: Option[GameSense] = None 7 | def opposite: Option[GameSense] = _opposite 8 | def setOpposite(argOpposite: GameSense): Unit = { 9 | _opposite = Some(argOpposite) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Information/Grids/Versioned/GridVersionedDouble.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Versioned 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridVersionedValue 4 | 5 | class GridVersionedDouble extends AbstractGridVersionedValue[Double] { 6 | override val defaultValue: Double = 0.0 7 | override protected val values: Array[Double] = Array.fill(length)(defaultValue) 8 | } 9 | -------------------------------------------------------------------------------- /src/Mathematics/Physics/Gravity.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Physics 2 | 3 | import Mathematics.Points.Pixel 4 | 5 | case class Gravity(pixel: Pixel, magnitude: Double) { 6 | def apply(target: Pixel): Force = { 7 | val scale = magnitude / target.pixelDistanceSquared(pixel) 8 | Force( 9 | scale * (pixel.x - target.x), 10 | scale * (pixel.y - target.y)) 11 | } 12 | } -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorAssemble.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object BehaviorAssemble extends SimulacrumBehavior { 4 | override val fighting: Boolean = false 5 | 6 | override def act(simulacrum: Simulacrum): Unit = { 7 | simulacrum.move(simulacrum.simulation.enemyVanguard, Some("Assemble")) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Grids/Versioned/GridVersionedBoolean.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Versioned 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridVersionedValue 4 | 5 | class GridVersionedBoolean extends AbstractGridVersionedValue[Boolean] { 6 | override val defaultValue: Boolean = false 7 | override protected val values: Array[Boolean] = Array.fill(length)(defaultValue) 8 | } 9 | -------------------------------------------------------------------------------- /src/Micro/Formation/FormationZone.scala: -------------------------------------------------------------------------------- 1 | package Micro.Formation 2 | 3 | import Information.Geography.Types.{Edge, Zone} 4 | import Tactic.Squads.FriendlyUnitGroup 5 | 6 | object FormationZone { 7 | def apply(group: FriendlyUnitGroup, zone: Zone, edge: Edge): Formation = { 8 | new FormationStandard(group, FormationStyleGuard, edge.pixelCenter, Some(zone)) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/SimulationEventDeath.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | import Mathematics.Points.Pixel 4 | 5 | final case class SimulationEventDeath(sim: Simulacrum) extends SimulationEvent(sim) { 6 | 7 | override def toString: String = f"$frame: ${sim.describe} dies" 8 | 9 | override val to: Pixel = from 10 | } 11 | -------------------------------------------------------------------------------- /configs/run_proxy.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | if "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( 3 | echo "64-Bit OS" 4 | if exist "bwapi-data/AI/jre/bin/java.exe" ( 5 | echo "Found bundled JRE." 6 | bwapi-data/AI/run64.bat 7 | ) else ( 8 | echo "Did not find bundled JRE." 9 | bwapi-data/AI/run32.bat 10 | ) 11 | ) else ( 12 | echo "32-Bit OS" 13 | bwapi-data/AI/run32.bat 14 | ) -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintLambda.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | 5 | class FingerprintLambda(predicate: () => Boolean, isSticky: () => Boolean = () => true) extends Fingerprint { 6 | override protected def investigate: Boolean = predicate() 7 | override def sticky: Boolean = isSticky() 8 | } 9 | -------------------------------------------------------------------------------- /src/Macro/Scheduling/MacroStep.scala: -------------------------------------------------------------------------------- 1 | package Macro.Scheduling 2 | 3 | import Macro.Requests.RequestBuildable 4 | 5 | class MacroStep { 6 | val state: MacroState = new MacroState 7 | var event: MacroEvent = new MacroEvent(state) 8 | var request: Option[RequestBuildable] = None 9 | 10 | override def toString: String = f"${request.map(r => f"[$r] ").getOrElse("")}$event" 11 | } 12 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Fun/ShowBlackScreen.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Fun 2 | 3 | import Debugging.Visualizations.Views.DebugView 4 | import Lifecycle.With 5 | import bwapi.Color 6 | 7 | object ShowBlackScreen extends DebugView { 8 | 9 | override def renderScreen() { 10 | With.game.drawBoxScreen(0, 0, 1500, 1200, Color.Black, true) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Grids/ArrayTypes/AbstractGridArrayBoolean.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.ArrayTypes 2 | 3 | abstract class AbstractGridArrayBoolean extends AbstractGridArray[Boolean] { 4 | override val defaultValue: Boolean = false 5 | override val values: Array[Boolean] = Array.fill(width * height)(defaultValue) 6 | override def repr(value: Boolean): String = if (value) "true" else "false" 7 | } 8 | -------------------------------------------------------------------------------- /src/ProxyBwapi/Races/Neutral.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.Races 2 | 3 | import ProxyBwapi.UnitClasses.UnitClasses 4 | import bwapi.UnitType 5 | 6 | object Neutral { 7 | lazy val Geyser = UnitClasses.get(UnitType.Resource_Vespene_Geyser) 8 | lazy val PsiDisruptor = UnitClasses.get(UnitType.Special_Psi_Disrupter) 9 | lazy val Autosupply = UnitClasses.get(UnitType.Unused_Cantina) 10 | } 11 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint9PoolGas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.Overpool8Gas_GasCompleteBy 5 | import Utilities.Time.Seconds 6 | 7 | class Fingerprint9PoolGas extends FingerprintGasCompleteBy(Overpool8Gas_GasCompleteBy - Seconds(5)) 8 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersSituational/TargetFilterVisibleInRange.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersSituational 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | object TargetFilterVisibleInRange extends TargetFilter { 7 | def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = target.visible && actor.inRangeToAttack(target) 8 | } 9 | -------------------------------------------------------------------------------- /src/Mathematics/Points/Points.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Points 2 | 3 | import Lifecycle.With 4 | import Mathematics.Maff 5 | 6 | object Points { 7 | 8 | def middle: Pixel = Pixel( 9 | Maff.div2(With.mapPixelWidth), 10 | Maff.div2(With.mapPixelHeight)) 11 | 12 | def tileMiddle: Tile = Tile( 13 | Maff.div2(With.mapTileWidth), 14 | Maff.div2(With.mapTileHeight)) 15 | } 16 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferAll.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 5 | 6 | case class PreferAll(preferences: Function[FriendlyUnitInfo, Double]*) extends UnitPreference { 7 | override def apply(unit: FriendlyUnitInfo): Double = { 8 | preferences.map(_(unit)).map(Maff.fastSigmoid01).sum 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Information/Geography/Calculations/GetExits.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Calculations 2 | 3 | import Information.Geography.Types.{Edge, Geo} 4 | 5 | object GetExits { 6 | def apply(geos: Iterable[Geo]): Set[Edge] = { 7 | geos 8 | .view 9 | .flatMap(_.edges) 10 | .filter(_.zones.exists(z => ! geos.view.flatMap(_.zones).exists(z==))) 11 | .toSet 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Mathematics/Shapes/Circle.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Shapes 2 | 3 | import Mathematics.Points.Point 4 | 5 | object Circle { 6 | 7 | def apply(radius: Int): Seq[Point] = 8 | (-radius to radius).view.flatMap(x => 9 | (-radius to radius).view.map(y => 10 | (x, y, x * x + y * y <= radius * radius))) 11 | .filter(_._3) 12 | .map(point => Point(point._1, point._2)) 13 | } 14 | -------------------------------------------------------------------------------- /src/Planning/Plans/Plan.scala: -------------------------------------------------------------------------------- 1 | package Planning.Plans 2 | 3 | import Debugging.SimpleString 4 | import Macro.Allocation.Prioritized 5 | 6 | class Plan extends Prioritized with SimpleString { 7 | 8 | protected def onUpdate(): Unit = {} 9 | 10 | final def update(): Unit = { 11 | prioritize() 12 | onUpdate() 13 | } 14 | 15 | final def apply(): Unit = { 16 | update() 17 | } 18 | } -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Skimulation/SkimulationTeam.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Skimulation 2 | 3 | trait SkimulationTeam { 4 | var skimMeanWarriorDistanceToEngage: Double = 0 5 | var skimStrengthTotal: Double = 0 6 | var skimStrengthAir: Double = 0 7 | var skimStrengthGround: Double = 0 8 | var skimStrengthVsAir: Double = 0 9 | var skimStrengthVsGround: Double = 0 10 | } 11 | -------------------------------------------------------------------------------- /src/Placement/Templating/RequireAnything.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | class RequireAnything extends TemplatePointRequirement { 4 | override val buildableBefore : Boolean = false 5 | override val walkableBefore : Boolean = false 6 | override val buildableAfter : Boolean = true 7 | override val walkableAfter : Boolean = true 8 | override val toString : String = "Anything" 9 | } 10 | -------------------------------------------------------------------------------- /src/Placement/Templating/RequireNothing.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | class RequireNothing extends TemplatePointRequirement { 4 | override val buildableBefore : Boolean = false 5 | override val walkableBefore : Boolean = false 6 | override val buildableAfter : Boolean = false 7 | override val walkableAfter : Boolean = false 8 | override val toString : String = "Nothing" 9 | } 10 | -------------------------------------------------------------------------------- /src/Placement/Templating/RequireWalkable.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | class RequireWalkable extends TemplatePointRequirement { 4 | override val buildableBefore : Boolean = false 5 | override val walkableBefore : Boolean = true 6 | override val buildableAfter : Boolean = false 7 | override val walkableAfter : Boolean = true 8 | override val toString : String = "Walkable" 9 | } 10 | -------------------------------------------------------------------------------- /src/Mathematics/Points/WalkTile.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Points 2 | 3 | import bwapi.WalkPosition 4 | 5 | case class WalkTile(argX: Int, argY: Int) extends AbstractPoint(argX, argY) { 6 | 7 | def bwapi: WalkPosition = new WalkPosition(x, y) 8 | 9 | def add(dx: Int, dy: Int): WalkTile = { 10 | WalkTile(x + dx, y + dy) 11 | } 12 | def add(point: Point): WalkTile = { 13 | add(point.x, point.y) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersSituational/TargetFilterWhitelist.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersSituational 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | case class TargetFilterWhitelist(units: Iterable[UnitInfo]) extends TargetFilter { 7 | def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = { 8 | units.exists(target==) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rdparty/jbwapi"] 2 | path = 3rdparty/jbwapi 3 | url = https://github.com/JavaBWAPI/JBWAPI 4 | [submodule "3rdparty/mjson"] 5 | path = 3rdparty/mjson 6 | url = https://github.com/bolerio/mjson 7 | [submodule "3rdparty/jbweb"] 8 | path = 3rdparty/jbweb 9 | url = https://github.com/MrTate/JBWEB 10 | [submodule "3rdparty/javajps"] 11 | path = 3rdparty/javajps 12 | url = https://github.com/MrTate/JavaJPS 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint1RaxGas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Terran 6 | import Utilities.Time.GameTime 7 | 8 | class Fingerprint1RaxGas extends FingerprintOr( 9 | With.fingerprints.oneFac, 10 | new FingerprintCompleteBy(Terran.Refinery, GameTime(2, 45), 1)) -------------------------------------------------------------------------------- /src/Micro/Actions/Commands/Attack.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Commands 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object Attack extends Action { 8 | override def allowed(unit: FriendlyUnitInfo): Boolean = unit.canAttack && unit.agent.toAttack.isDefined 9 | override def perform(unit: FriendlyUnitInfo): Unit = Commander.attack(unit) 10 | } 11 | -------------------------------------------------------------------------------- /src/Strategery/Selection/WeightedGame.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Selection 2 | 3 | import Strategery.History.HistoricalGame 4 | import Strategery.Strategies.StrategyBranch 5 | 6 | class WeightedGame(val branch: StrategyBranch, val game: HistoricalGame) { 7 | val similarity : Double = branch.strategies.count(game.weEmployed).toDouble / branch.strategies.length 8 | val finalWeight : Double = similarity * game.weight 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Grids/Movement/GridWalkable.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Movement 2 | 3 | import Information.Grids.AbstractTypedGrid 4 | import Lifecycle.With 5 | 6 | class GridWalkable extends AbstractTypedGrid[Boolean] { 7 | @inline final def getUnchecked(i: Int): Boolean = With.grids.walkableTerrain.getUnchecked(i) && ! With.grids.unwalkableUnits.isSetUnchecked(i) 8 | final override val defaultValue: Boolean = false 9 | } 10 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersRequired/TargetFilterType.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersRequired 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.Races.{Protoss, Zerg} 5 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 6 | 7 | object TargetFilterType extends TargetFilter { 8 | def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = target.isNone(Protoss.Interceptor, Zerg.Larva, Zerg.Egg) 9 | } 10 | -------------------------------------------------------------------------------- /src/Information/Battles/ProcessingStates/BattleProcessState.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.ProcessingStates 2 | 3 | import Lifecycle.With 4 | 5 | trait BattleProcessState { 6 | protected def transitionTo(newState: BattleProcessState): Unit = { 7 | With.battles.setProcessingState(newState) 8 | } 9 | 10 | def step(): Unit 11 | 12 | def isFinalStep: Boolean = false 13 | 14 | val frameStarted: Int = With.frame 15 | } 16 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/Internal/NeoContinentBackend.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo.Internal 2 | 3 | import Information.Geography.NeoGeo.NeoContinent 4 | import java.awt.Color 5 | 6 | import scala.collection.mutable 7 | 8 | class NeoContinentBackend extends NeoContinent { 9 | val walks = new mutable.ArrayBuffer[Int] 10 | var color = new Color(0, 0, 0) 11 | 12 | override def walkable: Seq[Int] = walks 13 | } 14 | -------------------------------------------------------------------------------- /src/Tactic/Tactics/TacticFloatBuildings.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Tactics 2 | 3 | import Lifecycle.With 4 | import Planning.ResourceLocks.LockUnits 5 | 6 | class TacticFloatBuildings extends Tactic { 7 | 8 | val floaties: LockUnits = new LockUnits(this, u => ! u.flying && With.blackboard.floatableBuildings().exists(_(u))) 9 | 10 | def launch(): Unit = { 11 | floaties.acquire().foreach(_.intend(this).setShouldLiftoff()) 12 | } 13 | } -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersSituational/TargetFilterPotshot.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersSituational 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | object TargetFilterPotshot extends TargetFilter { 7 | override def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = target.unitClass.attacksOrCastsOrDetectsOrTransports && TargetFilterVisibleInRange.legal(actor, target) 8 | } 9 | -------------------------------------------------------------------------------- /src/Gameplans/All/StandardGameplan.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.All 2 | 3 | import Gameplans.Protoss.ProtossStandardGameplan 4 | import Gameplans.Terran.TerranStandardGameplan 5 | import Gameplans.Zerg.ZergStandardGameplan 6 | import Planning.Plans.SwitchOurRace 7 | 8 | class StandardGameplan extends SwitchOurRace( 9 | whenTerran = new TerranStandardGameplan, 10 | whenProtoss = new ProtossStandardGameplan, 11 | whenZerg = new ZergStandardGameplan) -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorDetect.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object BehaviorDetect extends SimulacrumBehavior { 4 | val fighting: Boolean = true 5 | override def act(simulacrum: Simulacrum): Unit = { 6 | simulacrum.targets.removeIf(t => ! t.cloaked && ! t.burrowed) 7 | if (simulacrum.targets.isEmpty) { 8 | simulacrum.doBehavior(BehaviorFlee) 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorFlee.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object BehaviorFlee extends SimulacrumBehavior { 4 | val fighting: Boolean = false 5 | @inline override def act(simulacrum: Simulacrum): Unit = { 6 | if ( ! simulacrum.canMove) { 7 | simulacrum.doBehavior(BehaviorIdle) 8 | return 9 | } 10 | 11 | // TODO: Flee most recent attacker 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Tactic/Tactics/TacticGather.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Tactics 2 | 3 | import Debugging.SimpleString 4 | import Lifecycle.With 5 | import Planning.ResourceLocks.LockUnits 6 | import Utilities.UnitFilters.IsWorker 7 | 8 | class TacticGather extends Tactic with SimpleString { 9 | 10 | val workerLock: LockUnits = new LockUnits(this, IsWorker) 11 | 12 | def launch(): Unit = { 13 | With.gathering.setWorkers(workerLock.acquire()) 14 | } 15 | } -------------------------------------------------------------------------------- /src/Information/Grids/Construction/GridBuildable.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Construction 2 | 3 | import Information.Grids.AbstractTypedGrid 4 | import Lifecycle.With 5 | 6 | final class GridBuildable extends AbstractTypedGrid[Boolean] { 7 | 8 | @inline def getUnchecked(i: Int): Boolean = With.grids.buildableTerrain.getUnchecked(i) && ! With.grids.unwalkableUnits.isSetUnchecked(i) 9 | 10 | override val defaultValue: Boolean = false 11 | } 12 | -------------------------------------------------------------------------------- /src/Information/Grids/Construction/GridBuildableTerrain.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Construction 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridArrayBoolean 4 | import Lifecycle.With 5 | 6 | final class GridBuildableTerrain extends AbstractGridArrayBoolean { 7 | 8 | override def onInitialization(): Unit = { 9 | indices.foreach(i => set(i, With.game.isBuildable(i % With.mapTileWidth, i / With.mapTileWidth))) 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/Planning/ResourceLocks/LockCurrencyFor.scala: -------------------------------------------------------------------------------- 1 | package Planning.ResourceLocks 2 | 3 | import Macro.Allocation.Prioritized 4 | import ProxyBwapi.Buildable 5 | 6 | class LockCurrencyFor(prioritized: Prioritized, buildableType: Buildable, upgradeLevel: Int = 1) extends LockCurrency(prioritized) { 7 | minerals = buildableType.mineralCost(upgradeLevel) 8 | gas = buildableType.gasCost(upgradeLevel) 9 | supply = buildableType.supplyRequired 10 | } 11 | -------------------------------------------------------------------------------- /scripts/performance.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | echo "Good performance: $(find /c/Users/d/AppData/Roaming/scbw/games/*/logs_0 -name "bot.log" | xargs grep "performance was good" | wc -l)" 3 | echo "Dangerous performance: $(find /c/Users/d/AppData/Roaming/scbw/games/*/logs_0 -name "bot.log" | xargs grep "performance was DANGEROUS" | wc -l)" 4 | echo "Bad performance: $(find /c/Users/d/AppData/Roaming/scbw/games/*/logs_0 -name "bot.log" | xargs grep "performance was BAD" | wc -l)" -------------------------------------------------------------------------------- /src/ProxyBwapi/Upgrades/Upgrades.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.Upgrades 2 | 3 | import Lifecycle.With 4 | import bwapi.UpgradeType 5 | 6 | object Upgrades { 7 | def all: Vector[Upgrade] = With.proxy.upgrades 8 | def get(upgrade: UpgradeType): Upgrade = With.proxy.upgradesById(upgrade.id) 9 | lazy val None: Upgrade = all.find(_.bwapiType == UpgradeType.None).get 10 | lazy val Unknown: Upgrade = all.find(_.bwapiType == UpgradeType.Unknown).get 11 | } 12 | 13 | -------------------------------------------------------------------------------- /configs/PurpleWaveLocalMetal.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "human" : false, 3 | "ladder" : false, 4 | "livestream" : false, 5 | "tournament" : true, 6 | "roundrobin" : true, 7 | "elimination" : false, 8 | "pretraining" : false, 9 | "debugging" : true, 10 | "debugginglive" : true, 11 | "logstd" : true, 12 | "multiCPU" : true, 13 | "framemstarget" : 35, 14 | "framemslimit" : 35, 15 | "comments" : "" 16 | } -------------------------------------------------------------------------------- /src/Mathematics/Physics/ForceMap.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Physics 2 | 3 | import Debugging.Visualizations.ForceLabel 4 | 5 | import scala.collection.mutable 6 | 7 | class ForceMap extends mutable.HashMap[ForceLabel, Force](){ 8 | override def default(key: ForceLabel): Force = Forces.None 9 | def forces: Iterable[Force] = values 10 | def sum: Force = ForceMath.sum(forces) 11 | 12 | def allZero: Boolean = values.forall(f => f.x == 0 && f.y == 0) 13 | } 14 | -------------------------------------------------------------------------------- /src/Micro/Actions/Terran/Liftoff.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Terran 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object Liftoff extends Action { 8 | 9 | override def allowed(unit: FriendlyUnitInfo): Boolean = { 10 | unit.intent.shouldLiftoff && ! unit.flying 11 | } 12 | 13 | override def perform(unit: FriendlyUnitInfo) { 14 | Commander.lift(unit) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/ExplosionInfestedTerran.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import Mathematics.Physics.Force 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | class ExplosionInfestedTerran(infested: UnitInfo) extends CircularPush(TrafficPriorities.Dodge, infested.pixel, 60) { 7 | override def force(recipient: FriendlyUnitInfo): Option[Force] = { 8 | if(recipient.flying) None else super.force(recipient) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/ProxyBwapi/UnitClasses/UnitClasses.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.UnitClasses 2 | 3 | import Lifecycle.With 4 | import bwapi.UnitType 5 | 6 | object UnitClasses { 7 | def all: Vector[UnitClass] = With.proxy.unitClasses 8 | def get(unitType: UnitType): UnitClass = With.proxy.unitClassesById(unitType.id) 9 | lazy val None: UnitClass = all.find(_.bwapiType == UnitType.None).get 10 | lazy val Unknown: UnitClass = all.find(_.bwapiType == UnitType.Unknown).get 11 | } 12 | -------------------------------------------------------------------------------- /src/Debugging/EnumerateUnits.scala: -------------------------------------------------------------------------------- 1 | package Debugging 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object EnumerateUnits { 6 | def apply(units: Iterable[UnitInfo]): String = { 7 | val counts = units 8 | .toVector 9 | .map(_.unitClass) 10 | .groupBy(x => x) 11 | val output = counts 12 | .toSeq 13 | .sortBy(-_._2.size) 14 | .map(p => p._2.size + p._1.abbr) 15 | .mkString(".") 16 | output 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintRace.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import bwapi.Race 6 | 7 | class FingerprintRace(race: Race) extends Fingerprint { 8 | override def investigate: Boolean = With.enemies.exists(_.raceInitial == race) 9 | override def reason: String = f"$race: [${With.enemies.filter(_.raceInitial == race).map(_.name).mkString(", ")}]" 10 | } 11 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ProtossStrategies/FingerprintBunkerRush.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ProtossStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Utilities.UnitFilters.{IsAll, IsProxied} 5 | import ProxyBwapi.Races.Terran 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintBunkerRush extends FingerprintCompleteBy( 9 | IsAll(Terran.Bunker, IsProxied), 10 | GameTime(5, 0)) { 11 | 12 | override val sticky = true 13 | } -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint2Fac.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Terran 6 | import Utilities.Time.GameTime 7 | 8 | class Fingerprint2Fac extends FingerprintOr( 9 | With.fingerprints.twoFacVultures, 10 | new FingerprintCompleteBy(Terran.Factory, GameTime(4, 40), 2), // 4:10 normally 11 | new FingerprintNFactories(2)) -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint3Fac.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Terran 6 | import Utilities.Time.GameTime 7 | 8 | class Fingerprint3Fac extends FingerprintOr( 9 | With.fingerprints.threeFacVultures, 10 | new FingerprintCompleteBy(Terran.Factory, GameTime(5, 0), 3), // 4:40 normally 11 | new FingerprintNFactories(3)) -------------------------------------------------------------------------------- /src/Information/Grids/Floody/GridEnemyVision.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | final class GridEnemyVision extends AbstractGridFloody { 7 | 8 | override protected def include(unit: UnitInfo): Boolean = unit.isEnemy 9 | 10 | override protected def range(unit: UnitInfo): Int = if (unit.blind || ! unit.complete) 1 else Maff.div32(unit.sightPixels) 11 | 12 | override val margin: Int = 2 13 | } -------------------------------------------------------------------------------- /src/Information/Grids/Floody/GridEnemyRangeAir.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | final class GridEnemyRangeAir extends AbstractGridFloody { 7 | 8 | override protected def include(unit: UnitInfo): Boolean = unit.isEnemy && unit.canAttackAir 9 | 10 | override protected def range(unit: UnitInfo): Int = Maff.div32(unit.pixelRangeAir.toInt) 11 | 12 | override val margin: Int = 3 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/Micro/Agency/LocalSim.scala: -------------------------------------------------------------------------------- 1 | package Micro.Agency 2 | 3 | import Lifecycle.With 4 | 5 | class LocalSim { 6 | 7 | var lastFrame: Int = -1 8 | private var _shouldFight: Boolean = _ 9 | 10 | class LocalSimState { 11 | 12 | } 13 | 14 | def shouldFight(): Boolean = { 15 | if (lastFrame < With.frame) { 16 | performLocalSim() 17 | } 18 | _shouldFight 19 | } 20 | 21 | private def performLocalSim(): Unit = { 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferTiers.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | import Mathematics.Maff 3 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 4 | 5 | case class PreferTiers(preferences: Function[FriendlyUnitInfo, Double]*) extends UnitPreference { 6 | override def apply(unit: FriendlyUnitInfo): Double = { 7 | preferences 8 | .zipWithIndex 9 | .map(pair => Maff.fastSigmoid01(pair._1(unit)) * Math.pow(10, -pair._2)) 10 | .sum 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ProtossStrategies/FingerprintCannonRush.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ProtossStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Utilities.UnitFilters.{IsAll, IsProxied} 5 | import ProxyBwapi.Races.Protoss 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintCannonRush extends FingerprintCompleteBy( 9 | IsAll(Protoss.PhotonCannon, IsProxied), 10 | GameTime(4, 30)) { 11 | 12 | override val sticky = true 13 | } -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ProtossStrategies/FingerprintCoreBeforeZealot.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ProtossStrategies 2 | 3 | import Information.Fingerprinting.Generic.FingerprintCompleteBy 4 | import ProxyBwapi.Races.Protoss 5 | import Utilities.Time.GameTime 6 | 7 | // Sample Core-on-14 Core completion time: 2:45 8 | // Sample ZCore Core completion time: 3:08 9 | class FingerprintCoreBeforeZealot extends FingerprintCompleteBy(Protoss.CyberneticsCore, GameTime(2, 57)) 10 | -------------------------------------------------------------------------------- /src/Information/Grids/Floody/GridEnemyRangeAirGround.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | final class GridEnemyRangeAirGround extends AbstractGridFloody { 7 | 8 | override protected def include(unit: UnitInfo): Boolean = unit.isEnemy && unit.canAttack 9 | 10 | override protected def range(unit: UnitInfo): Int = Maff.div32(unit.pixelRangeMax.toInt) 11 | 12 | override val margin: Int = 3 13 | } 14 | -------------------------------------------------------------------------------- /src/Information/Grids/Floody/GridEnemyRangeGround.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | final class GridEnemyRangeGround extends AbstractGridFloody { 7 | 8 | override protected def include(unit: UnitInfo): Boolean = unit.isEnemy && unit.canAttackGround 9 | 10 | override protected def range(unit: UnitInfo): Int = Maff.div32(unit.pixelRangeGround.toInt) 11 | 12 | override val margin: Int = 3 13 | } 14 | -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsCombatSpellcaster.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | import ProxyBwapi.Races.{Protoss, Terran, Zerg} 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | object IsCombatSpellcaster extends UnitFilter { 6 | override def apply(unit: UnitInfo): Boolean = unit.isAny( 7 | Terran.ScienceVessel, 8 | Terran.Medic, 9 | Protoss.HighTemplar, 10 | Protoss.Arbiter, 11 | Protoss.DarkArchon, 12 | Zerg.Queen, 13 | Zerg.Defiler 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Information/Counting/MacroCounts.scala: -------------------------------------------------------------------------------- 1 | package Information.Counting 2 | 3 | import Performance.Cache 4 | import ProxyBwapi.UnitClasses.UnitClass 5 | import Utilities.CountMap 6 | 7 | class MacroCounts { 8 | def oursExtant: CountMap[UnitClass] = _oursExtant() 9 | def oursComplete: CountMap[UnitClass] = _oursComplete() 10 | private val _oursExtant = new Cache(() => MacroCounter.countOursExtant) 11 | private val _oursComplete = new Cache(() => MacroCounter.countOursComplete) 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintNot.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | 5 | class FingerprintNot(fingerprints: Fingerprint*) extends Fingerprint { 6 | 7 | override val children: Seq[Fingerprint] = fingerprints 8 | 9 | override def reason: String = f"[${children.view.filter(_()).map(_.explanation).mkString("; ")}]" 10 | 11 | override def investigate: Boolean = ! fingerprints.exists(_()) 12 | } 13 | -------------------------------------------------------------------------------- /src/Strategery/Selection/StrategySelectionFixed.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Selection 2 | 3 | import Strategery.Strategies.Strategy 4 | 5 | case class StrategySelectionFixed(strategies: Strategy*) extends StrategySelectionRecommended(StrategySelectionGreedy(), strategies: _*) { 6 | duration = 100000 7 | override def respectMap : Boolean = false 8 | override def respectHistory : Boolean = false 9 | 10 | override def toString: String = f"StrategySelectionFixed: $branchString" 11 | } 12 | -------------------------------------------------------------------------------- /src/Strategery/Selection/StrategySelectionRandom.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Selection 2 | 3 | import Lifecycle.With 4 | import Mathematics.Maff 5 | import Strategery.Strategies.StrategyBranch 6 | 7 | object StrategySelectionRandom extends StrategySelectionPolicy { 8 | 9 | def chooseBranch: StrategyBranch = { 10 | Maff.sampleWeighted(With.strategy.strategyBranchesLegal, (b: StrategyBranch) => b.explorationWeight).get 11 | } 12 | 13 | override def toString = "StrategySelectionRandom" 14 | } -------------------------------------------------------------------------------- /src/Utilities/UnitCounters/CountExcept.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitCounters 2 | 3 | import Lifecycle.With 4 | import Mathematics.Maff 5 | import Performance.Cache 6 | import Utilities.UnitFilters.UnitFilter 7 | 8 | class CountExcept(buffer: Int, matcher: UnitFilter) extends UnitCounter { 9 | private val matched = new Cache(() => With.units.countOurs(matcher)) 10 | override def minimum: Int = Maff.clamp01(matched() - buffer) 11 | override def maximum: Int = Math.max(0, matched() - buffer) 12 | } -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Planning/ShowWall.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Planning 2 | 3 | import Debugging.Visualizations.Views.DebugView 4 | import Lifecycle.With 5 | import Placement.Access.PlaceLabels.Wall 6 | 7 | object ShowWall extends DebugView { 8 | 9 | override def renderMap(): Unit = { 10 | With.placement.fits 11 | .view 12 | .filter(_.template.points.exists(_.requirement.labels.contains(Wall))) 13 | .foreach(_.drawMap()) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ProtossStrategies/FingerprintEarlyForge.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ProtossStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import ProxyBwapi.Races.Protoss 5 | import Utilities.Time.GameTime 6 | 7 | class FingerprintEarlyForge extends FingerprintOr( 8 | new FingerprintCompleteBy(Protoss.Forge, GameTime(4, 0)), 9 | new FingerprintCompleteBy(Protoss.PhotonCannon, GameTime(5, 0))) { 10 | 11 | override val sticky = true 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint10Hatch.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintCompleteBy, FingerprintOr} 4 | import Lifecycle.With 5 | import Utilities.UnitFilters.IsHatchlike 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint10Hatch extends FingerprintOr( 9 | new FingerprintCompleteBy(IsHatchlike, ZergTimings.TwelveHatch_HatchCompleteBy - Seconds(10), 2), 10 | With.fingerprints.tenHatchPool) -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint12HatchHatch.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.FingerprintCompleteBy 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.TwelveHatch11Pool13Hatch_HatchCompleteBy 5 | import Utilities.UnitFilters.IsHatchlike 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint12HatchHatch extends FingerprintCompleteBy(IsHatchlike, TwelveHatch11Pool13Hatch_HatchCompleteBy - Seconds(3), 3) 9 | -------------------------------------------------------------------------------- /src/Micro/Actions/Terran/FinishConstruction.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Terran 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object FinishConstruction extends Action { 8 | 9 | override def allowed(unit: FriendlyUnitInfo): Boolean = { 10 | unit.intent.toFinish.isDefined 11 | } 12 | 13 | override def perform(unit: FriendlyUnitInfo) { 14 | Commander.rightClick(unit, unit.intent.toFinish.get) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /configs/PurpleWaveLocalDocker.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "human" : false, 3 | "ladder" : false, 4 | "livestream" : false, 5 | "tournament" : true, 6 | "roundrobin" : true, 7 | "elimination" : false, 8 | "pretraining" : false, 9 | "debugging" : true, 10 | "debugginglive" : false, 11 | "logstd" : true, 12 | "multiCPU" : true, 13 | "framemstarget" : 35, 14 | "framemslimit" : 35, 15 | "comments" : "SC-Docker does not enforce per-frame limits." 16 | } -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintOr.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | 5 | class FingerprintOr(fingerprints: Fingerprint*) extends Fingerprint { 6 | 7 | override val children: Seq[Fingerprint] = fingerprints 8 | 9 | override def reason: String = f"Matched children: [${children.view.filter(_()).map(_.explanation).mkString("; ")}]" 10 | 11 | override def investigate: Boolean = fingerprints.exists(_()) 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Grids/Floody/GridFriendlyDetection.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | final class GridFriendlyDetection extends AbstractGridFloody { 7 | 8 | override protected def include(unit: UnitInfo): Boolean = unit.complete && unit.unitClass.isDetector && ! unit.blind && unit.isFriendly 9 | 10 | override protected def range(unit: UnitInfo): Int = Maff.div32(unit.sightPixels) 11 | 12 | override val margin: Int = 2 13 | } -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/ExplosionEMP.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import Mathematics.Physics.Force 4 | import ProxyBwapi.Bullets.BulletInfo 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | class ExplosionEMP(emp: BulletInfo) extends CircularPush(TrafficPriorities.Dodge, emp.targetPixel.getOrElse(emp.pixel), 96) { 8 | override def force(unit: FriendlyUnitInfo): Option[Force] = { 9 | if(unit.energy <= 5 && unit.shieldPoints == 20) None else super.force(unit) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Gameplans/Zerg/ZergStandardGameplan.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Zerg 2 | 3 | import Gameplans.All.ModalGameplan 4 | import Gameplans.Zerg.ZvP.ZergVsProtoss 5 | import Gameplans.Zerg.ZvR.ZergVsRandom 6 | import Gameplans.Zerg.ZvT.ZergVsTerran 7 | import Gameplans.Zerg.ZvZ.ZergVsZerg 8 | import Planning.Plans.SwitchEnemyRace 9 | 10 | class ZergStandardGameplan extends ModalGameplan( 11 | new ZergVsRandom, 12 | new SwitchEnemyRace( 13 | new ZergVsTerran, 14 | new ZergVsProtoss, 15 | new ZergVsZerg) 16 | ) -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/SimulationEventBehavior.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | import Mathematics.Points.Pixel 3 | 4 | final case class SimulationEventBehavior( 5 | sim: Simulacrum, 6 | behaviorOld: SimulacrumBehavior, 7 | behaviorNew: SimulacrumBehavior) 8 | extends SimulationEvent(sim) { 9 | 10 | override def toString: String = f"$frame: ${sim.describe} transitions from $behaviorOld to $behaviorNew" 11 | 12 | override val to: Pixel = from 13 | } 14 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintAnd.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | 5 | class FingerprintAnd(fingerprints: Fingerprint*) extends Fingerprint { 6 | 7 | override val children: Seq[Fingerprint] = fingerprints 8 | 9 | override def reason: String = f"Unmatched children: [${children.view.filterNot(_()).map(_.explanation).mkString("; ")}]" 10 | 11 | override def investigate: Boolean = fingerprints.forall(_()) 12 | } 13 | -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/ExplosionPsionicStorm.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import Mathematics.Physics.Force 4 | import ProxyBwapi.Bullets.BulletInfo 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | class ExplosionPsionicStorm(psionicStorm: BulletInfo) extends CircularPush(TrafficPriorities.Dodge, psionicStorm.pixel, 64) { 8 | override def force(recpient: FriendlyUnitInfo): Option[Force] = { 9 | if (recpient.unitClass.isBuilding) None else super.force(recpient) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferHatcheryWithThreeLarva.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | 3 | import Lifecycle.With 4 | import ProxyBwapi.Races.Zerg 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object PreferHatcheryWithThreeLarva extends UnitPreference { 8 | 9 | override def apply(unit: FriendlyUnitInfo): Double = 10 | Math.max(2, With.units 11 | .inTileRectangle(unit.tile.toRectangle.expand(3, 3)) 12 | .count(u => u != unit && u.isFriendly && u.is(Zerg.Larva))) 13 | } 14 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/FingerprintWallIn.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import Utilities.Time.GameTime 6 | 7 | class FingerprintWallIn extends Fingerprint { 8 | override protected def investigate: Boolean = With.frame < GameTime(3, 0)() && With.geography.zones.exists(z => z.walledIn && ! z.metro.exists(_.bases.exists(_.owner.isUs))) 9 | override protected def sticky: Boolean = true 10 | } -------------------------------------------------------------------------------- /src/Placement/Templating/RequireGas.scala: -------------------------------------------------------------------------------- 1 | package Placement.Templating 2 | 3 | import ProxyBwapi.Races.{Protoss, Terran, Zerg} 4 | 5 | class RequireGas extends TemplatePointRequirement(Terran.Refinery, Protoss.Assimilator, Zerg.Extractor) { 6 | override val buildableBefore : Boolean = false 7 | override val walkableBefore : Boolean = false 8 | override val buildableAfter : Boolean = false 9 | override val walkableAfter : Boolean = false 10 | override val toString : String = "Anything" 11 | } 12 | -------------------------------------------------------------------------------- /src/Utilities/DoQueue.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | import scala.collection.mutable 4 | 5 | /** 6 | * A syntax-light queue of things to do. 7 | * The intended use case is something you want to do exactly once, 8 | * but may want to consider doing at multiple points. 9 | */ 10 | class DoQueue(todo: (() => Unit)*) { 11 | val queue = new mutable.Queue[() => Unit] 12 | queue ++= todo 13 | 14 | def apply(): Unit = { 15 | if (queue.nonEmpty) { 16 | queue.dequeue()() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/ExplosionIrradiateSplash.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import Mathematics.Physics.Force 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | class ExplosionIrradiateSplash(burningMan: UnitInfo) extends CircularPush(TrafficPriorities.Dodge, burningMan.pixel, 64) { 7 | override def force(recipient: FriendlyUnitInfo): Option[Force] = { 8 | if (recipient == burningMan || ! recipient.unitClass.canBeIrradiateBurned) None else super.force(recipient) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Fun/ShowHappyVision.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Fun 2 | 3 | import Debugging.Visualizations.Views.Geography.ShowZones 4 | import Debugging.Visualizations.Views.DebugView 5 | 6 | object ShowHappyVision extends DebugView { 7 | 8 | def render() { 9 | ShowBlackScreen.renderScreen() 10 | ShowZones.renderMap() 11 | ShowHappyUnits.renderMap() 12 | ShowBulletsAsHearts.renderMap() 13 | ShowPlayerNames.renderScreen("Retro Arcade Happy Vision") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorRepair.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | object BehaviorRepair extends SimulacrumBehavior { 4 | val fighting: Boolean = true 5 | override def act(simulacrum: Simulacrum): Unit = { 6 | // TODO: Clear invalid targets 7 | // TODO: Sort targets 8 | simulacrum.targets.clear() 9 | if (simulacrum.targets.isEmpty) { 10 | simulacrum.behavior = BehaviorFlee 11 | simulacrum.act() 12 | return 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Mathematics/Shapes/Box.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Shapes 2 | 3 | import Mathematics.Points.Point 4 | 5 | object Box { 6 | def apply(width: Int, height: Int): Seq[Point] = ( 7 | (0 until width - 1 by 1).view.map(x => Point(x, 0)) 8 | ++ (0 until height - 1 by 1).view.map(y => Point(width - 1, y)) 9 | ++ (width - 1 until 0 by -1).view.map(x => Point(x, height - 1)) 10 | ++ (height - 1 until 0 by -1).view.map(y => Point(0, y))) 11 | } 12 | -------------------------------------------------------------------------------- /src/Mathematics/Shapes/RoundedBox.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Shapes 2 | 3 | import Mathematics.Points.Point 4 | 5 | object RoundedBox { 6 | def apply(width: Int, height: Int): IndexedSeq[Point] = ( 7 | (1 until width - 1 by 1).map(x => Point(x, 0)) 8 | ++ (1 until height - 1 by 1).map(y => Point(width - 1, y)) 9 | ++ (width - 2 until 0 by -1).map(x => Point(x, height - 1)) 10 | ++ (height - 2 until 0 by -1).map(y => Point(0, y))) 11 | } 12 | -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/ExplosionLurkerNow.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import Mathematics.Points.Pixel 4 | import ProxyBwapi.Bullets.BulletInfo 5 | 6 | class ExplosionLurkerNow(spine: BulletInfo) extends LinearPush { 7 | override protected def source: Pixel = spine.pixel 8 | 9 | override protected def destination: Pixel = spine.targetPixel.getOrElse(source) 10 | 11 | override protected def sourceWidth: Double = 20 12 | 13 | override val priority: TrafficPriority = TrafficPriorities.Shove 14 | } 15 | -------------------------------------------------------------------------------- /src/Placement/Architecture/ArchitecturalAssessment.scala: -------------------------------------------------------------------------------- 1 | package Placement.Architecture 2 | 3 | object ArchitecturalAssessment extends Enumeration { 4 | type ArchitecturalAssessment = Value 5 | val 6 | Accepted, 7 | Invalid, 8 | Unpowered, 9 | IsntBuildableTerrain, 10 | InaccessibleIsland, 11 | IsntGas, 12 | BlockedGas, 13 | IsntBasePosition, 14 | IsntLegalForTownHall, 15 | IsntBuildable, 16 | CreepMismatch, 17 | ViolatesResourceGap, 18 | BlockedByUnit 19 | = Value 20 | } -------------------------------------------------------------------------------- /src/Utilities/UnitFilters/IsRecruitableForCombat.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitFilters 2 | 3 | import ProxyBwapi.Races.Zerg 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | object IsRecruitableForCombat extends UnitFilter { 7 | override def apply(unit: UnitInfo): Boolean = ( 8 | unit.unitClass.orderable 9 | && ! unit.unitClass.isWorker 10 | && ! Zerg.Larva(unit) 11 | && unit.remainingCompletionFrames < 48 12 | && (unit.unitClass.canMove || unit.unitClass.isTank || (unit.unitClass.isBuilding && unit.flying))) 13 | } 14 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Planning/ShowHistory.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Planning 2 | 3 | import Debugging.Visualizations.Rendering.DrawScreen 4 | import Debugging.Visualizations.Views.DebugView 5 | import Lifecycle.With 6 | 7 | object ShowHistory extends DebugView { 8 | 9 | override def renderScreen(): Unit = { 10 | DrawScreen.column(5, 11 | With.visualization.lineHeightSmall * 7 12 | , With.history.games.toVector.sortBy(-_.timestamp).take(30).map(_.toString)) 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/SimulationEventSleep.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | import Mathematics.Points.Pixel 4 | 5 | final case class SimulationEventSleep(sim: Simulacrum, frames: Int, reason: Option[String] = None) extends SimulationEvent(sim) { 6 | 7 | override def toString: String = f"$frame: ${sim.describe} $from targeting ${describe(target)} ${describePixel(targetAt)} sleeps for $frames frames${reason.map(": " + _).getOrElse("")}" 8 | 9 | override val to: Pixel = from 10 | } 11 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint12Pool11Gas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintGasCompleteBy} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.TwelvePool11Gas_GasCompleteBy 5 | import Lifecycle.With 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint12Pool11Gas extends FingerprintAnd( 9 | With.fingerprints.twelvePool, 10 | new FingerprintGasCompleteBy(TwelvePool11Gas_GasCompleteBy + Seconds(10))) -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/FingerprintOverpoolGas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintGasCompleteBy} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.Overpool9Gas_GasCompleteBy 5 | import Lifecycle.With 6 | import Utilities.Time.Seconds 7 | 8 | class FingerprintOverpoolGas extends FingerprintAnd( 9 | With.fingerprints.overpool, 10 | new FingerprintGasCompleteBy(Overpool9Gas_GasCompleteBy + Seconds(15))) 11 | -------------------------------------------------------------------------------- /src/Information/Grids/Construction/GridBuildableTownHall.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Construction 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridArrayBoolean 4 | import Lifecycle.With 5 | 6 | class GridBuildableTownHall extends AbstractGridArrayBoolean { 7 | 8 | final override val defaultValue: Boolean = true 9 | 10 | override def onInitialization(): Unit = { 11 | reset() 12 | With.units.all.filter(_.unitClass.isResource).foreach(_.tileArea.expand(3, 3).tiles.foreach(set(_, false))) 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintTechBy.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import ProxyBwapi.Techs.Tech 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintTechBy(tech: Tech, gameTime: GameTime) extends Fingerprint { 9 | override def investigate: Boolean = With.frame < gameTime() && With.enemies.exists(_.hasTech(tech)) 10 | override val sticky: Boolean = true 11 | override def reason: String = tech.toString 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint2FacVultures.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintArrivesBy, FingerprintOr} 4 | import ProxyBwapi.Races.Terran 5 | import Utilities.Time.GameTime 6 | 7 | class Fingerprint2FacVultures extends FingerprintOr( 8 | new FingerprintArrivesBy(Terran.Vulture, GameTime(4, 35), 2), 9 | new FingerprintArrivesBy(Terran.Vulture, GameTime(5, 50), 4), 10 | new FingerprintArrivesBy(Terran.Vulture, GameTime(6, 10), 6), 11 | ) -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint3HatchSpeedling.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintUpgradeBy} 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Zerg 6 | import Utilities.Time.GameTime 7 | 8 | class Fingerprint3HatchSpeedling extends FingerprintAnd( 9 | With.fingerprints.threeHatchGas, 10 | new FingerprintUpgradeBy(Zerg.ZerglingSpeed, GameTime(5, 0))) { 11 | 12 | override protected val sticky: Boolean = true 13 | } 14 | -------------------------------------------------------------------------------- /src/Utilities/SpinWait.scala: -------------------------------------------------------------------------------- 1 | package Utilities 2 | 3 | import java.lang.reflect.Method 4 | 5 | object SpinWait { 6 | 7 | // We want to use Thread.onSpinWait() if it's available, 8 | // but that's only in Java 9+ 9 | 10 | private lazy val onSpinWait: Option[Method] = classOf[Thread].getDeclaredMethods.find(_.getName == "onSpinWait") 11 | def apply(): Unit = { 12 | if (onSpinWait.isDefined) { 13 | onSpinWait.get.invoke(Thread.currentThread()) 14 | } else { 15 | Thread.sleep(0, 100000) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Planning/ShowFingerprints.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Planning 2 | 3 | import Debugging.Visualizations.Rendering.DrawScreen 4 | import Debugging.Visualizations.Views.DebugView 5 | import Lifecycle.With 6 | 7 | object ShowFingerprints extends DebugView { 8 | 9 | override def renderScreen(): Unit = { 10 | DrawScreen.text( 11 | 5, 12 | 5 * With.visualization.lineHeightSmall, 13 | "Matched:\n\n" 14 | + With.fingerprints.status.mkString("\n") 15 | ) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Gameplans/Terran/TerranStandardGameplan.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Terran 2 | 3 | import Gameplans.All.ModalGameplan 4 | import Gameplans.Terran.TvP.TerranVsProtoss 5 | import Gameplans.Terran.TvR.TerranVsRandom 6 | import Gameplans.Terran.TvT.TerranVsTerran 7 | import Gameplans.Terran.TvZ.TerranVsZerg 8 | import Planning.Plans.SwitchEnemyRace 9 | 10 | class TerranStandardGameplan extends ModalGameplan( 11 | new TerranVsRandom, 12 | new SwitchEnemyRace( 13 | new TerranVsTerran, 14 | new TerranVsProtoss, 15 | new TerranVsZerg) 16 | ) 17 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint10Hatch9Pool8Gas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintGasCompleteBy} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.TenHatch9Pool8Gas_GasCompleteBy 5 | import Lifecycle.With 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint10Hatch9Pool8Gas extends FingerprintAnd( 9 | With.fingerprints.tenHatchPool, 10 | new FingerprintGasCompleteBy(TenHatch9Pool8Gas_GasCompleteBy + Seconds(15))) -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint1HatchGas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.TwoHatchGasCompleteBy 5 | import Lifecycle.With 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint1HatchGas extends FingerprintOr( 9 | new FingerprintGasCompleteBy(TwoHatchGasCompleteBy - Seconds(5)), 10 | With.fingerprints.ninePoolGas, 11 | With.fingerprints.overpoolGas, 12 | With.fingerprints.twelvePoolGas) -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/NeoBase.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | /** 4 | * A Base is a Region which contains a cluster of resources. 5 | * Each Base has a Foundation, which is an optimal location to construct a Command Center, Nexus, or Hatchery. 6 | */ 7 | class NeoBase extends NeoRegion { 8 | private var _country: NeoCountry = _ 9 | private var _metro: NeoMetro = _ 10 | private var _natural: Option[NeoBase] = None 11 | private var _main: Option[NeoBase] = None 12 | private var _isStart: Boolean = false 13 | } 14 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersRequired/TargetFilterExposed.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersRequired 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | object TargetFilterExposed extends TargetFilter { 7 | 8 | override def appliesTo(actor: FriendlyUnitInfo): Boolean = true 9 | 10 | // Avoid eating static anti-air shots unless necessary 11 | override def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = { 12 | target.tile.enemyRangeAgainst(actor) == 0 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Information/Geography/Types/LabelGenerator.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.Types 2 | 3 | import scala.collection.mutable 4 | import scala.util.Random 5 | 6 | class LabelGenerator(labels: Iterable[String]) { 7 | private var repeats: Int = 1 8 | private val names = Random.shuffle(labels) 9 | private val nameQ = new mutable.Queue[String] ++ names 10 | def next(): String = { 11 | if (nameQ.isEmpty) { 12 | repeats += 1 13 | nameQ ++= names.map(name => f"$name $repeats") 14 | } 15 | nameQ.dequeue() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Information/Grids/Vision/GridScoutingPathsBases.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Vision 2 | 3 | import Information.Grids.Movement.GridGroundDistance 4 | import Lifecycle.With 5 | import Mathematics.Points.Tile 6 | 7 | class GridScoutingPathsBases extends GridGroundDistance { 8 | 9 | override def origins: Vector[Tile] = 10 | With.geography.bases.map(_.heart).flatMap(a => 11 | With.geography.bases.map(_.heart).filterNot(a==) 12 | .flatMap(With.paths.profileDistance(a, _).find.tiles)) 13 | .flatten 14 | .distinct 15 | } 16 | -------------------------------------------------------------------------------- /src/Information/Scouting/Scouting.scala: -------------------------------------------------------------------------------- 1 | package Information.Scouting 2 | 3 | import Performance.Tasks.TimedTask 4 | 5 | final class Scouting extends TimedTask 6 | with Debuts 7 | with EnemyTechs 8 | with EnemyScouting 9 | with BaseInference 10 | with Intrigue 11 | with Timings 12 | with Tugging { 13 | override protected def onRun(budgetMs: Long): Unit = { 14 | updateEnemyTechs() 15 | updateEnemyScouting() 16 | updateBaseInference() 17 | updateIntrigue() 18 | updateDebuts() 19 | updateTimings() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Mathematics/Maff.scala: -------------------------------------------------------------------------------- 1 | package Mathematics 2 | 3 | import Mathematics.Functions._ 4 | 5 | object Maff 6 | extends Angles 7 | with Approximate 8 | with Bitshift 9 | with Convert 10 | with Polygons 11 | with Rectangles 12 | with Reduce 13 | with Sample 14 | with Sort { 15 | val inv8 : Double = 1 / 8.0 16 | val inv16 : Double = 1 / 16.0 17 | val inv32 : Double = 1 / 32.0 18 | val inv64 : Double = 1 / 64.0 19 | val inv128 : Double = 1 / 128.0 20 | val inv256 : Double = 1 / 256.0 21 | } 22 | -------------------------------------------------------------------------------- /src/Micro/Heuristics/SpellTargets.scala: -------------------------------------------------------------------------------- 1 | package Micro.Heuristics 2 | 3 | import Lifecycle.With 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | import Utilities.? 6 | 7 | object SpellTargets { 8 | 9 | def legal(target: UnitInfo): Boolean = ( 10 | ! target.invincible 11 | && ! target.stasised 12 | && target.likelyStillThere 13 | && (target.burrowed || With.framesSince(target.lastSeen) < ?(target.canMove, 24, 72))) 14 | 15 | def apply(caster: FriendlyUnitInfo): Seq[UnitInfo] = caster.matchups.allUnits.filter(legal) 16 | } 17 | -------------------------------------------------------------------------------- /src/Tactic/Tactics/Tactic.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Tactics 2 | 3 | import Macro.Allocation.Prioritized 4 | import Mathematics.Points.{Pixel, Points} 5 | import Planning.ResourceLocks.LockUnits 6 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 7 | import Tactic.Squads.FriendlyUnitGroup 8 | 9 | trait Tactic extends Prioritized with FriendlyUnitGroup { 10 | 11 | val lock: LockUnits = new LockUnits(this) 12 | var vicinity: Pixel = Points.middle 13 | 14 | @inline final def groupFriendlyUnits: Seq[FriendlyUnitInfo] = units 15 | 16 | def launch(): Unit 17 | } 18 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint12Hatch11Pool10Gas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintGasCompleteBy} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.TwelveHatch11Pool10Gas_GasCompleteBy 5 | import Lifecycle.With 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint12Hatch11Pool10Gas extends FingerprintAnd( 9 | With.fingerprints.twelveHatchPool, 10 | new FingerprintGasCompleteBy(TwelveHatch11Pool10Gas_GasCompleteBy + Seconds(15))) -------------------------------------------------------------------------------- /src/Gameplans/Protoss/ProtossStandardGameplan.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Protoss 2 | 3 | import Gameplans.All.ModalGameplan 4 | import Gameplans.Protoss.PvP.ProtossVsProtoss 5 | import Gameplans.Protoss.PvR.ProtossVsRandom 6 | import Gameplans.Protoss.PvT.ProtossVsTerran 7 | import Gameplans.Protoss.PvZ.ProtossVsZerg 8 | import Planning.Plans.SwitchEnemyRace 9 | 10 | class ProtossStandardGameplan extends ModalGameplan( 11 | new SwitchEnemyRace( 12 | new ProtossVsTerran, 13 | new ProtossVsProtoss, 14 | new ProtossVsZerg, 15 | new ProtossVsRandom) 16 | ) 17 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint14CC.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintCompleteBy, FingerprintNot} 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Terran 6 | import Utilities.Time.GameTime 7 | 8 | class Fingerprint14CC extends FingerprintAnd( 9 | new FingerprintNot(With.fingerprints.oneRaxFE), 10 | new FingerprintCompleteBy(Terran.CommandCenter, GameTime(4, 0), 2)) { 11 | override def sticky: Boolean = With.frame > GameTime(4, 0)() 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/FingerprintFD.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Terran 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintFD extends FingerprintAnd( 9 | With.fingerprints.oneFac, 10 | new FingerprintOr( 11 | new FingerprintArrivesBy(Terran.Marine, GameTime(5, 0), 5), 12 | new FingerprintCompleteBy(Terran.Marine, GameTime(4, 30), 5), 13 | new FingerprintCompleteBy(Terran.Marine, GameTime(6, 0), 6))) -------------------------------------------------------------------------------- /src/Information/Grids/Movement/GridFlowField.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Movement 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridArray 4 | import Mathematics.Physics.Force 5 | import Mathematics.Points.Tile 6 | 7 | class GridFlowField(origin: Tile) extends AbstractGridArray[Force] { 8 | 9 | final override val defaultValue: Force = Force(0, 0) 10 | final override val values: Array[Force] = Array.fill(length)(defaultValue) 11 | 12 | override def onInitialization(): Unit = { 13 | tiles.foreach(t => set(t, t.slowGroundDirectionTo(origin))) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Utilities/UnitPreferences/PreferScout.scala: -------------------------------------------------------------------------------- 1 | package Utilities.UnitPreferences 2 | import Mathematics.Maff 3 | import Mathematics.Points.{Pixel, Points} 4 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 5 | 6 | class PreferScout(val to: Pixel*) extends UnitPreference { 7 | override def apply(unit: FriendlyUnitInfo): Double = { 8 | (unit.remainingOccupationFrames 9 | + Maff.orElse(to, Seq(Points.middle)).view.map(unit.framesToTravelTo).min 10 | + (if (unit.intent.toScoutTiles.nonEmpty) 0 else 240) 11 | + (if (unit.carrying) 160 else 0)) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersRequired/TargetFilterScourge.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersRequired 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.Races.{Protoss, Zerg} 5 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 6 | 7 | object TargetFilterScourge extends TargetFilter { 8 | override def appliesTo(actor: FriendlyUnitInfo): Boolean = Zerg.Scourge(actor) 9 | def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = { 10 | if (target.unitClass.isBuilding) return false 11 | target.isNone(Protoss.Interceptor, Zerg.Overlord) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersSituational/TargetFilterCombatants.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersSituational 2 | 3 | import Micro.Targeting.TargetFilter 4 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 5 | 6 | object TargetFilterCombatants extends TargetFilter { 7 | 8 | // If we're fighting, target units that threaten to fight back 9 | def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = { 10 | target.unitClass.attacksOrCastsOrDetectsOrTransports || ( ! actor.team.exists(_.engagedUpon) && actor.matchups.pixelsToThreatRange.forall(_ > 96)) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Planning/ResourceLocks/LockCurrency.scala: -------------------------------------------------------------------------------- 1 | package Planning.ResourceLocks 2 | 3 | import Lifecycle.With 4 | import Macro.Allocation.Prioritized 5 | 6 | class LockCurrency(prioritized: Prioritized) { 7 | 8 | var minerals = 0 9 | var gas = 0 10 | var supply = 0 11 | var satisfied = false 12 | var expectedFrames = 0 13 | var owner: Prioritized = _ 14 | 15 | def acquire(): Boolean = { 16 | owner = prioritized 17 | owner.prioritize() 18 | With.bank.request(this) 19 | satisfied 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Micro/Actions/Scouting/DroneWarfare.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Scouting 2 | 3 | import Lifecycle.With 4 | import Micro.Actions.Action 5 | import Micro.Agency.Commander 6 | import Micro.Targeting.Target 7 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 8 | 9 | object DroneWarfare extends Action { 10 | 11 | override def allowed(unit: FriendlyUnitInfo): Boolean = unit.intent.toScoutTiles.nonEmpty && With.blackboard.droneWarfare() 12 | 13 | override protected def perform(unit: FriendlyUnitInfo): Unit = { 14 | Target.choose(unit) 15 | Commander.attack(unit) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintUpgradeBy.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import ProxyBwapi.Upgrades.Upgrade 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintUpgradeBy(upgrade: Upgrade, gameTime: GameTime, level: Int = 1) extends Fingerprint { 9 | override def investigate: Boolean = With.frame < gameTime() && With.enemies.exists(_.getUpgradeLevel(upgrade) >= level) 10 | override val sticky: Boolean = true 11 | override def reason: String = upgrade.toString 12 | } 13 | -------------------------------------------------------------------------------- /src/Micro/Actions/Protoss/Shuttle/Shuttling.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Protoss.Shuttle 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.Races.Protoss 5 | import ProxyBwapi.UnitInfo.UnitInfo 6 | 7 | object Shuttling { 8 | // How far is the pickup radius for a Shuttle? 9 | // It's "1" eg. 32 edge-to-edge pixels. 10 | // https://github.com/OpenBW/openbw/blob/master/bwgame.h#L5059 11 | val pickupRadiusEdge = 32 12 | 13 | def pickupRadiusCenter(other: UnitInfo): Int = { 14 | pickupRadiusEdge + Maff.div2(Protoss.Shuttle.dimensionMin + other.unitClass.dimensionMin) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Mathematics/Shapes/Ring.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Shapes 2 | 3 | import Mathematics.Points.Point 4 | import Utilities.? 5 | 6 | object Ring { 7 | 8 | def apply(radius: Int): Seq[Point] = { 9 | if (radius == 0) return Vector(Point(0, 0)) 10 | val rOut = radius * radius 11 | val rIn = ?(radius < 1, 0, (radius - 1) * (radius - 1)) 12 | (-radius to radius).view.flatMap(x => 13 | (-radius to radius).view.map(y => 14 | (x, y, { val d = x * x + y * y; d <= rOut && d > rIn }))) 15 | .filter(_._3) 16 | .map(point => Point(point._1, point._2)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Information/GameSense/GameSenses.scala: -------------------------------------------------------------------------------- 1 | package Information.GameSense 2 | 3 | object GameSenses { 4 | object EconAdvantage extends GameSense 5 | object EconDisadvantage extends GameSense 6 | object MuscleAdvantage extends GameSense 7 | object MuscleDisadvantage extends GameSense 8 | object MapControl extends GameSense 9 | object MapContained extends GameSense 10 | object CloakedCrisis extends GameSense 11 | object CloakedEdge extends GameSense 12 | object FlyingCrisis extends GameSense 13 | object FlyingEdge extends GameSense 14 | } 15 | -------------------------------------------------------------------------------- /src/Information/Grids/Vision/GridScoutingPathsStartLocations.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Vision 2 | 3 | import Information.Grids.Movement.GridGroundDistance 4 | import Lifecycle.With 5 | import Mathematics.Points.Tile 6 | 7 | class GridScoutingPathsStartLocations extends GridGroundDistance { 8 | 9 | override def origins: Vector[Tile] = 10 | With.geography.bases.filter(_.isMain).map(_.heart).flatMap(a => 11 | With.geography.bases.filter(_.isMain).map(_.heart).filterNot(a==) 12 | .flatMap(With.paths.profileDistance(a, _).find.tiles)) 13 | .flatten 14 | .distinct 15 | } 16 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ProtossStrategies/FingerprintNexusFirst.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ProtossStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Protoss 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintNexusFirst extends FingerprintCompleteBy( 9 | u => Protoss.Nexus(u) && ( 10 | ! u.base.exists(_.isMain) 11 | || ! u.complete 12 | || With.scouting.enemyMain.exists( ! u.base.contains(_))), 13 | GameTime(3, 30), 2) { 14 | 15 | override def sticky: Boolean = With.frame > GameTime(3, 20)() 16 | } 17 | -------------------------------------------------------------------------------- /src/Micro/Actions/Commands/Travel.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Commands 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import Micro.Coordination.Pathing.MicroPathing 6 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 7 | 8 | object Travel extends Action { 9 | override def allowed(unit: FriendlyUnitInfo): Boolean = unit.canMove 10 | override def perform(unit: FriendlyUnitInfo): Unit = { 11 | if (unit.intent.canSneak) { 12 | MicroPathing.tryMovingAlongTilePath(unit, MicroPathing.getSneakyPath(unit)) 13 | } else { 14 | Commander.move(unit) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Information/Battles/ProcessingStates/BattleProcessJudge.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.ProcessingStates 2 | 3 | import Information.Battles.Types.BattleJudgment 4 | import Lifecycle.With 5 | 6 | class BattleProcessJudge extends BattleProcessState { 7 | override def step(): Unit = { 8 | 9 | val unjudged = With.battles.nextBattles.find(_.judgement.isEmpty) 10 | 11 | if (unjudged.isDefined) { 12 | unjudged.get.judgement = Some(new BattleJudgment(unjudged.get)) 13 | return 14 | } 15 | 16 | With.battles.measureReactionTime() 17 | 18 | transitionTo(new BattleProcessSwap) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Information/Grids/Floody/GridEnemyDetection.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Floody 2 | 3 | import Mathematics.Maff 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | import Utilities.? 6 | 7 | final class GridEnemyDetection extends AbstractGridFloody { 8 | 9 | override protected def include(unit: UnitInfo): Boolean = unit.complete && unit.unitClass.isDetector && ! unit.blind && unit.isEnemy 10 | 11 | override protected def range(unit: UnitInfo): Int = ?(unit.unitClass.isBuilding, 8, Maff.div32(unit.sightPixels)) // Nominally 7 for buildings but 8 might help us avoid dumb DT suicides 12 | 13 | override val margin: Int = 2 14 | } -------------------------------------------------------------------------------- /src/Micro/Actions/Basic/Addon.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Basic 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.{BuildIntent, Commander} 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object Addon extends Action { 8 | 9 | def addonIntent(unit: FriendlyUnitInfo): Option[BuildIntent] = unit.intent.toBuild.find(b => b.unitClass.isAddon && b.startNow) 10 | 11 | override def allowed(unit: FriendlyUnitInfo): Boolean = addonIntent(unit).isDefined 12 | 13 | override def perform(unit: FriendlyUnitInfo): Unit = { 14 | addonIntent(unit).foreach(b => Commander.addon(unit, b.unitClass)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Micro/Coordination/Coordinator.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination 2 | 3 | import Lifecycle.With 4 | import Micro.Coordination.Pathing.GridPathOccupancy 5 | import Micro.Coordination.Pushing.Pushes 6 | 7 | class Coordinator { 8 | 9 | val damageTracker = new DamageTracker 10 | val occupancy = new GridPathOccupancy 11 | val pushes = new Pushes 12 | val healing = new Healing 13 | 14 | def onAgentCycle(): Unit = { 15 | damageTracker.update() 16 | occupancy.update() 17 | pushes.update() 18 | With.units.playerOwned.foreach(_.resetTargeting()) 19 | healing.update() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Strategery/Strategies/AllChoices.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Strategies 2 | 3 | import Strategery.Strategies.AllRaces.Sandbox 4 | import Strategery.Strategies.Protoss.ProtossChoices 5 | import Strategery.Strategies.Terran.TerranChoices 6 | import Strategery.Strategies.Zerg.ZergChoices 7 | 8 | object AllChoices { 9 | def treeVsKnownRace : Seq[Strategy] = TerranChoices.all ++ ProtossChoices.all ++ ZergChoices.all :+ Sandbox 10 | def treeVsRandom : Seq[Strategy] = TerranChoices.tvr ++ ProtossChoices.pvr ++ ZergChoices.zvr :+ Sandbox 11 | def tree : Seq[Strategy] = (treeVsKnownRace ++ treeVsRandom).distinct 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/ReportCard.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | import Information.Battles.Types.Battle 4 | 5 | class ReportCard(val simulacrum: Simulacrum, val estimation: Battle) { 6 | val damageDealt : Double = simulacrum.damageDealt 7 | val damageReceived : Double = simulacrum.damageReceived 8 | val alive : Boolean = simulacrum.alive 9 | val kills : Int = simulacrum.kills 10 | val events : Iterable[SimulationEvent] = simulacrum.events.toVector 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ProtossStrategies/FingerprintGatewayFirst.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ProtossStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Protoss 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintGatewayFirst extends FingerprintOr( 9 | With.fingerprints.oneGateCore, 10 | With.fingerprints.twoGate, 11 | With.fingerprints.fourGateGoon, 12 | new FingerprintCompleteBy(Protoss.Gateway, GameTime(2, 40)), 13 | new FingerprintArrivesBy(Protoss.Zealot, GameTime(3, 45))) { 14 | 15 | override val sticky = true 16 | } 17 | -------------------------------------------------------------------------------- /src/Placement/Architecture/GridExclusion.scala: -------------------------------------------------------------------------------- 1 | package Placement.Architecture 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridVersionedValue 4 | import Mathematics.Points.Tile 5 | 6 | class GridExclusion extends AbstractGridVersionedValue[Option[Exclusion]] { 7 | override val defaultValue: Option[Exclusion] = None 8 | override protected val values: Array[Option[Exclusion]] = Array.fill(length)(defaultValue) 9 | def excludes(tile: Tile, request: Option[BuildingPlacement] = None): Boolean = { 10 | if ( ! tile.valid) return true 11 | val i = tile.i 12 | isSet(i) && request != values(tile.i).flatMap(_.request) 13 | } 14 | } -------------------------------------------------------------------------------- /src/ProxyBwapi/UnitInfo/Targeter.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.UnitInfo 2 | 3 | import Lifecycle.With 4 | import Micro.Targeting.TargetScoring 5 | import Performance.Cache 6 | 7 | import scala.collection.mutable 8 | 9 | trait Targeter { 10 | 11 | def targetScore(target: UnitInfo): Double = { 12 | targetScores.getOrElseUpdate( 13 | target.id, 14 | new Cache[Double](() => 15 | With.units.getId(target.id) 16 | .map(target => TargetScoring.slow(this.asInstanceOf[FriendlyUnitInfo], target)) 17 | .getOrElse(0.0)))() 18 | } 19 | 20 | val targetScores = new mutable.HashMap[Int, Cache[Double]]() 21 | } -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintGasSteal.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import ProxyBwapi.UnitInfo.UnitInfo 6 | import Utilities.Time.Minutes 7 | 8 | class FingerprintGasSteal extends Fingerprint { 9 | override protected def investigate: Boolean = stolenGas.nonEmpty 10 | override def lockAfter: Int = Minutes(5)() 11 | override def reason: String = f"Stolen: [${stolenGas.mkString(", ")}]" 12 | override val sticky = true 13 | protected def stolenGas: Vector[UnitInfo] = With.geography.ourMain.gas.filter(_.isEnemy) 14 | } 15 | -------------------------------------------------------------------------------- /src/Information/Grids/Movement/GridUnwalkableUnits.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Movement 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridVersioned 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.{Terran, Zerg} 6 | 7 | final class GridUnwalkableUnits extends AbstractGridVersioned { 8 | 9 | override protected def updateCells() { 10 | With.units.all 11 | .foreach(unit => 12 | if ((unit.unitClass.isBuilding || unit.isAny(Zerg.Egg, Zerg.LurkerEgg)) 13 | && ! unit.flying 14 | && ! unit.is(Terran.SiegeTankSieged)) { 15 | unit.tiles.foreach(stamp) 16 | }) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Planning/Proxy/ProxyRequest.scala: -------------------------------------------------------------------------------- 1 | package Planning.Proxy 2 | 3 | import Lifecycle.With 4 | import Macro.Requests.RequestBuildable 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | import Tactic.Squads.Squad 7 | 8 | class ProxyRequest(val request: RequestBuildable, val unit: Option[FriendlyUnitInfo], val squad: Option[Squad]) { 9 | val frameCreated: Int = With.frame 10 | def this(unit: FriendlyUnitInfo, requestBuildable: RequestBuildable) = { 11 | this(requestBuildable, Some(unit), None) 12 | } 13 | def this(squad: Squad, requestBuildable: RequestBuildable) = { 14 | this(requestBuildable, None, Some(squad)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Planning/ResourceLocks/LockTiles.scala: -------------------------------------------------------------------------------- 1 | package Planning.ResourceLocks 2 | 3 | import Lifecycle.With 4 | import Macro.Allocation.Prioritized 5 | import Mathematics.Points.Tile 6 | 7 | class LockTiles(val owner: Prioritized) { 8 | 9 | private var _tiles: Seq[Tile] = Seq.empty 10 | var satisfied: Boolean = false 11 | 12 | def tiles: Seq[Tile] = _tiles 13 | 14 | def acquireTiles(tiles: Seq[Tile]): Boolean = { 15 | release() 16 | _tiles = tiles 17 | owner.prioritize() 18 | With.groundskeeper.satisfy(this) 19 | } 20 | 21 | def release(): Unit = { 22 | With.groundskeeper.release(this) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Strategery/Rolling.scala: -------------------------------------------------------------------------------- 1 | package Strategery 2 | 3 | import Lifecycle.With 4 | 5 | import scala.collection.mutable 6 | import scala.util.Random 7 | 8 | trait Rolling { 9 | val rolls: mutable.HashMap[String, Boolean] = new mutable.HashMap 10 | def roll(key: String, probability: Double): Boolean = { 11 | if ( ! rolls.contains(key)) { 12 | val rolled = Random.nextDouble() 13 | val success = rolled <= probability 14 | With.logger.debug(f"Roll for $key ${if (success) "PASSED" else "FAILED"} (Rolled $rolled into probability $probability)") 15 | rolls(key) = success 16 | } 17 | rolls(key) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Mathematics/Points/AbstractPoint.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Points 2 | 3 | abstract class AbstractPoint(val x: Int, val y: Int) { 4 | 5 | @inline final def length : Double = Math.sqrt(lengthSquared) 6 | @inline final def lengthSquared : Double = x * x + y * y 7 | 8 | def direction: Direction = new Direction(this) 9 | 10 | protected final val radiansOverDegrees = 2.0 * Math.PI / 256.0 11 | 12 | @inline final def asPixel: Pixel = Pixel(x, y) 13 | @inline final def asTile: Tile = Tile(x, y) 14 | @inline final def asPoint: Point = Point(x, y) 15 | 16 | override def toString: String = "[" + x + ", " + y + "]" 17 | } 18 | -------------------------------------------------------------------------------- /src/Micro/Actions/Terran/Scan.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Terran 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.Races.Terran 6 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 7 | 8 | object Scan extends Action { 9 | 10 | override def allowed(unit: FriendlyUnitInfo): Boolean = { 11 | unit.intent.toScan.isDefined 12 | } 13 | 14 | override def perform(unit: FriendlyUnitInfo): Unit = { 15 | Commander.useTechOnPixel(unit, Terran.ScannerSweep, unit.intent.toScan.get) 16 | // Ensure we don't spam scan in the absence of a new intention 17 | unit.intent.toScan = None 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /configs/PurpleWaveAIIDE.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "human" : false, 3 | "ladder" : false, 4 | "livestream" : false, 5 | "tournament" : true, 6 | "roundrobin" : true, 7 | "elimination" : false, 8 | "pretraining" : false, 9 | "debugging" : false, 10 | "debugginglive" : false, 11 | "logstd" : false, 12 | "multiCPU" : true, 13 | "framemstarget" : 35, 14 | "framemslimit" : 35, 15 | "comments" : "AIIDE enforces a 55ms frame duration. We set the limit lower due to 16ms timer resolution. We expect enough JVM memory for a framebuffer, and can dictate our memory ceiling through run_proxy.bat." 16 | } -------------------------------------------------------------------------------- /configs/PurpleWaveSCHNAIL.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "human" : true, 3 | "ladder" : false, 4 | "livestream" : false, 5 | "tournament" : false, 6 | "roundrobin" : false, 7 | "elimination" : false, 8 | "pretraining" : false, 9 | "debugging" : false, 10 | "debugginglive" : false, 11 | "logstd" : false, 12 | "multiCPU" : true, 13 | "framemstarget" : 35, 14 | "framemslimit" : 35, 15 | "comments" : "SCHNAIL enforces a 55ms frame duration. We expect enough JVM memory for a framebuffer, and can dictate our memory ceiling through run_proxy.bat. Treating the limit as lower due to 16ms timer resolution" 16 | } -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint1BaseBioMech.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintOr} 4 | import Lifecycle.With 5 | import Utilities.Time.Minutes 6 | 7 | class Fingerprint1BaseBioMech extends FingerprintAnd( 8 | new FingerprintOr( 9 | With.fingerprints.bio, 10 | With.fingerprints.twoRaxAcad), 11 | new FingerprintOr( 12 | With.fingerprints.oneFac, 13 | With.fingerprints.twoFac, 14 | With.fingerprints.threeFac)) { 15 | override val sticky: Boolean = true 16 | override val lockAfter: Int = Minutes(6)() 17 | } 18 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint3FacVultures.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintArrivesBy, FingerprintOr} 4 | import ProxyBwapi.Races.Terran 5 | import Utilities.Time.GameTime 6 | 7 | class Fingerprint3FacVultures extends FingerprintOr( 8 | // You can actually get 3 arriving by 5:13 by making 3 Vultures in a row out of an ordinary Factory timing 9 | //new FingerprintArrivesBy(Terran.Vulture, GameTime(5, 30), 3), 10 | new FingerprintArrivesBy(Terran.Vulture, GameTime(5, 50), 5), 11 | new FingerprintArrivesBy(Terran.Vulture, GameTime(6, 10), 8), 12 | ) -------------------------------------------------------------------------------- /src/Strategery/Selection/StrategySelectionDynamic.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Selection 2 | 3 | import Lifecycle.With 4 | import Mathematics.Maff 5 | import Strategery.Strategies.StrategyBranch 6 | 7 | object StrategySelectionDynamic extends StrategySelectionPolicy { 8 | 9 | def chooseBranch: StrategyBranch = { 10 | sample(16) 11 | } 12 | 13 | def sample(probabilityExponent: Double): StrategyBranch = { 14 | val branches = Maff.orElse(With.strategy.strategyBranchesLegal, With.strategy.strategyBranchesAll).toSeq 15 | Maff.sampleWeighted(branches, (branch: StrategyBranch) => Math.pow(WinProbability(branch), probabilityExponent)).get 16 | } 17 | } -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/ShowStoryteller.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views 2 | 3 | import Debugging.Visualizations.Rendering.DrawScreen 4 | import Lifecycle.With 5 | import Utilities.Time.Seconds 6 | 7 | //import scala.collection.JavaConverters._ 8 | 9 | object ShowStoryteller extends DebugView { 10 | val duration = Seconds(10)() 11 | 12 | override def renderScreen(): Unit = { 13 | val lines = With.storyteller.tales.view.filter(s => s.frame > 0 && With.framesSince(s.frame) < duration).flatMap(_.tale.lines).toVector 14 | DrawScreen.column(160, 331 - lines.length * (2 + With.visualization.lineHeightSmall), lines) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Skimulation/SkimulationUnit.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Skimulation 2 | 3 | import ProxyBwapi.UnitInfo.UnitInfo 4 | 5 | trait SkimulationUnit { 6 | var skimDistanceToEngage : Double = _ 7 | var skimStrength : Double = _ 8 | var skimMagic : Double = _ 9 | var skimDelay : Double = _ 10 | var skimExtension : Double = _ 11 | var skimPresence : Double = _ 12 | // Only for debug/display purposes 13 | var skimStrengthDisplay : Double = _ 14 | var skimPresenceDisplay : Double = _ 15 | var skimTarget : Option[UnitInfo] = None 16 | } 17 | -------------------------------------------------------------------------------- /src/Micro/Coordination/Pushing/UnitLinearGroundPush.scala: -------------------------------------------------------------------------------- 1 | package Micro.Coordination.Pushing 2 | 3 | import Mathematics.Physics.Force 4 | import Mathematics.Points.Pixel 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | import Utilities.? 7 | 8 | class UnitLinearGroundPush(val priority: TrafficPriority, val pusher: FriendlyUnitInfo, val destination: Pixel) extends LinearPush { 9 | override protected def source: Pixel = pusher.pixel 10 | override protected val sourceWidth: Double = pusher.unitClass.dimensionMax 11 | override def force(recipient: FriendlyUnitInfo): Option[Force] = ?(recipient == pusher || recipient.flying, None, super.force(recipient)) 12 | } 13 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/SimulationEventMove.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | import Debugging.Visualizations.Rendering.DrawMap 4 | import Mathematics.Points.Pixel 5 | 6 | final case class SimulationEventMove(sim: Simulacrum, to: Pixel, reason: Option[String] = None) extends SimulationEvent(sim) { 7 | 8 | override def toString: String = f"$frame: ${sim.describe} targeting ${describe(target)} ${describePixel(targetAt)} moves from ${sim.pixel} towards $to ${reason.map(": " + _).getOrElse("")}" 9 | 10 | override def draw(): Unit = { 11 | DrawMap.arrow(from, to, sim.realUnit.player.colorMedium) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Micro/Targeting/FiltersRequired/TargetFilterVulture.scala: -------------------------------------------------------------------------------- 1 | package Micro.Targeting.FiltersRequired 2 | 3 | import Lifecycle.With 4 | import Micro.Targeting.TargetFilter 5 | import ProxyBwapi.Races.Terran 6 | import ProxyBwapi.UnitInfo.{FriendlyUnitInfo, UnitInfo} 7 | import Utilities.Time.Minutes 8 | 9 | object TargetFilterVulture extends TargetFilter { 10 | private val cutoff = Minutes(4)() 11 | override def appliesTo(actor: FriendlyUnitInfo): Boolean = Terran.Vulture(actor) && With.frame < cutoff 12 | override def legal(actor: FriendlyUnitInfo, target: UnitInfo): Boolean = { 13 | target.unitClass.canAttack || ! target.unitClass.isBuilding 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Placement/Generation/TileGeneratorProximity.scala: -------------------------------------------------------------------------------- 1 | package Placement.Generation 2 | 3 | import Information.Geography.Types.Zone 4 | import Mathematics.Points.Tile 5 | 6 | import scala.collection.immutable.VectorIterator 7 | 8 | class TileGeneratorProximity(origin: Tile, zone: Zone, maximumDistance: Int = 256) extends TileGenerator { 9 | val tiles : Vector[Tile] = zone.tiles.view.filter(_.tileDistanceFast(origin) < maximumDistance).toVector.sortBy(_.tileDistanceSquared(origin)) 10 | val iterator: VectorIterator[Tile] = tiles.iterator 11 | 12 | override def next(): Tile = iterator.next() 13 | override def hasNext: Boolean = iterator.hasNext 14 | } 15 | -------------------------------------------------------------------------------- /src/Micro/Actions/Basic/Unstick.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Basic 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.Races.Protoss 6 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 7 | 8 | object Unstick extends Action { 9 | 10 | override def allowed(unit: FriendlyUnitInfo): Boolean = ( 11 | unit.canMove 12 | && ! unit.flying 13 | && ! unit.loaded 14 | && ! unit.unitClass.floats 15 | && ! Protoss.Reaver(unit) 16 | && unit.canAttack 17 | && unit.seeminglyStuck 18 | ) 19 | 20 | override protected def perform(unit: FriendlyUnitInfo): Unit = { 21 | Commander.stop(unit) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Strategery/Strategies/Protoss/PvRStrategies.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Strategies.Protoss 2 | 3 | import Gameplans.Protoss.PvR.{PvR2Gate4Gate, PvRDT} 4 | import Planning.Plans.Plan 5 | import Strategery.Strategies.Strategy 6 | import bwapi.Race 7 | 8 | abstract class PvRStrategy extends Strategy { 9 | override def ourRaces : Seq[Race] = Vector(Race.Protoss) 10 | override def enemyRaces : Seq[Race] = Vector(Race.Unknown) 11 | } 12 | 13 | object PvR2Gate4Gate extends PvRStrategy { 14 | override def gameplan: Option[Plan] = Some(new PvR2Gate4Gate) 15 | } 16 | 17 | object PvRDT extends PvRStrategy { 18 | override def gameplan: Option[Plan] = Some(new PvRDT) 19 | } -------------------------------------------------------------------------------- /src/Information/Battles/Types/JudgmentModifier.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Types 2 | 3 | import Debugging.Visualizations.Colors 4 | import Utilities.? 5 | import bwapi.Color 6 | 7 | case class JudgmentModifier( 8 | var name : String = "Modifier", 9 | var color : Color = Colors.DarkGray, 10 | speedMultiplier : Double = 1, 11 | targetDelta : Double = 0) { 12 | 13 | override def toString: String = f"$name${format("S", 1, speedMultiplier)}${format("T", 0, targetDelta)}" 14 | 15 | private def format(name: String, default: Double, value: Double): String = { 16 | ?(value == default, "", f" $name: ${"%1.2f".format(value)}") 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintExistsBy.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import Utilities.UnitFilters.UnitFilter 6 | import Utilities.Time.GameTime 7 | 8 | class FingerprintExistsBy(unitMatcher: UnitFilter, gameTime: GameTime, quantity: Int = 1) extends Fingerprint { 9 | override def investigate: Boolean = With.frame < gameTime() && observed >= quantity 10 | protected def observed: Int = With.units.countEverEnemyP(unitMatcher) 11 | override def reason: String = f"$observed $unitMatcher exist by $gameTime" 12 | override val sticky: Boolean = true 13 | } 14 | -------------------------------------------------------------------------------- /src/ProxyBwapi/Buildable.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi 2 | 3 | import ProxyBwapi.Techs.Tech 4 | import ProxyBwapi.UnitClasses.UnitClass 5 | import ProxyBwapi.Upgrades.Upgrade 6 | import bwapi.Race 7 | 8 | trait Buildable { 9 | def race: Race 10 | def productionFrames(quantity: Int): Int 11 | def mineralCost(quantity: Int): Int 12 | def gasCost(quantity: Int): Int 13 | def supplyProvided: Int 14 | def supplyRequired: Int 15 | 16 | lazy val asUnit : Option[UnitClass] = Option(asInstanceOf[UnitClass]) 17 | lazy val asTech : Option[Tech] = Option(asInstanceOf[Tech]) 18 | lazy val asUpgrade : Option[Upgrade] = Option(asInstanceOf[Upgrade]) 19 | } 20 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint2HatchGas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintGasCompleteBy, FingerprintNot, FingerprintOr} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.ThreeHatchGasCompleteBy 5 | import Lifecycle.With 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint2HatchGas extends FingerprintAnd( 9 | new FingerprintNot(With.fingerprints.oneHatchGas), 10 | new FingerprintOr( 11 | new FingerprintGasCompleteBy(ThreeHatchGasCompleteBy - Seconds(5)), 12 | With.fingerprints.tenHatchPoolGas, 13 | With.fingerprints.twelveHatchPoolGas)) -------------------------------------------------------------------------------- /src/Mathematics/Points/Point.scala: -------------------------------------------------------------------------------- 1 | package Mathematics.Points 2 | 3 | import Mathematics.Maff 4 | 5 | case class Point(argX: Int, argY: Int) extends AbstractPoint(argX, argY) { 6 | @inline final def degreesTo(other: Point): Double = { 7 | radiansTo(other) * Maff.x2PiInv360 8 | } 9 | @inline final def radiansTo(other: Point): Double = { 10 | Maff.fastAtan2(other.y - y, other.x - x) 11 | } 12 | 13 | @inline def radiansToSlow(other: Pixel): Double = { 14 | Math.atan2(other.y - y, other.x - x) 15 | } 16 | @inline final def distanceSquared(other: Point): Double = { 17 | val dx = x - other.x 18 | val dy = y - other.y 19 | dx * dx + dy * dy 20 | } 21 | } -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint12Hatch11Pool.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintCompleteBy, FingerprintNot} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.TwelveHatch13Hatch12Pool_PoolCompleteBy 5 | import Lifecycle.With 6 | import ProxyBwapi.Races.Zerg 7 | import Utilities.Time.Seconds 8 | 9 | class Fingerprint12Hatch11Pool extends FingerprintAnd( 10 | With.fingerprints.twelveHatch, 11 | new FingerprintNot(With.fingerprints.twelveHatchHatch), 12 | new FingerprintCompleteBy(Zerg.SpawningPool, TwelveHatch13Hatch12Pool_PoolCompleteBy - Seconds(3))) 13 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint2HatchMain.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import Utilities.UnitFilters.IsHatchlike 6 | import ProxyBwapi.UnitInfo.UnitInfo 7 | 8 | class Fingerprint2HatchMain extends Fingerprint { 9 | override protected def investigate: Boolean = { 10 | hatcheries.forall(_.base.exists(_.isMain)) && hatcheries.size > 1 11 | } 12 | 13 | override def reason: String = hatcheries.mkString(", ") 14 | 15 | override val sticky = true 16 | 17 | protected def hatcheries: Iterable[UnitInfo] = With.units.enemy.filter(IsHatchlike) 18 | } 19 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint3HatchHydra.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintArrivesBy, FingerprintCompleteBy, FingerprintOr} 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Zerg 6 | import Utilities.Time.GameTime 7 | 8 | class Fingerprint3HatchHydra extends FingerprintAnd( 9 | With.fingerprints.threeHatchGas, 10 | new FingerprintOr( 11 | new FingerprintCompleteBy(Zerg.HydraliskDen, GameTime(5, 0)), // Earliest observed: 4:37 12 | new FingerprintCompleteBy(Zerg.Hydralisk, GameTime(5, 18)), 13 | new FingerprintArrivesBy(Zerg.Hydralisk, GameTime(5, 48)))) -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint1RaxFE.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintCompleteBy, FingerprintOr} 4 | import ProxyBwapi.Races.Terran 5 | import Utilities.Time.GameTime 6 | 7 | class Fingerprint1RaxFE extends FingerprintAnd( 8 | new FingerprintOr( 9 | new FingerprintCompleteBy(Terran.Barracks, GameTime(3, 20)), 10 | new FingerprintCompleteBy(Terran.Marine, GameTime(3, 35)), 11 | new FingerprintCompleteBy(Terran.Bunker, GameTime(3, 39))), 12 | new FingerprintCompleteBy(Terran.CommandCenter, GameTime(4, 30), 2)) { 13 | override val sticky = true 14 | } 15 | -------------------------------------------------------------------------------- /src/Macro/Scheduling/Scheduler.scala: -------------------------------------------------------------------------------- 1 | package Macro.Scheduling 2 | 3 | import Macro.Requests.{RequestAutosupply, RequestBuildable} 4 | 5 | import scala.collection.mutable 6 | 7 | class Scheduler { 8 | private val _requests = new mutable.ArrayBuffer[ScheduleItem] 9 | 10 | def reset(): Unit = { 11 | _requests.clear() 12 | } 13 | 14 | def request(requester: Any, theRequest: RequestBuildable): Unit = { 15 | if (theRequest.tech.isDefined || theRequest.quantity > 0 || theRequest == RequestAutosupply) { 16 | _requests += ScheduleItem(requester, theRequest) 17 | } 18 | } 19 | 20 | def requests: Vector[ScheduleItem] = { 21 | _requests.toVector 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Performance/Cache.scala: -------------------------------------------------------------------------------- 1 | package Performance 2 | 3 | import Lifecycle.With 4 | 5 | class Cache[T](getValue: () => T, refreshPeriod: Int = 1) { 6 | private var nextUpdateFrame: Int = 0 7 | private var lastValue: T = _ 8 | private val defaultValue: T = lastValue 9 | 10 | @inline final def apply(): T = { 11 | if (With.frame >= nextUpdateFrame) { 12 | nextUpdateFrame = With.frame + refreshPeriod 13 | lastValue = getValue() 14 | } 15 | lastValue 16 | } 17 | 18 | @inline final def invalidate(): Unit = { 19 | nextUpdateFrame = With.frame 20 | lastValue = defaultValue 21 | } 22 | 23 | override def toString: String = apply().toString 24 | } 25 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint3HatchMuta.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintCompleteByArrivesBy, FingerprintNot, FingerprintOr} 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Zerg 6 | import Utilities.Time.GameTime 7 | 8 | class Fingerprint3HatchMuta extends FingerprintAnd( 9 | 10 | new FingerprintNot( 11 | With.fingerprints.oneHatchMuta, 12 | With.fingerprints.twoHatchMuta), 13 | 14 | new FingerprintOr( 15 | new FingerprintCompleteByArrivesBy(Zerg.Spire, GameTime(7, 35)), 16 | new FingerprintCompleteByArrivesBy(Zerg.Mutalisk, GameTime(8, 0)))) 17 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint9PoolHatch.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.NinePool13Hatch_HatchCompleteBy 5 | import Lifecycle.With 6 | import Utilities.UnitFilters.IsHatchlike 7 | import Utilities.Time.{GameTime, Seconds} 8 | 9 | class Fingerprint9PoolHatch extends FingerprintAnd( 10 | With.fingerprints.ninePool, 11 | new FingerprintNot(With.fingerprints.ninePoolGas), 12 | new FingerprintOr( 13 | new FingerprintCompleteBy(IsHatchlike, NinePool13Hatch_HatchCompleteBy + Seconds(5)), 14 | new FingerprintGasEmptyUntil(GameTime(1, 56)))) -------------------------------------------------------------------------------- /src/Micro/Actions/Scouting/Scout.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Scouting 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object Scout extends Action { 8 | 9 | override def allowed(unit: FriendlyUnitInfo): Boolean = unit.agent.isScout 10 | 11 | override protected def perform(unit: FriendlyUnitInfo): Unit = { 12 | DroneWarfare(unit) 13 | Harass4PoolWorkers(unit) 14 | SabotageProxy(unit) 15 | KnockKnock(unit) 16 | PreserveScout(unit) 17 | AttackBuilder(unit) 18 | BlockConstruction(unit) 19 | Search(unit) 20 | SearchWhenBored(unit) 21 | Commander.move(unit) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Utilities/Time/FrameCount.scala: -------------------------------------------------------------------------------- 1 | package Utilities.Time 2 | 3 | abstract class FrameCount(frames: Int) { 4 | 5 | def apply(): Int = frames 6 | final def totalSeconds: Int = frames / 24 7 | final def seconds: Int = totalSeconds % 60 8 | final def minutes: Int = totalSeconds / 60 9 | 10 | final def +(other: FrameCount) : FrameCount = Frames(this() + other()) 11 | final def -(other: FrameCount) : FrameCount = Frames(this() - other()) 12 | final def +(other: Int) : FrameCount = Frames(this() + other) 13 | final def -(other: Int) : FrameCount = Frames(this() - other) 14 | 15 | final override def toString: String = minutes + ":" + "%02d".format(seconds) 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/CPCount.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction 2 | 3 | import Information.Battles.Prediction.Simulation.Simulacrum 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | import scala.collection.mutable.ArrayBuffer 7 | 8 | object CPCount { 9 | @inline def apply(units: ArrayBuffer[UnitInfo], extract: Simulacrum => Double): Double = { 10 | var output = 0.0 11 | val length = units.length 12 | var i = 0 13 | while (i < length) { 14 | val simulacrum = units(i).simulacrum 15 | if (simulacrum.shouldScoreIfOurs || simulacrum.isEnemy) { 16 | output += extract(simulacrum) 17 | } 18 | i += 1 19 | } 20 | output 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/TerranStrategies/Fingerprint2PortWraith.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.TerranStrategies 2 | 3 | import Information.Fingerprinting.Generic._ 4 | import ProxyBwapi.Races.Terran 5 | import Utilities.Time.GameTime 6 | 7 | class Fingerprint2PortWraith extends FingerprintOr( 8 | new FingerprintCompleteBy(Terran.Starport, GameTime(5, 15), 2), 9 | new FingerprintCompleteBy(Terran.Wraith, GameTime(5, 30), 2), 10 | new FingerprintCompleteBy(Terran.Wraith, GameTime(6, 10), 4), 11 | new FingerprintArrivesBy(Terran.Wraith, GameTime(5, 55), 2), 12 | new FingerprintArrivesBy(Terran.Wraith, GameTime(6, 35), 4)) { 13 | 14 | override val sticky = true 15 | } 16 | -------------------------------------------------------------------------------- /src/Macro/Actions/BuildOnce.scala: -------------------------------------------------------------------------------- 1 | package Macro.Actions 2 | 3 | import Lifecycle.With 4 | import Macro.Requests.{RequestBuildable, RequestUnit} 5 | 6 | object BuildOnce { 7 | def apply(requester: Any, request: RequestBuildable): Unit = { 8 | With.scheduler.request( 9 | requester, 10 | if (request.unit.forall(_.isBuilding) || request.quantity <= 0) request else { 11 | val unit = request.unit.get 12 | val quantityLost = Math.max(0, With.productionHistory.doneAllTime(unit) - With.macroCounts.oursComplete(unit)) 13 | val quantityToRequest = request.quantity - quantityLost 14 | RequestUnit(unit, quantityToRequest) 15 | }) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Macro/Actions/SneakyCitadel.scala: -------------------------------------------------------------------------------- 1 | package Macro.Actions 2 | 3 | import Lifecycle.With 4 | import ProxyBwapi.Races.Protoss 5 | import Utilities.Time.Seconds 6 | 7 | object SneakyCitadel extends MacroActions { 8 | def apply(): Unit = { 9 | if (scoutCleared) { 10 | get(Protoss.CitadelOfAdun) 11 | cancel(Protoss.AirDamage) 12 | } else if (units(Protoss.CitadelOfAdun) == 0) { 13 | if (With.units.ours.find(_.upgradeProducing.contains(Protoss.AirDamage)).exists(_.remainingUpgradeFrames < Seconds(5)())) { 14 | cancel(Protoss.AirDamage) 15 | } else if ( ! upgradeStarted(Protoss.DragoonRange)) { 16 | get(Protoss.AirDamage) 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Performance/Timer.scala: -------------------------------------------------------------------------------- 1 | package Performance 2 | 3 | import Lifecycle.With 4 | 5 | class Timer(duration: Long = With.performance.msBeforeTarget) { 6 | private def now = With.performance.systemMillis 7 | val start: Long = now 8 | def elapsed: Long = if (With.performance.frameHitBreakpoint) 0 else now - start 9 | def remaining: Long = remainingUntil(start + duration) 10 | def remainingUntil(milliseconds: Long): Long = 11 | if (With.performance.frameHitBreakpoint) 12 | With.configuration.frameTargetMs 13 | else 14 | milliseconds - now 15 | def redLight : Boolean = remaining <= 0 && With.configuration.enablePerformancePauses 16 | def greenLight : Boolean = ! redLight 17 | } 18 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintHasExpanded.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import ProxyBwapi.Races.Terran 6 | import Utilities.Time.Forever 7 | 8 | class FingerprintHasExpanded(by: Int = Forever()) extends Fingerprint { 9 | override val sticky = true 10 | override def investigate: Boolean = With.frame < by && With.enemies.exists(e => { 11 | var output = e.bases.size > 1 12 | output ||= With.units.enemy.exists(u => Terran.CommandCenter(u) && u.player == e && ! u.base.exists(_.townHallTile == u.tileTopLeft)) 13 | output ||= e.bases.exists( ! _.isMain) 14 | output 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /src/Information/Grids/Vision/GridLastSeen.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Vision 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridFramestamp 4 | import Lifecycle.With 5 | import Mathematics.Points.Tile 6 | 7 | class GridLastSeen extends AbstractGridFramestamp { 8 | 9 | def hasSeen(tile: Tile): Boolean = get(tile) > 0 10 | def hasSeen(i: Int): Boolean = get(i) > 0 11 | 12 | override protected def updateCells() { 13 | var x = 0 14 | while (x < With.mapTileWidth) { 15 | var y = 0 16 | while (y < With.mapTileHeight) { 17 | if (With.game.isVisible(x, y)) { 18 | stamp(x, y) 19 | } 20 | y += 1 21 | } 22 | x += 1 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Micro/Actions/Scouting/PreserveScout.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Scouting 2 | 3 | import Micro.Actions.Action 4 | import Micro.Actions.Combat.Maneuvering.Retreat 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | 7 | object PreserveScout extends Action { 8 | 9 | override def allowed(unit: FriendlyUnitInfo): Boolean = ( 10 | (unit.matchups.framesOfSafety <= 24 11 | && unit.matchups.threats.exists( ! _.unitClass.isWorker)) 12 | || unit.totalHealth < 6 13 | ) 14 | 15 | override protected def perform(unit: FriendlyUnitInfo): Unit = { 16 | // FindBuildings can usually safely path around threats 17 | SearchWhenBored.delegate(unit) 18 | Retreat.delegate(unit) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint12Pool.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintCompleteBy, FingerprintNot} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.Latest_TwelvePool_PoolCompleteBy 5 | import Lifecycle.With 6 | import ProxyBwapi.Races.Zerg 7 | 8 | class Fingerprint12Pool extends FingerprintAnd( 9 | new FingerprintNot(With.fingerprints.fourPool), 10 | new FingerprintNot(With.fingerprints.ninePool), 11 | new FingerprintNot(With.fingerprints.overpool), 12 | new FingerprintCompleteBy(Zerg.SpawningPool, Latest_TwelvePool_PoolCompleteBy) // Going past 10 seconds intersects10h9p 13 | ) 14 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint4Pool.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintArrivesBy, FingerprintCompleteBy, FingerprintOr} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.{Latest_FourPool_PoolCompleteBy, Latest_FourPool_ZerglingArrivesBy, Latest_FourPool_ZerglingCompleteBy} 5 | import ProxyBwapi.Races.Zerg 6 | 7 | class Fingerprint4Pool extends FingerprintOr( 8 | new FingerprintCompleteBy(Zerg.SpawningPool, Latest_FourPool_PoolCompleteBy), 9 | new FingerprintArrivesBy(Zerg.Zergling, Latest_FourPool_ZerglingArrivesBy), 10 | new FingerprintCompleteBy(Zerg.Zergling, Latest_FourPool_ZerglingCompleteBy)) -------------------------------------------------------------------------------- /src/Micro/Actions/Combat/Spells/WraithUncloak.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Combat.Spells 2 | 3 | import Lifecycle.With 4 | import Micro.Actions.Action 5 | import Micro.Agency.Commander 6 | import ProxyBwapi.Races.Terran 7 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 8 | 9 | object WraithUncloak extends Action { 10 | 11 | override def allowed(unit: FriendlyUnitInfo): Boolean = ( 12 | unit.is(Terran.Wraith) 13 | && unit.cloaked 14 | && ! unit.matchups.enemies.exists(_.unitClass.attacksAir) 15 | && With.framesSince(unit.agent.lastCloak) > 24 * 10 16 | ) 17 | 18 | override protected def perform(unit: FriendlyUnitInfo): Unit = { 19 | Commander.decloak(unit, Terran.GhostCloak) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Micro/Actions/Terran/GetRepairedBuilding.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Terran 2 | 3 | import Micro.Actions.Action 4 | import ProxyBwapi.Races.Terran 5 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 6 | import Utilities.? 7 | 8 | object GetRepairedBuilding extends Action { 9 | 10 | override def allowed(unit: FriendlyUnitInfo): Boolean = ( 11 | unit.unitClass.isTerran 12 | && unit.unitClass.isBuilding 13 | && unit.complete 14 | && ?( 15 | unit.isAny(Terran.Bunker, Terran.MissileTurret), 16 | unit.hitPoints < unit.unitClass.maxHitPoints, 17 | unit.hitPoints * 2 < unit.unitClass.maxHitPoints)) 18 | 19 | override def perform(unit: FriendlyUnitInfo): Unit = { 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/DebugView.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views 2 | 3 | import Debugging.ToString 4 | import Lifecycle.With 5 | 6 | abstract class DebugView { 7 | 8 | lazy val name: String = ToString(this).replace("Show", "") 9 | 10 | def renderScreen(): Unit = {} 11 | def renderMap(): Unit = {} 12 | 13 | def inUse: Boolean = ( 14 | With.visualization.enabled 15 | && (With.visualization.map || With.visualization.screen) 16 | && With.visualization.views.contains(this) 17 | ) 18 | 19 | def mapInUse: Boolean = { 20 | inUse && With.visualization.map 21 | } 22 | 23 | def screenInUse: Boolean = { 24 | inUse && With.visualization.screen 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Information/Battles/Prediction/Simulation/BehaviorGather.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Prediction.Simulation 2 | 3 | import Mathematics.Maff 4 | import Utilities.Time.Forever 5 | 6 | object BehaviorGather extends SimulacrumBehavior { 7 | val fighting: Boolean = false 8 | override def act(simulacrum: Simulacrum): Unit = { 9 | val base = Maff.minBy(simulacrum.player.bases)(b => simulacrum.pixel.walkablePixel.groundPixels(b.heart)) 10 | base.foreach(b => { 11 | val to = b.heart.center 12 | if (simulacrum.pixelDistanceCenter(to) > 16) { 13 | simulacrum.move(to, Some("Gather")) 14 | } else { 15 | simulacrum.sleep(Forever(), Some("Gathering")) 16 | } 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Micro/Actions/Combat/Tactics/Potshot.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Combat.Tactics 2 | 3 | import Micro.Actions.Action 4 | import Micro.Targeting.Target 5 | import Micro.Agency.Commander 6 | import Micro.Targeting.FiltersSituational.TargetFilterPotshot 7 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 8 | 9 | object Potshot extends Action { 10 | 11 | override def allowed(unit: FriendlyUnitInfo): Boolean = ( 12 | (unit.tile.enemyVulnerabilityGround > 0 || unit.canAttackAir) 13 | && unit.tile.enemyRangeAgainst(unit) > 0 14 | && unit.readyForAttackOrder) 15 | 16 | override def perform(unit: FriendlyUnitInfo): Unit = { 17 | Target.choose(unit, TargetFilterPotshot) 18 | Commander.attack(unit) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Debugging/Visualizations/Views/Battles/ShowTeams.scala: -------------------------------------------------------------------------------- 1 | package Debugging.Visualizations.Views.Battles 2 | 3 | import Debugging.Visualizations.Colors 4 | import Debugging.Visualizations.Rendering.DrawMap 5 | import Debugging.Visualizations.Views.DebugView 6 | 7 | object ShowTeams extends DebugView { 8 | 9 | override def renderMap(): Unit = { 10 | ShowBattles.localBattle.foreach(battle => { 11 | val team = battle.us 12 | val bright = Colors.BrightTeal 13 | val medium = Colors.MediumTeal 14 | val dark = Colors.DarkTeal 15 | DrawMap.circle(team.centroidAir, 16, bright) 16 | DrawMap.box(team.attackCentroidKey.subtract(16, 16), team.attackCentroidKey.add(16, 16), bright) 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Tactic/Tactics/TacticMeldDarchons.scala: -------------------------------------------------------------------------------- 1 | package Tactic.Tactics 2 | 3 | import Lifecycle.With 4 | import Mathematics.Maff 5 | import ProxyBwapi.Races.Protoss 6 | 7 | class TacticMeldDarchons extends Tactic { 8 | 9 | lock.matcher = Protoss.DarkTemplar 10 | 11 | def launch(): Unit = { 12 | lock.release() // Ditch units that are already Dark Archons 13 | if (With.blackboard.makeDarkArchons()) { 14 | lock.acquire() 15 | val partyCentral = Maff.minBy(With.geography.ourBases)(_.groundPixels(With.scouting.ourMuscleOrigin)).map(_.heart).getOrElse(With.geography.home).center 16 | units.foreach(_.intend(this) 17 | .setShouldMeld(true) 18 | .setTerminus(partyCentral)) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Macro/Allocation/Priorities.scala: -------------------------------------------------------------------------------- 1 | package Macro.Allocation 2 | 3 | import Lifecycle.With 4 | 5 | import scala.collection.mutable 6 | 7 | class Priorities { 8 | private var _lastResetFrame: Int = -1 9 | private var _nextPriority: Int = 0 10 | 11 | val frameDelays: mutable.Queue[Int] = new mutable.Queue[Int] 12 | 13 | def lastResetFrame: Int = _lastResetFrame 14 | 15 | def nextPriority(): Int = { 16 | _nextPriority += 1 17 | _nextPriority - 1 18 | } 19 | 20 | def update() { 21 | frameDelays.enqueue(With.framesSince(_lastResetFrame)) 22 | while(frameDelays.sum > 24 * 10) { 23 | frameDelays.dequeue() 24 | } 25 | _lastResetFrame = With.frame 26 | _nextPriority = 0 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Performance/Tasks/StateTasks.scala: -------------------------------------------------------------------------------- 1 | package Performance.Tasks 2 | 3 | import scala.collection.mutable 4 | 5 | class StateTasks { 6 | private val tasks = new mutable.HashMap[Class[_], DummyTask]() 7 | def get(state: Any): DummyTask = { 8 | val stateClass = state.getClass 9 | if ( ! tasks.contains(stateClass)) { 10 | tasks(stateClass) = new DummyTask(stateClass) 11 | } 12 | tasks(stateClass) 13 | } 14 | 15 | def safeToRun(state: Any, budgetMs: Long): Boolean = { 16 | get(state).safeToRun(budgetMs) 17 | } 18 | 19 | def run(state: Any, runFunction: () => Unit, budgetMs: Long): Unit = { 20 | val task = get(state) 21 | task.runFunction = runFunction 22 | task.run(budgetMs) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/ZergStrategies/Fingerprint3HatchGas.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.ZergStrategies 2 | 3 | import Information.Fingerprinting.Generic.{FingerprintAnd, FingerprintGasCompleteBy, FingerprintNot, FingerprintOr} 4 | import Information.Fingerprinting.ZergStrategies.ZergTimings.ThreeHatchGasCompleteBy 5 | import Lifecycle.With 6 | import Utilities.Time.Seconds 7 | 8 | class Fingerprint3HatchGas extends FingerprintAnd( 9 | new FingerprintNot( 10 | With.fingerprints.oneHatchGas, 11 | With.fingerprints.twoHatchGas), 12 | new FingerprintOr( 13 | With.fingerprints.twelveHatchHatch, 14 | With.fingerprints.twelveHatchPoolHatch, 15 | new FingerprintGasCompleteBy(ThreeHatchGasCompleteBy + Seconds(25)))) 16 | -------------------------------------------------------------------------------- /src/ProxyBwapi/Readme.md: -------------------------------------------------------------------------------- 1 | # ProxyBwapi 2 | 3 | ## Motivation 4 | 5 | BWAPI, as made accessible via BWMirror, has a few limitations: 6 | 7 | * BWAPI only exposes currently available information. Units in the fog of war are inaccessible 8 | * Native BWAPI calls through BWMirror have a substantial overhead. Even a simple call like Game.getFrameCount quickly becomes expensive 9 | * The raw BWAPI type APIs can be confusing and are easily misused (for example, getPixel (unit center) vs getTile (unit corner)) 10 | * The raw BWAPI types aren't extensible 11 | 12 | For those reasons, the rest of PurpleWave interacts with ProxyBwapi. ProxyBwapi provides a faster, safer interface for interacting with the game state, and tracks information on units in the fog of war. 13 | 14 | -------------------------------------------------------------------------------- /src/Information/Fingerprinting/Generic/FingerprintGasEmptyUntil.scala: -------------------------------------------------------------------------------- 1 | package Information.Fingerprinting.Generic 2 | 3 | import Information.Fingerprinting.Fingerprint 4 | import Lifecycle.With 5 | import ProxyBwapi.UnitInfo.UnitInfo 6 | import Utilities.Time.FrameCount 7 | 8 | class FingerprintGasEmptyUntil(time: FrameCount) extends Fingerprint { 9 | override protected def investigate: Boolean = matchingGas.isEmpty 10 | override def sticky: Boolean = With.scouting.enemyMain.isDefined && With.frame >= time() 11 | override def reason: String = f"Gasses: [${matchingGas.mkString(", ")}]" 12 | protected def matchingGas: Iterable[UnitInfo] = With.scouting.enemyMain.toVector.flatMap(_.gas.filter(gas => gas.player.isEnemy && gas.lastSeen < time())) 13 | } 14 | -------------------------------------------------------------------------------- /src/Information/Geography/NeoGeo/MapIdentifier.scala: -------------------------------------------------------------------------------- 1 | package Information.Geography.NeoGeo 2 | 3 | import Mathematics.Maff 4 | import Mathematics.Points.{Pixel, Points} 5 | 6 | object MapIdentifier { 7 | def apply(mapString: String): String = { 8 | mapString.toLowerCase 9 | .replaceAll(".scm", "") 10 | .replaceAll(".scx", "") 11 | .replaceAll("kespa", "") 12 | .replaceAll("iccup", "") 13 | .replaceAll("neo", "") 14 | .replaceAll("new", "") 15 | .replaceAll("[^a-z]", "") 16 | } 17 | 18 | def clock(pixel: Pixel): String = { 19 | val output = Math.round(Maff.normalize0To2Pi(Points.middle.radiansTo(pixel)) * 6 / Math.PI).toInt.toString 20 | if (output == "0") "12" else output 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /configs/launch4jPurpleSimViz.xml: -------------------------------------------------------------------------------- 1 | 2 | false 3 | gui 4 | 5 | C:\p\pw\out\artifacts\PurpleSimViz.jar 6 | C:\p\pw\out\artifacts\PurpleSimViz.exe 7 | 8 | 9 | Debugging.PurpleSimViz 10 | 11 | 12 | 13 | false 14 | 1.8.0 15 | preferJre 16 | 64/32 17 | 18 | false 19 | false 20 | 21 | -------------------------------------------------------------------------------- /src/Gameplans/Terran/TvE/BunkerRush.scala: -------------------------------------------------------------------------------- 1 | package Gameplans.Terran.TvE 2 | 3 | import Lifecycle.With 4 | import Macro.Actions.MacroActions 5 | import Placement.Access.PlaceLabels.DefendHall 6 | import Placement.Access.PlacementQuery 7 | import ProxyBwapi.Races.{Protoss, Terran} 8 | import Utilities.UnitFilters.IsWarrior 9 | 10 | object BunkerRush extends MacroActions { 11 | def apply(): Unit = { 12 | With.scouting.enemyNatural 13 | .filter(_.townHall.isDefined) 14 | .foreach(natural => { 15 | if (enemies(IsWarrior, Protoss.PhotonCannon) == 0) { 16 | attack() 17 | get(1, Terran.Bunker, new PlacementQuery(Terran.Bunker).requireBase(natural).preferLabelYes(DefendHall)) 18 | } 19 | }) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Macro/Actions/PumpShuttleAndReavers.scala: -------------------------------------------------------------------------------- 1 | package Macro.Actions 2 | 3 | import ProxyBwapi.Races.Protoss 4 | 5 | object PumpShuttleAndReavers extends MacroActions { 6 | def apply(reavers: Int = 50, shuttleFirst: Boolean = true): Unit = { 7 | if (shuttleFirst && ! haveComplete(Protoss.RoboticsSupportBay)) { 8 | once(Protoss.Shuttle) 9 | } 10 | (0 to reavers).foreach(i => { 11 | pump(Protoss.Reaver, i) 12 | pump(Protoss.Shuttle, (i + 1) / 2) 13 | }) 14 | //pumpRatio(Protoss.Shuttle, 0, reavers / 2, Seq(Friendly(Protoss.Reaver, 0.5))) 15 | //pump(Protoss.Reaver, reavers) 16 | //pumpRatio(Protoss.Shuttle, 0, (reavers + 1) / 2, Seq(Flat(0.5), Friendly(Protoss.Reaver, 0.5)), round = Rounding.Down) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /configs/PurpleWaveBASIL.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "human" : false, 3 | "ladder" : true, 4 | "livestream" : false, 5 | "tournament" : false, 6 | "roundrobin" : false, 7 | "elimination" : false, 8 | "pretraining" : false, 9 | "debugging" : false, 10 | "debugginglive" : false, 11 | "logstd" : false, 12 | "multiCPU" : false, 13 | "framemstarget" : 42, 14 | "framemslimit" : 60, 15 | "comments" : "BASIL does not enforce per-frame limits, but does cap games at 30 minutes. We are memory-capped which means a small framebuffer, but without per-frame limits this doesn't matter much. Here we explicitly target 42ms (real-time) speed. BASIL promises only one CPU per bot, though the bot observes 8 in practice." 16 | } -------------------------------------------------------------------------------- /src/Information/Battles/Types/GroupCentroid.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.Types 2 | 3 | import Mathematics.Points.Pixel 4 | import Mathematics.Maff 5 | import ProxyBwapi.UnitInfo.UnitInfo 6 | 7 | object GroupCentroid { 8 | def air(units: Iterable[UnitInfo], extract: UnitInfo => Pixel): Pixel = Maff.centroid(units.view.map(extract)) 9 | def ground(units: Iterable[UnitInfo], extract: UnitInfo => Pixel): Pixel = { 10 | val groundedUnits = Maff.orElse(units.view.filterNot(_.airborne), units.view.filterNot(_.flying)) 11 | if (groundedUnits.isEmpty) return air(units, extract).walkablePixel 12 | val center = Maff.centroid(groundedUnits.map(extract)) 13 | groundedUnits.map(extract).minBy(_.pixelDistanceSquared(center)).walkablePixel 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ProxyBwapi/UnitTracking/IndexedSet.scala: -------------------------------------------------------------------------------- 1 | package ProxyBwapi.UnitTracking 2 | 3 | import scala.reflect.ClassTag 4 | 5 | final class IndexedSet[T: ClassTag] extends IndexedSeq[T] { 6 | private var _set: Set[T] = Set.empty 7 | private var _seq: IndexedSeq[T] = IndexedSeq.empty 8 | private def this(set: Set[T], seq: IndexedSeq[T]) { 9 | this 10 | _set = set 11 | _seq = seq 12 | } 13 | def this(other: Iterable[T]) { 14 | this 15 | _seq = other.toIndexedSeq 16 | _set = _seq.toSet 17 | } 18 | 19 | override def length: Int = _seq.length 20 | override def apply(idx: Int): T = _seq(idx) 21 | override def contains[Supertype >: T](elem: Supertype): Boolean = elem.isInstanceOf[T] && _set.contains(elem.asInstanceOf[T]) 22 | } 23 | -------------------------------------------------------------------------------- /src/Information/Battles/ProcessingStates/BattleProcessMatchupAnalysis.scala: -------------------------------------------------------------------------------- 1 | package Information.Battles.ProcessingStates 2 | 3 | import Lifecycle.With 4 | import ProxyBwapi.UnitInfo.UnitInfo 5 | 6 | import scala.collection.mutable 7 | 8 | class BattleProcessMatchupAnalysis extends BattleProcessState { 9 | 10 | lazy val units = new mutable.Queue[UnitInfo] 11 | units ++= With.battles.nextBattlesLocal.view.flatMap(_.teams.view.flatMap(_.units)) 12 | 13 | override def step(): Unit = { 14 | if (units.isEmpty) { 15 | transitionTo(new BattleProcessComplete) 16 | return 17 | } 18 | 19 | val nextUnit = units.dequeue() 20 | 21 | // TODO: Create matchup analyses here so it doesn't clog up expectations of agency duration 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Micro/Actions/Basic/Bunk.scala: -------------------------------------------------------------------------------- 1 | package Micro.Actions.Basic 2 | 3 | import Micro.Actions.Action 4 | import Micro.Agency.Commander 5 | import ProxyBwapi.Races.Terran 6 | import ProxyBwapi.UnitInfo.FriendlyUnitInfo 7 | 8 | object Bunk extends Action { 9 | 10 | override def allowed(unit: FriendlyUnitInfo): Boolean = { 11 | unit.agent.toBoard.exists(Terran.Bunker) 12 | } 13 | 14 | override def perform(unit: FriendlyUnitInfo) { 15 | if (unit.loaded) { 16 | if (unit.transport == unit.agent.toBoard) { 17 | Commander.doNothing(unit) 18 | } else { 19 | unit.transport.foreach(Commander.unload(_, unit)) 20 | } 21 | } else { 22 | Commander.rightClick(unit, unit.agent.toBoard.get) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Strategery/Strategies/Protoss/ProtossFPM.scala: -------------------------------------------------------------------------------- 1 | package Strategery.Strategies.Protoss 2 | 3 | import Gameplans.Protoss.FPM.PvPFPM 4 | import Planning.Plans.Plan 5 | import Strategery.Strategies.Strategy 6 | import bwapi.Race 7 | 8 | class AbstractProtossFPM extends Strategy { 9 | setOurRace(Race.Protoss) 10 | setMoneyMap(true) 11 | } 12 | 13 | object PvTFPM extends AbstractProtossFPM { 14 | setEnemyRace(Race.Terran) 15 | } 16 | 17 | object PvPFPM extends AbstractProtossFPM { 18 | override def gameplan: Option[Plan] = Some(new PvPFPM) 19 | setEnemyRace(Race.Protoss) 20 | } 21 | 22 | object PvZFPM extends AbstractProtossFPM { 23 | setEnemyRace(Race.Zerg) 24 | } 25 | 26 | object PvRFPM extends AbstractProtossFPM { 27 | setEnemyRace(Race.Unknown) 28 | } -------------------------------------------------------------------------------- /src/Information/Grids/Movement/GridWalkableTerrain.scala: -------------------------------------------------------------------------------- 1 | package Information.Grids.Movement 2 | 3 | import Information.Grids.ArrayTypes.AbstractGridArrayBoolean 4 | import Lifecycle.With 5 | import Mathematics.Points.Tile 6 | import Mathematics.Shapes.Square 7 | import Strategery.MapGroups 8 | 9 | class GridWalkableTerrain extends AbstractGridArrayBoolean { 10 | 11 | override def onInitialization(): Unit = { 12 | val walkableGoal = if (MapGroups.narrowRamp.exists(_())) 12 else 16 13 | indices.foreach(i => set( 14 | i, 15 | Square(4) 16 | .map(new Tile(i).topLeftWalk.add) 17 | .count(walkTile => With.game.isWalkable(walkTile.bwapi)) >= walkableGoal)) 18 | } 19 | 20 | @inline final override def getUnchecked(i: Int): Boolean = values(i) 21 | } 22 | --------------------------------------------------------------------------------