]> nyquistdev.net Git - balls.git/commitdiff
first commit main
authorA-Larsen <austin.larsen@mailfence.com>
Thu, 15 Oct 2026 02:34:59 +0000 (22:34 -0400)
committerA-Larsen <austin.larsen@mailfence.com>
Thu, 15 Oct 2026 02:34:59 +0000 (22:34 -0400)
28 files changed:
2d-projectile-motion/Makefile [new file with mode: 0644]
2d-projectile-motion/balls.c [new file with mode: 0644]
2d-projectile-motion/docs/formulas.adoc [new file with mode: 0644]
2d-projectile-motion/docs/formulas.html [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makehtml [new file with mode: 0755]
README.adoc [new file with mode: 0644]
bounce/Makefile [new file with mode: 0644]
bounce/balls [new file with mode: 0755]
bounce/balls.c [new file with mode: 0644]
bounce/docs/chatgpt_dump/circle-circle-collision.md [new file with mode: 0644]
bounce/docs/chatgpt_dump/circle-rectange-SDL2-collision.md [new file with mode: 0644]
bounce/docs/chatgpt_dump/circle-rectangle-collision.md [new file with mode: 0644]
bounce/docs/chatgpt_dump/physics.md [new file with mode: 0644]
bounce/docs/formulas.adoc [new file with mode: 0644]
bounce/docs/formulas.html [new file with mode: 0644]
collisions/Makefile [new file with mode: 0644]
collisions/balls [new file with mode: 0755]
collisions/balls.c [new file with mode: 0644]
collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes.adoc [new file with mode: 0644]
collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes.html [new file with mode: 0644]
collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes2.adoc [new file with mode: 0644]
collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes2.html [new file with mode: 0644]
collisions/docs/formulas.adoc [new file with mode: 0644]
collisions/docs/formulas.html [new file with mode: 0644]
docinfo.conf [new file with mode: 0644]
notes.adoc [new file with mode: 0644]
rendered.html [new file with mode: 0644]

diff --git a/2d-projectile-motion/Makefile b/2d-projectile-motion/Makefile
new file mode 100644 (file)
index 0000000..0ddb263
--- /dev/null
@@ -0,0 +1,11 @@
+LIBS = -lSDL2 -lSDL2_ttf -lm
+
+PROG = balls
+
+build: $(PROG).c
+       gcc -g -o $(PROG) $(PROG).c $(LIBS)
+
+clean:
+       rm -rf $(PROG)
+
+.PHONY: clean
diff --git a/2d-projectile-motion/balls.c b/2d-projectile-motion/balls.c
new file mode 100644 (file)
index 0000000..0846ca3
--- /dev/null
@@ -0,0 +1,244 @@
+/* 
+ * Copyright (C) 2024  Austin Larsen
+ * 
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <SDL2/SDL.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <math.h>
+
+#define SCREEN_WIDTH_PX 1600
+#define SCREEN_HEIGHT_PX 800
+#define ACC_GRAVITY_MPS 9.81f
+#define GROUND_HEIGHT_PX 750
+
+typedef struct _Mouse {
+    int x;
+    int y;
+    uint32_t button;
+} Mouse;
+
+enum /* color */ {COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_ORANGE, COLOR_GREY,
+                  COLOR_WHITE, COLOR_BLACK, COLOR_SIZE};
+
+void getMouse(Mouse *mouse);
+void update(SDL_Renderer *renderer, uint64_t frame, float seconds,
+            SDL_KeyCode key, Mouse *mouse);
+void
+setColor(SDL_Renderer *renderer, uint8_t color);
+
+
+
+void
+drawBall(SDL_Renderer *renderer, int px, int py, uint8_t radius, uint8_t color)
+// (x - h)^2 + (y - k)^2 = r^2
+// Drawing a circle with the standard circle formula.
+// There may be a more performant way to do this...
+{
+    setColor(renderer, color);
+
+    // diameter is radius * 2
+    for (int x = 0; x < radius * 2; x++) {
+        for (int y = 0; y < radius * 2; y++) {
+          if ( ((x - radius) * (x - radius)) +
+               ((y - radius) * (y - radius)) <=
+               radius * radius) {
+                int tx = px - radius + x;
+                int ty = py - radius + y;
+
+            // TODO: wrap circle around screen
+            SDL_RenderDrawPoint(renderer, tx, ty);
+
+          }
+        }
+    }
+}
+
+int main(void)
+{
+    SDL_Window *window;
+    SDL_Renderer *renderer;
+
+    printf("\033[2J"); // clear entire screen escape sequence
+
+    { // SDL Initialization
+        if (SDL_Init(SDL_INIT_VIDEO) != 0)
+            fprintf(stderr, "could not init video\n%s", SDL_GetError());
+
+        window = SDL_CreateWindow("Projectile",
+                                             SDL_WINDOWPOS_UNDEFINED,
+                                             SDL_WINDOWPOS_UNDEFINED,
+                                             SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX,
+                                             SDL_WINDOW_SHOWN);
+
+        renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_SOFTWARE);
+    } // SDL Initialization
+
+
+    { // game loop
+        bool quit = false;
+        const uint16_t fps = 60;
+        const float mspd = (1.0f / (float)fps) * 1000.0f;
+        uint64_t frame = 0;
+        float seconds = 0;
+
+        while (!quit) {
+            uint32_t loop_start = SDL_GetTicks();
+
+            SDL_Event event;
+            SDL_KeyCode key = 0;
+            Mouse mouse;
+            bool keydown = false;
+
+            getMouse(&mouse);
+
+            while (SDL_PollEvent(&event)) {
+                switch (event.type) {
+                case SDL_KEYDOWN: {
+                    if (event.key.repeat == 0) {
+                        key = event.key.keysym.sym;
+                        keydown = true;
+                    }
+                    break;
+                }
+                case SDL_KEYUP: keydown = false; break;
+                case SDL_QUIT: quit = true; break;
+                }
+            }
+
+            setColor(renderer, COLOR_BLACK);
+            SDL_RenderClear(renderer);
+            update(renderer, frame, seconds, key, &mouse);
+            SDL_RenderPresent(renderer);
+            frame++;
+            seconds = ((float)frame / (float)fps);
+
+            uint32_t loop_end = SDL_GetTicks();
+            uint32_t elapsed_time = loop_end - loop_start;
+
+            uint32_t delay = ceilf(mspd - (float)elapsed_time);
+
+            if (delay > 0) {
+                SDL_Delay(delay);
+            }
+        }
+
+    } // game loop
+
+
+    { // quit
+        SDL_DestroyRenderer(renderer);
+        SDL_DestroyWindow(window);
+        SDL_Quit();
+    } // quit
+
+}
+
+void getMouse(Mouse * mouse)
+{
+    mouse->button = SDL_GetMouseState(&mouse->x, &mouse->y);
+}
+
+void drawPath(SDL_Renderer *renderer, SDL_Point *point, float velocity,
+              float angle, float seconds)
+    // velocity in meters per second
+{
+    // REMEMBER! negative is upward and positive is downward. That is why
+    // the initial velocity for y (vi_y) is negative and acceleration due to
+    // gravity (ACC_GRAVITY_MPS) is positive
+    float vi_y = -velocity * sinf(angle);
+    float vi_x = velocity * cosf(angle);
+    float delta_x = (float)vi_x * (float)seconds;
+    float delta_y = (float)vi_y * (float)seconds + (0.5f * ACC_GRAVITY_MPS
+                        * (seconds * seconds));
+
+    // SDL_Rect rect = {
+    //     .x = point->x + delta_x,
+    //     .y = point->y + delta_y,
+    //     .w = 10,
+    //     .h = 10
+    // };
+    int tx = point->x + delta_x;
+    int ty = point->y + delta_y;
+
+    if (delta_y <= -1) {
+        printf("\033[H"); // clear and set to home position escape sequence
+        printf("seconds: %f\n", seconds);
+        printf("y displacement: %f\n", delta_y);
+        printf("x displacement: %f\n", delta_x);
+        printf("x: %d\n", tx);
+        printf("y: %d\n", ty);
+        // SDL_RenderFillRect(renderer, &rect);
+        drawBall(renderer, tx, ty, 20, COLOR_BLUE);
+    }
+
+}
+
+void update(SDL_Renderer *renderer, uint64_t frame, float seconds,
+            SDL_KeyCode key, Mouse *mouse)
+{
+    static float launch_start = 0;
+    static float launch_angle = 0;
+    static float launch_initial = 0;
+
+    SDL_Point point = {
+        .x = 10,
+        .y = GROUND_HEIGHT_PX
+    };
+
+    // 0 to 90 degrees (1/2 pi)
+    setColor(renderer, COLOR_BLUE);
+    SDL_RenderDrawLine(renderer, point.x, point.y, mouse->x, mouse->y);
+
+
+    int opposite = (mouse->y - point.y);
+    int adjacent = (mouse->x - point.x);
+    float angle = -atanf((float)opposite / (float)adjacent);
+
+    setColor(renderer, COLOR_RED);
+    SDL_RenderDrawLine(renderer, 0, GROUND_HEIGHT_PX, SCREEN_WIDTH_PX,
+                       GROUND_HEIGHT_PX);
+
+    if (mouse->button == 1) {
+        launch_start = seconds;
+        launch_angle = angle;
+        // hypotenuse is velocity
+        launch_initial = sqrtf((opposite * opposite) + (adjacent * adjacent));
+    }
+
+    if (launch_start > 0) {
+        drawPath(renderer, &point, launch_initial, launch_angle, seconds -
+                 launch_start);
+    }
+}
+
+void
+setColor(SDL_Renderer *renderer, uint8_t color)
+{
+    const SDL_Color colors[] = {
+        [COLOR_RED] = {.r = 217, .g = 100, .b = 89, .a = 255},
+        [COLOR_WHITE] = {.r = 255, .g = 255, .b = 255, .a = 255},
+        [COLOR_GREEN] = {.r = 88, .g = 140, .b = 126, .a = 255},
+        [COLOR_BLUE] = {.r = 146, .g = 161, .b = 185, .a = 255},
+        [COLOR_ORANGE] = {.r = 242, .g = 174, .b = 114, .a = 255},
+        [COLOR_GREY] = {.r = 89, .g = 89, .b = 89, .a = 89},
+        [COLOR_BLACK] = {.r = 0, .g = 0, .b = 0, .a = 0},
+    };
+
+    SDL_SetRenderDrawColor(renderer, colors[color].r, colors[color].g,
+                           colors[color].b, colors[color].a);
+}
+
diff --git a/2d-projectile-motion/docs/formulas.adoc b/2d-projectile-motion/docs/formulas.adoc
new file mode 100644 (file)
index 0000000..735bb81
--- /dev/null
@@ -0,0 +1,28 @@
+:stem: 
+:source-highlighter: pygments
+:pygments-style: monokai
+:wrap: normal
+
+= Formulas
+
+* Velocity of y
+    - stem:[\Deltay = V_{0}t + 1/2at^2]
+
+* Velocity of x
+    - stem:[\Deltax = V_{0}t]
+
+* Angle of trojectory
+    - stem:[\theta = \arctan(frac{opposite}{adjactent})]
+
+* Getting initial y velocity (going downward increases in value)
+    - stem:[y_{0} = -l_0 * \sin(\theta)]
+
+* Getting initial x velocity 
+    - stem:[x_{0} = l_0 * \cos(\theta)]
+
+* Pathagorean Theorem
+    - stem:[a^2 + b^2 = c^2]
+
+NOTE: launch_initial is just an intial, almost arbitrary, value. It is just a
+      distance the launch pad is from the mouse and is used to control the
+      amount of velocity you want.
diff --git a/2d-projectile-motion/docs/formulas.html b/2d-projectile-motion/docs/formulas.html
new file mode 100644 (file)
index 0000000..a226e81
--- /dev/null
@@ -0,0 +1,550 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 2.0.20">
+<title>Formulas</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
+/* Uncomment the following line when using as a custom stylesheet */
+/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
+html{font-family:sans-serif;-webkit-text-size-adjust:100%}
+a{background:none}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+b,strong{font-weight:bold}
+abbr{font-size:.9em}
+abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
+dfn{font-style:italic}
+hr{height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+audio,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type=checkbox],input[type=radio]{padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,::before,::after{box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:0}
+p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.square{list-style-type:square}
+ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt{background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+:not(pre).nobreak{word-wrap:normal}
+:not(pre).nowrap{white-space:nowrap}
+:not(pre).pre-wrap{white-space:pre-wrap}
+:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
+pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
+pre>code{display:block}
+pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #e7e7e9}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+details{margin-left:1.25rem}
+details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
+details>summary::-webkit-details-marker{display:none}
+details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
+details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
+details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
+.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
+@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
+.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
+.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.prettyprint{background:#f7f7f8}
+pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
+pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
+pre.prettyprint li code[data-lang]::before{opacity:1}
+pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
+table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
+table.linenotable td.code{padding-left:.75em}
+table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
+pre.pygments span.linenos{display:inline-block;margin-right:.75em}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
+.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
+.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
+.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
+.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
+td.tableblock>.content>:last-child{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>*>tr>*{border-width:1px}
+table.grid-cols>*>tr>*{border-width:0 1px}
+table.grid-rows>*>tr>*{border-width:1px 0}
+table.frame-all{border-width:1px}
+table.frame-ends{border-width:1px 0}
+table.frame-sides{border-width:0 1px}
+table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
+table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
+table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
+table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
+table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+li>p:empty:only-child::before{content:"";display:inline-block}
+ul.checklist>li>p:first-child{margin-left:-1em}
+ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
+ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+td.hdlist2{word-wrap:anywhere}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
+.imageblock.left{margin:.25em .625em 1.25em 0}
+.imageblock.right{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background:#00fafa}
+.black{color:#000}
+.black-background{background:#000}
+.blue{color:#0000bf}
+.blue-background{background:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background:#fa00fa}
+.gray{color:#606060}
+.gray-background{background:#7d7d7d}
+.green{color:#006000}
+.green-background{background:#007d00}
+.lime{color:#00bf00}
+.lime-background{background:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background:#7d0000}
+.navy{color:#000060}
+.navy-background{background:#00007d}
+.olive{color:#606000}
+.olive-background{background:#7d7d00}
+.purple{color:#600060}
+.purple-background{background:#7d007d}
+.red{color:#bf0000}
+.red-background{background:#fa0000}
+.silver{color:#909090}
+.silver-background{background:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]{border-bottom:1px dotted}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#header,#content,#footnotes,#footer{max-width:none}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+</head>
+<body class="article">
+<div id="header">
+<h1>Formulas</h1>
+</div>
+<div id="content">
+<div class="ulist">
+<ul>
+<li>
+<p>Velocity of y</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\$\Deltay = V_{0}t + 1/2at^2\$</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Velocity of x</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\$\Deltax = V_{0}t\$</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Angle of trojectory</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\$\theta = \arctan(frac{opposite}{adjactent})\$</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Getting initial y velocity (going downward increases in value)</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\$y_{0} = -l_0 * \sin(\theta)\$</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Getting initial x velocity</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\$x_{0} = l_0 * \cos(\theta)\$</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Pathagorean Theorem</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\$a^2 + b^2 = c^2\$</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">
+launch_initial is just an intial, almost arbitrary, value. It is just a
+      distance the launch pad is from the mouse and is used to control the
+      amount of velocity you want.
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2025-12-23 12:07:18 -0500
+</div>
+</div>
+<script type="text/x-mathjax-config">
+MathJax.Hub.Config({
+  messageStyle: "none",
+  tex2jax: {
+    inlineMath: [["\\(", "\\)"]],
+    displayMath: [["\\[", "\\]"]],
+    ignoreClass: "nostem|nolatexmath"
+  },
+  asciimath2jax: {
+    delimiters: [["\\$", "\\$"]],
+    ignoreClass: "nostem|noasciimath"
+  },
+  TeX: { equationNumbers: { autoNumber: "none" } }
+})
+MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
+  MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
+    if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
+      data.math.root.display = "block"
+    }
+    return data
+  })
+})
+</script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..d159169
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/Makehtml b/Makehtml
new file mode 100755 (executable)
index 0000000..a7e355a
--- /dev/null
+++ b/Makehtml
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+. docinfo.conf
+
+clean () {
+rm -rf diag*.png
+rm -rf $(find . \
+            -type f \
+            -regex '.*\.html' \
+            -not -name "rendered.html" \
+            | grep -v docinfo)
+}
+
+build () {
+FILENAME="$(find . -type f -name "*.adoc" -not -name "README.adoc" -not -name "notes.adoc")"
+asciidoctor -b html5 $FILENAME
+}
+
+make () {
+    clean
+    build
+}
+
+# use this to call one of the above functions
+$@
diff --git a/README.adoc b/README.adoc
new file mode 100644 (file)
index 0000000..42730b0
--- /dev/null
@@ -0,0 +1,52 @@
+= Balls
+
+This repository has physics examples using balls. Each folder has a different
+example, with a link to the formulas used in the readme's.
+
+== 2D Projectile Motion
+checkout this link
+https://nyquistdev.net/git/?p=balls.git;a=blob_plain;f=2d-projectile-motion/docs/formulas.html;hb=HEAD[formulas].
+for a list of forumlas used.
+
+[%header,cols="1,1"]
+|===
+| control                 | action
+| right-click and drag    | determine direction and velocity of ball
+| right-click release     | launch ball
+|===
+
+== Bouncing
+check out this link
+https://nyquistdev.net/git/?p=balls.git;a=blob_plain;f=bounce/docs/formulas.html;hb=HEAD[formulas].
+for the formulas used.
+
+== Collisions
+Creates random balls. These balls will resolve any collision issues. Launching a
+ball will show you an example of elastic collision.
+
+checkout this link
+https://nyquistdev.net/git/?p=balls.git;a=blob_plain;f=collisions/docs/formulas.html;hb=HEAD[formulas].
+for a list of forumlas used.
+
+[%header,cols="1,1"]
+|===
+| control                             | action
+| right-click                         | select ball
+| right-click and left-click and drag | flings ball on release, the distance
+                                        away from the ball determines the amount
+                                        of velocity to launch the ball at
+|===
+
+== Building html from formula _.adoc_ files
+
+----
+./Makehtml make
+----
+
+== Links
+* https://www.studyplan.dev/sdl2/sdl2-relative-mode[sdl2-relative-mouse-mode]
+* https://www.youtube.com/watch?v=XJnIdRXUi7A&t=315s[permutations and combinations]
+* https://www.youtube.com/watch?v=CFbo_nBdBco[OCT | Elastic Collisions]
+* https://www.wikihow.com/Normalize-a-Vector[Normalizing a Vector]
+* https://www.youtube.com/watch?v=Fp7D5D8Bqjc[conservation of Momentum]
+
diff --git a/bounce/Makefile b/bounce/Makefile
new file mode 100644 (file)
index 0000000..0ddb263
--- /dev/null
@@ -0,0 +1,11 @@
+LIBS = -lSDL2 -lSDL2_ttf -lm
+
+PROG = balls
+
+build: $(PROG).c
+       gcc -g -o $(PROG) $(PROG).c $(LIBS)
+
+clean:
+       rm -rf $(PROG)
+
+.PHONY: clean
diff --git a/bounce/balls b/bounce/balls
new file mode 100755 (executable)
index 0000000..51a3a1c
Binary files /dev/null and b/bounce/balls differ
diff --git a/bounce/balls.c b/bounce/balls.c
new file mode 100644 (file)
index 0000000..c794912
--- /dev/null
@@ -0,0 +1,336 @@
+#include <stdio.h>
+#include <SDL2/SDL.h>
+#include <stdbool.h>
+#include <SDL2/SDL_ttf.h>
+#include <assert.h>
+#include <stdint.h>
+#include <math.h>
+#include <SDL2/SDL_rect.h>
+
+// NOTE:
+// This is a less accurate depiction of gravity. I am using a different number
+// as the mesurement in meters per second because you cannot have fractions of a
+// pixel. In order to depict this more accurately I would need an approximate
+// size of a pixel, and not every pixel is the same size. I have decided not to
+// be THAT accurate.
+#define METER_AS_PIXELS 3779U
+// #define GRAVITY 0.5f
+
+#define END(check, str1, str2) \
+    if (check) { \
+        assert(check); \
+        fprintf(stderr, "%s\n%s", str1, str2); \
+        exit(1); \
+    } \
+
+#define SDL_main main
+
+
+typedef struct _Game {
+    SDL_Renderer *renderer;
+    SDL_Window *window;
+    bool out_of_bounds;
+    uint16_t fps;
+    float gravity;
+    float terminal_velocity;
+    SDL_Rect screen_rect;
+} Game;
+
+typedef struct _Ball {
+    SDL_Point center; 
+    SDL_Point velocities;
+    uint16_t radius;
+    bool down; // check if the ball is 
+    // these two varaibles reset with each fall
+    float time_falling; // time it takes to fall from peak
+    float height_falling; // max height for each fall
+    float e; // restition value
+} Ball;
+
+typedef uint8_t (*Update_callback) (Game *game, 
+                                    float seconds, 
+                                    uint64_t frame,
+                                    SDL_KeyCode key,
+                                    bool keydown);
+
+enum {UPDATE_MAIN, UPDATE_NOTHING};
+
+enum {COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_ORANGE, COLOR_GREY,
+      COLOR_BLACK, COLOR_SIZE};
+
+void
+setColor(SDL_Renderer *renderer,
+         uint8_t color)
+{
+    const SDL_Color colors[] = {
+        [COLOR_RED] = {.r = 217, .g = 100, .b = 89, .a = 255},
+        [COLOR_GREEN] = {.r = 88, .g = 140, .b = 126, .a = 255},
+        [COLOR_BLUE] = {.r = 146, .g = 161, .b = 185, .a = 255},
+        [COLOR_ORANGE] = {.r = 242, .g = 174, .b = 114, .a = 255},
+        [COLOR_GREY] = {.r = 89, .g = 89, .b = 89, .a = 89},
+        [COLOR_BLACK] = {.r = 0, .g = 0, .b = 0, .a = 0},
+    };
+
+    SDL_SetRenderDrawColor(renderer, colors[color].r, colors[color].g,
+                           colors[color].b, colors[color].a);
+}
+
+void
+drawCircle(SDL_Renderer *renderer,
+           int radius,
+           SDL_Point center,
+           uint8_t color)
+// (x - h)^2 + (y - k)^2 = r^2
+// Drawing a circle with the standard circle formula.
+// There may be a more performant way to do this...
+{
+    int size = radius;
+    setColor(renderer, color);
+
+    // diameter is radius * 2
+    for (int x = 0; x < radius * 2; x++) {
+        for (int y = 0; y < radius * 2; y++) {
+            if (((x - size)*(x - size)) + ((y - size)*(y - size)) <= radius
+                 * radius)
+                SDL_RenderDrawPoint(renderer, center.x - radius + x, center.y - radius + y);
+        }
+    }
+}
+
+float clamp(float v, float min, float max) {
+    if (v < min) return min;
+    if (v > max) return max;
+    return v;
+}
+
+bool circleRectCollide(SDL_Point circle,
+                       float r,
+                       SDL_Rect rect)
+{
+    float closestX = clamp(circle.x, rect.x, rect.x + rect.w);
+    float closestY = clamp(circle.y, rect.y, rect.y + rect.h);
+
+    // this gets the distance form the center of the circle to a side of a
+    // rectangle. It could be negative or positive. Because we are squaring them
+    // it doesn't matter.
+    float dx = circle.x - closestX;
+    float dy = circle.y - closestY;
+
+    // use the dot product to determine collision
+    return (dx*dx + dy*dy) <= (r*r);
+}
+
+static uint8_t
+updateNothing(Game *game,
+           float seconds,
+           uint64_t frame,
+           SDL_KeyCode key,
+           bool keydown)
+{
+    return UPDATE_NOTHING;
+}
+
+void
+worldBoundry(Game *game, Ball *ball)
+{
+    int padding = 1;
+
+    if (ball->center.x - ball->radius <= 0) {
+        ball->center.x = ball->radius + padding;
+    }
+
+    if (ball->center.y - ball->radius <= 0) {
+        ball->center.y = ball->radius + padding;
+    }
+
+    if (ball->center.x + ball->radius >= game->screen_rect.w) {
+        ball->center.x = game->screen_rect.w - ball->radius - padding;
+    }
+
+    if (ball->center.y + ball->radius >= game->screen_rect.h) {
+        ball->center.y = game->screen_rect.h - ball->radius - padding;
+    }
+}
+
+static uint8_t
+updateMain(Game *game,
+           float seconds,
+           uint64_t frame,
+           SDL_KeyCode key,
+           bool keydown)
+{
+    // as long as gravity and time are using the same units the fomrulas will
+    // work. in this case we will do frames as out unit
+    // * Rubber ball: (e \approx 0.8 - 0.9)
+    // * Basketball: (e \approx 0.75)
+    // * Tennis ball: (e \approx 0.6)
+    static Ball ball = {
+        .center = {.x = 400, .y = 400},
+        .radius = 30,
+        .down = true,
+        .e = 0.9f
+    };
+
+    static float initial_y = 400;
+    static float y = 400;
+    static float restitution = 1;
+    static float f = 0;
+    static float acceleration = 0;
+
+
+    if (ball.down)  // falling downward
+        acceleration += (game->gravity * f);
+     else 
+        acceleration -= restitution - (game->gravity * f);
+
+    // clip this to world border
+    ball.center.y = y + acceleration;
+
+    // ball.height_falling = initial_y + (0.5f * game->gravity) * (f * f);
+
+    // ball.time_falling = sqrt(2 * (initial_y - ball.radius) / game->gravity);
+    //
+    // This if statement cannot be used because
+     // if (f > time && ball.down) {
+     if ((ball.center.y + ball.radius >= game->screen_rect.h) &&
+         restitution >= 0) {
+         f = 0;
+         ball.down = false;
+         restitution *= ball.e;
+     }
+
+    worldBoundry(game, &ball);
+
+    // Should not go out of bounds. but check if it does
+     game->out_of_bounds =
+        !circleRectCollide(ball.center, ball.radius, game->screen_rect);
+
+    drawCircle(game->renderer, ball.radius, ball.center, COLOR_RED);
+    f++;
+
+    return UPDATE_MAIN;
+}
+
+void
+Game_Update(Game *game)
+// The main game loop. Sets up which callback will be used in the function loop.
+// Each update callback determines what update callback will be called next by
+// returning the appropriate enum value
+{
+    uint64_t frame = 0;
+    bool quit = false;
+    bool keydown = false;
+    uint8_t update_id = 0;
+    Update_callback update;
+    float mspd = (1.0f / (float)game->fps) * 1000.0f;
+    float seconds = 0;
+    SDL_Event event;
+    SDL_KeyCode key = 0;
+    uint32_t end = 0;
+    uint32_t elapsed_time = 0;
+    uint8_t color = COLOR_BLACK;
+
+    while (!quit) {
+        uint32_t start = SDL_GetTicks();
+        // clear screen
+        if (game->out_of_bounds) color = COLOR_GREEN;
+        setColor(game->renderer, color);
+        SDL_RenderClear(game->renderer);
+        // TODO:
+        // find milliseconds so you can update gravity more acurately
+        // (1 / frame)
+        seconds = ((float)frame / (float)game->fps);
+        // printf("%lu: %f\n", frame, seconds);
+ 
+
+        // Place update functions here
+        switch (update_id) {
+            case UPDATE_MAIN: update = updateMain; break;
+            case UPDATE_NOTHING: update = updateNothing; break;
+            // case UPDATE_LOSE: update = updateLose; break;
+        }
+
+
+
+        while (SDL_PollEvent(&event)) {
+            switch (event.type) {
+                case SDL_KEYDOWN: {
+                    if (event.key.repeat == 0) {
+                      key = event.key.keysym.sym;
+                      keydown = true;
+                    }
+
+                    break;
+                }
+
+                case SDL_KEYUP: keydown = false; break;
+                case SDL_QUIT: quit = true; break;
+            }
+        }
+
+        update_id = update(game, seconds, frame, key, keydown);
+
+        end = SDL_GetTicks();
+        elapsed_time = end - start;
+
+        if (elapsed_time < mspd) {
+            elapsed_time = mspd - elapsed_time;
+            SDL_Delay(elapsed_time);
+        } 
+
+        SDL_RenderPresent(game->renderer);
+        frame++;
+    }
+}
+
+void
+Game_Init(Game *game)
+// All the variable and data initialization needed for SDL and perhaps game
+// variables
+{
+    memset(game, 0, sizeof(Game));
+    game->screen_rect.x = 0;
+    game->screen_rect.y = 0;
+    game->screen_rect.w = 800;
+    game->screen_rect.h = 800;
+
+    END(SDL_Init(SDL_INIT_VIDEO) != 0, "Could not create texture",
+        SDL_GetError());
+
+    END(TTF_Init() != 0, "Could not initialize TTF", TTF_GetError());
+
+
+
+    game->window = SDL_CreateWindow("balls", SDL_WINDOWPOS_UNDEFINED, 
+                     SDL_WINDOWPOS_UNDEFINED, game->screen_rect.w, 
+                     game->screen_rect.h, SDL_WINDOW_SHOWN);
+
+    END(game->window == NULL, "Could not create window", SDL_GetError());
+
+    game->renderer = SDL_CreateRenderer(game->window, 0,
+                                        SDL_RENDERER_SOFTWARE);
+
+    END(game->renderer == NULL, "Could not create renderer", SDL_GetError());
+    game->fps = 400;
+    // game->terminal_velocity = 
+    game->gravity  = 0.004f;
+}
+
+void
+Game_Quit(Game *game)
+{
+    SDL_DestroyWindow(game->window);
+    SDL_DestroyRenderer(game->renderer);
+    TTF_Quit();
+    SDL_Quit();
+}
+
+int
+main(void)
+{
+    Game game;
+    Game_Init(&game);
+    Game_Update(&game);
+    Game_Quit(&game);
+    return 0;
+}
diff --git a/bounce/docs/chatgpt_dump/circle-circle-collision.md b/bounce/docs/chatgpt_dump/circle-circle-collision.md
new file mode 100644 (file)
index 0000000..cb838ac
--- /dev/null
@@ -0,0 +1,151 @@
+Below is a clear explanation of **circle–circle collision detection**, including the **math formulas** and **C code examples**.
+
+---
+
+# ✅ **Math Behind Circle Collision**
+
+Two circles collide (intersect or touch) when the **distance between their centers** is **less than or equal to** the **sum of their radii**.
+
+Let:
+
+* Circle 1 center: ((x_1, y_1)), radius (r_1)
+* Circle 2 center: ((x_2, y_2)), radius (r_2)
+
+### **1. Compute distance between centers**
+
+[
+d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}
+]
+
+### **2. Collision condition**
+
+[
+d \le r_1 + r_2
+]
+
+A common optimization is to avoid the expensive `sqrt()`:
+
+### **Squared distance method (no sqrt)**
+
+[
+(x_2 - x_1)^2 + (y_2 - y_1)^2 \le (r_1 + r_2)^2
+]
+
+This is identical mathematically, but faster.
+
+---
+
+# ✅ **C Example: Basic Circle Collision Check**
+
+```c
+#include <stdio.h>
+#include <math.h>
+#include <stdbool.h>
+
+typedef struct {
+    float x;
+    float y;
+    float r;
+} Circle;
+
+bool circlesCollide(Circle a, Circle b) {
+    float dx = b.x - a.x;
+    float dy = b.y - a.y;
+    float distance = sqrtf(dx * dx + dy * dy);
+
+    return distance <= (a.r + b.r);
+}
+
+int main() {
+    Circle c1 = {0.0f, 0.0f, 5.0f};
+    Circle c2 = {6.0f, 0.0f, 5.0f};
+
+    if (circlesCollide(c1, c2)) {
+        printf("Circles collide!\n");
+    } else {
+        printf("No collision.\n");
+    }
+
+    return 0;
+}
+```
+
+---
+
+# ✅ **C Example: Optimized (No sqrt)**
+
+```c
+#include <stdio.h>
+#include <stdbool.h>
+
+typedef struct {
+    float x;
+    float y;
+    float r;
+} Circle;
+
+bool circlesCollideFast(Circle a, Circle b) {
+    float dx = b.x - a.x;
+    float dy = b.y - a.y;
+
+    float distanceSquared = dx * dx + dy * dy;
+    float radiusSum = a.r + b.r;
+
+    return distanceSquared <= radiusSum * radiusSum;
+}
+
+int main() {
+    Circle c1 = {0.0f, 0.0f, 5.0f};
+    Circle c2 = {6.0f, 0.0f, 5.0f};
+
+    if (circlesCollideFast(c1, c2)) {
+        printf("Circles collide!\n");
+    } else {
+        printf("No collision.\n");
+    }
+
+    return 0;
+}
+```
+
+---
+
+# 🚀 **Example Output**
+
+For the sample circles, they collide because distance = 6 and r1 + r2 = 10.
+
+```
+Circles collide!
+```
+
+---
+
+# 🧠 Optional: Collision Penetration Depth (Extra Useful)
+
+Sometimes you want *how much* they overlap:
+
+[
+\text{penetration} = (r_1 + r_2) - d
+]
+
+C example:
+
+```c
+float penetrationDepth(Circle a, Circle b) {
+    float dx = b.x - a.x;
+    float dy = b.y - a.y;
+    float d = sqrtf(dx * dx + dy * dy);
+    return (a.r + b.r) - d;
+}
+```
+
+---
+
+If you'd like, I can also show:
+
+✅ Circle vs Rectangle collision
+✅ Circle movement simulation
+✅ Game-loop example using SDL2
+✅ Visual ASCII output
+
+Just tell me!
diff --git a/bounce/docs/chatgpt_dump/circle-rectange-SDL2-collision.md b/bounce/docs/chatgpt_dump/circle-rectange-SDL2-collision.md
new file mode 100644 (file)
index 0000000..d0c85ad
--- /dev/null
@@ -0,0 +1,119 @@
+```c
+#include <SDL2/SDL.h>
+#include <stdbool.h>
+#include <math.h>
+
+// -----------------------------------------
+// Utility functions
+// -----------------------------------------
+float clamp(float v, float min, float max) {
+    if (v < min) return min;
+    if (v > max) return max;
+    return v;
+}
+
+bool circleRectCollide(float cx, float cy, float r,
+                       float rx, float ry, float rw, float rh)
+{
+    float closestX = clamp(cx, rx, rx + rw);
+    float closestY = clamp(cy, ry, ry + rh);
+
+    float dx = cx - closestX;
+    float dy = cy - closestY;
+
+    return (dx*dx + dy*dy) <= (r*r);
+}
+
+// -----------------------------------------
+// Main SDL demo
+// -----------------------------------------
+int main() {
+    SDL_Init(SDL_INIT_VIDEO);
+
+    SDL_Window* window = SDL_CreateWindow(
+        "Circle vs Rectangle Collision - SDL2", 
+        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        800, 600,
+        SDL_WINDOW_SHOWN
+    );
+
+    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+
+    // Circle properties
+    float cx = 100.0f;
+    float cy = 100.0f;
+    float cr = 25.0f;
+    float speed = 200.0f; // pixels per second
+
+    // Rectangle properties
+    float rx = 400.0f;
+    float ry = 250.0f;
+    float rw = 150.0f;
+    float rh = 100.0f;
+
+    Uint32 last = SDL_GetTicks();
+    bool running = true;
+
+    while (running) {
+        Uint32 now = SDL_GetTicks();
+        float dt = (now - last) / 1000.0f;
+        last = now;
+
+        // ------------------
+        // Input
+        // ------------------
+        SDL_Event e;
+        while (SDL_PollEvent(&e)) {
+            if (e.type == SDL_QUIT) running = false;
+        }
+
+        const Uint8* keys = SDL_GetKeyboardState(NULL);
+        if (keys[SDL_SCANCODE_ESCAPE]) running = false;
+
+        // Move circle
+        if (keys[SDL_SCANCODE_W]) cy -= speed * dt;
+        if (keys[SDL_SCANCODE_S]) cy += speed * dt;
+        if (keys[SDL_SCANCODE_A]) cx -= speed * dt;
+        if (keys[SDL_SCANCODE_D]) cx += speed * dt;
+
+        // ------------------
+        // Collision check
+        // ------------------
+        bool hit = circleRectCollide(cx, cy, cr, rx, ry, rw, rh);
+
+        // ------------------
+        // Render
+        // ------------------
+        SDL_SetRenderDrawColor(renderer, 20, 20, 20, 255);
+        SDL_RenderClear(renderer);
+
+        // Rectangle (turn red when hit)
+        if (hit)
+            SDL_SetRenderDrawColor(renderer, 255, 50, 50, 255);
+        else
+            SDL_SetRenderDrawColor(renderer, 100, 100, 255, 255);
+
+        SDL_Rect rect = { (int)rx, (int)ry, (int)rw, (int)rh };
+        SDL_RenderFillRect(renderer, &rect);
+
+        // Draw circle (simple filled circle)
+        SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255);
+        for (int w = 0; w < cr * 2; w++) {
+            for (int h = 0; h < cr * 2; h++) {
+                int dx = cr - w;
+                int dy = cr - h;
+                if ((dx*dx + dy*dy) <= (cr * cr)) {
+                    SDL_RenderDrawPoint(renderer, cx + dx, cy + dy);
+                }
+            }
+        }
+
+        SDL_RenderPresent(renderer);
+    }
+
+    SDL_DestroyRenderer(renderer);
+    SDL_DestroyWindow(window);
+    SDL_Quit();
+    return 0;
+}
+```
diff --git a/bounce/docs/chatgpt_dump/circle-rectangle-collision.md b/bounce/docs/chatgpt_dump/circle-rectangle-collision.md
new file mode 100644 (file)
index 0000000..332d5b9
--- /dev/null
@@ -0,0 +1,171 @@
+Below is a clear explanation of **Circle vs Rectangle collision detection**, including **math formulas**, **edge-case handling**, and **C programming examples**.
+
+---
+
+# 🟢 **Circle vs Axis-Aligned Rectangle Collision**
+
+We assume the rectangle is **axis-aligned (AABB)** and defined by:
+
+* Rectangle min corner: ((rx, ry))
+* Width (w), height (h)
+* So max corner is ((rx+w,; ry+h))
+
+Circle:
+
+* Center: ((cx, cy))
+* Radius (r)
+
+---
+
+# ✅ **Math Formula (Shortest Distance Method)**
+
+The basic idea:
+
+1. **Clamp** the circle center to the edges of the rectangle
+2. Compute the closest point **inside the rectangle**
+3. Compute distance from the circle center to that point
+4. If distance ≤ radius → collision
+
+### 1. Clamp function
+
+[
+\text{clamp}(v, min, max) = \max(min,;\min(v, max))
+]
+
+### 2. Closest point on rectangle to circle
+
+[
+\text{closestX} = \text{clamp}(cx,; rx,; rx+w)
+]
+[
+\text{closestY} = \text{clamp}(cy,; ry,; ry+h)
+]
+
+### 3. Distance from circle to closest point
+
+[
+dx = cx - \text{closestX}
+]
+[
+dy = cy - \text{closestY}
+]
+
+### 4. Collision rule
+
+[
+dx^2 + dy^2 \le r^2
+]
+
+No square root needed → fast.
+
+---
+
+# 🟦 **C Code Example: Circle vs Rectangle Collision**
+
+```c
+#include <stdio.h>
+#include <stdbool.h>
+
+float clamp(float value, float min, float max) {
+    if (value < min) return min;
+    if (value > max) return max;
+    return value;
+}
+
+typedef struct {
+    float x, y;   // top-left corner
+    float w, h;
+} Rect;
+
+typedef struct {
+    float x, y;   // center
+    float r;
+} Circle;
+
+bool circleRectCollide(Circle c, Rect r) {
+    // Find the closest point on the rectangle to the circle
+    float closestX = clamp(c.x, r.x, r.x + r.w);
+    float closestY = clamp(c.y, r.y, r.y + r.h);
+
+    // Compute distance from circle center to that point
+    float dx = c.x - closestX;
+    float dy = c.y - closestY;
+
+    // If within radius, collision
+    return (dx * dx + dy * dy) <= (c.r * c.r);
+}
+
+int main() {
+    Circle c = { 5.0f, 5.0f, 3.0f };
+    Rect r = { 7.0f, 4.0f, 6.0f, 4.0f };
+
+    if (circleRectCollide(c, r)) {
+        printf("Collision!\n");
+    } else {
+        printf("No collision.\n");
+    }
+}
+```
+
+---
+
+# 🧪 **Explanation of the above example**
+
+Circle at (5,5), radius 3
+Rectangle at (7,4), size 6×4
+
+The closest point on the rect to the circle is (7,5).
+Distance = 2 → less than radius 3 → collision.
+
+---
+
+# 🧠 Extra: Detecting Penetration Vector / Push-out Direction
+
+If you're making a game, you often need to **push the circle out** of the rectangle.
+
+Short version:
+
+1. Compute closest point
+2. Compute distance
+3. Compute penetration vector
+
+Example:
+
+```c
+#include <math.h>
+
+void circleRectPenetration(Circle c, Rect r, float *outX, float *outY) {
+    float closestX = clamp(c.x, r.x, r.x + r.w);
+    float closestY = clamp(c.y, r.y, r.y + r.h);
+
+    float dx = c.x - closestX;
+    float dy = c.y - closestY;
+
+    float distSq = dx*dx + dy*dy;
+    float dist = sqrtf(distSq);
+
+    float penetration = c.r - dist;
+
+    if (penetration > 0) {
+        *outX = (dx / dist) * penetration;
+        *outY = (dy / dist) * penetration;
+    } else {
+        *outX = *outY = 0.0f;
+    }
+}
+```
+
+This gives the shortest vector needed to push the circle out of the rectangle.
+
+---
+
+# Want more?
+
+I can also show:
+
+✔ **Circle vs rotated rectangle (OBB)**
+✔ **Collision response (velocity reflection)**
+✔ **Graphical ASCII demo**
+✔ **SDL2 example with moving circle and rectangle**
+
+Just tell me!
diff --git a/bounce/docs/chatgpt_dump/physics.md b/bounce/docs/chatgpt_dump/physics.md
new file mode 100644 (file)
index 0000000..66e51d9
--- /dev/null
@@ -0,0 +1,227 @@
+Below is a **clear physics explanation**, the **math**, and **C programming examples** showing how to simulate a bouncing ball.
+
+---
+
+# 🌟 **Physics of a Bouncing Ball**
+
+A bouncing ball is controlled by three main ideas:
+
+---
+
+# 1️⃣ **Gravity Accelerates the Ball Downward**
+
+The ball’s vertical motion follows:
+
+[
+h(t) = h_0 - \tfrac{1}{2} g t^2
+]
+
+Velocity increases downward as:
+
+[
+v(t) = -gt
+]
+
+Where:
+
+* (h) = height
+* (g = 9.8\ \text{m/s}^2)
+* (v) = velocity
+* Downward is negative
+
+---
+
+# 2️⃣ **Impact With the Ground**
+
+When the ball hits the ground, it changes direction.
+
+A real ball **does NOT return to full height**; some energy is lost.
+
+This is described using the **coefficient of restitution**, (e):
+
+[
+e = \frac{v_{\text{after}}}{v_{\text{before}}}
+]
+
+Typical values:
+
+* Rubber ball: (e \approx 0.8 - 0.9)
+* Basketball: (e \approx 0.75)
+* Tennis ball: (e \approx 0.6)
+
+Meaning:
+
+* If velocity before impact is (-10\ \text{m/s})
+* With (e = 0.8), after impact:
+  [
+  v_{\text{after}} = -e \cdot v_{\text{before}} = 8\ \text{m/s}
+  ]
+
+(The sign flips because the direction reverses.)
+
+---
+
+# 3️⃣ **Each Bounce Gets Shorter**
+
+Because energy is lost each bounce, the maximum height shrinks:
+
+[
+h_{\text{after}} = e^2 \cdot h_{\text{before}}
+]
+
+---
+
+# ⭐ **MATHEMATICAL MODEL**
+
+Let:
+
+* (h) = current height
+* (v) = velocity
+* (dt) = time step
+
+Update each frame:
+
+### Gravity:
+
+[
+v = v - g \cdot dt
+]
+
+### Position:
+
+[
+h = h + v \cdot dt
+]
+
+### Bounce:
+
+If (h < 0):
+[
+h = 0
+]
+[
+v = -e \cdot v
+]
+
+---
+
+# 🖥️ **C Programming Example — Simple Bounce Simulation**
+
+This uses a time-step loop to simulate the ball in text mode.
+
+```c
+#include <stdio.h>
+
+int main() {
+    double h = 10.0;     // initial height in meters
+    double v = 0.0;      // initial velocity
+    double g = 9.8;      // gravity
+    double e = 0.8;      // coefficient of restitution
+    double dt = 0.01;    // time step (seconds)
+
+    for (int i = 0; i < 5000; i++) {
+        // apply gravity
+        v = v - g * dt;
+
+        // update position
+        h = h + v * dt;
+
+        // bounce
+        if (h < 0) {
+            h = 0;
+            v = -v * e;
+        }
+
+        printf("time = %.2f s, height = %.3f m, velocity = %.3f m/s\n",
+               i * dt, h, v);
+    }
+
+    return 0;
+}
+```
+
+This produces output like:
+
+```
+time = 0.00 s, height = 9.999 m, velocity = -0.098 m/s
+time = 0.01 s, height = 9.997 m, velocity = -0.196 m/s
+...
+Bounce!
+...
+```
+
+A very realistic-looking bounce.
+
+---
+
+# 🖥️ **C Example — Detecting Ground Collision Inside a Loop**
+
+```c
+if (h <= 0) {
+    h = 0;
+    v = -v * e;   // reverse and reduce velocity
+}
+```
+
+This is the typical “bounce line” used in game loops.
+
+---
+
+# 🖥️ **C Example — Continuous Simulation with ASCII Display**
+
+```c
+#include <stdio.h>
+#include <unistd.h>
+
+int main() {
+    double h = 20.0;
+    double v = 0.0;
+    double g = 9.8;
+    double e = 0.85;
+    double dt = 0.02;
+
+    while (1) {
+        v = v - g * dt;
+        h = h + v * dt;
+
+        if (h < 0) {
+            h = 0;
+            v = -v * e;
+        }
+
+        int screen_height = 25;
+        int pos = (int)(screen_height - h);
+
+        printf("\033[2J\033[1;1H");  // clear screen
+        for (int i = 0; i < pos; i++) printf("\n");
+        printf("   o\n");  // the ball
+        fflush(stdout);
+
+        usleep(20000);
+    }
+}
+```
+
+This animates the bouncing ball in your terminal.
+
+---
+
+# 🎯 Summary
+
+| Concept                     | Equation                                   |
+| --------------------------- | ------------------------------------------ |
+| Gravity acceleration        | (v = v - g \cdot dt)                       |
+| Position update             | (h = h + v \cdot dt)                       |
+| Bounce                      | (v = -e v)                                 |
+| New max height after bounce | (h_{\text{after}} = e^2 h_{\text{before}}) |
+
+This combination gives a physically accurate bouncing ball.
+
+---
+
+If you want, I can also show:
+
+* horizontal + vertical motion (parabolic bounce)
+* collisions with walls
+* 2D physics with vectors
+* full game loop frameworks for SDL, Raylib, or OpenGL
diff --git a/bounce/docs/formulas.adoc b/bounce/docs/formulas.adoc
new file mode 100644 (file)
index 0000000..d106b7e
--- /dev/null
@@ -0,0 +1,32 @@
+:stem: latexmath
+:source-highlighter: pygments
+:pygments-style: monokai
+:wrap: normal
+
+= Formulas
+
+* velocity downward
+    - stem:[v = g t]
+
+* height 
+    - stem:[h = h_0 - \frac{1}{2}t^2]
+
+* how long any object takes to fall from a given height
+    - stem:[t = \sqrt{\frac{2h}{g}}]
+
+* restitution
+    - stem:[v_1 = e * v_0]
+
+* rising
+    - stem:[ v = e * v - g t ]
+
+* falling
+    - stem:[ v = g t ]
+
+NOTE: the coefficent of restitution (e) represents energy loss.
+
+Typical values for restitution:
+
+* Rubber ball: stem:[e \approx 0.8 - 0.9]
+* Basketball: stem:[e \approx 0.75]
+* Tennis ball: stem:[e \approx 0.6]
diff --git a/bounce/docs/formulas.html b/bounce/docs/formulas.html
new file mode 100644 (file)
index 0000000..30e9175
--- /dev/null
@@ -0,0 +1,564 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 2.0.20">
+<title>Formulas</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
+/* Uncomment the following line when using as a custom stylesheet */
+/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
+html{font-family:sans-serif;-webkit-text-size-adjust:100%}
+a{background:none}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+b,strong{font-weight:bold}
+abbr{font-size:.9em}
+abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
+dfn{font-style:italic}
+hr{height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+audio,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type=checkbox],input[type=radio]{padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,::before,::after{box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:0}
+p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.square{list-style-type:square}
+ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt{background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+:not(pre).nobreak{word-wrap:normal}
+:not(pre).nowrap{white-space:nowrap}
+:not(pre).pre-wrap{white-space:pre-wrap}
+:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
+pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
+pre>code{display:block}
+pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #e7e7e9}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+details{margin-left:1.25rem}
+details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
+details>summary::-webkit-details-marker{display:none}
+details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
+details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
+details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
+.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
+@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
+.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
+.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.prettyprint{background:#f7f7f8}
+pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
+pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
+pre.prettyprint li code[data-lang]::before{opacity:1}
+pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
+table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
+table.linenotable td.code{padding-left:.75em}
+table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
+pre.pygments span.linenos{display:inline-block;margin-right:.75em}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
+.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
+.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
+.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
+.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
+td.tableblock>.content>:last-child{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>*>tr>*{border-width:1px}
+table.grid-cols>*>tr>*{border-width:0 1px}
+table.grid-rows>*>tr>*{border-width:1px 0}
+table.frame-all{border-width:1px}
+table.frame-ends{border-width:1px 0}
+table.frame-sides{border-width:0 1px}
+table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
+table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
+table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
+table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
+table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+li>p:empty:only-child::before{content:"";display:inline-block}
+ul.checklist>li>p:first-child{margin-left:-1em}
+ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
+ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+td.hdlist2{word-wrap:anywhere}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
+.imageblock.left{margin:.25em .625em 1.25em 0}
+.imageblock.right{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background:#00fafa}
+.black{color:#000}
+.black-background{background:#000}
+.blue{color:#0000bf}
+.blue-background{background:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background:#fa00fa}
+.gray{color:#606060}
+.gray-background{background:#7d7d7d}
+.green{color:#006000}
+.green-background{background:#007d00}
+.lime{color:#00bf00}
+.lime-background{background:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background:#7d0000}
+.navy{color:#000060}
+.navy-background{background:#00007d}
+.olive{color:#606000}
+.olive-background{background:#7d7d00}
+.purple{color:#600060}
+.purple-background{background:#7d007d}
+.red{color:#bf0000}
+.red-background{background:#fa0000}
+.silver{color:#909090}
+.silver-background{background:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]{border-bottom:1px dotted}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#header,#content,#footnotes,#footer{max-width:none}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+</head>
+<body class="article">
+<div id="header">
+<h1>Formulas</h1>
+</div>
+<div id="content">
+<div class="ulist">
+<ul>
+<li>
+<p>velocity downward</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\(v = g t\)</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>height</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\(h = h_0 - \frac{1}{2}t^2\)</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>how long any object takes to fall from a given height</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\(t = \sqrt{\frac{2h}{g}}\)</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>restitution</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\(v_1 = e * v_0\)</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>rising</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\( v = e * v - g t \)</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>falling</p>
+<div class="ulist">
+<ul>
+<li>
+<p>\( v = g t \)</p>
+</li>
+</ul>
+</div>
+</li>
+</ul>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">
+the coefficent of restitution (e) represents energy loss.
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>Typical values for restitution:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Rubber ball: \(e \approx 0.8 - 0.9\)</p>
+</li>
+<li>
+<p>Basketball: \(e \approx 0.75\)</p>
+</li>
+<li>
+<p>Tennis ball: \(e \approx 0.6\)</p>
+</li>
+</ul>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2025-12-23 12:07:18 -0500
+</div>
+</div>
+<script type="text/x-mathjax-config">
+MathJax.Hub.Config({
+  messageStyle: "none",
+  tex2jax: {
+    inlineMath: [["\\(", "\\)"]],
+    displayMath: [["\\[", "\\]"]],
+    ignoreClass: "nostem|nolatexmath"
+  },
+  asciimath2jax: {
+    delimiters: [["\\$", "\\$"]],
+    ignoreClass: "nostem|noasciimath"
+  },
+  TeX: { equationNumbers: { autoNumber: "none" } }
+})
+MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
+  MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
+    if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
+      data.math.root.display = "block"
+    }
+    return data
+  })
+})
+</script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/collisions/Makefile b/collisions/Makefile
new file mode 100644 (file)
index 0000000..0ddb263
--- /dev/null
@@ -0,0 +1,11 @@
+LIBS = -lSDL2 -lSDL2_ttf -lm
+
+PROG = balls
+
+build: $(PROG).c
+       gcc -g -o $(PROG) $(PROG).c $(LIBS)
+
+clean:
+       rm -rf $(PROG)
+
+.PHONY: clean
diff --git a/collisions/balls b/collisions/balls
new file mode 100755 (executable)
index 0000000..2ed592f
Binary files /dev/null and b/collisions/balls differ
diff --git a/collisions/balls.c b/collisions/balls.c
new file mode 100644 (file)
index 0000000..d4f1ed7
--- /dev/null
@@ -0,0 +1,622 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <stdint.h>
+#include <math.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <SDL2/SDL_rect.h>
+#include <SDL2/SDL_ttf.h>
+#include <SDL2/SDL.h>
+
+#define METER_AS_PIXELS 3779U
+#define BALL_COUNT 30
+
+// (BALL_COUNT * (BALL_COUNT - 1)) / 2
+// #define BALL_DISTINCT_UNORDERED_PAIRS 435
+
+#define END(check, str1, str2) \
+    if (check) { \
+        assert(check); \
+        fprintf(stderr, "%s\n%s", str1, str2); \
+        exit(1); \
+    } \
+
+#define SDL_main main
+
+typedef struct _Ball {
+    float px, py, vx, vy, ax, ay;
+    float radius;
+    uint8_t color;
+    float mass;
+} Ball;
+
+typedef struct _Mouse {
+    SDL_Point p;
+    bool down;
+    uint8_t button;
+} Mouse;
+
+typedef struct _Game {
+    SDL_Renderer *renderer;
+    SDL_Surface *backbuffer;
+    SDL_Window *window;
+    const SDL_Rect screen_rect;
+    Ball balls[BALL_COUNT];
+    uint32_t fps;
+    float terminal_velocity;
+    uint8_t ball_size_min;
+    uint8_t ball_size_max;
+    Ball **balls_colliding;
+    uint8_t collision_count;
+} Game;
+
+
+typedef uint8_t (*Update_callback) (Game *game, 
+                                    float seconds, 
+                                    uint32_t milliseconds,
+                                    SDL_KeyCode key,
+                                    Mouse mouse,
+                                    bool keydown);
+
+enum {UPDATE_MAIN, UPDATE_NOTHING};
+
+// Make sure last color is always black
+enum {COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_ORANGE, COLOR_GREY,
+      COLOR_PURPLE, COLOR_NEON_GREEN, COLOR_PINK, COLOR_YELLOW, COLOR_WHITE, 
+      COLOR_BLACK, COLOR_SIZE};
+
+const SDL_Color colors[] = {
+    [COLOR_RED] = {.r = 217, .g = 100, .b = 89, .a = 255},
+    [COLOR_GREEN] = {.r = 88, .g = 140, .b = 126, .a = 255},
+    [COLOR_BLUE] = {.r = 39, .g = 211, .b = 245, .a = 255},
+    [COLOR_ORANGE] = {.r = 242, .g = 174, .b = 114, .a = 255},
+    [COLOR_GREY] = {.r = 89, .g = 89, .b = 89, .a = 89},
+    [COLOR_YELLOW] = {.r = 230, .g = 240, .b = 0, .a = 255},
+    [COLOR_PINK] = {.r = 245, .g = 39, .b = 108, .a = 255},
+    [COLOR_NEON_GREEN] = {.r = 39, .g = 245, .b = 176, .a = 255},
+    [COLOR_PURPLE] = {.r = 176, .g = 39, .b = 245, .a = 255},
+    [COLOR_WHITE] = {.r = 255, .g = 255, .b = 255, .a = 255},
+    [COLOR_BLACK] = {.r = 0, .g = 0, .b = 0, .a = 0},
+};
+
+void
+setColor(SDL_Renderer *renderer,
+         uint8_t color)
+{
+
+    SDL_SetRenderDrawColor(renderer, colors[color].r, colors[color].g,
+                           colors[color].b, colors[color].a);
+}
+
+float getHyp(float x1, float y1, float x2, float y2) {
+    return sqrtf((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+}
+
+bool ballCollide(Ball b1,
+                 Ball b2)
+{
+    return fabs((b1.px - b2.px) * (b1.px - b2.px) +
+           (b1.py - b2.py) * (b1.py - b2.py)) <=
+           (b1.radius + b2.radius) * (b1.radius + b2.radius);
+}
+
+bool pointInBall(Ball b,
+                 SDL_Point p)
+{
+    return fabs((b.px - p.x) * (b.px - p.x) + (b.py - p.y) * (b.py - p.y))
+           <= (b.radius * b.radius);
+}
+
+void
+drawCircle(SDL_Renderer *renderer,
+           SDL_Rect border,
+           float radius,
+           int px,
+           int py,
+           int w,
+           uint8_t color)
+{
+    
+    float x = 0;
+    float y = 0;
+    for(float i = 0; i < 2 * M_PI; i += 0.001f)
+    {
+        x = cosf(i);
+        y = sinf(i);
+        int rx = (x * radius);
+        int ry = (y * radius);
+        int tx = rx + px;
+        int ty = ry + py;
+        // wraping
+        // This works except in case where a ball is in the corner. Than the
+        // ball will apear in all four courners
+        // SDL_Rect point = {
+        //     .x = (tx > border.w) ? tx -= border.w : (tx < 0) ? tx += border.w : tx, 
+        //     .y = (ty > border.h) ? ty -= border.h : (ty < 0) ? ty += border.h : ty, 
+        //     w, 
+        //     w
+        // };
+        SDL_Rect point = {
+            .x = tx, 
+            .y = ty, 
+            w, 
+            w
+        };
+        setColor(renderer, color);
+        SDL_RenderFillRect(renderer, &point);
+    }
+}
+
+void
+drawBall(SDL_Renderer *renderer,
+         Ball ball)
+// (x - h)^2 + (y - k)^2 = r^2
+// Drawing a circle with the standard circle formula.
+// There may be a more performant way to do this...
+{
+    setColor(renderer, ball.color);
+
+    // diameter is radius * 2
+    for (int x = 0; x < ball.radius * 2; x++) {
+        for (int y = 0; y < ball.radius * 2; y++) {
+          if ( ((x - ball.radius) * (x - ball.radius)) +
+               ((y - ball.radius) * (y - ball.radius)) <=
+               ball.radius * ball.radius) {
+            int px = ball.px - ball.radius + x;
+            int py = ball.py - ball.radius + y;
+
+            // TODO: wrap circle around screen
+            SDL_RenderDrawPoint(renderer, px, py);
+
+          }
+        }
+    }
+}
+
+void
+drawBall2(SDL_Surface *surface,
+          Ball ball)
+// (x - h)^2 + (y - k)^2 = r^2
+// Drawing a circle with the standard circle formula.
+// There may be a more performant way to do this...
+{
+    // setColor(renderer, ball.color);
+
+    // diameter is radius * 2
+    for (int x = 0; x < ball.radius * 2; x++) {
+        for (int y = 0; y < ball.radius * 2; y++) {
+          if ( ((x - ball.radius) * (x - ball.radius)) +
+               ((y - ball.radius) * (y - ball.radius)) <=
+               ball.radius * ball.radius) {
+            int px = ball.px - ball.radius + x;
+            int py = ball.py - ball.radius + y;
+
+            // TODO: wrap circle around screen
+            // SDL_RenderDrawPoint(renderer, px, py);
+            SDL_Rect r = {.x = px, .y = py, .w = 1, .h = 1};
+            uint32_t color = 
+                ((colors[ball.color].r << 24) | (colors[ball.color].g << 16) |
+                 (colors[ball.color].b << 8) | colors[ball.color].a);
+            SDL_FillRect(surface, &r, color);
+
+          }
+        }
+    }
+}
+
+float clamp(float v,
+            float min,
+            float max) {
+    if (v < min) return min;
+    if (v > max) return max;
+    return v;
+}
+
+bool circleRectCollide(SDL_Point circle,
+                       float r,
+                       SDL_Rect rect)
+{
+    float closestX = clamp(circle.x, rect.x, rect.x + rect.w);
+    float closestY = clamp(circle.y, rect.y, rect.y + rect.h);
+
+    // this gets the distance form the center of the circle to a side of a
+    // rectangle. It could be negative or positive. Because we are squaring them
+    // it doesn't matter.
+    float dx = circle.x - closestX;
+    float dy = circle.y - closestY;
+
+    // use the dot product to determine collision
+    return (dx*dx + dy*dy) <= (r*r);
+}
+
+
+static uint8_t
+updateNothing(Game *game,
+           float seconds,
+           uint32_t milliseconds,
+           SDL_KeyCode key,
+           Mouse mouse,
+           bool keydown)
+{
+    return UPDATE_NOTHING;
+}
+
+void
+worldBoundry(Game *game, Ball *ball)
+{
+    int padding = 1;
+
+    if (ball->px - ball->radius <= 0) {
+        ball->px = ball->radius + padding;
+    }
+
+    if (ball->py - ball->radius <= 0) {
+        ball->py = ball->radius + padding;
+    }
+
+    if (ball->px + ball->radius >= game->screen_rect.w) {
+        ball->px = game->screen_rect.w - ball->radius - padding;
+    }
+
+    if (ball->py + ball->radius >= game->screen_rect.h) {
+        ball->py = game->screen_rect.h - ball->radius - padding;
+    }
+}
+
+void
+drawCursor(SDL_Renderer *renderer, SDL_Point p) {
+    SDL_Rect r = {
+        .x = p.x - 5,
+        .y = p.y - 5,
+        .w = 15,
+        .h = 15
+    };
+    setColor(renderer, COLOR_WHITE);
+    SDL_RenderFillRect(renderer, &r);
+}
+
+static uint8_t
+updateMain(Game *game,
+           float seconds,
+           uint32_t milliseconds,
+           SDL_KeyCode key,
+           Mouse mouse,
+           bool keydown)
+{
+    static float elapsedTime = 0;
+    static int selected = -1;
+
+    // Ball *colliding[BALL_DISTINCT_UNORDERED_PAIRS] = {0};
+    game->balls_colliding  = NULL;
+    game->collision_count = 0;
+
+
+    // game->ball_distinct_unordered_pairs is the total number of possible
+    // collisions, it is multiplied was two because there needed to be two values
+    // for each collision, a ball at the target ball
+
+    // TODO
+    // Add a middle click feature that lets you look around. Then you could see
+    // balls that went off screen
+
+    // NOTE:
+    // issues arise when mouse movement is too fast
+    // don't check mouse click more than needed
+    if(mouse.button == SDL_BUTTON_LEFT && (selected < 0)) {
+        for (int i = 0; i < BALL_COUNT; ++i) {
+            Ball *b = &game->balls[i];
+            if (pointInBall(*b, mouse.p)) selected = i;
+        }
+    }
+
+    if((!mouse.down) && (mouse.button == SDL_BUTTON_RIGHT) && (selected >= 0)) {
+        Ball *b = &game->balls[selected];
+        b->vx = 5.0f * (b->px - (float)mouse.p.x);
+        b->vy = 5.0f * (b->py - (float)mouse.p.y);
+    }
+
+    if (!mouse.down) selected = -1;
+
+    if(selected >= 0 && mouse.button != SDL_BUTTON_RIGHT) {
+        elapsedTime = 0;
+        Ball *b = &game->balls[selected];
+        b->px = mouse.p.x;
+        b->py = mouse.p.y;
+    }  
+
+    for (int i = 0; i < BALL_COUNT; ++i) {
+        Ball *b1 = &game->balls[i];
+        // drag
+        b1->ax = -b1->vx * 0.8f;
+        b1->ay = -b1->vy * 0.8f;
+
+        b1->vx += b1->ax * elapsedTime;
+        b1->vy += b1->ay * elapsedTime;
+        b1->px += b1->vx * elapsedTime;
+        b1->py += b1->vy * elapsedTime;
+
+        // wrap around screen
+        // Looks really bad, I'm removing this
+        // if (b1->px < 0) b1->px += (float)game->screen_rect.w;
+        // if (b1->px >= game->screen_rect.w) b1->px -= (float)game->screen_rect.w;
+        // if (b1->py < 0) b1->py += (float)game->screen_rect.h;
+        // if (b1->py >= game->screen_rect.h) b1->py -= (float)game->screen_rect.h;
+
+        if (fabs(b1->vx * b1->vx + b1->vy * b1->vy) < 0.01f) {
+            b1->vx = 0;
+            b1->vy = 0;
+        }
+
+    }
+
+    setColor(game->renderer, COLOR_BLACK);
+    SDL_RenderClear(game->renderer);
+
+    for (int i = 0; i < BALL_COUNT; ++i) {
+        Ball *b1 = &game->balls[i];
+        if (i == selected) drawBall(game->renderer, *b1);
+        else drawCircle(game->renderer, game->screen_rect, b1->radius, b1->px,
+                        b1->py, 2, b1->color);
+        
+    }
+
+    // TODO
+    // set up a list of values that will not conflict for i and j in gameInit
+
+    // TODO
+    // there is an error were the collision_count varaible will not reset to
+    // zero
+    for (int i = 0; i < BALL_COUNT; ++i) {
+        Ball *b1 = &game->balls[i];
+
+        for (int j = i + 1; j < BALL_COUNT; ++j) {
+            Ball *b2 = &game->balls[j];
+
+            if (!ballCollide(*b1, *b2)) continue;
+                game->balls_colliding = calloc(sizeof(Ball *),
+                                        (game->collision_count + 2));
+                END((!game->balls_colliding), "calloc()", "could not allocate game->balls_colliding()" );
+                game->balls_colliding[game->collision_count++] = b1;
+                game->balls_colliding[game->collision_count++] = b2;
+                float distance = fabs(getHyp(b1->px, b1->py, b2->px, b2->py));
+
+                float overlap = (distance - b1->radius - b2->radius);
+
+                if (distance == 0) continue;
+
+                b1->px -= overlap * (b1->px - b2->px) / distance;
+                b1->py -= overlap * (b1->py - b2->py) / distance;
+                b2->px += overlap * (b1->px - b2->px) / distance;
+                b2->py += overlap * (b1->py - b2->py) / distance;
+            // }
+        }
+    }
+    // printf("collision count: %d\n", game->collision_count);
+    for (int i = 0; i < game->collision_count; ++i) {
+        Ball *b1 = game->balls_colliding[i];
+        Ball *b2 = game->balls_colliding[i + 1];
+        if (!b1 || !b2) continue;
+        float distance = getHyp(b1->px, b1->py, b2->px, b2->py);
+
+        // normal
+        float nx = (b2->px - b1->px) / distance;
+        float ny = (b2->py - b1->py) / distance;
+
+        // tangent
+        float tx = -ny;
+        float ty = nx;
+
+        float dpTan1 = b1->vx * tx + b1->vy * ty;
+        float dpTan2 = b2->vx * tx + b2->vy * ty;
+
+        float dpNorm1 = b1->vx * nx + b1->vy * ny;
+        float dpNorm2 = b2->vx * nx + b2->vy * ny;
+
+        float m1 =
+            (dpNorm1 * (b1->mass - b2->mass) + 2.0f * b2->mass * dpNorm2)
+            / (b1->mass + b2->mass);
+
+        float m2 =
+            (dpNorm2 * (b2->mass - b1->mass) + 2.0f * b1->mass * dpNorm1)
+            / (b1->mass + b2->mass);
+
+        b1->vx = tx * dpTan1 + nx * m1;
+        b1->vy = ty * dpTan1 + ny * m1;
+        b2->vx = tx * dpTan2 + nx * m2;
+        b2->vy = ty * dpTan2 + ny * m2;
+        
+    }
+
+    if((mouse.down) && (mouse.button == SDL_BUTTON_RIGHT) && (selected >= 0)) {
+        Ball *b = &game->balls[selected];
+        setColor(game->renderer, COLOR_WHITE);
+        SDL_RenderDrawLine(game->renderer, b->px, b->py, mouse.p.x, mouse.p.y);
+    }
+    if (selected < 0) drawCursor(game->renderer, mouse.p);
+
+    if (game->collision_count > 0)  {
+        // I do not have free each individual ball in ball colliding because
+        // they are all on the stack
+        free(game->balls_colliding);
+        game->balls_colliding = NULL;
+    }
+
+    elapsedTime += 0.0008f;
+
+    return UPDATE_MAIN;
+}
+
+void
+Game_Update(Game *game)
+// The main game loop. Sets up which callback will be used in the function loop.
+// Each update callback determines what update callback will be called next by
+// returning the appropriate enum value
+{
+    uint8_t update_id = 0;
+    uint64_t frame = 0;
+    bool quit = false;
+    bool keydown = false;
+    float mspf = (1.0f / (float)game->fps) * 1000.0f;
+    SDL_Event event;
+    SDL_KeyCode key = 0;
+    Update_callback update;
+    uint32_t ticks_start = SDL_GetTicks();
+    Mouse mouse;
+
+    // TODO
+    // add backbuffer
+
+    while (!quit) {
+
+        // Place update functions here
+        switch (update_id) {
+            case UPDATE_MAIN: update = updateMain; break;
+            case UPDATE_NOTHING: update = updateNothing; break;
+        }
+
+        while (SDL_PollEvent(&event)) {
+
+            switch (event.type) {
+                case SDL_KEYDOWN: {
+                    if (event.key.repeat == 0) {
+                      key = event.key.keysym.sym;
+                      keydown = true;
+                    }
+
+                    break;
+                }
+                case SDL_MOUSEBUTTONDOWN: {
+                    mouse.button = event.button.button;
+                    mouse.down = true;
+                    break;
+                }
+                case SDL_MOUSEBUTTONUP: {
+                    mouse.button = event.button.button;
+                    mouse.down = false;
+                    break;
+                }
+                case SDL_MOUSEMOTION: {
+                    mouse.p.x = event.motion.x;
+                    mouse.p.y = event.motion.y;
+                    break;
+                }
+
+                case SDL_KEYUP: keydown = false; break;
+                case SDL_QUIT: quit = true; break;
+            }
+        }
+
+        update_id = update(game, SDL_GetTicks(), frame, key, mouse,keydown);
+
+        if ((SDL_GetTicks() - ticks_start) >= mspf) {
+            ticks_start = SDL_GetTicks();
+            // SDL_SetRenderDrawBlendMode(game->renderer, SDL_BLENDMODE_NONE);
+            // SDL_Texture *texture =
+            //     SDL_CreateTextureFromSurface(game->renderer, game->backbuffer);
+            // SDL_RenderCopyEx(game->renderer, texture, NULL, &game->screen_rect,
+            //                 0, NULL, SDL_FLIP_NONE);
+            SDL_RenderPresent(game->renderer);
+            // SDL_DestroyTexture(texture);
+        }
+
+        frame++;
+    }
+}
+
+void createBalls(Game *game) {
+    for (int i = 0; i < BALL_COUNT; ++i) {
+        Ball *b = &game->balls[i];
+        b->vx = 0;
+        b->vy = 0;
+        b->ax = 0;
+        b->ay = 0;
+        b->radius = ((rand() / (float)RAND_MAX) * (game->ball_size_max -
+                    game->ball_size_min)) + game->ball_size_min;
+
+        b->px = (rand() / (float)RAND_MAX) * (float)game->screen_rect.w;
+
+        b->py = (rand() / (float)RAND_MAX) * (float)game->screen_rect.h;
+
+        b->color = (rand() / (float)RAND_MAX) * ((float)COLOR_SIZE - 2);
+
+        b->mass = b->radius * 10;
+    }
+
+}
+
+Game *
+Game_Init()
+// All the variable and data initialization needed for SDL and perhaps game
+// variables
+{
+    static Game game = {
+        .screen_rect = {.x = 0, .y = 0, .w = 800, .h = 800},
+        .fps = 60,
+        .ball_size_min = 15,
+        .ball_size_max = 50,
+        .backbuffer = NULL,
+    };
+
+    END(SDL_Init(SDL_INIT_VIDEO) != 0, "Could not create texture",
+        SDL_GetError());
+
+    END(TTF_Init() != 0, "Could not initialize TTF", TTF_GetError());
+
+
+
+    game.window = SDL_CreateWindow("balls", SDL_WINDOWPOS_UNDEFINED, 
+                     SDL_WINDOWPOS_UNDEFINED, game.screen_rect.w, 
+                     game.screen_rect.h, SDL_WINDOW_SHOWN);
+
+    END(game.window == NULL, "Could not create window", SDL_GetError());
+
+    game.renderer =
+        SDL_CreateRenderer(game.window, 0, SDL_RENDERER_ACCELERATED);
+
+    END(game.renderer == NULL, "Could not create renderer", SDL_GetError());
+
+    SDL_SetRelativeMouseMode(true);
+
+    // setColor(game->backbuffer, COLOR_BLACK);
+    // SDL_RenderClear(game->renderer);
+    game.backbuffer = 
+            SDL_CreateRGBSurface(0, game.screen_rect.w, game.screen_rect.h, 
+                                 32, 0xFF000000, 0x00FF0000, 0x0000FF00,
+                                 0x000000FF);
+    // fill backbuffer with black
+    SDL_FillRect(game.backbuffer, &game.screen_rect, 0x00000000);
+
+    // print system information
+    printf("big ending = %s\n", SDL_BYTEORDER == SDL_BIG_ENDIAN ? 
+                                "true": "False");
+
+    srand(time(NULL));
+    createBalls(&game);
+
+    return &game;
+}
+
+void
+Game_Quit(Game *game)
+{
+    if (game->collision_count > 0)  {
+        free(game->balls_colliding);
+        game->balls_colliding = NULL;
+    }
+    SDL_DestroyWindow(game->window);
+    SDL_DestroyRenderer(game->renderer);
+    SDL_FreeSurface(game->backbuffer);
+    TTF_Quit();
+    SDL_Quit();
+}
+
+int
+main(void)
+{
+    Game *game = Game_Init();
+    Game_Update(game);
+    Game_Quit(game);
+    return 0;
+}
diff --git a/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes.adoc b/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes.adoc
new file mode 100644 (file)
index 0000000..2f303ba
--- /dev/null
@@ -0,0 +1,192 @@
+= Why Your Collision-Resolution Loop Freezes and How to Fix It
+:wrap: normal
+
+[source,c]
+----
+for (int i = 0; i < BALL_COUNT; ++i) {
+    Ball *b1 = &game->balls[i];
+
+    for (int j = i + 1; j < BALL_COUNT; ++j) {
+        Ball *b2 = &game->balls[j];
+
+        if (!ballCollide(*b1, *b2)) continue;
+            colliding = calloc(sizeof(Ball *), (collision_count + 2));
+            END((!colliding), "calloc()", "could not allocate colliding()" );
+            colliding[collision_count++] = b1;
+            colliding[collision_count++] = b2;
+            float distance = getHyp(b1->px, b1->py, b2->px, b2->py);
+
+            float overlap = 0.5f * (distance - (float)b1->radius -
+                            (float)b2->radius);
+            b1->px -= 
+                overlap * (float)(b1->px - b2->px) / distance;
+            b1->py -= 
+                overlap * (float)(b1->py - b2->py) / distance;
+            b2->px += 
+                overlap * (float)(b1->px - b2->px) / distance;
+            b2->py += 
+                overlap * (float)(b1->py - b2->py) / distance;
+
+        // all collisions must be resolved
+        // TODO
+        // fix issue that freezes program from this loop
+        while(ballCollide(*b1, *b2)) {
+            b1->px -= (float)(b1->px - b2->px) / distance;
+            b1->py -= (float)(b1->py - b2->py) / distance;
+            b2->px += (float)(b1->px - b2->px) / distance;
+            b2->py += (float)(b1->py - b2->py) / distance;
+        }
+    }
+}
+----
+
+Your code contains the classic problem of **over-correcting** and then
+**rechecking using new positions**, which makes the loop never terminate.
+Let’s walk through why this happens and how to fix it.
+
+
+== 1. The critical problem: using updated positions inside the loop
+
+Inside your main collision-resolution:
+
+[source,c]
+----
+b1->px -= overlap * (b1->px - b2->px) / distance;
+b1->py -= overlap * (b1->py - b2->py) / distance;
+b2->px += overlap * (b1->px - b2->px) / distance;
+b2->py += overlap * (b1->py - b2->py) / distance;
+----
+
+This is correct.
+
+But then you do:
+
+[source,c]
+----
+while (ballCollide(*b1, *b2)) {
+    b1->px -= (b1->px - b2->px) / distance;
+    b1->py -= (b1->py - b2->py) / distance;
+    b2->px += (b1->px - b2->px) / distance;
+    b2->py += (b1->py - b2->py) / distance;
+}
+----
+
+== ❌ Why this freezes
+
+1. `distance` stays the **old** value (before modifying positions).
+2. But `(b1->px - b2->px)` is updated each iteration.
+3. This causes steps that:
+   * overshoot  
+   * oscillate  
+   * sometimes increase overlap instead of decreasing it  
+4. So `ballCollide()` keeps returning true forever → **infinite loop**.
+
+This is a well-known bug in naive iterative separation.
+
+== 2. Mathematical explanation
+
+Your update step behaves like:
+
+  x ← x − (x / constant)
+
+This only converges to zero if:
+  
+  |1 − 1/constant| < 1
+
+But because the denominator (`distance`) is incorrect after the first
+shift, the term can jump back and forth.
+
+In other words:
+
+You are using a **fixed-length correction step based on old geometry**,
+but applying it to **new geometry**.
+
+This makes the correction unstable.
+
+
+== 3. Proper fix: recompute distance each iteration OR limit iterations
+
+Method A — Recompute distance every pass:
+
+[source,c]
+----
+int loop_guard = 0;
+while (ballCollide(*b1, *b2) && loop_guard++ < 4) {
+    float dx = b1->px - b2->px;
+    float dy = b1->py - b2->py;
+    float d  = sqrtf(dx*dx + dy*dy);
+
+    if (d == 0) break;
+
+    float overlap = 0.5f * (d - b1->radius - b2->radius);
+    float nx = dx / d;
+    float ny = dy / d;
+
+    b1->px -= overlap * nx;
+    b1->py -= overlap * ny;
+    b2->px += overlap * nx;
+    b2->py += overlap * ny;
+}
+----
+
+Why this works:
+
+* `dx`, `dy`, and `distance` are recalculated from the new positions.  
+* The correction scales perfectly with the current geometry.  
+* The loop is guaranteed to converge.
+
+Method B — Avoid loops entirely  
+Just do **one correction step per frame**, which is how most engines and
+the Jonathan Blow code handle it.
+
+== 4. Even better fix: use Blow’s displacement formula directly
+
+His code displaces balls only **once** per collision pass:
+
+[source,c]
+----
+float fDistance = sqrtf(dx*dx + dy*dy);
+float fOverlap = 0.5f * (fDistance - r1 - r2);
+
+b1->px -= fOverlap * (dx / fDistance);
+b1->py -= fOverlap * (dy / fDistance);
+
+b2->px += fOverlap * (dx / fDistance);
+b2->py += fOverlap * (dy / fDistance);
+----
+
+This resolves overlap in **one stable pass**, so you don’t need a loop.
+
+== 5. Bonus: Your calloc() usage is also wrong
+
+You do:
+
+[source,c]
+----
+colliding = calloc(sizeof(Ball *), (collision_count + 2));
+----
+
+Correct `calloc` order is:
+
+  calloc(num_elements, element_size)
+
+So you should use:
+
+[source,c]
+----
+colliding = calloc(collision_count + 2, sizeof(Ball *));
+----
+
+== 6. Final Summary
+
+* The infinite loop comes from using **outdated distance values** while
+  updating positions.
+* This causes oscillation → `ballCollide()` never returns false.
+* Fixes:
+  - recompute distance each iteration, or  
+  - apply the correct one-shot overlap resolution (recommended).  
+* Also fix your `calloc` order.
+
+If you want, I can rewrite your entire collision loop into a clean,
+correct, minimal version similar to Jonathan Blow’s system.
+
diff --git a/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes.html b/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes.html
new file mode 100644 (file)
index 0000000..371d920
--- /dev/null
@@ -0,0 +1,738 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 2.0.20">
+<title>Why Your Collision-Resolution Loop Freezes and How to Fix It</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
+/* Uncomment the following line when using as a custom stylesheet */
+/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
+html{font-family:sans-serif;-webkit-text-size-adjust:100%}
+a{background:none}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+b,strong{font-weight:bold}
+abbr{font-size:.9em}
+abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
+dfn{font-style:italic}
+hr{height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+audio,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type=checkbox],input[type=radio]{padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,::before,::after{box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:0}
+p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.square{list-style-type:square}
+ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt{background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+:not(pre).nobreak{word-wrap:normal}
+:not(pre).nowrap{white-space:nowrap}
+:not(pre).pre-wrap{white-space:pre-wrap}
+:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
+pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
+pre>code{display:block}
+pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #e7e7e9}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+details{margin-left:1.25rem}
+details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
+details>summary::-webkit-details-marker{display:none}
+details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
+details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
+details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
+.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
+@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
+.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
+.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.prettyprint{background:#f7f7f8}
+pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
+pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
+pre.prettyprint li code[data-lang]::before{opacity:1}
+pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
+table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
+table.linenotable td.code{padding-left:.75em}
+table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
+pre.pygments span.linenos{display:inline-block;margin-right:.75em}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
+.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
+.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
+.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
+.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
+td.tableblock>.content>:last-child{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>*>tr>*{border-width:1px}
+table.grid-cols>*>tr>*{border-width:0 1px}
+table.grid-rows>*>tr>*{border-width:1px 0}
+table.frame-all{border-width:1px}
+table.frame-ends{border-width:1px 0}
+table.frame-sides{border-width:0 1px}
+table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
+table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
+table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
+table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
+table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+li>p:empty:only-child::before{content:"";display:inline-block}
+ul.checklist>li>p:first-child{margin-left:-1em}
+ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
+ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+td.hdlist2{word-wrap:anywhere}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
+.imageblock.left{margin:.25em .625em 1.25em 0}
+.imageblock.right{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background:#00fafa}
+.black{color:#000}
+.black-background{background:#000}
+.blue{color:#0000bf}
+.blue-background{background:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background:#fa00fa}
+.gray{color:#606060}
+.gray-background{background:#7d7d7d}
+.green{color:#006000}
+.green-background{background:#007d00}
+.lime{color:#00bf00}
+.lime-background{background:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background:#7d0000}
+.navy{color:#000060}
+.navy-background{background:#00007d}
+.olive{color:#606000}
+.olive-background{background:#7d7d00}
+.purple{color:#600060}
+.purple-background{background:#7d007d}
+.red{color:#bf0000}
+.red-background{background:#fa0000}
+.silver{color:#909090}
+.silver-background{background:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]{border-bottom:1px dotted}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#header,#content,#footnotes,#footer{max-width:none}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+</head>
+<body class="article">
+<div id="header">
+<h1>Why Your Collision-Resolution Loop Freezes and How to Fix It</h1>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">for (int i = 0; i &lt; BALL_COUNT; ++i) {
+    Ball *b1 = &amp;game-&gt;balls[i];
+
+    for (int j = i + 1; j &lt; BALL_COUNT; ++j) {
+        Ball *b2 = &amp;game-&gt;balls[j];
+
+        if (!ballCollide(*b1, *b2)) continue;
+            colliding = calloc(sizeof(Ball *), (collision_count + 2));
+            END((!colliding), "calloc()", "could not allocate colliding()" );
+            colliding[collision_count++] = b1;
+            colliding[collision_count++] = b2;
+            float distance = getHyp(b1-&gt;px, b1-&gt;py, b2-&gt;px, b2-&gt;py);
+
+            float overlap = 0.5f * (distance - (float)b1-&gt;radius -
+                            (float)b2-&gt;radius);
+            b1-&gt;px -=
+                overlap * (float)(b1-&gt;px - b2-&gt;px) / distance;
+            b1-&gt;py -=
+                overlap * (float)(b1-&gt;py - b2-&gt;py) / distance;
+            b2-&gt;px +=
+                overlap * (float)(b1-&gt;px - b2-&gt;px) / distance;
+            b2-&gt;py +=
+                overlap * (float)(b1-&gt;py - b2-&gt;py) / distance;
+
+        // all collisions must be resolved
+        // TODO
+        // fix issue that freezes program from this loop
+        while(ballCollide(*b1, *b2)) {
+            b1-&gt;px -= (float)(b1-&gt;px - b2-&gt;px) / distance;
+            b1-&gt;py -= (float)(b1-&gt;py - b2-&gt;py) / distance;
+            b2-&gt;px += (float)(b1-&gt;px - b2-&gt;px) / distance;
+            b2-&gt;py += (float)(b1-&gt;py - b2-&gt;py) / distance;
+        }
+    }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Your code contains the classic problem of <strong>over-correcting</strong> and then
+<strong>rechecking using new positions</strong>, which makes the loop never terminate.
+Let’s walk through why this happens and how to fix it.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_1_the_critical_problem_using_updated_positions_inside_the_loop">1. The critical problem: using updated positions inside the loop</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Inside your main collision-resolution:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">b1-&gt;px -= overlap * (b1-&gt;px - b2-&gt;px) / distance;
+b1-&gt;py -= overlap * (b1-&gt;py - b2-&gt;py) / distance;
+b2-&gt;px += overlap * (b1-&gt;px - b2-&gt;px) / distance;
+b2-&gt;py += overlap * (b1-&gt;py - b2-&gt;py) / distance;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This is correct.</p>
+</div>
+<div class="paragraph">
+<p>But then you do:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">while (ballCollide(*b1, *b2)) {
+    b1-&gt;px -= (b1-&gt;px - b2-&gt;px) / distance;
+    b1-&gt;py -= (b1-&gt;py - b2-&gt;py) / distance;
+    b2-&gt;px += (b1-&gt;px - b2-&gt;px) / distance;
+    b2-&gt;py += (b1-&gt;py - b2-&gt;py) / distance;
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_why_this_freezes">❌ Why this freezes</h2>
+<div class="sectionbody">
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p><code>distance</code> stays the <strong>old</strong> value (before modifying positions).</p>
+</li>
+<li>
+<p>But <code>(b1&#8594;px - b2&#8594;px)</code> is updated each iteration.</p>
+</li>
+<li>
+<p>This causes steps that:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>overshoot</p>
+</li>
+<li>
+<p>oscillate</p>
+</li>
+<li>
+<p>sometimes increase overlap instead of decreasing it</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>So <code>ballCollide()</code> keeps returning true forever → <strong>infinite loop</strong>.</p>
+</li>
+</ol>
+</div>
+<div class="paragraph">
+<p>This is a well-known bug in naive iterative separation.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_2_mathematical_explanation">2. Mathematical explanation</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Your update step behaves like:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>x ← x − (x / constant)</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This only converges to zero if:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>|1 − 1/constant| &lt; 1</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>But because the denominator (<code>distance</code>) is incorrect after the first
+shift, the term can jump back and forth.</p>
+</div>
+<div class="paragraph">
+<p>In other words:</p>
+</div>
+<div class="paragraph">
+<p>You are using a <strong>fixed-length correction step based on old geometry</strong>,
+but applying it to <strong>new geometry</strong>.</p>
+</div>
+<div class="paragraph">
+<p>This makes the correction unstable.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_3_proper_fix_recompute_distance_each_iteration_or_limit_iterations">3. Proper fix: recompute distance each iteration OR limit iterations</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Method A — Recompute distance every pass:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">int loop_guard = 0;
+while (ballCollide(*b1, *b2) &amp;&amp; loop_guard++ &lt; 4) {
+    float dx = b1-&gt;px - b2-&gt;px;
+    float dy = b1-&gt;py - b2-&gt;py;
+    float d  = sqrtf(dx*dx + dy*dy);
+
+    if (d == 0) break;
+
+    float overlap = 0.5f * (d - b1-&gt;radius - b2-&gt;radius);
+    float nx = dx / d;
+    float ny = dy / d;
+
+    b1-&gt;px -= overlap * nx;
+    b1-&gt;py -= overlap * ny;
+    b2-&gt;px += overlap * nx;
+    b2-&gt;py += overlap * ny;
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Why this works:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>dx</code>, <code>dy</code>, and <code>distance</code> are recalculated from the new positions.</p>
+</li>
+<li>
+<p>The correction scales perfectly with the current geometry.</p>
+</li>
+<li>
+<p>The loop is guaranteed to converge.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Method B — Avoid loops entirely
+Just do <strong>one correction step per frame</strong>, which is how most engines and
+the Jonathan Blow code handle it.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_4_even_better_fix_use_blows_displacement_formula_directly">4. Even better fix: use Blow’s displacement formula directly</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>His code displaces balls only <strong>once</strong> per collision pass:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">float fDistance = sqrtf(dx*dx + dy*dy);
+float fOverlap = 0.5f * (fDistance - r1 - r2);
+
+b1-&gt;px -= fOverlap * (dx / fDistance);
+b1-&gt;py -= fOverlap * (dy / fDistance);
+
+b2-&gt;px += fOverlap * (dx / fDistance);
+b2-&gt;py += fOverlap * (dy / fDistance);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This resolves overlap in <strong>one stable pass</strong>, so you don’t need a loop.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_5_bonus_your_calloc_usage_is_also_wrong">5. Bonus: Your calloc() usage is also wrong</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>You do:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">colliding = calloc(sizeof(Ball *), (collision_count + 2));</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Correct <code>calloc</code> order is:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>calloc(num_elements, element_size)</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>So you should use:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">colliding = calloc(collision_count + 2, sizeof(Ball *));</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_6_final_summary">6. Final Summary</h2>
+<div class="sectionbody">
+<div class="ulist">
+<ul>
+<li>
+<p>The infinite loop comes from using <strong>outdated distance values</strong> while
+updating positions.</p>
+</li>
+<li>
+<p>This causes oscillation → <code>ballCollide()</code> never returns false.</p>
+</li>
+<li>
+<p>Fixes:</p>
+<div class="ulist">
+<ul>
+<li>
+<p>recompute distance each iteration, or</p>
+</li>
+<li>
+<p>apply the correct one-shot overlap resolution (recommended).</p>
+</li>
+</ul>
+</div>
+</li>
+<li>
+<p>Also fix your <code>calloc</code> order.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If you want, I can rewrite your entire collision loop into a clean,
+correct, minimal version similar to Jonathan Blow’s system.</p>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2025-12-23 12:07:18 -0500
+</div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes2.adoc b/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes2.adoc
new file mode 100644 (file)
index 0000000..4c2fcdb
--- /dev/null
@@ -0,0 +1,95 @@
+= Why Recomputing Distance Still Freezes the Loop
+Even when recomputing `distance` inside the loop, it can still freeze. This
+happens when:
+
+* The distance between ball centers becomes **zero or extremely close to zero**.
+* The overlap becomes **very tiny** but never fully resolves because floating-
+  point error prevents the condition from becoming false.
+* The collision logic attempts to normalize a zero-length vector.
+
+Below is the real reason and the correct fix.
+
+== The Real Crash Scenario: Distance == 0
+If two balls overlap **perfectly**, meaning:
+
+----
+b1->px == b2->px
+b1->py == b2->py
+----
+
+Then:
+
+----
+dx = 0
+dy = 0
+distance = sqrt(0 + 0) = 0
+----
+
+Normalizing `(dx, dy)` becomes:
+
+----
+nx = dx / distance  --> division by zero
+----
+
+This produces `NaN`, and once NaNs enter your coordinates, your loop **never
+terminates**, because every test becomes nonsense.
+
+== Why This Happens
+Your simulation allows balls to be pushed so close together (or initialized too
+close) that they fully overlap before you start resolving.
+
+Your while-loop approach *cannot* recover when distance reaches 0.
+
+== The Fix: Replace the Loop With One Guaranteed Separation Step
+Physics engines never use repeated loops; they use one mathematically correct
+position correction.
+
+Here is the correct safe displacement code:
+
+[source,c]
+----
+float dx = b1->px - b2->px;
+float dy = b1->py - b2->py;
+float d2 = dx*dx + dy*dy;
+
+// If centers are identical, push them apart arbitrarily
+if (d2 == 0.0f) {
+    dx = 1.0f;
+    dy = 0.0f;
+    d2 = 1.0f;
+}
+
+float distance = sqrtf(d2);
+float overlap  = (b1->radius + b2->radius) - distance;
+
+if (overlap > 0.0f) {
+    float nx = dx / distance;
+    float ny = dy / distance;
+
+    float half = overlap * 0.5f;
+
+    b1->px += nx * half;
+    b1->py += ny * half;
+
+    b2->px -= nx * half;
+    b2->py -= ny * half;
+}
+----
+
+== Why This Works
+* **No loop**, so it can’t freeze.
+* Handles the `distance == 0` case safely.
+* Fully resolves the overlap mathematically.
+* Guaranteed to stop balls from colliding in a single step.
+* `collision_count` will now drop to zero.
+
+== Summary
+Recomputing distance didn't fix the freeze because the loop becomes invalid
+whenever the distance is zero or extremely tiny.  
+The correct solution is to completely remove the loop and use one safe,
+mathematically correct separation step.
+
+== Want the Full Fixed Version?
+If you want, I can rewrite your entire collision detection and resolution block
+into clean, safe, minimal C code.
+
diff --git a/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes2.html b/collisions/docs/chatgpt_dump/Collision-Resolution-Loop-Freezes2.html
new file mode 100644 (file)
index 0000000..bdd17be
--- /dev/null
@@ -0,0 +1,609 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 2.0.20">
+<meta name="author" content="Even when recomputing `distance` inside the loop, it can still freeze. This">
+<title>Why Recomputing Distance Still Freezes the Loop</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
+/* Uncomment the following line when using as a custom stylesheet */
+/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
+html{font-family:sans-serif;-webkit-text-size-adjust:100%}
+a{background:none}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+b,strong{font-weight:bold}
+abbr{font-size:.9em}
+abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
+dfn{font-style:italic}
+hr{height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+audio,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type=checkbox],input[type=radio]{padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,::before,::after{box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:0}
+p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.square{list-style-type:square}
+ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt{background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+:not(pre).nobreak{word-wrap:normal}
+:not(pre).nowrap{white-space:nowrap}
+:not(pre).pre-wrap{white-space:pre-wrap}
+:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
+pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
+pre>code{display:block}
+pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #e7e7e9}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+details{margin-left:1.25rem}
+details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
+details>summary::-webkit-details-marker{display:none}
+details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
+details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
+details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
+.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
+@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
+.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
+.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.prettyprint{background:#f7f7f8}
+pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
+pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
+pre.prettyprint li code[data-lang]::before{opacity:1}
+pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
+table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
+table.linenotable td.code{padding-left:.75em}
+table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
+pre.pygments span.linenos{display:inline-block;margin-right:.75em}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
+.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
+.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
+.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
+.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
+td.tableblock>.content>:last-child{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>*>tr>*{border-width:1px}
+table.grid-cols>*>tr>*{border-width:0 1px}
+table.grid-rows>*>tr>*{border-width:1px 0}
+table.frame-all{border-width:1px}
+table.frame-ends{border-width:1px 0}
+table.frame-sides{border-width:0 1px}
+table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
+table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
+table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
+table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
+table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+li>p:empty:only-child::before{content:"";display:inline-block}
+ul.checklist>li>p:first-child{margin-left:-1em}
+ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
+ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+td.hdlist2{word-wrap:anywhere}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
+.imageblock.left{margin:.25em .625em 1.25em 0}
+.imageblock.right{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background:#00fafa}
+.black{color:#000}
+.black-background{background:#000}
+.blue{color:#0000bf}
+.blue-background{background:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background:#fa00fa}
+.gray{color:#606060}
+.gray-background{background:#7d7d7d}
+.green{color:#006000}
+.green-background{background:#007d00}
+.lime{color:#00bf00}
+.lime-background{background:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background:#7d0000}
+.navy{color:#000060}
+.navy-background{background:#00007d}
+.olive{color:#606000}
+.olive-background{background:#7d7d00}
+.purple{color:#600060}
+.purple-background{background:#7d007d}
+.red{color:#bf0000}
+.red-background{background:#fa0000}
+.silver{color:#909090}
+.silver-background{background:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]{border-bottom:1px dotted}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#header,#content,#footnotes,#footer{max-width:none}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+</head>
+<body class="article">
+<div id="header">
+<h1>Why Recomputing Distance Still Freezes the Loop</h1>
+<div class="details">
+<span id="author" class="author">Even when recomputing `distance` inside the loop, it can still freeze. This</span><br>
+<span id="revdate">happens when</span>
+<br><span id="revremark"></span>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="ulist">
+<ul>
+<li>
+<p>The distance between ball centers becomes <strong>zero or extremely close to zero</strong>.</p>
+</li>
+<li>
+<p>The overlap becomes <strong>very tiny</strong> but never fully resolves because floating-
+point error prevents the condition from becoming false.</p>
+</li>
+<li>
+<p>The collision logic attempts to normalize a zero-length vector.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Below is the real reason and the correct fix.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_the_real_crash_scenario_distance_0">The Real Crash Scenario: Distance == 0</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>If two balls overlap <strong>perfectly</strong>, meaning:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>b1-&gt;px == b2-&gt;px
+b1-&gt;py == b2-&gt;py</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Then:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>dx = 0
+dy = 0
+distance = sqrt(0 + 0) = 0</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Normalizing <code>(dx, dy)</code> becomes:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>nx = dx / distance  --&gt; division by zero</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This produces <code>NaN</code>, and once NaNs enter your coordinates, your loop <strong>never
+terminates</strong>, because every test becomes nonsense.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_why_this_happens">Why This Happens</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Your simulation allows balls to be pushed so close together (or initialized too
+close) that they fully overlap before you start resolving.</p>
+</div>
+<div class="paragraph">
+<p>Your while-loop approach <strong>cannot</strong> recover when distance reaches 0.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_the_fix_replace_the_loop_with_one_guaranteed_separation_step">The Fix: Replace the Loop With One Guaranteed Separation Step</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Physics engines never use repeated loops; they use one mathematically correct
+position correction.</p>
+</div>
+<div class="paragraph">
+<p>Here is the correct safe displacement code:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-c" data-lang="c">float dx = b1-&gt;px - b2-&gt;px;
+float dy = b1-&gt;py - b2-&gt;py;
+float d2 = dx*dx + dy*dy;
+
+// If centers are identical, push them apart arbitrarily
+if (d2 == 0.0f) {
+    dx = 1.0f;
+    dy = 0.0f;
+    d2 = 1.0f;
+}
+
+float distance = sqrtf(d2);
+float overlap  = (b1-&gt;radius + b2-&gt;radius) - distance;
+
+if (overlap &gt; 0.0f) {
+    float nx = dx / distance;
+    float ny = dy / distance;
+
+    float half = overlap * 0.5f;
+
+    b1-&gt;px += nx * half;
+    b1-&gt;py += ny * half;
+
+    b2-&gt;px -= nx * half;
+    b2-&gt;py -= ny * half;
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_why_this_works">Why This Works</h2>
+<div class="sectionbody">
+<div class="ulist">
+<ul>
+<li>
+<p><strong>No loop</strong>, so it can’t freeze.</p>
+</li>
+<li>
+<p>Handles the <code>distance == 0</code> case safely.</p>
+</li>
+<li>
+<p>Fully resolves the overlap mathematically.</p>
+</li>
+<li>
+<p>Guaranteed to stop balls from colliding in a single step.</p>
+</li>
+<li>
+<p><code>collision_count</code> will now drop to zero.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_summary">Summary</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Recomputing distance didn&#8217;t fix the freeze because the loop becomes invalid
+whenever the distance is zero or extremely tiny.
+The correct solution is to completely remove the loop and use one safe,
+mathematically correct separation step.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_want_the_full_fixed_version">Want the Full Fixed Version?</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>If you want, I can rewrite your entire collision detection and resolution block
+into clean, safe, minimal C code.</p>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2025-12-23 12:07:18 -0500
+</div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/collisions/docs/formulas.adoc b/collisions/docs/formulas.adoc
new file mode 100644 (file)
index 0000000..91e3ad5
--- /dev/null
@@ -0,0 +1,126 @@
+:stem: latexmath
+:source-highlighter: pygments
+:pygments-style: monokai
+:wrap: normal
+
+= Formulas
+
+* Dot Product
+
+[stem]
+++++
+\overrightarrow{a} \cdot \overrightarrow{b} \\
+\left[ \begin{array}{c}
+a_{1} \\
+a_{2} \\
+\vdots \\
+a_{n}
+\end{array} \right]
+
+\cdot
+
+\left[ \begin{array}{c}
+b_{1} \\
+b_{2} \\
+\vdots \\
+b_{n}
+\end{array} \right]
+=
+a_{1} * b_{1} + a_{2} * b_{2} + * a_{n} * b_{n}
+++++
+
+* Circle Overlapping
+
+[stem]
+++++
+|\sqrt{a^2 + b^2}| <= r_1 + r_2
+++++
+
+NOTE: a and a is the opposite and adjacent sides found from
+      the centers of both circles
+
+
+* Pythagrean Thereom to find distancce between balls centers
+
+[stem]
+++++
+a^2 + b^2 = c^2
+++++
+
+* Vector Normalization
+
+[stem]
+++++
+\hat{u} = \frac{\overrightarrow{v}}{|\overrightarrow{v}|}
+++++
+
+
+* Magnitude of a Vector
+
+[stem]
+++++
+|\overrightarrow{a}| = \sqrt{a_{1}^2 + a_{2}^2 + \dots a_{n}^2}
+++++
+
+* Finding tangent vector
+
+[stem]
+++++
+x = -y, y = x
+++++
+
+* 1D Conservation of Momentum
+
+[stem]
+++++
+m_1 v_1 + m_2 v_2 = m_1 v_1 + m_2 v_2
+++++
+
+* 1D Elastic Collision
+
+[stem]
+++++
+v_1' = (v_1 * (m_1-m_2) + 2 * m_2 * v_2)) / (m_1 + m_2) \\
+v_2' = (v_2 * (m_2-m_1) + 2 * m_1 * v_1)) / (m_1 + m_2)
+++++
+
+* Finding magnitude in a specific direction
+
+[stem]
+++++
+|\overrightarrow{v}| = \overrightarrow{n} \cdot \overrightarrow{v}
+++++
+
+* Distinct unordered pairs
+
+[stem]
+++++
+(n,2) = \frac{n(n-1)}{2}]
+++++
+
+
+== Seeing if circle collide
+Instead of doing this:
+
+[source,c]
+----
+sqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)) <= (r1 + r2);
+----
+
+We can save some computing speed by removing the square root and just
+multiplying the left side by itself:
+
+[source,c]
+----
+fabs((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)) <= (r1 + r2)*(r1 + r2);
+----
+
+== Clamping Velocity
+
+We can use the dot product to find the velocity in specific direction and then
+clamp it
+
+[source,c]
+----
+if (fabs(ball.vx*ball.vx + ball.vy*ball.vy) < 0.01f)
+----
diff --git a/collisions/docs/formulas.html b/collisions/docs/formulas.html
new file mode 100644 (file)
index 0000000..efb1004
--- /dev/null
@@ -0,0 +1,745 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 2.0.20">
+<title>Formulas</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
+/* Uncomment the following line when using as a custom stylesheet */
+/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
+html{font-family:sans-serif;-webkit-text-size-adjust:100%}
+a{background:none}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+b,strong{font-weight:bold}
+abbr{font-size:.9em}
+abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
+dfn{font-style:italic}
+hr{height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+audio,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type=checkbox],input[type=radio]{padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,::before,::after{box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:0}
+p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.square{list-style-type:square}
+ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt{background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+:not(pre).nobreak{word-wrap:normal}
+:not(pre).nowrap{white-space:nowrap}
+:not(pre).pre-wrap{white-space:pre-wrap}
+:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
+pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
+pre>code{display:block}
+pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #e7e7e9}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+details{margin-left:1.25rem}
+details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
+details>summary::-webkit-details-marker{display:none}
+details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
+details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
+details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
+.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
+@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
+.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
+.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.prettyprint{background:#f7f7f8}
+pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
+pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
+pre.prettyprint li code[data-lang]::before{opacity:1}
+pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
+table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
+table.linenotable td.code{padding-left:.75em}
+table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
+pre.pygments span.linenos{display:inline-block;margin-right:.75em}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
+.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
+.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
+.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
+.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
+td.tableblock>.content>:last-child{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>*>tr>*{border-width:1px}
+table.grid-cols>*>tr>*{border-width:0 1px}
+table.grid-rows>*>tr>*{border-width:1px 0}
+table.frame-all{border-width:1px}
+table.frame-ends{border-width:1px 0}
+table.frame-sides{border-width:0 1px}
+table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
+table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
+table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
+table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
+table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+li>p:empty:only-child::before{content:"";display:inline-block}
+ul.checklist>li>p:first-child{margin-left:-1em}
+ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
+ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+td.hdlist2{word-wrap:anywhere}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
+.imageblock.left{margin:.25em .625em 1.25em 0}
+.imageblock.right{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background:#00fafa}
+.black{color:#000}
+.black-background{background:#000}
+.blue{color:#0000bf}
+.blue-background{background:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background:#fa00fa}
+.gray{color:#606060}
+.gray-background{background:#7d7d7d}
+.green{color:#006000}
+.green-background{background:#007d00}
+.lime{color:#00bf00}
+.lime-background{background:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background:#7d0000}
+.navy{color:#000060}
+.navy-background{background:#00007d}
+.olive{color:#606000}
+.olive-background{background:#7d7d00}
+.purple{color:#600060}
+.purple-background{background:#7d007d}
+.red{color:#bf0000}
+.red-background{background:#fa0000}
+.silver{color:#909090}
+.silver-background{background:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]{border-bottom:1px dotted}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#header,#content,#footnotes,#footer{max-width:none}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+<style>
+pre.pygments .hll { background-color: #49483e }
+pre.pygments { background: #272822; color: #F8F8F2 }
+pre.pygments .tok-c { color: #959077 } /* Comment */
+pre.pygments .tok-err { color: #ED007E; background-color: #1E0010 } /* Error */
+pre.pygments .tok-esc { color: #F8F8F2 } /* Escape */
+pre.pygments .tok-g { color: #F8F8F2 } /* Generic */
+pre.pygments .tok-k { color: #66D9EF } /* Keyword */
+pre.pygments .tok-l { color: #AE81FF } /* Literal */
+pre.pygments .tok-n { color: #F8F8F2 } /* Name */
+pre.pygments .tok-o { color: #FF4689 } /* Operator */
+pre.pygments .tok-x { color: #F8F8F2 } /* Other */
+pre.pygments .tok-p { color: #F8F8F2 } /* Punctuation */
+pre.pygments .tok-ch { color: #959077 } /* Comment.Hashbang */
+pre.pygments .tok-cm { color: #959077 } /* Comment.Multiline */
+pre.pygments .tok-cp { color: #959077 } /* Comment.Preproc */
+pre.pygments .tok-cpf { color: #959077 } /* Comment.PreprocFile */
+pre.pygments .tok-c1 { color: #959077 } /* Comment.Single */
+pre.pygments .tok-cs { color: #959077 } /* Comment.Special */
+pre.pygments .tok-gd { color: #FF4689 } /* Generic.Deleted */
+pre.pygments .tok-ge { color: #F8F8F2; font-style: italic } /* Generic.Emph */
+pre.pygments .tok-ges { color: #F8F8F2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */
+pre.pygments .tok-gr { color: #F8F8F2 } /* Generic.Error */
+pre.pygments .tok-gh { color: #F8F8F2 } /* Generic.Heading */
+pre.pygments .tok-gi { color: #A6E22E } /* Generic.Inserted */
+pre.pygments .tok-go { color: #66D9EF } /* Generic.Output */
+pre.pygments .tok-gp { color: #FF4689; font-weight: bold } /* Generic.Prompt */
+pre.pygments .tok-gs { color: #F8F8F2; font-weight: bold } /* Generic.Strong */
+pre.pygments .tok-gu { color: #959077 } /* Generic.Subheading */
+pre.pygments .tok-gt { color: #F8F8F2 } /* Generic.Traceback */
+pre.pygments .tok-kc { color: #66D9EF } /* Keyword.Constant */
+pre.pygments .tok-kd { color: #66D9EF } /* Keyword.Declaration */
+pre.pygments .tok-kn { color: #FF4689 } /* Keyword.Namespace */
+pre.pygments .tok-kp { color: #66D9EF } /* Keyword.Pseudo */
+pre.pygments .tok-kr { color: #66D9EF } /* Keyword.Reserved */
+pre.pygments .tok-kt { color: #66D9EF } /* Keyword.Type */
+pre.pygments .tok-ld { color: #E6DB74 } /* Literal.Date */
+pre.pygments .tok-m { color: #AE81FF } /* Literal.Number */
+pre.pygments .tok-s { color: #E6DB74 } /* Literal.String */
+pre.pygments .tok-na { color: #A6E22E } /* Name.Attribute */
+pre.pygments .tok-nb { color: #F8F8F2 } /* Name.Builtin */
+pre.pygments .tok-nc { color: #A6E22E } /* Name.Class */
+pre.pygments .tok-no { color: #66D9EF } /* Name.Constant */
+pre.pygments .tok-nd { color: #A6E22E } /* Name.Decorator */
+pre.pygments .tok-ni { color: #F8F8F2 } /* Name.Entity */
+pre.pygments .tok-ne { color: #A6E22E } /* Name.Exception */
+pre.pygments .tok-nf { color: #A6E22E } /* Name.Function */
+pre.pygments .tok-nl { color: #F8F8F2 } /* Name.Label */
+pre.pygments .tok-nn { color: #F8F8F2 } /* Name.Namespace */
+pre.pygments .tok-nx { color: #A6E22E } /* Name.Other */
+pre.pygments .tok-py { color: #F8F8F2 } /* Name.Property */
+pre.pygments .tok-nt { color: #FF4689 } /* Name.Tag */
+pre.pygments .tok-nv { color: #F8F8F2 } /* Name.Variable */
+pre.pygments .tok-ow { color: #FF4689 } /* Operator.Word */
+pre.pygments .tok-pm { color: #F8F8F2 } /* Punctuation.Marker */
+pre.pygments .tok-w { color: #F8F8F2 } /* Text.Whitespace */
+pre.pygments .tok-mb { color: #AE81FF } /* Literal.Number.Bin */
+pre.pygments .tok-mf { color: #AE81FF } /* Literal.Number.Float */
+pre.pygments .tok-mh { color: #AE81FF } /* Literal.Number.Hex */
+pre.pygments .tok-mi { color: #AE81FF } /* Literal.Number.Integer */
+pre.pygments .tok-mo { color: #AE81FF } /* Literal.Number.Oct */
+pre.pygments .tok-sa { color: #E6DB74 } /* Literal.String.Affix */
+pre.pygments .tok-sb { color: #E6DB74 } /* Literal.String.Backtick */
+pre.pygments .tok-sc { color: #E6DB74 } /* Literal.String.Char */
+pre.pygments .tok-dl { color: #E6DB74 } /* Literal.String.Delimiter */
+pre.pygments .tok-sd { color: #E6DB74 } /* Literal.String.Doc */
+pre.pygments .tok-s2 { color: #E6DB74 } /* Literal.String.Double */
+pre.pygments .tok-se { color: #AE81FF } /* Literal.String.Escape */
+pre.pygments .tok-sh { color: #E6DB74 } /* Literal.String.Heredoc */
+pre.pygments .tok-si { color: #E6DB74 } /* Literal.String.Interpol */
+pre.pygments .tok-sx { color: #E6DB74 } /* Literal.String.Other */
+pre.pygments .tok-sr { color: #E6DB74 } /* Literal.String.Regex */
+pre.pygments .tok-s1 { color: #E6DB74 } /* Literal.String.Single */
+pre.pygments .tok-ss { color: #E6DB74 } /* Literal.String.Symbol */
+pre.pygments .tok-bp { color: #F8F8F2 } /* Name.Builtin.Pseudo */
+pre.pygments .tok-fm { color: #A6E22E } /* Name.Function.Magic */
+pre.pygments .tok-vc { color: #F8F8F2 } /* Name.Variable.Class */
+pre.pygments .tok-vg { color: #F8F8F2 } /* Name.Variable.Global */
+pre.pygments .tok-vi { color: #F8F8F2 } /* Name.Variable.Instance */
+pre.pygments .tok-vm { color: #F8F8F2 } /* Name.Variable.Magic */
+pre.pygments .tok-il { color: #AE81FF } /* Literal.Number.Integer.Long */
+</style>
+</head>
+<body class="article">
+<div id="header">
+<h1>Formulas</h1>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="ulist">
+<ul>
+<li>
+<p>Dot Product</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\overrightarrow{a} \cdot \overrightarrow{b} \\
+\left[ \begin{array}{c}
+a_{1} \\
+a_{2} \\
+\vdots \\
+a_{n}
+\end{array} \right]
+
+\cdot
+
+\left[ \begin{array}{c}
+b_{1} \\
+b_{2} \\
+\vdots \\
+b_{n}
+\end{array} \right]
+=
+a_{1} * b_{1} + a_{2} * b_{2} + * a_{n} * b_{n}\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Circle Overlapping</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[|\sqrt{a^2 + b^2}| &lt;= r_1 + r_2\]
+</div>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">
+a and a is the opposite and adjacent sides found from
+      the centers of both circles
+</td>
+</tr>
+</table>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Pythagrean Thereom to find distancce between balls centers</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[a^2 + b^2 = c^2\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Vector Normalization</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[\hat{u} = \frac{\overrightarrow{v}}{|\overrightarrow{v}|}\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Magnitude of a Vector</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[|\overrightarrow{a}| = \sqrt{a_{1}^2 + a_{2}^2 + \dots a_{n}^2}\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Finding tangent vector</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[x = -y, y = x\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>1D Conservation of Momentum</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[m_1 v_1 + m_2 v_2 = m_1 v_1 + m_2 v_2\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>1D Elastic Collision</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[v_1' = (v_1 * (m_1-m_2) + 2 * m_2 * v_2)) / (m_1 + m_2) \\
+v_2' = (v_2 * (m_2-m_1) + 2 * m_1 * v_1)) / (m_1 + m_2)\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Finding magnitude in a specific direction</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[|\overrightarrow{v}| = \overrightarrow{n} \cdot \overrightarrow{v}\]
+</div>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Distinct unordered pairs</p>
+</li>
+</ul>
+</div>
+<div class="stemblock">
+<div class="content">
+\[(n,2) = \frac{n(n-1)}{2}]\]
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_seeing_if_circle_collide">Seeing if circle collide</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Instead of doing this:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c"><span></span><span class="tok-n">sqrtf</span><span class="tok-p">((</span><span class="tok-n">x1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">x2</span><span class="tok-p">)</span><span class="tok-o">*</span><span class="tok-p">(</span><span class="tok-n">x1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">x2</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">y1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">y2</span><span class="tok-p">)</span><span class="tok-o">*</span><span class="tok-p">(</span><span class="tok-n">y1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">y2</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">&lt;=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">r1</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">r2</span><span class="tok-p">);</span></code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>We can save some computing speed by removing the square root and just
+multiplying the left side by itself:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c"><span></span><span class="tok-n">fabs</span><span class="tok-p">((</span><span class="tok-n">x1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">x2</span><span class="tok-p">)</span><span class="tok-o">*</span><span class="tok-p">(</span><span class="tok-n">x1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">x2</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">y1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">y2</span><span class="tok-p">)</span><span class="tok-o">*</span><span class="tok-p">(</span><span class="tok-n">y1</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-n">y2</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">&lt;=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">r1</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">r2</span><span class="tok-p">)</span><span class="tok-o">*</span><span class="tok-p">(</span><span class="tok-n">r1</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">r2</span><span class="tok-p">);</span></code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_clamping_velocity">Clamping Velocity</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>We can use the dot product to find the velocity in specific direction and then
+clamp it</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c"><span></span><span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">fabs</span><span class="tok-p">(</span><span class="tok-n">ball</span><span class="tok-p">.</span><span class="tok-n">vx</span><span class="tok-o">*</span><span class="tok-n">ball</span><span class="tok-p">.</span><span class="tok-n">vx</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">ball</span><span class="tok-p">.</span><span class="tok-n">vy</span><span class="tok-o">*</span><span class="tok-n">ball</span><span class="tok-p">.</span><span class="tok-n">vy</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">&lt;</span><span class="tok-w"> </span><span class="tok-mf">0.01f</span><span class="tok-p">)</span></code></pre>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2025-12-23 12:07:18 -0500
+</div>
+</div>
+<script type="text/x-mathjax-config">
+MathJax.Hub.Config({
+  messageStyle: "none",
+  tex2jax: {
+    inlineMath: [["\\(", "\\)"]],
+    displayMath: [["\\[", "\\]"]],
+    ignoreClass: "nostem|nolatexmath"
+  },
+  asciimath2jax: {
+    delimiters: [["\\$", "\\$"]],
+    ignoreClass: "nostem|noasciimath"
+  },
+  TeX: { equationNumbers: { autoNumber: "none" } }
+})
+MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
+  MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
+    if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
+      data.math.root.display = "block"
+    }
+    return data
+  })
+})
+</script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/docinfo.conf b/docinfo.conf
new file mode 100644 (file)
index 0000000..57fa5b9
--- /dev/null
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+HOSTNAME=nyquistdev.net
+DOCINFODIR=/usr/local/share/readme-to-html
diff --git a/notes.adoc b/notes.adoc
new file mode 100644 (file)
index 0000000..3288e63
--- /dev/null
@@ -0,0 +1,12 @@
+== GDB
+
+remember that conditional break points exist
+
+== Links
+* https://www.youtube.com/watch?v=nXrEX6j-Mws&list=PLkhTWnF-dZA7fqD7CF8koSTsRbmfBfr2_
+* https://www.unitconverters.net/typography/pixel-x-to-meter.htm[pixels to meters]
+* https://simulationshub.com/ball-drop/[interactive ball]
+* https://www.physicslens.com/simulation-of-a-bouncing-ball/
+* https://www.youtube.com/watch?v=hG9SzQxaCm8
+* https://en.wikipedia.org/wiki/Bouncing_ball
+* https://youtu.be/LPzyNOHY3A4?si=Vv4pVQ0cbLwPI9Zt[javidx9]
diff --git a/rendered.html b/rendered.html
new file mode 100644 (file)
index 0000000..77e5c8c
--- /dev/null
@@ -0,0 +1,951 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 2.0.20">
+<title>Balls</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
+/* Uncomment the following line when using as a custom stylesheet */
+/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
+html{font-family:sans-serif;-webkit-text-size-adjust:100%}
+a{background:none}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+b,strong{font-weight:bold}
+abbr{font-size:.9em}
+abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
+dfn{font-style:italic}
+hr{height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+audio,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type=checkbox],input[type=radio]{padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,::before,::after{box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:0}
+p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.square{list-style-type:square}
+ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt{background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+:not(pre).nobreak{word-wrap:normal}
+:not(pre).nowrap{white-space:nowrap}
+:not(pre).pre-wrap{white-space:pre-wrap}
+:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
+pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
+pre>code{display:block}
+pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #e7e7e9}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+details{margin-left:1.25rem}
+details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
+details>summary::-webkit-details-marker{display:none}
+details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
+details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
+details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
+.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
+@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
+.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
+.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.prettyprint{background:#f7f7f8}
+pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
+pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
+pre.prettyprint li code[data-lang]::before{opacity:1}
+pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
+table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
+table.linenotable td.code{padding-left:.75em}
+table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
+pre.pygments span.linenos{display:inline-block;margin-right:.75em}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
+.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
+.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
+.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
+.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
+td.tableblock>.content>:last-child{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>*>tr>*{border-width:1px}
+table.grid-cols>*>tr>*{border-width:0 1px}
+table.grid-rows>*>tr>*{border-width:1px 0}
+table.frame-all{border-width:1px}
+table.frame-ends{border-width:1px 0}
+table.frame-sides{border-width:0 1px}
+table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
+table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
+table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
+table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
+table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+li>p:empty:only-child::before{content:"";display:inline-block}
+ul.checklist>li>p:first-child{margin-left:-1em}
+ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
+ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+td.hdlist2{word-wrap:anywhere}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
+.imageblock.left{margin:.25em .625em 1.25em 0}
+.imageblock.right{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background:#00fafa}
+.black{color:#000}
+.black-background{background:#000}
+.blue{color:#0000bf}
+.blue-background{background:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background:#fa00fa}
+.gray{color:#606060}
+.gray-background{background:#7d7d7d}
+.green{color:#006000}
+.green-background{background:#007d00}
+.lime{color:#00bf00}
+.lime-background{background:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background:#7d0000}
+.navy{color:#000060}
+.navy-background{background:#00007d}
+.olive{color:#606000}
+.olive-background{background:#7d7d00}
+.purple{color:#600060}
+.purple-background{background:#7d007d}
+.red{color:#bf0000}
+.red-background{background:#fa0000}
+.silver{color:#909090}
+.silver-background{background:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]{border-bottom:1px dotted}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#header,#content,#footnotes,#footer{max-width:none}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+<head>
+<!-- <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=DotGothic16"> -->
+<!-- <link rel="icon" type="image/x-icon" href="https://raw.githubusercontent.com/A-Larsen/math-notes/refs/heads/main/favicon.png"> -->
+<!-- <link rel="icon" type="image/png" href="N2DE_favicon.png"/> -->
+<!-- <link rel="preconnect" href="https://fonts.googleapis.com"> -->
+<!-- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> -->
+<!-- <link href="https://fonts.googleapis.com/css2?family=Abril+Fatface&display=swap" rel="stylesheet"> -->
+<style>
+
+/*--------------------------------------------------------------*/
+/*use '!important' to override default css used by asciidoctor*/
+/*--------------------------------------------------------------*/
+
+:root {
+    --gruvbox-black: #282828;
+    --gruvbox-black2: #1d2021;
+    --gruvbox-black3: #463f39;
+    --gruvbox-red: #fc7869;
+    --gruvbox-yellow: #fabd2f;
+    --gruvbox-white: #ebdbb2;
+    --gruvbox-white2: #a7a187;
+    --gruvbox-blue: #83a598;
+    --gruvbox-green: #b8bb26;
+    --gruvbox-bg1: #7c6f64;
+    --gruvbox-bg2: #665c54;
+
+}
+
+.title {
+  color: var(--gruvbox-red) !important;
+}
+
+blockquote {
+    color: var(--gruvbox-white) !important;
+}
+
+table {
+    margin: 0 auto !important;
+}
+
+.hdlist1 {
+  font-size: 1.3em;
+}
+
+cite {
+    color: var(--gruvbox-green) !important;
+}
+
+.tableblock {
+    background-color: inherit;
+    color: var(--gruvbox-white);
+    max-width: 95%;
+}
+
+.tableblock th {
+    background-color: var(--gruvbox-black3);
+    color: var(--gruvbox-white);
+    max-width: 97%;
+}
+
+code:not([data-lang]) {
+    background-color: var(--gruvbox-bg2) !important;
+    color: var(--gruvbox-white);
+    text-shadow: none;
+}
+
+.checklist {
+    text-align: left;
+    font-size: .8em;
+}
+
+.checklist li ul { margin-left: 3%;
+}
+
+#content, h1, pre {
+    border-radius: 8px !important;
+}
+
+#header, #content, #footnotes, #footer {
+  padding-left: 0 !important;
+  padding-right: 0 !important;
+}
+
+.api-type a:hover {
+    text-decoration: underline;
+}
+
+.api-type, .api-type a {
+    color: var(--gruvbox-green);
+    text-decoration: none;
+}
+
+pre {
+    border-style: solid !important;
+    border-color: white !important;
+    border-width: 2px !important;
+}
+
+h1 {
+   /* font-family: "DotGothic16", sans-serif !important;*/
+
+
+    background-color: var(--gruvbox-white2) !important;
+    color: var(--gruvbox-black) !important;
+}
+
+.admonitionblock > table td.content {
+    color: var(--gruvbox-white) !important;
+}
+
+/*
+html {
+    margin: 0;
+    height: 100%;
+    width: 100%;
+}
+
+
+*/
+/*html {*/
+
+body {
+    /*background: black url("background-image-space.jpeg") no-repeat fixed center;*/
+    /*background-color: black;*/
+    background-color: var(--gruvbox-black);
+    background-attachment: fixed;
+    background-size: cover;
+    overflow-y: scroll;
+    /*
+    margin: 0;
+    height: 100%;
+    width: 100%;
+    overflow: hidden;
+    */
+}
+
+
+/*
+body {
+    overflow-y: scroll;
+    background: rgba(0,0,0,0);
+    height: 100%;
+    margin: 2%;
+}
+*/
+
+#toc {
+    background-color: var(--gruvbox-black2) !important;
+    /*opacity: .9;*/
+}
+
+#toctitle {
+    color: var(--gruvbox-yellow);
+}
+
+a {
+    color: var(--gruvbox-bg1);
+}
+
+#content {
+    color: #ebdbb2;
+    background: var(--gruvbox-black);
+    /*opacity: .9;*/
+}
+
+#header > h1:nth-last-child(2) {
+    border-bottom: none !important;
+    background-color: rgba(0, 0, 0, .1);
+    padding-left: 2%;
+}
+
+.sect1 + .sect1 {
+  border-top: none !important;
+}
+
+.sect1 h2 {
+    background-size: cover;
+    background-attachment: fixed;
+    /*
+    border-bottom: 1px solid var(--gruvbox-white);
+    border-top: 1px solid var(--gruvbox-white);
+    */
+    padding: 10px;
+    text-align: left;
+    color: var(--gruvbox-red) !important;
+    /*
+    text-shadow: 1px 1px 1px var(--gruvbox-black);
+    text-shadow: 3px 3px 3px var(--gruvbox-black);
+    text-shadow: 5px 5px 5px var(--gruvbox-blue);
+    */
+}
+
+h3, h4, h5 {
+    /*
+    text-shadow: 1px 1px 1px var(--gruvbox-white);
+    */
+}
+
+h3 {
+  color: var(--gruvbox-red) !important;
+}
+
+h4 {
+  color: var(--gruvbox-yellow) !important;
+}
+
+h5 {
+  color: #83a598 !important;
+}
+
+h2 ~ *:not(h1) {
+  margin-left: .5em;
+}
+
+.pygments {
+    max-width: 97% !important;
+    white-space: pre;
+    overflow-x: scroll !important;
+}
+
+::before {
+    /*makes sure that the programming language that show up on hover is within
+      pre tag*/
+    padding-right: 3%;
+}
+
+@media screen and (max-width: 800px) {
+    .checklist li ul {
+        margin-left: 6% !important;
+    }
+    #toc {
+        padding-left: 10px;
+    }
+
+    footer {
+        margin-bottom: 10px !important;
+    }
+    html {
+        margin-bottom: 10px !important;
+    }
+}
+@media screen and (max-width: 535px) {
+    h3 ~ *:not(h2):not(h3) {
+      margin-left: 0 !important;
+    }
+
+    h4 ~ *:not(h2):not(h3):not(.h3):not(h4) {
+      margin-left: 0 !important;
+    }
+    h5 ~ *:not(h2):not(h3):not(.h3):not(h4):not(.h4):not(h5) {
+      margin-left: 0 !important;
+    }
+
+    footer {
+        margin-bottom: 10px !important;
+    }
+    html {
+        margin-bottom: 10px !important;
+    }
+}
+h3 ~ *:not(h2):not(h3) {
+  margin-left: 1.5em;
+}
+
+h4 ~ *:not(h2):not(h3):not(.h3):not(h4) {
+  margin-left: 2em;
+}
+h5 ~ *:not(h2):not(h3):not(.h3):not(h4):not(.h4):not(h5) {
+  margin-left: 2.5em;
+}
+
+
+.sect1 h2 {
+
+    /*
+    background: linear-gradient(
+        to bottom,
+        rgba(251, 189, 47, 0.2), /* yellow */
+        rgba(0, 0, 0, 0.4)       /* black */
+    );
+    */
+    /*opacity: .9;*/
+  }
+
+#preamble p{
+  padding-left: 10px;
+  color: var(--gruvbox-white) !important;
+}
+
+#footer {
+    max-width: 62.5em !important;
+    padding-left: 10px !important;
+    text-align: center;
+}
+
+.logo img {
+    display: block !important;
+    margin-left: auto !important;
+    margin-right: auto !important;
+}
+
+#header > h1:first-child {
+  margin-top: .3em !important;
+  padding-top: .2em !important;
+  text-align: center;
+}
+
+footer {
+    max-width: 62.5em;
+    margin-left: auto;
+    margin-right: auto;
+    display: block;
+
+}
+
+details[open] > summary::before {
+   /* display: none;*/
+    border-top: none;
+    content: "▼";
+    margin-top: -12px;
+}
+
+.example.stemblock {
+    border: solid;
+    font-size: 2vw;
+    max-width: 40%;
+    margin: auto;
+}
+
+.center {
+    max-width: 500px;
+    display: flex;
+    justify-content: center;
+}
+
+.highlight {
+    color: var(--gruvbox-yellow)
+}
+
+.border {
+    padding: 4px;
+    border: 2px solid rgba(255, 0, 0, .3);
+}
+
+.dull {
+    opacity: 40%;
+}
+
+.inline {
+    margin-right: 5%;
+    display: inline-block;
+}
+
+
+</style>
+
+</head>
+
+<script src="docinfo.js"></script>
+
+
+</head>
+<body class="article">
+<div id="header">
+<h1>Balls</h1>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph">
+<p>This repository has physics examples using balls. Each folder has a different
+example, with a link to the formulas used in the readme&#8217;s.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_2d_projectile_motion">2D Projectile Motion</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>checkout this link
+<a href="https://nyquistdev.net/git/?p=balls.git;a=blob_plain;f=2d-projectile-motion/docs/formulas.html;hb=HEAD">formulas</a>.
+for a list of forumlas used.</p>
+</div>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">control</th>
+<th class="tableblock halign-left valign-top">action</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">right-click and drag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">determine direction and velocity of ball</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">right-click release</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">launch ball</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_bouncing">Bouncing</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>check out this link
+<a href="https://nyquistdev.net/git/?p=balls.git;a=blob_plain;f=bounce/docs/formulas.html;hb=HEAD">formulas</a>.
+for the formulas used.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_collisions">Collisions</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Creates random balls. These balls will resolve any collision issues. Launching a
+ball will show you an example of elastic collision.</p>
+</div>
+<div class="paragraph">
+<p>checkout this link
+<a href="https://nyquistdev.net/git/?p=balls.git;a=blob_plain;f=collisions/docs/formulas.html;hb=HEAD">formulas</a>.
+for a list of forumlas used.</p>
+</div>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">control</th>
+<th class="tableblock halign-left valign-top">action</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">right-click</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">select ball</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">right-click and left-click and drag</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">flings ball on release, the distance
+                                        away from the ball determines the amount
+                                        of velocity to launch the ball at</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_building_html_from_formula_adoc_files">Building html from formula <em>.adoc</em> files</h2>
+<div class="sectionbody">
+<div class="listingblock">
+<div class="content">
+<pre>./Makehtml make</pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_links">Links</h2>
+<div class="sectionbody">
+<div class="ulist">
+<ul>
+<li>
+<p><a href="https://www.studyplan.dev/sdl2/sdl2-relative-mode">sdl2-relative-mouse-mode</a></p>
+</li>
+<li>
+<p><a href="https://www.youtube.com/watch?v=XJnIdRXUi7A&amp;t=315s">permutations and combinations</a></p>
+</li>
+<li>
+<p><a href="https://www.youtube.com/watch?v=CFbo_nBdBco">OCT | Elastic Collisions</a></p>
+</li>
+<li>
+<p><a href="https://www.wikihow.com/Normalize-a-Vector">Normalizing a Vector</a></p>
+</li>
+<li>
+<p><a href="https://www.youtube.com/watch?v=Fp7D5D8Bqjc">conservation of Momentum</a></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<script type="text/x-mathjax-config">
+MathJax.Hub.Config({
+  messageStyle: "none",
+  tex2jax: {
+    inlineMath: [["\\(", "\\)"]],
+    displayMath: [["\\[", "\\]"]],
+    ignoreClass: "nostem|nolatexmath"
+  },
+  asciimath2jax: {
+    delimiters: [["\\$", "\\$"]],
+    ignoreClass: "nostem|noasciimath"
+  },
+  TeX: { equationNumbers: { autoNumber: "none" } }
+})
+MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
+  MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
+    if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
+      data.math.root.display = "block"
+    }
+    return data
+  })
+})
+</script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
+</body>
+</html>
\ No newline at end of file