Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make code more modular #5

Merged
merged 9 commits into from
Feb 18, 2018
Merged

Make code more modular #5

merged 9 commits into from
Feb 18, 2018

Conversation

StefansM
Copy link
Contributor

@StefansM StefansM commented Feb 17, 2018

This pull request amalgamates some changes I made years ago that separates much of the logic into functions. I've learned how to use git more effectively since then, so the commits have been heavily modified, which is why the CommitDate is three years after the AuthorDate.

The original plan was to add separate rendering layers on top of one another: the current randomly-moving pipes, path-directed pipes, a clock overlay, etc. I've discarded my previous attempts to do that as being ill-conceived, but separating the code into modules will make anything more than the current very simple program much easier.

I will merge this later this weekend unless anyone has any objections.

Separate the logic for initialising, moving, wrapping and flipping the
state of a pipe.
I know I'll forget the "+1" in `(rand() / (RAND_MAX / width + 1)` at
some point, so refactor this into a function called `random_i` (`random`
will conflict with a built-in function with `--std=gnu99`).
Rendering the pipes to the screen and animating a frame are two separate
concepts. Rendering takes care of drawing the pipes and flushing
everything to the terminal. Animating involves rendering a frame,
determining the delay required before the next frame needs rendering and
sleeping for that length of time.

This commit separtes the two concerns out. The `animate` function now
calls an arbitrary renderer, which is passed as a function pointer. The
`animate` function could call the rendering function directly, but in
the future we may want to pass a list of renders to allow for overlays.
This moves the "should flip" condition into pipe.c. It also changes
"flip_pipe_state" so that it returns the previous state.
Actually referencing an element in these arrays was a painful exercise.
We can get around this by just using C-style arrays of C-strings.
Just so that if we want to render a pipe in a separate rendering
function (not that any exist yet), it's a bit easier.
util.c Outdated

///Get a random integer in the range [lo, hi).
int random_i(int lo, int hi){
return (rand() / (RAND_MAX / (hi - lo) + 1)) + lo;
Copy link
Contributor

@livibetter livibetter Feb 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right, I think you miss a ():

    return (rand() / (RAND_MAX /  (hi - lo) + 1) ) + lo;
    return (rand() / (RAND_MAX / ((hi - lo) + 1))) + lo;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was roughly correct as written, except for the obvious division by zero when lo == hi. E.g. if random_i(0, N) returns the maximum of RAND_MAX / ((RAND_MAX / N) + 1), which is < N.

I've altered this in 7d2e17e to give less surprising behaviour. It's still slightly biased when hi - lo is close to RAND_MAX (see http://c-faq.com/lib/randrange.html), but it's not important for our use.

util.c Outdated
#include <stdlib.h>
#include "util.h"

///Get a random integer in the range [lo, hi).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be range be [lo, hi], hi included as that's that +1 for?

random_i(0, 3);  // returns one of 0, 1, 2, 3

This commit replaces the function `random_i` with `randrange`. This
matches the Python nomenclature of using `randrange` for `[lo, hi)` and
`randint` for `[lo, hi]`, and removes a glaringly obvious possibility
for a divide-by-zero error when `random_i` was called with `lo == hi`.

For the sake of consistency, I also added `randbool` to avoid scattered
calls to `rand()` and usage of `RAND_MAX`.

Note: The current implementation of `randint` is slightly biased when
`hi - lo` is close to `RAND_MAX`, but that really doesn't matter for our
application.
@StefansM StefansM merged commit 09b0be3 into pipeseroni:master Feb 18, 2018
@StefansM StefansM mentioned this pull request Feb 18, 2018
@StefansM StefansM deleted the refactor branch February 20, 2018 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants