Commit graph

1351 commits

Author SHA1 Message Date
Natalie
7e3c573127 chore(@projects/@magic-civilization): 🔧 add scheduled_tasks.lock file
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 21:54:00 -07:00
Natalie
303919f5f1 feat(ai): add research automation logic
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 21:37:12 -07:00
Natalie
96bf38c9e4 feat(@projects/magic-civilization): add physics engine support
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 21:32:32 -07:00
autocommit
db5b2cd3ce ui(screenshots): 💄 Replace autoplay victory turn screenshot with corrected visual asset
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 19:30:32 -07:00
autocommit
8d4a1111eb ui(screenshots): 💄 Replace outdated autoplay screenshots for turns 41–50 with updated visual assets
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 19:24:39 -07:00
autocommit
63af9ae01c docs(screenshots): 📝 Add/update project screenshots for visual documentation
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 19:18:51 -07:00
Natalie
9db0c6ef81 feat(auto-play): build walls, settlers, forge — match AI strategy
Our auto-play now mirrors the AI's build order:
1. Walls (defense first)
2. Settler to expand to 3 cities
3. Forge (+2 production)
4. Warriors for military

Settlers move away from existing cities (5+ hex distance) before founding.
Removed debug prints from production tracking.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 19:17:42 -07:00
autocommit
7d74bde835 perf(physics): Update x86_64 physics engine library with performance optimizations and bug fixes
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 19:13:19 -07:00
autocommit
4daa0bfb66 chore(none-root-level-config): 🔧 Update .gitignore to exclude build outputs, logs, and sensitive data files
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 19:13:19 -07:00
Natalie
99ff12292f debug: log production progress 2026-04-12 19:06:47 -07:00
Natalie
1ef1c53caa debug: log AI set_production actions 2026-04-12 19:04:59 -07:00
Natalie
c9c5dcf2a9 feat: increase city center yields + smarter AI production priorities
City center now produces 2 food, 2 production, 1 gold, 1 science (was 2/1/0/0).
This doubles the pace of the game — warriors in ~20 turns instead of ~40,
walls in ~35 instead of ~70.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 19:00:00 -07:00
Natalie
ef65fb3dc2 feat(ai): smarter production — walls, settlers, forge, castle priority
AI production now follows a priority chain:
1. Build walls (defense first — every city gets walls)
2. Build settler if < 3 cities (expansion)
3. Build warriors to maintain 2 per city (military)
4. Build forge (+2 production for faster future builds)
5. Build castle (upgrades walls, enables bombard)
6. Build any remaining available building
7. Fallback: more military

This makes the AI significantly more challenging:
- Cities have walls (0.75x melee penalty, +50 HP)
- AI expands to 2-3 cities (domination requires capturing ALL)
- Forge accelerates subsequent production
- Castle adds city bombardment capability

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:53:35 -07:00
Natalie
6b03eca49d feat(city-defense): active city bombardment — cities attack once per turn
- Cities can bombard one enemy unit within range (2 hexes) per turn
- Human player: click own city → click enemy within range to bombard
- AI player: automatically bombards nearest enemy in range
- Damage formula: 20 * (city_str / def_str), clamped [5, 40]
- city_str = population * 3 + castle bonus (12)
- has_bombarded flag resets each turn via city.refresh_turn()
- New AI action type: "city_bombard" in simple_heuristic_ai + ai_turn_bridge

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:30:26 -07:00
Natalie
08abd276c5 feat(city-defense): population HP scaling + garrison combat strength boost
- City max_hp scales with population: base 200 + 10 per pop (pop 1 = 210)
- max_hp recalculated on growth/starvation, building bonuses preserved
- Garrison unit's attack adds to city bombard combat strength
- Renamed DEFAULT_CITY_HP → BASE_CITY_HP, added HP_PER_POP constant

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:22:25 -07:00
Natalie
9bbd80a426 feat(city-defense): city bombard retaliation + building HP bonuses
- City bombard: melee attackers take 5-30 damage based on city population
  and castle bombard bonus (city_str = pop*3 + castle bonus)
- Building HP bonuses: when walls/castle complete, increase city max_hp
  and heal by hp_bonus value from building data
- Castle data: added city_bombard_strength: 12, city_bombard_range: 2

Combined with prior commit's city healing (20 HP/turn) and tiered wall
penalties (walls=0.75x, castle=0.60x), cities now require sustained
multi-turn sieges instead of 1-2 turn captures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:04:28 -07:00
Natalie
00aa2ef601 feat(city-defense): city healing, tiered wall penalties, bombard damage function
- Cities heal 20 HP per turn (heal_per_turn in Rust, exposed via GDExtension,
  called from turn_processor after unit healing)
- Wall penalty scales by tier: none=1.0, walls=0.75, castle=0.60
- Added city_bombard_damage() function: 15 * (city_str/attacker_str), [5,30]
- Fixed "fortress"→"castle" references in combat_resolver.gd and combat_preview.gd
- Fixed defender.city_hp→defender.hp already done in prior commit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:01:45 -07:00
Natalie
0dc1fa5db8 refactor: rename hammer→production throughout codebase
Production is production, hammers are weapons. Single source of truth.

Rust: hammer_cost→production_cost, hammers_invested→production_invested,
hammers params→production (with serde aliases for JSON backward compat)
GDScript: hammers vars→prod, comments updated
Guide: "Hammers" label→"Production"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:56:17 -07:00
Natalie
d67d94e440 fix(combat): use defender.hp instead of nonexistent defender.city_hp
The City class has no 'city_hp' property — it uses 'hp' (backed by Rust
GDExtension). The combat resolver was reading/writing 'city_hp' which
created a dynamic property that never affected real city health. This
caused:
- City HP always passed as 0 to Rust resolver
- City damage never applied to actual city HP
- Cities could never be captured (HP never decreased)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:36:50 -07:00
Natalie
0a79576b5d fix(auto-play): use hex_distance for attack range instead of neighbor iteration
Neighbor-based enemy detection failed due to normalize_position changing
coordinates on wrapped maps. Now simply checks hex_distance <= 1 for all
enemy units and cities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:26:24 -07:00
Natalie
60d4128dd5 fix: check same-hex enemies in _try_attack_adjacent 2026-04-12 16:20:06 -07:00
Natalie
0b5dd48db6 fix(auto-play): attack adjacent enemies immediately instead of moving first
When already adjacent to the target, skip movement and attack directly.
Previously the deadlock-breaker would move the warrior AWAY from the
adjacent enemy to a random hex.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:15:33 -07:00
Natalie
dd966bea93 debug: log nearby enemies in _try_attack_adjacent 2026-04-12 16:13:42 -07:00
Natalie
962c9ea857 fix: allow attacking adjacent enemies even with 0 movement remaining 2026-04-12 16:07:51 -07:00
Natalie
f9f85937fa fix: attack with 2+ warriors (can't accumulate more in stalemate) 2026-04-12 16:01:57 -07:00
Natalie
3b2e07eef3 fix: set num_players=2 after initialize_game runs 2026-04-12 15:54:54 -07:00
Natalie
115d7e84dd fix(auto-play): force 2-player game for fair domination match
Default settings create 4 players even on a Duel (2) map. With 3 AI vs 1
human, we're permanently outnumbered. Force 2 players for a 1v1 match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:48:40 -07:00
Natalie
9e4c96faed debug: simplify combat handler to avoid crashes 2026-04-12 15:45:25 -07:00
Natalie
f3a7f486aa debug: log all combat involving Player 0 2026-04-12 15:43:23 -07:00
Natalie
d9d819b338 fix(auto-play): instant max fortification for garrison warriors
Set fortified_turns=2 immediately instead of waiting 2 turns to build up.
With max fortification (+4 defense), a warrior should take only ~3 damage
per enemy attack instead of ~34, allowing accumulation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:37:35 -07:00
Natalie
aeda438bf3 feat(auto-play): defensive counter-attacks + garrison until 5 warriors
- Build phase: attack adjacent enemies before fortifying (counter-attack)
- Only march when 5+ warriors accumulated (no more premature attacks)
- Warriors at city fortify for defense bonus AND fight back

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:29:43 -07:00
Natalie
156efa5692 fix(auto-play): only target enemies reachable by land path
Warriors were marching toward enemies across water with no land path.
Now uses PathfinderScript.find_path with budget=999 to verify land
reachability before selecting attack targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:23:29 -07:00
Natalie
53e01682e0 fix(auto-play): lock attack target, break movement deadlocks
- Lock onto one enemy target instead of switching every turn
- When stuck (no closer hex), try any valid move to break deadlock
- Verify locked target still exists before continuing march

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:17:10 -07:00
Natalie
51e163983f feat(auto-play): attack adjacent enemies after moving, increase to 500 turns
Warriors now check for adjacent enemy units/cities after moving and
initiate combat via CombatResolver. Also increased max turns to 500
and added unit position logging during attack phase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:04:18 -07:00
Natalie
7de6b6fd65 fix(auto-play): attack with 1+ warriors after turn 30 (can't accumulate 4)
With 1 hammer/turn and 40 cost warriors, accumulating 4 warriors is impossible
since each gets killed within ~20 turns. Attack with any available warrior
after turn 30 to make progress toward domination.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:58:23 -07:00
Natalie
f4ce0babe3 fix(ai): look up production cost in _apply_set_production
The AI's set_production action set queue items without a cost field, causing
all production to complete instantly (cost defaults to 0, progress >= 0 is
always true). This made AI warriors spawn every turn while the human player
waited 40 turns per warrior.

Now looks up cost from DataLoader for both units and buildings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:53:08 -07:00
Natalie
1ac301ec53 debug: add production tracking per turn 2026-04-12 14:50:58 -07:00
Natalie
dd40a998df feat(auto-play): fortify warriors at city during build phase
Warriors now fortify at the city position (+2 def/turn, max +4) instead of
sitting idle. This should help them survive enemy attacks while building up
to the 4-unit threshold for the attack march.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:48:39 -07:00
Natalie
1feeaccaec feat(auto-play): build-then-attack strategy — accumulate 4 warriors before marching
- Early game: found city, build warriors, keep military at home for defense
- Only scout explores (other units garrison)
- Once 4+ warriors accumulated, march all toward nearest enemy city
- Should survive enemy attacks with numerical advantage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:43:44 -07:00
Natalie
241391ddb4 debug: simplify combat logging 2026-04-12 14:41:25 -07:00
Natalie
4aefa304a2 debug: add combat result logging to auto_play 2026-04-12 14:38:54 -07:00
Natalie
040f53b09b fix: use EnvConfig.get_var not get_string for AUTO_PLAY_DIR 2026-04-12 14:33:50 -07:00
Natalie
2ea8da2479 fix(auto-play): use .visible instead of is_visible_in_tree for CanvasLayer nodes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:32:53 -07:00
Natalie
3823b6510b feat(auto-play): switch to autoload mode — fixes all autoload resolution errors
The -s SceneTree mode caused scripts to compile before autoloads were
registered, breaking any file referencing autoloads by name. Now auto_play
runs as a regular autoload that activates only when AUTO_PLAY=true env var
is set. All GameState, DataLoader, EventBus, EnvConfig references work
because autoloads are fully initialized before _ready() runs.

Also includes tile.gd lazy accessor fixes for DataLoader and EnvConfig.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:31:31 -07:00
Natalie
e3c7bd9832 fix(tile): also replace EnvConfig autoload with lazy accessor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:28:44 -07:00
Natalie
39216a1649 fix(tile): replace bare DataLoader autoload with lazy scene tree accessor
tile.gd referenced DataLoader by autoload name, which fails during initial
script compilation before autoloads are registered. This cascaded to break
game_map.gd, pathfinder.gd, and prevented tile creation during map generation.

Replace with static _data_loader() that resolves via Engine.get_main_loop().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:27:24 -07:00
Natalie
9d6d1e1da3 debug: log tiles count at frame 10 2026-04-12 14:24:46 -07:00
Natalie
1f6263c819 fix(auto-play): call _fix_start_positions at frame 10 when map tiles are loaded
The game_map.tiles dictionary is empty in _play_turn on the first frame
but populated by frame 10 when the world_map scene has fully initialized.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:24:02 -07:00
Natalie
0a51879f0f debug: early print in _fix_start_positions 2026-04-12 14:22:33 -07:00
Natalie
49e9a8caf1 fix(auto-play): use biome_id instead of get_terrain_flags for land tile detection
get_terrain_flags() calls DataLoader which fails in -s script context
due to class_name resolution order.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:21:54 -07:00