Thursday, August 19, 2010

Stuff I've been reading

"Zoe's Tale" (John Scalzi) - I really enjoy the "Old Man's War" universe, and Scalzi's style. That said, I am rather disappointed with this one.

Zoe's Tale is basically a retelling of "Lost Colony" from the point of view of Zoe. In the Acknowledgments, Scalzi tells how he thought this book would be easy - but it turned out very hard. Given his rather low bandwidth (one per year, which is typical for authors), I'd much rather see a new story.

I don't like to reread books. This one was different enough, and it has been long enough since I read LC, that I wasn't bothered. It was somewhat engaging; although it is more characterization, where the other OMW books focus more on events.

Wednesday, August 18, 2010

Since You've Been Gone

I couldn't hurt anymore
if you dropped a two-ton bowling ball on my toes

Since You've Been Gone
(O Since You've Been Gone)

You know I've been in a butt-load of pain
Since You've Been Gone


I feel almost as bad as I did
When you were still here!

Friday, August 13, 2010

Stuff I've been reading

"Claws That Catch" (John Ringo) - It's been a while since I've read any SF. Ringo comes through again!

The main thing I like about Ringo is brevity. This book is 343 pages long, compared to 600-800 for somebody like Stephenson.

Ringo captures the "hurry up and wait" and "long stretches of boredom, followed by moments of terror" of military life. There is no encounter with the enemy until page 278 - yet, he makes the "boring" parts interesting and funny (along with providing good characterization).

The closing action is as good as any you will find (with boarding actions, giant space battles, and fighters).

I hope Ringo keeps writing lots of books!

Thursday, August 12, 2010

NewStars Status

Whew, been a while... I have been putting off work on NewStars. I was afraid of "GUI load/unload", that is, the shuffling of cargo using the GUI. These orders have a separate order type from "Waypoint 0" (both happen before move). I was worried I would need to evaluate these orders in order to show the current levels on planets and in ships. Then, I would need to hide the orders in the order box, yet update the orders when the GUI instructs.

I figured out a way around all that. I left the GUI orders in place (visible and not evaluated) for loading/unloading to a planet. For ship-to-ship, I edit the XML (the reconciler handles edits in the XML).

The basic GUI is now ready:

Here we can see a transfer between the medium freighter and colony ship for player 1. The orders are executed when the window closes (I should add Cancel and Ok buttons...)

With that, everything needed to play is in the GUI!

Tuesday, August 10, 2010

Stuff I've been reading

"S is for Silence" (Sue Grafton)(audio) - I should gather statistics on how many people are killed in California. It seems like all of them are near (or killed directly by) Kinsey Millhone...

Monday, July 26, 2010

Stuff I've been reading

"N is for Noose" (Sue Grafton)(audio) -Meh.

Monday, July 19, 2010

Robot Builder

(continuing my review of Facebook games)

I previously mentioned a group that made several good games. The best of these is Robot Builder.

Robot Builder originally suffered from the same Add Me effect that most games have. Then some sort of bug caused them to remove it (this was before I started). They never did re-enable it, which turned out to be a great decision.

Game play is pretty simple. You have several resources to manage: energy, money, and robot tokens (RT, this is how they raise money, you can buy RT - although you can also find them in the game).

Energy is refilled at 10 per 15 minutes (as opposed to the typical 1/4 or 1/5). This is somewhat irritating early in the game, when you only have 10 or 11 max.

Your goal is to build robots. There are many different areas to salvage through (which take energy and money, sometimes RT). You can also do different "fights" in the arena - but these are basically different areas which can only be explored once per hour (or four hours, I forget).

You mainly raise money by selling parts, energy refills automatically, and you find RT. Different robots allow access to different arena fights, new areas, or give you additional energy storage.

Not a lot to see.

The hidden gem in this game is the market system.

The market allows players to trade items for RT. You can sell your rare parts (any parts really) for RT, and buy the parts you need. Or buy parts to sell for cash (giving RT a value in cash).

Being a market, there are tidal effects (as players sign off for the night, or sign on in the morning). This creates timing opportunities. You can buy parts when there are many players online as an investment, then sell them off when the market is short. You can also try to corner the market (by buying all the parts others supply, and holding out for higher prices).

This gives the game a lot of playability - even when there is no new content. It does require a large number of players to support the market. Sadly, total abandonment by the developers has pretty much killed this game.

Tuesday, July 13, 2010

Stuff I've read lately

R is for Ricochet (Sue Grafton)(audio) - It's interesting to bounce back and forth in the series (as library availability allows). The last book was from the 80's (or early 90's) and was 6 CD's. This book is from 2004 and is 10. There is not >50% more story...

I was especially disappointed that there was no ricochet. It is funny to hear a story about old time computers (carried in rolling luggage) and handfuls of floppy disks.

Monday, July 05, 2010

Frontierville

(continuing my review of Facebook games)
A quick word of warning about Zynga games (Mafia Wars, Farmville, Frontierville, among others). They are pretty public about how evil they are. They will sell you email to spammers, and do anything to spread to your friends and install toolbars on your browser. If you play their games (and I can't recommend any of them), make sure to use NoScript, Adblock, etc. and don't give them your email, make sure you block them from your wall and friends, etc...

So, continuing on the massive failure that is Farmville, there is now Frontierville.

The game mechanics (and engine) are basically the same - you have a set of land, on which you place buildings, crops, trees, and animals.

There are a number of changes, most of them bad: energy, wilderness, varmints.

Energy
In Farmville, you could plant your whole board in a 4 hour crop, come back in 4 hours and harvest it all (assuming you had the money). In Frontierville, every action takes 1 energy (like the energy in Mafia Wars). Of course, in Mafia Wars I have 1900 energy (at 1 energy per 5 minutes, that is 8 days). In Frontierville, I have 15 energy.

This does introduce some interesting strategy changes.

Now, you must pipeline out some crops in order to maximize experience. You can't just look at xp/hr, you must include energy as well (since all actions are 1 energy, this amounts to xp/crop). So, 3 day crops are the best, but you can't just fill the board with them. You have to stage them out, say 1 hour apart, 9 at a time (not 12, more later). This creates some interesting effects, when you start with a blank board, and want to scale up to a big harvest in 2 or 3 days (say over a long weekend). You lay down 9 of the 3 day jobs, and 9 one hour jobs (for when you come back). Then, in an hour, harvest and lay down 9 more of the 3-days. Rinse and repeat.

Wilderness
The wilderness is a huge pain. Your board is not open like in Farmville. It starts covered with all sorts of junk, which you have to expend energy to clear. Worse, the stuff grows back.

Varmints
This is probably the worst feature of all (especially when compounded with the other two). Every action has a chance to spawn a varmint (different ones for different actions). The varmint will block the 8 adjacent squares, forcing you to deal with it or pay 2 energy for actions. It takes 3 or 4 energy to remove a varmint (hence the 9 crops for a 12 energy period). If you luck out with no varmints, you need the energy for maintaining the wilderness anyway.

The game's isometric view is especially painful here. One time, I was clearing some trees, and a bear appeared. It was hidden behind a big tree, so I had to pay 2 energy times 12 to clear that tree!

Co-op Play
There is one nice new feature. In Farmville, you could visit your friends' farms. There you could get some extra xp and money by "helping out" (which actually did not help them at all). In Frontierville, you can actually help. This makes things a little better, but is not usually reliable enough to impact planning. You usually have more things than you have energy for, and friends can help there.

The game has just started, so it might get better - but probably not.

Saturday, July 03, 2010

Farmville

(continuing my review of Facebook games)

Farmville is a really bad game. Shockingly bad - especially considering how many people play it (Wikipedia claims 80 million installs).

The game mechanics are very simple, you have a set of land (which gets bigger as you progress) which you can fill with crops, trees, animals, and buildings. Buildings serve no point, except to give you experience points (and look pretty).

There is an interesting trade-off between crops and trees/animals.

Every unit of production has some cost, and produces some experience points and money. Trees and animals produce repeatedly, while crops are one-shot. Also, crops will expire (wither) if they are not gathered after reaching term - while trees and animals will keep indefinitely.

The optimal strategy is to maximize your return in money and experience (money can buy experience) for the land you have, and the time you have. If you can dedicate lots of time, you can make a lot of money and experience very quickly.

Higher levels give access to new crops, etc. but this is of limited effect. You have your spreadsheet of $/hr and xp/hr, grouped into time groups (4 hours, 8 hours, 1 day, etc.). Based on your schedule, you put down some crops. If you aren't sure when you will be back, you can invest more in trees or animals.

At some point they added vehicles, which reduces the tedium of plow/plant/harvest some (a vehicle can do 4 at a time). Not really worth the time, though.

Friday, July 02, 2010

I'm a Wiener

(continuing my review of Facebook games)
I got style, I got grace.

Perhaps the saddest part of Facebook games is the lack of winning.

For some reason, game designers think that if they don't have an ending, and don't declare a winner, people will just play forever.

Of course, this requires a steady rollout of new content. So really, you're just playing new games with a steady increase in gear - which leads to massive inflation (old gear becomes useless).

Usually, the developers can't keep up with the rate of consumption, and the game dies anyway.

So, ironically, the very attempt at creating a unending game ends the game (there's a sermon in there).

Friday, June 25, 2010

Stuff I've read lately

"D is for Deadbeat" (Sue Grafton)(audio) - This book actually covers some of Grafton's view of Christianity, and its not positive. Still, the book was moving in a way that these usually aren't.

Monday, June 14, 2010

Stuff I've read lately

"C is for Corpse" (Sue Grafton)(audio) - It was ok.

Friday, May 28, 2010

git rebase /home/you us

(That's "all your base are belong to us" in git-speak)
I think I am starting to get the hang of git.

The key is not to think of "versions" of the codebase, but rather, in terms of "patches". Git is not "version control" it is "patch management".

The rebase command is an excellent example of this, and it is really unusual and powerful (which can make it dangerous).

The best thing about it, is that it allows you to avoid the "shoulda syndrome".

For example, imagine you are working on a new feature. You spot a bug, and fix it on the spot.

In cvs or subversion, you have violated the "shoulda" policy dictated by these tools. You "shoulda" put your current changes somewhere else (or used a new area, I have about 4 local copies of my svn work project).

Now, in order to commit just the fix, you are going to have a lot of pain and suffering to split things out, test it, and commit it, then merge back.

But in git, there is no "shoulda". You can fix that bug, and carry on with life.

How so?

First, you need to get all your changes into patches. Use "add -i" (interactive) to get everything in (add interactive allows you to commit individual lines from a file, if necessary). Then you can use branches to test just the patches you want to commit.

The real power comes from rebase.

Rebasing is confusing (and potentially dangerous), because it allows you to edit the history of the repo.

It is also two different commands in one.

The first command is plain rebase (git rebase <relativeHead>). This is used in place of "git pull" to update a working branch (keeping it relative to that branch, rather than merging).

The second command is editing history (git rebase -i <relativeHead>). This allows you to shuffle the order of patches, and merge patches.

So if the patches to your working area are:
trunk
Start of new feature
Additional feature
More stuff
Bug fix

You can shuffle the bug fix up to right after the branch from the trunk. You can then push that patch into the trunk. Your working area is clean, and you don't have to bother the trunk with all your intermediate commits.

Thursday, May 27, 2010

Stuff I've read lately

"B is for Burglar" (Sue Grafton)(audio) - Much better than the previous book. Grafton stays away from the romance novel feel, and the narrator is much better. My only complaint is that the ending is over the top (especially in light of the last book).

Friday, May 14, 2010

git clone harrier

Well, I've started to get a feel for git, and it is not a good feeling.

It is the sort of, hollow, cold feeling you get when you see a Pat bus driving down the street.

I have been reading a lot, trying to figure out what is going on.

For personal projects, it is fine. If a little weird. "git commit -a" (not recommended, but sometimes you want to save some typing) misses new files. git diff doesn't always work right (show me what I've changed), sometimes you need to say "git diff HEAD".

At work, it has been more disastrous.

I admit, the first time, I gave it the hardest possible problem. I branched, then reformatted all the code. The next merge was totally hosed.

Ok, that was a hard problem, I can forgive that (although git seemed even more confused than svn - I find svn merge to be very good, git feels closer to the old cvs merge).

Then, I made some straight forward changes on another branch.

Still I get all sorts of weird merge conflicts.

Ugh.

I have had some success messing around with rebase. Still not convinced it is a good idea...

Wednesday, April 14, 2010

The Tcl War

Weird thing came up twice on the web in the past two days. First was a search for "Tcl nntps", the second was on Reddit.

I've always been an admirer of Richard Stallman. Although I prefer vi to emacs, and GNU Hurd seems like total vaporware, you have to admire the impact Stallman has had, and his consistent application of his values.

But now, I'm afraid I will have to charge him with heinous war crimes against humanity!

His objections are pretty weak (no linked lists?, slow adds?). And to suggest Lisp as a replacement is just silly. Tcl syntax is weird, but Lisp (from Wikipedia)?

(let loop ((n 1))
(if (<= n 10)
(begin
(display n)(newline)
(loop (+ n 1)))))

I have no idea what that does. I think it prints the numbers one to ten...
In Tcl:
for {set i 0} {$i <= 10} {incr i} {
puts $i
}

A lot closer to C. Actually, Tcl has gotten a lot easier for me once I started thinking of it as a prefix type language (like Lisp). Just with [] and {} instead of ().

Saturday, April 10, 2010

Delight

(Continuing my experiences with the D programming language) Hmm, missing some back links before this.

I have been looking into what it will take to program my video card (Nvidia GeForce FX 5200). It's embarrassing how little information is out there. Nvidia used to maintain an open source driver - which only supported 2D. Given their refusal to support 3D, I have to wonder about the quality of the 2D support. There is a project to develop 3D support, but their focus is newer cards (and they are short-staffed).

I've been itching to write a cycle based processor model, and it seems now would be the best time. To mix things up a little, I've decided to write in D.

I've been working (on and off) about a week now, and I must say that programming in D is quite delightful.

Best parts:
  • No IDE needed - I use vi and make, and its no problem at all
  • Enums auto-namespace - all the enums are like RegBytes.BH, no need for crazy C++ kung-fu
  • Built-in array - being able to write:
    mem_[startAddr..startAddr+img.length] = img;

    with auto-bounds checking is a lot nicer than fighting with the dangers of memcopy
  • Writefln - writefln("Null in decoder for byte: ", "%x", op); (format as needed)
I haven't had any real negative experiences. I need to figure out how dependencies work. I'm not sure when I need to recompile a module based on what it imports. I've had to do some make cleans.
There are some gotchas for hardened C++ users, but they are related to improvements:
  • struct and class are different - this is a good thing, but it can be easy to forget. A struct is plain-old-data (like an int), so it is allocated automatically. A class is a pointer, so it defaults to null. You need "ptr = new Class" before you can use it. I ran into this once.
  • Circular import dependencies - you have to avoid them. Sometimes this means you need to break some stuff into a separate file. C++ solves this by using includes to toss everything into one big stewpot and doing multiple passes.

Friday, April 02, 2010

Hello, Graphics World

Of course, a screen shot can make it look like you are much further along than you really are...

I don't have interrupts (so no disk, or keyboard) and I can't create processes, but I can (almost) print "Hello world".

Except, I can't print capital letters, or spaces...

Monday, March 29, 2010

Bugs

With all these successful screenshots, you might think this stuff just turns out correctly on the first try... here is a good example of how tricky it is to get everything right:

I am trying to print the 'H' in "Hello world". It should line up in the upper right of the black box. Instead, there are sets of white pixels spread out in the middle of the screen (look closely, they come in pairs spread apart, with one solid line - the bar of the 'H').

This tells me two things:
  1. My starting point into the video memory is short by about one xterm height
  2. My next row code is off, by maybe 6 or so

Sunday, March 21, 2010

Console Coming Soon

This was a lot of fun!

I am supposed to be enabling interrupts (which will require turning off the PIC, configuring the IOPIC, and enabling the local APIC - a lot of boring and complicated stuff).

So instead, I thought about drawing console windows!

I got to think about fill_rect, and I have enough of the fixed width font ready to print Hello world.

Thursday, March 04, 2010

NewStars Status

Cool little bug managed to waste a week of John's time...

I had noticed a difference in surface minerals for player 1 in 2401. Examining the mining code indicated it was probably due to scrapping the JOAT remote miner.

The code which calculates ship cost and scrap value is pretty complicated, so it seemed natural the bug would be there.

After digging into it, it became apparent that the bug was due to the miner being on a destroyer hull!

This is due to a copy/paste bug in the code which gives players their initial fleets:
In function makeInitialJoatMiner (copied from the make destroyer code)
Ship *design = new Ship(*(pd->gd_->hullList[destroyer_hull]));

Oops.

Sunday, February 28, 2010

Tcl Alarm

Alright, I have laid the ground work for our helper program, now let's see what Tcl can do:

First, we might have multiple things to wait for, and we want to see how much time is left, not just rely on a single sound to notify us:
set $var $tm
lappend ::dl $var
lappend ::al $var

pack [frame .tMain.f$var] -side top -expand 1 -fill x
pack [label .tMain.lT$var -text $tx] -in .tMain.f$var -side left
pack [label .tMain.l$var] -in .tMain.f$var -side right

This is actually a function (proc addLine {var tm tx}), so I can add lines programmatically.

The "lines" are placed in the window, each one representing a timer counting down.
You have parameters:
  • var - the variable which will hold the time, this is displayed elsewhere, so it can be descriptive, and is used inside functions, so it needs the global namespace like "::zombies" or "::arena"
  • tm - the time (in seconds) until the event
  • tx - the text description for the window
al and dl are global lists. dl is used for decrementing the timers, al is all the timers available (for listing the timers to reset)

Now, when we want to decrement all the timers:
proc decList {il} {
upvar $il l

# foreach variable in the list
foreach iu $l {
upvar $iu i

# decrement it
incr i -1

# update the GUI
.tMain.l$iu configure -text [tformat $i]

# check for timer expire
if {$i == 0} {
# remove the timer from the list
set idx [lsearch $l $iu]
set l [lreplace $l $idx $idx]

# flash the text
after 1000 ".tMain.lT$iu configure -fg #008800"
after 5000 ".tMain.lT$iu configure -fg #000000"

playSound
}
}
}

The upvar may not be needed, I was trying to work around not using globals...

tformat is my "time format". It converts a number of seconds into a nice "35 m 0 s" or "1 h 0 m 50 s" string for pretty display. It is left as an exercise for the reader.

Saturday, February 27, 2010

Better Games

(Continuing my treatment of Facebook games)

Given the number of * Wars games there are, there is sadly little content of interest. There is some adventure in exploring new content, but no staying power. They eventually devolve into a treadmill of grinding through new content, and waiting for new content. More jobs with different names dropping equipment with higher numbers and different names.

However, there is one group developing interesting games, and another with one good game (Nitrous Racing, and several boring games: Monster Defense and Fish Life, among others).

The first single-handedly developed five games that I was willing to try. Three of those were pretty good.

The games are Mad Scientist, Robot Builder, Robotico, Star Conquest, and War Machine.

The first three are good enough, that I will break them out separately. Star Conquest was a good try, and worth discussing. War Machine is actually one of the best * Wars games, but, ultimately, is not enough better.

I wanted to give a peak today of a tool I developed to help with the timers (in Tcl of course!).

Let's say you have some zombies cooking in 14 minutes for Mad Scientist, or you need to wait 45 minutes for more energy. You're in the middle of New Stars or NedOS programming, so you might get distracted and forget to look at a clock for an hour or two...

Enter Snack. Snack is a Tcl package for generating sound. It is really easy in wish:

$ package require snack

Now you need to load an alarm sound to notify you that it is time.

$ snack::sound s -load $path_to_file

Then set the alarm:
$ after [expr ($hour*3600 + $min*60 + $sec)*1000] {s play}

That's it. Just set the variables {hour,min,sec} and up-arrow to the after, and hit enter.

Friday, February 26, 2010

PvP

(Continuing my treatment on Facebook games)

I've mentioned PvP a couple times now, and for those who don't know (and haven't googled it yet), it is "Player vs. Player".

Now, some might think the purpose of a game (especially a game on a social network) would be for players to compete. The alternative is PvE (environment), sometimes called AI (which is too generous), or simply computer players. This is how Civilization and a lot of other games work, and work well.

All Facebook games are competitive, in that you can see what your friends and other players have accomplished, and use that to drive you to do more.

In the * Wars games, the PvP aspect is an in-game effect where you improve and the other player is set back (some games lack this PvP aspect, while being similar in most other ways. e.g. Metropolis)

This might seem to be the main focus of the game (it is for some), but in most cases, it is a simply a small annoyance.

In most games, your PvP power is proportional to the number of people in your network (which is usually capped at 500).

Now, no one has 500 friends, much less 500 friends all interested in playing the same game.

This leads to huge "Add Me" threads on the forums, and giant email chains.

If you're not interested in that (and I'm not), there is a simple precaution to avoid serious setback - bank (or spend) your money at the end of a session (and ignore the "defeated" statistic in your profile).

Thursday, February 25, 2010

* Wars

(Continuing from last time)

The biggest part of Facebook games is resource management. Usually, the biggest resource is your own time (micro-management). This is because Facebook is looking for ad impressions, so every time you load a new page, they get revenue.

Still, most games place some limit on your activity. This is usually referred to as "Energy" or "Fuel" or some other stat. It recharges at a flat rate (often 1 point per four minutes). Usually there is a recharge benefit which you can send to your friends.

The * Wars games all have the following character attributes: attack, defense, energy, stamina, health. Stamina is energy for PvP.

Advancement is experience point based, with experience given for jobs (which consume energy). Each level you gain 5 points which can be spent into your attributes. Also, when you level up, your ablative attributes (health, energy, stamina) are recharged

There is a virtuous cycle here.

Energy -> jobs -> experience -> level up (energy refilled) -> spend on energy attribute

In Mafia Wars, there were several times I was able to level up multiple times in a row (especially when coupled with the daily free energy recharge). The experience cost per level grows linearly, and there is a bonus for the first time you "complete" a job (do the job a lot).

So where do the spreadsheets come in?
Not all jobs are created equal. Your spreadsheet should include Xp/Energy and $/energy (money is needed for equipment, which is used in PvP and in enabling new jobs, usually it is not a limiting factor). Some jobs also drop special equipment. You will need a spreadsheet to track what equipment you have and need, and which drops are best (some games have wikis, but it is good to have a local copy).

Most games also have a notion of "investment" (current cash goes into giving cash per time). You can make a spreadsheet detailing the various return rates, but I haven't seen a game where it wasn't easier to just get money through jobs (which you are doing for the xp anyway - that is, high xp/energy and $/energy usually go together).

Wednesday, February 24, 2010

Add Me

A while back, I promised to tell all about Facebook games.

It has been a hard road, full of sacrifice.

I can say there is something new about Facebook games - the "add me" effect.

This is largely by design. Facebook encourages developers to incorporate some social aspect into games.

It's also apparent that this is often done with little or no thought or effort.

The net effect is that "Add Me" games can vary from annoying to unplayable - based on your willingness to add yourself to huge chain lists of email addresses on the forums.

Most games are built on a single dynamic - building. The other distinguishing feature is PvP.

When I say "building", it is basically grinding on your character/empire/whatever. There is little or no danger of loss. It is just a matter of you putting in the time. It can still be fun, especially when there is a wide variety of things to optimize for, and you can build spreadsheets to determine the optimal path (because a good game leads to building spreadsheets! I'm serious!)

The most popular games fall into what I call * Wars (pronounced Star Wars). That is the glob *, meaning "match everything". You have Mafia Wars, Mob Wars, Dragon Wars, Vampire Wars, Fashion Wars. I have played a handful of them, and they all play the same. A lot of other games use the same dynamic, but don't have Wars in the name - Street Racing, War Machine (now called War Metal), Star Conquest, even the RPG Hammerfall is really the same.

More later...

Tuesday, February 23, 2010

OS Info

I must say that Bochs is really a wonderful tool for OS development. The debugger is great: with breakpoints, single step, and full state inspection. It supports command history, and editing the command line.

That said, some stuff just needs to be printed at run time for inspection (particularly anything with loops).

With that in mind, I have forked the CD boot code into a program to dump the relevant structures for inspection. It keeps the screen in text mode, and is printing from 64 bit mode.

Monday, February 22, 2010

NewStars Status

Turn 2!

Here we can see some problems, although nothing earth shattering.

There is some difference in mining or scrapping (the JOAT miner was scapped on turn 1). But the pop growth looks good, as well as resource calculation, and production. I've also checked the resources going into research, and they match.

The x resources out of y is a known Tcl bug. I just put "x of x", and don't bother to include the research tax...

There should be a WM scout visible, but I need to create the P2 orders to make that happen...

Monday, February 15, 2010

Aqua Screen of Life

Oooh, aahh.

No, I didn't just change the pixel color.

The red screen is now part of the kernel panic function (which is now well tested - remind me to tell the story about the difference between step and next in the debugger, and how I spent an hour trying to figure out why call stopped working in 64 bit mode). If everything goes well, you get the aqua screen, else BOOM! red screen.

Under the covers, the code is now searching memory for the ACPI tables. Find them, you get aqua (actually alternating blue and green pixels, I write two pixels at a time 0x0000FF00_000000FF).

Sunday, February 14, 2010

Red Screen of Death

Check it out!

That beautiful red screen is brought to you by the NedOS boot loader, and the NedOS kernel (which is currently just a rep stosq and an infinite loop).

I was able to fit all the boot loader functionality into one 512 B sector.

It has to:
  1. Retrieve the memory map from the BIOS
  2. Enable A20
  3. Get a list of video modes, pick one, and set it
  4. Transition the system into 64 bit paged mode
The memory map code is kind of a hog. Together with the logic for picking a video mode, the boot loader is nearly 500 B. That is after a lot of effort to minimize code size.

That is too big for a harddrive boot sector (which has 64 B of partition tables and a 2 B signature). I have a version where I strip out all the error checking, that brings the size of the memory map code down significantly. Still, it is currently 433 B - leaving about 10 B to actually load something. Not enough to walk the partition table and figure out on its own what to load. I will have to load something from a hard coded location.

I'd like to be able to draw a text window, and put some text in it...

Saturday, February 13, 2010

New Stars Status

Another day, another bug!

This time, it looks like a bug (or bizarre algorithm) in Stars!

John was kind enough to fix the previous bug.

Now, our Long Range Scout has picked up a ly in the X direction.

The relevant X,Y pairs are:
Finale 78, 80
New Stars 101, 108
Stars 100, 108

The distances are 36.24 ly for New Stars, and 35.61 for Stars. It's really not clear why Stars didn't give up that last ly...

I'm tempted to call "Will Not Fix".

How can our lock step hope to succeed with bizarre bugs like this :(

Friday, January 29, 2010

HTML Canvas

Interesting development. The guys behind FreeCiv have developed a client using the HTML 5 canvas.

I remember looking at a proposal for canvas a while back. It was sorely lacking from the Tcl canvas (if only Tcl had made it as a web standard!).

But, if you can implement FreeCiv in it, maybe it has gotten better (or maybe FreeCiv doesn't use circles...).

Probably worth looking into. A NewStars web client would be nice.

Tuesday, January 26, 2010

NedOS on CD

Booting from a floppy is a good start. But there's just not much you can do with 1.44MB.

I looked into bootable CDs, and they are really nice!
  • You get >600 MB of storage for your OS and app code + read-only data.
  • Writable CDs are cheap and portable, potentially allowing you to run on any machine
  • You don't risk messing up your hard drive (particularly the boot sector)
Best of all, the boot CD spec (El Torito) allows you to load multiple sectors immediately. That means no messing with BIOS read disk routines in the boot loader.

Of course, switching my boot floppy code to CD ran into multiple problems (all stupid ones).
  • The boot code can load into any address. 0 will get you the default (7c00), but just to make sure I could write whatever I want when I need to, I set it to 7c00.
  • Of course, it is a segment address, so I got 7c000, which is near 512K, not 32K, so I was executing uninitialized RAM.
  • Then, when I fixed the segment, I forgot that my makecd program only writes those sectors for new disks, so I still had the old values.
  • The boot floppy code is org 7c3e (to skip the Bios Param Block), but the CD code needs org 7c00.
It took longer than it should of, but I can now boot from CD!

Monday, January 25, 2010

New Stars Status

Hopefully things will pick up...

Here we have our first turn gen, and our first bug!
Our move code has place the destroyer and the probe in the same location, while Stars has them one light year apart. Bizarro. Must be a rounding problem...

I also had to fix the recent file LRU yet again. Hopefully it is correct now.

Tuesday, January 19, 2010

New Stars Status

Not exactly a blitz, but moving along...

Here is player 2. Note, I have fixed the title bar. I did the Stars turn by hand, but the New Stars turn was generated from Tcl!

$ cat orders_P2_2400.tcl
set owd [pwd]
cd ../../../gui/tcl
load ./nstclgui.so
source nsCli.tcl

set nsGui::playerNum [newStars $::ns_open $owd/tiny_sparse_P2_Y2400.xml]
buildMyPlanetMap
set hwPID $nsGui::myPlanetMap(0)

set fid [findFleetByName "Armed Probe #2443026239740"]
sendFleetToPlanet "Armed Probe #2443026239740" [findPlanetByName Pervo]
sendFleetToPlanet "Armed Probe #2443026239740"
sendFleetToPlanet "Armed Probe #2443026239740"

# get a useful scout
newStars $::ns_design $::ns_loadPre scout "Smaugarian Peeping Tom"
newStars $::ns_design $::ns_save

# build it
newStars $::ns_planet $hwPID $::ns_addAtIndex 0 0 1 $::designMap(3)

# set orders for max growth
for {set i 0} {$i < 100} {incr i} {
newStars $::ns_planet $hwPID $::ns_addAtIndex 1 1 3
newStars $::ns_planet $hwPID $::ns_addAtIndex 2 1 4
}

newStars $::ns_save $owd/tiny_sparse_P2_Y2400.xml


Pasting Tcl code is so much easier than C++, a lot fewer < and >!

I had to override the logic for "sendFleetToPlanet" auto-pick. It picks the closest planet, but I wanted to send the Armed Probe on a one-way trip to cover a specific set of planets. The Smaug will cover closer planets.

I had to adjust the speed of the probe in Stars, but the New Stars auto-pick got the speed I wanted, very nice!

New Stars does not show what will finish, that is a very hard problem. I will have to address it at some point, though...

Saturday, January 16, 2010

New Stars Status

Let me start by saying the gcc maintainers are jerks.

I have heard this accusation often on comp.arch, but I was skeptical. Now I know it's true.

If you doubt, read this.

That was back in October, there is still no solution for Cygwin (as far as I can tell). My latest updates pulled down the latest versions, and now I can no longer build NewStars.

I had to back rev to gcc-3 (as mentioned in the post).

Which brings us:


Ahh yeah! Stars versus New Stars, head to head!

Turn 1, player 1 of the test game.

Obvious differences:
  1. Stars and New Stars have the origin of their graphics inverted. This creates a "mirror" effect when looking at the universe (not going to fix)
  2. Stars puts some useful info in the title bar (will fix ASAP)
  3. I am missing the planetary mineral concentrations (will fix, eventually)
More soon!

P.S. Interesting factoids
  1. Stars adds 1000 to x and y
  2. I used Tcl to verify the structure of the master xml
package require tdom
set doc [dom parse -channel [open tiny_sparse.xml]]
set root [$doc documentElement root]

set univP [$root selectNodes //UNIVERSE_PLANET_LIST/PLANET]
set playP [$root selectNodes //PLANET_LIST/PLANET]
puts "#\tX\tY\tName"
foreach p $univP {
set name [$p selectNodes string(NAME/text())]
set id [$p selectNodes string(OBJECTID/text())]
set x [$p selectNodes string(X_COORD/text())]
set y [$p selectNodes string(Y_COORD/text())]

incr x 1000
incr y 1000
puts "$id\t$x\t$y\t$name"
}

That creates the "Universe Definition File" (Report->Dump To Text File->Universe Definition). I have a longer version which checks the integrity of the player maps against the global map.

Saturday, January 09, 2010

We're On Pluto

I have been catching up on the newsgroup rec.arts.sf.science. There was an interesting interchange on Project Pluto.

Now, when some people think of Pluto, they think of the ninth planet (yes! a planet! My Very Excellent Mother Just Served Us Nine Pizzas). More, probably think of Mickey Mouse's dog.

Of course, Pluto is the Greek god of Hades/Death/the Underworld. That is probably the inspiration for this thing:
  • 75 foot long; 60,000 pound
  • nuclear ramjet, cruise missle bus
  • 26 nuclear warheads
The second point needs some explaining.
  • ramjet - flies by compressing incoming air, this requires a fair amount of air to work at all - end result - it cannot fly slower than the speed of sound (it would be launched using solid rocket boosters, and could never land)
  • nuclear - the incoming air is heated by being directly exposed to an unshielded, operating nuclear plant. This means the exhaust is highly radioactive.
  • cruise - designed to fly close to the ground (about 1000 feet)
  • missle bus - a missle that carries missles (the 26 warheads)
This thing (designed circa 1960!) would follow terrain using pre-constructed radar maps, shattering glass and damaging walls and roofs as it flew to its target - all the time irradiating everything it flew over. It would then pop out a nuke, which would detonate seconds later (Pluto flies just under one mile per second, so it is already miles away). Once it was out of nukes and losing power, it could be crashed into a secondary target (60,000 pounds at Mach 4, plus highly radioactive).

Magnum 360 said: "Thank you very much thats exactly what I was looking for. Wow thats amazing it had the possiablity of staying up in the air for months, to bad the project was stopped."

To which, Mike Ash says: "Too bad the unshielded and unfiltered airborne nuclear reactor with no ability to land after launch was stopped??!!"

This is pretty incredible work (terrain following using vacuum tubes?). Also, the sheer gall of the thing (spewing out radioactive exhaust). Of course, this was the same age which planned to blast a mountain into space using nuclear bombs!

You have to admire their sense of scale and boldness. Today, we are so safety conscious - we'd never do anything approaching this scale. It seems like there should be some middle ground...

Friday, January 08, 2010

New Stars Status

Well, looky here!



Here is the "Merge Fleets" dialog! (I know the spacing is off) It works! You can merge ships between fleets. I still don't have "Split All" and "Merge All", but they are basically macros that should be easy. All the core functionality is done.

I also fixed the "Goto" button in the "Other Fleets" area. It was really bugging me...

We are now ready to play! (except for fleet to fleet cargo transfer, but who ever does that :)

Thursday, January 07, 2010

Git 'er Done

I've finished looking over the "Why Git is Better Than X", and the propaganda pages from Bazaar and Mercurial (propaganda is good, you need to say why you think your system is better).

I think I had previously decided on Bazaar. I was really worried about Git on Windows, and Git's main features "Cheap Local Branches" and "The Staging Area" didn't impress me at the time. Bazaar has some really nice support for implementing different sharing schemes on top of the distributed model.

But now, I think Git is the way to go.

In my day-to-day work, I have at least three "local branches" in svn. They are:
  1. the working trunk - attached to the trunk, with all the changes I am thinking about making
  2. a clean trunk - this is my "Staging Area" where I copy changes in before commit
  3. an old copy of the trunk - for comparing really old revs (because history is not available offline in svn)
  4. a personal branch - for long term projects to make major changes
  5. a release branch - for when we are doing a public release
Each local repo can take up to 2 GB (if I need to build the executable). Wasting disk space isn't the biggest worry. It takes a long time to set up these repos, and a lot of work to keep them all in sync and up to date.

I really overlooked the Staging Area.

My concern was that I wouldn't be able to use it, because I need to test any changes before pushing anyway. Of course, I realized that I just need to push to my clean area, test there, then push to the "main" repo (as much as any repo is main in a distributed SCM).

Wednesday, January 06, 2010

Stuff I've read lately

"A is for Alibi" (Sue Grafton)(audio) - This is the first in the "Alphabet Murder" series. It's interesting to see how Grafton has developed as a writer.

And it is good they replaced this narrator.

She is terrible.

She has two tones - monotone and slightly deeper monotone. For an audio book, you need at least two distinct tones, so you can figure out when the speaker changes in a dialogue (basically, to denote the paragraph breaks). Distinct voices for each character and one for actions is a plus, but not absolutely necessary.

A lot of the time, I couldn't figure out who was talking - even if I was paying attention. And if distracted (say, by a crazy MD driver), it was easy to get lost. Sometimes it was hard to tell if someone was speaking or if something was happening.

That said, the story was ok. Grafton drifted some into "romance novel" territory, which she is obviously terrible at. Good to see she has dropped it in the later novels.

Tuesday, January 05, 2010

New Stars Status

So close now!

It's been a while since we had a Windows screen shot. See, it still looks the same! :)

I had to scp over the turn file from Linux for debugging, because I don't have a split case on Windows, and debugging through VNC can be a pain...

This looks like the normal split case, but look carefully...

The original fleet id is 234806..., now the fleet id is different. I did a split, where all the ships move into the new fleet (and the old fleet gets deleted). That was to test the fleet deletion code, which is needed for merge to be useful.

Now I can do merging.

Monday, January 04, 2010

Give in to the Darcs Side

Continuing from my last post, I did want to talk about SCM I will not be considering:

Darcs
  • Written in Haskell, considered the poster-program for Haskell. Haskell is a functional language, similar to ML. Given the horror of ML, and the behavior of Darcs - I am not motivated.
  • Operates on a "theory of patches". Finding the right set of patches, and applying them in the right order. I don't believe it is possible for a machine (currently) to handle this level of complexity. Heck, I don't know that I can handle the complexity!
  • Ate our repo, twice. Losing the repo is an unforgivable sin for SCM.
  • Was really slow. They are supposed to have fixed the number of "exponential merges" (nice). But it was slow all the time. The exponential merges were just insult to injury.
BitKeeper
  • Commerical software. No way I am going to pay for software for my personal projects.
  • Also ate the repo. Maybe twice.
SVN
  • No distributed model
  • Logs and history are not available offline
  • While creating branches is now easier than CVS, merging them back is still just as hard (this is a hard problem, so I don't blame them)

Sunday, January 03, 2010

Source Control to Major Tom

To a coder, nothing is more precious than his code. Source control management (SCM) is all about keeping your code safe. Not against disk failures, so much as against bad edits ("what was I thinking!" !). It's also a good place to stash some forms of comments (not what the code is doing, but why it was written). Mixing this into the code can be distracting. SCM also provides a nice log of when features were added ("it's been two years!?").

I had my first encounter with source control as an intern at Intel. Our files were under CVS (concurrent versioning system), with some binary files directly managed with RCS (CVS started as a wrapper around RCS - all those funny ,v files).

CVS is ancient (1990), and works really well. You have to be careful with merging conflicts, tagging takes forever, and branching is so confusing no one ever used it. You have to stretch the meaning of "really well"...

Eventually (about ten years ago), some people decided to improve on CVS. That project is called Subversion (svn). I didn't use Subversion until about two years ago. SVN is a big improvement over CVS. The main thing - being able to do a diff against a network repo while not connected to the network. Also, SVN is much better with merging. Tags and branches use the same mechanism, which is cheap and easy. Very nice.

I used CVS professionally until about 2003. That was when I was exposed to the Great SCM Wars - between minions of Darcs, and keepers of BitKeeper. I will have to rant about them sometime. Suffice to say, that no man has ever fought with them and lived! The bones of many projects lie strewn about their lairs. So if you do doubt you courage, come no further. For death awaits you all; with nasty, big, pointy teeth.

Ok, so I still use CVS for my personal projects. I would like to switch over to something new, probably "distributed". There are three alternatives:
  1. Git - created by none other than Linus of Linux fame. He too was a victim of BitKeeper, so he is familiar with pain. He is a really smart guy who churns out quality software at a prodigious rate. He also tends to be a little quirky, and he is (ultimately) writing software for himself, so there is no guarantee I will get the same returns...
  2. Mercurial (hg) - apparently started about the same time as Git (2005), for the same reason (holding the Linux kernel tree)
  3. Bazaar - the newbie in this line up (2007, and new is bad, like in compilers - new means buggy and untested). But, I am willing to give it a shot.
I had previously compared these three and decided on a winner. Sadly, I can no longer remember which one I picked. And things have changed some since then. At the time, Git was basically Linux only (there was a Windows hack by some guy who was trying madly to keep up). Now, I can get Git as a Cygwin package.

I will have to go through again and compare. I don't think SVN is in the running, as it does not have a distributed model. I like the distributed model, because it allows me to push code from one machine to another without having to worry about which one is the "master".

Saturday, January 02, 2010

The Bootstrap Problem

When you turn your computer on, it just boots. You take it for granted. It says "Windows loading" or "Grub", or "L..I..L..O".

But a lot of work goes into getting your computer to boot.

The main problem is the processor just runs programs. And it needs a program to tell it how to load programs. But you need to load a program, to run the program...

The solution is a program which lives at a particular address in permanent memory (ROM). This program is called the BIOS, and it has a really remarkable history going back to the original IBM PC.

The BIOS finds a boot device (usually floppy, harddrive, or CD-ROM, but now usually includes USB). It then loads the "boot sector". This is a 512 byte block of memory containing code which is placed at address 0x7c00. It then jumps to 0x7c00, and you're off!

In my NedOS musings, I considered using Grub as a boot loader. It handles a lot of stuff, and allows you to build your kernel like a regular program. In the end, I rejected it, because:
  1. I wanted to learn how to do a bootloader
  2. I didn't want to be bound to ext2fs and Elf (or worse, FAT32 and PE)
  3. You really need to build a cross compiler to use it
  4. Grub seems bound to 32bit kernels
  5. Grub is 3 stage, I wanted to see if I can get into 64bit mode in 1 hop
The fifth point is the most interesting. Your first stage is the bootsector (512 bytes, really 448 on a boot floppy). That's all you've got to get going, it is really cramped! But loading a second stage requires disk accesses and some sort of file system. I don't want to think about file systems right now, and I don't want to pick an existing one and get stuck with those assumptions.

After most of the day hacking, I have a minimal 64bit bootloader, in 170 bytes!

Now I need to figure out what BIOS info I want to extract before kicking into protected mode, and how I want to find the kernel.

Ugly/cool tip:
You cannot get to 64 bit mode in one step. You have to go through protected mode (because the bit for long mode is in a different register than the register used to enter protected mode - jerks). Further complicating things, the code descriptor for 32bit code is incompatible with the descriptor for 64bit code (nice work guys).

So what I do:
  • set the descriptor for 16bit protected mode code (yes, the original 286 style)
  • kick into protected mode
  • set for long mode (I'm now in a really tenuous position, but interrupts are off)
  • flip the descriptor bit for 64bit code
I could switch to 64 bit mode now, but I turn on paging first, just for good measure. Then with a far jump, I'm into 64 bit/paged mode!

Friday, January 01, 2010

Debacular

When something turns out really bad, you say it was a debacle. If you're in the middle of something that you know is going to end badly, you say the whole process is debacular.

So, a post on comp.arch led to a Google search, which led to a website called OsDev. Now, I have a directory in my projects area called NedOs, which I have been trying to figure out what to do with. There's really not much stuff in there, but it seems a shame to delete it. So, why, not, you know, write an OS? It's not like I'm hugely busy in every dimension, right? (mmm, debacular already)

I broke out my Intel software developer manuals, but they are all so old, they don't have 64 bit stuff. I downloaded the new one, and was greeted by this:

Now, that is debacular!

For anyone who is thinking of writing their own OS, this is the flow chart for enabling "Long Mode" (that is - X86-64, AMD64, EMT64T, or as Intel has now started calling it IA32e mode!) (technically it handles all the modes)

After staring at it for a while (I just want 64 bit mode with paging, is that so wrong!), I realized this could be three sentences:
  1. Enable PAE
  2. Enable LME
  3. Enable PG
You could have an optional fourth sentence - "The first two steps can be done in any order."

So, this picture is worth, like, -994 words.

Thursday, December 31, 2009

New Stars Status

Oh Frabjous Day! Calooh! Callay!

Here we can see the fleet split dialog in action. The cool thing about Tcl, is the whole dialog and the logic behind it is 90 lines of code...

Here's the bulk of it:
for {set i 0} {$i < $numDesigns} {incr i} {
pack [frame .tSplitter.fTop.fRow$i] -side top

set shipName [newStars $::ns_planet $fid $::ns_design $i $::ns_getName]
pack [label .tSplitter.fTop.fRow$i.lL -text $shipName] -side left

set shipCt [newStars $::ns_planet $fid $::ns_design $i $::ns_getNumFleets]
pack [label .tSplitter.fTop.fRow$i.lLC -text $shipCt] -side left

pack [button .tSplitter.fTop.fRow$i.bL -text "<" -command "adjustSplitRes $i -1"] -side left
pack [button .tSplitter.fTop.fRow$i.bR -text ">" -command "adjustSplitRes $i 1"] -side left

pack [label .tSplitter.fTop.fRow$i.lRC -text 0] -side left

lappend ::splitRes [list $shipCt 0]
}

Hardly any < or >!

In English, it says:
foreach ship design in the fleet do
create a new frame (invisible GUI packing object)
pull the ship name via the C++ bridge, and make a text widget for it
pull the ship count via same, and make a widget for it
make 2 buttons, one < and one > which will call adjustSplitRes (described later)
make a text widget with "0"
append a list to the global variable splitRes (which holds the split counts for each design)

Like 9 or 10 lines of specific English, roughly the same in Tcl (plus whitespace)
Here's adjustSplitRes in its entirety:
proc adjustSplitRes {row val} {
set left [.tSplitter.fTop.fRow$row.lLC cget -text]
set rght [.tSplitter.fTop.fRow$row.lRC cget -text]

if {$left < $val} {return}
if {$rght < -$val} {return}

set left [expr $left - $val]
set rght [expr $rght + $val]

lset ::splitRes $row 0 $left
lset ::splitRes $row 1 $rght

.tSplitter.fTop.fRow$row.lLC configure -text $left
.tSplitter.fTop.fRow$row.lRC configure -text $rght
}

This pulls the text labels for the left and right, checks for underflow, then applies the new count (for now, we only support moving up or down 1, but I should be able to bind shift and control click to move more). I then update the splitRes list, and the GUI text.

The C++ bridge does not handle deleting the old fleet... that will probably need to be fixed, although we should have new tools for handling chaff mine sweeping, which was the main reason for shedding old fleet nums (otherwise, you never need to move out the last ship from a fleet).

I should be able to use much of this logic to build the fleet merge dialog.

Split all and Merge all should be easy, and aren't strictly needed for playing (merge fleets is needed).

Almost there!

Monday, December 28, 2009

Stuff I've read lately

"O is for Outlaw" (Sue Grafton)(audio) - Meh.

Saturday, December 26, 2009

Black Hole Catalyzed Total Conversion

That has a nice ring to it. Kind of like "Laser Induced, Gravity Sustained Fusion Reactor".

Weird chain of events: a Slashdot article discussing the physics of space war. Leads me back to Project Rho, re-reading the sections on stealth and heat dissipation. Somehow, I ended up on stardestroyer.net, reading about the Death Star power system (I remember something about the importance of heat dissipation, and how Luke might not have had the impact he thought he did). Someone (maybe there, maybe elsewhere) mentioned the possibility of using black holes to convert matter to energy (this was in the context of a system failure not producing a tremendous boom, at least in comparison to the enormous power output before the failure [the Death Star is assumed to produce more power than Sol - blowing it up could easily wreck a solar system - that is, Yavin or Endor, places the heroes were supposed to be protecting]).

I decided to sit down and actually look at what it would be like to have a black hole around for energy conversion.

The idea is actually pretty simple, you feed matter into a black hole (presumably one already electrically charged so you can keep a handle on it). You then harness the Hawking radiation (HR) for energy.

There are several properties of black holes which make this not entirely unreasonable:

Power output (via HR) is inversely proportional to the square of the mass of the hole.

That means every (log) step down in mass, you go up two steps in the power of your reactor! Smaller holes give more power! It also means the black hole will likely not fail-big, but rather fail-evaporate (giving off a huge amount of energy). A small hole (2e10 kg) would produce about 1e11 W. Making it a little smaller (2e8 kg) would yield 1e15 W (probably too much to get rid of...)


Size is proportional to mass

This has good and bad points. A small hole is really small. 2e10 kg being about 3e-20 m (3e-11 of 1 nm) This means you won't accidentally fall in. But it also means you have to try very hard to get matter into the thing to keep it going.


Lifetime is proportional to mass cubed

This is kind of annoying, but the constants make it ok. A small hole (2e10 kg) would have a lifetime of about 21 million years. It does mean that your initial hole (unless you have a really big accelerator) is going to decay fast.

Actually, with a lifetime like that, it's effectively a battery, with no fuel input. A super small hole (2e6 kg, only two million kilograms!) would have a lifetime of 662 seconds! Definitely a problem, especially considering it is giving off a constant 1e19 W! Don't get burned!


People worrying about the Large Hadron Collider producing black holes shouldn't worry. The energy levels are way too low to produce a hole with any meaningful lifetime. It also means we will need a much larger collider (or better production methods - huge lasers?) to produce commercial black holes.

Wednesday, December 23, 2009

Civ Sequels

Of course, a game as successful as Civ is going to be followed by a lot of hangers-on (both products from the original designers, and imitators).

There was the natural progression: Civ-Net, Civ 2 (with a lot of variants, like Test of Time), Civ 3, and Civ 4.

There were clones: Civ Call to Power and Free Civ.

And in-spirit successors: Master of Orion (were you start with one planet and one colony ship), and Alpha Centauri (where you play the descendants of the original colony ship from Civ). Also, Colonization: a Civ-like specialized to a particular time.


The natural sequels were actually very disappointing.

Civ-Net: largely a Windows port (there may have been a Civ-Win). The network play had sequential (basically, hot-seat on different computers), or simultaneous. This really didn't work out, as a battle between two catapults could be decided by who was quickest with the keys.

Civ 2: Civ plus-plus. More of everything. More tech, more units, even more for settlers to do (double irrigation, anyone?). Of course, more is not necessarily better. The micro-management hassle of Civ became that much more in Civ 2. With more city improvements and more engineers needed, you built more cities. And the tedium of terraforming became just that much more. I largely play Civ 2 now, only because the old DOS Civ is a little buggy (some sort of weird memory corruption).

Civ 3: A good disaster. Introduced a lot of new concepts (culture, armies, a focus on fewer/better cities). I'm not sure what went wrong, had to be not enough play testing. Armies were way to powerful, culture didn't work quite right, the corruption in big empires was just crippling and small empires couldn't win.

Civ 4: Another hit. Largely made possible by the failures of Civ 3. Now culture is working right, the combat model is a lot better, and small empires really work. They also managed to fix the terraforming problem, where there is an actual choice to be made (not just, road-irrigate-railroad / next!). I'd play this more, except the graphics requirements are really steep.

Tuesday, December 22, 2009

The Life of the Game Designer

is not an easy one.

You have to spend hours thinking about (i.e. reminiscing) about all the great old games. Maybe talking with friends, or on rec.games.design, or even just alone.

Then, you have to go and play all sorts of games (for, you know, "research").

In that spirit, I have been playing some of the Facebook games (which a lot of people say are really bad).

They are really bad.

I will break out the how and why in (one or more) separate posts.

Monday, December 21, 2009

The Civ Legacy

I've been wanting to do some discussion of game design, and no better place to start than Civ.

Sid Meier's Civilization will always be remembered as a classic. You might say it is just Empire on steroids, or a translation of the board game - but millions of people don't play Empire and most have never heard of the board game.

Sid perfected "Just one more turn". Not only for Civ, but also in the less successful Alpha Centauri (lovingly known as SMAC).

The main advantage Civ had over Empire was splitting attack and defense (along with a more complex city model). This allowed specialization of units.

Civ also covered a much longer (and therefore more "epic") time scale.

The biggest failing of Civ was the old "phalanx beats tank" scenario. This comes from the simple unit progression (after the most basic unit - Militia 1/1):
Defensive



Phalanx12
Musketeer23
Rifleman35
Mechanized Infantry66

This is from memory, so I may be a little off. The general progression was just to add one or two to the attack and defense.

Offensive






Horseman21
Legion31
Chariot41
Catapult61
Cannon91
Tank105
Artillery12?

Sorry, I can't remember the artillery defense at all. It was less than the tank, making them very specialized (they could ignore city walls). Some of the offensive units could move at 2 (Tank may be 3, that has changed some in Civ, Civ 2, Civ 3, Civ 4).

The combat system was dead simple:
Chance of win = attack / (attack + defense)
So, a horseman attacking a phalanx has a 50% chance of winning. Of course, as a military option, a 50% chance isn't very attractive. I'm going to need an equal number of attackers as defenders, and defenders get an advantage for terrain and digging in ("fortifying").

I will cover naval combat in another post.

This is actually very easy to fix, although it didn't get fixed until Civ 4 (which, ironically, went back to a single strength number, although they did it very well).

Make the units improve by more than 1 per step! I mean, you've got at least a byte for strength and defense, that's 255 (or even 127 if signed).
In Civ 4, the "Modern Armor" unit is, like, strength 40. Plenty of firepower to crush that old phalanx.

Sunday, December 20, 2009

New Stars Status

I hacked in a simple fix for the case I can check. I will need more code once I can check more cases...


Now we can build multiple ships, and split them out one by one. The Tcl/C++ interface has everything we need (I created this case from the command line). I need to update the GUI to present it nicely.

Saturday, December 19, 2009

Sorry

I was going to do some New Stars stuff. But I was cleaning out my projects directory, and found some old code a friend sent me.

Of course, I had about three different versions from hard drive back ups and new computers, so I was reconciling them all and putting my changes into CVS (had to reformat all the code, you know).

I also fixed a bug due to wrap around, and added an alternate viewing mode.

Here is the normal view (it shows biomes - like desert, forest, etc):


Here is the alternate view (based solely on altitude):


Of course, all this map gen stuff made me want to play Civ. So I lost the day to Civ 2. Mmm, Civ 2.

Friday, December 18, 2009

New Stars Status



This is a particularly tricky set of code. I need to split off individual ships into a new fleet, and make sure the fuel and cargo are transferred proportionately.

Here we can see the 2 Toms have been split, but the fuel was left behind (as would the cargo)...

Wednesday, December 16, 2009

Stuff I've read lately

"P is for Peril" (Sue Grafton)(audio) - Choosing an audio book from the library is always hard. There tends to only be popular fiction, and I can't always concentrate on audio (with all the crazy Maryland drivers). So, I don't even want to choose "good" stuff.

This is the second Grafton book I've read (listened to). I wasn't at all happy with this one.

First, the red herring. Totally didn't fool me, not for a minute. In fact, I thought it was so overdone that it was actually the reverse. I figured the guy was being set up, and the main character's total hatred of him (after her initial liking him) would turn out to be misplaced. Nah, he was just evil.

The ending made no sense.

We had a lot of suspects to choose from:
  1. The ex-wife.
    • Gained $1e6 after his death
    • Significant circumstantial evidence
    • Spite against current wife
  2. The business partners
    • Protect their multi-million dollar business (blame him after he's dead)
    • He was going to the FBI (they might not have known)
  3. The step daughter
    • Conceal her drug habit
    • Conceal her theft of $30k
    • Escape her "constricted" lifestyle
The ending isn't totally clear (I listened to it three times, and I'm still not sure). You can sort of convince yourself that it was the step daughter, but I think the author intended to finger the current wife...
  • Gains nothing (life insurance went to ex-wife)
  • Loses the father of her two year old
  • Couldn't have wanted to get away (he was old and a workaholic)
Boo!

Friday, December 11, 2009

New Stars Status

I've been doing more work on the Linux side, as bugs come in and because I don't trust my XP regression (without comparing it to Vista).

This means I get my first Linux screen shot! (Which confused me for a second, I thought I would need to scp it back!)


Twm rulez!

The other advantage of working on Linux is that I need a new regression. That means I can use a disposable game, where everyone is not acting optimally.

Here, I have changed player two to build two scouts, instead of one.

That allows me to update the build logic to group new ships into fleets by design, rather than putting every ship in its own fleet.

This will allow me to work on the split fleet code.

Tuesday, December 08, 2009

Prime Directive

Let's see how D and C++ stack up when it comes time to maintain and expand our code.

I created a bash script to run the programs a lot (so we can check performance).

#!/usr/bin/bash
for i in {1..100}
do
./d_prime.exe > /dev/null
done

This isn't the greatest (generating more primes would be good too), but it should suffice...

On my Pentium 4, 2.4 GHz, D gives:
real 0m12.865s
user 0m3.888s
sys 0m10.450s

While C++ gives:
real 0m13.325s
user 0m4.128s
sys 0m10.667s

I won't be comparing the speeds directly, as much of that is a compiler issue (and I would need to evaluate turning on optimizations, which is a big headache). I am most interested in algorithmic improvements, and how hard they are to code.

The obvious thing is that the code is O(n^2), or at least O(n*p) where p is the current number of primes. We don't need to check primes that are larger than sqrt(n). So, how can we encode this?

The D code is an easy change:
We add:

uint ct = 0;
uint sqr = 4;
if( i >= sqr )
{
ct++;
sqr = primes[ct] * primes[ct];
}


And change:
if( isPrime(i, primes[0..ct+1]) )


This makes use of D's "slice syntax". That is, we can create a subarray just by specifying the elements we desire. The slice is a reference, so there is no copying.

real 0m12.915s
user 0m3.923s
sys 0m10.507s

The new time isn't any better, probably because the time is dwarfed by system (/dev/null doesn't seem any faster under Cygwin). But we have introduced a new algorithm that is potentially twice as fast with little effort.

When I come to the C++ version, I realize I've made a terrible error... the isPrime function takes a reference to a vector. But I only want to pass in part of my current vector. Now I have to come up with a slice class which is derived from vector, or change my function to use iterators (Note: I did not plan this to make C++ look bad!).

Iterators are ugly, but not as ugly as trying to implement my own slice class!

The new prototype is:
bool isPrime(unsigned n, const std::vector<unsigned>::const_iterator b,
const std::vector<unsigned>::const_iterator e)


and the for loop becomes:
for(std::vector<unsigned>::const_iterator i = b; i != e; ++i)


while the call point is:
if( isPrime(i, primes.begin(), primes.begin()+ct+1) )


Again the time isn't any better:
real 0m13.561s
user 0m4.097s
sys 0m10.855s

Of course, iterator addition is pretty unusual. It might give someone pause. And make them think about how it is just as ugly as normal iterator usage!

Now imagine I've had to edit header files and caused a dependency chain reaction which forces everything to rebuild. Or worse, altered a public API, which drives a version change. Maybe implementing that slice class wouldn't be so bad...

Sunday, December 06, 2009

D Code

I had a little time, and started playing with primes again (something fascinating about primes).

Good chance for a little D code:

import std.stdio;

bool isPrime(uint n, uint[] curPrimes)
{
foreach(i; curPrimes)
{
if( n % i == 0 )
{
return false;
}
}
return true;
}

void main(char[][] args)
{
uint[] primes;
primes ~= 2;

uint i = 3;
while( i < 1000 )
{
if( isPrime(i, primes) )
{
primes ~= i;
}
i += 2;
}

writefln(primes.length);
writefln(1);
foreach(j; primes)
{
writefln(j);
}
}

The C++ code is very similar (except with lots more editing for HTML, with &gt; and &lt;):

#include <iostream>
#include <vector>

bool isPrime(unsigned n, const std::vector<unsigned> &curPrimes)
{
for(std::vector<unsigned>::const_iterator i = curPrimes.begin();
i != curPrimes.end(); ++i)
{
if( n % *i == 0 )
{
return false;
}
}
return true;
}

int main(int argc, char **argv)
{
std::vector<unsigned> primes;
primes.push_back(2);

unsigned i = 3;
while( i < 1000 )
{
if( isPrime(i, primes) )
{
primes.push_back(i);
}
i += 2;
}

std::cout << primes.size() << std::endl;
std::cout << 1 << std::endl;
for(std::vector<unsigned>::const_iterator i = primes.begin();
i != primes.end(); ++i)
{
std::cout << *i << std::endl;
}

return 0;
}

I've already complained about hideous iterator syntax. But I will post more on some D goodness, when it comes time to make improvements to the algorithm.

Sunday, November 29, 2009

Fun With Excel

(Actually its the Open Office Excel clone, but I can't even remember it's name...)

Saturday night I got my development environment under Windows XP in workable shape (I won't say it is totally working, because there still seem to be some oddities).

I then started to look into the regression.

I am trying to run the regression like a real game, which means all the micro-management entailed in a new game (part of the reason for NewStars was the hope of eventually automating the micro-management).

I have a spreadsheet (the famous STARS!.xls), which allows for colony planning.

The spreadsheet is incredible, and is invaluable for checking the server code.

I found a bug regarding partial completion. Imagine a factory built 1 resource at a time, over 10 turns. The factory costs 4 germ. How do you subtract the 4 G, and not 0 or 10. Our code was subtracting 0...

After I fixed that, I found a (what I think is) a bug in the spreadsheet!

So, I spent all day looking at spreadsheets, and ending up starting a new spreadsheet.

Fun! Fun!

Tuesday, November 24, 2009

New Stars Status

Wow! A long time with no updates!

Real life has interfered with development, hampered by some irritating 64 bit problems. Apparently, the C runtime in Windows Vista accepts %ll for printf. The same cannot be said for Windows XP.

I had been doing most of my development on a Windows Vista machine, but lately have had to fall back to Windows XP. That's when I noticed the regression doesn't pass.

I tried to track down the printf's and replace them with ostringstreams (finally a case where C++ is better than C!), but there are just too many of them. I ended up doing:
vi `grep -l '%ll' *.cpp`
And
%s/%ll/%I64

Ahh, saved by vi.

The regression is now somewhat passing, but there are some oddities... need to check against Vista...

Sunday, July 26, 2009

New Stars Status

Getting close!



I added the "Other Fleets Here" GUI element. I also implemented the functions to populate the list.

As soon as I implement the functionality for split/merge and cargo, we will be ready for a developer test game!

Friday, July 24, 2009

Concepts Are Dead in C++0x

Long live Concepts in C++1x!

What are concepts? And what is C++0x?

C++0x is (in addition to being the worst name ever for anything) the next standards update to C++. It endeavors to add more to C++, not because C++ needs to be more complicated (which it already is, and which it will become more so), but to try and add some badly missing features to make C++ competitive with higher level languages.

Bjarne has a FAQ page.

Let's fisk the individual features he comments on:
  • "auto" keyword - good, D had this since version 1
  • for(auto x : container) - good, wordier than D version 1
  • fix for template<nested<>> - good to see this fixed, sorry for compiler and tool writers who need to make it work
  • default and delete - meh
  • enum class - good (if oddly named), D version 1
  • constexpr - good, D "pure" functions (maybe not until version 2) are more powerful
  • decltype - meh, I believe D has better introspection with typeof(?), etc.
  • initializer lists - not sure how much of a win this is, adds a lot of complexity. Built-in array types seems a better (simpler) solution
  • preventing narrowing - meh
  • delegating constructors - good, D version 1
  • in class member init - yeah!, D version 1
  • inherited constructors - meh
  • compile time assert - D version 1 (plus contracts are way better)
  • long long - ugh, why not standardize on int64_t?
  • nullptr - ugly name, D version 1 has null
  • suffix return type - "[] mul(T x, U y) -> decltype(x*y)" ahhh!!!!! that looks like ML or something else that Cthulhu would write
  • template alias - meh
  • variadic templates - much needed, although more complicated templates makes my head want to explode
  • more initialization syntax - cause more is better
  • rvalue references - wow, that is some ugly syntax. All hail swap!
  • union fixes - "s.~string();" nuff said
  • POD - meh
  • raw strings - meh
  • user defined literals - wow, I mean wow. Why? 'constexpr complex<double> operator "i"(long double d)' Why? Please, why?
  • attributes - seems good
  • lambda - yea! D version 1
  • local types as template arguments - never ran into this bug, good to see it fixed
  • C99 - meh
  • extended integer - why wasn't <stdint.h> enough?
  • extern templates - this is how some early template implementations worked, maintenance headache
  • std::array - D version 1
  • unique_ptr - nice
  • concepts - this would be nice. Much closer to what Java allows for its (much weaker) version of templates.
I have a lot of reservations about all this:
  1. More. More. More. It's all complexity-plus-plus. More complicated compiler, more bugs, more complicated IDE, more to learn, more to remember, more to code. Maybe a little less to code, sometimes. Ugh.
  2. A lot of this is no longer looking like C. What is some embedded guy who misses this update going to think when he sees this code? He'll have no idea what is going on.
  3. How long before I can actually use this stuff? Sure, g++ will have it quickly... MSVC will probably take 3-5 years after the standard (because they will keep trying to push their incompatible version). What about dmc? Or weird embedded compilers whose vendors have gone out of business? Oh, they'll never have this... which means, I shouldn't be using it if I need to be cross compatible. Which means I can't use it for the next 10 years.
  4. All this to get what D had in version 1. D version 2 will be done in the next year, and usable from day 1.

Tuesday, July 07, 2009

New Stars Status

Wow, a big change, not very fun, I was putting it off for a long time...



Notice the Long Range Scout is now named #1274... I have converted the ship design and fleet ids to follow the map given in my Sourceforge post (planet ids were the same before and after).

This revealed a bug that Cygwin Tcl 8.4 does not honor wide ints as 64 bits. It compiles, but apparently just gives you 32 bits... ugh. Then I had to switch everything over to -mno-cygwin, rebuild everything, and use the ActiveState Tcl (which is 8.5).

Since the new object id code makes use of rand, all the planets changed (which means I have to redo all the player orders). So, I took the opportunity to sort in the additional names John sent months ago. We now support ~2.5k planets with names. We will probably need an automated scheme for larger universes (which would probably be populated entirely by AI's, who aren't going to care about planet names).

I changed the fleet name label to left align. This is a little ugly for the shorter planet names, but it is much better for the longer fleet names. I also fixed a bug where fleet path highlighting would remain when you switch to a planet view.