Sewer / Drainage
Implementation of sewer / drainage that defines how players interact with this aspect of the game, including feedback and progression.
Overview
The sewer / drainage mechanic provides a framework that establishes rules governing player behavior and system responses. The implementation varies significantly across genres, with each game adapting the core concept to fit its specific design goals and target audience. Understanding the design principles behind this mechanic helps developers create more engaging and balanced game experiences.
Game Examples
Simulation Games
Simulation Games use this mechanic where players weigh competing priorities to support their team effectively. The system rewards both skill and knowledge, resulting in memorable moments.
Fighting Games
Fighting Games use this mechanic where players optimize their build to tell their own story. The system encourages experimentation, resulting in satisfying progression.
Turn-Based Strategy Games
Turn-Based Strategy Games use this mechanic where players customize their experience to progress through the content. The difficulty scales with player performance, resulting in personal achievement.
Pros & Cons
Advantages
- Enhances temporal without disrupting core gameplay
- Rewards both pattern recognition and mechanical skill
- Reduces tedium while maintaining challenge
- Provides long-term progression targets for dedicated players
Disadvantages
- May overwhelm competitive players with too many options
- Risk of power creep in competitive environments
- Can create confusing when RNG is unfavorable
- Increases CPU requirements significantly
- Requires significant balance data to implement well
Implementation Patterns
Crafting Queue
Event-driven pattern that reacts to sewer / drainage changes and updates dependent systems.
class SewerDrainageProcessor {
recipes: Recipe[] = [];
craft(recipeId: string, inventory: Inventory) {
const recipe = this.recipes.find(r => r.id === recipeId);
if (!recipe) return null;
for (const ingredient of recipe.ingredients) {
if (!inventory.has(ingredient.id, ingredient.amount)) {
return null; // Missing materials
}
}
for (const ingredient of recipe.ingredients) {
inventory.remove(ingredient.id, ingredient.amount);
}
const quality = this.rollQuality(0.2);
return { ...recipe.output, quality };
}
rollQuality(baseChance: number) {
const roll = Math.random();
if (roll < baseChance * 0.05) return "legendary";
if (roll < baseChance * 0.2) return "rare";
if (roll < baseChance) return "uncommon";
return "common";
}
}Quality Calculator
Data-driven implementation that loads sewer / drainage configuration from external definitions.
class SewerDrainageController {
recipes: Recipe[] = [];
craft(recipeId: string, inventory: Inventory) {
const recipe = this.recipes.find(r => r.id === recipeId);
if (!recipe) return null;
for (const ingredient of recipe.ingredients) {
if (!inventory.has(ingredient.id, ingredient.amount)) {
return null; // Missing materials
}
}
for (const ingredient of recipe.ingredients) {
inventory.remove(ingredient.id, ingredient.amount);
}
const quality = this.rollQuality(0.05);
return { ...recipe.output, quality };
}
rollQuality(baseChance: number) {
const roll = Math.random();
if (roll < baseChance * 0.05) return "legendary";
if (roll < baseChance * 0.2) return "rare";
if (roll < baseChance) return "uncommon";
return "common";
}
}