Skip to content

Instantly share code, notes, and snippets.

@turret-dev
Created November 16, 2021 04:12
Show Gist options
  • Save turret-dev/6a7792f9387d0e1d549089b80a03b7a4 to your computer and use it in GitHub Desktop.
Save turret-dev/6a7792f9387d0e1d549089b80a03b7a4 to your computer and use it in GitHub Desktop.
snokes!
/*
* MIT License
*
* Copyright (c) 2021 turret. <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* "snokes"
* This program makes use of x11 to
* display snakes moving randomly.
*
* This source file makes use of the VSCode extension 'file anchors',
* and comments use such
*/
/*
* Thank you for choosing to use my code and/or software
* - turret.
*/
// ANCHOR headers
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xcms.h>
// ANCHOR macros
#define NAME "snokes"
#define MAP_X 490
#define MAP_Y 490
#define MAP_SIZE MAP_X * MAP_Y
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
#define NUM_AGENTS 500
#define MOVE_SPEED 1.0f
#define EVAP_SPEED 0.10f
#define EVAP_CAP 0.10f
#define UPS 50000
#define RAND_TURN_PROB 0.1f
#define CEILING(x) (int)(x) + (1 - (int)((int)((x) + 1) - (x)))
#define TO_MAP(x, y) MAP_X * y + x
#define RAND(min, max) min + (rand() % ((max - min) + 1))
#define CLAMP(x, min, max) x < min ? min : x > max ? max : x
// ANCHOR types
typedef struct agent Agent;
struct agent {
int x;
int y;
float angle;
};
// ANCHOR function declarations
// - include variable names
// - for short files these can be left out
// - group/order in logical manner
int64_t currentTimeMillis();
// ANCHOR global variables
float map[MAP_X * MAP_Y];
Agent agents[NUM_AGENTS];
// ANCHOR function definitions
// - in same order as declarations
int64_t currentTimeMillis() {
struct timeval time;
gettimeofday(&time, NULL);
int64_t s1 = (int64_t)(time.tv_sec) * 1000;
int64_t s2 = (time.tv_usec / 1000);
return s1 + s2;
}
// ANCHOR main
int main(const int argc, const char *argv[]) {
// copyright & ident
printf("\"%s\" (c) 2021 turret. <[email protected]>\n", NAME);
srand(currentTimeMillis());
for(int i = 0; i < MAP_X * MAP_Y; ++i){
map[i] = 0.0f;
}
// initialize agents
for(int i = 0; i < NUM_AGENTS; ++i){
Agent agent = agents[i];
agent.angle = ((float)rand() / (float)RAND_MAX) * 2.0f * M_PI;
agent.x = RAND(5, MAP_X - 5);
agent.y = RAND(5, MAP_Y - 5);
map[TO_MAP(agent.x, agent.y)] = 1.0f;
agents[i] = agent;
}
Display *display;
int screen;
Window window;
GC gc;
display = XOpenDisplay((char*) 0);
screen = DefaultScreen(display);
window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0,
MAP_X + 10, MAP_Y + 10, 5, WhitePixel(display, screen), BlackPixel(display, screen));
XSizeHints *hints = XAllocSizeHints();
hints->max_height = MAP_Y + 10;
hints->max_width = MAP_X + 10;
hints->min_height = MAP_Y + 10;
hints->min_width = MAP_X + 10;
hints->flags |= (PMinSize | PMaxSize);
XSetWMNormalHints(display, window, hints);
XSetStandardProperties(display, window, NAME, NAME, None, NULL, 0, NULL);
XSelectInput(display, window, ExposureMask);
gc = XCreateGC(display, window, 0, 0);
XClearWindow(display, window);
XMapRaised(display, window);
Colormap def = DefaultColormap(display, screen);
XSetWindowColormap(display, window, def);
XEvent event;
long lastTime = clock();
double amountOfTicks = UPS;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long ticksTimer = currentTimeMillis();
int ticks;
while(1){
long now = clock();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
for(int i = 0; i < MAP_SIZE; ++i){
if(map[i] <= EVAP_CAP && map[i] != 0.0f)
map[i] = 0.0f;
if(map[i] == 0.0f)
continue;
map[i] = fmaxf(0.0f, map[i] - EVAP_SPEED);
}
for(int i = 0; i < NUM_AGENTS; ++i){
//printf("agent update");
Agent agent = agents[i];
float directionX = cos(agent.angle);
float directionY = sin(agent.angle);
int newX = roundf((float)agent.x + directionX * MOVE_SPEED);
int newY = roundf((float)agent.y + directionY * MOVE_SPEED);
if (newX < 0 || newX >= MAP_X || newY < 0 || newY >= MAP_Y) {
newX = fmin(MAP_X - 1, fmax(0, newX));
newY = fmin(MAP_Y - 1, fmax(0, newY));
agent.angle = ((float)rand() / (float)RAND_MAX) * 2.0f * M_PI;
}
agent.x = newX;
agent.y = newY;
map[TO_MAP(agent.x, agent.y)] = 1.0f;
if((float)rand() / (float)RAND_MAX < RAND_TURN_PROB)
agent.angle = ((float)rand() / (float)RAND_MAX) * 2.0f * M_PI;
agents[i] = agent;
}
ticks++;
int x = 0;
int y = 0;
while(y <= MAP_Y){
float pixel = map[TO_MAP(x, y)];
if(pixel != 0.0f && pixel != 1.0f){
XcmsColor exact;
exact.spec.RGBi.red = pixel;
exact.spec.RGBi.green = pixel;
exact.spec.RGBi.blue = pixel;
XcmsAllocColor(display, def, &exact, XcmsRGBiFormat);
XSetForeground(display, gc, (&exact)->pixel);
//XFree(&exact);
}else if(pixel == 0.0f)
XSetForeground(display, gc, BlackPixel(display, screen));
else if(pixel > EVAP_CAP)
XSetForeground(display, gc, WhitePixel(display, screen));
XDrawLine(display, window, gc, x + 5, y + 5, x + 5, y + 5);
//XSync(display, false);
++x;
if(x > MAP_X) {
++y;
x = 0;
}
}
delta--;
}
if(currentTimeMillis() - ticksTimer > 1000){
ticksTimer += 1000;
printf("TPS: %d\n", ticks);
ticks = 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment