Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

netorcai.standalone: netorcai agent in a box #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
29 changes: 29 additions & 0 deletions examples/hello-gl/hello-gl-standalone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env python3
from netorcai.agent import *
from netorcai.standalone import run_agent

def game_logic(agent):
print("Logging in as a game logic...", end=' ', flush=True)
agent.send_login("py-gl", "game logic")
agent.read_login_ack()
print("done")

print("Waiting for DO_INIT...", end=' ', flush=True)
do_init = agent.read_do_init()
print("done")

print("Sending DO_INIT_ACK...", end=' ', flush=True)
agent.send_do_init_ack({"all_clients":{"gl": "python"}})
print("done")

for i in range(do_init.nb_turns_max):
print("Waiting for DO_TURN...", end=' ', flush=True)
do_turn = agent.read_do_turn()
print("done")

print("Sending DO_TURN_ACK...", end=' ', flush=True)
agent.send_do_turn_ack({"all_clients":{"gl": "python"}}, -1)
print("done")

if __name__ == '__main__':
run_agent(game_logic)
4 changes: 2 additions & 2 deletions examples/hello-gl/hello-gl.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
from netorcai.client import *
from netorcai.agent import *
import sys

def main():
try:
client = Client()
client = Agent()

print("Connecting to netorcai...", end=' ', flush=True)
client.connect()
Expand Down
32 changes: 32 additions & 0 deletions examples/hello-player/hello-player-standalone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python3
from netorcai.agent import *
import sys
from netorcai.standalone import run_agent

def play(agent):

print("Connecting to netorcai...", end=' ', flush=True)
agent.connect()
print("done")

print("Logging in as a player...", end=' ', flush=True)
agent.send_login("py-player", "player")
agent.read_login_ack()
print("done")

print("Waiting for GAME_STARTS...", end=' ', flush=True)
game_starts = agent.read_game_starts()
print("done")

for i in range(game_starts.nb_turns_max):
print("Waiting for TURN...", end=' ', flush=True)
turn = agent.read_turn()
print("done")

actions = [{"player": "python"}]
print("Sending actions {}...".format(actions), end=' ', flush=True)
agent.send_turn_ack(turn.turn_number, actions)
print("done")

if __name__ == '__main__':
run_agent(game_logic)
4 changes: 2 additions & 2 deletions examples/hello-player/hello-player.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
from netorcai.client import *
from netorcai.agent import *
import sys

def main():
try:
client = Client()
client = Agent()

print("Connecting to netorcai...", end=' ', flush=True)
client.connect()
Expand Down
4 changes: 2 additions & 2 deletions examples/hello-splayer/hello-splayer.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
from netorcai.client import *
from netorcai.agent import *
import sys

def main():
try:
client = Client()
client = Agent()

print("Connecting to netorcai...", end=' ', flush=True)
client.connect()
Expand Down
35 changes: 35 additions & 0 deletions examples/hello-visu/hello-visu-standalone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python3
from netorcai.agent import *
from netorcai.standalone import run_agent

def visualize(agent):

client = Agent()

print("Connecting to netorcai...", end=' ', flush=True)
client.connect()
print("done")

print("Logging in as a visualization...", end=' ', flush=True)
client.send_login("py-visu", "visualization")
client.read_login_ack()
print("done")

print("Waiting for GAME_STARTS...", end=' ', flush=True)
game_starts = client.read_game_starts()
print("done")

for i in range(game_starts.nb_turns_max):
print("Waiting for TURN...", end=' ', flush=True)
turn = client.read_turn()
print("done")

print("world state for turn", i, turn.game_state)

actions = []
print("Sending actions {}...".format(actions), end=' ', flush=True)
client.send_turn_ack(turn.turn_number, actions)
print("done")

if __name__ == '__main__':
run_agent(visualize)
6 changes: 4 additions & 2 deletions examples/hello-visu/hello-visu.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
from netorcai.client import *
from netorcai.agent import *
import sys

def main():
try:
client = Client()
client = Agent()

print("Connecting to netorcai...", end=' ', flush=True)
client.connect()
Expand All @@ -24,6 +24,8 @@ def main():
turn = client.read_turn()
print("done")

print("world state for turn", i, turn.game_state)

actions = []
print("Sending actions {}...".format(actions), end=' ', flush=True)
client.send_turn_ack(turn.turn_number, actions)
Expand Down
31 changes: 22 additions & 9 deletions netorcai/client.py → netorcai/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,40 @@ def recvall(sock, size, flags=0):
data += packet
return data

class Client:
"""A netorcai Client.
class Agent:
"""A netorcai Agent.

Handles client-side communications of the netorcai metaprotocol.
Most of the time, only the following methods should be called:
- connect() and close(), to connect to or disconnect from netorcai
An agent is any netorcai program except the gamemaster.
Handles agent-side communications of the netorcai metaprotocol.

Once connected to the gamemaster, only the following methods
should be called:
- close(), to connect to or disconnect from netorcai
- send_<MESSAGE_TYPE>, to send a message to netorcai
- recv_<MESSAGE_TYPE>, to blockingly receive a message from netorcai
- recv_<MESSAGE_TYPE>, to blockingly receive a message from netorcai.

In order to connect, you can either use:
- connect() to connect to a gamemaster running as a server
- take_over() to use an existing socket, for instance to talk to a
gamemaster connecting to this program as a server.
"""
def __init__(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
pass

def __del__(self):
self.close()

def connect(self, hostname="localhost", port=4242):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
self.socket.connect((hostname, port))

def take_over(self, socket):
self.socket = socket

def close(self):
self.socket.close()
if self.socket:
self.socket.close()

def send_string(self, string):
send_buffer = (string + "\n").encode('utf-8')
Expand Down
63 changes: 63 additions & 0 deletions netorcai/standalone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env python3

import netorcai.agent
import argparse
import socket
from threading import Thread

def run_agent(game_func):
parser = argparse.ArgumentParser()
parser.add_argument("--server", help="run as a server", action="store_true")
parser.add_argument("--port", type=int, help="port to use (as server or client)")
parser.add_argument("--host", type=str, help="host to connect to (as a client)",
default="localhost")
parser.add_argument("--verbose")

args = parser.parse_args()

if args.server:
serve(args, game_func)
else:
run_client(args, game_func)

def run_client(args, game_func):
agent = netorcai.agent.Agent()

port = args.port or 4242
host = args.host or "localhost"

if args.verbose:
print("Connecting to netorcai...", end=' ', flush=True)
agent.connect(hostname=host, port=port)
if args.verbose:
print("done")

try:
game_func(agent)
except Exception as e:
print(e)
sys.exit(1)
sys.exit(0)


def serve(args, game_func):

port = args.port or 4567

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
sock.listen()

while True:
(clientsocket, address) = sock.accept()

def run_on_sock():
agent = netorcai.agent.Agent()
agent.take_over(clientsocket)
try:
game_func(agent)
except Exception as game_exc:
print("fatal error in game function", game_exc)

t = Thread(target=run_on_sock)
t.run()