Super Mario Bros


Hello, if you have any need, please feel free to consult us, this is my wechat: wx91due


Task Overview

For this assignment we will be working with a simulated version of Super Mario Bros that is written entirely in Java and developed by Ahmed Khalifa and modified for use with this assignment by Nic Pallant. For installation, setup and detailed instructions, please refer to our Getting Started Guide. Your task is to implement a game-playing controller for a Mario agent. To complete this task you will analyse the state of the game at different times and you will compute simulated button presses in response: LEFT, RIGHT, DOWN, RUN, and JUMP.

Your objective is to help Mario overcome a series of increasingly tricky obstacle courses before time runs out. Stomp on the enemies, jump over pits and grab the powerups on your way to the flagpole that awaits at the end of each level!

Your controller must use evolutionary principles: parent selection, breeding and mutation, a fitness function, population selection, and genotypes. How you implement these ideas is up to you:

  • You are free to consider any features you like from the game environment (e.g., as part of your genotypes).
  • You are free to use any kind of evolutionary process (e.g., fixed-length, variable-length and evolutionary programming)
  • You can combine evolution with other strategies (e.g., neural networks) 

Task 1: Beat Level 1-1 (Submission A)

You will be required to test your evolutionary algorithm’s performance by ensuring that it can complete Mario Level 1-1. Your performance will be assessed based on the Percentage Completion of the level.

4. Getting Started

Starting Off

Open IntelliJ and then Select Open and then navigate to the directory where you cloned the base code. Specifically make sure you open the directory that contains the img, levels, and src folders.

You will most likely get a message up the top that says “Project JDK is not defined”, click on Setup SDK, and then select Add SDK->Download JDK. Then when the window pops up, install JDK Version 21.With that, open up src->PlayLevel and then hit the Play button in the top right of the screen, this should start level 1-1 with a human controller (you!)

The controls are:

Left: Left Arrow Key
Right: Right Arrow Key
Down: Down Arrow Key
Speed: A
Jump: S

Have some fun trying to beat 1-1, you’ll be dealing with this level a lot over the next few weeks!

Creating a Controller

First, create a Package (folder) inside of the agents named EAController:

Then, right click inside this new folder and create a New Java Class named Agent. With this, you should have a blank class called Agent.

After that, at the end of the class declaration, add implements MarioAgent(You will need to add an import for engine.core.MarioAgent). This makes it so your new agent actually has the functions we need.

Speaking of functions, add the following four overridden functions:

To actually test it, head into PlayLevel.java and then change the Agent passed in in runGame to be agents.EAController.Agent() and then hit play! You should see Mario just standing there doing nothing until the timer runs out. This is because we haven’t given him any inputs!

Implementing Your Controller 

These are the only four functions we need to override, and will do all of the work we need it to do. The game can run in one of two modes, “assessed”, and “training” mode. The mode the game is in impacts what user defined functions are called. More details about these modes can be found in Section 5: The Game Loop.

The four functions that you will need to implement are:


  • initialize acts as a constructor/beginplay function here, where you can initialise/reset any variables.
    • This could include any minor pre-training / setting of initial genotypes.
  • getActions is the function that needs to return a list of 5 boolean values representing the buttons on a physical controller that it is pressing, in order they are [LEFT, RIGHT, DOWN, RUN, JUMP]. By default, each of these are set to false. This function is called every single tick to be able to figure out what buttons are being pressed each frame.
  • getAgentName just returns the name of the controller.
  • train is a function that gets called only when the assessedMode variable inside of
  • MarioGame is set to false. This will allow you to do any pre-training you want to do, which might be something like running a bunch of evolutionary controllers all the way through the level on repeat to generate better genotypes!


If we wanted to make Mario only run to the right of the screen, we could change the getActions to return instead:

5. The Game Loop

This section explains the main game loop. You will not need to modify this code, but you may find it helpful to understand how it works. This code is found in MarioGame.java.

First here the game creates a new world and sets up the level with a game timer of however much is specified in the timer parameter. If the visual boolean is set to true, then it will actually create a screen we can see, and if not the game is run without a GUI. After that, it sets Mario’s state to match what we specify in the marioState parameter, then the graphics are actually initialised and created.

Next we get the current system time as the start time, and create a new MarioTimer.

MarioTimer is responsible for how long the agent is allowed to take on each action, and if it takes too long, it will abort the operation. After this, we run the agent’s initialize functionand pass in a new MarioForwardModel (this class will be important later -- see Section 6) as well as the MarioTimer we just created. Lastly here we call the train function if assessedMode is false, letting you train your agents if you would like for as long as you like.

Now for the actual “loop”, here we check to see if the game is running and it’s not paused, if so, then we tick the real-time timer if we’re in assessed mode, and if it gets to the maximum amount of time, it changes the state to REAL_TIME_OUT, stopping the level.

Then, we create a new timer to time the agent out this tick if they take too long. Then we actually call the getActions function from our agent, getting a boolean array of actions.

After that, we check to see if the MarioTimer passed in is taking longer than one frame should take, and if it does, we print how long extra the getActions function is taking to return than the amount of time left in the frame. For example, if we were running 30 FPS, we would have 33.33ms per frame to run on time, any longer than that and the game slows down!

Next, we actually update the world based on Mario’s actions, then add all of the events that happened last frame to our arrays we declared above the while loop. After this, we check to see if we should render the game, and lastly here we check to see if the game is going too quickly and slow it down by an appropriate amount if it is. This is because the game should be running at the specified FPS (30) and if we return our actions super quickly, we need to slow the game down to maintain this 30 FPS.

Lastly we return our MarioResult so we can print the results out for our stats!

6. What is a MarioForwardModel?

MarioForwardModel is a super useful class located under engine->core->MarioForwardModel which allows you to simulate the next frame of the game by passing in a set of actions using the advance function! This means that you can say, simulate 1000 marios for 1 second and take the best 100 or so marios, then attempt to breed them!... Never thought I’d say that in my teaching career but here we are.

NB: Make sure that you’re creating a copy of the MarioForwardModel for each simulated playout by using the Clone function!

发表评论

电子邮件地址不会被公开。 必填项已用*标注