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

NF: Add --stop-after-kill option #843

Open
wants to merge 1 commit into
base: main
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
12 changes: 9 additions & 3 deletions pelita/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@
DEAD_ENDS = 0.25

class TkViewer:
def __init__(self, *, address, controller, geometry=None, delay=None, stop_after=None, fullscreen=False):
self.proc = self._run_external_viewer(address, controller, geometry=geometry, delay=delay, stop_after=stop_after, fullscreen=fullscreen)
def __init__(self, *, address, controller, geometry=None, delay=None,
stop_after=None, stop_after_kill=False, fullscreen=False):
self.proc = self._run_external_viewer(address, controller, geometry=geometry, delay=delay,
stop_after=stop_after, stop_after_kill=stop_after_kill, fullscreen=fullscreen)

def _run_external_viewer(self, subscribe_sock, controller, geometry, delay, stop_after, fullscreen):
def _run_external_viewer(self, subscribe_sock, controller, geometry, delay, stop_after, stop_after_kill, fullscreen):
# Something on OS X prevents Tk from running in a forked process.
# Therefore we cannot use multiprocessing here. subprocess works, though.
viewer_args = [ str(subscribe_sock) ]
Expand All @@ -60,6 +62,8 @@ def _run_external_viewer(self, subscribe_sock, controller, geometry, delay, stop
viewer_args += ["--delay", str(delay)]
if stop_after is not None:
viewer_args += ["--stop-after", str(stop_after)]
if stop_after_kill:
viewer_args += ["--stop-after-kill"]

tkviewer = 'pelita.scripts.pelita_tkviewer'
external_call = [sys.executable,
Expand Down Expand Up @@ -251,12 +255,14 @@ def setup_viewers(viewers=None, options=None, print_result=True):
if viewer_state['controller']:
proc = TkViewer(address=zmq_publisher.socket_addr, controller=viewer_state['controller'].socket_addr,
stop_after=options.get('stop_at'),
stop_after_kill=options.get('stop_after_kill'),
geometry=options.get('geometry'),
delay=options.get('delay'),
fullscreen=options.get('fullscreen'))
else:
proc = TkViewer(address=zmq_publisher.socket_addr, controller=None,
stop_after=options.get('stop_at'),
stop_after_kill=options.get('stop_after_kill'),
geometry=options.get('geometry'),
delay=options.get('delay'),
fullscreen=options.get('fullscreen'))
Expand Down
6 changes: 5 additions & 1 deletion pelita/scripts/pelita_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ def long_help(s):
parser.set_defaults(timeout_length=3)
game_settings.add_argument('--stop-at', dest='stop_at', type=int, metavar="N",
help='Stop before playing round N.')
game_settings.add_argument('--stop-after-kill', dest='stop_after_kill', action='store_true',
help='Stop when a bot has been killed.')

viewer_settings = parser.add_argument_group('Viewer settings')
viewer_settings.add_argument('--geometry', type=geometry_string, metavar='NxM',
Expand Down Expand Up @@ -363,12 +365,14 @@ def main():
geometry = args.geometry
delay = int(1000./args.fps)
stop_at = args.stop_at
stop_after_kill = args.stop_after_kill

viewer_options = {
"fullscreen" : args.fullscreen,
"geometry": geometry,
"delay": delay,
"stop_at": stop_at
"stop_at": stop_at,
"stop_after_kill": stop_after_kill
}

if args.reply_to:
Expand Down
5 changes: 4 additions & 1 deletion pelita/scripts/pelita_tkviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def geometry_string(s):
help='delay')
parser.add_argument('--stop-after', type=int, metavar="N",
help='Stop after N rounds.')
parser.add_argument('--stop-after-kill', action='store_true',
help='Stop after a bot has been killed.')
parser._optionals = parser.add_argument_group('Options')
parser.add_argument('--version', help='show the version number and exit',
action='store_const', const=True)
Expand All @@ -59,7 +61,8 @@ def main():
'geometry': args.geometry,
'fullscreen' : args.fullscreen,
'delay': args.delay,
'stop_after': args.stop_after
'stop_after': args.stop_after,
'stop_after_kill': args.stop_after_kill
}
v = TkViewer(**{k: v for k, v in list(tkargs.items()) if v is not None})
v.run()
Expand Down
18 changes: 17 additions & 1 deletion pelita/ui/tk_canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class UI:

class TkApplication:
def __init__(self, window, controller_address=None,
geometry=None, delay=1, stop_after=None, fullscreen=False):
geometry=None, delay=1, stop_after=None, stop_after_kill=False, fullscreen=False):
self.window = window
self.window.configure(background="white")

Expand Down Expand Up @@ -344,6 +344,9 @@ def __init__(self, window, controller_address=None,
self._stop_after_delay = delay
if self._stop_after is not None:
self._delay = self._min_delay
self._stop_after_kill = stop_after_kill
# This will be set once we get data
self._last_bot_was_killed = []

self._check_speed_button_state()

Expand Down Expand Up @@ -1139,6 +1142,19 @@ def observe(self, game_state):
game_state['bots'] = _ensure_list_tuples(game_state['bots'])
game_state['shape'] = tuple(game_state['shape'])
game_state['food_age'] = {tuple(pos): food_age for pos, food_age in game_state['food_age']}

# check if a bot has been killed in the last round
# gs.bot_was_killed does not reset the True state for a killed bot
# until a whole round is over, so we have to cache previous values
bot_was_killed = False
for last, now in zip(self._last_bot_was_killed, game_state['bot_was_killed']):
if now and not last:
bot_was_killed = True
self._last_bot_was_killed = game_state['bot_was_killed']

if self._stop_after_kill and bot_was_killed:
self.running = False

self.update(game_state)
if self._stop_after is not None:
if self._stop_after == 0:
Expand Down
7 changes: 5 additions & 2 deletions pelita/ui/tk_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,14 @@ class TkViewer:
app : The TkApplication class

"""
def __init__(self, address, controller_address=None, geometry=None, delay=1, stop_after=None, fullscreen=False):
def __init__(self, address, controller_address=None, geometry=None, delay=1, stop_after=None, stop_after_kill=False, fullscreen=False):
self.address = address
self.controller_address = controller_address
self.delay = delay
self.geometry = geometry if geometry else (900, 580)
self.fullscreen = fullscreen
self.stop_after = stop_after
self.stop_after_kill = stop_after_kill

self.context = zmq.Context()
self.socket = self.context.socket(zmq.SUB)
Expand Down Expand Up @@ -113,7 +114,9 @@ def run(self):
controller_address=self.controller_address,
geometry=self.geometry,
delay=self.delay,
stop_after=self.stop_after, fullscreen=self.fullscreen)
stop_after=self.stop_after,
stop_after_kill=self.stop_after_kill,
fullscreen=self.fullscreen)
# schedule next read
self.root.after_idle(self.read_queue)
try:
Expand Down