QB Express

Issue #10  ~  May 26, 2005

"A magazine by the QB community, for the QB community!"

In This Issue

From The Editor's Desk

Written by Pete

Twenty-four hours ago, QB Express #10 looked like it was going to be a standard issue -- the regular tutorials, articles, project announcements and editorials. It was business as usual.

But then yesterday evening everything changed. The Qmunity was dealt a terrific blow when QBasic News, its central message forums, were unexpectedly shut down. Thousands of messages -- volumes upon volumes of valuable QB history, tutorials, questions and news posts -- were instantly destroyed. And over 1600 QB/FB programmers were left without a home.

But instead of taking this as a deathblow, the QBasic News debacle just motivated QBers to save their community. After the dust settled, the Qmunity sprung into action. The QB/FB scene has been at its busiest and most productive in months -- just trying to restore what was lost when Wildcard, the QBasic News administrator, snapped.

In the last day, the entire face of the QB community has changed. New splinter communities made up of QBasic News refugees are forming all over the web. Meanwhile, people are trying to sort out what exactly happened -- and why. In this issue, I'll do my best to explain the situation surrounding the QBasic News shutdown, and let you know about the huge upsurge in new QB forums and site updates as a result of this unfortunate event.

Meanwhile, we still have the regular goods, including NINE tutorials and SEVEN articles / editorials, in addition to the regular columns and QB / FB news. I'm not going to summarize everything for you since that would just be repetitive -- but I'm sure you're gonna love it. Even if the rest of the Qmunity is in chaos right now, you don't have to worry about QB Express. We're not going anywhere.

Submit To QB Express

You all know the drill. This magazine can't exist without people SUBMITTING articles, editorials, tutorials, reviews, news and feedback. This is not just a solo effort by me... it's a group effort by people throughout the QB community. If you have anything to submit, or have time to write something, DO IT!

If you want to write about something, but can't think of a topic, or need inspiration, email me! I'm good at thinking of stuff to write about, and I know quite a bit about the QB community and about QB programming. If you're interested in getting your own monthly column or just want to write an article or two, by all means, do it! Anything that is submitted will be included!

I also want feedback and letters to the editor regarding this magazine. I want suggestions and critiques. What do you like? What don't you like? What could be done better? Let me know!

All submissions and feedback can be sent to pberg1@gmail.com. You can also PM me on the Pete's QB Site or QBasic News message forums. If QB Express is going to continue to be so good, YOU need to contribute!



Letter From MystikShadows

Hi Pete,

Well, a wise man once said, he who reads QB Express #9 shall find find himself enlightened and enriched. Hmmm I think that it was me who said that to the wise man...;-). Every time I know QB Express is to release a new issue, I jump into what I like to affectionately call, my "Johny 5 is alive" mode. I need, want and crave input, information, you name it. lol. And so far, QB Express has always answered that call of the binary wilderness successfully, taming down the beast within me that needs to read, learn, acquire new knowledge, solve problems and the likes. After reading #9, I'm calmer now, I've finally managed to sleep some, cut down on half the caffeine intake I've been having anticipating the arrival of #9. QB Express' #1 fan you say, YES INDEED ;-) and I hold that title with great pride (and selfish joy might I add). But realistically, I don't print all my articles so I have to humbly accept position #2 and give position #1 to Lurah ;-). As the saying goes "Anticipate denotes intelligence" Quoted from "The 5th Element", if that's so, then for about a week's time around each release of QB Express, I'm as brilliant as I can get ;-). lol

As far as the Number one contributor, well I've been pondering that ;-). Sure I can submit alot of stuff, there's still plenty I haven't written yet, and will be writing. But due to the nature of the tutorials I present, and in relations to QB Express' orientation (although that is changing too, more on that later in this letter ;-). I'm not sure all that I submit qualifies as true QB Express material. What I've seen in QB Express is that it is a game oriented magazine. the Qmunity is indeed one of game development. I haven't seen many accounting systems, databases management systems, word processors applications and other "business related or commercial software related" stuff in QB Express or anywhere else in Qmunity.. However, I do think that what I submit is good stuff as far as it's quality goes. But as far subject matter, for the game developers out there in the Qmunity some might wonder what my submissions are doing there as in how do they related to their projects. My programming background isn't from the gaming world (although I do have a game in the making ;-) it is my first attempt at a game. My background is more in the business application and commercial application development level. From that background comes some knowledge that I feel is important to share to those game programmers that might want to add a bit to their game. Sure some of what I cover may seem out of bound to the Qmunity...As I told you before, I like to cover the boring part of programming. Why? because to any programmer, game or otherwise, I think they can benefit from the submissions I have made and if I can make the boring side at least a bit less boring by the way I teach it, then I call that a successful submission. I believe I'm the only one that covers that side, it's a dirty job, but somebody's gotta do it. I can't make a 3D space ship do it's thing, but I can make sure it does it well, all the time ;-). It's that side that I offer to Qmunity the behind the scene side. Whether the game is to be of personal, Qmunity or even commercial value, I think that what I mention in my tutors and articles are worth reading just to help the developers at least think about a few things just to help their games get the edge.

I totally agree with Lachie Dazdarian, the articles he liked were as fascinating and brilliant as he puts it. One thing about Lurah that I can say is that maybe english isn't is native tongue, but his convictions and ideals are very strong and well founded that makes him more than credible for any discussion/debates about what he likes to talk about :-) and with his game, Tales form Argania in the making he'll be proving that everything that he believes in, is indeed, true. :-) (no pressure there Lurah right? lol). Lurah is a very realistic and down to earth kinda person, he'll tell things how they are, even bluntly if he has to, to get his point across some might find that his point is usually right too. I could also relate, in a non game fashion, to "What QB means to me". although I started coding long before QB, heck long before any basic lol. the situations he mentions were still there back then. Very insightful and nostalgic in some way, at least to me ;-).

I have at least 3 other submission ideas, 1 of which will probably be a series, once again...so I'm far from done writing articles and such...as I told you before, these require coding before I go ahead and write about them...so since I have submissions a plenty for the upcoming issues, I got in coding mode, get these things done so I can write about them ASAP :-). So don;t worry Qmunity, there's plenty of boring stuff to talk about ;-). But I think that you'll agree that in programming, just like in math, two negatives really do make a positive ;-). Remember what I told you about the Qmunity growing and focusing and such, projects emerging and the likes in my last letter? Well I think the reviews and projects you talk about in #9 is already a good proof of that. Games are awesome, and there's till people coding tools for game makers, basically, it's always great to see all this happening. Makes me wish I was in the QB community from day one so I wouldn't have missed a single moment of it. I mean don't get me wrong, I was in the community as in I was a QB coder in it's very start and all, but I was never online, didn't know there were groups forming and all since about 10 or 11 months ago...so I missed alot :-). But I'm glad to be here now :-).

I'd like to commend Rattrapmax6, his horse humor was much better this time around. Oh and you should see is 400x400 scolling text map editor he's working on, there's something for QB Express #10 for sure you can read about it here: http://textworld.adaworld.com/forum/viewtopic.php?t=51&start=0 and awesome piece of work if I do say so myself. Umm errr, I just did didn't I? ;-).

Thank you so much for announcing our competition on http://www.ascii-world.com in QB Express. I don't know about the others, but I'm sure, in advance, that any success this competition has will be greatly thanks to you and QB Express and whatever forum we'll announce it on ;-). I for one hope that it will be a great success.

Congratulations again Pete for continuously outdoing yourself in the way things are organized and presented in every issue, like Lachie said your positive approach to the Magazine, the Qmunity and the humor make QB Express the success it is. oh and the contributors of course have 50% of the honors :-).

And now that I've made this letter as big as my average article, I'll stop ;-)...

Signed, the number one errr two Fan ;-).

Stephane Richard

Thanks again for all the kind words, man! I agree with you that the Qmunity is mostly a game programming community -- but there are many people interested in non-gaming types of programming as well. GUIs, for example, or graphics demos. Just look at this issue -- we have a GUI tutorial and Adigun's running a FB graphics demo competition. Plus, business / professional program development is a very important skill to have if you ever want to get a legit programming job. I'm glad to run those tutorials!

There are no ifs, ands or butts about it, you're still the most dedicated and productive writer that QB Express has. Every month you submit three to four tutorials, a letter to the editor, some announcements, etc. Truly remarkable. Without people like you, I couldn't pull this magazine off.


Letter From Jacob Palm

Hi Pete Berg!

First of all, I'd like to say that I read every single article in every single issue of QB Express. It's simply the best QB zine ever, no doubt!

Well, I'm kind of a GUI-guy, so I was wondering if the magazine could have some GUI related stuff? I'd be more than happy to contribute with some reviews, tutorials etc.

Keep up the good work with QB Express and Pete's QB site!

Jacob Palm


QB Express has had quite a bit of GUI stuff in the past, if I do say so myself: a two-part series on QB GUI programming by VonGodric (Issue #3 & #5) - on buttons and textboxes, and a two-part FB GUI series by Nekrophidius that ran in Issue #6 & #7. But obviously, that's not meeting the demand. :)

Therefore, I encourage anyone with knowledge in GUI programming that's interested in writing to buckle down and write an article or tutorial for QB Express. Clearly there's a captive audience! If you want to write but don't have a topic, GUIs are a great place to start.

Anyway -- shortly after he sent this letter in, Jacob sent me an article on QBasic GUI Development. So it looks like he's taking up his own suggestion.


Letter From aetherFox

Hey Pete,

Excellent work on QB Express #9. As usual, it was a good read on the most part, and I wanted to commend you for the excellent job you did (and have been doing, and will do) in keeping the magazine in what generally is excellent shape.

My biggest problem is that it doesn't render properly in Firefox, which is a shame because I think a lot of people in the community use that browser. I am sure it is a simple fix, running the CSS through the W3C compliance check should tell you what is wrong.

It's nice to see that some people appreciate what na_th and I have done, and it's awesome to see that the game was well recieved by some people. While Joseph's review was information-wise terribly flawed, both na_th_an and I recieve criticism well; however it is a little pointless to review a text adventure game when you clearly don't seem to enjoy them. Nevertheless, Los Monos del Obús is cooking something pretty interesting for out next release. I'll be writing you an article this next issue hopefully, I have exams coming up and time is kind of sparse, but I'll do what I can.

Keep up the excellent work,
Avinash Vora a.k.a. aetherFox

I know all about the FireFox errors. The CSS is valid, but FireFox has a bug (something to do with its Gecko engine) that causes it to put big gray boxes everywhere. (That's probably what you're talking about.) I've been searching for a long time to find a better solution to this problem, but I've yet to come across one that works better than the current solution. So if there are any CSS geniuses out there that know of a better way to make textboxes that are both Pre-formatted and have text wrapping -- let me know!

About Joe's review -- I know that it was intentionally biased, since he wrote it right after you two had your flame war at QBNews. He later admitted that his review was intentionally close-minded and harsh -- and then he claimed it was a joke. (I say "claimed" since nobody really found it all that funny...) There was a huge discussion about this in the QBasic News thread that I would reprint some quotes from, but since Wildcard shut down QBN it is now no longer available. So I say we just let the issue rest.

Thanks for the letter -- and I'm glad you and Na_th_an handled Joe's negative review so well.


Letter From nitro2k01

Why the heck do you have that pikachu guy as a favicon?


That icon isn't Pikachu...but it sure looks like him. :)

It's actually an "Electric Rat" from DarkDread's The Secret of Cooey 2. When I redesigned my site, I decorated it with sprites from popular QB games that had been reviewed on my site in the past. Since DarkDread's Electric Rat was the perfect size (16x16 pixels, I believe), and I liked the picture, I made it my favicon.

Look here: Secret of Cooey 2 Review


Letter From anarky

Where are they now?

Last month's WATN article promised an interview with Eric Cowles, better known as 1000101. I have unfortunately not been able to interview Eric before the deadline. After posting on the forums, and emailing a nunber of people, I received two interested parties. DarkDread and Gianfranco of QBGames. DarkDread isn't online at the time of writing the article, and I have not been able to get him at a point where he is not too busy. Gainfranco emailed me recently, but since I have only just received the letter, I have insufficient time to compose the article. Therefore, in issue 11 of QBExpress, expect another interview by either one of the three people above. Apologies for the inconvenience.


Hey man, no problem at all. You don't even need to apologize. If you can't meet the deadline, your article can just wait for next month. Or even better - you could do two interviews for the next issue to make up for it. :)


Have a letter for the editor? Send all your rants, raves, ideas, comments and questions to pberg1@gmail.com.

Express Poll

Every issue, QB Express holds a poll to see what QBers are thinking. The poll is located on the front page of Pete's QBasic Site, so that's where you go to vote. Make sure your voice is heard!

What is the most overrated QB game?

Bob Saget Killer 2000
M \ K Productions
Dark Ages I
Michael Hoopman
The Game
Elysian Fields
Lianne in...the Dark Crown
Legend of Lith II
Hack-Man 3
Mini RPG 2 / 3
Dark Woods 2
Jocke The Beast
47 Total Votes

A lot of people hold very high opinions of various QB games that -- when you look back on it -- aren't really all they're chocked up to be. In Issue #2, I wrote an article about Tsugumo's much-lauded RPG, TheGame...which amounts to little more than an RPG engine demo. Yet when it came out, the Qmunity considered it the best thing since sliced bread. All of the games nominated on this page are considered by some to be highly overrated. I decided to nominate the ten games the most people think are overblown and take a vote. As you can see from the results, people are pretty split on this issue.

The results are a bit surprising. I thought that Bob Saget Killer 2000 would easily take the top prize, considering how highly it was rated back in the day, considering how stupid and senseless this game really is. Sure Bob Saget sucks, but you can only kill him so many times. Vance Velez even wrote an editorial at V Planet! about how BSK2000 isn't even really a game.

Instead, the top vote getters were the MiniRPG series by Jaws-V-Soft and Dark Woods 2 by Jocke The Beast -- which are, as far as I'm concerned, excellent games. They certainly are popular among the Qmunity, but I think that their popularity is warranted. MiniRPG 2 and 3 are just oozing with style -- the animation and sprites just have so much character to them. And Dark Woods 2 is one of the most addictive QB games ever released, with a huge fan following that made custom maps and even a graphical remake. I can certainly see how someone who didn't enjoy these games could see them as overrated... but compared to TheGame or BSK2000, these games are masterpieces.

News Briefs

News from all around the QB community, about the latest games, site updates, program releases and more!

Site News

The QBasic News Debacle

QBasic News was shut down yesterday for absolutely no good reason, and it REALLY pisses me off. That forum was the best collection of QBasic help, tutorials, questions, answers, news, debate, information and just good ol' conversation in the history of the QBasic scene. It is an irreplacable resource and historical document, and if it is not restored, the community made up of 1650 users -- and almost 100,000 messages will be lost forever. And according to Wildcard, it's NOT coming back. Nobody really knows exactly what happened except for Wildcard. For now, I'm not even gonna try to explain it. I guess he just snapped.

NOTE: I had a much longer news report planned for this, but I've run out of time and have to leave a on an extended 4-day trip. When I return I plan on doing a special update to QB Express #10 to give you the full story (or as much of it as I can find). Until then, I leave you with this news report, courtesy of the ASCII-WORLD guys:

UPDATE (5/31): Well, now that I'm back from my trip it looks like the whole QBasic News thing has blown over. Wildcard restored the site in full over the weekend and then announced his retirement from QBasic News. Although the site is restored, however, the damage has already been done. The once thriving community has been diffused over a half dozen new or recovering QB/FB forums, and QBasic News is now missing the majority of its active and respected senior members. The new owner of the website is Sumo Jo, the guy behind Quickhost and Freebasic.tk. Hopefully he will be able to restore QBasic News to its former glory, but I don't see it happening anytime soon. So much can change in just a matter of days.

QBasicNews, What the ... ?

A Newsbrief by MystikShadows and Lurah

Where to begin, not sure, but the most established online forum to our beloved QB Community, QBasicNews has come to a harsh, unpredictable, definitaly avoidable end, in my most humble opinion. From what i've seen, it would seem many posts aimed at helping were misread or simply disregarded, some jumped to conclusions they shouldn't have, hell almost broke loose, next thing you know a post about "QbasicNews is shutting down" surfaces.

How did it all happen? on the surface and from what users can read, it seems that what started out as a thread about a competition, ended as a public debate about what's doing (or not doing) what to help make QBasicNews a better place. After a few exchance of ideas/criticism/suggestions/comments WildCard seemed to have decided to close the boards. In my opinion this decision was absolutely uncalled for and was the result of either the powers that be are unable to accept criticism of any kind (thinking they are above it or something, yeah right). or the admin, WildCard, was looking for a way out of QBasicNews and decided that that thread that started a debate was going to be his way out. in both cases, it just doesn't make sense and showed the immaturity of the board administrator(s).

All I know is that the comments that were made, most of them were to help and give tricks and tips about what could be done, not just by my but by others, in their own special way ;-). But it seems the admins and mods had a very different concept of what a moderator and administrator should do or have to do. All this lead to what we can read now on QBasicNews.

From the quick time it took to come to the decision to close this board, all I can think is those two reasons I mentionned. No other reason would cause such a quick reaction of this nature.

MystikShadows and Lurah


QB Forum Wrap-Up

There have been about a trillion new QB forums started within the last 24 hours, and there's no way in hell I'm going to create separate news items for all of them. :) But they are worth mentioning, especially if you're looking for a new home in the wake of QBasic News's shutdown yesterday. So here you go:

  • The Basic Network (http://www.basicnetwork.net)

    Nekrophidius and Rhiannon resurrected The Basic Network within minutes of when Wildcard shut down QBasic News, and this forum has quickly become the most active QB/FB forum on the 'net. There are already over 500 posts and 34 NEW members who have registered in the last 24 hours. This is the closest thing to the old QB News forums that's going right now.

  • Bad-Logic (http://ratatoskr.dragonhill.cc/forum/)

    Marzec started this forum a while ago, but until yesterday it was just a back-up version of the old Bad-Logic.com forum that was popular last year until the website went down. Therefore, it is starting out with a rich archive of past posts and started with 42 users. Now it has 43 though, heheh. :) It's been fairly active in the past day.

  • QBasic Network (http://www.qbasicnetwork.com/)

    Anarky actually started this website a few weeks ago, but it's been little more than a forum since then. (It also has a bit of Legend of Aquarius info -- about an RPG in the works). But otherwise it's a new QB forum that has has a tiny bit of activity and an annoying default skin (Blue Steel). Hopefully this site will expand become more active soon.

  • FreeBasic.net Forums (http://www.freebasic.net/forum/)

    V1ctor, oh great one, god among men, the holiest of holy and creator of FreeBasic started this forum in response to the QB News FreeBasic forums shutting down. I guess you could say it's the spiritual successor of the QBN FB forums...but it's not nearly as active yet.

  • FBTK.net (http://www.fbtk.net/)

    Okay, so FBTK.net really isn't new (it's just FreeBasic.tk with a new address and a new server) -- but it did move yesterday, the same day as all hell broke loose. So update your freakin links!

  • FBForum (http://www.fbforum.tk/)

    VonGodric made this PHPBB forum in the exact same style as the old QBasic News forums -- it has the Smart Dark skin and the exact same forum headings. As of right now, though, it has very few members and is not really been active (maybe because it just started less than an hour ago, heheh).

I suggest that everyone congregate at a single QB forum and try to repopulate the old QB News crowd elsewhere, rather than spreading ourselves thin on lots of different forums. For now, The Basic Network is the most active one, so I'm going to throw my support behind them as the new QBN home.

Lachie Dazdarian begins QBasic games archive
Lachie Dazdarian, a HUGE QB gaming fan, began an enormous effort recently to collect all the good (or decent) QB games ever made into one gigantic searchable archive -- and he's made a lot of progress so far. A few weeks ago, he posted a preview version of the future site on the QBasic News forums and it was exciting and inspiring to see all of those great QB games collected together, rated and described. Somewhere on the web you can still access this preview version, but I don't know where to find it now that the QBasic News forums have shut down. The original post used to be at: this address. Maybe in the next issue I can give you more info.
QB45.com and V Planet! coming back within a week!
I have read in numerous places that the people in charge of QB45.com and V Planet! will be returning within the next few days. Fling-master and Jofers have posted about this at the QB45.com board, and Joe King (who is helming the V Planet! return) has also said that VP will come back by the end of the month. Now I know that these announcements have been made many times in the past and not come true, but once again I'll hold on to hope that it will actually happen this time. And if it does: HOORAY!!
FreeBasic Wiki Started!
V1ctor has started a FB Wiki, which is already become a great information source. I encourage everyone to contribute! http://www.freebasic.net/wiki/wikka.php?wakka=FBWiki

Project News

Dark Prevail unleashes an ArKade game
Dark Prevail recently released an arcade shooter game with old school wireframe graphics and a frenetic pace. It's also got a very simple name: ArKade. It's worth a download just to see the menu screen (it's actually really cool). The game's not bad either. :) Download it here (987KB).
Space Impakto makes an impact

Relsoft released a demo of an awesome space shooter on May 9th that apparently goes by the name Space Impakto. Like all of Rel's releases, this is very graphically impressive. Colorful, detailed enemy and gunfire sprites dart around the screen (complete with Mode7 2D effects) on top of nice backgrounds -- and even though it's at just 320*240 resolution, it still really impresses.

At this stage in development, it's really still just an engine demo -- and there's no real way to win (you just play until you run out of health). Rel posted this early release in order to get feedback and FPS reports from the Qmunity -- not that it's really necessary. The latest version runs at a full 60fps on a Pentium 233. That's pretty darn good. Download it here.

Mazerun by loking1235
Loking1235 released a cool FB minigame a few weeks ago where you guide your mouse cursor through mazes. It's called Mazerun. Here's his description: "Mazerun Can you make it through the maze? Use your mouse to move the little green ball to the red goal. Do not touch the walls or you will have to start over again. " Simple but addictive. You can get it at this website.
Z!re Gets Bored
If you're looking for a simple game, Z!re's BORED v1 is as simple as they come. Basically, don't let your mouse cursor hit the wall -- that's all there is to it. This game is a fun distraction for a few minutes... you can find out more at this address.
GFXLib Gets Alpha Capabilities
Angelo Mottola's FB graphics library that allows you to use the old QB graphics commands (and much, much more) got another new feature on May 13th -- Alpha channels in your PUT sprites. For more info, check out lillo's thread: here.
FBIde v0.4 Released!
VonGodric's much-heralded FreeBasic IDE had a new version released on May 18th -- you can read his news posts here and here, among other places. Version 0.4 features tabbed coding windows, quick run, code highlighting and a whole lot more. If you'd like to see a screenshot, there's one HERE. :) But you should really visit FBIde.sourceforge.net for the full scoop and to get a copy of this supremely useful FB coding tool.
FreeTile Library for FreeBasic

Xerol announced his plans to open up a FreeTile Library for FreeBasic where users will be able to share sprites for use in game projects through a database-driven website. I think it's a great idea. Here's some more info from Xerol:

Ok, while slaving over a 32x32 badly made grass tile in Paint last night, I really wanted to find a place where there'd be a bunch of tiles just ready to use.

The concept is that all these tiles would be free to use, in any project, commercial or not, as long as they were used with a FreeBasic game. (Or non-game program that for some reason uses sprites.) I'll provide the hosting myself unless the size gets out of hand.

Check out this thread to get involved.

MariuZ announces an RPG ... a Pure QB RPG!
There aren't too many of these getting announced anymore and they used to be a dime a dozen...pure QB RPGs. But they're not a completely extinct species. MariuZ just announced one at Jocke The Beast's board. The game will be written in pure QB except for sound, will have "selfmade music" and "hopefully about 5 hours of gameplay". You can see a screenshot here. I wish MariuZ luck!
Zero Divide releases new QB GUI

Zero_Divide released CycloNe v1.5 recently, a GUI library for QB 4.5. It has a nice Windows 95 look to it and is one of the better QB GUIs I've seen. You can find out about it at Zero_Divide's Site. Here's a list of features:

  • Work with high resolutions from 320?200 to 1280?1024 in 256 color palette
  • Loading of BMP pictures in deph 8 bit
  • Support XMS Memory
  • Whole Support of mouse
  • All elements have its own features and can be changed as well
  • Built using SVGAQB v2.6

Other News

Dark Ages II: Engel gets new demo release (!)

As many of you may recall, back in 1998, Michael Hoopman's Dark Ages I: The Continents was the talk of the town. It was one of the first finished QB RPGs, and it got a lot of recognition (it was even included on the pack-in CD of a mass market PC gaming magazine - PC Gamer or PC World or one of those mags). So when Hoopman started making a sequel to Dark Ages, it was big news. QBasic: The Magazine (the reigning QB zine of the time) spent quite a bit of time hyping it up, including a huge preview in December 1998 and constant updates. DA2 got quite the fan following in the QB scene.

But that was 1998. Now it's 2005. I'm sure most people assumed that Dark Ages II was just another dead project, abandoned somewhere in mid-development and never to see the light of day. Well, it turns out that DA2 never ended up dying like we all assumed. It ended up being ported to Visual Basic and is actually STILL in development.

On May 15th, Michael Hoopman released a new beta release of the game at his website, Dark Knight Software. As a huge fan of the first game, I was amazed when I heard this news and rushed to check out ... what ended up being a fairly lackluster demo that hasn't changed much from its QB demos back in 1999. And it still features the same old sprite graphics that look incredibly dated these days. Oh well. Maybe one day when it gets finished it will manage to live up to the simple fun of the first one.

New QBXL Audio Edition

SJ Zero has *finally* released a new QBXL audio version after more than a year. Like the previous three audio editions, this features satire and parody news with a Daily Show-like radio delivery style. This latest issue made fun of several things around the Qmunity, and even mentioned myself and QB Express in its report on Adigun A. Polack's FreeBasic Demo Competition. You can find the new edition here: qbxl.net/downloads/qbxlAudio4.ogg


Written by Pete

Every issue QB Express features a preview and exciting new screenshots from an upcoming QB game. If you would like your game featured, send in some screenshots!

ASCIIQUEST Editor v1.0

The following information was reprinted from http://qb45.think-new.com/asciiquest.php.

Jace Masula (better known as momoguru on some forums) has been working on an incredible looking ASCII RPG / "quest" editor for the past few months that everyone should definitely check out. Last month, a beta version was released on his website, and version 1.0 is due out soon. (The official release date according to the website is June 17th, though I have heard through the grapevine that this program may bre released as early as TODAY, May 27th.

I had time to briefly check out a special preview copy of v1.0, and I must say that it is one powerful piece of software. Everything you need to create an awesome ASCII game world is here, and the presentation of this package is excellent. This app has a great map editor (with a lot of awesome demo maps included of dungeons, castles and grassy overworlds), a music editor, an enemy / object editor, and an ASCII paint program. The interface is very intuitive and is mouse driven, and you should have no problem finding your way around the program. Also included is a giant FAQ / Readme which is very extensive. This is a very impressive package, and everything is well thought-out.

I didn't have the chance to try making a game with ASCIIQUEST in the short time that I had to check it out (ugggh, deadlines)... but when v1.0 is released, I encourage everyone else to give it a try -- and actually make an ASCII quest game with it.

Due to deadline constraints, I've reprinted the description of ASCIIQUEST from the QBasic Lab website for your reading pleasure (rather than rewriting it). Enjoy!


ASCIIQUEST is an ascii game creation package. It contains everything you need to created and play you very own ascii character rpg / puzzle games. You can create maps that are scripted to events. The easy to use event scripting allows you to build simple or complex game events.

ASCIIQUEST is easy to use and the game engine makes the games you create easy to play. This program is 100% free and only displays 2 small lines of credits at the bottom of the game engine credits screen.

The ASCIIQUEST Game editor / engine
These 2 main components will allow you to create and play your very own ASCII character RPG type puzzle games. The Download comes with a simple manual which will help you get started creating your first game. Keep in mind that the editor and engine are somewhat simple…
if you are looking for an advanced RPG game maker, this is NOT it. However, the ASCIIQUEST game engine can do some neat stuff. (once you get the hang of how it works)

Some of the basic things you can do with ASCIIQUEST are: change maps, healers, inns. taverns, quests, gate triggers and ifgate checking, teleporting, combat spells, unlimited items, objects, weapons, armor, spells and quests. cutscreens, and more.

There are a few additional programs that I have included to help you construct various elements used by the game engine. ASCIIPAINT will help you create game screens and ascii graphics. QBPLAY will assist you in creating sound and music for the game. and EDIT, which will allow you to edit your enemy.DAT and objects.DAT files.
Keep in mind these are separate programs. You may want to check for newer versions.

Everything you need to created your very own ascii game is included. I still plan do update this here and there as I get time. If you encounter any errors, do your best to work around them until I cant get them fixed.

Visit the Jace Masula's QBasic Lab for more information.

Review of Battle Pong by Lithium

Written by Adigun Azikiwe Polack

SURE there has been countless and countless many Pong clones out there every which way you look these days, but I mean, hey, only few of the QB games of this type have *really* stood out from the crowd, including Pong: Battle Royal by Budfish Software (remember that one?). But now since the very advent of FreeBASIC, game programming has finally broadened and exploded into a whole entirely new level already! And I am so glad to say that Battle Pong by Chris Adams (aka Lithium) uses that power so well, and has taken the ordinary Pong game into a whole new direction for FB!!!

G A M E • S Y N O P S I S

When you first rev up the game, you are taken immediately to a title/menu screen where you have some excellent options to choose from like the enemy AI of the opposing player, the number of maximum balls to be placed on-screen (up to five!), the color of your paddle that you want (Silver, Blue, or Pink), the time limit, the score limit (number of pts. needed to win), and even the odds of an item appearing on the screen. Very cool stuff, Lithium, as it truly is a great start for you here!

When the game finally starts with the two paddles entering the arena, it may look like ordinary Pong on the surface, BUT, when the power-up items begin to fly off of at least one of the paddles, you know the game is gonna be some truly hot stuff!! Why? Because the power-ups do consist of the following:

Machine Gun ::: Lets you fire off rapid shots in order to chip away at the opposing paddle to dish out some damage in your favor.

Freezer Item ::: When this weapon is used on enemy paddle successfully, it simply slows it down, giving you some advantage!

Missile ::: Gives you the ability to fire them rockets to score some bigger destruction on the opposition, because they are much more poweful than the Machine Gun alone!

Death Ray ::: The ULTIMATE weapon!! When this is fired on an enemy paddle, it simply destroys it completely. Period. Beware, however, for you have only TWO (2) shots of ammo on this, so make ‘em count!!

In addition, there are other items just waiting for you to grab, including ones marked “25”, “50”, and “100” that replenish some to a lot of health to you, as well as “Shrink” and “Expand” items that adjust the size of your paddle, and if that ain’t enough, there is even an item that puts an additional ball into play when gotten! Watch out though, as your opposing paddle can ALSO grab the same items as well, causing it to possibly do you some damage. With all of this going on and more, it simply adds depth and big challenge to the game, I believe!

T H E • B R E A K D O W N

As a one-player game, Battle Pong really is some awesome stuff right there, *especially* in the Enemy AI that plays some serious games with you in serving the ball and keeping it in play! Smart, truly well-balanced and challenging stuff!!! (Now let us see other games in FB that do that! ) In addition, bring a friend, fire up the two player game, and watch this game REALLY rock!!! d==b ! Hey, you can even watch the computer play against itself, too!

The keyboard-based play control here is nothing short of excellent, and the speed at which your paddle is moving is handled just right, the way is should DEFINITELY be for such an original Pong-based game as this in FB!! (^_^)v

The graphics are some pretty good caliber stuff, clean and simple, albeit being done in SDL and some high-res graphics, and the candystriped-like blue-and-black background is much easier on the eyes and does not even distract the intense gameplay action one bit! Nicely done now!

As for the sound effects, they are AWESOME, from the sound of the ball to the intense warfare of gunfire and even to the sound of your opponent being covered in ice or even exploding under the prey of your shots, too, only they are all being done so very wonderfully here! Lithium sure knows how to take his own time in choosing the right sounds for the right moments in this game, and I am truly proud of him on that!!

The minor small problems I had were absolutely no music at all, and that the opposing paddle you are facing in a one-player game can sometimes be no more than just a sitting duck while waiting for the ball to come to it, leaving it open prey for your continuous machine gun shots. That takes away some of the challenge a bit. Still, I highly recommend this game personally, especially for you Pong maniacs out there who want some pizazz and excellent long-lasting gameplay to take you out of the ordinary, and Battle Pong by Chris Adams (aka Lithium) does exactly that and more, making it the first TRULY GOOD ball-and-paddle game ever created in FreeBASIC!! Take a bow, Lithium!!! !!

T H E • F I N A L • V E R D I C T


With loads of features, excellent power-ups, a *perfectly* well-balanced enemy AI, mass-destructive weaponry, great SFX, and awesome gameplay that lasts and lasts, Battle Pong by Lithium is an real intensely good time for 1 or 2 players that takes the original Pong game to a much higher and better level in FreeBASIC!!! =b !

Download Battle Pong, or visit the AAP Official Projects Squad.

AI: Artifical Stupidity

Written by aetherFox

First of all, this is going to be an extremely short and completely theory based tutorial. The reason I will not provide code on implementing the techniques discussed below is that they are (in my opinion) implemented differently for whatever situation they are coded for. There are many source examples on the Internet should you care to look hard enough.

Artificial intelligence is one area where many games fail to make a big impression on gamers. Many people complain about the dull and (ironically) robotic AI, that is so predictable and monotonous that it hinders the overall impact of the game.

There are many ways to make the artificial intelligence of a game more interesting and ways to make it part of the core gameplay - enemies that seek the player out, attempt to defend territory, heal when injured, or flee when dying. You might think this is complex and difficult to achieve, but through two quite standard and simple techniques - Finite State Machines (FSM) and Probability Distributions (PD), you can make your game a much more enjoyable experience.

Finite State Machines - A behaviour model that simulates intelligence wherein the "machine" (object) can act in only a finite number of ways.

Let's use a simple example - a shooter. Your basic enemy will be a fighter, that might have 3 states. Find, Flee, Attack. Using the principle of FSM, you would take information from the environment of the machine and from that information, invoke one of the states. In psuedo-code, using our shooter example:

The problem with this is that you suffer from the same problem that was the cause of writing the tutorial, predictability. The player would immediately see the states and every single enemy would become part of a "flock" an do the exact same thing in the same scenario.

The way to overcome this is to use Probability Distributions:

Probability Distributions - A list of probabilities assigned to various states of an object.

To implement it to our shooter example, instead of invoking the Attack subroutine when PlayerIsNear is true, you would raise the probability of attacking the player and reduce the probability of finding the player. Then, you could choose a random number from a range (one that is suitable for your game's difficulty), and depending on the number, invoke one of the states.

This leads on to many interesting things. If you introduce more states, then you could have very complex NPC's. Imagine in a shooter, where if you injure the enemy, and then the enemy runs off, but might alarm others if it is brave enough? Using the probabilities, it opens up a whole range of possibilites. You might have the problem that in a state where fleeing is the dominant probability, attacking, which is the least probable state, is chosen. No worries, this enemy might be a rogue brave fighter. Similarly, you could have fighters that flee at sight of you, making them seem cowardly.

The words "brave" and "cowardly" I have used there are personifying a few lines of computer code. With time and practice, you could come up with perfect probabilites to have a range of possibilites that your "AI" might take as a course of action.

This is just a short bit of theory that shows a little about a very underused (in the amateur game community) technique for implementing clever NPC's. It is also such a generic technique, it can be applied to every style of game where a certain level of intelligence is needed. An NPC in an RPG town who might react differently to different situations - if the evil king is defeated, he might be scared. Or maybe in your FPS you might have a group of zombies who when they are together have the guts to face you, but when they are alone they might just run away, alert others and call them to your location. If you look at it from other perspectives, it may seem that your game is "intelligent," but from the fairly simple code you wrote to implement them, you'll see that AI is actually pretty stupid.

Avinash "aetherFox" Vora
avinashvora [at] gmail [dot] com.

Download a copy of this article.

ASCII-WORLD Competition Follow-Up

Organized by lurah and MystikShadows

Last month, QB Express brought you news about ASCII-WORLD's first competition, which had a summer theme. You can read all about it in this article.

This month, lurah brings us some updated rules and deadline information.


We, Stephane Richards and I have received some questions about date what is last one to submit demos.

So here is, a bit modified but clear informations about submitting, voting and declaring winner.

  1. The 30th of June is last day to submit demos.
  2. Voting of winner starts the 2nd of July.
  3. We announce about voting practically in every site that we can imagine.
  4. Winner is declared on QBExpress #11
  5. Winner should get hes/her prize in same month, no matter where on earth he/she lives =)
  6. Stephane Richards is offline for a week (approximately) so if any one has questions about our contest, then fastest way to get ansver is to email at virtanen.kristian@lemmikkini.net or go in our forum at www.ascii-world.com.

    Regards, lurah

So What The Heck Is Fun Anyways?

Written by Deleter

In my last article, I stressed the need for fun in a game without really defining what fun is. So, what is it? My good friend, the online Merriam Webster dictionay, tells me that fun is "what provides amusement or enjoyment." There you go, thats it! Go and make your fun games now =D. Oh, that isn't enough, you say? Of course not, if that was enough, you wouldn't have opened this article in the first place.

So how do we really define fun? Let me start with a poem:

Once there was a programmer,
He didn't have the best grammer,
He couldn't rhyme worth a damn,
Couldn't keep a good rythym,
Couldnt't keep it flowing,

(Crickets) Ahem. So, why did I just put you through that horrifying experience? Here's why: I hate poetry. I hate writing it, reading it, and especially anyalyzing it. Therefore, I had no fun whatsoever writing the above passage, and I surely hope you didn't have any fun reading it. So, what does writing poetry have to do with game programming? Not much actually. But here's what I'm trying to say: if its not the type of game you would want to play, not only is it going to be a type of game you don't want to program, people aren't going to want to play it, either.

Hmm, so I've picked a genre I know and love, now what? Well hyar naje rgw danw abs rgwt qukk akk kicw tiy. You get that? Didn't think so. If your design and implementation confuse the driving force of your game (what makes it fun), just like my writing that message all wrong, people are NOT going to get anything out of it.

So, you made a clear design with the backdrop of your favorite style of game, and and and and and and yoooooooooooooooooooooooooooooooou hhhhaaaaaavvvveeee mAdE thhhhee game. Make sure you DEBUG it all the way. Don't let things slide, and for sure don't be ignorant enough to leave any code/game resource untested. A simple bug can ruin a whole game.

Ok, I thought you were going to tell me what to do, not what not to do.... That I did. So now that I have the basic.....erm.....BASIC and design stuff out of the way, whats fun? What takes a game from a lifeless collection of pixels moving on a screen to an enjoyable and interesting use of code for entertainment? Want to know what the answer is?


Thats right, nothing makes a game fun. Perhaps I should rephrase that, no one thing will make your game fun for everyone. Why? Everyone likes different things. What sort of world would it be if everyone played the exact same games? Boring as heck, for sure.

So, then how do I make it fun? Well, since different people think different things are fun, you need a target audience, in other words, you need a group of people whom find what your making fun. The RPG crowd will never like you if you give them an RTS, FPS'ers won't accept your SIM.

So, the question then become, which group? Easy, remember my poem? The idea works with groups as well. Make games for the groups you consider yourself to be a part of.

Ok, I've got all that down, but my game just isn't right. There aren't bugs, its my favorite genre and I kept it simple and limited complicated code, but after awhile, it just gets flat out boring. For this problem, I'm going to give you three short narratives:

1) You're going down a flat, broad river. Your boat dips and rises with the almost nonexistent current. The hot, bright sun beats on you as it has for the last five weeks. The shore is stagnet. Nothing moves, the heat causing all to stay still.You sit back against the raft, half asleep. a cloudless sky offers nothing to watch.
2) A waterfall looms several hundred meters before you, you know it will be your death. You fall down it!!!!! As your boat hits the river, you thank God you're still alive.
3) The river's current rushes past your boat, suddenly active with energy from an unknown source. You become alive with energy as your boat picks up speed. A quiet noise comes to your attention. As you clench the sides of your boat with white fists, your attention is captivated by the noise, which is growing ever louder and more ominous. You can't see where its coming from, but you know that whatever it is, it can't be good. The unknown menace hides behind the thick trees lining the shore that bends in front of you. With panic, you stare wide-eyed as your boat turns around the bend.

Which did you like best? The last one, I hope. Why did I drag you through more of my literature? Flow. No, not river flow, Game flow. The flow of the river in these did indeed represent the ways in which your game can flow. How do you apply this to game flow? Lets briefly examine my literature and see how.

In the first piece, you are presented with a situation where nothing happens, there isn't a dilemma of any sort. If in a game, there is no motive it will quickly turn monotonous and people wont play for very long.

In the second piece, there is a dilemma, however, the player isn't given enough time to work up to it and get interested before its all over. If in a game, you rush the player, forcing this or that, end it real fast, or have things happen prematuraly, your player is going to get frustrated and quit.

The third piece has: A dilemma: check. Enough time for the player to care: check. Enough content to keep the player interested: check. Properly implemented events: check. I wrote player instead of reader, because this directly translates to gaming.

Basically, flow is pushing the player at the right speed, while giving him enough to be interested in to want to go at that speed. This is easier defined in an RPG with progressing the story, but can be applied to other games as well. FPS, for example. Ease of maps to avoid long stalls, new monsters and guns to keep them interested, and usually some sort of boss battle to build up to and look forward to.

So, to sum it all up:

  1. Interest - make something you're interested in
  2. Clear Design / Debugging - Don't let sloppy plans or code ruin your awesome game
  3. Release to the right people - Not really important to the game's fun so much as its acceptance/success
  4. Game flow - One of the hardest elements of programmer/designing. This includes all elements of game creation. Design - Making sure your game idea won't stall and the player won't 'snag' on any parts of your game. Programming - Not only bugs, but simply programming choices (player speed/power, for example) can affect the flow of your game. And finally Implementation & Story: Implementation is the content creation (maps, sprites, models =P, etc.). Map design is the most important as it directly affects the player's experience and can't be looked over. Story is mostly RPG's, since all other games don't rely to heavily on the story. Basically, your story ought to follow my example above, allow enough time between start and climax, have interesting content that keeps the player hooked, events at the right time, and a worthy climax.

That's all I can think of, and I know its a lot more than you wanted to read, so I'll end it here *hears cries of relief*. Thanks for reading! Remember: Please send comments/suggestions/insults to my email (barbarian_roleplayer@yahoo.com) Also, if you have any ideas for upcoming articles, feel free to suggest them to me.

Visit Deleter's new site, Random Musings of a QBasic/FBasic Game Programmer.

The BASIC User's Guide to English Spelling and Grammar

Compiled by DrV, Unofficial Master of the English Language

I've seen all of these incorrect uses of English repeatedly on multiple forums and various pages on the World Wide Web. Please pay close attention and take notes. :)

(I realize that not everyone speaks English natively and that not everyone has had a decent English education, but I feel the need to share my knowledge and experience in order to improve the level of aptitude among forum posters and others whose writing appears on publicly accessible Internet resources. I'm not trying to be elitist or flaunt my superior language skills. I'm sure I would get bashed immediately for my grammar and spelling if I tried to write in some other language. If you still feel the need to send me large quantities of inflamed commentary on my high-falutin' approach to educatin' the populace, feel free - you can reach me at the QBN forums.)

Commonly Misspelled Words

Common Misspelling(s)
definately (I see this one two or three times on an average day...if you don't get anything else out of this, remember this one!)

Commonly Misused Words

Common Misuse
recursive decent parser (should be "descent")
All three of these are commonly interchanged when they shouldn't be. "There" is a location, "they're" is a contraction for "they are", and "their" is a possessive adjective.
"Then" and "than" are interchanged often. "Then" is a time or conditional ("I ate lunch, and then I went home"); "than" is an adjective ("I ate more than George.").
Commonly interchanged. "It's" is a contraction for "it is" ("It's cold outside."); "its" is a possessive adjective ("Its wheels were round.").
Commonly interchanged. "Who's" is a contraction for "who is" ("Who's eating the apple pie?"); "whose" is a possessive adjective ("Whose apple pie is that?").
"To" is a preposition; "too" is a comparative adjective. "I went to the store"; "I drank too much."
"Your" is a possessive adjective ("This was your idea.");
"you're" is a contraction for "you are" ("You're so smart.").
Usually used by Nintendo newbies when speaking of Link in the Legend of Zelda series.
"Effect" is a noun meaning "the result of an action" ("The effect of excessive drinking is a hangover."); affect is a verb meaning "to manipulate in some way" ("I wish my ranting would affect these people.")
"Good" is an adjective ("You are a good reader.");
"well" is an adverb ("I did well on the test.").

Just Plain Wrong Words

Why it's wrong
This word does not exist in the English language. "Them" is plural; it cannot be used to refer to one person. Therefore, "themself" cannot logically exist. "Themselves" is the usual correct replacement, but the structure of the entire sentence must be considered in such a situation; an entirely different word or phrase or even restructuring of the sentence might be in order.


I'm sure I haven't caught everything here, but these are the most overtly ridiculous and often-occuring examples of poor grammar and spelling encountered by yours truly.

(If you didn't notice, some of this wasn't entirely serious, but if you take most of it to heart, you'll live a more enjoyable and productive life and impress people with your mad English skillz. Ignorance is not bliss. For great justice!)

You can find DrV at the QBasic News Forums.

QBasic GUI Development

Written by Jacob Palm


Have you ever been annoyed by Windows taking up way to much RAM and CPU power, and felt like switching to DOS, but then haven't because of the lack of a graphical interface? I know I have. That's why I decided to make a graphical interface (GUI for short) myself. When you make a GUI yourself, you can leave out all the stuff you newer use anyway, which will make the GUI faster and smaller, allowing it to run on old computers, too.

Of course you don't necessarily have to replace Windows or DOS with your GUI. You can make one just for fun, or maybe for other people to use. The reason I make a GUI is that I think it's funny to see how much I can get the computer to do, how nice I can make it look, how far I can push QBasic and such. I've also really learned a lot about computers while making a GUI. But whatever reason you may have to make a GUI, I'll do my best to tell you something about QBasic GUI's. Don't expect to find any code here, this article is purely theoretical. I'll write some stuff about what a good GUI should have, and give some tips. Maybe I'll write a tutorial for the next issue of QB Express.

Excuse me if my english isn't perfect, don't forget that I'm only 15 years old and from Denmark. This is the first article I've ever written. I hope you'll find it interesting.

What a good GUI should have

What your GUI should contain of accessories is fully up to you. But there is some accessories the user would expect to find in a GUI. Below I've made a list of some accessories every GUI should have.

Of course there's more than what I've listed here. This is just a list of some of the most common things users expect to find in a GUI. You could of course release a SDK (Software Development Kit) for your GUI, allowing users to write their own accessories which fit in to the GUI nicely. Some users actually send their creations to the author of the GUI, which in some cases include it in the GUI, making it even better.


I've listed some tips below which you may find useful in the development of a GUI.

  1. Many people like it when the GUI displays some icons. If your GUI is made up of text and windows only, it might be a little boring to look at. But don't just make some icons, they should fit in to the correct places. For example, an icon of a cow doesn't belong in an error-message (unless it's a dead cow, maybe)
  2. Split up your GUI in several EXE's. This will help improve the stability of the GUI. For improved stability, each accessory should be in it's own EXE file. Then, when an accessory makes an error and exits, the user will still return to the program launcher. Splitting up the GUI in several EXE files will, however, make it a lot harder to do multitasking(thank you to Todd Suess for this tip)
  3. Use screen modes with page-support. It will drastically reduce flicker in your GUI if you draw the screen on a videopage before you show it on the screen. The best screen mode for GUI's (which support pages) would be screen 9, since it has a high resolution (640x350 pixels). You can also use the statement "WAIT &H3DA, 8" (without the quotes) to wait for the next screen redraw before drawing something. Don't use it in a loop, though, that would drastically reduce the speed of the GUI.
  4. Use a font routine which doesn't display capital letters only. IT'S VERY ANNOYING TO READ TEXT WITH UPPERCASE LETTERS ONLY, as you may see.
  5. If possible, provide an e-mail address or website where the user can get support if he/she has a problem or question regarding the GUI.
  6. Try to make the interface as easy to use as possible. It's not easy using a program if the buttons only have pictures on them which doesn't tell what the button does. The best way would be to add text to the button, or a tooltip.

There are more ways to optimize your GUI, but most of them isn't GUI related, but works in all QBasic programs (some of the tips above work in all QBasic programs, but they're very useful in GUI's, so I decided to list them anyway)

Links to GUI pages

There are some QBasic GUI related pages out there, but not that many. I've listed below some of my favorite sites (and my own, of course).

There used to be more GUI sites, but most of them are closed now.

That's it for now

Well, I don't have much more for you this time. I hope you enjoyed reading this article, and found the contents useful. If you have any questions or comments regarding this article, feel free to e-mail me at hvalrossen@jacobpalm.dk. You can also post in the forum at my website. Good luck with your GUI programming!

Jacob Palm
(The Walrus at some forums)

Make sure you visit JacobPalm.dk, Jacob's great QB GUI site and last month's QB Express Site of the Month!

Monthly Awards

Written by Pete

Every month, QB Express hands out two awards to recognize QB or FB coders and websites that have done exceptional work in the last month. They are not awarded for work done in the past, only for work that has been released since the last issue of the magazine. Z!re and I have teamed up to bring you these awards on a monthly basis to help give credit where credit is due.

Site of the Month

The Basic Network

Webmasters: Nekrophidius & Rhiannon

Since its relaunch less than 24 hours ago, The Basic Network has really made waves in the Qmunity. In its first half-day of life, this new QB forum has had nearly 400 posts, and has become a haven for QBasic News refugees seeking a stable, active forum. If any QB forum is going to become the new QBasic News, The Basic Network is it. I encourage all QBasic News members looking for a new forum to join The Basic Network today. Of all the forums out there, I think this one has the best chance of becoming the new center of the Qmunity.

Programmer of the Month


This month, VonGodric released version 0.4 of his awesome IDE for FreeBasic, FBIde. The interface of this IDE turns the scary & unfriendly (to newbies) command-line interface of FreeBasic into an experience not unlike the user-friendly IDE that made QB so popular.

FBIde features tabbed editing, code highlighting, quickrun (just like pressing F5 in QB), and a sleek Windows interface.

VonGodric was also a highly respected and very helpful member of the QBasic News forums, helping QB and FB coders alike with their questions. Shortly before QBN was now shut down, VonGodric was appointed moderator of the forums for his outstanding dedication the Qmunity.

FreeBASIC Ultimate Demo Compo:
the brighter new gala of the FB demoscene!

Written by Adigun Azikiwe Polack

Are you psyched and ready for a whole new and freshly different breed of compo by yours truly? You better be now, because you are looking at an ever-promising new gala that is even more brighter than my three QuickBASIC Caliber Programming Compos. And the gala is entitled the FreeBASIC Ultimate Demo Compo, which is *entirely* so different from my previous compos in many different ways.

Here is why:

(Left to right:The Final Frontier” by Qasir; and “Digital Reality” by Plasma.)

And also, Pete Berg of QB Express is so wonderfully honored to sponsor this very special event. =b ! Remember too that this compo is aimed primarily for those who simply want to create such fresh and imaginative new demos like never before in FB, as well as for anybody at all that wants to enter to take on the ultimate challenge, too.

The special prize plaques are set for the winners as follows:

Grand Prize” plaque (for 1st place!!)

Silver Prize” plaque (for 2nd place)

Bronze Prize” plaque (for 3rd place)

The official compo deadline is set to Wednesday, August 31, 2005, so that you have plenty of time to dig in and create your most inspiring entry!! After the deadline is up, I will be launching a very special thread in the QBasicNews.com forums to let YOU decide which demo will take home the Grand Prize indeed!!!

For a full description of this compo and all the details, please go to http://dhost.hopto.org/aapproj/fbgfx/compo.html and do enjoy the festivities.



Adigun Azikiwe Polack
Official Founder of the “FreeBASIC Ultimate Demo Compo

Visit the FreeBASIC Ultimate Demo Compo!


By Rattrapmax6

Rattrapmax6 is back this month with another QBasic Horse Humor comic.

I.F. Games Chapter 5:
"Teaching English to our computer"

Written by Na_th_an

Y'ello, guys and girls. One more month and one more chapter in which will become a true Quixote. Originally I had planed just 3 chapters, but you see. Things are gotten out of hand, mainly 'cause I've found that some things really HAVE TO be explained in depth. If I had just thrown in a bunch of code in the last chapter, covering the whole engine, you would have ended with an IF engine which would be worth nothing, tutorial-wise. I have two main objectives with this series, the first of them being you learning to write proper text adventure games for yourself, and the second, underlying one which is teaching people to produce better code. That's why this series will take much longer than expected, I just want to discuss every bit, how it works and why is it coded that way, 'cause the goal is that you are able to write your own engine instead of having to use mine.

This chapter we're discussing about the parser module. First of all we'll make a quick reminder on what we want this module to do and then we'll see how.

Coding the Parser Module

Our parser module will be comprised of two, clearly differentiated parts. As they both use the same subroutines for string slicing and formatting, we've decided to place them both together in the parser module 'cause they both, in different ways, parse stuff: these two parts are the scripts interpreter and the player's command interpreter. Before diving into these parts, let's examine and explain the auxiliary subroutines we are gonna use. These subroutines will be kept internal, i.e. they won't be referenced in the .bi file as we won't need them outside (read the previous chapter to refresh your mind about this topic).

All the snippets in this chapter should go inside a file called "parser.bas", for example. The exported SUBs/FUNCTIONs will be in "parser.bi".

Auxiliary functions

If we need to parse a string containing several words (which can be a natural language sentence, or a line of code - think in tokens and values as words), the first thing we need is a subroutine which slices the string into words and return them conveniently formatted. If we are gonna try to understand what's in the sentence, we need to easen the things a bit to the computer: we need trimmed words (with no whitespace) in lowercase. This is what the next piece of code does: it takes a sentence, slices it, and stores each word in an array index.

We will set this array (the one which will contain each word in the sentence) as a shared variable so it is accessible from any subroutine or function in this module. The string containing the whole sentence will be a shared variable as well, which should be able to be modified or read from the outside, so we'll create a SUB and a FUNCTION to do such tasks which will be exported in the .bi:

Const phraseLENGTH = 50 Dim Shared words(phraseLENGTH) As String Dim Shared phrase As String Sub Parser.setPhrase (newphrase As String) phrase = newphrase End Sub Function Parser.getPhrase () Parser.getPhrase = phrase End Function

I think that 50 words is far enough. In fact, I doubt that you will need more than 10.

The slicing function will read the string character by character, stopping when finding a space and storing what he got so far as an array element. It will do a couple things more: it will take track of multi-proposition sentences (such as "get book and read it", or "get pen, open the case and put the pen inside it"), and will split the sentence accordingly.

This can be done in a relatively easy and simple way: we will only parse the sentence until we find a separator (such as a comma, a stop or the "and" word), then we'll wipe out what we have parsed, so the next time we call the subroutine the next portion of the phrase will be parsed. For example, imagine that phrase contains "get pen, open the case and put the pen inside it":

1.- The first time we call to the function, we get:

words(0) = "get", words(1) = "pen", words(2-50) = "" phrase = "open the case and put the pen inside it"

2.- Next time:

words(0) = "open", words(1) = "the", words(2) = "case", words(3-50) = "" phrase = "put the pen inside it"

3.- And the next one:

words(0) = "put", words(2) = "the", words(2) = "pen", words(3) = "inside", words(4) = "it", words(5-50) = "" phrase = ""

You'll see how it works later with a simple (coding) example. The code is as follows:

Sub Parser.Parse Dim word As Integer Dim i As Integer Dim m As String ' To make things easier, we make a first pass changing every separator ' for a common symbol, which happens to be "&": For i = 1 To Len (phrase) If i < Len (phrase) - 1 Then If Mid$ (phrase, i, 3) = "and" Then If i = 1 Then phrase = "&" + Right$ (phrase, Len (phrase) - i - 2) ElseIf i < Len (phrase) - 2 Then phrase = Left (phrase, i - 1) + "&" + Right$ (phrase, Len (phrase) - i - 2) Else phrase = Left (phrase, i - 1) + "&" End If End If End If m = Mid$ (phrase, i, 1) If m = "." Or m = "," Then phrase = Left$ (phrase, i - 1) + "&" + Right$ (phrase, Len (phrase) - i) End If Next i ' Okay, after some string slicing now we have all the separators replaced by "&". ' Sometimes I wish BASIC had the regular expression managing Perl has :P ' Now break up the phrase into words. Stop at & and return the remaining. ' This will allow to use . and , to tell the Parser.Parser several actions ' from within the same command, as explained. word = 0: words(word) = "" ' word will keep track of the array index For i = 1 To Len (phrase) ' loop for every char in the string m = Mid$ (phrase, i, 1) ' get it If m = " " Then ' Whitespace found If words (word) <> "" Then ' If current word is not empty word = word + 1 ' Go to next word. If word = PHRASELENGTH + 1 then ' If no space left in the array phrase = "" ' clear phrase. Exit For ' exit. End If Words (Word) = "" ' Initialize next word End If ElseIf m = "&" Then ' Separator found If i < Len (phrase) Then ' Trim if more chars in phrase: phrase = Ltrim$ (Rtrim$ (Right$ (phrase, Len (phrase) - i) ) ) Else phrase = "" End If Exit For ' Let's get outta here. Else words (word) = words(word) + lcase$(m) ' Any other char gets added to the ' current word. End If Next i End Sub

You can see this in action with the following testing code:

Dim o As String Do Input o Parser.setPhrase o Do Print Parser.getPhrase Parser.parse Loop Until Parser.getPhrase = "" Loop

It's important that you fully understand how this sub works. This a fairly good example of string slicing works, complete with substring replacement. It's also important that you understand how to make it work: First you must feed the sentence to the engine using Parser.setPhrase, then you call to Parser.parse until getPhrase returns the empty string. When we put together the main loop, we'll have to run the common actions and the post-input exceptions until getPhrase returns the empty string. The diagram we saw two chapters ago ends having this shape:

' Main loop in pseudo-code DO DO DO parse phrase. interpret phrase. [ | |] LOOP UNTIL phrase is empty LOOP UNTIL LOOP

Once we've seen the auxiliary functions we're ready to go ahead to the important things, for example the interpreter. But before...

We need a dictionary!

The dictionary in our game will serve two purposes. The most important and basic is to be able to identify which kind each word is, i.e. it is a verb, a noun or and adjective. The second one, not less important, is to be able to have synonyms. Check Chapter #1 again for a deeper discussion about the meaning of this all.

We start, as always, defining data types, constants and module-level shared arrays.

CONST MAXWORDS = 1000 ' Max. number of words in the dictionary. CONST WTVERB = 1 ' Word types CONST WTNAME = 2 CONST WTADJ = 3 Type DictionaryType id as Integer ' Word ID (useful for synonyms) w as String * 20 ' Word. typ as integer ' Word type (1 = verb, 2 = noun, 3 = adjective). End Type Dim Shared D (MAXWORDS) As DictionaryType

As with the location descriptions, we'll store the dictionary in a separate text file with an easy to parse format. We just need id, the word itself, and a numeric type. The easiest way of doing this is having a word per line with those data separated by commas, i.e.

1,n,1 1,north,1 2,s,1 2,south,1 3,e,1 3,east,1 4,w,1 4,west,1 5,ex,1 5,examine,1 5,look,1 100,book,2 101,jewel,2 200,red,3 201,green,3 202,big,3 203,empty,3 9000,it,2 9000,them,2

(remember that you should include "it" and "them" as synonyms and names).

With the data stored in such an easy format, loading it into the D array is really simple, we just create an idex variable as iterator and fill the D array until we reach MAXWORDS or the end of file. This function will be exported in the .bi file:

Sub Parser.Load (fileName As String) Dim f As Integer Dim wrdIdx As Integer ' Just load the dictionary from the file. f = freeFile Open fileName for Input as #f wrdIdx = 0 While (Not(Eof(f))) And (wrdIdx <= MAXWORDS) input #f, D (wrdIdx).id input #f, D (wrdIdx).w input #f, D (wrdIdx).typ wrdIdx = wrdIdx + 1 Wend Close #f End Sub

Coding the interpreter

The interpreter is the heart of the first part of the Parser. It is in charge of translating from English to the language the engine understands, which is a very "simple simplification" of English with just one verb per sentence, and whether one or two nouns each one with an optional adjective, provided they are in the dictionary (check back chapter #1 for a more complete explanation). Every other word is wiped out. At a later time, the common actions and the exception manager will rely in these "important words" extracted from the player input. So the first thing we need is adding a few module-level shared variables:

Dim Shared Verb As String, Noun1 As String, Noun2 As String, Adj1 As String, Adj2 As String Dim Shared PrevNoun As String, PrevAdj As String

This function is also in charge of doing some dirty hacks needed for the English language and its phrasal verbs. Note that we have to find the "verb" 'cause we are gonna use it as a "command" for our engine. In other languages, you have a word for each verb. In English you have very different meanings depending on the preposition which comes with the verb, i.e. "look for" and "look after" have completely different meanings (in Spanish we have different words: "buscar" and "cuidar", i.e. interpreting is easier), so to decide which action the engine should perform we can't only focus on the verb. As prepositions may come in different positions inside the sentence (you can write "put the shirt on" or "put on the shirt") we have to "fix" it, or, better expressed: we can't just extract the verb from the words array, we have to figure it out. Basicly, if we find a phrasal verb we scan the rest of the words for prepositions, then we change the verb accordingly. For example, if we find "turn", we scan the rest of the words. If we find "on" in the sentence, we change the verb for "turnon"; if we find "off", we change the verb for "turnoff". That way, a sentence which is "turn the lamp on" will become "verb: turnon, noun1: lamp".

We need a simple function that finds a word in the array "words" starting from a given position:

Function Parser.findFrom (from As Integer, w As String) As Integer Dim res As Integer Dim i As Integer res = 0 For i = from To PHRASELENGTH If words(i) = "" Then ' We find an empty word: no more words Exit For ' in the sentence. End If If words(i) = w Then ' We found it! res = -1 ' Return true Exit For End If Next i Parser.Findfrom = res End Function

This interpreter subroutine introduces the first finite state machine (FSM from now on) we are gonna use in this engine. Basicly, a FSM is just "something" that has a state and reacts to something external, changing its state for another one depending on what happened. FSMs are very used in parsing. In this scenario, that "something external" is the symbol being read, in this case a new word; imagine that we put each word in a transporting tape and we have a machine that gets them one by one, sequentially, and processes them. We'll define four states for our machine which will be "init", "found verb", "found noun1", and "phrase complete". In the following diagram there's an explanation on how this FSM works, according to the state it is in and the word read:

If we run out of words at any time, the FSM is killed as well.

There's some other important things that this Subroutine do:

This is the code. Pay special attention to how the FSM flows.

Sub Parser.Translate Static Dim state As Integer Dim i As Integer, j As Integer Dim word As Integer Dim assignA As String, assignN As String ' * Identifies the synonyms and word type (verb, noun, adjective) ' According to the dictionary file. ' * Whipes out unneeded words from the words() array, such as "the, as"... ' * Substitutes "it", "them"... etc by the remembered word. ' * Updates remembered word. ' Phrasal verbs force me to do some kinky hacks to get this working. ' I mean, some verbs change its meaning depending on the preposition ' used, and that preposition isn't always just after the verb, i.e. ' "turn the torch on". ' This SUB does the "dirty work" of simplifying simple English. ' Note that this is the most difficult SUB to adapt when translating ' an IF. In fact, you could only translate this one, as it is, ' in fact, some kind of "ENGLISH TO ENGINE" translator :P ' Phrase always follows the same structure: ' VERB [[ADJ1] NOUN1 [[ADJ2] NOUN2]], ' we have to wipe everything out but this. ' We can do this with a very easy FSM (Finite State Machine): state = 0 ' 0 = Init ' 1 = Found Verb ' 2 = Found Noun1 ' 3 = Phrase complete ' Let's analyze word by word. ' Don't forget the good ol' initialization: Verb = "": Adj1 = "": Noun1 = "": Adj2 = "": Noun2 = "" For i = 0 To PHRASELENGTH ' Dirty optimization: As soon as we find an empty word, it ' means that the phrase has finished, so we exit: If words (i) = "" Then Exit For ' Find words (i) in the dictionary. Linear search. We could make ' this in a better way, for example sorting the dictionary alpha- ' betically and using a binary search which is O(logN). Anyway, ' O(N) is not that bad for this: word = -1 For j = 0 TO MAXWORDS If D (j).w = words (i) Then ' Found in the dictionary! word = j: Exit For End If Next j If word <> -1 Then ' If word was in the dictionary: ' Find 1st synonym: For j = 0 TO word ' This snippet just selects If D(j).id = D(word).id Then ' the first word that's in the word = j: Exit For ' dictionary with the same id End If ' as the word the player entered Next j ' ie. the 1st synonym. ' Found, what type? (verb, noun, adjective?) Select Case D(word).typ Case WTVERB: ' Found a verb If State = 0 Then ' We only want a verb in state 0. verb = D(word).w State = 1 ' Here comes the hacks! ' I can think of takeoff puton turnon and turnoff ' Basicly we look for the preposition further in the phrase. Select Case verb case "take": If Parser.findFrom (i + 1, "off") Then verb = "takeoff" End If case "put": If Parser.findFrom (i + 1, "on") verb = "puton" End If case "turn": If Parser.findFrom (i + 1, "on") Then verb = "turnon" ElseIf Parser.FindFrom (i + 1, "off") Then verb = "turnoff" End If End Select End If Case WTADJ: ' found adjective ' This way we can use more than 1 adjective per object, i.e. ' "small green box" will result on adj1 = "smallgreen" and noun1 = "box", ' as long as words are well defined in the dictionary. If State = 1 Then Adj1 = Adj1 + D (word).w If State = 2 Then Adj2 = Adj2 + D (word).w Case WTNOUN: ' ¿Pronoun? it/them... etc, just check "it" if we set up the synonyms correctly. If D(word).w = "it" Then assignN = prevNoun assignA = prevAdj Else assignN = D (word).w assignA = "" End If ' Depending on the FSM state ... If state = 1 Then noun1 = assignN If assignA <> "" Then adj1 = assignA state = 2 ElseIf state = 2 Then noun2 = assignN If assignA <> "" Then adj2 = assignA state = 3 End If End Select End If Next i ' Remember for "it"/"them"/etc: Always remember noun1/adj1 unless noun2/adj2 exists and ' was previously used: If noun2 = "" Then prevNoun = noun1 prevAdj = adj1 Else If prevNoun <> noun2 Then prevNoun = noun1 prevAdj = adj1 else prevNoun = noun2 ' This is redundant and not needed, prevAdj = adj2 ' but here for readability. End If End If ' This way, this (which makes sense) can be entered: ' > get box ' > open it ' > put pencil into it ' > close it End Sub ' PHEW!!

We just need a way to retrieve the verb, nouns and adjectives from outside.

Function Parser.getVerb () Parser.getVerb = verb End Function Function Parser.getNoun1 () Parser.getNoun1 = noun1 End Function Function Parser.getNoun2 () Parser.getNoun2 = noun2 End Function Function Parser.getAdj1 () Parser.getAdj1 = adj1 End Function Function Parser.getAdj2 () Parser.getAdj2 = adj2 End Function

How the player command interpreter works

We have seen a tad of subroutines and you may feel a little puzzled. Before we start with the scripts interpreter, I think we should stop a bit on explaining how does this all work.

Let's define what we want to do: we want to read what the player has entered, and extract the important information from there so we know what to do. The command interpreter just reads the player's input and guesses what he or she wants to do. We need a simple but descriptive way to pass this information to the Objects Manager. Just five words (maximum): "verb adj1 noun1 adj2 noun2" are enough. So the command interpreter translates the player input (in natural language) to these 5 words. And this is done in several steps:

0.- Initialize: We just call "Parser.setPhrase" passing a string with the player's input. The local variable "Phrase" stores it. This input may contain more than one sentence, delimited using separators.

1.- Slice the string: The subroutine Parser.parse takes the string containing the player's input (stored in the variable Phrase), and breaks it into words, which are stored in the local array "words ()". If Phrase contains more than one sentence (delimited with separators such as "and"s, commas or stops), the subroutine just considers the first sentence (from the beginning to the first separator); then it "consumes" this sentence from the string (leaving the rest right after the first separator). At any time, we can read the "Phrase" from outside this module calling to the function "Parser.getPhrase".

2.- Translate words (): The subroutine Parser.translate reads the words and extracts the info from them: verb, adj1, noun1, adj2 and noun2. For this subroutine to perform this action correctly, a correct dictionary file has to be present on memory. Note that this file should contain every word you want the engine to understand. Ever word found in the array words not found in the dictionary won't be taken in account.

3.- At this point we would call the Object Manager's functions and/or run scripts with exceptions, just to execute the player's will examining these five words produced by Parser.translate. This will be covered on future chapters.

4.- If Phrase is not empty yet, go back to 1 to process the next sentence.

Tips for creating a dictionary

You don't need all the English language in your dictionary array, just the verbs you are gonna obey to (which most of the time are just north, south, east, west, ..., examine, get, take, drop, put, wear ... etcetera), and all the nouns and adjectives used to identify all the objects (common and fixed) and non playing characters in your game.

Every word has an ID. synonyms have the same ID. This ID is an integer, so it can climb to 32767 in QB or way more than 2 billion in fB. To keep things tidy, I begin assigning numbers from 1 onwards for verbs, for 1000 onwards for nouns and for 2000 onwards for adjectives. Special stuff at the end, i.e. the prepositions, which I give a 9000. This is not done "just because". Note that verbs are the most used words in the game, then nouns, then adjectives. As we search the array linearly, it's good practice to order the stuff from "most used" to "less used". A good improvement to the engine would be to have the dictionary alphabetically sorted and use a binary search, but I'll leave that as an excercise for the coder.

Let's begin with our dictionary. We'll start with the directional commands:

1,n,1 1,north,1 2,s,1 2,south,1 3,e,1 3,east,1 4,w,1 4,west,1 5,ne,1 5,northeast,1 6,se,1 6,southeast,1 7,nw,1 7,northwest,1 8,sw,1 8,southwest,1 9,up,1 10,down,1 11,enter,1 12,exit,1

Note the use of synonyms: "se" and "southeast" are synonyms so they use the same ID. Note how this works: if the player enters "southeast" as a comment, the translator will find it in the dictionary, and then find the first synonym (first word found in the array with the same ID): "se", so "verb = se". That way we just have to code the engine to obey "se", not both "se" and "southwest". I tend to do this, i.e. have the shortest form of each word as the first synonym. That way I have to type less when coding the engine :P It is also faster, as less characters have to be compared. Other people think that it is more intuitive to have the most expanded word as the first synonym, just for readability, as they prefer to read:

If verb = "north" Or verb = "south" Or verb = "east" Or verb = "west" Or ... Then movePlayer If verb = "examine" Then doExamine ...

rather than

If verb = "n" Or verb = "s" Or verb = "e" Or verb = "w" Or ... Then movePlayer If verb = "ex" Then doExamine ...

Just decide what's your favourite approach. You know what's mine :P <- lazy coder.

Back to the dictionary. Now we're gonna add the verbs corresponding with the actions we are gonna allow in this game plus their synonyms:

13,i,1 13,inventory,1 13,objects,1 14,ex,1 14,examine,1 15,look,1 15,description,1 16,x,1 16,xx,1 16,exits,1 17,get,1 18,drop,1 18,leave,1 19,put,1 20,take,1 21,puton,1 21,wear,1 22,takeoff 22,unwear,1 23,turn,1 ...

Note the synonyms again: "inventory" or "objects" will be changed for "i". "examine" for "ex". In the same way you can use "put trousers on" which will get extracted to "verb = puton, noun1 = trousers". If the player wants to ask for the exits, he can whether write "exits", "xx" or "x", which will be translated to "x". In our engine (the objects manager and the exceptions scripts), we'll have to respond to those first synonyms, i.e. "i", "ex", "n", "x", etcetera. Again, if you prefer having this the way around and enjoying of a more readable piece of code, go ahead. I prefer this way: less typing, faster engine.

Take special attention to this paragraph, 'cause this is a side effect of the hack we use for phrasal verbs: all those phrasal verbs HAVE TO be in the dictionary, but not the prepositions that come with them. For example, if we allow "turn off" in our game, "turn" should be in the dictionary, but not the word "for" (after all, FOR is a preposition which we DON'T NEED). Note how it works: 1.- The translator finds "look", 2.- if we have defined it as a phrasal verb (take a glance at the code - you have to manually add each phrasal verb in the 'here comes the hacks' section) it searches the rest of the words for a preposition. 3.- If it finds "for" (again, blatantly hard-coded, check code), it changes the verb from "look" to "lookfor". So adding "for" to the Dictionary is whether futile (if you add it as a verb it will be ignored once we exit "state 0" in the FSM) or error-prone (if you add it as a name or adjective really nice odd stuff could happen). Plus the more words in the dictionary, the slow the engine will be - just avoid adding words that are not going to be used ;)

There are more restrictions with phrasal verbs and their synonyms. I'll try to show you this with an example. Let's consider the construction "put shirt on". To make it work, "shirt" (noun) and "put" (verb) have to be in the dictionary. The translator will replace then "put" for "puton" when it finds "on" further in the words array. Okay, that worked great, in our objects manager we'll do the correct actions reacting to verb = "puton". But what if the player prefers to use "wear shirt"? It's clear that we have to define "wear" as a synonym of something. "put" is in the dictionary, why not use it? No way, our engine will only react to "puton", so puton must be in the dictionary as well, and "wear" should be synonym of "puton". Note that you can't do this the way around (i.e. "wear" as 1st synonym and "puton" as synonym of "wear"), 'cause once the engine substitutes put for puton (after finding that "on" is in the words array) it won't look for synonyms. So for actions that can be expressed with a phrasal verb, make sure that this phrasal verb plus the preposition is the first synonym, then add the remaining, then add the phrasal verb without preposition with a different ID. With "puton" we have "puton", then "wear" with the same ID, then "put" with a different ID. After all, "put" alone is also used (to "put" something inside a container), so it is in the dictionary anyway.

Once you've finished adding verbs, let's begin adding nouns. Note that if you begin to ID the nouns from 1,000 onwards, you'll be able to add more verbs at a later time. Begin entering the objects first, then the fixed objects. Same with adjectives. You should add every noun and every adjective that you think the player could think on entering. Note that the better response your IF has, the greater it is. IF players love to be responded to almost everything they might enter. That's why betatesting is so important when coding an IF. Let your friends play to it and note all the things they write that don't get a proper reply, just to add them later! :D


I was gonna explain the scripts interpreter for the exceptions now, but I've just noticed that this article is really long and I don't want to take half the e-zine for (it can take as much as this!) me so... See ya in the next chapter!

If you missed them, check out part #1, part #2, part #3 or part #4!
You can contact Na_th_an at this link.

Coding Techniques in FreeBasic: Part 1
Variables and Var Initializers

Written by VonGodric

Hello to you all, it's been awhile since I wrote something for QBE, but here it is now once again. Before I continue I'd like to stress out few points about this small tutorial. First: do not take it all as absolute truth, Second: since FreeBasic is ever-changing then these snippets work with FB 0.13 so older ones may not work. And lastly: if you notice mistakes or misleadings then please do not kill me. And now to the point.

1. Variables and Var Initializers

FreeBasic as we all know is very compatible with several older Microsoft Basic variants. Thus also including a lot of hacks from them and I'd personally advise to avoid them. For one of them is no need for defining variables prior their use. While in a very small programs it may simplify things, then in big programs this can be one major source of bugs due misspelled identifier or just being for example out of bounds of the variable's reach. (like in another sub/function for instance). So the solution is to use OPTION EXPLICIT in your code. This forces the need to declare variable prior it's use thus we never have problems like I described before because compiler will give an error during compile.

Another aspect of defining variables is FB's feature that allows you to declare several variables of the same type. Like this:


This way all variables that follow are STRING type. This method can also be used to declare user defined types for example. Rule is:

DIM AS [type] var_1, var_2, ..., var_n

Inside Type fields just don't put DIM Like this:


Another new feature of FreeBasic are var initializers. This allows you to give a variable value when it is declared. But here's small problem. Outside of subs and functions only constant values can be given, but inside function / sub you can assign also non constant value. Also outside of function/sub you cannot assign dynamic length strings

DIM J AS INTEGER = 10 DIM S AS STRING = “non fixed” DIM m AS STRING * 10 => “Fixed”

You might notice that for last example I used => instead of just =. They both are equal, but only time you have to use => is with fixed length strings.

While this is pretty straightforward it is also possible to assign values to created arrays and user defined types.

DIM i(5) AS INTEGER = {1,2,3,4,5}

It is pretty simple just use { and } to group them together. Now multidimensional array.

DIM i(5, 5) AS INTEGER = {{1,12,13,14,15}, _ 'i( 0, x ) {2,22,23,24 }, _ 'i( 1, x ) {3,32,33,34,35}, _ 'i( 2, x ) {4,45 }, _ 'i( 3, x ) {5,52,53,54,55}} 'i( 4, x )

As you see it's just a matter of grouping into { and } inside another group. Also you don't need to specify all variables. And like in FB in general -their value will be 0. And now to last major type of var initializers -user defined types.

TYPE var i AS INTEGER s AS STRING * 11 m(5) AS INTEGER END TYPE DIM i AS var = ( 10, "hello world", {1,2,3,4,5} )

It's just simple as that. Note that user defined types are grouped together with ( and ) while arrays are grouped with { and }. Here's one more example:

TYPE udt1 i(2) AS INTEGER s AS STRING * 5 END TYPE TYPE udt2 k(2) AS STRING * 10 j AS udt1 END TYPE DIM i AS udt2 = ({"k(0)", "k(1)", "k(2)"}, _ 'k(_) ( {1,2,3}, "udt1" )) 'j as udt1

One thing you should keep in mind that var initializers work in the same order as you define elements in user defined type.

This shall now conclude this first part of this small tutorial series I plan to write. If you are interested in some certain subject then please let me know -- and now farewell and thanks for reading it!

Download a copy of this tutorial in RTF format!


Written by Stéphane Richard (Mystikshadows)


When you think of data validation, what's the first thing that comes to your mind? Is it, by any chance, to enter numbers when an application is expecting numbers out of you, the user? If so, then you're already well under way to grasping the full understand of just what data validation is all about. In essence data validation is about having valid data for a given type of variable and wether you are creating a business application or a game, good data validation will add a certain level of professionalism to your programming endeavours. There's more to data validation that simply validating the data, alot more as you'll see there is alot of things that can be done to help in the data validation process.

In this document, we will cover all you'll ever need to know about data validation, what it really means, how to use it effectively and ultimately how to minimize the use of data validation while still assuring that the data is indeed valid. So get ready, the journey begins here.


Data validation, as explained above, is making sure that all data (whether user input variables, read from file or read from a database) are valid for their intended data types and stay valid throughout the application that is driving this data. What this means is data validation, in order to be as successful as it can be, must be implemented at all parts that get the data, processes it and saves or prints the results. Let's take the time and list those parts here and explain why they should be considered.

These are the 3 major areas where you'd want to be sure that proper data validation is applied properly. This will only help with the rest of the application because you'll be able to cross out the data as being a cause for problem in possible errors that might slip into the application. That is, of course, once the data validation is debugged. But making sure that these are implemented in the development process rather than after the program is done will help minimize the burdon of integrating data validation in your application. Let's take a look and the types of validation that exist and are commonly used to give you an idea of where they can be used as well as how.


Why different types of data validation? The answer is simple. Essentially everything depends on the reason why you'd want to do data validation, it's degree of importance (as far as the data available to the application) and the actually type of the data as well. Here's a quick example just to put you into focus. Let's say you're making a mortage calculation program (that will be used by professionals all over the the continent). Typically, this kind of application would get initial data for the calculation of the mortgage itself. Hence a Principle amount, a length of the load, an interest rate, a data of first payment, the number of compounding periods per per year. This would be aside the client's information itself such as address, telephone number and the likes. Once the loan related data is entered the software would offer to generate an amortization table for each payment stating the payment amount, the amount give to the payment of the interest, the amount given towards the payment of the capital itself and some running totals at each payment period. If the initial data ends up being wrong, can you imagine just how bad the amortization table would end up being at the end of the calculation? Don't you think that the entry screen should be 100% sure of it's data before it goes ahead and performs the generation of the amortization table? The answer to this question ultimately must be yes. For the sake of the customer and the financial institution that will be loaning the money. With this in mind, let's see here what we can do to help the software make sure that the data is valid all the way.

We will be using the example of a mortgage calculation application because this, and other directly or indirectly related types of application such ass long term rental places, banks, realestate related businesses will love the fact that the data must be accurate for the reasons mentionned above and aq couple more that we'll see later in this document. So let's get right to it. The first thing will see is the different types of data validation that can be performed and describing them.

Many times people just don't bother implementation data validation at all while they are creating their application and this usually results in very bad things happening that really could have been avoided with proper data validation. In a big project, the right data validation should be established at the screen design phase of development as this is where you'd usually have time to talk about the role of each form and how important the data validation would be for the given forms. Let's see now what is available as far as tips and tricks to help eliminate or atleast minimize the risk of error in your application.


As mentionned, there are ways around data validation. Ever heard the expression "prevention is the best policy"? Well as far as data validation is concerned, this saying definitaly applies. The best place to prevent human error is of course at the data entry screen level. From there, giving the user the right means of entering his data can, in most cases, eliminate the need for data validation. Indeed, a good data entry screen will be equipped with all that's needed to validate the data long before it can become dangerous to other parts of the application. Depending on the datatype at hand different types of field specific validations can be made available for different purposes. Let's see the different techniques and I'll explain what kind of data they apply to and how to effectively use them.

The best thing I can say at this point is to use common sense when evaluating the need for data validation. Typically it's not worth implementing data validation on small projects that you'd make for yourself because since they're your creations, chances are you'll know what data you need to enter and you can deal with the consequences of wrong data. For a game (depending on how widespread the game is) you might want to consider it for the sake of not having to answer repetitive questions that not having data validation might give you. For business applications and commercial applications of any type, you'd usually want to be as sure as possible about data validation. There's no room to mess around in the commercial application industry and if you can't be sure of what you are acquiring from the user, how can you garantee the results for the businesses that will be using it? Inserting data validation where appropriate only lifts your application's overall quality to a higher level and in today's computer world, any level higher is an excellent thing, it gives your application the edge it needs make itself worthy of considerations by those that will need an application like yours.

Many developers today already have libraries, in many languages, to take care of atleast part of the data validation process. Some even offer them for use in your own applications so you could find them and download them for your own needs if you don't want to code for them yourself. Me I like to use data validation in any project, even those I do for myself I try to put myself in the user's shoes, think of how I'd like to see things done and then make it happen. Sure when you're creating the application (even those for yourself) you might think I'll always know what goes where, but think of what if life gets you out of using that application for a couple years and you get back to it then. Would you remember everything that goes everywhere? The moral of the story is data validation can even protect you from yourself.


And there you have it. Another aspect of the development process explained clearly, I hope. For an ending word, I can say that data validation, in many cases, has helped me even in ways I didn't think it could. I think we've all heard about the KISS development method (Keep It Simple and Stupid) and data validation is one of the best tools you have to help keep things simple, for the potential users of your application. Of course, the simpler you make it for your users, usually, the harder (and consequently the longer) it is for you to create the solution. That goes without saying but the rewards of such an effort are greater than the effort you put into the data validation process. Users will like your application for one thing. But they will also tend to use your application correctly as well which results in less support phone calls and emails and that should always be your ultimate goal, to make something that won't cause you to have to stay up all night answering questions about your application.

Like everything else I write, I can only hope I was clear enough. If I wasn't I would like to know, that's how one betters himself after all. So if there's a part of this article that just doesn't seem clear to you, email me, I'll see what I can do to make it as clear as it can be and that will be added/altered in this document to help make it as clear as possible. Happy coding.

Stéphane Richard

Download a copy of this tutorial.

Writing A Simple BASIC Interpreter:
Lesson #02

Written by Vincent Peters (BazzokaSquirrel)

First of all I want to thank Pete Berg in motivating me to write another lesson about writing a simple BASIC interpreter. I also would like to thank Liz Brower for all her efforts of spell checking my tutorials. Another very special word of thank goes to V1ctor who made FreeBasic AND GOT ME PROGRAMMING AGAIN. Without those three people this lesson won’t be here. Thanks again, and to Pete: Keep up the good work.

In the first tutorial we created the backbone of our interpreter. We did our first statement, the PRINT statement. In order to go further it may be easier to re-read the past tutorial and refresh our memory. I have rewritten the code we ended with a little bit to add more functionality and speed. It is self explanatory if you have a little bit experience in reading code and I used comments so it won’t be difficult. By the way, it’s only possible to work with one parameter. E.g.: PRINT “Hello World”; Here this is the code we start with:

DIM LineOfCode$ SCREEN 12 OPEN "C:\TEST.TXT" FOR INPUT AS #1 DO LINE INPUT #1, LineOfCode$ IF LEFT$(LineOfCode$, 5) = "PRINT" THEN IF MID$(LineOfCode$, 7, 1) = CHR$(&H22) THEN 'Check if it is a string LastCharOfString% = INSTR(8, LineOfCode$, CHR$(&H22)) 'Get the end of the string to PRINT SELECT CASE MID$(LineOfCode$, LastCharOfString% + 1, 1) CASE CHR$(&H3B) 'We have a ";" at the end PRINT MID$(LineOfCode$, 8, LastCharOfString%-8); CASE CHR$(&H2C) 'We have a "," at the end PRINT MID$(LineOfCode$, 8, LastCharOfString%-8), CASE ELSE PRINT MID$(LineOfCode$, 8, LastCharOfString%-8) END SELECT ELSE 'We will use this later on... END IF END IF LOOP UNTIL EOF(1) CLOSE #1 SLEEP

Some pieces of code seem to be a bit out of use, but we will use those pieces if we work on the use of variables in our interpreter.

Now let’s add another keyword: SLEEP. We would also like to add a parameter at the end to specify the number of milliseconds to sleep. If there is no parameter added we want to wait for the usual keyboard input.

Here we go:

IF LEFT$(LineOfCode$, 5) = "SLEEP" THEN 'The SLEEP keyword IF VAL(MID$(LineOfCode$, 6)) <> 0 THEN 'If there is a parameter SLEEP VAL(MID$(LineOfCode$, 6)) ELSE IF MID$(LineOfCode$, 7, 1) <> "0" THEN 'If there is no parameter 'or the parameter is a zero SLEEP END IF END IF END IF

The SLEEP keyword accepts one parameter, but it’s not a necessity to add this parameter. Because FreeBasic is an extremely speedy compiler we all adore, we need to replace the SLEEP statement at the and of our program with:


The next keyword we add is the COLOR keyword. This keyword is going to act like the COLOR statement in FreeBasic. Without a parameter the interpreter will not accept the COLOR statement and return an error. Here’s the code:

IF LEFT$(LineOfCode$, 5) = "COLOR" THEN 'The COLOR keyword IF VAL(MID$(LineOfCode$, 6)) <> 0 THEN 'If there is a parameter COLOR VAL(MID$(LineOfCode$, 6)) ELSE IF MID$(LineOfCode$, 7, 1) <> "0" THEN PRINT "Hey you made a mistake dude, you should add a parameter!" ELSE COLOR 0 END IF END IF END IF

If you like to, you can change your error handler to display another message to make it clear to people that they made a syntax error. Of course you can also add a central error handler.

Now we will add the three IF LEFT$(LineOfCode$, 5) pieces together in one SELECT CASE piece. We do this in order to make it more speedy. So now the final code looks like this:

DIM LineOfCode$ SCREEN 12 OPEN "C:\TEST.TXT" FOR INPUT AS #1 DO LINE INPUT #1, LineOfCode$ SELECT CASE LEFT$(LineOfCode$, 5) CASE "PRINT" 'The PRINT keyword IF MID$(LineOfCode$, 7, 1) = CHR$(&H22) THEN 'Check if it is a string LastCharOfString% = INSTR(8, LineOfCode$, CHR$(&H22)) 'Get the end of the string to PRINT SELECT CASE MID$(LineOfCode$, LastCharOfString% + 1, 1) CASE CHR$(&H3B) 'We have a ";" at the end PRINT MID$(LineOfCode$, 8, LastCharOfString%-8); CASE CHR$(&H2C) 'We have a "," at the end PRINT MID$(LineOfCode$, 8, LastCharOfString%-8), CASE ELSE PRINT MID$(LineOfCode$, 8, LastCharOfString%-8) END SELECT ELSE 'We will use this later on... END IF CASE "SLEEP" 'The SLEEP keyword IF VAL(MID$(LineOfCode$, 6)) <> 0 THEN 'If there is a parameter SLEEP VAL(MID$(LineOfCode$, 6)) ELSE IF MID$(LineOfCode$, 7, 1) <> "0" THEN 'If there is no parameter 'or the parameter is a zero SLEEP END IF END IF CASE "COLOR" 'The COLOR keyword IF VAL(MID$(LineOfCode$, 6)) <> 0 THEN 'If there is a parameter COLOR VAL(MID$(LineOfCode$, 6)) ELSE IF MID$(LineOfCode$, 7, 1) <> "0" THEN PRINT "Hey you made a mistake dude, you should add a parameter!" GOTO ErrorExit: ELSE COLOR 0 END IF END IF END SELECT LOOP UNTIL EOF(1) ErrorExit: CLOSE #1 DO UNTIL INKEY$ = CHR$(27) LOOP

Okay, I admit it’s not much this time. All we covered up to now are 3 main keywords: PRINT, COLOR and SLEEP. But it’s a step up for the next big step: VARIABLES. Feel free to add pieces of code in order to improve my basic code. My code is not optimized for beauty, because beautiful code doesn’t matter at all to me. Only beautiful and fast algorithms are important to a programmer. So get going and improve my code.

Be prepared for the VARIABLES and ‘Beam me up, Scotty!’

Vincent Peters aka the BazookaSquirrel

I’m not a FreeBasic professional, I’m just a BazookaSquirrel. If you improve my code, drop me a note at: vajpeters@gmail.com
Download a MS Word version of this tutorial.


Written by Stéphane Richard (Mystikshadows)


Don't be scared by the title. Believe it or not, it's amazing the problems that can be solved just by taking the time to implement a proper error management system into your code. Error management is often overlooked today no matter what platform your projects are intended. Why you ask? Simply because it is seen as a big beast to implement. This is usually because many coders who claim this tend to implement error management after the game or application is developed already. Indeed, to have a good control over the error management system, it needs to be implemented before and during the coding of the application, not after. Then, you'll see, error management won't be the big beast it is claimed to be.

This article will attempt to cover error management as it could be implemented in FreeBasic as well as see how to manage the errors themselves. Indeed, the application doesn't need to be halted everytime an error occurs, we'll see why here and what you can do instead of halting the program.


The best way to explain this concept is to start by defining what an error is in this context. In this document we'll be covering the runtime errors not the syntax errors because the compiler reports those errors so you can correct them. Runtime errors are, well, errors that happen while your program is executing itself. Error management is the art of controling these runtime errors, reporting the problem and taking the proper action for these errors. The first thing I need say is that I split errors up into three general categories. There are the software errors, operating system errors and the hardware errors. Let me explain these:

The reason why I split the errors that can occur into these three categories is mainly to split the error management task into 3 simpler functions. It is also because I treat these three groups of error differently. Like I mentionned, not all errors need the same kind of management nor do they need the same type of exit procedure. The art of deciding which method to use and when to return to the program itself and when to halt everything and go back to the operating system is what proper error management is all about.


Again I can only share what I know and what I use. So in a typical error management scenario, what you'll see here is how I would cope with the situations. When you get an error, in freebasic and alot of other BASICs i'm familiar with, the error number of the problem can be found in the Err variable. First thing I do is look up the error in a table like this one to know what exactly the error actually is. Then according to the error number, I have the application report the error (if needed) and perform certain recovery functions (if needed) and finally the application can continue (once all the precautions are taken). Here's a rundown of these situations, and what could be done with them. Atleast, it's what I'd do when I encounter them. This is a list of circumstances that could potentially cause errors and what one could do with them. These are suggestions (as in what would/could be considered proper thing to do) in some cases, you might need to halt on every error (really depends on the nature of the application).

Typically, these are the errors you need to be careful and pay special attention to. There are other types of errors but usually they can be handled without being reported. How you treat these errors will vary based on the importance of the situation or the part of the application that is causing the error. If you're saving you'll want to give a few options to see if there could be a way to not loose the file for example. As files are usually quite important and typically not created just for fun. Now that we know the types of errors and the situations and circumstances that can cause them, we'll now look at what good error management could be at the level of the language itself, in our case, FreeBasic.


The first thing to know about coding for error trapping and management is what the language offers as tools for error control. In the case of FreeBasic, errors are trapped as events so to speak and a series of statements are provided to manage them. Let's start by looking at an empty skeletal code sample to start to situate where things go. In FreeBasic errors are best managed at the sub or function level. So hor first example will be a function example.

FUNCTION OpenDatabaseFile(FilePath AS STRING) AS INTEGER ' ----------------------------------- ' First we Turn On Error Management ' ----------------------------------- ON ERROR GOTO ErrorManager ' -------------------------------------------------------- ' Here we put the code that the function should perform ' -------------------------------------------------------- OpenDatabaseFile = 0 ' ----------------------------------------------------- ' When we're exiting we can turn off Error management ' ----------------------------------------------------- ON ERROR GOTO 0 ' ----------------------------------------------- ' We now need to exit the function so the error ' manager part isn't executed accidentally ' ----------------------------------------------- EXIT FUNCTION ErrorManager: ' --------------------------------- ' Error Management Code goes here ' --------------------------------- RESUME NEXT END FUNCTION

Now let's see what we have here. The first line in the function turns Error trapping on so to speak by telling the program that if an error occurs, go to the ErrorManager label to execute the code that's there. After that first line goes the code to what the function should be doing. Here I just assign 0 as the return value of the function. But the actual opening of the database would have been right before that assignment. Next we turn error management off with the ON ERROR GOTO 0 <- (zero). This is how you turn off error management in FreeBasic (and most basic dialects today). Since in FreeBasic error trapping is at the sub or function level you can omit this line as it will be turned off at the end of the subroutine. We then exit the function with EXIT FUNCTION. I can stress the importance of that EXIT FUNCTION statement. If it is not present the code will naturally continue all the way to the label ErrorManager and execute that code too because it's part of the function. So you need to exit the function before the program gets a chances to get to that error manager. If an error Occurs, the program will jump to that label and execute the code, that's the only time you'll want to execute that code. Finally the error management could should Resume execution of the program with RESUME NEXT if the error is critical enough to warrant exiting the program it should be done before the RESUME NEXT statement. We'll see examples of this later in this document.

Now let's put some code in here to see what we can do. Taking our sample function which would typically open a database file it's important to note that error management in FreeBasic or any other languages should be context sensitive. For example, if this function opens a database file, it wouldn't make sense to manage calculation errors like division by zero because you won't be calculating in this function. That's what I mean by you have to keep things in context. Here's some code.

FUNCTION OpenDatabaseFile(FilePath AS STRING) AS INTEGER ' ----------------------------------- ' First we Turn On Error Management ' ----------------------------------- ON ERROR GOTO ErrorManager ' -------------------------------------------------------- ' Here we put the code that the function should perform ' -------------------------------------------------------- OpenDatabaseFile = 0 ' ----------------------------------------------------- ' When we're exiting we can turn off Error management ' ----------------------------------------------------- ON ERROR GOTO 0 ' ----------------------------------------------- ' We now need to exit the function so the error ' manager part isn't executed accidentally ' ----------------------------------------------- EXIT FUNCTION ErrorManager: ' --------------------------------- ' Error Management Code goes here ' --------------------------------- SELECT CASE ERR CASE 2 ' The system cannot find the file specified. Message$ = "The system cannot find the file specified." CASE 3 ' The system cannot find the path specified. Message$ = "The system cannot find the path specified." CASE 4 ' The system cannot open the file. Message$ = "The system cannot open the file." END SELECT PRINT Message$ OpenDatabaseFile = Err END FUNCTION

As you can see, I only manage file related errors and that is the way it should be as well. This is a basic error manager in that it only displays the error that just occured and exit the subroutine, not the whole program, just the faulty function. The code that called this function would either continue with the code or stop should the error justify it. You can use error management to provide alot more information that this however (which is useful, for instance, in a testing and debugging session) where the aim of the error management isn't only to trap errors but to fix them whenever possible). Here's the same code with a bit more useful detail if you wanted to search for the bug.

FUNCTION OpenDatabaseFile(FilePath AS STRING) AS INTEGER ' ----------------------------------- ' First we Turn On Error Management ' ----------------------------------- ON ERROR GOTO ErrorManager ' -------------------------------------------------------- ' Here we put the code that the function should perform ' -------------------------------------------------------- OpenDatabaseFile = 0 ' ----------------------------------------------------- ' When we're exiting we can turn off Error management ' ----------------------------------------------------- ON ERROR GOTO 0 ' ----------------------------------------------- ' We now need to exit the function so the error ' manager part isn't executed accidentally ' ----------------------------------------------- EXIT FUNCTION ErrorManager: ' --------------------------------- ' Error Management Code goes here ' --------------------------------- SELECT CASE ERR CASE 2 ' The system cannot find the file specified. Message$ = "The system cannot find the file specified." & _ "In the OpenDatabaseFile Function with " & _ FilePath & " Passed as a parameter." CASE 3 ' The system cannot find the path specified. Message$ = "The system cannot find the file specified." & _ "In the OpenDatabaseFile Function with " & _ FilePath & " Passed as a parameter." CASE 4 ' The system cannot open the file. Message$ = "The system cannot find the file specified." & _ "In the OpenDatabaseFile Function with " & _ FilePath & " Passed as a parameter." CASE ELSE RESUME NEXT END SELECT PRINT Message$ OpenDatabaseFile = Err END FUNCTION

You can be as detailed in your explanation of the error as you want. The important thing is that adequate information should be reported with the error to help correct it. If there's more than one thing that could happen in the process of performing an operation, you could write these errors to a log file so that all the details of the operation can be recorded and studied at a later time for possible correction. The CASE ELSE clause is telling the program that if any errors that aren't 2, 3 or 4 occurs, just continue with the normal execution of the code. I would say that the best thing to do is to use common sense and what you feel should be done. If you are using an application and you don't like the fact that the program stops everytime an insignificant error happens, then you need to assume that most people shouldn't like it if your program exits for the same reasons. Indeed a good way to learn is to see how other (popular and well known) programs handle their errors and to mimic them basically. If it's good enough for the others it should be good enough for your projects.

What can you learn from this? When you manage your errors, while you are coding (not adding error management to the project) the task doesn't look as bad and yet it requires the same amount of work. Usually, I have code snippets for all my error management situations and I just paste the appropriate code in the appropriate sub or function. Saves alot of typing and makes error management quite easy this way especially if the project is a big one. You can create standards this way that others can follow which also helps manage the overall quality of the whole project just by having a certain control over the errors that could occur even if the fault is that of the programmer.


And this concludes our technique on proper error management. As you can see from the short code samples here, error management can represent a good part of the programming process. The more errors a sub or function needs to manage, the longer the error management part for that function or sub will be. And because that, you can imagine what a job it can be to add after you coded the program. It's doable but it's a big chunk of coding in itself if kept for the end of the programming phase.

Functions that perform calculations don't all need error management either. If you don't divide a variable by another in that function, you'll never cause a division by zero so that function can be spared the error management code. You have to take the time to see what the sub is doing, and what could go wrong when it does it's job. That's why common sense is of the essence. As always I'm opened to comments, suggestions and ideas about this document. Feel free to email me, as always, with any questions. Until I write again, have a good error free program.

Stéphane Richard

Download a copy of this tutorial.

Artificial Intelligence, Real Intelligence and QBasic,

Written by Robert Hambly

Disclaimer: The following article and program are very much a work in progress. They are offered for publication because today is a deadline. The article was dictated last night using a DS-2 Radio Shack Voice Recorder into Word 2003. The program was converted the day before from ancient Basic code (GW Basic and others – circa 1970’s and 80’s).

There are some websites created today to support AI and QBasic. They are available by sending an email stating your interests to me (roberthambly2000@hotmail.com). One site is for support for this QBasic AI Program. One is support for Writing with a Voice Recorder, and one is for discussing Writing Articles in Computer Legible Form (using bold face and underlines for noun phrases and verb action items). Please put the words AI in the subject line of your email so I can attend to it appropriately.

The enclosed QBasic program is a working model using a multilevel nested tree data structure similar to those used in artificial intelligence. This one is a very user friendly data structure, perfect for children of all ages. It can immediately tell stories using the data you have formatted.

The stories can be in color, and used to prompt children and help them read. It can also be used to help adults clarify and define their goals, write thank you notes, and even perhaps write a love stories.

You might take a minute to look at the data structure and think about what output is produced. As you read further, you could begin thinking about how you can start to represent something important in your own world.

Artificial Intelligence

Artificial intelligence programs, especially programs working with natural language, usually have three parts:

  1. An input parser, that attempts to understand human input.
  2. Large knowledge structure representations of information that can be utilized by the computer when mixed with the natural language input.
  3. An output generator which takes the new internal representations, and create sentences for humans to understand.

Most work in artificial intelligence has been done in Lisp or Logo, but as you see in the program enclosed, simple knowledge representation can be done in QBasic, at least with properly formatted QBasic data structures.

Your Intelligence

Anyone reading this article possesses some intelligence, and probably a lot of the particular kind of intelligence common to mathematicians or programmers.

It is interesting to explore your own intelligence. What do you think? How do you think? What are your value system coefficients? How do you represent what you believe? What do you know or understand? And how can you use computer representations to move our understandings of ourselves and each other forward?

The enclosed program is a simple system that allows you to begin representing any piece of knowledge you have. The structure consists of multilevel data symbols, where you can have as many labels for an idea as you wish.

Representing Intelligence

Right now the program mostly represents you. It relies entirely on you for input, and your gradual clarification (editing) of its symbol (word phrase) definitions from which it generates random output.

The output is in the form of simple stories, generated by a random selection of different components (words or phrases) under your variables.

As you’ll see if you study the data structure, simple sentences describing who you are, or what you like, can be displayed in different ways.

Complex Sentence Structures

The simple examples however don’t in any way exhaust the ultimate powers represented by these structures.

You do not need to use declarative sentences. Any linguistic structure (in any language) can be used. Anything that you can define or label, the computer can “understand” and then look up your definitions, select randomly from your details, and either display your words or find other symbols to look up further.

The discipline for the programmer is to clarify his understanding, her expertise, her world, or her understanding of the child’s world.

Whether you’re interested in investments, computer games, recipes, football, or mysticism, if you can talk about it, the computer can tell stories about it.

Recursion via a Stack

The program works by allowing recursion through a simple internal stack structure. The current program was re-written from programs written for old Atari computers, where there were recursion limits built into subroutine calls by the compiler.

We chose to implement our own recursion routines as a simple array stack, rather than restrict the depth of our subroutine calls. We put sentences on the stack and pulled phrases off the stack as we moved up and down levels so that we could generate reasonable size stories.

QBasic has a good level of subroutine recursion (programs repeatedly calling themselves), so that any further programs we write may well use familiar Lisp or Logo structures for recurrence with subroutines and functions calling themselves (see the ButFirst Example, Line 80).

Program Operation

The program as it currently stands offers very simple data abstractions. The code is small, and should be easy to understand. Some debugging code was left in place so you can look at the internal operation anytime you wish to see what is happening, or why your new script isn't running.

The most common problem you will have with adding new elements of the script (DATA statements), is not following each group with a blank DATA statement or now having the Z. symbols spelled perfectly and exactly the same everywhere, matching in upper and lower case letters.

You can copy and paste this program right now into QBasic, and it should run perfectly. Then you can start editing your data structures, and immediately start producing stories so that you see your personal functionality. You can engage in the discipline of modeling yourself, your favorite games, your best friends, your goals or desires, and create some new interesting ways of telling your stories.

From the web, you can use the mouse to select the entire program from this web page, copy and paste it into notepad, save it as a .txt or .bas file, load it into QBasic (or beyond), and start editing. The data you use will begin to represent your world, your word phrases, even your current language preference. If you speak another language, so does your program.


Symbol definition and manipulation is one of the foundational arts of artificial intelligence since humans deal in symbols. Words for word phrases are the easiest symbols for QBasic to represent.

We differ from each other in our understandings of those symbols, in terms of the data structures underneath the symbols that represent the meaning or understanding of those symbols. We also differ in the value system coefficients we place on the symbols in terms of whether they are true, or beautiful, or good, or important, etc.

The symbols in this QBasic program are defined simply by beginning a word phrase with two characters 'Z.’.

Different Colors for Different Symbols

To add interest, and visual variety, as well as identifying multiword phrases, we’ve included the ending '.C' QBasic color number to the symbols.

Right now when the computer looks up a value for a symbol in the six or eight items below the symbol in the DATA table, and randomly selects an item, it will color the text found according to a QBasic color number found after the '.C'.

All words in a phrase within the symbol definition are colored the same color. When the value for the symbol has been printed out, then the color is returned to QBasic color seven.

Five Parts of Five Programming Style

The program has been written in a modified five parts of five programming style. This program has been rewritten, from several old basic programs. And although it has been tested on several current scripts, it is still far from perfect.

In old GW basic, my programming used odd numbers for main functioning code, using 1 for Introduction, 3 for Input, 5 for Work, 7 for Output, and 9 for Control. The even numbers were for less important material, or poorly thought out material. 1 or 10 of 100 or 1000 had the same broad function, but reflected a different level of detail.

Modern subroutines and other structured programming techniques make this kind of structural definition less necessary, but these modern techniques also don't immediately flag the level or priority of the subroutines within the program.

The old GW basic would not allow material between the line numbers. QBasic gives us that option. I have left the number labels mostly intact, so that you can see how this extra material is still roughly organized within the five parts of five system.

This five part structure has also been useful in other academic areas, for writing, for thinking about problems, and even for programming with other computer languages.

Suggestions for Program Additions

There are many obvious additions that can be made to this program. The most immediate additions would include:

  1. reading data from a text file. (using Line Input #1 for the a$ data array),
  2. story capture to text file (using Print #2 to CLIP: for clipboard paste),
  3. symbols as actual programs (using an if Z.Symbol then gosub structure).

Routines can be added while still preserving the Five Part Structure by renumbering the code up to 100 - Initialize, 300 - Input, 500 - Work, 700 - Output and 900 - Control areas. This would allow more room for code while preserving an over all picture.

Programming within these larger numbers, allows more room to continuously upgrade the routines while leaving overall functional descriptive labels intact. This means someone reading or maintaining the program in the future can still preserve the label system organization of the program reflected by the numeric label each segment has.

There have been many programming structure systems developed, and if people suggest improvements to this code, I will try to preserve this label numbering system, so we can look at each other’s work quickly and understand easily where each new piece fits.

Roger C. Schank

If people are interested in artificial intelligence, and exploring Lisp or Logo like structures in QBasic, then I will be using books by Roger Shank for his style of conceptual information processing. I have some old material already written and will convert this to a tutorial format.

The specific book we will study and represent within QBasic is a book published in 1981 called Inside Computer Understanding - Five Programs plus Miniatures.

He has elaborate nested tree data structures that represent meaning in his conceptual dependency terms.

Many of these are simple structures to understand at the outset. We may begin a series of tutorials next month if there’s interest in this subject.

Children Stories Now

Right now you can use the program to generate some simple stories, especially children stories. The program is perfect for children learning to read.

You can attempt to model your child’s world. You can see her games, his friends, and you can use different colors for the words that describe these favorite items.

Children can then read stories about themselves and recognize words and phrases within their lives.

Adult Stories

Certainly adult goals, vacation plans, sermons and projects can begin to be represented.

Indeed any subject people are talking about can probably have a representational discipline added. You can start thinking about representing the world of anyone around you in these detailed symbols.

Yes, of course, you can be used this program to represent adult stories, in the full sense of that word.

As you find you enjoy romantic themes or other kinds of adventures, you can represent those through whatever level of abstraction you choose. Then you can have the computer tell you stories prompting or suggesting other aspects or combinations of the material.

AI QBasic Web Site

Everyone is busy, and the future of this program or of artificial intelligence and QBasic is up to us.

I will be maintaining a web site that will include detailed scripts for this program that we’ve already done, and can possibly make the best scripts available here in this newsletter.

I will make this AI QBasic Web Site available to those who send me e-mail with some thought either about AI data structures, about this little program, or about the future of computer understanding in general.

The websites are currently password protected, but I will make them available to anyone who shows he or she is serious about thinking about their thinking.

So Write Some Code (or Edit a Script)

The bottom line in artificial intelligence programming is that you must have a program. Theories, descriptions, ideas, must be somehow represented in computer code.

This program allows any words you can think of, any data, any symbolic abstraction hierarchy you can create to be represented in the computer

The discipline of continually adding depth, adjusting the symbols, redefining the symbols, and eventually adding program capacities to your symbols, as is available in Lisp and Logo, means that there’s no excuse for not beginning your work now.

Copy the program into QBasic, run it, change it immediately into something that’s real to you, and begin to add some depth to your new representation of you, and make plans to share that on the web.

Thanks to Pete and his newsletter for the opportunity for presenting this material.

Robert Hambly

AI Ed(ucator)


QBasic Story Program

Download the QBasic Story Program (17KB, txt format) that accompanies this article.

Coding A Parallax Scrolling Platformer

Written by Na_th_an

Hello people! I've been suggested by a couple of friends that I should create yet another tutorial series, this time in something less complex yet equally challenging: parallax scrolling platformers. So I've decided to give it a go. Don't worry, this won't become an encyclopaedia like the IF tutorials, we all know that parallax scrolling platformers are way more simple to code. Oh, what are you saying? That you didn't know that? Well, once you finish with this series you'll be able to assure that. You can code this engine in one afternoon when you know what you are doing.

What we are coding

First of all let's define the kind of engine we are going to build:

Until now, I've tried to give you code snippets that would work with both QB and fB, but this time this is impossible. The built-in QB graphics routines are far too slow and too limited for this, plus I could not be using function pointers. Instead of having to choose a third party graphics library for QB, I prefer to go for fB and stick to Angelo's GFXLib which everyone has and everyone should be familiar with.

What we need

Well, first of all, the latest release of freeBasic, which I'm pretty sure you know where to get form, but anyways, follow the arrow -> http://www.freebasic.net.

You need to create some graphics. Get a nice tool, one you feel comfortable with. You can use whatever you like. In this tutorial, I'm gonna show you how to store all your gfx in a GIF file and get them from there, instead of having a single sprite file for each sprite/tile or having to use strange PP256 subroutines and hacks. You can, of course, rip the graphics from various resource sites if you feel happy with it.

We are gonna use FMOD for sound, so it would be nice that you had the latest FMOD.DLL file lying somewhere where it is accessible (the /WINDOWS/SYSTEM32 folder, for example).

Be sure to download Paint Shop Pro 3.1 from here -> ftp://ftp.kemmunet.net.mt/pub/software/win3.11/utilities/psp311.exe or any other program which is able to save GIFs in the "GIF87a" format, as we'll be using Rich Gieldreich's loader which sometimes has problems with "GIF89a" files. This is the GIF loader we'll be using. Copy it into an empty text file and save it as giffb.bas. We'll use it as an external module all the time:

' GIF loader and decompressor by Rich Geldreich/ ' ported to FB by na_th_an ' Disclaimer: Mr Geldreich wrote the most ugly code out there. ' This has been beautified a bit by yours truly, but I did not ' spend so much time. ' You may want to remove "screenlock" and "screenunlock" from ' the LoadGIF Sub. ' To use this in your program, just add: ' Declare Sub LoadGIF (xx%, yy%, gif$) ' To the top of it, and don't forget to add this .bas file ' to your compiling line, i.e. ' $ fbc mygame.bas mymodule.bas gifloader.bas -s gui ' BTW, this SUB just loads GIF87a, non interlaced GIF files. ' Most modern program use the GIF89a standard, which is NOT ' supported. ' If you don't have a program that exports to GIF87a, you can ' download Paint Shop Pro 3.12, which helps you converting ' from GIF89a to GIF87a. ' Paint Shop Pro 3.12 can be downloaded from: ' ftp://ftp.kemmunet.net.mt/pub/software/win3.11/utilities/psp311.exe DEFShort A-Z Declare Sub LoadGIF(xx%, yy%, gif$) Declare SUB Plot (A) Declare FUNCTION Getbit () Declare FUNCTION ReadCode (CodeSize) as Long CONST True = -1, False = 0 DIM Shared ByteBuffer AS STRING * 1 DIM Shared Powers(8), Prefix(4096), Suffix(4096), Outcode(1024), CodeMask(8) DIM Shared MaxCodes(12), Powers2(16), Pal(255) AS LONG DIM SHARED Xstart, Xend, X, Y, Xinit, Yinit Dim Shared Bitsin, BlockLength, Num, TempChar Dim Shared ffHandle% GifData: DATA 4,8,16,&h20,&h40,&h80,&h100,&h200,&h400,&h800,&h1000,8192 DATA 1,3,7,15,31,63,127,255 DATA 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384 Sub LoadGIF(xx%, yy%, gif$) dim red as long, green as long, blue as long dim palcolor as long ScreenLock Num = 0: Bitsin = 0: BlockLength = 0 Xinit = xx% : Yinit = yy% Restore GifData FOR A = 1 TO 8: Powers(A) = 2 ^ (A - 1): NEXT FOR A = 0 TO 11: READ MaxCodes(A): NEXT FOR A = 1 TO 8: READ CodeMask(A): NEXT FOR A = 0 TO 14: READ Powers2(A): NEXT F$ = ltrim$(rtrim$(gif$)) ffHandle% = Freefile OPEN F$ FOR BINARY AS #ffHandle% LEN = 1 FOR A = 1 TO 6 GET #ffHandle%, , ByteBuffer: A$ = A$ + ByteBuffer NEXT GET #ffHandle%, , TotalX GET #ffHandle%, , TotalY GET #ffHandle%, , ByteBuffer: A = ASC(ByteBuffer) BitsPixel = (A AND 7) + 1 GET #ffHandle%, , ByteBuffer: Background = ASC(ByteBuffer) GET #ffHandle%, , ByteBuffer IF ASC(ByteBuffer) <> 0 THEN PRINT "Bad file." Goto EXITSUB END IF FOR A = 0 TO 2 ^ BitsPixel - 1 GET #ffHandle%, , ByteBuffer: Red = ASC(ByteBuffer) GET #ffHandle%, , ByteBuffer: Green = ASC(ByteBuffer) GET #ffHandle%, , ByteBuffer: Blue = ASC(ByteBuffer) Red = Red \ 4 Green = Green \ 4 Blue = Blue \ 4 palcolor = Red or (Green shl 8) or (Blue shl 16) palette A, palcolor NEXT GET #ffHandle%, , ByteBuffer IF ByteBuffer <> "," THEN PRINT "Bad file." Goto EXITSUB END IF GET #ffHandle%, , Xstart GET #ffHandle%, , Ystart GET #ffHandle%, , Xlength GET #ffHandle%, , Ylength Xend = Xlength + Xstart - 1: Yend = Ylength + Ystart - 1 GET #ffHandle%, , ByteBuffer A = ASC(ByteBuffer) IF (A AND 128) = 128 THEN PRINT "Local colormap encountered." Goto EXITSUB ELSEIF (A AND 64) = 64 THEN PRINT "Image is interlaced!" Goto EXITSUB END IF GET #ffHandle%, , ByteBuffer CodeSize = ASC(ByteBuffer): ClearCode = Powers2(CodeSize) EOFCode = ClearCode + 1: FirstFree = ClearCode + 2 FreeCode = FirstFree: CodeSize = CodeSize + 1 InitCodeSize = CodeSize: Maxcode = MaxCodes(CodeSize - 2) Bitmask = CodeMask(BitsPixel) GET #ffHandle%, , ByteBuffer BlockLength = ASC(ByteBuffer) + 1: Bitsin = 8 OutCount = 0 X = Xstart: Y = Ystart DO Code = ReadCode(CodeSize) if eof(ffHandle%) Then Exit Do IF Code <> EOFCode THEN IF Code = ClearCode THEN CodeSize = InitCodeSize Maxcode = MaxCodes(CodeSize - 2): FreeCode = FirstFree Code = ReadCode(CodeSize): CurCode = Code OldCode = Code: FinChar = Code AND Bitmask Plot FinChar ELSE CurCode = Code: InCode = Code IF Code >= FreeCode THEN CurCode = OldCode Outcode(OutCount) = FinChar OutCount = OutCount + 1 END IF IF CurCode > Bitmask THEN DO Outcode(OutCount) = Suffix(CurCode) OutCount = OutCount + 1 CurCode = Prefix(CurCode) LOOP UNTIL CurCode <= Bitmask END IF FinChar = CurCode AND Bitmask Outcode(OutCount) = FinChar OutCount = OutCount + 1 FOR I = OutCount - 1 TO 0 STEP -1 Plot Outcode(I) NEXT OutCount = 0 Prefix(FreeCode) = OldCode: Suffix(FreeCode) = FinChar OldCode = InCode: FreeCode = FreeCode + 1 IF FreeCode >= Maxcode THEN IF CodeSize < 12 THEN CodeSize = CodeSize + 1: Maxcode = Maxcode * 2 END IF END IF END IF END IF A$ = INKEY$ LOOP UNTIL Code = EOFCode OR A$ <> "" ExitSub: ScreenUnlock Close #ffHandle% End Sub 'This subprogram gets one bit from the data stream. FUNCTION Getbit () 'SHARED Bitsin = Bitsin + 1 IF Bitsin = 9 THEN GET #ffHandle%, , ByteBuffer TempChar = ASC(ByteBuffer) Bitsin = 1 Num = Num + 1 IF Num = BlockLength THEN BlockLength = TempChar + 1 GET #ffHandle%, , ByteBuffer TempChar = ASC(ByteBuffer) Num = 1 END IF END IF IF (TempChar AND Powers(Bitsin)) = 0 THEN Getbit = 0 ELSE Getbit = 1 END FUNCTION 'This subprogram plots one pixel on the display. SUB Plot (A)' STATIC PSET (Xinit + X, Yinit + Y), A X = X + 1 IF X > Xend THEN X = Xstart Y = Y + 1 END IF END SUB 'This subprogram reads one LZW code from the data stream. FUNCTION ReadCode (CodeSize) as Long Dim Code as Long Code = 0 FOR Aa = 0 TO CodeSize - 1 Code = Code + Getbit * Powers2(Aa) NEXT ReadCode = Code END FUNCTION

(Please don't complain for the above code, it is not mine - I just spent a bad time formatting it to make it, at least, readable. It looks like old time gurus didn't know shit about clean code :D But hey, it works and it's fast! - I would not have been able to code this with all my "clean code" to save my life - lol)

Also you would need a map editor which is able to save data in a raw way, i.e. 1 byte per tile and nothing else. I use mappy ( which can be found at http://www.geocities.com/SiliconValley/Vista/7336/robmpy.htm ), which is simple, easy to use, and small. You can use whatever you like, or code your own (I might have coded a map editor per game <- not a good idea, specially for lazy coders like me).

Breaking this into pieces

I always feel the need to have an schematic view of what I am gonna code, so let's overview which parts our engine will be composed of.

1. Initialization tasks

You know, load graphics and sounds, etcetera. This isn't something out of the blue, so we'll go accross this part fast. Basicly I'll explain how to stuff all your tiles in a GIF file and creating the sprites from there, plus how to load samples using FMOD and a couple of functions to wrap FMOD's so it's easier to deal with streaming background music.

2. Level loader

This part will depend on which map editor you use and the format it saves its files in. I'm using the binary export of mappy, which just saves every tile in the grid as 1 byte value, using row-order (this is, first 1st row, then 2nd row...), so my code will be prepared to load such kind of maps.

3. Camera movement / Map rendering

This is what makes the "parallax magic". This is so simple that fits in 10 lines and you'll be amazed on how easy it is.

4. Player movement

This is a bit more complex but nothing to be scared about. If you understand simple physics, you won't have problems with this. We will just building a "world" with gravity and friction and will move our player inside, following our own rules.

5. NPC movement

This will be the most interesting part, IMHO. It will cover finite state machines (FSM from now on) and function pointers, plus nice tricks to store all your enemies in an array.

6. Main loop

And this thingo will glue everything together. We'll begin building it (in a skeletal form) as soon as we begin coding, so you'll be able to "see things move" from the beginning.


I have to make clear that, as always, what I try to explain only reflects my point of view and my way of coding. Maybe you disagree with some of my programming practices or my methods. I'm fine with that. This is just a way of doing something that can be done in a lot of ways, and that comes out directly from my researching and experiments. I'm pretty sure that you will find better ways to do some of the things I'll cover in this tutorial. If you think so, go ahead and write your own tutorial ;). The more, the merrier, they say.

Some data types and some introducing explanations

First things first. We need the correct data structures and arrays to contain the values we need for the game. The most important type structure is the PlayerType structure which will contain our main character's data and values. Our main character will move inside a 2D world, so the first thing we need is to store its position: x, y. We just said that our main charracter will move, so we need velocities, one for each direction: vx, vy. In each loop, vx will be added to x and vy will be added to y, making the player move. If vx is positive, the player will move to the right, if it is negative, the player will move to the left. Same with vy: if it is positive, the player will move down, and if it is negative it will move up. Note that we can have many different combinations of vx and vy resulting on diagonal and oblique directions.

As our "world" is 2D, we can break it into two axes: vertical and horizontal. As we'll explain later, horizontal and vertical movements won't interfere (although they happen at the same time), so we can deal with them separately. In the vertical axis, we have the strength that pulls the player down, i.e. gravity. Storing this value in the PlayerType structure will allow us to change it whenever we want (fancy a level at a moon base? then another one under the sea?). We also have the jump strength, which is the value that's substracted to vy when the player is pressing JUMP. Playing with these two values you can get very different behaviours when jumping. Big figures in both gravity and jump strength will make the character to jump very fast, allowing little horizontal movement while jumping. Low figures in both will make the character jump slower and fall slower, like under water, allowing a whole lot of horizontal movement. High gravity, small jumping strength will make the player heavy and the way around will make the player fly. Another value, "jumpmax", will limit the vertical speed we can get by jumping. If we don't use this, as long as we keep pressing JUMP the player will fly! We'll also need a flag to be set when jumping. Jumping is a bit complex and will be explained at a later time, when coding the movement routine. This has to do with the fact that the longer you press JUMP the higher the main character will jump (think of Mario or Sonic).

In the horizontal axis, we have linear movements with acceleration and friction. So we need two values: ax, or horizontal acceleration, and r, horizontal friction. When the player presses the left or right direction keys, the player gets accelerated just by adding ax to vx.when the player releases the key, in each loop we substract r from vx deccelerating the player. You can play with these two values to create fast running charcters, or icy floor (friction and acceleration very low!).

For animation we need two variables more: frame and subframe. The first one will carry which frame to render, the second one will be used to count how many game frames are between frame and frame. If we get our game to run at 60fps, maybe we don't want the animation in our main player to cycle at 60 fps, so we use "subframe". Letting subframe count to 5 before incrementing frame would make our main player animation run at 12 fps, for example. Also, a "facing" variable will be used to know whether the player is looking left or right.

Added to everything, we add a general purpose "flag" just in case we need it for something. Also, a pair "prevx" and "prevy" will be used to store the player coordinates before it jumps. That way, if the player makes a false jump and dies, we know where to reposition it.

The type structure ends as follows:

Type PlayerType x As Integer ' x coordinate in pixels * 100. y As Integer ' y coordinate in pixels * 100. vx As Integer ' horizontal speed. vy As Integer ' vertical speed. g As Integer ' gravity. jump As Integer ' jump strength. jumpMax As Integer ' jump max speed. ax As Integer ' horizontal acceleration. r As Integer ' horizontal friction. frame As Integer ' animation frame #. ps As Integer ' animation subframe counter. dontFall As Integer ' flag set if jumping. flag As Integer ' general purpose. prevX As Integer ' last x coordinate before jumping. prevY As Integer ' last y coordinate before jumping. facing As Integer ' left = 1, right = 0 End Type

"Real Numbers" in Integer Variables

We want this smooth. We want that the objects in the game move along nice curves. That implies some "real" numbers, i.e. numbers will decimals, so a "pixel" is not the smaller unit in our "world".

Some will say that I could do this with floating point numbers, that the floating point unit works and it is fast, that integer numbers are not needed anymore for speed, and some other things, but this is my way. I grew up in the times when floating point math was slow and was completely unsuited if you wanted a fast paced game, so I learned to use integers in an intelligent way.

The "trick" is as follow: imaginary divide each pixel in 100 "sub-pixels", and place your coordinates using those units. That way, if x = 6700 that means that the player is located at pixel 67 horizontal. Multiplying by 100 will translate from pixels to "units", and dividing by the same figure will do the opposite operation.

Now you might be thinking that, having to divide and multiply constantly, it would be better to use powers of two (such as 128 or 256) and then shifts to gain even more speed, and you are right. I'm using 100 here just for readability. Just by looking at the figure you know which pixel position it refers to, which is more suited for learning. Once you are more familiar with how everything works, I suggest you to use powers of two instead of 100, shifts instead of division and multiplication and ANDs instead of modules, just remember the three most well-known optimizations:


Pseudo-Stupid Characters, that's why we call our non playing characters, i.e. the baddies or whatever you want moving in your map. First of all, we have to make some desing decisions:

All of this, and how to implement it, will be discussed in the PSCs section, which will be the longer, most complex, final part of this tutorial.


We've introducted this more than enough. Next month we'll build the parallax engine.

Check out Na_th_an's programming site, Los Monos del Obús. Oh yeah, and his awesome QB platformer Jill The Goddess.

Part Three - The Conceptualization Process

Written by Stéphane Richard (Mystikshadows)


And here we are, the 3rd part of this series. What exactly can you expect in this section? Well let's start by stating what you would typically have before arriving to this section. In theory, you would have your analysis documents (the 3 of them) completed, you would have gotten the solution discussed and approved by management and everything is ready to go to the next step of the development cycle. What is that next step? It's called Conceptualization phase, and entails the beginning of the creation of the proposed solution as it is defined in the detailed analysis and the solution proposal document. Since any flow of information between process steps and between departments in the company (if need be) have been defined in the detailed analysis, you should be ready to go on and start to create the solution. In this 3rd part of the series, we'll cover all you need to know about the conceptualization phase, what it is, what tools are available to you during this phase, and some good practice to use throughout the process.

By the end of this 3rd part, you will be well equipped with the knowledge you need to conceptualize an idea into a workable solution ready for the development phase (which we'll cover in the next part of this series). So indeed, there's alot of ground to cover here. Grab your favorite drink and let's get started shall we?


In the software engineering field, conceptualization is taking everything in the analysis and building a solution from all the information gathered in the analysis phase. Of course, as I mentionned in the previous section, there are many ways to arrive at that, and each of those ways involve a different point of view on the creation of the solution. I'm not going to detail each method again here, you can review them here. if you recall, I mentionned that we would be using UML (Unified Modelling Language) for our project, and that is exactly what we will be doing here.

Is there a preferred order of things that can work better than others? Many software engineers might argue on this. Me, I tend to use somewhat of a top to bottom approach in that I'll start with the bigger, more complex objects (which are usually objects that are made of other objects) and work my way down to each object that the bigger objects are made of. The reason I work in this order is it gives me a bigger picture so to speak and i can work on the relationships between the objects as I break them down. Since we'll be using UML as our tool, actually, we'll be using a text version of UML which means that I'll be describing the objects as text as well as the relationships between the objects. This is a quicker method than going into some application and creating UML diagrams. And it can be done in notepad or your favorite text editor. Let's start by covering what UML is and what it allows to do to familiarize ourselves with it.


U.M.L. is a language that used to describe a problem based on the entities involved, howw to describe these entities (properties) and what those entities can do (methods). UML also alows to describe the relationship between each entity. It doesn't stop there however, UML is also used to describe Organization Diagrams, Use Case Scenario diagrams, Activity and State diagrams, and Static and Dynamic Model (class) diagrams, Sequence Diagrams (to explain certain ordered steps), Collaboration diagrams (where more than one process need to work together to get a given job done) as well as a whole bunch of other types of diagrams that are useful when modeling a solution from start to finish.

For some reference you can take a look at Allen Holub's UML Quick Reference which details all the types of diagrams that are available in UML as well as examples on what those diagrams can look like. Also you can take a look at the UML 2.0 Superstructure Final Adopted specification. With these documents at hand, you'll be equipped to tackle any conceptualization model you would be likely to encounter.

I need to add a distinction here. In many cases, people tend to confuse the concept of composition versus the concept of aggregation. So I will explain these two right here to a bit of clarity. Here they are:

With all this in mind, you can see that UML can be a very powerful tool to add to your arsenal of software engineering tools for more than one reason. For the sake of this example, we'll be using what I called a text version of UML as in there will be no diagrams. The description of objects will be nade in a textual, almost pseudo code like even, because when you look at an object class model diagram, that's exactly what you're seeing for an object is all it's properties and methods listed and described. If the need for a sequence or a collaboration diagram is needed in our description I will use lists or paragraph describing the sequence and/or collaboration. This way you should be able to see clearly what should be going on in an object. Also as mentionned, I will start with the bigger objects and clearly state what the object is composed of. the components of the objects will be detailed later in the scripted UML model.


To start this model, I will begin at the highest possible level of FinanceCAD, the Application itself. Indeed the FinanceCAD Application can definitaly be thought of as an object, a very complex object that comprises everything else in the project.

ENTITY FinanceCAD PROPERTIES: ApplicatioNPath Text VersionMajor Numeric VersionMinor Numeric VersionRevision Numeric VersionRelease Character VersionStamp Text METHODS: CreateNewDesign <- DesignName Text OpenDesign <- FileName Text SaveDesign <- FileName Text PrintDesign <- PrinterNumber Numeric COMPONENTS: OBJECT Canvas <- The main Drawing Canvas OBJECT DatabaseEngine <- File and database functionality OBJECT PrintingEngine <- Printing functionality for the design OBJECT ReportEngine <- Printing Functionality for the reports OBJECT NetworkEngine <- Detection and access to the network folders OBJECT ImportExportEngine <- Import and Export for the design and the reports RELATIONSHIPS: No relationship at this level of refinement. END ENTITY

So far it's not too long is it? There's a median to reach when you are describing a problem using this approach. For the sake of our example here, there's no need to go into any more details, at the application level, than to list what the general components of the application would typically be. As you can see from this first description, things can become obvious quite quickly using this description method. You described the Application just as you would any other type of object. All Objects have qualities and properties that describe them, they also have actions that they can perform. Just by saying what the object looks like, and what it can do, you end up with a pretty complete description of the object itself. Take a look at the Canvas object defined below, you'll see what I mean when I say a complete picture.

OBJECT Canvas PROPERTIES: FileName Text UnitOfMeasure Numeric Scale Numeric NumberOfShapes Numeric Layers List METHODS: Create <- The constructor, called when object is initialized Destroy <- The destructor, called when object is destroyed SetUnitOfMeasure <- NewUnitOfMeasure Numeric SetScale <- NewScale Numeric ClearCanvas RefreshCanvas AddCircle <- Layer Numeric, Radius Numeric AddEllipse <- Layer Numeric, Ratio Numeric AddArc <- Layer Numeric, Ratio Numeric, Length Numeric AddSquare <- Layer Numeric, Length Numeric AddRectangle <- Layer Numeric, Height Numeric, Width Numeric AddTriangle <- Layer Numeric, TriangleType Numeric, Lengths() Numeric AddHexagon <- Layer Numeric, SideLength Numeric AddOctogon <- Layer Numeric, SideLength Numeric AddLine <- Layer Numeric, X1, Y1 Numeric, X2, Y2 Numeric RELATIONSHIPS: One To Many -> Circle Object One To Many -> Ellipse Object One To Many -> Arc Object One To Many -> Square Object One To Many -> Rectangle Object One To Many -> Triangle Object One To Many -> Hexagon Object One To Many -> Octogon Object One To Many -> Line Object DESCRIPTION: The Canvas object is where the drawing of the design actually occurs. It is composed of a drawing area and a command processor (to get and process all the different commands that would typically be entered. The One To Many relationships to the different Shape Objects are because Shapes are added to the canvas rather than just drawn. This way, each shape can be treated as an independant entity and moved independant of the other shapes on the given design. END OBJECT

The first thing to notice here is how I categorized each descriptive element. this method is the one I prefer to describe a physical object in an application hierarchy. I'm not going to define the Circle, Ellipse and the other basic objects for this example. Just remember that when describing a different scenario (typically when you are modelling a manual process) it will be a good idea to define each little element that make up a given object. In this case the Circle object and the other shapes would be defined in the same fashion as the canvas objects with the properties section, the methods, relationships and so on.

We'll just go down the list of objects in the order they have been defined in our application entity. As such, here's the definition of the DatabaseEngine object:

OBJECT DatabaseEngine PROPERTIES: DatabasePath Text ConnectionString Text ConnectionMade Boolean TableCount Numeric TableList List Table Objects METHODS: Create <- The constructor, called when object is initialized Destroy <- The destructor, called when object is destroyed ConnectToDB <- ConnectionString Text, DBPath Text ValidatePath <- PathToValidate Text OpenTable <- TableName Text ExecuteQuery <- QueryToExecute Text InsertRecord <- RecordData Text UpdateRecord <- RecordData Text DeleteRecord <- RecordNumber Numeric FindRecord <- Criteria Text RELATIONSHIPS: One To One -> NetworkEngine Object DESCRIPTION: The DatabaseEngine as defined here is not a Database Management System but rather a wrapper that connects to the existing database engines via the ODBC database connectivity library. Each method will therefore portray a function calling to the inner ODBC functions in the actual coding phase. The relationship to the Network Engine is for validating the actual path to the global database and assure proper connection between the the Database Engine and the physical location of the database itself as well as validating the existence of the network printers and plotters to print the designs and the reports. END OBJECT

And that was the DatabaseEngine object definitions. As you go along refining the object model when issues get solved and questions get answered, you may want to add to this model. For example, maybe you'll find you need more properties in the list of properties depending on what the users know that they need to get access to the database. Perhaps the ability to specify a username and a password to the ConnectDB method rather than the way it's designed right now. You need to remember that typically you are at the start of the conceptualization phase and that you may as the modelling moves along, move properties and methods around to other objects perhaps for whichever reason. Just remember that you need to have an open mind at this stage of conceptualization. Things can and will change in your model and knowing that in advance can influence the initial design to be as open and flexible as it needs to be to allow for these changes. As a quick note, you can see I named the constructor and the destructor the same name as the canvas object. It's good practice to name functions that perform the same things by the same name not just in the conceptualization phase but throughout the whole development cycle all the way to the source code as well. This way you know that Create will always create and initialize the object no matter what that object is.

Likewise, the PrintingEngine Object is defined as any other objects it has properties and methods that will be used by the main application object at will to get things in output format. A typical definition for a printer object could be as follows:

OBJECT PrintingEngine PROPERTIES: PlottingJobs List PlotterList List JobCount Numeric HasJobsToDo Boolean METHODS: Create <- The constructor, called when object is initialized Destroy <- The destructor, called when object is destroyed DetectPlotter <- PlotterToDetect Text InitializePlotter <- PlotterToInitialize Text AddToJobs <- JobNumber Numeric, FileName text PrintFirstInList <- No Parameters, will print the first job in list RELATIONSHIPS: One To One -> NetworkEngine Object One To Many -> ReportEngine Object DESCRIPTION: The PrintingEngine as defined here is a central object where all printing jobs are passed. This object will determine the type of document that is being requested for printing, determine where it should be printed (Physical location of the plotter) and send the job to there to be printed. It does nothing to the actual design file itself other than send it to be printed. The One to One relationship to the NetworkEngine object is to detect the presence of the plotter that has been configured by the design. The One to Many relationship to the ReportingEngine Object is because when the user prints a design he or she could want to print more than one report for the cost of the design itself. END OBJECT

There you have it, the PrintingEngine Ojbect as you can see is the object that manages and prints The Design file itself. In the description part is where you defined the exact relationship between the object as I've done here. it will help the coding phase alot to know why a relationship is defined. Notice how every object is defined using the same structure no matter what it's role is. That's the beauty of this method. Consistency in structure will help you, and everyone that needs to see the model, quickly learn how to read the model and where to locate vital information they will need in their part of the project.

To continue with our modeling, as per our list of components in the Application definition the next object on our list is the ReportEngine Object. So then, let's define that one right now:

OBJECT ReportEngine PROPERTIES: PrinterJobs List PrinterList List JobCount Numeric HasJobsToDo Boolean METHODS: Create <- The constructor, called when object is initialized Destroy <- The destructor, called when object is destroyed DetectPrinter <- PrinterToDetect Text InitializePrinter <- PrinterToInitialize Text CreateSummaryCost <- DesignFile Text CreateDetailCost <- DesignFile Text AddSummaryJob <- JobNumber Numeric, FileName text AddDetailJob <- JobNumber Numeric, FileName text PrintFirstInList <- No Parameters, will print the first job in list RELATIONSHIPS: One To One -> NetworkEngine Object Many To One -> PrintingEngine Object DESCRIPTION: The ReportObject takes care of all the paperwork related to a given design file. the user will have 2 choices when requesting a report to be printed with a design. He or she can have a sumarry report (usually used inhouse for quick evaluation of costs) and a detail report (usually used both inhouse and sent to the client for aproval purposes. The two reports are added to the same list of print jobs as they will typically be sent to the same printer. The One to One relationship to the NetworkEngine Object is to validate the existence of the physical printer on the network. The Many to One relationship to the PrintingEngine is because the reports that are offered here are only available when printing a design (an optional checkbox may be added to select to print just the design, the design and the report, or just the report, but they will all originate from the same print dialog). END OBJECT

The good part of this type of definition is let's say the users, even at this stage of the conceptualization process, decide they want another type of report, all you have to do is add an Add________Job method (these will be defined at the coding phase). The model can stay as abstract as needed to isolate itself from the actual coding of the application this way. By tracing this line between the conceptualizaton and the coding phase, it's easier to set a limit to when the conceptualization phase will end and when the coding phase will begin. Note that so far there are no screens or any visual aspects defined at this stage either. You'll see why in the next section, the coding phase of the development cycle. But let's just say here that the coding phase is and should be split into two sub-phases, The design phase and the programming phase.

Moving right along in our model, the next object to attack is the NetworkEngine Object. Before we begin the model, just keep in mind one thing. Unlike the rest of the objects here, the NetworkEngine object is an independant object in that it doesn't need the other object to execute itself, however, there are relationships because the other objects of the application will give the NetworkEngine object it's purpose of existence. So let's define this object and we'll see what I am talking about:

OBJECT NetworkEngine PROPERTIES: DriveCount Numeric ListOfDrives List PrinterCount Numeric ListOfPrinters List PlotterCount Numeric ListofPlotters List IsNetworkPresent Boolean METHODS: Create <- The constructor, called when object is initialized Destroy <- The destructor, called when object is destroyed GetListOfDrives <- No Parameters, gets list of network drives SetDriveCount <- Count Numeric ValidateDrive <- DriveIndex Numeric GetListOfPrinters <- No Parameters, gets list of available printers SetPrinterCount <- Count Numeric ValidatePrinter <- PrinterIndex Numeric GetListOfPlotters <- No Parameters, gets list of available plotters SetPlotterCount <- Count Numeric ValidatePlotter <- PrinterIndex Numeric RELATIONSHIPS: Many To One -> Canvas Object Many To One -> DatabaseEngine Object Many To One -> PrintingEngine Object Many To One -> ReportEngine Object DESCRIPTION: The NetworkEngine Object is an object that performs all necessary validation against the network in order to get all the valid drives, printers and the plotters that are available on the network. The list of drives will contain the physical Drive Letter, the logical Drive number, and the network path to the physical hard disk. The list of printers will contain printer relevant information such as printer path, shared name, and the likes. The same goes for the list of plotters. The printers and plotters will be initially determined by the printer drivers installed on the user's machine then validated against the printer and plotter list on the network. All of the many to one relationships are established because the Canvas, DatabaseEngine, PrintingEngine and ReportEngine will use the NetworkEngine to determine the existence and validity of the drives, databases, printers and plotters that were configured at the application level (hence on the user's installation of the FinanceCAD Application). END OBJECT

In most cases, a One to Many relationship determines that the modeled object has one or more of the related object. This is know as a "has a" relation. When you encounter a Many to One relationship usually indicates that the modeled object uses the related object. This is called a Uses relationship. This can mean that it uses the related object or is used by the related object. To know which of the two is entailed, you'll need to look at the related object's relationships section and the description.

One more object to worry about, it is the ImportExportEngine object. If you remember in the previous section, there was mention that the design, and the attached reports have the ability to be exported into more well known file formats for compatibity purposes. In this object I'll introduce sequences (or order in which steps are to be performed) and how to define them in the definition of the given object. So then, Here is the definition of the ImportExportEngine object:

OBJECT ImportExportEngine PROPERTIES: ImportFormats List ExportFormats List FileName Text FileType Numeric ImportFormat Numeric [Index to the Import File Format] ImportCompleted Boolean ExportFormat Numeric [Index to the Export File Format] ExportCompleted Boolean METHODS: Create <- The constructor, called when object is initialized Destroy <- The destructor, called when object is destroyed ImportFromDXF <- DXFFileName Text [Autocad Data eXchange Format] ImportFromWMF <- WMFFileName Text [Windows Meta File Format] ImportFromTHREEDS <- THREEDSFileName Text [3D Studio file format] ExportToDXF <- DXFFileName Text [Autocad Data eXchange Format] ExportToWMF <- WMFFileName Text [Windows Meta File Format] ExportToTHREEDS <- THREEDSFileName Text [3D Studio File format] ExportToDOC <- DOCFileName Text [Microsoft Word Format] ExportToWPD <- WPDFileName Text [Word Perfect File Format] ExportToPDF <- PDFFileName Text [Adobe Portable Document File] ExportToRTF <- RTFFileName Text [Microsoft Rich text Format] ExportToHTML <- HTMLFileName Text [HTML 4.01 Compliant format] ExportToTXT <- TXTFileName Text [Standard ANSI Text File] ExportToCSD <- CSDFileName Text [Comma Seperated File Format] ExportToXLS <- XLSFileName Text [Microsoft Excel Spreadsheet] ExportToWKS <- WKSFileName Text [Lotus File Format] ExportToDBF <- DBFCFileName Text [X-Base compatible format] SEQUENCES: Importing from a format 1. Select the file to be imported 2. Determine format based on file extension 3. Perform the import Exporting to a format 1. Select a file from the list of files 2. Select the desired output format 3. Perform The export RELATIONSHIPS: Many To One -> Canvas Object One To One -> NetworkEngine Object DESCRIPTION: The ImportExportEngine object is created at the start of the application and available live from the main application object. when a Design is created, or opened, the ability to export the design itself or the reports are also made available for direct access to it's functionality. This way the user can export the design and/or the reports anytime he or she wishes to do so. The many to One relationship with the Canvas object is defined because Any of the open Canvas Objects (hence any Opened design files) can be exported. The One to One relationship with the NetworkEngine Object is present for drive and folder validation purposes only. END OBJECT

You can see that I used file extension as a mean to differentiate the different file formats I plan on being compatible to for the design file and for the reports as well. You can also see that I don't import anything for the report files as only exporting of our reports are necessary. Here to the constructor and destructor of the object are named the same as all other objects for familiarity and the beginning of a certain naming convention that can be followed all the way through the coding phase. As you can see, sequences are nothing more than an ordered enumeration of what needs to happen in what order, simple as that really. And that goes for any model that may need any type of ordered list of objects or list of actions to take.

And there we have it, the modeling is completed. we've defined our application object and it's 6 components. In the coming section we'll see what we can extract, as far as notions are concerned, from the model as well as some special considerations and notes that need to be mentionned for all your modeling projects.


As I mentionned before, this model is rudimentary and at the surface level of the objects it models. The goal here is to teach you what modelling is and I believe this top level of refinement is more than adequate to show you how it's done. In a typical scenario however, you would be modeling everything from the top level down to the bottom levels of an object hierarchy. To know how low a level you need to go to, you just need to know where your entities end and when you can only talk of properties and methods of your entities. When you can no longer define an entity as having sub entities (objects) then the hierarchy is complete and so is the levels of refinement of your model. It's the best trick I can give you.

The order where I defined the methods is important in this model. the only Object I have defined sequences for is ImportExportEngine object. In the case of the other objects, if a certain order of things is needed, they can be define simply by the order in which the methods are defined in each object. The specific order of things are usually defined either in the user requirements document (when the order are ordered set of steps or commands to get towards the accomplishment of the desired function). or the detailed analysis document (when the order of things are steps to execute a given process).

This is why it's important to be prepared before entering the conceptualization phase. As you can see here, when you have all the documents you need, before you enter the conceptualization phase of the development cycle, you have all the information and tools you need to get through the conceptualization phase as straightforwardly and as smoothly as it can possibly be. And since this phase is a big part of the development cycle, I would urge you to take the time to be as prepared as you can be before you start the conceptualization phase. You'll thank yourself later.


That was a big load to digest wasn't it? Well, when you have the right notions, it is a big job to conceptualize, but it can be quite rewarding as well, when you are well prepared, you'll find out that this phase will be invalluable for the rest of the development cycle. I can't stress enough that the key to this phase, and absolutely all phases of the development cycle (as defined in the 1st part of this series) is to be prepared. If you take the extra time to ask the right questions, you'll get the right answers to work with. This is true for all phases. There are types of projects that for some reason are harder to gather a complete range of information than others. This is usually a sign that the application will need to consider adaptability in the process. For example, many reporting systems may not know, in advance the whole list of reports it will need to create. In this case, being prepared means you have a list of report as are currently known. Adapability means the reporting engine is designed to accept new reports as if they were always part of the list of reports and therefore can be as integrated to the system as the known reports would be. There are other situation where it's difficult at best to acquire a complete list of specifications or list of reports, or list of things that will need to be implemented as well. But again asking the right questions in this case will tell you, atleast, that what you have is incomplete and should be made to grow. This is also called programming for the future.

And that's it for this part of the series. I hope you enjoyed it, and especially, I hope you learned what I tried to teach in this document. Remember, as always that I am there to answer questions as well as for comments and suggestions so email me with any concerns or discrepencies in what you've learned so that we can clear things up together. AS such, a note must be made that the contents might change if I get enough requests to make certain parts of this document clearer than they already are. In the next section we'll attack the coding phase in all it's glory. We'll see why being prepared is important at that phase too, just like all other phase of the development cycle, and we'll see all the special consideration we'll need in that phase. Happy reading and see you then.

Stéphane Richard

Check out Issue #9 for parts 1 and 2, or download a copy of this tutorial.

Part Four - From Conceptualization To Application

Written by Stéphane Richard (Mystikshadows)


Welcome to this Fourth part of this series. We've covered, I believe, alot of ground so far in this series, and this fourth part will be no exception. In this part we will be covering everything there is to know about the Development phase, or the Coding phase per se. We will be seeing what is available to you at this stage of the development cycle just as we have in the other phases. You'll also see here why the previous phases are important even in the coding phase. You need to understand that all documents, from the analysis documents to the modeling of the application play their role in this phase. You'll see how, and where, in this document. The coding phase is where you take all the knowledge, that you built from the analysis and conceptualization phase, and materialize them into an application. To do so, the right way, most big application projects will need a bit of preparation and documentation about different parts of the application to build.

With this in mind, let's begin this 4th part of the series by seeing what makes up an application and later we'll defined what is needed for each of them as far as documents (however detailed they may or may not need to be). Since our first target operating system is Windows™, the rest of this document will taking the target operating system into consideration throughout its contents.


Aside the objects defined in the UML Scriptual Model in the previous part of this series, there are also other types of components to consider when you are building an application. They each play their role in to proper operations of the application and well should be considered as independant of the main engines of the application. Here is a list of these parts along with their descriptions and considerations (if any):

Those are pretty much all the forms you might ever need. Some very specific applications may find a different type of form but usually, simple common sense is all you need to figure those out as they are presented to you. I wanted to make a whole section on forms and dialogs because when you are creating an application, user interactivity is always an important aspect to your application, it's the part of the application that your users can make themselves an opinion on your work so when you design your forms, it's important to take the time to design them properly, align your controls, give your whole application a professional and consistent look and feel and users will like to use your application. Remember that you never get a 2nd chance to make a good first impression so the impact of your forms on your users should be top priority on your list of considerations especially if the application is to be sold commercially (in which case your forms also need to be universally acceptable to the common user).

And now that we also covered the visual aspect of an application, we can move on to the actual programming of the forms and the rest of the application. So let's talk a little bit about what development is exactly and see how we can go about developing the application.


The best way to describe the programming or coding phase is to simply say that this phase takes the documents and models as they were defined in the analysis and the conceptualization phase and creates an application that confirms to these documents and models. Sounds simple doesn't it? In a way I would say that it is that simple, long because applications this size still need a minimal time to code for, but simple nonetheless. Because of the importance of the visual aspect of an application as describe above, I would highly recommend breaking the coding phase into two independant sections. These sections are:

I should note that sometimes the Visual Design Phase is spread out across the programming process in that each form is first designed, shown to the users to be approved, then the inner workngs of the form are coded and the form is then put to the test. I say this because not every company works the same way, but even if done on a form by form basis, the design phase is still very present and very important, it would be futile to create a form, code everything that goes under it, then show it to the user to see if they like it because you have 1/2 chances that they won't like it and you'll then have to start over from scratch. In the corporate world that's a very big lost of time for you, your team and the users which also means it's a waste of money. The more of these little waste of times you can avoid, the better it is for the life of the project, that goes without saying of course. Once again good planning from the start, all the way to the coding phase helps prevent alot of these situations just because you took the time to think about things for a little bit.

Of course, to begin the coding phase, it makes sense to know what programming language you'll be using since, obviously, it will be your main tool from now on in the development cycle. The following section will help you make the choice of language by highlighting some language features that you might want to consider for the project at hand. I will be covering the languages at the language level itself, not the brand of compiler. I will show you the popular compilers for each language however but just as a reference, not as a criteria for selecting the language itself.


That is always a big question, it's not always as simple as saying "well everyone's using this language so I'll just go ahead and use it", atleast, it shouldn't be. The choice of language is just as important as the choice of tools you'll have to make throughout the rest of the development cycle and depending on the project, that can represent a big portion of the project's life. So then, what makes a language better suited for a given task? Well, if you really know what the task is, it's easier to come to a decision if you also know your languages. Of course, this is an ongoing debate, C and C++ programmers will argue that only C or C++ is the language to use, Ada developers will say otherwise, Pascal programmers will have their version of the story, VisualBasic users, well, you get the idea. You really have to sit down and write some list of consideration to choose the language. You see, all language manufacturers boast their own respective language as beeing an all purpose language capable of taking of all possible types of projects and project sizes. Now you need to take a step back, and think about what you want for your application and see what languages meet the criteria. Let's review what feature of FinanceCAD we have and let's see what we can determine from them:

Let's just stop at these three features because they should be enough to make our choice of language. Of course not all projects would allow you to make a decision based on three features, but in the case of an Autocad like application, like FinanceCAD is, these three features should be quite enough to come to a decision. To recapitulate, we want a language that is very fast on graphics, can be ported at least to the linux platform without the need to rewrite the whole application from scratch and while keeping the porting effort to a minimum. And we want a language that can connect to a database quite easily and trouble free. Let's look at some of the languages available and see what features they offer.

Before you go ahead and wonder why I haven't mentionned any other language as a feasible solution, you need to remember that this series is aimed at professional and commercial application development. In this context I have stopped my suggestions to what is commercially available only. I know there are many other languages, each with their own set of features and I believe each language is a work of art and art is a question of taste. One thing I don't like is a group of programmers of a language bring other languages down because they are not the language they would choose to program in. So this is not the object of this series of documents. The object is to give you, the professional programmer a lead on what's available out there. If you choose whatever language, it really doesn't matter to me as long as the language you choose gets the job done for you. In this document I'm just trying to give you a few pointers to help make sure you select the language that is truely suited for your particular big scale projects. With this information there are two more things we need to cover for FinanceCAD and for alot of other projects as well. There is the issue of finding a good multiplatform GUI library so that the visual aspect of the application can be ported with minimal to no effort between the platforms we will want to support. And the issue of which database we could use for our database and reporting purposes. Let's get right into it shall we?


This questions ringed in my head many times in my career. The biggest issue, when it comes to multiplatform development projects is none other than the user interface, the visual aspect of the application. Windows™, KDE, Motif, Gnome, Mac OS X all have specific functionalities available as far as how controls are built, drawn and managed at the operating system level. If there weren't any good multiplaform GUI (Graphical User Interface) multiplatform libraries out there, this would surely raise alot of concerns at pretty much all phases of the development cycle. Surprisingly, my recommendations here are not all at the commercial level as it seems that the libraries I will be suggesting here seem to offer better control and a better coding experience than anything I've seen commercially available. Of course, if you are creating a text mode application or a 100% GUI independant graphical application then the issue of multiplatform GUI is irrelevant in your particular case. We will be looking at four widely used GUI libraries so that you know of their existence for one thing and that you have a brief overview of how it works and how you could potentially use it in your application projects.

These are the four toolkits I can recommend. If you take a look at the links I provide to each of them, you can get a much better picture of what the toolkits are capable of and where they have been used so far. You will aslo be able to make a better judgement as to which library you should consider for your programming project. Just remember that, as you can see, there are tools and libraries available to greatly help you when the time comes to port your project to other platforms.


The first thing I can say about the databases is that they all do one thing in common. They all serve to manage databases and each databases consists of table structures, primary keys, indexes and the likes to present the data in desired orders and to allow to quickly locate records in the tables. All the databases I am recommending here also offer SQL (Structured Query Language) which allows for a complete range of database maintenance functions and reporting purposes. In order to select the right database for the job, you need to take a look at the exact reasons why your project would be using the database in question. How powerful does it really need to be to meet your specific needs depends on what the needs are to begin with. There are 6 database I would like to recommend you look at. 3 of them are commercial products, the others are OpenSource (for OpenSource projects) and have licenses available for commercial development using those database systems).

There are of course other databases available. These seem to be the most widely used and that is basically why I recommended those. Depending on the database needs however you might find other databases outthere that answers your needs without giving you all the power that are offered by those listed above. For example, I can think of two systems that offer their databases as engines that you can include with your appliation, they are smaller, and probably faster (for smaller database tasks) than the 6 listed. They are SQL Lite and Suneido. It all depends on your specific database needs. So to know which database you should use, you need to know exactly what you'll be doing with the database as in it's specific role in the application. You can find this kind of information in the detailed analysis and the application model but usually, the detailed analysis is where it should at least first appear.


That was a big chunk of theory I threw at you in this part of the series. You might want to reread this a few times and take the time to visit the links I provided to get better acquainted with the products that you can choose from and do a little research just so that when you need to use this theory, you'll be a bit better equipped to make the choices that will drive your project to it's success. I think that by now you noticed that I always seem to be pushing the need to be as prepared as you can be between the different parts of the application development process. You're right, I am pushing this, with a good reason too. I strongly believe that being prepared is the only way to take on a project of these sizes (the big scale projects). You have to think in terms of what you have versus what you need. the more closely these two lists follow each other, the less questions you'll have to ask later and the less research you'll have to do at a later time in the project. The less research in the analysis, the faster the analysis can be completed, and this rolls off and accumulates itself throughout the whole development cycle too. All the time you can save at the beginning will shorten your project's development life. If you are developing a commercial product, I'm sure you know that especially in that case, time is of the essence. You need to get things done fast, and right. And the better you can do that, throughout the development process, the better for the project and for you too, of course.

In the next section, we will be looking at that ever eternal phase I "not so affectionately" like to call "testing and debugging". Yes, every programmer's nightmare, it is unevitable no matter how well intensionned you and your development team are, sooner or later, you will fall into this phase. Rest assured however, there are many tools to help you out in that phase too. We'll see what they are and the role they play. We'll also see how to best prepare for that phase too (indeed preparation plays an important role here as well). So until then, if you have questions and comments, by all means, do email me and we'll see what we can do to clear things up for you. Happy reading and see you in the next section.

Stéphane Richard

Check out Issue #9 for parts 1 and 2, or download a copy of this tutorial.

Final Word

That's all for now. I'm in a rush to get this out before I go on a four day trip, so I can't stay to chat... Hope you liked it and thanks a lot for reading!

Next month's deadline: June 15th, 2005

Until next time...END.


Copyright © Pete Berg and contributors, 2005. All rights reserverd.
This design is based loosely on St.ndard Bea.er by Altherac.