コード例 #1
0
    def _add_stationary_unit(self, pos, attacking=True):
        """
        attacking: True if this unit is a destructor
        """
        x, y = pos
        if transform.is_lowerHalf(y):
            for (i, j, r) in self.CIRCLE:
                if not transform.pos2_inbound((x + i, y + j)): continue
                p = transform.pos2_encode((x + i, y + j))

                if r < self.proximity_self[p]:
                    if attacking:
                        self.proximity_self[p] = r
                    else:
                        self.proximity_self[p] = self.MAX_STATIONARY_RANGE
        else:
            for (i, j, r) in self.CIRCLE:
                if not transform.pos2_inbound((x + i, y + j)): continue
                p = transform.pos2_encode((x + i, y + j))

                if r < self.proximity_enemy[p]:
                    if attacking:
                        self.proximity_enemy[p] = r
                    else:
                        self.proximity_enemy[p] = self.MAX_STATIONARY_RANGE
コード例 #2
0
 def _add_destructor_contribution(self, pos):
     (x, y) = pos
     if transform.is_lowerHalf(pos[1]):
         self.number_D_self += 1
         for (dx, dy, r) in self.CIRCLE_DESTRUCTOR:
             if not transform.pos2_inbound((x + dx, y + dy)): continue
             p = transform.pos2_encode((x + dx, y + dy))
             self.barrage_self[p] += 1
     else:
         self.number_D_enemy += 1
         for (dx, dy, r) in self.CIRCLE_DESTRUCTOR:
             if not transform.pos2_inbound((x + dx, y + dy)): continue
             p = transform.pos2_encode((x + dx, y + dy))
             self.barrage_enemy[p] += 1
コード例 #3
0
 def integrate(self, field):
     """
     Expensive function! If you need complex integration schemes consider
     doing this yourself. Integrates on a field, which is a function taking
     a position 0 <= p < ARENA_VOL
     """
     result = 0
     for pos in self:
         p = transform.pos2_encode(pos)
         result += field(p)
     return result
コード例 #4
0
    def analyseReactive(self):
        for path in self.path1_self:
            if not path: continue

            path.hazard = 0
            for i in range(len(path)):
                x2, y2 = path[i]
                p = transform.pos2_encode((x2, y2))

                stability = 0
                for (dx, dy) in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
                    stability += self.stability_F[p] \
                            + self.stability_E[p] \
                            + self.stability_D[p] * 2
                path.hazard_dp[i] = self.pressure_enemy[p] - stability
                path.hazard += path.hazard_dp[i]
コード例 #5
0
 def addUnit(self, game_state, pos, unittype):
     """
     Called by spawnDefensiveUnit only. Can only add points in friendly
     territory
     """
     uid = UNIT_TYPE_TO_INDEX[unittype]
     assert transform.is_lowerHalf(pos[1])
     p = transform.pos2_encode(pos)
     stability = self.STABILITY[uid]
     if uid == UNIT_TYPE_TO_INDEX[FILTER]:
         self._add_stationary_unit(pos, attacking=False)
         self.stability_F[p] = self.STABILITY[uid]
     elif uid == UNIT_TYPE_TO_INDEX[ENCRYPTOR]:
         self._add_stationary_unit(pos, attacking=False)
         self.stability_E[p] = self.STABILITY[uid]
     elif uid == UNIT_TYPE_TO_INDEX[DESTRUCTOR]:
         self._add_stationary_unit(pos, attacking=True)
         self._add_destructor_contribution(pos)
         self.stability_D[p] = self.STABILITY[uid]
コード例 #6
0
    def analyseAttack(self):
        # Find optimal path for self and enemy
        p_self = None
        f_self = float('-inf')

        def extract_feas(p):
            if p == None: return float('-inf')
            else: return p.feasibility

        def softmax(l: list):
            SOFTMAX_COMPRESS = 10
            l = [x / SOFTMAX_COMPRESS for x in l]
            m = max(l)
            if m == float('-inf'):
                return [0] * len(l)

            def condexp(x):
                if x == float('-inf'):
                    return 0
                else:
                    return math.exp(x - m)

            l = [condexp(x - m) for x in l]
            m2 = sum(l)
            l = [x / m2 for x in l]
            return l

        # Max # EMP spawnable
        maxemp_self = self.getNUnitsAffordable(EMP, player=0)
        for path in self.path1_self:
            if not path: continue

            f = self._evaluatePath(path, maxemp_self)
            path.analysed_attack = True
            if f > f_self:
                #gamelib.debug_write("New max: {} at {}".format(f, path.px[0]))
                f_self = f
                p_self = path

        # Use weighted feasibility to get pressure field for the other player
        feas = [extract_feas(p) for p in self.path1_self]
        feas = softmax(feas)
        if max(feas) <= 0.0:
            gamelib.debug_write("Self path maximum feasibility = 0")
        for (f, path) in zip(feas, self.path1_self):
            if f <= 0: continue
            for i in range(len(path)):
                # Calculate contribution
                x, y = path[i]
                p = transform.pos2_encode((x, y))
                self.pressure_enemy[p] += path.pressure_dp[i] * f

        p_enemy = None
        f_enemy = float('-inf')
        maxemp_enemy = self.getNUnitsAffordable(EMP, player=1)
        for path in self.path1_enemy:
            if not path: continue

            f = self._evaluatePath(path, maxemp_self)
            path.analysed_attack = True
            if f > f_enemy:
                f_enemy = f
                p_enemy = path
        # Use weighted feasibility to get pressure field for the other player
        feas = [extract_feas(p) for p in self.path1_enemy]
        feas = softmax(feas)
        if max(feas) <= 0.0:
            gamelib.debug_write("Enemy path maximum feasibility = 0")
        for (f, path) in zip(feas, self.path1_enemy):
            if f <= 0: continue
            for i in range(len(path)):
                # Calculate contribution
                x, y = path[i]
                p = transform.pos2_encode((x, y))
                self.pressure_self[p] += path.pressure_dp[i] * f

        self.primal_self = p_self
        self.primal_enemy = p_enemy

        if not self.primal_self:
            gamelib.debug_write('[Model] No primary trajectory is found!')
            return
        else:
            gamelib.debug_write('[Model] Primal Path start at [{}, {}]'.format(
                self.primal_self.px[0], self.primal_self.py[0]))
コード例 #7
0
    def _evaluatePath(self, path, nEMP: int = 1):
        """
        Populate the shield,damage field of the path. Populate pressure field.
        """
        if not path:
            # Path starts from a occupied unit.
            return float('-inf')

        path.evaluated = True
        player = 0 if transform.is_lowerHalf(path.py[0]) else 1

        path.feasibility = 0.0
        path.shield = 0.0
        path.damage = 0.0
        path.harass = 0.0

        if path.isDeadend:
            path.feasibility = float('-inf')
            return path.feasibility

        # Get list of encryptors
        if player == 0: encs = self.li_encryptors_self.copy()
        else: encs = self.li_encryptors_enemy.copy()

        EMP_STABILITY = self.STABILITY[UNIT_TYPE_TO_INDEX[EMP]]
        EMP_SPEED = self.SPEED[UNIT_TYPE_TO_INDEX[EMP]]
        EMP_RANGE = self.RANGE[UNIT_TYPE_TO_INDEX[EMP]]

        n = len(path)
        for i in range(n):
            x = path.px[i]
            y = path.py[i]
            p = transform.pos2_encode((x, y))

            # Filter the encs list
            ne = len(encs)
            encs = [e for e in encs if \
                transform.distance2(e, (x,y)) >= \
                    self.RANGE[UNIT_TYPE_TO_INDEX[ENCRYPTOR]] + 0.51]
            shield = (ne - len(encs)) * self.ENCRYPTOR_SHIELD
            path.shield_dp[i] = shield
            path.shield += shield

            # Enemy destructor
            if player == 0: damage = self.barrage_enemy[p]
            else: damage = self.barrage_self[p]
            path.damage_dp[i] = damage
            path.damage += damage

            if transform.is_lowerHalf(y) == (player == 0):
                path.dist_self += 1
            else:
                path.dist_enemy += 1

            nEMP += shield / EMP_STABILITY
            nEMP -= damage / EMP_STABILITY / EMP_SPEED

            path.pressure_dp[i] = nEMP * self.DAMAGE_F_EMP
            if player == 0:
                if self.proximity_enemy[p] == EMP_RANGE:
                    path.harass += 1
                    #gamelib.debug_write('Harassed (Self)')

                # This is always 0
                if transform.is_upperHalf(y):
                    path.pressure_dp[i] -= \
                        self.stability_F[p] + \
                        self.stability_E[p] + \
                        self.stability_D[p]
            else:
                if self.proximity_self[p] == EMP_RANGE:
                    path.harass += 1
                    #gamelib.debug_write('Harassed (Enemy)')

                # This is always 0
                if transform.is_lowerHalf(y):
                    path.pressure_dp[i] -= \
                        self.stability_F[p] + \
                        self.stability_E[p] + \
                        self.stability_D[p]

            AMBIENT_PRESSURE = self.DAMAGE_F_EMP
            path.pressure_dp[i] = max(path.pressure_dp[i], AMBIENT_PRESSURE)

        x_normal, y_normal = path.px[0], path.py[0]
        if player == 0:
            policy = self.policy_self
        else:
            policy = self.policy_enemy
            x_normal, y_normal = transform.pos2_flip((x_normal, y_normal))
        x_normal /= (transform.ARENA_SIZE - 1)
        y_normal /= (transform.HALF_ARENA - 1)
        path.feasibility = policy.w_dist_self  * path.dist_self \
                         - policy.w_dist_enemy * path.dist_enemy \
                         + policy.w_shield     * path.shield \
                         + policy.w_damage     * path.damage \
                         + policy.w_pos_x      * x_normal \
                         + policy.w_pos_y      * y_normal \
                         + policy.w_harass     * path.harass
        return path.feasibility
コード例 #8
0
ファイル: visual.py プロジェクト: LogicFan/c1game_terminal
            default=1, help='Turns', type=int)

    parser_analyse = subparsers.add_parser('analyse')
    parser_analyse.add_argument('-f', dest='path', action='store',
            help='Data Path', default='.', type=str)

    args = parser.parse_args()
    print('Mode: {}'.format(args.mode))
    if args.mode == 'test':
        # Generate random ARENA-sized array.
        a = [random.randint(0,2) for x in range(transform.ARENA_VOL)]
        a = array.array('i', a)
        # Set the bottom line to 1
        for p in range(transform.ARENA_SIZE):
            x,y = transform.pos2_edge_decode(p)
            p2 = transform.pos2_encode((x,y))
            a[p2] = 5

        printHeat(a)
        plotHeat(a)
        pyplot.show()
    elif args.mode == 'plot':
        printFloatReplay(args.path, args.turns)
        pyplot.show()
    elif args.mode == 'analyse':
        print('Starting Interactive UI')
        try:
            interactive_ui(args.path)
        except Exception as e:
            traceback.print_exc()
            print("Caught error ... Exiting")