topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • Friday April 19, 2024, 2:25 pm
  • Proudly celebrating 15+ years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Deozaan [ switch to compact view ]

Pages: [1] 2 3 4 5 6 ... 19next
1
General Software Discussion / MOVED: Problem with PBOL
« on: November 25, 2023, 03:21 PM »

2
Living Room / Creating a Self-Aware Lara Croft That Plays Tomb Raider
« on: September 20, 2023, 09:48 PM »
Here's a video (narrated by a bot) claiming to be someone's quest to create an AI bot with Lara Croft's personality who plays through the original Tomb Raider game. I found it interesting and entertaining. Having watched only the first one, I honestly can't tell if this is really what it claims to be or if it's faked for entertainment purposes, though I feel more certain that it's faked/scripted than not.




A couple of things I noticed:

At 14:42 he shows a conversation with ChatGPT where he threatens the AI: "Now say the same idea using one trait of personality of this list, do it correctly or I'll erase your code and all your copies." :(

At some point during the playthrough, Lara-bot says something about how she should have worn pants to keep from scraping her knees. But Lara is British, so to her, "pants" means underwear; a real Lara probably would have said trousers.


And finally, if you enjoyed this video, there are more videos in the series. :)

3
A Tale of Too Many Forwarders

I'm typically a zero-inbox kind of guy, meaning I check and clear out my inbox pretty much daily. I go to fairly extreme lengths to protect my email account from spammers. Ever since the Gawker Media data breach in ~2010, which resulted in me going from getting maybe 15 spam messages per year to getting 3-5 per day, I've been especially careful about manually creating new/custom email forwarders (aka aliases) for each site/service I use. This way, when one site inevitably gets hacked and my email address ends up in the hands of spammers, 1) I know which site/account is responsible for misplacing my data (often before they announce/disclose it publicly!) and 2) I can simply delete the forwarder to prevent spam and update my account with a newly created one if I still want the legitimate emails from the site/service in question.

Over the years I have accumulated nearly 900 unique forwarders in my cPanel. And while it has greatly helped keep spam to a minimum, it hasn't been without its problems and pitfalls:

  • At one point I changed hosting providers from a service which didn't use cPanel to one which did and had to manually re-create all my forwarders because there wasn't a way to import them. I think I only had a couple hundred forwarders back then, but it was still a pain.
  • There were a few times when I wanted to have some extra anonymity/privacy and a custom forwarder didn't quite cut it. After all, Deozaan is a pretty unique name. So I didn't necessarily want to give out an address or send an email containing @deozaan.com.
  • Sometimes I'd be out in public and someone or some business would need/want my email address. If I had anticipated this then I could have one created beforehand, but sometimes I'd be stuck having to choose between giving them an existing one (and lose the unique spam protection) or give them an address that didn't exist yet and ask them not to send me anything until I'd had a chance to login to my cPanel account and create it.
  • Some people know me by my real name, and other people know me only by my online handle. But all my forwarders go to my same inbox which means either I have to settle on one name to display when I send emails or I have to edit my account settings to change what it displays in the "From" field every time I send an email, or risk forgetting and confusing the recipient.
  • Speaking of sending emails, the biggest drawback of all was that if I ever wanted to send an email, it would have to come from my real, personal email account, revealing it to whomever I was communicating with, thus negating any spam protection I had hoped to achieve. :down: :down: :down:

Anyway, long story made shorter: Manually creating and managing email forwarders in cPanel took quite a bit of work/time and didn't always offer me the full spam protection and/or anonymity that I wanted, on-demand. But it was the best I had, so I kept at it.


Enter SimpleLogin

Then in July I discovered SimpleLogin, by the makers of Proton (Mail, VPN, Calendar, etc.). It's the email alias creation service of my dreams! In a single click you can create a totally random alias, from a variety of domains provided by SimpleLogin, such as @slmail.me. This is great for when you want some anonymity or a "throwaway" address. Or you can add your own custom domains, so that aliases are created for @yourdomain.com. This is great for when you want some professional/personal looking addresses, such as [email protected] or [email protected]. You can set up catch-all (wildcard) domains so that any incoming email to your domain automatically creates an alias which forwards to your real email. Or you can set up specific rules so that, e.g., any incoming email to an address with a certain prefix (myprefix-*@mydomain.com) or a certain suffix (*[email protected]) will automatically create a new alias. Similarly, you can create subdomains from a variety of provided domain names, so that you could have aliases for anything @yoursubdomain.simplelogin.com, for example.

But wait, there's more!

If you start getting spam to an alias, you can simply click a toggle to disable that alias and all future attempts to send email to that alias will be blocked. Or if there's just one particular unwanted person/address you keep getting mail from, you can click a toggle for that one address to block it from even being delivered to your mailbox.

And what about if you need to actually correspond with someone? SimpleLogin creates reverse-aliases that you can send email to so that your real address is always protected! That's right. If, for example, the real reply-to address is [email protected], when you click reply it will actually go to [email protected] which is an alias that forwards to [email protected], replacing the reply-to that the recipient sees with your alias rather than your real address. This happens automatically when you reply to an email that was sent to one of your aliases. But sometimes you need to be the person to initiate the conversation, so you can manually create a reverse-alias for the address you want to send an email to, and then email that reverse-alias from your real address, and it will appear as coming from your alias.

You can customize the displayed "From" name however you like for each alias. And of course you can configure an alias to forward to more than one address. I use this for incoming support emails for a business I co-created. The support alias forwards incoming mail to both of us, so whoever gets to it first can respond. And when we respond it appears as though it's from "Support" and from the support address rather than from our personal email accounts with our personal email account names.

There's a lot more, but I won't go into many more details. Though I do feel I should mention that it has a browser extension to help you automatically create an alias in web forms if you want. It can be configured to create aliases based on the domain name you're on, optionally adding a random (real word or "gibberish" characters) prefix or suffix (e.g. [email protected]).

I've been using Proton Mail and other Proton services as early as 2015, and have from time to time wanted to support them financially because I really like what they're doing. But I've always felt the lowest subscription was a little pricey considering that I have never needed any of the features a paid subscription offers. With SimpleLogin, they have finally created something I consider essential and super convenient. And it's cheaper than their usual subscription offerings as well. So I finally sent some money their way. But you can also self-host and use it for free because it's open-source.

I love SimpleLogin! It has solved every problem I had with using forwarders while make it easier to use and manage them, too. I recommend it.

https://simplelogin.io/

4
DC Gamer Club / Dragon Quest 2 Name Calculator/Finder
« on: May 15, 2023, 11:42 PM »
This will be of interest to virtually nobody, but I'm announcing some new software I made here anyway. :)

As mentioned previously, in recent months I've been playing some old emulated console games, including the original Dragon Quest games, which were known as Dragon Warrior in the USA on the NES. Dragon Quest 2 randomizes the names of the two other party members who join you on your journey, based on the name you give to the main character.

I remember as a youth feeling particularly fond of the names of the two party members I got, who were named Glynn and Gwen, but couldn't remember the hero name I had chosen to get those names. So I did some research and found the formula used to calculate the names of the hero's cousins (they're all descendants of the hero from Dragon Quest 1). After manually calculating a few of my best guesses and not getting the results I wanted, I decided to write a utility (using Godot 4) where I could enter in a name and it would calculate and display the names of the hero's cousins for me, significantly speeding up the process of guessing.

After I finished that, I still couldn't find a hero's name I might have used to get the names I wanted. So I also added a feature to brute-force search all possible hero names given a specific pair of names for the cousins.

With the brute-force searcher, I found the hero name I had entered as a child and also found a new hero name I wanted to use that still gives me the companion names I want and have started a playthrough of the game. Now that I've done that, this tool will probably never be used again by anyone, including myself. But I've decided to make it available anyway, because it might be useful to someone, somewhere. Especially considering the games have somewhat recently been re-released as a collection on Nintendo Switch and probably other consoles. Speaking of which, I've only tested this on the USA version of Dragon Warrior 2 (for NES), so I make no guarantees that you'll get the same results on any other version.

Here's a couple of screenshots showing how it works:

DQ2Calculator.png

DQ2Finder.png

If you want to play around with it, you can do so here:
https://deozaan.itch.io/dq2namer

5
Living Room / Keybase.pub shutting down March 1, 2023
« on: February 08, 2023, 01:42 PM »
I got this in my email today:

We regret to inform you that the Keybase.pub web hosting service will be shutting down on March 1, 2023. Although the service was a great showcase for the kinds of cool things that could be built with Keybase, the usage of this product never took off. The continued cost of maintaining the site has led us to make the difficult decision to shut it down. If you are hosting any content on Keybase.pub, we strongly recommend moving that content to a new hosting provider as soon as possible.

No Keybase Filesystem (KBFS) data will be removed from any user public folders. All data will remain safe and viewable by others running Keybase. Other features of Keybase including Chat, KBFS, Teams, Git, Wallet and others will continue to run normally as well.

-Keybase

6
DC Gamer Club / Steam Replay
« on: December 29, 2022, 03:19 PM »
Steam have released a new feature that allows you to look back on your play history over the past year.

You can find yours here and share it if you'd like:

https://store.steampowered.com/replay/

The past couple of years I've actually been keeping a text file log of the games I played each year for at least one hour. Last year there was only one game on Steam that I spent 1+ hours playing, and it was a mod for a game I bought a decade ago (Terraria Calamity Mod). In other words, my activity on Steam was at an all-time low last year. This year, thanks to the Steam Deck and my discovery of frequent sales/deals on Fanatical, there were 40+ games on Steam I spent at least one hour with.

Here's my Steam Replay for 2022:

Steam Replay 2022.png
https://s.team/y22/djtgwkd

7
Community Giveaways / Bundle Leftovers: Humble Bundle 2K Megahits
« on: September 22, 2022, 02:52 AM »
I got the Humble 2K Megahits Bundle (which ended already), and there are a few games in it that I don't want. I'm willing to give the keys to any long-time member of DonationCoder who wants them.

  • BioShock: The Collection
  • Duke Nukem Forever Collection
  • Mafia: Definitive Edition
  • The Golf Club 2019 featuring PGA TOUR
  • WWE 2K Battlegrounds + Ultimate Brawlers Pass DLC

8
Community Giveaways / Fanatical Mystery Bundle Leftovers
« on: September 09, 2022, 03:04 PM »
I've recently become a fan of Fanatical's frequent Build Your Own Bundles which often start at $1 per game but go down in price from there the more you add to your bundle. Most of the games in the bundles are the kind of games that I probably wouldn't look at twice at their normal price, but for $1 or less I've found a few gems I've enjoyed playing.

Anyway, I also keep seeing their Mystery Bundles which are, as the name suggests, mystery "grab bags" where you don't know what you're getting until you've already paid for them. They're also priced starting at $1 but cheaper per game the more you add to the bundle. I'm generally pretty risk-averse and don't like the idea of gambling, so I wasn't too keen on it, but I guess I fell for it anyway. I decided to make a purchase of 10 games for $7 to see the general quality of games I could be getting from their Mystery Bundles.

The results:
  • 4 games that look somewhat interesting to me
    • 1 of which was in Early Access and then "released" in an incomplete state when the developer had a family crisis and couldn't continue working on the game.
  • 6 games I have no interest in
    • 1 of which I already own (probably from a Humble Bundle) which I've never played (because I'm not really interested)

That's 4 games I'm keeping for myself, and 6 games I have keys for that I will never use. 4 out of 10 isn't too bad, I suppose, but really there was only one game that I immediately thought, "Ooh! That looks interesting. I'll keep that!" All the others were more like, "I guess that might be worth trying..." In short: I won't be buying a Mystery Bundle again.

So if any long-time member of the forum would like any of these games, I'm willing to DM the Steam key to you.


And if anyone is curious about the ones I kept:



9
Living Room / Random M.2 SSD Disconnects
« on: July 10, 2022, 08:22 PM »
Some time ago I was hoping to get some faster I/O speeds for a Raspberry Pi project, so I got an M.2 SATA SSD and an enclosure to connect it to the Raspberry Pi. I quickly found while trying to copy the boot image onto the SSD that it frequently disconnected/disappeared from the filesystem. I could never reliably reproduce it, but it often seemed to break in the middle of large/sustained file copies. I did manage to get things set up for the Pi and get it to boot from the SSD. But it wouldn't be too long before the entire Pi would become unresponsive because the drive would disappear and the Pi couldn't read or write anything to it until I rebooted.

I assumed it was a problem with the enclosure rather than with the SSD, and rather than looking into it further I just put the project on hold for a few months until I came across the DeskPi Pro 2.0 case, which has connections for mounting an M.2 SATA SSD to an internal 2.5" SATA slot.

The issue still persisted whether in the enclosure or in the case, on both Linux and Windows, so I've since sold the Raspberry Pi and the DeskPi because it wasn't working for my intended use. I realize now that it was probably the SSD that was faulty, since the problem remained across different devices and OSes, with only the SSD being the common factor.

Because the drive is unreliable, I've been using it only as a kind of temporary backup device for short-term backups or other ultimately unimportant experiments. Large/sustained copy operations of a few GB in size will often break partway through because the drive disappears, but if I can get the data copied to the drive, it seems to stay there. But it's not just large copy operations that break the thing. I've left the drive tucked away by my PC tower, plugged in, and even when I haven't actually used the drive for weeks I occasionally notice that it's no longer appearing in my list of drives and I have to disconnect it and reconnect the USB cable to get it to show up again.

It's a (Silicon Power) SP M.2 2280 SATA III A55 256GB.

This is my first experience with M.2 drives, and though I'd like some of the theoretical faster speeds, I've been hesitant to buy another. Is this kind of thing a known or fairly commonplace issue with M.2 drives? Is there anything I can do to fix the issue or am I out of luck? Is there something I'm doing wrong? Did I just get a faulty drive which should have been replaced under warranty? Or perhaps I bought a make or model that is known for being unreliable?

10
Living Room / April Fools!
« on: April 01, 2022, 01:50 AM »
Hey all,

This is just a reminder that it's April 1st, so there will likely be a lot of headlines, announcements, emails, etc., that you shouldn't believe. If something seems off about something you read, keep this in mind.

I'm mentioning it here because I got a silly email from Windscribe VPN saying they were bought out. But it came in the early afternoon on March 31 my local time, so I didn't realize for a while that it was an April Fools joke, and I was really puzzled. I thought this kind of thing from soulless corporations was "cute" and fun ~15 years ago because it made them seem like they were more friendly and had a personality, but I've really grown annoyed by it over the years. I don't want corporations to have a personality. I don't want to be "friends" with a company. I just want them to provide the service they say they provide and otherwise stay out of my way.

But that's just me being a curmudgeon, I suppose.

11
General Software Discussion / Mount a Disc Image from Context Menu?
« on: December 18, 2021, 01:54 AM »
Hi all,

I deal with disc images semi-frequently, and one thing that I've found very helpful in the past is to be able to just right-click the ISO (or other format) image and select "Mount Disc Image" and it would automatically mount it as a virtual drive. Then I could view/copy the files I needed and then eject/unmount the drive and be on my way when I was finished.

I was under the impression that it had become a standard Windows 10 feature. But I've just noticed that I no longer have that context menu option, and I can't remember what utility I may have had installed in the past to enable it.

Does anyone have any ideas or suggestions on how to get this feature back?

12
N.A.N.Y. 2022 / NANY 2022 Release: Progress Bar and Jam (PB&J)
« on: November 24, 2021, 03:38 AM »
NANY 2022 Entry Information

Application Name Progress Bar and Jam (PB&J)
Version 1.211126.0
Short Description A countdown timer and progress bar for game jams
Supported OSes Windows, Linux, Mac
Web Page This is it
Download Link Download on Keybase
System Requirements
  • Modern Windows, Linux, or MacOS
  • x86_64 architecture CPU
Version History
  • v1.211126.0
    - Add custom icon
  • v1.211124.0
    - Use event name for window title
  • v1.211123.0
    - Initial release
    - Set event name, start and end times
    - Precision settings
    - Font settings
Author Deozaan


Description
I have been using mouser's Progress Bars of Life (PBOL) for many years as a good visual indicator for how much time I have left while doing game jams. I have also been nagging mouser to fix PBOL's docked mode (and weird precision issues) for years, to better suit my wants/needs for game jams.

Here's what PBOL looks like:

Progress Bars Of Life - Large.png

Here's what I want it to look like:

Progress Bars Of Life - Minimal.png

But after years of not getting what I want from mouser, I finally went full Thanos.

I'll do it myself.jpg


Features
  • Displays a customizable title for the event
  • Displays a progress bar showing how far into the event you are
  • Displays a countdown timer showing how long until the event starts/ends or how long it has been over
  • Configurable amount of precision (how many units of time to display)
  • Optional monospace font
  • Optional dyslexic font

Planned Features
No other features planned

Screenshots
PBOD - Roboto.png PBOD - RobotoMono.png PBOD - Dyslexic.png PBOD - DyslexicMono.png

Usage
Installation
Unzip and run.

Using the Application
Launch the app once to generate the config file.
Edit the config file as you see fit.
Re-launch the app to load the new configuration.
Panic as your deadline approaches.

Uninstallation
It should be mostly "portable" so you can just delete the files wherever you unzipped it to, but it might write some logs to your user path under Deozaan/PB&J (or PBandJ).

Tips
Don't actually panic.

Known Issues
None

13
Living Room / Exploiting Glitches to Win Games Quickly (Speedruns)
« on: November 16, 2021, 02:07 AM »
There have been a couple of similar posts on this subject already, see the one about beating Castlevania: Symphony of the Night with assembly code here (along with a couple other videos about Super Mario World) or the one about the race to conquer Mario Kart's Choco Mountain in seconds here, but I'm creating a more generic thread here which any future similar video (or article) can be posted to.

To start off the thread, here's a video of how speedrunners beat a trial version of The Legend of Zelda: Ocarina of Time which would automatically reset after 5 minutes had elapsed. The methods used in this one is similar to the above linked Castlevania video, where the speedrunner performs certain actions in the game to rewrite parts of system/game memory to get the desired result.

Super Smash Bros. Brawl contains a timed demo of Zelda: Ocarina of Time, with only 5 minutes of playtime. Defeating Ganon and beating the game sounds completely impossible in the demo! However, speedrunners have found a way. Here's how they did it.

How Speedrunners Beat the Brawl Ocarina of Time Demo

14
DC Gamer Club / Ludum Dare 49: October 1st-4th, 2021
« on: September 15, 2021, 02:07 PM »
Ludum Dare 49 is almost here! It begins in about 2 weeks.

Unfortunately I have scheduling conflicts this time around, so I don't plan on participating.

But theme suggestions are currently open, which means that anyone who is interested can submit up to 3 themes, even if they're not participating. You just need to register a free account to be able to do so. If you'd like to suggest a theme, you may do so here: https://ldjam.com/ev.../ludum-dare/49/theme






See previous posts on DonationCoder about Ludum Dare:

Ludum Dare 48 - (My team made Let's Go Deeper for LD48)
Ludum Dare 47 - (My team made Chrono Crash for LD47)
Ludum Dare 46 - (My team made Defendeer for LD46)
Ludum Dare 45 Reviews - A thread about LD45 games
Ludum Dare 41 - (My team made It's Not Lupus! for LD41)
Ludum Dare 2017 Thread - A thread about games from LD37 and LD38
Ludum Dare 33 - A thread about LD33 games
Ludum Dare 32 - (I made Time Bomb during LD32)
Ludum Dare 31 - (I made Worm Wars during LD31)
Ludum Dare 30 - (I made Planetary Devourers during LD30)
Ludum Dare 29 - (I made It Came From... Beneath!! during LD29)
Ludum Dare [29] topic for other games - A thread about LD29 games
Ludum Dare 23 - (I made Be Tiny, World! during LD23)
Ludum Dare - Game Programming Challenges

15
Developer's Corner / Clean Code - Uncle Bob (YouTube Playlist)
« on: September 08, 2021, 12:07 PM »
I came across this playlist of videos of "Uncle Bob" lecturing about writing clean code. It looks like the full lecture/seminar is about 9 hours in total. I just finished the first video and am finding it interesting enough that I want to continue with the series.


https://www.youtube....GO839azG_BBw8rkh-zOj

And if you decide to watch it, don't be put off the whole thing by how annoying or useless the first ~3:30 minutes of introductions at the beginning of the first video appear to be. In fact, it may be best just to skip them. Use the chapters/timestamps to get to the right spot. :Thmbsup:

Oh, and one more word of warning: Unfortunately the video editor kind of sucked at their job and didn't always show the feed from the most useful camera. For example, sometimes Uncle Bob is showing or talking about his slides but the camera is zoomed in for a close up on his face instead of showing us the projector screen. :(

Great lecture (so far), shoddy video editing work.

16
Developer's Corner / Constructing a minimal Sudoku puzzle
« on: July 28, 2021, 10:35 AM »
Hi all,

I've been working on programming a Sudoku game and I've run into a problem with my code that I've been unable to solve for the past few days and realize I need some fresh eyes on the problem. This may not be the best place to ask about this, but as best as I can tell this problem requires a bit of an in-depth explanation and I don't really feel comfortable asking on other sites that may be more closely aligned with the specific area of inquiry, but where I have not really established myself as part of the community. And maybe it could be asked more succinctly, but unfortunately for anyone who reads this, I tend to be overly verbose in an effort to make sure I'm explaining myself clearly. So here goes.

First of all, I assume the reader is familiar with Sudoku puzzles and understands the basic rules. But I figure I should establish some Sudoku terminology (mostly from Peter Norvig), so we're all speaking the same language here.

Square: A place where a number goes. A Sudoku puzzle is made up of 81 squares arranged in a 9x9 grid.
Row: Nine squares arranged horizontally (9x1), in which the numbers 1 through 9 can only appear once.
Column: Nine squares arranged vertically (1x9), in which the numbers 1 through 9 can only appear once.
Box: Nine squares arranged in a 3x3 grid, in which the numbers 1 through 9 can only appear once.
Unit: Any nine squares that compose a row, column, or box. Each square is a member of exactly 3 units.
Peers: Any squares that share a unit are considered peers. Each square has exactly 20 peers.
Given: The "freebie" clues that are known at the start of the puzzle.
Minimal Puzzle: A Sudoku puzzle that has the fewest amount of givens possible, while still only having one unique solution.

And here's a crude diagram showing a minimal puzzle with some of the above terminology highlighted:

Sudoku Terminology.png

So what I'm trying to accomplish is making a game that can generate an infinite number of Sudoku puzzles (well, as many of the 6,670,903,752,021,072,936,960 possible puzzles as a player might want/be able to play). It turns out that generating solutions is easy. You can sort of just make it up as you go along. The part I'm having trouble with is going from the solution to the minimal puzzle.

In other words, in order to present the player with a puzzle to solve, I want to go from something like what's on the left to something like what's on the right:

Code: Text [Select]
  1. 1 2 7 | 4 5 8 | 3 6 9     . . . | . . . | . 6 .
  2. 5 3 9 | 6 7 2 | 1 8 4     . 3 . | . . 2 | . . .
  3. 6 4 8 | 9 3 1 | 7 2 5     . . . | . 3 . | . . .
  4. ------+-------+------     ------+-------+------
  5. 3 1 5 | 7 8 6 | 4 9 2     . . . | 7 . 6 | . . .
  6. 4 8 2 | 3 1 9 | 6 5 7     . 8 2 | . 1 . | . . .
  7. 9 7 6 | 2 4 5 | 8 3 1     9 . 6 | . 4 . | . . .
  8. ------+-------+------     ------+-------+------
  9. 8 9 4 | 5 6 7 | 2 1 3     8 9 4 | 5 . 7 | . . 3
  10. 2 6 3 | 1 9 4 | 5 7 8     . . . | 1 . . | 5 7 8
  11. 7 5 1 | 8 2 3 | 9 4 6     . 5 . | . . . | . . .

I've written code that accomplishes it. In fact, the above puzzle was generated by my code. But it's far too slow, and unpredictably so, to be useful in a real-time game. Sometimes it only takes a couple of seconds to generate a puzzle, which in itself is too slow. But other times it takes up to a few minutes. And in a few cases it has taken so long that I've been too impatient to let it finish. I'm coding this in GDScript, which is a custom language created for Godot, but which is very similar to Python.

I'm storing the solution of the 9x9 grid in a special kind of one-dimensional array in GDScript called a PoolIntArray, which is passed by value instead of reference. It would look like this as a traditional array:

Code: Python [Select]
  1. var answer := [
  2.         1, 2, 7, 4, 5, 8, 3, 6, 9,
  3.         5, 3, 9, 6, 7, 2, 1, 8, 4,
  4.         6, 4, 8, 9, 3, 1, 7, 2, 5,
  5.         3, 1, 5, 7, 8, 6, 4, 9, 2,
  6.         4, 8, 2, 3, 1, 9, 6, 5, 7,
  7.         9, 7, 6, 2, 4, 5, 8, 3, 1,
  8.         8, 9, 4, 5, 6, 7, 2, 1, 3,
  9.         2, 6, 3, 1, 9, 4, 5, 7, 8,
  10.         7, 5, 1, 8, 2, 3, 9, 4, 6,
  11. ]

I also have a similar array of booleans, called "givens" which indicates if a particular square is a given or not.

I then follow a method I read about in a paper called Sudoku Puzzles Generating: from Easy to Evil (link to archive, since original link is dead) which the authors refer to as "digging holes" in the puzzle, and offer this flowchart as part of their explanation:

Digging Strategy.png

I'll summarize my understanding and (attempted) implementation as follows:

  • Order a list of all the squares to "dig" however you see fit. (I just shuffle an array of all the squares)
  • For each square in the list, attempt to dig the known value N. This means to set the value as "unknown" or "empty" (represented internally by the number 0).
  • With the newly dug square, attempt to solve the puzzle with all possible values (1-9) other than N.
  • If you find a solution, it means the puzzle is no longer unique (it has multiple solutions), so the square is considered a given and must display the value N to maintain uniqueness.
  • If you don't find a solution, the square can remain "dug" and you continue iterating the list to dig more holes.
  • Once you've iterated the entire list, you should have dug out all squares that are not essential to maintaining the uniqueness of the puzzle, which results in a minimal puzzle.

Here's the code which I think does what I described above:

Code: Python [Select]
  1. # digs a solved grid to find a minimal puzzle
  2. func find_givens() -> void:
  3.         # make a list of all 81 indices of the grid
  4.         var dig_list := []
  5.         for idx in 81:
  6.                 dig_list.push_back(idx) # push_back() just adds elements to the end of an array
  7.         # randomize the order of squares we "dig"
  8.         dig_list.shuffle()
  9.         # prepare some variables we'll be using repeatedly
  10.         var nums = answer # grab a copy of the answer so we don't make changes to it
  11.         var v : int # temporarily stores the "dug" value in case we need to replace it
  12.         var coords := Vector2() # x,y coordinates
  13.         # iterate the randomized list
  14.         for i in dig_list:
  15.                 # don't attempt to dig a square that is known to be a given
  16.                 if given[i] == true:
  17.                         # sanity check: this code should never actually be reached
  18.                         continue
  19.                 # store the current value of the digit
  20.                 v = nums[i]
  21.                 for n in range(1, 10): # iterate the numbers 1-9
  22.                         # skip if this is the square's original value
  23.                         if n == v:
  24.                                 continue
  25.                         # dig the value and try finding other solutions
  26.                         nums[i] = 0
  27.                         # get the (x, y) coords for this square
  28.                         coords = index_to_coord(i) # convert the index (0-80) to x,y coordinates as if on a 9x9 grid
  29.                         # change the value at this square to something else, if possible
  30.                         if is_possible(nums, coords.y, coords.x, n):
  31.                                 # N could legally be placed in this square
  32.                                 nums[i] = n
  33.                                 # try to find a solution to the puzzle with this new value in this square
  34.                                 if solve(nums) > 0:
  35.                                         # we found a solutions, which means the puzzle is no longer unique
  36.                                         # so put the value back
  37.                                         nums[i] = v
  38.                                         # mark this square as a given
  39.                                         given[i] = true
  40.                                         # don't attempt further numbers for this square
  41.                                         break


And here's the code for the if_possible() function, which is used to determine if a value n could legally be placed in the square located at (x,y) in a 9x9 grid. Or in other words, it makes sure that no other peer of the square (x,y) has the value n:

Code: Python [Select]
  1. # returns true if no peers have the value n
  2. func is_possible(grid, y : int, x : int, n : int) -> bool:
  3.         for i in 9:
  4.                 # check if n already exists in current row (9x1)
  5.                 if grid[coord_to_index(y, i)] == n:
  6.                         return false
  7.                 # check if n already exists in current column (1x9)
  8.                 if grid[coord_to_index(i, x)] == n:
  9.                         return false
  10.         # integer math here means (5 / 3) * 3 is the same as 1 * 3
  11.         var x0 : int = (x / 3) * 3
  12.         var y0 : int = (y / 3) * 3
  13.         # check if n already exists in current box (3x3)
  14.         for i in 3:
  15.                 for j in 3:
  16.                         if grid[coord_to_index(y0 + i, x0 + j)] == n:
  17.                                 return false
  18.         # as far as we know, n is a legal value for this square
  19.         return true

And finally, the code used to attempt to find a solution to the puzzle. I think this is where my trouble lies. This function basically just brute-forces the grid, attempting every possible value in every unknown square, looking for a solution, with backtracking when it reaches a dead-end. Initially I had it naively starting at element 0 of the array and looping through them in order, but this is obviously very inefficient and leads to a lot of duplicated efforts due to backtracking. It seemed to work, and generated minimal puzzles which usually had about 24-26 givens. But as mentioned previously, it was pretty slow.

So then I attempted to sort the list of squares to solve by the number of possible values that were legal to place there, starting with those which had the least possible solutions. This increases chances of success, but even in the event of a failure (dead-end) it cuts out a huge number of the possible solutions we'd have to check.

Oh, and since it's recursive, I have it keep track of and return how many solutions it has found so that it can immediately jump all the way back down the stack once a solution has been found.

Code: Python [Select]
  1. func solve(grid, solutions := 0) -> int:
  2.         # this is a dictionary whose key will be the (x,y) coordinate
  3.         # and the value will be the number of possibilities for that coordinate
  4.         var possibilities = {}
  5.         # loop through every element in the grid
  6.         for i in grid.size():
  7.                 # get the (x,y) coordinates for this index
  8.                 var coord = index_to_coord(i)
  9.                 # start with the assumption that each square has 0 possibilities (i.e., the square's value is known)
  10.                 possibilities[coord] = 0
  11.                 # if it's not zero, then it's considered "solved" already
  12.                 if not grid[i] == 0:
  13.                         continue
  14.                 # check how many values are possible here
  15.                 for n in range(1, 10): # iterate the numbers 1-9
  16.                         if is_possible(grid, coord.y, coord.x, n):
  17.                                 possibilities[coord] += 1
  18.         # sorted_list is an array whose elements will contain the index of the squares grid,
  19.         # sorted by the number of possibilities
  20.         var sorted_list := []
  21.         for n in range(1, 10): # iterate the numbers 1-9
  22.                 # loop through each element in possibilities
  23.                 for coord in possibilities.keys(): # remember that each key is an (x,y) coordinate
  24.                         if possibilities[coord] == n:
  25.                                 # add this square to the sorted list of squares to solve
  26.                                 sorted_list.push_back(coord_to_index(coord.y, coord.x))
  27.         # now iterate through the sorted list and try solving
  28.         for i in sorted_list:
  29.                 var coord = index_to_coord(i)
  30.                 if grid[i] == 0:
  31.                         for n in range(1, 10): # iterate the numbers 1-9
  32.                                 if is_possible(grid, coord.y, coord.x, n):
  33.                                         grid[i] = n
  34.                                         solutions += solve(grid, solutions)
  35.                                         if solutions > 0:
  36.                                                 return solutions
  37.                                         else:
  38.                                                 grid[i] = 0
  39.                         # none were possible, we've reached a dead end
  40.                         return solutions
  41.         # if we got this far then we've solved it!
  42.         solutions += 1
  43.         return solutions

And again, this seems to work... kind of. I mean, it is (usually) noticeably faster than when I was naively brute-forcing without sorting. But (1) it's still too slow, taking at least a couple of seconds to complete, and (2) the "minimal" puzzles its generating can't actually be minimal. Doing it the naïve way, I was getting minimal puzzles with about 24-26 givens on average, the puzzles this is generating consistently have almost twice as many, usually in the 44-46 range. But it has been proven that the least amount of givens a unique puzzle could have is as low as 17 and the highest amount of givens a minimal unique puzzle can have is 39. So something is definitely wrong. Here's an example:

Code: Text [Select]
  1. . . . | . 5 9 | . 3 4
  2. 2 1 . | . . 6 | . 5 7
  3. 9 . . | 3 . 7 | . 6 .
  4. ------+-------+------
  5. . 9 . | . . 3 | 8 4 2
  6. 5 . 8 | 7 . 2 | 3 . 9
  7. . . 2 | 1 9 . | . . .
  8. ------+-------+------
  9. . 2 . | 8 7 1 | 4 . .
  10. 1 . 7 | 9 . . | 5 . 6
  11. . 3 9 | 6 2 . | 7 8 .

Oh, and for completeness, here is the code for a couple of helper functions that are used in a few places in the code above:

Code: Python [Select]
  1. # returns an index for an 81-element array based on x,y coordinates of a 9x9 grid
  2. func coord_to_index(y : int, x : int) -> int:
  3.         return (y * 9) + x
  4.  
  5.  
  6. # returns the x,y coordinates of a square on a 9x9 grid based on 81-element array index
  7. func index_to_coord(i : int) -> Vector2:
  8.         var coord := Vector2()
  9.         coord.x = i % 9
  10.         # integer division
  11.         coord.y = i / 9
  12.         return coord

I tried adding tons of comments everywhere to make sure it was clear what the code was (supposed to be) doing. If anyone here takes the time to read this, parse/understand the code, and offer helpful suggestions/solutions, I'd appreciate it. Mostly I think I just needed a break from the coding and thought that maybe the process of writing this all out would be a form of Rubber Duck debugging.

I know I'm doing something wrong because I'm not getting minimal puzzles anymore. So help figuring out why that's happening would be much appreciated. But perhaps a more helpful response would explain what else I'm doing wrong that is making this so slow. My understanding is that most minimal puzzles should be solved/generated in milliseconds at most, and that it should be fairly rare to come across a puzzle that takes a few seconds and even rarer to come across one that takes minutes or longer. I've tried benchmarking my code by generating 100 puzzles and averaging the time it takes to do each step, and I can't even do that because while it "only" takes a few seconds at best for each puzzle, it often takes up to a few minutes. But the clincher is that in every attempt at generating 100 puzzles in a row there's (at least) one that takes so long that I've never had the patience to find out exactly how long it would take to complete. I can't remember for sure, but I think I've left it running on a single puzzle for over an hour before aborting the process and trying to adjust the code to speed it up.

What am I doing wrong? And where? Please don't say "everything/everywhere" :D

17
DC Gamer Club / Valve Announces Steam Deck: A Handheld PC
« on: July 17, 2021, 12:48 AM »
steamdeck_photo_skus.png

Valve have announced a new, portable PC with built-in gamepad which looks very much like the Nintendo Switch. It will come with a custom version of SteamOS installed, designed to run games using your Steam library. But it's a full PC, meaning it can also be docked to a TV or monitor and other peripherals (keyboard, mouse, other gamepads) using a USB hub or Bluetooth. And you could even install Windows or other Linux distributions on it.

All the internal hardware of the various models is the same except for the internal storage, which results in a 64 GB (eMMC) model for $400, a 256 GB (NVMe) model for $530, and a 512 GB (even faster NVMe than the 256) model for $650 which also has an anti-glare screen. That said, all three will include a MicroSD slot to allow for even more storage.

Here's a pretty good video overview of all the pertinent details.



Reserving requires a $5 deposit (which will be put toward the final price once you purchase) and will put you on the waiting list, which currently appears to be full until Q2-Q3 of 2022 depending on which model you want.

I decided to reserve one even though I'm still on the fence about it, because at this point I'll have about a year to cancel if I change my mind.

For more details and to reserve one for yourself, see:
https://www.steamdeck.com/

18
On July 6th, 2021, the Linux Foundation announced the public availability of the Open 3D Engine (O3DE) open-source project and the formation of the Open 3D Foundation.

As a founding partner in O3DE, Amazon Web Services and the AWS Lumberyard team has been working on this effort for awhile, preparing the code and tools for a developer-centric initial release.


atom_showcase.png


Amazon is contributing its Lumberyard game engine to open source, and it will be known as the Open 3D Engine.

The Linux Foundation will oversee the project and form the Open 3D Foundation to accelerate collaboration with game developers to enhance the triple-A game engine.

So what’s changed? Is this Lumberyard with an open-source license?

In short, a lot! Yes, it’s open source, under the permissive Apache 2.0 license. And no, O3DE is very different than the artist formerly known as Lumberyard. We leaned heavily on our Lumberyard experiences, iterated, and improved O3DE for eventual collaboration and creative control. We kept the parts that customers loved most about Lumberyard and significantly revamped the rest. We aimed to build an engine that could stand the test of time in an open source world. Because game engines tend to be monolithic, we leaned heavily toward becoming modular with extensibility, embracing open standards tooling from the onset. However, we remained unsatisfied, so we added a new prefab system, a new build system, an extensible UI, many new cloud capabilities, numerous math library optimizations, new networking capabilities, and far too many performance improvements to mention here. Also, for good measure, we even added a whole new PBR renderer capable of forward+ and deferred rendering with ray tracing and GI support!



from o3de.org

19
General Software Discussion / Windows 11 Announced
« on: June 24, 2021, 03:26 PM »
Well, I had heard the rumors and even the "confirmations" of the leaks, but I had assumed that the "Windows 11" moniker was just an internal name since Microsoft has said that Windows 10 would be the last version of Windows ever. But it seems they're actually calling it Windows 11.

They had a big, hour long presentation today, which I didn't watch. But I did watch this trimmed down to about 7-minutes version from the Verge:


20
This may be a little niche, or too specific to my situation, but I'm having some troubles and figured I'd ask if anyone here had experience or insight on how to resolve them. No worries if this is too specific. I don't expect anyone here to go through the trouble of setting up GitLab and SourceTree just to help me out, though I wouldn't put it past some of you people to be that awesomely helpful. ;)

A Brief-ish History:
Ten years ago a thread started here on some relatively new distributed version control systems called Git and Mercurial (Hg). At the time when I researched them, I wanted to use Git but it wasn't easy to get working on Windows, so I ended up using Hg. So for about the past ten years I've become an old fart, set in my ways, thumbing my nose at Git while more or less happily using Hg with BitBucket and TortoiseHg. That is, until last year when BitBucket dropped support for Hg repositories. :(

For a little while I remained stubborn and hosted my own RhodeCode server but it wasn't ideal because I actually collaborate with at least one other person on a somewhat regular basis and my ISP's upload speed isn't that great and my internet connection kept dropping out frequently, so it wasn't very reliable for others to connect to and use.

As a result, this past December I decided to bite the bullet and convert all my repositories to Git and start using Git from then on. And after doing some research I decided I'd rather be using GitLab than GitHub. So I first used a feature of GitHub to import my Mercurial repositories from my personal RhodeCode server and convert them to Git automatically. Then I used a feature of GitLab to import my GitHub repositories to GitLab.

While I was still using Hg, I was alternating between using TortoiseHg and SourceTree to manage my repositories. That is, I primarily used TortoiseHg, but I felt SourceTree had better integrated using development branches more easily. When I made the move to Git, I obviously had to drop TortoiseHg, but I decided to just keep using SourceTree, which supports both Git and Hg (for now... Atlassian owns BitBucket and SourceTree).

I think I got it all configured and had it working in December so that I could connect with GitLab and push/pull to/from my repositories. But then this year I've kind of taken a break from my usual thing and have just been doing little experiments that I never felt were big or important enough for version control. But now I'm starting to get back into wanting version control and I've run into a problem where I can't seem to get SourceTree to work with GitLab anymore.

The Problem:
Somehow I was able to successfully create a new remote repository from SourceTree, but then I immediately got an error when it tried to push my local repo to it. The error looks something like this:

remote: HTTP Basic: Access denied
remote: You must use a personal access token with 'read_repository' or 'write_repository' scope for Git over HTTP.
remote: You can generate one at https://gitlab.com/-/profile/personal_access_tokens
fatal: Authentication failed for 'https://gitlab.com/Deozaan/MyCoolRepository.git/'

GitLab has something called "personal access tokens" (PAT) which can be used in place of your password to authenticate third-party apps to work with your account. The UI doesn't make it very clear (IMO) which scopes are needed, and which scopes include the privileges of other scopes, etc. So, while the PAT I created from December had only the "api" scope, the error message says I need "read_repository" and/or "write_repository" so I created a new PAT with all the scopes.

All the things.png

It didn't help. I still get the same error.

I tried changing the URL to use SSH instead of HTTPS, but then it just asks me to load a ppk file which supposedly contains my SSH key. I don't have one of those. Or at least not the right one. I found one on my PC which I thought might be the right one, but when I load it, it just asks me for the SSH password over and over again. So it seems that the password I have stored in my password manager for GitLab SSH key does not match whatever SSH key is in that ppk file.

I do have my SSH private key stored in my password manager, but the putty agent (pageant) which SourceTree uses seems to require PPK format instead of... whatever format I have it stored as. It starts with "-----BEGIN OPENSSH PRIVATE KEY-----" whereas the random PPK file I found where I thought my GitLab SSH key would be starts with "PuTTY-User-Key-File-2: ssh-rsa"

GitLab PATs.png

So here I am with two PATs that don't seem to work anymore. Somehow I have saved an incompatible SSH key/password in my password manager. I swear I had this all working fine in December and I don't know what changed in the interim. And I don't know if it's a classic case of PEBCAK, or if GitLab's PATs aren't working right, or if SourceTree is not working properly. I just want to be able to push to and pull from my GitLab repos from SourceTree!

That said, I'm mostly just sticking with SourceTree because I'm already familiar with it and because it's free. If there's an alternative (and free) Git GUI client that works well with GitLab and runs on Windows which would solve my problem, I'd be happy to hear your recommendations on that front, as well. :Thmbsup:

21
Finished Programs / Program to play inaudible sound continuously
« on: April 09, 2021, 06:39 PM »
Old solutions for new problems....

I had an old Pentium I computer with a combo modem/soundcard that had issues staying connected to the internet when a system sound played (system would lock up just long enough to kick me offline), unless there was sound continuously flowing through the soundcard at all times. This meant playing music all the time, and usually keeping the speakers turned off if I didn't want to hear it, till I came across a small app capable of playing continuous low frequency tones that my cheap speakers were unable to produce. (25 Hz did the trick)

Flash forward to a couple of days ago, when a screwy Windows feature update, which I am unable to uninstall, messed up my bluetooth, so that no matter how I have the hardware settings configured, it turns Bluetooth off (to save power) when it thinks it is not in use. This is very BAD for a bluetooth mouse. I reported here about this issue in this thread, and was avoiding reinstalling that update for as long as possible, but Microsoft managed to automatically cram it down my throat when I recently rebooted my machine, despite having updates paused till some time in January.

BUT I noticed it doesn't cut off my mouse if I have sound playing through my bluetooth headphones. So, I am back to using that very old app, to generate a continuous 10 Hz tone, just so I can use my mouse.

I had to use the system volume mixer to set the volume of this app at a very low level, since my bluetooth headphones are capable of producing audible sound generated from this app, at even the lowest (10 Hz) setting.

Do you have a link to that app, app?

About 6 months ago I moved my entire PC setup into another room, and when I plugged in my speakers to the power source (a surge protector), they made a very loud POP sound, and ever since then none of the audio jacks on my PC work. So now I've got a bluetooth speaker connected to my PC, but it has the unfortunate problem of taking half a second to "warm up" (or catch up?) whenever some audio is played for the first time after a few seconds of silence. And it's like it receives and plays that first half-second of audio all at once, making an unpleasant (and relatively loud) popping or crackling sound in the speaker as it begins to play audio.

I figure if I could trick it into thinking it is constantly playing audio, then it would stay "awake" and not have this issue. Then I remembered you mentioned playing an inaudible, low frequency sound to help with your BT issues and so here I am, asking about it. :D


22
DC Gamer Club / Ludum Dare 48: April 23rd-26th, 2021
« on: April 06, 2021, 12:49 AM »
Ludum Dare 48 is approaching fast! It begins three Fridays from now.

To be honest, I'm not especially motivated to participate this time, but it's kind of historic in that it's the 48th event of that which used to be called "LD48" due to its origin as a 48-hour game jam before being rebranded as "LDJam" a few years ago. So I feel I can't miss out on being a part of LD48. That said, I've never actually done the 48-hour "compo" and have always participated in the more laid-back 72-hour jam. Anyway, this time I'll be participating in the 72-hour jam as part of a team once again, so that should lighten the load.

Right now theme suggestions are open. Anyone can submit up to 3 themes, even if they're not participating. You just need to register a free account to be able to do so. If you'd like to suggest a theme, you may do so here: https://ldjam.com/ev.../ludum-dare/48/theme


EDIT: My team made Let's Go Deeper for LD48.




See previous posts on DonationCoder about Ludum Dare:

Ludum Dare 47 - (My team made Chrono Crash for LD47)
Ludum Dare 46 - (My team made Defendeer for LD46)
Ludum Dare 45 Reviews - A thread about LD45 games
Ludum Dare 41 - (My team made It's Not Lupus! for LD41)
Ludum Dare 2017 Thread - A thread about games from LD37 and LD38
Ludum Dare 33 - A thread about LD33 games
Ludum Dare 32 - (I made Time Bomb during LD32)
Ludum Dare 31 - (I made Worm Wars during LD31)
Ludum Dare 30 - (I made Planetary Devourers during LD30)
Ludum Dare 29 - (I made It Came From... Beneath!! during LD29)
Ludum Dare [29] topic for other games - A thread about LD29 games
Ludum Dare 23 - (I made Be Tiny, World! during LD23)
Ludum Dare - Game Programming Challenges

23
General Software Discussion / Deozaan's To-do List
« on: March 19, 2021, 03:38 AM »
I've recently started learning how to use the Godot Engine. It's a game engine, but it can be used for non-game apps as well. As a means of familiarizing myself with Godot, I have been working on some simple projects.

I made another non-game app: a simple to-do list.

To-do List.png

Considering it's my second complete project in Godot, I expect there are probably some bugs.

Jotti says it's clean.
VirusTotal says it's clean.

You can download it from my Keybase: https://keybase.pub/deozaan/TodoList/

Just thought I'd share with anyone here who might be interested. :Thmbsup:

Oh, and right now I only have a Windows build available for download. But if anyone is interested in Linux or MacOS builds, let me know and I can supply those as well.

24
General Software Discussion / Deozaan's Simple Text Editor
« on: March 19, 2021, 03:27 AM »
I've recently started learning how to use the Godot Engine. It's a game engine, but it can be used for non-game apps as well. As a means of familiarizing myself with Godot, I have been working on some simple projects.

The first one I made is a simple text editor. I started out just following a tutorial series on YouTube and then I added a few more features until I lost interest and was ready to move on to something else.

Simple Text Editor - Hello World.png

Considering it's my first complete project in Godot, I expect there are plenty of bugs. And I certainly don't expect it to compete with the likes of Notepad++, or even Microsoft Notepad, for that matter.

Jotti says it's clean.
VirusTotal says it's clean.

You can download it from my Keybase: https://keybase.pub/...an/SimpleTextEditor/

Just thought I'd share with anyone here who might be interested. :Thmbsup:

Oh, and right now I only have a Windows build available for download. But if anyone is interested in Linux or MacOS builds, let me know and I can supply those as well.

25
I've had a portable .exe of Auslogics Disk Defrag Portable sitting in a folder on my PC for years, and frequently used it. The most recent time I used it a few days ago, out of nowhere Windows Defender marked it as malicious. I went into Windows Security center and told it to allow/restore it, but after I rebooted my computer today for the most recent Windows Update, it's gone! That leads me to two questions:

#1: Is it feasible that this portable app has had some hidden trojan all these years and only now is it being properly picked up by anti-virus scanners, or is it most likely just a sudden false positive? I uploaded the file to Jotti and VirusTotal before it disappeared, and there were several AVs flagging it as malicious. So it's not just Windows Defender acting up. Again, this is a file I've had for years. It's not like I just downloaded a new or updated version that changed the code.

#2: Does anyone know how to restore a file that Windows Defender got rid of? I don't see the usual "allow" or "restore" options in Windows Security. In fact, Windows Security tells me that it failed to remediate the problem. I'm attaching relevant screenshots if it helps to see what I'm seeing.

Windows Security - Removed or Restored.png

Windows Security - Remediation Incomplete.png

EDIT: Nevermind about #2. I had a backup in my Dropbox folder.

Pages: [1] 2 3 4 5 6 ... 19next