This game is for training mental conversion of various number formats to binary. The first screenshot shows the fairly easy default level. The second one shows all kinds of tasks, as you get them in the hardest level. (And how I've fallen back behind my high score, through errors :-) Most people will want to play somewhere in between, with hex stuff, but without decimal or Ascii.

All screenshots show the same game. All but the first are running in a terminal with a quick and dirty Gimp job as background, to hide the lines. This illusion gives a real graphics feeling. The third one is a two player (-m2) game.

These screenshots show narrow two player games with a different background. In the first case (-m3) each player has access to only three of the tasks in the middle column. In the second case (-m6) the tasks are shared, and both players can play at most four bits, and score at most seven bits. The winner of such a task also takes the bits the adversary got right.

It's already quite fascinating to play. But in fact this is only a primitive non-graphical, non-curses prototype of the game idea. It only works in vt100 like terminals because of the key and bold codes. The stty call works for GNU/Linux but may have to be adjusted elsewhere.

There are no timers yet, for automatic shooting of bits after prolonged inactivity, nor expiration of bytes that have not been touched for too long, nor animation or mouse/joystick support.

Many thanks to SourceForge for hosting this project at <http://sourceforge.net/projects/okopo/>!

You have a bit gun that you can move up and down in the middle column. It can shoot the displayed bit, which appears randomly, to the left or the right into the caves. You can even shoot it in both directions at once. In each cave there sits a task for you. The task is a byte which you have to constitute bit by bit. On the left you start with the high bits, on the right with the low bits.

It can pay to plan ahead a little. You may wind up with every task needing the same bit, but you have a 50% chance of getting the other one. Even if you toggle, you may get the same one again next time. So try to always have open positions for both bits.

You use the arrow keys (only works on an Ansi/VT100 like terminal) to move up and down, and to shoot left and right. The space keys shoots left and right at once. The return key allows you to toggle the current bit, if you have enough toggles left.

In a two player game, the right player uses the numeric keypad. The arrow keys work likewise. The key in the middle, '5' shoots left and right at once. The enter key allows you to toggle the current bit, if you have enough toggles left.

Each bit has a value depending on the difficulty of the byte representation. These are one for binary, three for octal literals or octal coded characters, four for binary coded decimal, six for hexadecimal or hex coded characters, seven for color codes, eight for octal bit ops, nine for hex bit ops, ten for decimal, eleven for signed decimal, twelve for time and 15 for Ascii characters.

If you get a byte right, you get that many points per bit, e.g. 80 for a correctly converted decimal constant. If you get a bit wrong, you get that many points taken away per missing bit, say 9 less for an octal byte which already had 5 correct bits.

For every bit you shoot left and right at once, you increase the value of both tasks by 5%. If you thus get the left and right bytes right simultaneously, you double your score for that strike.

Each time you get a bytefull (256) of points you very gradually add weight to your scores, so that you begin to get more than this.

Once in a while you will fall back to small scores with a letter. These letters come from the SI system, where they mean k (kilo) for thousand, M (Mega) for Million and so forth. Since this is fundamentally decimal, and decimal doesn't fit too well with computers, these have been bent a little. But, as the growth is exponential, a little bend at the bottom means a lot of divergence at the top:

1k (kilo) 1024 1M (Mega) 1048576 1G (Giga) 1073741824 1T (Tera) 1099511627776 1P (Peta) 1125899906842624 needs 64bit Perl or Math::BigInt 1E (Exa) 1152921504606846976

usage: okopo [-m*mode*] [*level* [*2nd-player-level*]]

A *mode* argument of 2 or higher or the presence of a 2nd level starts up a
two player game. If the *mode* argument is 3 or more, it is a narrower 3
column game. With 3 one player has three middle tasks at the top, the other
at the bottom. With 4 and 5 the middle tasks are positioned alternatingly.
With 4 player one has one more, with 5 player two does.

With modes 5 and 6 it's the same as with 4 and 5, but both players compete to get the middle tasks. Both only need to solve their half of the byte, and the first to finish it wins the whole task. This challenges the player with the lower level to solve some harder tasks.

This game has ever harder levels that present you with more and more harder tasks. Level defaults to 2. There is always a variant that only reduces the frequency of the simpler tasks and adds a new one. The other variant, obtained with a negative level, gives only the next harder task, i.e. -3 for only hex. You do not change levels dynamically.

0 Binary (this one is for practice, really)

1 Octal

2 Binary Coded Decimal

3 Hexadecimal

4 Computer Colors

5 Octal Bit Ops

6 Hexadecimal Bit Ops

7 Decimal

8 Signed Decimal

9 Time

10 Ascii Characters

11 Mix all kinds with the same frequency

Decimal is the natural number system, right? Well, in fact no, there is nothing special about decimal, except that we chose to use it. That may be, because we have ten fingers.

Other systems played a great role in the past, for example a twelve and five times twelve based system still seen by the fact that numbers have simple names up to twelve, and our way of measuring time.

The celts had a base twenty system, vestiges of which can be found in modern Irish and in strange French numbers (e.g. 92 is four twenty twelve).

Mathematically any number can be used as a base, and the system will always function exactly like our decimal system, except that it will not have ten, but that many different digits. Some of them make a lot of sence for use with computers.

Base 2 or binary number system works exactly like decimal, except that there are only two digits, 0 and 1. As in every base, the base itself is the first number that can not be represented by one digit. This means that a decimal 2 in binary must be written as 10. Again as in decimal, the number that comes after 10 is 11, which is one more, i.e. a decimal 3. Now all digits have their highest binary value, so we must carry over to a new position, which logically enough gives 100, equivalent to decimal 4 or in other words, the base to a power of 2.

Binary digits are commonly abbreviated as bits. Binary is extremely important to computers at a low level. That's because a 1 can be stored as an electrical charge, a 0 as no charge. Customarily computers group 8 bits as a byte, giving this game its name (okopo is Esperanto for octuple or byte: ok - eight, op - in groups of, o - noun ending).

Some languages don't allow binary literals. Perl notation is used here, as in 0b0011_0101 with the optional separator splitting the byte into 4-bit groups (nibbles) for easier recognition.

Base 8 or octal number system again works exactly like decimal or binary, except that there are only eight digits, 0 through 7. As in every base, the base itself is the first number that can not be represented by one digit. This means that a decimal 8 in octal must be written as 10. Again as in decimal, the number that comes after 10 is 11, which is one more, i.e. a decimal 9.

Each time the last digit reaches 7, the next digit becomes one more, and the last goes to 0, e.g. 17 -> 20. When both digits have their highest octal value (77), we must carry over to a new position, which logically enough gives 100, equivalent to decimal 64 or in other words, again the base to a power of 2.

Octals are useful, because it is easy to map 3 bits to one octal digit. But three octal digits can represent 9 bits, one too many. So in truth octal byte representations are a base 4 digit (0 through 3) followed by two octal digits.

Octals are commonly prefixed by a 0 as in 0377. In character literals they are prefixed by a backslash, as in '\177'.

Decimal or base 10 number system is the one humans commonly use. So you know how it works. And you have already seen how to store the numbers 0 through 7. Unsurprisingly, decimal does it the same way as octal.

Binary coded decimal (BCD) codes each digit as 4 bits, or 2 digits per byte. This is easy to convert to binary. But it is wasteful in space requirement, because it doesn't use the combinations 0b1010 through 0b1111. Conversely these bit combinations, when they occur, do not give a valid BCD number. So it isn't much used anymore. It is noted here with a fantasy prefix 0d, as in 0d12.

If you look at the bit patterns of these digits, you'll notice that there are only about 37% of 1-bits. To compensate that, this game will present you BCD tasks with few 1-bits less frequently. This raises the amount of overall 1-bits in this category to about 43%.

That still leaves part of the compensation in your hands. The best way to do this is to shoot 0-bits left and right more often than 1-bits. This doubles them.

Base 16, hexadecimal or simply hex number system again works exactly like decimal or binary, except that there are an amazing sixteen digits, 0 through 9 followed by A through F. As in every base, the base itself is the first number that can not be represented by one digit. This means that a decimal 16 in hex must be written as 10. Again as in decimal, the number that comes after 10 is 11, which is one more, i.e. a decimal 17.

Each time the last digit reaches F, the next digit becomes one more, and the last goes to 0, e.g. 1F -> 20. When both digits have their highest hex value (FF), we must carry over to a new position, which logically enough gives 100, equivalent to decimal 256 or in other words, again the base to a power of 2.

This is actually an extension of BCD, where the missing combinations are put to use. Conversely, unlike BCD, every possible bit combination gives a valid hex number.

Hexadecimals are commonly prefixed by a 0x as in 0x7F. In character literals they are prefixed by a backslash and x, as in '\x6A'.

This table shows how all the different digits map to binary:

8 4 2 1 __ value of this column 0 0 0 0 0 1 0 0 0 1 __ binary 2 0 0 1 0 3 0 0 1 1 __ base 4 (first digit of octal bytes) 4 0 1 0 0 5 0 1 0 1 6 0 1 1 0 7 0 1 1 1 __ octal 8 1 0 0 0 9 1 0 0 1 __ (binary coded) decimal A 1 0 1 0 B 1 0 1 1 C 1 1 0 0 D 1 1 0 1 E 1 1 1 0 F 1 1 1 1 __ hexadecimal

All preceding levels can be mastered by merely replacing the digits with their binary pattern as shown in the digits table. Now come tasks which require more concentration and learning additional things.

Computers use additive color mixing of red, green and blue (RGB). The higher the value of one of these is, the brighter that color. The more of these are bright, the closer you get to white.

Web pages and X11 traditionally denoted these as # followed by one, two or four hex digits per color. The latter, being for two or four byte representations, are not important here, even though one byte colors are rare nowadays. A problem common to all these representations is that you write more precision than can be stored. In other words, the lowest bits get truncated, one for the first and last digit, two for the middle one. So, for example, #F7A is indistinguishable from #E4B. For both you must find 111 01 101.

The most elementary operations of a computer are performed bitwise. The bytes are shown either in octal or hex notation.

There is one unary operator, i.e. it has only one operand. That is the complement, where each bit becomes the opposite of what it was. This is written with the operator ~, i.e. ~ 1 is 0.

The others are all binary, i.e. they have two operands which they combine. There is logical or, where the result is 1 if at least one of the original bits is 1. This is written with the operator |, i.e. 0 | 1 is 1.

Logical and is the opposite. The result is 1 only if both operands are 1. This is written with the operator &, i.e. 1 & 1 is 1.

Exclusive Or is 1 only if both operands are different. This is written with the operator ^, i.e. 1 ^ 0 is 1.

The effect is explained above for single bits, but in fact it happens pairwise for the bits in the same positions of both bytes. There are two more operators which only make sence for bytes (or bigger numbers). These are the left shift operator <<, e.g. 0xF8 << 4 is 0x80, and the right shift operator >>, e.g. 0xF8 >> 2 is 0x3E.

Since shift operators always shift in 0-bits, you get a surplus of them. To compensate that, this game will present you big shifts less frequently. It will also shift in the direction where less 1-bits are shifted out. This raises the overall amount of 1-bits in this category to about 46%.

That still leaves part of the compensation in your hands. The best way to do this is to shoot 0-bits left and right more often than 1-bits. This doubles them.

This one should be the easiest, because were used to it. But in fact it's the hardest, because, unlike octal or hexadecimal, it doesn't map well to binary. That is, there are no subgroups of bits you can treat apart. The reason being that neither 10, nor any multiple, can be expressed as a power of two.

If you've gotten used to the funny hex digits, you've covered the first 16 numbers. From there you just continue in the same way, all the way up to 255, the biggest number a byte can hold.

So if a byte holds 256 different numbers, where do the negative ones go? You have to make space, by sacrificing one bit fo the sign. That gives us the numbers -128 through 127.

Alas it's not so easy. You must take a positive number, say 110, subtract one, giving 0110 1101. Then you flip all the bits, so -110 is stored as 1001 0010. Don't blame me, computers work that way!

Our time system is actually a disguised base 60 system. If we had 60 different digits, we could write hours, minutes and seconds as a ``normal'' number with 3 digits. Instead we write each ``digit'' as a decimal number and put in a separator to tell them apart.

Each time the last ``digit'' reaches 59, the next ``digit'' becomes one more, and the last goes to 00, e.g. 00:00:59 -> 00:01:00. When both ``digits'' have their highest value (00:59:59), we must carry over to a new position, which logically enough gives 01:00:00, again the base to a power of 2.

One byte isn't really much use since it can only go up to 00:04:15. Even two bytes combined are not enough, since they stop at 18:12:15, not even one day's worth. So instead 4 bytes are commonly used today. The epoch, or beginning of all time was generally defined to be 1970. And again it's not enough, as we'll run out of time by 2038, unless we switch to 8 bytes.

Ascii is limited to simple latin letters, digits, plus a couple punctuation and other signs. This is by no means sufficient for languages other than English. But a byte can only represent 256 different characters, which is still far from enough.

So different combinations have been thought up, like Latin-1, updated since to Latin-9 for western European signs. Eastern Europe uses Latin-2. You can't mix the two without extra indications, so 1 byte codes are coming to an end. Unicode originally had two bytes for 65536 characters, meanwhile it needs a few bits more for all the characters of the world. To save space, and to have a / still separate directories, there are variable length encodings for this.

But all these different codes (except Ebcdic), share the 128 initial Ascii characters. So this game limits itself to those. Since C-like languages use the single quote to mark characters, the quote itself is protected by a backslash. So the backslash must also be protected. Additionally a few of the low numbers, the control characters, can also be entered with a backslash sequence.

All numbers not shown in the table, occur rather rarely in this game, and are shown either in octal '\226' or hex '\xA5' notation. The table combines hex and octal values for the characters. Simply replace a digit from the top rows for an underscore.

0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 0x0_ / 000_: \a 001_: \b \t \n \f \r 0x2_ / 004_: ! " # $ % & \' 005_: ( ) * + , - . / 0x3_ / 006_: 0 1 2 3 4 5 6 7 007_: 8 9 : ; < = > ? 0x4_ / 010_: @ A B C D E F G 011_: H I J K L M N O 0x5_ / 012_: P Q R S T U V W 013_: X Y Z [ \\ ] ^ _ 0x6_ / 014_: ` a b c d e f g 015_: h i j k l m n o 0x7_ / 016_: p q r s t u v w 017_: x y z { | } ~

Daniel Pfeiffer <occitan@esperanto.org>