spacepaste

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
from copy import deepcopy
from collections import defaultdict
from operator import itemgetter
    
# Creates flags for states
def create_constants(*constants):
     return {key: 2 ** index for index, key in enumerate(constants)}

for constant, value in create_constants("ROLE_SIMULATED", "ROLE_AUTONOMOUS", "ROLE_AUTHORITY").items(): 
    exec("{0} = {1}; NOT_{0} = ~{1}".format(constant, value))
 
for constant, value in create_constants("NET_DIRTY", "NET_OWNER", "NET_INITIAL").items(): 
    exec("{0} = {1}; NOT_{0} = ~{1}".format(constant, value))

class RoleSpecificFunction:
    def __init__(self, func):
        self.func = func
        self.bound_func = None
        
    def __get__(self, instance, base):
        if self.bound_func is None:
            self.bound_func = self.func.__get__(instance, base)
        return self
    
    def __call__(self, *args, **kwargs):
        return self.bound_func(*args, **kwargs)

class Simulated(RoleSpecificFunction):
    role = ROLE_SIMULATED
    
class Attribute:
    def __init__(self, condition, value):
        self.condition = condition
        self.default = value
        self.getter = self.setter = None
    
    def register_access(self, getter, setter):
        self.getter = getter
        self.setter = setter
        
    def __get__(self, instance, owner):
        try:
            return self.getter(self)
        except TypeError:
            if instance is None:
                return self
            raise NotImplementedError
        
    def __set__(self, instance, value):
        self.setter(self, value)
    
    def __repr__(self):
        return "<Attribute with condition {}, default value {}>".format(self.condition, self.default)

class ActorManager:
    def __init__(self):
        self.actors = []
        
    def create_actor(self):
        actor = Actor()
        self.actors.append(actor)
        return actor
    
class Scraper:
    def __init__(self):
        condition_to_attributes = {}
        attributes_to_values = {}
        
        current_role = 0
        
        # Get attributes
        for k, v in self.__class__.__dict__.items():
            if isinstance(v, RoleSpecificFunction):
                role = v.role
                if role != current_role:
                    v.bound_func = lambda *a, **b: None    
            
            if not isinstance(v, Attribute):
                continue
            
            condition_to_attributes.setdefault(v.condition, dict())[v] = k 
            attributes_to_values[v] = deepcopy(v.default)
            
            v.register_access(getter=attributes_to_values.__getitem__, 
                                setter=self.on_attribute_changed(attributes_to_values.__setitem__))
        
        # Sort by name within conditions
        for condition, values in condition_to_attributes.items():
            condition_to_attributes[condition] = sorted(values.keys(), key=values.__getitem__)
      
        self.attr_by_condition = condition_to_attributes
        self.value_by_attr = attributes_to_values
        self.attributes_changed = False
    
    def on_attribute_changed(self, dictionary):
        def _wrapper(*args, **kwargs):
            dictionary(*args, **kwargs)
            self.attributes_changed = True
        return _wrapper
    
class Actor(Scraper):
    score = Attribute(NET_DIRTY|NET_OWNER, 0) 
    argon = Attribute(NET_DIRTY|NET_OWNER, 3) 
    aim = Attribute(NET_OWNER, 1)
    
    @Simulated
    def shoot(self):
        return 2
        
    
class NetworkManager:
    def __init__(self, actor_manager):
        self.actor_manager = actor_manager
        self.last_values = defaultdict(set)
        self.replication_map = defaultdict(set)
        
    def state_for_actor(self, actor_caller):
        last_values = self.last_values
        replication_map = self.replication_map
        
        for actor in self.actor_manager.actors:
            is_owner = NET_OWNER if actor is actor_caller else 0
            is_dirty = NET_DIRTY if actor.attributes_changed else 0
            is_initial = 0 if (actor_caller in replication_map[actor]) else NET_INITIAL
            state = is_owner | is_dirty | is_initial
           
            try:
                attributes = actor.attr_by_condition[state]
            except KeyError:
                continue
            
actor_manager = ActorManager()

for i in range(60): 
    actor_manager.create_actor() 
    
network_manager = NetworkManager(actor_manager)

def main():
    # Not all actors are socket-owning players.
    for actor in actor_manager.actors[:4]:
        actor.shoot()
        network_manager.state_for_actor(actor)