stepstead-backend/db/seed_enemies_forest.py
jts ea049b8ccd İlk commit: Stepstead backend (FastAPI)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:30:24 +03:00

166 lines
7.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Orman düşmanları — 12 çeşit hostile NPC (2026-07-08).
NPC sayfasının yazdığı `npcs` tablosuna eklenir (stance='hostile').
Yer = forest region'larına (map_tags kind='region' category='forest', O-1..O-10)
round-robin dağıtılır. İsim'e göre idempotent (varsa günceller, yoksa ekler).
Çalıştırma:
cd /opt/stepstead && ./venv/bin/python3 db/seed_enemies_forest.py
"""
import asyncio
import sys
sys.path.insert(0, "/opt/stepstead")
import asyncpg # noqa: E402
from config import settings # noqa: E402
def desc(hp, dmg, atk, dc, weak, drops, danger, lore):
"""Özellikleri okunur bir description bloğuna paketle."""
return (
f"{lore}\n\n"
f"⚔ Saldırı türü: {atk}\n"
f"❤ Can (HP): {hp}\n"
f"🗡 Hasar: {dmg}\n"
f"🎯 Savaş zorluğu (combat DC): {dc}\n"
f"💀 Tehlike: {danger}\n"
f"🩹 Zayıflık: {weak}\n"
f"🎁 Düşürdükleri: {drops}"
)
# (name, role, stance, description)
ENEMIES = [
("Mana Solucanı", "Büyülü Yaratık", "hostile",
desc(hp=18, dmg="4-8 (mana yakımı)", atk="Büyü — mana emer",
dc=13, weak="Fiziksel darbe, demir silah",
drops="Mana özü ×1-2, parlak salgı",
danger="Orta",
lore="Yeraltı mana damarlarında beslenen, ışıldayan segmentli bir solucan. "
"Yaklaşana enerjisini emer; öldürüldüğünde içindeki saf mana damlar.")),
("Aç Kurt", "Canavar", "hostile",
desc(hp=22, dmg="6-10 (ısırık)", atk="Yakın dövüş — sürü halinde",
dc=13, weak="Ateş, yüksek zemin",
drops="Kurt eti ×1-2, kurt derisi ×1",
danger="Orta",
lore="Kışın açlıktan gözü dönmüş orman kurdu. Tek başına ürkek ama "
"sürüye katılınca korkusuzca saldırır.")),
("Yaşlı Ağaç Adam", "Bitki Devi", "hostile",
desc(hp=55, dmg="12-18 (dal savurma)", atk="Yakın dövüş — ağır ve yavaş",
dc=16, weak="Ateş, balta (woodcutting)",
drops="Kadim odun ×2-3, canlı kök, meşe palamudu",
danger="Yüksek",
lore="Yüzyıllık bir meşenin uyanmış ruhu. Toprağı sarsan adımlarla yürür; "
"yavaştır ama tek darbesi kemik kırar. Ateşten ölesiye korkar.")),
("Dev Orman Faresi", "Haşere", "hostile",
desc(hp=8, dmg="2-4 (kemirme)", atk="Yakın dövüş — kalabalık",
dc=9, weak="Hemen her şey",
drops="Fare kuyruğu, paslı çöp, bazen 1-3 gold",
danger="Düşük",
lore="İnsan boyunun yarısı kadar, hastalık taşıyan bir kemirgen. Tek başına "
"zararsız ama erzak çuvalını bir gecede boşaltır.")),
("Zehirli Orman Örümceği", "Haşere", "hostile",
desc(hp=16, dmg="5-9 (zehirli ısırık)", atk="Yakın dövüş — zehir + ağ",
dc=14, weak="Ateş, alan silahları",
drops="Örümcek zehri ×1, ipek ×1-2",
danger="Orta",
lore="Karanlık kovuklara dev ağlar geren, avını zehirle felç eden bir örümcek. "
"ı hareketi yavaşlatır, ısırığı damarlarda yanar.")),
("Sarmaşık Cini", "Bitki Ruhu", "hostile",
desc(hp=24, dmg="6-11 (sarma + diken)", atk="Yakın dövüş — kavrayıp sıkar",
dc=14, weak="Ateş, kesici balta",
drops="Canlı sarmaşık ×2, diken tozu, çiçek özü",
danger="Orta",
lore="Küçük ama sinsi bir bitki ruhu. Yaprakların arasına gizlenir, "
"geçeni sarmaşıklarıyla sarıp dikenlerine çeker.")),
("Mantar Spor Yaratığı", "Sporlu Canavar", "hostile",
desc(hp=20, dmg="4-7 (spor bulutu)", atk="Alan — zehirli spor patlaması",
dc=13, weak="Ateş, uzak menzil",
drops="ıldayan mantar ×2, spor tozu, şifa mantarı",
danger="Orta",
lore="Yürüyen dev bir mantar kümesi. Vurulunca zehirli spor bulutu patlatır; "
"yakın dövüşte nefes almak tehlikelidir.")),
("Gölge Kurdu (Alfa)", "Canavar (Elit)", "hostile",
desc(hp=40, dmg="10-16 (gölge pençesi)", atk="Yakın dövüş — hızlı, görünmez sıçrar",
dc=17, weak="ık, gümüş silah",
drops="Gölge postu ×1, alfa dişi, gümüş ore ×1",
danger="Yüksek",
lore="Karanlık ormanın en yaşlı kurt sürüsünün lideri. Gölgelerde erir, "
"arkandan belirir. Işık tuttuğunda bir an donar — tek fırsatın odur.")),
("Orman Haydutu", "Goblin", "hostile",
desc(hp=26, dmg="7-12 (paslı hançer)", atk="Yakın dövüş — pusu + hırsızlık",
dc=14, weak="Cephesel saldırı, gürültü",
drops="Çalıntı kese (5-20 gold), paslı hançer, kuru erzak",
danger="Orta",
lore="Yol kenarında pusu kuran sinsi bir goblin. Önce keseni çalmaya çalışır, "
"başaramazsa hançerine sarılır.")),
("Kanlı Yarasa", "Uçan Haşere", "hostile",
desc(hp=12, dmg="3-6 (kan emme)", atk="Havadan — dalış + kan emer",
dc=11, weak="Ateş, geniş savurma",
drops="Yarasa kanadı ×1-2, kan kesesi",
danger="Düşük",
lore="Mağara ağızlarında ve yaşlı ağaç kovuklarında asılı duran kan emici. "
"Sürü halinde daldığında kanını damla damla çeker.")),
("Bataklık Sülüğü", "Asalak", "hostile",
desc(hp=14, dmg="3-7 (yapışıp emer)", atk="Yakın dövüş — yapışır, sürekli hasar",
dc=12, weak="Tuz, ateş",
drops="Sülük özü, iyileştirici salgı ×1",
danger="Düşük-Orta",
lore="Ormanın nemli bataklık kıyısında saklanan dev sülük. Bacağına yapışır, "
"koparana dek yavaşça kan emer. Salgısı ilginç şekilde şifalıdır.")),
("Lanetli Karga Sürüsü", "Uçan Sürü", "hostile",
desc(hp=30, dmg="5-9 (gaga yağmuru)", atk="Alan — sürü halinde gözlere dalış",
dc=15, weak="Alan silahları, ateş, ses",
drops="Kara tüy ×3, lanetli boncuk, bazen gümüş ore",
danger="Orta-Yüksek",
lore="Tek bir kötü ruhu paylaşan bir karga sürüsü. Ayrı ayrı zayıf ama "
"birlikte gökten kara bir bulut gibi iner, gözleri hedef alır.")),
]
async def main():
dsn = settings.DATABASE_URL.replace("+asyncpg", "")
c = await asyncpg.connect(dsn)
forests = [r["id"] for r in await c.fetch(
"SELECT id FROM map_tags WHERE kind='region' AND category='forest' ORDER BY id"
)]
if not forests:
print("UYARI: forest region bulunamadı, map_tag_id NULL bırakılıyor.")
added = updated = 0
for i, (name, role, stance, description) in enumerate(ENEMIES):
tag = forests[i % len(forests)] if forests else None
existing = await c.fetchval("SELECT id FROM npcs WHERE name=$1", name)
if existing:
await c.execute(
"UPDATE npcs SET role=$2, stance=$3, description=$4, map_tag_id=$5, "
"updated_at=now() WHERE id=$1",
existing, role, stance, description, tag)
updated += 1
else:
await c.execute(
"INSERT INTO npcs(name,role,stance,description,map_tag_id) "
"VALUES($1,$2,$3,$4,$5)",
name, role, stance, description, tag)
added += 1
total = await c.fetchval("SELECT count(*) FROM npcs WHERE stance='hostile'")
print(f"Eklendi: {added}, güncellendi: {updated}. Toplam hostile NPC: {total}")
await c.close()
asyncio.run(main())