ORIGINAL: cwie
And the same applies here.
Great! I really hate it when good discussions go bad due to misunderstandings.
ORIGINAL: cwie
Yes, but not at design time!
True, but I don't think it matters. The DLL will get its data in one of two ways. It will either be passed an object or record that contains all of the data or it will be passed the address of an object that will give it the data when it asks for it.
Either way, the DLL will have to have access to the interface of that object or record. (Earlier when I said the minimum documentation would be the interface section of the DLL, I was wrong. The interface section of the global data object or the data interface object will have to be published as well. (How's that for too many uses of the word interface [:(])
It is common for separate encapsulated segments of a project to use the same interfaces.
ORIGINAL: cwie
A key point of a DLL is to enable development of code that does not directly understand it's enclosing framework - it interacts with the exe via a clearly defined (and limited) interface.
I agree with that statement in general, but there are specific situations where it can be more encompasing.
One would be a situation where a piece of software was sold to different customers with different levels of functionality (and at different prices). The main module would expect 'FOOBAR.DLL' to exist but would not necessarily know which version of 'FOOBAR.DLL' was there. As long as the interfaces matched it doesn't care how the DLL does its thing as long as it gets done. (This is very similar to what I am proposing if not dead on.)
Another is where the development platform for the main project is not well suited for a specific task and does not play well with other platforms. I worked on a project where the main development was done on a Macintosh. It was an interactive Atlas of the Human Body for medical students. A windows port was required. Some functions that were provided by the MAC OS were not so easily provided for in Windows. The development platform was mostly a 'show and tell' that displayed images. I wrote the DLL in Delphi to handle the 'outline', 'cut' and 'paste' functions that were already there in the MAC version of this package. In this case, it was the main program that was blissfully ignorant and the DLL that had to make do with a limited interface.
ORIGINAL: cwie
This is a two-way street : the DLL code (a) works independant of the details of it's enclosing shell and (b) cannot directly affect it's enclosing shell.
The DLL is encapsulated. It should be able to work with any program that can use its interface. IMO, it
should not directly affect it's enclosing shell - BUT - Depending on how the interface is written and used, it
can. The Main program
can pass a pointer to an object or data structure which the DLL can use and allow it to change the data.
This is why I suggested passing an 'interface object' that can answer the DLL's questions. This prevents disreputable developers from 'cheating'.
ORIGINAL: cwie
Without getting into too much detail, what I mean by 'sync' here is that the AIO DLL needs to keep it's own 'state' in step with the main gamestate. To make decisions, the AIO probably needs to gather and build tables and structures of it's own, which are not visible to the main exe. Incorrect duplication of data is a major source of programming errors ... especially in threaded apps. Unless the AIO has absolutely no internal state whatsoever between calls to it's interface, then syncing is an issue.
If one of the parameters to every call is a helper 'interface object' that can answer questions, the DLL will not have to maintain it's own copy of the game state. It will likely keep track of it's plans to prevent 'double clutching' from turn to turn in close situations, but I would think that reevaluation of 'preconcieved notions' should be a regularly occuring process. How it is triggered is probably best done based on 'what turn/impulse/phase' is it. Every time the game engine calls the DLL, there will be a context to the call. For example, the game engine will not ask which unit to move during the initiative roll phase or ask for builds during a movement phase.
ORIGINAL: cwie
As an example, the AIO probably tries to keep track of the relative 'value' of certain map hexes when determining possible moves. This "AIO internal" data is built from information derived from the gamestate, but updated and refereshed by the AIO. Imagine that as part of the AIO, the main program needs to ask the AIO to determine a land unit movement. The AIO requests info from the gamestate, and updates it's internal data. It then decides to move unit 'X' 3 hexes west, and the program acts on this decision and updates it's gamestate accordingly. Yet this single move may affect much of the gamestate - changing supply states for units and hexes in surrounding areas, cutting rail lines, changing calculations of production/resources, etc . The exe now asks the AIO for another movement. At this point, how much internal state does the AIO need to refresh? Everything? Or can it assume that some data simply cannot have changed since the last movement calculation? If your answer is "it needs to access/refresh all relevant data' then the question becomes "How does the AIO writer determine 'relevant data'"? Unless you understand all possible consequences of all possible actions, you have to either (a) play it safe and gather everything everytime or (b) try to optimise by gathering just what you think is necessary.
Perhaps this is a poor example ... and perhaps having a poor example is an indication of a weak point! But to me if the AIO is a separate logical entity then it will need at least some internal state to operate efficiently.
No, it is a very good example. But I don't think it matters. If the DLL can ask for any piece of information when it needs to access it, then it doesn't need to keep its own copy and worry about sync problems. There are certainly difficulties in planning ahead (as Steve mentioned), but I don't know of any good way around them. If something changes, how can you tell how much it affects your plan unless you replan?
The key is arranging things so that the DLL can ask the game engine for information but cannot directly change it.
ORIGINAL: cwie
Correct, and my use of the turn 'marshalling' may have created confusion. I did not mean to imply inter-process communication or COM interfaces.
OMG -- ANYTHING but COM - I once accidentaly SLAYED a Windows install experimenting with COM.
ORIGINAL: cwie
What I wanted to convey was that when the AIO DLL is written/designed it will need a 'view' of the data. That 'view' is not necessarily the same as the main programs 'view' - we probably want to restrict some data, for example. Hence, you need to create a defintion/description of the gamestate that is appropriate for the AIO.
thus the helper object to serve data to the dll
ORIGINAL: cwie
The idea of 'marshalling' is far more important if threading is involved - access to data from two threads (even if one is only reading) must be tightly controlled.
Absolutely true. I can't speak for other languages, but Delphi has a special function that asks the main thread to process a method to prevent these problems.
ORIGINAL: cwie
Well, I don't know how to measure the significance. The issue here is that you place a permanent 'caveat' on Steve - future changes he may wish to make need to consider the effect on custom AIOs. Sure, he can decide that a change is necessary and anyone taking the new patch must restart any saved games. But this also means anyone who has written and distributed a custom AIO needs to recheck and potentially rewrite/debug their code.
This is a catch 22 situation. If very few people ever write AIOs, then versioning is insignificant ... but then by definition the entire ability to write custom AIOs is insignificant! If custom AIOs are a great success, then versioning looms as a major issue.
Yes. When Steve changes the game state data, it may break the AIOs or at least make them stupid. He would release new interface information and AIO creators would need to update thiers.
ORIGINAL: cwie
I can agree that MOST crashes in a custom AIO will be pretty obviously an error caused by the AIO. But I've done enough plug-in work to know that the problem lies in the 20% of issues that aren't obvious, not the 80% that are.
And Steve and Matrix have a direct responsibility for ensuring that stability, and fixing it if it's not there. The problems can come from determining who is responsible for "preceived instability" resulting from AIO development.
I can't argue with problems not always being obvious. But, I would hope that anyone who would percieve a publisher to be at fault after installing a purely optional plug in that only changes existing functionality instead of adding functionality would be too uniformed to bother in the first place.
ORIGINAL: cwie
To be sure, I doubt this will be part of the first version. But, as I pointed out earlier, if things are structured correctly now, it will leave room for such an expansion. If not, it will likely never happen.
Agreed, to a point. Programming is always an exercise in choosing alternatives, measuring benefit versus cost. You've made the case to show the "benefit" of an AIO as a separate DLL with a tightly defined interface. I've simply tried to shown that there is a "cost" that comes with this approach. It's up to Steve to decide, based on what he knows of his requirements and his timeframe.
I agree wholeheartedly. I am just excited to realize that it is still early enough in the development cycle to make those decisions without even more 'cost'. Nothing hurts worse than someone changing the requirements of a piece of software after you have built code upon the premise that those requirements were not needed. ('Requirements' is too strong a word for what we are talking about but I think you know what I mean.)
ORIGINAL: cwie
The longest software project I've been actively ionvolved with has code that is now almost 20 years old, and is still in production use and (ongoing) development. Documentation is never sufficient. And getting one programmer to explain his decisions (it's the 'why' more that the 'what' that often matters) in writing to another that he has never met is ... tricky at best.
Tricky? Some days I would rather take a beating than answer that question. It is always a value judgement, isn't it?
ORIGINAL: cwie
Ah ... perhaps this is just a point of detail. As an example, in CWIE there are hexes containing resources. If the German captures such a hex during a game turn, the hex is immediately considered 'German owned'. However, the variable that tracks the number of german controlled resources is only used in the 'production cycle' which occurs every 4 turns. So that variable is only updated at the start of the production cycle, to reflect all activity in the past 4 turns. Accessing that variable during any of the preceeding 4 turns would produce a possibly incorrect value. The program knows this, and doesn't access this variable. An AIO writer however might assume that when he finds a variable called "NumGermanOwnedResources" that he can access this at anytime. He'd be wrong, and a subtle bug has entered the system.
In the above example the 'gamestate' variable that tracks German controlled resources is valid whenever the program needs it to be. That doesn't mean it is valid at all times.
Now that is an interesting point. Just because I want to know doesn't mean that Steve thought I would want to know at that time. Is everything adjusted on the fly or are some values batch processed? Steve knows. Maybe he will tell.
The way around that may be simple or it may be hard -- depending on the specific piece of information. If that piece of information were provided by a function that recalculated it, it would always be right. On the other hand, if it is a time intensive calculation, now some of our speed and efficiency went out of the window.
ORIGINAL: cwie
To be clear, I'm not arguing against your suggestion. Merely trying to point out that it's not a "free ride" to go down that path. We've kicked a few ideas around for the possible (but not yet definite) AI for future inclusion in CWIE-II, and the DLL idea is on the table. The other main contender for offering 'custom-AI' that we are considering is to offer a limited scripting ability, with key 'execution points' in the main code that would allow users to write their own scripts. Both approaches share many common pitfalls, and it's possible that if and when we proceed with the AI work that customisation will not be a feature. Or maybe it will!
The debate is accepted in the spirit it is offered. Hashing out possible problems is certainly part of the early process. Thanks for letting me be part of it.
I am fully aware that as a deveoper, you are always weighing 'bang for the buck'. Development costs time which is money. I am a developer too. I have been programming computers professionally for 23 years. I understand these things. My personal cross to bear is that I always want to do things 'exactly' right and therefore development is slow. And therefore it is expensive. But, so far, the results have been good and my 'users' are generally happy.
Scripting will certainly be able to be used by a larger group of players.
The two are not necessarily mutually exclusive. If the game engine asks the scripting engine questions about what to do, then maybe the scripting engine could be implemented in the stock DLL which could still be replaced by a user implementd one. (run, duck, and cover) [:)] I say this with tounge only partially in cheek.
It is clear that cost to value will be the determining factor and that is exactly how it should be. Exactly.
You guys keep up the good work and understand this above all. If the decision is made not to expose the AI to oustide influences, I will smile and buy the game just like I will if these ideas are implemented. I promise not to whine or beg. I promise to be happy.
Dean
Bridge is the best wargame going .. Where else can you find a tournament every weekend?