244 karma · joined May 15, 2022
Although it has cult status in Israel for some reason.
It's similar with Turbo Pascal 3.0, but there's only one segment since it's a good old COM file. The compiler just copies its own first ~10000 bytes, comprising the standard library, and splices the compiled result to the end.
I can see how this makes transcompilation relatively straightforward, although the real mode 16-bit code is a bit unpleasant with all the segment stuff going on, so you might as well just decompile :D. It's very possible that similar instructions will be emitted in 3.0 and 4.0 for the same source input.
My program also has the stack checking calls everywhere before calling functions. I think that people using Pascal weren't worried about performance that much to begin with, so they didn't bother disabling it.
Since TP 3.0 does no optimisations, and looking at the progress so far (~25% decompiled), it seems like matching decompilation should be achievable.
If/when I get to 100%, I hope to make the process of annotating the result (Func13_var_2_2 is hardly an informative variable name) into a community project.
I think it's a bit difficult to describe a game as purely strategic/operational/tactical.
Games can contain strategic/operational/tactical elements or choices, and I would say that a game where the vast majority of choices are operational can be called an "operations game".
When I played Konquest/Galcon, I felt that the biggest challenge was figuring the correct timing and order of expansion, which to me feels like strategy. It's very possible that AIs would disagree with me.
I have more experience with the discrete version - e.g., Konquest[0].
I think it's not very operational, as getting your ships to battle is as simple as saying go from A to B. Your operational choices boil down to whether you want to pass through planet C, to trade time for flexibility.
While it has perfect information over your own ships, I think the core idea can be easily adapted to have separate players controlling separate planets, with delayed communication, both for people playing this game and for an AI competition.
It looks more or less like this:
__m256i s = _mm256_add_epi64(a, b);
const __m256i all_ones = _mm256_set1_epi64x(~0);
int g = _mm256_cmpgt_epu64_mask(a, s);
int p = _mm256_cmpeq_epu64_mask(s, all_ones);
int carries = ((g << 1) + p) ^ p;
__m256i ret = _mm256_mask_sub_epi64(s, carries, s, all_ones);
The throughput even seems to be better: https://godbolt.org/z/e7zETe8xYIt's trivial to change this to do 512 bit addition where the improvement will be even more significant.
If a free Linux distribution is more successful, its resources don't scale accordingly.
Close to the midpoint you're walking up and down a bunch of small but steep hills and valleys, when a huge tree appears in the next valley.
It was really a memorable view in the mostly monotonous English countryside.
Even small things like converting multiplications followed by additions to FMA will reduce the operation count.
Add to that constant folding etc. and a speedup factor of ~3 is not so hard to imagine.
The founder of Steve Jackson Games and creator of Munchkin and GURPS [0]
The writer of Fighting Fantasy and founder of Games Workshop and Lionhead Studios [1]
I find the fact that the two are in business quite satisfying.
[0] https://en.m.wikipedia.org/wiki/Steve_Jackson_(American_game...
[1] https://en.m.wikipedia.org/wiki/Steve_Jackson_(British_game_...
It's orders of magnitude faster than my naive hand-written emulator.
The series 0.9, 0.99, 0.999,... is asymptotically close to 1 and also asymptotically close to 0.9999... (with infinite 9s), since for any epsilon, I can find an index N after which all elements of the series are within epsilon of the target.
Since a single series can't have two limits, 1.0 should be equal to 0.999...
Note that real numbers are allowed to have infinite digits after the point, otherwise they wouldn't include things like 1/3.
It's pretty clear why that's the opposite of filing off material close to the tip, so obviously the tone goes lower.
In my mental image, filing close to the base of the reed gives the reed a similar shape as putting extra material next to the tip (thinner at the base, thicker next to the tip), and that's why it behaves the same.
In other languages these would require much more effort.
[1] https://github.com/spring/spring or https://github.com/beyond-all-reason/spring (yay for forks!)
[2] Preserving the order of iteration on items in a hash table after deserialization and further manipulations.
The interface might be intimidating at first, but with two wave generators and a couple of patterns you can already conjure a passable background track. A bit more complexity and it can sound pretty good.
I'm not a prolific writer and the subjects are just what interested me at that point in time and I feel should be public. Unfortunately, there aren't many companies looking for experts in palindromes.
Looking at the websites shared here, it seems like web development tutorials and tips are the way to go if you want to get hired.
I, however, recommend writing about whatever gets you excited and you want to share with the world. Especially since you're happy in your current place.
import itertools import functools
for eve_card in range(7): cards_left = set(range(7)) cards_left.remove(eve_card)
mod_to_cards = [[], [], [], [], [], [], []]
for c in itertools.combinations(cards_left, 3):
mod = sum(c) % 7
mod_to_cards[mod].append(set(c))
for combs in mod_to_cards:
i = functools.reduce(lambda x, y: x.intersection(y), combs)
if len(i) != 0:
print("intersection", eve_card, combs, i)
u = functools.reduce(lambda x, y: x.union(y), combs)
if len(u) != 6:
print("union", eve_card, combs, u)So far it's working quite nicely. Every now and then you take a look and notice that your modules are now at the top, so you quickly fix them, passing the honour to the next victim.
Running the equivalent C code takes ~2.3 seconds on my machine. Same order of magnitude as bend on the beefy GPU.
It follows the principle that one can represent a board by choosing k filled spots from 9 and then choosing k / 2 Os from k. These two combinations can be converted into an index, which can then be offset according to k to prevent collisions with indices from other ks. This offset is not pretty, but it works.
I haven't thoroughly tested my code, but the principle should work even if there's a bug or two :)
With some luck I'll find time to write a clearer explanation or a blog post.
Regarding the low core-count, you might actually lose performance when having less CGUs, since your absolute estimation error is larger.
For example if a CGU can take 3 times as long to compile as another with the same estimate, we might end up with a 0.75:0.25 split if we have 2 CGUs, ending up with a 50% increase in compilation time, but with 16 CGUs the worst case (one CGU taking a 1/6 of the time and 15 CGUs taking 1/18 of the time) will only result in ~11% increase in compilation time, due to the automatic balancing that job scheduling gives us.