Skip to content

Commit 654e9ad

Browse files
committed
Initial commit
0 parents  commit 654e9ad

File tree

42 files changed

+522
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+522
-0
lines changed

Protokoll.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Gruppe:
2+
3+
Bearbeitet von:
4+
Aufgabe 1 (Markov Decision Process) ->
5+
Aufgabe 2 (Basic Agent) ->
6+
Aufgabe 3 (Q-Learning) ->

agents/AbstractAgent.py

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from abc import abstractmethod
2+
3+
import numpy as np
4+
from pysc2.lib import actions, features
5+
6+
7+
class AbstractAgent:
8+
_DIRECTIONS = {'N': [0, -1],
9+
'NE': [1, -1],
10+
'E': [1, 0],
11+
'SE': [1, 1],
12+
'S': [0, 1],
13+
'SW': [-1, 1],
14+
'W': [-1, 0],
15+
'NW': [-1, -1]}
16+
17+
_DIRECTIONS_REVERSE = {"[0, -1]": 'N',
18+
"[1, -1]": 'NE',
19+
"[1, 0]": 'E',
20+
"[1, 1]": 'SE',
21+
"[0, 1]": 'S',
22+
"[-1, 1]": 'SW',
23+
"[-1, 0]": 'W',
24+
"[-1, -1]": 'NW'}
25+
26+
"""Sc2 Actions"""
27+
_MOVE_SCREEN = actions.FUNCTIONS.Move_screen
28+
_NO_OP = actions.FUNCTIONS.no_op()
29+
_SELECT_ARMY = actions.FUNCTIONS.select_army("select")
30+
31+
def __init__(self, screen_size):
32+
self.screen_size = screen_size
33+
34+
@abstractmethod
35+
def step(self, obs):
36+
...
37+
38+
@abstractmethod
39+
def save_model(self, path):
40+
...
41+
42+
@abstractmethod
43+
def load_model(self, path):
44+
...
45+
46+
def _get_beacon(self, obs):
47+
"""Returns the unit obj representation of the beacon"""
48+
beacon = next(unit for unit in obs.observation.feature_units
49+
if unit.alliance == features.PlayerRelative.NEUTRAL)
50+
return beacon
51+
52+
def _get_marine(self, obs):
53+
"""Returns the unit obj representation of the marine"""
54+
marine = next(unit for unit in obs.observation.feature_units
55+
if unit.alliance == features.PlayerRelative.SELF)
56+
return marine
57+
58+
def _get_unit_pos(self, unit):
59+
"""Returns the (x, y) position of a unit obj"""
60+
return np.array([unit.x, unit.y])
61+
62+
def _dir_to_sc2_action(self, d, marine_center):
63+
"""Takes the direction the marine should walk and outputs an action for PySC2"""
64+
65+
def _xy_offset(start, offset_x, offset_y):
66+
"""Return point (x', y') offset from start.
67+
Pays attention to not set the point off beyond the screen border"""
68+
dest = start + np.array([offset_x, offset_y])
69+
if dest[0] < 0:
70+
dest[0] = 0
71+
elif dest[0] >= self.screen_size:
72+
dest[0] = self.screen_size - 1
73+
if dest[1] < 0:
74+
dest[1] = 0
75+
elif dest[1] >= self.screen_size:
76+
dest[1] = self.screen_size - 1
77+
return dest
78+
79+
if d in self._DIRECTIONS.keys():
80+
next_pos = _xy_offset(marine_center,
81+
self.screen_size * self._DIRECTIONS[d][0],
82+
self.screen_size * self._DIRECTIONS[d][1])
83+
return self._MOVE_SCREEN("now", next_pos)
84+
else:
85+
return self._NO_OP

agents/BasicAgent.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from agents.AbstractAgent import AbstractAgent
2+
3+
4+
class BasicAgent(AbstractAgent):
5+
def __init__(self, train, screen_size):
6+
super(BasicAgent, self).__init__(screen_size)
7+
8+
def step(self, obs):
9+
if self._MOVE_SCREEN.id in obs.observation.available_actions:
10+
marine = self._get_marine(obs)
11+
if marine is None:
12+
return self._NO_OP
13+
marine_coordinates = self._get_unit_pos(marine)
14+
marine_x, marine_y = marine_coordinates[0], marine_coordinates[1]
15+
16+
beacon = self._get_beacon(obs)
17+
if beacon is None:
18+
return self._NO_OP
19+
beacon_coordinates = self._get_unit_pos(beacon)
20+
beacon_x, beacon_y = beacon_coordinates[0], beacon_coordinates[1]
21+
22+
move = ""
23+
if(marine_y < beacon_y):
24+
move += "S"
25+
elif (marine_y > beacon_y):
26+
move += "N"
27+
28+
if(marine_x < beacon_x):
29+
move += "E"
30+
elif(marine_x > beacon_x):
31+
move += "W"
32+
33+
assert move != ""
34+
35+
return self._dir_to_sc2_action(move, marine_coordinates)
36+
else:
37+
return self._SELECT_ARMY
38+
39+
def save_model(self, filename):
40+
pass
41+
42+
def load_model(self, filename):
43+
pass

agents/QLearningAgent.py

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from agents.AbstractAgent import AbstractAgent
2+
import pandas as pd
3+
import numpy as np
4+
5+
def get_row_index_in_string_format(state):
6+
"""
7+
Returns a state (row index) as q-table row index string.
8+
9+
Parameters:
10+
state ([int, int]): The distance between agent (marine) and beacon.
11+
12+
Returns:
13+
state (str): Transformed state, so it can be used as index in the q-table.
14+
"""
15+
return "("+str(state[0]) + "," + str(state[1]) + ")"
16+
17+
18+
class QLearningAgent(AbstractAgent):
19+
def __init__(self, train, screen_size, explore=1):
20+
super(QLearningAgent, self).__init__(screen_size)
21+
# TODO Initialize all hyperparameter and the q-table (with the helper function below)
22+
self.train = train
23+
self.explore = explore
24+
self.actions = self._DIRECTIONS.keys()
25+
self.states = []
26+
for x in range(-64, 65):
27+
for y in range(-64, 65):
28+
self.states.append((x, y))
29+
self.q_table = self.init_q_table()
30+
31+
pass
32+
33+
34+
def step(self, obs):
35+
# TODO step method
36+
if self._MOVE_SCREEN.id in obs.observation.available_actions:
37+
pass
38+
else:
39+
return self._SELECT_ARMY # initialize army in first step
40+
41+
def save_model(self, path):
42+
self.q_table.to_pickle(path)
43+
44+
def load_model(self, path):
45+
self.q_table = pd.read_pickle(path)
46+
47+
def get_new_action(self, state):
48+
"""
49+
Returns the action to execute.
50+
51+
Parameters:
52+
state ([int, int]): A row index (a state) of the q-table.
53+
54+
Returns:
55+
action (str): e.g. 'N', 'NW', 'NO', ...
56+
"""
57+
# TODO get_new_action method
58+
...
59+
60+
def get_q_value(self, q_table_column_index, q_table_row_index):
61+
"""
62+
Returns a q-value.
63+
64+
Parameters:
65+
q_table_column_index (str): The column index of the searched value (the action).
66+
q_table_row_index (str): The row index of the searched value (the state).
67+
68+
Returns:
69+
action (float): The value for the given indices.
70+
"""
71+
# TODO get_new_action method
72+
...
73+
74+
def update_q_value(self, old_state, old_action, new_state, reward, terminal):
75+
# TODO update_q_value method
76+
...
77+
78+
def get_q_state_from_position(self, marine_position, beacon_position):
79+
"""
80+
Transforms the position of agent (marine) and beacon into a q-table row index.
81+
82+
Parameters:
83+
marine_position ([int, int]): The position of the agent (marine).
84+
beacon_position ([int, int]): The position of the beacon.
85+
86+
Returns:
87+
state ([int, int]): A row index (a state) of the q-table.
88+
"""
89+
# TODO get_q_state_from_position method
90+
...
91+
92+
def init_q_table(self):
93+
"""
94+
Initializes the q-table
95+
96+
Returns:
97+
q_table (panda.Dataframe): The q-table.
98+
The row indices must be in the format '(x,y)'
99+
The column indices must be in the format 'action' (e.g. 'W')
100+
"""
101+
return pd.DataFrame(np.random.rand(len(self.states), len(self.actions)), index=self.states, columns=self.actions)

agents/RandomAgent.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from agents.AbstractAgent import AbstractAgent
2+
import numpy as np
3+
4+
5+
class RandomAgent(AbstractAgent):
6+
7+
def __init__(self, train, screen_size):
8+
super(RandomAgent, self).__init__(screen_size)
9+
10+
def step(self, obs):
11+
if self._MOVE_SCREEN.id in obs.observation.available_actions:
12+
marine = self._get_marine(obs)
13+
if marine is None:
14+
return self._NO_OP
15+
marine_coordinates = self._get_unit_pos(marine)
16+
17+
d = np.random.choice(list(self._DIRECTIONS.keys()))
18+
return self._dir_to_sc2_action(d, marine_coordinates)
19+
else:
20+
return self._SELECT_ARMY
21+
22+
def save_model(self, filename):
23+
pass
24+
25+
def load_model(self, filename):
26+
pass

env.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from pysc2.env import sc2_env
2+
from pysc2.lib import features
3+
4+
5+
class Env:
6+
def __init__(self, screen_size=32, minimap_size=32, visualize=False):
7+
self.sc2_env = sc2_env.SC2Env(
8+
map_name="MoveToBeacon",
9+
players=[sc2_env.Agent(sc2_env.Race.terran)],
10+
agent_interface_format=features.AgentInterfaceFormat(
11+
feature_dimensions=features.Dimensions(screen=screen_size, minimap=minimap_size),
12+
use_feature_units=True
13+
),
14+
step_mul=8,
15+
visualize=visualize
16+
)
17+
18+
def reset(self):
19+
return self.preprocess_obs(self.sc2_env.reset())
20+
21+
def step(self, action):
22+
return self.preprocess_obs(self.sc2_env.step([action]))
23+
24+
def preprocess_obs(self, timsteps):
25+
# Any kind of preprocessing can take place here
26+
return timsteps[0]

runScripts/runBasicAgent.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from absl import app
2+
3+
from env import Env
4+
from runners.basic_runner import Runner
5+
from agents.BasicAgent import BasicAgent
6+
7+
_CONFIG = dict(
8+
episodes=100,
9+
screen_size=64,
10+
minimap_size=64,
11+
visualize=True,
12+
train=False,
13+
agent=BasicAgent
14+
)
15+
16+
def main(unused_argv):
17+
18+
agent = _CONFIG['agent'](
19+
train=_CONFIG['train'],
20+
screen_size=_CONFIG['screen_size']
21+
)
22+
23+
env = Env(
24+
screen_size=_CONFIG['screen_size'],
25+
minimap_size=_CONFIG['minimap_size'],
26+
visualize=_CONFIG['visualize']
27+
)
28+
29+
runner = Runner(
30+
agent=agent,
31+
env=env,
32+
train=_CONFIG['train']
33+
)
34+
35+
runner.run(episodes=_CONFIG['episodes'])
36+
37+
38+
if __name__ == "__main__":
39+
app.run(main)

runScripts/runQLAgent.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# TODO Write the runQLAgent script
2+
from absl import app
3+
4+
from env import Env
5+
from runners.basic_runner import Runner
6+
from agents.QLearningAgent import QLearningAgent
7+
8+
_CONFIG = dict(
9+
episodes=100,
10+
screen_size=64,
11+
minimap_size=64,
12+
visualize=True,
13+
train=False,
14+
agent=QLearningAgent
15+
)
16+
17+
def main(unused_argv):
18+
19+
agent = _CONFIG['agent'](
20+
train=_CONFIG['train'],
21+
screen_size=_CONFIG['screen_size']
22+
)
23+
24+
env = Env(
25+
screen_size=_CONFIG['screen_size'],
26+
minimap_size=_CONFIG['minimap_size'],
27+
visualize=_CONFIG['visualize']
28+
)
29+
30+
runner = Runner(
31+
agent=agent,
32+
env=env,
33+
train=_CONFIG['train']
34+
)
35+
36+
runner.run(episodes=_CONFIG['episodes'])
37+
38+
39+
if __name__ == "__main__":
40+
app.run(main)

0 commit comments

Comments
 (0)