2025-08-08 23:33:16 -05:00

295 lines
6.6 KiB
Go

/*
Package towns is the active record implementation for towns in the game.
# Basic Usage
To retrieve a town by ID:
town, err := towns.Find(db, 1)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found town: %s at (%d,%d)\n", town.Name, town.X, town.Y)
To get all towns:
allTowns, err := towns.All(db)
if err != nil {
log.Fatal(err)
}
for _, town := range allTowns {
fmt.Printf("Town: %s\n", town.Name)
}
To find a town by name:
midworld, err := towns.ByName(db, "Midworld")
if err != nil {
log.Fatal(err)
}
To filter towns by affordability:
cheapInns, err := towns.ByMaxInnCost(db, 25)
if err != nil {
log.Fatal(err)
}
affordableTP, err := towns.ByMaxTPCost(db, 50)
if err != nil {
log.Fatal(err)
}
To find nearby towns:
nearbyTowns, err := towns.ByDistance(db, playerX, playerY, 100)
if err != nil {
log.Fatal(err)
}
# Creating Towns with Builder Pattern
The package provides a fluent builder interface for creating new towns:
town, err := towns.NewBuilder(db).
WithName("New Settlement").
WithCoordinates(150, -75).
WithInnCost(35).
WithMapCost(125).
WithTPCost(40).
WithShopItems([]string{"1", "5", "10", "20"}).
Create()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created town with ID: %d\n", town.ID)
# Updating Towns
Towns can be modified and saved back to the database:
town, _ := towns.Find(db, 1)
town.Name = "Enhanced Midworld"
town.InnCost = 8
town.MapCost = 10
err := town.Save()
if err != nil {
log.Fatal(err)
}
# Deleting Towns
Towns can be removed from the database:
town, _ := towns.Find(db, 1)
err := town.Delete()
if err != nil {
log.Fatal(err)
}
# Database Schema
The towns table has the following structure:
CREATE TABLE towns (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
x INTEGER NOT NULL DEFAULT 0,
y INTEGER NOT NULL DEFAULT 0,
inn_cost INTEGER NOT NULL DEFAULT 0,
map_cost INTEGER NOT NULL DEFAULT 0,
tp_cost INTEGER NOT NULL DEFAULT 0,
shop_list TEXT NOT NULL DEFAULT ''
)
Where:
- id: Unique identifier
- name: Display name of the town
- x, y: World coordinates for the town location
- inn_cost: Cost in gold to rest at the inn
- map_cost: Cost in gold to buy the world map from this town
- tp_cost: Cost in gold to teleport to this town from elsewhere
- shop_list: Comma-separated list of item IDs sold in the town shop
# Town Economics
## Inn System
Towns provide rest services through inns:
if town.CanAffordInn(playerGold) {
fmt.Printf("You can rest at %s for %d gold\n", town.Name, town.InnCost)
}
Inn costs typically increase with town size and distance from starting area.
## Map Purchase
Maps can be bought from certain towns:
if town.MapCost > 0 && town.CanAffordMap(playerGold) {
fmt.Printf("Map available for %d gold at %s\n", town.MapCost, town.Name)
}
Not all towns sell maps (cost = 0 means unavailable).
## Teleportation Network
Towns with teleport access allow fast travel:
if town.TPCost > 0 && town.CanAffordTeleport(playerGold) {
fmt.Printf("Can teleport to %s for %d gold\n", town.Name, town.TPCost)
}
Starting town (Midworld) typically has no teleport cost.
# Shop System
## Item Management
Towns have shops that sell specific items:
shopItems := town.GetShopItems()
fmt.Printf("%s sells %d different items\n", town.Name, len(shopItems))
if town.HasShopItem("5") {
fmt.Println("This town sells item ID 5")
}
## Shop Inventory
Shop inventories are stored as comma-separated item ID lists:
// Current inventory
items := town.GetShopItems() // Returns []string{"1", "2", "3"}
// Update inventory
newItems := []string{"10", "15", "20", "25"}
town.SetShopItems(newItems)
town.Save() // Persist changes
# Geographic Queries
## Coordinate System
Towns exist on a 2D coordinate plane:
fmt.Printf("%s is located at (%d, %d)\n", town.Name, town.X, town.Y)
// Calculate distance between towns
distance := town1.DistanceFrom(town2.X, town2.Y)
## Proximity Search
Find towns within a certain distance:
// Get all towns within 50 units of player position
nearbyTowns, err := towns.ByDistance(db, playerX, playerY, 50)
// Results are ordered by distance (closest first)
if len(nearbyTowns) > 0 {
closest := nearbyTowns[0]
fmt.Printf("Closest town: %s\n", closest.Name)
}
## Starting Location
The starting town is identifiable:
if town.IsStartingTown() {
fmt.Println("This is where new players begin")
}
Starting towns are typically at coordinates (0, 0).
# Cost-Based Queries
## Budget-Friendly Services
Find towns within budget constraints:
// Towns with affordable inns
cheapInns, err := towns.ByMaxInnCost(db, playerGold)
// Towns with affordable teleportation
affordableTP, err := towns.ByMaxTPCost(db, playerGold)
Results are ordered by cost (cheapest first).
## Service Availability
Check what services a town offers:
fmt.Printf("Services at %s:\n", town.Name)
if town.InnCost > 0 {
fmt.Printf("- Inn: %d gold\n", town.InnCost)
}
if town.MapCost > 0 {
fmt.Printf("- Map: %d gold\n", town.MapCost)
}
if town.TPCost > 0 {
fmt.Printf("- Teleport destination: %d gold\n", town.TPCost)
}
# Game Progression
## Town Hierarchy
Towns typically follow a progression pattern:
1. **Starting Towns** (Midworld): Free teleport, basic services, low costs
2. **Early Game Towns** (Roma, Bris): Moderate costs, expanded shops
3. **Mid Game Towns** (Kalle, Narcissa): Higher costs, specialized items
4. **Late Game Towns** (Hambry, Gilead, Endworld): Premium services, rare items
## Economic Scaling
Service costs often scale with game progression:
// Example progression analysis
towns, _ := towns.All(db)
for _, town := range towns {
if town.TPCost > 100 {
fmt.Printf("%s is a late-game destination\n", town.Name)
}
}
# World Map Integration
## Navigation
Towns serve as waypoints for world navigation:
// Find path between towns
startTown, _ := towns.ByName(db, "Midworld")
endTown, _ := towns.ByName(db, "Endworld")
distance := startTown.DistanceFrom(endTown.X, endTown.Y)
fmt.Printf("Distance from %s to %s: %.0f units\n",
startTown.Name, endTown.Name, distance)
## Strategic Planning
Use town data for strategic decisions:
// Find cheapest inn route
route := []string{"Midworld", "Roma", "Bris"}
totalInnCost := 0
for _, townName := range route {
town, _ := towns.ByName(db, townName)
totalInnCost += town.InnCost
}
fmt.Printf("Route inn cost: %d gold\n", totalInnCost)
# Error Handling
All functions return appropriate errors for common failure cases:
- Town not found (Find/ByName returns error for non-existent towns)
- Database connection issues
- Invalid operations (e.g., saving/deleting towns without IDs)
*/
package towns