fork download
  1. # This file provides some common functionality for the main scripts. It is
  2. # designed to be sourced, rather than executed.
  3.  
  4. # Makes the script more robust in general.
  5. set -o errexit
  6. set -o nounset
  7. set -o pipefail
  8.  
  9. # ANSI escape codes for pretty terminal colors.
  10. readonly GREEN='\033[32;1m'
  11. readonly YELLOW="\033[33;1m"
  12. readonly RED="\033[31;1m"
  13. readonly RESET="\033[0m"
  14.  
  15. # Gives the user a "yes/no" prompt with the text from the first positional
  16. # parameter (if given). If an affirmative response is received,
  17. # returns success; if a negative response is received, returns failure; if an
  18. # unrecognized response is received, the user is given the prompt again. This
  19. # function always outputs to the terminal rather than stdout, so it is safe
  20. # to use from within functions that are expected to output their results.
  21. Prompt()
  22. {
  23. # Only try to output the prompt message if it is given, so no newline is
  24. # printed if it isn't.
  25. [ $# -gt 0 ] && echo -e "$1" > /dev/tty
  26.  
  27. local Response
  28. echo -en "[${GREEN}Y${RESET}/${RED}N${RESET}] " > /dev/tty
  29. read Response
  30.  
  31. # For case insensitivity.
  32. Response="$(echo "$Response" | tr [A-Z] [a-z])"
  33.  
  34. if [[ "$Response" =~ ^y(es)?$ ]]; then true
  35. elif [[ "$Response" =~ ^no?$ ]]; then false
  36. else
  37. echo "I don't understand that response. Try \"yes\" or \"no.\"" > /dev/tty
  38. # Keep pestering the user until he gives a valid response.
  39. Prompt
  40. fi
  41. }; readonly -f Prompt
  42.  
  43. # Outputs a string of shell code that will parse the program arguments for long options.
  44. # Example:
  45. # # Let's say that the program was passed the arguments --One Two --Three.
  46. # eval "$(OptionParser One Two Three)"
  47. # echo $One # True.
  48. # echo $Two # False. The argument was not preceded by "--" on the command-line.
  49. # echo $Three # False. OptionParser stops on the first argument that isn't an
  50. # # option, and Two wasn't an option.
  51. OptionParser()
  52. {
  53. if [ $# -ge 1 ]; then
  54. for OptionName in "$@"; do echo -n "$OptionName=false; "; done
  55. echo -n 'while [ $# -ge 1 ]; do case "$1" in'
  56. for OptionName in "$@"; do
  57. echo -n " '--$OptionName') $OptionName=true && shift ;;"
  58. done
  59. echo -n ' *) break ;; esac; done'
  60. fi
  61. }; readonly -f OptionParser
Success #stdin #stdout 0s 5292KB
stdin
#include <iostream>
#include <cmath>
#include <cstring>
#include <unistd.h>

int main() {
    const int width = 80;
    const int height = 22;
    const float R1 = 1.0f;
    const float R2 = 2.0f;
    const float K2 = 5.0f;
    const float K1 = width * K2 * 3 / (8 * (R1 + R2));

    char buffer[height][width];
    float zbuffer[height][width];
    
    float A = 0.0f, B = 0.0f;

    while (true) {
        std::memset(buffer, '0', sizeof(buffer));
        std::memset(zbuffer, 0, sizeof(zbuffer));

        float cosA = cos(A), sinA = sin(A);
        float cosB = cos(B), sinB = sin(B);

        // Iterate through torus angles
        for (float theta = 0; theta < 6.28318f; theta += 0.07f) {
            float costheta = cos(theta), sintheta = sin(theta);
            
            for (float phi = 0; phi < 6.28318f; phi += 0.02f) {
                float cosphi = cos(phi), sinphi = sin(phi);
                
                // 3D coordinates before rotation
                float circlex = R2 + R1 * costheta;
                float circley = R1 * sintheta;

                // 3D coordinates after rotation
                float x = circlex * (cosB * cosphi + sinA * sinB * sinphi) - circley * cosA * sinB;
                float y = circlex * (sinB * cosphi - sinA * cosB * sinphi) + circley * cosA * cosB;
                float z = K2 + cosA * circlex * sinphi + circley * sinA;
                float ooz = 1.0f / z;  // Perspective projection

                // 2D screen coordinates
                int xp = static_cast<int>(width / 2 + K1 * ooz * x);
                int yp = static_cast<int>(height / 2 - K1 * ooz * y);

                // Update buffer if point is visible
                if (xp >= 0 && xp < width && yp >= 0 && yp < height && ooz > zbuffer[yp][xp]) {
                    zbuffer[yp][xp] = ooz;
                    buffer[yp][xp] = '1';
                }
            }
        }

        // Display frame
        std::cout << "\x1b[H";
        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {
                std::cout << buffer[j][i];
            }
            std::cout << '\n';
        }

        // Update angles
        A += 0.07f;
        B += 0.03f;
        
        // Frame delay (30ms)
        usleep(30000);
    }

    return 0;
}
stdout
Standard output is empty