Assignment 2 - Plantastic

This assignment will get your GOAP game strong.

The good news: it comes with an existing *kinda* functional GOAP reasoner based off of the tutorial series here (worth a watch!):

git-amend GOAP Tutorial


This takes place in the SouflAI environment with simulated .

Your Primary Goal: Develop the Chef AI that will make Overcooked look Undercooked!


As you complete your assignment, you may be asked to make additions to your Report or Recordings, which will be artifacts you generate alongside your programmatic component. These requirements are tagged in purple boxes like this one so don't miss them!

For any written response, you should collect your answers in a single PDF that clearly indicates which answers pertain to which questions from the spec.

For any recorded / video response, you should upload a video to a hosting service like YouTube, Vimeo, Box, etc. and include a link in your report.

Important: for any video resource, ensure that you can access it without being logged into your account before submitting!


Motivation


Fans of Overcooked, the teambuilding / friendship ending coop cook-em-up, will rejoice at this assignment.

If you haven't played it, the game requires you (and usually some co-chefs sharing a kitchen) to prepare orders that usually consist of multi-step processes to prepare, all while finding the optimal path through the kitchen and ways to delegate labor between one another.


For example, to prepare a burrito requires the steps:

  1. Obtain and plate a tortilla

  2. Obtain and cook the rice

  3. Obtain and cook the chicken

  4. Combine the ingredients in the burrito

  5. Deliver the prepared meal to the kitchen counter


Hilariously, there are often wrenches thrown in the gears of your recipe that require dynamic decisions and readaptation:

  • A fire erupts and extinguishing it becomes the highest priority

  • The cooked rice your partner passed to you falls off a conveyer belt and is no longer available

  • The river raft you're cooking on desyncs with the raft carrying the ingredients (OK so these kitchens aren't always to code)


The above covers precisely the kind of gameplay loop that you might find palatable to insert an AI planner into, e.g., providing an AI teammate or even creating a new type of game where the cooking process is automated, but the player designs the kitchen.

As such, we'll serve up a GOAP-enabled Chef capable of bringing these ideas, and many adjacent, to life.



Solution Skeleton

Start with the solution skeleton in-hand!

Inside, the important things to pay attention to are:

  • Assets/Scripts/Inventory containing the behaviors for managing the Chef's inventory and how it is manipulated when he enters certain zones (e.g., fetching ingredients from the fridge, requiring those ingredients to cook food at a stove).

  • Assets/Scripts/GOAP contains all of the GOAP planning logic classes, whose components are described below.


GitHub Classroom Link


Once open in the Unity Hub, ensure that you can open the SouflAI scene and that all assets are visible.

This project uses the following FREE asset packs (credit to their creators):


Important: Use Unity Version 6000.0.38f1 for this assignment (you should be prompted to download it when loading into your editor).



Specifications

Let's start by just getting familiar with the codebase, pieces of which have been demonstrated during lecture.

  1. Begin by opening the ChefsKitchen scene, clicking on the Chef game object to open it in the inspector, focus on the Goap Agent (Script) Component, and run the game. Observe where the Chef visits and the importance of the game objects associated with the order; you should also see what happens to the Chef's Stats and Beliefs as they move.

  2. Take a dive into the code and review the files introduced during the lectures, paying attention to the following:

    • Beliefs.cs: determine what data structures are used to manage the Agent's belief state and describe the important methods used to manipulate these structures.

    • Actions.cs: determine what data members characterize an Action and how these relate to Strategies.

    • Strategies.cs: observe how the MovementStrategy is implemented in relation the the Strategy interface.

    • GoapAgent.cs: examine the SetupBeliefs, SetupActions, and SetupGoals methods to determine how the agent's current behavior is implemented when run.


[The Kitchen Never Closes]

Currently, our Chef thinks that cooking and delivering one meal is all he has to do before he sits in place and contemplates life, wondering how he never got into Le Cordon Bleu (you might say he has the Le Cordon Blues juejuejue).

A quick look at how the planning operation works will show you that GoapAgents maintain a lastGoal member that, in unison with the CalculatePlan method, prevents the same Goal from being chosen twice in a row. This is a problem because our agent currently has ONLY one goal.

To fix this:

  1. Add a new member + Builder option to the Goals class called repeatable such that Goals created with this option can be taken back-to-back.

  2. Back in GoapAgent, modify the SetupGoals method to make the OrderUp Goal repeatable.

  3. Change the logic in CalculatePlan to prevent the lastGoal from stopping the selection of a repeatable Goal.

  4. Currently, the Chef receives a "tip" in his inventory for completing an order -- you may need to change this to make the kitchen continuously open.

  5. Once complete, record a video of your Chef continuously going to fetch ingredients, cook them, and then deliver to the order spot, and include a link in your report.



[Don't Trust a Skinny Chef]

Hey, Chefs are people, and people get hungry -- extra so if you're in the kitchen all day.

Head on over to GoapAgent.cs and observe two of the Chef's members: Inventory, Hunger -- fun fact, you also saw these while running the game and watching the Chef's Stats change in the inspector / on the UI.

By default, the Chef's hunger starts at 20 and decreases by 1 each second. Examining the SetupBeliefs method, you can also see that he gains the belief that he's hungry when this value falls below a certain threshold.

Your task:

  1. Create a new Goal in the GoapAgent called FeedSelf with priority 2 and the desired belief of AgentIsSated.

  2. Update the agent's Beliefs in SetupBeliefs to have the belief that this new Goal will be sensitive to.

  3. Create a new method for the GoapAgent that sets their Hunger to a parameterized amount.

  4. Examine the scripts in Scripts/Inventory used to manage the agent's inventories. Add a new one for the Chef's Table such that, when the Chef collides with the Chef's Chair while having food in their inventory, his Hunger will be set to 30 and the food will be removed from his inventory.

  5. Create a new Action EatAtChefsTable with the proper preconditions and effects such that the Chef can only choose this action if they are Hungry and HasFood. The effects should be that they are sated and no longer have food.

  6. If you've combined the above pieces correctly, you should now see your Chef periodically go feed himself at the Chef's table in the bottom left of the scene once his hunger is below the threshold!

  7. Once you have gotten this behavior, take a video of him taking his meal breaks, making sure to record the Beliefs and Stats panel in the inspector as they change. Add a link to the recording to your report.



[A Chef's Greatest Test]

Every step in the kitchen counts -- tell that to our current chef!

Currently, our Chef takes a leisurely path through the kitchen on the way to ingredients / stoves -- anything for which a goal can be met by multiple satisfying locations.



Let's make sure we have test coverage for later when we fix his ability to plan more optimal paths.

Remember: This is a common practice and good habit for test-driven development -- make the tests *first* and then implement fixes later!

Your task: Implement a PlayTest (setting up the test assembly like the tutorials had you do in Ass-1) that checks that the Chef visits the more optimal ingredients station before cooking the food and delivering it, as demonstrated here:


Once completed, record a video of you running the PlayTest, and your agent FAILING it as they visit the suboptimal station. Attach this video in your report.

Lastly, include the full test code in your report.



[Recipe for Success]

Currently, our Chef makes some nebulous "food" from "ingredients" without any real variety nor lots of steps in the process

Let's spice things up a bit!

First, plan your menu out:

  1. You must create a menu of 2 separate dishes that are made from 3-4 unique ingredients, and each recipe of which must have at least 1 intermediary step; for example:

    Recipe / Goal: Cook Rice Burrito

    Ingredients: Tortilla, Rice, Tomato

    Intermediary Step: The Rice must first be cooked (adding CookedRice to inventory while having Rice at a CookingStation)

  2. Next, plan out the actions and game objects needed for your Chef to cook these recipes. E.g., you may want to make a chopping station for chopping tomato, or separate ingredient sources located in different parts around the kitchen.


Now, on to implementation:

  1. Clone the ChefsKitchen scene into a new one you call HellsKitchen

  2. In this new scene, incorporate all of the assets needed to serve as ingredient / cooking sources. You are also free to move around the existing tables, fridges, stoves however you see fit. Feel free to get creative (within reasonable limits like... don't have your Chef cooking meth)!

  3. Take a screenshot of this new scene for your report and annotate the game objects alongside how they are being used for your recipes.

  4. Implement the necessary Inventory scripts in Scripts/Inventory needed for each of these new game objects, similar to how these operated in the original ChefsKitchen's Ingredients source, Cooking station, etc.

  5. In GoapAgent.cs, replace the OrderUp Goal with 2 Goals: one for each recipe, and make sure that these goals are NOT repeatable. The reason: we'll want to see our Chef cook these recipes in alternating fashion.

    This is just to keep things simple for the constraints of this assignment; in general, you'd want some sort of order system to dynamically add / remove recipe goals as orders come in from the dining floor.

  6. Add any necessary inventory, Action, and Belief changes to your GoapAgent so that these Goals can be accomplished.

  7. Finally, once all's ready, record a video of your Chef making your recipes and delivering them to the OrderZone! Attach this video in your report.



[Building a Smarter Chef]

And now, the pièce de résistance!

Currently, the planner in GoapPlanner.cs is implemented using a Depth First Search, which will not necessarily take cost of each action into consideration.

We remember this from algorithms, wherein depth first search can even solve simple paths in a gridworld suboptimally:


Instead, you will implement Best First / A* search to deliver an optimal plan! To do so, you will have to:

  • Refactor GoapPlanner so that it ascribes to the traditional A* paradigm, e.g., using a priority queue frontier, defining the evaluation function for each node and how they are ranked, etc.

    This might seem like a big ask, but remember your lessons from algorithms / familiarity with A* -- the implementation should look similar here even if you need to remake some helpers like getting the transitions from a state.

    Likewise, remember that you are able to use the assistance of GenAI and AI IDEs like Cursor to help you here -- their implementations may not be perfect but can give you good starting points if you prompt them carefully!

  • You may also need to keep track of locations required by each action (e.g., Actions may now need to be buildable with a WithLocation Builder option) so that the cost of a transition can be computed via the distance between the parent's location and the next in the search tree.

  • [Optional] Develop an admissible heuristic that guides your planner to improve efficiency and include this heuristic in your report. In its absence, you will simply be implementing Best First search, not A*, but either will deliver optimal paths for this assignment.

  • Once complete, run your original ChefsKitchen scene and verify that your Chef chooses the more optimal path from ingredients to stove to delivery.

  • Record your running of the test from the earlier problem and show in the test runner that the test now passes! Include this recording in your report.



Congratulations! You may feel cooked after this assignment, but what a delicious addition to your portfolio it makes.



Grading

Your submission will be graded on successful completion and report on all Problems listed above. Each are weighted equally.

Since some portions leave some room for creativity / interpretation, feel free to reach out if you have questions of whether or not your approach meets the stated spec.



Submission

You will be submitting your assignments through GitHub Classroom!

What

Complete all requested sections of the skeleton above AND finalize your report in a /doc/ subdirectory as shown in the skeleton before pushing your finished project to your GitHub Classroom repo.


How

To clone this assignment (if you need a refresher), consult the guide here:

GitHub Classroom Tutorial

To submit this assignment:

  • Simply push your final, submission copy to the GitHub Classroom repository associated with your account.

  • Place your name(s) at the top of *all modified* files AND in the accompanying readme file.



  PDF / Print