Code Highlights

Here, I’ve gathered some examples of code I’ve personally written and am proud of.

You can view all of my public source code at Github.

Mobile Monsters

Mobile Monsters

Mobile Monsters is an Android game developed with the AndEngine framework. It is heavily inspired by the Nintendo game, Pokemon.

This game was developed as part of the Development of Games and Mobile Applications course at the University of North Florida and took roughly three weeks to develop.

The final game was demonstrated at the School of Computing Symposium December 2015.

The game can be downloaded and played via Android devices via the game’s homepage.

Gameplay

The user selects a team of three monsters to do battle against a team of monsters controlled by an AI opponent. On their turn throughout the battle, the user can select from several different attacks based on the attacks type, attack strength, and the defending monster’s type.

Code Excerpt

The following code excerpt is a bit of the logic the AI agent goes through in the “Hard” difficulty mode. The AI opponent determines the best attack against the player by analyzing its attacks against the opponent’s strengths and weaknesses.

The entire codebase is available on Github.


    /*
        Determine AI's next attack 
        Depends on difficulty mode, player's current weaknesses, and other factors
    /*
    public int opponentChooseAttack() {

        ArrayList<Monster> monsters = this.characterTeams.get(opponentIndex);
        Monster opponentMonster = monsters.get(activeOpponentMonsterIndex);
        Monster activeMonster = this.characterTeams.get(playerIndex).get(activeOpponentMonsterIndex);

        if(hardMode) {

            float effectiveness;

            ArrayList<Float> effectivenesses = new ArrayList<>();

            // Check all attacks for effectiveness, including STAB
            for(Attack attack : opponentMonster.getAttacks()) {
                effectiveness = 1f;

                // STAB - Same Type Attack Bonus
                if(opponentMonster.getTypes().indexOf(attack.getType()) > -1) {
                    effectiveness = 1.5f;
                }

                // process each of the player's active monster's types to determine best result
                for(MonsterType playerType : activeMonster.getTypes()) {
                    // if the opponent is weak to the attack, increase the effectiveness rate
                    if (attack.getType().getWeaknesses().indexOf(playerType.getName()) >= 0) {
                        effectiveness *= 2;
                    }

                    // if the opponent is resistant to the attack, decrease the effectiveness rate
                    if (attack.getType().getResistances().indexOf(playerType.getName()) >= 0) {
                        effectiveness /= 2;
                    }

                    // if the opponent is immune to the attack, eliminate attack from selection
                    if (attack.getType().getImmunities().indexOf(playerType.getName()) >= 0) {
                        effectiveness = 0f;
                    }
                }
                effectivenesses.add(effectiveness);
            }

            // Attack with the highest effectiveness against opponent is chosen
            return effectivenesses.indexOf(Collections.max(effectivenesses));
        } else {
            // In easy mode, just choose a random attack
            return new Random().nextInt(opponentMonster.getAttacks().size());
        }
    }

Screenshot

Mobile Monsters battle
Mobile Monsters battle

Networking

Online Multiplayer Mobile Game

I’ve developed an online multiplayer game for Android (and iOS-pending) using Monogame – a C# library for developing multimedia applications.

The game consists of two players being matched up by a matchmaking server algorithm, and taking turns choosing an attack against each other. The first player to lose all of their health loses the match.

Code Excerpt

The complexity of the project lies in the need to asynchronously access server resources so that the game’s animations and other functions are not hindered.

Below is the asynchronous update loop in C#, which processes server requests at the end of the update in order to not cause hiccups when the server responds with requested data.

        public override async void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            var timer = (float)gameTime.ElapsedGameTime.TotalSeconds;

            throbber.rotation += timer * throbberRotationSpeed;
            float circle = MathHelper.Pi * 2;
            throbber.rotation = throbber.rotation % circle;

            if (connected)
            {
                connectedDelay -= timer;
                if ((int)(connectedDelay) == 0)
                {
                    this.connectingMessage.label = "Match is starting...";
                }
                else
                {
                    this.connectingMessage.label = ((int)connectedDelay).ToString() + " Match found...";
                }
                if (connectedDelay <= 0) 
                { 
                    game.changeGameState(GameState.GAME_START); 
                } 
            }

            // if webclient is not already busy doing something
            if (!RestService.IsBusy())
            {
                // if server doesn't know we're ready to play - tell it!
                if (!this.server_notified)
                {
                    this.server_notified = await NotifyServer();
                }

                // if we're not connected to another player yet - see if one is ready!
                else if(!this.connected)
                {
                    this.connected = await CheckMatchFound();
                }

                else
                {
                    bool match_status = await CheckMatchStatus();

                    if(!match_status)
                    {
                        matchConnectionLostCounter++;
                    }

                    if(matchConnectionLostCounter >= 3)
                    {
                        connectedDelay = connectedDelayInitial;
                        this.server_notified = false;
                        this.matchConnectionLostCounter = 0;
                        this.connectingMessage.label = "Finding match...";
                    }
                }
            }
        }

Language Translators

C-minus Language Translator

This project was designed as part of a Construction of Language Translators course at the University of North Florida.

The program takes an input file consisting of a potentially valid C-minus program. The input file is processed for lexical and semantic errors, and if the program is valid the resulting quadruples (assembly instructions) are generated.

The entire codebase is available at Github.

Code Excerpt

Below is a small excerpt from the extensive recursive descent parser. The input file is broken down and is tested against the language’s grammar rules.

    # program -> declaration-list
    def program(self):
        self.start()
        self.declaration_list()
        self.end()

    # declaration-list -> var-declaration | function-declaration | empty-declaration
    def declaration_list(self):
        self.start()
        while len(self.tokens) > 0 and self.accepted is not False:
            self.declaration()
        self.end()

    # declaration -> type-specifier ID ; | type-specifier ID [ NUM ] ;
    def declaration(self):
        self.start()

        if self.current_token == [";", "OPERATORS"]:
            self.empty_declaration()
        else:
            current_symbol = symbol_table.Symbol()
            type = self.current_token[0]
            current_symbol.set_scope(self.scope)
            array_info = [False, 0]

            if self.current_token[0] == "void":
                self.found_void_type = True
            if self.current_token[0] == "int":
                self.found_int_type = True
            if self.current_token[0] == "float":
                self.found_float_type = True

            self.type_specifier()

            identifier = self.current_token[0]
            current_symbol.set_identifier(identifier)
            if self.current_token[0] == "main":
                self.parsing_main = True

            self.match("IDENTIFIER")

            if self.current_token == ["[", "OPERATORS"]:
                type += "[]"

            current_symbol.set_type(type)

            is_function = False
            if self.current_token == ["(", "OPERATORS"]:
                is_function = True
                current_symbol.set_is_function(is_function)

            elif self.found_void_type:
                self.reject_semantic("invalid type for variable, void")

            if not self.symbol_table.add_symbol(current_symbol):
                self.reject_semantic("Symbol already exists in scope: " + current_symbol.identifier)

            if self.current_token == ["(", "OPERATORS"]:

                if self.found_void_type:
                    self.parsing_void_function = True
                if self.found_int_type:
                    self.parsing_int_function = True
                if self.found_float_type:
                    self.parsing_float_function = True

                function_quadruple = len(self.quadruples)
                self.add_quadruple("func", identifier, type, 0)
                param_count = self.function_declaration()
                self.apply_functionpatch(function_quadruple, param_count)

                self.found_void_type = False
                self.parsing_void_function = False
                self.found_int_type = False
                self.parsing_int_function = False
                self.found_float_type = False
                self.parsing_float_function = False

                self.add_quadruple("end", "func", identifier, "")

            elif self.current_token and self.current_token[0] in ['[', ';']:
                array_info = self.var_declaration()
                size = self.calculate_quadruple_size(type, array_info)
                self.add_quadruple("alloc", size, "", identifier)

            self.parsing_main = False

        self.end()

AI & Robotics

Artificially Intelligent Robot

As part of an Artificial Intelligence course at the University of North Florida, I worked with a team of senior Computer Science students to develop an autonomous robot capable of recognizing objects by color and shape, and recognizing voice commands to perform appropriate actions.

I designed and wrote the OpenCV integration for the robot’s vision-based tasks. The implementation involved writing code directly to a Raspberry Pi to work in tandem with a USB-powered webcam. The script triggers the webcam to take a picture and processes the data in that picture to tell the robot where predetermined objects are.

Unfortunately, the source code is not available for this project.

Screenshots

Preview of in-progress color detection source, and processed image output.

2016-09-13-22_16_49-in-class-presentation-google-slides

First successful demonstration of a line-following algorithm (Excuse some language in the video).