Hrvoje’s Blog

It’s only ones and zeroes.

The Eagle Has Landed

The year was 1984. Apple Macintosh was just introduced, as well as our own shiny new computer called “Orao” (Eagle). It ended up being chosen as a standard primary school computer in Croatia from 1985 to 1991. For many of us, kids back then, this was one of the first opportunities to ever use a computer. Simple and rudimentary by today’s standards, Orao was brilliantly designed to avoid using specialized components - only simple TTL logic and off-the-shelf parts were used.

I wanted to write a cross-platform emulator, and after making one in Python, decided to go a step further and port it to Javascript. This is perhaps the most convenient way to use it, even though not all features were ported. To invoke BASIC, enter “BC” after booting. It can fetch one of the available tape images as .wav files via AJAX and load them. Loading takes time, computers were slow back then. :-)

For a slightly more complete version, check the Python version, but if you just want a quick dose of nostalgia - HERE it is!

TL;DR: enter BC at the * (star) prompt, press ENTER when asked about the memory size and try one of the following:

1
2
3
4
5
6
LMEM "SPACEINV"
LMEM "CRVIC"
LMEM "MUZIKA"
LMEM "DEMO2"
LMEM "RUSENJE"
LMEM "TETRIS" (start with LNK4096)

Double quotes = shift + 2. To erase something, use ctrl + H or left arrow.

Ghost Ship

Lately I’ve been solving some problems on CheckiO, a really addictive programming site, and stumbled upon a very interesting golf mission. So, you might ask: “What are golf missions?!”. The idea is to solve the problem using as little code as theoretically possible. Your score is inversely related to code length and transforms a mildly challenging problem into a very addictive one.

One of the most interesting missions is called Ghost Detect. It might not seem special at first, but it gets tricky as solutions get shorter. The mission goal is to write the shortest possible code to recognize if three consecutive signals sent in binary are of the same length. 11000001100011 is a good signal while 111000100011 is a bad one. There is at least one zero between every group of ones. For each character used (less than 200) you earn 1 point. So, how do we do this?

Cookie Math

There was a very interesting presentation at the last 31C3 conference given by two very talented security researchers: Shahar Tal and Lior Oppenheim. The vulnerability they found targets many different routers from various manufacturers and was, apparently, patched 10 years ago (!) by the software company who made RomPager, the software in question. Let’s just say vendors are slow in deploying patches, leaving tens of millions of routers vulnerable to potential remote bricking, turning into botnets or who knows what else. It was named Misfortune Cookie for a good reason, but what does that have to do with math?

Tic-Tac-Toe in … MySQL

If you ever attended a boring lecture, you probably know this game by heart. Frequently scribbled on textbook margins and school desks, it’s insanely popular and fun to play. Talking to a friend about MySQL made me wonder if such a respectable, high performance database can be misused and tricked into being a gaming platfom. While it isn’t likely going to run Quake, maybe a simple game of Tic-Tac-Toe would be just right.

Why would anyone do this? Well, making floppy drives play The Imperial March isn’t very useful either, but it’s darn entertaining. MySQL is a powerful tool with strong scripting capabilities and Turing complete as well, so implementing this game in a single player mode is possible.

My Friend’s 2048 Version

Recently I tried implementing a cool game called 2048 in Python and make it as short as possible. Thinking I did a decent job, I challenged a friend to give it a go. Blown away how much shorter it turned out to be, all I can say is - kudos to Veky.

A Simple 2048 Clone in Python

Every now and then a viral game shows up. It is difficult to name a particular quality which makes a game popular, but most people would probably describe it as addictive. 2048 is just that, despite its remarkable simplicity.

Soon, I started wondering how many lines of code would it take to write it and what are the bare essentials of the game, and tried writing my own version. To keep things short, movements are implemented in a single direction only. For the rest of the moves to work you have to rotate the matrix a few times first, perform the move and rotate it some more to return to your starting point. Not ideal, but simple it is. Game over detect simply checks if movement in any direction affects the board.

Tile creation needed to be short, so a list of zero-valued matrix elements’ coordinates was made, one picked out at random and a 2 or 4 placed there. To color the backgrounds differently, its background color is derived from its value. A dictionary could have been used as well, but it would be slightly longer.

That’s pretty much it - no score, no menu, no restart, no keypress error handling… just the bare essentials, but - it works. And it’s kind of fun, too!

Short attempt with Tkinter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import random,Tkinter
def shift(c): return list([i for i in c if i>0] + [0]*c.count(0))
def sms(l):
        l=shift(l)
        for i in range(len(l)-1):
                if l[i+1]==l[i]: l[i], l[i+1] = 2*l[i], 0
        return shift(l)
class igra(Tkinter.Tk):
        b = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
        def __init__(self,parent):
                Tkinter.Tk.__init__(self,parent)
                self.parent = parent
                self.grid()
                self.bl = [Tkinter.Button(self, height=2, width=4, state=Tkinter.DISABLED, font=("Helvetica", 24)) for i in range(16)]
                for i in range(16): self.bl[i].grid(row=i//4, column=i%4)
                self.dodaj_novu()
                self.bind_all('<Key>', self.key)
                self.mainloop()
        def rot(self): self.b = list(map(list, zip(*self.b[::-1])))
        def move(self, n):
                diff = self.b[:]
                for i in range(n): self.rot()
                for i in range(4): self.b[i] = sms(self.b[i])
                for i in range(4-n): self.rot()
                return 1 if self.b != diff else 0
        def dodaj_novu(self):
                k = [(i//4, i%4) for i,j in enumerate(sum(self.b, [])) if j == 0][random.randint(0, sum(self.b, []).count(0)-1)]
                self.b[k[0]][k[1]] = random.randint(1,2)*2
                for i in range(16):
                        d = self.b[i//4][i%4]
                        self.bl[i].config(text=d if d else ' ', bg='#%06x'% ((2**24-1) - (d*1500) ))
        def key(self, event):
                direction={'Left': 0, 'Down': 1, 'Right': 2, 'Up': 3}
                if self.move(direction[event.keysym]): self.dodaj_novu()
                p = self.b[:]
                for i in range(4):
                        self.move(i)
                        if self.b != p:
                                self.b = p[:]
                                return
                for i in range(16): self.bl[i].config(bg='red', text=':(')
a = igra(None)

…and it looks like this: