How to select your SCV!?
์ด ์ฅ์์ ๋ฐฐ์ธ ๊ฒ
SCV๋ฅผ ์ ํํ๊ณ , ์๋๋ฐฉ์ ์ง์์ผ๋ก SCV๋ฅผ ์ ์ฐฐ๋ณด๋ด๊ณ ๋น๋น ๋๋ฆฌ๋ ํ์๋ฅผ ํด๋ณผ ๊ฒ์ ๋๋ค.
Let's Start!
์์ํด๋ณด๊ฒ ์ต๋๋ค. ์ผ๋จ ์ง๋๋ฒ์ agent๋ no_op()์ ํตํด ์๋ฌด action์์ด ๋๊ธฐํ๋ agent๋ฅผ ๋ง๋ค์์ต๋๋ค. ์ด๋ฒ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผ SCV๋ฅผ ์ ํํ๊ณ , ์๋๋ฐฉ ์ง์์ ๋ณด๋ด๊ณ , ์์์ด ๋ ๋, ์ปค๋งจ๋ ์ผํฐ๋ฅผ ์ง์ ์ ์์๊น์?
์ด์ ์ step function์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
class Agent(base_agent.BaseAgent):
def step(self,obs):
super(Agent,self).step(obs)
return actions.FUNCTIONS.no_op()
return์ ํตํด action์ output์ผ๋ก ์ฃผ๋ฉด ๋๋ ๊ฐ๋จํ ๊ตฌ์กฐ์ธ ๊ฒ์ ๋๋ค! ๋จผ์ , SCV๊ฐ ์กด์ฌํ๋์ง observation์์ ํ์ธํด์ผ ํฉ๋๋ค.
from pysc2.lib import units
scvs = [unit for unit in obs.observation.feature_units if unit.unit_type == units.Terran.SCV]
์ด๋ ๊ฒ input์ผ๋ก ํ์ฌ ํ๋ฉด์์ ๋ณด์ด๋ scvs๋ค์ ์ก์ต๋๋ค. ์ด์ , ๊ทธ์ค scv ์๋ฌด ๋์ ์ก์์, ์ ํํด์ค๋๋ค.
scv = scvs[0]
return actions.FUNCTIONS.select_point("select",(scv.x,scv.y))
3select_point๋ฅผ ํตํด scv์ ์ขํ๋ฅผ ์ ํํด scv๋ฅผ ์ฝ ์ฐ์ ์ํ์ ๋๋ค. ๋ค์ step์ผ๋ก ๋์ด๊ฐ๊ฒ ๋๋ฉด ๊ทธ scv์๊ฒ ๋ช ๋ น์ ๋ด๋ ค์ผ ํ๊ฒ ์ฃ ! ๊ทธ๋ฆฌ๊ณ ํ์ฌ scv๋ฅผ ์ก๋ ํ์๋ ๊ทธ๋งํด์ผํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ฅผ ๋ค์๊ณผ ๊ฐ์ ํจ์๋ฅผ ๋ง๋ค์ด ํด๊ฒฐํ ์ ์์ต๋๋ค.
def unit_type_is_selected(obs,unit_type):
if len(obs.observation.single_select) > 0 and obs.observation.single_select[0].unit_type == unit_type:
return True
elif len(obs.observation.multi_select) > 0 and obs.observation.multi_select[0].unit_type == unit_type:
return True
else:
return False
์์ ํ๋๋ค์ ํฉ์ณ SCV๋ฅผ ์ก์์ฑ๋ก ๊ฐ๋งํ ์๋๋ก ํ๋ Agent๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
class Agent(base_agent.BaseAgent):
def unit_type_is_selected(self,obs,unit_type):
if (len(obs.observation.single_select) > 0 and obs.observation.single_select[0].unit_type == unit_type):
return True
elif (len(obs.observation.multi_select) > 0 and obs.observation.multi_select[0].unit_type == unit_type):
return True
else :
return False
def step(self,obs):
super(Agent,self).step(obs)
scvs = [unit for unit in obs.observation.feature_units if unit.unit_type == units.Terran.SCV]
if len(scvs) > 0 and not self.unit_type_is_selected(obs,units.Terran.SCV):
scv = scvs[0]
return actions.FUNCTIONS.select_point("select",(scv.x,scv.y))
else:
return actions.FUNCTIONS.no_op()
์ด์ ๋ agent๋ฅผ ๊ณจ๋์ ๋, ์๋ฌด๊ฒ๋ ์ํ๋๊ฒ ์๋, SCV๋ฅผ ์ ํ๋ ์ starting point๋ก ์ ์ฐฐ์ ๋ณด๋ด๊ณ , ๋น๋น๋๋ ค์ผํฉ๋๋ค. ๊ทธ๋ ๊ฒ ํ๊ธฐ ์ํด์ ,
SCV ํ ๊ธฐ๋ฅผ ํด๋ฆญ(์์์์งํ)
SCV๋ฅผ ๋ถ๋์ง์
SCV๋ฅผ ์นด๋ฉ๋ผ๋ก ๋ฐ๋ผ๋ค๋๋ฉฐ ๋ฐ ์ปจํธ๋กค
์๋์ฒ๋ผ ๋ถ๋์ง์ ์ด 1๋ฒ์ด ๋์ด์์ง์๋ ๊ฒฝ์ฐ์ ์๋์ฒ๋ผ ๊ทธ๋ฃน์ง์ ์ ํฉ๋๋ค.
CONTROL_GROUP_SET = 1
CONTROL_GROUP_RECALL = 0
SCV_GROUP_ORDER = 1
def step(self,obs):
super(Agent,self).step(obs)
scvs = [unit for unit in obs.observation.feature_units if unit.unit_type == units.Terran.SCV]
if len(scvs) > 0 and not self.unit_type_is_selected(obs,units.Terran.SCV):
scv = scvs[0]
return actions.FUNCTIONS.select_point("select",(scv.x,scv.y))
elif self.unit_type_is_selected(obs,units.Terran.SCV) and obs.observation.control_groups[SCV_GROUP_ORDER][0] == 0:
return actions.FUNCTIONS.select_control_group([CONTROL_GROUP_SET], [SCV_GROUP_ORDER])
else :
return actions.FUNCTIONS.no_op()
๋ค์์, ์นด๋ฉ๋ผ๋ฅผ ๋ฐ๋ผ๋ค๋๋๋ก ํด์ผํ๋๋ฐ, ์ฌ๊ธฐ์ ํธ๋ฒ(?)์ ์ฌ์ฉํ ์์ ์ ๋๋ค. FUNCTIONS์ camera move๊ฐ ์๊ธดํ์ง๋ง ๋ฏธ๋๋งต์ ์ชผ๊ฐ์ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ์ฌ, ๋ถ๋์ง์ ํ ์ ๋์ผ๋ก ์ด๋ํ๋๊ฒ ๊น๋ค๋กญ์ต๋๋ค. ๊ทธ๋ ๊ธฐ๋๋ฌธ์ pynput ์ ์ด์ฉํ๊ฒ ์ต๋๋ค.
import pynput
keyboard_button = pynput.keyboard.Controller()
keyboard_key = pynput.keyboard.Key
CONTROL_GROUP_SET = 1
CONTROL_GROUP_RECALL = 0
SCV_GROUP_ORDER = 1
NOT_QUEUED = [0]
MOVE_SCREEN = 331
def step(self,obs):
super(Agent,self).step(obs)
scvs = [unit for unit in obs.observation.feature_units if unit.unit_type == units.Terran.SCV]
if len(scvs) > 0 and not self.unit_type_is_selected(obs,units.Terran.SCV):
scv = scvs[0]
return actions.FUNCTIONS.select_point("select",(scv.x,scv.y))
elif self.unit_type_is_selected(obs,units.Terran.SCV) and obs.observation.control_groups[SCV_GROUP_ORDER][0] == 0:
return actions.FUNCTIONS.select_control_group([CONTROL_GROUP_SET], [SCV_GROUP_ORDER])
elif len([x for x in obs.observation.feature_units if x.is_selected == 1]) == 0:
keyboard_button.press(str(SCV_GROUP_ORDER))
keyboard_button.release(str(SCV_GROUP_ORDER))
keyboard_button.press(str(SCV_GROUP_ORDER))
keyboard_button.release(str(SCV_GROUP_ORDER))
return actions.FUNCTIONS.select_control_group([CONTROL_GROUP_RECALL], [SCV_GROUP_ORDER])
elif len([x for x in obs.observation.feature_units if ((x.is_selected == 1) and x.order_length == 0)]) == 1 :
x,y = random.randint(0,64),random.randint(0,64)
return actions.FunctionCall(MOVE_SCREEN,[NOT_QUEUED,[x,y]])
else:
return actions.FUNCTIONS.no_op()
๋ถ๋์ง์ ํ ์ ๋์ด ๋งต์์ ์ฌ๋ผ์ง๋ฉด SCV๋ถ๋์ง์ ํค๋ฅผ ๋๋ฌ ๊ทธ๊ณณ์ผ๋ก camera๋ฅผ ์ด๋ํ๊ณ , SCV๊ฐ ์๋ฌด๊ฒ๋์ํ๋ฉด random์ผ๋ก ์ด๋์์ผ ๋บ๋บ ๋๊ฒ ๋ง๋๋ ์คํฌ๋ฆฝํธ์ ๋๋ค.
์ ์ ๋ณธ์ง์ผ๋ก ์ ์ฐฐ์ ๋ณด๋ด์ผํ๋๋ฐ, ์์์ ์ ์์ ์ ๋ณธ์ง์ด ์ด๋ ๋ฐฉํฅ์ผ์ง ์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก, step๋ด์ ๋ค์๊ณผ ๊ฐ์ ๋ผ์ธ์ ์ถ๊ฐํฉ๋๋ค.
if obs.first():
player_y, player_x = (obs.observation.feature_minimap.player_relative == PLAYER_SELF).nonzero()
xmean = player_x.mean()
ymean = player_y.mean()
if xmean <= 31 and ymean <= 31:
self.scout_coordinates = (40, 40)
else:
self.scout_coordinates = (20, 20)
step function์ ์ ์ฒด๋ฅผ ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def step(self,obs):
super(Agent,self).step(obs)
if obs.first():
player_y, player_x = (obs.observation.feature_minimap.player_relative == PLAYER_SELF).nonzero()
xmean = player_x.mean()
ymean = player_y.mean()
if xmean <= MINIMAP_SIZE / 2 and ymean <= MINIMAP_SIZE / 2:
self.scout_coordinates = (40, 40)
else:
self.scout_coordinates = (20, 20)
scvs = [unit for unit in obs.observation.feature_units if unit.unit_type == units.Terran.SCV]
if len(scvs) > 0 and not self.unit_type_is_selected(obs,units.Terran.SCV):
#์ ๋ ์
๋
scv = scvs[0]
return actions.FUNCTIONS.select_point("select",(scv.x,scv.y))
elif self.unit_type_is_selected(obs,units.Terran.SCV) and obs.observation.control_groups[SCV_GROUP_ORDER][0] == 0:
#control unit์ก๊ธฐ
return actions.FUNCTIONS.select_control_group([CONTROL_GROUP_SET], [SCV_GROUP_ORDER])
elif len([x for x in obs.observation.feature_units if x.is_selected == 1]) == 0:
#ํ๋ฉด๋ฐ๋ฒ์ด๋ฌ์๋
keyboard_button.press(str(SCV_GROUP_ORDER))
keyboard_button.release(str(SCV_GROUP_ORDER))
keyboard_button.press(str(SCV_GROUP_ORDER))
keyboard_button.release(str(SCV_GROUP_ORDER))
return actions.FUNCTIONS.select_control_group([CONTROL_GROUP_RECALL], [SCV_GROUP_ORDER])
elif len([x for x in obs.observation.feature_units if ((x.is_selected == 1) and x.order_length == 0)]) == 1 and\
SCREEN_ENEMY in [x.alliance for x in obs.observation.feature_units] :
#ํ๋ฉด๋ด random ์ด๋
x,y = random.randint(0,SCREEN_SIZE),random.randint(0,SCREEN_SIZE)
return actions.FunctionCall(MOVE_SCREEN,[NOT_QUEUED,[x,y]])
elif len([x for x in obs.observation.feature_units if (x.is_selected == 1)]) == 1 \
and SCREEN_ENEMY not in [x.alliance for x in obs.observation.feature_units]:
#์ ์์น๋ก ์ ์ฐฐ
x,y = self.scout_coordinates
return actions.FunctionCall(MOVE_MINIMAP,[NOT_QUEUED,[x,y]])
else:
return actions.FUNCTIONS.no_op()
์ ์ฒด์ ์คํฌ๋ฆฝํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
from pysc2.env import sc2_env
from pysc2.agents import base_agent
from pysc2.lib import actions,units,features
from absl import app
import random
import pynput ###
keyboard_button = pynput.keyboard.Controller()
keyboard_key = pynput.keyboard.Key
MAPNAME = 'Simple64'
APM = 300
APM = int(APM / 18.75)
UNLIMIT = 0
VISUALIZE = True
REALTIME = True
CONTROL_GROUP_SET = 1
CONTROL_GROUP_RECALL = 0
SCV_GROUP_ORDER = 1
NOT_QUEUED = [0]
MOVE_SCREEN = 331
MOVE_MINIMAP = 332
SCREEN_ENEMY = 4
PLAYER_SELF =features.PlayerRelative.SELF
SCREEN_SIZE = 84
MINIMAP_SIZE = 64
players = [sc2_env.Agent(sc2_env.Race.terran),\
sc2_env.Bot(sc2_env.Race.zerg,\
sc2_env.Difficulty.very_easy)]
interface = features.AgentInterfaceFormat(\
feature_dimensions = features.Dimensions(\
screen = SCREEN_SIZE, minimap = MINIMAP_SIZE), use_feature_units = True)
class Agent(base_agent.BaseAgent):
def unit_type_is_selected(self,obs,unit_type):
if (len(obs.observation.single_select) > 0 and obs.observation.single_select[0].unit_type == unit_type):
return True
elif (len(obs.observation.multi_select) > 0 and obs.observation.multi_select[0].unit_type == unit_type):
return True
else :
return False
def step(self,obs):
super(Agent,self).step(obs)
if obs.first():
player_y, player_x = (obs.observation.feature_minimap.player_relative == PLAYER_SELF).nonzero()
xmean = player_x.mean()
ymean = player_y.mean()
if xmean <= MINIMAP_SIZE / 2 and ymean <= MINIMAP_SIZE / 2:
self.scout_coordinates = (40, 40)
else:
self.scout_coordinates = (20, 20)
scvs = [unit for unit in obs.observation.feature_units if unit.unit_type == units.Terran.SCV]
if len(scvs) > 0 and not self.unit_type_is_selected(obs,units.Terran.SCV):
#์ ๋ ์
๋
scv = scvs[0]
return actions.FUNCTIONS.select_point("select",(scv.x,scv.y))
elif self.unit_type_is_selected(obs,units.Terran.SCV) and obs.observation.control_groups[SCV_GROUP_ORDER][0] == 0:
#control unit์ก๊ธฐ
return actions.FUNCTIONS.select_control_group([CONTROL_GROUP_SET], [SCV_GROUP_ORDER])
elif len([x for x in obs.observation.feature_units if x.is_selected == 1]) == 0:
#ํ๋ฉด๋ฐ๋ฒ์ด๋ฌ์๋
keyboard_button.press(str(SCV_GROUP_ORDER))
keyboard_button.release(str(SCV_GROUP_ORDER))
keyboard_button.press(str(SCV_GROUP_ORDER))
keyboard_button.release(str(SCV_GROUP_ORDER))
return actions.FUNCTIONS.select_control_group([CONTROL_GROUP_RECALL], [SCV_GROUP_ORDER])
elif len([x for x in obs.observation.feature_units if ((x.is_selected == 1) and x.order_length == 0)]) == 1 and\
SCREEN_ENEMY in [x.alliance for x in obs.observation.feature_units] :
#ํ๋ฉด๋ด random ์ด๋
x,y = random.randint(0,SCREEN_SIZE),random.randint(0,SCREEN_SIZE)
return actions.FunctionCall(MOVE_SCREEN,[NOT_QUEUED,[x,y]])
elif len([x for x in obs.observation.feature_units if (x.is_selected == 1)]) == 1 \
and SCREEN_ENEMY not in [x.alliance for x in obs.observation.feature_units]:
#์ ์์น๋ก ์ ์ฐฐ
x,y = self.scout_coordinates
return actions.FunctionCall(MOVE_MINIMAP,[NOT_QUEUED,[x,y]])
else:
return actions.FUNCTIONS.no_op()
def main(args):
agent = Agent()
try:
with sc2_env.SC2Env(map_name = MAPNAME, players = players,\
agent_interface_format = interface,\
step_mul = APM, game_steps_per_episode = UNLIMIT,\
visualize = VISUALIZE, realtime = REALTIME) as env:
agent.setup(env.observation_spec(), env.action_spec())
timestep = env.reset()
agent.reset()
while True:
step_actions = [agent.step(timestep[0])]
if timestep[0].last():
break
timestep = env.step(step_actions)
except KeyboardInterrupt:
pass
app.run(main)
Last updated
Was this helpful?