Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ You can then run it (assuming the simulation is already running in another termi
```
python socket_agent.py
```

### Running the simulation with Python agents that takes keyboard inputs

Take a look at the "keyboard_agent.py" file which has an example of how to send keyboard input commands through a socket.

```
<python-command> keyboard_agent.py
```
A control display will pop up. Click on the display to focus on it and send keyboard commands. The program will convert the commands and send the action commands to the socket environment to carry out the game play.

### Running the simulation with recorded action history

Take a look at the "replay_agent_actions.py" file which has an example of how to send recorded commands from a file through a socket.
Expand Down
88 changes: 88 additions & 0 deletions keyboard_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Author: Tia Chen
# Email: qingyan.chen@tufts.edu

import argparse
import json
import socket
import pygame

from utils import recv_socket_data

def send_command(command):
print("Sending action: ", command)
sock_game.send(str.encode(command)) # send action to env

output = recv_socket_data(sock_game) # get observation from env (wait for response before sending next command)
# output = json.loads(output) # Put back if you want to inspect received message

# print("JSON: ", output)

if __name__ == "__main__":

parser = argparse.ArgumentParser()

parser.add_argument(
'player_id',
type=int,
help="Please provide the player id that you are playing for",
)
args = parser.parse_args()

action_commands = ['NOP', 'NORTH', 'SOUTH', 'EAST', 'WEST', 'TOGGLE_CART', 'INTERACT', 'CANCEL']

game_commands = ['ESCAPE', 'SAVE', 'TOGGLE_RECORD', 'PAUSE', 'REVERT']

print("action_commands: ", action_commands)
print("game_commands: ", game_commands)

# Connect to Supermarket
HOST = '127.0.0.1'
PORT = 9000
sock_game = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_game.connect((HOST, PORT))

pygame.init()

# Set up a display to accept keyboard command
screen_size = (400, 100)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("Control Display")

running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
# game events
if event.key == pygame.K_ESCAPE:
send_command('ESCAPE')
elif event.key == pygame.K_s:
send_command('SAVE')
elif event.key == pygame.K_r:
send_command('TOGGLE_RECORD')
elif event.key == pygame.K_p:
send_command('PAUSE')
elif event.key == pygame.K_z:
send_command('REVERT')
elif event.key == pygame.K_c:
send_command(str(args.player_id) + ' TOGGLE_CART')
elif event.key == pygame.K_RETURN:
send_command(str(args.player_id) + ' INTERACT')
elif event.key == pygame.K_b:
send_command(str(args.player_id) + ' CANCEL')


# Player events to send repeatedly to smooth transition
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
send_command(str(args.player_id) + ' NORTH')
elif keys[pygame.K_DOWN]:
send_command(str(args.player_id) + ' SOUTH')
elif keys[pygame.K_LEFT]:
send_command(str(args.player_id) + ' WEST')
elif keys[pygame.K_RIGHT]:
send_command(str(args.player_id) + ' EAST')

pygame.quit()
exit()
22 changes: 20 additions & 2 deletions socket_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import argparse
import datetime
import json
from pprint import pprint
import selectors
import socket
import types
Expand All @@ -15,6 +14,8 @@

ACTION_COMMANDS = ['NOP', 'NORTH', 'SOUTH', 'EAST', 'WEST', 'INTERACT', 'TOGGLE_CART', 'CANCEL', 'SELECT','RESET']

GAME_COMMANDS = ['ESCAPE', 'SAVE', 'TOGGLE_RECORD', 'PAUSE', 'REVERT']

def serialize_data(data):
if isinstance(data, set):
return list(data)
Expand Down Expand Up @@ -261,6 +262,20 @@ def get_action_json(action, env_, obs, reward, done, info_=None, violations=''):
# action_json = {"hello": "world"}
return action_json

def is_game_command(command_):
return command_ in GAME_COMMANDS

def get_event(command_):
if command_ == 'ESCAPE':
return pygame.event.Event(pygame.KEYDOWN, key=pygame.K_ESCAPE)
elif command_ == 'SAVE':
return pygame.event.Event(pygame.KEYDOWN, key=pygame.K_s)
elif command_ == 'TOGGLE_RECORD':
return pygame.event.Event(pygame.KEYDOWN, key=pygame.K_r)
elif command_ == 'PAUSE':
return pygame.event.Event(pygame.KEYDOWN, key=pygame.K_p)
elif command_ == 'REVERT':
return pygame.event.Event(pygame.KEYDOWN, key=pygame.K_z)

def is_single_player(command_):
return ',' not in command_
Expand Down Expand Up @@ -449,7 +464,7 @@ def accept_wrapper(sock):
curr_action = [(0,0)] * env.unwrapped.num_players
e = []
if not args.headless:
handler.handle_events() # TIA TODO: INJECTION OF KEYBOARD COMMANDS
handler.handle_events()
env.render()
for key, mask in events:
if key.data is None:
Expand All @@ -474,6 +489,9 @@ def accept_wrapper(sock):
data.outb = str.encode(json.dumps(json_to_send,default=lambda o: o.__dict__) + "\n")
if is_playback_mode(command):
env.unwrapped.game.is_playback = True
if is_game_command(command):
keydown_event = get_event(command)
pygame.event.post(keydown_event)
if is_single_player(command):
player, command, arg = get_player_and_command(command)
e.append((key, mask, command))
Expand Down