Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1410915 Posts in 69594 Topics- by 58583 Members - Latest Member: Keyframe

October 11, 2024, 04:44:28 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogs5N²+6N-4 . . . . . . (codename)
Pages: 1 ... 10 11 [12] 13 14
Print
Author Topic: 5N²+6N-4 . . . . . . (codename)  (Read 68439 times)
a-k-
Level 2
**


View Profile
« Reply #220 on: October 15, 2022, 06:30:11 AM »

Did I just use Python to transpile the Go code that the C++ game generated to WASM?


(WASM now available in the captcha spinoff as the 9th language)

WASM could actually be a nice addition also to the main game if I didn't find the translation of individual commands too verbose to my taste. Given that it's a standalone thing, basing this off Go was easiest: Go's support of multi-level break/continue transfers directly to WASM's named blocks/loops, and its restricted goto can be handled as if it were syntactic sugar for break/continue inside for { ... break }.

The new game should (hopefully) be playable on all Safari versions now, after implementing a workaround for a seemingly-obscure bug. Only to find another Safari-specific cosmetic issue with my indentation guides...
Logged

a-k-
Level 2
**


View Profile
« Reply #221 on: November 19, 2022, 03:28:55 AM »

I think that I've found the ultimate language for concealing goto's:



This shares the same algorithm that I implemented for Prolog, being little more than a nicer syntax at the moment. It won't apply to f1 and f2 above, but in general most helper functions should be eliminable by inlining loops. In Prolog, conditional loops needed their own predicates, while here anything can be nested inside anything. I'm going to do just that - hopefully with inlining the translations get "lispy" enough.
Logged

a-k-
Level 2
**


View Profile
« Reply #222 on: November 26, 2022, 01:13:03 AM »

Scheme has been integrated, for a total of 18 languages:


(loops using named let instead of local function definitions)
Logged

a-k-
Level 2
**


View Profile
« Reply #223 on: December 03, 2022, 02:52:32 AM »

The captcha spinoff game has just grown to 10 languages with the addition of OCaml:




How was that implemented? By transpiling from Scheme, of course:

Scheme

(define (tractors)
  (define (f1)
    [
0]
    (cond (<1>
           [2]
           (when <3>
             [4]
             (f2)))

          (else
           [5]
           (f2))))
  (define (f2)
    [6]
    (f1))

  [7]
  (let loop ()
    (when <8>
      [9]
      (f1)
      [10]
      (loop)))
  [11])
    ===>    OCaml

let tractors () =
  let rec f1 () =
    [
0];
    if <1> then begin
      [2];
      if <3> then
        let () = [4] in
        f2 ()
    end
    else
      let () = [5] in
      f2 ()
  and f2 () =
    [6];
    f1 ()
  in
  [7];

  while <8> do
    [9];
    f1 ();
    [10]
  done;
  [11]


In terms of control flow, for our purposes OCaml is merely Scheme plus while loops that don't support break/continue, so conversion was pretty easy. But then, getting it to a style that looked good, with proper line breaks/indentation and judicious use of idioms (or so I hope), took lots of iterations. (And if the result looks alien to you, so did it to me at first...)
Logged

a-k-
Level 2
**


View Profile
« Reply #224 on: December 17, 2022, 08:25:08 AM »

Following player feedback, I've read Whenever's specification once again and realized that the language was stricter than I'd thought, and required print() statements to be placed on lines of their own.

Combined with the earlier (and unrelated) change of limiting the number of commands on a line to no more than 5, this has made the translations longer in about a third.


(the code in the middle is incorrect (both lines) - can't have print() and 2#1-N(2) or 1 on the same line)

I should note that by the same token, read() also needs a separate line, so the code that I generate for conditions (not shown above) is incorrect too. I'm not keen on changing that, however - it seems more natural for language implementors to treat read() as a function than as a statement, so the restriction may not be imposed in practice.
« Last Edit: December 17, 2022, 08:34:29 AM by a-k- » Logged

a-k-
Level 2
**


View Profile
« Reply #225 on: January 14, 2023, 07:22:51 AM »

New level

  • Added a reduction-like level where the input needs to be transformed to a different "representation" (chosen by the player) and then converted back
  • The game now has 72 levels and 18 languages, which seems to perfectly fit its 6 commands. Of course I'm hoping to ruin that (although it's getting harder...)

Chrome 108 saga

Two players reported that the HTML5 version on Chrome started eating memory like crazy (gigabytes), ultimately crashing the browser. I couldn't reproduce it with my savefile, so was mostly shooting in the dark. Nothing I did help, and when one of them, having 64GB RAM and 8 cores, reported that they could barely pass the title screen, I jokingly recommended IE 11, where the game runs smoothly at 60Hz and uses only 200-300MB.
It was obviously that very suggestion that prompted Google, just a few minutes later, to deploy their new version (109) to the player, which fixed all issues.

Gained in the process:
  • Memory optimizations to applicative caches - compression (standard/custom/both) and hashing of keys where these were absent, stricter eviction, and a complete overhaul of one cache whose effectiveness had gradually diminished since the game stopped having only one language (4 years ago)
  • Ctrl+Shift+D also displaying memory use, rather inconsistently - private bytes on Windows, peak heap space rounded up to the next power of 2 in the HTML5 version, and total heap allocations (without fragmentation) on Linux (using malloc_info, possibly the only glibc function that returns XML...)
  • Ctrl+Shift+M (undocumented) - clears most caches, rebuilds font textures (so unused font sizes get deleted), and on Windows and Linux, also returns memory to the OS
  • WebGL 1-->2 transition (HTML5 version)
  • A change that was done and then reverted (killed FPS of HTML5 version on mobile) - moving from using freshly-allocated (static and smaller) VBO per draw call to allocating one (dynamic and larger) VBO and using it cyclically across all draw calls and all frames

Tablet support in HTML5 version

An experiment to test whether, without any changes to the UI, touch input would work well enough as a baseline.

Changes to the HTML5 version:
  • Touch support - fix for old SDL2 version that always reported (0, 0) coordinates, and manual handling of buttons that open browser windows/file dialogs
  • Fullscreen by default, web/standalone app manifests, and CSS/JS voodoo to encourage mobile browsers to not hide the game with all sorts of top/bottom bars (with partial success; dvh may help in the future)
Logged

Alain
Level 10
*****



View Profile WWW
« Reply #226 on: January 22, 2023, 08:50:33 PM »

Hey a-k! I just wanted to leave a word of encouragement: You have been cracking at your game consistently for a long time and it seems crazy complex. I have to admit it scares me a bit, but I'll keep an eye on it :D Keep up the great work!
Logged

a-k-
Level 2
**


View Profile
« Reply #227 on: February 02, 2023, 07:11:05 PM »

Hey a-k! I just wanted to leave a word of encouragement: You have been cracking at your game consistently for a long time and it seems crazy complex. I have to admit it scares me a bit, but I'll keep an eye on it :D Keep up the great work!
Thanks! Don't let all the "extras" fool you, the core game, what players do, is actually simple and hasn't changed since day 1! It's a tried-and-true formula...
Logged

a-k-
Level 2
**


View Profile
« Reply #228 on: February 19, 2023, 01:36:51 PM »

I've managed to reduce the executable size of the Windows and HTML5 versions by 850KB each (and the Linux one a little less) by eliminating about 14,000 compiler-generated initializers and uninitializers.

Imagine having a type such as (greatly simplified for illustrative purposes):

Code:
class Object {
public:
    Object(int v) : val(v) {}

    // methods...

private:
    int val;
    std::string str;
};

And assume that some .cpp files each had 40 objects defined in global scope like this:

Code:
Object foo(1);
Object bar(22);
Object baz(333);
...

Since std::string has both a constructor and a destructor, the compiler would generate 40 static initializers, each constructing a string and registering a distinct atexit callback for destructing it upon program termination.

At first, I replaced the above with

Code:
class Object {
public:
    Object(std::string &s, int v) : str(s), val(v) {}

    // methods...

private:
    std::string &str;    // notice the &
    int val;
};

std::string strs[40];

Object foo(&strs[0], 1);
Object bar(&strs[1], 22);
Object baz(&strs[2], 333);
...


Object instances became initialized by values that are known at either compile time (val) or link time (str = address + constant offset), so I expected the build to hard-code all of them into the executable's data section without any need for special initialization code. strs would still need one, but that would be only 2 compiler-generated functions instead of 80.

That was the case in VC++, and doing the change above to 175 files removed 850KB from the exe. But the reduction in Linux and HTML5 build sizes was much smaller than anticipated. Looking at a listing file, it seemed that gcc and clang removed the uninitializers (now that Object didn't have a destructor) but kept all 40 initializers.

A little push with C-style initializers finally did the trick:

Code:
struct Object {
    #define CONSTRUCTOR(s, v) { s, v }

    // methods...

    std::string &str;
    int val;
};

std::string strs[40];

Object foo = CONSTRUCTOR(&strs[0], 1);
Object bar = CONSTRUCTOR(&strs[1], 22);
Object baz = CONSTRUCTOR(&strs[2], 333);
...
Logged

a-k-
Level 2
**


View Profile
« Reply #229 on: March 05, 2023, 12:16:02 PM »

The game has recently crossed 20,000 player solutions:



Also displayed is the # of optimal cost-cycles thresholds per level, which, unlike the other lines, can also decrease over time.


Intro variant - Polars


(I couldn't wait for v1.0 this time.)


Obscure UI enhancements


(warning in Replace for irreversible transformations (of course, Undo always works.))


(View Solution available also in Records > Code)


(a second Controls screen (on the right))


Obscure HTML5-specific enhancements

  • Client-->server transfers are now done in binary rather than base64, just like in the PC versions.
    (Previously, I used Emscripten APIs, which use x-www-form-urlencoded encoding.)
  • The integrity of the .mem file that's fetched from the CDN is now verified in browsers that support Web Crypto API. (Previously, only the JS was verified, using SRI.)
    This is done by man-in-the-middle'ing the XHR that Emscripten sends.
Logged

a-k-
Level 2
**


View Profile
« Reply #230 on: March 10, 2023, 11:40:22 PM »

Started working on the 19th language:



Somehow, I forgot that there's syntax highlighting and decided to use only digits so that control flow be easily distinguished from actual commands. Switching to alphanumeric symbols will make the translation more compact, and also allow me to reserve 0 and 1 only for conditions so that I can eliminate most '?' symbols.

And I'll need to improve the inlining to be on par with Prolog and Scheme (it's the same foundation underneath.)



A new addition to the captcha spinoff, for a total of 11 languages - SNUSP:


(same control flow as above)

It reminds of Befunge in the main game, except that this time I was less wasteful of horizontal space. I guess that's the benefit of implementing something twice, in two different languages (I mean C++ and Python, if that wasn't clear...)
Logged

a-k-
Level 2
**


View Profile
« Reply #231 on: March 18, 2023, 12:39:19 AM »

Thue has been integrated in the main game as the 19th language and in the captcha game as the 12th one.
For the former, here's the up-to-date translation of the example from the last post:



Changes:
- Alphanumeric symbols
- Consistent "evaluation order" (left-to-right)
- More inlining (fewer rules)
- Fewer '.' and '?' symbols
- Improved order of basic blocks
Logged

LiquidAsh
Level 2
**



View Profile WWW
« Reply #232 on: March 19, 2023, 11:14:19 AM »

I was just checking in on this project and notices that this is the 7 year birthday from the first devlog here!  Beer!

I also see that the game is marked as 70% complete.  Does this mean that we should expect a release in three more years?  Hand Money Right
Logged
JobLeonard
Level 10
*****



View Profile
« Reply #233 on: March 19, 2023, 10:46:56 PM »

Wow, seven years?! Congrats! Coffee
Logged
Alain
Level 10
*****



View Profile WWW
« Reply #234 on: March 20, 2023, 10:51:21 PM »

Nice catch LiquidAsh Smiley Congratulations from me as well!
Logged

a-k-
Level 2
**


View Profile
« Reply #235 on: March 22, 2023, 11:17:22 AM »

I was just checking in on this project and notices that this is the 7 year birthday from the first devlog here!  Beer!

I also see that the game is marked as 70% complete.  Does this mean that we should expect a release in three more years?  Hand Money Right

Wow, seven years?! Congrats! Coffee

Nice catch LiquidAsh Smiley Congratulations from me as well!

Thank you all!

LiquidAsh, that's a tough question! I can add a new language to the game in a few hours (if it's a simple one), but feeling the need to release it and then determining what I'm willing to do as part of such a release can certainly take three years. But you know, if you didn't ask it might take longer!

Anyway, I'll update the first post and the site on itch.io to make it clearer that the PC versions are already available. And by the way, it appears that I started this devlog with 60% completion and changed to 70% after just one year...
Logged

a-k-
Level 2
**


View Profile
« Reply #236 on: April 01, 2023, 04:27:30 AM »

LiquidAsh's question reminded me that the minigame lacked a decent win screen. Better late than never...


(work in progress)
Logged

a-k-
Level 2
**


View Profile
« Reply #237 on: April 02, 2023, 10:25:12 AM »

Comparing the behavior of "break" and "continue" inside labeled blocks in three modern languages:
   
Code: (Zig)
outer: while (true) {
  inner: {
    ... break;     // breaks outer
    ... continue;  // continues outer
  }
  ...
}
Code: (Rust)
loop {
  'inner: {
    ... break;     // error
    ... continue;  // error
  }
  ...
}
Code: (Nim)
block outer:
  while true:
    block inner:
      ... break     # breaks inner
      ... continue  # continues outer
    ...

Is this what happens when you don't want to add "goto" to a language?
Logged

JobLeonard
Level 10
*****



View Profile
« Reply #238 on: April 02, 2023, 11:22:42 PM »

 Shrug

I'm more curious about whether there is a labeled break or not
Logged
a-k-
Level 2
**


View Profile
« Reply #239 on: April 04, 2023, 08:16:05 AM »

Shrug

I'm more curious about whether there is a labeled break or not
Are you asking about Rust? Yes, it supports unlabeled break, but not inside labeled blocks (and the same holds for continue.)

Edit: oh I misread your question; all three languages support labeled break, which gives you the ability to perform "structured" gotos. I'll provide an example in the next post, but you can see it also in the WASM translation at the top of this page.
« Last Edit: April 04, 2023, 08:33:21 AM by a-k- » Logged

Pages: 1 ... 10 11 [12] 13 14
Print
Jump to:  

Theme orange-lt created by panic