Skip to content

feat: Add farming system — planting, crop growth, and harvesting#348

Merged
dmccoystephenson merged 5 commits into
mainfrom
copilot/add-farming-mechanic
Apr 20, 2026
Merged

feat: Add farming system — planting, crop growth, and harvesting#348
dmccoystephenson merged 5 commits into
mainfrom
copilot/add-farming-mechanic

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 20, 2026

Adds a renewable food source via farming. Players craft wheat seeds from grass, plant them on grass tiles, wait for two growth stages driven by TickCounter, and harvest mature crops for wheat (food).

New entities

  • WheatSeed — craftable, plantable, non-solid
  • YoungCrop / MatureCrop — non-solid, store tickPlanted for growth tracking
  • Wheat(Food) — energy 10–20, harvested from mature crops

Growth

  • Room.tickCrops(tick, config) — mirrors tickExcrement pattern. YoungCrop → MatureCrop after cropGrowthTicks ticks (default 1800 ≈ 1 min at 30 tps). MatureCrop waits for player harvest.
  • cropGrowthTicks added to Config

Planting & harvesting (worldScreen.py)

  • executePlaceAction: WheatSeed on grass → remove grass, consume seed, place YoungCrop. Non-grass → "Must plant on grass". Locations that already contain a crop are blocked with "A crop is already growing here".
  • executeGatherAction: MatureCrop → remove, add Wheat to inventory. YoungCrop → "Crop is not ready".
  • Energy is only deducted after all planting validations succeed — failed attempts don't drain energy.
  • Wheat is registered in the Player's edibleEntityTypes so harvested wheat is consumable.

Crafting

  • Recipe: 1× Grass → 3× WheatSeed
  • Recipe gains resultCount param; craft() now returns a list:
Recipe("Wheat Seed", {Grass: 1}, WheatSeed, "assets/images/wheatSeed.png", 3)
  • craftRecipe() pre-validates inventory capacity for all resultCount items (including stacking space) before consuming ingredients, and handles placement failures mid-loop.

Persistence

  • YoungCrop/MatureCrop serialize tickPlanted in both roomJsonReaderWriter and inventoryJsonReaderWriter, following the Excrement.tickCreated pattern
  • All four entity types added to entity registries in both reader/writers
  • _CROP_ENTITY_CONSTRUCTORS registry added to inventory reader/writer for tick-parameterized construction

Tests

  • 21 new tests: entity init/properties, crop growth stage transitions, serialization round-trips, recipe validation
  • All 363 tests pass

Copilot AI linked an issue Apr 20, 2026 that may be closed by this pull request
8 tasks
…tities with planting, growth, and harvesting

Agent-Logs-Url: https://github.com/Preponderous-Software/roam/sessions/5179343d-6ba3-4b52-a04a-410ce8f30a1b

Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
Copilot AI changed the title [WIP] Add farming mechanic for planting and harvesting crops feat: Add farming system — planting, crop growth, and harvesting Apr 20, 2026
Copilot AI requested a review from dmccoystephenson April 20, 2026 00:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a farming loop (seed crafting → planting → time-based crop growth → harvesting) to provide a renewable food source, integrated into ticking, persistence, UI actions, and tests.

Changes:

  • Introduces WheatSeed / YoungCrop / MatureCrop / Wheat entities plus placeholder sprites.
  • Adds crop growth ticking (Room.tickCrops) and world interactions for planting/harvesting in WorldScreen.
  • Extends crafting to support multi-item outputs via Recipe.resultCount and updates persistence + tests.

Reviewed changes

Copilot reviewed 22 out of 26 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/world/test_roomJsonReaderWriter.py Expands room JSON coverage for wheat/crops + tickPlanted round-trips
tests/world/test_cropGrowth.py New unit tests for Room.tickCrops() growth transitions
tests/entity/test_youngCrop.py New tests for YoungCrop defaults + tickPlanted accessors
tests/entity/test_wheatSeed.py New tests for WheatSeed defaults
tests/entity/test_wheat.py New tests for Wheat defaults + energy range
tests/entity/test_matureCrop.py New tests for MatureCrop defaults + tickPlanted accessors
tests/crafting/test_wheatSeedRecipe.py New test asserting Grass → WheatSeed×3 recipe exists
tests/crafting/test_recipe.py Updates to expect Recipe.craft() returns a list
src/world/roomJsonReaderWriter.py Registers wheat/crops for room (de)serialization + tickPlanted
src/world/room.py Adds tickCrops() to mature crops over time
src/screen/worldScreen.py Adds planting/harvesting behaviors; calls crop ticking in main loop
src/screen/inventoryScreen.py Updates crafting flow to handle list results
src/inventory/inventoryJsonReaderWriter.py Adds wheat/crops to inventory (de)serialization + tickPlanted
src/entity/youngCrop.py New YoungCrop entity (non-solid, tickPlanted)
src/entity/wheatSeed.py New WheatSeed entity (non-solid)
src/entity/wheat.py New Wheat food entity (energy 10–20)
src/entity/matureCrop.py New MatureCrop entity (non-solid, tickPlanted)
src/crafting/recipeRegistry.py Adds Wheat Seed recipe (Grass → WheatSeed×3)
src/crafting/recipe.py Adds resultCount; craft() now returns a list of results
src/config/config.py Adds cropGrowthTicks config option (default 1800)
assets/images/youngCrop.png New sprite placeholder
assets/images/wheatSeed.png New sprite placeholder
assets/images/wheat.png New sprite placeholder
assets/images/matureCrop.png New sprite placeholder
README.md Documents new planting/harvesting controls
CHANGELOG.md Documents feature and adds learning-log notes

Comment thread src/screen/inventoryScreen.py
Comment thread src/screen/worldScreen.py Outdated
Comment on lines 763 to 767
@@ -738,6 +766,34 @@ def executePlaceAction(self):
if inventorySlot.isEmpty():
self.status.set("Select an item first (1-0)")
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

executePlaceAction() deducts interaction energy before verifying that a selected WheatSeed can actually be planted (and before other early-return validations like an empty slot). With the new seed-planting branch, a failed plant attempt (e.g., not on grass) still costs energy. Move the energy deduction to after all validations succeed (or refund on failure) so unsuccessful actions don’t drain energy.

Copilot uses AI. Check for mistakes.
Comment thread src/screen/worldScreen.py
Comment thread src/screen/inventoryScreen.py Outdated
Comment on lines 275 to 277
if not self.inventory.hasAvailableSlotFor(recipe.getResultClass()):
self.status.set("Inventory full")
return
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

craftRecipe() only checks hasAvailableSlotFor(recipe.getResultClass()), which is insufficient now that Recipe.craft() can return multiple items via resultCount. This can allow crafting to proceed when there isn’t enough total capacity for all results, leading to partial placement and/or item loss after ingredients are consumed. Consider adding an inventory-capacity check that accounts for recipe.getResultCount() (including stacking space) before calling craft().

Copilot uses AI. Check for mistakes.
@dmccoystephenson
Copy link
Copy Markdown
Member

@copilot You are a coding agent tasked with resolving all open comments and review threads
on this pull request. Work through every comment systematically and apply the
appropriate code changes.


Instructions

1. Discover all comments

  • Read every review thread, inline comment, and general PR comment
  • Include comments from: Copilot, human reviewers, and any other bots
  • Do not skip comments marked as suggestions — apply them if they make sense

2. For each comment, do the following:

  • Understand what is being requested or flagged
  • Locate the relevant file(s) and line(s)
  • Apply the fix directly in code
  • If a Copilot suggestion diff is provided, apply it (or an equivalent fix)
  • If the comment is ambiguous, use your best judgment and reply in the PR thread or review comment explaining what you did; only add a code comment when explicitly requested or when future maintainers would benefit from it
  • After addressing a comment, reply to the thread summarising what you did and mark it as resolved if your environment supports it

3. Types of issues to handle:

  • Code quality / style issues (naming, formatting, readability)
  • Logic bugs or edge cases flagged by reviewers
  • Security concerns (e.g. input validation, secrets, injection risks)
  • Performance suggestions
  • Missing or incomplete error handling
  • Test coverage gaps
  • Documentation / comment improvements
  • Dependency or import issues

4. Do NOT:

  • Dismiss or ignore any comment without acting on it — note that "acting" can also mean replying to the thread with a rationale (e.g., won't fix, already addressed elsewhere) and leaving the code unchanged when appropriate
  • Leave TODO comments as a substitute for fixing the issue
  • Break existing tests while addressing comments
  • Change functionality beyond the scope of what the comment asks for

After making changes

  • Ensure all existing tests still pass
  • Add or update tests if a comment explicitly asks for them, or if a bug fix warrants it
  • Double-check that every open thread has been addressed, replied to, and resolved

Context

  • This PR may contain Copilot-generated review comments — treat these with the same priority as human comments
  • If two comments conflict with each other, prefer the human reviewer's intent and document the conflict and resolution in the PR conversation or commit message, not in a code comment
  • Commit changes in logical groups if there are many unrelated fixes

…gy/inventory issues in crafting and planting

Agent-Logs-Url: https://github.com/Preponderous-Software/roam/sessions/78cbe4e0-050b-43d3-b2b7-68e529faf105

Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 20, 2026

@copilot You are a coding agent tasked with resolving all open comments and review threads
on this pull request. Work through every comment systematically and apply the
appropriate code changes....

All four review threads addressed in a518d48:

  1. Wheat not edible (worldScreen.py:600-604): Added Wheat to Player's edibleEntityTypes in player.py so harvested wheat is consumable via auto-eat and canEat().

  2. Energy deducted before validation (worldScreen.py:763-767): Moved removeEnergy() to after all validations succeed — failed plant attempts (e.g., "Must plant on grass", empty slot) no longer drain energy. For the general place path, energy is deducted only after the slot check passes.

  3. Inventory capacity not checked for resultCount (inventoryScreen.py:275-277): Replaced hasAvailableSlotFor() with a full capacity check that accounts for resultCount and stacking space before consuming ingredients.

  4. Placement failures ignored during crafting (inventoryScreen.py:280-282): Added explicit return value check on placeIntoFirstAvailableInventorySlot() — if inventory fills mid-loop, crafting stops with a status message.

@dmccoystephenson
Copy link
Copy Markdown
Member

@copilot Prevent placing crops in locations that already have a crop present

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 20, 2026

@copilot Prevent placing crops in locations that already have a crop present

Added in 58100b0. The planting logic in executePlaceAction() now checks for existing YoungCrop or MatureCrop entities at the target location before planting. If a crop is already present, it shows "A crop is already growing here" and returns without consuming the seed or energy.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 27 changed files in this pull request and generated no new comments.

@dmccoystephenson dmccoystephenson marked this pull request as ready for review April 20, 2026 01:50
@dmccoystephenson dmccoystephenson merged commit 99abc33 into main Apr 20, 2026
5 checks passed
@dmccoystephenson dmccoystephenson deleted the copilot/add-farming-mechanic branch April 20, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Farming

3 participants