Exemple #1
0
    def score(self, state: GameState, p: GoalParams) -> float:
        score = 0

        # bonus: be near the target
        for figure in state.getFigures(self.team):
            if not figure.killed:
                score += p.defend_team_near * self.values[
                    figure.position.tuple()] + 1

        # malus: having enemy units near the target
        for figure in state.getFigures(self.hostiles):
            if not figure.killed:
                score -= p.defend_enemy_near * self.values[
                    figure.position.tuple()] + 1

        return score
Exemple #2
0
    def score(self, state: GameState, p: GoalParams) -> float:
        score = 0

        # bonus: be near the target
        for figure in state.getFigures(self.team):
            if not figure.killed:
                score += p.reach_team_near * self.values[
                    figure.position.tuple()] + 1

        return score
Exemple #3
0
    def step(self,
             board: GameBoard,
             state: GameState,
             action: Action,
             forceHit: bool = False) -> Outcome:
        """Update the given state with the given action in a irreversible way."""

        team: str = action.team  # team performing action
        comment: str = ''

        logger.debug(f'{team} step with {action}')
        state.lastAction = action

        if isinstance(action, Wait):
            logger.debug(f'{action}: {comment}')
            return Outcome(comment=comment)

        if isinstance(action, Pass):
            if isinstance(action, PassFigure):
                f: Figure = state.getFigure(action)  # who performs the action
                f.activated = True
                f.passed = True

            if isinstance(action,
                          PassTeam) and not isinstance(action, Response):
                for f in state.getFigures(team):
                    f.activated = True
                    f.passed = True

            logger.debug(f'{action}: {comment}')

            return Outcome(comment=comment)

        if isinstance(action, Move):
            f: Figure = state.getFigure(action)  # who performs the action
            f.activated = True
            f.moved = True

            f.stat = stat('IN_MOTION')
            if isinstance(action, MoveLoadInto):
                # figure moves inside transporter
                t = state.getTransporter(action)
                t.transportLoad(f)
                comment = f'(capacity: {len(t.transporting)}/{t.transport_capacity})'
            elif f.transported_by > -1:
                # figure leaves transporter
                t = state.getFigureByIndex(team, f.transported_by)
                t.transportUnload(f)
                comment = f'(capacity: {len(t.transporting)}/{t.transport_capacity})'

            state.moveFigure(f, f.position, action.destination)

            for transported in f.transporting:
                t = state.getFigureByIndex(team, transported)
                t.stat = stat('LOADED')
                state.moveFigure(t, t.position, action.destination)

            logger.debug(f'{action}: {comment}')

            return Outcome(comment=comment)

        if isinstance(action, AttackGround):
            f: Figure = state.getFigure(action)  # who performs the action
            x: Cube = action.ground
            w: Weapon = state.getWeapon(action)

            f.stat = stat('NO_EFFECT')
            f.activated = True
            f.attacked = True
            w.shoot()

            if w.smoke:
                cloud = [
                    x + Cube(0, -1, 1),
                    x + Cube(1, -1, 0),
                    x + Cube(1, 0, -1),
                    x + Cube(0, 1, -1),
                    x + Cube(-1, 1, 0),
                    x + Cube(-1, 0, 1),
                ]

                cloud = [(c.distance(f.position), c) for c in cloud]
                cloud = sorted(cloud, key=lambda y: -y[0])

                state.addSmoke([c[1] for c in cloud[1:3]] + [x])

                comment = f'smoke at {x}'

            logger.debug(f'{action}: {comment}')

            return Outcome(comment=comment)

        if isinstance(action, Attack):  # Respond *is* an attack action
            f: Figure = state.getFigure(action)  # who performs the action
            t: Figure = state.getTarget(action)  # target
            # g: Figure = action.guard  # who has line-of-sight on target
            w: Weapon = state.getWeapon(action)
            # los: list = action.los  # line-of-sight on target of guard
            lof: list = action.lof  # line-of-fire on target of figure

            # consume ammunition
            f.stat = stat('NO_EFFECT')
            w.shoot()

            if forceHit:
                score = [0] * w.dices
            else:
                score = np.random.choice(range(1, 21), size=w.dices)

            # attack/response
            if isinstance(action, Response):
                ATK = w.atk_response
                INT = f.int_def
                # can respond only once in a turn
                f.responded = True
            else:
                ATK = w.atk_normal
                INT = f.int_atk
                f.activated = True
                f.attacked = True

            # anti-tank rule
            if state.hasSmoke(lof):
                DEF = t.defense['smoke']
            elif w.antitank and t.kind == 'vehicle':
                DEF = t.defense['antitank']
            else:
                DEF = t.defense['basic']

            TER = board.getProtectionLevel(t.position)
            STAT = f.stat.value + f.bonus
            END = f.endurance

            hitScore = hitScoreCalculator(ATK, TER, DEF, STAT, END, INT)

            success = len([x for x in score if x <= hitScore])

            # target status changes for the _next_ hit
            t.stat = stat('UNDER_FIRE')
            # target can now respond to the fire
            t.attacked_by = f.index

            if success > 0:
                self.applyDamage(state, action, hitScore, score, success, t, w)

                comment = f'success=({success} {score}/{hitScore}) target=({t.hp}/{t.hp_max})'
                if t.hp <= 0:
                    comment += ' KILLED!'

            elif w.curved:
                # missing with curved weapons
                v = np.random.choice(range(1, 21), size=1)
                hitLocation = MISS_MATRIX[team](v)
                missed = state.getFiguresByPos(t.team, hitLocation)
                missed = [m for m in missed if not m.killed]

                comment = f'({success} {score}/{hitScore}): shell missed and hit {hitLocation}: {len(missed)} hit'

                for m in missed:
                    self.applyDamage(state, action, hitScore, score, 1, m, w)

            else:
                logger.debug(f'({success} {score}/{hitScore}): MISS!')

            logger.debug(f'{action}: {comment}')

            return Outcome(
                comment=comment,
                score=score,
                hitScore=hitScore,
                ATK=ATK,
                TER=TER,
                DEF=DEF,
                STAT=STAT,
                END=END,
                INT=INT,
                success=success > 0,
                hits=success,
            )