Sign in with
Sign up | Sign in
Your question

Architecture OOD

Last response: in Video Games
Share
Anonymous
September 22, 2005 3:50:30 PM

Archived from groups: rec.games.roguelike.development (More info?)

I know that we all want to build our own roguelikes with our own
individual visions of how it should work down to the smallest detail,
but it occurs to me that it would be helpful to get some input on the
big details. What most people want to design in their games are the
rules of play, not the organization of data structures, etc. So here
I provide an idea for the overall architecture of a roguelike,
deliberately leaving out anything that might be different from one
game to another. With a good overall design, there should never be
any need to scrap your game and start from scratch, which is a very
good thing. I think that for every roguelike there should be an
'architecture' that is so abstract that no matter how badly you need
to redesign your game, you will never need to rewrite it all.

I'm not going to guarantee that what follows is a very good design
because I'm fairly certain that it isn't, but it is a place to start
thinking about roguelike architecture. I will use Java interface
notation.

/** This is a class for representing a level. This will be useful for
display, AI, telling a player if the PC can or can't move somewhere,
and other things. None of those things requires modifying the level,
so let's make this an immutable interface. */
interface Level
{
/** Here we get access to each cell of the level map by coordinate
position. The definition of Pos is trivial and will be omitted here.
*/
public Square get(Pos p);
/** This is where the PC is. Very important for AI and also for
display if we are scrolling the map. */
public Pos findPC();
/** This is the center of the level. This is used for displaying a
non-scrolling map where this point will be in the center of the
screen. We could have also provided methods for collecting
rectangular bounds on the level, but this seems better. Here we free
to have levels with no known rectangular boundary and still produce a
reasonable value here. */
public Pos center();
}

/** This is a class where we put the ways that one game object can do
things in the world. Each Effector will be associated with an Actor
who will be the target for these activities. It combines mutable
access to the level with anything else that a game event might affect
so that the actors are not given direct access to the entire game.
They can only do things through this carefully controlled interface.
This will probably have a really long list of methods in practice,
but methods that only affect an Actor or and Item don't need to be
here. Any ideas on how to make this bit more manageable? */
interface Effector
{
/** Gives us direct access to the actor that is the focus of our
commands. */
public Actor getActor();
/** Gives us an effector for another actor, hiding the
implementation class of Effector */
public Effector getEffector(Actor a);
/** This is the method that is called when any actor tries to move
itself anywhere. You can put checks here of you need to, it returns a
success/fail code based on the game rules.*/
public boolean moveSelf(Pos p);
/** This is the method that is called when one thing moves another:
teleportation, pushing, etc. It's distince from moveSelf() because it
will surely have different rules. */
public void moveTo(Pos p);
/** Picking up and dropping items to the map. There will probably
be a bunch of misc methods like this. */
public void remove(Item i, Pos p);
public void put(Item i, Pos p);
/** This is for summoning new monsters into the level. It takes an
ActorType and magically constructs an Actor, puts it into the level,
and returns it. We don't know the actual implementation class of the
Actor and we don't care. */
public Actor createActor(ActorType at, Pos p);
/** Display a message to the player. */
public void say(String message);
/** Display the first message if the actor is the PC, and the
second one otherwise. */
public void sayToActor(String messageForActor,
String messageForPlayer);
/** Damages everything contained in the cell, probably by calling
the onDamage method of contained objects. */
public void damage(Damage d, Pos p, Effector effector);
}

/** This is a class for representing a cell in a level. It represents
everything relevant about this cell for all purposes: display, AI,
game rules, etc. There is no need to use this interface as part of
the data structure for the level, but it seems quite useful as a
level interface element. */
interface Square
{
/** blocksLight() and blocks(Actor) are two fundamental properties
of cells in a roguelike level that deserve to be represented here. */
public boolean blocksLight();
/** This is for implementing walls and monsters and anything that a
character cannot walk through. It will be used in path finding and in
responding to player movement commands. */
public boolean blocks(Actor a);
/** It seems to me that the effect of stepping onto a map cell is
primarily a property of a map, so it should be implemented here. If
there are different effects for different kinds of actors, let's
handle those options in this method */
public void onStep(Actor a, Effector effector);
/** Maybe leaving a map cell will have an effect. There is no harm
in checking, right? */
public void onStepOff(Actor a, Effector effector);
/** We're assuming that there is only one actor in a cell, which is
restrictive but fair, I think. */
public Actor getActor();
public Item[] getItems();
/** We're going to want to display this square somehow and to do
that we'll need some kind of drawing tool that I'll call a
DrawingContext. I can't think of a useful interface for
DrawingContext that doesn't start getting into low-level detail, so I
will omit it. */
public void draw(DrawingContext dc);
}

interface Actor
{
/** We put the AI or UI stuff here. We pass in the current level
and position so the actor can find itself and make a decision. This
is probably called according to some kind of timing system that will
want to know how long this turn took, so we pass out a 'Timing'
object. As far as I'm concerned, each turn taking the same amount of
game time is just fine, but lots of games have complex timing. Any
thoughts on what kind of interface Timing should have to be generally
useful? */
public Timing takeTurn(Level level, Pos p, Effector effector);
/** This is how we hurt people. An actor gets hurt by a Damage
object, not by another Actor, because lots of things can cause
damage: map cells full of lava, traps, and things I haven't even
thought of.*/
public void onDamage(Damage d, Effector effector);
/** Called by the draw(dc) method in Square. There would also be a
similar method in Item. */
public void draw(DrawingContext dc);
/** This is where we access the game state of this Actor.
Attributes could probably use a fairly complex interface to make it
abstract and secure, but I won't get into that here. */
public void Attributes getAttributes();
}

/** This is the class that represents attacks. The source is kept
anonymous, but it is remembered in the form of the messages that this
object displays.*/
interface Damage
{
/** Called if this damage manages to impact this actor. We're
probably going to implement HP reduction and such effects here, but
this could be as simple as displaying a message based on the nature
of this attack. */
public void onHit(Actor a, Effector effector);
/** Called if this damage misses the actor. We'll probably just
want to display a message here. */
public void onMiss(Actor a, Effector effector);
public void onHit(Item i, Effector effector);
/** This probably isn't called unless the item was specifically the
target of the attack. It won't likely have actual game effect, just
messages. */
public void onMiss(Item i, Effector effector);
}

The goal of all this is to write as much as we can using just these
interfaces and in that way we know that what we have written is so
generally applicable that we'll never need to change it just because
something else in the program changes. To that end, we are going to
want to have more interfaces, especially ones for creating objects
without calling a constructor so we don't get exposed to
implementation details.

I'd like to get people's comments on this design before I move on to
suggest interfaces for other areas of roguelike design.

More about : architecture ood

Anonymous
September 22, 2005 4:33:50 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Thu, 22 Sep 2005 11:50:30 GMT,
Brendan Guild wrote:

> I'm not going to guarantee that what follows is a very good design
> because I'm fairly certain that it isn't, but it is a place to start
> thinking about roguelike architecture. I will use Java interface
> notation.

<snip>

Do you really *must* post code for this?
I'm sure there are much better presentation methods to describe the
structure...

--
Radomir `The Sheep' Dopieralski @**@_
($s) 3 Ching!
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 22, 2005 7:09:10 PM

Archived from groups: rec.games.roguelike.development (More info?)

Brendan Guild wrote:
> Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
> news:slrndj595e.lp.thesheep@atos.wmid.amu.edu.pl:
> >> I'm not going to guarantee that what follows is a very good design
> >> because I'm fairly certain that it isn't, but it is a place to
> >> start thinking about roguelike architecture. I will use Java
> >> interface notation.
> >
> > Do you really *must* post code for this?
> > I'm sure there are much better presentation methods to describe the
> > structure...
>
> No, not really *must* and I certainly won't do it again, since I've
> never seen anything like this here before and I wasn't really sure
> how it would go over. Sure, it is technically code but it's not the
> usual connotation for that word, since I excluded anything that would
> actually do something when compiled.
>
> Out of curiosity, what presentation method would you suggest?

SNIP Roguelikie UML

> Surprisingly, even without the comments about what anything means,
> this is more work. Is this worth the effort? At least it did give me
> a reason to take another look at UML.

I also think code is a cleanest way to present it, however when I want
to post long articles that include code I upload them somewhere and
just put a link on my usenet post for people to read it, that way you
get to format your article if on need and don't upset the people with a
long post! (yes, some people get upset when they see a long post like
this (or may be just feel uncomfortable):D  )

Peace!

--
Slash
Related resources
Anonymous
September 23, 2005 12:38:08 AM

Archived from groups: rec.games.roguelike.development (More info?)

Brendan Guild <dont@spam.me> writes:

> No, not really *must* and I certainly won't do it again, since I've
> never seen anything like this here before and I wasn't really sure
> how it would go over. Sure, it is technically code but it's not the
> usual connotation for that word, since I excluded anything that would
> actually do something when compiled.
>
> Out of curiosity, what presentation method would you suggest?

I didn't mind the code as such, although I would like to point out that
spaces and newlines are *not* a precious, scarce commodity. A little bit
of cleaning up and reformatting goes a long way:

/** This is a class for representing a level. This will be useful for
display, AI, telling a player if the PC can or can't move somewhere,
and other things. None of those things requires modifying the level,
so let's make this an immutable interface. */

interface Level
{
/** Here we get access to each cell of the level map by coordinate
position. The definition of Pos is trivial and will be omitted here.
*/
public Square get(Pos p);

/** This is where the PC is. Very important for AI and also for
display if we are scrolling the map. */
public Pos findPC();

/** This is the center of the level. This is used for displaying a
non-scrolling map where this point will be in the center of the
screen. We could have also provided methods for collecting
rectangular bounds on the level, but this seems better. Here we free
to have levels with no known rectangular boundary and still produce a
reasonable value here. */
public Pos center();
}



/** This is a class where we put the ways that one game object can do
things in the world. Each Effector will be associated with an Actor
who will be the target for these activities. It combines mutable
access to the level with anything else that a game event might affect
so that the actors are not given direct access to the entire game.
They can only do things through this carefully controlled interface.
This will probably have a really long list of methods in practice,
but methods that only affect an Actor or and Item don't need to be
here. Any ideas on how to make this bit more manageable? */

interface Effector
{
/** Gives us direct access to the actor that is the focus of our
commands. */
public Actor getActor();

/** Gives us an effector for another actor, hiding the
implementation class of Effector */
public Effector getEffector(Actor a);

/** This is the method that is called when any actor tries to move
itself anywhere. You can put checks here of you need to, it returns a
success/fail code based on the game rules.*/
public boolean moveSelf(Pos p);

/** This is the method that is called when one thing moves another:
teleportation, pushing, etc. It's distince from moveSelf() because it
will surely have different rules. */
public void moveTo(Pos p);

/** Picking up and dropping items to the map. There will probably
be a bunch of misc methods like this. */
public void remove(Item i, Pos p);
public void put(Item i, Pos p);

/** This is for summoning new monsters into the level. It takes an
ActorType and magically constructs an Actor, puts it into the level,
and returns it. We don't know the actual implementation class of the
Actor and we don't care. */
public Actor createActor(ActorType at, Pos p);

/** Display a message to the player. */
public void say(String message);

/** Display the first message if the actor is the PC, and the
second one otherwise. */
public void sayToActor(String messageForActor,
String messageForPlayer);

/** Damages everything contained in the cell, probably by calling
the onDamage method of contained objects. */
public void damage(Damage d, Pos p, Effector effector);
}



/** This is a class for representing a cell in a level. It represents
everything relevant about this cell for all purposes: display, AI,
game rules, etc. There is no need to use this interface as part of
the data structure for the level, but it seems quite useful as a
level interface element. */
interface Square
{
/** blocksLight() and blocks(Actor) are two fundamental properties
of cells in a roguelike level that deserve to be represented here. */
public boolean blocksLight();

/** This is for implementing walls and monsters and anything that a
character cannot walk through. It will be used in path finding and in
responding to player movement commands. */
public boolean blocks(Actor a);

/** It seems to me that the effect of stepping onto a map cell is
primarily a property of a map, so it should be implemented here. If
there are different effects for different kinds of actors, let's
handle those options in this method */
public void onStep(Actor a, Effector effector);

/** Maybe leaving a map cell will have an effect. There is no harm
in checking, right? */
public void onStepOff(Actor a, Effector effector);

/** We're assuming that there is only one actor in a cell, which is
restrictive but fair, I think. */
public Actor getActor();
public Item[] getItems();

/** We're going to want to display this square somehow and to do
that we'll need some kind of drawing tool that I'll call a
DrawingContext. I can't think of a useful interface for
DrawingContext that doesn't start getting into low-level detail, so I
will omit it. */
public void draw(DrawingContext dc);
}



interface Actor
{
/** We put the AI or UI stuff here. We pass in the current level
and position so the actor can find itself and make a decision. This
is probably called according to some kind of timing system that will
want to know how long this turn took, so we pass out a 'Timing'
object. As far as I'm concerned, each turn taking the same amount of
game time is just fine, but lots of games have complex timing. Any
thoughts on what kind of interface Timing should have to be generally
useful? */
public Timing takeTurn(Level level, Pos p, Effector effector);

/** This is how we hurt people. An actor gets hurt by a Damage
object, not by another Actor, because lots of things can cause
damage: map cells full of lava, traps, and things I haven't even
thought of.*/
public void onDamage(Damage d, Effector effector);

/** Called by the draw(dc) method in Square. There would also be a
similar method in Item. */
public void draw(DrawingContext dc);

/** This is where we access the game state of this Actor.
Attributes could probably use a fairly complex interface to make it
abstract and secure, but I won't get into that here. */
public void Attributes getAttributes();
}



/** This is the class that represents attacks. The source is kept
anonymous, but it is remembered in the form of the messages that this
object displays.*/
interface Damage
{
/** Called if this damage manages to impact this actor. We're
probably going to implement HP reduction and such effects here, but
this could be as simple as displaying a message based on the nature
of this attack. */
public void onHit(Actor a, Effector effector);

/** Called if this damage misses the actor. We'll probably just
want to display a message here. */
public void onMiss(Actor a, Effector effector);
public void onHit(Item i, Effector effector);

/** This probably isn't called unless the item was specifically the
target of the attack. It won't likely have actual game effect, just
messages. */
public void onMiss(Item i, Effector effector);
}

sherm--

--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
Anonymous
September 23, 2005 1:37:25 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
news:slrndj595e.lp.thesheep@atos.wmid.amu.edu.pl:
>> I'm not going to guarantee that what follows is a very good design
>> because I'm fairly certain that it isn't, but it is a place to
>> start thinking about roguelike architecture. I will use Java
>> interface notation.
>
> Do you really *must* post code for this?
> I'm sure there are much better presentation methods to describe the
> structure...

No, not really *must* and I certainly won't do it again, since I've
never seen anything like this here before and I wasn't really sure
how it would go over. Sure, it is technically code but it's not the
usual connotation for that word, since I excluded anything that would
actually do something when compiled.

Out of curiosity, what presentation method would you suggest?

I can't think of anything very different except vague hand waving
that leaves people to figure out the details on their own. I thought
giving people some precise method signatures would make things more
concrete and easier to discuss. I suppose I could make ASCII Art UML
diagrams; would that be better or worse? Let me try a small example:

| Actor | | Attributes |
|=================| * 1 |==================================| *
| getAttributes() |------->| update(Effector) |---
* ^ ^ 1 | get(AttributeKey) | |
| | | set(AttributeKey,AttributeValue) | |
1 | 1 * | * | getKey(Name) | |
[ Game ]<---| Effector | | modifyBy(Attributes) | |
| 1 |============| | * |
| | doStuff | | |
v 1 | getActor() | | * v
[ Player ] | | AttributeValue |
v * Creates |====================|
| AttributeKey |- - - >| toString() |
|=================================| | intValue() |
| update(Effector,AttributeValue) | | inc(AttributeValue)|
| getName() |
| defaultValue() |

Surprisingly, even without the comments about what anything means,
this is more work. Is this worth the effort? At least it did give me
a reason to take another look at UML.
Anonymous
September 23, 2005 6:04:40 AM

Archived from groups: rec.games.roguelike.development (More info?)

SZDev - Slash wrote in news:1127426950.882416.269630
@g49g2000cwa.googlegroups.com:
> I also think code is a cleanest way to present it, however when I
> want to post long articles that include code I upload them
> somewhere and just put a link on my usenet post for people to read
> it, that way you get to format your article if on need and don't
> upset the people with a long post! (yes, some people get upset when
> they see a long post like this (or may be just feel
> uncomfortable):D  )

They aren't alone! I feel uncomfortable when I post things like this.
When reading, I gladly ignore anything that doesn't interest me, but
when I'm posting I'm self-conscious that I might be just wasting
people's time. Paragraph upon paragraph of text doesn't concern me
when I post, but code seems different somehow. I got around that
concern by telling myself that this wasn't really code: it's just a
definition, a description in standardized notation, and it was
fundamental to the point of my post. I didn't post this as something
people could copy into their own roguelike project[1]; I posted it to
be a subject of discussion, hopefully picked apart and critiqued by
people far more experienced with making roguelikes than myself.

Where would you suggest uploading and linking articles?

[1] I strongly advise against using the design I provide directly in
an actual game! It is a thoughtful suggestion for a design, but only
thoughtful on the order of days, nowhere near the amount of careful
planning that should go into your high-level design.
Anonymous
September 23, 2005 8:55:19 AM

Archived from groups: rec.games.roguelike.development (More info?)

Timothy Pruett wrote:
>
> I hope you do intend to do it again. Like I said before, I'm interested
> in what you have to say, but I didn't care for how you presented it.
> Don't take offense, because none is intended, but I felt like you didn't
> really explain your ideas that well. When describing an interface, you
> really need to provide a lot of detail concerning the interactions with
> the interface, conventions to be used, etc. You just didn't give enough
> detail.

I think describing a roguelike design in more detail (with
interactions between objects, etc) could be a subject to a 2 hour
lecture. I wouldn't even try to describe my roguelike in a usenet
post, but if I had to, a UML diagram would come in the first place,
and then the interfaces maybe.
Anonymous
September 23, 2005 12:07:36 PM

Archived from groups: rec.games.roguelike.development (More info?)

You are more than welcome to put stuff like this in the Roguelike
Basin.

T.
Anonymous
September 23, 2005 1:23:27 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Thu, 22 Sep 2005 21:37:25 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
> news:slrndj595e.lp.thesheep@atos.wmid.amu.edu.pl:
>>> I'm not going to guarantee that what follows is a very good design
>>> because I'm fairly certain that it isn't, but it is a place to
>>> start thinking about roguelike architecture. I will use Java
>>> interface notation.
>>
>> Do you really *must* post code for this?
>> I'm sure there are much better presentation methods to describe the
>> structure...
>
> No, not really *must* and I certainly won't do it again, since I've
> never seen anything like this here before and I wasn't really sure
> how it would go over. Sure, it is technically code but it's not the
> usual connotation for that word, since I excluded anything that would
> actually do something when compiled.
>
> Out of curiosity, what presentation method would you suggest?
>
> I can't think of anything very different except vague hand waving
> that leaves people to figure out the details on their own. I thought
> giving people some precise method signatures would make things more
> concrete and easier to discuss. I suppose I could make ASCII Art UML
> diagrams; would that be better or worse? Let me try a small example:
>
>| Actor | | Attributes |
>|=================| * 1 |==================================| *
>| getAttributes() |------->| update(Effector) |---
> * ^ ^ 1 | get(AttributeKey) | |
> | | | set(AttributeKey,AttributeValue) | |
> 1 | 1 * | * | getKey(Name) | |
> [ Game ]<---| Effector | | modifyBy(Attributes) | |
> | 1 |============| | * |
> | | doStuff | | |
> v 1 | getActor() | | * v
> [ Player ] | | AttributeValue |
> v * Creates |====================|
> | AttributeKey |- - - >| toString() |
> |=================================| | intValue() |
> | update(Effector,AttributeValue) | | inc(AttributeValue)|
> | getName() |
> | defaultValue() |
>
> Surprisingly, even without the comments about what anything means,
> this is more work. Is this worth the effort? At least it did give me
> a reason to take another look at UML.


How about just showing the structure with a nice, indented tree (it's
not much work as long as you've got TAB on your keyboard) and then
describe the relations and the overall concept separately -- so that
the semi-graphical representation fits on screen and can be actually
perceived.

Also, I agree with Sherm that formatting helps a lot. I'd even say
that when you're presenting the code, you can safely ignore most of
the syntactical noise (braces, semicolons, /* */ around comments) and
rely on formatting -- it's much more readable this way.

The point is I really can't understand a thing from your code by just
looking at it.

--
Radomir `The Sheep' Dopieralski @**@_
(*+) 3 Sparkle
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 23, 2005 1:23:28 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote:
> At Thu, 22 Sep 2005 21:37:25 GMT,
> Brendan Guild wrote:
>
>
>>Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
>>news:slrndj595e.lp.thesheep@atos.wmid.amu.edu.pl:
>>
>>>>I'm not going to guarantee that what follows is a very good design
>>>>because I'm fairly certain that it isn't, but it is a place to
>>>>start thinking about roguelike architecture. I will use Java
>>>>interface notation.
>>>
>>>Do you really *must* post code for this?
>>>I'm sure there are much better presentation methods to describe the
>>>structure...
>>
>>No, not really *must* and I certainly won't do it again, since I've
>>never seen anything like this here before and I wasn't really sure
>>how it would go over. Sure, it is technically code but it's not the
>>usual connotation for that word, since I excluded anything that would
>>actually do something when compiled.
>>
>>Out of curiosity, what presentation method would you suggest?
>>
>>I can't think of anything very different except vague hand waving
>>that leaves people to figure out the details on their own. I thought
>>giving people some precise method signatures would make things more
>>concrete and easier to discuss. I suppose I could make ASCII Art UML
>>diagrams; would that be better or worse? Let me try a small example:
>>
>>| Actor | | Attributes |
>>|=================| * 1 |==================================| *
>>| getAttributes() |------->| update(Effector) |---
>> * ^ ^ 1 | get(AttributeKey) | |
>> | | | set(AttributeKey,AttributeValue) | |
>> 1 | 1 * | * | getKey(Name) | |
>>[ Game ]<---| Effector | | modifyBy(Attributes) | |
>> | 1 |============| | * |
>> | | doStuff | | |
>> v 1 | getActor() | | * v
>>[ Player ] | | AttributeValue |
>> v * Creates |====================|
>> | AttributeKey |- - - >| toString() |
>> |=================================| | intValue() |
>> | update(Effector,AttributeValue) | | inc(AttributeValue)|
>> | getName() |
>> | defaultValue() |
>>
>>Surprisingly, even without the comments about what anything means,
>>this is more work. Is this worth the effort? At least it did give me
>>a reason to take another look at UML.
>
>
>
> How about just showing the structure with a nice, indented tree (it's
> not much work as long as you've got TAB on your keyboard) and then
> describe the relations and the overall concept separately -- so that
> the semi-graphical representation fits on screen and can be actually
> perceived.

I second that. Trees are a great way to visually express programming
ideas. Trees, coupled with an indepth explanation below would be ideal,
allowing anyone to instantly grasp what it is you're getting at.

> Also, I agree with Sherm that formatting helps a lot. I'd even say
> that when you're presenting the code, you can safely ignore most of
> the syntactical noise (braces, semicolons, /* */ around comments) and
> rely on formatting -- it's much more readable this way.
>
> The point is I really can't understand a thing from your code by just
> looking at it.

I gave up trying to understand it after about two seconds. It was a
mess, and I wasn't going to painfully crawl through that unformatted
text in the hopes of finding something useful.

I do hope you'll consider Radomir's suggestions, because I'm definitely
interested in what you're trying to say. I'm always interested in
seeing other people's ideas and methods concerning the actual
structure/architecture of the game.
Anonymous
September 23, 2005 2:05:42 PM

Archived from groups: rec.games.roguelike.development (More info?)

I'll respond to this nicely formatted one. FWIW...I think the post is long,
but straightforward. However, I do think the status quo around here is this:
when you are making design considerations that involve a lotta (pseudo)code,
articles are the way to go.

>
> interface Level
> {
> /** Here we get access to each cell of the level map by coordinate
> position. The definition of Pos is trivial and will be omitted here.
> */
> public Square get(Pos p);

There's another recent thread around here regarding the merits of a separate
Square class. While I support such a construct, I don't think it needs to be
exposed to the rest of the world. The implementor of Level can provide a
facade that allows clients interact indirectly with Squares without knowing
about them.

> /** This is for summoning new monsters into the level. It takes an
> ActorType and magically constructs an Actor, puts it into the level,
> and returns it. We don't know the actual implementation class of the
> Actor and we don't care. */
> public Actor createActor(ActorType at, Pos p);

I like to have each class support one abstraction. Here we've bundled up the
abstraction of a "level" with that of an "actor factory"; I like to keep
these separate.

>
> /** Display a message to the player. */
> public void say(String message);
>

Once again I like to keep the abstraction of an onscreen "message area"
separate from that of a "level".

> /** This is a class for representing a cell in a level. It represents
> everything relevant about this cell for all purposes: display, AI,
> game rules, etc. There is no need to use this interface as part of
> the data structure for the level, but it seems quite useful as a
> level interface element. */
> interface Square

I noticed this interface does not expose how large this cell is (e.g. a
single spot, a 2x2 grid, etc.) This could lead to interesting possibilities.
Or maybe not.

> {
> /** blocksLight() and blocks(Actor) are two fundamental properties
> of cells in a roguelike level that deserve to be represented here. */
> public boolean blocksLight();

>
> /** This is for implementing walls and monsters and anything that a
> character cannot walk through. It will be used in path finding and in
> responding to player movement commands. */
> public boolean blocks(Actor a);
>

I equate "blocksLight()" with an "opacity" flag, and "blocks()" with a
"walkable" flag. Likely you will find many other flags that deserve
representation here.

My two cents,
Nathan
Anonymous
September 23, 2005 2:46:25 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndj7icf.lc6.thesheep@atos.wmid.amu.edu.pl:
> How about just showing the structure with a nice, indented tree
> (it's not much work as long as you've got TAB on your keyboard) and
> then describe the relations and the overall concept separately --
> so that the semi-graphical representation fits on screen and can be
> actually perceived.

Unfortunately, I doubt that pressing the keys would be the majority
of the work. The designs I have proposed in interface format didn't
really have any clear tree structure (even to me), so I anticipate
some difficulty in finding one. More importantly, a design
represented by interfaces is going to be focusing on abstract
operations and relations, so the second part of that presentation
would be much larger than the first and I would probably want to find
some way of organizing it.

I'm not sure I completely understand what you are saying about
fitting on screen and being perceivable. Do you mean that you
couldn't see the ASCII Art UML diagram because it was too large? I'm
also considering that I should have laid out the interfaces without
comments first, then explained what it means after, so that the
various interfaces would fit nearly all on one screen.

> Also, I agree with Sherm that formatting helps a lot. I'd even say
> that when you're presenting the code, you can safely ignore most of
> the syntactical noise (braces, semicolons, /* */ around comments)
> and rely on formatting -- it's much more readable this way.

I agree that there was a lot of noise in the presentation the way I
gave it. I guess that I'm so used to reading Java syntax that it
didn't occur to me that it might give some people problems. If I were
to do it again, I'd strip it down to be completely free of needless
syntactic garbage. However, I don't think I'm going to repost it all
just for that. Sherm has already done a very nice job of reformatting
and reposting and I think a third would be one time too many.

> The point is I really can't understand a thing from your code by
> just looking at it.

That is very disappointing for me, but not very surprising. I was
really hoping to get some feedback from some of the most respectable
contributors to rgrd. Unfortunately, I have only ever gotten two
small comments on designs that I have posted this way. Since I can
only assume that you are interested in roguelike design, I had
already guessed that you weren't reading them or weren't
understanding them. I will keep this lesson in mind in case I ever
try again.
Anonymous
September 23, 2005 2:46:26 PM

Archived from groups: rec.games.roguelike.development (More info?)

Brendan Guild wrote:

<snip>

> That is very disappointing for me, but not very surprising. I was
> really hoping to get some feedback from some of the most respectable
> contributors to rgrd. Unfortunately, I have only ever gotten two
> small comments on designs that I have posted this way. Since I can
> only assume that you are interested in roguelike design, I had
> already guessed that you weren't reading them or weren't
> understanding them. I will keep this lesson in mind in case I ever
> try again.

Maybe if you just explained it all in more detail, it would help.
Splice in relevant code samples only when necessary. I think people
would show more interest if you went more indepth. I know I would.
Anonymous
September 23, 2005 2:47:09 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote:
> Also, I don't like several things about where things are stored. For
> example, why the PC position is stored in the Level, not the Actor (or
> maybe it's Effector?) itself? Where are stored the positions of all
> other monsters and items?

I think that design is not from a working game:) 
Also I believe there is no single right way to express the relations
between objects. In some cases there might not be a strong relation
at all. For example I've never understood the way tile "has" items
or other objects. Why? Is tile a container?:) 
Anonymous
September 23, 2005 3:09:35 PM

Archived from groups: rec.games.roguelike.development (More info?)

Timothy Pruett wrote in news:YqQYe.5967$P7.2133@fe06.lga:
> Radomir 'The Sheep' Dopieralski wrote:
>> How about just showing the structure with a nice, indented tree
>> (it's not much work as long as you've got TAB on your keyboard)
>> and then describe the relations and the overall concept separately
>> -- so that the semi-graphical representation fits on screen and
>> can be actually perceived.
>
> I second that. Trees are a great way to visually express
> programming ideas. Trees, coupled with an indepth explanation
> below would be ideal, allowing anyone to instantly grasp what it is
> you're getting at.

I thought that I fairly well understood Radomir's comments, but now
I'm not so sure. I'd like to ask you to give an example of how my
design could be organized into trees, but obviously that won't work.

>> Also, I agree with Sherm that formatting helps a lot. I'd even say
>> that when you're presenting the code, you can safely ignore most
>> of the syntactical noise (braces, semicolons, /* */ around
>> comments) and rely on formatting -- it's much more readable this
>> way.
>>
>> The point is I really can't understand a thing from your code by
>> just looking at it.
>
> I gave up trying to understand it after about two seconds. It was
> a mess, and I wasn't going to painfully crawl through that
> unformatted text in the hopes of finding something useful.
>
> I do hope you'll consider Radomir's suggestions, because I'm
> definitely interested in what you're trying to say. I'm always
> interested in seeing other people's ideas and methods concerning
> the actual structure/architecture of the game.

Thanks for your interest, but I don't entirely understand your
concern. How was that post significantly less formatted than this
one? I could easily have done better, as Sherm proved very nicely,
but 'painful' seems strong. It was divided into paragraphs, which is
the only formatting this post has. I didn't space the paragraphs out,
but I did indent the first line. I even included /** at the start of
most of them, which to me makes the breaks between paragraphs stand
out like sore thumbs.

If I was going to do it again, I would have put in blank lines. The
only reason I didn't was because I was slightly ashamed of my line
count, which now seems extremely silly.
Anonymous
September 23, 2005 3:09:36 PM

Archived from groups: rec.games.roguelike.development (More info?)

Brendan Guild wrote:
> Timothy Pruett wrote in news:YqQYe.5967$P7.2133@fe06.lga:
>
>>Radomir 'The Sheep' Dopieralski wrote:
>>
>>>How about just showing the structure with a nice, indented tree
>>>(it's not much work as long as you've got TAB on your keyboard)
>>>and then describe the relations and the overall concept separately
>>>-- so that the semi-graphical representation fits on screen and
>>>can be actually perceived.
>>
>>I second that. Trees are a great way to visually express
>>programming ideas. Trees, coupled with an indepth explanation
>>below would be ideal, allowing anyone to instantly grasp what it is
>>you're getting at.
>
>
> I thought that I fairly well understood Radomir's comments, but now
> I'm not so sure. I'd like to ask you to give an example of how my
> design could be organized into trees, but obviously that won't work.
>
>
>>>Also, I agree with Sherm that formatting helps a lot. I'd even say
>>>that when you're presenting the code, you can safely ignore most
>>>of the syntactical noise (braces, semicolons, /* */ around
>>>comments) and rely on formatting -- it's much more readable this
>>>way.
>>>
>>>The point is I really can't understand a thing from your code by
>>>just looking at it.
>>
>>I gave up trying to understand it after about two seconds. It was
>>a mess, and I wasn't going to painfully crawl through that
>>unformatted text in the hopes of finding something useful.
>>
>>I do hope you'll consider Radomir's suggestions, because I'm
>>definitely interested in what you're trying to say. I'm always
>>interested in seeing other people's ideas and methods concerning
>>the actual structure/architecture of the game.
>
>
> Thanks for your interest, but I don't entirely understand your
> concern. How was that post significantly less formatted than this
> one? I could easily have done better, as Sherm proved very nicely,
> but 'painful' seems strong.

Yes, sorry, 'painful' was a bit strong. How about 'hassle'? Sherm's
job of formatting it definitely improved it's readibility, but I don't
think that was the only problem.

> It was divided into paragraphs, which is
> the only formatting this post has. I didn't space the paragraphs out,
> but I did indent the first line. I even included /** at the start of
> most of them, which to me makes the breaks between paragraphs stand
> out like sore thumbs.
>
> If I was going to do it again, I would have put in blank lines. The
> only reason I didn't was because I was slightly ashamed of my line
> count, which now seems extremely silly.

I hope you do intend to do it again. Like I said before, I'm interested
in what you have to say, but I didn't care for how you presented it.
Don't take offense, because none is intended, but I felt like you didn't
really explain your ideas that well. When describing an interface, you
really need to provide a lot of detail concerning the interactions with
the interface, conventions to be used, etc. You just didn't give enough
detail.
Anonymous
September 23, 2005 3:39:11 PM

Archived from groups: rec.games.roguelike.development (More info?)

Timothy Pruett wrote in news:EpRYe.6208$845.5604@fe03.lga:
> Maybe if you just explained it all in more detail, it would help.
> Splice in relevant code samples only when necessary. I think
> people would show more interest if you went more indepth. I know I
> would.

This advice is totally unexpected. I was beginning to regret posting
even what I had and when I did it I felt that it was rather long; it
never occurred to me that if I had posted more I would have gotten
more interesting responses, but of course that makes perfect sense
now that I think about it.

Still, I hesitate. I don't want to post more stuff that no one will
read. At least I will certainly be able to avoid code samples, since
sample code goes strongly against what I'm trying to accomplish,
which is very abstract roguelike design. On the other hand, a little
sample code would increase the level of detail that I'm working at.

When I was writing my original post, I never imagined that the format
would be more important than the content, but so it is. Now I need to
know: Is it better to mix the comments into the interface as I was
doing, or should I take a radical new approach and save all the
comments for the end? Based on the formatting tips I've gotten, I
think it's the latter, but I'm not going to take any chances.

I'd also like to hear about any other formatting rules that anyone
cares to mention.
Anonymous
September 23, 2005 3:39:12 PM

Archived from groups: rec.games.roguelike.development (More info?)

Brendan Guild wrote:
> Timothy Pruett wrote in news:EpRYe.6208$845.5604@fe03.lga:
>
>>Maybe if you just explained it all in more detail, it would help.
>>Splice in relevant code samples only when necessary. I think
>>people would show more interest if you went more indepth. I know I
>>would.
>
>
> This advice is totally unexpected. I was beginning to regret posting
> even what I had and when I did it I felt that it was rather long; it
> never occurred to me that if I had posted more I would have gotten
> more interesting responses, but of course that makes perfect sense
> now that I think about it.

We're coders. Coders like indepth explanations of everything. :-)

> Still, I hesitate. I don't want to post more stuff that no one will
> read. At least I will certainly be able to avoid code samples, since
> sample code goes strongly against what I'm trying to accomplish,
> which is very abstract roguelike design. On the other hand, a little
> sample code would increase the level of detail that I'm working at.

Try using very generic pseudocode. I'd probably avoid making it look
like any language specifically, but that's just my personal preference.
Sample code is fine, but only to help make a point made in the article.

> When I was writing my original post, I never imagined that the format
> would be more important than the content, but so it is.

Format isn't more important than the content, but format *can* prevent
the content from reaching it's desired audience in the first place.

> Now I need to
> know: Is it better to mix the comments into the interface as I was
> doing, or should I take a radical new approach and save all the
> comments for the end? Based on the formatting tips I've gotten, I
> think it's the latter, but I'm not going to take any chances.

I'd go with the latter approach. Write it more like an article.
Articles describe the idea in detail, and only bother to use code when
it makes illustrating a point easier.

> I'd also like to hear about any other formatting rules that anyone
> cares to mention.

There aren't any real rules, just try and make it as readable as
possible. Also, make sure your method of presentation is fitting with
your goal. The approach you used before (pseudocode with comments mixed
in) is better suited to describing a dungeon generation technique, or
something similar, but it didn't really fit with your idea to well.

I'm looking forward to seeing your new version. Good luck. :-)
Anonymous
September 23, 2005 3:51:15 PM

Archived from groups: rec.games.roguelike.development (More info?)

Timothy Pruett wrote in news:FARYe.2504$X6.8@fe05.lga:
> I hope you do intend to do it again. Like I said before, I'm
> interested in what you have to say, but I didn't care for how you
> presented it. Don't take offense, because none is intended, but I
> felt like you didn't really explain your ideas that well. When
> describing an interface, you really need to provide a lot of detail
> concerning the interactions with the interface, conventions to be
> used, etc. You just didn't give enough detail.

Now this is something that I really can understand! Thank you very
much for giving me a comment about the content of my designs. I see
that I made the mistake of relying too heavily on my own
understanding of the design and accidentally assumed knowledge on the
reader that only I have. Now that I see this, I will repost the same
interfaces with expanded commentary, reduced syntactic clutter, and
lots of whitespace.
Anonymous
September 23, 2005 5:34:01 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Fri, 23 Sep 2005 11:09:35 GMT,
Brendan Guild wrote:

> Timothy Pruett wrote in news:YqQYe.5967$P7.2133@fe06.lga:
>> Radomir 'The Sheep' Dopieralski wrote:
>>> How about just showing the structure with a nice, indented tree
>>> (it's not much work as long as you've got TAB on your keyboard)
>>> and then describe the relations and the overall concept separately
>>> -- so that the semi-graphical representation fits on screen and
>>> can be actually perceived.
>>
>> I second that. Trees are a great way to visually express
>> programming ideas. Trees, coupled with an indepth explanation
>> below would be ideal, allowing anyone to instantly grasp what it is
>> you're getting at.
>
> I thought that I fairly well understood Radomir's comments, but now
> I'm not so sure. I'd like to ask you to give an example of how my
> design could be organized into trees, but obviously that won't work.

If it doesn't fit into text easily, tehn just upload an image somewhere
(lots of free sites that allow you to upload images) and then post the
URL in your article, or even go for it and make a full-blown article
in html, and then just post the URL here.

I'm not sure more spaces help here -- the whole thing becomes larger,
and even harder to grasp. Indentation is perfect to show any kind
of hierarchy, and to visualise not very dense graphs (you show
them as trees and mark the additional edges)

I don't understand your code, so I cannot really propose a better way
of representing it -- all I can give is some hints that maybe could work.

--
Radomir `The Sheep' Dopieralski @**@_
(*+) 3 Sparkle
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 23, 2005 6:51:52 PM

Archived from groups: rec.games.roguelike.development (More info?)

Brendan Guild <dont@spam.me> schrieb:
> Unfortunately, I have only ever gotten two small comments on designs
> that I have posted this way. Since I can only assume that you are
> interested in roguelike design, I had already guessed that you weren't
> reading them or weren't understanding them. I will keep this lesson in
> mind in case I ever try again.

The problem is that you're aren't asking a specific question or stating
a specific problem.

--
Jim Strathmeyer
Anonymous
September 23, 2005 7:03:38 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Thu, 22 Sep 2005 20:38:08 -0400,
Sherm Pendley wrote:
> Brendan Guild <dont@spam.me> writes:

I'll try read into this and describe what I understand from it. Please
correct me when I'm mistaken. I'll put my own comments after the '#'
character.

Level - description of single dungeon level
Squares - individual map squares (created on request, not stored)
center - the center of the level
findPC - the position of player character on the level

Effector - a way for the actor to change environment
getActor - the focus of commands
getEffector(actor) - the effector of another actor
moveSelf(position) - moves the actor being the focus, invoked by the
actor itself
moveTo(position) - moves the actor being the focus, invoked by other
actors
remove(item, position) - remove an item from level map square
put(item, position) - put an item on a map square
createActor(actor_type, position) - create and put an actor on a map
square
say(message) - display a message to the player
sayToActor(message1, message2) - display message1 if focus is PC, or
message2 otherwise
damage(damage, position, effector) - applies damage to everything on
the map cell
# What's effector parameter here for?

Square - a single square of the dungeon level map
blocksLight - true if creatures can't see trough it
blocks(actor) - true if actor can't move trough it
onStep(actor, effector) - called by actor it moves on the square
onStepOff(actor, effector) - called by actor when it leaves square
getActor - what creature is on this square
getItems - what items are on this square
draw(context) - draw the square in the drawing context

Actor - the AI or UI of the creature
takeTurn(level, position, effector) - performs action and returns how
long it took
onDamage(damage, effector) - apply damage to the actor's creature
draw(context) - draw actor's creaturte in the drawing context
getAttributes - the creature's stats

Damage - represents attacks
source - anonymous but remembered in form of messages # ?????
onHit(actor, effector) - called by the actor being hit by it # ?
onMiss(actor, effector) - called by the actor being missed by it
onHit(item, effector) - called by the item being hit by it
# items have effectors too?
onMiss(item, effector) - called by the item being missed by it

#

Ok, that's a quick summary to give a picture of the structure, now should
be a part describing the interactions -- maybe with some examples of
actors performing tasks, etc.

Of course, it's kind of personal taste here -- I find it easier to
understand when complicated things are explained top-down.

I'll put my feedback here instead ;) 

I don't fully "get" the purpose and meaning of the "Effector" objects.
Does every item, monster and terrain feature (like door) have it's own?
Or are they created ad-hoc when needed and destroyed right after a single
action have been performed?

Also, I don't like several things about where things are stored. For
example, why the PC position is stored in the Level, not the Actor (or
maybe it's Effector?) itself? Where are stored the positions of all
other monsters and items?
Why items and monsters are created in effectors? Which object "owns"
them?

Is an Item an Actor too?

Why two separate methods for moving the actors?

I think an example of a monster (or PC) performing some action would
clarify things *a lot*.

--
Radomir `The Sheep' Dopieralski @**@_
<..> ] 0110110?
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 23, 2005 9:04:57 PM

Archived from groups: rec.games.roguelike.development (More info?)

At 23 Sep 2005 15:03:38 GMT,
Radomir 'The Sheep' Dopieralski wrote:

> At Thu, 22 Sep 2005 20:38:08 -0400,
> Sherm Pendley wrote:
>> Brendan Guild <dont@spam.me> writes:

I'll try to post my own try at this, so that we've got something to
compare and argue over ;) 

Dungeon - everything that gets saved a the game state
timeline - contains all the active actors
levels - the permanent and the current, even when it's not permanent
hero - a reference to the PC actor (if the PC is special)
stats - all the global world parameters.

build(level_kind) - generate new level
wake(actor_kind, creature) - add new actor to the timeline

Level - your basic dungeon level
map - the map of the level
creatures - all the creatures on the level
items - all the items on the level
exits - the stairs with references to other levels

move(creature, position) - puts/moves the creature on the level
move(creature, exit) - puts/moves creature to another level
kill(creature) - removes the creature from the level
give(item, position) - drops an item on the floor
take(item) - takes an item from the floor

can_*() - true if that action if possible
can_walk(creature, position)
can_attack(creature, creature, attack_kind)
can_eat(creature, item)
can_pick(creature, item)
can_see(creature, creature)
can_see(creature, position)
can_see(creature, item)
...
do_*() - performs the action
do_walk(creature, position)
do_attack(creature, creature, attack_kind)
do_eat(creature, item)
do_pick(creature, item)
...

Timeline - decides who goes next
getActor() - return the actor to act next
putActor(actor, time) - schedules the next actor's action
clear() - removes all the actors

Actor - anything that can perform actions
act(dungeon) - perform an action in the actor's turn

state - the state of AI or UI
creature - the creature controlled by the actor
level - the level on which the actor operates

Creature - a monster or the player character
stats - the statistics, attributes, etc.
flush_stats() - recalculates all the stats based on equipment, etc.

inventory - the items in possesion of the creature
equipment - etc.
position - the creature's position on it's level

equip(item) \
damage(amount) \ The atom events that can
give(item) / be applied to the creature
take(item) /
...

Item - something you can pick up
stats - statistics, attributes, etc.
position - if the item is lying on the floor
owner - if the item is held
...

Ok, now the explanation.
The <dungeon> is a singleton object being the game state. I skip
all the game data that is read from the data files and static thru the
game -- they'd probably go into a separate object, with all the factories
and the like, and then go into the <dungeon>.

Everything and anything that changes in the dungeon during the game is
recorded somewhere in the <dungeon> object. Any change with it's scope
larger than thesingle object performing the change has to be done using
one of the <do_*> methods of the <dungeon>.
You can split this part using <action_kind> objects and having only do_action
and can_action methods, but let's keep things simple for the start.

The <dungeon> has it's state recorded in two layers -- there is the list
of <levels> that records the, mhm, physical information about the dungeon,
like the maps, the positions and stats of items and creatures, etc.
Them there's the <timeline> object, that records the turn order in which
the actors are supposed to act.

In the main game loop, after creating the <dungeon>, an <actor> is taken
from the <timeline> and it's <act> method is called. The method checks
the <dungeon>, especially the <creature> to which the <actor> is
connected, and decides on the action to perform, using the <can_*> methods
of <dungeon>. Then it calls one (or multiple) <do_*> methods to actually
perform the action, and puts itself back into the <timeline>.

The <do_*> methods will usually call a whole bunch of simplier <do_*>
methods, and those will perform the actual actions using the atom events
methods of <dungeon>, <item> and <creature>.

The only way the <actors> know about the actions performed by other
<actors> (like the fact that a monster attacked it's creature) is by
examining the internal state of the <creatures> and other <dungeon>
elements. The <creatures> can, for example, record the last action
performed.

--
Radomir `The Sheep' Dopieralski @**@_
(: ) 3 Snap!
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 23, 2005 10:04:09 PM

Archived from groups: rec.games.roguelike.development (More info?)

At 23 Sep 2005 10:47:09 -0700,
Krice wrote:

> Radomir 'The Sheep' Dopieralski wrote:
>> Also, I don't like several things about where things are stored. For
>> example, why the PC position is stored in the Level, not the Actor (or
>> maybe it's Effector?) itself? Where are stored the positions of all
>> other monsters and items?

> I think that design is not from a working game:) 

Sure, it was explicitly stated at the beginning of this thread.

> Also I believe there is no single right way to express the relations
> between objects. In some cases there might not be a strong relation
> at all.

Sure, but some ways seems tho be "righter" than others :) 
Plus, you definitely need to keep the references to your objects
*somewhere*, or they get GC-ed.

> For example I've never understood the way tile "has" items
> or other objects. Why? Is tile a container?:) 

Well, I don't think the square "has" items. It's just that you
have to somehow index them, and since you often want a list of
items on given position (or withing certain radius), it's
convenient to have them indexed by their position, so the square
in fact only "has" a list of items, not the items themselves :) 
It also works nicely when you're destroying the level -- the items
that lie on the floor get destroyed with the squares, while the
items in the PC inventory get transported with him to another
level.

I'm almost sure it would bee much more efficient to store the
(lying) items and monsters in a map, hashed by their positions.
Such a list would get destroyed with the level anyways, so...

--
Radomir `The Sheep' Dopieralski @**@_
<..> ] 0110110?
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 24, 2005 1:52:13 AM

Archived from groups: rec.games.roguelike.development (More info?)

Jim Strathmeyer wrote in news:ApSdnUZj9YpFwaneRVn-1Q@adelphia.com:
> The problem is that you're aren't asking a specific question or
> stating a specific problem.

I take your point completely. Though actually I did ask a couple of
questions, they weren't very specific. One of them was looking for a
way to represent timing information in a implementation independent way
and the other was trying to break up one of the larger interfaces into
smaller ones. They were kind of buried in with everything else.
Anonymous
September 24, 2005 4:57:23 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndj86aa.vj8.thesheep@atos.wmid.amu.edu.pl:
> I'll try read into this and describe what I understand from it.
> Please correct me when I'm mistaken. I'll put my own comments after
> the '#' character.

Thanks! I was actually about to do something very much like this. It
is perfectly correct.

> Level - description of single dungeon level
> Squares - individual map squares (created on request, not
> stored)
> center - the center of the level
> findPC - the position of player character on the level
>
> Effector - a way for the actor to change environment
> getActor - the focus of commands
> getEffector(actor) - the effector of another actor
> [snip]
> damage(damage, position, effector) - applies damage to
> everything on the map cell
> # What's effector parameter here for?

Nothing. The effector parameter there was my mistake. That should be:
damage(damage, position)

> Damage - represents attacks
> source - anonymous but remembered in form of messages # ?????

In other words, we don't let the code for handling attacks become
dependant on the attacker, because we want to be able to use this for
trap damage as well. But of course, we'll still want to be able to
display messages about who hit who. To do this, we don't keep a
reference to the source, we just have the source create messages
describing what it is doing and keep those. Or perhaps we do keep a
reference to the source and use it to invoke sophisticated message
generation procedures, but we don't expose the source to the clients
of the Damage interface.

> onHit(actor, effector) - called by the actor being hit by it
> # ?

Right, this is a helper function for Actor's onDamage() that we can
implement to help represent different kinds of attacks by different
subclasses of Damage.

> onHit(item, effector) - called by the item being hit by it
> # items have effectors too?

They don't have effectors because they can't be moved as easily as
Actors. I think it's best to allow for a implementation that isn't
able to look up an item's position on the level. However, that
doesn't mean that item's won't do things when they are hit, so I
provide an effector and all it's useful abilities.

The effector will be the one that caused the damage through it's
damage() method, or the effector held by whatever other method called
the onDamage(damage,effector) method of the item. So if damaging this
item somehow causes an attack on another item, we'll call: onDamage
(damage,effector) with the effector that was given to us.

> I don't fully "get" the purpose and meaning of the "Effector"
> objects. Does every item, monster and terrain feature (like door)
> have it's own? Or are they created ad-hoc when needed and destroyed
> right after a single action have been performed?

Neither, really.

An effector is designed to be an fascade onto a unknown game
implementation. It's where my design stops and the rest of it begins,
thus allowing code which works through an effector to be independent
of code which works behind an effector. This way we won't ever need
to rewrite both!

An Effector has a pointer to an Actor only because actors are
instrumental in all effects that occur in the game world. I didn't
include the possibility of pointing to an item because I don't expect
an item to move as an Actor would. In this design, it one wanted an
item to move around the level through calls like moveSelf(), you'd
make it an Actor.

An actor isn't likely to own an effector: an effector is passed into
the methods of Actor whenever it might be needed. Anything that has
an effector can create a new effector with the getEffector(actor)
method which they then 'own' but aren't expected to keep it around
for longer than the method call that gave them their original
effector.

> Also, I don't like several things about where things are stored.
> For example, why the PC position is stored in the Level, not the
> Actor (or maybe it's Effector?) itself? Where are stored the
> positions of all other monsters and items?

It's an important point that this design doesn't specify where the
positions of things are stored. The reason that we are given access
to the PC position from the Level interface is because that is
critical to so many activities involving the Level interface, such as
representing the level on the screen and controlling the monsters.

> Why items and monsters are created in effectors? Which object
> "owns" them?

Those things are owned by something behind the effector, probably a
level representation where items are in a 2D array and the monsters
are in a list with a hashtable. It is also going to be behind the
Level interface. It might look something like this:

MutableLevel - A class with absolute power over a level, not to be
accessed directly!
put(Item,pos) - Put anything anywhere
getItems(pos) - A list of items
remove(Item,pos) - For when we pick up or destroy something
set(Actor,pos) - Dictating where this actor is on this map
find(Actor) - Position of this actor
getActor(pos)
set(pos,TileType) - Set the TileType of this spot (eg. Wall)
getTile(pos) - Finds the TileType at this spot
center() - Center of the level

MutableLevel is never going to be seen by any of the AI or UI code,
they use Level and Effector objects instead. This way, MutableMap is
free to be more low-level, perhaps working with more concrete
implementations of Actor and Item. It might have access to an actor's
internal representation of where it is, or it might use a hashtable
for that. Even so, it won't construct anything itself; it just
accepts what we give it blindly.

If we ever need to completely redesign MutableLevel, we will need to
rewrite our Level and Effector classes, but we won't need to rewrite
our precious AI or UI.

We allow actors to be created through an effector to make summoning
possible. Monsters that create monsters, traps that create monsters,
etc. It's a parallel operation to attacking with the damage() method.

> Is an Item an Actor too?

Not in my design. I was actually thinking that Actor could be an
Item, but there didn't seem to be a need.

> Why two separate methods for moving the actors?

Because one of them is for moving an actor normally and may be able
to enforce restrictions on where an actor may move, such as not going
through walls. The other one is for teleportation, mostly, and any
other cases of movement other than normal movement.

> I think an example of a monster (or PC) performing some action
> would clarify things *a lot*.

I apologize in advance for the code. I hope my overly simplified
example really will clarify things.
In a monster's takeTurn(level, position, effector) method we could
have something like this:
{
Position pcPos = level.findPC();
// Figure out where the PC is, then try to get to it and attack
int dx = signOf(pcPos.x - position.x);
int dy = signOf(pcPos.y - position.y);
// Try a few directions. If we do anything during an attempt, our
// turn is over.
int time;
time = tryDirection(Position(position.x+dx,position.y+dy),
level, effector);
if(time>0) return new Timing(time);
time = tryDirection(Position(position.x+dx,position.y),
level, effector);
if(time>0) return new Timing(time);
time = tryDirection(Position(position.x,position.y+dy),
level, effector);
if(time>0) return new Timing(time);
return new Timing(1); // do nothing
}

int tryDirection(position, level, effector)
{
if(!level.get(position).blocks(this))
{ // Move towards the PC
effector.moveSelf(position);
return 1;
}
if(position==level.findPC())
{ // Here we attack the PC, passing in all the information
// needed to figure out if and how badly we hit it.
PokeWithSpoon poke = new PokeWithSpoon(myAttackAttributes);
poke.hitMess("The " + name() + " pokes you with a spoon!");
poke.missMess("The " + possessive() + " spoon misses you!");
effector.damage(poke,position);
return 1;
}
return 0; // Do nothing
}
Anonymous
September 24, 2005 5:49:21 AM

Archived from groups: rec.games.roguelike.development (More info?)

"Nathan Jerpe" <nathanunderscorejerpe@msn.com> wrote in
news:43340bbb$0$49010$14726298@news.sunsite.dk:
>> interface Level
>> {
>> /** Here we get access to each cell of the level map by coordinate
>> position. The definition of Pos is trivial and will be omitted
>> here. */
>> public Square get(Pos p);
>
> There's another recent thread around here regarding the merits of a
> separate Square class. While I support such a construct, I don't
> think it needs to be exposed to the rest of the world. The
> implementor of Level can provide a facade that allows clients
> interact indirectly with Squares without knowing about them.

Actually, I meant Square to be a facade that allows clients to
interact with the level without knowing that it's not actually
organized so simply. It just seems like a nice way to separate out
some of the level interface to simply things. However, whether or not
Square is actually used in the implementation is now very easily
changed behind the scenes.

>> /** This is for summoning new monsters into the level. It takes an
>> ActorType and magically constructs an Actor, puts it into the
>> level, and returns it. We don't know the actual implementation
>> class of the Actor and we don't care. */
>> public Actor createActor(ActorType at, Pos p);
>
> I like to have each class support one abstraction. Here we've
> bundled up the abstraction of a "level" with that of an "actor
> factory"; I like to keep these separate.

Very good point. I certainly considered not having createActor here,
but it seems unavoidable! This method is needed for magical summoning
and spawning that could happen nearly anywhere by anything. I would
have to be passing around actor factories as much as I'm passing
around effectors. Nothing prevents createActor() from using an actor
factory underneath, right?

>> /** Display a message to the player. */
>> public void say(String message);
>
> Once again I like to keep the abstraction of an onscreen "message
> area" separate from that of a "level".

Yeah, but this is even worse than with createActor. Nearly everything
that happens will have a message associated with it and I don't want
to have to pass an extra argument into everything.

>> interface Square
>
> I noticed this interface does not expose how large this cell is
> (e.g. a single spot, a 2x2 grid, etc.) This could lead to
> interesting possibilities. Or maybe not.

You mean for multi-cell monsters and things like that? That's not
something I considered when writing this design, but I'm pretty sure
my design is sufficiently abstract to allow them. The position of a
monster just needs to be a center point and then have that monster
present as the actor in every square that it covers and let it manage
it's own body how it chooses.

> I equate "blocksLight()" with an "opacity" flag, and "blocks()"
> with a "walkable" flag. Likely you will find many other flags that
> deserve representation here.

Very true, but we don't need to represent everything that the game
will need, only those things that we are fundamental to our important
algorithms or very roguelike. It would be very hard to remove things
from this interface later if we change our mind.

This problem is even worse in the Effector interface, which is pretty
big and doomed to get bigger.

If something needs more detail than we represent in this interface,
it can cast a Square to a more specific type.
Anonymous
September 24, 2005 1:37:02 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndj8ddp.tqf.thesheep@atos.wmid.amu.edu.pl:
> I'll try to post my own try at this, so that we've got something to
> compare and argue over ;) 

Much appreciated!

> Dungeon - everything that gets saved a the game state
> timeline - contains all the active actors
> levels - the permanent and the current, even when it's not
> permanent
> hero - a reference to the PC actor (if the PC is
> special)
> stats - all the global world parameters.
>
> build(level_kind) - generate new level
> wake(actor_kind, creature) - add new actor to the timeline
>
> Level - your basic dungeon level
> map - the map of the level
> creatures - all the creatures on the level
> items - all the items on the level
> exits - the stairs with references to other levels
>
> move(creature, position) - puts/moves the creature on the level
> move(creature, exit) - puts/moves creature to another level

I don't see how this operation can be performed. In order to move to
another level, I'd need to change the level in the actor but I don't
see a way to get the actor with just level, the creature and an exit.

If this method is called from the actor and it remembers to update
it's own level from the exit, then it would work, but otherwise this
method will likely have a very strange effect, where the creature is
on one level and the actor on another. And there doesn't seem to be
any way to verify that the actor has been updated correctly in this
method.

> kill(creature) - removes the creature from the level
> give(item, position) - drops an item on the floor
> take(item) - takes an item from the floor
>
> can_*() - true if that action if possible
> can_walk(creature, position)
> can_attack(creature, creature, attack_kind)
> can_eat(creature, item)
> can_pick(creature, item)
> can_see(creature, creature)
> can_see(creature, position)
> can_see(creature, item)
> ...
> do_*() - performs the action
> do_walk(creature, position)
> do_attack(creature, creature, attack_kind)
> do_eat(creature, item)
> do_pick(creature, item)
> ...
>
> Timeline - decides who goes next
> getActor() - return the actor to act next
> putActor(actor, time) - schedules the next actor's action
> clear() - removes all the actors
>
> Actor - anything that can perform actions
> act(dungeon) - perform an action in the actor's turn
>
> state - the state of AI or UI
> creature - the creature controlled by the actor
> level - the level on which the actor operates

Why do we store the level here? The act() method already gets the
entire dungeon, so it doesn't need another way to access the level.
If it's for locating the creature we are controlling, why isn't the
level stored in the creature with the position?

[snip Creature and Item]

> Everything and anything that changes in the dungeon during the game
> is recorded somewhere in the <dungeon> object. Any change with it's
> scope larger than thesingle object performing the change has to be
> done using one of the <do_*> methods of the <dungeon>.

This is like my effector class. Are messages to the player handled
this way?

> You can split this part using <action_kind> objects and having only
> do_action and can_action methods, but let's keep things simple for
> the start.

How about splitting them up into objects for <can> and objects for
<do>? Doing something will always be pretty much the same, but the
abilities of a creature might change more easily. It could be helpful
to be able to change the implementation of the <can_*> methods
separately from <do_*> methods. Plus, wouldn't <can_*> methods be
more likely to want to share helper functions with each other than
with a <do_*> method?

> In the main game loop, after creating the <dungeon>, an <actor> is
> taken from the <timeline> and it's <act> method is called. The
> method checks the <dungeon>, especially the <creature> to which the
> <actor> is connected, and decides on the action to perform, using
> the <can_*> methods of <dungeon>. Then it calls one (or multiple)
> <do_*> methods to actually perform the action, and puts itself back
> into the <timeline>.

The timing is what concerns me most as the greatest weakness of my
own design. I know that there are all kinds of complex timing
systems. Can you modify your game to use any of them just by
modifying your Timeline implementation?

> The only way the <actors> know about the actions performed by other
> <actors> (like the fact that a monster attacked it's creature) is
> by examining the internal state of the <creatures> and other
> <dungeon> elements. The <creatures> can, for example, record the
> last action performed.

I see that is enforced by the fact that a creature has no idea who
it's actor is. I was planning on having the AI implemented by
subclassing an Actor implementation, where the highest Actor would
hold all the stuff that the creature holds in your design and
subclasses would override the act() method. Your design is better
because changing AI implementations for a character is as simple as
inserting a different Actor for your creature at the end of the act()
method instead of 'this'.

But why not provide some kind of interface by which a creature can
inform its actor of important events? I think especially it would be
good to be able to change the AI implementation upon being attacked.
It would be very intuitive to have a method called onAttacked() where
you can do stuff.

Clearly it is good to have separate concepts and class for creatures
and actors, but it's a pretty subtle difference, isn't it? That's why
I would hide them within a single class from the point of view of the
vast majority of my code. I'd make the Creature hold an Actor, then
have the creature call event methods on the actor, especially act().
The Creature could hold all of the properties that the Actor might
need in a single object that can be passed easily into methods of the
Actor. Most importantly, there would be no way to access the Actor
from outside of Creature. Special creatures, such as the PC, might
not even have an Actor and know one would know the difference.

You could still force the Actor to check the Creature for events, but
would be in a better position to change your mind later.
Anonymous
September 24, 2005 4:06:45 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Sat, 24 Sep 2005 09:37:02 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski wrote in
> news:slrndj8ddp.tqf.thesheep@atos.wmid.amu.edu.pl:
>> move(creature, position) - puts/moves the creature on the level
>> move(creature, exit) - puts/moves creature to another level
>
> I don't see how this operation can be performed. In order to move to
> another level, I'd need to change the level in the actor but I don't
> see a way to get the actor with just level, the creature and an exit.
>
> If this method is called from the actor and it remembers to update
> it's own level from the exit, then it would work, but otherwise this
> method will likely have a very strange effect, where the creature is
> on one level and the actor on another. And there doesn't seem to be
> any way to verify that the actor has been updated correctly in this
> method.

Yes, you're right, I assumed that this method will be called only by the
actor controlling it. Note that this method is useless for all kinds of
level teleportation and trapdoors anyways -- it must use an exit,
a stairway.

To teleport creature between levels you'd have to use the more low-level
methods <kill> to remove it from the current level and <bear> to put it
on a new one. Then there's the problem of the <actor> having improper
information about it's creature's level. :/ 

I don't put the reference to <level> in the <creature> itself because
it's supposed to be only a token, a figurine on the table (with maybe
a sheet of paper attached to record it's stats). It doesn't know it's
surroundings. But it definitely should know it's position. So maybe
you should store some kind of <level_id>, and index to <dungeon.levels>
or the depth and branch, or something like this... But then it doesn't
encapsulate nicely.

I didn't consider teleporting levels.

>> level - the level on which the actor operates
>
> Why do we store the level here? The act() method already gets the
> entire dungeon, so it doesn't need another way to access the level.
> If it's for locating the creature we are controlling, why isn't the
> level stored in the creature with the position?

Yes, you're right. But it shoudn't be a reference to the level directly,
rather kind of position too.

>> Everything and anything that changes in the dungeon during the game
>> is recorded somewhere in the <dungeon> object. Any change with it's
>> scope larger than thesingle object performing the change has to be
>> done using one of the <do_*> methods of the <dungeon>.
> This is like my effector class. Are messages to the player handled
> this way?

Most of the player interaction is done by the actors, especially the
actor controlling the PC creature. It's already responsible for displaying
the map and teh stats, prompting for input, displaying all the menus
and stuff. It already displays all "you can't do it" and "are you sure"
messages. Logically, it should also display all the other messages (so
that the AIs and the player have "equal chances" ;)  ).

But this approach would probably make the <creature> class very fat with
all the state variables needed to record important information, or would
make the <actor> actively search the <dungeon> for the traces of events.

That's not nice for the ones who will have to implement the actors...

I'd say that the <dungeon> can generate all the messages that doesn't
depend on the <actor's> perception -- things like "you're bleeding",
"you're poisoned", "you enter a maze of staircases", etc.


>> You can split this part using <action_kind> objects and having only
>> do_action and can_action methods, but let's keep things simple for
>> the start.
>
> How about splitting them up into objects for <can> and objects for
><do>? Doing something will always be pretty much the same, but the
> abilities of a creature might change more easily. It could be helpful
> to be able to change the implementation of the <can_*> methods
> separately from <do_*> methods. Plus, wouldn't <can_*> methods be
> more likely to want to share helper functions with each other than
> with a <do_*> method?

I mean something like, you know, you want to go to certain position,
so you do:

action := new walk_action(creature, position)
if dungeon.possible(action) then
dungeon.perform(action)

Where <possible> and <perform> are more friendly names for <can_action>
and <do_action>. The action objects could be then stored in the creatures
and used to generate messages, as well as in the timeline, to make delayed
actions or actions that take time.

It might be better to have action.possible(dungeon) and
action.perform(dungeon) though...

>> In the main game loop, after creating the <dungeon>, an <actor> is
>> taken from the <timeline> and it's <act> method is called. The
>> method checks the <dungeon>, especially the <creature> to which the
>> <actor> is connected, and decides on the action to perform, using
>> the <can_*> methods of <dungeon>. Then it calls one (or multiple)
>> <do_*> methods to actually perform the action, and puts itself back
>> into the <timeline>.
>
> The timing is what concerns me most as the greatest weakness of my
> own design. I know that there are all kinds of complex timing
> systems. Can you modify your game to use any of them just by
> modifying your Timeline implementation?

Of course not! I doubt there's a way to do it in an absolutley flexible
way, and even if there is, it's probably very complicated.

The <timeline> is just as it's called, a timeline, a scheudle. All it does
is keeping track of the order of events. You can have trouble implementing
various timing tricks that make events happen before they happen, etc. --
some timing systems, like the energy-based ones, have these. But this
system is pretty flexible as long as you know when your next turn should
happen.

There's a large problem with interrupted actions. To implement a long,
interruptible action, you typically split it into two phases -- the
preparation phase makes you wait some time, but does nothing else, and
the final phase is short, but performs the actual action.

Now, when you enter the preparation phase, you'd like to be informed about
things that happen around you, so that you can decide to abandon the
preparation pahse and get your turn moved to the front of the time line, so
that you can react immediately.

I'd do it by introducing an <interrupt> method in the actors, that would
return true if the <actor> decides the event was important the action
should be interrupted. But since the <dungeon> knows nothing about which
actor is responsible for which creature, the thing gets complicated.

Maybe you could introduce a separate list of <watchers> in the <dungeon>,
where <actors> that expect to be interrupted could register themselves, so
that they are informed about all the events?

>> The only way the <actors> know about the actions performed by other
>> <actors> (like the fact that a monster attacked it's creature) is
>> by examining the internal state of the <creatures> and other
>> <dungeon> elements. The <creatures> can, for example, record the
>> last action performed.
>
> I see that is enforced by the fact that a creature has no idea who
> it's actor is. I was planning on having the AI implemented by
> subclassing an Actor implementation, where the highest Actor would
> hold all the stuff that the creature holds in your design and
> subclasses would override the act() method. Your design is better
> because changing AI implementations for a character is as simple as
> inserting a different Actor for your creature at the end of the act()
> method instead of 'this'.
>
> But why not provide some kind of interface by which a creature can
> inform its actor of important events? I think especially it would be
> good to be able to change the AI implementation upon being attacked.
> It would be very intuitive to have a method called onAttacked() where
> you can do stuff.

Of course you can have such an unterface. The creature can record those
events in it's internat state, so that any actor that cares about them can
read them decide what to do. Note that you can make the events independant
of their order easily this way.

> Clearly it is good to have separate concepts and class for creatures
> and actors, but it's a pretty subtle difference, isn't it? That's why
> I would hide them within a single class from the point of view of the
> vast majority of my code. I'd make the Creature hold an Actor, then
> have the creature call event methods on the actor, especially act().
> The Creature could hold all of the properties that the Actor might
> need in a single object that can be passed easily into methods of the
> Actor. Most importantly, there would be no way to access the Actor
> from outside of Creature. Special creatures, such as the PC, might
> not even have an Actor and know one would know the difference.
>
> You could still force the Actor to check the Creature for events, but
> would be in a better position to change your mind later.

The problem is -- there can be more than one actor for a creature, and
there can be more than one creature for an actor. For example, if you're
poisoned, you can have a separate actor representing the poison, that
would scheuldle in the timeline and regularily apply damage to it's
creature, as long as the creture has the 'poisoned' flag.
A creature can be moved or it's state changed by any actor, as long as the
world rules allow for this.
With a slight modification you could even have multi-tile monsters or
hive-mind monsters share an actor - altrough it would make them act all
on the same time, which is strange.

Inactive creatures (on other levels tha the PC or, like in rogue, the ones
that the player didn't attack yet) can have no actor at all.

--
Radomir `The Sheep' Dopieralski @**@_
(==) 3 Yawn?
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 25, 2005 5:28:54 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
news:slrndjagal.3ao.thesheep@atos.wmid.amu.edu.pl:
[snip]
> I mean something like, you know, you want to go to certain
> position, so you do:
>
> action := new walk_action(creature, position)
> if dungeon.possible(action) then
> dungeon.perform(action)
>
> Where <possible> and <perform> are more friendly names for
> <can_action> and <do_action>. The action objects could be then
> stored in the creatures and used to generate messages, as well as
> in the timeline, to make delayed actions or actions that take time.
>
> It might be better to have action.possible(dungeon) and
> action.perform(dungeon) though...

I see what you mean now! This is a very interesting design but it
seems to be locking you into one exact implementation for
walk_action.perform(). Since you are constructing walk_action
yourself, you are fixing it's type.

When you call can_walk and do_walk from a Level class, you always
have the possiblity that this might actually be a subclass of Level,
or that Level had some settings adjusted before it was given to you
that changed how can_walk and do_walk work.

Doing it this way is making it harder to vary the implementation of
those methods from outside of this actor. Instead of having the actor
create walk_action itself, you could have a getWalkAction() method in
Level, which at least reduces the number of methods as compared to
the original design with one method for walking instead of two.

> At Sat, 24 Sep 2005 09:37:02 GMT,
> Brendan Guild wrote:
>> The timing is what concerns me most as the greatest weakness of my
>> own design. I know that there are all kinds of complex timing
>> systems. Can you modify your game to use any of them just by
>> modifying your Timeline implementation?
>
> Of course not! I doubt there's a way to do it in an absolutley
> flexible way, and even if there is, it's probably very complicated.
>
> The <timeline> is just as it's called, a timeline, a scheudle. All
> it does is keeping track of the order of events. You can have
> trouble implementing various timing tricks that make events happen
> before they happen, etc. -- some timing systems, like the energy-
> based ones, have these. But this system is pretty flexible as long
> as you know when your next turn should happen.

I can think of two solutions for that problem. We need a value to
represent speed and modify the given time to next action, not because
we actually want to use that in our games, but because we might want
to use that in later versions of our games and we do not want to have
to do a full rewrite if that happens.

We can either have a speed() method in Actor and expect Timeline to
poll it as often as needed, or we can have a setSpeed(Actor,speed)
method in Timeline.

The first one allows us to code the Actor without needing to know
when the speed changes, all we need is to be able to calculate the
speed at any moment, which is nice.

The second one is more efficient because then Timeline can forget
about an Actor until something interesting happens, like changing
speed or coming to the head of the queue.

I recommend providing an interface for both. We can have a
registerVariableSpeed(Actor) method that adds an actor to a list in
the Timeline of actors who should be polled for speed. Other actors
will have to call setSpeed(Actor,speed) to change speed. Now we are
free to implement it in either way from actor to actor, or not
implement speed at all. We don't even need to implement it in the
Timeline if we aren't going to be using, but we've set ourselves up
for making it easily doable if we change our minds.

> There's a large problem with interrupted actions. To implement a
> long, interruptible action, you typically split it into two phases
> -- the preparation phase makes you wait some time, but does nothing
> else, and the final phase is short, but performs the actual action.
>
> Now, when you enter the preparation phase, you'd like to be
> informed about things that happen around you, so that you can
> decide to abandon the preparation pahse and get your turn moved to
> the front of the time line, so that you can react immediately.
>
> I'd do it by introducing an <interrupt> method in the actors, that
> would return true if the <actor> decides the event was important
> the action should be interrupted. But since the <dungeon> knows
> nothing about which actor is responsible for which creature, the
> thing gets complicated.
>
> Maybe you could introduce a separate list of <watchers> in the
> <dungeon>, where <actors> that expect to be interrupted could
> register themselves, so that they are informed about all the
> events?

Wouldn't it be better to register the actors on the creatures? That
way they would only get messages that relate to the creature they
care about.

>> But why not provide some kind of interface by which a creature can
>> inform its actor of important events? I think especially it would
>> be good to be able to change the AI implementation upon being
>> attacked. It would be very intuitive to have a method called
>> onAttacked() where you can do stuff.
>
> Of course you can have such an unterface. The creature can record
> those events in it's internat state, so that any actor that cares
> about them can read them decide what to do. Note that you can make
> the events independant of their order easily this way.

I was actually referring to an onAttacked() method on the Actor, so
that it could effect the AI. Does order independence mean that the
messages would always be displayed in the same order?

[snip my idea about storing the actor in the creature]
> The problem is -- there can be more than one actor for a creature,
> and there can be more than one creature for an actor. For example,
> if you're poisoned, you can have a separate actor representing the
> poison, that would scheuldle in the timeline and regularily apply
> damage to it's creature, as long as the creture has the 'poisoned'
> flag. A creature can be moved or it's state changed by any actor,
> as long as the world rules allow for this.

That makes sense, but none of the actors in your plan actually
'watch' the creatures, so they are essentially just act() methods on
a rotation. You could define an interface for act() methods that
would allow Creatures to be put into the Timeline as well as other
actors for poison, etc. The poison actor would work exactly like you
would write it in your design. When the creature comes around, then
it's the creature's turn to act, which you must admit is applying
appropriate specialness to a more special event.

> With a slight modification you could even have multi-tile monsters
> or hive-mind monsters share an actor - altrough it would make them
> act all on the same time, which is strange.

That's a very good point and a good idea, too. I doubt the player
would notice that they are acting simultaneously. Still, there is
nothing that prevents creatures from sharing an actor in my idea,
they just need to be constructed in the same bit of code that assigns
them all the same actor. I'll just have to be sure that something
that uniquely identifies the creature is passed into the Actor's
methods to allow it.
Anonymous
September 25, 2005 1:48:51 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Sun, 25 Sep 2005 01:28:54 GMT,
Brendan Guild wrote:

> When you call can_walk and do_walk from a Level class, you always
> have the possiblity that this might actually be a subclass of Level,
> or that Level had some settings adjusted before it was given to you
> that changed how can_walk and do_walk work.

You can have the <act> method return an <action> object, instead of
performing the action himself. Then you can do with the returned <action>
object whatever you want, including modyfying any settings or even
re-creating it into another object...

> Doing it this way is making it harder to vary the implementation of
> those methods from outside of this actor. Instead of having the actor
> create walk_action itself, you could have a getWalkAction() method in
> Level, which at least reduces the number of methods as compared to
> the original design with one method for walking instead of two.

If you had the <get_*_action> methods in the creature, you'd get something
very similar to your <effector> class :) 

>> The <timeline> is just as it's called, a timeline, a scheudle. All
>> it does is keeping track of the order of events. You can have
>> trouble implementing various timing tricks that make events happen
>> before they happen, etc. -- some timing systems, like the energy-
>> based ones, have these. But this system is pretty flexible as long
>> as you know when your next turn should happen.
>
> I can think of two solutions for that problem. We need a value to
> represent speed and modify the given time to next action, not because
> we actually want to use that in our games, but because we might want
> to use that in later versions of our games and we do not want to have
> to do a full rewrite if that happens.
>
> We can either have a speed() method in Actor and expect Timeline to
> poll it as often as needed, or we can have a setSpeed(Actor,speed)
> method in Timeline.
>
> The first one allows us to code the Actor without needing to know
> when the speed changes, all we need is to be able to calculate the
> speed at any moment, which is nice.
>
> The second one is more efficient because then Timeline can forget
> about an Actor until something interesting happens, like changing
> speed or coming to the head of the queue.
>
> I recommend providing an interface for both. We can have a
> registerVariableSpeed(Actor) method that adds an actor to a list in
> the Timeline of actors who should be polled for speed. Other actors
> will have to call setSpeed(Actor,speed) to change speed. Now we are
> free to implement it in either way from actor to actor, or not
> implement speed at all. We don't even need to implement it in the
> Timeline if we aren't going to be using, but we've set ourselves up
> for making it easily doable if we change our minds.

Changing speed isn't that bad, and can be handled by the long-action
code -- just call the actor's <interrupt> method and allow him to
reschedule his next action. You could make your special <set_speed>
method for the actor, so that you don't have to check the reason
for interruption in <interrupt>.

>> There's a large problem with interrupted actions. To implement a
>> long, interruptible action, you typically split it into two phases
>> -- the preparation phase makes you wait some time, but does nothing
>> else, and the final phase is short, but performs the actual action.
>>
>> Now, when you enter the preparation phase, you'd like to be
>> informed about things that happen around you, so that you can
>> decide to abandon the preparation pahse and get your turn moved to
>> the front of the time line, so that you can react immediately.
>>
>> I'd do it by introducing an <interrupt> method in the actors, that
>> would return true if the <actor> decides the event was important
>> the action should be interrupted. But since the <dungeon> knows
>> nothing about which actor is responsible for which creature, the
>> thing gets complicated.
>>
>> Maybe you could introduce a separate list of <watchers> in the
>> <dungeon>, where <actors> that expect to be interrupted could
>> register themselves, so that they are informed about all the
>> events?

> Wouldn't it be better to register the actors on the creatures? That
> way they would only get messages that relate to the creature they
> care about.

Well, the best thing that comes to my mind is the C#'s delegates.
The <creature> could then just hold a bunch of <interrupt> delegate
methods from <actors>.

>>> But why not provide some kind of interface by which a creature can
>>> inform its actor of important events? I think especially it would
>>> be good to be able to change the AI implementation upon being
>>> attacked. It would be very intuitive to have a method called
>>> onAttacked() where you can do stuff.
>>
>> Of course you can have such an unterface. The creature can record
>> those events in it's internat state, so that any actor that cares
>> about them can read them decide what to do. Note that you can make
>> the events independant of their order easily this way.
>
> I was actually referring to an onAttacked() method on the Actor, so
> that it could effect the AI.

It's the same. Whether you mark in the creature that it was attacked,
so that the <actor> can do something in its next turn, or whether
you change the <actor> state itself, so that it can do something when
it's its next turn...
The only moment you really need to call the <actor> directly is when
it must reschedule it's next turn.

> Does order independence mean that the
> messages would always be displayed in the same order?

Not necessarily, but you can do that. You can record the order of events
in the creature. The key is that when it comes to processing those events
and deciding on the next turn, you already have a whole bunch of them --
you don't have to process one at a time, but instead include rules like,
well "if attacked by more than 3 opponents -- explode".

> [snip my idea about storing the actor in the creature]
>> The problem is -- there can be more than one actor for a creature,
>> and there can be more than one creature for an actor. For example,
>> if you're poisoned, you can have a separate actor representing the
>> poison, that would scheuldle in the timeline and regularily apply
>> damage to it's creature, as long as the creture has the 'poisoned'
>> flag. A creature can be moved or it's state changed by any actor,
>> as long as the world rules allow for this.
>
> That makes sense, but none of the actors in your plan actually
> 'watch' the creatures, so they are essentially just act() methods on
> a rotation. You could define an interface for act() methods that
> would allow Creatures to be put into the Timeline as well as other
> actors for poison, etc. The poison actor would work exactly like you
> would write it in your design. When the creature comes around, then
> it's the creature's turn to act, which you must admit is applying
> appropriate specialness to a more special event.

You mean to make the <creature> a subclass of <actor>?
It somehow breaks my nifty top-down design ;) 

Actor ------------.
Dungeon |
Timeline -'
Level
Map
Item
Creature

Ok, it's already a little broken by including the <timeline> in the
<dungeon>. But if the <actor> returns an <action> object with it's
duration, it can be rescheduled automatically based on it, so it doesn't
need access to <timeline> anymore... Hmmm...

Timeline
Actor
Dungeon
Level
Map
Item
Creature


>> With a slight modification you could even have multi-tile monsters
>> or hive-mind monsters share an actor - altrough it would make them
>> act all on the same time, which is strange.
>
> That's a very good point and a good idea, too. I doubt the player
> would notice that they are acting simultaneously. Still, there is
> nothing that prevents creatures from sharing an actor in my idea,
> they just need to be constructed in the same bit of code that assigns
> them all the same actor. I'll just have to be sure that something
> that uniquely identifies the creature is passed into the Actor's
> methods to allow it.

The actor would hold a list of his creatures. No need to identify them,
he's got all the references, which idetify in rather unique way.
Are you thinking about putting <creatures> on the <timeline>?

--
Radomir `The Sheep' Dopieralski @**@_
(--) 3 ..zzZZ
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 25, 2005 3:52:43 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndjcsk2.3tv.thesheep@atos.wmid.amu.edu.pl:

> At Sun, 25 Sep 2005 01:28:54 GMT,
> Brendan Guild wrote:
>
>> When you call can_walk and do_walk from a Level class, you always
>> have the possiblity that this might actually be a subclass of
>> Level, or that Level had some settings adjusted before it was
>> given to you that changed how can_walk and do_walk work.
>
> You can have the <act> method return an <action> object, instead of
> performing the action himself. Then you can do with the returned
> <action> object whatever you want, including modyfying any settings
> or even re-creating it into another object...

Very true. In fact, it doesn't really matter where the action is
performed so long as it is not performed 'directly' by the AI.

The AI is complex and likely spread across several classes for
varying behaviours in monsters, so it is precious and should be
heavily insulated from the rest of the game. It should never do
anything to the data structures of the level or creatures in a way
that can be traced staticly. In other words, for every method that it
calls, we should have no idea how that method works or where the code
is, we'll just trust that it will 'do the right thing' and worry
about what the right thing is somewhere else.

>> Radomir 'The Sheep' Dopieralski wrote:
>>> Maybe you could introduce a separate list of <watchers> in the
>>> <dungeon>, where <actors> that expect to be interrupted could
>>> register themselves, so that they are informed about all the
>>> events?
>>
>> Wouldn't it be better to register the actors on the creatures?
>> That way they would only get messages that relate to the creature
>> they care about.
>
> Well, the best thing that comes to my mind is the C#'s delegates.
> The <creature> could then just hold a bunch of <interrupt> delegate
> methods from <actors>.

That's the usual Observer pattern. All you need to do is have your
actors subclass an interface with whatever you want the <creature> to
delegate, then give the actor to the creature using only that
interface. It's effectively just like C# delegates. For example:

class Interruptible { interrupt(); };
class Actor : public Interruptible
{
implement interrupt() somehow;
A bunch of other stuff that Creature will never know about;
};
class Creature { youCanInterruptThis(Interruptible); };

Then call creature.youCanInterruptThis(actor) for all the actors that
would want to be interrupted for stuff that happened to the creature.
A delegate is really not much more than a class with one method like
Interruptible.

>> I was actually referring to an onAttacked() method on the Actor,
>> so that it could effect the AI.
>
> It's the same. Whether you mark in the creature that it was
> attacked, so that the <actor> can do something in its next turn, or
> whether you change the <actor> state itself, so that it can do
> something when it's its next turn...
> The only moment you really need to call the <actor> directly is
> when it must reschedule it's next turn.

Yes, you are right; it's not an important difference. But it seems
more intuitive to call the actor directly when something that might
interest it happens, then let it record that if it wants to. I'm not
eager to code the creature to record everything that happens just so
that the actor might use some of that record. It seems like that is
putting a needlessly complicated data structure into creature.

>> Does order independence mean that the
>> messages would always be displayed in the same order?
>
> Not necessarily, but you can do that. You can record the order of
> events in the creature. The key is that when it comes to processing
> those events and deciding on the next turn, you already have a
> whole bunch of them -- you don't have to process one at a time, but
> instead include rules like, well "if attacked by more than 3
> opponents -- explode".

Rules like that seem a little unfair, don't you think? It should
depend on how powerful the attackers are and on how close together
the attacks were. If we are summing the strength of the attackers
then it's no harder to sum them one-at-a-time, than it is to sum the
strengths from a list.

If the actor is performing a long action, it will be a lot easier for
3 attacks to come in than during a short action. The length of the
action your character is taking shouldn't affect the results of the
other characters attacks on your character. Suppose you were
defending. Defending should take a rather large amount of time; the
goal is to buy yourself time to rest while your attackers waste their
energy. It would be odd to make that the move that makes you most
vulnerable.

The point is that the time that an action takes shouldn't mean an
increase in vulnerability, so we should just take attacks as they
come and not think about things as accumulating between turns.

[snip discussion on actors with multiple creatures and various things
which I will respond to when I am less tired.]

> The actor would hold a list of his creatures. No need to identify
> them, he's got all the references, which idetify in rather unique
> way. Are you thinking about putting <creatures> on the <timeline>?

Yes, exactly. Of course, I wouldn't let <timeline> know what a
creature is, but I would provide <creature> with an suitable
interface so that it can be put into <timeline> and <timeline> would
treat a creature just like any of the actors that it manages.

I was thinking that since I was going to have creature hold a
reference to it's actor, then it would be messy to also have the
actor hold a reference to it's creatures. Really, an actual reference
shouldn't be needed by <actor>. Does the actor really need the
precise identity of the creature to do it's job? It should be
satisfied by examining the properties of the creature and making a
decision based on those.
Anonymous
September 25, 2005 4:14:40 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Sun, 25 Sep 2005 11:52:43 GMT,
Brendan Guild wrote:

>> The actor would hold a list of his creatures. No need to identify
>> them, he's got all the references, which idetify in rather unique
>> way. Are you thinking about putting <creatures> on the <timeline>?
>
> Yes, exactly. Of course, I wouldn't let <timeline> know what a
> creature is, but I would provide <creature> with an suitable
> interface so that it can be put into <timeline> and <timeline> would
> treat a creature just like any of the actors that it manages.

Funny. I just remembered why I separated the <actor> and the <creature>
classes in the first place, long time ago when I first encountered
this kind of design. You see, I mainly program in C, and it's one of
the most popular methods to implement inheritance... ;) 

> I was thinking that since I was going to have creature hold a
> reference to it's actor, then it would be messy to also have the
> actor hold a reference to it's creatures. Really, an actual reference
> shouldn't be needed by <actor>. Does the actor really need the
> precise identity of the creature to do it's job? It should be
> satisfied by examining the properties of the creature and making a
> decision based on those.

Well,it needs the creature's stats, it's latest history and it's
surroundings -- and that's what the <creature> is, apart from it's
representational elements, like the name and looks.

I guess I don't understand what you mean by "precise identity".

On the other hand, the creature doesn't need to know it's <actor>
as long as the commands are "pushed". It needs a list of sources of
commands when it comes to "pulling", though.

Are you suggesting to make the creature "pull" all the commands?
Pyt the creatures on the <timeline> and make the <act> method of
<actor> be called by the <creature>? What with multiple actors that
have differing timings? (Poison can work in very small steps, much
faster than the creature's turns).

--
Radomir `The Sheep' Dopieralski @**@_
(: ) 3 Snap!
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 25, 2005 8:04:08 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
news:slrndjd55f.81f.thesheep@atos.wmid.amu.edu.pl:

> At Sun, 25 Sep 2005 11:52:43 GMT,
> Brendan Guild wrote:
>
>> I was thinking that since I was going to have creature hold a
>> reference to it's actor, then it would be messy to also have the
>> actor hold a reference to it's creatures. Really, an actual
>> reference shouldn't be needed by <actor>. Does the actor really
>> need the precise identity of the creature to do it's job? It
>> should be satisfied by examining the properties of the creature
>> and making a decision based on those.
>
> Well,it needs the creature's stats, it's latest history and it's
> surroundings -- and that's what the <creature> is, apart from it's
> representational elements, like the name and looks.
>
> I guess I don't understand what you mean by "precise identity".

I really just mean the memory address of the creature. That's not
important to the actor. There could be two creatures with the same
name, stats, etc. but different locations and the actor would behave
as if they were the same because it couldn't know the difference, and
that might even be a good thing.

Plus, I'm wondering why do we even store the latest history in a
creature? Doesn't that go against the concept that it is just a piece
to be played with? It really shouldn't have such a complex state.

> On the other hand, the creature doesn't need to know it's <actor>
> as long as the commands are "pushed". It needs a list of sources of
> commands when it comes to "pulling", though.
>
> Are you suggesting to make the creature "pull" all the commands?
> Pyt the creatures on the <timeline> and make the <act> method of
> <actor> be called by the <creature>? What with multiple actors that
> have differing timings? (Poison can work in very small steps, much
> faster than the creature's turns).

Yes, that's what I'm suggesting. I like to think of it as the
creature passing the event of it being this creature's turn to act to
it's actor, just like it would pass all other important events. But
we're probably not going to want a creature to have more than one
actor at one time.

Just because we are putting an actor inside each creature, doesn't
mean that we can't do poison and other effects just as in your
design. Poison should be put directly onto the timeline as it's own
actor still; it doesn't need to get events from the creature, right?
We can use an attribute of the creature to indicate that the poison
has been cured and the poison can stop itself the next time it comes
up.

I like to think of the actor inside the creature as the creature's
mind, guiding it's body. We'll want to be able to switch that actor
during the game to change behaviour, maybe even put in the UI actor
to give the player control of that creature. It's a benefit to not
letting the actor hold a reference to it's creature that the actor
becomes interchangeable more easily
Anonymous
September 25, 2005 10:11:36 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndjcsk2.3tv.thesheep@atos.wmid.amu.edu.pl:

> At Sun, 25 Sep 2005 01:28:54 GMT,
> Brendan Guild wrote:
>> You could define an interface for act() methods that would allow
>> Creatures to be put into the Timeline as well as other actors for
>> poison, etc. The poison actor would work exactly like you would
>> write it in your design. When the creature comes around, then it's
>> the creature's turn to act, which you must admit is applying
>> appropriate specialness to a more special event.
>
> You mean to make the <creature> a subclass of <actor>?
> It somehow breaks my nifty top-down design ;) 
>
> Actor ------------.
> Dungeon |
> Timeline -'
> Level
> Map
> Item
> Creature
>
> Ok, it's already a little broken by including the <timeline> in the
> <dungeon>. But if the <actor> returns an <action> object with it's
> duration, it can be rescheduled automatically based on it, so it
> doesn't need access to <timeline> anymore... Hmmm...
>
> Timeline
> Actor
> Dungeon
> Level
> Map
> Item
> Creature

Now that I look at it this way, it does seem like an elegant design!
It's like a layered approach that is used in the OSI!

http://en.wikipedia.org/wiki/OSI_reference_model

Each layer calls methods only of the layer below to fullfil it's
obligations to the layer above, allowing an ultimate security against
total rewrite.

To be a true layer design, we need to clearly define a simple
interface for each layer and never ever reach beyond it in our code.
Each layer interface doesn't necessarily need to be a single object,
the only real rule is that if we have layers A -> B -> C, then
nothing in the code of A calls methods of C, it must all go through
B.

So, we can use the following layers:

Layer 4 - Timeline - The main loop of the game, responsible for
determining who goes when, like sitting around a table and going in
clockwise order.

Layer 3 - Actors - The brains of the game, responsible for deciding
what should be done and providing timing information for Timeline to
examine, such as speed and the duration of each action.

Layer 2 - Dungeon - The body of the game, responsible for
representing the imagined physical reality of the game, the spatial
relationship between creatures, the map.

Layer 1 - Creatures - The guts of the game, responsible for
representing items, the stats of the creatures, the interactions
between creatures, especially fighting and plot.

The benefit of organizing things in a manner similar to this is that
we can first define the layers, then discuss the interface for each
layer individually. For example, the above layers divides the complex
problem of creating a roguelike into 4, each one much easier than the
whole. We could discuss classes on Layer N and while we might still
become confused, we would always know approximately what we are
talking about, because we know the responsibilities of Layer N.

An interesting side-effect of this design is that what we are
currently dividing into two parts: Actors and Creatures, would have
to be divided into 3, such as:

Actor (for Layer 3) the AI
Mob (for Layer 2) part of representing the dungeon, they would hold
the coordinate position of the creature.
Creature (for Layer 1) for stats, fighting, etc, independent of
decision or location.

Each one holding a reference to the one below and calling methods on
that one only.

Layer 4 doesn't actually have an interface; there is no higher layer
to call methods of Layer 4, so it is probably just main() and
helpers.

The UI would unfortunately have to exist outside of these layers, I
think. Layer 4 would create UI objects and pass them to methods of
Layer 3, thereby controlling how and when Layer 3 gets to display
itself. Layer 3 would use the UI objects it was given to create new
UI objects for Layer 2 and pass them down, until finally the
creatures are allowed to display themselves, working only through all
the other layers.
Anonymous
September 25, 2005 10:16:37 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Sun, 25 Sep 2005 16:04:08 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
> news:slrndjd55f.81f.thesheep@atos.wmid.amu.edu.pl:

> Plus, I'm wondering why do we even store the latest history in a
> creature? Doesn't that go against the concept that it is just a piece
> to be played with? It really shouldn't have such a complex state.

Do you know any other place that's better to store it? You'll usually
want to access it on "by creature" basis, so it'd have to be indexed
by creature anyways -- string it directly in <creature> seems the
simplest approach, just as storing items and creatures in the <square>
(and might be, in fact, equally misleading ;)  ).

Another option I coud think of is to store the history in the level,
indexed somehow by location (it's most clean when you've got room-based
levels with auto-closing doors -- you'd just store the events indexed
by rooms, because any event can only affect creatures in the same room).

>> On the other hand, the creature doesn't need to know it's <actor>
>> as long as the commands are "pushed". It needs a list of sources of
>> commands when it comes to "pulling", though.
>>
>> Are you suggesting to make the creature "pull" all the commands?
>> Pyt the creatures on the <timeline> and make the <act> method of
>> <actor> be called by the <creature>? What with multiple actors that
>> have differing timings? (Poison can work in very small steps, much
>> faster than the creature's turns).
>
> Yes, that's what I'm suggesting. I like to think of it as the
> creature passing the event of it being this creature's turn to act to
> it's actor, just like it would pass all other important events. But
> we're probably not going to want a creature to have more than one
> actor at one time.

Then indeed you can safely merge the <creature> and the <actor>.
But somehow I don't like it. I can't really say why -- just a whisper
in my Ghost ;) .

> Just because we are putting an actor inside each creature, doesn't
> mean that we can't do poison and other effects just as in your
> design. Poison should be put directly onto the timeline as it's own
> actor still; it doesn't need to get events from the creature, right?

On the contrary -- it has to react to all kinds of "cure poison" events,
as well as any subsequent "poison" ones -- we don't want to create
a separate actor for every snake's bite.

Also, the actor itself is supposed to change its speed and reschedule
itself on the timeline when there's any kind of "slow poison" or
"haste poison" event...

Anyways, the "poison actor" is just an example. You get similar behavior
with monster pushing past each other and swapping positions, monsters
using each other as weapons or missiles, and all kinds of "automatic"
actions that doesn't use up the creature's turn.

> We can use an attribute of the creature to indicate that the poison
> has been cured and the poison can stop itself the next time it comes
> up.

I think you're separating similar objects just to merge them with
distinct ones. If the "poison actor" can read those things from the
creature's state, why can't any other actor, includiong the "creature's
mind" do it this way, and thus needs some <on_attack> and similar methods?

On the other hand, if the "creature's mind" actor has those methods, why
can't the "poison actor" have <on_cure_poison> method?

> I like to think of the actor inside the creature as the creature's
> mind, guiding it's body. We'll want to be able to switch that actor
> during the game to change behaviour, maybe even put in the UI actor
> to give the player control of that creature. It's a benefit to not
> letting the actor hold a reference to it's creature that the actor
> becomes interchangeable more easily

I'd strongly discourage this way of changing behavior. Sure, it's good
for things like "possesing" (altrough I'd introduce a helper actor here,
that calls the original UI actor for actions, but also takes care of
spell expiration and similar things by itself), but using it for changing
behavior from "wandering" to "aggressive" is IMHO an overkill.

You'd quickly find yourself adding to the creatures variables or even
a stack, indicating what actors it was controlled by before, and you
quickly develop a <meta-actor> class to switch the actors.

I think that the <actor> should be a clearly implemented state machine,
using lots of helper functions, like "run_away" or "charge" where
appropriate.

Maybe it shoudn't even be stored as code, but as a transition table
instead? :)  But then you'd need a clean definition of it's input, which
is rather differentfor different kinds of creatures. :( 

--
Radomir `The Sheep' Dopieralski @**@_
(nn) 3 Grin
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 25, 2005 10:42:23 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Sun, 25 Sep 2005 18:11:36 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski wrote in
> news:slrndjcsk2.3tv.thesheep@atos.wmid.amu.edu.pl:
>
>> Timeline
>> Actor
>> Dungeon
>> Level
>> Map
>> Item
>> Creature
>
> Now that I look at it this way, it does seem like an elegant design!
> It's like a layered approach that is used in the OSI!
Yes, something like that.
> http://en.wikipedia.org/wiki/OSI_reference_model
I'm a network administrator, I know the OSI model ;) 

> To be a true layer design, we need to clearly define a simple
> interface for each layer and never ever reach beyond it in our code.
> Each layer interface doesn't necessarily need to be a single object,
> the only real rule is that if we have layers A -> B -> C, then
> nothing in the code of A calls methods of C, it must all go through
> B.
I'm not sure whether the "perfectly clean" design is worth the efficiency
drawbacks and general code complication it sometimes introduces.
As always, you need to find the "aurea mediocritas".


> An interesting side-effect of this design is that what we are
> currently dividing into two parts: Actors and Creatures, would have
> to be divided into 3, such as:
>
> Actor (for Layer 3) the AI
> Mob (for Layer 2) part of representing the dungeon, they would hold
> the coordinate position of the creature.
> Creature (for Layer 1) for stats, fighting, etc, independent of
> decision or location.

Good idea, only I'd call the Creature an Entity, as it also includes
items and other non-living objects.

It also goes well with my idea of <items> (having their looks, size,
weight, etc.) be only container for their <usages> (having their
stats, like AC or ToHit). You'd equip <usages>, not items -- so you
can wear a towel on your head or as your cloak, but also you can
equip your dagger both as your main weapon and your tin opener, at the
same time. Or have your lantern be your light source but also the
default missile.

> Layer 4 doesn't actually have an interface; there is no higher layer
> to call methods of Layer 4, so it is probably just main() and
> helpers.

In fact it has. There's the Layer 5, which handles things like character
generation, saving and loading game, etc.

Note how you can't avoid some "two step" communication in the real,
not idealized implementation. For example, you will usually "freeze"
all the monsters on levels other than current, for efficiency and
simplicity.
But then the Layer 4 (timeline) has to react to Level 2 (dungeon)
event -- in particular, it has to reload it's actor list when one
specific creature, namely the PC, changes level.

> The UI would unfortunately have to exist outside of these layers, I
> think. Layer 4 would create UI objects and pass them to methods of
> Layer 3, thereby controlling how and when Layer 3 gets to display
> itself. Layer 3 would use the UI objects it was given to create new
> UI objects for Layer 2 and pass them down, until finally the
> creatures are allowed to display themselves, working only through all
> the other layers.

I'd keep the UI contained in the PC actor as much as possible -- all
other objects could return their desired representation to it.

--
Radomir `The Sheep' Dopieralski @**@_
(Xx) 3 ...
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 25, 2005 11:33:00 PM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndjdqc5.fhh.thesheep@atos.wmid.amu.edu.pl:

> At Sun, 25 Sep 2005 16:04:08 GMT,
> Brendan Guild wrote:
>> Plus, I'm wondering why do we even store the latest history in a
>> creature? Doesn't that go against the concept that it is just a
>> piece to be played with? It really shouldn't have such a complex
>> state.
>
> Do you know any other place that's better to store it? You'll usually
> want to access it on "by creature" basis, so it'd have to be indexed
> by creature anyways -- string it directly in <creature> seems the
> simplest approach, just as storing items and creatures in the
> <square> (and might be, in fact, equally misleading ;)  ).

I would prefer not to store it at all! And I think we can do that by
having the creature inform the actor immediately. The actor will be
able to determine the exact significance of each event and modify it's
own state accordingly, then throw away the event forever.

If anything does actually need to be stored, then the actor is the
perfect place to do it, because the actor knows exactly what is
important to store and would store exactly that, while all others would
have to store everything just to be sure not to throw something
important away.

>> Just because we are putting an actor inside each creature, doesn't
>> mean that we can't do poison and other effects just as in your
>> design. Poison should be put directly onto the timeline as it's own
>> actor still; it doesn't need to get events from the creature, right?
>
> On the contrary -- it has to react to all kinds of "cure poison"
> events, as well as any subsequent "poison" ones -- we don't want to
> create a separate actor for every snake's bite.
>
> Also, the actor itself is supposed to change its speed and reschedule
> itself on the timeline when there's any kind of "slow poison" or
> "haste poison" event...

I see that you are right! In fact, the actor and the creature should be
kept separate with the actor going through the timeline and essentially
just responding to events with in-game actions. The events will be The
Timer Event, indicating the actors turn to act, as well as all of the
various watcher events that each actor could register to receive from
characters, the dungeon, anywhere.

This doesn't prevent other things from putting themselves onto the
timeline, either. We could have a creature without an actor that puts
itself onto the Timeline and responds to it's own events. All it needs
is to subclass the right interface.

> Anyways, the "poison actor" is just an example. You get similar
> behavior with monster pushing past each other and swapping positions,
> monsters using each other as weapons or missiles, and all kinds of
> "automatic" actions that doesn't use up the creature's turn.

These other things don't seem to parallel the poison example very well.
They seem like one creature's actor taking control of another creature
for one turn.

>> I like to think of the actor inside the creature as the creature's
>> mind, guiding it's body. We'll want to be able to switch that actor
>> during the game to change behaviour, maybe even put in the UI actor
>> to give the player control of that creature. It's a benefit to not
>> letting the actor hold a reference to it's creature that the actor
>> becomes interchangeable more easily
>
> I'd strongly discourage this way of changing behavior. Sure, it's
> good for things like "possesing" (altrough I'd introduce a helper
> actor here, that calls the original UI actor for actions, but also
> takes care of spell expiration and similar things by itself), but
> using it for changing behavior from "wandering" to "aggressive" is
> IMHO an overkill.

Well, at least we will have that option, as long as actors are separate
from creatures. So if you change your mind, your design has you
covered.

> I think that the <actor> should be a clearly implemented state
> machine, using lots of helper functions, like "run_away" or "charge"
> where appropriate.

Changing between actors is like a state machine, where the actors each
represent states. Especially if an actor is responsible for putting
itself back into the Timeline each turn, it would be so easy to just
put a different actor there instead. Each turn would be like a state
transition.

But actually, I agree. I think that we should avoid sharing actors
between different types of creatures. They should all have their own
distinct flavor of behaviour, and breaking the actors up into things
like Wandering and Aggressive is just asking for them to be reused
again and again and it makes adding little quirks in monster behaviour
more difficult.
Anonymous
September 26, 2005 12:25:25 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndjdrsf.e3.thesheep@atos.wmid.amu.edu.pl:

> At Sun, 25 Sep 2005 18:11:36 GMT,
> Brendan Guild wrote:
>> To be a true layer design, we need to clearly define a simple
>> interface for each layer and never ever reach beyond it in our code.
>> Each layer interface doesn't necessarily need to be a single object,
>> the only real rule is that if we have layers A -> B -> C, then
>> nothing in the code of A calls methods of C, it must all go through
>> B.
> I'm not sure whether the "perfectly clean" design is worth the
> efficiency drawbacks and general code complication it sometimes
> introduces. As always, you need to find the "aurea mediocritas".

Let's not forget where most of the time goes in a roguelike. We could
think of it like an optimization problem: The efficiency drawbacks you
are talking about are at runtime, but the average roguelike spends way
more time in development than it does in play. If we can reduce the
number of rewrites by reducing the amount of coupling, we are saving
ourselves way more than some little runtime efficiency.

> It also goes well with my idea of <items> (having their looks, size,
> weight, etc.) be only container for their <usages> (having their
> stats, like AC or ToHit). You'd equip <usages>, not items -- so you
> can wear a towel on your head or as your cloak, but also you can
> equip your dagger both as your main weapon and your tin opener, at
> the same time. Or have your lantern be your light source but also the
> default missile.

What would the interfaces for <item> and <usage> look like?

Each item would have methods for getting usages of various types and
those usages would have various methods for all the things that could
be done with the item equipped in that way, including messages and code
to handle the action. Would the various usages even have a common
interface?

> Note how you can't avoid some "two step" communication in the real,
> not idealized implementation. For example, you will usually "freeze"
> all the monsters on levels other than current, for efficiency and
> simplicity.
> But then the Layer 4 (timeline) has to react to Level 2 (dungeon)
> event -- in particular, it has to reload it's actor list when one
> specific creature, namely the PC, changes level.

I'm not so sure. Perhaps we can't avoid calling methods in both
directions, up and down, but I wouldn't be surprised if we can avoid 2-
step communication in a practical implementation. At most it would
require adding more methods just to relay messages between distant
layers.

In this example, all we have to do is have the actor layer (3) inform
the timeline layer (4) about the change. The actor layer is the one
that directed the PC to go down the stairs, after all.

If we really wanted to avoid even this kind of backwards method
invocation, we could rely on the timeline layer to recognize that actor
layer has disowned the actors it used to be responding to and then the
timeline can repopulate it's list with the new actors.

> I'd keep the UI contained in the PC actor as much as possible -- all
> other objects could return their desired representation to it.

The UI is especially tricky. It seems to need access to everything, but
we can't allow that without seizing up our entire implementation into a
solid block that lives or dies with the UI.

So I think that above all, the UI needs to be designed extremely
carefully. Why do you keep the UI contained in the PC actor? Surely the
input is vital to the PC actor, but the output seems to be omnipresent
and important to all things equally.
Anonymous
September 26, 2005 12:38:16 AM

Archived from groups: rec.games.roguelike.development (More info?)

At Sun, 25 Sep 2005 19:33:00 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski wrote in
> news:slrndjdqc5.fhh.thesheep@atos.wmid.amu.edu.pl:
>
>> At Sun, 25 Sep 2005 16:04:08 GMT,
>> Brendan Guild wrote:

[ storing event history ]

> If anything does actually need to be stored, then the actor is the
> perfect place to do it, because the actor knows exactly what is
> important to store and would store exactly that, while all others would
> have to store everything just to be sure not to throw something
> important away.

Right. Good point.
Now, how we should do the informing -- use a bunch of methods and
interfaces for <on_attacked>, <on_talked_to>, <on_tickled>, etc.
or rather use <event> objects?

The second approach seems to have the advantage of possibility to
create your own, custom events not included in the interface.

But how to exchange them? Should there be a listener callback
passing all the <event> objects, or maybe there's some way to
filter them out?

[ separate actors and creatures ]

> This doesn't prevent other things from putting themselves onto the
> timeline, either. We could have a creature without an actor that puts
> itself onto the Timeline and responds to it's own events. All it needs
> is to subclass the right interface.

Well, then it's only a coincidence that the actor and the creature are
incidentally the same object. The engine still treats it as two distinct
objects, using two different interfaces.

>> Anyways, the "poison actor" is just an example. You get similar
>> behavior with monster pushing past each other and swapping positions,
>> monsters using each other as weapons or missiles, and all kinds of
>> "automatic" actions that doesn't use up the creature's turn.
>
> These other things don't seem to parallel the poison example very well.
> They seem like one creature's actor taking control of another creature
> for one turn.

Depends on your actual game mechanics --- I, for example, prefer to make
the "pushing" an additional action, so that the creature that is pushed
can still act in it's own turn.

>> I think that the <actor> should be a clearly implemented state
>> machine, using lots of helper functions, like "run_away" or "charge"
>> where appropriate.
>
> Changing between actors is like a state machine, where the actors each
> represent states. Especially if an actor is responsible for putting
> itself back into the Timeline each turn, it would be so easy to just
> put a different actor there instead. Each turn would be like a state
> transition.

Then you have basically the mathematical abstraction of the state machine,
with each state being just an element of a set, without any internal
properties (since, technically, a state with different internal properties
is just a different state). This might be sometimes convenient for proving
certain things about finite automata, but is certainly a PITA to program
and generally wrap your mind around it.

Normally you'd have a whole bunch of variables indicating your automaton's
state -- of course, from the mathematical point of view, they are all
describing a single state.

--
Radomir `The Sheep' Dopieralski @**@_
($s) 3 Ching!
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 26, 2005 1:07:05 AM

Archived from groups: rec.games.roguelike.development (More info?)

At Sun, 25 Sep 2005 20:25:25 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski wrote in
> news:slrndjdrsf.e3.thesheep@atos.wmid.amu.edu.pl:
>
>> It also goes well with my idea of <items> (having their looks, size,
>> weight, etc.) be only container for their <usages> (having their
>> stats, like AC or ToHit). You'd equip <usages>, not items -- so you
>> can wear a towel on your head or as your cloak, but also you can
>> equip your dagger both as your main weapon and your tin opener, at
>> the same time. Or have your lantern be your light source but also the
>> default missile.
>
> What would the interfaces for <item> and <usage> look like?
>
> Each item would have methods for getting usages of various types and
> those usages would have various methods for all the things that could
> be done with the item equipped in that way, including messages and code
> to handle the action. Would the various usages even have a common
> interface?

Every <usage> would be, well, a single usage (duh!) :) 
There are three basic methods needed:
equip(creature) -- called when the usage is put into an equipment slot
unequip(creature) -- called when the usage is removed
activate(...) -- called when the usage is... well... used

Of course a single usage can go only into a single kind of slot (some
usages can only be activated and can't be put into a slot), and it also
has a method to check whether it doesn't conflict with any other usage
already equipped (ie. gloves and rings, or the towel that can be worn
on head or as cloak, but not both at the same time).

Let's look at a simple mulit-use item, like a crossbow:

crossbow:
a) ranged weapon
b) improvised mace

First, you can activate the crossbow to shoot bolts from it (you need
the "ammo" usage of bolts equiped, or maybe you can be prompted to
choose the ammo). This can be disalowed if you want to force the player
to equip it to use (can be important considering sticky curses, etc.).

You can also wield the crossbow as your default ranged weapon. If the
crossbow isn't enchanted in any way, then this has no effect on the
creature, other than that when you press [f]ire, you're not prompted
what you want to use, but the crossbow is selected by default.
Of course, when you do press [f]ire, the crossbow's <activate> method
is called, with the ammo and the target, as well as the shooter as parameters.

You can wield the crossbow as your default melee weapon. This is a generic
usage, shared between many items, and it modifies your stats and causes
damage on activation, according to the size and weight of the actual
item containing it. Other items could have "improvised blade" or
"improvised missile" usages too.

The <item> would have it's physical attributes, it's "looks" and the
list of possible usages. One of the usages could be marked as "default"
if you like the generic se command.

>> I'd keep the UI contained in the PC actor as much as possible -- all
>> other objects could return their desired representation to it.
>
> The UI is especially tricky. It seems to need access to everything, but
> we can't allow that without seizing up our entire implementation into a
> solid block that lives or dies with the UI.
>
> So I think that above all, the UI needs to be designed extremely
> carefully. Why do you keep the UI contained in the PC actor? Surely the
> input is vital to the PC actor, but the output seems to be omnipresent
> and important to all things equally.

Most of the time you want to update the screen only just before asking
the player for input -- you might also update it *during* the wait for
input, if you're doing animations.

There's nothing interesting for the UI in the layers above the actors.
Most of what you want/need to display is either internal to the actor
(dialogs, menus, warning messages, confirmations), or is contained
in the lower layers (dungeon map, message buffer, pc stats, inventory).
It seems intuitive to keep all the formatting in one place -- and
because of the dialogs, menus, etc. it has to be the actor, or rather
the helper functions that the actor uses. All other elements can be
retrieved by the actor in form of raw data -- lists, <looks> objects,
events, message tags, etc.

Ok, there's one thing above the <actor> class -- all the meta-game
functions, save/load/new, options menu, etc.
--
Radomir `The Sheep' Dopieralski @**@_
(==) 3 Yawn?
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 26, 2005 2:36:12 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndje2lo.n6q.thesheep@atos.wmid.amu.edu.pl:

[snip Actors watching characters for events]

> Now, how we should do the informing -- use a bunch of methods and
> interfaces for <on_attacked>, <on_talked_to>, <on_tickled>, etc.
> or rather use <event> objects?
>
> The second approach seems to have the advantage of possibility to
> create your own, custom events not included in the interface.
>
> But how to exchange them? Should there be a listener callback
> passing all the <event> objects, or maybe there's some way to
> filter them out?

We can do both. We should definitely include methods for the most
obvious and fundamental events, like attacking. Additional ones might
be done using event objects, but that's going to have to end up as some
kind of switch statement somewhere.

The only place our selection of watchable events will be listed in our
code will be the Creature interface, where we will have to include
methods to register actors who will watch.

For example:
Creature
addAttackWatcher(AttackWatcher)
addTalkWatcher(TalkWatcher)
addEventWatcher(EventWatcher)

AttackWatcher
onAttack(Damage,Creature,Dungeon)
TalkWatcher
onTalk(Creature,Creature,Dungeon)
EventWatcher
onEvent(Event,Dungeon)

I pass in the <dungeon> so that the actor might provide an instant
response to the event.

When we create subclasses of creature, we can add additional watchable
things, but the actors who watch them would have to be around when the
actor is created so that they know that it has those watchables, or we
would have to adjust the factories so that all creatures were of a
common subclass with the new methods.

As far as the Actor is concerned, there are limitless possibilities for
watchable things, you just need to subclass the right interfaces. When
an actor receives a generic Event it will be forced to dynamically
determine the type of event, which is messy.

>> Radomir 'The Sheep' Dopieralski wrote in
>>> Anyways, the "poison actor" is just an example. You get similar
>>> behavior with monster pushing past each other and swapping
>>> positions, monsters using each other as weapons or missiles, and
>>> all kinds of "automatic" actions that doesn't use up the creature's
>>> turn.
>
> At Sun, 25 Sep 2005 19:33:00 GMT,
> Brendan Guild wrote:
>> These other things don't seem to parallel the poison example very
>> well. They seem like one creature's actor taking control of another
>> creature for one turn.
>
> Depends on your actual game mechanics --- I, for example, prefer to
> make the "pushing" an additional action, so that the creature that is
> pushed can still act in it's own turn.

Me, also. In fact, to prevent that creature from taking it's own turn,
we would have to take drastic steps. We couldn't just remove the actor
from the timeline, because then the actor would never act again! We
would have to get the actor itself to choose to skip it's next turn.

What I meant was that we don't need to create a new actor to push a
creature around, we can just change it's location directly from our
current actor in the pushy creature's turn.

[snip state machine discussion]
> Normally you'd have a whole bunch of variables indicating your
> automaton's state -- of course, from the mathematical point of view,
> they are all describing a single state.

I was thinking that the new state could be created with some values
from the previous state, so those variables could continue. It would be
constructed directly by the actor, after all, so we still have total
control.
Anonymous
September 26, 2005 2:39:29 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndjd55f.81f.thesheep@atos.wmid.amu.edu.pl:
> Funny. I just remembered why I separated the <actor> and the
> <creature> classes in the first place, long time ago when I first
> encountered this kind of design. You see, I mainly program in C, and
> it's one of the most popular methods to implement inheritance... ;) 

Who says that a roguelike shouldn't be done object-oriented? I know that
it's been discussed and some people declined OO, but just look at all the
power we have!
Anonymous
September 26, 2005 4:05:05 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
news:slrndje4bp.qas.thesheep@atos.wmid.amu.edu.pl:
> Every <usage> would be, well, a single usage (duh!) :) 
> There are three basic methods needed:
> equip(creature) -- called when the usage is put into an equipment
> slot
> unequip(creature) -- called when the usage is removed
> activate(...) -- called when the usage is... well... used
>
> Of course a single usage can go only into a single kind of slot (some
> usages can only be activated and can't be put into a slot), and it
> also has a method to check whether it doesn't conflict with any other
> usage already equipped (ie. gloves and rings, or the towel that can
> be worn on head or as cloak, but not both at the same time).

What about monsters, would they use the same usage classes or would
that just be for players? How would things work in a monster?

How do the messages about conflicts and unequipables come to the
player? Does the PC Actor pass some kind of UI control object to the
usage for the check methods? How does it know not to do that when a
monster equips it?
Anonymous
September 26, 2005 6:33:40 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Sun, 25 Sep 2005 22:36:12 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski wrote in
> news:slrndje2lo.n6q.thesheep@atos.wmid.amu.edu.pl:
>
> [snip Actors watching characters for events]
>
>> Now, how we should do the informing -- use a bunch of methods and
>> interfaces for <on_attacked>, <on_talked_to>, <on_tickled>, etc.
>> or rather use <event> objects?
>>
>> The second approach seems to have the advantage of possibility to
>> create your own, custom events not included in the interface.
>>
>> But how to exchange them? Should there be a listener callback
>> passing all the <event> objects, or maybe there's some way to
>> filter them out?
>
> We can do both. We should definitely include methods for the most
> obvious and fundamental events, like attacking. Additional ones might
> be done using event objects, but that's going to have to end up as some
> kind of switch statement somewhere.

Somehow I don't like this. I think consistency is important here.

>>> These other things don't seem to parallel the poison example very
>>> well. They seem like one creature's actor taking control of another
>>> creature for one turn.
>>
>> Depends on your actual game mechanics --- I, for example, prefer to
>> make the "pushing" an additional action, so that the creature that is
>> pushed can still act in it's own turn.
>
> Me, also. In fact, to prevent that creature from taking it's own turn,
> we would have to take drastic steps. We couldn't just remove the actor
> from the timeline, because then the actor would never act again! We
> would have to get the actor itself to choose to skip it's next turn.
>
> What I meant was that we don't need to create a new actor to push a
> creature around, we can just change it's location directly from our
> current actor in the pushy creature's turn.

How about creatures pushed so hard, that they roll for several turns
after they are pushed? :D 

--
Radomir `The Sheep' Dopieralski @**@_
(--) 3 ..zzZZ
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 26, 2005 6:38:22 PM

Archived from groups: rec.games.roguelike.development (More info?)

At Mon, 26 Sep 2005 00:05:05 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
> news:slrndje4bp.qas.thesheep@atos.wmid.amu.edu.pl:
>> Every <usage> would be, well, a single usage (duh!) :) 
>> There are three basic methods needed:
>> equip(creature) -- called when the usage is put into an equipment
>> slot
>> unequip(creature) -- called when the usage is removed
>> activate(...) -- called when the usage is... well... used
>>
>> Of course a single usage can go only into a single kind of slot (some
>> usages can only be activated and can't be put into a slot), and it
>> also has a method to check whether it doesn't conflict with any other
>> usage already equipped (ie. gloves and rings, or the towel that can
>> be worn on head or as cloak, but not both at the same time).
>
> What about monsters, would they use the same usage classes or would
> that just be for players? How would things work in a monster?

That's a hard part no matter whether you use <usages> or not.
You'd probably need some kind of way either judge the value of certain
item-related action, or to present the most probable results of this
action to the monster, so that it can judge the value for itself...
I think both depend heavily on the AI implementation, so maybe this
part should rather be included in the <actor>, not in the <item>?

> How do the messages about conflicts and unequipables come to the
> player? Does the PC Actor pass some kind of UI control object to the
> usage for the check methods? How does it know not to do that when a
> monster equips it?

Well, I suppose that the equip_action.possible could return the list
of conflicting usages on failure, so that the actor can decide to
either remove them automatically or inform the player about them.

--
Radomir `The Sheep' Dopieralski @**@_
($s) 3 Ching!
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 27, 2005 1:10:21 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski wrote in
news:slrndjg1uu.dgs.thesheep@atos.wmid.amu.edu.pl:

>> Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
>> news:slrndje4bp.qas.thesheep@atos.wmid.amu.edu.pl:
>>> Every <usage> would be, well, a single usage (duh!) :) 
>>> There are three basic methods needed:
>>> equip(creature) -- called when the usage is put into an equipment
>>> slot
>>> unequip(creature) -- called when the usage is removed
>>> activate(...) -- called when the usage is... well... used
>>>
>>> Of course a single usage can go only into a single kind of slot
>>> (some usages can only be activated and can't be put into a slot),
>>> and it also has a method to check whether it doesn't conflict with
>>> any other usage already equipped (ie. gloves and rings, or the
>>> towel that can be worn on head or as cloak, but not both at the
>>> same time).

[snip]

> You'd probably need some kind of way either judge the value of
> certain item-related action, or to present the most probable results
> of this action to the monster, so that it can judge the value for
> itself...
> I think both depend heavily on the AI implementation, so maybe this
> part should rather be included in the <actor>, not in the <item>?

We will probably want to assign a value to each usage that the monsters
can compare if we ever want to create a monster that picks items up
from the floor and uses them.

In fact, thinking from a monster's perspective, we would want to have a
list of all the monsters combat powers so that the AI can pick things
at random to do. That list should include the usages of it's equipment,
and also any items in it's inventory and any innate powers, like
attacking with bare hands. All of them should be given at least one
value so that the monster can pick the best, but perhaps we can give
them several values so the AI can try to balance conflicting desires
with it's choices of attacking/potion quaffing/wand zapping.

Therefore, we should have a common superclass for usages and other
things. Like this:
Ability - Something that a creature can do.
canAttack(Creature,Dungeon,Creature target)
- Make sure we are in range and we aren't healing the target
instead of killing it.
activate(Creature,Dungeon,Creature target) - Do whatever it is
range() - How close we have to be
attackValue() - approximate relative value of attacking with this
defenseValue() - approximate relative defensive value
A monster doesn't know it's got a sword, it just knows that it has
something with a high attackValue, a low range and a low defenseValue.
High defenseValues would probably come from things like healing
potions. These values are just our guesses about what these abilities
are worth to help our AI, not anything that affects the result.

A monster can use the range() values of it's abilities to figure out if
it should be charging the player or not.
Anonymous
September 27, 2005 1:20:39 AM

Archived from groups: rec.games.roguelike.development (More info?)

At Mon, 26 Sep 2005 21:10:21 GMT,
Brendan Guild wrote:

> Radomir 'The Sheep' Dopieralski wrote in
> news:slrndjg1uu.dgs.thesheep@atos.wmid.amu.edu.pl:
>> You'd probably need some kind of way either judge the value of
>> certain item-related action, or to present the most probable results
>> of this action to the monster, so that it can judge the value for
>> itself...
>> I think both depend heavily on the AI implementation, so maybe this
>> part should rather be included in the <actor>, not in the <item>?
>
> We will probably want to assign a value to each usage that the monsters
> can compare if we ever want to create a monster that picks items up
> from the floor and uses them.
>
> In fact, thinking from a monster's perspective, we would want to have a
> list of all the monsters combat powers so that the AI can pick things
> at random to do. That list should include the usages of it's equipment,
> and also any items in it's inventory and any innate powers, like
> attacking with bare hands. All of them should be given at least one
> value so that the monster can pick the best, but perhaps we can give
> them several values so the AI can try to balance conflicting desires
> with it's choices of attacking/potion quaffing/wand zapping.


Isn't it too specific?
We are restricting the way the AI works here.
It's the work of the AI designer, our interface should have nothing to do
with it.
I think that each <actor> should have it's own ways of deciding on value
of certain items, usages and actions --- all we should do is to provide it
with means of gathering information and maybe some helper functions for
the most common tasks.

> Therefore, we should have a common superclass for usages and other
> things. Like this:
> Ability - Something that a creature can do.
> canAttack(Creature,Dungeon,Creature target)
> - Make sure we are in range and we aren't healing the target
> instead of killing it.
Isn't it a really specific action?

> activate(Creature,Dungeon,Creature target) - Do whatever it is
Does the target have to be creature?
Also, weren't we supposed to use the <action> objects for performing
actions?

> range() - How close we have to be
> attackValue() - approximate relative value of attacking with this
> defenseValue() - approximate relative defensive value
Specific.


> A monster doesn't know it's got a sword, it just knows that it has
> something with a high attackValue, a low range and a low defenseValue.
> High defenseValues would probably come from things like healing
> potions. These values are just our guesses about what these abilities
> are worth to help our AI, not anything that affects the result.

Yes, a dumb orc will pick anything that's large and sharp and call it
"choppa". But a fencer will rather prefer fast and light weapons.
We have to allow the AI decide.

--
Radomir `The Sheep' Dopieralski @**@_
(*+) 3 Sparkle
. . . ..v.vVvVVvVvv.v.. .
Anonymous
September 27, 2005 3:15:19 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
news:slrndjgph7.ed.thesheep@atos.wmid.amu.edu.pl:

> At Mon, 26 Sep 2005 21:10:21 GMT,
> Brendan Guild wrote:
>>
>> We will probably want to assign a value to each usage that the
>> monsters can compare if we ever want to create a monster that picks
>> items up from the floor and uses them.
>>
>> In fact, thinking from a monster's perspective, we would want to
>> have a list of all the monsters combat powers so that the AI can
>> pick things at random to do. That list should include the usages of
>> it's equipment, and also any items in it's inventory and any innate
>> powers, like attacking with bare hands. All of them should be given
>> at least one value so that the monster can pick the best, but
>> perhaps we can give them several values so the AI can try to balance
>> conflicting desires with it's choices of attacking/potion
>> quaffing/wand zapping.
>
> Isn't it too specific?
> We are restricting the way the AI works here.
> It's the work of the AI designer, our interface should have nothing
> to do with it.
> I think that each <actor> should have it's own ways of deciding on
> value of certain items, usages and actions --- all we should do is to
> provide it with means of gathering information and maybe some helper
> functions for the most common tasks.

Doing something like this is abstracting the interface that the AI
works with and thereby allowing us to change the implementation of the
world, introduce new attributes and weapons, etc, without having to
change the AI.

But you are right that we don't want to restrict what the AI can do,
either. We certainly don't want to have to rewrite everything because
we want a monster to have some bizarre behaviour that we never thought
of when making the architecture! So we still give the AI total access
to the creature's inventory. I like to think of a setup like this as a
tool for writing more flexible, simpler AIs. attackValue(),
defenseValue(), etc, are just some of those helper functions.

>> Therefore, we should have a common superclass for usages and other
>> things. Like this:
>> Ability - Something that a creature can do.
>> canAttack(Creature,Dungeon,Creature target)
>> - Make sure we are in range and we aren't healing
>> the target
>> instead of killing it.
> Isn't it a really specific action?

Yes, I've changed my mind about this method. It's not very useful, it
should be implemented in the AI, not the Usage. Perhaps just isAttack()
with no parameters to indicate if this is an attack <usage>.

>> activate(Creature,Dungeon,Creature target) - Do whatever it
>> is
> Does the target have to be creature?

Good point. We might want to have a separate method for activating with
an item as the target, or we could have both Creature and Item have a
common superclass.

> Also, weren't we supposed to use the <action> objects for performing
> actions?

Nothing is preventing that here, right? It's the <usage> that
determines what happens when we activate, so it could create an
<action> itself and apply it to the dungeon. I'm not sure exactly how
things should be implemented inside the <usage>. What did you picture
usage.activate(...) doing?

>> A monster doesn't know it's got a sword, it just knows that it has
>> something with a high attackValue, a low range and a low
>> defenseValue. High defenseValues would probably come from things
>> like healing potions. These values are just our guesses about what
>> these abilities are worth to help our AI, not anything that affects
>> the result.
>
> Yes, a dumb orc will pick anything that's large and sharp and call it
> "choppa". But a fencer will rather prefer fast and light weapons.
> We have to allow the AI decide.

It will still be the AI that takes a dungeon object and uses it to
figure out that there is something on the floor, then removes the item
from the map and puts it into the creatures inventory. The AI would
check for usages on the object. Maybe the AI will add the usages into a
list with other usages, maybe it will organize things totally
differently, but there are things similar to usages (such as attacking
with bare hands) which I don't think the AI will often want to code a
special case for. That's the basis of the idea of having those kinds of
things share a common superclass like Ability.

The AI would still have total control over what the creature does. The
AI doesn't even have to use abilities of the creature, it can just
directly use the dungeon interface to do whatever that interface will
allow.
Anonymous
September 27, 2005 5:20:11 AM

Archived from groups: rec.games.roguelike.development (More info?)

Radomir 'The Sheep' Dopieralski <thesheep@ sheep.prv.pl> wrote in
news:slrndjg1m4.dgs.thesheep@atos.wmid.amu.edu.pl:

> At Sun, 25 Sep 2005 22:36:12 GMT,
> Brendan Guild wrote:
>
>> Radomir 'The Sheep' Dopieralski wrote in
>> news:slrndje2lo.n6q.thesheep@atos.wmid.amu.edu.pl:
>>> Now, how we should do the informing -- use a bunch of methods and
>>> interfaces for <on_attacked>, <on_talked_to>, <on_tickled>, etc.
>>> or rather use <event> objects?

[snip]

>> We can do both. We should definitely include methods for the most
>> obvious and fundamental events, like attacking. Additional ones
>> might be done using event objects, but that's going to have to end
>> up as some kind of switch statement somewhere.
>
> Somehow I don't like this. I think consistency is important here.

It's not really inconsistency, it's just elevating certain events as
being more important than other events, with justification. I mean,
being attacked is a very important event. We can use an Event class to
represent special events that only special actors would want to respond
to, things that we can't predict would be needed in the interface,
things that come up during implementation.

We treat special events specially and general events generally, that's
not inconsistent, right?
!