<?xml version=”1.0” encoding=”UTF-8” ?>

moofy.org https://moofy.org/</link> Sun, 06 Sep 2026 01:45:38 +0000 Sun, 06 Sep 2026 01:45:38 +0000 Jekyll v3.10.0 Introducing FINDS: the Fish INteraction and Dynamics Simulation Library <p>I’ve had the pleasant experience of working in a fluid mechanics laboratory for the past two-and-a-half months, and this lab was primarily focused on schooling behavior of fish due to hydrodynamic interactions. I had originally intended to do something a bit more fundamental in fluid mechanics so that I could learn some fluid physics while working, but interestingly, their concern on fish dynamics is actually far more of a particle simulation problem.</p> <p>The issue they tasked me with solving is fairly simple and purely computational: real fish schools are far larger than they could simulate using straightforward, brute-force calculations. They were interested in modelling only passive hydrodynamic interactions between fish (so ignoring behavioral factors or active effects like vortical wake), but any simulation system consisting of \(N\) point-masses (or similar) where each point-mass effects each other point mass requires the calculation of \(N^2\) interactions per time-step. This is, by definition, the \(N\)-body problem as seen in countless situations in computational physics, and as anybody who has ever dealt with this problem will tell you, it is the greatest bottleneck performing any computational research in particle-based systems. In particular, in this lab, they couldn’t get much farther than tens of thousands of swimmers: numbers around fifty thousand fish were considered quite high for simulation, and most of the research in the lab focused on less then fifty (often only two). This is a massive problem for research into this field, however, as real fish schools have been found to contain hundreds of millions of swimmers, thus leaving a massive gap in research as group sizes in the tens of thousands are puny compared to the hundreds of millions.</p> <p>Therefore, I was tasked with creating a simulation program efficient enough to handle hundreds of millions of swimmers by using standard computational particle dynamics techniques, such as implementing the Barnes-Hut algorithm, the Fast Multipole Method, and using parallel and/or distributed computing. This led to the creation of <a href="/finds">FINDS</a>, a C library for performing fast simulation of large schools.</p> <p>This library brings the computation time for the derivative of a system down from a time complexity of \(O(N^2)\) to \(O(N \log N)\) and \(O(N)\) using the Barnes-Hut approximation and the Fast Multipole Method respectively, and this translates into a difference in computation time from hours or days per computation to seconds at scales at or above \(10^5\) fish (see the figure below).</p> <p><img src="/images/finds/benchmark.png" alt="Derivative Computation Scaling Figure" /></p> <h3 id="finds-by-example">FINDS by example</h3> <p>The way that FINDS works is incredibly simple, and I’ll use the example <a href="https://github.com/mufaro3/finds/raw/refs/heads/master/examples/imploding_sphere.c">imploding_sphere.c</a>.</p> <p>First, we can load in all of FINDS with the header <code class="language-plaintext highlighter-rouge">&lt;finds/finds.h&gt;</code>, but each individual module can be loaded in manually. The beginning system configuration is manually defined by the user, and this can be done by setting the distribution, orientation, and constant options to define standard schools or by manually setting the parameters for each fish in the system.</p> <p>In this case, we want to produce a sphere that implodes upon itself, i.e., what we can see in the figure below.</p> <p><img src="/images/finds/initial-system.png" alt="Imploding sphere system" /></p> <p>To do this, we first need to set a spherical distribution (a fibonacci sphere) with the following code:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="n">distribution_options_t</span> <span class="n">dist_opts</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="n">dist_opts</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">DISTRIBUTION_SPHERE</span><span class="p">;</span> <span class="n">dist_opts</span><span class="p">.</span><span class="n">radius</span> <span class="o">=</span> <span class="n">RADII</span><span class="p">;</span> <span class="n">dist_opts</span><span class="p">.</span><span class="n">spacing</span> <span class="o">=</span> <span class="n">SPACING</span><span class="p">;</span></code></pre></figure> <p>Then, we set the orientation of the fish to all face the origin:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="n">orientation_options_t</span> <span class="n">ori_opts</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="n">ori_opts</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">ORIENTATION_RADIAL_INWARD</span><span class="p">;</span></code></pre></figure> <p>And then, lastly, we set the fish to all be uniform in length and volumetric flow rate:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="n">constant_options_t</span> <span class="n">const_opts</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="n">const_opts</span><span class="p">.</span><span class="n">random_length_selection</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="n">const_opts</span><span class="p">.</span><span class="n">uniform_length</span> <span class="o">=</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span> <span class="n">const_opts</span><span class="p">.</span><span class="n">random_volumetric_flow_selection</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="n">const_opts</span><span class="p">.</span><span class="n">uniform_sigma</span> <span class="o">=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">M_PI</span><span class="p">;</span></code></pre></figure> <p>Then, we build the overall initial system:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="n">fish_system_t</span> <span class="o">*</span><span class="n">system</span> <span class="o">=</span> <span class="n">fish_system_generate</span><span class="p">(</span> <span class="n">dist_opts</span><span class="p">,</span> <span class="n">ori_opts</span><span class="p">,</span> <span class="n">const_opts</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">system</span><span class="p">)</span> <span class="k">return</span> <span class="n">EXIT_FAILURE</span><span class="p">;</span></code></pre></figure> <p>Now, all that is necessary is determining how we compute the derivative of each state and how we will integrate this derivative to compute each next state. Per the derivative scaling figure above, it would be ideal to compute the derivative using the Barnes-Hut algorithm with a high approximation ratio, \(\theta=1.0\), as the initial overhead is considerably low.</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="n">derivative_computation_opts_t</span> <span class="n">dc_opts</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="n">dc_opts</span><span class="p">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">BARNES_HUT</span><span class="p">;</span> <span class="n">dc_opts</span><span class="p">.</span><span class="n">approximation_threshold</span> <span class="o">=</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span> <span class="n">dc_opts</span><span class="p">.</span><span class="n">regularize</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span> <span class="n">dc_opts</span><span class="p">.</span><span class="n">regularization_epsilon</span> <span class="o">=</span> <span class="mf">1E-6</span><span class="p">;</span></code></pre></figure> <p>Then, for the integrator, we can pick a basic non-adaptive integrator as this is a fairly stable system (up until the point of implosion, at which it becomes extremely unstable, making regularization would be necessary):</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="n">integration_opts_t</span> <span class="n">int_opts</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span> <span class="n">int_opts</span><span class="p">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">RUNGE_KUTTA_4</span><span class="p">;</span> <span class="n">int_opts</span><span class="p">.</span><span class="n">eval_time_step</span> <span class="o">=</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span> <span class="n">int_opts</span><span class="p">.</span><span class="n">end_time</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span> <span class="n">int_opts</span><span class="p">.</span><span class="n">print_time_progression</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span></code></pre></figure> <p>With all of that setup, we can perform the simulation, and this returns the filename of the produced trajectory data in HDF5 format:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="kt">char</span> <span class="n">output_folder_name</span><span class="p">[</span><span class="n">BUFFER_SIZE</span><span class="p">];</span> <span class="kt">char</span> <span class="n">output_filename</span><span class="p">[</span><span class="n">DOUBLE_BUFFER_SIZE</span><span class="p">];</span> <span class="n">errcode</span> <span class="o">=</span> <span class="n">perform_simulation</span><span class="p">(</span> <span class="n">system</span><span class="p">,</span> <span class="n">dc_opts</span><span class="p">,</span> <span class="n">int_opts</span><span class="p">,</span> <span class="n">output_filename</span><span class="p">,</span> <span class="n">output_folder_name</span><span class="p">,</span> <span class="n">BUFFER_SIZE</span><span class="p">,</span> <span class="n">DOUBLE_BUFFER_SIZE</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="n">errcode</span> <span class="o">!=</span> <span class="n">ERR_OK</span><span class="p">)</span> <span class="p">{</span> <span class="n">puts</span><span class="p">(</span><span class="s">"Error occurred! Dataset is likely corrupted."</span><span class="p">);</span> <span class="k">goto</span> <span class="n">jmp_system</span><span class="p">;</span> <span class="p">}</span></code></pre></figure> <p>And after performing a simulation, we can run the post-processing modules on the produced dataset with <code class="language-plaintext highlighter-rouge">make analyze file={ouptut_filename}</code>, and this produces analysis figures like a plot of the mean radial distance, animations, etc.</p> <p><img src="/images/finds/mean-radial-distance.png" alt="Mean Radial Distance Plot" /></p> <h2 id="locating-finds-and-the-manuscript-pre-print">Locating FINDS and the Manuscript Pre-print</h2> <p>For more in-depth information, the FINDS documentation can be found online (<a href="/finds">Online Link</a>) and the pre-print manuscript describing FINDS can also be found here (<a href="/documents/finds-preprint.pdf">PDF</a>).</p> Mon, 31 Aug 2026 15:00:14 +0000 https://moofy.org/posts/finds/</link> https://moofy.org/posts/finds/ python c physics mathematics programming Introducing the Experimentalis Library <p>Flashback to last year. I took a physics laboratory course that would routinely hand me new functions for fitting nearly every week, and with each new week, I continued to build a growing, monstrous Python file containing each of these analysis routines. I called this file <code class="language-plaintext highlighter-rouge">common.py</code>, and as the file grew, it became incredibly cumbersome and annoying to try and manage everything, so I had to start going back into the file and generalizing everything with classes and generics and such. When this first lab class ended, I thought that I was done with having to bother with these for good, but following the end of the class, my immediate next lab course required the same work, so I started again with a fresh <code class="language-plaintext highlighter-rouge">common.py</code> that seemed to grow even larger and faster than the previous one did. At that point, I got fed up, and just did a little Sphinx magic to finally document and formalize this franken-file of jumbled up functions into a proper library for data analysis called <a href="https://moofy.org/experimentalis">Experimentalis</a>.</p> <p>The way that the library works is very, very simple. It’s based on two key data types: <a href="https://moofy.org/experimentalis/api/data.html#experimentalis.dataset.Dataset">datasets</a> and <a href="https://moofy.org/experimentalis/api/models.html#experimentalis.models.Model">models</a>, and the whole point is building a big repository of various models to fit to various models to approximate parameters.</p> <p>Some examples are included with the project’s <a href="https://github.com/mufaro3/experimentalis">GitHub repository</a>, but I’ll illustrate two of them here as well. Imagine I have some noisy dataset that I believe matches some known form (which can be an analytical function or some differential equation) such as the case of a damped harmonic oscillator:</p> <p><img src="/images/posts/damped-harmonic-data.png" alt="Raw Data" /></p> <p>Now, assuming I have some arrays <code class="language-plaintext highlighter-rouge">t</code>, <code class="language-plaintext highlighter-rouge">y</code>, <code class="language-plaintext highlighter-rouge">dx</code>, and <code class="language-plaintext highlighter-rouge">dy</code> containing the time values, the amplitude-values, and the uncertainty in the time-values for each measurement, I can build a <code class="language-plaintext highlighter-rouge">Dataset</code> object to store this full dataset:</p> <figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">dataset</span> <span class="o">=</span> <span class="n">Dataset</span><span class="p">(</span> <span class="n">x</span><span class="o">=</span><span class="n">t</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y</span><span class="p">,</span> <span class="n">dx</span><span class="o">=</span><span class="n">dx</span><span class="p">,</span> <span class="n">dy</span><span class="o">=</span><span class="n">dy</span> <span class="p">)</span></code></pre></figure> <p>Then, I can make some guesses on this dataset based on first principles or background knowledge or etc. I already know that this dataset should be the result of a damped harmonic oscillator, so I’ll be fitting a model of the form</p> \[f(t) = A \exp(-t/\tau) \cos(2 \pi f t + \phi)\] <p>where \(A\) is the amplitude, \(\tau\) is the time/damping constant, \(f\) is the frequency of oscillation, and \(\phi\) is the phase. I could do some simple mathematical analysis or simply guess to develop some simple guesses for where each parameter realistically should be, and in this case, our guesses can safely end up being \(A = 0.8, \tau = 0.1, f = 1,\) and \(\phi = 0\). From that, we can make our model:</p> <figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">model</span> <span class="o">=</span> <span class="n">DampedHarmonicModel</span><span class="p">(</span> <span class="n">amplitude</span> <span class="o">=</span> <span class="mf">0.8</span><span class="p">,</span> <span class="n">time_constant</span> <span class="o">=</span> <span class="mf">0.1</span><span class="p">,</span> <span class="n">frequency</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">,</span> <span class="n">phase</span> <span class="o">=</span> <span class="mi">0</span> <span class="p">)</span></code></pre></figure> <p>and now, all we need to do is just fit the model to the data, and see what happens:</p> <figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">result</span> <span class="o">=</span> <span class="n">autofit</span><span class="p">(</span><span class="n">dataset</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">graphing_options</span><span class="o">=</span><span class="n">g_opts</span><span class="p">)</span> <span class="n">print_results</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">units</span><span class="o">=</span><span class="p">[</span><span class="s">'m'</span><span class="p">,</span> <span class="s">'Ns/m'</span><span class="p">,</span> <span class="s">'Hz'</span><span class="p">,</span> <span class="s">'rad'</span><span class="p">])</span></code></pre></figure> <p>And the output of this yields \(A = 1.0, \tau = 0.15, f = 1.2,\) and \(\phi = 0.3\) for \(\chi^2 = 1.0\), and we get the following plot:</p> <figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">display</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">autofit_graph</span><span class="p">)</span></code></pre></figure> <p><img src="/images/posts/fitted-harmonic.png" alt="Fit-to-function" /></p> <p>showing that this fit really did work as-intended, and the parameters we obtained are reasonable.</p> <p>Now, what is incredibly important to keep in mind here is that fundamentally, this data is just a one-dimensional series. This means that we can very easily make new models for fitting all kinds of one-dimensional series, such as time-series, and a very classic example of this is in stock market prediction. A fairly trivial model for stock markets, in particular, is <a href="https://en.wikipedia.org/wiki/Geometric_Brownian_motion">Geometric Brownian Motion</a> from Stochastic Calculus, and similarly to before, we can also use this library to fit a GBM model to real stock data. Once again, presume we have some stock data on Microsoft as loaded in this form:</p> <figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">prices</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="n">stock</span><span class="p">].</span><span class="n">values</span> <span class="n">dates</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">arange</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">prices</span><span class="p">))</span> <span class="n">returns</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">diff</span><span class="p">(</span><span class="n">prices</span><span class="p">)</span> <span class="o">/</span> <span class="n">prices</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="n">noise_std</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">std</span><span class="p">(</span><span class="n">returns</span><span class="p">)</span> <span class="n">dataset</span> <span class="o">=</span> <span class="n">Dataset</span><span class="p">(</span> <span class="n">x</span><span class="o">=</span><span class="n">dates</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">prices</span><span class="p">,</span> <span class="n">dx</span><span class="o">=</span><span class="n">np</span><span class="p">.</span><span class="n">full_like</span><span class="p">(</span><span class="n">dates</span><span class="p">,</span> <span class="mi">2</span><span class="o">/</span><span class="mi">24</span><span class="p">),</span> <span class="n">dy</span><span class="o">=</span><span class="n">np</span><span class="p">.</span><span class="n">full_like</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span> <span class="n">noise_std</span><span class="p">)</span> <span class="c1"># small assumed measurement uncertainty </span><span class="p">)</span></code></pre></figure> <p>which looks like the following:</p> <p><img src="/images/posts/msft-data.png" alt="MSFT Data" /></p> <p>We can then build a simple GBM based on assuming 2% volatility (\(\sigma=0.02\)) and 0.11% drift (\(\mu=0.0011\)):</p> <figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">model</span> <span class="o">=</span> <span class="n">GBM</span><span class="p">(</span> <span class="n">initial_value</span> <span class="o">=</span> <span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">drift</span> <span class="o">=</span> <span class="mf">1.1e-3</span><span class="p">,</span> <span class="n">drift_bounds</span> <span class="o">=</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mf">0.1</span><span class="p">),</span> <span class="n">volatility</span> <span class="o">=</span> <span class="mf">2e-2</span><span class="p">,</span> <span class="n">volatility_bounds</span> <span class="o">=</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="p">)</span></code></pre></figure> <p>Then, we can just let it run buck-wild on this data:</p> <figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">result</span> <span class="o">=</span> <span class="n">autofit</span><span class="p">(</span><span class="n">dataset</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">graphing_options</span><span class="o">=</span><span class="n">g_opts</span><span class="p">)</span> <span class="n">print_results</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span></code></pre></figure> <p>and this actually won’t change the model parameters we gave it due to the fact that its a stochastic model (so there are local minima essentially everywhere, making <code class="language-plaintext highlighter-rouge">curve_fit</code> useless), but it can give some really interesting potential fits:</p> <p><img src="/images/posts/msft-fit.png" alt="MSFT Fit" /> <img src="/images/posts/msft-fit-2.png" alt="MSFT Fit 2" /></p> <p>However, each at a substantial price: \(\chi^2 &gt; 5 \times 10^7\). Again, though, this is to be expected, as this is a very naive model, so it is entirely to-be-expected that it wouldn’t work.</p> Sat, 24 Jan 2026 23:26:31 +0000 https://moofy.org/posts/experimentalis/</link> https://moofy.org/posts/experimentalis/ python mathematics programming My Trip to New England <p>I went to New England last summer, took a whole bunch of pictures, then I started this article and proceeded to not finish it for four months straight. I feel as though it is more than high time that I went back through here and showed off some of the great things I got to see.</p> <p>I took the trip in mid-July, a few weeks before going back to school for the year. At the time, I was finishing the Autobiography of Malcolm X, and the last time I had been to Boston was my Senior year of high school, so I knew I really wanted to get a good look around both Manhattan and Boston, particularly to visit Harlem and a few big-name universities.</p> <p>So, I took a six-hour flight to Newark, then ended up hoteled in Jersey City, NJ, right outside of Manhattan. Right outside my hotel, there was this little gang of homeless street-cats just chilling out near a railway line, and I thought that they looked super cool, so I took plenty of pictures of the little guys. Check it out:</p> <p><img src="/images/new-england-trip/cats/DSC03449.JPG" alt="Kitty looking away at something." /> <img src="/images/new-england-trip/cats/DSC03460.JPG" alt="Another kitty, looking at me." /></p> <blockquote> <p>If you want to see all of the cat pictures, you can see them <a href="https://github.com/mufaro3/mufaro3.github.io/tree/master/images/new-england-trip/cats">here</a>.</p> </blockquote> <p>Of course, I was in New Jersey, after all, so there are plenty of non-feline flicks from there. What was most interesting to me was the ethnic-Indian neighborhood called “Little India” near where I was staying.</p> <p><img src="/images/new-england-trip/new%20jersey/little-india-street.JPG" alt="Little India" /></p> <p>It had this particular street called “India Square” that had all sorts of cool restaurants and shops. I even had lunch at one of the places, and it was pretty great.</p> <p><img src="/images/new-england-trip/new%20jersey/india-square.JPG" alt="India Square" /></p> <p>I also just generally walked around New Jersey, and that was fun. For example, I got to see Central Avenue:</p> <p><img src="/images/new-england-trip/new%20jersey/central-ave.JPG" alt="Central Avenue" /></p> <p>Then, once New Jersey was all said-and-done, I skipped on over to Manhattan. First, I headed on over to Central Park, and got a good look at all sorts of interesting wildlife and greenery:</p> <p><img src="/images/new-england-trip/manhattan/central-park/bench.JPG" alt="Benches" /></p> <p><img src="/images/new-england-trip/manhattan/central-park/lake.JPG" alt="Lake" /></p> <p>Naturally, as anybody in Manhattan, I spent plenty of time on the subway:</p> <p><img src="/images/new-england-trip/manhattan/subway/crowded.JPG" alt="The Crowded Tube" /></p> <p><img src="/images/new-england-trip/manhattan/subway/exit.JPG" alt="Exit" /></p> <p><img src="/images/new-england-trip/manhattan/subway/polycule.JPG" alt="Polycule" /></p> <blockquote> <p><em>Targeted advertising.</em></p> </blockquote> <p>As a Vancouverite, it baffled me just how hot the NYC subway was. The Vancouver SkyTrain is always freezing cold, regardless of the time of year, so I naturally went into the NYC subway with my full jacket on. I was completely wrong.</p> <p>Anyway, I spent plenty of time walking around Manhattan normally. I first found my way over to Times Square, getting to see big, gold Raisin’ Canes:</p> <p><img src="/images/new-england-trip/manhattan/times/canes.JPG" alt="Canes" /></p> <p>then I oogled at all of the advertisements on Times Square:</p> <p><img src="/images/new-england-trip/manhattan/times/ads.JPG" alt="Ads" /> <img src="/images/new-england-trip/manhattan/times/sweeney.JPG" alt="Sydney Sweeney" /></p> <p>I also found the crowd at Times Square incredibly interesting:</p> <p><img src="/images/new-england-trip/manhattan/times/crowd.JPG" alt="Crowd" /></p> <p>it was absolutely packed with people! I was so suprised. Next, I did a bit more looking-around, visiting (just outside of) Columbia University and Barnard College, and <a href="https://www.youtube.com/watch?v=j4jtIDaeaWI">Tom’s Diner</a>:</p> <p><img src="/images/new-england-trip/manhattan/toms/toms.JPG" alt="Tom's Diner" /></p> <p>Alongside, of course, plenty of Zohran Mamdani posters and Malcolm X landmarks:</p> <p><img src="/images/new-england-trip/manhattan/street/mamdani-shabazz.JPG" alt="Mamdani-Shabazz" /></p> <p>When all of this was said and done, I took and AMTRAK over to Boston. I started out by taking a trip over to Northeastern University as a friend of mine goes here:</p> <p><img src="/images/new-england-trip/boston/neu/neu.JPG" alt="Northeastern University" /></p> <p><img src="/images/new-england-trip/boston/neu/cathedral.JPG" alt="NEU Cathedral" /></p> <p>Then, of course, I headed over to Harvard and MIT as is ritual:</p> <p><img src="/images/new-england-trip/boston/harvard-mit/harvard-2.JPG" alt="Harvard" /></p> <p><img src="/images/new-england-trip/boston/harvard-mit/mit.JPG" alt="MIT" /></p> <p>And to end out, I headed over to Salem, MA, to do a witch tour:</p> <p><img src="/images/new-england-trip/boston/salem/first-church.JPG" alt="First Church" /></p> <p>And, altogether, it was super fun! There’s a ton more pictures, but in general, I thought this was a fun trip. There wasn’t really much that was all that interesting to see out of the universities, though, because I had already been to Harvard and most of MIT was under construction and blocked off.</p> Sat, 24 Jan 2026 13:22:17 +0000 https://moofy.org/posts/new-england-trip/</link> https://moofy.org/posts/new-england-trip/ photography travel personal Douglas Rushkoff's Cyberia: Objectivity and Reality in the Virtual Age <p>I recently finished <em>Cyberia</em> by Douglass Rushkoff, and in it, Rushkoff discusses the paradigm shift of the supposed grounded, objective reality essentially losing its footing as humanity begins its exploration into digital consciousness, as virtual space acts as an entirely unique dimension to the one in which we presently inhabit. As such, it operates on entirely different rules. It is as though laws of natural sciences like Physics are of little importance in a digital ecosystem and more abstract, philosopical or sociological ideologies such as metaphysics, abstract mathematics, and religious or spiritual ideas have a heightened applicability. We can most directly feel such a change from its parallel in the shift from an industrial society, marked by technological dominance in the forms of physical engineering, to an information age, marked by technological dominance in the form of largely ideological technology.</p> <p>From this, Rushkoff’s <em>Cyberia</em>, then, poses some incredible questions, most importantly “Where is this new technology going to take us?” and “How objective is objectivity?” First and foremost, the former question is so pivotal to understanding just how important the virtual age is, and as it is such a complex question to tackle, I won’t go into it. (Rushkoff’s <em>Cyberia</em> spends its length chiefly concerned with finding its answer, so I recommend reading the book to examine that.) Rather, I’m much more interested in the latter question: “How objective is objectivity?,” or, in other words, “How do we define reality?”</p> <p>So, I start by thinking of our definition of objective reality based on our senses, but similarly, we know that biologically, our senses have to work off of approximations of reality (such as reasonably having a discrete rate at which information is processed, so, for example, time is approximated as continuous in the brain from discrete measurements), so we know that our senses are not as good of a barometer for understanding the underlying nature of reality. Instead, our senses are not much more than exactly what they are: a system for perceiving the working reality necessary to live our lives effectively. What this means isn’t necessarily that what we perceive physically isn’t the “true reality,” but rather, that what we perceive is not guaranteed to be the “true reality,” and this “true reality” may be something beyond our physical or biological perception.</p> <p>Furthermore, I think that this is just indicative of the failures of perceiving the world as a human being. Another interesting point that <em>Cyberia</em> brings up is on viewing the world under the context of ego (in particular, <em>Cyberia</em> was interested in how the use of psychedelics broke free from this context). Many things that we take as axioms for how the world works, like gender roles, physical perception (like hearing sounds and seeing colors), identity, etc. fall apart when the ego is removed, and the destruction of these axioms ripples out in a fractal-like manner (as the book describes it, where fractals in Chaos theory are uber-sensitive to initial conditions and recursive such that these changes persist and grow over each recursion) to affect all kinds of great conclusions about how we perceive the world.</p> Sun, 03 Aug 2025 22:55:55 +0000 https://moofy.org/posts/objectivity-and-reality/</link> https://moofy.org/posts/objectivity-and-reality/ philosophy essay Kafkaesque and Catch-22's: Bureaucracy, Drugs, Universities, Networking, and Corporations <p>Hell is on earth, and it’s a waiting room, a line, a series of multicolored files and lengthy emails, weekly zoom meetings, LinkedIn posts, shareholder conferences, university applications, keynote speeches, and god-knows how much other representations of institutional red tape. In such a hell, by the <a href="https://moofy.org/posts/nightmare-of-interconnection">“Nightmare of Interconnection”</a>, all beings within it can be said to be simultaneously its victims and its demons, and the devil at the head of it all isn’t any particular individual, but rather, the system itself.</p> <p>Of Kafka’s three major works, <em>The Metamorphosis, The Trial,</em> and <em>The Castle</em>, I’ve only read the two former works. In particular, in <em>The Trial</em>, Franz Kafka displays the grotesque, demonic face of the needlessly bureaucratic system in such a way that every member of “civilized” society knows all too well. We’ve constructed a system of of over-organization, one that prioritizes a working order of rules and regulations so much that the the welfare of individuals is considered last, and ironically, such a system becomes so organized that its effectively something of a lawless, unempathetic mess in its final effect.</p> <p>For example, we write laws with the intent of providing an orderly system of morality and punishment under society, and seemingly, the more rigid laws are written, the more the order is enforced. The more absolute and unchangeable a law is, the easier it is to enforce (and intrinsically, the more fair it becomes). The issue, however, is that just like physical rigidity or hardness of objects, the more rigid a law is, the cleaner it shall break. Loopholes in rigid laws are considerably more exploitable than laws which are flexible and open to interpretation, and although one could argue that flexible laws are easier to produce loopholes for (due to being open to interpretation), again, their flexible nature makes combatting these loopholes similarly simple through exploring other interpretations.</p> <p>What a rigid society produces is an over-emphasis on rules and order with a lack of interest in the wellbeing of individuals and a fragility in the social order due to being largely unable to change with the course of humanity and thus much quicker to break. What comes immediately to mind is the legislation produced about recreational drugs. Legislation regarding drug use (that being, wide-sweeping bans with immense penalties for illegal distribution or usage) has historically had little to do with the supposed or fronted reasons of promoting social welfare. Rather, it’s far more been a tool for systematically oppressing groups that are the most susceptible to drug use. Controlled substances have been popular in human society from our initial civilizations, especially those like alcohol and medicinal herbs, and despite this, the rhetoric concerning drug use is largely conflicting. The state emphasizes an avoidance of drugs of all kind yet many fail to see the similarities between a drug like alcohol to drugs like Marijuana or psychedelics like psilocybin (magic mushrooms).</p> <p>Regardless of the negative effects of such drugs, much of which has been studied relentlessly due to this long debate over the decriminalization or legalization of such drugs, we know from history (such as the effects of the prohibition) that wide-sweeping, rigid bans are not in the true interest of social welfare whatsoever. If we truly wanted to aid the population in avoiding addictance to these drugs and lowering deaths due to overdose or poison (from misuse), then the public must be educated about the full range of the effects of drugs alongside the proper, safe consumption of these drugs, and the entirety of the production and distribution system of such drugs must also be made into a legalized process such that the industry can be regulated. It is a fundamental fact of free-market capitalism that where there is a demand, there shall be someone that will look to meet it with a supply. The question thereby lies in the hands of the government: would they rather that someone be somebody above-board that they can control, or somebody unscrupulous whose success entirely depends on evading your control as much as possible?</p> <p>Furthermore, we engage in the kafkaesque in all manners of society: especially the pipeline of education to the working, corporate world. Due to the capitalism underlying everything in education, much of the education system feels like a peacock show more than its actually about scholarship. For example, scientists are only really scholars as a part-time job. First and foremost, they are salesmen. The success of a researcher, especially in STEM, is largely based on their ability to sell their research to investors (grant funding organizations, such as corporations). Similarly, the success of a student is based on their ability to sell themselves to investors of other kinds, such as the universities, scholarships, or professors they apply to. Universities see the students they admit like investments, with the most likely candidates for admission being those who the university sees as the most likely to be a valuable relationship to have years after graduation. In turn, we see the effect of the children of the uber-wealthy or heads of state being disproportionately admitted to elite universities, but who can blame the colleges? Each admit is something of a gamble to the university, and an already wealthy or well-connected student is a far safer bet for how much the university can profit off of the student later down the line.</p> <p>Furthermore, the entirety of the topic of networking is such an absurd system from the outside looking in. Many people justify the intense desire to enter elite universities by stating that top universities act as aggregators for the sharpest minds around, and as such, the appeal of a top university is the ability to network with the most powerful leaders-to-be. As James Bryant Conant once stated, <em>“A Harvard education consists of what you learn at Harvard while you are not studying.”</em></p> <p>The issue I see with the mentality behind networking is that it views social interaction in such a performative and lain manner. The networking mentality reduces people down into tools for hierarchical advancement, and the irony of advancing in capitalism fundamentally boils down to the idea that you can have anything when you fundamentally don’t need it, and with regards to networking or college applications, any college will quickly accept you and any person will swiftly try to connect with you if they see that their connection with you will allow them to gain something. The irony, therefore, is that the peoplpe that can make the most use out of a university education or a professional connection are those who cannot access it. It’s something of a Catch-22. You need clout or appeal to attract the relationships and positions that will garner you clout. For example, consider job experience. The age-old lamentation is <em>“You need job experience to get a job, but the only way to get job experience is to get a job.”</em> Catch-22, QED.</p> <p>Our world is red tape and contradictions, rules and operations that make sense at individual levels but come together to produce a whole system that is woefully out-of-order. And what is to remedy it? Burning it down? Is anarchism the answer? Perhaps a return to some idealistic traditional society? In my opinion, probably not, and also due to the nightmare of interconnection. Such problems are probably more intrinsic to humanity than simple the result of the systems we have at hand. However, in all, I don’t know. I just don’t know.</p> Sat, 02 Aug 2025 15:45:02 +0000 https://moofy.org/posts/kafkaesque-bureaucracy/</link> https://moofy.org/posts/kafkaesque-bureaucracy/ society political essay The Nightmare of Interconnection <p>The nightmare of interconnection is simple: it’s the extension of the perils of individual connections extended to scale of entire networks of conjoined masses. It’s the ripple effect of the transfer of information and ideas from one person to another, the basket of negative effects that continuously seems to arise time and time again both to and from the torment of the masses involved. The nightmare of interconnection, as I choose to refer to it, is something like the underlying beast in systems of people: mob mentality, herd culture, gossip, tyranny of the majority, and so on.</p> <p>It certainly feels like much of the anti-central establishment ideology and conspiracy theories around shadowy organizations designed to control the masses ever-so-slightly miss the mark of the truth, as the true horror of this nightmare is that individuals are never truly in control or free. Rather, it’s the hidden, invisible beast of interconnection that dominates absolutely everything, and those who hold any power simply find tricky ways to influence the beast’s actions.</p> <p>I understand that this may come across as an overcomplicated definition or overly-dramatic description of the problems that can arise from people in mass-networks acting as herds, as countless people have studied its patterns and effects throughout history (look no further than the rise of the Nazis, it’s puzzled sociologists for decades just how good-natured Germans could be driven to believe in such racist and vile ideas), but I have chosen to represent it as something like a hidden beast intentionally. It’s the rawest form of humanity: our collective subconscious ideas and desires, and our formation of organized, hierarchical, worker-bee society has sharpened the fangs of the beast as it grew in power alongside the growth of organized civilization itself.</p> <p>And now, we find ourselves at firmly settled into a new era, one with rapid interconnection of fiber-optic speed. At all times, all peoples connected to the internet are connected to each other, and with this, we connect with far more than merely just our thoughts, jokes, purchases, and the like. We connect our identities, our desires, and <a href="https://moofy.org/posts/cosmetics-and-appearances/">our insecurities</a>.</p> <p>The more we interconnect, the more we lose our sense of self. We become another face in the mob, another like or comment in a sea. And who, just who, is truly in charge? Many point to those who profiteer, the businessmen and polticians that hold the power to influence the actions of the mob, to push advertisements to affect the desires and convictions of the masses to get them to purchase their products or serve in their militaries or otherwise subscribe to their ideals.</p> <p>However, these people are no more capable of controlling of the collective subconscious than a sailor can control the sea. The nightmare of interconnection, the terrors from the collective subconscious, can be studied, affected, manipulated, and finally exploited in much the way the ocean has for thousands of years, but despite the immense impact humanity has had on the ocean, we still hardly have anything even remotely close to a sense of control over it. The irony of attempts to control the societal subconscious in any form is that any affectation given to it is simultaneously an affectation given to the self. All people within it, meaning all humans, are affected by it through history (as all events, too, are connected). It’s like Milo Minderbinder’s syndicate in Joseph Heller’s <em>Catch-22</em>: “Everybody gets a share.”</p> <p>To provide some examples, look at autocratic states run by ideologies of distrust or hate. Those spewing the hate, stoking the passionate fire of a desire for purge or blood within the subconscious of the nation’s constituents, can often have that same hate turned right back towards them. Look how quickly Soviet Russia post-revolution could turn against its founders. Lenin was hailed more as an idea than a man, and Trotsky was driven right out of the country only to be later brutally murdered. Look at stories like the assassination of Malcolm X by his own muslims, a betrayal not too unlike the historic assassination of Julius Caesar.</p> <p>The ideologies or systems these men fight to create become their own worst enemy. Stalin himself was notoriously paranoid of assassination from his closest comrades, fearing that what he had done unto his comrades would be done unto him, leading to the great purge of Soviet Russia where many innocent people were sent to gulags and brutally murdered. Really, it cannot be that Stalin was truly in charge, for he had a master of his own he had to do all in his power to appease throughout his rule. The true kingpin of the USSR was not Joseph Stalin, but rather, it was the all-consuming Bolshevik-turned-Stalinist ideology that was primed to exact its terror on Stalin himself in its quest for constant blood and exact ideological purity, and the only way Stalin could keep its hunger sated to prolong his downfall was to keep maintaining a masquerade of control for as long as he could.</p> <p>And just think, this behavior of a great fear of the system one has built (a system comprised of fear-based rule) is not the exception for these autocrats (or any leader whatsoever), rather, it’s generally the rule. Presidents fear that their constituents will believe that they have betrayed the ideologies that sworn them in, and all representatives are constantly acting such that they can safely secure re-election.</p> <p>So, then, I ask again: are these people really in charge? Are individuals, even top executive chairmen of international corporations or political heads-of-state, really to be considered as “running things” as there are? <em>Is anyone, anybody at all, actually at the wheel of this bus?</em> It seems so easy to come up with such daydreams of hidden syndicates of unscrupulous, expensive-suited men deciding the world order between coffee-breaks, but I believe the true entity in charge of the state of the world’s affairs is much, much more of an uncontrollable, unpredictable nightmare.</p> Thu, 31 Jul 2025 17:12:20 +0000 https://moofy.org/posts/nightmare-of-interconnection/</link> https://moofy.org/posts/nightmare-of-interconnection/ society philosophy essay N00M: My Attempt at Raycasting and 3-D Video Game Design in C <p>A few months ago, I asked myself what it would take to make a raycaster in C. I’ve seen other programmers before make successful raycasters, namely <a href="https://www.youtube.com/@jdh/videos">jdh</a> in one of my favorite videos of his: <em>Programming a first person shooter from scratch like it’s 1995</em></p> <div class="video-container"> <iframe src="https://www.youtube.com/embed/fSjc8vLMg8c" frameborder="0" allowfullscreen=""></iframe> </div> <p>In particular, I’m incredibly inexperienced in basically all facets of game development, but especially with 3-D games. I’ve only ever made a singular useful graphical program before, <a href="https://github.com/mufaro3/sorting-visualization">mufaro3/sorting-visualization</a>, and it was in C++ using SFML rather than C, and the most I had attempted graphical program design in C was using some basic SDL to draw a few shapes onto the screen about a year or so prior. The bottom line is that in starting this project, I might as well be jumping off into the void.</p> <p>However, I was really certain that I wanted to understand the basics of 3-D software rendering, as it seemed so incredibly complicated. Therefore, what I set out to do in <a href="https://github.com/mufaro3/n00m">mufaro3/n00m</a> was to follow <a href="https://lodev.org/cgtutor/raycasting.html">Lode’s Computer Graphics Tutorial</a> on raycasting engine development as much as possible to successfully build my own DOOM clone (thus, why I called it N00M, as it’s my own “nickelulzian doomstyle renderer”).</p> <p>I opted to make N00M in C using SDL for graphics, <a href="https://github.com/recp/cglm">recp/cglm</a> to simplify the linear algebra calculations, and <a href="https://github.com/rxi/log.c">rxi/log.c</a> for logging. Therefore, to begin with, I set up my C directory as follows (my usual structure):</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>n00m/ ├── src/ │ ├── main.c │ └── common.h ├── lib/ │ ├── cglm │ └── log.c ├── res ├── CMakeLists.txt ├── Makefile ├── .gitignore ├── LICENSE ├── AUTHORS └── README </code></pre></div></div> <p>I first just made sure to set up my build system with a basic headerfile to test if everything could link and build successfully:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="cp">#include</span> <span class="cpf">"common.h"</span><span class="cp"> </span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="n">printf</span><span class="p">(</span> <span class="s">"Hello, World!</span><span class="se">\n</span><span class="s">"</span> <span class="p">);</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span></code></pre></figure> <p>Once this worked, I got started on the actual program structure. Good graphical programs, even in C, are highly modularized, so I started breaking down the system into modules (essentially a variable/struct storing the state of that module for the program at a given time and a header and associated source file for that module with related functions):</p> <ol> <li><code class="language-plaintext highlighter-rouge">graphics</code> for managing everything rendering/graphics related</li> <li><code class="language-plaintext highlighter-rouge">state</code> for the actual logical game state</li> <li><code class="language-plaintext highlighter-rouge">config</code> for configuration values managed under <code class="language-plaintext highlighter-rouge">config.h</code> and <code class="language-plaintext highlighter-rouge">config.c</code></li> </ol> <p>Then, I started writing out the graphics module directly. I started with some functions to initialize SDL and close the graphics module as</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="kt">void</span> <span class="nf">graphics_init</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">config_t</span> <span class="o">*</span><span class="n">config</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">SDL_Init</span><span class="p">(</span><span class="n">SDL_INIT_VIDEO</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="n">log_fatal</span><span class="p">(</span><span class="s">"SDL could not be initialized!</span><span class="se">\n</span><span class="s">"</span> <span class="s">"SDL Error: %s"</span><span class="p">,</span> <span class="n">SDL_GetError</span><span class="p">());</span> <span class="n">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span> <span class="p">}</span> <span class="n">SDL_SetHint</span><span class="p">(</span><span class="n">SDL_HINT_RENDER_SCALE_QUALITY</span><span class="p">,</span> <span class="s">"1"</span><span class="p">);</span> <span class="kt">int</span> <span class="n">image_flags</span> <span class="o">=</span> <span class="n">IMG_INIT_PNG</span> <span class="o">|</span> <span class="n">IMG_INIT_JPG</span> <span class="o">|</span> <span class="n">IMG_INIT_TIF</span><span class="p">;</span> <span class="kt">int</span> <span class="n">image_init</span> <span class="o">=</span> <span class="n">IMG_Init</span><span class="p">(</span><span class="n">image_flags</span><span class="p">);</span> <span class="k">if</span> <span class="p">((</span><span class="n">image_init</span> <span class="o">&amp;</span> <span class="n">image_flags</span><span class="p">)</span> <span class="o">!=</span> <span class="n">image_flags</span><span class="p">)</span> <span class="p">{</span> <span class="n">log_fatal</span><span class="p">(</span><span class="s">"SDL_image could not be initialized!</span><span class="se">\n</span><span class="s">"</span> <span class="s">"SDL_image Error: %s"</span><span class="p">,</span> <span class="n">IMG_GetError</span><span class="p">());</span> <span class="n">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span> <span class="p">}</span> <span class="k">if</span> <span class="p">(</span><span class="n">TTF_Init</span><span class="p">()</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="n">log_error</span><span class="p">(</span><span class="s">"SDL_TTF could not be initialized!</span><span class="se">\n</span><span class="s">"</span> <span class="s">"SDL_TTF Error: %s"</span><span class="p">,</span> <span class="n">TTF_GetError</span><span class="p">());</span> <span class="p">}</span> <span class="cp">#if defined linux &amp;&amp; SDL_VERSION_ATLEAST(2, 0, 8) </span> <span class="cm">/* Disable compositor bypass */</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">SDL_SetHint</span><span class="p">(</span><span class="n">SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR</span><span class="p">,</span> <span class="s">"0"</span><span class="p">))</span> <span class="p">{</span> <span class="n">log_fatal</span><span class="p">(</span><span class="s">"SDL cannot disable compositor bypass!"</span><span class="p">);</span> <span class="n">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span> <span class="p">}</span> <span class="cp">#endif </span> <span class="n">gfx</span><span class="o">-&gt;</span><span class="n">window</span> <span class="o">=</span> <span class="n">SDL_CreateWindow</span><span class="p">(</span><span class="n">config</span><span class="o">-&gt;</span><span class="n">window_title</span><span class="p">,</span> <span class="n">SDL_WINDOWPOS_CENTERED</span><span class="p">,</span> <span class="n">SDL_WINDOWPOS_CENTERED</span><span class="p">,</span> <span class="n">config</span><span class="o">-&gt;</span><span class="n">window_width</span><span class="p">,</span> <span class="n">config</span><span class="o">-&gt;</span><span class="n">window_height</span><span class="p">,</span> <span class="n">SDL_WINDOW_SHOWN</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">window</span><span class="p">)</span> <span class="p">{</span> <span class="n">log_fatal</span><span class="p">(</span><span class="s">"Window could not be created!</span><span class="se">\n</span><span class="s">"</span> <span class="s">"SDL Error: %s"</span><span class="p">,</span> <span class="n">SDL_GetError</span><span class="p">());</span> <span class="n">SDL_Quit</span><span class="p">();</span> <span class="n">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span> <span class="p">}</span> <span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span> <span class="o">=</span> <span class="n">SDL_CreateRenderer</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">window</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">SDL_RENDERER_PRESENTVSYNC</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">)</span> <span class="p">{</span> <span class="n">log_fatal</span><span class="p">(</span><span class="s">"Renderer could not be created!</span><span class="se">\n</span><span class="s">"</span> <span class="s">"SDL Error: %s"</span><span class="p">,</span> <span class="n">SDL_GetError</span><span class="p">());</span> <span class="n">SDL_DestroyWindow</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">window</span><span class="p">);</span> <span class="n">SDL_Quit</span><span class="p">();</span> <span class="n">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span> <span class="p">}</span> <span class="n">gfx</span><span class="o">-&gt;</span><span class="n">screen_texture</span> <span class="o">=</span> <span class="n">SDL_CreateTexture</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="n">SDL_PIXELFORMAT_RGBA8888</span><span class="p">,</span> <span class="n">SDL_TEXTUREACCESS_STREAMING</span><span class="p">,</span> <span class="n">config</span><span class="o">-&gt;</span><span class="n">window_width</span><span class="p">,</span> <span class="n">config</span><span class="o">-&gt;</span><span class="n">window_height</span><span class="p">);</span> <span class="p">}</span> <span class="kt">void</span> <span class="nf">graphics_close</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">)</span> <span class="p">{</span> <span class="n">SDL_DestroyTexture</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">screen_texture</span><span class="p">);</span> <span class="n">SDL_DestroyRenderer</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">);</span> <span class="n">SDL_DestroyWindow</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">window</span><span class="p">);</span> <span class="n">TTF_Quit</span><span class="p">();</span> <span class="n">IMG_Quit</span><span class="p">();</span> <span class="n">SDL_Quit</span><span class="p">();</span> <span class="p">}</span></code></pre></figure> <p>The idea behind this is that every module will have this same kind of structure, an initialization function and a deinitialization (or close) function. Why this is useful is that it simplifies the general structure of my program. To see this, we can look directly at the main function:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="kt">int</span> <span class="nf">main</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span> <span class="n">log_info</span><span class="p">(</span><span class="s">"Initializing"</span><span class="p">);</span> <span class="cm">/* setup the random number generator */</span> <span class="n">srand</span><span class="p">(</span><span class="n">time</span><span class="p">(</span><span class="mi">0</span><span class="p">));</span> <span class="n">config_t</span> <span class="n">config</span><span class="p">;</span> <span class="n">config_load</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> <span class="n">graphics_t</span> <span class="n">gfx</span><span class="p">;</span> <span class="n">graphics_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">gfx</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> <span class="n">state_t</span> <span class="n">state</span><span class="p">;</span> <span class="n">state_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">state</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> <span class="n">log_info</span><span class="p">(</span><span class="s">"Looping"</span><span class="p">);</span> <span class="k">while</span> <span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">running</span><span class="p">)</span> <span class="n">loop</span><span class="p">(</span><span class="o">&amp;</span><span class="n">state</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">gfx</span><span class="p">);</span> <span class="n">log_info</span><span class="p">(</span><span class="s">"Closing"</span><span class="p">);</span> <span class="n">graphics_close</span><span class="p">(</span><span class="o">&amp;</span><span class="n">gfx</span><span class="p">);</span> <span class="n">config_close</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> <span class="p">}</span></code></pre></figure> <p>The layout of each module’s data structure was pretty simple. In <code class="language-plaintext highlighter-rouge">graphics_t</code>, I included some simple SDL pointers necessary for basic rendering. The idea behind <code class="language-plaintext highlighter-rouge">graphics_t</code>, after all, is as a singular struct that simplifies passing-in the graphical state of the program into various functions (so any function with a graphical component that may need to access just the <code class="language-plaintext highlighter-rouge">SDL_Window</code> context or the <code class="language-plaintext highlighter-rouge">SDL_Renderer</code> or etc. can just simply have the entire graphical state passed in at once for simplicity).</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">typedef</span> <span class="k">struct</span> <span class="n">_graphics</span> <span class="p">{</span> <span class="n">SDL_Window</span> <span class="o">*</span><span class="n">window</span><span class="p">;</span> <span class="n">SDL_Renderer</span> <span class="o">*</span><span class="n">renderer</span><span class="p">;</span> <span class="n">SDL_Texture</span> <span class="o">*</span><span class="n">screen_texture</span><span class="p">;</span> <span class="p">}</span> <span class="n">graphics_t</span><span class="p">;</span></code></pre></figure> <p>Similarly, the other modules were much the same. The entire game state in <code class="language-plaintext highlighter-rouge">state_t</code> was:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">typedef</span> <span class="k">struct</span> <span class="n">_fpstimer</span> <span class="p">{</span> <span class="kt">uint64_t</span> <span class="n">ticks</span><span class="p">,</span> <span class="n">frames</span><span class="p">,</span> <span class="n">last_update_time</span><span class="p">;</span> <span class="kt">float</span> <span class="n">tps</span><span class="p">,</span> <span class="n">fps</span><span class="p">;</span> <span class="n">bool</span> <span class="n">infinite_fps</span><span class="p">;</span> <span class="p">}</span> <span class="n">fpstimer_t</span><span class="p">;</span> <span class="cm">/* fonts */</span> <span class="k">enum</span> <span class="p">{</span> <span class="n">DEJAVU_SANS_MONO</span><span class="p">,</span> <span class="n">TOTAL_FONTS</span> <span class="p">};</span> <span class="cp">#define TEXTURE_WIDTH 64 #define TEXTURE_HEIGHT 64 #define NUM_TEXTURES 8 </span> <span class="k">typedef</span> <span class="k">struct</span> <span class="n">_state</span> <span class="p">{</span> <span class="n">bool</span> <span class="n">running</span><span class="p">;</span> <span class="n">vec2s</span> <span class="n">camera_plane</span><span class="p">;</span> <span class="n">ivec2s</span> <span class="n">map_size</span><span class="p">;</span> <span class="n">ivec2s</span> <span class="n">resolution</span><span class="p">;</span> <span class="cm">/* textures */</span> <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">textures</span><span class="p">[</span><span class="n">NUM_TEXTURES</span><span class="p">];</span> <span class="cm">/* loaded fonts */</span> <span class="n">TTF_Font</span> <span class="o">*</span><span class="n">fonts</span><span class="p">[</span><span class="n">TOTAL_FONTS</span><span class="p">];</span> <span class="n">TTF_Font</span> <span class="o">*</span><span class="n">debug_font</span><span class="p">;</span> <span class="kt">int</span> <span class="n">debug_line_y</span><span class="p">;</span> <span class="cm">/* map information */</span> <span class="n">map_t</span> <span class="n">map</span><span class="p">;</span> <span class="cm">/* controls and whatnot */</span> <span class="n">bool</span> <span class="n">keys</span><span class="p">[</span><span class="n">SDL_NUM_SCANCODES</span><span class="p">];</span> <span class="n">ivec2s</span> <span class="n">mouse_pos_delta</span><span class="p">;</span> <span class="kt">float</span> <span class="n">mouse_sensitivity</span><span class="p">;</span> <span class="n">player_t</span> <span class="n">player</span><span class="p">;</span> <span class="n">fpstimer_t</span> <span class="n">timer</span><span class="p">;</span> <span class="p">}</span> <span class="n">state_t</span><span class="p">;</span></code></pre></figure> <p>with some code for player information, the presently loaded fonts, debugging info, and some controls and timing variables. Lastly, <code class="language-plaintext highlighter-rouge">config_t</code> was much the same:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">typedef</span> <span class="k">struct</span> <span class="n">_config</span> <span class="p">{</span> <span class="kt">uint32_t</span> <span class="n">window_height</span><span class="p">,</span> <span class="n">window_width</span><span class="p">;</span> <span class="kt">uint8_t</span> <span class="n">debug_font_size</span><span class="p">;</span> <span class="kt">char</span> <span class="n">window_title</span><span class="p">[</span><span class="mi">512</span><span class="p">];</span> <span class="cm">/* system specification */</span> <span class="n">bool</span> <span class="n">is_big_endian</span><span class="p">;</span> <span class="p">}</span> <span class="n">config_t</span><span class="p">;</span></code></pre></figure> <p>Altogether, it’s a fairly simple system, and from there, I sought to actually being on rendering. I started by writing in some simple graphics functions (which I won’t show the implementations of, only the declarations):</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="kt">void</span> <span class="nf">graphics_init</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">config_t</span> <span class="o">*</span><span class="n">config</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">graphics_close</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">graphics_draw_pixel_buffer</span><span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">ivec2s</span> <span class="n">resolution</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">pixels</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">graphics_draw_text</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">TTF_Font</span> <span class="o">*</span><span class="n">font</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">text</span><span class="p">,</span> <span class="n">SDL_Color</span> <span class="n">text_color</span><span class="p">,</span> <span class="n">SDL_Color</span> <span class="n">background_color</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">,</span> <span class="kt">int</span> <span class="n">padding</span><span class="p">);</span></code></pre></figure> <p>and a map management system as well:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="cm">/* common defines */</span> <span class="cp">#define MAP_OPEN 0 #define NOT_FOUND -1 </span> <span class="k">typedef</span> <span class="k">struct</span> <span class="n">_map</span> <span class="p">{</span> <span class="kt">int</span> <span class="o">*</span><span class="n">cells</span><span class="p">;</span> <span class="n">ivec2s</span> <span class="n">size</span><span class="p">;</span> <span class="p">}</span> <span class="n">map_t</span><span class="p">;</span> <span class="n">SDL_Color</span> <span class="nf">map_get_color</span> <span class="p">(</span><span class="kt">int</span> <span class="n">map_value</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">map_init</span> <span class="p">(</span><span class="n">map_t</span> <span class="o">*</span><span class="n">map</span><span class="p">);</span> <span class="kt">void</span> <span class="nf">map_close</span> <span class="p">(</span><span class="n">map_t</span> <span class="o">*</span><span class="n">map</span><span class="p">);</span> <span class="kt">int</span> <span class="nf">map_at_vec</span> <span class="p">(</span><span class="n">map_t</span> <span class="o">*</span><span class="n">map</span><span class="p">,</span> <span class="n">ivec2s</span> <span class="n">pos</span><span class="p">);</span> <span class="kt">int</span> <span class="nf">map_at_fvec</span> <span class="p">(</span><span class="n">map_t</span> <span class="o">*</span><span class="n">map</span><span class="p">,</span> <span class="n">vec2s</span> <span class="n">pos</span><span class="p">);</span> <span class="kt">int</span> <span class="nf">map_at</span> <span class="p">(</span><span class="n">map_t</span> <span class="o">*</span><span class="n">map</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">);</span></code></pre></figure> <p>Finally, with this background, I could get started on the following static <code class="language-plaintext highlighter-rouge">main</code> file functions:</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">static</span> <span class="kt">void</span> <span class="nf">draw_current_frame</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">state_t</span> <span class="o">*</span><span class="n">state</span><span class="p">);</span> <span class="k">static</span> <span class="kt">void</span> <span class="nf">draw_mini_map</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">state_t</span> <span class="o">*</span><span class="n">state</span><span class="p">);</span> <span class="k">static</span> <span class="kt">void</span> <span class="nf">poll_events</span> <span class="p">(</span><span class="n">state_t</span> <span class="o">*</span><span class="n">state</span><span class="p">);</span> <span class="k">static</span> <span class="kt">void</span> <span class="nf">handle_keys</span> <span class="p">(</span><span class="n">state_t</span> <span class="o">*</span><span class="n">state</span><span class="p">);</span> <span class="k">static</span> <span class="kt">void</span> <span class="nf">draw_debug</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">state_t</span> <span class="o">*</span><span class="n">state</span><span class="p">,</span> <span class="n">config_t</span> <span class="o">*</span><span class="n">config</span><span class="p">);</span> <span class="k">static</span> <span class="kt">void</span> <span class="nf">loop</span> <span class="p">(</span><span class="n">state_t</span> <span class="o">*</span><span class="n">state</span><span class="p">,</span> <span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">config_t</span> <span class="o">*</span><span class="n">config</span><span class="p">);</span></code></pre></figure> <p>The idea behind these is that each handles a specific function. The main loop of the program is performed by <code class="language-plaintext highlighter-rouge">loop</code>, events and input are handled by <code class="language-plaintext highlighter-rouge">poll_events</code> and <code class="language-plaintext highlighter-rouge">handle_keys</code>, and then we have the three main drawing functions: <code class="language-plaintext highlighter-rouge">draw_current_frame</code> for the actual game scene, <code class="language-plaintext highlighter-rouge">draw_mini_map</code> for the minimap, and <code class="language-plaintext highlighter-rouge">draw_debug</code> for the debug screen. In this post, I won’t go into <code class="language-plaintext highlighter-rouge">draw_debug</code>, and I’ll mostly focus on the other two.</p> <p>To begin, drawing the minimap was quite simple. Essentially, what I’m doing is just first performing some calculations to determine how big the minimap should be and where it should be, then I draw the background of the minimap, and then I go in and loop through each of the squares of the minimap to draw in each square unit area by its associated color (as given by its mapvalue).</p> <figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">static</span> <span class="kt">void</span> <span class="nf">draw_mini_map</span> <span class="p">(</span><span class="n">graphics_t</span> <span class="o">*</span><span class="n">gfx</span><span class="p">,</span> <span class="n">state_t</span> <span class="o">*</span><span class="n">state</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* minimap background constants */</span> <span class="k">static</span> <span class="k">const</span> <span class="kt">uint8_t</span> <span class="n">BOX_SIZE</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> <span class="cm">/* width of each box */</span> <span class="k">static</span> <span class="k">const</span> <span class="kt">uint8_t</span> <span class="n">PADDING</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="cm">/* padding for the background */</span> <span class="k">static</span> <span class="k">const</span> <span class="kt">uint8_t</span> <span class="n">MARGIN</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="cm">/* the outer margin */</span> <span class="k">static</span> <span class="k">const</span> <span class="kt">uint8_t</span> <span class="n">PLAYER_SIZE</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> <span class="cm">/* width/height of the player icon */</span> <span class="cm">/* set up the box sizing for the outer box */</span> <span class="n">ivec2s</span> <span class="n">full_minimap_size</span> <span class="o">=</span> <span class="p">...</span> <span class="cm">/* determine placement based on the sizing */</span> <span class="n">ivec2s</span> <span class="n">full_minimap_position</span> <span class="o">=</span> <span class="p">...</span> <span class="cm">/* draw the background */</span> <span class="n">SDL_Rect</span> <span class="n">bg_rect</span> <span class="o">=</span> <span class="p">...</span> <span class="n">SDL_SetRenderDrawColor</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="n">EXPAND_COLOR</span><span class="p">(</span><span class="n">COLOR_WHITE</span><span class="p">));</span> <span class="n">SDL_RenderFillRect</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bg_rect</span><span class="p">);</span> <span class="n">ivec2s</span> <span class="n">box_top_left</span> <span class="o">=</span> <span class="n">glms_ivec2_adds</span><span class="p">(</span><span class="n">full_minimap_position</span><span class="p">,</span> <span class="n">PADDING</span><span class="p">);</span> <span class="p">...</span> <span class="cm">/* draw all of the boxes */</span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">state</span><span class="o">-&gt;</span><span class="n">map</span><span class="p">.</span><span class="n">size</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="o">++</span><span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">state</span><span class="o">-&gt;</span><span class="n">map</span><span class="p">.</span><span class="n">size</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="o">++</span><span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* get the fill color from the position */</span> <span class="kt">int</span> <span class="n">map_value</span> <span class="o">=</span> <span class="n">map_at</span><span class="p">(</span><span class="o">&amp;</span><span class="n">state</span><span class="o">-&gt;</span><span class="n">map</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">);</span> <span class="n">SDL_Color</span> <span class="n">fill_color</span> <span class="o">=</span> <span class="n">map_value</span> <span class="o">==</span> <span class="n">MAP_OPEN</span> <span class="o">?</span> <span class="n">COLOR_BLACK</span> <span class="o">:</span> <span class="n">map_get_color</span><span class="p">(</span><span class="n">map_value</span><span class="p">);</span> <span class="cm">/* calculate the fill position from the r,c value */</span> <span class="n">SDL_Rect</span> <span class="n">box</span> <span class="o">=</span> <span class="p">...</span> <span class="cm">/* now draw it to the screen */</span> <span class="n">SDL_SetRenderDrawColor</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="n">EXPAND_COLOR</span><span class="p">(</span><span class="n">fill_color</span><span class="p">));</span> <span class="n">SDL_RenderFillRect</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">box</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> <span class="cm">/* draw a tiny square to represent the player */</span> <span class="n">ivec2s</span> <span class="n">player_indicator_center</span> <span class="o">=</span> <span class="p">...</span> <span class="n">SDL_Rect</span> <span class="n">player_indicator_bounds</span> <span class="o">=</span> <span class="p">...</span> <span class="p">...</span> <span class="n">SDL_SetRenderDrawColor</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="n">EXPAND_COLOR</span><span class="p">(</span><span class="n">COLOR_LIGHT_GRAY</span><span class="p">));</span> <span class="n">SDL_RenderFillRect</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">player_indicator_bounds</span><span class="p">);</span> <span class="cm">/* draw a line to represent the view direction */</span> <span class="k">static</span> <span class="k">const</span> <span class="kt">int</span> <span class="n">view_line_distance</span> <span class="o">=</span> <span class="mi">20</span><span class="p">;</span> <span class="cm">/* normalize the direction vector then scale by the distance */</span> <span class="n">vec2s</span> <span class="n">direction_vector</span><span class="p">;</span> <span class="n">glm_vec2_normalize_to</span><span class="p">((</span><span class="kt">float</span><span class="o">*</span><span class="p">)</span> <span class="n">state</span><span class="o">-&gt;</span><span class="n">player</span><span class="p">.</span><span class="n">dir</span><span class="p">.</span><span class="n">raw</span><span class="p">,</span> <span class="n">direction_vector</span><span class="p">.</span><span class="n">raw</span><span class="p">);</span> <span class="n">direction_vector</span> <span class="o">=</span> <span class="n">glms_vec2_scale</span><span class="p">(</span><span class="n">direction_vector</span><span class="p">,</span> <span class="n">view_line_distance</span><span class="p">);</span> <span class="n">ivec2s</span> <span class="n">direction_vector_end</span> <span class="o">=</span> <span class="n">glms_ivec2_add</span><span class="p">(</span><span class="n">VEC2_INT</span><span class="p">(</span><span class="n">direction_vector</span><span class="p">),</span> <span class="n">player_indicator_center</span><span class="p">);</span> <span class="cm">/* draw the vector to the screen */</span> <span class="n">SDL_SetRenderDrawColor</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="n">EXPAND_COLOR</span><span class="p">(</span><span class="n">COLOR_LIGHT_GRAY</span><span class="p">));</span> <span class="n">SDL_RenderDrawLine</span><span class="p">(</span><span class="n">gfx</span><span class="o">-&gt;</span><span class="n">renderer</span><span class="p">,</span> <span class="p">...</span> <span class="p">}</span></code></pre></figure> <p>From there, I started working on the actual raycasting (the bread and butter of this program).</p> <p><em>Note: This post is currently unfinished for some reason. Check back in later to see if I ever ended up coming around to finishing it!</em></p> Wed, 30 Jul 2025 08:44:42 +0000 https://moofy.org/posts/raycasting-videogame-in-c/</link> https://moofy.org/posts/raycasting-videogame-in-c/ c in-progress programming Looking into "Excursions in Number Theory" <p>In New York, I picked up a new fun textbook, <em>Excursions in Number Theory</em> by C. Stanley Ogilvy and John T. Anderson. It’s a fun little pocketread about all sorts of wacky things in number theory, a field of principle mathematics that seems pointless on the surface but tends to have big implications. The book is fairly short, only 144 pages of direct content, but the information is puzzling to say the least. I found the book next to mathematical books about various games like Poker and Chess, and as this book tackles concepts like probability and combinatorics heavily (as that is where the majority of the implications of number theory seems to lie), it seemed like it fit in well.</p> <p>In this post, I’m going to dive into the book chapter-by-chapter with some light thoughts, some proofs, and what I think about what was written. Additionally, in order to understand what was going on in each chapter, I sought to try and write some example code alongside each lesson in Common Lisp, so perhaps this could be something of an educational journey for both you, the reader, and me. As usual, it’s best to read this post as though it were a Jupyter notebook (or something of the sort).</p> <h3 id="chapter-1-the-beginnings">Chapter 1: The Beginnings</h3> <p>The book opens by explaining the necessity of number theory. One thing it shows is how number theory serves as the basis by which efficient algorithms for all kinds of calculations is usually produced.</p> <p>One example the authors provide is the how non-decimal number systems had no mainstream application or use for many years (a topic largely only explored under number theory) until the invention of binary computers, which operate fundamentally on the binary number system (zeroes and ones) and then at higher levels on octal and hexadecimal.</p> <p>For those unaware, the basic understanding of what a number system is essentially the basis number through which numbers are represented by the multiplication of numbers less than that number by powers of that number. Put more mathematically, we can represent any number that exists using a number system based on the natural number \(n\) by multiplying powers of \(n\) by the whole numbers within \([0,n-1]\). For example, if we wanted to make the number \(N\), we would use the form</p> \[N = a_1 \times n^0 + a_2 \times n^1 + a_3 \times n^2 + \dots\] <p>where \(a_i \in [0, n-1]\) for all \(i\). For an even simpler, direct example, the decimal system works where \(n=10\). Imagine we wanted to represent a number like 203463 in decimal (which is just as we normally write it). Therefore, we could represent it as</p> \[203463 = 2 \times 10^5 + 0 \times 10^4 + 3 \times 10^3 + 4 \times 10^2 + 6 \times 10^1 + 3 \times 10^0.\] <p>Now, continuing onward, we know that the decimal system makes the most sense for computers because its the easiest to represent (as it only requires two values, 1 and 0. For example, we can represent the number 13 using the following powers, essentially just adding up specific values of powers of 2:</p> \[13 = 1 \times 2^3 + 1 \times 2^2 + 0 \times 2^1 + 1 \times 2^0 = 8 + 4 + 0 + 1,\] <p>and then, we can represent it as just being the coefficients from that expression, leading us to represent 13 in binary as 1101.</p> <p>Now, specifically, one of the applications of number theory that the book references is the fast algorithm for converting decimal numbers into binary (as its very quick to convert numbers from non-decimal number systems into demical but seemingly tedious to convert from decimal to non-decimal systems due to having to find and calculate the powers of the system).</p> <p>This quick algorithm boils down to taking an ordered stock of the pattern in which the division of a number by 2 repeatedly results in odd or even numbers (discarding the \(1/2\) each time the result is odd). For example, for the number 13, we can divide it by 2 until we reach 0, discarding \(\frac{1}{2}\) each time, to get the sequence 13, 6, 3, 1. Then, we can write 1 for each odd number and 0 for each even number and reverse the order, giving 1, 0, 1, 1, which is the digits of 13 in binary (as we showed before).</p> <p>I thought that this algorithm was ingenious, so I wrote some common lisp code to test it out.</p> <figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nb">defun</span> <span class="nv">binary</span> <span class="p">(</span><span class="nv">n</span><span class="p">)</span> <span class="p">(</span><span class="k">labels</span> <span class="p">((</span><span class="nv">binary-recursive</span> <span class="p">(</span><span class="nv">cur</span> <span class="nv">seen</span><span class="p">)</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">=</span> <span class="mi">0</span> <span class="nv">cur</span><span class="p">)</span> <span class="nv">seen</span> <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">next-value-int</span> <span class="p">(</span><span class="nb">truncate</span> <span class="p">(</span><span class="nb">/</span> <span class="nv">cur</span> <span class="mi">2</span><span class="p">))))</span> <span class="p">(</span><span class="nv">binary-recursive</span> <span class="nv">next-value-int</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">evenp</span> <span class="nv">cur</span><span class="p">)</span> <span class="mi">0</span> <span class="mi">1</span><span class="p">)</span> <span class="nv">seen</span><span class="p">))))))</span> <span class="p">(</span><span class="nv">binary-recursive</span> <span class="nv">n</span> <span class="no">nil</span><span class="p">)))</span></code></pre></figure> <p>and a few tests of the function result in exactly the behavior we expect!</p> <figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nb">print</span> <span class="p">(</span><span class="nv">binary</span> <span class="mi">13</span><span class="p">))</span> <span class="nv">-&gt;</span> <span class="p">(</span><span class="mi">1</span> <span class="mi">1</span> <span class="mi">0</span> <span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="nb">print</span> <span class="p">(</span><span class="nv">binary</span> <span class="mi">10</span><span class="p">))</span> <span class="nv">-&gt;</span> <span class="p">(</span><span class="mi">1</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">0</span><span class="p">)</span> <span class="p">(</span><span class="nb">print</span> <span class="p">(</span><span class="nv">binary</span> <span class="mi">27</span><span class="p">))</span> <span class="nv">-&gt;</span> <span class="p">(</span><span class="mi">1</span> <span class="mi">1</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">1</span><span class="p">)</span></code></pre></figure> <h3 id="chapter-2-number-patterns">Chapter 2: Number Patterns</h3> <p>The next chapter deals with patterns in numbers, such as efficient algorithms for adding numbers. One example they provide is the somewhat legendary story of Gauss adding all of the numbers between 1 and 100 incredibly quickly as a child (I’ll save you all the story: he just knew to pair up numbers on either side of 50 including 0 such that it turned into a product of 11 50s, or \(11 \times 50 = 5050\)).</p> <p>I thought this chapter was interesting and good foundational mathematics. It deals with series such as the triangular and square numbers and how formulae for adding numbers, squares, and cubes were proven (but not developed) by introducing the method of proof by induction.</p> <h3 id="chapter-3-prime-numbers-as-building-blocks">Chapter 3: Prime Numbers as Building Blocks</h3> <p>This chapter, obviously, is all about prime numbers: finding primes, calculatings made easy with primes, and relatively prime numbers. One thing it touches on, for example, is Euclid’s algorithm for calculating greatest common denominators as a way to check if two numbers are relatively prime (meaning their only shared factor is 1) or not. The algorithm consists of taking two numbers you want to test, a and b, and then repeatedly changing whichever value is greater to the absolute value of the difference between the two numbers until the two numbers become factorable, at which case the greatest common denominator is the smaller of the two values.</p> <p>To test this, I wrote the following code</p> <figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nb">defun</span> <span class="nv">euclid-gcd</span> <span class="p">(</span><span class="nv">a</span> <span class="nv">b</span><span class="p">)</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">=</span> <span class="mi">0</span> <span class="p">(</span><span class="nb">mod</span> <span class="nv">a</span> <span class="nv">b</span><span class="p">))</span> <span class="p">(</span><span class="nb">min</span> <span class="nv">a</span> <span class="nv">b</span><span class="p">)</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">&gt;</span> <span class="nv">a</span> <span class="nv">b</span><span class="p">)</span> <span class="p">(</span><span class="nv">euclid-gcd</span> <span class="p">(</span><span class="nb">-</span> <span class="nv">a</span> <span class="nv">b</span><span class="p">)</span> <span class="nv">b</span><span class="p">)</span> <span class="p">(</span><span class="nv">euclid-gcd</span> <span class="nv">a</span> <span class="p">(</span><span class="nb">-</span> <span class="nv">b</span> <span class="nv">a</span><span class="p">)))))</span></code></pre></figure> <p>Now, Common Lisp does provide Euclid’s greatest common denominator algorithm as a standard library function in the form <code class="language-plaintext highlighter-rouge">gcd</code> but I chose to make my own, <code class="language-plaintext highlighter-rouge">euclid-gcd</code> regardless. What I found is that this function seemed to work (of course, I can’t test it for all numbers, but we know that by proof given in the book, it works.</p> <p>Furthermore, this is where things get insane. The book poses the question of “<em>If we picked any two numbers at random, what is the probability that they are relatively prime?</em>,” and it provides a lengthy proof involving the Riemann Zeta function that proves that the probability is \(6/\pi^2,\) or roughly 0.61 (or about 61%). I wanted to test this empirically, so I wrote the following function:</p> <figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nb">defun</span> <span class="nv">test-probability</span> <span class="p">(</span><span class="nv">to-see</span> <span class="nv">max-value</span><span class="p">)</span> <span class="p">(</span><span class="k">labels</span> <span class="p">((</span><span class="nv">test-probability-recursive</span> <span class="p">(</span><span class="nv">total-seen</span> <span class="nv">prime-pairs</span><span class="p">)</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">&gt;=</span> <span class="nv">total-seen</span> <span class="nv">to-see</span><span class="p">)</span> <span class="p">(</span><span class="nb">/</span> <span class="nv">prime-pairs</span> <span class="nv">total-seen</span><span class="p">)</span> <span class="p">(</span><span class="k">progn</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">=</span> <span class="mi">1</span> <span class="p">(</span><span class="nv">euclid-gcd</span> <span class="p">(</span><span class="nb">random</span> <span class="nv">max-value</span><span class="p">)</span> <span class="p">(</span><span class="nb">random</span> <span class="nv">max-value</span><span class="p">)))</span> <span class="p">(</span><span class="nb">incf</span> <span class="nv">prime-pairs</span><span class="p">)</span> <span class="no">nil</span><span class="p">)</span> <span class="p">(</span><span class="nv">test-probability-recursive</span> <span class="p">(</span><span class="nb">1+</span> <span class="nv">total-seen</span><span class="p">)</span> <span class="nv">prime-pairs</span><span class="p">)))))</span> <span class="p">(</span><span class="nv">test-probability-recursive</span> <span class="mi">0</span> <span class="mi">0</span><span class="p">)))</span></code></pre></figure> <p>and with the following test, running the function 10 times, generating 10,000 pairs each time and selecting values within \([0, 10000]\):</p> <figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nb">loop</span> <span class="nv">for</span> <span class="nv">x</span> <span class="nv">from</span> <span class="mi">0</span> <span class="nv">to</span> <span class="mi">10</span> <span class="nb">do</span> <span class="p">(</span><span class="nb">format</span> <span class="nv">T</span> <span class="s">"~f~%"</span> <span class="p">(</span><span class="nv">test-probability</span> <span class="mi">10000</span> <span class="mi">10000</span><span class="p">)))</span></code></pre></figure> <p>I empirically observed the result</p> <figure class="highlight"><pre><code class="language-text" data-lang="text">0.6068 0.6089 0.6052 0.6054 0.6129 0.6033 0.5967 0.6007 0.6056 0.6029</code></pre></figure> <p>So, wow! It was true! I honestly couldn’t believe my eyes when I saw this. That’s just the power of number theory, we could calculate a limit to a problem like that that seemed so random and neigh-unanswerable.</p> <p><em>Note: This post is currently unfinished for some reason. Check back in later to see if I ever ended up coming around to finishing it!</em></p> Mon, 28 Jul 2025 11:30:18 +0000 https://moofy.org/posts/excursions-in-number-theory/</link> https://moofy.org/posts/excursions-in-number-theory/ mathematics common-lisp in-progress programming The Hypocrisy of Religious Supremacy and Cultural "Civility" <p>I recently saw an American, Christian white woman exclaim on social media how its not unreasonable to be afraid or suspicious of muslims due to their supposedly violent nature. In particular, she went so far as to claim that islamophobia isn’t real, and is simply a made-up, dismissive term to ignore real concerns and kill any actual discussion about the actions of muslims within western nations like the United States.</p> <p>Obviously, this woman was largely just fearmongering, but her mentality represents a greater problem within western or historically christian nations: fear hypocrisy. My point is this: we don’t understand things that are not integrated into our society and we fear things we don’t understand, and this sense of fear is self-supporting by events that are caused either in part or in whole by this fear or hate. Things, such as events or people, that support such conclusions are taken in full and things that do not are quickly ignored, all because the image of the status quo in the minds of the masses must be maintained at all costs.</p> <p>To begin with this discussion, I have to put forward an idea for understanding how people in the world act. We must first begin with the axiom that every person in the world lives with the goal of being happy, and that we each act in whatever way we believe will eventually lead us to achieving what we believe as happiness in our lives. What is important to understand, therefore, is that different people have vastly different ideas of happiness in their minds, and psychologically, it’s most reasonable to believe that the ideal world people envision in which they can be most happy is heavily related to the world in which they grew up. Many people fight outwardly to the world (such as in politics) with the hope of somehow realizing a world they once knew, a world from a time when they felt as though they were happy.</p> <p>For example, let’s think of social archetypes like NIMBYism. Many people are quick to support the adoption of new ideas so-long as they have no immediate effect on their way of life in any way. Change, inherently, is something terrifying to people, and even long after change has taken effect, people desire to return back to idealized versions of the past that they once knew.</p> <p>Two things must be taken into consideration from this: understanding what this past often looks like and the problem that naturally arises from that. Firstly, this ideal past is often highly cultural. People can be very adverse to things such as integration because they simply have no desire to enter themselves into the embarrassing comfort of having to come to find a common ground with another group of people. This much is natural, think about the anxiety of meeting new people in the first place. At the very least, on a societal scale, many people who are used to a certain set of demographics (racial, cultural, gender, etc.) within their communities are going to be considerably more open to meeting new people, at the very least, if these people are still at least part of the demographics that they are already well-acquainted-with, and this becomes even worse the more ethnically/culturally homogeneous the community originally was. To put it in plain words, the more white and christian or brown and muslim or etc. a community is, the less the residents would want to integrate any other groups of people. (Again, note that this is not a problem of white people or christians or whatever, this essay is simply dealing with the hypocrisy arising from the integration of muslims into christian, white American/British/Canadian society.)</p> <p>Secondly, the problem that arises is a cognitive dissonance when coping with change in the forms of integration of new peoples, that being forgetting the nature of one’s own culture in relation to another by way of various excuses to push a final conclusion. For example, some of the major concerns raised about the integration of muslims into American society are the belief that islam is an inherently violent religion, muslims have a history of extreme violence or terrorism within or against the west, and that the values of Islam (such as polygamy) are entirely incompatible with western (again, notably Christian) values. The issue is that each of these concerns lacks an understanding of the present state of Christianity in relation to the present state of Islam, that being, they are very much in parallel.</p> <p>To begin, we can break down the belief that Islam is an inherently violent religion, especially given the main support to this point, the idea of Jihad (the holy war all muslims are ordered to undertake against all non-believers of Islam). What many christians do not fully comprehend is how the adoption/support of Jihad ideology is a very radical ideology within the muslim community, and most importantly, that Christianity has many of the same things. Nearly every religion has devout, radicalized sects or movements that support ideals of a so-called “Holy War” against non-believers in the modern day.</p> <p>If we continue further onward to the supposed historical backing of Islam as a violent religion from terrorist attacks or Jihadist wars (such 9/11 and the subsequent war on terror, the London Bombings, the taliban etc.), these events, groups, and wars seem sufficient to paint Islam, at the very least, as a breeding ground for violence until you consider the same historical context for Christians (the crusades, transatlantic slavery and the land grab, the many wars over protestantism, etc.). We can then return back to the original question, whether violence is inherent to Islam, by considering another angle: “How is violence and brutality viewed as a tool for holy dominance in Abrahamic religions?” The answer to this question, I believe, gives us the key to understanding the nature of the cognitive dissonacne I mentioned previously. Obviously, Islam serves as a breeding ground for violence, but so does Christianity, if not historically moreso. Another amazing example is Judaism, as the first testament of the Bible is obviously interpreted by Christians to be overly violent due to the lack of the love and influence of Jesus Christ. Violence, unequivocally, is viewed as a tool for asserting religious dominance over non-believers across religions.</p> <p>The key to understanding the difference between religions, however, is understanding how each group changes roles over time between being the outward supporter of barbarism and being the supposedly peaceful group. Christianity spent thousands of years as the bloodthirsty hegemon hungry for further control of all society, with the Jews largely split across nations and stateless. Christians position as the hegemon lasted for so long that the requirement for drawing blood in the name of god constantly no longer became necessary, and then it was admissible for these states to claim a push for peace and the use of violence only for protection. In other words, these nations claimed that they were now simply civilized in their matters, and ironically this opinion of themselves as being “civilized” was then used as a justification to promote further violence against cultures they deemed “uncivilized.” It was something of a positive feedback loop: Christians had fought themselves and others so much that extreme, outspoken violence no longer became necessary, so they declared themselves as civilized over nations ruled by Muslims, Hindus, native tribes of foreign lands, etc., but in doing so, they then believed that they ought to continue spreading their culture outward to aid other peoples by civilizing them.</p> <p>Christians merely swapped roles, they were no longer the barbarians simply winning against other barbarians by brutally murdering them to spread their culture. Now, they were civilized peoples civilizing barbarians by brutally murdering them to spread their culture. And thus, Christian society finds itself at a cognitive dissonance today from the fear of the violence of Islam by not recognizing how violent it has been in spreading its own culture (and how this sentiment is, by no means, gone–it just changes forms).</p> <p>Lastly, we can examine the claim that the beliefs of Islam and Christianity are incompatible. I’ll concede that, as with any two religions, the devout, fundamentalist sects are likely entirely incompatible (because the more sternly fundamentalist the groups are, even a slight disagreement will make the two groups incompatible), but if we rephrase the question into whether or not eastern, predominantly islamic culture (as we see it in countries such as Egypt or Syria or Iran) is compatible with western, predominantly Christian culture (as we see it in countries such as the US, Canada, or the UK), we generally don’t find it being incompatible whatsoever. Going back to the example of polygamy, polygamy has existed in the US for hundreds of years (however, as a controversial and contested practice), primarily through Christian-adjacent groups such as the Latter-Day Saints (Mormons). More importantly, it’s also key to consider two things: polyamory is presently making a revival in the west due to a greater culture of sexual freedom (which is largely because of the plain fact that it entirely does not and should not matter to the government what consenting adults choose to do sexually or romantically between each other) and islam is not monolitihic on the topic of polygamy: many islamic people are personally monogamous (and, in another consideration, it is important to remember that just like Christians, not all of the religious scripture in the Quran is directly and literally followed).</p> <p>Now, to end out this post, I’d like to notice that some people reading this may be especially curious as to why I singled out white christians over other races in a post primarily dealing with religion. This is because this post deals with the issue of religious prejudice but all of the topics within it are heavily related to racial prejudice. Christianity was historically used as a justification of racial injustices of all kind: from justifying the scramble for Africa/America and the transatlantic slave trade to upholding systems such as segregation long after the international abolition of slavery. Therefore, to summarize my beliefs, I see anti-integrationist, islamophobic western attitudes as ironic and hypocritical.</p> Mon, 28 Jul 2025 06:26:50 +0000 https://moofy.org/posts/religious-hypocrisy/</link> https://moofy.org/posts/religious-hypocrisy/ political religion society essay How I Created and Manage This Website <p>I’ve previously received a questions asking for advice on how to create a website like mine, and in order to help others looking to make blog sites or portfolios like this, I thought I’d give a full technical breakdown of how this website works, including web design, hosting, domain management, and lastly, article writing. Beware: to make a website like this, you will need to be comfortable with both the heavy technical aspects of running a site like this alongside the creative aspects of producing this content. The biggest pro to this website is that the vast majority of this website (and all of its core functions) are completely free to produce, run, and manage, but there are several bells and whistles that I willingly fork up about 30 USD yearly to operate, and I’ll explain why shortly.</p> <h2 id="hosting">Hosting</h2> <p>This website is hosted through <a href="https://pages.github.com/">GitHub Pages</a>, which is an entirely-free static website hosting service that operatures through hosting out of GitHub repositories. All you need to do to make a basic github pages site is to first make a GitHub account and then follow the instructions on the GitHub Pages landing page to produce the minimal github pages example, which will be hosted at <code class="language-plaintext highlighter-rouge">(your github username).github.io</code>. This domain is provided free-of-charge by GitHub, but I didn’t quite like it (<code class="language-plaintext highlighter-rouge">mufaro3.github.io</code>), so I switched to a custom domain (see “Domain Management”).</p> <p>It’s a simple process to get set-up, and all you really need to understand for this section is how to make a github repository named correctly (to auto-integrate github pages), and then from there, the rest is web design.</p> <h2 id="web-design-programming">Web Design (Programming)</h2> <p>Now, remember how I said that this site is a <em>static site</em>. That means that it’s contents are (mostly) non-dymanic, meaning that there is no database attached to this website in any way. Dynamic elements of the site are website contents that aren’t directly attributed to the site contents and can change regularly without manually changing the site, and this site does contain some dynamic elements such as the youtube videos, user comments, and a (soon-to-be) mailing-list, but these elements are all embedded from other services.</p> <p><img src="/images/posts/jekyll.png" alt="Jekyll Logo" /></p> <p>In the case of this site, all of the page contents are generated from special text files known as Markdown using <a href="https://jekyllrb.com/">Jekyll</a>, a popular static site generator written in the programming language Ruby. The main advantage of this is that all of the posts on the site are very easily and concisely written in Markdown then compiled out into the HTML that you view on your web browser. Most importantly, due to Jekyll’s popularity, it has a quick-and-easy integration for GitHub pages, not requiring any compilation to occur locally (although, I obviously could just compile the site locally and have GitHub pages serve the compiled form).</p> <h3 id="theming">Theming</h3> <p><img src="/images/posts/clyell-theme.png" alt="Clyell Theme Screenshot" /></p> <p>For theming on Jekyll, I started by taking a theme that already exists, Gildasio’s <a href="https://github.com/gildasio/clyell">Clyell</a>, and started adapting it manually. There are many Jekyll tutorials available online, so I’m not going to get into the specifics for how each element of this website was adapted from Clyell (there is a lot), but to give a general summary, I cleaned up and standardized the theming system of <code class="language-plaintext highlighter-rouge">main.css</code>, moved all of the syntax highlighting parts of <code class="language-plaintext highlighter-rouge">main.css</code> out and introduced a different theme (gruvbox), and removed bootstrap (the css library). If you don’t understand basic HTML/CSS, most of what I just said won’t make sense, but similarly, any further tweaking to the layout of the webpage won’t really make sense if you don’t understand HTML and CSS, so if you wish to make a blog website like this without learning those things, just download a premade theme from a website like <a href="http://jekyllthemes.org/">Jekyll Themes</a> and don’t make any changes.</p> <h2 id="domain-management">Domain Management</h2> <p>GitHub Pages automatically provides a domain for all websites it hosts, the aforementioned <code class="language-plaintext highlighter-rouge">&lt;username&gt;.github.io</code>, but I didn’t really like this domain (plus, I wanted a cool custom e-mail address), so I purchased a custom domain from NameCheap for about 15 USD a year alongside another 15 USD a year for one custom email address for a total of 30 USD a year for everything. From there, all I needed to do was configure the GitHub Pages site to automatically force any users that connect to the website to connect via my domain by setting the domain of the website on the repository settings, and while there, I also set the website to automatically enforce HTTPS over HTTP (so all traffic to/from this website is automatically encrypted).</p> <h2 id="article-writing">Article Writing</h2> <h3 id="the-technical-part">The Technical Part</h3> <p>Posts have to be stored under <code class="language-plaintext highlighter-rouge">_posts</code> in a very specific way, that being</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>YYYY-MM-DD-&lt;post-link&gt;.md </code></pre></div></div> <p>and each post requires a header like</p> <figure class="highlight"><pre><code class="language-markdown" data-lang="markdown"><span class="nn">---</span> <span class="na">layout</span><span class="pi">:</span> <span class="s">post</span> <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">a</span><span class="nv"> </span><span class="s">look</span><span class="nv"> </span><span class="s">into</span><span class="nv"> </span><span class="s">a</span><span class="nv"> </span><span class="s">quantum</span><span class="nv"> </span><span class="s">mechanical</span><span class="nv"> </span><span class="s">carnot</span><span class="nv"> </span><span class="s">engine</span><span class="nv"> </span><span class="s">(alongside</span><span class="nv"> </span><span class="s">a</span><span class="nv"> </span><span class="s">bit</span><span class="nv"> </span><span class="s">of</span><span class="nv"> </span><span class="s">python)"</span> <span class="na">date</span><span class="pi">:</span> <span class="s">2025-07-24 12:19:00</span> <span class="na">comments</span><span class="pi">:</span> <span class="no">true</span> <span class="na">categories</span><span class="pi">:</span> <span class="pi">-</span> <span class="s">programming</span> <span class="na">tags</span><span class="pi">:</span> <span class="pi">-</span> <span class="s">physics</span> <span class="pi">-</span> <span class="s">python</span> <span class="pi">-</span> <span class="s">mathematics</span> <span class="nn">---</span></code></pre></figure> <p>So, to automate this, I have a bash script under <code class="language-plaintext highlighter-rouge">_posts</code> labelled <code class="language-plaintext highlighter-rouge">newpost.sh</code>. Let’s say, for example, that I wanted to write a new post on the basics of number theory. I would first <code class="language-plaintext highlighter-rouge">cd</code> into the <code class="language-plaintext highlighter-rouge">_posts</code> directory then call <code class="language-plaintext highlighter-rouge">newpost.sh</code>:</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">cd</span> ./_posts/ <span class="nv">$ </span>./newpost.sh number-theory-basics</code></pre></figure> <p>Let’s say that the current time as of running that command was January 10th, 2026, at 12:37 PM (48 seconds in, or 12:37:48). The script would therefore know to generate the file <code class="language-plaintext highlighter-rouge">_posts/2026-01-10-number-theory-basics.md</code> storing</p> <figure class="highlight"><pre><code class="language-markdown" data-lang="markdown">layout: post title: "number-theory-basics" date: 2026-01-10 12:37:48 comments: true categories: <span class="p"> -</span> category tags: <span class="p"> -</span> tag <span class="p">---</span></code></pre></figure> <p>and from there, I would open the file with emacs with</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>emacs <span class="nt">-nw</span> ./2026-01-10-number-theory-basics.md</code></pre></figure> <p>and just edit in the title and tags and the category to produce something like</p> <figure class="highlight"><pre><code class="language-markdown" data-lang="markdown">layout: post title: "An Explanation of the Basics of Number Theory" date: 2026-01-10 12:37:48 comments: true categories: <span class="p"> -</span> programming tags: <span class="p"> -</span> mathematics <span class="p">---</span></code></pre></figure> <p>Keep in mind that “programming” doesn’t mean that it’s an article about programming, it just means that it will end up on the “programming”/STEM board that I call lambda.</p> <p>From there, I just write the post content normally in Markdown on Emacs. Once I’m done writing, I add the new file to the git working tree with <code class="language-plaintext highlighter-rouge">git add</code></p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>git add ./2026-01-10-number-theory-basics.md</code></pre></figure> <p>and then commit that file alongside any other changes I made with a short comment about what changed</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>git commit <span class="nb">.</span> <span class="nt">-m</span> <span class="s1">'basics of number theory article'</span></code></pre></figure> <p>and lastly, I push the article to the main branch.</p> <figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>git push</code></pre></figure> <p>This is a considerably easier process with editors like Visual Studio Code that have simpler, non-terminal Git integration, but I don’t have a problem with doing it all manually via terminal and editing with Emacs. I like it this way.</p> <h3 id="the-artisticmotivational-part">The Artistic/Motivational Part</h3> <p>Lastly, for the motivational part, I keep a small notepad with me where I write down ideas whenever I get them (such as short questions that bug me) and then I settle them by sitting down and writing an article. Like they say, a man that’s thinking all the time will have nothing to think about but thoughts, so the best way to think about things worth writing about is to not think about things worth writing about, but instead, go out and live your life for a while and then things will come to you, and when they do, save those ideas somewhere.</p> <p>Most of the things that I have written about thus far are projects that I worked on for fun months prior without ever intending to really do a full write-up, but afterward, I thought it would be useful to write a description of what happened, what worked, what didn’t, and what I learned. For any creators or experimenters out there, I think that format is really worth a try.</p> <p>It’s incredibly easy to avoid writer’s block when you aren’t trying to force ideas out of you. Some ideas just come naturally, and when they do, you need to listen. Those are the ideas most worth writing down. It always seems like they come at the dumbest times, like when you’re taking a bath or going for a walk or brushing your teeth or some shit, but ironically, those mundane moments where you’re just existing in monotony are the best for thinking because your brain understands just how meaningless that time is. I think that meaningless time really has all the time in the world for that exact reason. Spend more of your life actually living it than thinking or writing and then think and write as much as you can.</p> Sun, 27 Jul 2025 09:24:41 +0000 https://moofy.org/posts/running-this-website-explained/</link> https://moofy.org/posts/running-this-website-explained/ web-development programming