| CPSC 329 | Software Development | Fall 2026 |
In this (mostly) group project, you and a partner will extend the Hedgehogs in a Hurry game from project P0. This project has two parts:
Part B will be released after lab 6 on Tuesday 10/6.
Teams. You'll work in pairs, starting from both partners' P0 codebases. If your P0 isn't complete enough for your partner to work with, talk to me before starting. A reference implementation is available as a substitute. The teams will be the same pairs that have formed in lab: Jubayer and Andrae, William and Anik, Sebastian and Henry, Ainsley and Brooke.
Individual and team work.
Tasks A1 (seeded dice) is individual. The code and associated deliverables must be entirely your own work, though you may ask your partner questions about their code. No pair programming on A1!
Task A2 (code review) is also individual. Do this on your own, without help from your partner.
The rest of Part A and all of Part B are team tasks, though many of the deliverables are individual. The individual deliverables must be entirely your own work, while the code and team deliverables must be entirely your team's work.
No AI. Review the course AI policy for details.
Check-in meetings. Two short check-in meetings are required:
Drop in during office hours — no appointment is necessary unless you are unable to make any of the scheduled office hours.
The check-in meetings aren't graded; their purpose is to make sure your team is on track. At least one partner must attend each meeting and both are encouraged to attend. In addition, each partner must attend at least one of the two meetings, so if only one of you comes to the first check-in, the other must attend the second.
Hand-in meeting. A 20-minute individual hand-in meeting is required after handin of the whole project. These meetings will be scheduled before the due date and normally take place within a day or two of it. Be ready to walk through your own code and other deliverables. Also be ready to explain parts of your partner's work, and bigger-picture things like design decisions and your team's process. This isn't a quiz about content; it's to confirm that your handin reflects your own understanding and effort.
Due Monday 10/26 at the start of class. There is a single handin for both parts. Late handins are not accepted for projects, but an occasional 1-2 day extension is possible in case of a last-minute time crunch. (Plan ahead to avoid this!) See the late policy for details.
In Part A, you'll add reproducible dice rolls to the game, which is handy for testing. Read through this whole part (sections marked with "[A]" in the heading) to get an overview of what you'll be doing, then work through the five tasks in the Tasks section in order.
It can be useful for testing to be able to replay the same sequence of turns. Since the rest of the game is deterministic, this only requires being able to repeat the same sequence of dice rolls: with the same rolls and the same player input, the game plays out the same way.
Computers typically do not generate truly random numbers; instead a pseudorandom number generator produces a sequence of numbers that appears random but is completely determined by a starting value called the seed. Two generators created with the same seed produce the same sequence of numbers. In Java, new Random(seed) creates a generator with the specified seed.
While the same seed ensures the same sequence of values, ensuring the same sequence of dice rolls requires a few additional things:
All dice rolls come from a single generator. The generator is created once, with the game's seed, and every roll is drawn from it.
The dice generator is used only for dice rolls. Nothing else draws numbers from it.
Exactly one roll occurs per turn. The die is rolled once, at the start of each turn, regardless of what happens during the turn, including turns in which the forward move turns out to be impossible or where invalid input results in a reprompt.
If these conditions hold, a game can be replayed exactly by starting it with the same number of players, the same dice choice, and the same sequence of player moves.
Three dice roll options should be supported:
Random — the standard option, where a new sequence of dice rolls is used for each game. Print the seed needed to replay the game at the beginning and the end of the game.
Chosen seed — prompt for the desired seed on game startup. Any value that fits in a Java long (including negative values) is a valid seed. Print the seed at the beginning and the end of the game.
Dice script — prompt for a filename on game startup. Dice rolls are taken from the file, one per turn. If the script runs out of rolls before anyone has won, continue with a random seed and print a message to that effect.
There's no way to find out a Random object's seed once it has been constructed, so for random mode it is necessary to generate a seed first and then create the dice generator with that seed. An option here is to create a Random object with the default constructor and use that to generate a random value for the seed. Create a new Random object with the seed to use for dice rolls. Usability suggestion: seeds that are at most 7-8 digits long are much easier to read and type, so consider limiting the range of generated seeds.
Do these tasks in order.
This project starts with each partner working with the other's codebase before settling on one to continue with for the rest of the project.
Each partner, in your own P0 repository:
Establish a GitHub repository: create a new private GitHub repository named hedgehogs and push your completed P0 main to it. If your P0 isn't complete enough to move forward with adding new features, a reference implementation is available as a substitute. In this case, create the GitHub repository, add me (sbridgeman) as a collaborator, and send me an email asking for the reference implementation. I'll push it to your repository.
Mark the end of P0. Create a tag named p0-handin on main to reflect the handin version of P0. Do this on GitHub: go to the repository's main page, locate "Create a new release" under the Releases heading on the righthand sidebar, choose "Create new tag" under "Tag: Select tag" and enter p0-handin, make sure that the target is main, enter a human-readable release title such as "hedgehogs P0 handin", and publish the release.
Add your partner and me (sbridgeman) as collaborators.
Each partner, in your partner's P0 repository:
Accept the collaborator invitation.
Check out (clone) your partner's repository as a new Eclipse project.
Make sure the Eclipse project is linked to main before proceeding — switch branches if necessary.
As a team:
Read through the Team Process section below together.
Hold your team kickoff meeting and record the results. Also start the team log with an entry for this meeting. For now, use Google Docs or similar collaborative tool; once you have chosen a codebase to work with in A3, copy them over into docs/team-kickoff and doc/team-log respectively.
This is an individual task — no pair programming! You may ask your partner questions about their code if there is something confusing, but not otherwise work together on this part.
Add the random and chosen seed options to your partner's P0 codebase (not your own!). To do this:
Change impact analysis. Before writing any code, identify what will need to change to accommodate the new features. Write a short report addressing:
Remember the strategies discussed in class for understanding existing code. Hand the report in on Canvas (PDF) before writing any code.
Test plan. Working in the main branch, write a test plan for the new functionality in docs/A1-test-plan. Commit and push to GitHub when you are done.
Implement and test the new functionality, writing JUnit tests using the same standard as for project P0 — you can skip testing low-risk methods and may defer complex scenarios to manual testing, with a brief rationale in your test plan for any tests you don't implement. Remember the workflow: create a new branch for your work on this feature, commit to your local repository and push the branch to GitHub as appropriate, then open a pull request and merge the branch back into main on GitHub when you are done. You can delete the branch once the merge is successful.
Reflection: After merging, switch back to the main branch, copy your initial change impact analysis report into docs/A1-change-impact, and add a short reflection (a few paragraphs) at the end. How does what you actually did compare to your initial analysis? What did you miss or what did you anticipate that didn't materialize? What can you take away to help you analyze changes more accurately next time? Commit and push when you are done.
Note that all A1 deliverables (other than the initial change impact report submitted on Canvas) go into your partner's repository.
This is an individual task.
Coming soon!
This is a team task.
Coming soon!
This is a team task.
Coming soon!
(the end results for your part A code) Coming soon!
Part B will be added after lab 6 on Tuesday 10/6.
These practices apply to all team tasks in both parts.
As part of A0, discuss the following and record notes in a shared document in Google Docs (or similar). Once you've chosen a codebase to work with in A3, move the document to the file docs/team-kickoff.
Availability. When is each of you realistically available to work on the project, and when not? Include known busy periods during the project, such as exams, other project deadlines, travel, athletics, or work shifts.
Standing meetings. Pick two regular weekly meeting times (in person or online) that you'll both keep for the whole project. These can be brief meetings, but they shouldn't be skipped. Put them in your calendars now.
Communication. Which channel will you use (email, text, ...) and when do you each typically check it?
Work habits. Do you tend to start early or work close to deadlines? Do you prefer long sessions or short ones? Differences are fine; knowing about them lets you plan around them.
Review turnaround. How soon after a pull request is opened will it be reviewed? Pick a time that fits both of your schedules but no more than 48 hours.
Goals. What does each of you want to get out of this project? What would a successful outcome look like to you? Are there skills or parts of the work you especially want experience with, or feel less confident about? This can help you split tasks.
Meet at least twice a week; short check-ins are fine.
Keep a running log in docs/team-log. (Until you've chosen a codebase in A3, use a shared document in Google Docs or similar.) Each entry should have the date, who attended, the decisions made, and open questions. When new tasks are identified, create issues in GitHub and reference them in the log entry (e.g. created #14-16; moved target date on #9"). Note that issues include non-code tasks too, such as "write codebase decision memo", "submit individual effort estimates", or "schedule check-in meeting".
Day-to-day coordination happens in the channel chosen in your team kickoff (email, text, etc). This is for quick back-and-forth; anything decided that affects the project should be recorded in the team log or in the relevant GitHub issue so it is available to the whole team and doesn't get lost in only one partner's memory.
Tasks and commitments are tracked as GitHub issues, one per task, including non-code tasks such as drafting a memo or submitting estimates. Each issue has its owner as the assignee, a size: label for its estimate (and joint if applicable), and a target date in its description. Close an issue when the task is done; a pull request that completes a task should say "Closes #n" in its description so that merging it closes the issue.
Discussion about specific code happens in pull request comments, where it stays attached to the code it's about.
Deliverables and records — the team kickoff, team log, plans, memos, reviews, and change impact analyses — are plain text files in the docs/ directory of the appropriate repository. These are the official versions that are assessed.
Google Docs (or similar) may be used as a scratch space for writing together in real time, such as taking notes during a meeting or drafting a memo. Final versions must be copied into docs/; anything that exists only in a Google Doc doesn't count.
If you're going to miss a target date, tell your partner before it passes, not after, and update the issue.
When a team task is split between partners, plan it using SML effort estimation. The goal is a fair split, but just as important is to identify misunderstandings early — if two people give very different estimates for the same task, it is likely that they are picturing different things.
Each split team task has its own plan, consisting of:
the tasks themselves, tracked as GitHub issues grouped in a milestone for the plan (see the Communication and Shared Records section)
each partner's independent estimates, submitted on Canvas
a short plan summary in docs/ (described below)
When estimating a task's size, include the time to write its tests. As an approximate guideline:
S (small) tasks are those where the change is well understood (you have a pretty good idea of what to do) and limited to one method or class.
M (medium) tasks involve a few methods or classes or a design decision or some unknowns that you'll need to work out.
L (large) tasks span several classes or there is a lot of uncertainty about how best to approach them.
A task bigger than large must be split into smaller tasks. If you are unsure how to decide between two sizes, choose the larger. Uncertainty is itself a cost, as time spent figuring out what to do is part of the task. As a (very) rough guide, small tasks shouldn't take more than an hour and medium tasks shouldn't take more than 1-3 hours.
Steps in the planning process:
Define the tasks. Create a milestone for the plan and an issue for each task in it, with a title and a description of what the task involves. Leave the assignee and size label blank for now. (Tasks may be given in the handout, or you may identify them yourselves.)
Estimate independently. Without discussing estimates with your partner, give an S/M/L estimate for each task (by issue number), plus a one-line note on what you think the task involves. Submit your individual estimates on Canvas before the team planning meeting.
Compare. In the planning meeting, discuss every task where your estimates differ: what was each of you picturing, and why? Resolve the difference. This may mean clarifying what the task involves, splitting it, or agreeing on a size. Update the issue description if your understanding of the task changed.
Agree on interfaces. Where one task depends on another, agree on the connection point (method names, parameters, behavior) before either of you starts, and record it in both issues.
Assign owners. Decide who owns each task (see Ownership, Pair Programming, and Swarming), then set each issue's assignee and size: label, and add a target date to its description. To balance the work, count S = 1, M = 2, L = 4 points. Each partner's share should fall between 40% and 60% of the total for each of Part A and Part B. (Doing less on one part can't be made up by doing more on the other.) In each plan, each partner must own at least one task, and joint tasks may make up no more than one-third of the points.
Record actual sizes. When you close an issue, add a comment giving the task's actual size, with a brief explanation if it differs from the estimate (e.g. "Actual: L — validation had many more cases than expected").
For each plan, commit a short summary to docs/ (the task instructions give the filename). Refer to tasks by issue number rather than repeating them. The summary contains:
any differences between your independent estimates and how you resolved each one
each partner's point total (counting joint tasks as half to each)
once the work is done, a few sentences comparing the estimates to the actual sizes. Where were you off, and did the differences discussion predict it?
Owners. Every task has exactly one owner, who is responsible for completing it (with tests) and for opening its pull request. Work is assessed according to ownership (see Assessment).
Pair programming is allowed on team tasks. Pairing doesn't change ownership: the owner is still responsible for the task. When pairing, whoever is typing commits and credits their partner by ending the commit message with a blank line followed by Co-authored-by: and the partner's name and email as shown:
Co-authored-by: Arthur Dent <dent@xyz.edu>
Use the email associated with the partner's GitHub account so that GitHub credits things properly when showing ownership of commits.
Joint tasks. If you plan to pair program a task from start to finish, you may designate it as joint when assigning owners: give it the joint label, and its points count half to each partner. Both partners are responsible for a joint task and must be able to explain it.
Swarming means both partners working on one problem together. Use it for design decisions, agreeing on interfaces, and integration problems. Planning meetings are a form of swarming. Implementation is usually split — if you work together on implementation, use pair programming.
Follow the GitHub Flow workflow:
main always contains working code with all tests passing.
All code changes are done on a branch, one branch per task. Never commit code directly to main. (Files in docs/, such as the team log, may be committed directly to main.)
Commit incrementally with meaningful messages, as in P0. Commits must be made under your own GitHub account.
When a task is done, update your local main, merge main into your branch, resolve any conflicts, make sure all tests pass, and open a pull request. If main changes again before your pull request is merged, repeat this before merging. (This is a stricter version of the workflow from lab — there you only merged main into your branch when GitHub flagged merge conflicts, but just because things merge smoothly doesn't mean nothing broke. Merging main first means you can run tests on the result and make sure everything works before updating the remote repository.)
Coming soon!
Hand in all of the following — each is an essential part of the assessment for this project.
Coming soon!
The course projects together account for 50% of your final grade in this course. There are two distinct components to the project grade:
Program and deliverable quality. (15%) Does the program correctly implement the specification and are the other deliverables complete and done properly (not just present)? This is graded against the stated program and process requirements — a program missing functionality or crashing on bad input, documentation that's missing or incomplete, or process steps that weren't followed fall short here.
Skills standards. (35%) Your work also provides evidence towards the following skills standards. These are assessed directly from your deliverables, and some may be followed up on briefly in the handin meeting, where you may be asked to explain a specific choice you made.
In addition, teamwork is part of the course engagement grade. Teamwork conduct is assessed through a structured peer evaluation at the end of the project. Your team log and pull request history are used to corroborate the peer evaluations.