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.

Friday, May 29, 2009

The Horror Returns

I last complained about C++ back in September (on the 20th and 21st). I thought I had seen all the horrors that the new template error checking could produce.

I was wrong.

Check out the new spewage from g++:

main.cpp: In member function `void Test<t>::test()':
main.cpp:11: error: expected `;' before "i"
main.cpp:11: error: `i' undeclared (first use this function)
main.cpp:11: error: (Each undeclared identifier is reported only once for each function it appears in.)
main.cpp: In member function `void Test<t>::test() [with T = int]':
main.cpp:20: instantiated from here
main.cpp:11: error: dependent-name ` std::vector<t,std::allocator<_chart> >::const_iterator' is parsed as a non-type, but instantiation yields a type
main.cpp:11: note: say `typename std::vector<t,std::allocator<_chart> >::const_iterator' if a type is meant


Not bad, 8 lines (some very long) for a 24 line program! Oh, and can I say how much I "love" the <> syntax for templates when it comes time to post into HTML (of course, C++ predates the web, so I can't blame Bjarne too much :)

Here is "teh codz"

#include <vector>
#include <cstdio>

template<typename T>
class Test
{
public:
void test(void)
{
std::vector<T> v;
for(std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)
printf("%p\n", &*i);
}
};

int main(int argc, char **argv)
{
Test<int> t;

t.test();

return 0;
}


Line 11 is the 'for' loop. g++ is complaining about the declaration for 'i', which is the standard (ugly) iterator. The note must of been added after lots of people complained.

The core of the error is "parsed as a non-type, but instantiation yields a type". It means that because it uses <T> somewhere, it must be parsed as a non type (that is, g++ has no idea what the type could be at this time). However, it is being used to declare a variable - which must have a type. So, g++ is confused.

The note tells us how to fix it:

$ diff main.bad.cpp main.cpp
11c11
< for(std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)
---
> for(typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)

Thanks diff for more < and >! (also predates HTML, so maybe HTML is to blame...)

Of course, if the compiler knows what the problem is well enough to emit the note, and the fix is so easy, makes you wonder why the compiler can't just fix it for you...

Thursday, May 28, 2009

Lua

I have been hearing a lot about Lua. Apparently it is very popular in game development circles. I love to read about the history of things, and Lua has a nice page for that.

They say:
"The main contenders were Tcl and, far behind, Forth and Perl."
That's pretty interesting to see. What made them not use Tcl?
"In 1993, Tcl and Perl ran only on Unix platforms."
That's a real shame. I was introduced to Tcl in 1999, when there was already a Windows version. I'm not sure when the code was first ported to Windows, I found a Usenet post from comp.lang.tcl called "New Release of TkWin -- Tk for Windows" discussing version 0.2, from Jul 18 1994. Incredible to think there may not have been a Lua by so slim a margin...

So, could Lua be a replacement for Tcl for me?

Lua feels like "everything is a table". This causes the problem that tables are not a primitive type, so there are also types for numbers and strings (as well as boolean). The syntax is vaguely C (actually more Pascal).

The use of tables seems to give easy access to object oriented programming. That is something Tcl is weaker on (mostly from the "too many choices" problem). I'm not too concerned about OO in my scripting. Scripting is for fast development, OO is for structure and maintenance.

I think I will pass on Lua for now.

Wednesday, May 27, 2009

Iterators::end

The greatest benefit of moving vectors and maps into the base language is an improvement in the syntax for iterators.

For example, C++:

std::vector<MyCoolType*> myVec;
myVec.push_back(new MyCoolType);
for(std::vector<MyCoolType*>::const_iterator i = myVec.begin(); i != myVec.end(); ++i)
(**i).print();


Versus D:

MyCoolType[] myVec;
myVec ~= new MyCoolType
foreach(i; myVec)
i.print();


First, the differences:
  1. Every class reference is automatically a pointer (MyCoolType[], not MyCoolType*[])
  2. Binary operator~ is used for vector concatenation (an object is promoted to a vector of size 1)
  3. Pointers to structures can use '.' It's obvious that the pointer needs to be dereferenced.
  4. "foreach" allows automatic const iteration. There is "foreach(ref i; myVec)" for non-const.
The advantages should be clear. Iteration in C++ is an abomination. Typedef's can clean things up some, but they also obscure what is really happening (error messages will likely come back as the underlying types).

I have become inoculated to these problems, partly because the Visual C++ IDE makes it easier (with auto complete). D makes it possible to be productive in Vi again... (not every machine has VStudio)

Monday, February 23, 2009

STL::collapse

A simple addition to C (variable length arrays using the [] notation), allows the removal of std::string and std::vector.

The question becomes, "how much do we really need from STL"?

From personal experience, the most used classes are std::string, and std::vector. The next is probably std::map (although std::list is handy, but vector can do most of it). Keep in mind, Tcl gets by with just string and maps of strings to strings...

D uses a simple concept to add maps.

char[][char[]] strStrMap; // a map from string to string
int[int] intIntMap; // a map from int to int
char[][int] intStrMap; // a map from int to string


The usage is just like it looks:

strStrMap["hello"] = "world";
intintMap[6] = 4; // Craw Giant
intStrMap[0] = "trample";

Sunday, February 22, 2009

Native Vector

I think the D Faq makes my point for me:
"the implementation of a string type in STL is over two thousand lines of code, using every advanced feature of templates. How much confidence can you have that this is all working correctly, how do you fix it if it is not, what do you do with the notoriously inscrutable error messages when there's an error using it, how can you be sure you are using it correctly"
Vectors are built in to D:

char str1[8]; // eight chars, enough to hold a string of length 7 and the 0 terminator
char str2[]; // a variable size string
char *str3; // a C style unknown length string


D strings are not NULL terminated (although string literals are given an extra NULL byte so that they can easily be used as C strings). This allows substrings to be referenced in situ. String length is determined using the vector length.

D is also able to avoid a pitfall of Java. When Java was developed, Unicode was all the rage. So, strings in Java are all Unicode (2 bytes). That means every string is taking up twice the memory of a C string.

D uses UTF-8 (which I've only learned of recently, Wikipedia says it was first presented in 1993 - Java was started in 1991). That means we can get all the juiciness of foreign characters sets (Hebrew and Greek being of interest to me lately), without the 2x memory penalty.

Saturday, February 21, 2009

Native String

The lack of native support for strings in C++ was a determined decision on the part of Stroustrup (I'd love to read his book on the history of the development of C++).

It is largely this decision which has made C++ everything it is (good and bad). Templates are driven by the need to implement vectors, so that strings can be vector<char> (or vector<short> for unicode). Allocation and comparison get added to the template implementation, which requires default parameters. Horribly long and ugly template definitions (std::vector<char, std::alocator, std::traits<char> >::basic_function, etc.) lead to changes in error detection and reporting.

What if we take a step back.

What if we look at a few simple additions to C, that will bring in some of the functionality people have come to enjoy in higher level languages (and what functionality is "good", how do we define "good").

Friday, February 20, 2009

std::string

I was reading the Daily WTF (which is can be a great learning resource on the potential horrors of any programming language and development system).

I saw the most incredible claim, "C/C++ has no native support for such a structure [strings]. It's only in the STL.".

Err, yea, it's hard to do C++ nowadays without the STL.

You might think this code won't work:

std::string arg("Hi me");
if( "Hi me" == arg ) { printf("Yup"); }


But it resolves to
operator==(const char*, std::string &);


Of course it leads to the horror I have to deal with:

Ret myFun(const char *charp)
{
FX::FXString foxStr(charp);
randomFoxFun(&foxStr);

std::string stlStr(foxStr.text());
randomStlFun(&stlStr);

// convert STL string to Fox String
// convert STL string to char*
}

Thursday, February 19, 2009

Stuff I've read lately

"March Upcountry" (John Ringo and David Weber) - I was looking for more John Ringo. This series is in the library under Weber. I wasn't sure if it would be more Weber or Ringo. I would say it is more Ringo's style. Straight up marines slogging through enemy territory. Well done.

Sunday, February 01, 2009

Stuff I've read lately

"Manxome Foe" (John Ringo) - This is the third book in the "Into the Looking Glass" series. This is really excellent space opera. Ringo is pacing himself nicely - I think he will be able to avoid painting himself into a corner (ala Peter Hamilton's Reality Dysfunction). Good space combat and marine boarding action scenes. The right mix of humor and seriousness.