```python
import bpy, math, random
from mathutils import Vector

# ============================================================
# Abandoned village reclaimed by nature
# ============================================================

random.seed(18)

# Clear scene
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
for datablocks in (bpy.data.meshes, bpy.data.curves, bpy.data.materials, bpy.data.cameras, bpy.data.lights):
    pass

# ---------- Materials ----------
def mat(name, color, rough=0.8, metallic=0.0):
    m = bpy.data.materials.new(name)
    m.diffuse_color = (*color, 1)
    m.use_nodes = True
    bs = m.node_tree.nodes.get("Principled BSDF")
    bs.inputs["Base Color"].default_value = (*color, 1)
    bs.inputs["Roughness"].default_value = rough
    bs.inputs["Metallic"].default_value = metallic
    return m

wall_mats = [
    mat("Faded ochre plaster", (0.29, 0.25, 0.17), .98),
    mat("Pale cracked limewash", (0.40, 0.39, 0.29), .98),
    mat("Damp gray plaster", (0.25, 0.28, 0.25), .95),
]
wood = mat("Blackened rotten timber", (0.10, 0.075, 0.045), .98)
wood_light = mat("Sun bleached wood", (0.28, 0.22, 0.13), .95)
roof = mat("Rust and oxidized iron", (0.24, 0.09, 0.035), .82, .48)
roof_dark = mat("Deep rust seams", (0.12, 0.045, 0.018), .9, .35)
glass = mat("Empty black windows", (0.012, 0.018, 0.015), .92)
glass_blue = mat("Broken dusty glass", (0.09, 0.16, 0.15), .4, .05)
moss = mat("Thick moss", (0.08, 0.22, 0.075), 1)
moss_light = mat("Fresh green moss", (0.18, 0.38, 0.10), 1)
grass = mat("Wild grass", (0.12, 0.29, 0.08), .96)
grass_light = mat("Sunlit grass", (0.29, 0.46, 0.10), .92)
vine_mat = mat("Climbing ivy stems", (0.055, 0.16, 0.035), .95)
leaf_mat = mat("Ivy leaves", (0.10, 0.31, 0.055), .9)
leaf_dark = mat("Dark ivy leaves", (0.035, 0.14, 0.025), .95)
trunk_mat = mat("Old tree bark", (0.16, 0.09, 0.045), 1)
stone = mat("Mossy fallen stone", (0.20, 0.22, 0.17), 1)
path_mat = mat("Forgotten muddy path", (0.21, 0.16, 0.10), 1)
flower = mat("Small violet flowers", (0.28, 0.10, 0.36), .8)

# ---------- Helpers ----------
def cube(name, loc, scale, material, bevel=0.0, rot=(0,0,0)):
    bpy.ops.mesh.primitive_cube_add(location=loc, rotation=rot)
    o = bpy.context.object
    o.name = name
    o.dimensions = scale
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    if material: o.data.materials.append(material)
    if bevel:
        mod = o.modifiers.new("Soft eroded edges", "BEVEL")
        mod.width = bevel
        mod.segments = 2
    return o

def cyl(name, loc, radius, depth, material, vertices=8, rot=(0,0,0)):
    bpy.ops.mesh.primitive_cylinder_add(vertices=vertices, radius=radius, depth=depth, location=loc, rotation=rot)
    o = bpy.context.object
    o.name = name
    if material: o.data.materials.append(material)
    return o

def ico(name, loc, scale, material, subdiv=1):
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdiv, radius=1, location=loc)
    o = bpy.context.object
    o.name = name
    o.scale = scale
    if material: o.data.materials.append(material)
    return o

def curve_obj(name, points, bevel, material):
    cu = bpy.data.curves.new(name, "CURVE")
    cu.dimensions = "3D"
    cu.resolution_u = 2
    cu.bevel_depth = bevel
    cu.bevel_resolution = 2
    sp = cu.splines.new("BEZIER")
    sp.bezier_points.add(len(points)-1)
    for bp, p in zip(sp.bezier_points, points):
        bp.co = p
        bp.handle_left_type = "AUTO"
        bp.handle_right_type = "AUTO"
    ob = bpy.data.objects.new(name, cu)
    bpy.context.collection.objects.link(ob)
    ob.data.materials.append(material)
    return ob

def leaf(loc, scale=(.16,.08,.23), material=leaf_mat, rot=(0,0,0)):
    o = ico("Ivy leaf", loc, scale, material, 1)
    o.rotation_euler = rot
    return o

def look_at(obj, target):
    direction = Vector(target) - obj.location
    obj.rotation_euler = direction.to_track_quat('-Z','Y').to_euler()

# ---------- Ground ----------
cube("Earth floor", (0, 2, -0.38), (32, 29, .65), path_mat, .15)
# irregular muddy path
for i in range(18):
    x = -5.5 + i * .55 + random.uniform(-.25,.25)
    y = -8 + i*.55 + random.uniform(-.35,.35)
    s = random.uniform(.5, 1.2)
    ico("Path stone", (x,y,-.02), (s, s*.55, .12), stone, 1)

# ---------- House construction ----------
def roof_panel(x, y, z, sx, sy, angle):
    p = cube("Bent rusted roof sheet", (x,y,z), (sx,sy,.22), roof, .04, (angle,0,0))
    # corrugated ribs
    sign = 1 if angle > 0 else -1
    for j in range(8):
        local_y = -sy/2 + .25 + j*.38
        # approximate sloping positions
        yy = y + local_y * math.cos(angle)
        zz = z + local_y * math.sin(angle)
        cyl("Raised rust corrugation", (x,yy,zz+.13), .055, sx+.12, roof_dark, 8, (0,math.pi/2,0))
    return p

def window_front(x, y, z, w=1.25, h=1.55, boarded=False):
    cube("Void behind broken window", (x,y-.04,z), (w,h,.08), glass)
    # rough timber frame
    for dx in (-w/2, w/2):
        cube("Rotten window jamb", (x+dx,y-.11,z), (.13,.16,h+.18), wood_light, .025)
    for dz in (-h/2, h/2):
        cube("Rotten window lintel", (x,y-.11,z+dz), (w+.15,.16,.13), wood_light, .025)
    if not boarded:
        cube("Broken glass remnant", (x-.28,y-.145,z+.18), (.10,.025,.55), glass_blue, 0, (0,.22,-.15))
        cube("Broken glass shard", (x+.32,y-.15,z-.25), (.08,.025,.34), glass_blue, 0, (0,-.35,.2))
    else:
        for k in range(2):
            cube("Boarded window plank", (x+random.uniform(-.1,.1),y-.18,z+random.uniform(-.3,.3)),
                 (w*.95,.10,.16), wood, .02, (0,random.uniform(-.15,.15),random.uniform(-.3,.3)))

def house(x, y, sx, sy, h, style=0):
    wall = wall_mats[style % len(wall_mats)]
    # main block
    cube("Abandoned house walls", (x,y,h/2), (sx,sy,h), wall, .10)
    # exposed dark timber lines
    for dx in (-sx*.42, sx*.42):
        cube("Exposed corner timber", (x+dx,y-.05,h/2), (.18,sy+.1,h+.12), wood, .035)
    for zz in (1.05, 2.15):
        cube("Sagging timber beam", (x,y-sy/2-.035,zz), (sx+.1,.15,.16), wood, .025,
             (0, random.uniform(-.02,.02), random.uniform(-.03,.03)))
    # roof
    ridge_z = h + 1.55
    roof_panel(x, y-sy*.24, h+.75, sx+1.0, sy*.72, math.radians(-34))
    roof_panel(x, y+sy*.24, h+.75, sx+1.0, sy*.72, math.radians(34))
    # ridge
    cube("Rusted roof ridge", (x,y,ridge_z), (sx+1.12,.28,.22), roof_dark, .04)
    # front windows
    window_front(x-sx*.23, y-sy/2-.06, h*.53, sx*.22, h*.36, style==2)
    window_front(x+sx*.25, y-sy/2-.065, h*.53, sx*.20, h*.34, False)
    # door, partly collapsed
    cube("Doorway darkness", (x, y-sy/2-.07, h*.34), (sx*.22,.08,h*.56), glass)
    cube("Hanging crooked door", (x+.06, y-sy/2-.13, h*.35), (sx*.19,.12,h*.55), wood_light, .025,
         (0, .03, -.08))
    # plaster scars
    for i in range(8):
        px=x+random.uniform(-sx*.42,sx*.42)
        pz=random.uniform(.35,h-.25)
        cube("Flaked plaster", (px,y-sy/2-.10,pz),
             (random.uniform(.18,.55),.035,random.uniform(.08,.3)), wall_mats[(style+1)%3], .02,
             (0,random.uniform(-.2,.2),random.uniform(-.2,.2)))
    # moss along roof edges
    for side in (-1,1):
        for i in range(7):
            xx=x-sx*.42+i*sx*.14
            yy=y+side*sy*.48
            zz=h+.82
            ico("Roof moss", (xx,yy,zz+random.uniform(-.05,.15)),
                (random.uniform(.25,.5),.16,random.uniform(.08,.2)), moss, 1)
    return (x,y,h,sx,sy)

houses = [
    house(-5.2, 2.0, 6.2, 4.7, 4.0, 0),
    house(2.1, 3.1, 6.8, 5.1, 4.5, 1),
    house(7.0, 7.0, 5.2, 4.2, 3.7, 2),
]

# ---------- Vines and ivy ----------
def vine_on_front(x, y, z0, height, lean=0):
    pts=[]
    for j in range(6):
        t=j/5
        pts.append((x + lean*t + math.sin(t*7)*.10, y, z0 + height*t))
    curve_obj("Climbing vine", pts, .045, vine_mat)
    for j in range(2,6):
        t=j/5
        px=x+lean*t+math.sin(t*7)*.10
        pz=z0+height*t
        for side in (-1,1):
            leaf((px+side*.13,p y if False else y-.05,pz+random.uniform(-.08,.08)),
                 (random.uniform(.12,.22),.06,random.uniform(.17,.28)), leaf_mat if j%2 else leaf_dark,
                 (random.uniform(-.5,.5),random.uniform(-.5,.5),side*random.uniform(.2,1.2)))
# avoid typo through explicit vine implementation
def vine_front(x,y,z0,height,lean=0):
    pts=[]
    for j in range(7):
        t=j/6
        pts.append((x+lean*t+math.sin(t*8)*.09, y, z0+height*t))
    curve_obj("Ivy tendril",pts,.045,vine_mat)
    for j in range(1,7):
        t=j/6
        px=x+lean*t+math.sin(t*8)*.09
        pz=z0+height*t
        side=-1 if j%2 else 1
        leaf((px+side*.15,y-.06,pz),(.18,.06,.26), leaf_mat if j%3 else leaf_dark,
             (random.uniform(-.4,.4),random.uniform(-.4,.4),random.uniform(-1,1)))

for x,y,h,sx,sy in houses:
    for k in range(3):
        vine_front(x-sx*.34+k*sx*.28, y-sy/2-.14, .1, h*.9+random.uniform(.2,1.0), random.uniform(-.45,.45))
    # vines spilling over roof edge
    for k in range(5):
        xx=x-sx*.42+k*sx*.2
        curve_obj("Roof creeping vine",
                  [(xx,y-sy*.52,h+.88),(xx+random.uniform(-.2,.2),y-sy*.60,h+.55),
                   (xx+random.uniform(-.3,.3),y-sy*.63,h+.18)], .035, vine_mat)

# ---------- Wild grass ----------
for i in range(170):
    x=random.uniform(-14,14)
    y=random.uniform(-9,14)
    # keep some foreground dense
    z=.05
    height=random.uniform(.25,.9)
    ang=random.uniform(-.35,.35)
    cyl("Wild grass blade", (x,y,z+height/2), random.uniform(.025,.06), height,
        grass if i%4 else grass_light, 5, (ang,random.uniform(-.2,.2),random.uniform(0,math.pi)))
# grass clumps around house bases
for x,y,h,sx,sy in houses:
    for i in range(24):
        px=x+random.uniform(-sx*.6,sx*.6)
        py=y+random.uniform(-sy*.62,sy*.62)
        for q in range(3):
            height=random.uniform(.35,1.1)
            cyl("Tall grass cluster",(px+random.uniform(-.12,.12),py,.05+height/2),
                .035,height,grass_light if q==0 else grass,5,
                (random.uniform(-.4,.4),random.uniform(-.25,.25),random.uniform(0,6.2)))

# ---------- Trees and distant shrubs ----------
def tree(x,y,z=0,scale=1):
    cyl("Twisted tree trunk",(x,y,2.2*scale+z),.28*scale,4.4*scale,trunk_mat,8,
        (random.uniform(-.12,.12),random.uniform(-.12,.12),random.uniform(-.2,.2)))
    for q in range(4):
        ang=q*1.55
        curve_obj("Bare crooked branch",
                  [(x,y,3.5*scale+z),(x+math.cos(ang)*1.0*scale,y+math.sin(ang)*.6*scale,4.3*scale+z),
                   (x+math.cos(ang)*1.7*scale,y+math.sin(ang)*1.0*scale,4.5*scale+z)],
                  .11*scale,trunk_mat)
    for q in range(9):
        a=random.random()*6.28
        r=random.uniform(.5,1.5)*scale
        ico("Wild tree foliage",(x+math.cos(a)*r,y+math.sin(a)*r,4.2*scale+z+random.uniform(-.4,.8)),
            (random.uniform(.6,1.15)*scale,random.uniform(.45,.9)*scale,random.uniform(.55,1.1)*scale),
            leaf_dark if q%3 else moss,1)

tree(-12,8,0,1.25)
tree(12,10,0,1.45)
tree(-11,-1,0,.85)
tree(11,1,0,1.0)

# shrubs and mossy stones
for i in range(45):
    x=random.uniform(-14,14); y=random.uniform(-8,13)
    if random.random()<.65:
        ico("Overgrown shrub",(x,y,random.uniform(.15,.5)),
            (random.uniform(.3,.8),random.uniform(.3,.7),random.uniform(.3,.8)), moss,1)
    else:
        ico("Mossy rubble",(x,y,.15),(random.uniform(.25,.7),random.uniform(.2,.5),random.uniform(.15,.35)),stone,1)

# small flowers scattered
for i in range(20):
    x=random.uniform(-10,10); y=random.uniform(-7,11)
    cyl("Flower stem",(x,y,.25),.012,.45,grass,5)
    ico("Purple wildflower",(x,y,.49),(.11,.11,.06),flower,1)

# ---------- Lighting / camera ----------
world=bpy.context.scene.world
world.use_nodes=True
world.node_tree.nodes["Background"].inputs["Color"].default_value=(0.025,0.045,0.05,1)
world.node_tree.nodes["Background"].inputs["Strength"].default_value=.28

bpy.ops.object.light_add(type='AREA', location=(-5,-8,16))
key=bpy.context.object
key.name="Cold overcast sunlight"
key.data.energy=1450
key.data.shape='DISK'
key.data.size=8
look_at(key,(0,3,2))

bpy.ops.object.light_add(type='AREA', location=(10,-2,8))
fill=bpy.context.object
fill.name="Muted forest fill"
fill.data.energy=700
fill.data.color=(.45,.58,.48)
fill.data.size=10
look_at(fill,(1,3,2))

bpy.ops.object.light_add(type='SUN', location=(0,0,12))
sun=bpy.context.object
sun.name="Low late afternoon sun"
sun.data.energy=1.6
sun.data.angle=math.radians(18)
sun.rotation_euler=(math.radians(25),math.radians(-20),math.radians(-30))

# Camera
bpy.ops.object.camera_add(location=(17,-22,13.5))
cam=bpy.context.object
cam.name="Presentation camera"
cam.data.lens=48
cam.data.sensor_width=36
look_at(cam,(-.2,2.7,2.9))
bpy.context.scene.camera=cam

# ---------- Render settings ----------
scene=bpy.context.scene
scene.render.engine='BLENDER_EEVEE_NEXT'
scene.render.resolution_x=1536
scene.render.resolution_y=1536
scene.render.resolution_percentage=70
scene.render.image_settings.file_format='PNG'
scene.render.film_transparent=False
scene.render.filepath="/tmp/abandoned_village.png"
scene.render.image_settings.color_mode='RGBA'
scene.view_settings.look='AgX - Medium High Contrast'
scene.render.resolution_percentage=100

# Ground mist-like translucent planes are avoided for GLB compatibility.
# Organize object selection state
bpy.ops.object.select_all(action='DESELECT')

# Save
bpy.ops.wm.save_as_mainfile(filepath="/tmp/abandoned_village.blend")
```