From 73277aad81b98e314757c3efc0246ceaccacda18 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Thu, 19 Apr 2012 14:32:05 +0200 Subject: [PATCH] Fix Python 3 compatibility of the assembler. --- assembler.py | 2 +- core.py | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 3 deletions(-) mode change 100644 => 100755 core.py diff --git a/assembler.py b/assembler.py index 616bf9a..db8a56e 100755 --- a/assembler.py +++ b/assembler.py @@ -143,7 +143,7 @@ def evaluate_operand(operand): description='Assembles a RedCode assembly file into a load file.') parser.add_argument('--force', '-f', action='store_true', help='determines whether existing files will be overwritten') - parser.add_argument('warriors', metavar='warrior.red', type=file, + parser.add_argument('warriors', metavar='warrior.red', type=open, nargs='+', help='file to be assembled') for (key, value) in core.MarsProperties().as_dict.items(): diff --git a/core.py b/core.py old mode 100644 new mode 100755 index e8726ed..613ec9e --- a/core.py +++ b/core.py @@ -1,10 +1,16 @@ +#!/usr/bin/env python """This is the memory of the MARS.""" +from __future__ import print_function + __all__ = ['RedcodeSyntaxError', 'Instruction', 'Mars', 'Memory', 'Warrior'] import re +if 'xrange' not in globals(): # Python 3 + xrange = range + def get_int(operand): """Shortcut for extracting the integer from an operand.""" if len(operand) < 1: @@ -350,8 +356,6 @@ def __init__(self, size): if not isinstance(size, int): raise ValueError('Memory size must be an integer, not %r' % size) self._size = size - if 'xrange' not in globals(): # Python 3 - xrange = range self._memory = [Instruction('DAT', None, '$0', '$0') for x in xrange(1, self.size)] self._loaded_warriors = {} @@ -442,6 +446,7 @@ def as_dict(self): class Mars(object): def __init__(self, properties): + self._properties = properties self._memory = Memory(properties.coresize) self._warriors = [] @@ -467,7 +472,17 @@ def run(self): else: return warrior + def cycle(self): + warriors = [] + for i in xrange(1, len(self._warriors)): + warrior = self.run() + if warrior is not None: # Warrior died + warriors.append(warrior) + return warriors + class Warrior(object): + name = None + author = None def __init__(self, program='', origin=None): if origin is not None: if not isinstance(program, list): @@ -479,6 +494,13 @@ def __init__(self, program='', origin=None): program) self._origin = origin self._initial_program = program + for line in program.split('\n'): + if not line.startswith(';'): + break; + if line.startswith(';name '): + self.name = line[len(';name '):] + elif line.startswith(';author '): + self.author = line[len(';author '):] else: if isinstance(program, list): raise ValueError('If you supply a list as the program, you ' @@ -499,6 +521,10 @@ def __init__(self, program='', origin=None): def __eq__(self, other): return self._initial_program == other._initial_program + def __str__(self): + return '%s by %s' % (self.name or 'unnamed warrior', + self.author or 'anonymous') + @property def threads(self): return [x for x in self._threads] # Shallow copy @@ -522,3 +548,49 @@ def run(self, memory): self._threads.extend(new_threads) return (self._threads != []) # True if warrior is still alive +if __name__ == '__main__': + import os + import sys + import argparse + parser = argparse.ArgumentParser( + description='Runs a bunch of warriors.') + parser.add_argument('warriors', metavar='warrior.rc', type=open, + nargs='+', help='warrior source codes.') + + for (key, value) in MarsProperties().as_dict.items(): + parser.add_argument('--' + key, default=value, type=int) + + try: + args = vars(parser.parse_args()) + except IOError as e: # Failed to open files + sys.stderr.write(str(e) + '\n') + sys.stderr.flush() + exit() + + warriors = args.pop('warriors') + + print('Booting MARS.') + properties = MarsProperties(**args) + mars = Mars(properties) + + print('Loading warriors:') + warriors = [Warrior(x.read()) for x in warriors] + for warrior in warriors: + print(str(warrior)) + mars.load(warrior) + + print('Running processes.') + for cycle in xrange(1, properties.maxcycles): + dead_warriors = mars.cycle() + for warrior in dead_warriors: + warriors.remove(dead_warriors) + print('\tWarrior %s died at cycle %i' % warrior, cycle) + if len(mars.warriors) <= 1: + break + + print('War ended at cycle %i.' % cycle) + for warrior in warriors: + if warrior in mars.warriors: + print('\t%s survived.' % warrior) + else: + print('\t%s died.' % warrior)