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).