This is John Harris’ review of Athena, for the Nintendo Entertainment System, with accompanying, brief lecture on Basic Videogame Design, good for one credit hour at Everything Community College.

If you thought World 6 of Super Mario Bros. was hard… ha! Adventures of Lolo III was mere child’s play. Solomon’s Key is as nothing compared to this. I’m here to tell you guys, I eat the likes of space blaster archetype Zanac for breakfast, but this one is just insane. Athena, by SNK, known best these days as the producer of late 80’s disposable income emblem Neo-Geo and umpteen thousand identical fighting games, is perhaps the most difficult of all winnable NES games. (Games which never end don’t count, and Athena does have an ending. It just seems like it lasts forever.)

The fact that Athena was very sloppily programmed doesn’t help much, either.

The story is that Athena, the Roman goddess of wisdom (and war too but the manual doesn’t mention that) is bored with her betogaed, grape-popping existence up on Mt. Olympus, so she goes off into Fantasy World for some blob-slappin’ action. (By the way, if this is actually a fantasy world, I’d sure as hell would like to meet the person whose weird-ass fantasy it is. I’d also like to ask him what the hell the boss of the fifth level is supposed to be. Guh.) I suppose this game is due points for giving us a female protagonist almost a decade before Lara Croft. The odd thing is, Athena doesn’t have anything even remotely approaching omnipotent, goddessly powers. In fact, she has a hard time deciding how high she wants to jump.

The jumping convention created in Super Mario Bros., and wisely copied by almost every other game in which jumping is an option, is that the height of the hero’s jump is determined by how long the player holds down the jump button. When you press the jump button in Athena, our little four-color goddess gives a little bounce, about two "blocks" high. Then, if you press the jump button after she lands within about a second or two, her next jump will be a huge bound, almost as tall as the screen. Her next jump after that will be similar if made within a similar time frame after landing from that one. If she waits longer than a couple of seconds, or after making two really big jumps in a row, her next jump is just the ordinary bounce sort again. You aren't the only one confused by all this. I was confused as hell, and I had to figure it out through experimentation, as the manual is no help at all and the screen gives no clues.

Athena must have been released soon after Super Mario, because it features the same kinds of block smashing gameplay, although Athena is more flexible in this regard, allowing her to use the stronger weapons to destroy blocks as well as by hitting them with her head (but only if she’s found the appropriate headgear). Unfortunately, it is super easy to be caught in a place where you need a certain item to escape, but have no way to acquire it. This is called “extremely poor game design,” folks. In these cases, you end up waiting for the interminable five minute clock to expire, killing the immortal heroine. In fact, the supposedly fallible, flesh-and-blood inhabitants of Fantasy World, with their repetitive A.I. and firing patterns, often make quick work of their divine foe, thanks to another lesson the designers failed to learn from SMB: when the player is hit, he/she should be made invulnerable for a brief period, so continued contact will not rapidly slaughter the omnipotent weakling. There must be an astounding number of notches on the sword of Horse Guy, Private 3rd Class in the Fantasy World Army, because no matter what equipment Athena may have acquired, one bad bounce and it's over.

Add to this the most convoluted win requirements of any videogame. You can play through all the levels and still not win. That’s right! Just like videogame contemporaries Solomon’s Key and Mighty Bomb Jack, there are special requirements you have to meet to get the true ending. Or any ending. In Athena, if you don’t finish the secret shopping list the game designer keeps under lock-and-key, the final boss is invulnerable! Here, you must find a key in one of the levels, then finish that level, which will then warp you to the secret world, “World of Labyrinth,” which is a murderous trial that would have caused Hercules himself to fling down his Magic Shovel of Stable Cleaning and reattempt his college entry exams. In this level, the player must scour both the top and bottom halves of the level (don’t ask) to find the Magic Harp that will make the final boss beatable. And you have to make sure to find the real harp, because the fake one will just take away everything you’re carrying. And you have to have the mystic carrying case beforehand, I believe. Oh, and if you lose a life, you lose the harp and have to go find another key and play the board all over again. The only good thing about this excruciating, immensely frustrating root canal of a level is that, despite its name, David Bowie is no where to be found.

Just so you know the sacrifices I am prepared to make for the elucidation of you, the Everything reader, concerning misshapen NES cartridges, I will have you know that indeed, I have actually won Athena. The ending, basically, is that the background changes to a castle and field, and the game locks up. Yippie! Thankfully, about the only sort of legacy this festering, loathsome, thesaurus-defying turkey, no, piece of crap, no, piece of turkey crap, has left the gaming world is that the art style is awfully similar to Crystalis, SNK’s later Zelda wannabe, which is thankfully a much better (though still kinda average) game.

Athena is the name of the 14 issue long comic series by Dean Hsieh. Athena chronicles the adventures of Olympian Greek gods who have since been overthrown by the new generation of gods and "retired" to the future.

Characters
Athena---Athena, the star of the series, has retired to Pan Athens(year 2047) where she is the lead singer and guitarist of the struggling punk rock band Serpenteena. Hot-headed and aggressive, Athena has been blessed with superhuman powers that make her the ideal bouncer for her fellow retired god Dionysus' exotic club.

Kallie---Kallie, the bassist for Serpenteena, has no clue about Athena's past. Kallie seems to be slightly attracted to Athena, and is highly sensitive about many issues between them.

Jay---Drummer for Serpenteena, Jay also is unaware of Athena's past. He has a crush on Herma, but does not know how to deal with his feelings for her.

Dionysus---Ex-god of wine, intoxication and promiscuity, it is no surprise that in the future Dionysus has chosen to run an exotic club featuring dancers of all sorts.

Herma---Herma, goddess of bisexuality and androgyny, is an exotic dancer at Dionysus' club. She has feelings for Jay, but realizes that he does not know how to deal with a transvestite such as herself.

Hephaestus---Hephaestus is humble and kind, but finds himself hopelessly attracted to Athena. He is a professor at Pan Athens University where he utilizes his knowledge of sciences.

Emmeleia---The daughter of Apollo and Erato and part of the new generation of gods, Emmeleia is the goddess of the futuristic simwave music. She has fallen in unrequited love with Hephaestus.

Αθηνα

A goddess identified in Rome with Minerva, the daughter of Zeus and Metis. Metis was pregnant and was about to give birth to a daughter when Zeus swallowed it; he did so on the advice of Uranus and Gaia who disclosed to him that if Metis had a daughter, she would afterwards have a son, who would deprive Zeus of his heavenly kingdom. When the time for the child to be born arrived Zeus bade Hephaestus to personally split open his head with a blow from an axe. A girl in full armour sprang forth from his head: it was the goddess Athena. The place where the birth took place is generally said to be the shore of Lake Tritonis in Libya. As she leaped out, she uttered a war-cry which resounded in heaven and earth.

Athena, the warrior goddess, armed with spear and aegis (a kind of goat-skin breatplate) played an important part in the struggle against the Giants. She killed Pallas and Encelades. She flayed the former and made herself a breastplate from the skin and she pursued Encelades as far as Sicily and put him out of action by chasing him over the whole island. In the Iliad, she participated in the fighting on the side of the Achaeans (she was hostile to the Trojans ever since Paris, on Mount Ida, had refused to award her the prize for beauty). She supported Diomedes, Odysseus, Achilles and Menelaus in the Trojan War.

Similarly, she protected Heracles in the fighting and she also began to arm Heracles, just as he was about to undertake his Labours. She gave him the bronze castanets with which he scared the birds of Lake Stymphalos, enabling him to shoot them down with his arrows. In return, Heracles offered Athena the golden apples of the Hesperides when Eurystheus gave them up to him, and he fought beside her in the struggle against the Giants.

Athena also helped Odysseus to return to Ithaca. In the Odyssey she is an active figure intervening under the disguise of various human forms, to give assistance to the hero. Athena also sent dreams: to Nausicca, for example, to give her the idea of taking her washing to the river on the day that she knew that Odysseus was due to land in the island of Phaeacia. She endowed her favourite with supernatural good looks, to make quite sure that the girl should at this meeting obtain a boat for Odysseus to return to his native land. She also begged Zeus to show Odysseus his favour, and caused the order to be given to Calypso to release Odysseus and supply him with the means to put to sea again.

The assistance given to Odysseus and Heracles is a symbol of the help brought by the mind of the brute strength and personal courage of the heroes. For Athena was regarded, both in the Greek world at large, and especially in her own city of Athens, as the goddess of Reason. She presided over the arts and literature, in which position she tended to encroach on the role of the Muses, but she was more closely connected with philosophy than with poetry and music in the true sense. In her role of the goddess of intelligent activity she was also the patroness of spinners, weavers, embroiderers and similar occupations (see Arachne). Her ingenuity, allied with her warlike spirit, led her to invent the quadriga and the war chariot; she was also in overall charge of the building of the ship Argo, the biggest ever built up to that time.

She also applied her ingenuity to the arts of peace and in Attica she was blessed for the discovery of olive oil, among other kind actions, and even the introduction of the olive tree itself, which she was said to have given in order to deserve being regarded as its ruler: Poseidon disputed the sovereignty of Athena with her and each of them tried to give Attica the best present they could, to increase their status. Poseidon, with one blow from his trident, made a salt-water spring gush forth on the Acropolis and Athena made an olive tree grow there. The twelve gods called in to judge decided that the olive tree was the better of the two and they gave Athena sovereignty over Attica.

Athena was often adopted as protectress and patroness of towns. Apart from Athens, to which she gave her name, there were temple dedicated to her in the citadels of cities such as Sparta, Megara, Argos and others. At Troy she was especially worshipped in the form of a very ancient idol called the Palladium. Troy could not be captured before the Palladium had been taken, and this is the reason why Diomedes and Odysseus made their way by night into Troy and stole it, thus removing the city's protection. This was the same Palladium which was kept in the post-classical era in the temple of Vesta in Rome, where it performed its original function.

Athena remained a virgin though she was said to have had a son in the following way: she went to pay a visit to Hephaestus in his smithy to acquire some weapons. He, who had been deserted by Aphrodite, fell in love with Athena at first sight and began to chase her. She fled but, although he was lame, Hephaestus caught up with her and embraced her. She did not yield to his advances but in his passion Hephaestus wetted the goddess' leg. In her revulsion she wiped her leg with some wool and threw the dirty piece on the ground. From the earth which was fertilized in this way Ericthonius was born, and Athena regarded him as her son. She brought him up without the other gods knowing and in her desire to make him immortal she shut him in a chest, set a serpent to guard him, and entrusted it to the daughters of the kings of Athens (see Aglaurus).

Athena's attributes were the spear, the helmet and the aegis, which she shared with Zeus. She attached the Gorgon's head which Perseus had given her to her shield, and this had the special quality of turning to stone every living thing that looked at it. Her favourite animal was the owl and her favourite plant the olive tree. She was tall, with calm features, majestic rather than beautiful, and was traditionally described as 'the goddess with grey eyes'. (For her name of Pallas see that entry.)

{E2 DICTIONARY OF CLASSICAL MYTHOLOGY}

Table of Sources:
- Hesiod, Theog. 886ff.
- Pind. Ol. 7, 35ff. (65ff.)
- Euripides, Ion. 454ff.
- Apollod. Bibl. 1, 3, 6ff.; 1, 6, 1ff.; 2, 4, 3; 2, 4, 11; 3, 14, 1; 3, 14, 6; 3, 13, 3
- Virgil, Aen. 3, 578ff.
- Hdt. 8, 55
- Ovid, Met. 6, 70ff.
- Hyg. Fab. 164; 166
- Serv. on Virgil Geo. 1, 12; 3, 113
- schol. on Hom. Il. 2, 547
- Hyg. Astron. 2, 13
- Paus. 1, 18, 2
- Ovid, Met. 2, 552ff.
- Dion. Hal. 1, 68ff.; 2, 66, 2
- Conon, Narr. 34

The Athena widget set was the first major free widget set for the X Window System. It is based on Xt, the X Toolkit Intrinsics, so it uses the Xt interface functions, like Motif and Openlook. Athena is sometimes referred to as Xaw. The Athena widget set is packaged with the X Window System distribution and is used to build the basic X applications such as xterm, xedit and xload.

The look and feel of Athena is extremely flat and boring, but there are 3d alternatives. People who use Athena programs regularly have the option of a derivative with a 3D appearance, such as Xaw-3d. While the flat variety is not as pretty, it is fully functional and is maintained as part of the X Window System distribution directly, rather than as a possibly incompatible outside project.

Since Athena is directly built on Xt and Xlib, it is tied closely to the X. This puts it at a disadvantage to toolkits like GTK+ and QT that are more loosely bound to the windowing system (GTK+ through GDK, QT through it's own internals), and are thus portable to other platforms.

Using Athena in 2 quick example programs

Here's a small tutorial to let you see the essentials of Athena, and get you on the way to building larger things in Athena. If you've already used Motif or some other Xt based widget set, you should just look at the Athena documentation. Along those lines, experience in Athena will transfer well to Motif and OpenLook.

Program 1: Hello, World!

athena1.c:


#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/Xaw/Label.h>

String app_resources[] =
	{ "*label.Label: Testing Athena Label Widget", NULL };
// This is where you set initial widget properties


XrmOptionDescRec options[] = {
	{ "-label", "*label.Label", XrmoptionSepArg, NULL };
}
// This lets us give -label "label text" on the command line

int main(int argc, char **argv)
	{
	XtAppContext app_context;
	Widget top_level, label;
	// You will need 1 XtAppContext for any Xt/Athena application
	// You will need a Widget for each widget in your program

	top_level = XtOpenApplication( &app_context, "test", NULL, 0,
			&argc, argv,
			shellWidgetClass,
			app_resources,
			NULL, 0);
	// Magic for now; read the function specification if you want.

	label = XtCreateManagedWidget("label", labelWidgetClass, 
			top_level, NULL, 0);
	// Most widgets are created like this.

	XtRealizeWidget(top_level);

	XtAppMainLoop(app_context);
	return (0);
	}

Lesson one: Yes, it's complicated. Sorry.

The first example is not quite as minimal as it could have been. A simpler program would use NULL and 0 in the place of app_resources and options, and 1, respectively, and had those parts left out. I just thought it would be nice to showcase Xt right from the start. I've provided a Makefile at the bottom for building the examples.

#include ...

In any Athena program, you will need the Xt header file, as well as headers for any Athena widgets you plan on using, in this case just the Label widget. The Shell.h file is for the the top level shell widget. For any Athena experts reading this, I read that XtAppInitialize was deprecated in favor of XtOpenApplication, so I used that instead, but X11R6 programs still use it, so it's not a big deal I suppose.

top_level = XtOpenApplication(...);

This line initializes all typical Xt programs. It sets up the low-level Xlib stuff, and takes typical command like arguments such as "-geometry WxH+x+y", which are indispensable to people who use .xsession and suchlike heavily. You will need an XtAppContext to pass to this function and the main loop function. It returns a Widget type which for practical purposes represents the top level window of the application (shellWidgetClass type, in this case). It also takes app_resources, which I will ponder in a minute.

label = XtCreateManagedWidget("label", labelWidgetClass,
top_level, NULL, 0);

The XtCreateManagedWidget function will be used to create widgets, which can be visible widgets like text boxes and non-visible things like containers. The widget is given an Xt-internal name, "label", which is used in other places. The next argument is the class of widget we are using, which is a symbol from the Label.h header file. Next, we need the widget which contains the one we are creating, which in this case is the top level widget. The next two arguments have to do with passing arguments to the widget. We'll use those later.

XtRealizeWidget(top_level); XtAppMainLoop(app_context);

XtRealizeWidget is the function that makes the widget and it's children active and visible, in the case of the top level widget, makes the window appear. XtAppMainLoop is the function in which Xt actually sets up and draws all the widgets we've set up, and then loop forever waiting for events. Programs will not typically get past this function except by explicitly stopping Xt which is unneccesary in basic examples, so for now we won't put any useful code after it.

String app_resources[] =
{ "*label.Label: Testing Athena Label Widget", NULL };
XrmOptionDescRec options[] = {
{ "-label", "*label.Label", XrmoptionSepArg, NULL } }

These two lists are common in any Xt program. The first, a String array, is a list of resources that are added to the X resource database, which is beyond the scope is this tutorial. For the time being, it's an easy way of setting options on your widgets, in this case the text that goes on the label. There is another way (The real way, actually) to set and get properties of widgets, but I'll cover that later.

The second list, which is a list of XrmOptionDescRec structs, allows you to specify certain properties of widgets to be set from the command line. In this case, this allows us to optionally set the text of the label.

These two lists do nothing unless they are passed as parameters to XtOpenApplication.

Compile and run

"make athena1" should make this program, if your box is set up approximately like mine. If not, you may have to poke around. As for running it, try "atthena1 -label 'MY LABEL HERE' ", or try giving it geometry options.

Program 2: Callbacks and multiple widgets


#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Box.h>
// We need StringDefs.h for the symbol XtNlabel;
// When in doubt, include more headers than necessary

String app_resources[] =
	{ "*label.Label: Button not clicked yet", 

	"*command.Label: Click this button",
	NULL };
// Properties for our label and button

static int click_count = 0;
// I wouldn't normally use a global variable, but in this case
// I didn't want to overcomplificate things by passing a struct
// to the callback function.

// This is the callback function. It is set up to be called when the
// 'command' button is pressed.
void button_clicked(Widget w, XtPointer client_data, XtPointer call_data)
	{
	Widget label = (Widget) client_data;

	char string[50] = "Button clicked this many times: ";

	click_count++;

	sprintf(string + strlen(string), "%d", click_count);

	XtVaSetValues( label, XtNlabel, string, NULL);
	// This is a simple way of changing or setting values on
	// a widget. A more complicated and general way involves the
	// XtSetArg macro and the XtSetValues function.
	}

int main(int argc, char **argv)
	{

	XtAppContext app_context;
	Widget top_level, label, command, box;

	top_level = XtOpenApplication( &app_context, "test", options, 1,
			&argc, argv,
			app_resources,
			shellWidgetClass,
			NULL, 0);
	box = XtCreateManagedWidget("box", boxWidgetClass, top_level, 
		NULL, 0);
	// 'box' is a container widget to hold 'label' and 'command'

	label = XtCreateManagedWidget("label", labelWidgetClass, box, 
		NULL, 0);
	command = XtCreateManagedWidget("command", commandWidgetClass, 
		box, NULL, 0);
	// Now we put both or our widgets in the box.

	XtAddCallback(command, XtNcallback, button_clicked, label);
	// Add a callback function (button_clicked) to the
	// command widget, and pass that function 'label' as an argument.

	XtRealizeWidget(top_level);

	XtAppMainLoop(app_context);
	return (0);
	}

Lesson 2: Yes, it's still complicated

This example adds to the last bloodbath two of the underlying widget concepts that you see in any library: Containing widgets, and callbacks.


box = XtCreateManagedWidget("box", boxWidgetClass, 
	top_level, NULL, 0);
label = XtCreateManagedWidget("label", labelWidgetClass, 
	box, NULL, 0);
command = XtCreateManagedWidget("command", commandWidgetClass, 
	box, NULL, 0);

This part is pretty simple. We can't just pop as many widgets as we want into the top level widget; it's a limited monster, and rightfully so. So we use a special widget (a container widget, or a composite widget) that is built to contain and arrange multiple widgets. I've intentionally used the simplest of these, which doesn't require any special tampering to work.

Note the way we put the other widgets in the box; instead of naming top_level as the parent, we name 'box' as the parent and they appear in the box. The terminology for this is that 'box' is a child of top_level, and 'command' and 'label' are both children of 'box'. The moral of the story: Put your children in a box. There. I said it.


// In main:
XtAddCallback( command, XtNcallback, button_clicked, label);

// Elsewhere:
void button_clicked(Widget w, XtPointer client_data, XtPointer call_data)

Callbacks are the program's way of doing things after entering the main loop phase. What we are doing, in this case, is telling Xt to call the function "button_clicked", with 'label' as one of the arguments, whenever the 'command' button is pressed. Different types of widgets have different types of callback information, but you can set all of them up with this function.

All functions set up to be Athena callbacks must take 3 arguments: The calling widget, a client data pointer, and a call data pointer. We don't need to worry about the calling widget or the call data pointer, because we know where the call came from; but in some other instances, we might not. The type XtPointer looks funny, but it's just a void* in this case, so we can use it however we want.


XtVaSetValues( label, XtNlabel, string, NULL);

This is another way to set the resources of a widget. The XtVaSetValues function takes a variable number of arguments, starting with the widget you want to change, and ending with a NULL. In between are pairs of the name of the resource (XtNlabel, the text of the label), and the value we want to give it (here given as string).

There is a more complicated way of doing this that doesn't require us to put it all in one function call. I may address that way in the future.

Not satisfied? Read more code, get the specs

If you want to browse some of the most commonly used Athena source code, get the source of the most recent X Window System distribution. There are a whole wealth of programs (Under xc/programs) that use Athena and Xt exclusively. Some of the simpler programs to look up might be xload and xclock; there are more complicated beasts like xedit and xterm, if you're feeling frisky.

Obviously, you will have no idea what you're looking at; that's why you will need the specifications for both Xt and for Athena if you're planning on getting anywhere, and even then it's going to be tough sledding. See the link at the bottom for where you can find these in PostScript format.

Wrapping up: Makefile and links

No, this isn't a typical fancy makefile. I just needed something to work at the time. Poke around other makefiles to see how things are generally done, if you want. This makefile may or may not work for you; it was written for Debian Linux. YMMV.

Makefile:

CC = gcc
LIBS = -L/usr/X11R6/lib -lXaw -lXt -lX11

athena1:
	$(CC) -o athena1 athena1.c $(LIBS)

athena2:
	$(CC) -o athena2 athena2.c $(LIBS)

Last notes: I plan to add to this tutorial, but I'm just in a rush to get it posted and I'm tired of having it sitting around waiting. If you want to reserve judgement until I feel I'm completely finished, give it a few days and I may come through for you.

Links and resources:

Log in or register to write something here or to contact authors.