Useless Hack a Week.

1v1 any creature using Animal Fights

Cover Image for 1v1 any creature using Animal Fights
Nick
Nick

We all know that a man's worth is directly linked to how many animals he could beat in a fight. Sadly, in todays world, people will get mad at you if you simply try to fight a dog, so its very difficult to know your worth as a person.

I would win

Luckily, with the power of AI, we can now simulate what it would be like if you actually fought any animal that exists, and even those that don't!

Use Cases

There is a lot of use cases for a program like Animal Fights. Lets list a few:

  1. You want to show other people how cool you are
  2. You want to show other people how cool they aren't

Bear Fight

Ultimately, it's good to know your limits, it would suck if you tried to fight a bear thinking you could win, and lost your life. If you used this app beforehand, you would know "I don't stand a chance" and run for it.

Vice versa, maybe you are hanging out with your friends in your neighborhood, and all of a sudden an angry pitbull starts running up to you:

Pitbull Scenario

According to the app, you have an opportunity to impress your friends now, show them what you got!

Jokes aside, its pretty cool to run these hypothetical situations. Everyone has wondered if they can beat a tiger in a fight. It's the sort of thing thats fun to think about, but horrible in practice.

That's why this is fun to use. Not only does it show you who would win, but it gives a story on how it would play out.

Project Structure

You can implement a silly little app like this very easily, and in many different ways. I used next.js (a variant of node.js) with App Router, Tailwind CSS, and Typescript for my implementation. I only had to modify 1 file and add 1 new one to get this up and running.

Setup

Prerequisites

Firstly, make sure you have an OpenAI Account and API Key.

Also make sure you have downloaded Node.js.

Steps

1. Initialize a Next.js project

npx create-next-app my-next-app

You will only be modifying the page.tsx file found in the src/app directory of your project, and creating a new file called openai.ts.

Lets start by creating our openai.ts file. I put created a src/utils directory to put this file in.

2. Create your openai.ts file

const API_KEY = process.env.NEXT_PUBLIC_OPENAI_API_KEY;

export async function callOpenAI(
    prompt: string,
    model: string = 'gpt-3.5-turbo',
    temperature: number = 0.7
): Promise<string> {

    const OPENAI_API_URL = `https://api.openai.com/v1/chat/completions`;

    const headers = {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json',
    };

    const requestBody = {
        model: model,
        messages: [{
            role: "user",
            content: prompt
        }],
        temperature: temperature
    };

    const response = await fetch(OPENAI_API_URL, {
        method: 'POST',
        headers: headers,
        body: JSON.stringify(requestBody)
    });

    if (!response.ok) {
        const errorDetail = await response.text();
        throw new Error(`OpenAI API call failed: ${response.statusText}. Details: ${errorDetail}`);
    }

    const responseBody = await response.json();
    return responseBody.choices[0].message.content.trim();
}

The above code is very straightforward, I used OpenAI's documentation to create a setup where I can call a function called CallOpenAI() to make my calls to their LLMs.

I can specify three parameters:

Prompt: The prompt I send

Model: The LLM I use

Temperature: How creative the response can be (A value between 0 and 2)

The only parameter that is required is the prompt. If I dont specify the model, it will default to gpt-3.5-turbo and the temperature will default to 0.7

Now I can import it into any file I want like this:

import { callOpenAI } from '@/utils/openai';

3. Modify page.tsx

Creating this file is pretty straightforward. We first make page.tsx a client side file by writing "use client at the top of the file.

Then we initialize references for the input boxes so we can extract the data and send it to OpenAI:

const nameRef = useRef<HTMLInputElement>(null);
const weightRef = useRef<HTMLInputElement>(null);
const heightRef = useRef<HTMLInputElement>(null);
const animalRef = useRef<HTMLInputElement>(null);

We also initialize state variables to keep track of the values of these variables on the screen:

const [loading, setLoading] = useState(false);
const [response, setResponse] = useState<string | null>(null);
const [story, setStory] = useState<string | null>(null);
const [winner, setWinner] = useState<string | null>(null);

I use JSON prompts instead of natural language to get more specific results from GPT 3.5. Here are my three prompts:

 const initialPromptJSON = {
        'role': ' Hypothetical Fight Result Generator',
        'animal': animal,
        'your_weight': weight,
        'your_height': height,
        'rules': [
          `1. Write between 1 and 3 sentences.`,
          `2. You must come up with a definitive result.`
        ],
        'prompt': `How would you, weighing ${weight} and standing at ${height}, fare against a ${animal}?`
      };
      const initialPrompt = JSON.stringify(initialPromptJSON);

  
      const storyPromptJSON = {
          'role': 'Fight Encounter Generator',
          'animal': animal,
          'human_name': name,
            'human_weight': weight,
          'human_height': height,
          'initial_result': firstResult,
          'rules': [
            `1. Use the initial result to write how the encounter would play out.`,
            `2. Make it entertaining and engaging.`,
            `3. The encounter should be no longer than a paragraph.`
          ],
          'prompt': `Write a short encounter of how the fight would play out in third person."`
        };
        const storyPrompt = JSON.stringify(storyPromptJSON);


        const WinnerPromptJSON = {
          'role': ' Winner Selector',
          'animal': animal,
          'human_weight': weight,
          'human_height': height,
          'result': firstResult,
          'rules': [
            `1. Either print "You" or the Animal name, with no extra text/tokens for context.`,
          ],
          'prompt': `Based on the previous outcome, who won: You or the ${animal}? Remember, only output "You" or the name of the animal as your answer.`
        };
        const winnerPrompt = JSON.stringify(WinnerPromptJSON);

The rest of the code is simply hooking up the variable references and state variables to work, and writting the JSX. At the end, you should have a file that looks like this:

"use client"
import Image from 'next/image'
import React, { useState, useRef } from 'react';
import { callOpenAI } from '@/utils/openai';


export default function Home() {

  const nameRef = useRef<HTMLInputElement>(null);
  const weightRef = useRef<HTMLInputElement>(null);
  const heightRef = useRef<HTMLInputElement>(null);
  const animalRef = useRef<HTMLInputElement>(null);

  const [loading, setLoading] = useState(false);
  const [response, setResponse] = useState<string | null>(null);
  const [story, setStory] = useState<string | null>(null);
  const [winner, setWinner] = useState<string | null>(null);


  async function handleSubmit(event: React.FormEvent) {
    event.preventDefault();

    if (nameRef.current && weightRef.current && heightRef.current && animalRef.current) {
      const name = nameRef.current.value;
      const weight = weightRef.current.value;
      const height = heightRef.current.value;
      const animal = animalRef.current.value;

      const initialPromptJSON = {
        'role': ' Hypothetical Fight Result Generator',
        'animal': animal,
        'your_weight': weight,
        'your_height': height,
        'rules': [
          `1. Write between 1 and 3 sentences.`,
          `2. You must come up with a definitive result.`
        ],
        'prompt': `How would you, weighing ${weight} and standing at ${height}, fare against a ${animal}?`
      };
      const initialPrompt = JSON.stringify(initialPromptJSON);

      setLoading(true);

      try {
        const firstResult = await callOpenAI(initialPrompt);
        setResponse(firstResult);

        // Based on the firstResult, construct a new prompt

        const storyPromptJSON = {
          'role': 'Fight Encounter Generator',
          'animal': animal,
          'human_name': name,
            'human_weight': weight,
          'human_height': height,
          'initial_result': firstResult,
          'rules': [
            `1. Use the initial result to write how the encounter would play out.`,
            `2. Make it entertaining and engaging.`,
            `3. The encounter should be no longer than a paragraph.`
          ],
          'prompt': `Write a short encounter of how the fight would play out in third person."`
        };
        const storyPrompt = JSON.stringify(storyPromptJSON);
        const storyResult = await callOpenAI(storyPrompt);

        // Assuming you want to show this story result, you might want to create another state variable like 'setStory'

        setStory(storyResult);

        const WinnerPromptJSON = {
          'role': ' Winner Selector',
          'animal': animal,
          'human_weight': weight,
          'human_height': height,
          'result': firstResult,
          'rules': [
            `1. Either print "You" or the Animal name, with no extra text/tokens for context.`,
          ],
          'prompt': `Based on the previous outcome, who won: You or the ${animal}? Remember, only output "You" or the name of the animal as your answer.`
        };
        const winnerPrompt = JSON.stringify(WinnerPromptJSON);

        const winnerResult = await callOpenAI(winnerPrompt);
        setWinner(winnerResult);

      } catch (error) {
        console.error("Error calling OpenAI:", error);
        setResponse("Error getting response.");
        setWinner(null);
      }

      setLoading(false);
    }
  }


  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-24">
      <div className="max-w-5xl w-full text-center font-mono text-sm mb-8">
        <h1 className="mb-4 text-xl font-bold">Animal Fights</h1>
        <p>How do you fare against different creatures?</p>
      </div>

      <form className="w-full">
        <div className="mb-32 w-full flex justify-center">
          <div className="grid grid-cols-2 gap-20 lg:max-w-5xl">
            {/* Column 1 */}
            <div>
              <h2 className="mb-4 text-xl font-bold text-center">You</h2>
              <div className="mt-4">
                <label className="block mb-2 text-sm font-medium">Your Name</label>
                <input ref={nameRef} type="text" className="p-2 border rounded text-black" placeholder="Enter name..." />
              </div>
              <div className="mt-4">
                <label className="block mb-2 text-sm font-medium">Your Weight</label>
                <input ref={weightRef} type="text" className="p-2 border rounded text-black" placeholder="Enter weight..." />
              </div>
              <div className="mt-4">
                <label className="block mb-2 text-sm font-medium">Your Height</label>
                <input ref={heightRef} type="text" className="p-2 border rounded text-black" placeholder="Enter height..." />
              </div>
            </div>

            {/* Column 2 */}
            <div>
              <h2 className="mb-4 text-xl font-bold text-center">Animal</h2>
              <div>
                <label className="block mb-2 text-sm font-medium">Animal</label>
                <input ref={animalRef} type="text" className="p-2 border rounded text-black" placeholder="Enter animal weight..." />
              </div>
            </div>
          </div>
        </div>

        <div className="text-center mt-6">
          <button onClick={handleSubmit} className="mt-4 p-2 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:opacity-50" disabled={loading}>
            Submit
          </button>
          {response && (
            <div className="mt-4 text-center">
              <h3 className="font-medium text-lg">Result</h3>
              <p>{response}</p>
            </div>
          )}
          {story && (
            <div className="mt-4 text-center">
              <h3 className="font-medium text-lg">Encounter</h3>
              <p>{story}</p>
            </div>
          )}
          {winner && (
            <div className="mt-4 text-center">
              <h3 className="font-medium text-lg">Winner</h3>
              <p>{winner}</p>
            </div>
          )}
        </div>

      </form>
    </main>
  )
}

Thats It! Now you can find out how powerful you and your friends are. Ostrich Fight

Results   Code for this project can be found here!

Do you like unhinged content? Follow me on X! Or Buy me a coffee!