Skip to content

Instantly share code, notes, and snippets.

@tpmccallum
Last active February 22, 2020 02:02
Show Gist options
  • Select an option

  • Save tpmccallum/13e3d30e713a1a66e83d245d12d3fbc7 to your computer and use it in GitHub Desktop.

Select an option

Save tpmccallum/13e3d30e713a1a66e83d245d12d3fbc7 to your computer and use it in GitHub Desktop.
An idea that allows a simple computer game's state to be stored in one variable only

Idea

In the context of a computer game (where each player or the game board etc. holds a "state") rather than having an array of variables or storing small[ish] values (like 0 or 1 or 2 etc) in separate variables (like u32) we could treat one variable as many by turning that single variable into a multi-slot representation through the use of modulo arithmetic and exponentiation.

Question

Hand writing memory in WebAssembly is possible. But if we are only writing in Rust and treating Wasm as a compilation target could the following idea be implemented as a design pattern for higher level programming i.e. Rust? Or, is the compiler so smart that this idea is redundant (after all of the wonderful optimisations and magic that compilers perform)?

Example

The u32 variable in Rust can hold a value within the range of 0 to 2147483648. We essentially have access to 10 separate slots. If we initialise the variable with 1000000000 (first digit set to 1) then any of the remaining 9 slots can each hold a separate value of 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9.

Slot [10| 9| 8| 7| 6| 5| 4| 3| 2| 1]
Value[ 1| 0| 0| 0| 0| 0| 0| 0| 0| 0]

How to access each slot - psuedo code

The following psuedo code allows us to access each of the individual slots of the _value, by specifying the slot's _position and the _size of the slot.

((_value % (10 ** _position)) - (_value % (10 ** (_position - _size)))) / (10 ** (_position - _size));

In this example, lets just make the size of the slot 1. For example let's just access any one of the 9 individual slots as a single digit. For example, in order to do this we can go ahead and rewrite this psuedo code with _size statically set to 1.

((_value % (10 ** _position)) - (_value % (10 ** (_position - 1)))) / (10 ** (_position - 1));

How - in practice using Rust

The following code demonstrates how we can access each of the 9 slots.

Please note:

  • _value is set to 1987654321 for this example
  • _size is set to 1 for this example
  • _position indicates which Slot we are accessing
Slot number we are accessing [10| 9| 8| 7| 6| 5| 4| 3| 2| 1]
Value stored in that slot    [ 1| 9| 8| 7| 6| 5| 4| 3| 2| 1]

Accessing a single value

(_value % (10_u32.pow(_position)) - (_value % (10_u32.pow(_position - _size)))) / 10_u32.pow(_position - _size)

If _position is 1, this code returns 1 If _position is 2, this code returns 2 etc.

Flushing a single value to zero

It is super easy to flush a value back to 0. For example we can set slot 1 to 0 like this. Where _position is 1

_value = _value - ((_value % (10_u32.pow(_position))) - (_value % (10_u32.pow(_position - _size))));

Returns a new state of 1987654320

Inserting a single value between 0 and 9

After we have zero'd out a slot, it is also super easy to explicitly insert/update one of the slots with a new single digit. For example, where _single_value is 9 and _position is 1.

_value + _single_value * (10_u32.pow(_position - 1));

Returns a new state of 1987654329

Caveats

There needs to be some static code that can validate _position, _value and the overall state, for safety. This code would be trivial and would/could ship as part of Wasm binary executable with fixed static values.

Conclusion

It is hoped that there is a sufficient trade-off between the computation required to perform the arithmetic and the amount of memory that would be saved. There may be other applications for this, other than remote multiplayer games or where perhaps game state has to be sent across the network quickly etc.

I would really appreciate feedback in relation to how this would compile in terms of WebAssebly memory and whether this idea could become a design pattern for building memory efficient applications where the final code is a compilation target. For example, is this useful in WebAssembly where (whilst you can write wat) there is a strong chance that a higher level language like Rust will create the wat, wasm automatically (in this case we have less control over memory and so hopefully this design pattern will be a cool trick in our toolboxes).

Please comment

Please leave a comment below if you have any suggestions or ideas on how this could be of benefit to something you are working on. I am very happy to perform more research, development and testing if this will be of use to you. For example can a Wasm executable of the logic in this idea be stored on CDN as accessed like a library/service. With only the game state needing to be stored locally? Open to all ideas.

Thanks for reading :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment