The best kittens, technology, and video games blog in the world.

Monday, August 27, 2012

Script to convert Google+ takeout into a single easy to use document

Search cat by zenera from flickr (CC-SA)

Google+ did many things wrong like their retarded and discriminatory real name policy, but one surprising thing they did right that almost everybody else gets wrong was making it easy to export all your data using Google Takeout.

Unfortunately Google+ posts from Takeout (and pretty much everything else from Takeout) are pretty hard to use directly, but we're all hackers, so it's not a big deal to reformat them, and at least this one time it doesn't involve breaking any Terms of Service or working around any rate limiters, captchas, and other such nonsense just to get your own data.

I wrote a script to process Takeout archive into a single easy to search HTML document. Since it's pretty short, I put it in unix-utilities repository on github (the one I wrote about earlier) instead of making a new repository for it.

It's very easy to use (Stream/ directory is how it's packed in Takeout .zip):
process_gplus_takeout Stream/ output.html
It removes everything except actual content and attachments, and sorts entries by date. If you want to include different things or filter them, it should be pretty easy to modify the script.

It's even a reasonable example of how to use Hpricot to mass-process a lot of HTML documents if that's a new thing to you.

About the only hard part is not arranging computations in a way that doesn't load DOM of every single HTML file in memory simultaneously, but extracts them one by one instead, and frees DOM in between. It probably doesn't even matter in this case, since it's just a few MBs of HTML, so even all DOMs will fit in memory together, but it's a good practice in general.

Thursday, August 16, 2012

Blank political maps for Rome and Medieval 2 Total War

I don't know about you but everytime I play any Total War game - or any strategic game for that matter, I always draw ton of maps with my empire, my expansion plans, how the wars went etc.

And I discovered I'm pretty awful at keeping proportions right - which isn't really different from vast majority of people (give it a try yourself). But then, I thought - I can use a computer to draw blank map for me, and I can then draw on that.

For games based on Rome engine there's already regions.tga with all the data we need, it just needs some processing to make it usable as a blank political map.

And once I had a script to do so, I thought why not generate such map for all the games.

It would be pretty easy to generate such maps for any other mod, but I recently reinstalled everything so I have no Rome/Medieval2 mods (other than Concentrated Vanilla) currently installed.

If you want such map for you mod, email me regions.tga and I'll email you back the map. Or I could send you the script if you want.

Blue is water (regions.tga doesn't indicate which regions are water, so I had to do that part manually), green is land, black is city, white is port, dark gray borders should be continuous, so flood filling can be safely used for coloring (just remember to turn off anti-aliasing in tools options if your graphics program defaults to that like Photoshop does, since it's pixel data).

Rome - vanilla



Rome - Barbarian Invasion



Rome - Alexander



Medieval 2 - vanilla



Medieval 2 - Concentrated Vanilla 0.52



Kingdoms - Americas


Kingdoms - British Isles



Kingdoms - Crusades



Kingdoms - Teutonic



I'm sure there will be more cats in the next post.

Saturday, August 11, 2012

Medieval 2 Total War Concentrated Vanilla 0.52 - now with more settlements

Close-up portrait of the golden tiger by Tambako the Jaguar from flickr (CC-NC-ND)

In my previous post I mentioned that what bothers me the most in Concentrated Vanilla (and other mods I tired) are hugs gaps in the map which result in no action ever taking place there.

So I thought I'd actually do something about it - I found a tutorial for adding provinces, consulted with Reddit historians on which settlements in relevant regions were actually most important, and after fighting through far too many game crashes I did it - where "it" is adding a bunch of settlements.

The map is not terribly optimized, I just added 7 new regions:
They all start as rebels, but maybe at least Fes should be Moorish, since adding 3 rebel settlement in the middle of Moorish kingdom sort of screws them, especially with Concentrated Vanilla's big rebel garrisons.

I also added roads to Tripoli, Benghazi, and Alexandria, to make Egypt better connected with the rest of Africa. 

These areas should generally be pretty poor, since I didn't add any new resources. Belgrade gets gold and timber from Zagreb, which is only left with double-gold, so that's one exception, but neither of them has ports, so they're only moderately wealthy. I probably should add a few resources there, just without overdoing it.

Old distance-to-nearest-settlement map:



With these new settlements:


This isn't really finished, but it should make at least some areas playable, and I really want to just playtest it now to see if it's getting anywhere at all.

If you could help me with playtesting (and just have fun with the mod), I'd appreciate it very much.

Moors, Egypt, and Byzantium would be the most obvious playtesting campaigns, but I'm always looking for feedback from players. Especially if you try to build the mod from sources.

Source Code

Adding the first region was massive pain but thanks to the mod being based on solid source code and not manual messing with files, it soon got reduced to just two steps:

First, edit map bitmap in data/world/maps/base/map_regions.tga, marking new region with some new unique color.

Then, add another entry like this:
    add_regions_to_merc_pool!({
      "Fes" => "North_Africa",
    })
    add_region!({
      :name => "Fes",
      :faction => "moors",
      :rebels => "Saharan_Rebels",
      :color => "57 218 57", # <- the color you used in previous step
      :religion => [0, 0, 90, 5, 5],
      :resources => "none",
      :farming => 3,
      :level => "town",
      :population => 1500,
      :buildings => ["core_building wooden_pallisade"],
      :x => 65,
      :y => 62,
      :commander_name => "Yusuf Hissou", # anything from descr_names.txt, doesn't matter
      :units => [
        "Sudanese Tribesmen", "ME Town Militia", "ME Town Militia", "Desert Archers",
      ]
    })
which the code converts to edits in 5 different files automatically (and then multiplies garrisons a few times due to some other settings).

Oh, and there's also third step of compiling the mod and moving its files to the right place on the second computer, but that's automatable enough.

Credits

Concentrated Vanilla 0.52 uses some files from the following minimods:
  • Sinuhet's Battle Mechanics
  • Lusted's Better BAI/CAI
  • Agart's Cities/Castles Strat

Links

You can download mod here.

You can download sources here.

If you're interested in how this mod evolved, posts about previous versions (with links inside):

Friday, August 10, 2012

Fixing Medieval 2 Total War map

I have a lot of problems with Medieval 2 Total War map. At first it looks quite sensible, with all parts of the map covered by regions:

But that's an illusion, region borders don't matter at all, except maybe for diplomacy - AI gets annoyed when you cross its borders and it can see it - but it gets annoyed by just about anything or totally at random, so it matters little.

What matters is where the cities are. And heatmap of distance to the nearest city reveals something very different:


Now you can see that parts of the map have plenty of cities - and plenty of action - while others are huge gaps where nothing happens.

This map is an approximation - it ignores how difficult terrain is (deserts, mountains), how likely it is that there are already roads there and so on.

Almost the entire Western Europe is fully covered by cities with ton of action. There's also reasonable number of settlements on the entire Northern coast of the Mediterranean - all the way from Cordoba to Marseille to Italy to Greece to Constantinople to Antioch to Jerusalem to Alexandria.

There are a few small gaps like Burgundy, Northern Netherlands, or middle Balkans, but since they have a lot of settlements on all sides, they are an interesting aspect of campaign strategy.

One thing which I feel is somewhat questionable is how natural barriers like Alps which should provide a solid barrier between North Italy and the rest of Europe doesn't - the Alps are very well connected, and the big gap is in Burgundy for some reason. Anyway, I can live with that.

The problem with Medieval 2 map

Outside of Western Europe and Northern Mediterranean the map is filled with huge gaps where nothing ever happens. Every single settlement in Africa is so far from all other settlements it could as well be an island.

You know how Islam ruled the entire African coast, from Morocco to Egypt? That never happens in Medieval 2 since neither Moors nor Egyptians have any way to reach Tripoli or Tunis in reasonable time - or to even reinforce Algiers for that matter. So they become colonized by Italians in every single game I played.

And remote places like Timbuktu, Arguin? It takes so ridiculously long to go there, that you're better off sending just your general and recruiting all infantry on site. They never take part in any action, and neither does Jedda or Dongola which are simply part of a final cleanup after Egyptians have been defeated.

Sparsely settled places like Scandinavia, Black Sea coast, Caucasus, Mesopotamia - all suffer from the same fate of nothing ever happening there. Do you remember having any epic battles over Stockholm, Caffa, Tbilisi, or Algiers in any of your campaign? No way! But I bet most of you can easily recall some great battles over places like Paris, Venice, Antioch, and Jerusalem, or even smaller but well connected places like Bruges, Florence, Zagreb, and Acre see far more action.

This annoys me mostly as a gameplay problem. People often want to extend the map, but one third of it is currently so sparsely settled hardly anything ever happens there. If we connected all these isolated settlements into bigger areas of activity, it would lead to a lot of new fun.

It's also not very historically accurate - places like Asia Minor, Mesopotamia, Northern Coast of Africa were fairly densely populated compared to a lot of places like Northern Europe.

Oh, and the thing many mods do - making the map bigger and adding a lot more settlements, but about evenly everywhere - it doesn't actually fix the problem. If Africa is 50% bigger and has 50% more settlements, it still has small islands of safely held settlements and huge gaps where nothing ever happens.

What should be done?

So the simple question to all of you - which historically important settlements would also enhance gameplay by filling the worst gaps? They should all probably start as rebels and pretty small to avoid breaking balance too much.

Would you like to play on such fixed map? Possibly independently from the rest of Concentrated Vanilla, since I can simply disable all other options in the build script.

Medieval 2 Total War Concentrated Vanilla 0.51

bee by lutty moreira from flickr (CC-BY)

Here's a very small bugfix/tweak release.
  • AI passivity problems should be fixed.
  • Units with missing texture for rebels hopefully all fixed now.
  • Crusade/Jihad/Hordes can now target more settlements.
  • Assassins enabled, since you don't really have to use them if you don't like them. Merchants still disabled, since they annoy me too much.
  • Priests now move with the same speed as spies/assassins (somewhat slower than diplomats/princesses).
  • Attack strength increased from 50% to 60% of vanilla values, since it nerfed AI cavalry too hard, and make spearmen (who still use vanilla +4 or +8 bonus against cavalry, not half of it) considerably too strong against cavalry.
  • Settlement towers now fire strength 3 arrows, so they're somewhat more dangerous to medium-level units.
  • Religious conversion by buildings decreased from 200% vanilla to 150% vanilla rate.
  • Source code cleaned up and now should work with Ruby 1.8 or 1.9 with fewer problems.
Various settings in the mod can be tweaked forever, and "perfect" balance will never be achieved.

Things I'd like to change in the future:
  • People have problem with installation. I might add some kind of logo to the start menu so people know they got the mod running correctly. Installation instructions are below, if you still have troubles do not hesitate to contact me.
  • Some parts of the map - especially North African coast, but also Scandinavia, Ukraine, and Caucasus have too few settlements spread too far apart so they see no action. I don't want to mod the map to the point where it has two times as many settlements, but adding like 5-10 settlements to fill the biggest gaps would be a good idea. I'd especially want Egypt to have a realistic option of expanding to the West and Moors to the East - right now Tunis/Tripoli become Southern Italy in every single campaign, no exceptions. I've never done it, but it seems like adding new regions is relatively simple in Medieval 2.
  • It wouldn't hurt to add a few extra factions like let's say Armenians or Bulgaria, but that would pretty much have to be including somebody else's mod.
  • I'd like the sources to be usable to everyone. If you want to tweak the mod, give it a try, and tell me how it went.

Installation - step 1 (all versions)

First, regardless of your version, find directory where medieval2.exe is located, and put all unpacked files (concentrated_vanilla.batconcentrated_vanilla.cfg, and concentrated_vanilla directory) in the same directory.

If you're playing retail this directory should be something like C:\Program Files\Creative Assembly\Medieval 2 Total War . If you have Steam version, it should be something like C:\Program Files\Steam\steamapps\common\Medieval 2 Total War.

If you have retail version, that's it. Double click on concentrated_vanilla.bat and go.

Installation - step 2 (Steam)

With Steam it's much harder because they added crappy launcher and broke modding.

I recommend removing the launcher completely. Delete Launcher.exe, make a copy of medieval2.exe and rename the copy as launcher.exe.

Then go to your Steam library, select Medieval 2 Total War, right click on it, select properties, Set launch options - type @concentrated_vanilla.cfg in the box, and confirm. Then when you start Medieval 2 Total War from Steam it will load the mod.

Installation - alternative step 2 (Steam)

I haven't actually tested it, but it should work, and is theoretically simpler.

Edit medieval2.cfg and paste this there:

[features]
mod = concentrated_vanilla

Then start Medieval 2 as normally.

Credits

Concentrated Vanilla 0.51 uses some files from the following minimods:
  • Sinuhet's Battle Mechanics
  • Lusted's Better BAI/CAI
  • Agart's Cities/Castles Strat

Links

You can download mod here.

You can download sources here.

If you're interested in how this mod evolved, posts about previous versions (with links inside):

Sunday, August 05, 2012

Medieval 2 Total War Concentrated Vanilla 0.50

Dagje bij Sandra. by Marianne de Wit from flickr (CC-NC-SA)

I haven't played any of the new Total War games in ages, but I keep coming back to Medieval 2 Total War. Since it's so amazingly simple to mod, I tweak a few things before each campaign - either things I didn't feel quite balanced the previous time I played, or just to try something different.

I thought I'd release the current state of my tweaking - Concentrated Vanilla 0.50. It's meant as mild modification to vanilla campaign, fixing bugs, balancing things out, and making the entire game more dynamic. It introduces no particularly drastic changes.

Here's extensive notes on what I changed, why I change it, and which things I tried that I eventually abandoned.

Church matters

Engine used by Medieval 2 Total War assumes characters age by half a year every turns - the way Rome Total War worked. However, since now 1 turn is 2 years not 0.5 year, this means characters live something like 300 years. So very often the initial Pope will last the entire campaign - and you never get to experience papal elections. And since by the time cardinals start dying there's ton of replacements, it's really hard to stuff College of Cardinals. This part of the game gets much underutilized.

One tweak that helps surprisingly much is simply making initial cardinals and pope older. Giving cardinals extra 15 years and the pope extra 25 feels like about the right balance. 20 years older cardinals I tried at first were definitely too disruptive.

Since priests need 5 piety to become cardinals, it still takes some effort to stuff the College of Cardinals, but it's doable.

For a long time I wanted to make Papal missions of "do not attack for or you'll be excommunicated" less annoying. And making Pope and Cardinals older does just that - whenever the Pope changes, most excommunications expire (I think you only remain excommunicated if you're at was with Papal States, but I could be wrong here). Unless of course Pope called a Crusade against you and you're now at war with the entire Europe...

You're free to ignore all of this, but now you have more options for getting involved into Church politics.

Another minor change I did was doubling conversion rate from all religious buildings. I don't particularly care for spamming Priests or other agents as a gameplay element.

Crusades

Crusades and Jihads are tweaked a bit. Most important of all, there's no penalty for not going in the direction of the Crusade target. I disabled it since it was extremely buggy feature - it often triggered even when you were taking the most direct route towards Crusade target - and AI cheated since it never applied to it no matter what. It's up to you - either have a house rule that you're going to be honest with it, or have a house rule that you won't.

A few minor changes - Crusading can start right away (the same way as Jihads), and minimum piety to call Jihads lowered to 2 (otherwise if you played a Muslim faction and your initial Imam died unexpectedly, this part of the game would be turned of for a very long time).

I sometimes play with allowing every settlement to be Crusade/Jihad target, but that's a bit too easy to abuse, so it's currently not enabled.

Reduced agent spam

I seriously dislike spamming agents, and agent gameplay in general, so I removed as much of it as I could.

I removed merchants and assassins completely - merchant gameplay was unfun (and really asked for save&load abuse), and assassins matter very little with their tiny success chance, and new family members coming via adoption pretty much all the time. Merchant buildings and guild still provide trade bonuses to your settlements, so they're still useful.

Priests are impossible to disable without breaking papal elections and Jihads, but with religious buildings providing double the conversion bonus they're less necessary to spam.

Diplomats and princesses travel at 5x baseline speed (on top of general 1.5x campaign movement speed increase, so 7.5x faster than in vanilla), so you need fewer diplomats, and have more options to arrange marriages for your princesses before they get too old by the time they reach the other side of the map.

It's possible to remove spies, and I often play without spies, but then nobody forces the player to recruit them, so it's fine to leave them be. They travel at 3x baseline speed (on top of general 1.5x speed increase, so total of 4.5x), so they can actually do some spying where they're needed.

Heretics, witches, and inquisitors are all optional gameplay elements, but since the player doesn't control them, I let them all stay. 

Settlement economics

I did a lot of experimenting here, but it's not included in the mod, since it strays pretty far from vanilla.

Some thing I tried that are not included - and they work pretty well if you're looking for variety - single settlement type like in Rome Total War; core building (city wall or castle) doing features of all buildings it enables (except churches and ports which cannot work for technical reasons); removing all generic units so that all factions get to fight with their special units from the start etc.

I tried to increase either resource value or trade bonus value, and this always resulted in everybody being flooded in money, so I stopped doing that. Another thing was rearranging resource values so something else (like amber) was extremely valuable for a change. It turns out it doesn't make that much of a difference - remote places like Baltic Sea have too few tiny settlements to ever match economies of the Mediterranean even with this boost.

Things that are included (as in previous versions)  - mine bonus is 2x, all buildings build in one turn and cost 50% extra. I stopped making mines cost 3x since AI then was too stupid to actually build them. AI is still pretty stupid with building things.

I increased population of all villages to 800 (minimum needed to upgrade them to small town), as otherwise you'd always change them to castles so you can start building something there.

An extra thing I've done was making guilds much easier to get - you still need to do a bit of effort if you want a particular guild, but it's not as unreasonable as it was in vanilla. It's not balanced between guilds so it might turn out to be too easy perhaps. IIRC if you have a few of your generals join crusades, it will make all crusader knight orders ecstatic and offer their buildings all over the place - offering you an extra incentive to join crusades.
Maine Coon - Creative Commons by gnuckx by gnuckx from flickr (CC-BY)

Unit recruitment

Now cities can have bigger free garrisons (up to 12 units for huge cities). I sometimes play with castles also having free garrisons of mid-level infantry, but this is currently disabled - partially because it helps some factions much more than others, and partially because AI is really dumb and has no idea how to take advantage of it.

I tried to make unit retraining use no recruitment slots like in Rome Total War, but this doesn't work, even though there are entries for in it XML files.

One thing that works really well is making mercenary pools much bigger. Currently they're at probably somewhat excessive 2x initial size, 4x maximum size, 8x replenishment rate - whenever I try something new I go for very high multiplier, I then tone it down if I don't like the result - and here I really don't mind much no matter how high it is, so I never bothered tuning it down.

Extra mercenaries help AI a lot - if you face crusades prepare for 10 stacks of crusading knights and sergeants before it ends. Now it's entirely possible to abuse it and play with just mercenaries ignoring your faction's units, but I never actually do that (just a little when I'm crusading myself).

Primarily to help AI not destroy its economies, I lowered all units maintenance cost to just 60% of vanilla values (in addition to larger garrisons being free). This means you'll be facing much bigger stacks. Agents' wages are the same.

I didn't tweak costs or upkeep of different unit classes since I balanced them differently (read on).

Settlement defenses

I probably overdid settlement defenses in my early Concentrated Vanilla so it's milder now.

Tower fire rate is 3x for normal missiles and 1x for fire missiles - but power of arrows is down from 12 to 2 - so while it massacres unarmored Town Militias happily, well armored Knights can fight quite long while being shot at with only moderate losses. This is a pretty decent balance overall.

Ballista and cannon towers are as powerful as before and they still get 3x fire rate. In vanilla they were often weaker than arrows, since you just need to get close to the walls fast, and you were out of their range instantly.

More important than this - distance units need to be to enable towers is 4x. This is about the best balance I could get for interesting battles - pushing defenders far enough from walls to disable the towers is hard but not too hard.

Taking over decently defended stone Castle or Fortress without some serious artillery is now going to cost you massive casualties, especially if you just plan to throw masses of low level units at it. 2 units of Ballistas to storm a castle and 2:1 ratio in infantry are pretty much a minimum, and I'd recommend at least 2 Catapults unless you're going for Pyrrhic victory.

Battering rams are now much weaker to make gates more meaningful.

There's also one thing I did that makes settlement defenses a lot weaker - in vanilla defenders will only sally out if their (AI-judged) strength ratio against attackers is 2:1 or better. I lowered it to 2:3, so they'll sally out even when they're slightly weaker, instead of waiting inside. This sometimes benefits AI, more often it doesn't, but it sure as hell makes things a lot more interesting.

The worst battles are when AI stands there doing nothing - as it sadly usually does when you sally out with some shooters and it just stands there not even bothering to shoot back. This seems to be a bug, but I have no fix. I much prefer stupidly active AI to stupidly passive AI (since it's rarely actually smart), so I like more frequent sallying out. (only in battle, campaign sallying out is hardcoded, and I cannot influence it)

Plaza capture timeout is reduced from 3 minutes to 1 minute. 3 minutes was far too long to be of any use - now you can win battles with some smart maneuvering, but it's pretty hard to do so.

Bug fixes and small tweaks

And speaking of bug fixes, there's a ton. "Everyone hates you bug" is fixed. Turn number is displayed as year, not as turn (which is not technically a bug, but it annoyed me as hell).

I removed rubber swords from pikemen, which makes them a lot more powerful as well, but units are rebalanced anyway. I removed "fire by rank" from gunpowder units since it was mostly just bugged.

In Rome Total War settlement center was considered defended as long as at least 1 soldier stayed there. Medieval changed it to 4:1 attackers to defender ratio, but nobody told AI so AI often stands there thinking it's playing Rome, while attackers take over settlement without a fight. So I changed it to 20:1 ratio, which doesn't occur in practice and is less annoying than "infinity:1" and  stray fleeing defender won't reset your timer when he gets to the square. (and timeout is 1 minute not 3 minutes now).

I tried to reduce Captain Obvious telling you "we're under attack, we must do something" all the fucking time, but I failed. If there's a fix I'd like to see it.

Naval autoresolve is tweaked so naval battles can actually sometimes be decisive, but if it does something, the effect is pretty small.

I'm somewhat annoyed by adoptions in Medieval 2, since they are very inappropriate for the period. There's no way to disable them, and I tried just about everything. The best I could do was making everyone super-fertile since there's a limit of 4 children (adopted or natural) per couple, but that was ridiculous as well.

Then I checked some history books, and it turns out that while Roman-style adoptions weren't that common (but still happened occasionally!), other forms of arranged succession by marrying king's widow, or some niece, or some other relative was actually happening all the time, especially in the Middle East (Byzantium, Islamic states, Crusader kingdoms etc.).  So just think about it as "do you want this guy to marry your second cousin", not as "do you want to adopt this guy", and it might bother you less.

Campaign timing

I often play with big events like gunpowder, discovery of the New World, Mongol/Timurid invasions happening earlier, but currently it's all back to defaults, except crusading can start nearly right away.

One big change on campaign map in the mod is that all rebel settlements now have a lot more defenders, and often pretty decent level defenders, so you cannot just blindly blitz 10 settlements before turn 10. I think I screwed up unit lists and gave rebels a few units for which they have no proper textures (textures in Medieval 2 are per-faction, so giving a faction another faction's units is not as easy as it sounds) so you'll be fighting very shiny enemies in a few settlements, but it's not big deal. I'll get it fixed eventually. Incidentally giving rebels massive stacks of units is precisely what they've done in Empire Total War, except they're called "minor factions" there, not rebels.

A few times I played with all settlements upgraded one or two levels, and all factions getting two stacks of high level units for fun, or pre-configured wars, but currently it's very close to vanilla except with that blitz slowdown.

It slows you down more than it slows AI since AI can cheat with autoresolve and you're presumably fighting well defended settlements honestly.
Anton by Marianne de Wit from flickr (CC-NC-SA)

Unit rebalancing

And now for the biggest change in the mod - rebalanced unit system. Unfortunately vanilla is so ridiculously out of balance that it's necessary to do some pretty drastic things here.

A single change that gets really close to restoring balance is cutting melee and missile attack by half. The results are so amazing that I disabled most of my other balancing hack.

It's not entirely clear how "cutting some number by half" translates into actual fighting, since Medieval 2 has very complicated system with huge number of modifiers for everything and it even includes attack animations in its calculations somehow.

But now a single cavalry charge doesn't end the battle, flanking makes a huge amount of difference, and stamina and managing reserves is surprisingly important (since in infantry-vs-infantry battles everyone tends to last a lot longer).

Missile infantry ammo is still doubled, quite appropriately now since their missiles do less damage now. As I said before gunpowder units do not have to use formations (if you ever get far enough to play them). One thing I did what giving all archers (even Peasant Archers) stakes, to differentiate them from crossbowmen and introduce more tactical diversity. You won't get to use stakes all that much, since usually you're the attacker, and sadly AI doesn't seem to use them ever, but it's more fun this way.

The only other change was massively improving artillery. They have 2.5x ammo, partially to balance lower attack strength. They have 50% more units - so artillery units which used to have 2 now have 3. I tried giving them 4 but maneuvering with that completely broke pathfinding - it's still really hard for them to maneuver in inner circles of Fortresses and Citadels where you need them most. And most important of all - their accuracy factor is 2.5x higher.

What does 2.5x higher accuracy mean? Well, they're ridiculously better than they were before on the battlefield. In optimal situation where your opponent stands idle doing nothing, which sadly happens sometimes, your artillery can be really murderous. If there's a proper battle, usually you'd still would rather have Pavise Crossbowmen instead, and whatever is their attack power, artillery is really bad at defending itself so it works better as part of a balanced army than in any kind of spam (the way you can spam heavy cavalry or crossbowmen).

Another issue is that AI really overbuilds artillery - and instead of fixing AI, why not actually make what it's doing smart instead of dumb?

Sources

This time I'm uploading sources for the mod as well - the mod consists of a big library of functions performing various changes and a short control block calling these functions to assemble the mod, currently this (removing comments):

M2TW_Mod.new do
  ### Settlement
  construction_time_one_turn!
  building_cost!(1.5, 1.0)
  religion_bonus!(2.0)
  mine_resource!(2.0)
  villages_800_people!

  ### Unit recruitment and upkeep
  big_garrisons!
  more_recruitment_slots!
  unit_cost!(1.0, 0.6)

  ### Basic settings
  plaza_capture!(1.0, 0.95)
  fix_standing!
  more_mercenaries!
  show_date_as_year!
  ### Captain obvious
  reduce_captain_obvious!

  ### Crusades
  fast_crusades!
  min_jihad_piety!(2)
  no_crusade_disband!
  older_cardinals!

  ### CAI
  fix_naval_autoresolve!

  ### BAI
  sally_out_ratio!(0.65)
  stronger_ratio!(0.65)

  ### Agents
  remove_agents!('merchant')
  remove_agents!('assassin')
  campaign_movement_speed!(1.5)
  agent_speed!('diplomat', 5.0)
  agent_speed!('princess', 5.0)
  agent_speed!('spy', 3.0)

  ### Guilds
  easy_guilds!

  ### Units
  missile_infantry_ammo!(2.0)
  all_archers_stakes!
  artillery_range_ammo!(1.0, 2.5)
  artillery_size!(1.0, 1.5)
  mod_unit_attack!(0.5)
  nerf_rams!
  increase_artillery_accuracy!(2.5)

  ### Units - bug workarounds
  fix_rubber_swords!
  no_fire_by_rank!

  ### Sieges
  wall_control_area!(4.0)
  tower_fire_rate!(3.0, 1.0)
  rebalance_wall_arrows!
end

I'm not putting it on github, since the mod also includes some third party files - some from vanilla Medieval 2 Total War, some from other mods - Sinuhet's AI tweaks and Cities/Castle Strat v1.0, and I didn't get proper permissions or anything since it was really meant for my personal use only. Hopefully nobody will be angry enough with me for it.

Personal use only, no warranty, don't sue me etc. etc. Install Ruby (I think JRuby should work just as well, and it's probably easier to install), tweak make_vanilla_dynamic.rb to your liking, then run it, then the mod will be produced in output directory (and don't actually delete that directory, some files there are not recreated, they're just static stuff needed to make the mod work, copy it out instead)

Credits


Concentrated Vanilla 0.50 uses some files from the following minimods:

  • Sinuhet's Battle Mechanics
  • Lusted's Better BAI/CAI
  • Agart's Cities/Castles Strat
They are all optional, and if you want you can rebuild Concentrated Vanilla without them by just removing their files from data directory.

Links

You can download mod here.

You can download sources here.

If you're interested in how this mod evolved, posts about previous versions (with links inside):

RLisp is on github now

Buddha Belly by windy_sydney from flickr (CC-NC)

Continuing cleanup of my old software, I uploaded RLisp to github, cleaned it up a bit and made it compatible with both Ruby 1.8 and 1.9.

Stack backtraces with 1.9 seem somewhat less informative now, but they were pretty mediocre to begin with. Other than that and an small example involving complex numbers (1.8 Complex#new is 1.9 Complex#rect), it all works just the same.

Rakefile to build Debian/RPM packages is most likely broken, but if anybody cares it's probably just a matter of fixing a few paths, so send me a pull request if you do.

I would really love to build a gem for that, but I don't know how to build binary gems, and RLisp includes a small C program to make #! work correctly (99% of functionality works fine without it).

Another thing - how the hell should RLisp / Rlisp / rlisp be capitalized? I wrote it years ago and I still have no idea.

Saturday, August 04, 2012

7 Languages in 7 Weeks

Maine coon kittens by eleda 1 from flickr (CC-NC)


I got Bruce Tate's "Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages" book ages ago, but like with all books which require significant active effort it gathered dust on my bookshelf for quite some time. Now that I've read it and did all the recommended exercises I must say it's absolutely awesome!

The book introduces 7 diverse programming languages, and for each of them it skips generic hello world nonsense, and dives directly into what makes each of them special.

Each chapter was a lot of fun even though I had some (or pretty massive) amount of experience with some of the languages in the book.

I put my solutions to the exercises on my github in case you're interested, but I recommend not looking at them until you try to solve them yourself.

1. Ruby

Ruby is the most questionable inclusion in the book, since of the kind of people who read programming books for fun, every one of them already knows Ruby. Fortunately the book mostly focuses on metaprogramming, so it won't be too boring for most people who know some basic Ruby.

Another good thing are all the "compare how solves " exercises scattered throughout the book - small but important things you don't normally notice about languages.

2. Io

This is by far my favourite chapter. Io has absolutely insane programming model vaguely resembling message passing.

In "normal" Smalltalk-style message passing the basic operation is:
send(receiver object, message identifier, list of evaluated arguments passed by value)
Ruby, Javascript and all other proper object-oriented languages all do more or less the same thing with some minor complications.

What Io does is completely reversing this:
send(receiver object, sender's lexical context, message s-expession)
If receiver wants to evaluate arguments in the s-expressions (OK, it's not literally s-expression, it's just the best analogy I could come up with, call them ASTs if you wish) - which it does 99% of the time, it sends them back as new messages to sender's lexical context. And there they're evaluated by lexical context object (which doesn't have particularly much to do with sender object).

For "normal" messages it's syntactic-sugared sufficiently that you don't have to think about it.
fib := method(n,
  if(n <= 2, return 1)
  return(fib(n-1) + fib(n-2))
)

Here, since method(n, body) has multiple arguments, first argument is evaluated (in sender's lexical context) and assigned to n, then body is evaluated.

But how do you implement high-order methods? Why, by subclassing sender's lexical context of course. I'll let the awesomeness of this sink in for a bit.

Here's Matrix foreach method I wrote for one of the exercises (it's not directly anything they're ask for, so it's technically not a spoiler):
Matrix foreach := method(
  args := call message arguments
  xi := args at(0) name
  yi := args at(1) name
  vi := args at(2) name
  msg :=  args at(3)
  ctx := Object clone
  ctx setProto(call sender)
  for(i,1,xsize,
    for(j,1,ysize,
      ctx setSlot(xi, i)
      ctx setSlot(yi, j)
      ctx setSlot(vi, get(i,j))
      msg doInContext(ctx)
    )
  )
)

First, since method( ) has only one argument (function body), there's no automatic evaluation. Instead we parse argument, extracting names for the first three, and msg for the last.

Then we subclass sender's lexical context into ctx, set some variables in it with setSlot message, then send msg (body which was passed to our foreach as 4th argument) to ctx. Why does it work? That's because evaluating anything is sending a message to some lexical context. Our entire function body is one big message consisting of a sequence of smaller messages like yi := args at(1) name and ctx := Object clone.

Unfortunately the book focuses mostly on prototype-based programming part of Io, while Javascript and even Ruby do that much just as well. The brilliant insanity hidden within Io is barely scratched. I recommend playing with it a lot more than the book recommends.
maine coon kitten by dirk huijssoon from flickr (CC-NC-ND)

3. Prolog

If the first thing which comes to your mind when someone mentions Prolog is sudoku solvers, you're right! If you've never done any Prolog, it's a fun few evenings to spend.

Sadly in my experience programming in Prolog is about as practical as "programming in SQL" or "programming in XSLT". It's not really a programming language, it only pretends to be one. If someone took good ideas of Prolog and implemented them as an extension for a real programming language, it might be getting somewhere.

4. Scala

It feels like modern version of Ocaml in so many ways. Not only it's statically-typed mostly-functional somewhat-object-oriented language, they've thrown everything including a kitchen sink into the language and added such massive amounts of syntactic sugar for each of its features it all looks really weird and gets you thinking that there's surely some simpler syntax which does most of these things just fine.

Scala seems to have significantly less awful standard library than Ocaml - I'm not really a big fan of Java libraries so many people fawn over so much, but just about anything beats the pile of mess Ocaml standard library is.

Scala's syntax, while it won't be winning many converts, is still the best I've ever seen in an Ocaml-like language. Its feature set also looks like mostly a nice improvement over what Ocaml has.

So I'd recommend giving it a serious look if you're an Ocaml programmer.

5. Erlang

I blogged about my first impressions of Erlang a few years ago, and giving it another go didn't really change that much.

It's the Ocaml Symptom all over again - it was developed in isolation from the mainstream programming world, so its standard library is awful mess, syntax is awkward as hell, and all the small things other languages get right (like having string type, or ^D to exit) it gets totally wrong. In this case it was isolation at Erlang not in the academia, but it's a very similar problem.

Now by throwing some significant effort and abandoning concern for backwards compatibility you could probably turn languages like Erlang and Ocaml into something actually good, but nobody seems to have any intention of doing so.

This shouldn't stop you from playing with it a bit, but using Erlang in production environment? I don't think so.
Ragnificent Ragdolls - Peekaboo by DirtBikeDBA (Mike) from flickr (CC-NC-ND)

6. Clojure

Lisp is my favourite language I never actually use. Clojure is trying to do something vaguely similar to RLisp - being a sensible Lisp integrated with an object-oriented environment in existing VM (Ruby's vs JVM). And just like RLisp Clojure also attempts to fix one of the worse aspects of Scheme and such traditional Lisp dialects - far too many completely worthless parentheses.

It makes some very different choices too, and that's part of the beauty of Lisp - you can stretch the concept of Lisp really far, and it's still Lisp in the end.

Anyway, If I accidentally win a few billion drachmas somehow, I'll hire a bunch of people to turn RLisp into a real programming language.

7. Haskell

Haskell is a wonderful programming language - I'm surprised it's not used more in psychology as it'd make for some really great case studies in Stockholm Syndrome.

Here's a stylized history of Haskell design, in which they've been digging themselves deeper and deeper with each decision:

  • Traditional static typing doesn't handle high level functions well, so let's add a really sophisticated type system.
  • Our new sophisticated type system requires too much typing, so let's add type inference.
  • Type inference cannot handle programs with mutable state, so let's remove all mutable state.
  • Without mutable state we cannot actually do much, so let's add monads.
  • Nobody understand monads, so let's make hundreds of tutorials "explaining" monads in terms of containers, astronauts, dragon liars, and high grade nuclear waste.
  • and so on

What's surprising is how many Haskell programmers don't understand that monads are simply a hack to make I/O in Haskell bearable, they seriously think monads are the greatest thing ever which should be ported to programming languages that don't really need them, and everything else Haskell did as a part of general digging itself deeper and deeper is the One True Way to Program.

Disregarding that rant, while monads (and comonads, and arrows, and the rest of such insanity) have no place in any sane language, they are fun to play with for a bit.

Summary

I really recommend this book. It's not meant as a way to learn any particular programming language (and except for Ruby and arguably Scala/Clojure, none of them are remotely suitable for production use), it's a celebration of diversity of programming languages.

Or at least it will give you better arguments for your rants.