Skip to content

Commit

Permalink
Merge pull request #5 from FredNoonienSingh/restucture_for_ladder
Browse files Browse the repository at this point in the history
Restucture for ladder
  • Loading branch information
FredNoonienSingh authored Dec 4, 2024
2 parents 9d7f0a5 + 430bc6b commit 2c7d7b7
Show file tree
Hide file tree
Showing 52 changed files with 175 additions and 12,075 deletions.
Binary file added .DS_Store
Binary file not shown.
Binary file added HarstemsAunt/.DS_Store
Binary file not shown.
Binary file modified HarstemsAunt/__pycache__/main.cpython-312.pyc
Binary file not shown.

This file was deleted.

This file was deleted.

This file was deleted.

Binary file not shown.
72 changes: 41 additions & 31 deletions HarstemsAunt/main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""MainClass of the Bot handling"""
import csv
from common import MAP_LIST
from random import choice
from .common import MAP_LIST

"""SC2 Imports"""
from sc2 import maps
from sc2.position import Point2
from sc2.bot_ai import BotAI
from sc2.main import run_game
from sc2.position import Point2
from sc2.data import Race, Difficulty
from sc2.ids.unit_typeid import UnitTypeId
from sc2.player import Bot, Computer, Human
Expand All @@ -20,15 +20,16 @@

"""Actions"""
from actions.expand import expand
from actions.chronoboosting import chronoboosting
from actions.set_rally import set_rally
from actions.build_structure import build_gas
from actions.build_supply import build_supply
from actions.chronoboosting import chronoboosting
from actions.unit_controll import control_stalkers, control_phoenix, control_zealots
from actions.build_structure import build_gas

"""Utils"""
from utils.can_build import can_build_unit
from utils.handle_alerts import handle_alerts
from utils.get_build_pos import get_build_pos
from utils.can_build import can_build_unit

class HarstemsAunt(BotAI):

Expand All @@ -37,7 +38,7 @@ def __init__(self, debug:bool=False) -> None:
self.race:Race = Race.Protoss
self.name:str = "HarstemsAunt"
self.version:str = "0.1"
self.taunt:str = " "
self.greeting:str = " "
self.debug:bool = debug
self.expand_locs = []
self.temp = []
Expand All @@ -46,20 +47,13 @@ def __init__(self, debug:bool=False) -> None:
self.map_corners = []
self.map_ramps = []
self.researched = []

"""ECO COUNTER"""
self.base_count = 5
self.gas_count = 1

"""INFRA COUNTER"""
self.gateway_count = 1
self.robo_count = 0
self.stargate_count = 1

"""ENEMY DATA"""
self.seen_enemys = []
self.enemy_supply = 12

self.chatter_counts = [1, 1, 1]
self.last_tick = 0

Expand All @@ -76,16 +70,14 @@ async def on_before_start(self) -> None:
self.map_corners = [top_right, bottom_right, bottom_left, top_left]
self.map_ramps = self.game_info.map_ramps
if self.enemy_race == Race.Zerg:
self.taunt = "Ihhh, Bugs ... thats disgusting"
self.greeting = "Ihhh, Bugs ... thats disgusting"
if self.enemy_race == Race.Terran:
self.taunt = "Humans, thats very original... "
self.greeting = "Humans, thats very original... "
if self.enemy_race == Race.Protoss:
self.taunt = "At least you choose the right race"
print(self.game_info.pathing_grid.print())
self.game_info.pathing_grid.save_image("data/pathinggrid.png")
self.greeting = "At least you choose the right race"

async def on_start(self):
await self.chat_send(self.taunt)
await self.chat_send(self.greeting)
self.expand_locs = list(self.expansion_locations)

async def on_step(self, iteration):
Expand All @@ -106,14 +98,20 @@ async def on_step(self, iteration):
and self.structures(UnitTypeId.GATEWAY) and len(self.structures(UnitTypeId.ASSIMILATOR)) < self.gas_count \
and not self.already_pending(UnitTypeId.ASSIMILATOR):
await build_gas(self, townhall)

# Build_Probes
if townhall.is_idle and can_build_unit(self, UnitTypeId.PROBE):
townhall.train(UnitTypeId.PROBE)
await self.distribute_workers(resource_ratio=2)

build_pos = get_build_pos(self) # THIS NEEDS TO IMPROVED
worker = self.workers.closest_to(build_pos)
# Needs improvement
build_pos = get_build_pos(self)
if self.workers:
worker = self.workers.closest_to(build_pos)
else:
return
if self.time < 180:
await game_start(self, worker, build_pos)
await game_start(self, worker)

await build_infrastructure(self,worker, build_pos)
get_upgrades(self)
Expand All @@ -131,9 +129,6 @@ async def on_step(self, iteration):
await control_zealots(self)
await control_stalkers(self)
await control_phoenix(self)

# print(self.game_info.pathing_grid.print())

return

if self.last_tick == 0:
Expand All @@ -156,8 +151,10 @@ async def on_building_construction_complete(self, unit):
case "Assimilator":
if self.gas_count < 2:
self.gas_count += 1
#case "Gateway":
# await set_nexus_rally(self, self.structures(UnitTypeId.NEXUS)[0], self.structures(UnitTypeId.NEXUS)[0].position.towards(self.game_info.map_center, -5))
case "Gateway":
await set_rally(self,unit, self.structures(UnitTypeId.NEXUS).center)
case "RoboticsFacility":
await set_rally(self,unit, self.structures(UnitTypeId.NEXUS).center)

async def on_enemy_unit_entered_vision(self, unit):
if not unit.tag in self.seen_enemys:
Expand All @@ -178,6 +175,17 @@ async def on_enemy_unit_entered_vision(self, unit):
async def on_enemy_unit_left_vision(self, unit_tag):
return await super().on_enemy_unit_left_vision(unit_tag)

async def on_unit_created(self, unit):
return await super().on_unit_created(unit)

async def on_unit_type_changed(self, unit, previous_type):
return await super().on_unit_type_changed(unit, previous_type)

async def on_unit_took_damage(self, unit, amount_damage_taken):
if self.chatter_counts[2] == 1:
await self.chat_send("HEY! that hurt - cut it out !")
self.chatter_counts[2] = 0

async def on_unit_destroyed(self, unit_tag):
unit = self.enemy_units.find_by_tag(unit_tag)
if unit:
Expand All @@ -192,6 +200,7 @@ async def on_upgrade_complete(self, upgrade):
async def on_end(self,game_result):
# path = f'data/{self.name}_{self.version}_vs{self.enemy_race}_at_{datetime.now()}_{game_result}.csv'
#await self.writetocsv(path)
await self.client.save_replay(f"data/replays/HarstemsAunt.SC2Replay")
await self.client.leave()

def run_ai(race, diffiicultiy, time):
Expand All @@ -201,7 +210,8 @@ def run_ai(race, diffiicultiy, time):
Bot(AiPlayer.race, HarstemsAunt(debug=True)),
Computer(race, difficulty=(diffiicultiy))
],
realtime=time
realtime=time,
sc2_version="5.0.10"
)

def play_against_ai(race):
Expand All @@ -220,7 +230,7 @@ def play_against_ai(race):
Race.Zerg,
Race.Protoss
]
enemy:Race = Race.Zerg


#play_against_ai(Race.Protoss)
run_ai(enemy,Difficulty.Hard, False)
for race in races:
run_ai(race,Difficulty.Hard, False)
77 changes: 77 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# pylint: disable=W0212
import argparse
import asyncio

import aiohttp
from loguru import logger

import sc2
from sc2.client import Client
from sc2.protocol import ConnectionAlreadyClosed


# Run ladder game
# This lets python-sc2 connect to a LadderManager game: https://github.com/Cryptyc/Sc2LadderServer
# Based on: https://github.com/Dentosal/python-sc2/blob/master/examples/run_external.py
def run_ladder_game(bot):
# Load command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("--GamePort", type=int, nargs="?", help="Game port")
parser.add_argument("--StartPort", type=int, nargs="?", help="Start port")
parser.add_argument("--LadderServer", type=str, nargs="?", help="Ladder server")
parser.add_argument("--ComputerOpponent", type=str, nargs="?", help="Computer opponent")
parser.add_argument("--ComputerRace", type=str, nargs="?", help="Computer race")
parser.add_argument("--ComputerDifficulty", type=str, nargs="?", help="Computer difficulty")
parser.add_argument("--OpponentId", type=str, nargs="?", help="Opponent ID")
parser.add_argument("--RealTime", action="store_true", help="Real time flag")
args, _unknown = parser.parse_known_args()

if args.LadderServer is None:
host = "127.0.0.1"
else:
host = args.LadderServer

host_port = args.GamePort
lan_port = args.StartPort

# Add opponent_id to the bot class (accessed through self.opponent_id)
bot.ai.opponent_id = args.OpponentId

realtime = args.RealTime

# Port config
if lan_port is None:
portconfig = None
else:
ports = [lan_port + p for p in range(1, 6)]

portconfig = sc2.portconfig.Portconfig()
portconfig.server = [ports[1], ports[2]]
portconfig.players = [[ports[3], ports[4]]]

# Join ladder game
g = join_ladder_game(host=host, port=host_port, players=[bot], realtime=realtime, portconfig=portconfig)

# Run it
result = asyncio.get_event_loop().run_until_complete(g)
return result, args.OpponentId


# Modified version of sc2.main._join_game to allow custom host and port, and to not spawn an additional sc2process (thanks to alkurbatov for fix)
async def join_ladder_game(host, port, players, realtime, portconfig, save_replay_as=None, game_time_limit=None):
ws_url = f"ws://{host}:{port}/sc2api"
ws_connection = await aiohttp.ClientSession().ws_connect(ws_url, timeout=120)
client = Client(ws_connection)
try:
result = await sc2.main._play_game(players[0], client, realtime, portconfig, game_time_limit)
if save_replay_as is not None:
await client.save_replay(save_replay_as)
# await client.leave()
# await client.quit()
except ConnectionAlreadyClosed:
logger.error("Connection was closed before the game ended")
return None
finally:
ws_connection.close()

return result
Binary file added __pycache__/__init__.cpython-312.pyc
Binary file not shown.
File renamed without changes.
Binary file added actions/__pycache__/abilliies.cpython-312.pyc
Binary file not shown.
Binary file added actions/__pycache__/build_army.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes.
Binary file added actions/__pycache__/set_rally.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file added actions/__pycache__/unit_controll.cpython-312.pyc
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file added macro/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file added macro/__pycache__/build_army.cpython-312.pyc
Binary file not shown.
Binary file added macro/__pycache__/game_start.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
6 changes: 3 additions & 3 deletions HarstemsAunt/macro/build_army.py → macro/build_army.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from sc2.bot_ai import BotAI
from sc2.ids.unit_typeid import UnitTypeId
from actions.build_army import \
build_gateway_units, build_stargate_units, build_robo_units
build_gateway_units, build_stargate_units

async def build_army(bot:BotAI) -> None:
if len(bot.units(UnitTypeId.STALKER)) > 20:
await build_gateway_units(bot, UnitTypeId.ZEALOT)
await build_gateway_units(bot, UnitTypeId.STALKER)
await build_stargate_units(bot, UnitTypeId.PHOENIX)
await build_gateway_units(bot, UnitTypeId.STALKER)
await build_stargate_units(bot, UnitTypeId.PHOENIX)
10 changes: 8 additions & 2 deletions HarstemsAunt/macro/game_start.py → macro/game_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@
from sc2.ids.unit_typeid import UnitTypeId
from actions.set_rally import set_nexus_rally

async def game_start(bot:BotAI, worker, build_pos) -> None:
if not bot.structures(UnitTypeId.PYLON) or not bot.structures(UnitTypeId.GATEWAY):
async def game_start(bot:BotAI, worker) -> None:

if not bot.structures(UnitTypeId.PYLON):
build_pos = bot.main_base_ramp.protoss_wall_pylon
await bot.build(UnitTypeId.PYLON, build_worker=worker, near=build_pos)

if not bot.structures(UnitTypeId.GATEWAY):
build_pos = list(bot.main_base_ramp.protoss_wall_buildings)[0]
nexus = bot.structures(UnitTypeId.NEXUS)[0]
minerals = bot.expansion_locations_dict[nexus.position].mineral_field.sorted_by_distance_to(nexus)
if bot.already_pending(UnitTypeId.PYLON) and worker.is_idle:
Expand Down
File renamed without changes.
File renamed without changes.
19 changes: 19 additions & 0 deletions readME.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Harstems Aunt

### What is Harstems Aunt ?

Harstems Aunt is a StarCraft AI written for the AI Ladder on https://aiarena.net/. It is still under active development at the moment it is building Stalkers, Zealots and Phoenixes.

### How to run locally:

Download StarCraft 2 and the Maps from https://aiarena.net/wiki/maps/.

Then run:
```zsh
pip install -e .
```
inside the Bot directory after cloning the repository.

### Next Steps

Fixing the positioning of Buildings and improvements to the unit control.
27 changes: 27 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

from random import choice
from HarstemsAunt.main import HarstemsAunt
from HarstemsAunt.common import MAP_LIST

import sys

from __init__ import run_ladder_game

from sc2 import maps
from sc2.data import Difficulty, Race
from sc2.main import run_game
from sc2.player import Bot, Computer

bot = Bot(Race.Protoss, HarstemsAunt())

# Start game
if __name__ == "__main__":
if "--LadderServer" in sys.argv:
# Ladder game started by LadderManager
print("Starting ladder game...")
result, opponentid = run_ladder_game(bot)
print(result, " against opponent ", opponentid)
else:
# Local game
print("Starting local game...")
run_game(maps.get(choice(MAP_LIST)), [bot, Computer(Race.Protoss, Difficulty.CheatInsane)], realtime=False, sc2_version="5.0.10")
Empty file added utils/__init__.py
Empty file.
File renamed without changes.
File renamed without changes.
Binary file added utils/__pycache__/get_build_pos.cpython-312.pyc
Binary file not shown.
Binary file added utils/__pycache__/handle_alerts.cpython-312.pyc
Binary file not shown.
Binary file added utils/__pycache__/in_proximity.cpython-312.pyc
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 2c7d7b7

Please sign in to comment.