Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - mike3

Pages: [1] 2 3 ... 9
Programming / Re: pedantic object oriented question
« on: October 06, 2013, 10:25:05 PM »
Well I don't know how you've written your event system, but I can see a potential problem. If event 1 modifies the map but event 2 has an old copy of the map, it might be working with old data. What does your event loop look like?

There's a priority queue, ordered by logical time. The most recent event is fetched, handled, and then the time remaining on the other events is decreased, and the new most-recent event is handled next, and so forth. There is only one map in use at any time (that is, the map the player is on), and I was just thinking of passing a reference/pointer to the map. Copying the map over and over sounds like it'd make for huge overheads anyways.

Programming / Re: pedantic object oriented question
« on: October 06, 2013, 11:15:06 AM »
Never mind. I decided to implement it anyway. You can't expect to make something "impossible" to break if it isn't used correctly...

Programming / Re: pedantic object oriented question
« on: October 06, 2013, 03:16:26 AM »
There are two ways the critter can know about the map (well, three, but let's exclude global variables for the moment). It can have a reference to the map, or you can pass it the map. You seem to think the first way is the only way to do it, but there's nothing wrong with the second, and IMO it's a better idea than the reference.

Actually, I had considered such a possibility. But I wasn't sure how to make it work here. When a door is opened/closed, it is passed an event from the event queue, which it handles to open/close. Not sure whether it'd be a good idea to pass a map in the event object. I suppose it'd be OK, though, but one has to be sure not to send the wrong map. I guess that would be my concern, that such would be bug-prone.

Programming / Re: pedantic object oriented question
« on: October 05, 2013, 09:55:22 PM »
Hmm. I'm curious: if the critter object doesn't know its map, then what do you do with something as basic as this: movement. Suppose your "Critter" object has a "move()" method, which, well, makes the critter move. Seems reasonable, no? But then you have to check for walls, etc. (you don't want your critter to move through the walls (unless it's a ghost or something)!) which means you need access to the map. Plus, if the map contains a reference to the critter attached to the tile it's standing on, that needs updating. So what should one do? What should that call to "move()" do?

In that particular design the move() method should be in the map rather than the critter because the map is the only object with the required context to actually perform the operation. The only way the critter could really know how to move is by accessing the map anyway (by a cached map reference in the critter or the map being passed as an argument to an update() method).

This doesn't occur to a lot of people because standard teaching of OOP is just hideously bad. The focus on the intuitive real world concept of objects just leads to tears in the end. Intuitively it feels like the move() method should be on the critter because critters move but that's not how you should decide where methods live.

Because a critter can't stand in the same cell as other critters you need more contextual information about how to perform the action (i.e. where the other critters are). Also a move can fail for reasons beyond a critter being in the way, e.g. lava, walls. The only place where all the data is at hand is the map object, so move() should go there.

I'm resurrecting this thread, because I want to come back to this point as I've noticed something else here: doors require access to the map too, to open and close, since they need to check if they're blocked. So now it seems the map would acquire an open/close method for doors as well. It seems the map is gaining more and more responsibilities to make up for the lack of a reverse reference... violating the one-responsibility principle. Isn't that bad?

Programming / Re: "Game time"
« on: September 16, 2013, 03:21:29 AM »
Perhaps this is the source of difficulty: in the program as it exists now, I use an internal unit of "ticks" to separate various events on a queue. Each entity that does something has a place on the queue which represents when it acts. So there may be 1000 ticks (say) of this between actions (it depends on the entity's speed). But this queue doesn't relate directly to the time represented on the clock. An entity gets 1000 ticks (say) between actions, but such an action may take a lot of clock time, e.g. the player walking on difficult terrain. Are these kind of ticks the same as what you are calling "ticks"?

Programming / Re: "Game time"
« on: September 14, 2013, 09:00:15 PM »
I'm not sure about something here. When you're on the world map, no combat maps have been generated (they are generated upon encountering an enemy). So the game is not dealing with movement across the combat map, but on the world map itself. Are you suggesting to use the size of the combat map just to get a number, as opposed to having to have one generated at the time? But if a world map tile represents, say, 2 km, and a regular map tile 2 m (for example), then that'd need a ridiculously huge combat map of 1000x1000 (bigger than any dungeon map!) to get the right travel time via that method.
It's just a possibility. I don't know how crazy you are about perfect realism (I've seen some people on this forum and IRC who would settle for nothing less). It might not be practical to run A* on a 10^6 tile map every time the player moves on the world map, but who would want to deal with combat on a map that size anyway? And who would take 6 hours to walk 2km?

That's right, so I wouldn't have the combat map that huge... yet the tile still needs to represent 2km. Also, 6 hours and 2 km were pulled from my head separately.

And my question was also about the logical vs. game time thing. A tile movement may take 6 hours, but each action may correspond to only a small number of logical ticks (for example, an entity of speed 1.0 may have, say, 1000 logical ticks between actions, which does not necessarily correspond to the amount of in-universe-clock time spent.). That's the discrepancy problem I was wondering about. Should one try to make the logical time and in-universe time in 1-1 correspondence, or what? (so that a move across the world map advances the logical counter a million ticks, for example)
It all depends on the system you use. If the combat map of a world tile is supposed to be a literal map of the whole extent of that tile, then it should probably take the same time (or approximately the same time) to traverse it in either mode. If it's just a representation of a typical region within that world tile, then it doesn't matter what you do in that tile - time stops on the combat map, and it can't be used for travel. It doesn't matter if it takes 5 game minutes to cross the combat map, because it's just a microcosm of that world tile.

Yes, the combat map is just supposed to be part of the tile. As mentioned, having the entire tile would create a ridiculously-large combat map (1000x1000). In which case, advancing the time by the time required to walk across the map would vastly underestimate the time it "should" take, no?

Also, what should be done if we want to have things that happen at different clock times?

Programming / Re: "Game time"
« on: September 14, 2013, 08:57:06 AM »
I don't see a problem. If a world map tile corresponds to a combat map of a certain size, then the time to traverse the world map tile is the diameter of the combat map divided by the entity's speed. Or if you want to be strictly simulationist for no good reason, you can use pathfinding to find the shortest route across that combat map.

If world map tiles don't correspond to combat maps, then there's even less of a problem - you set an arbitrary travel time for world map tiles, which might be a function of terrain types. If you have difficulty making up numbers, you can calculate the physical size of a world map tile (size of the world map by comparison with a real-world country/island/continent, divided by number of tiles) and divide by 1.5 metres per second.

I'm not sure about something here. When you're on the world map, no combat maps have been generated (they are generated upon encountering an enemy). So the game is not dealing with movement across the combat map, but on the world map itself. Are you suggesting to use the size of the combat map just to get a number, as opposed to having to have one generated at the time? But if a world map tile represents, say, 2 km, and a regular map tile 2 m (for example), then that'd need a ridiculously huge combat map of 1000x1000 (bigger than any dungeon map!) to get the right travel time via that method.

And my question was also about the logical vs. game time thing. A tile movement may take 6 hours, but each action may correspond to only a small number of logical ticks (for example, an entity of speed 1.0 may have, say, 1000 logical ticks between actions, which does not necessarily correspond to the amount of in-universe-clock time spent.). That's the discrepancy problem I was wondering about. Should one try to make the logical time and in-universe time in 1-1 correspondence, or what? (so that a move across the world map advances the logical counter a million ticks, for example)

Programming / Re: "Game time"
« on: September 14, 2013, 08:06:59 AM »
I would pick a small unit of time (a tick) and decide how many ticks there are in a second, how many seconds there are in an hour, and how many hours there are in a day. I would definitely not use numbers from the real world.
The tick small enough for the time of all in-game actions to be expressible as an integer number of ticks. That might mean that 1 tick = 1 second and all actions take one tick, or it might mean that 100 ticks =  1 second and action times are rounded to 2 decimal places. A middle ground would be 2 ticks = 1 second and action speeds can be 1 tick, 2 ticks, or 4 ticks.
If you want to express action times in terms of speed rather than time, you might consider an energy system.

However, what about terrains with differing movement cost? In "logical time", which is the time used to sequence actions or events from entities, movement might take some number of ticks regardless of where you are. But in "game time", it might take 6 hours to move across a world map square, while only a few seconds to traverse a dungeon map square (because the world map square represents a much bigger area "in-universe".). So what do you do?

Programming / "Game time"
« on: September 14, 2013, 05:15:34 AM »

I was wondering about this: what are some good ways to do an "in-game time" system, that is, where there's a count of hours, days, etc. in addition to the turns and "logical time" used by the game logic, which is "ticks" or whatever, and where, for example, moving over a terrain takes a certain number of hours, and things can happen at certain times (measured on this hours/days/etc. clock)?


I was wondering about this now. On this thread:

I discussed some stuff with regards to how to program movement in a roguelike without the "critters" containing a reference to the map which they're on. One suggestion was to have a move method on the map itself, but what about other commands that require detecting if another critter or object is on the map, like kick? It seems that adding "kick" now to the map starts to sound like too many responsibilities for the map! Doesn't it make more sense to have that on the critter?

The discussion also went to the topic, which I discussed some more in later threads, of "component" architecture. It was mentioned in the referenced thead also that "throwing away code" is not a good idea (since I'm not using a component system now), but also was said "You might try encapsulating a few of the ideas into what you already have-- breaking the logic of your game into component-systems is a very good idea whether you are OOP or DOP.". Though I don't still yet have a good, strong feel for the component architecture, but it was mentioned that the systems in component architecture should be just stateless functions operating on a database... isn't that DOP? What would be the way to handle these kinds of commands (kick, talk, etc.) both in a component and also a more "traditional" non-component setup like I have now, since it seems a move to component would be a total redo of all the progress acquired so far?

Programming / Re: Window managers and "printing messages"
« on: August 14, 2013, 11:52:17 PM »
I updated the post to include some more questions.

Programming / Re: Window managers and "printing messages"
« on: August 13, 2013, 11:01:57 PM »
Comments but also some more questions:

I think it makes it easier to develop if the Game isn't working with a wide variety of Event objects. You can make Events be the product of composition instead of inheritance by passing an array of objects that would represent the construction parameters. Usually the first element would need to be an enum or flag to indicate the type of the event.

However, in the languages I'm using (C++), an array must all be of a single type, yet depending on the kind of event we may need parameters of multiple types. E.g. a message event may take in both a message -- a string -- and also a color -- a number -- to display it as. So a single array would not work. A "ChangeLevel" event (signals that we are transitioning to a different level map) would have to pass a reference/pointer/handle/etc. to the new level map -- yet another type (though a handle might still just be a number). So we have strings, numbers, pointers to level maps. That's 3 different types right there. An "explosion" event might need a reference or handle for the asset of the explosion, PLUS a coordinate indicating where it happens. So there is 2 types in the same event: reference/handle to asset and a coordinate (which in my program is a single type and not just two numbers separate from each other).

What do you suggest should be done in this case?

Prompts are pure UI. They're simply a menuing schema to help the player communicate to the game what s/he wants to do. Or rather, prompts/menus help the user fill out the parameters necessary to produce a game action that makes sense. In this vein, I don't use callbacks. The Game propagates an event saying what type of situation the player is in and what range of actions are available. The UI is responsible for formatting that information in a way that helps the user select an action and send it to the game. I just don't see where there is a need for a callback (in this case). Even if the action being taken doesn't have to do with the scheduling of the game, it's still a 'wait for player action' scenario, so, again, as long as the UI knows which actions to present to the player, you don't need anything fancy. I don't see any harm in using a callback though.

Why callbacks? Well, the answer was discussed earlier in this thread. We have a main loop (this is not the game logic loop, but the main program loop), which fetches the input and passes it to the window manager:

Code: [Select]
Loop until (stopping condition):
          input = inputSource.grabInputEvent();

or something like that. So there's a simple sequence input -> logic -> render involved. The input goes into the window manager and then to the pane that's focused. Note that the above loop is sort of akin to a Windows message loop in a Windows program.

The reason for the callbacks is to keep things so that all input-getting and render is handled by that loop. Suppose we press a key to do something in the game, and the logic says it needs a confirmation prompt. The event goes out to the UI object (or the Application, but gets there somehow), and the UI processes it (this all happens when the logic called the receiveUIEvent() thingy). So the UI does something, like put out a pane showing the confirmation prompt. But now in order for input to hit that confirmation prompt, control has to return to the outer, main loop just mentioned. So our logic function must stop there and let control bubble back up to the main loop where the input is gotten and passed on to the UI to handle the prompt. Which means once the prompt is satisfied, the logic must resume, and the callback handles this by calling the logic function that handles everything post-prompt.

The other way I mentioned, which would avoid a callback, would require the UI to spawn a new "pump" (like the main loop just mentioned) when it receives an event, to handle this, creating a blocking call when such a UI event is sent. But it seems this would break the centralization of the getting of input, the logic, and the render and we'd end up ultimately starting a UI pump inside a UI pump.

Or do you know of a third option? If so, what is it? Also, if you use a non-callback option, how do you get the return values from the prompts (whether yes or no was pressed, for example)?

I think that kind of depends. Suppose you send an event for creature that moves in the player's LOS. In this way, the UI can update each move in sequence so that the actions are graphically offset. Alternatively, the event could just throw all the information at once and the UI is just responsible for updating each move in some sequence (which could be canceled by input to skip the animation, or something). The latter case is more elegant and gives your UI more control over how it presents its information. In this sense, you may only 'need' one message sent to the UI that contains all the information about how the game state changed and what actions the game will accept-- the UI can then animate that information or not, doesn't matter to the game.

But it still seems that even in the second approach we need some kind of ordering/sequencing system either way, to, e.g. order monster moves and other things (if one monster moves first, then there is an explosion, then a second monster moves). We have to know which monster moved before which other one, so some kind of sequence specification seems unavoidable. If we just sent something saying "on this turn there was an explosion, monster A moved and monster B moved", the order is lost. This sequencing information could not be reconstructed by the UI, since it could be just the case that B moved before A as much as A moving before B, unless it is explicitly provided. We don't even know whether the explosion came between the moves of A and B or not. Unless you're suggesting to dispense with chronological accuracy, in which case sending a single giant command might work.

So how do you propose to address this?

That's what the WM is for. You make a selection to start a new character. That menu sends a message to the WM to queue up all the necessary input prompts to build the necessary parameters to pass into a new game (possibly closing itself out  in the process). The WM should manage which inputs go where.

In what I have now, the menu is a pane, and panes are registered with window managers. They know their window manager, so all it does is fire up a new pane for the selected menu option and then close itself. The PC-generation wizard then is just the sequence of panes, with an object passing from one to the next that accumulates the parameters that have been input, and then at the end a new PC is generated and goes into the game.

It would seem also that the UI object would need to sense when the panes for the game are open so it can properly handle game UI events, though. Of course, since it knows about the WM and panes, then this shouldn't be a problem.

Inventory screen is typically pure UI, though you could make it so that looking at inventory is an action sent to the game which then responds with a UIEvent that provides all the information necessary to present the inventory. In this case, that action doesn't consume a turn, so the game is still waiting for an action that results in a game update.

And this is where the callback would also come in handy. The inventory screen could get an item, or it could be dismissed. If the pane is dismissed, then it doesn't call the callback that runs the turn logic.

Traditional Roguelikes (Turn Based) / Re: Lips of Suna (now at 0.7.0)
« on: August 12, 2013, 10:05:44 PM »
The starting post in this thread, at the top part at least, pretty well sums it up---crazed dungeon crawling of the world saving variety with an odd edge to it.   :D

Yes, but what about the specific meaning of the name? "Lips"? And is "Suna" the name of the dungeon complex, or the world?

Programming / Re: Window managers and "printing messages"
« on: August 12, 2013, 08:52:09 PM »
Didn't read the whole thread- sorry.

There are, probably, at least 2 forms of feedback. Real-Time and Event-Driven. In a turn-based game, everything is Event-Driven.

The "Game" is a Server and the UI is a Client.

The game is turn-based, so the server is oftentimes waiting for input before updating. When the game updates, the Server sends information to the Client, which then decides how that information should be presented to the player. In a similar manner, the UI captures the input and evaluates it at an application level to determine if it is used in the game, if it is, it gets passed to the server.

So-- a generic UIEvent is produced by the Logical Game whenever anything happens, and the Application passes that information down Window Management until something happens.

Let's say you have a 'more' prompt or a confirmation message-- that's ALL UI, it has nothing to do with your game logic.

Similarly, your UIEvents shouldn't target specific windows/panes, but should allow any Client to process that information however it wants. When you take damage, you may want the screen to flash red, the HP bar to go down, and a message in the log saying "You've been hit." The game logic shouldn't know any of that.

A server client relationship, I think, is a good way of looking at the relationship between the UI and the Game. They each have their own logic designed to work with each other, but not dependent of each other.

So would this work? I'm not sure if this is 100% in line with your ideas, but it seems it'd achieve the separation I desire (of UI and logic). One would have a distinct UI object, which can catch UI events. Buried inside the UI object is the window manager and panes. There is an interface available, which is what we can pass around -- that takes up UI events (UIEvent objects). Call it a "UIEventReceiver", for example. It might only provide a single method -- "receiveUIEvent()", for example -- and that's it.

We have the whole program as an "Application" object. Within this is a UI object and GameLogic object. The only thing the GameLogic object knows about the UI object is the interface to pass events (UIEventReceiver). Note that if we want to modify the UI to be a different kind, e.g. a graphical one instead of a console one, or to use a different set of panes, or whatever, we just rewrite the relevant parts of the UI object and the GameLogic and everything associated with it is unaffected, since it only cares about the UIEventReceiver interface and sees and knows of nothing else.

But here's where I'm not sure if this works with what you suggest: You mention that Application passes down to the window manager, etc. In the setup I mention above, the thing that receives the UI events is ultimately the UI object. Should Application receive those events instead and store the window manager/panes itself?

When the game logic wants to do something to the UI, like print a message, it sends an event. You mention "UIEvent" is "generic". What does this mean, that it has no derived types? But different types of events may require different parameters. For example, a "warning event" (which may flash the screen red, for example) may not have any parameters, while a "message event" (to print a message) must carry with it the message to be printed, and a "prompt event" must carry with it the prompt text, range of options available (yes/no, a direction, whatever), and also the callback functions to be invoked upon choosing an option. This suggests UIEvent should have derived types for each of these various kinds of event.

Also, when we send UIEvent to the UI object or Application object (?), what should happen right there? Should it be put on a queue of some kind, and then the logic has to finish before the event can be handled (which happens in the outer "main program loop" that pumps the UI), or should it get "handled right then and there", e.g. a pane with the prompt is opened, or the message is stuck in the message buffer, or whatever "thing" the UI does in that case is done?

Also, what about the non-"game" parts? That is, the main menu and player generation screens. These require different panes than the game -- but how do we handle the invoking of them? How is the UI told it needs to do these special actions, when "panes" are an internal? Is it time to resurrect the "game state" idea, but as part of the UI or the Application -- that is, the UI or Application has a number of states, e.g. "Menu" and "Game", and there is a transition which shuts down or loads the appropriate panes? Or is there another way you might know of -- especially since you mentioned in an earlier post the whole window/pane system functions as a kind of state in itself, so it'd seem redundant to have an additional state mechanism in there? What would your suggestion of a mechanism for this be?

And what about when we do the inventory screen? Though I suppose this isn't as much of a problem, since when the UI gets a command requiring inventory, it could just open the screen right there, before the game logic knows about anything. The situation would seem to be different for commands requiring confirmation prompts, like moving on a dangerous piece of terrain, since that requires some game-logicy stuff, namely the evaluation of terrain difficulty, before a prompt can be issued. I'd imagine the UI would pass such a command straight on to the game logic, and it notifies the UI of the confirmation. Or do you suggest some other way?

Traditional Roguelikes (Turn Based) / Re: Lips of Suna (now at 0.7.0)
« on: August 11, 2013, 11:40:31 PM »
I'm curious: what is this game supposed to be about (when completed)? With a title as strange as that...

Pages: [1] 2 3 ... 9