
My tooth hurt a bit in the last week, and it got really bad yesterday, so I called some 24h dental service. It wasn't as 24h as they claimed and I was only able to get an appointment for the next day. The bad news is - root canal treatment was required. The even worse news - it was damn 700 quid for two visits. Here goes the new computer, at least for now. It's seriously insanely expensive compared to dentistry in Poland, whene plain checkup is about 10 GBP, and root canal treatment is about 50 GBP - just Google for prices if you don't believe me. If I actually knew in advance it would cost that much I'd probably just book a flight. Too bad you cannot schedule your dental problems.
The best kittens, technology, and video games blog in the world.
Sunday, January 20, 2008
My poor bottom left 6
Sunday, January 13, 2008
Protecting custom SQL in Rails from SQL injections

The technique I'm presenting here is not an "awesome revolutionary breakthrough in Rails security" kind of thing (like XSS Shield), it's more like a small cool trick that can improve your code and make it more secure.
Most web applications are backed by some SQL-based database. If they're written in a language like PHP in which SQL is freely mixed with code, it's very easy to open an SQL injection vulnerability. There are two common solutions for making such vulnerabilities less likely. One is "prepared statements", where instead of creating complete SQL like "SELECT * FROM foo WHERE name='#{name}'" one crerates SQL with placeholders like "SELECT * FROM foo WHERE name=?", and then fills the placeholders with the actual data in a safe way within the database or database driver. The other solution is using Object-Relational Mappers instead of raw SQL, and that's what Rails is doing with Active Record. As long as you're using Active Record only with no custom SQL you don't have to worry about SQL injections at all.
Unfortunately in real applications Active Record is often not good enough. It is OK for locally manipulating small graphs of objects (basically creating, reading, updating and deleting single objects/rows at time), but you need to go back to raw SQL every time you want to compute a query on a lot of data (database views would also work, but that's not a subject today). Having to use SQL is not a bad thing, however due to Rails' lack of support for prepared statements it leaves us in a rather bad situation from security point of view.
Did I just say Rails doesn't support prepared statements ? So what are all those :conditions => ['foo > ? AND bar IN ?', frob, bang] if not prepared statements ? They are "fake" prepared statements, expanded on ActiveRecord level unlike "real" prepared statements expanded on database level. The method which fakes them is ActiveRecord::Base#sanitize_sql and we can reuse it to fake prepared statements of other kinds.
This means replacing ugly code like that:
connection.select <<SQL
SELECT COUNT(*) FROM people WHERE last_name LIKE '#{quote_value(prefix)}%'
SQL by far nicer:connection.safe_select <<SQL, "#{prefix}%"
SELECT COUNT(*) FROM people WHERE last_name LIKE ?'
SQLThe code to make that happen is pretty simple:
class ActiveRecord::ConnectionAdapters::AbstractAdapter
[:select, :delete, :update, :execute].each do |m|
define_method(:"safe_#{m}") do |*args|
send(m, ActiveRecord::Base.send(:sanitize_sql, args))
end
end
end
Wednesday, January 09, 2008
Voter discrimination in Polish parliamentary elections

Poland has a reputation of a stable democratic country, and indeed - pretty much everybody can vote or candidate, and there have never been any vote counting problems. However, there's a massive discrimination of some classes of voters going on, one that the mainstream media never talk about. Your vote will count for less if you:
- vote in a district with a high turnout
- vote in a district which arbitrarily got fewer mandates per person
- you were arbitrarily excluded from district's population count
To cut the story short, here's a table of voting power depending on district. Elections to both houses have slightly different number of districts (40 vs 41) so I'll show them separately.
| Upper house (Senat) | |||||
|---|---|---|---|---|---|
| District | Mandates | Eligible voters | Actual voters | Vote weight (theoretical) | Vote weight (actual) |
| Warszawa I | 4 | 1567038 | 1144318 | 63 | 40 |
| Warszawa II | 2 | 756628 | 460634 | 65 | 50 |
| Poznań | 2 | 681953 | 444243 | 72 | 52 |
| Szczecin | 2 | 837580 | 440897 | 58 | 52 |
| Łódź | 2 | 693779 | 422493 | 71 | 54 |
| Bydgoszcz | 2 | 806833 | 421442 | 61 | 55 |
| Kraków | 4 | 1431548 | 829767 | 68 | 55 |
| Wrocław | 3 | 971597 | 557429 | 76 | 62 |
| Bielsko-Biała | 2 | 598761 | 346544 | 82 | 66 |
| Gdynia | 3 | 906688 | 506522 | 81 | 68 |
| Lublin | 3 | 964553 | 501398 | 76 | 69 |
| Krosno | 2 | 697632 | 331401 | 70 | 70 |
| Gliwice | 2 | 659406 | 330660 | 74 | 70 |
| Rzeszów | 3 | 956730 | 493160 | 77 | 70 |
| Sosnowiec | 2 | 600155 | 326536 | 82 | 71 |
| Kielce | 3 | 1043578 | 484240 | 70 | 71 |
| Gdańsk | 3 | 823742 | 473407 | 89 | 73 |
| Katowice | 3 | 826292 | 468692 | 89 | 74 |
| Białystok | 3 | 951236 | 464432 | 77 | 74 |
| Płock | 2 | 668405 | 307810 | 73 | 75 |
| Rybnik | 2 | 583350 | 303688 | 84 | 76 |
| Olsztyn | 2 | 628234 | 301048 | 78 | 77 |
| Piła | 2 | 596237 | 300511 | 82 | 77 |
| Nowy Sącz | 2 | 584126 | 299453 | 84 | 77 |
| Konin | 2 | 604427 | 299432 | 81 | 77 |
| Piotrków Trybunalski | 2 | 590193 | 292757 | 83 | 79 |
| Radom | 2 | 575812 | 285526 | 85 | 81 |
| Tarnów | 2 | 552942 | 283424 | 89 | 81 |
| Wałbrzych | 2 | 567692 | 272550 | 86 | 85 |
| Legnica | 3 | 806174 | 405298 | 91 | 85 |
| Zielona Góra | 3 | 801490 | 396389 | 92 | 87 |
| Toruń | 3 | 834430 | 393878 | 88 | 88 |
| Kalisz | 3 | 782596 | 388566 | 94 | 89 |
| Częstochowa | 2 | 493644 | 256382 | 100 | 90 |
| Sieradz | 3 | 792112 | 383239 | 93 | 90 |
| Koszalin | 2 | 516655 | 248912 | 95 | 93 |
| Opole | 3 | 830903 | 370996 | 89 | 93 |
| Siedlce | 3 | 746842 | 368269 | 99 | 94 |
| Chełm | 3 | 778641 | 352365 | 95 | 98 |
| Elbląg | 2 | 504837 | 232096 | 97 | 100 |
| Lower house (Sejm) | |||||
|---|---|---|---|---|---|
| District | Mandates | Eligible voters | Actual voters | Vote weight (theoretical) | Vote weight (actual) |
| Warszawa I | 19 | 1567038 | 1145983 | 74 | 47 |
| Poznań | 10 | 681953 | 447616 | 90 | 63 |
| Kraków | 13 | 929826 | 561404 | 85 | 65 |
| Łódź | 10 | 693779 | 422754 | 88 | 67 |
| Warszawa II | 11 | 756628 | 460582 | 89 | 67 |
| Wrocław | 14 | 971597 | 556133 | 88 | 71 |
| Gdańsk | 12 | 823742 | 472504 | 89 | 71 |
| Katowice | 12 | 826292 | 465482 | 89 | 73 |
| Bielsko-Biała | 9 | 598761 | 344763 | 92 | 74 |
| Częstochowa | 7 | 493644 | 255728 | 87 | 77 |
| Sosnowiec | 9 | 600155 | 325737 | 92 | 78 |
| Gdynia | 14 | 906688 | 503636 | 94 | 78 |
| Bydgoszcz | 12 | 806833 | 418902 | 91 | 81 |
| Wałbrzych | 8 | 567692 | 271278 | 86 | 83 |
| Szczecin | 13 | 837580 | 438829 | 95 | 83 |
| Legnica | 12 | 806174 | 404559 | 91 | 84 |
| Rybnik | 9 | 583350 | 302914 | 94 | 84 |
| Chrzanów | 8 | 501722 | 267676 | 97 | 84 |
| Lublin | 15 | 964553 | 501704 | 95 | 84 |
| Piła | 9 | 596237 | 298569 | 92 | 85 |
| Nowy Sącz | 9 | 584126 | 297902 | 94 | 85 |
| Konin | 9 | 604427 | 297645 | 91 | 85 |
| Gliwice | 10 | 659406 | 329350 | 93 | 86 |
| Zielona Góra | 12 | 801490 | 394215 | 91 | 86 |
| Rzeszów | 15 | 956730 | 491363 | 96 | 86 |
| Piotrków Trybunalski | 9 | 590193 | 291982 | 93 | 87 |
| Kalisz | 12 | 782596 | 386235 | 94 | 88 |
| Sieradz | 12 | 792112 | 382387 | 93 | 88 |
| Radom | 9 | 575812 | 284839 | 96 | 89 |
| Tarnów | 9 | 552942 | 281323 | 100 | 90 |
| Koszalin | 8 | 516655 | 246514 | 95 | 92 |
| Białystok | 15 | 951236 | 461180 | 96 | 92 |
| Płock | 10 | 668405 | 306981 | 91 | 92 |
| Siedlce | 12 | 746842 | 368142 | 98 | 92 |
| Toruń | 13 | 834430 | 392729 | 95 | 93 |
| Kielce | 16 | 1043578 | 482571 | 94 | 93 |
| Krosno | 11 | 697632 | 330228 | 96 | 94 |
| Olsztyn | 10 | 628234 | 299231 | 97 | 94 |
| Chełm | 12 | 778641 | 351500 | 94 | 96 |
| Elbląg | 8 | 504837 | 230592 | 97 | 98 |
| Opole | 13 | 830903 | 368540 | 96 | 100 |
So if you live in Warsaw or London, your vote only counts as 40% to 47% of someone living in Elbląg or Opole. How it happened again ?
- Allocation of mandates per district was distriminatory in the first place - even dividing mandates per eligible voters a citizen in some districts (like Warsaw) are worth only 63%/74% of a citizen in other district
- Counts of eligible voters exclude people living abroad. Even worse - for purposes of mandate assignment they are falsely counted as still living at their last address in Poland. So if a few thousand people moved from Legnica district to London (and are now voting in Warsaw I district), a mandate for them is not reassigned from Legnica to London. So people who stayed in Legnica get to vote for them, while people living in Warsaw or London get their votes diluted !
- Mandates are allocated based on number of theoretical eligible voters, not number of people who actually voted. Just because you live in the same district as someone who didn't bother to vote doesn't give you any right of voting for that person! Only actual voters should be counted.
Sunday, January 06, 2008
GNOME sucks

My dead Macbook returned with a new disk. I normally use KDE, but this time I thought it would be a good idea to try the Ubuntu's default GNOME desktop. And it sucks.
The thing which sucks most is virtual desktops support. If I have programs opened on different virtual desktops I cannot switch between them using alt+tab. I cannot switch between them using taskbar. And I cannot take my mouse and simply move from one virtual desktop to another over screen edge. That makes the whole virtual desktop thing pretty much useless.
The second things which sucks is lack of single place with all configuration options. I don't think it even has configuration options I want, believing instead in "one size fits all". Wake up GNOME people - configurable Windows is way more popular than one-true-way Mac for a reason, and so is configurable KDE way more popular than one-true-way GNOME.
The third thing which sucks is GNOME trying too hard to be a Mac but failing. There's even a menubar at top of the screen, but it does not host current application's menus. Instead it takes one of the most valuable parts of screen (top edge) and completely wastes it. It's even worse on a computer with tiny screen like Macbook, where top bar and bottom bar together take large part of total screenspace, leaving much less for applications.
A few more things. Applications menu does not remember my recently used programs. The only reason I would ever use Applications menu instead of Alt+F2 is if it listed the few most frequently (or most recently) used programs for simple clicking. Without that it's completely useless. Places menu is completely useless, and System menu as I said should be replaced by a single place with all config it in. Like your beloved Mac. Or Windows. Or KDE. Or anything except for GNOME.
Posted by
taw
at
17:12
14
comments
Wednesday, January 02, 2008
24C3

24C3 is over. Here's a quick summary of events I attended and some general impressions. Recordings of most of the events are downloadable.
Anonymity for 2015: Why not just use Tor? was a quick overview of state of web anonymizers. In case you wondered - they're all insecure against serious attackers and there's little hope for them ever being secure. Web (low latency) anonymizers are much worse than email (high latency) anonymizers.
Make Cool Things with Microcontrollers: Hacking with Microcontrollers and "Design Noir: The seedy underbelly of electronic engineering" talked about microcontrollers and cool things you can do with them. The most popular one was TV-B-Gone which is an universal TV remote with just an off button. In some modded versions it can turn off all TVs in radius of 100 meters. Apparently everyone who bought one at the Congress tested it at nearby MediaMarkt or Saturn, what really pissed them off. Another popular thing was Brainwave Machine, which allegedly affects your brainwave patterns using flashing diodes and binaural sounds. I tested it and it only made my eyes hurt by flashing diodes directly into them.
Programming DNA: A 2-bit language for engineering biology talked about progress of DNA-based engineering, and how cheap and simple DNA synthesis became in recent years, at Moore's Law kind of pace. One thing I'm wondering is if we will ever create DNA processors which do something to DNA (or RNA) linearly one nucleotide at a time. In nature there are only two such processors - one for copying DNA (or RNA) to DNA (or RNA), and one for RNA to protein synthesis. There's a lot of stuff based on local pattern matching (DNA repairs, post-transcription RNA modification, RNA interference etc.) but they seem much less interesting. It would be really awesome if we could create more DNA processors, let's say one which would synthesize different kind of polymers based on DNA/RNA, or one which would do interpret nucleotides as instructions more complex than "copy, move forward by one". In a way DNA sequencing and DNA synthesis are DNA processors, but they're purely artificial and we cannot use them from within cells. Maybe I'll talk about it more in some other post.
The second day was probably the most interesting. In started with the first round of the Ligthning Talks, where I gave a brief presentation of XSS Shield plugin for Ruby on Rails. It was released only a few days before the Congress, so I had no time to do it before, but I will definitely blog about it soon. Some other interesting talks were about UN Democracy and vulnerabilities in Mac desktop widgets. Unfortunately the rest of the lightning talks were scheduled for fourth day evening, so I was unable to see them.
Then I've seen Quantum Cryptography and Possible Attacks which was rather introductory and hand-wavy, so I'd probably be better off seing After C: D, libd and the Slate project: A clean slate for operating systems in the same time slot.
Linguistic Hacking: How to know what a text in an unknown language is about? was very introductory too. It's kinda difficult to know in advance which CCC talk is going to be introductory and which is going to be totally hardcore.
Just in Time compilers - breaking a VM: Practical VM exploiting based on CACAO was something I enjoyed a lot, as writing compilers is my hobby. Immediately afterwards there was Modelling Infectious Diseases in Virtual Realities: The "corrupted blood" plague of WoW from an epidemiological perspective which applied epidemiological models to Corrupted Blood epidemics from World of Warcraft.
Then was the rescheduled AES: side-channel attacks for the masses talk which was very interesting in spite of being a clear case of Death By PowerPoint. It wasn't the only messily structured presentation, but the Congress average was pretty good, so I'm not going to complain.
The late evening of the second day was even better, with DIY Survival: How to survive the apocalypse or a robot uprising and the absolute hit of the 24C3: Rule 34 Contest: There is porn of it. Unfortunately there are no official recordings of Rule 34 contest (no idea about unofficial ones), but participants searched for porn on various subjects ranging from the simplest like Star Wars to more difficult like Apple and Religion. Contest winner was an experienced porn seeker who used websites like Encyclopedia Dramatica and Rule 34 search engine, but participants were able to get really far with just plain Google Image search. Fittingly the first prize was an inflatable sheep.
The third day was the weakest, with From Ring Zero to UID Zero: A couple of stories about kernel exploiting being the only really good talk. haXe: hacking a programming language didn't really explain what's the point of haXe, and Space Communism: Communism or Space first? started with an interesting premise but was very boring in execution.
The last day was full of really great talks which I wasn't able to attend as I had a train at 16:10. It would be much better if they moved some of the good ones from day 4 to the least interesting day 3.
A Spotter's Guide to AACS Keys presented a gloom view of widespread censorship we would live in if Hollywood won. It is very important to keep breaking every digital restriction management system Hollywood, RIAA, Microsoft and other forces of evil keep throwing at us. If we are unable to do so, we're going to live in the fascist world where only licenced "content providers" will be allowed. In their evil world there would be no Wikipedia, no YouTube, no blogs, and IMs would be paid per message. Just look at game consoles and mobile phones, which were the most successful in implementing DRMs - is this the world you want ? I like free Internet much more.
The second talk was Overtaking Proprietary Software Without Writing Code: a few rough insights on sharpening free software, the basic premise of which was that quality is massively overrated when it comes to Open Source software popularity. But that's not all - shitty quality cheap stuff is what created the civilization. Ten thousand years ago people gave up good quality food they hunted and gathered and for which they were evolutionarily adapted, and replaced it with agricultural food which lacked adequate nutrituion, made them fall to many diseases, increased their death rates, reduced their heights, shortened their lifespans, made them susceptible to regular mass starvation events due to bad weather, and eventually enabled civilization as we know it. Gradually the quality of food and life improved, but many people in poor countries are in many ways still worse off than in the Paleolithic.
Many other social and technical changes required giving up quality in exchange for something else, usually quantity. For a recent example - people are reading blogs instead of reading newspapers and other traditional media - quality of presentation in blogs is typically far worse than in newspapers, but there are more blogs, on more subjects, presenting more points of view, and so blogs get more and more popular. Wikipedia vs professionally developed textbooks is another good example. Wikipedia is often less well edited, has typos, bad grammar and inconsistencies which would never get past even the quickest review, not to mention occasional vandalisms and pov wars. But Wikipedia is also much bigger and much more accessible than traditional textbooks and encyclopedias, and somewhat worse quality is not that big of a deal (I'm talking about small articles about less popular subjects mostly, quality of the most popular 10% of articles is usually very high). Oh and it's free, what also helps.
Browsers are another good example. The most popular browser IE is worse than any other browser ever made, but has one good feature of being preinstalled (where's antitrust law when we need it, OEMs should be free to install IE or Firefox or Opera as they see fit, instead of being de facto forced to install IE only). The second most popular browser Firefox has better quality than IE, and is gaining popularity relative to IE. But that's not a victory of quality - Opera is even better when it comes to low bug counts but it never got anywhere as popular as Firefox (or IE). Firefox is winning not because of quality but because it has very easy to write extensions, and therefore more useful extensions than any other browsers. That and good marketing.
The last talk I attended was Ruby on Rails Security, which is really a must-see for anybody doing Rails. It covers everything you need to know except of XSS Shield.
Just afterwards there was a Lego Sumo contest where people built and programmed their Lego Mindstorms robots which tried to throw each other off the table.
A few observations - I liked go corner more when it was located in the dining hall like on 23C3. Some German language talks had English descriptions (like Sex 2.0: Hacking Heteronormativity, and Hacker Jeopardy) and there was no way to tell that from the paper Fahrplan. They should make it possible to pay for tickets by cards for 25C3, cash is so 20th century. In spite of these minor glitches I think 24C3 was a really awesome event, and I'm definitely attending the next year.
Wednesday, December 26, 2007
Looking for a new computer

Because my hatred towards my Macbook reached unprecedented level, and I didn't take my old desktop with me to London, I' looking for a new computer. I probably won't be buying it for another few weeks, but here's a rough spec/wishlist (which reads a lot like "why Macbook sucks" list):
- The options are - one good laptop for work+home, or shitty laptop at work + good desktop at home. Right now I think a good all-purpose laptop would be a better solution.
- At least 2GB RAM, 4GB even better. That's really non-negotiable, computers with less than that are good for little more than web browsing.
- Probably dual boot Ubuntu (for 90% of normal use)/XP (for occasional gaming/compatibility testing). I've seen Vista and I don't like it. Most laptops these days come with Vista by default, but I can always wipe it out.
- At least 1440x900 or even better 1680x1050. Macbook resolution of 1280x800 is painful.
- I don't really care about screen size that much, resolution is much more important. 17-inch screen usually means bigger keyboard and that's a nice thing to have, even if 15-inch screen with good resolution is all right.
- I would like to play something more recent than Quake 3, so integrated GPU is completely out of a question. 8600M GT with 256MB memory would certainly be nice. Something somewhat less powerful is probably going to be fine too.
- 160/200 GB disk would be nice for dual boot system, 5400 rpm is good enough on Linux as it has really awesome I/O caching unlike OSX. I'm not sure about XP.
- I don't remember the last time I've seen a CPU-bound program, vast majority being limited by memory or I/O or GPU. So Intel Core 2 Duo 2.0 GHz or its moral equivalent by AMD should be just fine.
- At least 3 USB ports, with 4 or more points scoring extra points.
- DVD burner and real DVD drive (not annoying slit like in Macbook) would be a big plus.
- I woudn't care if it was a desktop but for a laptop 3-year guarantee is pretty much necessary.
Monday, December 24, 2007
Javascript version of jrpg
I have just written a very small Javascript version of jrpg, which can be accessed here:
If you want to try it out, you will need a decent browser like Firefox 2, and Japanese fonts. It might work with other browsers, but I haven't done any testing yet. Just like in pygame version you can move around using arrow keys, and if they don't work by using numeric keyboard with numlock on. Battles are fought by keyboard and enter key.
The game is a very small demo, allowing you to only go around a very small map, collecting coins and fighting hiragana demons. Most of the cool features from the full pygame version are not implemented, so if you haven't seen it yet go ahead and download it. I did it because I wanted to see what's possible with pure Javascript+CSS, and relearn modern Javascript.
Things I learned from the experience:
- I really like jQuery. Mixing DOM and jQuery operations could be made somewhat easier, but even without that jQuery really greatly improves the code.
- Declarative specifications of presentation and semi-declarative specifications of behaviour are extremely convenient way of creating user interfaces. They definitely beat pygame in convenience.
- Having fully powerful layout engine, and font engine is a great improvement over pygame.
- Javascript's OO system is quite nice to use in spite of being so different from other OO systems. Definitely beats Java's.
- Functional programming in Javascript is possible, but much more painful than in any other language I know due to its strictly C-like syntax, except for the languages which do not support functional programming at all like Python, Java, or Prolog. It would be nice if future version of Javascript at least introduced implicit return, and renamed
functiontofun. Compare Javascriptfoo.map(function(x){return x+1})with hypothetical improved Javascriptfoo.map(fun(x){x+1})and Rubyfoo.map{|x| x+1}. Bad syntax discourages using high order function a lot, and creating your own high order functions even more. - Destructuring assignment is an awesome feature that is not normally noticed when it's there, but it hurts a lot when it's missing.
- Lack of string interpolation makes string building code look like crap.
- Firebug is even more awesome than I thought.
Wednesday, December 19, 2007
My Macbook died

Hard drive in my Macbook died. One of the most annoying things about laptops is that there's no way of fixing them on your own, even if it's something trivial like replacing a hard drive with a new one. I'm going to see how good Apple customer support really is.
Frankly I have been disappointed by pretty much everything Apple. Their hardware is underpowered relative to price, comes in weird configurations, and doesn't even look that pretty after some use because it's so easily scratchable. For example Macbooks don't have a real GPU, but they have a totally useless FireWire port instead of a third USB. Even iPods which seem to be the most popular Apple product all come with crappy earphones and no USB port.
Apple software also ranges from very bad like Safari (why couldn't they simply bundle reskinned Firefox ?) through really horrible like OS X to iTunes which is able to define its own category of suckiness way beyond any other program I know. I haven't ever touched iPhone and I do not intend to, so I'm not going to say anything about it. The only piece of Mac software that I actually liked was TextMate, which obviously wasn't created by Apple. If it was it would be an AppleScript Editor.
Basically Apple sucks and no amount of TextMate bundles and "cool" marketing are going to change that.
Wednesday, December 05, 2007
Civilization II

Because the damn Macbook comes with integrated GPU instead of even a very cheap real one I can only play very old games on it. So I'm kinda going through the old titles, at least until I can get a decent box.
I remember playing 4X games like Civilization, Civilization II, Colonization (about which I wrote some time ago), Master of Magic, and Freeciv a lot when I was younger. Now that I look at them again the original Civilization seems rather unplayable due to VGA graphics, and as the gameplay isn't much different I tried Civilization II.
The first thing I noticed is what a bunch of lies the unit statistics are. You see - in the original Civilization units had attack and defense points. In Civilization II they wanted to keep these points essentially unchanged so it would look familiar to the player base, but to rebalance the game by changing their meanings. So they introduced hit points and firepower. A quick math shows that the effective attack and defense ratings follow these rules:
effective attack = attack × firepower × hitpoints
effective defense = defense × firepower × hitpoints
Here's a full table of units, ordered by more or less their battle power.
| Name | Effective attack | Effective defense | Nominal attack | Nominal defense | Firepower | Hitpoints |
|---|---|---|---|---|---|---|
| Battleship | 96 | 96 | 12 | 12 | 2 | 4 |
| Nuclear Missle | 99 | 0 | 99 | 0 | 1 | 1 |
| AEGIS Cruiser | 48 | 48 | 8 | 8 | 2 | 3 |
| Howitzer | 72 | 12 | 12 | 2 | 2 | 3 |
| Carrier | 8 | 72 | 1 | 9 | 2 | 4 |
| Submarine | 60 | 12 | 10 | 2 | 2 | 3 |
| Cruiser | 36 | 36 | 6 | 6 | 2 | 3 |
| Stealth Bomber | 56 | 12 | 14 | 3 | 2 | 2 |
| Cruise Missle | 60 | 0 | 20 | 0 | 3 | 1 |
| Bomber | 48 | 4 | 12 | 1 | 2 | 2 |
| Helicopter | 40 | 12 | 10 | 3 | 2 | 2 |
| Armor | 30 | 15 | 10 | 5 | 1 | 3 |
| Artillery | 40 | 4 | 10 | 1 | 2 | 2 |
| Stealth Fighter | 32 | 12 | 8 | 3 | 2 | 2 |
| Mechanized Infantry | 18 | 18 | 6 | 6 | 1 | 3 |
| Marines | 16 | 10 | 8 | 5 | 1 | 2 |
| Fighter | 16 | 8 | 4 | 2 | 2 | 2 |
| Ironclad | 12 | 12 | 4 | 4 | 1 | 3 |
| Destroyer | 12 | 12 | 4 | 4 | 1 | 3 |
| Cavalry | 16 | 6 | 8 | 3 | 1 | 2 |
| Paratroopers | 12 | 8 | 6 | 4 | 1 | 2 |
| Alpine Troops | 10 | 10 | 5 | 5 | 1 | 2 |
| Cannon | 16 | 2 | 8 | 1 | 1 | 2 |
| Riflemen | 10 | 8 | 5 | 4 | 1 | 2 |
| Partisans | 8 | 8 | 4 | 4 | 1 | 2 |
| Fanatics | 8 | 8 | 4 | 4 | 1 | 2 |
| Dragoons | 10 | 4 | 5 | 2 | 1 | 2 |
| Frigate | 8 | 4 | 4 | 2 | 1 | 2 |
| Musketeers | 6 | 6 | 3 | 3 | 1 | 2 |
| Transport | 0 | 9 | 0 | 3 | 1 | 3 |
| Catapult | 6 | 1 | 6 | 1 | 1 | 1 |
| Crusaders | 5 | 1 | 5 | 1 | 1 | 1 |
| Legion | 4 | 2 | 4 | 2 | 1 | 1 |
| Knights | 4 | 2 | 4 | 2 | 1 | 1 |
| Elephant | 4 | 1 | 4 | 1 | 1 | 1 |
| Archers | 3 | 2 | 3 | 2 | 1 | 1 |
| Chariot | 3 | 1 | 3 | 1 | 1 | 1 |
| Galleon | 0 | 4 | 0 | 2 | 1 | 2 |
| Engineers | 0 | 4 | 0 | 2 | 1 | 2 |
| Horsemen | 2 | 1 | 2 | 1 | 1 | 1 |
| Caravel | 2 | 1 | 2 | 1 | 1 | 1 |
| Pikemen | 1 | 2 | 1 | 2 | 1 | 1 |
| Phalanx | 1 | 2 | 1 | 2 | 1 | 1 |
| Warriors | 1 | 1 | 1 | 1 | 1 | 1 |
| Trireme | 1 | 1 | 1 | 1 | 1 | 1 |
| Settlers | 0 | 2 | 0 | 1 | 1 | 2 |
| Freight | 0 | 1 | 0 | 1 | 1 | 1 |
| Explorer | 0 | 1 | 0 | 1 | 1 | 1 |
| Caravan | 0 | 1 | 0 | 1 | 1 | 1 |
| Spy | 0 | 0 | 0 | 0 | 1 | 1 |
| Diplomat | 0 | 0 | 0 | 0 | 1 | 1 |
So a cruise missle with nominal attack of 20 (effective 60) usually won't be able to take carrier of nominal defense 9 (effective 72), let alone a Battleship of nominal defense 12 (effective 96), even though by the original rules it should sink both without any trouble. On the other hand Ironclads at 12/12 (nominal 3/3) will easily take down every single land unit from their era, what every Civilization II player probably knows - but it was definitely not so in the original Civilization.
This isn't that bad now that I know it, but I feel so cheated. I remember playing Civilization II so many times while believing in the official attack and defense strengths, and wondering why I'm so lucky or unlucky (depending on circumstances).
When it comes to cheating, Civilization II does plenty of it. First, computer players totally ignore the fog of war. That's especially annoying when playing WW2 scenario, because their submarines are invisible and can sink your ships easily, but your submarines have big bullseyes on them. In the real game AI would be totally exterminated by the time submarines are invented of course.
Also computer players pay less for production and city growth (depending on difficulty level), don't suffer from the annoying 50% production switch penalty, and cheat in many other ways. Of course all that is understandable - the AI is so horrible compared to recent games it had to massively cheat to be any challenge.
But let's leave the question of cheating, and concentrate on gameplay. Unlike Freeciv which requires a very specific strategy (smallpoxing + We Love the Consul) to have any chance, Civilization II is so simple that a wide range of strategies lead to victory. Unless you're very unlucky early in game it's difficult not to win. The simplest strategy is plenty of settlers for expansion (and later roads/irigation), Republic, and as much spent on research as possible. Easy victory can be achieved by building Marco Polo's Embassy, which costs only 200 and lets you exchange technology with all computer players. This lets you get ten technologies by giving five players only two technologies each. This is normally a game winning event. Wonders which reduce unhappiness are also very useful and you should get them all.
It's often easier to simply buy other civilizations' cities and units than try to conquer them. An unfortunate thing about conquest is that it kills large part of the population and destroys many city impovements, and bribery lets you avoid it. You can also steal technologies with diplomats/spies. Normally there's no point bothering with sabotage.
Armies are expensive, so it's usually cheapest to connect all your cities with roads and railroads and have only a few units which you can move wherever they're needed quickly. AI is totally incapable of performing any serious offensive so you can usually defend yourself without too much trouble. Conquest is somewhat more difficult because AI cities tend to have plenty of armies inside (which just sit there doing nothing). Diplomats/Spies are one easy way of conquering cities. Ironclads/Cruisers are another very effective way - just kill everybody inside with naval bombardment and then transport some land unit to take the city, or Paratroop one if you have Paratroopers. Ironclad's effective attack strength of 12 can easily handle most fortified units of the era, and naval attacks apparently ignore City Walls. Cruiser's effective attack of 36 does the same trick in the later era. One more thing - naval units defending cities have firepower reduced to one. This halves effective defense of Cruisers, AEGIS Cruisers, Carriers, Battleships, and Submarines, but does not affect other ships like Ironclads, Destroyers, and Transports which already have firepower one. So it's not such a big deal.
Consul's Day apparently works in Civilization II, but it makes sense to refrain from using it because it becomes just soo damn easy. For people who don't know it - in Republic/Democracy if over 50% of citizens are happy and nobody is unhappy, a city starts growing 1 population a turn. Just max luxury rate for a couple of turn and reassign some people to Elvis roles until you get that in every city. It's just way too easy.
I could go on talking about strategy but the game is basically so easy that you should have absolutely no trouble winning it. Overall if you feel nostalgic and don't want too much of a challenge, go for it !
Wednesday, November 28, 2007
Installing Oracle 10g Enterprise Edition on Ubuntu 7.10 gutsy gibbon

As Trampoline Systems is doing "Enterprise" software we don't have a luxury of choosing whatever database we want (most likely mysql or postgresql, at least as far am I'm concerned), but need to support whichever database our customers use. I don't think there's any objective reason for customers being interested in database used by application any more than they should be interested in its programming language or ORM library, but for some reason the current tradition says that in "Enterprise" software applications can use any programming language and ORM they want, but the customer determines the database.
Now some people who never tried it claim that moving Rails application from one database to another is just a matter of a single line configuration change. How do I know they never tried it ? Because we did. At the very least it requires all tests to be run twice, once with mysql and the second time with Oracle. And number of things which work differently is just enormous. To make things worse most people here use Intel Macs, and there are not even Oracle clients for them, let alone servers, so when any problems happen they need to be fixed on a Linux server over ssh or on a borrowed Windows machine. It all works, but it's far from trivial.
Now since I wiped out OSX on my machine and installed Ubuntu, I thought I might be able to install Oracle 10g Enterprise Edition on it. Unfortunately Ubuntu is not an officially supported platform for Oracle, and Express Edition is apparently different enough that we don't want to use it. In the end it all worked quite less with just a little bit of hacking.
First you need to get Linux installer (10201_database_linux32.zip) and unpack it. The installer relies on some binaries being in /bin instead of /usr/bin so you need to make a few links.
$ sudo ln -s /usr/bin/basename /bin/basename
$ sudo ln -s /usr/bin/awk /bin/awkNow you need to add a "nobody" group. Debian-based system use
nobody.nogroup instead of nobody.nobody, but we aren't losing any security by creating an extra group.$ sudo addgroup nobodyNow enter installer directory (
database), and run the installer. There are many questions, but they are straightforward to answer even if you know little about Oracle. You do not need to do it as root.$ ./runInstaller -ignoresysprereqsAfter you do that the installer will ask you to run two scripts as root. Paths to these scripts (shown in installer dialog) depend on your system, for me they were:
$ sudo /home/taw/oraInventory/orainstRoot.sh
$ sudo /home/taw/oracle/product/10.2.0/db_1/root.shNow test if it works with your Rails. If it doesn't due to being unable to load
oci8lib.so either recompile OCI8, or more easily add the following line to your .bashrc:export LD_LIBRARY_PATH=/home/taw/oracle/product/10.2.0/db_1/lib/By this point you should have Oracle working. The only thing missing is getting it working again after reboot. Just create a
/etc/init.d/oracle like this one (correct path and oracle account):#!/bin/bash
ORACLE_HOME=/home/taw/oracle/product/10.2.0/db_1
ORACLE_OWNR=taw
# if the executables do not exist -- display error
if [ ! -f $ORACLE_HOME/bin/dbstart -o ! -d $ORACLE_HOME ]
then
echo "Oracle startup: cannot start"
exit 1
fi
# depending on parameter -- startup, shutdown, restart
# of the instance and listener or usage display
case "$1" in
start)
# Oracle listener and instance startup
echo -n "Starting Oracle: "
su - $ORACLE_OWNR -c "$ORACLE_HOME/bin/lsnrctl start"
su - $ORACLE_OWNR -c $ORACLE_HOME/bin/dbstart
touch /var/lock/subsys_oracle
echo "OK"
;;
stop)
# Oracle listener and instance shutdown
echo -n "Shutdown Oracle: "
su - $ORACLE_OWNR -c "$ORACLE_HOME/bin/lsnrctl stop"
su - $ORACLE_OWNR -c $ORACLE_HOME/bin/dbshut
rm -f /var/lock/subsys_oracle
echo "OK"
;;
reload|restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 start|stop|restart|reload"
exit 1
esac
exit 0and create symlinks to it:
$ sudo ln -s /etc/init.d/oracle /etc/rc0.d/K01oracle
$ sudo ln -s /etc/init.d/oracle /etc/rc2.d/S99oracle
$ sudo ln -s /etc/init.d/oracle /etc/rc6.d/K01oracle
Posted by
taw
at
01:43
23
comments

