All Posts

Most recent displayed first:

  • ChatGPT Story Time

    I’ve been facinated by ChatGPT, specifically using the GPT-4 model.

    One fun activity is to have ChatGPT generate short stories. Stories generated by GPT-3.5 are a little off base, but GPT-4 closes that gap.

    If you want to skip ahead to the generated stories, here they are:

    I suspect I could get even better stories if my prompt was better… I’ve been surprised how much intelligence is hidden away in GPT-4 that you don’t experience if your prompt strategy is naive.

    My first attempts at prompting were along the lines of “Write me a short story with a good twist ending”. These sorts of prompts do work, but it’s really asking a lot of the model.

    I’ve been evolving my prompt over time. My latest interation involves two steps. The first step is to generate outlines:

    Your task is to brainstorm horror stories with twist endings, by generating outlines in a specific format.

    Each outline should be broken into a Setup, Misdirection, Twist Ending, and Title.

    A good horror setup starts with corrupt characters who want to fulfill their immoral desires in short sighted ways. They are con artists, or manipulative, or jealous, or cheats, etc. If they have a profession, it should be something unique - not a typical profession for mystery stories (not a detective, not a psychic medium, etc). The setup should reflect modern times so readers can imagine themselves or someone they know in the story.

    Good misdirection means leading the reader into thinking the story will end one particular way. It should be the most obvious conclusion of the story. However, this is not the real ending of the story. When you write the misdirection, say specifically what readers will be led to believe the ending will be.

    The twist ending is the real ending, which should be shocking, and surprise the reader. It usually has some element of dark humor. There doesn't need to be a lesson to the story, it's more important that the ending is unpredictable. The twist will happen at the very last moments of the story, so it shouldn't require introducing new characters. If a character is needed for the twist, they should be part of the setup.

    Overall, the story should have elements of horror, with dark and twisted humor, involving corrupt characters, and a surprise twist ending. Do not directly use adjectives like "dark", "twisted", "terrible", etc - instead, describe the underlying idea. For example, do not say "Jack played a twisted game", but instead describe the actual rules of the game. Do not say "the drug has terrible side effects", instead describe the actual side effects, etc.

    Once I find an outline I like, I start a new session with the prompt:

    Your task is to write a short story based on the outline I provide.

    The outline contains a Setup, Misdirection, Twist Ending, and Title.

    It's important to understand that the misdirection is not the real ending of the story. Your task is to lead the reader into thinking that the misdirection will be the ending. However, right at the end of the story, you should reveal the twist ending. Do not reveal the twist earlier than three paragraphs from the end.

    The timing and reveal of the twist ending is very important. The story should be building towards the climax of the misdirection, but right when the climax happens, the twist should be revealed in a sudden and abrupt mannor.

    In order to save the twist ending for the very end, you might need to incorproate supporting elements earlier in the story, so that you don't need to describe those elements after the twist is revealed. For example, if the twist requires an earlier event to have happened, make that event be part of the setup or misdirection.

    Overall, the story should have elements of horror, with dark and twisted humor, involving corrupt characters, and the surprise twist ending. Do not break out of the story with statements like "the reader is led to believe" or "the story eventually concludes". Do not incorporate a lesson into the story. Do not directly use adjectives like "dark", "twisted", "terrible", etc - instead, describe the underlying idea. For example, do not say "Jack played a twisted game", but instead describe the actual rules of the game. Do not say "the drug has terrible side effects", instead describe the actual side effects, etc.

    Here is the outline:

    <paste chosen outline>

    By having ChatGPT create outlines first, it gives them the ability to foreshadow and plan ahead when it comes time to write the story.

    ChatGPT will generate outlines like this:

    Setup: A successful but morally bankrupt real estate developer acquires an ancient cemetery, planning to remove the graves and build a luxury housing complex on the land. He callously dismisses the pleas of the local community to preserve the historical site.

    Misdirection: Readers will be led to believe that the restless spirits of the cemetery will rise up and haunt the developer, eventually driving him mad.

    Twist Ending: As construction begins, workers unearth a hidden underground crypt containing the remains of a long-lost ancestor of the real estate developer. The crypt reveals a terrible family secret, which becomes public knowledge and leads to the developer's financial ruin and social ostracization. The cemetery remains untouched, serving as a grim reminder of the developer's downfall.

    Title: "The Unearthed Legacy"

    And on, and on, and on.

    Then I pick an outline I like, and have ChatGPT write the story. It’s been lots of fun!

    For your enjoyment, here are a currated collection of stories generated by ChatGPT as I’ve been playing with this process.

    The Unearthed Legacy

    For years, the town of Ashgrove had been trying to preserve the ancient cemetery that rested on the outskirts of the village. The cemetery held the remains of the town’s founding families, and its moss-covered tombstones were a testament to the community’s rich history. However, change was inevitable, and the once-quaint town was now under the shadow of development, led by the ruthless and avaricious real estate mogul, William Preston.

    Preston had acquired the land on which the cemetery stood and was determined to demolish it and erect a luxury housing complex in its place. The townsfolk had pleaded with him, citing the historical significance of the cemetery and the generations of memories it held. Preston had dismissed their concerns, remarking that progress was more important than sentiment.

    As the day approached for the construction to begin, whispers began to spread among the townspeople about the restless spirits that resided within the cemetery. Stories of vengeful ghosts, souls wronged in life, who wouldn’t hesitate to avenge themselves on those who disturbed their eternal rest. These tales soon reached Preston’s ears, but he laughed them off, confident in his own power and influence.

    The first day of construction was met with an eerie silence. The bulldozers and construction crew gathered at the cemetery gates, waiting for Preston to give the order. The townsfolk watched from a distance, fear and apprehension in their eyes. As Preston raised his hand to signal the beginning of the demolition, a strange fog rolled over the cemetery, casting an ominous pall over the proceedings.

    As the days went on, strange occurrences began to plague the construction site. Equipment would malfunction, workers would report strange sightings and eerie whispers in the night. Some workers even quit, claiming that the spirits of the dead were haunting them, seeking retribution for the desecration of their resting place. Preston, however, refused to give in to fear and pressed on with the project.

    As the construction crew dug deeper into the earth, they uncovered a hidden underground crypt, untouched by the passage of time. Intrigued, Preston ordered the crypt to be opened, brushing off the crew’s concerns about disturbing the resting place of the dead. As they lifted the heavy stone slab that sealed the crypt, an overwhelming stench of decay and death filled the air.

    Within the crypt lay the remains of a long-lost ancestor of William Preston, a man whose very existence had been erased from the family records. The walls of the crypt bore inscriptions that detailed the family’s dark and twisted history, filled with tales of treachery, murder, and unspeakable atrocities committed in the name of wealth and power. As the contents of the crypt were exposed, the town’s historians were called upon to authenticate the findings.

    The news of the terrible family secret spread like wildfire through the town, and soon the entire nation was abuzz with the story of the Preston family’s gruesome past. William Preston’s name became synonymous with the dark deeds of his ancestors, and his business ventures crumbled under the weight of public scrutiny and outrage.

    As the last of his fortune vanished, and his social standing shattered, William Preston was forced to abandon his plans for the luxury housing complex. The ancient cemetery remained untouched, a solemn reminder of the grim legacy that had been unearthed. In the end, it was not the vengeful spirits that had brought about Preston’s downfall, but the dark truth hidden within the earth that had waited for centuries to be revealed.

    Phantom Profits

    Laura Morrison, the CEO of a once-esteemed pharmaceutical company, slipped through the dimly lit hallways of her company’s research facility. Her heart raced as she unlocked the door to the restricted area. A drug, designed to induce vivid hallucinations and allow users to experience their deepest fantasies, was in the final stages of development. In her desperation to regain the fortune she had lost from the company’s recent downturn, Laura had devised a plan to steal the experimental drug and sell it on the black market.

    As she filled a small vial with the luminescent liquid, Laura was keenly aware of the potential consequences. The drug was unstable, with unpredictable effects on the human psyche. But her greed overshadowed her concerns. With trembling hands, she stashed the vial in her coat pocket and slipped back out of the facility.

    Over the next few weeks, Laura made a fortune selling the drug on the black market. The vivid hallucinations it produced were unmatched, and it quickly became the hottest commodity. Meanwhile, back at the office, whispers of the missing drug circulated among the employees. One employee in particular, a young man named Thomas, seemed to take a particular interest in the mysterious disappearance.

    Thomas was relentless in his pursuit of the truth. He spent long hours piecing together the puzzle, rummaging through security footage and company records. He began to suspect Laura and started gathering evidence against her. Unbeknownst to Laura, Thomas had been keeping tabs on her activities, tracking her movements outside the office and even managing to secure a sample of the stolen drug.

    As the days passed, Laura noticed Thomas paying closer attention to her. Their encounters became increasingly tense, and she couldn’t shake the feeling that he was closing in on her secret. In a moment of paranoia, Laura decided to confront Thomas, hoping to find a way to throw him off her trail.

    Before the confrontation, she retreated to her private office, her mind racing with possible scenarios. Her hands trembled as she poured herself a drink, her thoughts fixated on the potential end of her dark venture. The ice cubes clinked in her glass as she took a deep breath, bracing herself for what was to come.

    In the hallway outside Thomas’s office, Laura hesitated. Her heart pounded in her chest as she prepared to face him. As she reached for the door handle, a wave of disorientation washed over her. She blinked, and suddenly she was back in her own office, the drink still in her hand.

    Laura stared at her surroundings, confused and disoriented. She blinked again, and she was back outside Thomas’s office, hand on the door handle. The world spun around her, and she found herself trapped in a never-ending loop, bouncing between her office and the hallway. Panic began to rise in her chest as she realized the horrifying truth.

    All this time, she had been unknowingly taking the experimental drug herself. Her entire scheme, along with Thomas and his efforts to expose her, was just a vivid hallucination. As she grappled with this revelation, the line between reality and fantasy began to blur, and Laura was left to face the dark and twisted consequences of her own insatiable greed. The phantom profits she had so desperately sought now slipped through her fingers like smoke, leaving her trapped in a kaleidoscope of her own nightmares.

    The Surgeon’s Harvest

    Dr. Arnett was a brilliant and highly sought-after surgeon, known for his exceptional skills in the operating room. He enjoyed a lavish lifestyle, thanks to his successful practice. But Dr. Arnett had a dark secret. He had discovered a unique method of extracting organs from his patients without leaving a trace, which he then sold on the black market. These organs brought him a fortune, but his greed was insatiable.

    His latest patient was a young man named Ethan, who had come in for a routine appendectomy. Dr. Arnett quickly identified Ethan’s liver as a perfect candidate for his underground organ trafficking ring. He performed the surgery, skillfully removing both the appendix and the liver, and then stitched Ethan back up, leaving no sign of his criminal act.

    As Ethan recovered from his surgery, he began to feel increasingly unwell. Meanwhile, Detective Marlowe, a seasoned investigator, was growing suspicious of the inexplicable health decline of Dr. Arnett’s patients. He started to dig deeper, looking for connections between the cases, and noticed the odd absence of certain organs in a number of the victims.

    Detective Marlowe decided to confront Dr. Arnett, but before doing so, he carefully studied the surgeon’s unique technique, learning how he extracted organs without leaving any trace. As the investigation progressed, the story led the reader to believe that Dr. Arnett would eventually be caught by the police as they closed in on him.

    One night, Detective Marlowe showed up at Dr. Arnett’s luxurious home, confronting him about the missing organs. Dr. Arnett tried to deny the accusations, but Detective Marlowe knew better. They argued, and the confrontation escalated, with Dr. Arnett attempting to escape. However, Detective Marlowe managed to subdue him and brought him back to his own operating room.

    In a shocking twist, it was revealed that Detective Marlowe was, in fact, one of Dr. Arnett’s former patients. The detective had been living with only one kidney after the surgeon had stolen the other during a previous surgery. Driven by revenge, Detective Marlowe decided to give Dr. Arnett a taste of his own medicine.

    Strapping the terrified surgeon to the operating table, Detective Marlowe prepared his instruments, his eyes filled with a vengeful fire. He began the gruesome operation, skillfully removing Dr. Arnett’s organs one by one, mimicking the surgeon’s own method.

    As Dr. Arnett lay on the table, his life slowly slipping away, he realized the consequences of his actions. His greed and disregard for human life had finally caught up to him, and he was now at the mercy of one of his own victims. With his last breath, Dr. Arnett succumbed to the darkness, leaving behind a legacy of pain and corruption.

    Detective Marlowe stood over the lifeless body of the once-renowned surgeon, finally avenging his own suffering and the countless lives Dr. Arnett had destroyed. He knew that his actions had crossed a line, but for him, it was a twisted form of justice. The organ thief’s reign of terror was finally over, brought to a gruesome end by the very person he had least suspected.

    ...read more

  • Batman (NES) Pixel Art Study

    I’m trying to improve my pixel art skill, so I thought it would be fun to take a closer look at one of the most beautiful NES games ever made – Batman!

    I love the pixel art in Batman! Let’s dive in and bask in its glory. Feel free to ignore my commentary and just enjoy the art :-).

    ...read more

  • FABRIK Algorithm (2D)

    FABRIK stands for Forward-and-Backward Reaching Inverse Kinematics, and it’s a very simple, fast, and clever solution to the inverse kinematics problem.

    Let’s inspect this interesting algorithm in 2D.

    ...read more

  • This Isn't Normal

    “That’s just the way it is!”

    It amazes me how easily bad ideas fool humans.

    ...read more

  • Super Trump Run

    I’ve been depressed lately. I decided to make a game to make me laugh and vent some steam. Enjoy!

    ...read more

  • The Failure of Being Right

    Doesn’t it feel great to be right?

    ...read more

  • NaN-Boxing

    How do dynamicly typed languages allow any variable to hold any type? There are a few different techniques, but the one I use for sink is NaN-boxing.

    ...read more

  • Growing Through Pain

    Watching the children around me growing up, I am always amazed at the amount of pain they are forced to deal with. Illness, uncertainty, divorce, frustration, powerlessness, death…

    A child experiences such extreme amounts of pain on a daily basis.

    ...read more

  • Polygon Clipping (Part 2)

    My previous polygon clipping tutorial dove into the Greiner-Hormann clipping algorithm. Unfortunately, this algorithm fails at common cases… so let’s revist the problem and try again.

    The F. Martinez 2008 algorithm handles coincident edges (unlike Greiner-Hormann), but it still has some minor goofiness. Let’s solve this problem once and for all.

    ...read more

  • Polygon Clipping (Part 1)

    Polygon clipping is an interesting problem: how do you intersect, union, or diff two polygons?

    The Greiner-Hormann clipping algorithm is quite beautiful and intuitive. Let’s dissect it and take a look.

    ...read more

  • C Tricks

    I’ve been coding in C99 quite a lot lately. I wanted to write down some of the tricks I’ve been using.

    I don’t take credit for any of these ideas – I’ve either directly stolen these ideas from other coders, or rediscovered techniques that have probably been known for 40 years.

    I will continue updating this document as I stumble across more useful tricks.

    The code on this page is Public Domain, but this article is copyright according to the notice at the very bottom.

    ...read more

  • Tri-Color Garbage Collector

    Garbage collectors (GCs) feel like some sort of esoteric programming magic. What’s really funny is that a simple good-enough garbage collector is actually quite easy to write. The core functionality of a basic tri-color GC is only around 250 lines of C code.

    ...read more

  • You Are The Cook

    What a shame that so many people lead the same basic life.

    ...read more

  • Genetic Algorithms

    In my Ludum Dare 31 entry, Bunnies!, I used a very simple genetic algorithm to breed bunnies. It can seem like magic at first, but genetic algorithms are very simple at their core.

    ...read more

  • Ludum Dare 31 Live-Blog!

    Live-blogging my Ludum Dare 31 experience. Most recent entries are on top. I’ll plan to post about once an hour (while working). You’ll have to manually refresh the page to get updates. Follow and comment on twitter @velipso. All timestamps in EST.

    ...read more

  • Shunting Yard (Part 3)

    Let’s continue adding to our Shunting Yard code base.

    In Part 2, we created operator precedence. This allowed us to delay application of operators indefinitely, using a stack. Next, we’ll focus on adding parentheses, so that the end-user can manually override precedence.

    Series: Part 1, Part 2, Part 3, …

    ...read more

  • Odyssey (LD30) Postmortem

    Results are out for Ludum Dare 30, and my game Odyssey did pretty damn good!

    Rank (of 1493) Category Rating
    #13 Fun 4.11
    #24 Theme 4.16
    #34 Overall 4.00
    #60 Innovation 4.00
    #200 Mood 3.45
    #269 Audio 3.22
    #337 Humor 2.71
    #484 Graphics 3.19

    The #13 ranking in Fun just blows me away! My aggregate rating is 93.6% (+0.1% from last time).

    ...read more

  • Everyone's Ludum Dare 30 Results

    Like last time, I analyzed the Ludum Dare results.

    Click here to analyze the LD30 results!

    Alternatively, you can download the raw data here:

    ...read more

  • Shunting Yard (Part 2)

    Let’s continue building a general purpose Shunting Yard algorithm.

    We left off with bare-bones skeleton that implements a shunt to delay building of the abstract syntax tree (AST). Our skeleton left a lot to be desired. For this article, we’ll implement operator precedence.

    Please read Part 1 first, since the code here builds directly on the source from that article.

    Series: Part 1, Part 2, Part 3

    ...read more

  • Procedurally Generated Planet Textures

    For my Ludum Dare entry, I procedurally generate the textures for the planets. In the game, my math is a little off, and I didn’t have time to derive the correct formula – but now, with unlimited time, I can think a little more clearly :-).

    ...read more

  • Ludum Dare 30 Live-Blog!

    Live-blogging my Ludum Dare 30 experience. Most recent entries are on top. I’ll plan to post about once an hour (while working). You’ll have to manually refresh the page to get updates. Follow and comment on twitter @velipso. All timestamps in EST.

    ...read more

  • Everyone's Ludum Dare 29 Results

    I became slightly annoyed at the analysis and accessibility of the Ludum Dare 29 results. So I decided to write a program that would scrape all the pages and extract the necessary data.

    You can now download the LD29 results in a convenient CSV or JSON format, here:

    Or, for even more fun, I made a page that analyzes results:

    Have fun!

    ...read more

  • Shunting Yard (Part 1)

    The Shunting Yard Algorithm is, quite possibly, my favorite algorithm. It transforms a series of tokens into an abstract syntax tree, taking into account operator type, precedence, and parenthesis.

    Through the next series of articles, I want to build a general purpose expression parser using the algorithm. By the end, we’ll have an algorithm that can be easily extended to add many different types of operators… any arity (unary, binary, ternary, etc), prefix, infix, and postfix.

    Series: Part 1, Part 2, Part 3

    ...read more

  • Inner Demons (LD29) Postmortem

    Voting has officially ended for Ludum Dare 29. My entry was ranked as follows:

    Rank (of 1493) Category Rating Percent Improvement
    #63 Mood 3.88 95.8% +31.9%
    #70 Humor 3.64 95.3% +22.0%
    #101 Innovation 3.88 93.2% +26.5%
    #116 Overall 3.76 92.2% +23.3%
    #148 Fun 3.60 90.1% +10.9%
    #149 Audio 3.50 90.0% N/A
    #227 Theme 3.64 84.8% +52.3%
    #551 Graphics 3.17 63.1% -8.0%

    Average score: 88.1% (+23.0% improvement from previous entry)

    If you’re curious, you can play my game, Inner Demons! Let’s dive into the postmortem…

    ...read more

  • Ludum Dare 29 Live-Blog!

    Live-blogging my Ludum Dare 29 experience. Most recent entries are on top. I’ll plan to post about once an hour (while working). You’ll have to manually refresh the page to get updates. Follow and comment on twitter @velipso. All timestamps in EST.

    ...read more

  • Winter Olympics Game Jam

    I decided to challenge myself this weekend, with a faux-game-jam. I came up with a theme on Friday (Winter Olympics), and built Sled Drifter! over the course of the long weekend.

    ...read more

  • Diner Devil! (LD28) Postmortem

    Voting has officially ended for Ludum Dare 28. My entry was ranked as follows:

    Rank (of 1284) Category Rating Percent
    #267 Fun 3.22 79.2%
    #343 Humor 2.61 73.3%
    #371 Graphics 3.17 71.1%
    #399 Overall 3.13 68.9%
    #427 Innovation 3.00 66.7%
    #464 Mood 2.81 63.9%
    #867 Theme 2.14 32.5%

    Average score: 65.1%

    If you’re curious, you can play my game, Diner Devil! Let’s dive into the postmortem…

    ...read more

  • Two-Dimensional Bin Packing

    Two-dimensional bin packing turns out to be quite a pickle.

    I was introduced to the problem as a 13 year old. My Dad’s friend, Keith, noticed I was taking a knack to programming, and wanted to see if I could help him. Keith was (and still is) a carpenter.

    Keith wanted me to write a program where he could input a list of shapes, and the program would figure out the best way to cut a board of wood into those shapes, while minimizing scrap wood. Seems reasonable.

    My 13 year old mind quickly exploded… I couldn’t figure out one simple, obvious way to do it. Eventually I gave up, to my ego’s dismay (and Keith’s disappointment!).

    ...read more

  • Ludum Dare 28 Live-Blog!

    Live-blogging my Ludum Dare 28 experience. Most recent entries are on top. I’ll plan to post about once an hour (while working). You’ll have to manually refresh the page to get updates. Follow and comment on twitter @velipso. All timestamps in EST.

    ...read more

  • How to Fix Banding in Gradients

    Photoshop’s gradient algorithm is quite disappointing. It is notorious for creating gradients with banding. Here is an example, attempting to create a gradient from #222 to #333:

    Photoshop's Gradient with Banding

    Photoshop's Gradient with Banding

    Eeeww!

    Can you see it? If you look closely, there are vertical “lines” in the image where the color changes. This is incredibly easy to fix algorithmically - but very difficult to fix any other way.

    ...read more