Porting a raylib example to GNU Algol 68

Mohammad-Reza Nabipoor mnabipoor@gnu.org
Wed Jun 3 22:37:29 GMT 2026


Hello.

I was playing with raylib library (which is a simple and easy-to-use library
for graphics programming (video games, GUI, etc.)).
It's a simple nice library written in C, and I decided to port one of its
examples to GNU Algol 68 to make the learning experience more fun!

I chose this example (just randomly):

  https://www.raylib.com/examples/shapes/loader.html?name=shapes_lines_bezier

You can find the functional demo and the C code there.

To build the port, you have to install raylib library. 
Either from your distro (https://repology.org/project/raylib/versions),
or by building from source (https://github.com/raysan5/raylib/wiki/Working-on-GNU-Linux).

I built it like this:

```sh
git clone https://github.com/raysan5/raylib.git
cd raylib
mkdir _build && cd _build
cmake -DCMAKE_INSTALL_PREFIX=$HOME/usr ..
make -j && make install
```

The port consists of two files:
  - cstring.c
  - shapes_lines_bezier.a68

One can build the demo like this:

```sh
gcc -ggdb3 -c cstring.c
ga68 -ggdb3 -o shapes_lines_bezier shapes_lines_bezier.a68 \
     -L$HOME/usr/lib -lraylib -lX11 -lm cstring.o
```

The `cstring.c' is the to convert GNU Algol 68 strings to C strings:

```c
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

uintptr_t
cstring_alloc (uint32_t *codepoints, size_t len, size_t stride)
{
  char *buf;
  int buflen;

  if (len == 0)
    return (uintptr_t)strdup ("");

  assert (stride == 4);

  buf = malloc (len);
  assert (buf != NULL); // FIXME Use proper err handling.

  buflen = 0;
  for (size_t i = 0; i < len; ++i)
    {
      assert ((codepoints[i] & ~0x7f) == 0); // Just ASCII.
      buf[buflen++] = (uint8_t)codepoints[i];
    }
  buf[buflen] = '\0';

  return (uintptr_t)buf;
}

void
cstring_free (uintptr_t p)
{
  free ((void *)p);
}
```

And the port to GNU Algol 68:

```ga68
{ gcc -ggdb3 -c cstring.c }
{ ga68 -ggdb3 -o shapes_lines_bezier{,.a68} -L$HOME/usr/lib -lraylib -lX11 -lm cstring.o }

{******************************************************************************
 *
 *   raylib [shapes] example - lines bezier ported to GNU Algol 68
 *
 *   Example complexity rating: [★☆☆☆] 1/4
 *
 *   Example originally created with raylib 1.7, last time updated with
 *raylib 1.7
 *
 *   Example licensed under an unmodified zlib/libpng license, which is an
 *OSI-certified, BSD-like license that allows static linking with closed source
 *software
 *
 *   Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
 *   Copyright (c) 2026 Mohammad-Reza Nabipoor
 *
 ******************************************************************************}
(
  { Defined in cstring.c }
  proc(string)long bits cstring_alloc = nest C "cstring_alloc";
  proc(long bits)void cstring_free = nest C "cstring_free";

  { raylib }
  mode Vector2 = struct(real x, y);
  mode Color = struct (short short int r, g, b, a);
  bits k_flag_msaa_4x_hint = 16r00000020;
  int k_mouse_button_left = 0;
  Color k_raywhite = (SHORTEN SHORTEN -11 {245},
                      SHORTEN SHORTEN -11 {245},
                      SHORTEN SHORTEN -11 {245},
                      SHORTEN SHORTEN -1 {255}),
        k_gray = (SHORTEN SHORTEN -126 {130},
                  SHORTEN SHORTEN -126 {130},
                  SHORTEN SHORTEN -126 {130},
                  SHORTEN SHORTEN -1 {255}),
        k_blue = (SHORTEN SHORTEN 0,
                  SHORTEN SHORTEN 121,
                  SHORTEN SHORTEN -15 {241},
                  SHORTEN SHORTEN -1 {255}),
        k_red = (SHORTEN SHORTEN -26 {230},
                 SHORTEN SHORTEN 41,
                 SHORTEN SHORTEN 55,
                 SHORTEN SHORTEN -1 {255});
  proc(bits)void set_config_flags = nest C "SetConfigFlags";
  proc(int{width},int{height},long bits)void init_window = nest C "InitWindow";
  proc(int)void set_target_fps = nest C "SetTargetFPS";
  proc Vector2 get_mouse_position = nest C "GetMousePosition";
  proc(Vector2{point},Vector2{center},real{radius})bool
    check_collision_point_circle = nest C "CheckCollisionPointCircle";
  proc(int{button})bool is_mouse_button_down     = nest C "IsMouseButtonDown",
                        is_mouse_button_released = nest C "IsMouseButtonReleased";
  proc void begin_drawing = nest C "BeginDrawing",
            end_drawing   = nest C "EndDrawing",
            close_window  = nest C "CloseWindow";
  proc bool window_should_close = nest C "WindowShouldClose";
  proc(Color)void clear_background = nest C "ClearBackground";
  proc(Vector2{start_pos},Vector2{end_pos},real{thick},Color{color})void
    draw_line_bezier = nest C "DrawLineBezier";
  proc(Vector2{center},real{radius},Color{color})void draw_circle_v
    = nest C "DrawCircleV";
  proc(long bits{text},int{posX},int{posY},int{fontSize},Color{color})void
    draw_text = nest C "DrawText";

  int screen_width = 800, screen_height = 450;
  long bits window_title = cstring_alloc("raylib [shapes] example - lines bezier");
  long bits text_explanation = cstring_alloc("MOVE START-END POINTS WITH MOUSE");

  set_config_flags(k_flag_msaa_4x_hint);
  init_window(screen_width, screen_height, window_title);

  Vector2 start_point := (30, 30), endpoint := (screen_width - 30, screen_height - 30);
  bool move_start_point := false;
  bool moveendpoint := false;

  set_target_fps(60);

  while NOT window_should_close
  do
    Vector2 mouse = get_mouse_position;

    if (check_collision_point_circle (mouse, start_point, 10)
        | is_mouse_button_down (k_mouse_button_left))
    then
      move_start_point := true
    elif (check_collision_point_circle (mouse, end_point, 10)
          | is_mouse_button_down (k_mouse_button_left))
    then
      move_end_point := true
    fi;

    if move_start_point then
      start_point := mouse;
      (is_mouse_button_released (k_mouse_button_left) | move_start_point := false)
    fi;

    if move_end_point then
      end_point := mouse;
      (is_mouse_button_released (k_mouse_button_left) | move_end_point := false)
    fi;

    begin_drawing;
    (
      clear_background(k_raywhite);
      draw_text(text_explanation, 15, 20, 20, k_gray);

      { Draw line Cubic Bezier, in-out interpolation (easing), no control
        points.  }
      draw_line_bezier(start_point, end_point, 4, k_blue);

      { Draw start-end spline circles with some details.  }
      draw_circle_v(start_point,
                    (check_collision_point_circle(mouse, start_point, 10) | 14 | 8),
                    (move_start_point | k_red | k_blue));
      drawcirclev(endpoint,
                  (checkcollisionpointcircle(mouse, endpoint, 10) | 14 | 8),
                  (moveendpoint | k_red | k_blue))
    );
    end_drawing
  od;

  close_window;

  cstring_free(text_explanation);
  cstring_free(window_title)
)
```


If you have any comments, ideas or code improvements, feel free to reply :)

Happy Algoling,
Mohammad-Reza


More information about the Algol68 mailing list