Sign in with
Sign up | Sign in
Your question

Every tile an object?!

Last response: in Video Games
Share
Anonymous
August 25, 2005 7:08:24 PM

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

I've been looking at the source code to IVAN for the past 30 minutes. IVAN
is a RL written in C++ and which is more object-oriented than some other RL
code that I have read.

IVAN uses an array of "lsquare" objects to represent the map. These lsquares
have about 20-30 different fields and at least 150 different functions
handling everything from lighting to the handling of spells.

I'm thinking about switching to the "every tile is an object" methodolgy
myself. Currently my tile map just stores an array of tile structs; and a
tile struct is the index of the ground tile at this square, and a pointer to
an ArrayList holding anything that might be occupying the tile. I'm thinking
that the every-tile-an-object idea would make it easier to keep my code
object-oriented and it would also make it easier to keep track of the
properties of different tiles.

But it seems like the IVAN design takes things a little too far... I mean,
spell-handling logic in the map tile object?

What do you guys think?

--
Blog:
Shedletsky's Bits: A Random Walk Through Manifold Space
http://www.stanford.edu/~jjshed/blog

More about : tile object

Anonymous
August 25, 2005 10:28:52 PM

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

First post via a new news server...your patience is appreciated.

"Shedletsky" <mylastname@stanford.edu> wrote in message
news:D el4vc$1l1$2@news.Stanford.EDU...
> IVAN uses an array of "lsquare" objects to represent the map. These
> lsquares
> have about 20-30 different fields and at least 150 different functions
> handling everything from lighting to the handling of spells.
>

In my project, I've encapsulated each square as its own object, and it has
led to some nice simplifications in the map class. My profiler has shown the
cost of using objects here to be negligible.

Nathan
Anonymous
August 25, 2005 11:16:54 PM

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

At Thu, 25 Aug 2005 15:08:24 -0400,
Shedletsky wrote:

> I've been looking at the source code to IVAN for the past 30 minutes. IVAN
> is a RL written in C++ and which is more object-oriented than some other RL
> code that I have read.
>
> IVAN uses an array of "lsquare" objects to represent the map. These lsquares
> have about 20-30 different fields and at least 150 different functions
> handling everything from lighting to the handling of spells.
>
> I'm thinking about switching to the "every tile is an object" methodolgy
> myself. Currently my tile map just stores an array of tile structs; and a
> tile struct is the index of the ground tile at this square, and a pointer to
> an ArrayList holding anything that might be occupying the tile. I'm thinking
> that the every-tile-an-object idea would make it easier to keep my code
> object-oriented and it would also make it easier to keep track of the
> properties of different tiles.
>
> But it seems like the IVAN design takes things a little too far... I mean,
> spell-handling logic in the map tile object?
>
> What do you guys think?

I think treating the map as an object is enough. The squares themselves
are just an internal feature of the map object, and their exact
implementation shoudn't be revelant for the rest of code.


--
Radomir `The Sheep' Dopieralski @**@_
(Uu) 3 Sigh!
. . . ..v.vVvVVvVvv.v.. .
Anonymous
August 26, 2005 1:08:22 AM

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

Shedletsky wrote:
> But it seems like the IVAN design takes things a little too far... I mean,
> spell-handling logic in the map tile object?

I don't see anything inherently wrong with making every tile an object, but it's up to you, really. If it makes more sense to you to abstract things to that level, go for it.

Spell-handling logic in the tile object sounds broken (in the "pure OO" sense) to me, but that's a separate issue. Unless, of course, the magic in question is operating on the tile itself, whatever that means. ;) 

-Aaron
Anonymous
August 26, 2005 3:17:39 AM

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

Shedletsky wrote:
> But it seems like the IVAN design takes things a little too far... I mean,
> spell-handling logic in the map tile object?
>
> What do you guys think?

Depends if you highest goal is clean design, or finite ressource
usage ...
Anonymous
August 26, 2005 12:41:16 PM

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

Andreas Koch wrote:
> Shedletsky wrote:
> > But it seems like the IVAN design takes things a little too far... I mean,
> > spell-handling logic in the map tile object?
> >
> > What do you guys think?
>
> Depends if you highest goal is clean design, or finite ressource
> usage ...

In either case, the answer is the same: don't make map tiles objects.
You get clean design and avoid unnecessary code and data bloat.

I find it depressing that this is even considered an option to people.
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)
Anonymous
August 26, 2005 2:34:05 PM

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

> Depends if you highest goal is clean design, or finite ressource
> usage ...

Well there is that... But most RL maps are smaller than 100x100. So even
with a bloated tile object we are talking about map memory footprints on the
order of kilobytes here. In comparison the .Net framework code that gets
loaded into memory when my program is running is on the order of 20 MB. And
that's still not even worth thinking about these days -- the 3-year old
laptop I'm developing on has a gig of RAM. For anything you'd want to do in
the RL space, memory is basically limitless.

So maybe I should go with clean design. Seems to work for the IVAN people.

--
Blog:
Shedletsky's Bits: A Random Walk Through Manifold Space
http://www.stanford.edu/~jjshed/blog
Anonymous
August 26, 2005 5:11:09 PM

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

John wrote:
> On 2005-08-26, Andreas Koch <nospam@kochandreas.com> wrote:
> > Depends on what you are targeting. If you only want to run on modern
> > Wintel PCs, RAM is no limit. But you should consider that a gig
> > is more than many CURRENT super market PCs have (at least here
> > in germany), and many people still run boxes with Win98 and
> > 64 Meg (and no .NET ... )...
>
> And what roguelike, no matter how bloated, doesn't run on 64MB?
>
> > If you want to port on something like PDAs with 2 Meg of Memory for
> > disk and working RAM, it DOES matter if that 100x100 map needs
> > 100x100 bytes or 100x100 pointers+byte+etc ...
>
> What color screen PDA made in the last 5 years has only 2MB of memory?
> Please provide a model number and link.

The Gameboy Advance is made to this day.
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)
Anonymous
August 26, 2005 5:32:06 PM

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

Shedletsky wrote:
>
> > Lack of experience combined with "object-oriented" being their only tool
> > leads them to believe that every problem has an object-oriented
> > decomposition and that every last thing in a program must be an
> > object. Java doesn't help in this regard.
>
> Beyond the fact that C# basically forces OOP, I want my code to be as
> extensible as possible and OOP seems like a good paradigm for this.

OOP has nothing to do with making tiles objects. OOP means you make
the map an object. Tiles are not things that should be exported
outside of the map. Thus, you *could* implement them as objects
*inside* the map's universe. But the rest of the world should
interface with a map, not with a MxN array of Tiles.

When you build this distinction you then realize your reprsentation of
tiles can be arbitrary. There is no need to store monsters "inside"
your "tile" structure. And for the vast majority of roguelikes a
simple index sufficies to completely describe each tile. At this
point, it is simpler code wise, more effecient memory wise, to just use
an MxN array of indices.

This also lets you do any other tricks you feel like. For example,
breaking your 1000x1000 map into 50x50 chunks can be done seamlessly
from the viewpoint of the outside world. Compressing these in ram,
swapping to disk, whatever, can be done without dealing with outside
TILE references dangling. Building a KD tree to store creature and
item positions for fast nearest searches can be cached and maintained
at the level that makes sense. You don't have to worry about the tree
becoming invalid because someone with a pointer to a tile changed the
monster value there (or, alternatively, making sure the proper dirty
notifications get bumped back up to the tile's parent (which requires
storing with the tile its parent information - ugh!) whenever the tile
set() methods are invoked).

This is why I'm tired with this tacit assumption that "Everything Is An
Object" implies some magical cleaner design. It doesn't. A clean
design seeks to minimize the number of objects you need.

> like a lot of RL coders are old school procedural C hacks, which has made it
> difficult to read other source code for ideas of how to do things.

Have you read the source for You Only Live Once?

http://www.zincland.com/7drl/liveonce
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)
Anonymous
August 26, 2005 5:51:02 PM

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

John wrote:
> On 2005-08-26, Jeff Lait <torespondisfutile@hotmail.com> wrote:
> > > What color screen PDA made in the last 5 years has only 2MB of memory?
> >
> > The Gameboy Advance is made to this day.
>
> Too bad its not a PDA.

I forgot. The GBA is analog, so it is really a PAA.
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)
Anonymous
August 26, 2005 7:56:37 PM

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

"Shedletsky" <mylastname@stanford.edu> writes:
> > Depends if you highest goal is clean design, or finite ressource
> > usage ...
>
> Well there is that... But most RL maps are smaller than 100x100. So even
> with a bloated tile object we are talking about map memory footprints on the
> order of kilobytes here. In comparison the .Net framework code that gets
> loaded into memory when my program is running is on the order of 20 MB. And
> that's still not even worth thinking about these days -- the 3-year old
> laptop I'm developing on has a gig of RAM. For anything you'd want to do in
> the RL space, memory is basically limitless.

Well, maybe. The major roguelikes (and quite a lot of the minor ones)
still run fine on my 100Mhz/96Mb machine, and out of a feeling that
roguelikes shouldn't eat memory or require the 'latest' hardware I'd
like mine too as well. So far mine's an order of magnitude too slow.

I don't know... it already runs at a reasonable speed on a 450MHz
machine - is it worth optimising so that it runs on a 100MHz machine
or should I just give up and expect people to have a machine from this
decade or so?

Another reason to avoid power-hungry roguelikes, at least on the
Unix/Linux platform, is that lots of machines are multi-user and so
while the machine might have 2Gb you'll be in real trouble with the
admin/other users if you use it all yourself. Similarly with processor
usage.

On the windows platform where the majority of machines are single-user
it's obviously not so important.

--
Chris
Anonymous
August 26, 2005 9:29:20 PM

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

Shedletsky wrote:

> Well there is that... But most RL maps are smaller than 100x100. So even
> with a bloated tile object we are talking about map memory footprints on the
> order of kilobytes here. In comparison the .Net framework code that gets
> loaded into memory when my program is running is on the order of 20 MB. And
> that's still not even worth thinking about these days -- the 3-year old
> laptop I'm developing on has a gig of RAM. For anything you'd want to do in
> the RL space, memory is basically limitless.

Depends on what you are targeting. If you only want to run on modern
Wintel PCs, RAM is no limit. But you should consider that a gig
is more than many CURRENT super market PCs have (at least here
in germany), and many people still run boxes with Win98 and
64 Meg (and no .NET ... )...

If you want to port on something like PDAs with 2 Meg of Memory for
disk and working RAM, it DOES matter if that 100x100 map needs
100x100 bytes or 100x100 pointers+byte+etc ...

I read a nice document about designing games for java enabled phones.
They strongly suggested to use as less objects as possible
(in java ... <g>) because of the overhead.
August 26, 2005 9:30:57 PM

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

On 2005-08-26, Jeff Lait <torespondisfutile@hotmail.com> wrote:
> In either case, the answer is the same: don't make map tiles objects.
> You get clean design and avoid unnecessary code and data bloat.
>
> I find it depressing that this is even considered an option to people.

My theory is that most schools teach new programmers an "object-oriented"
language like Java or C++ and most roguelike "developers" are still in
school.

Lack of experience combined with "object-oriented" being their only tool
leads them to believe that every problem has an object-oriented
decomposition and that every last thing in a program must be an
object. Java doesn't help in this regard.

Unfortunately, being new, inexperienced, and intelligent, these
"developers" are too sure of themselves to see their own faults.

I think a look at the source code for most new roguelikes will lend
credibility to my theory.

This is also why most of the posts in this newsgroup are about trivial
non-issues rather than real development challenges.

Just my $.02
Anonymous
August 26, 2005 9:30:58 PM

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

> My theory is that most schools teach new programmers an "object-oriented"
> language like Java or C++ and most roguelike "developers" are still in
> school.

Yes. That's probably true.

> Lack of experience combined with "object-oriented" being their only tool
> leads them to believe that every problem has an object-oriented
> decomposition and that every last thing in a program must be an
> object. Java doesn't help in this regard.

Beyond the fact that C# basically forces OOP, I want my code to be as
extensible as possible and OOP seems like a good paradigm for this. It seems
like a lot of RL coders are old school procedural C hacks, which has made it
difficult to read other source code for ideas of how to do things.

> Unfortunately, being new, inexperienced, and intelligent, these
> "developers" are too sure of themselves to see their own faults.

Damn straight.

> This is also why most of the posts in this newsgroup are about trivial
> non-issues rather than real development challenges.

All development challenges are trivial if you already know the answer.

--
Blog:
Shedletsky's Bits: A Random Walk Through Manifold Space
http://www.stanford.edu/~jjshed/blog
August 26, 2005 11:37:46 PM

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

On 2005-08-26, Andreas Koch <nospam@kochandreas.com> wrote:
> > And what roguelike, no matter how bloated, doesn't run on 64MB?
> OP was talking about using .NET, with a 20 meg runtime.

That leaves 44 MB. Your roguelike doesn't fit in that?

> > What color screen PDA made in the last 5 years has only 2MB of memory?
> Who did say color screen?

Everyone in this newsgroup who uses a non-color screen PDA with 2MB of
memory on a daily basis raise your hand.

> > I think you are arguing just to hear yourself speak at this point.
> Oh, a Troll. Couldn't you have said that right in the beginning?
> Would have saved me typing ...

Calling a person a troll because you can't deal with there differing
opinion is pretty sad.
Anonymous
August 26, 2005 11:37:47 PM

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

John <piQqySNI@mailinator.com> schrieb:
> Calling a person a troll because you can't deal with there differing
> opinion is pretty sad.

More or less sad than trolling someone with a different opinion because
you have nothing useful to say?

--
Jim Strathmeyer
August 27, 2005 12:40:50 AM

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

On 2005-08-26, Jeff Lait <torespondisfutile@hotmail.com> wrote:
> > What color screen PDA made in the last 5 years has only 2MB of memory?
>
> The Gameboy Advance is made to this day.

Too bad its not a PDA.
Anonymous
August 27, 2005 2:18:33 AM

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

Jeff Lait wrote:
> This is why I'm tired with this tacit assumption that "Everything Is An
> Object" implies some magical cleaner design. It doesn't. A clean
> design seeks to minimize the number of objects you need.

I don't want to get *too* nitpicky, but a clean design seeks to minimise the amount of trouble involved in making changes to your source code. For roguelikes it might mean minimising the number of objects, but it might not.

Ultimately it depends on the programmer.

-Aaron
Anonymous
August 27, 2005 3:21:10 AM

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

John wrote:

> Everyone in this newsgroup who uses a non-color screen PDA with 2MB of
> memory on a daily basis raise your hand.

Well, "on a daily basis" seems to me to make this into a strawman.

I use a Palm ... er, 3, I think it is? on an irregular basis to play
some simple games on. I have one of those super-simplistic elite-clones,
and a couple of "make shaded blocks come next to each other" games. A
roguelike for it would be very cool.
Anonymous
August 27, 2005 7:55:38 AM

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

Shedletsky wrote:
> I've been looking at the source code to IVAN for the past 30 minutes. IVAN
> is a RL written in C++ and which is more object-oriented than some other RL
> code that I have read.
>
> IVAN uses an array of "lsquare" objects to represent the map. These lsquares
> have about 20-30 different fields and at least 150 different functions
> handling everything from lighting to the handling of spells.

Sounds a little dangerous to me - most of this stuff either belongs in
the map object or in separate spell handling code.

Having said that, there is a case for making tiles into object *if*
they are immutable. By this I mean that you can't change any of the
fields. If you do this, you effectively have no per-tile resource
overhead because you use a single object instance for every "wall" tile
in the entire game, and the reference to these objects only take up 4
bytes per tile. Any event that changes a tile would just need to change
the reference for that tile to a different tile object instance.
Anonymous
August 27, 2005 5:57:20 PM

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

> Thus, you *could* implement them as objects
> *inside* the map's universe. But the rest of the world should
> interface with a map, not with a MxN array of Tiles.

Right. This is model that IVAN uses and the one I had in mind when I posted
the original topic.

> When you build this distinction you then realize your reprsentation of
> tiles can be arbitrary. There is no need to store monsters "inside"
> your "tile" structure. And for the vast majority of roguelikes a
> simple index sufficies to completely describe each tile. At this
> point, it is simpler code wise, more effecient memory wise, to just use
> an MxN array of indices.

Definitely it is more efficient memory-wise - that was never contested.
However, it seems like there is a design advantage to allowing the tiles to
be objects. For example: If my tile object has an EntityEntersTile(Entity
*ent) method and I have a Lava tile that burns any entity that steps on it,
this would be a good place to do ent->TakeDamage(10). Without the object
model, whenever a creature moves in my map, I will have to do the test (If
map[new_x,new_y] == LAVA_TILE then...) That's ugly. I want an extensible
system, which mean I want to minimize special case code like that. The tiles
probably will store pointers to all the entities standing on them, to make
getting a list of entities at (x,y) very fast. This doesn't prevent a
separate list of entity pointers in the map object for interating over all
entities (to update their states or what have you).

> This also lets you do any other tricks you feel like. For example,
> breaking your 1000x1000 map into 50x50 chunks can be done seamlessly
> from the viewpoint of the outside world. Compressing these in ram,
> swapping to disk, whatever, can be done without dealing with outside
> TILE references dangling.

I can still do that with a map of tile references. C# is garbage collected,
so dangling refs are no problem.

> Building a KD tree to store creature and
> item positions for fast nearest searches can be cached and maintained
> at the level that makes sense.
> You don't have to worry about the tree
> becoming invalid because someone with a pointer to a tile changed the
> monster value there (or, alternatively, making sure the proper dirty
> notifications get bumped back up to the tile's parent (which requires
> storing with the tile its parent information - ugh!) whenever the tile
> set() methods are invoked).

KD tree? Is this like a BSP or QuadTree? I don't know anything about that so
you may be right. If my tiles store references to all the entities on them,
finding all the monster entities in a set of tiles is going to be pretty
fast.

> This is why I'm tired with this tacit assumption that "Everything Is An
> Object" implies some magical cleaner design. It doesn't. A clean
> design seeks to minimize the number of objects you need.

Clean design seeks to minimize special case logic.

>> like a lot of RL coders are old school procedural C hacks, which has made
>> it
>> difficult to read other source code for ideas of how to do things.
>
> Have you read the source for You Only Live Once?

No, but I will look at it right now. Thanks for pointing it out to me.

Thanks for the thought-provoking response,
John
Anonymous
August 27, 2005 5:57:21 PM

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

Shedletsky <mylastname@stanford.edu> schrieb:
> Definitely it is more efficient memory-wise - that was never
> contested. However, it seems like there is a design advantage to
> allowing the tiles to be objects. For example: If my tile object has
> an EntityEntersTile(Entity *ent) method and I have a Lava tile that
> burns any entity that steps on it, this would be a good place to do
> ent->TakeDamage(10). Without the object model, whenever a creature
> moves in my map, I will have to do the test (If map[new_x,new_y] ==
> LAVA_TILE then...) That's ugly. I want an extensible system, which
> mean I want to minimize special case code like that. The tiles
> probably will store pointers to all the entities standing on them, to
> make getting a list of entities at (x,y) very fast. This doesn't
> prevent a separate list of entity pointers in the map object for
> interating over all entities (to update their states or what have
> you).

This is a good point. A tile can also have EntityLeavesTile(),
Drop/PickUp(Item*), and other tile specific actions.

I don't see what the big deal is. Asking questions like this and only
seeing pro/con OO reactions is sort of useless. How you implement maps
and tiles depends upon how much you want tiles to be able to do, and if
it's very little (such as a tile just being what the tile looks like,
whether it's passable, and what items and characters are on it) then it
may be easier to not make a map a list of tile objects. But every time
you encapsulate something as an object, you make it easier to extend and
refine it.

--
Jim Strathmeyer
Anonymous
August 27, 2005 5:58:38 PM

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

> Sounds a little dangerous to me - most of this stuff either belongs in
> the map object or in separate spell handling code.
>
> Having said that, there is a case for making tiles into object *if*
> they are immutable. By this I mean that you can't change any of the
> fields. If you do this, you effectively have no per-tile resource
> overhead because you use a single object instance for every "wall" tile
> in the entire game, and the reference to these objects only take up 4
> bytes per tile. Any event that changes a tile would just need to change
> the reference for that tile to a different tile object instance.

Hmm. I hadn't thought of doing it that way. That might be a good solution.
Anonymous
August 27, 2005 7:22:25 PM

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

U¿ytkownik "Shedletsky" <mylastname@stanford.edu> napisa³ w wiadomo¶ci
news:D el4vc$1l1$2@news.Stanford.EDU...
> But it seems like the IVAN design takes things a little too far... I
> mean,
> spell-handling logic in the map tile object?

Sounds like a bad design.
We have one of the three cases here:
1. a tile object knows (or is able to find out) its position on the
map
2. a tile object does not know (and is unable to find out) its
position
3. tile objects know their neighbours, (eg. have pointers to them) and
make up a map by themselves. There is no additional map object.

In the first case we have a circular dependency: map asks tiles about
some things, and tiles ask map about some other things. This will make
debugging and writing code harder than it should be, especially the
serialization routines.

In the second case - the tile objects will have a very limited use.
All effects concerning area will have to be handled by the map anyway.
This makes tile objects almost useless, they won't encapsulate
anything meaningful.

The third case _might_ work, but seems really complicated and
indirect. Maybe it could be used for hexagonal grids?

Good design is choosing the right algorithms and data structures.
Encapsulating a bad algorithm or a poor structure will not make it any
better.

regards,
Filip
Anonymous
August 27, 2005 9:02:26 PM

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

John <4gjehIqp@mailinator.com> wrote:

> On 2005-08-26, Andreas Koch <nospam@kochandreas.com> wrote:
>> Depends on what you are targeting. If you only want to run on
>> modern Wintel PCs, RAM is no limit. But you should consider that
>> a gig is more than many CURRENT super market PCs have (at least
>> here in germany), and many people still run boxes with Win98 and
>> 64 Meg (and no .NET ... )...
>
> And what roguelike, no matter how bloated, doesn't run on 64MB?
>
>> If you want to port on something like PDAs with 2 Meg of Memory
>> for disk and working RAM, it DOES matter if that 100x100 map
>> needs 100x100 bytes or 100x100 pointers+byte+etc ...
>
> What color screen PDA made in the last 5 years has only 2MB of
> memory? Please provide a model number and link.

Almost all of them, actually. You see, the "memory" advertised is the
combined heap+storage, but almost all of it is allocated for storage.
So on, for example, my Palm Tungsten E (32MB), the heap is only 2MB. On
16 meg Palms, you've got 1MB of heap. On phones, you could have even
less.

--
CalcRogue: TI-89, TI-92+, PalmOS, Windows and Linux:
calcrogue.jimrandomh.org/
Remove the "NOSPAM-" from my e-mail address to contact me.
Anonymous
August 27, 2005 11:27:54 PM

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

John <piQqySNI@mailinator.com> wrote:
>On 2005-08-26, Andreas Koch <nospam@kochandreas.com> wrote:
>> > And what roguelike, no matter how bloated, doesn't run on 64MB?
>> OP was talking about using .NET, with a 20 meg runtime.
>
>That leaves 44 MB. Your roguelike doesn't fit in that?

*Windows* doesn't fit in that.
--
Martin Read - my opinions are my own. share them if you wish.
\_\/_/ meteorites are outta sight but this one's place is in outer space
\ / if you wanna know i'll tell you why it's cause radiation makes you die
\/ -- Zombina and the Skeletones, "Meteorite"
Anonymous
August 28, 2005 1:10:47 AM

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

U¿ytkownik "Jim Strathmeyer"
<strathWHATEVERIGETENOUGHSPAMANYWAYS@ipass.net> napisa³ w
> I don't see what the big deal is. Asking questions like this and
> only
> seeing pro/con OO reactions is sort of useless. How you implement
> maps
> and tiles depends upon how much you want tiles to be able to do,

Right!

> But every time
> you encapsulate something as an object, you make it easier to extend
> and
> refine it.

No! If the boundaries between classes force you to make requent calls
between objects or duplicate data they contain, you end up with
something very hard to extend or refine.

regards,
Filip
Anonymous
August 28, 2005 1:10:48 AM

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

Filip Dreger <fdreger@amiga.pl> schrieb:
> U?ytkownik "Jim Strathmeyer"
> <strathWHATEVERIGETENOUGHSPAMANYWAYS@ipass.net> napisa? w

>> But every time you encapsulate something as an object, you make it
>> easier to extend and refine it.

> No! If the boundaries between classes force you to make requent calls
> between objects or duplicate data they contain, you end up with
> something very hard to extend or refine.

Ok, then make that "every time you correctly encapsulate something as an
object". You can always come up with examples of badly doing good
implementation.

--
Jim Strathmeyer
Anonymous
August 28, 2005 1:32:08 AM

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

In article <430f8830@news.broadpark.no>, Elethiomel <kkkk@lllllll.mmmm> wrote:
>John wrote:
>
>> Everyone in this newsgroup who uses a non-color screen PDA with 2MB of
>> memory on a daily basis raise your hand.
>
>Well, "on a daily basis" seems to me to make this into a strawman.
>
>I use a Palm ... er, 3, I think it is? on an irregular basis to play
>some simple games on. I have one of those super-simplistic elite-clones,
>and a couple of "make shaded blocks come next to each other" games. A
>roguelike for it would be very cool.

http://roguelike-palm.sourceforge.net/iLarn/

Alan
Anonymous
August 28, 2005 1:49:12 AM

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

On 26 Aug 2005 15:56:37 +0100, Chris Morris <c.i.morris@durham.ac.uk>
wrote:

>"Shedletsky" <mylastname@stanford.edu> writes:
>> > Depends if you highest goal is clean design, or finite ressource
>> > usage ...
>>
>> Well there is that... But most RL maps are smaller than 100x100. So even
>> with a bloated tile object we are talking about map memory footprints on the
>> order of kilobytes here. In comparison the .Net framework code that gets
>> loaded into memory when my program is running is on the order of 20 MB. And
>> that's still not even worth thinking about these days -- the 3-year old
>> laptop I'm developing on has a gig of RAM. For anything you'd want to do in
>> the RL space, memory is basically limitless.
>
>Well, maybe. The major roguelikes (and quite a lot of the minor ones)
>still run fine on my 100Mhz/96Mb machine, and out of a feeling that
>roguelikes shouldn't eat memory or require the 'latest' hardware I'd
>like mine too as well. So far mine's an order of magnitude too slow.
>
>I don't know... it already runs at a reasonable speed on a 450MHz
>machine - is it worth optimising so that it runs on a 100MHz machine
>or should I just give up and expect people to have a machine from this
>decade or so?

You should always try to get your code running on the slowest computer you
can grab. If it runs okay on a 450Mhz, then all it takes is quadrupling
the processing load before it suddenly needs a ~2Ghz computer. (And it will
happen.)

Adom is a prime example - the FOV code runs fine on modern computers -
however, it runs slowly on a Pentium 133 as soon as you cast Farsight. (To
contrast, Nethack's FOV appears to run much more quickly under similar
conditions.)

>Another reason to avoid power-hungry roguelikes, at least on the
>Unix/Linux platform, is that lots of machines are multi-user and so
>while the machine might have 2Gb you'll be in real trouble with the
>admin/other users if you use it all yourself. Similarly with processor
>usage.

That's where nice comes into play - if a user process takes up too much
CPU/memory, it gets niced. The next step is to make an autonice utility
that nices processes based on haw much CPU they recently used.

Even so, there's only so much CPU power a roguelike will use. It generally
sleeps when waiting for user input.
Anonymous
August 28, 2005 5:34:53 AM

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

R. Alan Monroe wrote:
> In article <430f8830@news.broadpark.no>, Elethiomel <kkkk@lllllll.mmmm> wrote:
>
>>John wrote:
>>
>>
>>>Everyone in this newsgroup who uses a non-color screen PDA with 2MB of
>>>memory on a daily basis raise your hand.
>>
>>Well, "on a daily basis" seems to me to make this into a strawman.
>>
>>I use a Palm ... er, 3, I think it is? on an irregular basis to play
>>some simple games on. I have one of those super-simplistic elite-clones,
>>and a couple of "make shaded blocks come next to each other" games. A
>>roguelike for it would be very cool.
>
>
> http://roguelike-palm.sourceforge.net/iLarn/
>
> Alan

Cool, thanks!
Anonymous
August 29, 2005 2:11:17 PM

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

Shedletsky wrote:
> > Thus, you *could* implement them as objects
> > *inside* the map's universe. But the rest of the world should
> > interface with a map, not with a MxN array of Tiles.
>
> Right. This is model that IVAN uses and the one I had in mind when I posted
> the original topic.

If the rest of the universe interfaces with a map (ie, doesn't acquire
and hold onto tile objects), I am really perplexed why it is seen as
easier to create the tile objects at all. Let the responsibility begin
and end at the map.

> > When you build this distinction you then realize your reprsentation of
> > tiles can be arbitrary. There is no need to store monsters "inside"
> > your "tile" structure. And for the vast majority of roguelikes a
> > simple index sufficies to completely describe each tile. At this
> > point, it is simpler code wise, more effecient memory wise, to just use
> > an MxN array of indices.
>
> Definitely it is more efficient memory-wise - that was never contested.
> However, it seems like there is a design advantage to allowing the tiles to
> be objects. For example: If my tile object has an EntityEntersTile(Entity
> *ent) method and I have a Lava tile that burns any entity that steps on it,
> this would be a good place to do ent->TakeDamage(10). Without the object
> model, whenever a creature moves in my map, I will have to do the test (If
> map[new_x,new_y] == LAVA_TILE then...) That's ugly. I want an extensible
> system, which mean I want to minimize special case code like that.

This is exactly the problem I have. Why is map[newx,newy] == LAVA_TILE
considered special-casing, but overriding the
LAVA_TILE::EntityEntersTile() method is not considered special casing?

They are both special casing! If you really wanted to eliminate
special casing, you'd go for a data-driven approach. In this system,
you'd have the Damage data attached to the tile to signifiy what sort
of damage it does. Then, in either map::EntityMoves() or in
tile::EntityEntersTile() you can lookup the tiles damage type and apply
it.

Moving your special case damage code into subclassed EntityEntersTile
has another serious problem. There is no longer one place to look for
to find out what happens when a mob enters a tile. This means it is
harder to get a feel for this code path. It is also harder to
recognize that we've written four different ways that the user could
take damage from a tile, so we really should factor it out into a
data-driven scheme.

> The tiles
> probably will store pointers to all the entities standing on them, to make
> getting a list of entities at (x,y) very fast. This doesn't prevent a
> separate list of entity pointers in the map object for interating over all
> entities (to update their states or what have you).

That is a question of caching. Caching can equally well be done at the
map level. Doing it at the map level has the advantage that you have
one place to update the cache from. You can also add it when you find
it necessary.

> > This also lets you do any other tricks you feel like. For example,
> > breaking your 1000x1000 map into 50x50 chunks can be done seamlessly
> > from the viewpoint of the outside world. Compressing these in ram,
> > swapping to disk, whatever, can be done without dealing with outside
> > TILE references dangling.
>
> I can still do that with a map of tile references. C# is garbage collected,
> so dangling refs are no problem.

So, when the Fire Elemental enters the Water Tile and the
TILE::EntityEntersTile decides to turn the tile into a Pit Tile and
generate a cloud of smoke, you don't have to worry about someone having
acquired the old Water Tile and holding on to an outdated reference?
Garbage collection merely means that the outdated tile isn't freed.
Explicit allocation is better as you are likely to get a hard crash and
thus discover the dangling reference rather than just having odd
behaviour.

For example, in this case, whenever we move a creature there is the
chance that the creature died as a result of the move. If we are
holding onto a pointer to the creature, we need to check to see if it
is dead or not before proceeding with any post-move logic.

Of course, we then have to ask if the Fire Elemental should trigger a
TILE::EntityEntersTile on the new pit tile to see if it falls into the
pit (though in this case, as it flies, it will trivially evade that
trap)

> > Building a KD tree to store creature and
> > item positions for fast nearest searches can be cached and maintained
> > at the level that makes sense.
> > You don't have to worry about the tree
> > becoming invalid because someone with a pointer to a tile changed the
> > monster value there (or, alternatively, making sure the proper dirty
> > notifications get bumped back up to the tile's parent (which requires
> > storing with the tile its parent information - ugh!) whenever the tile
> > set() methods are invoked).
>
> KD tree? Is this like a BSP or QuadTree?

Yes.

> > This is why I'm tired with this tacit assumption that "Everything Is An
> > Object" implies some magical cleaner design. It doesn't. A clean
> > design seeks to minimize the number of objects you need.
>
> Clean design seeks to minimize special case logic.

There is nothing wrong with special case logic in a roguelike. A
roguelike exists in tension between special case logic to provide cool
one off flavour effects, and general purpose logic that tries to
subsume the cases where the special cases match up.

As such, I do not think OOP is best represented by making a hierarchy
of physical objects. Or a hierachy of tile types. While it is
tempting to classify all potions together and all lights into another
group, you inevitably decide that the glowing potion should cast light
and muddle the hierarchy.

What I want when maintaing a roguelike is the ability to understand
what the potential effects of a code path are. It is a GoodThing when
the special cases are staring at you at the base level rather than
hidden under several levels of indirection. Sure, the code looks
uglier. But the code *is* ugly with those special cases! Hiding them
in a #define would be no better. Consider it a good way to remind you
what you still have to find a way to factor.
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)
Anonymous
August 29, 2005 4:21:02 PM

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

The downside to this, of course, it that the tile objects don't know
their own location when methods are called (since they may be in many
places!)

This generally means that you have to pass the map location as an extra
parameter which is somewhat annoying.
Anonymous
August 29, 2005 8:07:28 PM

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

Mike Anderson <mike.r.anderson@gmail.com> schrieb:
> The downside to this, of course, it that the tile objects don't know
> their own location when methods are called (since they may be in many
> places!)

> This generally means that you have to pass the map location as an
> extra parameter which is somewhat annoying.

Can you give examples of when a tile would need to know what map it is
on? Seems unnecessary...

--
Jim Strathmeyer
August 29, 2005 10:51:26 PM

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

On 2005-08-29, Jeff Lait <torespondisfutile@hotmail.com> wrote:
> So, when the Fire Elemental enters the Water Tile and the
> TILE::EntityEntersTile decides to turn the tile into a Pit Tile and
> generate a cloud of smoke, you don't have to worry about someone having
> acquired the old Water Tile and holding on to an outdated reference?

Here is a thought question for everyone. Its a general question not
necessarily directed at this post.

Why is anything other than the map ever "holding onto" a tile?

In real life when you stand in a cave, are you holding the cave or is the
cave holding you? If the situation is different in your game structure
then why is it different and is that a good thing?

I would assert that nothing in the engine other than the map _ever_ needs
to _hold_ a tile. Objects other than the map retaining references to items
contained in the map (tiles in this case) seems like a design problem that
should be fixed.

You can't have a dangling reference if you never have the reference in the
first place.

Just my $.02
Anonymous
August 30, 2005 1:39:17 AM

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

U¿ytkownik "John" <8gnBo6vh@mailinator.com> napisa³ w wiadomo¶ci
news:slrndh6m9e.8pu.8gnBo6vh@mailinator.com...
> On 2005-08-29, Jeff Lait <torespondisfutile@hotmail.com> wrote:
> I would assert that nothing in the engine other than the map _ever_
> needs
> to _hold_ a tile. Objects other than the map retaining references to
> items
> contained in the map (tiles in this case) seems like a design
> problem that
> should be fixed.
>
> You can't have a dangling reference if you never have the reference
> in the
> first place.

Hmmm... As already stated, having tiles as separate objects is asking
for trouble. While you can do a workaround to fix some obvious
problems, they will not cease to exist.
The root of all the evil is that sometimes the player, an item or a
spell must know the exact type of a certain tile. There are two ways
to handle this:
If they extract this knowledge from a pointer, you lose. Because in
roguelikes a lot of actions depend on other actions, some of which
might need the same pointer.
If the map encapsulates the tile objects completely, you lose. Because
at some point you have to translate types of tiles (their classes)
into some kind of enum (hash, whatever) to show to the rest of your
api. You end up with two ways of referencing tiles:

if (container(level,x,y).gettype()==TILE_WATER) entity.drown(); //
inside your map object

if (map.tile(level,x,y)==TILE_WATER) entity.drown(); // in the rest of
your game

This gives your program all the bad sides of both object oriented and
procedural approach, as well as a lot of bloat and inconsistency.
I strongly disagree with Jeff when it comes to data-driven approach,
my own RL is script-driven. But it seems that keeping your object
hierarchy flat and adhering to the rule 'keep code handling similiar
situations together' helps in both cases. I would discourage anyone
from inheriting things like special effects (eg. having 'lava' inherit
from 'hot_tile') and, generaly, using objects where structs do.
Of course while Jeff created two great, playable games, I still
struggle with mine - so it's his authority behind the two tips, not
mine :-)

regards,
Filip
Anonymous
August 30, 2005 3:38:36 AM

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

In article <1125335477.543734.253180@g14g2000cwa.googlegroups.com>,
"Jeff Lait" <torespondisfutile@hotmail.com> wrote:
> Shedletsky wrote:
> > I can still do that with a map of tile references. C# is garbage collected,
> > so dangling refs are no problem.
>
> So, when the Fire Elemental enters the Water Tile and the
> TILE::EntityEntersTile decides to turn the tile into a Pit Tile and
> generate a cloud of smoke, you don't have to worry about someone having
> acquired the old Water Tile and holding on to an outdated reference?
> Garbage collection merely means that the outdated tile isn't freed.
> Explicit allocation is better as you are likely to get a hard crash and
> thus discover the dangling reference rather than just having odd
> behaviour.

Better approach: Make all tiles singleton classes.

i.e., there is exactly one instance of each type of tile, so there is no
such thing as an "outdated reference". There's only one object to have
a reference to.

There are occasions when using objects for tiles might be cleaner than
the alternative, although you can certainly argue either way. For
example, consider a game where every type of terrain has a different
degree of visibility, from 0 to 100%. High mountains have 0%
visibility, causing LOS to stop at that tile. Open grassland has 100%
visibility, allowing LOS to pass through unobstructed. Light forest has
50% visibility--it takes two tiles of forest to terminate LOS.

You could assign an integer to each terrain type, and build an array to
indicate visibility:

vis += Visibility[tile[x][y]];

Or you could make each tile an object and call a method to look up the
visibility:

vis += tile[x][y].visibility();

The former is going to be more efficient, but the latter lets you keep
the definitions of terrain types separate from each other. It also
makes it a bit easier to handle cases such as the the visibility of a
certain type of tile changing without putting special cases in your LOS
code--perhaps druids have the ability to see farther through forests.

- Damien
August 30, 2005 4:22:54 AM

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

Jim Strathmeyer <strathWHATEVERIGETENOUGHSPAMANYWAYS@ipass.net> wrote:
> Mike Anderson <mike.r.anderson@gmail.com> schrieb:
>> This generally means that you have to pass the map location as an
>> extra parameter which is somewhat annoying.
>
> Can you give examples of when a tile would need to know what map it is
> on? Seems unnecessary...

The tile doesn't need to know, but there are cases in my game where both
pieces of information (the tile reference and its co-ordinates) are
required in the one function. Of course, they should be (and are) passed
in separately, because giving every tile a reference to its own co-ords
would be an incredible waste of data storage space with no benefit.

--
--jude hungerford.
Anonymous
August 30, 2005 9:20:51 AM

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

Damien Neil wrote:
> In article <1125335477.543734.253180@g14g2000cwa.googlegroups.com>,
> "Jeff Lait" <torespondisfutile@hotmail.com> wrote:
> > Shedletsky wrote:
> > > I can still do that with a map of tile references. C# is garbage collected,
> > > so dangling refs are no problem.
> >
> > So, when the Fire Elemental enters the Water Tile and the
> > TILE::EntityEntersTile decides to turn the tile into a Pit Tile and
> > generate a cloud of smoke, you don't have to worry about someone having
> > acquired the old Water Tile and holding on to an outdated reference?
> > Garbage collection merely means that the outdated tile isn't freed.
> > Explicit allocation is better as you are likely to get a hard crash and
> > thus discover the dangling reference rather than just having odd
> > behaviour.
>
> Better approach: Make all tiles singleton classes.
>
> i.e., there is exactly one instance of each type of tile, so there is no
> such thing as an "outdated reference". There's only one object to have
> a reference to.

Then, instead of storing pointers to the singleton class, we can store
indices into an instantiated array of such classes. We can also
initialize the data fields of the singleton classes from an external
data file, thus letting us add new tile types just by editting one data
file location.

Of course, then we'd just have rebuilt what I've been talking about all
along. The map stores a two dimensional array of indices that are used
to cross reference into a database describing the tile types. In my
case, I use an array of C structs. I believe Filip would want an Lua
assoiative array that lets him make member data functions. You want an
array of classes so you have the option of overloading the classes.

None of these options involve calling new Tile[y*w+x] at any point.

> There are occasions when using objects for tiles might be cleaner than
> the alternative, although you can certainly argue either way. For
> example, consider a game where every type of terrain has a different
> degree of visibility, from 0 to 100%. High mountains have 0%
> visibility, causing LOS to stop at that tile. Open grassland has 100%
> visibility, allowing LOS to pass through unobstructed. Light forest has
> 50% visibility--it takes two tiles of forest to terminate LOS.
>
> You could assign an integer to each terrain type, and build an array to
> indicate visibility:
>
> vis += Visibility[tile[x][y]];
>
> Or you could make each tile an object and call a method to look up the
> visibility:
>
> vis += tile[x][y].visibility();

I would rather do:
vis += map->getVisibility(x, y);

The map then could do:
float
MAP::getVisibility(int x, int y) const
{
TILE_NAMES tile;
float vis;

tile = getTile(x, y);
vis = glb_tiledefs[tile].visibility;

MOB *mob;
mob = getMob(x, y);
vis *= mob->getOcclusion();
}

> The former is going to be more efficient, but the latter lets you keep
> the definitions of terrain types separate from each other. It also
> makes it a bit easier to handle cases such as the the visibility of a
> certain type of tile changing without putting special cases in your LOS
> code--perhaps druids have the ability to see farther through forests.

I don't see how either system would give you that. You haven't passed
down the player's class type, so unless you are hacking your way back
up with a global variable (which would mean all creatures see farther
in a forest if the player happens to be a druid) there are problems...

I guess we could add a MOB * to the getVisibility() call in both
systems. I'd then add that special case in MAP::getVisibility().
Avoids messing up the LOS code, and avoids hiding it inside the forest
tile definition.
--
Jeff Lait
(POWDER: http://www.zincland.com/powder)
Anonymous
August 30, 2005 11:33:32 AM

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

At Mon, 29 Aug 2005 21:39:17 +0200,
Filip Dreger wrote:

> U¿ytkownik "John" <8gnBo6vh@mailinator.com> napisa³ w wiadomo¶ci
> news:slrndh6m9e.8pu.8gnBo6vh@mailinator.com...
>> On 2005-08-29, Jeff Lait <torespondisfutile@hotmail.com> wrote:
>> I would assert that nothing in the engine other than the map _ever_
>> needs
>> to _hold_ a tile. Objects other than the map retaining references to
>> items
>> contained in the map (tiles in this case) seems like a design
>> problem that
>> should be fixed.
>>
>> You can't have a dangling reference if you never have the reference
>> in the
>> first place.
>
> Hmmm... As already stated, having tiles as separate objects is asking
> for trouble. While you can do a workaround to fix some obvious
> problems, they will not cease to exist.
> The root of all the evil is that sometimes the player, an item or a
> spell must know the exact type of a certain tile. There are two ways
> to handle this:
> If they extract this knowledge from a pointer, you lose. Because in
> roguelikes a lot of actions depend on other actions, some of which
> might need the same pointer.
> If the map encapsulates the tile objects completely, you lose. Because
> at some point you have to translate types of tiles (their classes)
> into some kind of enum (hash, whatever) to show to the rest of your
> api. You end up with two ways of referencing tiles:
>
> if (container(level,x,y).gettype()==TILE_WATER) entity.drown(); //
> inside your map object
>
> if (map.tile(level,x,y)==TILE_WATER) entity.drown(); // in the rest of
> your game

Errm...

if (world.getLevel(level).map.getTileKind(x, y).flags & TileKind.IS_WET)
entity.drown()

You need a separate set of objects, called TileKind here, that would
store all the information about the kinds of tiles you need. The map
tiles themselves would only have indices or pointers to the tile kinds.
Right?

--
Radomir `The Sheep' Dopieralski @**@_
(Uu) 3 Sigh!
. . . ..v.vVvVVvVvv.v.. .
Anonymous
August 30, 2005 1:22:30 PM

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

Damien Neil <neild-usenet4@misago.org> writes:
> You could assign an integer to each terrain type, and build an array to
> indicate visibility:
>
> vis += Visibility[tile[x][y]];
>
> Or you could make each tile an object and call a method to look up the
> visibility:
>
> vis += tile[x][y].visibility();

Third option

vis += getVisibility(tile[x][y]);

Very similar to the second option but doesn't require the tiles to be
objects, they can just be ints.

--
Chris
Anonymous
August 30, 2005 2:47:11 PM

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

U¿ytkownik "Radomir 'The Sheep' Dopieralski" <thesheep@ sheep.prv.pl>
napisa³ w wiadomo¶ci
news:slrndh82u8.ulq.thesheep@atos.wmid.amu.edu.pl...
>> If the map encapsulates the tile objects completely, you lose.
>> Because
>> at some point you have to translate types of tiles (their classes)
>> into some kind of enum (hash, whatever) to show to the rest of your
>> api. You end up with two ways of referencing tiles:
>>
>> if (container(level,x,y).gettype()==TILE_WATER) entity.drown(); //
>> inside your map object
>>
>> if (map.tile(level,x,y)==TILE_WATER) entity.drown(); // in the rest
>> of
>> your game
>
> Errm...
>
> if (world.getLevel(level).map.getTileKind(x, y).flags &
> TileKind.IS_WET)
> entity.drown()
>
> You need a separate set of objects, called TileKind here, that would
> store all the information about the kinds of tiles you need. The map
> tiles themselves would only have indices or pointers to the tile
> kinds.
> Right?

You are writing about the idea "_kinds_ of tiles are objects", not
"tiles are objects". The original post referred to IVAN, where:
<quote>
IVAN uses an array of "lsquare" objects to represent the map. These
lsquares
have about 20-30 different fields and at least 150 different functions
handling everything from lighting to the handling of spells.
</quote>

"Each kind of tile is an object" also seems a strange idea to me. I
don't know a single roguelike in which tile properties would change
over time. So the 'type of tile' objects would be entirely static.
They would have no other methods than getters, and probably not even
that.
Now an object without methods is just a struct, nothing else. Nothing
is gained from making objects representing each kind of tile, and some
clarity is lost.

regards,
Filip
Anonymous
August 30, 2005 5:22:42 PM

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

Filip Dreger a écrit :
> U¿ytkownik "Radomir 'The Sheep' Dopieralski" <thesheep@ sheep.prv.pl>
> napisa³ w wiadomo¶ci
> news:slrndh82u8.ulq.thesheep@atos.wmid.amu.edu.pl...
>
>>>If the map encapsulates the tile objects completely, you lose.
>>>Because
>>>at some point you have to translate types of tiles (their classes)
>>>into some kind of enum (hash, whatever) to show to the rest of your
>>>api. You end up with two ways of referencing tiles:
>>>
>>>if (container(level,x,y).gettype()==TILE_WATER) entity.drown(); //
>>>inside your map object
>>>
>>>if (map.tile(level,x,y)==TILE_WATER) entity.drown(); // in the rest
>>>of
>>>your game
>>
>>Errm...
>>
>>if (world.getLevel(level).map.getTileKind(x, y).flags &
>>TileKind.IS_WET)
>> entity.drown()
>>
>>You need a separate set of objects, called TileKind here, that would
>>store all the information about the kinds of tiles you need. The map
>>tiles themselves would only have indices or pointers to the tile
>>kinds.
>>Right?
>
>
> You are writing about the idea "_kinds_ of tiles are objects", not
> "tiles are objects". The original post referred to IVAN, where:
> <quote>
> IVAN uses an array of "lsquare" objects to represent the map. These
> lsquares
> have about 20-30 different fields and at least 150 different functions
> handling everything from lighting to the handling of spells.
> </quote>
>
> "Each kind of tile is an object" also seems a strange idea to me. I
> don't know a single roguelike in which tile properties would change
> over time. So the 'type of tile' objects would be entirely static.
> They would have no other methods than getters, and probably not even
> that.
> Now an object without methods is just a struct, nothing else. Nothing
> is gained from making objects representing each kind of tile, and some
> clarity is lost.

I should remind you that objets don't need properties. You can perfectly
have property-less objects with virtual methods. Such object would of
course be immutable.
Anonymous
August 30, 2005 5:36:28 PM

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

Quoting John <piQqySNI@mailinator.com>:
>On 2005-08-26, Andreas Koch <nospam@kochandreas.com> wrote:
>>>What color screen PDA made in the last 5 years has only 2MB of memory?
>>Who did say color screen?
>Everyone in this newsgroup who uses a non-color screen PDA with 2MB of
>memory on a daily basis raise your hand.

My Psion 5mx doesn't have a colour screen, a useful feature which means
the batteries actually last. Since the "memory" serves as both memory and
disc, there certainly have been times where a 2Mb memory footprint would
be awkward. It runs NetHack...
--
David Damerell <damerell@chiark.greenend.org.uk> Kill the tomato!
Today is Second Monday, August.
Anonymous
August 30, 2005 5:41:27 PM

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

Quoting Jeff Lait <torespondisfutile@hotmail.com>:
>This is exactly the problem I have. Why is map[newx,newy] == LAVA_TILE
>considered special-casing, but overriding the
>LAVA_TILE::EntityEntersTile() method is not considered special casing?

Well, to be fair, when you write a new kind of tile, it's a lot easier to
remember to give it all the appropriate special-case methods.

[But I concur that data-driven is superior to either approach.]
--
David Damerell <damerell@chiark.greenend.org.uk> Kill the tomato!
Today is Second Monday, August.
Anonymous
August 30, 2005 10:43:05 PM

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

In article <1125404451.955539.257550@g44g2000cwa.googlegroups.com>,
"Jeff Lait" <torespondisfutile@hotmail.com> wrote:
> Damien Neil wrote:

> > Better approach: Make all tiles singleton classes.
> >
> > i.e., there is exactly one instance of each type of tile, so there is no
> > such thing as an "outdated reference". There's only one object to have
> > a reference to.
>
> Then, instead of storing pointers to the singleton class, we can store
> indices into an instantiated array of such classes. We can also
> initialize the data fields of the singleton classes from an external
> data file, thus letting us add new tile types just by editting one data
> file location.

....which adds an unnecessary extra level of indirection. If you're
using singleton classes, there's no reason not to store the pointer.
That's what singletons are for.


> > You could assign an integer to each terrain type, and build an array to
> > indicate visibility:
> >
> > vis += Visibility[tile[x][y]];
> >
> > Or you could make each tile an object and call a method to look up the
> > visibility:
> >
> > vis += tile[x][y].visibility();
>
> I would rather do:
> vis += map->getVisibility(x, y);

The two options I presented are different ways of implementing the
getVisibility() method on the map object.


> I don't see how either system would give you that. You haven't passed
> down the player's class type, so unless you are hacking your way back
> up with a global variable (which would mean all creatures see farther
> in a forest if the player happens to be a druid) there are problems...

Obviously, if the viewer can affect the visibility of different tiles,
you will need to include that information in the call to whichever
function or method contains the special-case check implementing that
feature.

- Damien
Anonymous
August 30, 2005 10:44:13 PM

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

In article <87psrvltq1.fsf@dinopsis.dur.ac.uk>,
Chris Morris <c.i.morris@durham.ac.uk> wrote:
> Damien Neil <neild-usenet4@misago.org> writes:

> > vis += Visibility[tile[x][y]];
> > vis += tile[x][y].visibility();

> Third option
>
> vis += getVisibility(tile[x][y]);

You may consider my examples to be alternate ways of implementing the
getVisibility() function.

- Damien
Anonymous
August 31, 2005 9:03:48 AM

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

John wrote:
> Why is anything other than the map ever "holding onto" a tile?

In my game the map is a representation of tiles. Some of those
tiles may contain an object, but the map doesn't know that (in
the object level). Only the objects are aware of the map. This
makes the map fast to draw in each turn (I'm using a scrolling map)
because only those objects that move will change the map in
their place.

Every tile is an object in all roguelike games, but (usually) in
a simple way, contained by a map.
When objects are holding onto a tile the tile becomes a container:) 
Anonymous
August 31, 2005 12:12:57 PM

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

Damien Neil wrote:
> In article <1125404451.955539.257550@g44g2000cwa.googlegroups.com>,
> "Jeff Lait" <torespondisfutile@hotmail.com> wrote:
> > Damien Neil wrote:
>
> > > Better approach: Make all tiles singleton classes.
> > >
> > > i.e., there is exactly one instance of each type of tile, so there is no
> > > such thing as an "outdated reference". There's only one object to have
> > > a reference to.
> >
> > Then, instead of storing pointers to the singleton class, we can store
> > indices into an instantiated array of such classes. We can also
> > initialize the data fields of the singleton classes from an external
> > data file, thus letting us add new tile types just by editting one data
> > file location.
>
> ...which adds an unnecessary extra level of indirection. If you're
> using singleton classes, there's no reason not to store the pointer.
> That's what singletons are for.

Ignoring the potential savings of using a smaller index than 64 bits,
there are a few other advantages of indices:

1) Marshalling is already done. To save out the tiles, you can just
save the indices. You don't need to write save/load code for each tile
(which will likely just save and load an index anyways, so it's not
like you won't have indices somewhere with singleton classes)
2) Sanity tests are straight forward. The set of values allowed for
elements of your map array are nicely bounded. This lets you throw in
some run time asserts to catch invalid values.

Finally, I am somewhat confused about the extra level of indirection.
I believe you are proposing data-less singleton classes which override
the visibility() method to get the data?

The index based method does one look up to get the index. It then does
a second lookup to get the visibility value
  • . The singleton method
    does one lookup to get the singleton class. It then does a second
    lookup to get the pointer to the visibility method from its virtual
    function table. It then does a function call to the visibility method.

    Both systems seem to have the same amount of indirection? Virtual
    function tables just hide indirection - they don't eliminate it.

    > > > You could assign an integer to each terrain type, and build an array to
    > > > indicate visibility:
    > > >
    > > > vis += Visibility[tile[x][y]];
    > > >
    > > > Or you could make each tile an object and call a method to look up the
    > > > visibility:
    > > >
    > > > vis += tile[x][y].visibility();
    > >
    > > I would rather do:
    > > vis += map->getVisibility(x, y);
    >
    > The two options I presented are different ways of implementing the
    > getVisibility() method on the map object.

    Then I do not understand the advantage of making it a function? If
    this code path only exists inside of MAP::getVisibility(), there is
    nothing to be gained by hiding away the tile[x][y].visibility()
    function. We aren't reusing it, so why factor it? It is much better
    to put all of your special case code there, in one place, where it can
    easily be refactored across tiles.

    Finally, I'd definitely go for the third method for doing it inside of
    the map object:
    vis += glb_tiledefs[getTile(x,y)].visibility;

    > > I don't see how either system would give you that. You haven't passed
    > > down the player's class type, so unless you are hacking your way back
    > > up with a global variable (which would mean all creatures see farther
    > > in a forest if the player happens to be a druid) there are problems...
    >
    > Obviously, if the viewer can affect the visibility of different tiles,
    > you will need to include that information in the call to whichever
    > function or method contains the special-case check implementing that
    > feature.

    Which means changing the prototype for the visibility() method and thus
    updating the visibility() method on all of your tile classes. Yay!

    That seems like another good idea to stop the function call tree at the
    map level.

  • I'm assuming that the tile definition is stored in a static global
    structure, allowing its address to be constant. The compiler thus
    doesn't have to do a read to find the address of the start of the
    global tile definition structure, so can directly calculate
    &glb_tiledefs[index].visibility from the index alone. If you
    dynamically allocate the glb_tiledefs, perhaps to initialize from a
    data file, this advantage goes away. However, we aren't comparing
    apples with apples then, as I don't think you can't easily initialize
    your class hierarchy from a data file either.
    --
    Jeff Lait
    (POWDER: http://www.zincland.com/powder)
    Anonymous
    August 31, 2005 2:52:49 PM

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

    Damien Neil a écrit :
    > In article <1125404451.955539.257550@g44g2000cwa.googlegroups.com>,
    > "Jeff Lait" <torespondisfutile@hotmail.com> wrote:
    >
    >>Damien Neil wrote:
    >
    >
    >>>Better approach: Make all tiles singleton classes.
    >>>
    >>>i.e., there is exactly one instance of each type of tile, so there is no
    >>>such thing as an "outdated reference". There's only one object to have
    >>>a reference to.
    >>
    >>Then, instead of storing pointers to the singleton class, we can store
    >>indices into an instantiated array of such classes. We can also
    >>initialize the data fields of the singleton classes from an external
    >>data file, thus letting us add new tile types just by editting one data
    >>file location.
    >
    >
    > ...which adds an unnecessary extra level of indirection. If you're
    > using singleton classes, there's no reason not to store the pointer.
    > That's what singletons are for.

    Not really. An object pointer is 32bits or even 64bits on some
    architectures whereas you will probably never get more than 65536
    different tiles and so a 16bits should be enouth and most of the time,
    8bits would do the work too.

    Also, there could be a real speed advantage if you use that level of
    indirection. In the case that all the tile types are perfectly know at
    compile time, you can use a switch case instead and the compiler should
    be able to optimise away all the virtual function calls because the type
    of the object is perfectly know at compile time.
    !