#!/usr/bin/python
# Author: Theodore Zacharia
# V0.1: 24/04/2026 - Based on buzzwords but for art
#
# This script uses concepts to make a sort of sensible art prompt
# you can test this as follows:
#   python -c 'import artprompt ; print artprompt.artprompt(2, 3)' 
# or for python 3 and above
#   python -c 'import artprompt ; print (artprompt.artprompt(2, 3))' 
#     where 2 is relative length of block and 3 is number of blocks (paragraphs)
# or running as a main script
#   python artprompt.py 2 3

import random
import sys

# SET 1: Visual Modifiers
compositions = [
    'A wide angle shot of', 'A close-up portrait of', 'A birds eye view of', 
    'A cinematic low-angle shot of', 'A macro detail of', 'A panoramic view of',
    'A symmetrical composition of', 'A double exposure of', 'A bokeh photograph of',
    'A low shutter speed photograph of', 'A silhouette photograph of', 'A worms eye view of',
    'A dutch angle of', 'A long exposure photograph of', 'An isometric view of', 'A fisheye lens view of',
    'A telephoto shot of', 'A wide aperture shot of', 'A compressed perspective shot of',
    'A forced perspective shot of', 'An aerial drone shot of', 'A surveillance camera view of',
    'A rule-of-thirds composition of', 'A centered composition of', 'A leading lines composition of',
    'A frame-within-a-frame of', 'A negative space composition of', 'A minimalist composition of',
    'A layered depth composition of', 'A shallow depth-of-field composition of', 'A deep focus composition of',
    'A foreground-background contrast of', 'A cross-section illustration of', 'A cut-away technical drawing of'
];

# see https://zapier.com/blog/ai-art-styles/ for various styles
subjects = [
    # --- Sci-Fi & Cyberpunk ---
    'an abandoned space station', 'a neon-drenched tea house', 'a rusted skyscraper garden', 
    'a cyborg geisha with porcelain skin', 'a retro-futuristic monorail', 'a holographic memory projector',
    'a sprawling megacity at night', 'a sentient AI core pulse',
    'a Star Wars Star Destroyer', 'a Star Wars X-Wing',
    'a Star Trek starship', 'a Star Trek transporter',
    'a cyberpunk city', 'an ancient forest', 'a cosmic nebula', 'a steampunk airship', 
    'a mystical samurai', 'a futuristic laboratory', 'an underwater kingdom', 'a majestic griffin',
    'a sneeky spy', 'a beautiful woman', 'a wicked witch', 'an evil wizard',
    'floating islands', 'inverted mountains', 'dreamlike architectures', 'a city skyline',
    'cybernetic hackers', 'medieval knights', 'steampunk explorers', 'otherworldly alien diplomats',

    # --- Fantasy & Mythical ---
    'a crystalline dragon', 'a floating marble island', 'an emerald-robed sorceress',
    'a knight in translucent glass armor', 'a phoenix rising from blue flames', 
    'an ancient stone giant sleeping under a mountain', 'a golden fleece draped over an altar',
    'elves', 'dragons', 'centaurs',

    # --- Steampunk & Victorian ---
    'a Victorian clockwork owl', 'a steam-powered deep sea diver', 'a brass-plated telescope',
    'an alchemist\'s messy workshop', 'a grand library with flying books', 'a luxury airship lounge',

    # --- Nature & Surrealism ---
    'a nomadic desert traveller', 'a bioluminescent mushroom forest', 'a waterfall made of liquid silver',
    'a tree with crystalline leaves', 'a desert oasis inside a giant bubble', 'a field of floating lotus flowers',
    'desert canyon at twilight', 'ancient redwood forest', 'stormy coastline', 'celestial astrophotography',

    # --- Dark & Mysterious ---
    'a ghostly shipwreck', 'a masked Venetian plague doctor', 'a mirror reflecting a different world',
    'a gothic cathedral carved from obsidian', 'a forgotten throne in a frozen hall', 'a shadow figure in a rainy alley',
    'futuristic eco-city', 'rainy European cobblestone street', 'minimalist Japanese tea house', 'brutalist concrete structures',

    # --- General Nature ---
    'lions', 'tigers', 'bears', 'monkeys', 'dogs', 'cats', 'elephants', 'crocodiles', 'pandas', 'giant pandas', 'penguins',
    'sharks', 'dolphins', 'birds', 'fish', 'horses', 'chickens', 'a lone wolf', 'wolves', 'cows', 'sheep', 'rabbits',
    'forest animals', 'jungle animals', 'tundra animals', 'gorillas', 't-rex', 'an owl', 'bees',
    'trees', 'a forest', 'a rainforest', 'a valley', 'a mountain range', 'a cliff', 'a planet', 'a waterfall', 'a river',
    'flowers', 'a coral reef', 'a honeycomb', 'ant colony',

    # --- General Objects ---
    'a car', 'an airplane', 'a fighter plane', 'a battleship', 'a ship', 'a sail ship', 'a train', 'a city', 'a bus', 'a lorry',
    'an 1800s battleship', 'an army regiment', 'an 1800s army regiment', 'an 1800s cavalry regiment',
    'buildings', 'transport', 'a computer', 'a laptop', 'a mobile phone', 'a desk', 'a chair'
]


# The "Mood" array - this changes the emotional "filter" of the image
moods = [
    'haunting and melancholic', 'epic and cinematic', 'whimsical and playful', 
    'dark and foreboding', 'serene and tranquil', 'chaotic and energetic', 'dystopian',
    'nostalgic and warm', 'sterile and cold', 'ethereal and dreamlike',
    'with golden hour light', 'dramatic rim lighting', 'soft moonlight', 'neon glow',
    'volumetric fog', 'harsh sunlight', 'bioluminescent highlights', 'ethereal glow',
    'neon lighting', 'volumetric lighting',
    'high-key lighting', 'low-key lighting', 'backlit composition', 'rim-lit portrait',
    'soft diffused light', 'harsh directional light shot', 'golden hour', 'blue hour',
    'chiaroscuro lighting'
]

environments = [
    'inside a swirling vortex', 'at the edge of a black hole', 'in a lush tropical jungle', 
    'within a gothic cathedral', 'submerged under a turquoise sea', 'floating in a dreamscape',
    'during a heavy thunderstorm', 'in a silent, snowy mountain pass', 'in a busy city', 'in a vast tundra', 'in a dry desert',
    'in a dense jungle', 'in a dense forest', 'in a dense forest with glowing plants and insects',
    'in a small town', 'in a large city', 'in a vast arctic ice covered land',
    'inside a collapsing star nursery', 'on a windswept alien plateau', 'within an ancient underground cavern',
    'at the bottom of a bioluminescent ocean trench', 'inside a forgotten stone ruin', 'on a floating sky island',
    'amid a glowing crystal valley', 'in a mist-filled rainforest canopy', 'inside a ruined futuristic megacity',
    'on the edge of a volcanic caldera', 'beneath a blood-red sky', 'in a frozen boreal forest', 'across a rolling grassland at dawn',
    'in a rain-soaked neon-lit city street', 'inside a vast abandoned factory', 'in a quiet lakeside village', 'on a storm-battered coastline',
    'inside a sunken ancient temple', 'in a shadowy mountain fortress', 'within a sprawling underground city', 'in a glowing mushroom forest',
    'inside a shifting sandstorm', 'on an endless salt flat', 'within a massive space station hangar','in a post-apocalyptic wasteland',
    'inside a dense fog-covered swamp', 'on a frozen alien moon', 'in a vast subterranean ice cave','inside a sacred mountain monastery',
    'at the center of a cosmic nebula'
]

aesthetics = [
    'cinematic', 'realistic modern', 'cyberpunk 2077 aesthetic', 'solarpunk dream', 'dark fantasy realism', 
    'retro-futurism', 'surrealism', 'bioluminescent wonder', 'grimdark atmosphere', 'macro photography',
    'ethereal minimalism', 'cyberpunk', 'steampunk', 'street photography', 'studio portrait', 'neo-noir style',
    'golden hour cinematic lighting', 'dark thriller style', 'historical film look', 'old Hollywood glamour',
    'space opera style', 'dystopian future', 'utopian future', 'digital hologram style',
    'renaissance', 'baroque', 'impressionist', 'expressionist', 'surrealist', 'Art Nouveau', 'medieval',
    'classical', 'romanticism', 'fresco', 'vaporwave', 'K-pop', 'Anime', 'Cartoon',
    'abstract illustration',
    'freeze-frame', 'motion blur', 'time-lapse', 'stroboscopic multiple-exposure', 'panning shot'
]

artists = [
    'Salvador Dali', 'Hayao Miyazaki', 'Wes Anderson',
    'H.R. Giger', 'Claude Monet', 'Moebius', 'Annie Leibovitz', 'Van Gogh',
    'Leonardo da Vinci', 'Michelangelo', 'Rembrandt', 'Pablo Picasso', 'Edvard Munch',
    'Frida Kahlo', 'Andy Warhol', 'Jackson Pollock', 'Henri Matisse', 'Thomas Kinkade',
    'Tony Sart', 'Anato Finnstark', 'Randy Vargas', 'Diego Gisbert Llorens', 'Johan Grenier', 'Bayard Wu', 'Marc Simonetti',
    'Frank Frazetta', 'Boris Vallejo', 'Julie Bell', 'Gerald Brom', 'Michael Whelan', 'Keith Parkinson', 'Gustavo Cabral', 'Dariusz Zawadzki'
]

mediums = [
  'matte painting', 'heavy impasto oil on canvas', 'charcoal on parchment', 
  '35mm film grain', 'unreal engine 5 render', 'watercolor wash', 'watercolor painting',
  'intricate papercut art', 'cyanotype print', 'ink illustration', 'gouache painting', 'fantasy illustration',
  'digital art', 'photorealistic', 'pencil sketch', 'pastel drawing', 'hand-painted illustration',
  'vaporwave aesthetic', 'oil painting', '3D render', 'studio Ghibli', 'childrens book illustration',
  'cinematic film still', 'baroque masterpiece', 'low poly',
  'minimalist vector illustration', 'modern infographic style', 'flat UI illustration', 'poster design style',
  'corporate illustration', 'line art illustration', 'geometric illustration', 'icon-style illustration',
  'isometric 3D illustration', 'realistic 3D render', 'low-poly 3D style', 'diorama scene', 'game art style',
  'clay-style 3D render', 'Instant polaroid photo', '1970s film photography', '1980s retro synthwave', 'stencil',
  'papercraft', 'marker illustration'
]

details = [
    'hyper-detailed', 'intricate textures', '8k resolution', 'masterpiece', 
    'trending on ArtStation', 'sharp focus', 'surreal atmosphere', 'highly symmetrical'
]

# do in StableDiffusion formatting
mediums_sd = [
  # Paper / craft variations
  '(intricate papercraft layers:1.5)', '(kirigami style composition:1.5)', '(quilled paper illustration:1.4)',
  '(hand-cut collage aesthetic:1.5)', '(layered cardstock diorama:1.6)', '(delicate paper filigree:1.4)', '(origami-inspired geometry:1.3)',

  # Painterly / traditional
  '(oil painting with rich impasto:1.4)', '(watercolor wash, soft edges:1.5)', '(gouache illustration, matte finish:1.4)',
  '(ink and wash drawing:1.5)', '(charcoal sketch, dramatic shading:1.3)', '(pastel painting, textured strokes:1.4)',

  # Digital / modern
  '(ultra-detailed digital painting:1.5)', '(3D render, octane lighting:1.4)', '(isometric illustration, clean vector:1.5)',
  '(low poly 3D art:1.3)', '(pixel art, 16-bit style:1.2)', '(cyberpunk neon glow aesthetic:1.4)',

  # Graphic / stylized
  '(flat vector illustration, bold colors:1.5)', '(minimalist line art:1.3)', '(comic book inking, halftone shading:1.5)',
  '(art nouveau ornamental style:1.4)', '(bauhaus geometric design:1.3)', '(psychedelic poster art:1.5)',

  # Realism / cinematic
  '(photorealistic, shallow depth of field:1.5)', '(cinematic lighting, volumetric fog:1.4)', '(macro photography detail:1.5)',
  '(studio portrait lighting:1.3)', '(hyperrealism, 8k detail:1.6)',

  # Fantasy / niche aesthetics
  '(dark fantasy illustration:1.5)', '(steampunk mechanical detail:1.4)', '(bioluminescent alien aesthetic:1.5)',
  '(surreal dreamlike composition:1.5)', '(ethereal glow, soft bloom lighting:1.4)'

]

def getNegativePrompt(aNegativePromptLength):
    
    negativeText = "";

    if (aNegativePromptLength == 1):
        negativeText = " --no blur, distorted, low quality, grainy, text, watermark";
    elif (aNegativePromptLength == 2):
        negativeText = " -- no duplicate character, Deformed, blurry, bad anatomy, disfigured, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long neck, long body, mutated hands and fingers, out of frame";
    elif (aNegativePromptLength == 3):
        negativeText = " -- no bad anatomy, mutated limbs, extra/missing hands/fingers/feet, fused/cloned/duplicate faces, asymmetrical features, distorted proportions, disconnected limbs, amputations, unrealistic skin texture, over/under exposure, oversaturated/desaturated colors, harsh lighting, JPEG artifacts, texture bleed, floating objects, watermark, out of frame elements, bad writing, missing words, mispelt words, extra words";

    return negativeText;


def artprompt(aMediumOption, aNegativePromptLength):

     # we can produce a reproducabile sequence by having a know start state
     random.seed()

     statement = ""

     statement = random.choice(compositions)
     statement = statement + " " + random.choice(subjects)
     statement = statement + ", " + random.choice(moods)
     statement = statement + ", " + random.choice(environments)
     statement = statement + ", " + random.choice(aesthetics)
     if aMediumOption == 1:
          statement = statement + ", " + random.choice(mediums_sd)
     else:
          statement = statement + ", " + random.choice(mediums) + " style "
     statement = statement + ", " + random.choice(artists)
     statement = statement + ", " + random.choice(details)

     statement = statement + getNegativePrompt(aNegativePromptLength)
     return statement

def main():
     if len(sys.argv) < 2:
        print("Usage: artprompt.py <medium_arg> [<neg_prompt_length>]")
        print("Example: artprompt.py 0")
        print("Example: artprompt.py 0 3")
        print("Example: artprompt.py 1")
        sys.exit(1)

     medarg = int(sys.argv[1])

     if len(sys.argv) > 2:
          negarg = int(sys.argv[2])
     else:
          negarg = 0

     print(artprompt(medarg, negarg))

if __name__ == "__main__":
    main()