GitHub - benmayersohn slotenium Play and collect statistics on demo versions of slot machine games

Saved searches

Use saved searches to filter your results more quickly

Cancel Saved Search Register Unfocused

You entered the system in another tab or window. Reload to refresh your session. You exited the system in another tab or window. Reload to refresh your session. You switched your account to another tab or window. Reload to refresh your session.

Play a demo version of a slot machine using Selenium and collect statistics.

Notifications You need permission to change notification settings.

benmayersohn/slotenium

This community does not belong to one branch in this repository, but may belong to an end outside the repository.

To File

Folders and files

Message about last modification Last modification date

Latest commit

History

View all files

Repository files navigation

Slotenium

  • Currently works with online slots from International Game Technology (IGT) and Aristocrat. IGT games from official servers and Aristocrat games from supermegaslot. com. SupermegasLot is known for posting pirate games where the RTP values ​​may be altered, making it an interesting place to try out slotium!
  • You cannot use this application to play real money games.
  • If you use this application frequently, your IP address may be blocked on the site that offers the games. Therefore, we recommend using a VPN.

How it Works

When you press the spin button in a gambling game, your browser binds to a server, which starts a random number generator (GSC) to calculate the result. This result is sent back to your browser and displayed on the drum. The National Medical University works on the server side, so we don't have access to it, but we can try to restore the probabilistic distribution of the recoil after they run the simulation many times.

Currently, most of these games are made in HTML5, which is very convenient for browser automation tools like Selenium. You can download one of these games and use Selenium to determine the spin button, bet field, profit, and balance. The IGTSLOTSESSION and ARISTOCRATESESSION classes use Selenium to drive the drum and get information about the results of the RELAN field. When the session ends, the results are saved in a CSV file. Whether you play an IGT or an aristocrat game, the results are saved in the same format and can be analyzed using the same code. In this repository, we include an analysis of one example of IGT (siberian_storm_analysis. py).

Installation

To determine slotenium requirements, use

Pip instal l-r requirements.

We recommend creating a virtual environment so that the required versions of each package are installed without conflicts.

Directory Structure

Here is the breakdown of the files in this repository:

Slotenium | ____ Assets | ____ rtp_dist. png # Probability distribution RTP | ____ RTP_EVOL. PNG # EVOLUTION RTP with the number of simulations | ____ igt. py # Code to set up the game session IGT | ____ Aristocrat. PY # Code to set up the game session Aristocrat | ____ Requirements. txt # Libraries needed to run the whole code in this directory | ____ Results | ____ Siberian_storm # Directory with simulation results | ____ Readme. MD # This | _siberian_storm_analysis. py # Builds the schema for the simulation results and count statistics Siberian Storm | ____ Play_igt. py # IG T-simulations (standard Siberian Storm) | 50 dragons) | ____ helpers . py # Helper functions to start the simulations and analysis. 

Games

It contains several games from both companies and functions to build the corresponding URLs. All games can be fully automated (this means that the endless games do not require user intervention, even during the bonus round).

You can find other games compatible with slotenium with this Google search. Keep in mind that some of them require user intervention during the bonus round or to communicate some initial instructions, and will disconnect if not maintained.

Example: Siberian Storm

IGT's Siberian Storm is a tiger- and cat-themed slot machine with five drums and 720 lines. The slot machine's color scheme is white, which corresponds to the Siberian tiger and the snowy regions where it lives. The symbols used in the game include the mighty Siberian tiger, orange tiger, golden tiger claws, tiger eyes, emerald ring, and the Siberian Storm logo.

The game features a wild symbol with a white tiger motif, as well as spread symbols that activate bonus features. Siberian Storm is a slot that belongs to the Fire Horse-slot family and has a very high payout percentage of about 96%.

This means that the payout percentage is about 96%. We would like to confirm this in our simulator.

Using the IgtSslotsison tool, we recorded 11718 Siberian Storm spins. This is not enough to represent the full distribution of recoils and would require infinite spins. However, according to the law of large numbers, the average RTP value should converge to the actual expected value.

Below I have constructed a spread of odds to return to groups that represent the spectrum of multiple bets.

The odds are 63, 6%. This is comparable to the 20-line slot Cleopatra (also IGT), which lost in 64, 2% of cases over 10 million simulations (thanks to Casino Guru for the analysis!).

Average RTP

We can calculate the sample average RTP for each game. Recall that before Siberian Storm I was within 96% of the time. I was 96%, 64% (see siberian_storm_analysis. py)! Below you can see how the average RTP changes with the number of wins.

Volatility

Two games with similar average RTPs can have quite different odds distributions. One way to reflect these differences is to decompose the average RTP in function of two characteristics: average RTP by win (RTPW) and odds of winning. In low volatility games, the big authority includes the winning probability, in high volatility games, the big authority includes the RTPW.

In Siberian Storm, the average RTPW is about 2, 66 times the bet. We arrived at this indicator by dividing the average importance of the RTP to the winning probability (0, 364) in the form of a fraction (0. 9664). This is a game with average volatility, which basically applies to 20-line Cleopatra. If we compare this to 1-line Cleopatra, its RTP is 95, 02%, but the winning probability is 11, 3%. This corresponds to a bet of 8, 4 times the RTPW, a fairly volatile game.

The RTPW is a desirable indicator, but it is incomplete, since it does not outline the full shape of the odds spread. Another measure of volatility (and more common) is considered the variance of profitability, or the mean squared research deviation from the mean significance. If you take the square root of the variance and divide it by the mean significance of the RTP, you get the option (CV), which (in my opinion) is considered a more necessary measure of volatility.

If you launch Siberian_storm_analysis. py, you will see that the CV of Siberian Storm is 6. 12. If you use Casino Guru's crawling feature, you will find that the CV of 20 linear Cleopatra, like Siberian Storm, is within 5, 58. The CV of 1 linear CV is much higher - 14, 64.

Saved searches

Use saved searches to filter your results more quickly

Cancel Saved Search Register Unfocused

You entered the system in another tab or window. Reload to refresh your session. You exited the system in another tab or window. Reload to refresh your session. You switched your account to another tab or window. Reload to refresh your session.

C ++ DRAGONBOX reference

License

Apache-2. 0, BSL-1. 0 license was found.

Licenses found

Licens e-apache2-VOLVM License-Boost

Notifications You need permission to change notification settings.

jk-jeon/dragonbox

This community does not belong to one branch in this repository, but may belong to an end outside the repository.

To File

Folders and files

Message about last modification Last modification date

Latest commit

History

View all files

Repository files navigation

Dragonbox

This bookbinding provides standard implementation of DragonBox on C ++. DRAGONBOX is a method of reconstructing the row floating based on the excellent Schubfach method developed by Raffaello Julietti from 2017 to 2018. DRAGONBOX is also inspired by Grisu and Grisu-Exact.

Introduction

  1. This includes a bypass guarantee. In other words, faithful parsers interpret the generated output line as the initial input amount with floating point. (Click here for some explanations about this excuse).
  2. In other words, other weekends interpreted as an input amount are unlikely to hold a smaller number of symbols than the DRAGONBOX output.
  3. The output data is rolled up with wander, and the amount generated by the Dragonbox is close to the actual value of the input between output, which could be output with the minimum number.

About the Name "Dragonbox"

The main idea of ​​Schubfach implemented with DragonBox is the constant analog of DoveCote's discrete principle. The title of Schubfach is derived from the German name SchubfachPrinzip of the pigeon principle, and basically means the principle of boxes. Another title of the pigeon principle is the principle of the Chelikle Box, so I respect the origin of "Schubfach" and "Grisu", and the personal method is "Dragon". I decided to call it a box.

How to Use

The DragonBox is specialized in the reconstruction procedure of the linear floating volume, but the actual line generation is not officially regarded as part of the method. DragonBox displays two integrated amounts (decimal numbers/ display), and they may be applied in line generation procedures. Header files Includes/Dragonbox/Dragonbox. h connect everything for this (this is just a header). In particular, the advancement procedure is integrated into a library. For this, it is include/dragonbox/dragonbox_to_chars. H and cpp. Since only three files including ASPIRATION, it is easy to manually set this library, but you can also apply with CMAKE as described later. For those who are not used to Cmake, we recommend a great introductory book.

Installing Dragonbox

The following effect creates an assemblifile for specific platforms in the catalog:

Git Clone https: // gitHub. com/jeon/dragonbox CD dragonbox Mkdir Build CD Build cake ... 

If you only need dragonbox. h and do not need dragonbox_to_chars. h / . cpp, make sure that Dragonbox. h is in the system:

Cmake ... cmake ... -ddragonbox_install_to_chars = uit cmake install. 

If you need to generate a character string, build a file generated using a platfor m-specific build tool (Make, Visual Studio, etc.) and execute the appropriate action.

Install Cmake. 

Is installed in the build directory.

Including Dragonbox into CMake project

The easiest way to associate DRAGONBOX to the CMAKE subscription is to arrange as follows:

Incration(FetchContent) fetchContent_declare (dragonbox git_repository https: // gitHub. Com/jk-jeon/dragonbox) X)Library _ goal_ link(My_goal Dragonbox :: Dragonbox)#Or dragonbox :: dragonbox_to_chars

Or, if you have already installed DragonBox on your system, you can link with support:

Find_package(DragonBox)Library _ goal_ link(My_goal Dragonbox :: Dragonbox)#Or dragonbox :: dragonbox_to_chars

Language Standard

C ++ 11 or higher is required to operate this library. After C ++ 20, all the provided functions are considered a ConsTEXPR.

Usage Examples

(Simple exercise from FLOAT/DOUBLE)

#Incration "DragonBox/Dragonbox_to_chars. H" consTEXPR intBuffa length1 + //Tojkj :: dragonbox :: max_output_string_length;DOUBLEx =1. 234; //It still moves in Float CharredBuffer [Buffer_length];//Zero the buffer and return the pointer to Zero Mark //The line length is equal to (End_pt r-Buffer). //Current bufferingCharred* end_ptr = jkj :: dragonbox :: to_chars (x, buffer);//Returns the limit of the next line without resetting the buffer //Current buffering//You can wrap the buffer like STD :: string_view.END_PTR = jkj :: dragonbox :: to_chars_n (x, buffer);

(JKJ :: Dragonbox :: to_decimal directly implemented)

#Incration "DragonBox/Dragonbox. h" DOUBLEx =1. 234; //It still moves in Float //Here, X must be a finite number that is not 0! //The return value of V is a structure with three members: //Signifier: Modimal numbers (1234 in the given case); //STD :: UINT64_T for DOUBLE, STD :: UINT32_T for Float. //Exponent: Printing index (if specifie d-3); Include in image //IS_NEGATIVE: Includes Bool images according to the title autov = jkj :: dragonbox :: to_decimal (x);

By default, jkj :: dragonbox :: to_decimal returns a structure with three members (valid numbers, index, is_negative). However, if you show the characteristics of a politician, it is highly likely that the image will be returned. See below.

Principles JKJ :: Dragonbox :: to_decimal Specializes to operate only with the latest no n-equivalent input data. The operation when INFINITY/nan's/+0/-0 is applied is undefined. Jkj :: dragonbox :: to_chars and jkj :: dragonbox :: to_chars_n work completely for any input.

To people wanting to port the algorithm

If you want to transfer this method to another language or want to realize it from a Nuremarker, we recommend that you first see more plain implementation instead of presenter. More ordinary implementation owns a certain amount of minimum elasticity and minimum performance, which is much more normal, which makes it easier to take.

Policies

Dragonbox has determined the number of diplomats that users can choose. In most cases, politicians are sufficient, but some settings may require this option probability. In rea l-time, there are five types of diplomats that can be set: Symbol politicians, zero markers slide, politicians who have decimal fractions (syntax analysis), decimal fractions in decimal numbers. A rounded politician (format), a cash politician. These politicians exist in place of the name of JKJ :: Dragonbox :: Policy. Politicians can indicate jkj :: dragonbox :: to_decimal or jkj :: dragonbox :: to_chars or jkj :: dragonbox :: to_chars_n as additional attributes. The following is an application model:

#Incration "DragonBox/Dragonbox. h" autov = jkj :: dragonbox :: to_decimal (x, jkj :: dragonbox :: sign :: ganore, jkj :: dragonbox :: Policy :: CACHE :: Compact)

In this case, a politician who ignores the symbol and a small cash politician are shown. Returned does not have an IS_NEGATIVE member, but JKJ :: Dragonbox :: to_decimal applies terrible cache instead of absolute cache for calculation. Regarding the functions, politicians are not specific; you can witness them in any order. If it is not clearly displayed, politicians will be selected by default. For example, in the above example, Close_k_chok, a politician with a system that allows the fractions of the decimal to binary, and defaults, is a policy of rounding decimal fractions into binary numbers. If you display the first diplomat in two or more in similarity, or make a mistake in the parameters of politicians, the calculation will be difficult.

Politicians' attributes (for example, in the above, jkj :: dragonbox :: policy :: sign :: imnore) has different types, and as a result, all kinds of diplomats are usually different in template. It leads to an instance, even the possibility of blasting binary files. (However, the meaning is only the combination, and if one is set, the composition of the function is not displayed in another binary file in principle).

Sign policy

JKJ decides whether to extract and give the input parameter signal with :: dragonbox :: to_decimal.

  • JKJ :: Dragonbox :: Policy :: Sign :: Ignore: There is no IS_NEGATIVE member in the returned structure, and the input parameter signal is not returned. Performance procedures have the ability to overcome the symbols in each case, and as a result, this member is often not needed. In this case, refusal to the IS_NEGATIVE member may reduce costs. JKJ :: Dragonbox :: to_chars and jkj :: dragonbox :: to_chars_n is used to this politician morally. When implementing jkj :: dragonbox :: to_decimal, the input data signal only has the meaning of determining the rounded interval of a specific political value in the round mode. Signals are completely ignored in default rounded mode politicians.
  • JKJ :: Dragonbox :: Policy :: Sign :: Return_sign: This is a default political value. The input signal is included in the returned structure is_negative member.

JKJ :: Dragonbox :: to_chars / jkj :: dragonbox :: to_chars_n cannot be displayed.

Trailing zero policy

He has decided that jkj :: dragonbox :: to_decimal will be created with zero decimal points.

  • JKJ :: Dragonbox :: Policy :: Trailing_zero :: Ignore: Ignore: Ignore: The output symbol has a function to hold zero end of the line. The removal of the sliding zero mark is a relatively slow operation, including a large number of divisions, and it is necessary to output division each time, so JKJ :: DragonBox :: to_decimal A sliding zero from to_decimal. It is possible to achieve the highest joint performance by removing mark removal and guaranteeing this in other space.
  • JKJ :: Dragonbox :: Policy :: Trailing_zero :: Removal: This is a default policy. Delete all zero at the end. JKJ :: Dragonbox :: to_chars and jkj :: dragonbox :: to_chars_n IEEE-754 BINARY32 (also known as Float) uses this policy.
  • JKJ :: Dragonbox :: Policy :: Trailing_Zero :: Report: The output symbolic has the ability to hold sliding zeros, but such ability is reported in an additional member of the returned structure may_have_trailing_zeros, which is installed to true if there is a possibility of sliding zeros and to false if no sliding zeros can be placed. According to the principle of operation, this method is guaranteed, indeed, that trailing zeros may be present, and the maximum number of trailing zeros is exactly 7 for binary System32 and 15 for binary System64.

JKJ :: Dragonbox :: To_chars / jkj :: Dragonbox :: To_chars_n cannot display politicians with trailing zeros.

Decimal-to-binary rounding policy

Dragonbox guarantees diversion. This means that if you convert the output of Dragonbox to IEEE-754 binary format with floating point, the result must be equal to the initial input of Dragonbox. However, reorganizing Dragonbox's decimal output back to binary with floating point gets confused by the need for rounding. As a result, to guarantee the detour guarantee, Dragonbox needs to imagine the rounded image being output. Revolutionarily, it reorganizes decimal to binary.

  • JKJ :: Dragonbox :: Policy :: decimal_to_binary_rounding :: Nearest_to_even: This is the politician by default. Nearest rounding mode is used.
  • JKJ :: Dragonbox :: Policy :: decimal_to_binary_rounding :: Nearest_to_odd: Turn ties into ties, apply beloved rounding mode.
  • JKJ :: Dragonbox :: Policy :: decimal_to_binary_rounding :: Nearest_to_plus_infinity: Apply lover rounding mode, ties to plus infinity.
  • JKJ :: Dragonbox :: Policy :: decimal_to_binary_runDing :: Nearest_toward_Minus_Infinity: Apply lovers rounding mode, tie-toward-minus-infinity.
  • JKJ :: Dragonbox :: Policies :: decimal_to_binary_rounding :: Nearest_toward_Zero: The rounding mode is tie-toward-Zero. This gives the freshest code of all the rounding modes for a near-a loved one.
  • JKJ :: Dragonbox :: Policy :: decimal_to_binary_rounding :: Nearest_away_from_Zero: Apply lovers rounding away from zero.
  • JKJ :: Dragonbox :: Policy :: decimal_to_binary_rounding :: nearest_to_even_static_boundary: The rounding regime is close, but these are absolutely autonomous paths for even and odd entries. This gives good binary codes, but may work faster for the environment than JKJ :: Dragonbox :: policy :: decimal_to_binary_rounding :: nearest_to_even.
  • JKJ :: Dragonbox :: Policy :: Decimal_biny_ROUNDING :: Naest_TODD_STATIC_BOUNDARY: I have it. This creates a larger binary number, but depending on the situation, it is faster than JKJ :: Dragonbox :: Policy :: Decimal_to_biny_rounding :: Neato_odd.
  • JKJ :: DragonBox :: Decimal_binary_Rounding :: NEEST_TOWARD_PLUS_STATIC_BOUNDARY: The closest round mode We use, but have a completely independent code path for positive and negative input. As a result, the binary number will increase, but depending on the situation, it will be faster than JKJ :: Dragonbox :: Policy :: Decimal_to_biny_rounding :: Neatoward_Plus_infinity.
  • JKJ :: DragonBox :: Decimal_binary_rounding :: NEEST_TOWARD_MINUS_STATIC_BOUNDARY: The closest round mode We use, but have a completely independent code path for positive and negative input. This gives a larger binary result, but depending on the situation, it is faster than jkj :: dragonbox :: policy :: decimal_biny_biny_rounding :: naest_toward_minus_infinity.
  • JKJ :: Dragonbox :: Policy :: Decimal_to_biny_rounding :: TOWARD_PLUS_INFINITY: Plus Infinity round mode.
  • JKJ :: Dragonbox :: Policy :: Decimal_to_biny_Rounding :: Toward_minus_infinity: Use a mode that rounds negative infinity.
  • JKJ :: Dragonbox :: Policy :: Decimal_to_biny_Rounding :: Toward_zero: Use a round mode in the zero direction.
  • JKJ :: Dragonbox :: Policy :: Decimal_to_biny_rounding :: Away_from_zero: Use a round mode from zero.

All of these policies can also be specified in jkj :: dragonbox :: to_chars / jkj :: dragonbox :: to_chars_n.

Binary-to-decimal rounding policy

JKJ :: Dragonbox :: to_decimal determines the operation in the event of a rounding error when receiving decimal. If the specified BCD round policy is not one of the ROUND TO NEAREST policy, this policy is completely ignored (because other policies simply have Round to Nearest).

  • jkj :: dragonbox :: policy :: binary_to_decimal_rounding :: do_not_care As a result, the code is faster, but the difference in performance is smaller.
  • JKJ :: Dragonbox :: Policy :: binary_to_decimal_rounding :: to_even: This is a default policy. If a round error occurs, select an even number.
  • Jkj :: dragonbox :: policy :: binary_to_decimal_rounding :: to_odd: Select an odd number for rounding.
  • Jkj :: dragonbox :: Policy :: binary_to_decimal_rounding :: away_from_zero: Select a large number of absolute values ​​when rounded.
  • Jkj :: dragonbox :: Policy :: binary_to_decimal_rounding :: ROWS_ZERO: Select a numerical value that is less than 0 when rounded.

All of these policies can also be specified in jkj :: dragonbox :: to_chars / jkj :: dragonbox :: to_chars_n.

Cache policy

Select whether to cache or compress the full table. Using a compressed cache will reduce the code about 20%slower, but can significantly reduce the required amount of data. At present, it has no effect on binary32 (float) input. JKJ :: Dragonbox :: for FULL, JKJ :: Dragonbox :: to_decimal uses a static data table of 619*16 = 9904 For compact Is 23*16 + 27*8 = 584 bytes.

  • JKJ :: DragonBox :: Policy :: Cash :: Full :: This is a default policy: Full :: This is a default policy. Use a full table.
  • JKJ :: DragonBox :: Policy :: Cash ::: Use the compression table.

All of these policies can also be specified in jkj :: dragonbox :: to_chars / jkj :: dragonbox :: to_chars_n.

Performance

In my car (Intel Core i7-7700HQ 2. 80GHz, Windows 10), it is at the same level to beat other latest algorithms, including Grisu-Xact, Ryu, and Schubfach.

The following benchmark results (implemented on March 30, 2024) were obtained using Milo's DTOA benchmark FREIM (https: // github. Com/miloyip/dtoa-benchmark). The following source code is that this benchmark is available here.

Note 1: DRAGONBO X-DRAGONBOX performance using a full cash table, DRAGONBOX_COM P-DRAGONBOX performance using a cash compact table.

Note 2: FMT uses a dragonbox internally and is almost the same as the one in this repository.

There is also a benchmark I created (this is also executed on 2024/03/30):

(The average value is the average value, the dotted line is a median, the diagonal line is 30 %, 50 %, 70 %):):

Another performance chart using floatin g-point data (top) or doubl e-point data (bottom) generated randomly:

(Note: the equation with e. g. Schubfach is not absolutely inelegant, since the implementation I related uses the ability to generate numbers with a different set of constraints. A more correct comparison can be found in this repository).

Comprehensive Explanation of the Algorithm

Read this document.

How to Run Tests, Benchmark, and Others

This repository has 4 subsections:

  1. Ordinary: Subprojects on which other subprojects depend.
  2. Benchmark: Hitting the ideal.
  3. TEST: Starting the research.
  4. Meta: Generating static data used in the main book.

Build each subproject independently

All subprojects covering tests and benchmarks are considered independent. For example, to start the research, you can arrange the appropriate one:

Git Clone https://github. com/jk-weon/dragonbox CD Dragonbox mkdi r-p build/subproject/test cd build/subproject/test cmake ../../../../../../../Subprojet/stet cmake buld. Ctest. 

(There is an option to transfer configuration options to CMAKE and CTEST if you use a generator with different configurations, like VisualStudio).

Build all subprojects from the root directory

It is also possible to compile all subsections from the root catalog by forwarding th e-ddragonbox_enable_subproject = option.

Git Clone https://github. com/jk-weon/dragonbox CD Dragonbox Mkdir Build CD Build Cmake ... -ddragonbox_enable_subPrect = on cmake build. 

Notes on working directory

Some executables insist on installing the correct working catalog. For example, the Benchmark executable launches some MATLAB scripts provided in the subproject/benchmark/matlab catalog, but they will not run unless proletarian is installed in subproject/benchmark. When creating a Visual Studi o-conclusion using a cmakelists. txt file, the debugger' s-catalogue proletarian is mechanically specified in the c o-filing directory. For example, for benchmar k-su b-project, the proletarian catalog is specified in sub-project/benchmark. However, other cmak e-generators do not provide any opportunity to introduce the debugge r-catalog proletaria, so in this case you will need to manually enter the required proletaria catalog at launch to make the executable work correctly.

Notes

Correctness of the algorithm

In this paper, I mathematically prove the correctness of the algorithms using the test and metacatalogue test programs. In addition, I performed a sufficient number of uniform random number tests against RYU (which is itself very strongly tested), and a joint test of a procedure that converts binary numbers to decimal numbers with floating point and Dragonbox, and confirmed the correct bypass for all possible numbers with floating point. Therefore, I am confident of the correctness of both algorithms.

Precise meaning of roundtrip guarantee

The exact meaning of the bypass guarantee can be difficult, since it depends on the notion of a "correct parser". For example, if the signifier and exposition are Dragonboxes and are outputs for an input number with a floating point X, such as double, then something like X==Sitrifice * pow(10. 0, expositions) may or may not be correct, since each operation with a floating point in the signifier expression * pow(10. 0, expositions) introduces rounding errors that can accumulate to large errors. What a correct parser should do is to correctly compute a floating-point number from this expression according to the proposed rounding rules, and the result should be "correctly rounded" in the sense that it allows only the smallest possible rounding error. Implementing a correct parser is a very non-trivial task, so if you want to check this rounding guarantee yourself, you may need additional libraries (such as RYU or double conversion).

License

The entire code, other than references to third-party libraries (code from subproject/3rdparty), is under one of the following licenses:

  • Apache License version 2. 0 with LLVM exceptions (License-Apache2-Llvm or https://llvm. org/foundation/releucensing/license. txt) or) or)
  • Boost version 1. 0 License (license-boost or https://www. boost. org/license_1_0. txt).

avatar-logo

Elim Rim - Journalist, creative writer

Last modified 14.04.2025

Play for real with EXCLUSIVE BONUSES
Play
enaccepted