Last active
January 7, 2023 12:16
-
-
Save mrbid/6552c9a6d52d1be452aecefbb8fb8b72 to your computer and use it in GitHub Desktop.
The best trained minimal CNN bot for CS:GO.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| -------------------------------------------------- | |
| James William Fletcher (github.com/mrbid) | |
| SEPTEMBER 2022 | |
| -------------------------------------------------- | |
| *** WIP, did I get the 4 dimensional array index right? where is walley leaking memory? *** | |
| I lost interest in this for now, may revisit it next year. | |
| This is a forward pass network I have spent a lot of | |
| time working on from scratch. As of this month and | |
| year I consider this to be the best performing | |
| minimal network. | |
| Weights exported from Keras for inference. | |
| no padding, no bias, grayscale input, 3x3 kernels, channels_last | |
| rows, cols, kernels | |
| y,x,k | |
| kernels: | |
| 3,3,2 | |
| 3,3,4 | |
| 3,3,8 | |
| input: 28x28x1 | |
| conv: 3x3x2 > 26x26x2 : relu | |
| maxpool: 13x13 | |
| conv: 3x3x4 > 11x11x4 : relu | |
| maxpool: 5x5 | |
| conv: 3x3x8 > 3x3x8 : relu | |
| gap: array(8) | |
| dense: sigmoid output | |
| - 28088 FLOPS (floating-point operations per scan) | |
| - This network identifies heads in the Valve Software game CS:GO. | |
| - Maybe I should have transposed these to channels_first? | |
| - If not maybe I should invert the for loop nesting to channels first? | |
| - You may want to install espeak via your package manager. | |
| - clang main.c -Ofast -mfma -lX11 -lm -o aim | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <math.h> | |
| #include <time.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <unistd.h> | |
| #include <stdint.h> | |
| #include <X11/Xlib.h> | |
| #include <X11/Xutil.h> | |
| #include <sys/time.h> | |
| #include <sys/stat.h> | |
| // general | |
| #pragma GCC diagnostic ignored "-Wgnu-folding-constant" | |
| #define forceinline __attribute__((always_inline)) inline | |
| #define uint unsigned int | |
| // scan area vars | |
| #define SCAN_AREA 28 | |
| const uint r0 = SCAN_AREA; // dimensions of sample image square | |
| const uint r2 = r0*r0; // total pixels in square | |
| const uint r2i = r2*3; // total inputs to neural net pixels*channels | |
| const uint rd2 = r0/2; // total pixels divided by two | |
| uint x=0, y=0; | |
| float input[r2] = {0}; | |
| // x11 vars | |
| Display *d; | |
| int si; | |
| Window twin = 0; | |
| GC gc = 0; | |
| unsigned char pgmbytes[r2] = {0}; | |
| char targets_dir[256]; | |
| uint sps = 0; // for SPS | |
| // settings | |
| uint enable = 0; | |
| uint sample_capture = 0; | |
| uint crosshair = 1; | |
| uint hotkeys = 1; | |
| // hyperparameters that you can change | |
| #define TRIGGER 1 // how many times to pull the trigger when a target is detected | |
| //#define SCAN_VARIANCE 0.f // how much to randomly wiggle the scan area between scans | |
| #define SCAN_DELAY 1000 // scan frequency delay in microseconds | |
| #define ACTIVATION_SENITIVITY 0.9f // minimum activation sensitivity to fire a shot | |
| #define REPEAT_ACTIVATION 0 // how many positive activations in a row before firing a shot | |
| #define FIRE_RATE_LIMIT_MS 100 // delay between firing shots in milliseconds | |
| #define TRIGGER_RATE_LIMIT_MS 30 // delay between firing shots between TRIGGER iterations in milliseconds | |
| /*************************************************** | |
| ~~ Neural Network Forward-Pass | |
| */ | |
| // Layers | |
| forceinline uint CL0(uint y, uint x){return y * 28 + x;} | |
| float CL1F[1352]; | |
| forceinline uint CL1(uint y, uint x, uint k){return y * (2 * 26) + x * 2 + k;} | |
| float CL1PF[338]; | |
| forceinline uint CL1P(uint y, uint x, uint k){return y * (2 * 13) + x * 2 + k;} | |
| float CL2F[484]; | |
| forceinline uint CL2(uint y, uint x, uint k){return y * (4 * 11) + x * 4 + k;} | |
| float CL2PF[100]; | |
| forceinline uint CL2P(uint y, uint x, uint k){return y * (4 * 5) + x * 4 + k;} | |
| float CL3F[72]; | |
| forceinline uint CL3(uint y, uint x, uint k){return y * (8 * 3) + x * 8 + k;} | |
| // Kernels | |
| const float /*18*/ f1[] = {-0.10085268f,-0.5327633f,-0.093879305f,0.9093193f,0.45742872f,-0.54601395f,-0.109133825f,0.27121156f,-0.3521443f,-0.44989288f,0.37559956f,0.28491852f,0.8056581f,0.36666352f,0.5286602f,-0.60915345f,-0.11539043f,0.22436628f}; | |
| forceinline uint CF1(uint y, uint x, uint k){return y * (2 * 3) + x * 2 + k;} | |
| const float /*72*/ f2[] = {0.3625854f,-0.2961693f,0.34357676f,-0.09004362f,0.51307756f,-3.5217664f,-0.39044002f,-0.2900187f,0.13758732f,-0.32059073f,-0.10238134f,0.37341678f,1.2980468f,-1.8488529f,-1.5052714f,0.7356388f,-0.078636244f,0.27923414f,0.077999316f,0.4445f,-0.36241f,0.9078533f,-0.38832384f,0.21853346f,-0.46116298f,0.30799797f,0.5373813f,0.37880236f,-0.7928643f,-0.8725977f,0.2778252f,0.097840056f,0.42987445f,0.14128259f,0.36648455f,-0.22519167f,0.15652227f,0.92756784f,0.23862366f,0.6194639f,0.30409643f,-0.51745474f,0.0024263235f,-0.12897015f,1.1616807f,0.7814885f,-0.62208676f,-0.40302494f,-0.16045721f,0.2694907f,-0.21484402f,0.11004151f,0.764975f,0.33624822f,-0.19113706f,1.9655595f,-0.46846592f,0.22514774f,0.43947503f,-1.0024278f,0.36089367f,0.15557878f,-0.2792994f,0.12491965f,-0.22553426f,-0.3300921f,-0.017703544f,-0.7742302f,1.2367371f,0.1950125f,-1.3916389f,-0.2607476f}; | |
| forceinline uint CF2(uint y, uint x, uint k, uint d){return y * (2 * 4 * 3) + x * (4 * 3) + d * 2 + k;} | |
| const float /*288*/ f3[] = {-0.6666318f,-0.6499509f,0.017249504f,-0.16326442f,-0.22811371f,0.6105372f,-1.2061936f,0.010394949f,1.9372067f,1.7710887f,1.7254974f,1.7425989f,-1.3244041f,1.048707f,2.1588702f,1.7392019f,-0.42127144f,-0.11061933f,-0.3554936f,-0.019667566f,0.12338132f,-0.06739373f,0.20636322f,-0.05645989f,0.90321827f,1.4634635f,1.3782281f,1.2930415f,-1.1278466f,0.7545569f,0.82316697f,1.4057527f,0.38134363f,-0.64948016f,0.42578185f,-0.23418133f,0.30430847f,-0.31941235f,0.017438103f,-0.33156964f,0.5274514f,1.8053904f,0.786523f,1.5999506f,-1.629409f,1.9005216f,1.5866919f,1.8491492f,0.45213234f,0.15404697f,0.5348579f,-0.03504686f,0.50366986f,-0.38578567f,0.09311065f,0.14972478f,0.06680024f,0.24241066f,-0.5661344f,-0.46240142f,0.6674583f,-0.061471906f,0.7778293f,0.00547942f,0.3505525f,-0.3217814f,0.5647048f,-0.46430093f,0.3413247f,-0.93530357f,0.68285865f,-0.8179386f,-0.9443577f,0.99222124f,-0.74951744f,1.5060915f,-1.8539797f,-1.2733712f,-0.3136488f,1.6198969f,0.3050006f,-0.12353183f,0.2600941f,-0.05577971f,0.7012368f,-0.69120103f,0.08819378f,-0.23662797f,-0.9264782f,0.02257323f,-1.304195f,-0.266403f,0.35280138f,-0.93557376f,-0.2724371f,0.036498073f,-1.0345271f,-0.09567977f,-0.6391683f,-0.14270216f,-0.11629022f,0.13955416f,-0.72821933f,-0.17132543f,0.35356653f,-0.2813003f,-0.60093063f,-0.18304347f,0.14200652f,1.4064893f,0.32346547f,-0.5312404f,-0.23669605f,-0.11699825f,-0.29569745f,-0.25634912f,0.30916855f,0.4422385f,-0.106391065f,-0.16948828f,0.06795499f,0.5405564f,-0.07677913f,0.23410861f,-0.30062374f,1.1781301f,-1.1384887f,-0.017022943f,-0.30742258f,-0.17424811f,-0.011861075f,-0.006211239f,0.07467434f,-0.4911204f,-0.42237592f,0.19911426f,0.94744396f,0.56354165f,0.12879127f,0.69064784f,-0.7407655f,1.937518f,0.3084967f,0.844227f,-0.121149786f,0.2743653f,0.38621083f,0.3470594f,0.056427915f,-0.12770227f,-0.13791257f,0.23218161f,0.7226025f,-0.22627075f,-0.246187f,-0.7509091f,0.97558045f,0.75327444f,0.8887772f,-0.7208585f,0.9673093f,-0.2824686f,0.158171f,-0.63391435f,0.56319493f,0.23208329f,0.48720482f,-0.33179942f,-0.34003234f,0.17145425f,0.107116565f,0.5767645f,0.17950015f,-0.58480746f,-0.886015f,0.3794311f,0.037069265f,-0.03622643f,0.08028794f,0.24633844f,0.10488024f,0.17855826f,-0.113084584f,0.13750535f,-0.23423539f,-0.012242726f,-0.26542222f,-0.1018701f,0.8441302f,0.29523608f,-0.32725728f,0.040206067f,0.0357823f,0.0075954227f,-0.23309204f,0.24467848f,-1.1471972f,-0.1885725f,-0.17840974f,0.31720218f,1.2253202f,-0.33104882f,0.3171273f,-0.25064176f,-0.41660643f,1.2757696f,1.1084087f,-0.033284497f,0.18243246f,-0.09396731f,-0.09534969f,-0.1469201f,0.33480045f,0.6946161f,0.2978034f,-0.36039257f,1.0407037f,0.1910912f,1.3607627f,0.48659712f,-2.0204294f,0.6403378f,-0.08928161f,0.9058087f,-0.24339463f,0.5362985f,-0.0608694f,0.33523193f,-1.1249162f,-1.2907683f,0.14169537f,0.12229522f,0.10730731f,0.5749354f,0.36680436f,0.5716122f,-0.9392891f,1.2686868f,0.9139534f,0.20032431f,-0.58617896f,0.2567366f,-0.50432104f,0.10609374f,0.32372996f,-0.20171365f,-0.33536744f,0.31133586f,0.61647445f,-0.33804142f,0.35246393f,-0.615248f,0.0524327f,0.66400695f,1.0802368f,-0.8643f,0.43973807f,0.5051888f,0.1118751f,0.49338824f,-0.8811681f,-2.5034041f,0.49740288f,0.46392873f,-0.4952641f,-0.123362236f,-0.8946474f,-0.195359f,0.07260272f,-1.8585433f,-1.1545897f,0.36304718f,-0.7406244f,0.07727978f,-0.48872453f,-0.045256052f,0.4778138f,-0.15295202f,-0.7671279f,0.13332541f,-1.1735713f,-0.22989619f,-0.6292691f,-0.5701288f,0.37870747f,-0.35531673f,0.4285855f,-0.5731319f}; | |
| forceinline uint CF3(uint y, uint x, uint k, uint d){return y * (4 * 8 * 3) + x * (8 * 3) + d * 8 + k;} | |
| // final dense layer | |
| const float /*8*/ d1[] = {2.3085554f,1.15268f,2.1598685f,1.219241f,-1.2499405f,-3.7682545f,2.529647f,1.0187337f}; | |
| // bias: -1.4903662 | |
| // processModel | |
| float processModel() | |
| { | |
| printf("a0\n"); | |
| // 2 kernels on input, no padding | |
| for(uint y = 1; y < 27; y++) | |
| { | |
| for(uint x = 1; x < 27; x++) | |
| { | |
| for(uint k = 0; k < 2; k++) | |
| { | |
| float ro = 0.f; | |
| // lower row | |
| printf("a0.0.1 - %u %u %u\n", y-1,x-1,CL0(y-1,x-1)); | |
| ro += input[CL0(y-1,x-1)]* f1[CF1(0,0,k)]; | |
| printf("a0.0.2\n"); | |
| ro += input[CL0(y-1,x)] * f1[CF1(0,1,k)]; | |
| printf("a0.0.3\n"); | |
| ro += input[CL0(y-1,x+1)]* f1[CF1(0,2,k)]; | |
| printf("a0.1\n"); | |
| // middle row | |
| ro += input[CL0(y,x-1)] * f1[CF1(1,0,k)]; | |
| ro += input[CL0(y,x)] * f1[CF1(1,1,k)]; | |
| ro += input[CL0(y,x+1)] * f1[CF1(1,2,k)]; | |
| printf("a0.2\n"); | |
| // top row | |
| ro += input[CL0(y+1,x-1)]* f1[CF1(2,0,k)]; | |
| ro += input[CL0(y+1,x)] * f1[CF1(2,1,k)]; | |
| ro += input[CL0(y+1,x+1)]* f1[CF1(2,2,k)]; | |
| printf("a0.3\n"); | |
| // set output | |
| if(ro < 0.f){ro = 0.f;} // relu | |
| CL1F[CL1(x-1, y-1, k)] = ro; | |
| } | |
| } | |
| } | |
| printf("a1\n"); | |
| // max pool it | |
| uint oy = 0, ox = 0; | |
| for(uint y = 0; y < 26; y += 2, oy++) | |
| { | |
| for(uint x = 0; x < 26; x += 2, ox++) | |
| { | |
| for(uint k = 0; k < 2; k++) | |
| { | |
| float max = 0.f; | |
| if(CL1F[CL1(y,x,k)] > max) | |
| max = CL1F[CL1(y,x,k)]; | |
| if(CL1F[CL1(y,x+1,k)] > max) | |
| max = CL1F[CL1(y,x+1,k)]; | |
| if(CL1F[CL1(y+1,x,k)] > max) | |
| max = CL1F[CL1(y+1,x,k)]; | |
| if(CL1F[CL1(y+1,x+1,k)] > max) | |
| max = CL1F[CL1(y+1,x+1,k)]; | |
| // output max val | |
| CL1PF[CL1P(oy,ox,k)] = max; | |
| } | |
| } | |
| } | |
| printf("a2\n"); | |
| // 4 kernels on pooled output, no padding | |
| for(uint y = 1; y < 12; y++) | |
| { | |
| for(uint x = 1; x < 12; x++) | |
| { | |
| for(uint k = 0; k < 4; k++) | |
| { | |
| float ro = 0.f; | |
| for(uint d = 0; d < 2; d++) | |
| { | |
| // lower row | |
| ro += CL1PF[CL1P(y-1,x-1,d)]* f2[CF2(0,0,d,k)]; | |
| ro += CL1PF[CL1P(y-1,x,d)] * f2[CF2(0,1,d,k)]; | |
| ro += CL1PF[CL1P(y-1,x+1,d)]* f2[CF2(0,2,d,k)]; | |
| // middle row | |
| ro += CL1PF[CL1P(y,x-1,d)] * f2[CF2(1,0,d,k)]; | |
| ro += CL1PF[CL1P(y,x,d)] * f2[CF2(1,1,d,k)]; | |
| ro += CL1PF[CL1P(y,x+1,d)] * f2[CF2(1,2,d,k)]; | |
| // top row | |
| ro += CL1PF[CL1P(y+1,x-1,d)]* f2[CF2(2,0,d,k)]; | |
| ro += CL1PF[CL1P(y+1,x,d)] * f2[CF2(2,1,d,k)]; | |
| ro += CL1PF[CL1P(y+1,x+1,d)]* f2[CF2(2,2,d,k)]; | |
| } | |
| if(ro < 0.f){ro = 0.f;} // relu | |
| CL2F[CL2(x-1, y-1, k)] = ro; | |
| } | |
| } | |
| } | |
| printf("a3\n"); | |
| // max pool it | |
| oy = 0, ox = 0; | |
| for(uint y = 0; y < 11; y += 2, oy++) | |
| { | |
| for(uint x = 0; x < 11; x += 2, ox++) | |
| { | |
| for(uint k = 0; k < 4; k++) | |
| { | |
| float max = 0.f; | |
| if(CL2F[CL2(y,x,k)] > max) | |
| max = CL2F[CL2(y,x,k)]; | |
| if(CL2F[CL2(y,x+1,k)] > max) | |
| max = CL2F[CL2(y,x+1,k)]; | |
| if(CL2F[CL2(y+1,x,k)] > max) | |
| max = CL2F[CL2(y+1,x,k)]; | |
| if(CL2F[CL2(y+1,x+1,k)] > max) | |
| max = CL2F[CL2(y+1,x+1,k)]; | |
| // output max val | |
| CL2PF[CL2P(oy,ox,k)] = max; | |
| } | |
| } | |
| } | |
| printf("a4\n"); | |
| // 8 kernels on pooled output, no padding | |
| for(uint y = 1; y < 4; y++) | |
| { | |
| for(uint x = 1; x < 4; x++) | |
| { | |
| for(uint k = 0; k < 8; k++) | |
| { | |
| float ro = 0.f; | |
| for(uint d = 0; d < 4; d++) | |
| { | |
| // lower row | |
| ro += CL2PF[CL2P(y-1,x-1,d)]* f3[CF3(0,0,d,k)]; | |
| ro += CL2PF[CL2P(y-1,x,d)] * f3[CF3(0,1,d,k)]; | |
| ro += CL2PF[CL2P(y-1,x+1,d)]* f3[CF3(0,2,d,k)]; | |
| // middle row | |
| ro += CL2PF[CL2P(y,x-1,d)] * f3[CF3(1,0,d,k)]; | |
| ro += CL2PF[CL2P(y,x,d)] * f3[CF3(1,1,d,k)]; | |
| ro += CL2PF[CL2P(y,x+1,d)] * f3[CF3(1,2,d,k)]; | |
| // top row | |
| ro += CL2PF[CL2P(y+1,x-1,d)]* f3[CF3(2,0,d,k)]; | |
| ro += CL2PF[CL2P(y+1,x,d)] * f3[CF3(2,1,d,k)]; | |
| ro += CL2PF[CL2P(y+1,x+1,d)]* f3[CF3(2,2,d,k)]; | |
| } | |
| if(ro < 0.f){ro = 0.f;} // relu | |
| CL3F[CL3(x-1, y-1, k)] = ro; | |
| } | |
| } | |
| } | |
| printf("a5\n"); | |
| // gap | |
| float dense[8] = {0.f}; | |
| for(uint y = 0; y < 3; y++) | |
| { | |
| for(uint x = 0; x < 3; x++) | |
| { | |
| for(uint d = 0; d < 8; d++) | |
| { | |
| dense[d] += CL3F[CL3(y, x, d)]; | |
| } | |
| } | |
| } | |
| for(uint d = 0; d < 8; d++) | |
| dense[d] /= 9; | |
| printf("a6\n"); | |
| // dense | |
| float out = 0.f; | |
| for(uint d = 0; d < 8; d++) | |
| out += dense[d] * d1[d]; | |
| out += -1.4903662f; | |
| printf("a7\n"); | |
| // sigmoid output | |
| return 1.f / (1.f + expf(-out)); | |
| } | |
| /*************************************************** | |
| ~~ Utils | |
| */ | |
| uint qRand(const float min, const float max) | |
| { | |
| static float rndmax = 1.f/(float)RAND_MAX; | |
| return (((float)rand()) * rndmax) * (max-min) + min; | |
| } | |
| void writePGM(const char* file, const unsigned char* data) | |
| { | |
| FILE* f = fopen(file, "wb"); | |
| if(f != NULL) | |
| { | |
| fprintf(f, "P5 28 28 255 "); | |
| fwrite(data, 1, r2i, f); | |
| fclose(f); | |
| } | |
| } | |
| uint64_t microtime() | |
| { | |
| struct timeval tv; | |
| struct timezone tz; | |
| memset(&tz, 0, sizeof(struct timezone)); | |
| gettimeofday(&tv, &tz); | |
| return 1000000 * tv.tv_sec + tv.tv_usec; | |
| } | |
| void rainbow_printf(const char* text) | |
| { | |
| static unsigned char base_clr = 0; | |
| if(base_clr == 0) | |
| base_clr = (rand()%125)+55; | |
| base_clr += 3; | |
| unsigned int clr = base_clr; | |
| const unsigned int len = strlen(text); | |
| for(unsigned int i = 0; i < len; i++) | |
| { | |
| clr++; | |
| printf("\e[38;5;%im", clr); | |
| printf("%c", text[i]); | |
| } | |
| printf("\e[38;5;123m"); | |
| } | |
| void rainbow_line_printf(const char* text) | |
| { | |
| static unsigned char base_clr = 0; | |
| if(base_clr == 0) | |
| base_clr = (rand()%125)+55; | |
| printf("\e[38;5;%im", base_clr); | |
| base_clr++; | |
| if(base_clr >= 230) | |
| base_clr = (rand()%125)+55; | |
| const unsigned int len = strlen(text); | |
| for(unsigned int i = 0; i < len; i++) | |
| printf("%c", text[i]); | |
| printf("\e[38;5;123m"); | |
| } | |
| //https://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h | |
| int key_is_pressed(KeySym ks) | |
| { | |
| char keys_return[32]; | |
| XQueryKeymap(d, keys_return); | |
| KeyCode kc2 = XKeysymToKeycode(d, ks); | |
| int isPressed = !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7))); | |
| return isPressed; | |
| } | |
| void speakS(const char* text) | |
| { | |
| char s[256]; | |
| sprintf(s, "/usr/bin/espeak \"%s\"", text); | |
| if(system(s) <= 0) | |
| sleep(1); | |
| } | |
| Window findWindow(Display *d, Window current, char const *needle) | |
| { | |
| Window ret = 0, root, parent, *children; | |
| unsigned cc; | |
| char *name = NULL; | |
| if(current == 0) | |
| current = XDefaultRootWindow(d); | |
| if(XFetchName(d, current, &name) > 0) | |
| { | |
| if(strstr(name, needle) != NULL) | |
| { | |
| XFree(name); | |
| return current; | |
| } | |
| XFree(name); | |
| } | |
| if(XQueryTree(d, current, &root, &parent, &children, &cc) != 0) | |
| { | |
| for(unsigned int i = 0; i < cc; ++i) | |
| { | |
| Window win = findWindow(d, children[i], needle); | |
| if(win != 0) | |
| { | |
| ret = win; | |
| break; | |
| } | |
| } | |
| XFree(children); | |
| } | |
| return ret; | |
| } | |
| void processScanArea(Window w) | |
| { | |
| // get image block | |
| XImage *img; | |
| #ifdef SCAN_VARIANCE | |
| img = XGetImage(d, w, (x+qRand(-SCAN_VARIANCE, SCAN_VARIANCE))-rd2, (y+qRand(-SCAN_VARIANCE, SCAN_VARIANCE))-rd2, r0, r0, AllPlanes, XYPixmap); | |
| #else | |
| img = XGetImage(d, w, x-rd2, y-rd2, r0, r0, AllPlanes, XYPixmap); | |
| #endif | |
| if(img == NULL) | |
| return; | |
| // extract colour information | |
| int i = 0; | |
| for(int y = 0; y < r0; y++) | |
| { | |
| for(int x = 0; x < r0; x++) | |
| { | |
| const unsigned long pixel = XGetPixel(img, x, y); | |
| const unsigned char sr = (pixel & img->red_mask) >> 16; | |
| const unsigned char sg = (pixel & img->green_mask) >> 8; | |
| const unsigned char sb = pixel & img->blue_mask; | |
| // 0-1 norm | |
| input[i] = ((sr * 0.003921568859f) + (sg * 0.003921568859f) + (sb * 0.003921568859f)) * 0.3333333433f; | |
| pgmbytes[i] = (sr + sg + sb) / 3; | |
| i++; | |
| } | |
| } | |
| // free image block | |
| XDestroyImage(img); | |
| // increment SPS | |
| sps++; | |
| } | |
| void reprint() | |
| { | |
| //system("clear"); | |
| rainbow_printf("James William Fletcher (github.com/mrbid)\n"); | |
| rainbow_printf("L-CTRL + L-ALT = Toggle BOT ON/OFF\n"); | |
| rainbow_printf("R-CTRL + R-ALT = Toggle HOTKEYS ON/OFF\n"); | |
| rainbow_printf("P = Toggle crosshair.\n"); | |
| rainbow_printf("G = Get activation for reticule area.\n"); | |
| rainbow_printf("H = Hold pressed to print scans per second.\n"); | |
| rainbow_printf("L = Toggle sample capture.\n"); | |
| rainbow_printf("E = Manual sample capture.\n"); | |
| printf("\e[38;5;76m"); | |
| printf("\nMake the crosshair a single green pixel.\nOR disable the game crosshair and use the crosshair provided by this bot.\nOR if your monitor provides a crosshair use that. (this is best)\n\n"); | |
| printf("This bot will only auto trigger when W,A,S,D & L-SHIFT are not being pressed.\n(so when your not moving in game, aka stationary)\n\nL-SHIFT allows you to disable the bot while stationary if desired.\n\n"); | |
| printf("\e[38;5;123m"); | |
| if(twin != 0) | |
| { | |
| printf("CS:GO Win: 0x%lX\n\n", twin); | |
| if(enable == 1) | |
| rainbow_line_printf("BOT: \033[1m\e[32mON\e[0m\n"); | |
| else | |
| rainbow_line_printf("BOT: \033[1m\e[31mOFF\e[0m\n"); | |
| if(hotkeys == 1) | |
| rainbow_line_printf("HOTKEYS: \033[1m\e[32mON\e[0m\n"); | |
| else | |
| rainbow_line_printf("HOTKEYS: \033[1m\e[31mOFF\e[0m\n"); | |
| if(sample_capture == 1) | |
| rainbow_line_printf("SAMPLE CAPTURE: \033[1m\e[32mON\e[0m\n"); | |
| else | |
| rainbow_line_printf("SAMPLE CAPTURE: \033[1m\e[31mOFF\e[0m\n"); | |
| if(crosshair == 1) | |
| rainbow_line_printf("CROSSHAIR: \033[1m\e[32mON\e[0m\n"); | |
| else | |
| rainbow_line_printf("CROSSHAIR: \033[1m\e[31mOFF\e[0m\n"); | |
| printf("\n"); | |
| } | |
| } | |
| /*************************************************** | |
| ~~ Program Entry Point | |
| */ | |
| int main(int argc, char *argv[]) | |
| { | |
| srand(time(0)); | |
| // wipe old data | |
| remove("/dev/shm/pred_r.dat"); | |
| remove("/dev/shm/pred_input.dat"); | |
| // intro | |
| reprint(); | |
| // open display 0 | |
| d = XOpenDisplay(":0"); | |
| if(d == NULL) | |
| { | |
| printf("Failed to open display\n"); | |
| return 0; | |
| } | |
| // get default screen | |
| si = XDefaultScreen(d); | |
| // get graphics context | |
| gc = DefaultGC(d, si); | |
| // find window | |
| twin = findWindow(d, 0, "Counter-Strike"); | |
| if(twin != 0) | |
| reprint(); | |
| // | |
| XEvent event; | |
| memset(&event, 0x00, sizeof(event)); | |
| // | |
| uint tc = 0; | |
| while(1) | |
| { | |
| // loop every SCAN_DELAY ms (1,000 microsecond = 1 millisecond) | |
| usleep(SCAN_DELAY); | |
| // bot toggle | |
| if(key_is_pressed(XK_Control_L) && key_is_pressed(XK_Alt_L)) | |
| { | |
| if(enable == 0) | |
| { | |
| // get window | |
| twin = findWindow(d, 0, "Counter-Strike"); | |
| if(twin == 0) | |
| { | |
| printf("Failed to detect a CS:GO window.\n"); | |
| sleep(1); | |
| continue; | |
| } | |
| // get center window point (x & y) | |
| XWindowAttributes attr; | |
| XGetWindowAttributes(d, twin, &attr); | |
| x = attr.width/2; | |
| y = attr.height/2; | |
| // set mouse event | |
| memset(&event, 0x00, sizeof(event)); | |
| event.type = ButtonPress; | |
| event.xbutton.button = Button1; | |
| event.xbutton.same_screen = True; | |
| event.xbutton.subwindow = twin; | |
| event.xbutton.window = twin; | |
| enable = 1; | |
| usleep(100000); | |
| reprint(); | |
| speakS("on"); | |
| } | |
| else | |
| { | |
| enable = 0; | |
| usleep(100000); | |
| reprint(); | |
| speakS("off"); | |
| } | |
| } | |
| // toggle bot on/off | |
| if(enable == 1) | |
| { | |
| // always tracks sps | |
| static uint64_t st = 0; | |
| if(microtime() - st >= 1000000) | |
| { | |
| if(key_is_pressed(XK_H)) | |
| printf("\e[36mSPS: %u\e[0m\n", sps); | |
| sps = 0; | |
| st = microtime(); | |
| } | |
| // input toggle | |
| if(key_is_pressed(XK_Control_R) && key_is_pressed(XK_Alt_R)) | |
| { | |
| if(hotkeys == 0) | |
| { | |
| hotkeys = 1; | |
| usleep(100000); | |
| reprint(); | |
| speakS("hk on"); | |
| } | |
| else | |
| { | |
| hotkeys = 0; | |
| usleep(100000); | |
| reprint(); | |
| speakS("hk off"); | |
| } | |
| } | |
| if(hotkeys == 1) | |
| { | |
| // crosshair toggle | |
| if(key_is_pressed(XK_P)) | |
| { | |
| if(crosshair == 0) | |
| { | |
| crosshair = 1; | |
| usleep(100000); | |
| reprint(); | |
| speakS("cx on"); | |
| } | |
| else | |
| { | |
| crosshair = 0; | |
| usleep(100000); | |
| reprint(); | |
| speakS("cx off"); | |
| } | |
| } | |
| // sample capture toggle | |
| if(key_is_pressed(XK_L)) | |
| { | |
| if(sample_capture == 0) | |
| { | |
| char* home = getenv("HOME"); | |
| sprintf(targets_dir, "%s/Desktop/targets", home); | |
| mkdir(targets_dir, 0777); | |
| sample_capture = 1; | |
| usleep(100000); | |
| reprint(); | |
| speakS("sc on"); | |
| } | |
| else | |
| { | |
| sample_capture = 0; | |
| usleep(100000); | |
| reprint(); | |
| speakS("sc off"); | |
| } | |
| } | |
| // sample capture | |
| static uint64_t scd = 0; | |
| if(sample_capture == 1 && key_is_pressed(XK_E) && microtime() > scd) | |
| { | |
| char name[32]; | |
| sprintf(name, "%s/%i.pgm", targets_dir, rand()); | |
| processScanArea(twin); | |
| writePGM(name, &pgmbytes[0]); | |
| printf("\e[93mMANUAL SAVE:\e[38;5;123m %s\n", name); | |
| scd = microtime() + 350000; | |
| } | |
| } | |
| if(hotkeys == 1 && key_is_pressed(XK_G)) // print activation when pressed | |
| { | |
| const float ret = processModel(); | |
| if(ret > 0.f) | |
| { | |
| if(ret > ACTIVATION_SENITIVITY) | |
| { | |
| printf("\e[93mA: %f\e[0m\n", ret); | |
| XSetForeground(d, gc, 65280); | |
| XDrawRectangle(d, event.xbutton.window, gc, x-rd2-1, y-rd2-1, r0+2, r0+2); | |
| XSetForeground(d, gc, 0); | |
| XDrawRectangle(d, event.xbutton.window, gc, x-rd2-2, y-rd2-2, r0+4, r0+4); | |
| XFlush(d); | |
| } | |
| else | |
| { | |
| const uint s = (uint)((1.f-ret)*255.f); | |
| printf("\x1b[38;2;255;%u;%um A: %f\n", s, s, ret); | |
| XSetForeground(d, gc, 16711680); | |
| XDrawRectangle(d, event.xbutton.window, gc, x-rd2-1, y-rd2-1, r0+2, r0+2); | |
| XSetForeground(d, gc, 0); | |
| XDrawRectangle(d, event.xbutton.window, gc, x-rd2-2, y-rd2-2, r0+4, r0+4); | |
| XFlush(d); | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if(crosshair == 1) | |
| { | |
| XSetForeground(d, gc, 65280); | |
| XDrawRectangle(d, event.xbutton.window, gc, x-rd2-1, y-rd2-1, r0+2, r0+2); | |
| XSetForeground(d, gc, 0); | |
| XDrawRectangle(d, event.xbutton.window, gc, x-rd2-2, y-rd2-2, r0+4, r0+4); | |
| XFlush(d); | |
| } | |
| if(key_is_pressed(XK_W) == 0 && key_is_pressed(XK_A) == 0 && key_is_pressed(XK_S) == 0 && key_is_pressed(XK_D) == 0 && key_is_pressed(XK_Shift_L) == 0) | |
| { | |
| const float activation = processModel(); | |
| // passed minimum activation? | |
| if(activation > ACTIVATION_SENITIVITY) | |
| { | |
| tc++; | |
| // did we activate enough times in a row to be sure this is a target? | |
| if(tc > REPEAT_ACTIVATION) | |
| { | |
| if(sample_capture == 1) | |
| { | |
| char name[32]; | |
| sprintf(name, "%s/%i.pgm", targets_dir, rand()); | |
| writePGM(name, &pgmbytes[0]); | |
| printf("\e[38;5;123mSAVED: %s\n", name); | |
| } | |
| // fire off as many shots as we need to | |
| for(int i = 0; i < TRIGGER; i++) | |
| { | |
| // fire mouse down | |
| event.type = ButtonPress; | |
| event.xbutton.state = 0; | |
| XSendEvent(d, PointerWindow, True, 0xfff, &event); | |
| XFlush(d); | |
| // wait 100ms (or ban for suspected cheating) | |
| usleep(100000); | |
| // release mouse down | |
| event.type = ButtonRelease; | |
| event.xbutton.state = 0x100; | |
| XSendEvent(d, PointerWindow, True, 0xfff, &event); | |
| XFlush(d); | |
| // fire limit | |
| usleep(TRIGGER_RATE_LIMIT_MS * 1000); | |
| } | |
| // fire limit | |
| usleep(FIRE_RATE_LIMIT_MS * 1000); | |
| } | |
| } | |
| else | |
| { | |
| tc = 0; | |
| } | |
| } | |
| } | |
| /// | |
| } | |
| } | |
| // done, never gets here in regular execution flow | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment