KIPR · Botball Explorer
Activity Sections

Unit 1 · Big Idea 2

Problems Can Be Broken Into Smaller Problems

Student Lab · The Red Cube Breakdown

Unit Guiding Question
How can a machine understand and act within the world?
Big Idea
Problems Can Be Broken Into Smaller Problems
AI Literacy Thread
Intelligent systems solve complex problems by breaking them into smaller parts.
CS1 Concepts
· Computational Thinking · Planning ·
Game Context
Mission 2 — Relocate the Red Cube (drive, push, return) · builds toward Mission 8 — Deliver the Red Cube
What You Need
Explorer robot kit · game field · this lab sheet · sticky notes (optional)
Before you start: type your PIN in the box at the top of the page. Your teacher gave you this number. When you finish, press Submit & Download to turn in your work and save a copy.

Overview

Today’s challenge looks impossible at first glance. Mission 2 — Relocate the Red Cube — requires your robot to drive to the Large Red Cube (which starts its ), push the whole palletized assembly off the black line, and then return to its starting box. That’s not one task. That’s a system of tasks.

Core Insight

No intelligent system solves a complex problem all at once.

It solves many small problems in sequence — and the intelligence lies in knowing how to break the big problem apart.

By the end of this activity you will be able to:

  • Define decomposition and explain why it is a foundational strategy for both programmers and AI systems.
  • Break a multi-stage game mission into independent sub-problems and identify dependencies between them.
  • Write modular code where each solves exactly one sub-problem.
  • Connect the structure of your program to how large intelligent systems are architected.

New This Time: and Functions

Two new tools you’ll use today. You already know k.motor(), k.msleep(), and k.ao() — these let you organize them.

A variable --- a named number

A variable gives a number a name, so you can use the name instead of typing the number everywhere. Change it once at the top, and every place that uses the name updates.

DRIVE_SPEED = 50        # name a number: DRIVE_SPEED now means 50

k.motor(0, DRIVE_SPEED)  # same as writing k.motor(0, 50)
k.motor(3, DRIVE_SPEED)  # same as writing k.motor(3, 50)

Here you’ve named your motors’ speed once. If you want them slower later, you change 50 in one spot instead of hunting through your whole program.

A function --- a name for a group of commands

A function lets you take several commands and give them one name. After you build it once, you can run all of those commands by just writing its name. Writing def means you’re defining a function that does a job but doesn’t hand a number back.

def drive_forward():        # make a new command called drive_forward
    k.motor(0, DRIVE_SPEED)  # these lines are the job it does
    k.motor(3, DRIVE_SPEED)
    k.msleep(1000)
    k.ao()                   # stop at the end

Now, anywhere in your program, writing drive_forward() runs all of those lines. You built your own command.

Phase 1 — Activate: The Impossible Errand

Imagine someone gives you one instruction: “Make dinner.”

Break it down --- list as many sub-steps as you can think of:

At what point did you stop breaking it down? What made you decide a step was “small enough”?

How is “Make dinner” similar to a robot mission on the Foundations field?

Phase 2 — Concept: Decomposition & Abstraction

Decomposition

Decomposition is the process of breaking a complex problem into smaller sub-problems that are each simple enough to solve independently. It is one of the four pillars of computational thinking and one of the most important strategies in both programming and AI system design.

Why Decomposition Works

  1. Each sub-problem can be solved and tested independently.
  2. Sub-problems can be worked on by different people (or different parts of a system) at the same time.
  3. A solution to one sub-problem can often be reused in a different context.
  4. When something breaks, you know exactly which sub-problem to fix.

Abstraction

Abstraction means hiding the details of how something works so you can use it without thinking about those details. When you call drive_forward(), you don’t think about motor power, wheel friction, or timing. You just think: “the robot drives forward.” That’s abstraction. In this activity, every function you write is an abstraction — once it works, you use it without thinking about its internals.

Dependencies

When decomposing a problem, some sub-problems must be solved before others. This ordering relationship is called a dependency. Identifying dependencies before you code prevents wasted effort.

Example

You cannot push the palletized cube off the line until the robot has driven to it. “Drive to the cube” is a dependency of “push the cube” — so you build and test the driving first, before you write a single line of the pushing. Get the order wrong and you waste time testing a push on a robot that isn’t even in the right place yet.

In your own words: what is the difference between decomposition and just “making a list”?

Phase 3 — Analyze

Mission 2 — What Must Happen?

Watch Mission 2 video

Base Mission

1 point Live judged

The Large Red Cube and its pallet are both the black line.

Bonus Mission

3 points Live judged

Both Small Red Cubes are the black line. The Small Red Cubes are not required to remain stacked.

Scores

  • The Large Red Cube and pallet are both the black line.
  • The Large Red Cube and pallet are the black line, even if no longer touching one another.
  • Both Small Red Cubes are the black line.
  • The Small Red Cubes are the black line and separated from one another.

Does Not Score

  • Any portion of the Large Red Cube is touching the black line.
  • Any portion of the pallet is touching the black line.
  • The Large Red Cube is the line but the pallet is still touching the line.
  • Either Small Red Cube is touching the black line.

Mission 2 Key Rule

Both the cube AND the pallet must independently satisfy the OFF definition. The cube rides on the pallet, so pushing the assembly together is what scores — no lifting required.

Your target today: drive, push, return. Your robot will use only the driving and turning commands you already have. It drives to the palletized cube, pushes the whole assembly off the black line, and returns to its starting box. No arm, no lifting — that comes in a later lesson.

Later in the game, Mission 8 — Deliver the Red Cube asks the robot to lift that same palletized cube up onto the Loading Dock. That takes an arm, which means — a tool you haven’t met yet. We’ll worry about that lifting motion in a later lesson. For now, notice that the very first part of Mission 8 is the same as Mission 2: drive to the cube. The work you do today is a piece you’ll reuse.

Step 1 — Identify the Sub-Problems

Before writing any code, decompose Mission 2 into its smallest independent pieces. List every distinct action your robot must perform, in order — from leaving the starting box to returning to it.

Step 2 — Identify Dependencies

For each sub-task, note what must happen first, and whether you could test it on its own. The first row is filled in as an example.

Sub-TaskDepends On (must happen first)Test alone?
Drive to the cubeStart positionYes

Step 3 — Name Your Functions

Each sub-task should become its own function. Name them here before you write any code. Good function names describe exactly what the function does. The first row is an example.

Function NameWhat it does (one sentence)Output / Effect
drive_to_cube()Drive from the start box to the cubeRobot at the cube

Look at your function list. Which function are you most uncertain about? What specifically makes it hard?

Phase 4 — Build

Code Scaffold

Where do functions go?

A function has to be defined before the code that uses it. Since main() is what runs your program, your functions live above the place main() is called. The computer reads top to bottom, so it needs to know what drive_forward() means before it reaches the line that calls it.

Your program structure should look like this. Notice the movement commands are now functions you name, and each uses the named speed variables set at the top. Fill in each function body from your Phase 3 decomposition. Only add a function call in main() once that function is tested and working.

#!/usr/bin/python3

# Unit 1, Big Idea 2: Red Cube Breakdown

# Name: _______________________   Date: ___________

import os, sys
sys.path.append("/usr/lib")
import _kipr as k

# Named values to change as you test
DRIVE_SPEED = 50
TURN_SPEED  = 40

# Main is defined here, and it can use functions written anywhere in this file.
def main():
    # Integration: only add each call only after that function works:
    # your_first_function()
    # your_second_function()
    # your_third_function()
    pass

# Movement commands you can reuse (no parameters yet)
def drive_forward():
    k.motor(0, DRIVE_SPEED)
    k.motor(3, DRIVE_SPEED)
    k.msleep(1000)
    k.ao()

def turn_right():
    k.motor(0, TURN_SPEED)
    k.motor(3, -TURN_SPEED)
    k.msleep(600)
    k.ao()

# Write and test ONE sub-task function before moving to the next.

# Build each function using drive_forward() and turn_right().

# Use the names from your Phase 3 list. For example, write a function that

# drives the robot to the cube, pushes it off the line,

# or returns the robot to the starting box.

# Main is called here, so all functions it uses must be defined above it.
main()

Build Log — Track Each Function

Complete one row when you finish building and testing each function. Do not move to the next function until the current one passes 3 runs in a row.

Function NameRuns triedPasses (3 needed)Problem encounteredHow you fixed it
drive_to_cube()

Phase 5 — Integrate

Once all your individual functions pass, add all the calls in main() and run the complete sequence. Record what happens.

What to watch for during integration

Functions that worked alone sometimes fail when combined. Why? Because the robot’s position at the end of one function is the starting position for the next.

If function B fails after function A, the problem is usually function A — it left the robot in the wrong position. Fix function A before modifying function B.

Integration Trial Log

TrialLast function reachedWhere it failedRoot causeFix applied
1
2
3
4

Did any function that passed alone fail during integration? Describe exactly what happened and why.

Phase 6 — Connect: The AI Literacy Bridge

Big Idea 2 --- AI Literacy Thread

Intelligent systems solve complex problems by breaking them into smaller parts.

A self-driving car isn’t just programmed to “drive.” It runs hundreds of sub-systems at once: one detects lane markings, one tracks other vehicles, one monitors speed, one predicts pedestrian movement, one manages braking, one handles steering. Each sub-system is a decomposed piece of the larger problem. The complexity of the whole emerges from the coordination of the parts. Today, you built that coordination from scratch.

Read each scenario. Think it through, then write your answer.

A search engine returns results in under a second for any query ever typed. Decompose this: what are at least four distinct sub-problems the system must solve to do this?

Each sub-task function you wrote is an abstraction — once it works, you call it by name without thinking about the drive_forward() and turn_right() steps inside it. Pick one of your functions: what details does it hide from the rest of your program? Why does hiding those details make your code better?

In Phase 5 you may have found that functions interacted in unexpected ways during integration. What does this tell you about the challenge of building large AI systems from many smaller components?

Phase 7 — Individual Reflection

Complete this section on your own.

1. Define decomposition in your own words. What problem does it solve for a programmer?

2. What is a dependency? Give one example of a dependency from your robot program today.

3. The One-Function Rule says: don’t write the next function until the current one works. Why is this discipline hard to follow? What happens when you skip it?

4. Complete this in 2–3 sentences: “Intelligent systems solve complex problems by breaking them into smaller parts. This means that when an AI system fails at a complex task…”

Extension Challenges

Finished early? Try one or more of these.

Extension A — Going for the Bonus

  • The Mission 2 bonus also requires both Small Red Cubes to be OFF the black line.
  • Where are the small cubes relative to your push path? Could one push clear everything, or do you need a separate move?
  • Decompose the bonus: what new sub-task(s) would you add, and where in your sequence would they go?

Extension B — Dependency Map

  • Create a visual dependency map of your full program. Each function is a node; draw an arrow from A to B if B depends on A.
  • What shape does your map have — a linear chain, a branching tree, something else?
  • What does the shape tell you about the structure of your solution?

Extension C — The Reuse Test

  • Can any of your sub-task functions be reused for a different mission?
  • Which functions are specific to Mission 2? Which are general-purpose?
  • Which function would you redesign to be more general, and how?

Extension D — Abstraction Levels

  • Right now your program has two levels: main() calls sub-task functions, which call movement functions.
  • Add a third level: group your sub-task functions into two or three higher-level functions (e.g., relocate_cube(), return_home()).
  • Rewrite main() to call only those high-level functions. Did this make the program easier to read and modify? Why or why not?

When you are finished, press the button to turn in your work and save a copy.

KIPR · Botball Explorer · Unit 1 Big Idea 2 — Student Lab