Info Assignments Office Hours Hall of Fame Notes
Info Assignments Office Hours Hall of Fame Notes

Mechanized Mining 3.0

Assigned: 2020-09-22
Due Date: 2020-09-29 by 11:59PM U.S. Central Time

Goals

Assignment Spec

Gradescope

You will need to submit your GitHub repository to Gradescope after completing this assignment.

Getting Started

For this assignment, you will be creating at least one intelligent player strategy for a strategy game based on exhilarating concepts like mining and economics. This game is called Mine-opoly. Unlike previous assignments, we are giving you a significant amount of code. We have taken care of everything needed to run the game. This includes a game engine, graphics, and of course an interface for your strategy implementation. You are not allowed to modify this MinePlayerStrategy interface. You are however free to modify any other files including the game engine and graphics, but you do so at your own risk, and we will be using the original copy that we gave you to run the competition.

Get your copy of the assignment here: https://classroom.github.com/a/MU3MLl9F

Why the 3.0? This is a new and improved version of previous semesters’ games.

The Game

The game is a turn based mining competition played on an NxN square set of tiles which is considered the Game Board. There are 4 types of tiles on the board:

There are two players per game, one with a red robot and one with a blue robot. Both players start in the center of the board on their lower market tile. Each turn both players will receive information about the board state. This information contains where all the resources are, where your opponent is, prices for each resource, and other such information. Each turn both players will be required to return a TurnAction. This TurnAction is an enum value which indicates what your strategy wants your player to do for the current turn. TurnActions are one of the following:

As previously mentioned, market tiles are where you can sell your gathered gems for points. Stepping on one of these tiles will immediately sell every gem in your inventory at the current price for each type of gem. The price for each gem will then decrease depending on the amount of each type sold. Prices for gems will steadily increase over time again until reaching the max value for the gem type.

Finally, since players execute turns "at the same time", potential conflicts such as moving into the same tile will be handled by the concept of red turns and blue turns. On a red turn, the red player will have priority for these types of moves. On a blue turn, the blue player will have priority. Red turns and blue turns will alternate throughout the game. The first turn will be a red turn. So if two players are trying to move into the same tile, and it is currently a red turn, the red player has priority and will successfully move into that tile. The blue player will be blocked from moving and therefore do nothing.

The Interface

We have given you an interface that your player strategy should implement. You need to implement this interface without modifications, otherwise your strategy will not run in the provided game engine or the competition. This interface is called MinePlayerStrategy. It has the following methods:

  1. initialize() - This function will be called at the start of every round, passing in the size of the board, the maximum items that a player can carry in their inventory, the maximum charge that your robot will start with the score to reach to win a single round, an initial view of the GameBoard, the starting tile location for the player, whether the player is a red player, and finally a Random object for the player to use for generating random numbers if their strategy needs that.

  2. getTurnAction() - This function is the primary purpose of your strategy. It is called every turn to get the action your player should execute. The parameters are a PlayerBoardView object which represents the state of the board, an Economy object with resource price information, the current charge your robot has, and a boolean to say if the current turn is a red priority turn or not. This function returns a TurnAction for the action the player wants to execute. Returning null from this function will cause the player to do nothing.

  3. onReceiveItem() - This function is called whenever the player successfully executed a PICK_UP TurnAction on their last turn. The only parameter for this function is a reference to the InventoryItem picked up. This function is not called when the player inventory is full because the item is not picked up in that case.

  4. onSoldInventory() - This function is called whenever the player steps on a market tile of their color with at least one gem in their inventory. The only parameter for this function is an int for the total number of points received by selling everything in the inventory.

  5. getName() - This function is super simple, just return the name that you want to give your player on the GUI and in the competition. Can be as simple as a string constant like "ExampleName". Note that if you somehow manage to throw an exception in this function, your player's name will be the exception that you threw. That's super embarrassing for everyone involved.

  6. endRound() - This function is called at the end of every round. This passes in the number of points that your player scored and the number of points that the opposing player scored. You should also use this method to reset the state of your strategy class. Every semester we get complaints from people that their strategy acts buggy in the competition, and it turns out their strategy is still using variables set in the previous round.

Assignment Requirements

To fully complete this assignment, you must write at least one MinePlayerStrategy in the mineopoly_three.strategy package that meets the following requirements:

The provided implementation of RandomStrategy cannot pick up gems, so it cannot score any points. It will therefore only make things easier for you to score more points.

In addition to those requirements on the strategy:

You are entirely allowed to write more than one strategy. In fact it probably makes sense to have a strategy that maximizes your points against a RandomStrategy for the assignment, and then another strategy that does more complicated actions against a smarter human-programmed opponent for the competition. If you write a separate strategy for the competition, it will not be graded as part of this assignment.

Part of this assignment is becoming familiar with an unfamiliar codebase. IntelliJ has built-in tools to allow you to more easily explore code

By all means feel free to ask questions on Campuswire or in office hours if you get stuck, but you have all the code running the game in front of you. If you look around enough, you can probably find the answer to any question you may have, and develop a useful skill in the process.

Consider exploring around before you ever attempt to write a strategy. Are there some parts that seem more important than others (like the main method in MineopolyMain, or runGameLoop() in GameEngine)? Are there some parts that seem irrelevant to your needs (like anything dealing with the graphics or the paint() methods)?

When you do feel like you are ready to write a strategy, are there certain helper methods it would make sense to have? If you do decide to write a more complex strategy for the competition, are there some design choices you could make to implement complicated conditional behavior more easily? Can an interface or abstract base class you write help you swap strategy behaviors on the fly?

Other things we will take into consideration:

Test suites for this assignment are expected to be a bit slim, since of course you are only writing a strategy, and all of the game engine functionality has been done for you. That being said, if you write helper methods that you reuse (which is a good idea in general), you should be testing them.

This assignment is a test of your problem-solving skills: if you don't know how to do something (for example, writing an abstract class,) you should try your favorite search engine. (Make sure you follow our policy on citing online code.) If you're still stuck, consider Campuswire and office hours.

Tips

The Autominer

This feature is not necessary to complete the assignment. The autominer exists to aid those who seek ultimate glory by winning the competition. There are two autominers per map, spawning in the same corners each time. Anybody can pick up either autominer, but it does fill an inventory space. When placed, the autominer mines the surrounding tiles and the tile that it is placed on. Note that this mining rate is slower than the player's. Mined resources still have to be picked up. Additionally, if a autominer and resource are both on the same tile, it will take two turns to pick them up, as each item must be picked up individually. We encourage you to explore the starter code to maximize the effectiveness of the autominer's usage.

The Competition (you don't need to read this before completing the assignment)

Participation in the competition is completely optional. However, we make no guarantees about the impact of these things on your sense of self-worth. The top 8 strategies will be immortalized in a Hall of Fame on the website. The losing strategies... will not be. Particpation is worth 2.5 points of EC, you will earn an additional bonus based on your ranking: (ranking/total * 7.5).

How to submit code

Push code to your master branch. This is the branch we will pull from when we run the competition.

In order for us to run your player strategy in the tournament, you must put a single class that implements the MinePlayerStrategy in the competition package. You may also put any other classes you need in that package. This package is package mineopoly_three.competition;

How to make sure your code compiles in the competition

Do not include any subpackages in the competition package. These will not get compiled or run. Do not reference any classes that you personally created which are outside the competition package.

How to ensure your code is valid

Put only one player strategy in the competition package, otherwise we will not know which strategy to run. There should only be one class in the competition package that implements MinePlayerStrategy

Competition Runs

We will be auto-running the competition starting this Tuesday, September 29th. Indeed, this is on the due date, but we won't be closing the competition until the following Tuesday, October 6. Note that you will still have an assignment due that week, and it will be our first C++ assignment. However, the workload should be smaller, so you can spend some time tweaking your strategy if you'd like.

Assignment Rubric

Note that this rubric is not a comprehensive checklist; it’d be impossible to list out every single thing that you should be considering while writing your code. The rubric is slightly different from what you're used to, as a small part of your grade is dependent on having a strategy that meets the winning requirements for each board size.

Click here to view

Readability and flexibility of code

  • Modularity: each method should perform one distinct task
  • It should be easy to read through each method, follow its control flow, and verify its correctness
  • The code should be flexible/ready for change (no magic numbers, no violations of DRY)

Object decomposition

  • Member variables stored by each class
    • Classes should store their data using the most intuitive data structure
    • No "missing" member variables
    • No member variables which should be local variables
    • No redundancy / storing multiple copies of the same data in different formats
  • Encapsulation
    • Appropriate access modifiers
    • Member variables should generally only modified by member functions in the same class
    • The interface of a class should be intuitive/abstract, and external code should only interact with the class via the interface
      • By intuitive, we mean that it should be easy to understand and use the class, and there shouldn’t be any hidden assumptions about how the class should be used
      • By abstract, we mean that an external client shouldn’t need to worry about the internal details of the class
    • No unnecessary getters/setters
    • In Java, getters should not return a mutable member variable

Documentation

  • Specifications
    • Specifications are required for all functions which are part of the public interface of a class
    • Specifications should precisely describe the inputs and outputs of a function, and should also describe what the function does (e.g. mutating state of object)
    • Specifications should also be formatted properly (e.g. follow Javadoc style for Java assignments)
  • Inline comments should not describe things which are obvious from the code, and should describe things which need clarification

Naming

  • Semantics: names should effectively describe the entities they represent; they should be unambiguous and leave no potential for misinterpretation. However, they should not be too verbose.
  • Style: names should follow the Google Java/C++ Style Guide

Layout

  • Spacing should be readable and consistent; your code should look professional
    • Vertical whitespace should be meaningful
      • Vertical whitespace can help create paragraphs
      • Having 2+ empty lines in a row, or empty lines at the beginning or end of files, is usually a waste of space and looks inconsistent
    • Horizontal whitespace should be present where required by the Google Style Guide
  • Lines should all be under 100 characters; no horizontal scrolling should be necessary

Testing

  • You should make sure all types of inputs and outputs are tested.
    • If category A of inputs is likely to cause different behavior than category B, then you should test inputs from both categories
  • Boundary/edge cases often cause different/unexpected behavior, and thus, they should be tested
  • Your tests should cover all of the functionality that you’ve implemented. In other words, every line of code should be exercised by some test case, unless the assignment documentation says otherwise
  • Each individual test case should only serve one coherent purpose. Individual test cases should not have assertions testing unrelated things
  • Your tests, like your code, should be organized and easy to understand. This includes:
    • Easy to verify thoroughness / all possibilities covered
    • Easy to verify the correctness of each test case
    • Clear categories of test cases, where similar tests are grouped together
      • In Java, this can be accomplished by inserting comments to separate groups
    • Test case names make the purpose of each test case clear
      • Here is one possible way to name test methods in JUnit

Process

  • Commit modularity
    • Code should be checked-in periodically/progressively in logical chunks
    • Unrelated changes should not be bundled in the same commit
  • Commit messages
    • Should concisely and accurately describe the changes made
    • Should have a consistent style and look professional
      • First word of the message should be a verb, and it should be capitalized

Presentation

  • Arrived on time with all necessary materials and ready to go
  • Good selection of topics to focus on
  • Logical order of presentation
  • Appropriate pacing and engagement of the fellow students
  • Speaking loud enough and enunciating clearly

Participation

  • Each student should contribute at least one meaningful comment or question for every other student who presents in his/her code review
  • Students must behave respectfully to moderator and other students

Weightings

Your grades for each section of the rubric will be weighted as follows:

  • Readability and flexibility of code (15%)
  • Object decomposition (10%)
  • Documentation (7.5%)
  • Naming (7.5%)
  • Layout (5%)
  • Testing (20%)
  • Process (10%)
  • Presentation (5%)
  • Participation (5%)
  • Strategy Win Percent (15%)