Minifundium logo

An AI-driven agriculture simulation and intelligent NPC laboratory built in Godot 4 - a research project on breaking static NPC routines with lightweight, native Reinforcement Learning.

Godot Engine 4.6 Stage: Beta v0.4.0 License: CC BY-NC-ND 3.0 Research Prototype
The project

Teaching NPCs to farm

In cozy farming sims like Stardew Valley or Animal Crossing, NPCs usually follow rigid, pre-scripted daily routines. Minifundium asks a different question: what if a farm helper actually learned from how you play, instead of just executing a schedule? The name comes from the Latinized Spanish word “minifundio”, referring to a very small farming plot.

Experimental design

The AI Laboratory Architecture

Minifundium is split into four isolated layouts, each swapping the chicken helper's "brain" for a different decision-making model - letting deterministic behavior be directly compared against adaptive learning.

Diagram of the four AI laboratories in Minifundium
LAB 1 - BASELINE

Directly Commanded

The chicken stays Idle until the player explicitly signals a harvest with the contextual action key (R). Validates the physical controller and navigation.

LAB 2 - INDUSTRY STANDARD

Finite State Machine

Classic reactive AI: on a timer, the brain checks "is there a ready crop?" and transitions accordingly. Autonomous, but inflexible.

LAB 3 - INDIVIDUAL

Native Reinforcement Learning

A lightweight, tabular Q-learning analogue built from scratch in GDScript. The agent builds its own weighted transition matrix from the player's reinforcement.

LAB 4 - COLLECTIVE

Group Reinforcement Learning

Multiple chickens share one autoloaded global matrix. Teaching a single helper instantly optimizes the behavior of the entire flock.

Deep dive

How the native RL matrix works

To avoid resource-heavy external dependencies, sockets, or ML frameworks like MLAgents, Minifundium implements its weight-based transition logic natively inside lightweight GDScript components (brain_rl.gd).

1. Balanced starting weights

var matrix = {
   "Idle": {"Idle": 1, "Harvest": 1},
   "Harvest": {"Idle": 1, "Harvest": 1}
}

2. Reinforcing a player command

func on_player_command() -> void:
    var crop = chicken.find_ready_crop()
    if crop:
        matrix[last_state]["Harvest"] += 1
        chicken.target_crop = crop
        last_state = "Harvest"
        chicken.state.transition_to("Movement")

3. Choosing the next action - weighted roulette selection

func _choose_weighted_action() -> String:
    var choices = matrix[last_state]
    var total_weight = 0
    for w in choices.values():
        total_weight += w

    var random_val = randi() % total_weight
    var current_sum = 0
    for state in choices.keys():
        current_sum += choices[state]
        if random_val < current_sum:
            return state
    return "Idle"

Every time the player rewards a harvest, the odds shift a little further away from wandering and toward farm work - turning an aimless chicken into a proactive helper shaped by the player's own habits.

From the write-up

What building this taught me

Notes from the full article on building Minifundium's AI.

Weight saturation → infinite loops

Spamming the reward key skewed the roulette wheel so hard that chickens got stuck trying to harvest empty plots forever. Fixed with a clamping function that caps and normalizes matrix weights.

A reality check before acting

A predictive context validator now double-checks the world state before executing the roulette wheel's choice - if the chosen action isn't actually viable, its weight is temporarily zeroed and the wheel spins again.

Accidental hive mind

Sharing one matrix across three chickens in Lab 4 meant training a single bird instantly changed how the whole flock behaved - a small, unplanned glimpse of collective learning.

Under the hood

Technical specifications

EngineGodot 4.6, Forward Plus renderer, TileMapLayer nodes for Water / Grass / Ground / Tilled Dirt.
ArchitectureStrict State Pattern - Idle, Movement and Harvest states emit transitions to a StateMachine arbiter.
ComponentsTyped Hitbox / Hurtbox areas drive tool validation (e.g. trees only take damage from the Axe).
AutoloadsGameTime (growth cycle), Resources (inventory counters), GlobalAI (shared flock matrix for Lab 4).