Exemple #1
0
 def setup(self):
     # State
     self._state = GameState()
     # Setup Functions
     self.setup_audio()
     self.setup_textures()
     self.setup_sprites()
     self.setup_animations()
     self.setup_meshes()
     # Setup Hud
     GameHud.get_singleton().setup()
     # Initial State
     self.set_state(GameState_Game())
     self.is_setup = True
Exemple #2
0
 def __init__(self, display):
     self.display = display
     self.currentState = 0
     self.maxStates = 5
     self.states = [
         GameState.MenuState(display, self),
         TrainingState.TrainingState(display, self)
     ]
Exemple #3
0
    def value_iteration(self):
        """
        Main work horse for the VI algorithm.

        after initialization of everything so that all states are known and stored in V and Q

        start updating V and Q until the largest difference in V and V_last is less than epsilon.
        """
        epsilon = .1

        states = self.game.get_valid_states()
        for state in states:
            if self.game.is_goal(state):
                self.v[state.value()] = 1
            else:
                self.v[state.value()] = 0

        v_last = copy.deepcopy(self.v)

        self.q = self.init_q(self.v, self.possible_actions)
        policy = self.init_policy(self.v)

        is_first_round = True
        update_cycle = 0
        while not self.v_s_comp_v_s_last_less_than_epsilon(
                v_last, self.v, epsilon, is_first_round):
            is_first_round = False
            v_last = copy.deepcopy(self.v)
            # count = 0
            for tuple_state in self.v:
                if self.game.is_goal(
                        GameState((tuple_state[0], tuple_state[1]),
                                  (tuple_state[2], tuple_state[3]))):
                    policy[tuple_state] = None
                    # reward value
                    self.v[tuple_state] = 1
                else:
                    for action in self.possible_actions:
                        self.update_q_iteration(self.game, tuple_state, action,
                                                self.q, self.gamma, v_last)
                    policy[tuple_state] = self.arg_max_iteration_version(
                        tuple_state, self.q)
                    self.v[tuple_state] = self.q[tuple_state][
                        policy[tuple_state]]
                # print(count)
                # count += 1
            print(update_cycle)
            update_cycle += 1

        return policy, update_cycle
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.hColor = "blue"
        self.vColor = "maroon"

        # stores information about the game
        self.gameState = GameState()
        # used to calculate win expectancy
        # Run Environment: 4.5
        # Home Team Win %: .5
        self.winCalc = WinExpCalculator(4.5, 0.5)

        self.createWidgets()
        self.updateGameDisplay()
        self.updateStateDisplay()
def scoreGame(view: GameViewSource, showDisplay: bool=False, showFullDisplay: bool=False, slowDown: int=1):
    """The main game function."""

    prevFrame = None

    if showFullDisplay:
        cv2.namedWindow("window", cv2.WND_PROP_FULLSCREEN)
        cv2.setWindowProperty("window", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

    servingSide = getSideSignal(view, [0, 0], showFullDisplay)
    if servingSide is None:
        print('Quiting...')
        exit(-1)

    ball = Ball(view.netX, servingSide=servingSide)
    game = GameState(view)
    game.begin(view.netX, servingSide)
    CURRENT_DISPLAY = getDisplay(game.score, servingSide)
    print('Got serving side')

    gameMonitor = GameMonitor(game)

    while True:
        frame = view.read()

        # End of video
        if frame is None:
            print("Stream ended.")
            break

        if ball.updatePosFromFrame(prevFrame, frame, showProcessedFrame=False, showMaskFrame=False):
            ball.updateProcessedData(output=False)
            game.updateState(ball, output=False)

            gameMonitor.printNewEvents()

            if showDisplay:
                key = cv2.waitKey(int(1000 / view.fps * (slowDown if slowDown != -1 else 1.0)))
                if key == ord('q'):
                    print('Quiting.')
                    exit(0)
                if slowDown == -1:
                    input('>')

            if showFullDisplay:
                newDisplay = gameMonitor.getGameDisplay()
                if newDisplay is not None:
                    CURRENT_DISPLAY = newDisplay
                cv2.imshow('window', CURRENT_DISPLAY)
                if cv2.waitKey(1) == ord('q'):
                    break

        prevFrame = frame
Exemple #6
0
def ucs(current_state, goal_pos, chooseVisited=False):
    startpos = current_state.agent.pos
    factor = -1 if chooseVisited else 1
    # print(startpos, goal_pos)

    explored = []
    frontier = PriorityQueue()
    frontier.push((startpos, []), 0)
    while not frontier.isEmpty():
        pos, moves = frontier.pop()
        if pos == goal_pos:
            return moves
        explored.append(pos)

        for adj, action in GameState.get_adjs(current_state, pos):
            if adj not in explored:
                newMoves = moves + [action]
                frontier.update(
                    (adj, newMoves),
                    factor *
                    getCostOfActions(current_state, startpos, newMoves))
Exemple #7
0
    def update_q(self, q, new_state: GameState, previous_state: GameState, action_taken: tuple, reward: int) -> dict:
        """
        Update q based on:
        q[s,a] = Q[s,a] + alpha(r + gamma* max_args(Q[s'])

        The main update function for updating a given q value.
        """
        previous_state_hash = previous_state.value()

        if action_taken is None:
            action_taken = ("end", "end")

        if previous_state_hash not in q:
            q[previous_state_hash] = {}

        if action_taken not in q[previous_state_hash]:
            q[previous_state_hash][action_taken] = reward

        current_q_value = q[previous_state_hash][action_taken]
        q[previous_state_hash][action_taken] = \
            current_q_value + self.alpha * (reward + (self.gamma * self.get_max_value(new_state.value(), q)) - current_q_value)

        return q
Exemple #8
0
    def get_action(self, state):
        pos = state.agent.pos
        adjs = GameState.get_adjs(state, pos)
        self.description = '\n--------------------\nPos: ' + name(pos) + '\n'
        self.description += "KB:\t" + str(self.KB.KB) + '\n'

        "Moving following by the temporary goals"
        if (self.actions != []):
            self.description += 'Goal: Move to the next safe place: '
            if (self.iLeaving):
                self.description += name(state.exit) + ' (Exit)'
            else:
                self.description += name(self.safe_places[0])
            return self.actions.pop(0)

        "Gold picking - Prioritize picking gold"
        if ('G' in state.explored[pos]):
            self.description += 'Goal: Pick gold'
            return Actions.PICK_GOLD

        "Add KB"
        if 'S' in state.explored[pos]:
            self.handle_stench(pos, adjs)
            "If there is enough condition to conclude the wumpus position"
            target_dir, target_pos = self.wumpus_check(pos, adjs)
            if (target_dir != None and target_pos not in self.checked_places):
                self.checked_places.append(target_pos)
                # self.safe_places.append(target_pos)
                self.description += 'Goal: Attempting to shoot at ' + \
                    name(target_pos)
                return Actions.shoot(target_dir)
        else:
            self.handle_not_stench(pos, adjs)
        if 'B' in state.explored[pos]:
            self.handle_breeze(pos, adjs)
        else:
            self.handle_not_breeze(pos, adjs)

        "Update safe places"
        temp = []
        for adj, _ in adjs:
            if (self.is_safe(adj)
                ) and adj not in self.visited and adj not in self.safe_places:
                temp.append(adj)
                self.safe_places.insert(0, adj)
        if (temp != []):
            self.description += 'Percept: ' + \
                str(temp) + ' is safe and not yet visited\n'

        "Update visited lists"
        self.visited.append(pos)
        if (pos in self.safe_places):
            self.safe_places.remove(pos)

        "Find the next place to move"
        if (self.safe_places != []):
            self.actions = ucs(state, self.nearest_safe_place())
            self.description += 'Goal: Move to the next unvisited safe place: ' + \
                name(self.safe_places[0])
            return self.actions.pop(0)

        "If there is no safe place => Exit"
        if pos == state.exit and self.iLeaving:
            self.description += 'Goal: Climb out of the cave'
            return Actions.EXIT
        else:
            self.iLeaving = True
            self.description += 'Goal: Find the exit to leave'
            self.actions = ucs(state, state.exit)
            return self.actions.pop(0)
Exemple #9
0
class Game:
    def __init__(self):
        # State
        self._state = None
        self.is_setup: bool = False

    def setup(self):
        # State
        self._state = GameState()
        # Setup Functions
        self.setup_audio()
        self.setup_textures()
        self.setup_sprites()
        self.setup_animations()
        self.setup_meshes()
        # Setup Hud
        GameHud.get_singleton().setup()
        # Initial State
        self.set_state(GameState_Game())
        self.is_setup = True

    @staticmethod
    def get_singleton():
        global _instance
        if _instance is None:
            _instance = Game()
        return _instance

    def set_state(self, _new_state: GameState):
        self._state.exit()
        self._state = _new_state
        self._state.enter()

    def get_state(self) -> GameState:
        return self._state

    def setup_audio(self):
        # Load Audio (music)
        Song('music_25m', 'audio/music_25m.wav')
        Song('music_50m', 'audio/music_50m.mp3')
        Song('music_75m', 'audio/music_75m.mp3')
        Song('music_100m', 'audio/music_100m.mp3')
        # Load Audio (sound effects)
        SFX('sfx_jump', 'audio/sfx_jump.wav')
        SFX('sfx_walk1', 'audio/sfx_walk1.wav')
        SFX('sfx_walk2', 'audio/sfx_walk2.wav')
        SFX('sfx_walk3', 'audio/sfx_walk3.wav')
        SFX('sfx_walk4', 'audio/sfx_walk4.wav')
        SFX('sfx_walk5', 'audio/sfx_walk5.wav')
        SFX('sfx_barrel_score', 'audio/sfx_barrel_score.wav')
        SFX('sfx_death', 'audio/sfx_death.wav')

    def setup_textures(self):
        # Font Texture
        Texture('font', 'assets/text/tilesheet.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('numbers', 'assets/numbers/numbers.png', FilterMode.POINT,
                WrapMode.CLAMP)

        # Special Stuff
        Texture('pixel_black', 'assets/pixels/pixel_black.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('pixel_white', 'assets/pixels/pixel_white.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('pixel_red', 'assets/pixels/pixel_red.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('pixel_green', 'assets/pixels/pixel_green.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('pixel_blue', 'assets/pixels/pixel_blue.png', FilterMode.POINT,
                WrapMode.CLAMP)

        # Hud Stuff
        Texture('mini_mario', 'assets/hud/mini_mario.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('bonus_counter', 'assets/hud/bonus_counter.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('highscore1', 'assets/hud/highscore1.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('highscore2', 'assets/hud/highscore2.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('highscore3', 'assets/hud/highscore3.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('life_icon', 'assets/hud/life_icon.png', FilterMode.POINT,
                WrapMode.CLAMP)

        # Game Stuff
        Texture('score_100', 'assets/effects/score_100.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('score_200', 'assets/effects/score_200.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('score_300', 'assets/effects/score_300.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('score_500', 'assets/effects/score_500.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('score_800', 'assets/effects/score_800.png', FilterMode.POINT,
                WrapMode.CLAMP)

        Texture('dk_center', 'assets/dk/dk1.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('dk_left', 'assets/dk/dk2.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('dk_drop', 'assets/dk/dk3.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('dk_pound', 'assets/dk/dk4.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('dk_climb1', 'assets/dk/dk5.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('dk_climb2', 'assets/dk/dk6.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('dk_hold1', 'assets/dk/dk7.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('dk_hold2', 'assets/dk/dk8.png', FilterMode.POINT,
                WrapMode.CLAMP)

        Texture('mario1', 'assets/mario/mario1.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('mario2', 'assets/mario/mario2.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('mario3', 'assets/mario/mario3.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('mario_jump', 'assets/mario/mario_jump.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('mario_death1', 'assets/mario/mario_death1.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('mario_death2', 'assets/mario/mario_death2.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('mario_dead', 'assets/mario/mario_dead.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('mario_climb1', 'assets/mario/mario_climb1.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('mario_climb2', 'assets/mario/mario_climb2.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('mario_climb3', 'assets/mario/mario_climb3.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('mario_climb4', 'assets/mario/mario_climb4.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('mario_climb5', 'assets/mario/mario_climb5.png',
                FilterMode.POINT, WrapMode.CLAMP)

        # Idle hammer
        Texture('hammer_idle1_red', 'assets/mario_hammer/idle1_red.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_idle2_red', 'assets/mario_hammer/idle2_red.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_idle1_yellow', 'assets/mario_hammer/idle1_yellow.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_idle2_yellow', 'assets/mario_hammer/idle2_yellow.png',
                FilterMode.POINT, WrapMode.CLAMP)
        # Walk with hammer
        Texture('hammer_walk1_red', 'assets/mario_hammer/walk1_red.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_walk2_red', 'assets/mario_hammer/walk2_red.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_walk3_red', 'assets/mario_hammer/walk3_red.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_walk4_red', 'assets/mario_hammer/walk4_red.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_walk1_yellow', 'assets/mario_hammer/walk1_yellow.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_walk2_yellow', 'assets/mario_hammer/walk2_yellow.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_walk3_yellow', 'assets/mario_hammer/walk3_yellow.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('hammer_walk4_yellow', 'assets/mario_hammer/walk4_yellow.png',
                FilterMode.POINT, WrapMode.CLAMP)

        Texture('floor1', 'assets/tiles/floor1.png', FilterMode.POINT,
                WrapMode.REPEAT)
        Texture('ladder1', 'assets/tiles/ladder1.png', FilterMode.POINT,
                WrapMode.REPEAT)

        Texture('hammer', 'assets/objects/hammer.png', FilterMode.POINT,
                WrapMode.CLAMP)

        Texture('barrel_side1', 'assets/objects/barrel_side1.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('barrel_side2', 'assets/objects/barrel_side2.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('barrel', 'assets/objects/barrel.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('barrel_side1_blue', 'assets/objects/barrel_side1_blue.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('barrel_side2_blue', 'assets/objects/barrel_side2_blue.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('barrel_blue', 'assets/objects/barrel_blue.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('barrel_vertical', 'assets/objects/barrel_vertical.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('barrel_stack', 'assets/objects/stacked_barrels.png',
                FilterMode.POINT, WrapMode.CLAMP)

        Texture('fire_barrel1', 'assets/enemies/fire_barrel1.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('fire_barrel2', 'assets/enemies/fire_barrel2.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('fire_barrel3', 'assets/enemies/fire_barrel3.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('fire_barrel4', 'assets/enemies/fire_barrel4.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('fire_barrel5', 'assets/enemies/fire_barrel5.png',
                FilterMode.POINT, WrapMode.CLAMP)

        Texture('fire1', 'assets/enemies/fire1.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('fire2', 'assets/enemies/fire2.png', FilterMode.POINT,
                WrapMode.CLAMP)
        Texture('fire_blue1', 'assets/enemies/fire_blue1.png',
                FilterMode.POINT, WrapMode.CLAMP)
        Texture('fire_blue2', 'assets/enemies/fire_blue2.png',
                FilterMode.POINT, WrapMode.CLAMP)

    def setup_sprites(self):
        # Load Sprites
        Sprite('spr_pixel_black', 'pixel_black')
        Sprite('spr_pixel_white', 'pixel_white')
        Sprite('spr_pixel_red', 'pixel_red')
        Sprite('spr_pixel_green', 'pixel_green')
        Sprite('spr_pixel_blue', 'pixel_blue')

        # Hud
        Sprite('spr_mini_mario', 'mini_mario', Anchor.BOTLEFT)
        Sprite('spr_bonus_counter', 'bonus_counter', Anchor.BOTLEFT)
        Sprite('spr_highscore1', 'highscore1', Anchor.BOTLEFT)
        Sprite('spr_highscore2', 'highscore2', Anchor.BOTLEFT)
        Sprite('spr_highscore3', 'highscore3', Anchor.BOTLEFT)
        Sprite('spr_life_icon', 'life_icon', Anchor.BOTLEFT)

        # Game
        Sprite('spr_score_100', 'score_100', Anchor.BOT)
        Sprite('spr_score_200', 'score_200', Anchor.BOT)
        Sprite('spr_score_300', 'score_300', Anchor.BOT)
        Sprite('spr_score_500', 'score_500', Anchor.BOT)
        Sprite('spr_score_800', 'score_800', Anchor.BOT)

        Sprite('spr_dk_center', 'dk_center', Anchor.BOT)
        Sprite('spr_dk_left', 'dk_left', Anchor.BOT)
        Sprite('spr_dk_right', 'dk_left', Anchor.BOT).set_flip_x(True)
        Sprite('spr_dk_drop', 'dk_drop', Anchor.BOT)
        Sprite('spr_dk_hold_barrel1', 'dk_hold1', Anchor.BOT)
        Sprite('spr_dk_hold_barrel2', 'dk_hold2', Anchor.BOT)

        # Mario
        Sprite('spr_mario1', 'mario1', Anchor.BOT)
        Sprite('spr_mario2', 'mario2', Anchor.BOT)
        Sprite('spr_mario3', 'mario3', Anchor.BOT)
        Sprite('spr_mario_jump', 'mario_jump', Anchor.BOT)
        Sprite('spr_mario_death1', 'mario_death1', Anchor.BOT)
        Sprite('spr_mario_death2', 'mario_death2', Anchor.BOT).set_flip_x(True)
        Sprite('spr_mario_death3', 'mario_death1', Anchor.BOT).set_flip_y(True)
        Sprite('spr_mario_death4', 'mario_death2', Anchor.BOT)
        Sprite('spr_mario_dead', 'mario_dead', Anchor.BOT)
        Sprite('spr_mario_climb1', 'mario_climb1', Anchor.BOT)
        Sprite('spr_mario_climb2', 'mario_climb2', Anchor.BOT)
        Sprite('spr_mario_climb3', 'mario_climb3', Anchor.BOT)
        Sprite('spr_mario_climb4', 'mario_climb4', Anchor.BOT)
        Sprite('spr_mario_climb5', 'mario_climb5', Anchor.BOT)
        # Mario Hammer
        Sprite('spr_hammer_idle1_red', 'hammer_idle1_red', Anchor.BOT)
        Sprite('spr_hammer_idle2_red', 'hammer_idle2_red', Anchor.BOT)
        Sprite('spr_hammer_idle1_yellow', 'hammer_idle1_yellow', Anchor.BOT)
        Sprite('spr_hammer_idle2_yellow', 'hammer_idle2_yellow', Anchor.BOT)
        Sprite('spr_hammer_walk1_red', 'hammer_walk1_red', Anchor.BOT)
        Sprite('spr_hammer_walk2_red', 'hammer_walk2_red', Anchor.BOT)
        Sprite('spr_hammer_walk3_red', 'hammer_walk3_red', Anchor.BOT)
        Sprite('spr_hammer_walk4_red', 'hammer_walk4_red', Anchor.BOT)
        Sprite('spr_hammer_walk1_yellow', 'hammer_walk1_yellow', Anchor.BOT)
        Sprite('spr_hammer_walk2_yellow', 'hammer_walk2_yellow', Anchor.BOT)
        Sprite('spr_hammer_walk3_yellow', 'hammer_walk3_yellow', Anchor.BOT)
        Sprite('spr_hammer_walk4_yellow', 'hammer_walk4_yellow', Anchor.BOT)

        Sprite('spr_floor_red_1', 'floor1', Anchor.BOTLEFT)
        Sprite('spr_floor_red_2', 'floor1',
               Anchor.BOTLEFT).set_scale_x(2.0).set_uv_right(2.0)
        Sprite('spr_floor_red_6', 'floor1',
               Anchor.BOTLEFT).set_scale_x(6.0).set_uv_right(6.0)
        Sprite('spr_floor_red_14', 'floor1',
               Anchor.BOTLEFT).set_scale_x(14.0).set_uv_right(14.0)
        Sprite('spr_floor_red_18', 'floor1',
               Anchor.BOTLEFT).set_scale_x(18.0).set_uv_right(18.0)

        Sprite('spr_ladder_52', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(52.0 / 8.0).set_uv_top(52.0 / 8.0)
        Sprite('spr_ladder_24', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(24.0 / 8.0).set_uv_top(24.0 / 8.0)
        Sprite('spr_ladder_20', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(20.0 / 8.0).set_uv_top(20.0 / 8.0)
        Sprite('spr_ladder_16', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(16.0 / 8.0).set_uv_top(16.0 / 8.0)
        Sprite('spr_ladder_13', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(13.0 / 8.0).set_uv_top(13.0 / 8.0)
        Sprite('spr_ladder_8', 'ladder1', Anchor.BOTLEFT)
        Sprite('spr_ladder_6', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(6.0 / 8.0).set_uv_top(6.0 / 8.0)
        Sprite('spr_ladder_4', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(4.0 / 8.0).set_uv_top(4.0 / 8.0)
        Sprite('spr_ladder_3', 'ladder1',
               Anchor.BOTLEFT).set_scale_y(3.0 / 8.0).set_uv_top(3.0 / 8.0)

        Sprite('spr_fire_barrel1', 'fire_barrel1', Anchor.BOT)
        Sprite('spr_fire_barrel2', 'fire_barrel2', Anchor.BOT)
        Sprite('spr_fire_barrel3', 'fire_barrel3', Anchor.BOT)
        Sprite('spr_fire_barrel4', 'fire_barrel4', Anchor.BOT)
        Sprite('spr_fire_barrel5', 'fire_barrel5', Anchor.BOT)

        Sprite('spr_barrel_side1', 'barrel_side1', Anchor.BOT)
        Sprite('spr_barrel_side2', 'barrel_side2', Anchor.BOT)
        Sprite('spr_barrel_1', 'barrel', Anchor.BOT)
        Sprite('spr_barrel_2', 'barrel', Anchor.BOT).set_flip_x(True)
        Sprite('spr_barrel_3', 'barrel',
               Anchor.BOT).set_flip_x(True).set_flip_y(True)
        Sprite('spr_barrel_4', 'barrel', Anchor.BOT).set_flip_y(True)

        Sprite('spr_barrel_side1_blue', 'barrel_side1_blue', Anchor.BOT)
        Sprite('spr_barrel_side2_blue', 'barrel_side2_blue', Anchor.BOT)
        Sprite('spr_barrel_1_blue', 'barrel_blue', Anchor.BOT)
        Sprite('spr_barrel_2_blue', 'barrel_blue', Anchor.BOT).set_flip_x(True)
        Sprite('spr_barrel_3_blue', 'barrel_blue',
               Anchor.BOT).set_flip_x(True).set_flip_y(True)
        Sprite('spr_barrel_4_blue', 'barrel_blue', Anchor.BOT).set_flip_y(True)

        Sprite('spr_barrel_vertical', 'barrel_vertical')
        Sprite('spr_barrel_stack1', 'barrel_stack', Anchor.BOTLEFT)

        Sprite('spr_enemy_fire1', 'fire1')
        Sprite('spr_enemy_fire2', 'fire2')

    def setup_animations(self):
        # Load Animations
        SpriteSequence('anim_mario_idle', 'spr_mario1')
        SpriteSequence('anim_mario_walk', 'spr_mario1', 'spr_mario2',
                       'spr_mario2', 'spr_mario1', 'spr_mario3', 'spr_mario3')
        SpriteSequence('anim_mario_jump', 'spr_mario_jump')
        SpriteSequence('anim_mario_dying', 'spr_mario_death1',
                       'spr_mario_death2', 'spr_mario_death3',
                       'spr_mario_death4')
        SpriteSequence('anim_mario_dead', 'spr_mario_dead')
        SpriteSequence('anim_mario_climb', 'spr_mario_climb1',
                       'spr_mario_climb2', 'spr_mario_climb3',
                       'spr_mario_climb4', 'spr_mario_climb5')

        SpriteSequence('anim_mario_hammer_idle_red', 'spr_hammer_idle1_red',
                       'spr_hammer_idle2_red')
        SpriteSequence('anim_mario_hammer_idle_yellow',
                       'spr_hammer_idle1_yellow', 'spr_hammer_idle2_yellow')

        # Sprite('spr_hammer_idle1_red', 'hammer_idle1_red', Anchor.BOT)
        # Sprite('spr_hammer_idle2_red', 'hammer_idle2_red', Anchor.BOT)
        # Sprite('spr_hammer_idle1_yellow', 'hammer_idle1_yellow', Anchor.BOT)
        # Sprite('spr_hammer_idle2_yellow', 'hammer_idle2_yellow', Anchor.BOT)
        # Sprite('spr_hammer_walk1_red', 'hammer_walk1_red', Anchor.BOT)
        # Sprite('spr_hammer_walk2_red', 'hammer_walk2_red', Anchor.BOT)
        # Sprite('spr_hammer_walk3_red', 'hammer_walk3_red', Anchor.BOT)
        # Sprite('spr_hammer_walk4_red', 'hammer_walk4_red', Anchor.BOT)
        # Sprite('spr_hammer_walk1_yellow', 'hammer_walk1_yellow', Anchor.BOT)
        # Sprite('spr_hammer_walk2_yellow', 'hammer_walk2_yellow', Anchor.BOT)
        # Sprite('spr_hammer_walk3_yellow', 'hammer_walk3_yellow', Anchor.BOT)
        # Sprite('spr_hammer_walk4_yellow', 'hammer_walk4_yellow', Anchor.BOT)

        SpriteSequence('anim_dk_frames', 'spr_dk_center', 'spr_dk_left',
                       'spr_dk_right', 'spr_dk_hold_barrel1',
                       'spr_dk_hold_barrel2', 'spr_dk_drop')

        SpriteSequence(
            'anim_oil_barrel_empty',
            'spr_fire_barrel5',
        )
        SpriteSequence('anim_oil_barrel_normal', 'spr_fire_barrel1',
                       'spr_fire_barrel2')
        SpriteSequence(
            'anim_oil_barrel_burn',
            'spr_fire_barrel3',
            'spr_fire_barrel4',
        )

        SpriteSequence('anim_barrel_roll', 'spr_barrel_1', 'spr_barrel_2',
                       'spr_barrel_3', 'spr_barrel_4')
        SpriteSequence('anim_barrel_fall', 'spr_barrel_side1',
                       'spr_barrel_side2')
        SpriteSequence('anim_barrel_roll_blue', 'spr_barrel_1_blue',
                       'spr_barrel_2_blue', 'spr_barrel_3_blue',
                       'spr_barrel_4_blue')
        SpriteSequence('anim_barrel_fall_blue', 'spr_barrel_side1_blue',
                       'spr_barrel_side2_blue')

        SpriteSequence('anim_enemy1', 'spr_enemy_fire1', 'spr_enemy_fire2')

    def setup_meshes(self):
        # Load Meshes
        # _m1 = Mesh('quad_2d')
        # _v = (
        #     Vector3(-0.5, -0.5, 0),
        #     Vector3(+0.5, -0.5, 0),
        #     Vector3(+0.5, +0.5, 0),
        #     Vector3(-0.5, +0.5, 0)
        # )
        # _uv = (
        #     Vector2(0, 0),
        #     Vector2(1, 0),
        #     Vector2(1, 1),
        #     Vector2(0, 1)
        # )
        # _m1.set_vertices(_v)
        # _m1.set_uvs(_uv)
        pass

    def update(self, delta_time: float):

        # State Update
        self._state.update(delta_time)

        # Move Camera
        if Engine.Input.get_key(pygame.K_w):
            Engine.Camera.move_up()
        elif Engine.Input.get_key(pygame.K_s):
            Engine.Camera.move_down()
        if Engine.Input.get_key(pygame.K_a):
            Engine.Camera.move_left()
        elif Engine.Input.get_key(pygame.K_d):
            Engine.Camera.move_right()

        # Mode Switcher
        if Engine.Input.get_key(pygame.K_1):
            self.set_state(GameState_Menu())
        elif Engine.Input.get_key(pygame.K_2):
            self.set_state(GameState_Intro())
        elif Engine.Input.get_key(pygame.K_3):
            self.set_state(GameState_Ready())
        elif Engine.Input.get_key(pygame.K_4):
            self.set_state(GameState_Game())

        # Check if mario dead for level reset
        if type(self._state) is GameState_Game:
            _mario: Mario = self._state._mario
            if not _mario.alive:
                self.set_state(GameState_Game())

    def draw(self):
        Engine.Camera.push()

        # State Draw
        self._state.draw()

        # Draw Hud
        GameHud.get_singleton().draw()

        Engine.Camera.pop()

        # Flush it
        glFlush()

    def draw_debug(self, delta_time):

        # Draw UI
        self._state.draw_debug(delta_time)

    def get_Mario(self) -> Mario:
        return self._state._mario
class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.hColor = "blue"
        self.vColor = "maroon"

        # stores information about the game
        self.gameState = GameState()
        # used to calculate win expectancy
        # Run Environment: 4.5
        # Home Team Win %: .5
        self.winCalc = WinExpCalculator(4.5, 0.5)

        self.createWidgets()
        self.updateGameDisplay()
        self.updateStateDisplay()

    # This function creates the widgets used in the GUI's display
    def createWidgets(self):
        # current state of game
        self.gameFrm = Frame(self)
        # home score
        self.homeFrm = Frame(self.gameFrm)
        self.homeScoreLbl = Label(self.homeFrm)
        self.homeScoreTxt = StringVar()
        self.homeScoreLbl["textvariable"] = self.homeScoreTxt
        self.homeScoreLbl.pack(side=TOP)
        self.homeScoreLbl.configure(foreground=self.hColor, font=20)
        self.homePctLbl = Label(self.homeFrm)
        self.homePctTxt = StringVar()
        self.homePctLbl["textvariable"] = self.homePctTxt
        self.homePctLbl.configure(foreground=self.hColor)
        self.homePctLbl.pack(side=TOP)
        self.homeFrm.pack(side=LEFT)
        # visitor score
        self.visFrm = Frame(self.gameFrm)
        self.visScoreLbl = Label(self.visFrm)
        self.visScoreTxt = StringVar()
        self.visScoreLbl["textvariable"] = self.visScoreTxt
        self.visScoreLbl.pack(side=TOP)
        self.visScoreLbl.configure(foreground=self.vColor, font=20)
        self.visPctLbl = Label(self.visFrm)
        self.visPctTxt = StringVar()
        self.visPctLbl["textvariable"] = self.visPctTxt
        self.visPctLbl.configure(foreground=self.vColor)
        self.visPctLbl.pack(side=TOP)
        self.visFrm.pack(side=RIGHT)
        # win probability
        self.winFrm = Frame(self.gameFrm)
        self.wBar = WinBar(self.winFrm, self.hColor, self.vColor)
        self.innLbl = Label(self.winFrm)
        self.innTxt = StringVar()
        self.innLbl["textvariable"] = self.innTxt
        self.baseLbl = Label(self.winFrm)
        self.baseTxt = StringVar()
        self.baseLbl["textvariable"] = self.baseTxt
        self.playLbl = Label(self.winFrm)
        self.playTxt = StringVar()
        self.playLbl["textvariable"] = self.playTxt
        self.wBar.pack(side=TOP)
        self.innLbl.pack(side=TOP)
        self.baseLbl.pack(side=TOP)
        self.playLbl.pack(side=TOP)
        self.winFrm.pack(side=TOP)

        # visual separator
        self.separator = Frame(self, height=5, borderwidth=5, relief=SUNKEN)
        self.gameFrm.pack(side=TOP)
        self.separator.pack(side=TOP, fill=X, padx=5, pady=5)

        # run specific plays
        self.playFrm = LabelFrame(self, text="Choose Play:", borderwidth=2)
        self.plays = sorted(list(self.gameState.playDict.keys()))
        self.playMenVar = StringVar()
        self.playMenVar.set(self.plays[0])
        self.playSelect = OptionMenu(self.playFrm, self.playMenVar, *self.plays)
        self.playBttn = Button(self.playFrm, text="Run Play", command=self.playClick)
        self.playSelect.pack(side=LEFT)
        self.playBttn.pack(side=LEFT)
        self.playFrm.pack(side=TOP)

        # visual separator
        self.separator2 = Frame(self, height=5, borderwidth=5, relief=SUNKEN)
        self.gameFrm.pack(side=TOP)
        self.separator2.pack(side=TOP, padx=5, pady=5)

        # enter a specific game state
        self.stateFrm = LabelFrame(self, text="Go To Specific Game State:", borderwidth=2)
        self.innStFrm = Frame(self.stateFrm)
        self.innStLbl = Label(self.innStFrm, text="Inning: ")
        self.innEnter = Spinbox(self.innStFrm, from_=1, increment=1, to=100)
        self.halfStFrm = Frame(self.stateFrm)
        self.halfLbl = Label(self.halfStFrm, text="Top/Bottom: ")
        self.halfEnter = Spinbox(self.halfStFrm, values=("Bottom", "Top"))
        self.outStFrm = Frame(self.stateFrm)
        self.outLbl = Label(self.outStFrm, text="Outs: ")
        self.outEnter = Spinbox(self.outStFrm, from_=0, to=2, increment=1)
        self.hStFrm = Frame(self.stateFrm)
        self.hStLbl = Label(self.hStFrm, text="Home Score: ")
        self.hEnter = Spinbox(self.hStFrm, from_=self.gameState.hScore, increment=1, to=100)
        self.vStFrm = Frame(self.stateFrm)
        self.vStLbl = Label(self.vStFrm, text="Visitor Score: ")
        self.vEnter = Spinbox(self.vStFrm, from_=self.gameState.vScore, increment=1, to=100)
        self.baseStFrm = Frame(self.stateFrm)
        self.stateBttn = Button(self.stateFrm, text="Go", command=self.stateClick)
        self.hStLbl.pack(side=LEFT)
        self.hEnter.pack(side=LEFT)
        self.vStLbl.pack(side=LEFT)
        self.vEnter.pack(side=LEFT)
        self.hStFrm.pack(side=TOP)
        self.vStFrm.pack(side=TOP)
        self.innStLbl.pack(side=LEFT)
        self.innEnter.pack(side=LEFT)
        self.innStFrm.pack(side=TOP)
        self.halfLbl.pack(side=LEFT)
        self.halfEnter.pack(side=LEFT)
        self.halfStFrm.pack(side=TOP)
        self.outStFrm.pack(side=TOP)
        self.outLbl.pack(side=LEFT)
        self.outEnter.pack(side=LEFT)
        self.baseStFrm.pack(side=TOP)
        self.baseStLbl = Label(self.baseStFrm, text="Baserunners: ")
        self.baseStLbl.pack(side=LEFT)
        self.baseInt = []
        self.baseCh = []
        self.baseNames = ["1st", "2nd", "3rd"]
        for i in range(0, 3):
            self.baseInt.append(IntVar())
            self.baseCh.append(Checkbutton(self.baseStFrm, variable=self.baseInt[i], text=self.baseNames[i]))
            self.baseCh[i].pack(side=LEFT)
        self.stateBttn.pack(side=TOP)
        self.stateFrm.pack(side=BOTTOM)

    # updates the game to a state provided by input from gui
    def stateClick(self):
        try:
            self.gameState.outs = int(self.outEnter.get())
            if self.gameState.outs > 2 or self.gameState.outs < 0:
                raise ValueError("Bad Outs value")
            self.gameState.inning = int(self.innEnter.get())
            if self.gameState.inning < 1:
                raise ValueError("Inning < 1")
            self.gameState.hScore = int(self.hEnter.get())
            if self.gameState.hScore < 0:
                raise ValueError("Score < 1")
            self.gameState.vScore = int(self.vEnter.get())
            if self.gameState.vScore < 0:
                raise ValueError("Score < 1")
        except ValueError as e:
            print("Bad Game State Input: " + str(e))
            return
        halfStr = self.halfEnter.get()
        if halfStr == "Bottom":
            self.gameState.half = 1
        elif halfStr == "Top":
            self.gameState.half = 0
        else:
            print("Bad inning half value: " + halfStr)
        for i in range(0, 3):
            if self.baseInt[i].get() == 1:
                self.gameState.base[i] = True
            elif self.baseInt[i].get() == 0:
                self.gameState.base[i] = False
            else:
                print("Bad base checkbox value: " + str(self.baseInt[i].get()))
        self.updateGameDisplay()

    # runs a particular play from the drop down
    def playClick(self):
        play = self.playMenVar.get()
        self.gameState.runPlay(play)
        self.updateGameDisplay()
        self.updateStateDisplay()

    # updates the win probabilities displayed
    def updateProb(self):
        prob = self.getWinProb()
        self.wBar.update(prob)
        prob = int(round(prob, 0))
        self.homePctTxt.set("Win Pct: " + str(prob) + "%")
        self.visPctTxt.set("Win Pct: " + str(100 - prob) + "%")

    # Simple function to call getWinPct with the correct arguments
    def getWinProb(self):
        p = self.winCalc.getWinPct(
            self.gameState.getBaseState(),
            self.gameState.hScore - self.gameState.vScore,
            self.gameState.inning,
            self.gameState.outs,
            self.gameState.half,
        )
        return p * 100

    # Updates the display of the state of the game (top)
    def updateGameDisplay(self):
        # Inning display
        innStr = ""
        if self.gameState.half == 0:
            innStr += "Top "
        elif self.gameState.half == 1:
            innStr += "Bottom "
        innStr += "of inning "
        innStr += str(self.gameState.inning)
        innStr += ", " + str(self.gameState.outs) + " outs"
        self.innTxt.set(innStr)

        # Baserunner display
        baseStr = ""
        if self.gameState.getBaseState() == 1:
            baseStr = "Bases Empty"
        else:
            comma = 0
            if self.gameState.base[0]:
                comma = 1
                baseStr += " 1st"
            if self.gameState.base[1]:
                if comma == 1:
                    baseStr += ","
                baseStr += " 2nd"
                comma += 1
            if self.gameState.base[2]:
                if comma > 0:
                    baseStr += ","
                comma += 1
                baseStr += " 3rd"
            if comma > 1:
                baseStr = "Runners on:" + baseStr
            else:
                baseStr = "Runner on" + baseStr
        self.baseTxt.set(baseStr)

        # Score display
        hScore = self.gameState.hScore
        vScore = self.gameState.vScore
        if hScore != -1:
            self.homeScoreTxt.set("Home " + str(hScore))
        if vScore != -1:
            self.visScoreTxt.set("Visitor " + str(vScore))

        # Updates win probability and sets win % displays
        self.updateProb()

        # Win % change display
        lc = int(round(self.wBar.lastChange, 0))
        playTxt = "Last W% Change: "
        if lc > 0:
            playTxt += "Home +" + str(lc) + "%"
        elif lc < 0:
            playTxt += "Visitor +" + str(-1 * lc) + "%"
        else:
            playTxt += "Change < 1%"
        self.playTxt.set(playTxt)

    # Updates the "Go to specific game state" section to follow the actual
    # game state
    def updateStateDisplay(self):
        while self.gameState.inning > int(self.innEnter.get()):
            self.innEnter.invoke("buttonup")
        while self.gameState.inning < int(self.innEnter.get()):
            self.innEnter.invoke("buttondown")
        if self.gameState.half == 0:
            self.halfEnter.invoke("buttonup")
        else:
            self.halfEnter.invoke("buttondown")
        while self.gameState.outs > int(self.outEnter.get()):
            self.outEnter.invoke("buttonup")
        while self.gameState.outs < int(self.outEnter.get()):
            self.outEnter.invoke("buttondown")
        while self.gameState.hScore > int(self.hEnter.get()):
            self.hEnter.invoke("buttonup")
        while self.gameState.hScore < int(self.hEnter.get()):
            self.hEnter.invoke("buttondown")
        while self.gameState.vScore > int(self.vEnter.get()):
            self.vEnter.invoke("buttonup")
        while self.gameState.vScore < int(self.vEnter.get()):
            self.vEnter.invoke("buttondown")
        for i in range(0, 3):
            if self.gameState.base[i] == True:
                self.baseCh[i].select()
            else:
                self.baseCh[i].deselect()
        return