Re: Event Based or Get-Key based



awhite wrote:

How many are programming their RLs using an event-based model? That is to say, much like you'd program a GUI - the main loop just collects input, and that input is then passed to (dynamic) call backs. Pressing "i" for inventory sets up a call-back for future input to apply to the inventory display dialog.
(clip)
Alternatively, most traditional RLs seem to be written on a "get-key" basis - where input is read from the player as needed. So, for example, that same "i" for inventory immediately passes control to the inventory display, then waits for input there. No need to save state, or set up call-backs.
(clip)
Has anyone else faced this? What did you decide?

Hmmm. Neither is an accurate description of how my framework
is working now.

I originally wrote a "getkey based" framework but found that
there were some UI things I couldn't really do that way.

I'm now using an "event based" model but aside from checking to
see if the screen has been resized, the main loop doesn't
collect input -- my "events" are things that happen in or to the
dungeon or game settings, not input events. Therefore they can
collect input locally and use it locally, and there's no problem
that way.

The game has a timequeue structure where events that haven't
happened yet wait. It's an array of pointers to linked lists,
where each linked list is an ordered list of the events that
will happen on a particular "beat" (modulo array length) of
gametime and each event is a record containing a bunch of
arguments and a code pointer.

The main game loop looks like this:

void mainloop(gametype *game)
{
eventtype *event = NULL;
int lasteventtype = ENDGAME - 1;
insertevent(game, makegamestartevent(), 0);
game->clock = 0;

while (lasteventtype != ENDGAME) {
event = popnextevent(game);
event->evcode(game, nextevent);
lasteventtype = event->evtype;
free(event);
}
}

notes: popnextevent may increment game->clock. If there
are no more events, popnextevent allocates and returns an
ENDGAME event. ENDGAME events are normally entered in
the queue when character death (or win) is detected.
Executing an ENDGAME event removes all pending events
still in the timequeue.

Each event, when executed, adds zero or more additional
events to the timequeue. For example the gamestart event
queues up game initialization, dungeon generation,
random character generation, character placement, and
character customization actions, then exits.

The character customization event loops, displaying the
character, executing a getkey then doing something to the
character based on locally comparing the getkey result to
its own action table. When the key indicates the player
is ready to start playing, it queues up a select-action
event for the player character and exits.

The select-action event calls the AI routine associated
with that monster (a code pointer in the actor record)
to find out how long until the next select-action for that
monster, queues up the next select-action for that monster,
and exits. The AI routine for the player displays the
dungeon, executes getkey, compares the result to its local
action table, then queues up the selected action and returns
the amount of time it'll take. The AI routine for the
monsters determines action in other ways, but it also
returns the amount of time the action will take.

Note I've my input routine wraps getkey to check for screen-
resizing events, so those get handled no matter what event
code is calling for player input.

rinse, repeat. Sooner or later the character wins or dies,
the ENDGAME event is executed, the queue is cleared, and the
mainloop returns.

Bear

.



Relevant Pages

  • Re: looking for implementation of strtok
    ... contains a ',' character. ... we enter the ugly loop that simply implements strspn: ... loop sets spanp to delim, then loops while seting sc (the "span ... If there are no more tokens, we set *lastp to NULL (this is, I ...
    (comp.lang.c)
  • Re: Which assembler can handle the BIG stuff ?
    ... |> jnz loop;or JNS/JNGE if endmark included in size ... | Yeah, but this is done once, not once per character, so it isn't going ... |> Ok, I'd use KESYS Fn50 to create a formatted, sorted table ... I don't sort ...
    (alt.lang.asm)
  • Re: Histogram of character frequencies
    ... to any valid character value). ... quits the loop without entering the body. ... we then use feof() to test for an end of file ... Dig the sig! ...
    (comp.lang.c)
  • Re: writing to a partition
    ... and sit waiting in a loop or for a key press. ... don't even need to do much given that you can use the bios ... a character and sending it to the bios point that displays a character, ... Then you look up what's needed to make a boot sector, ...
    (comp.os.linux.misc)
  • Re: reading an external text file
    ... If you did a while loop ... Let the open statement include using the IOstatus ... where you have writewould be, in essence, "copy filea fileb" at a DOS prompt...note that Fortran I/O will, by default, write the appropriate for the OS newline sequence transparently -- that's part of the record-based i/o paradigm as opposed to C stream i/o. ... There is a possible difference in that Fortran uses fixed-length character variables so if the source file is variable length records unless you TRIMthe data as it is written to the output file each line will be the same length as the defined character variable. ...
    (comp.lang.fortran)