Skip to content

Instantly share code, notes, and snippets.

@ChintanTrivedi
Last active June 25, 2018 08:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ChintanTrivedi/0377d1bb1b32e538bfd8f9f57efdb9a0 to your computer and use it in GitHub Desktop.
Save ChintanTrivedi/0377d1bb1b32e538bfd8f9f57efdb9a0 to your computer and use it in GitHub Desktop.
class FIFA(object):
"""
This class acts as the intermediate "API" to the actual game. Double quotes API because we are not touching the
game's actual code. It interacts with the game simply using screen-grab (input) and keypress simulation (output)
using some clever python libraries.
"""
# Define actions that our agent can take and the corresponding keys to press for taking that action.
actions_display_name = ['shoot low', 'shoot high', 'move left', 'move right']
key_to_press = [spacebar, spacebar, leftarrow, rightarrow]
# Initialize reward that will act as feedback from our interactions with the game
self.reward = 0
def __init__(self):
# Create a CNN graph object that will process screenshot images of the game.
self.cnn_graph = CNN()
# Observe our game environment by taking screenshot of the game.
def observe(self):
# Get current state s from screen using screen-grab and narrow it down to the game window.
screen = grab_screen(region=None)
game_screen = screen[25:-40, 1921:]
# Process through CNN to get the feature map from the raw image. This will act as our current state s.
return self.cnn_graph.get_image_feature_map(game_screen)
# Press the appropriate key based on the action our agent decides to take.
def act(self, action):
# If we are shooting low (action=0) then press spacebar for just 0.05s for low power.
# In all other cases press the key for a longer time.
PressKey(key_to_press[action])
time.sleep(0.05) if action == 0 else time.sleep(0.2)
ReleaseKey(key_to_press[action])
# Wait until some time after taking action for the game's animation to complete.
# Taking a shot requires 5 seconds of animation, otherwise the game responds immediately.
time.sleep(5) if action in [0, 1] else time.sleep(1)
# Once our environment has reacted to our agent's actions, we fetch the reward
# and check if the game is over or not (ie, it is over once the shot been taken)
reward = self._get_reward(action)
game_over = self._is_over(action)
return self.observe(), reward, game_over
# Get feedback from the game - uses OCR on "performance meter" in the game's top right corner.
# We will assign +1 reward to a shot if it ends up in the net, a -1 reward if it misses the net
# and 0 reward for a left or right movement.
def _get_reward(self, action):
screen = grab_screen(region=None)
game_screen = screen[25:-40, 1921:]
# Narrow down to the reward meter at top right corner of game screen to get the feedback.
reward_meter = game_screen[85:130, 1650:1730]
i = Image.fromarray(reward_meter.astype('uint8'), 'RGB')
try:
# Use OCR to recognize the reward obtained after taking the action.
ocr_result = pt.image_to_string(i)
ingame_reward = int(''.join(c for c in ocr_result if c.isdigit()))
# Determine if the feedback is positive or not based on the reward observed.
# Also update our reward object with latest observed reward.
if ingame_reward - self.reward > 200:
# If ball goes into the net, our ingame performance meter increases by more than 200 points.
self.reward = ingame_reward
action_reward = 1
elif self._is_over(action):
# If ball has been shot but performance meter has not increased the score, ie, we missed the goal.
self.reward = ingame_reward
action_reward = -1
else:
# If ball hasn't been shot yet, we are only moving left or right.
self.reward = ingame_reward
action_reward = 0
except:
# Sometimes OCR fails, we will just assume we haven't scored in this scenario.
action_reward = -1 if self._is_over(action) else 0
return action_reward
def _is_over(self, action):
# Check if the ball is still there to be hit. If shoot action has been initiated,
# the game is considered over since you cannot influence it anymore.
return True if action in [0, 1] else False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment