I added an entire separate .cpp file for handling buttons because I wasn’t satisfied with how they were working (I love ricing).
Yes, it did take 9 hours. I have a skill issue. There are 3 main things I improved on:
(I haven’t actually tested the code out yet, I feel pressured to get the devlog out ASAP)
I highkey have trouble keeping track of what I did between devlogs sometimes, so I’m adding the SHA of the Git commit to devlogs.
So I tried to create a dedicated c++ file for handling buttons, since I wanted to have even more control over them, but ran into the issue of not having a way to share variables across different files. I know global variables are kinda bad, but I mean in this scenario they’re like config stuff that isn’t really going to be that harmful…
Most of the time was spent creating the button.cpp and button.h files, and they’re not even in GitHub yet lol
Pretty short devlog. I added some simple QoL changes: the main menu title is now centered, and the popup and some captions now have a margin around them so they aren’t stuck right on the edge.
Also this was technically done a couple of devlogs ago, but I added shell scripts to compile and run the program so I don’t have to type g++ -std=c++17 -Wall -Wextra -Werror -pedantic -o build/tic-tac-cube src/main.cpp src/board.cpp src/bot.cpp src/logs.cpp -lraylib every single time I want to compile the program.
I tried to make the UI look good. It isn’t necessarily good, but it’s better than it used to be IMO.
I just changed the color scheme, and now the text is round and the boxes are rounded.
I also reworked the board position display system. Since the squares are just buttons, and the button class can display text, I just made the board display text by itself.
For context I wrote the button class to draw and handle buttons. There might be a class for this or something but idc i just wrote it myself like 17 days ago.
Lowkey, when I started this project I was expecting to take 1 week max, and it was supposed to be like practice for making a more advanced project. I’ve since decided to not make the more advanced project (for now). Now, it’s been more than 2 weeks since I’ve started it, and it’s still in rough shape and probably not ready for release.
The UI still sucks, but I added like a popup system for displaying messages, such as telling the user why they won/lost without the win being visible due to the nature of the board being a cube. I was going to make a class to handle all the popups, but I settled for global variables and functions. Probably not the best practice, but it works, and if it ain’t broke don’t fix it.
I also added a entire new menu, the help menu. It could probably use some improvements, so if you have anything you’re curious about or confused about, drop a comment. There’s like 8 people that have seen this project, so I’m really expecting anything, but it would be appreciated greatly.
I lowkey forgot to add one break statement, so I spent like 30 minutes trying to figure out why it wasn’t working
Still, how the hell did this take 7 hours? I swear I’m not inflating my time by any means.
“Minor” improvements that take like hours to do is literally my entire C++ learning experience so far. This time, I improved the “wild card” function that rotates the cube randomly. Before, it just actually rotated randomly, and now, I changed it to check and make sure that moves it makes does not cause the opponent to win on the very next move.
fyi i DO write these devlogs myself without ai, I just literally need Vim keybinds to function as a person and therefore type all the devlogs inside of NeoVim before pasting them into the devlog. felt like writing this after i discovered that the “please write this yourself, humans read it” text at the bottom actually flashes red when you paste text.
I made the buttons look nicer by centering the text inside of them. It was much harder than it looked and I had to work with “Vector2” in Raylib. I may or may not have spent like half and hour trying to find documentation on it, only for me to discover that it’s a struct inside of Raylib. Still not entirely sure what a struct is. So I may or may not have spent another half and hour trying to declare the struct inside of the main.cpp file, before I finally gave up and asked DeepSeek. Turns out, it’s just Vector2 something{(float)x, (float)y}. It’s not exactly simple if you don’t have much experience with C++, but I started coding in C++ 16 days ago and I understand it just fine.
Halfway through, while testing, I accidentally overrode the main file and had to restore it and re-add all the changes I make. I don’t like committing before the program doesn’t have that many bugs, so a lot of progress was lost. This is like the second time I’ve done this, and if you’re curious what I did, well… The command used to compile my program for testing is g++ -std=c++17 -o build/program src/main.cpp src/board.cpp src/bot.cpp src/logs.cpp -lrayib. This compiles the code for all the C++ files and the Raylib library, and creates and executable inside the build/ directory. Except I forgot to type build/program, and so GCC just overrode main.cpp. Honestly though, it didn’t do that much harm, thanks to the test.cpp file having a similar version of code as the code that was overridden, and also git.
hackatime isn’t working so i can’t even post this devlog
nvm it just worked
nvm it broke again
honestly this is one of the first times anything has broken in my experience as someone who joined hack club like 3 months ago. im sure everyone involved in fixing this is trying their absolute best.
I am very very very very bad at debugging code. Somehow I managed to fix the major rendering bug and also make the fork handling better within 2 hours. I don’t believe I’ve mentioned anything about it before, but there was a rendering glitch upon the bot winning the game right after the user has made a cube turn that allowed the bot to win the game. I’m still not sure wy that happened, but I fixed it by re-rendering the entire board before drawing the board position again. If that didn’t make sense to you, it doesn’t make much sense to me either. If it did, well good for you ig.
I feel like the fork handling deserves and entire paragraph, so here:
I changed the win blocking function to also log the direction that potential win is in, by logging “position 1” of that specific potential win. The possible neutralizing moves of the directional indicator value is then compared against the potential win location neutralizing move to try to find a match. If a match is found, that means that the move is guaranteed to neutralize the given threat.
That paragraph did not make much sense, even to me. If you read my code, it’ll probably make more sense, as long as you do not get permanent brain damage from reading the it (I need to learn how to write better code)
I abandoned searching for potential forks and stopping them from ever forming in favour of handling forks that have already been formed. After more than one win for the opponent is detected, the bot registers that it is a fork. It then calculates which moves are best to neutralize the threat. There are four ways for each single win to be neutralized, so I need to make one of these four moves, for each of the two cases. In some cases, one or more of the moves overlap, in which case the overlapped move will be immediately returned, but most of the time, the bot just picks from one of the 8 possible neutralization moves randomly.
This is definitely less efficient than just figuring out how to prevent forks from ever forming, but I mean it’s a good implementation for the cube part of this game.
(Sometimes it messes up and I just win instantly)
In an effort to procrastinate fixing the bot fork bug while still doing something useful, I 1) took a 2 day break from this project to work (and ship) something else, and 2) fixed a very annoying bug where the user would be X every single time. I solved the issue by switching from older, more C-like rand() from cstdlib to the more modern #include <random>. I highkey copied the code from Stack Overflow, but at least it’s better than relying on AI.
That solved like half of the problem, but then I discovered that I wasn’t actually resetting the board properly when manually exiting a game, since I was looking through the logs. I made the logs are procrastination, but they’re actually really nice.
In case you were wondering btw, most of the time logged in this devlog was spent on trying to fix the fork bug, but I’ll make a dedicated devlog only when I’ve actually fixed the bug.
I changed the spacing on the program to make it look better and also made it so that the user can search if the “contains all of the following” field is blank, as long as the specific search field has some content.
If you’re wondering why it took me like an hour to do these simple changes, it because I had to package the extension and put it on GitHub (and the Mozilla store). I created two releases, and halfway through the second release, I realized that I forgot to change the version number in the manifest. Since I need an unique version number to put it on Firefox, I changed the release I was working on. And I just gave up on changing the already released on, since I’ve already spent like 17 minutes timelapsing, and wasn’t a fan of working 10 more minutes for something no one is actually going to see.
My UI still sucks. So, I searched for a website that looks good and easy to recreate. After about 15 minutes of searching with no avail, I realized that there was a really good website sitting right in front of me all this time: the Stardance website, which I’ve had open for like 5 hours atp. I proceded to use KColorChooser to get every single color on the Stardance website. I proceeded to make the extension look kinda like Stardance, except it is still noticeably worse.
Some of the changes I implemented in order to be more like Stardance also doubled as general quality of life improvements. One such improvement was changing the search button to not even being able to be pressed when query is empty. It now copies the Stardance UI by greying out the button, and changing the cursor to “not-allowed”. A popup also appears when you hover over the greyed-out button, also like Stardance.
The UI still needs some improvements probably, I hope I can get it done soon.
I wasted an hour trying to add time operators. Then I discovered that time and data operators are not universal across search engines, which means that it would take absolutely forever to implement it. Rather than waste more time, I just decided to cut my losses and quit before it consumes too much of my time. I still have several other projects I would like to start/finish, so yeah. TD;DR: spent an hour doing nothing (that I didn’t decided to undo).
When I shipped the project, the feedback from the reviewers was mostly positive, and there was only one real problem: the UI sucks. Which, for the record, I totally agree with. I don’t know what I was thinking, shipping a project that looks like someone made it in like 2004. Now, uh… the UI is like 10% better. Yes, it took me 5 hours to do it (I mean, some of the time was spent improving the README to be better). I went through like 10 different versions with different colours, fonts, and text box rounding. If you think one of the themes is better than the current one, please tell me, I need feedback.
I worked on the logs even more, and now they are in separate files. You wouldn’t believe the amount of time this took me. Evidently, I’m not a very good C++ dev, and when I was searching on Stack Overflow and other sites, I kept running into things I don’t understand like &, auto, and probably many others. So of course, I resorted to coding my own functions at the most low level C++ possible without actually being totally backwards compatible with C.
Essentially, every time the game starts, function runs that tries to generate a log file with the current time. There is a theoretically possible edge case where the user opens the project more than once in a single second, so I added some code to make absolute sure not to override any existing files. That took me like at least 15 minutes to half and hour, for an edge case that probably can only happen in testing, and that will not actually affect the game at all. Yay, what great decision making skills.
I still haven’t fixed the fork detection and response function, but at least I can now have a way to find out what is going wrong. The only progress with finding out what is wrong is just narrowing the error location down to the function where I already knew there was going to be an error. Yay.
Guess what I did today: a) fixed the fork, b) optimized UI, c) hunted bugs, or d) added a random new c++ file for the sole purpose of logging information because I don’t want to use an IDE or configure NeoVim.
The answer, of course, is D. I really need a way to figure out what is happening inside my code. Even though I wrote the code, it’s still kinda a black box to me, so I need to have some logs to figure out why the program is not working as expected. I have yet to actually implement the function or add out a way to have different logs files for different sessions though, I’m doing that next.
I added creating and defending against forks. One of my previous projects, Gomoku Balanced, had some decent defense and offense, which was even able to beat some people, according to the reviews on my ship. The one thing it was missing was the ability to detect potential forks and combat them, which was why I was able to beat it almost every single time. This bot, however, will not be the same. Mostly because the board is kinda small. I literally just added every single possibility of a fork to the to the bot.
I just got notified that I have like 8 hours without a devlog, and since I am horrible at coding, the bot function I’m working on isn’t even working yet. I’m also just not getting it done within 2 hours. The function is supposed to block the fork, but it doesn’t work for some reason. DeepSeek (AI) gave me a list of 20 reasons it’s breaking, but I’m not about to blindly trust AI. I mean it doesn’t raise any errors, so that’s good. For me at least, I spend a lot of time just trying to get the code to compile properly. And in this case, even when the code compiles, half the time it just runs into a runtime error and crashes.
The bot crashed like 20 times. They were all runtime errors, and I use C++, so I have absolutely no idea where the error occurs. Also, I want to be different, and therefore I use NeoVim, and since I don’t want to spend time that I could be building actually good projects for Stardance in the time it takes to configure NeoVim, and therefore I can’t see any warnings or errors. I did try using CLion and VSCode, but CLion takes up a lot of RAM and VSCode is made by Microsoft (and VSCodium and Code OSS don’t have that many plugins). Also, when I was using CLion, the errors didn’t really appear… and CLion also does a bunch of stuff and creates a bunch of mysterious files. I don’t really like doing stuff without knowing what they do, so I just ditched CLion altogether.
Did I seriously go on a paragraph-long rant about how using NeoVim leads to not being able to know why my code sucks? Is the paragraph-long rant in question also probably longer than the entire rest of the devlog? (Yes and yes);
Anyway you still can’t tell that I made any changes to the bot from a single screenshot, so I’m just going to attach one of my old ones.
I updated the bot to give it two of the most important features: winning the game, and trying to prevent your opponent from winning.
This was done by saving every single possible way to have a two-in-a-row on the board, connected and disconnected, 24 possible combinations in total. And of course, because I’m not experienced enough to do it any other way, it was all written by hand. And since I don’t like using AI, and don’t really trust it, I wrote all of it myself, and used only used AI to check that I didn’t mess something up.
Now how the hell do I make it detect forks….