Room Interface
Go provides a concept of "interfaces": essentially bits of functionality that all types to implement that interface must have. A similar concept can be emulated in C++ by using base classes, but it is implicit rather than explicit in go.
E.g. something like this:
type Fooer interface {
Foo()
}
Any type that has a method Foo() will automatically implement the Fooer interface.
Now, after that interlude, what do you think that the interface defining rooms should look like? This is for the server-side, the interface on the client-side will likely be different (although have many of the same methods). How is this handled in the current code, where it is presumably emulated through a base class?
I remember the concept of interfaces from Objective-C. It's actually pretty neat to get around ugly multiple inheritance stuff.
I think a room should provide such information as:
- Location and size
- People currently inside the room
- People spawned/owned by the room (Offices spawn Office Workers, Hotel Rooms spawn Hotel Guests, etc.)
- Population contributed
- Functions for putting people into the room and taking them back out, possibly in combination with a similar call to the person being moved to an item.
- Mechanism that determines whether a room is reachable from the lobby. This needs to be re-evaluated whenever the transportation layout changes.
There's probably a lot more. The current implementation in C++ contains a whole bunch of other stuff in its OSS::Classic::Item class that handles rendering of the room.
Unfortunately I'm absolutely unfamiliar with Go, except from what I've read on the start guide on the website. I don't know what language constructs are available for things like vectors (location and size of rooms).
I think you should make a new directory source/server and start putting Go files there so I can have a look at how things specific for this project look in Go and think of some interfaces :)
PS: Currently, everything that you can build is derived from the Item class which provides basic rendering and construction functionality (not only as an interface, but also some basic implementations of such functions). Rooms then derive from FacilityItem : Item, transportation from TransportItem : Item. But it's probably best practice to not look at the current code structure too much, I originally intended it for massive extension for the Deluxe version. Now I think we'd be better off getting the Classic stuff running and then writing a entirely new foundation for any further developments.
I've started working on this in the very preliminary stages (super busy lately) on my fork. Your suggestions are all helpful, but I have a few questions:
- How do rooms "spawn" people? Don't they have to get there by elevator or other transportation first?
- How does population contributed differ from people currently inside the room? Is this just an efficiency thing (e.g.
return len(people)rather thanreturn people)? - Why does each room determine it's own transportation? It would seem more logical to have some kind of transportation manager that determined these things, although I have no idea how to go about implementing one... this seemed the most difficult part of OpenTower to me.
Vectors are not commonly used in go, arrays are used instead. Although you have to manually size these, slices can provide something similar to dynamically-sized arrays. If you allocate an underlying array bigger than you need at the current moment, you can "grow" the slice as you need more storage (until you hit the array limit, in which case you have to reallocate). Usually I just use append(), since my arrays contain almost all pointers, and the reallocation cost is usually trivial. Might be more difficult with the large numbers of rooms we will have to deal with.
I'll look at your code for Item and inheriting classes, it looks clean and well thought out (on the surface at least :P). I would be against re-implementing and rewriting everything, simply because it's been done... 3 times before :). A lot of the code may need to be adapted to the client-server model, but adapting the existing code would likely be easier than writing new code. The fact that you planned for a future version is not necessarily a bad thing, just so long as you didn't over-engineer everything. Every programmer is brutally aware of the flaws in his own code, or else is lying to himself.
- In the model of the current implementation, a room like an office is responsible for creating instances of
Personin memory. These instances implement a minor A.I. that tells them when to enter the tower and go to which room. My programming style originates in user interface-heavy application development, so my approach to object models is usually not the fastest but the one to provide most strict separation of hierarchy functionality separation. So it actually might be a good idea for a game to split things up and have the room not be responsible for getting sold or vacant, etc.. -
Population is supposed to be a number, but it should rather by called
contributedPopulationsince it should not return how many people there are in the room at the moment, but how many people are considered to be living in this tower. This might be trivial for offices (0 if for rent, 5 otherwise), but fast foods seem to set this value to the number of patrons of the day after closing at 21:00. We should probably have a mechanism where an item may tell the item manager thatpopulationChangedwhich causes the manager to set a flagbool needToRecalculatePopulation. If the flag is set for more than say 500ms the server actually recalculates. This is an extreme form of lazy evaluation called delayed evaluation which is an important concept in GUI programming since it allows items to freely ask for population updates without them being executed at once. This effectively limits the number of calls per time to a given function which greatly enhances speed. - The transportation issue falls into the same category as the first one. In my approach an item asks the tower's pathfinder to check whether there is a route to it. Again this is likely to be better moved to a transportation manager which handles everything.
I hope that Go is up for this task. I figure there's stuff that's incredibly hard to do without certain C++ language specifics (operator overloading and the like).
Something we should rewrite in its entirety is the construction stuff. It is highly trimmed for further expansion which makes the code a pain to maintain and ridiculously complicated for simple construction stuff as in the original SimTower.
PS: I meant the actual mathematical vector as in quantity and direction, not the array :)