Simon blogs

Started by Simon, October 18, 2015, 06:05:44 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Simon

#75
Main reason is slight ease to keep data when replacing the system. With SSDs, we don't have to put the system or the most interesting files on the fastest disk area anymore, because everything is fast.

Indeed, I have reinstalled Arch several times in the first week because I trashed the system. But the reason remains weak. Maybe I should have put everything on one partition for simplicity.




Games that I invented 5-10 years go

I have a scrap heap of tabletop game ideas, sometimes entire games with full rule text files. Here are some of these games that weren't entirely terrible.

A two-player strategic game with secret information. You have a map with territories. New military units spawn regularly in your home territory. There is only one type of unit, like in Risk. Units take several turns to move between adjacient territories. You announce that your units move from a territory, but don't announce where they move; instead you place them on a face-down card that names the target territory. A die goes on the card along with the units, this die counts time. You can time your attacks such that units from different territories arrive at a target territory at the same time. The game is feels very slow and bureaucratic.

A solitaire with 52 face-up cards dealt to 10 tableau piles spread downwards. You can move single cards to build downwards regardless of suit (e.g., place a frontmost 8 on a frontmost 9). You can also build upwards in suit. Upwards builds (e.g. 5-6-7-8 in spades, with the 5 buried deepest) can be moved as a unit (the example 5-6-7-8 in spades can be be built on the 4 of spades, or on a 6 of any suit). Free spaces can accept any single card or upwards built. You win if you assemble all four suits in four long upwards builds.

Cluedo (a.k.a. Clue) without a board or dice, only with the cards. It's perfectly possible to play with three suits of varying length from a standard deck. Every turn, you suspect a triplet or make an accusation. It feels like this must be a very smart game, but I'm sure there are better deduction games.

A multiplayer trick-taking card game with more than 4 suits, but it works in a pinch with 4 suits. Card ranks are ordered, like in most trick-taking games, but suits are ordered too. In the 1st, 3rd, 5th, ... trick, you must follow suit. If you can't follow suit, you may trump with the lowest-ordered suit. In the 2nd, 4th, 6th, ..., trick, you must follow rank. If you don't have a card of the given rank, you may trump with the lowest-ordered rank. With 3 or more players, this game is really chaotic and we didn't see much strategy in it. But it's not a good beer-and-pretzels game either because the rules are so unintuitive.

A game where every player puts some cards from his hand face-down onto one shared pile, then everybody guesses or bets on the entire pile's content. This should be interesting because everybody knows other things about the pile. But I didn't find a good ruleset around this idea, it felt like a lottery. In hindsight, if you can somehow react to other players' guesses by adjusting your guess, we get close to Liar's Dice, a good game.

-- Simon

Simon

#76
My first Mandelbrot-drawing code


import std.algorithm;
import std.complex;
import std.string;

import allegro5.allegro;
import allegro5.allegro_image;

alias Albit = ALLEGRO_BITMAP*;
alias Alcol = ALLEGRO_COLOR;

void main()
{
    al_run_allegro({
        al_init();
        al_init_image_addon();
        Albit bmp = makeMandel(300*6, 260*6);
        "./a.png".toStringz.al_save_bitmap(bmp);
        return 0;
    });
}

enum maxIters = 100;

Albit makeMandel(in int xl, in int yl)
{
    Albit b = al_create_bitmap(xl, yl);
    al_set_target_bitmap(b);

    foreach (int bx; 0 .. xl)
        foreach (int by; 0 .. yl) {
            Complex!double c = complex(
                -2.2 + 3.0 * bx / xl,
                -1.3 + 2.6 * by / yl);
            double darkness = clamp(
                (1.0 * maxIters - howManyIterations(c)) / maxIters,
                0, 1);
            al_draw_pixel(bx, by, Alcol(darkness, darkness, darkness, 1));
        }
    return b;
}

int howManyIterations(Complex!double c)
{
    int ret = 0;
    Complex!double z = c;
    while (abs(z) < 2 && ret < maxIters) {
        z = z^^2 + c;
        ++ret;
    }
    return ret;
}


I've never took computer science classes, therefore I never had to write this lovely toy program. I did it for fun tonight. The math isn't hard, the programming isn't hard, but the images are as awesome and intriguing as ever.

<SimonN> the standard mandelbrot belongs to f(z) = z^2 + c, this weird insect-like set is f(z) = z^2.1 + c
<mobius`> that's flippin' crazy man
<SimonN> I wouldn't want this to crawl into my bed at night >_>


Also attached is a bonus image that I generated on the next day, from the Burning Ship.

-- Simon

mobius

what is the equation for the last (new) one?
and why is it cutoff at the bottom or is this normal? Is that the limits of the program?
everything by me: https://www.lemmingsforums.net/index.php?topic=5982.msg96035#msg96035

"Not knowing how near the truth is, we seek it far away."
-Hakuin Ekaku

"I have seen a heap of trouble in my life, and most of it has never come to pass" - Mark Twain


Simon

#78
Iterate f(z) = (|Re z| + i |Im z|)^2 + c.

Burning Ship fractal on Wikipedia. I plotted one of the small ships at the left side. Nice zoom anim on youtube.

My image is cut off because I zoomed in on a part. The entire fractal has a unique shape, but I like these towers even better.

-- Simon

mobius

Quote from: Simon on June 02, 2017, 02:10:52 PM

Games that I invented 5-10 years go

I have a scrap heap of tabletop game ideas, sometimes entire games with full rule text files. Here are some of these games that weren't entirely terrible.


I'd like to see more of those if you're willing to share. The clue one sounded like a good idea I want to try that out, and maybe the others too. I used to play lots of cards years ago but haven't for a long time. Recently I've started getting back into it.
everything by me: https://www.lemmingsforums.net/index.php?topic=5982.msg96035#msg96035

"Not knowing how near the truth is, we seek it far away."
-Hakuin Ekaku

"I have seen a heap of trouble in my life, and most of it has never come to pass" - Mark Twain


Simon

#80
More renderings of the Burning Ship. This is the most beautiful math I've ever done. :lix-blush:

The color scheme is discontinuous. I defined an arbitrary cutoff: How many iterations are still dark blue air, and how many iterations are the fiery-orange towers or sails? I chose 20 for the first and 23 for the second image. The more iterations a point takes to escape, the lighter the sails become.

(Re more games: I plowed through my collection, but no more sprung forward as worthwhile. Maybe one-card poker? Impose a linear order on all cards, i.e, order by suit whenever rank is equal, deal a card to each player. Start player posts a blind, then you have one street of betting. Highest card wins among the non-folders.)

Bonus image for Icho:
Armada to the left of the main fractal in 6240x1560.
Armada with transparent bg
Armada, only the background in blue

-- Simon

Simon

So Long Sucker

Found a strange 4-player tabletop game, So Long Sucker, invented by John Nash and others. If the linked rules on Wikipedia aren't clear -- the game appears subtle on first read -- consider the rules PDF linked on Wikipedia, and read that too. I believe I have fully understood the rules.

The driving mechanic: On your turn, you must make a play, thereby diminishing your stash of chips. You lose if it's your turn and you're out of chips. But having the move can be very good also, because you can capture chips under special conditions. You must decide whose chips to remove from the game, and you must decide who gets the next turn.

Coalitions, or agreements to cooperate, are permitted, and may take any form. No penalty for failure to live up to an agreement.

I don't dare to suggest play-by-forum. :lix-evil: In the negotiation games, you make and break your alliances as you see fit. That can leave even seasoned gamers with a sour aftertaste for weeks. To compare, the Lemmings Mafia went well, nobody got sour from Mafia -- but the teams were determined by the game. You don't backstab in standard Mafia.

-- Simon

Simon

#82
#ifdef __cplusplus extern "C" { #endif __attribute__((__deprecated__))

Allegro 5 on Arch lacks .xm/.mod/.it support: A5 doesen't support the newest version of the DUMB library that interprets the music files. What to do? Dive into the internals of both libaries and connect wires yourself.

First, we ask around what people know, or have already tried. I'm lucky: I'm not the first to have run into this problem, 1-2 others have investigated already. Soak up all wisdom of the ancients.

C and git are the building blocks of culture, and you can safely assume that everybody in the world knows them well. Whoever doesn't know either one won't be able to help you in this quest anyway. :lix-evil:

Build debugging versions of both libraries. Maybe script around the build systems if they need arcane flags. Finally, instead of opaque crashes, we get nice assertion failures.

We find a segfault in DUMB from null function pointer where A5 is expected to pass a function, but doesn't pass anything because the old DUMB version didn't have that pointer. What function should we pass? DUMB doesn't tell us because the docs are work-in-progress, therefore research and submit documentation yourself.

Realize that, by here, we already know more than whoever has tried this before. Even though we haven't contributed code to either library before, we're getting knowledge of the domain. If we get stuck, we can make educated decisions on what expert to ask.

Rage about C error reporting culture. Functions that produce data can often fail, and they return null pointer on failure. No exceptions, not even error codes. Want want want the program to blow up with a nice informative error message, but we don't get that in C land. The moment a function doesn't behave 100 % as expected, we must dive further into internals.

The biggest C hack is to return negative values to signal errors, and 0 or positive values as good results.
Zig gets that right: You have your function return exactly either a good result or an error, then the compiler checks that you handle that properly. Product types (structs) are popular, but most languages sorely lack sum types (= either-or-types).

Accept that you might get stuck halfway. Make the changes as readable as possible, preparing to publish them however far we get. Somebody else on the internet might be crazy enough to work on the same problem.

Edit: Pull request against A5!

-- Simon

mobius

'Culture' is not your friend: ;)
https://www.youtube.com/watch?v=OdUCa5TrC9Q

thanks for liking our music so much :D I wasn't so sure about the titles I picked but I closed my eyes and named them for what I saw in my head when listening.
everything by me: https://www.lemmingsforums.net/index.php?topic=5982.msg96035#msg96035

"Not knowing how near the truth is, we seek it far away."
-Hakuin Ekaku

"I have seen a heap of trouble in my life, and most of it has never come to pass" - Mark Twain


Simon

#84
How often does ccexplore have to post on Lemmingsforums until all the displayed hamsters match the rotational energy of the earth?

The earth weighs 6 × 1024 kg, has a radius of 6.4 × 106 m and spins at 7.3 × 10−5 radians per second. The rotational energy of solid spheres is 0.2 × mass × radius2 × (angular speed)2. A gold hamster weighs 0.12 kg. Measure the rotational speed of ccxeplore's avatar yourself -- rotational speed speed in radians is 6.24 / (time for one revolution). Assume the hamster is very fat is a sphere of radius 0.07 m for distribution of mass.




Points A and B are 1 km apart. A river flows from A to B with constant speed. We travel between these points on a motorboat that has constant speed relative to the water. From A to B, we take 2 minutes riding with the current. From B to A, we take 4 minutes against the current. How long would we take to travel 1 km with this boat in a lake without any water current?

-- Simon

nin10doadict

Problem 1 is a trick question because you said "displayed hamsters" and I can't fit enough hamsters on the screen at once to get that high of a value. My computer would probably crash from trying to display too many at once.

Simon

#86
Quote from: nin10doadictProblem 1 is a trick question because you said "displayed hamsters"

Hehe, this sort of answer classifies you as a good mathematician or computer scientist: Edge cases matter. Also good backroute.

Design of a search feature: Hide your complexity

tl;dr: Use fibers for expensive work.

Lix 0.9 will have a level search. Type a query into a search box, and the game presents you a list of levels that match your query. I'm proud of this feature because I thought of it first: No other Lemmings engine has it, nobody has requested it before, but I'm already using it in my regular level-maintaining workflow. Good stuff. Good broccoli.

I want to be Google! What are the hallmarks of Google search?
  • One good search box, no distracting options.
  • Searches in everything you might want to. In our case, filenames and level titles.
  • While you're typing, you're already seeing first hits on the screen.
  • As you type more characters, earlier hits vanish as they become irrelevant.
  • Hits appear and vanish in realtime. Very handy: You can stop typing when you've narrowed down to 1 hit.
  • All this good stuff happens magically in the background, it doesn't freeze the app.
Now, I said that the search matches both filenames and level titles. The operating system can quickly produce a list of files in levels/, but to filter for level titles, I have to open each file and read the first couple lines. Opening a file is crucially slow: With 1,100 files in levels/, if I open them all in one loop, Lix freezes for a second -- despite my decent CPU, RAM, and SSD.

I could read and index all levels when the program loads, but that goes against the general laziness of the design. I load resources only when I need them; in exceptional cases, I load them when I'll probably need them. Also, if I loaded everything at start of program, Lix would ignore when you move files externally while Lix is still open. And I'd have to hard-wire indexing of new files that you generate with the editor... Blergh, this is asking for bugs from outdated caches. No no no. :lix-scared:

Instead, I index afresh every time I open the search dialog, but hide the work. Getting the tree of filenames from the operating system is fast, I do that immediately, eagerly. Then, Lix begins indexing the levels by opening the level files one after another, caching the level title. After a bunch of files, there comes the time to paint to the screen, read hardware input again, etc.; then we interrupt the caching and work with the half-done index. When the main loop hits the search dialog for the next time, again we work on opening some remaining files, improving the index. Eventually, 1 to 2 seconds into the dialog, the index is complete.

Even if this takes a couple seconds, we can already start typing into the search box, with good performance. We don't get 100 % perfect preview hits, but they will become better in the blink of an eye. On my fast machine, I don't even notice anything off, it looks instant. I'm sure it feels reasonably good on slower machines, too.

Most importantly, The game doesn't freeze during the indexing by definition. :lix-grin: We index while the game would wait on the next frame anyway, then we paint.

The general concept behind this is a fiber. It's not a full thread or process, but it's an expensive function in the main thread that you can pause and resume. You don't get the result ASAP, but you get it reasonably early, and you don't have to freeze your program meanwhile.

I have only this one fiber, and I even rolled my own code here. I simply let the fiber run until I would draw. This approach obviously doesn't generalize to having more fibers. If you want many fibers producing all sorts of good work for you, look into your language's standard library. :8():

-- Simon

mobius

Quote from: Simon on September 27, 2017, 12:23:28 PM
Quote from: nin10doadictProblem 1 is a trick question because you said "displayed hamsters"

Hehe, this sort of answer classifies you as a good mathematician or computer scientist: Edge cases matter. Also good backroute.

Design of a search feature: Hide your complexity

tl;dr: Use fibers for expensive work.

Lix 0.9 will have a level search. Type a query into a search box, and the game presents you a list of levels that match your query. I'm proud of this feature because I thought of it first: No other Lemmings engine has it, nobody has requested it before, but I'm already using it in my regular level-maintaining workflow. Good stuff. Good broccoli.

I want to be Google! What are the hallmarks of Google search?
  • One good search box, no distracting options.
  • Searches in everything you might want to. In our case, filenames and level titles.
  • While you're typing, you're already seeing first hits on the screen.
  • As you type more characters, earlier hits vanish as they become irrelevant.
  • Hits appear and vanish in realtime. Very handy: You can stop typing when you've narrowed down to 1 hit.
  • All this good stuff happens magically in the background, it doesn't freeze the app.

in my experience since they started the "While you're typing, you're already seeing first hits on the screen." feature; it definitely does freeze/slow down. It actually kind of annoys me. I see why it's nice; but I don't think I've ever needed this. I always know what I need to or can type in. I can wait (what; 0.X seconds?) to type and press enter again and again a couple of times.
everything by me: https://www.lemmingsforums.net/index.php?topic=5982.msg96035#msg96035

"Not knowing how near the truth is, we seek it far away."
-Hakuin Ekaku

"I have seen a heap of trouble in my life, and most of it has never come to pass" - Mark Twain


Simon

#88
Quote from: mobius on September 29, 2017, 01:45:36 AM
since they started the "While you're typing, you're already seeing first hits on the screen." feature; it definitely does freeze/slow down. It actually kind of annoys me.

I felt the same with the Google page 5 years ago, it slowed my 11-year-old laptop. I've resorted to typing in the browser's own bars, they call Google when you press Enter.

Searching from the browser bar is better anyway: We save one page load, the search engine's homepage.

Quote
I can wait (what; 0.X seconds?) to type and press enter again and again a couple of times.

I can understand this if you don't trust the computer during the fast operation, or the fast operation has an issue (like Google freezing, as you reported).

But in general, modern UI design suggests that we behave differently when a wait is 0.3 seconds than when it is 0.1 seconds. Even when we don't notice it, small waits break flow.




My pull request for tracked music in Allegro 5 on Linux got merged. The next A5 release won't crash anymore on module files. :lix-tongue: This lifts a roadblock on Lix music. Of course, it takes time before such a change sinks into culture. The library has to release, then distributions have to update their packages, then users have to update their system, ...

-- Simon

Simon

Google's evil UI

Google search offers several tabs: [all] [images] [videos] [shopping] ...
But sometimes, it switches around: [all] [shopping] [images] [videos] ...

Because the first sequence is so common, lazy Simon is conditioned that Google's image search is on the second button from the left, and always clicks that second button without reading. Occasionally, that lands me on the shopping page. A nasty way to peddle stuff. :lix-glare:

Overhead around video game rules

We have the core game rules of Lix, of NeoLemmix, of Nepster's BoxPuzzle, ..., and all these core rules are different.

Then we write applications around these rules, and the nice applications load level files, offer undo and framestepping, save and load replays, maintain backwards compatibilty. The programs must be documented and bugfixed. All this is far more elaborate than the implementation of the core rules.

But it's the only way, sadly. If you merge any two of these programs, the result would be an unmaintainable mess. The rules and physics differ in enough details to warrant separate programs with separate algorithms.

Their ecosystems are complex enough to always have bugs. You stop fixing bugs only when there is no more interest in a program, after many years. And every couple of years, a new idea pops into existence, warranting another large ecosystem to be developed around it.

It's the circle of life. Can you feel the bloat tonight?

Small level packs

I agreed with mobius how the recent small level packs are refreshing, with around 10 levels per pack. Culture handles them like it handles large packs: Replays get posted, maintainer checks whether they're intended, and fixes backroutes.

My view is that packs and ranks are arbitrary in the first place: Ranks are sets of levels, and packs are sets of levels, or of ranks. Others' feelings go deeper with ranks. That's fine, from the standpoint of distribution, we'll arrive at the same result with either feeling.

git

I still want a children's cartoon with a catchy singalong song that teaches people how to use git. I'm sure it would be a massive hit. After all, these things exist for other basic things in life. :lix-unsure:

-- Simon