AI re-devlopment thread
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
When i look at code, i want to look at as little whitespace as possible while still retaining the structure of the code.
This rides in the face of certain stylistic concerns of some people, and who's to say it's more important than those concerns, or less. ie, I hate one line opening brackets. But i hate lack of indentation more (or too much).
I propose this, and then we'll split this stuff into a new thread if need be:
No reformatting file commits. I can see this immediately becoming a race to enforce what one person considers correct over what others consider correct and we dont need that kind of crap right now.
You can format your code how you like, but it damn well better be in direct consequence to having to change that code.
And when i'm talking about format only changes, i'm talking about indentation and bracket placement. I'm not talking about stuff relating to how long functions are or how many classes per header and such. We can move ahead with that stuff, nobody is disagreeing there.
This rides in the face of certain stylistic concerns of some people, and who's to say it's more important than those concerns, or less. ie, I hate one line opening brackets. But i hate lack of indentation more (or too much).
I propose this, and then we'll split this stuff into a new thread if need be:
No reformatting file commits. I can see this immediately becoming a race to enforce what one person considers correct over what others consider correct and we dont need that kind of crap right now.
You can format your code how you like, but it damn well better be in direct consequence to having to change that code.
And when i'm talking about format only changes, i'm talking about indentation and bracket placement. I'm not talking about stuff relating to how long functions are or how many classes per header and such. We can move ahead with that stuff, nobody is disagreeing there.
Ed Sweetman endorses this message.
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
Getting back on AI for a second:
A lot of the non-aggressive class code is static. So it's in this file for a reason, that reason being that these functions have been made "shared" across every instance of the Aggressive class that uses them. It's going to take abit more time to re-organize this file than i originally thought.
anyways, Here is aggressive.cpp run through indent (simple neat too for fixing up files). This was achieved via just -linux, to match the code requirements of the linux kernel. Note, this has not been touched up yet to fix unnecessary line breaks, nor am i intending on committing this. Just a sample.
http://signal-lost.homeip.net/files/agg ... inuxindent
I'll continue working on figuring out just how we can re-organize aggressiveAI tomorrow. One thing i want to look into is if we can do a name change without mucking up python code, and without needing a stupid typedef to not muck it up. A better name for aggressiveAI is AciveAI, as it appears that the AI code in aggressive AI was meant to counter a more passive AI that simply reacts to things rather than act first. Aggressive is one way to see such behavior, but that denotes an emotional state, which is counter to what this code actually covers. So unless someone has a better name, I'll go with activeAI.
I can remove the static variable usage dealing with options without a problem, but the other static usages may be necessary, and in such a case, we wont be able to sanitize the source to the level we would like. static is Fun (tm).
A lot of the non-aggressive class code is static. So it's in this file for a reason, that reason being that these functions have been made "shared" across every instance of the Aggressive class that uses them. It's going to take abit more time to re-organize this file than i originally thought.
anyways, Here is aggressive.cpp run through indent (simple neat too for fixing up files). This was achieved via just -linux, to match the code requirements of the linux kernel. Note, this has not been touched up yet to fix unnecessary line breaks, nor am i intending on committing this. Just a sample.
http://signal-lost.homeip.net/files/agg ... inuxindent
I'll continue working on figuring out just how we can re-organize aggressiveAI tomorrow. One thing i want to look into is if we can do a name change without mucking up python code, and without needing a stupid typedef to not muck it up. A better name for aggressiveAI is AciveAI, as it appears that the AI code in aggressive AI was meant to counter a more passive AI that simply reacts to things rather than act first. Aggressive is one way to see such behavior, but that denotes an emotional state, which is counter to what this code actually covers. So unless someone has a better name, I'll go with activeAI.
I can remove the static variable usage dealing with options without a problem, but the other static usages may be necessary, and in such a case, we wont be able to sanitize the source to the level we would like. static is Fun (tm).
Ed Sweetman endorses this message.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
One thing I find remarkable is that as much as I hate indentation by 8 spaces, it allows me to follow the logic even with { in the same line, --though I still much prefer indentation by 4 and { in new line.safemode wrote:Here is aggressive.cpp run through indent (simple neat too for fixing up files). This was achieved via just -linux, to match the code requirements of the linux kernel. Note, this has not been touched up yet to fix unnecessary line breaks, nor am i intending on committing this. Just a sample.
http://signal-lost.homeip.net/files/agg ... inuxindent
Sounds good to me.I'll continue working on figuring out just how we can re-organize aggressiveAI tomorrow. One thing i want to look into is if we can do a name change without mucking up python code, and without needing a stupid typedef to not muck it up. A better name for aggressiveAI is AciveAI, as it appears that the AI code in aggressive AI was meant to counter a more passive AI that simply reacts to things rather than act first. Aggressive is one way to see such behavior, but that denotes an emotional state, which is counter to what this code actually covers. So unless someone has a better name, I'll go with activeAI.
Necessary static variables could ve converted to class variables, which then shifts the problem of re-entrancy to a more standard problem of asynchronous object access.I can remove the static variable usage dealing with options without a problem, but the other static usages may be necessary, and in such a case, we wont be able to sanitize the source to the level we would like. static is Fun (tm).
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Re: AI re-devlopment thread
No, very simple: my experience with those tools is that they make mistakes.chuck_starchaser wrote:That's false. There was an article years ago, not sure if in C++ Journal or DrDobbs (used to buy both), and the article was precisely about this problem, and he acknowledged that to many programmers formatting is more than just "a preference" and presented a solution that tied a formatter to (then CVS) to reformat code on checkout and commit. They were using the system at his company. I have a feeling you just don't WANT me to get this wish. This is damn important to me, if I'm going to get involved with the C++ code. But if you don't care for my help, then so be it. This is how so many great plans go to shit.
So if you tie the tool to SVN, then you'll have to battle with those problems.
If you use the tool in your working directory, you'll have to battle with those problems just as well (only perhaps more controllably).
So ya, I don't want to use those tools. It's not necessary for me. If it is for you, feel free to use them personally. Just don't impose them on everybody else because they will be trouble at some point.
It's different. He'll use the formatter in a piece of code that is heavily broken, format-wise, and only once. You're proposing to turn it into an SVN hook - can you not see the difference?chuck_starchaser wrote:Now I capitalized what I've repeated so often, and you make a face about it. Safemode was saying he's tempted to run a formatter on all the code.
You don't have to request it, you can simply do it in your working directory. I don't see why it has to be an SVN hook.chuck_starchaser wrote:so I can format the code in a way I can work with it, and then format it back before committing.
What is so evil about my request?
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
I see. So, tying them to svn is not a good idea; I can live with that.klauss wrote:No, very simple: my experience with those tools is that they make mistakes.chuck_starchaser wrote:That's false. There was an article years ago, not sure if in C++ Journal or DrDobbs (used to buy both), and the article was precisely about this problem, and he acknowledged that to many programmers formatting is more than just "a preference" and presented a solution that tied a formatter to (then CVS) to reformat code on checkout and commit. They were using the system at his company. I have a feeling you just don't WANT me to get this wish. This is damn important to me, if I'm going to get involved with the C++ code. But if you don't care for my help, then so be it. This is how so many great plans go to shit.
So if you tie the tool to SVN, then you'll have to battle with those problems.
That's fine with me.If you use the tool in your working directory, you'll have to battle with those problems just as well (only perhaps more controllably).
I wasn't really insisting on tying them to svn; all I asked for was a tool and a config string, so I can reformat code to the taste of the majority here before I commit. Anyways, I'm playing with uncrustify right now, and I'm hoping to be able to come up with both configs myself; --I'm calling them unc_me.cfg and unc_them.cfg.So ya, I don't want to use those tools. It's not necessary for me. If it is for you, feel free to use them personally. Just don't impose them on everybody else because they will be trouble at some point.
But I wasn't; that was one option; the other option was simply a tool and a configuration. Safemode runs the initial formatter, and if I know what the configuration for it is, I can reformat to suit my needs, work with the file, then format back with his settings, and it shouldn't be much different than editing the file directly.It's different. He'll use the formatter in a piece of code that is heavily broken, format-wise, and only once. You're proposing to turn it into an SVN hook - can you not see the difference?chuck_starchaser wrote:Now I capitalized what I've repeated so often, and you make a face about it. Safemode was saying he's tempted to run a formatter on all the code.
It doesn't.You don't have to request it, you can simply do it in your working directory. I don't see why it has to be an SVN hook.chuck_starchaser wrote:so I can format the code in a way I can work with it, and then format it back before committing.
What is so evil about my request?
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
Keep in mind too, when i say i am running a formatter on something, I have to go through line by line and fix various lines (c++ formatting is riddled with mistakes with such tools). It's not something that can just be batch processed and let go. So i only tend to use it on stuff i'm going to be messing with anyway. And I haven't done it in VS (not in a long long time anyway) at all yet, and wasn't intending to unilaterally
The discrepancies with style is why i suggested we only deal with indentation. This would still need to be doublechecked after running on a file, but it would be much less intrusive on everyone's personal coding habits. In many decent editors, the tab is customizable (either as a real tab or converting to spaces and the size/amount thereof). But even in those that aren't, we are less likely to run up against a problem where the need to run it through a formatting program lacks a certain feature if all we care about is indentation.
Ie. windows developers may not have the same formatter available in linux land, so what are they to do? Have one of the linux developers process their patches ? Or even in linux land, which formatter would we decide on? There are many. I would just rather avoid all this mess with formatting and only fix the indentations, since many many files become nearly unreadable when nothing is indented correctly.
About AggressiveAI:
I dont think we're ready to split this file into anything yet. I dont know if we ever will. The long switch statements would only be shortened by making them call separate functions consisting of each case, which adds a function call and slows things down, and switch statements are more efficient than a long ifelse tree. So while it looks ugly, i dont think it you're gonna be able to optimize this out. Further, outside of tiny micro-optimizations, i dont think anything in here is really horribly inefficient considering what it does. My previous profiles which i did for collisions did not show barely any cpu being used up by the AI at all, (granted i wasn't dogfighting anyone). So other than some simple variable -> options changes and some code re-formatting, I'm not seeing much we can do here. Not without full on writing a new AI system and this isn't the time nor do we have any such code ready to do such a thing.
The discrepancies with style is why i suggested we only deal with indentation. This would still need to be doublechecked after running on a file, but it would be much less intrusive on everyone's personal coding habits. In many decent editors, the tab is customizable (either as a real tab or converting to spaces and the size/amount thereof). But even in those that aren't, we are less likely to run up against a problem where the need to run it through a formatting program lacks a certain feature if all we care about is indentation.
Ie. windows developers may not have the same formatter available in linux land, so what are they to do? Have one of the linux developers process their patches ? Or even in linux land, which formatter would we decide on? There are many. I would just rather avoid all this mess with formatting and only fix the indentations, since many many files become nearly unreadable when nothing is indented correctly.
About AggressiveAI:
I dont think we're ready to split this file into anything yet. I dont know if we ever will. The long switch statements would only be shortened by making them call separate functions consisting of each case, which adds a function call and slows things down, and switch statements are more efficient than a long ifelse tree. So while it looks ugly, i dont think it you're gonna be able to optimize this out. Further, outside of tiny micro-optimizations, i dont think anything in here is really horribly inefficient considering what it does. My previous profiles which i did for collisions did not show barely any cpu being used up by the AI at all, (granted i wasn't dogfighting anyone). So other than some simple variable -> options changes and some code re-formatting, I'm not seeing much we can do here. Not without full on writing a new AI system and this isn't the time nor do we have any such code ready to do such a thing.
Ed Sweetman endorses this message.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Re: AI re-devlopment thread
As I said, optimizing this means refactoring it.safemode wrote:I dont think we're ready to split this file into anything yet. I dont know if we ever will. The long switch statements would only be shortened by making them call separate functions consisting of each case, which adds a function call and slows things down, and switch statements are more efficient than a long ifelse tree. So while it looks ugly, i dont think it you're gonna be able to optimize this out.
Switch statements are converted into a lookup table and indirect jumps by the compiler, which is fast but unpredictable. So when you get to such a statement, the whole pipeline gets flushed - it's a big performance hit. But only if the switch is hot.
Now... not all AI is hot, you're probably not seeing it on the profilings because it must have been tuned to run less and less often. I'll have to do some profiling of my own. In any case a more efficient architecture would enable us to implement smarter AIs, and that's something everybody wants IIRC.
Look again. There's some unneeded string parsing there at rather critical paths (critical if the AI gets evaluated often).safemode wrote:Further, outside of tiny micro-optimizations, i dont think anything in here is really horribly inefficient considering what it does.
Ya, the formatting is a no brainer, and small cleanup can be done too.safemode wrote:My previous profiles which i did for collisions did not show barely any cpu being used up by the AI at all, (granted i wasn't dogfighting anyone). So other than some simple variable -> options changes and some code re-formatting, I'm not seeing much we can do here. Not without full on writing a new AI system and this isn't the time nor do we have any such code ready to do such a thing.
And documentation.
Try to document stuff as you go (as you figure out how the stuff works).
If anyone can figure out this AI system, it will be a big gain.
@chuck: great, so I misunderstood. Sorry
-
- Elite
- Posts: 1567
- Joined: Tue Jan 26, 2010 2:03 am
Re: AI re-devlopment thread
I actually think this was done client side. In one of the links I provided, a formatter hook was added to TortioseSVN to run during commit. I'm pretty sure it could be made to work at checkout as well. If it was done server side.. well that could cause some nasty problems if the formatter sucked.chuck_starchaser wrote:I see. So, tying them to svn is not a good idea; I can live with that.klauss wrote:No, very simple: my experience with those tools is that they make mistakes.chuck_starchaser wrote:That's false. There was an article years ago, not sure if in C++ Journal or DrDobbs (used to buy both), and the article was precisely about this problem, and he acknowledged that to many programmers formatting is more than just "a preference" and presented a solution that tied a formatter to (then CVS) to reformat code on checkout and commit. They were using the system at his company. I have a feeling you just don't WANT me to get this wish. This is damn important to me, if I'm going to get involved with the C++ code. But if you don't care for my help, then so be it. This is how so many great plans go to shit.
So if you tie the tool to SVN, then you'll have to battle with those problems.
The ones i linked too I believe are cross-platform, will have to double check. Astyle was regarded as the best by most of the people who needed one.safemode wrote:Ie. windows developers may not have the same formatter available in linux land, so what are they to do? Have one of the linux developers process their patches ? Or even in linux land, which formatter would we decide on? There are many. I would just rather avoid all this mess with formatting and only fix the indentations, since many many files become nearly unreadable when nothing is indented correctly.
Refering to just aggressiveai.cpp or all the AI files?safemode wrote:About AggressiveAI:
I dont think we're ready to split this file into anything yet. I dont know if we ever will. The long switch statements would only be shortened by making them call separate functions consisting of each case, which adds a function call and slows things down, and switch statements are more efficient than a long ifelse tree. So while it looks ugly, i dont think it you're gonna be able to optimize this out. Further, outside of tiny micro-optimizations, i dont think anything in here is really horribly inefficient considering what it does. My previous profiles which i did for collisions did not show barely any cpu being used up by the AI at all, (granted i wasn't dogfighting anyone). So other than some simple variable -> options changes and some code re-formatting, I'm not seeing much we can do here. Not without full on writing a new AI system and this isn't the time nor do we have any such code ready to do such a thing.
Because of YOU Arbiter, MY kids? can't get enough gas. OR NIPPLE! How does that mkae you feeeel? ~ Halo
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
@Safemode: If you can break it into functions, function call overhead could be prevented by #inline-ing the functions.
And what we gain really, is just the function names, and an easier to read main function, but it'd be a start anyways.
I'm about half way through setting the parameters for uncrustify; both for myself and for VS. Sorry it's taking so long; it's 370+ parameters to go through; and I'm having trouble with public: private: and protected: (wanted them to have relative indentation, so as to be able to have nested class declarations, but it's giving me trouble).
And what we gain really, is just the function names, and an easier to read main function, but it'd be a start anyways.
I'm about half way through setting the parameters for uncrustify; both for myself and for VS. Sorry it's taking so long; it's 370+ parameters to go through; and I'm having trouble with public: private: and protected: (wanted them to have relative indentation, so as to be able to have nested class declarations, but it's giving me trouble).
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
Done with the uncrustify configs.
Try this, Safemode:
Continued on next post, since this stupid thing limits message size to 60k chars...
Try this, Safemode:
Code: Select all
#include "config.h"
#include "aggressive.h"
#include "event_xml.h"
#include "script.h"
#include <list>
#include <vector>
#include "vs_globals.h"
#include "config_xml.h"
#include "xml_support.h"
#include "cmd/unit_generic.h"
#include "communication.h"
#include "cmd/script/flightgroup.h"
#include "flybywire.h"
#include "hard_coded_scripts.h"
#include "cmd/script/mission.h"
#include "gfx/cockpit_generic.h"
#include "lin_time.h"
#include "faction_generic.h"
#include "cmd/role_bitmask.h"
#include "cmd/unit_util.h"
#include "warpto.h"
#include "cmd/csv.h"
#include "universe_util.h"
#include "vs_random.h"
#include "python/python_compile.h"
#include "cmd/unit_find.h"
#include "faction_generic.h"
#include "docking.h"
using namespace Orders;
const EnumMap::Pair element_names[] = {
EnumMap::Pair("AggressiveAI", AggressiveAI::AGGAI),
EnumMap::Pair("UNKNOWN", AggressiveAI::UNKNOWN),
EnumMap::Pair("Distance", AggressiveAI::DISTANCE),
EnumMap::Pair("MeterDistance", AggressiveAI::METERDISTANCE),
EnumMap::Pair("Threat", AggressiveAI::THREAT),
EnumMap::Pair("FShield", AggressiveAI::FSHIELD),
EnumMap::Pair("LShield", AggressiveAI::LSHIELD),
EnumMap::Pair("RShield", AggressiveAI::RSHIELD),
EnumMap::Pair("BShield", AggressiveAI::BSHIELD),
EnumMap::Pair("Hull", AggressiveAI::HULL),
EnumMap::Pair("Facing", AggressiveAI::FACING),
EnumMap::Pair("Movement", AggressiveAI::MOVEMENT),
EnumMap::Pair("FShield_Heal_Rate", AggressiveAI::FSHIELD_HEAL_RATE),
EnumMap::Pair("BShield_Heal_Rate", AggressiveAI::BSHIELD_HEAL_RATE),
EnumMap::Pair("LShield_Heal_Rate", AggressiveAI::LSHIELD_HEAL_RATE),
EnumMap::Pair("RShield_Heal_Rate", AggressiveAI::RSHIELD_HEAL_RATE),
EnumMap::Pair("FArmor_Heal_Rate", AggressiveAI::FARMOR_HEAL_RATE),
EnumMap::Pair("BArmor_Heal_Rate", AggressiveAI::BARMOR_HEAL_RATE),
EnumMap::Pair("LArmor_Heal_Rate", AggressiveAI::LARMOR_HEAL_RATE),
EnumMap::Pair("RArmor_Heal_Rate", AggressiveAI::RARMOR_HEAL_RATE),
EnumMap::Pair("Hull_Heal_Rate", AggressiveAI::HULL_HEAL_RATE),
EnumMap::Pair("Target_Faces_You", AggressiveAI::TARGET_FACES_YOU),
EnumMap::Pair("Target_In_Front_Of_You", AggressiveAI::TARGET_IN_FRONT_OF_YOU),
EnumMap::Pair("Rand", AggressiveAI::RANDOMIZ),
EnumMap::Pair("Target_Going_Your_Direction", AggressiveAI::TARGET_GOING_YOUR_DIRECTION)
};
const EnumMap AggressiveAIel_map(element_names, 25);
using std::pair;
vsUMap< string, AIEvents::ElemAttrMap* >logic;
extern bool CheckAccessory (Unit *tur);
//extern void TurretFAW(Unit *parent); /*
static void TurretFAW (Unit *parent)
{
un_iter iter = parent->getSubUnits();
Unit *un;
while ( NULL != (un = *iter) ) {
if ( !CheckAccessory(un) ) {
un->EnqueueAIFirst( new Orders::FireAt(15.0f) );
un->EnqueueAIFirst( new Orders::FaceTarget(false, 3) );
}
TurretFAW(un);
++iter;
}
}
static vsUMap< string, string >getAITypes ()
{
vsUMap< string, string >ret;
VSFileSystem::VSFile f;
VSError err = f.OpenReadOnly("VegaPersonalities.csv", AiFile);
if (err <= Ok) {
CSVTable table( f, f.GetRoot() );
vsUMap< std::string, int >::iterator browser = table.rows.begin();
for (; browser != table.rows.end(); ++browser) {
string rowname = (*browser).first;
CSVRow row(&table, rowname);
for (unsigned int i = 1; i < table.key.size(); ++i) {
string hasher = rowname;
if (i != 1) hasher = rowname+"%"+table.key[i];
string rawrow = row[i];
if (rawrow.length() > 0) {
ret[hasher] = rawrow;
}
}
}
f.Close();
}
return ret;
}
static string select_from_space_list (string inp, unsigned int seed)
{
if (inp.length() == 0) return "";
int count = 1;
string::size_type len = inp.length();
for (unsigned int i = 0; i < len; ++i) {
if (inp[i] == ' ')
count++;
}
count = seed%count;
int ncount = 0;
unsigned int j;
for (j = 0; j < len; ++j) {
if (inp[j] == ' ') ncount++;
if (ncount >= count) break;
}
if (inp[j] == ' ') j++;
inp = inp.substr(j);
if ( ( len = inp.find(" ") ) != string::npos )
inp = inp.substr(0, len);
return inp;
}
static AIEvents::ElemAttrMap * getLogicOrInterrupt (string name,
int faction,
string unittype,
vsUMap< string, AIEvents::ElemAttrMap* > &mymap,
int personalityseed)
{
string append = "agg";
static vsUMap< string, string > myappend = getAITypes();
vsUMap< string, string >::iterator iter;
string factionname = FactionUtil::GetFaction(faction);
if ( ( iter = myappend.find(factionname+"%"+unittype) ) != myappend.end() )
append = select_from_space_list( (*iter).second, personalityseed );
else if ( ( iter = myappend.find(factionname) ) != myappend.end() )
append = select_from_space_list( (*iter).second, personalityseed );
if (append.length() == 0) append = "agg";
string hashname = name+"."+append;
vsUMap< string, AIEvents::ElemAttrMap* >::iterator i = mymap.find(hashname);
if ( i == mymap.end() ) {
AIEvents::ElemAttrMap *attr = new AIEvents::ElemAttrMap(AggressiveAIel_map);
string filename(name+"."+append+".xml");
AIEvents::LoadAI( filename.c_str(), *attr, FactionUtil::GetFaction(faction) );
mymap.insert( pair< string, AIEvents::ElemAttrMap* > (hashname, attr) );
return attr;
}
return i->second;
}
static AIEvents::ElemAttrMap * getProperLogicOrInterruptScript (string name,
int faction,
string unittype,
bool interrupt,
int personalityseed)
{
return getLogicOrInterrupt(name, faction, unittype, logic, personalityseed);
}
static AIEvents::ElemAttrMap * getProperScript (Unit *me, Unit *targ, bool interrupt, int personalityseed)
{
if (!me || !targ) {
string nam = "eject";
int fac = 0;
if (me) {
fac = me->faction;
nam = me->name;
}
return getProperLogicOrInterruptScript("default", fac, nam, interrupt, personalityseed);
}
return getProperLogicOrInterruptScript(ROLES::getRoleEvents( me->attackPreference(),
targ->unitRole() ), me->faction, me->name, interrupt,
personalityseed);
}
inline std::string GetRelationshipColor (float rel)
{
if (rel >= 1) return "#00FF00";
if (rel <= -1) return "#FF0000";
rel += 1.;
rel /= 2.;
char str[20]; //Just in case all 8 digits of both #s end up inside the string for some reason.
sprintf( str, "#%2X%2X00", (int) ( (1-rel)*256 ), (int) (rel*256) );
return str;
}
unsigned int DoSpeech (Unit *un, Unit *player_un, const FSM::Node &node)
{
unsigned int dummy = 0;
string speech = node.GetMessage(dummy);
string myname("[Static]");
if (un != NULL) {
myname = un->isUnit() == PLANETPTR ? un->name : un->getFullname();
Flightgroup *fg = un->getFlightgroup();
if (fg && fg->name != "base" && fg->name != "Base")
myname = fg->name+" "+XMLSupport::tostring( un->getFgSubnumber() )+", "+un->getFullname();
else if (myname.length() == 0) myname = un->name;
if (player_un != NULL) {
if (player_un == un)
myname = std::string("#0033FF")+myname+"#000000";
else {
float rel = un->getRelation(player_un);
myname = GetRelationshipColor(rel)+myname+"#000000";
}
}
}
mission->msgcenter->add(myname, "all", GetRelationshipColor(node.messagedelta*10)+speech+"#000000"); //multiply by 2 so colors are easier to tell
return dummy;
}
void LeadMe (Unit *un, string directive, string speech, bool changetarget)
{
if (un != NULL) {
for (unsigned int i = 0; i < _Universe->numPlayers(); i++) {
Unit *pun = _Universe->AccessCockpit(i)->GetParent();
if (pun) {
if ( pun->getFlightgroup() == un->getFlightgroup() )
DoSpeech( un, pun, FSM::Node::MakeNode(speech, .1) );
}
}
Flightgroup *fg = un->getFlightgroup();
if (fg) {
if (fg->leader.GetUnit() != un) {
if ( ( !_Universe->isPlayerStarship( fg->leader.GetUnit() ) ) || _Universe->isPlayerStarship(un) )
fg->leader.SetUnit(un);
}
fg->directive = directive;
if (changetarget) fg->target.SetUnit( un->Target() );
if ( (directive == "") ) fg->target.SetUnit(NULL);
}
}
}
static float aggressivity = 2.01;
static int randomtemp;
AggressiveAI::AggressiveAI (const char *filename, Unit *target) : FireAt()
, logic( getProperScript( NULL, NULL, "default", randomtemp = rand() ) )
{
currentpriority = 0;
last_jump_time = 0;
nav = QVector(0, 0, 0);
personalityseed = randomtemp;
last_jump_distance = FLT_MAX;
interruptcurtime = 0;
creationtime = getNewTime();
jump_time_check = 1;
last_time_insys = true;
logiccurtime = logic->maxtime; //set it to the time allotted
obedient = true;
if (aggressivity == 2.01) {
static float defagg = XMLSupport::parse_float( vs_config->getVariable("unit", "aggressivity", "2") );
aggressivity = defagg;
}
if (target != NULL)
AttachOrder(target);
last_directive = filename;
//AIEvents::LoadAI (filename,logic,"neutral");
//AIEvents::LoadAI (interruptname,interrupt,"neutral");
}
void AggressiveAI::SetParent (Unit *parent1)
{
FireAt::SetParent(parent1);
string::size_type which = last_directive.find("|");
string filename( string("default.agg.xml") );
string interruptname( string("default.int.xml") );
if (which != string::npos) {
filename = last_directive.substr(0, which);
interruptname = last_directive.substr(which+1);
}
last_directive = "b"; //prevent escort race condition
//INIT stored stuff
Fshield_prev = parent->graphicOptions.InWarp ? 1 : parent->FShieldData();
Fshield_rate_old = 0.0;
Fshield_prev_time = UniverseUtil::GetGameTime();
Bshield_prev = parent->graphicOptions.InWarp ? 1 : parent->BShieldData();
Bshield_rate_old = 0.0;
Bshield_prev_time = UniverseUtil::GetGameTime();
Lshield_prev = parent->graphicOptions.InWarp ? 1 : parent->LShieldData();
Lshield_rate_old = 0.0;
Lshield_prev_time = UniverseUtil::GetGameTime();
Rshield_prev = parent->graphicOptions.InWarp ? 1 : parent->RShieldData();
Rshield_rate_old = 0.0;
Rshield_prev_time = UniverseUtil::GetGameTime();
Farmour_prev = 1.0;
Farmour_rate_old = 0.0;
Farmour_prev_time = UniverseUtil::GetGameTime();
Barmour_prev = 1.0;
Barmour_rate_old = 0.0;
Barmour_prev_time = UniverseUtil::GetGameTime();
Larmour_prev = 1.0;
Larmour_rate_old = 0.0;
Larmour_prev_time = UniverseUtil::GetGameTime();
Rarmour_prev = 1.0;
Rarmour_rate_old = 0.0;
Rarmour_prev_time = UniverseUtil::GetGameTime();
Hull_prev = parent->GetHullPercent();
Hull_rate_old = 0.0;
Hull_prev_time = UniverseUtil::GetGameTime();
}
void AggressiveAI::SignalChosenTarget ()
{
if (parent)
logic = getProperScript(parent, parent->Target(), false, personalityseed);
FireAt::SignalChosenTarget();
}
bool AggressiveAI::ExecuteLogicItem (const AIEvents::AIEvresult &item)
{
if (item.script.length() != 0) {
Order *tmp = new ExecuteFor(new AIScript( item.script.c_str() ), item.timetofinish);
//parent->EnqueueAI (tmp);
EnqueueOrder(tmp);
return true;
} else
return false;
}
bool AggressiveAI::ProcessLogicItem (const AIEvents::AIEvresult &item)
{
float value = 0.0;
static float game_speed = XMLSupport::parse_float( vs_config->getVariable("physics", "game_speed", "1") );
static float game_accel = XMLSupport::parse_float( vs_config->getVariable("physics", "game_accel", "1") );
switch ( abs(item.type) )
{
case DISTANCE:
value = distance;
break;
case METERDISTANCE:
{
Unit *targ = parent->Target();
if (targ) {
Vector PosDifference = targ->Position().Cast()-parent->Position().Cast();
float pdmag = PosDifference.Magnitude();
value = ( pdmag-parent->rSize()-targ->rSize() );
float myvel = PosDifference.Dot( parent->GetVelocity()-targ->GetVelocity() )/value; ///pdmag;
if (myvel > 0) value -= myvel*myvel/( 2*( parent->Limits().retro/parent->GetMass() ) );
} else
value = 10000;
value /= game_speed; /*game_accel*/
}
break;
case THREAT:
value = parent->GetComputerData().threatlevel;
break;
case FSHIELD:
value = parent->graphicOptions.InWarp ? 1 : parent->FShieldData();
break;
case BSHIELD:
value = parent->graphicOptions.InWarp ? 1 : parent->BShieldData();
break;
case HULL:
{
value = parent->GetHullPercent();
break;
}
case LSHIELD:
value = parent->graphicOptions.InWarp ? 1 : parent->LShieldData();
break;
case RSHIELD:
value = parent->graphicOptions.InWarp ? 1 : parent->RShieldData();
break;
case FSHIELD_HEAL_RATE:
{
double delta_t = UniverseUtil::GetGameTime()-Fshield_prev_time;
if (delta_t > 0.5) {
//0.5 = reaction time limit for hit rate
double delta_v = parent->graphicOptions.InWarp ? 1 : parent->FShieldData()-Fshield_prev;
value = delta_v/delta_t;
Fshield_rate_old = value;
Fshield_prev_time = UniverseUtil::GetGameTime();
Fshield_prev = parent->graphicOptions.InWarp ? 1 : parent->FShieldData();
} else value = Fshield_rate_old; //if(value != 0.0)
//{
//string mystr ("Fshield "+XMLSupport::tostring (value));
//UniverseUtil::IOmessage (0,"game","all",mystr);
//}
break;
}
case BSHIELD_HEAL_RATE:
{
double delta_t = UniverseUtil::GetGameTime()-Bshield_prev_time;
if (delta_t > 0.5) {
//0.5 = reaction time limit for hit rate
double delta_v = parent->graphicOptions.InWarp ? 1 : parent->BShieldData()-Bshield_prev;
value = delta_v/delta_t;
Bshield_rate_old = value;
Bshield_prev_time = UniverseUtil::GetGameTime();
Bshield_prev = parent->graphicOptions.InWarp ? 1 : parent->BShieldData();
} else value = Bshield_rate_old; //if(value != 0.0)
//{
//string mystr ("Fshield "+XMLSupport::tostring (value));
//UniverseUtil::IOmessage (0,"game","all",mystr);
//}
break;
}
case LSHIELD_HEAL_RATE:
{
double delta_t = UniverseUtil::GetGameTime()-Lshield_prev_time;
if (delta_t > 0.5) {
//0.5 = reaction time limit for hit rate
double delta_v = parent->graphicOptions.InWarp ? 1 : parent->LShieldData()-Lshield_prev;
value = delta_v/delta_t;
Lshield_rate_old = value;
Lshield_prev_time = UniverseUtil::GetGameTime();
Lshield_prev = parent->graphicOptions.InWarp ? 1 : parent->LShieldData();
} else value = Lshield_rate_old; //if(value != 0.0)
//{
//string mystr ("Fshield "+XMLSupport::tostring (value));
//UniverseUtil::IOmessage (0,"game","all",mystr);
//}
break;
}
case RSHIELD_HEAL_RATE:
{
double delta_t = UniverseUtil::GetGameTime()-Rshield_prev_time;
if (delta_t > 0.5) {
//0.5 = reaction time limit for hit rate
double delta_v = parent->graphicOptions.InWarp ? 1 : parent->RShieldData()-Rshield_prev;
value = delta_v/delta_t;
Rshield_rate_old = value;
Rshield_prev_time = UniverseUtil::GetGameTime();
Rshield_prev = parent->graphicOptions.InWarp ? 1 : parent->RShieldData();
} else value = Rshield_rate_old; //if(value != 0.0)
//{
//string mystr ("Fshield "+XMLSupport::tostring (value));
//UniverseUtil::IOmessage (0,"game","all",mystr);
//}
break;
}
case FARMOR_HEAL_RATE:
value = 0.0;
break;
case BARMOR_HEAL_RATE:
value = 0.0;
break;
case LARMOR_HEAL_RATE:
value = 0.0;
break;
case RARMOR_HEAL_RATE:
value = 0.5;
break;
case HULL_HEAL_RATE:
{
double delta_t = UniverseUtil::GetGameTime()-Hull_prev_time;
if (delta_t > 0.5) {
//0.5 = reaction time limit for hit rate
double delta_v = parent->GetHullPercent()-Hull_prev;
value = delta_v/delta_t;
Hull_rate_old = value;
Hull_prev_time = UniverseUtil::GetGameTime();
Hull_prev = parent->GetHullPercent();
} else value = Hull_rate_old; //if(value != 0.0)
//{
//string mystr ("Fshield "+XMLSupport::tostring (value));
//UniverseUtil::IOmessage (0,"game","all",mystr);
//}
break;
}
case TARGET_FACES_YOU:
{
value = 0.0;
Unit *targ = parent->Target();
if (targ) {
Vector Q;
Vector P;
Vector R;
Vector PosDelta = ( parent->Position() )-( targ->Position() );
PosDelta = PosDelta/PosDelta.Magnitude();
targ->GetOrientation(Q, P, R);
value = PosDelta.Dot(R);
}
}
break;
case TARGET_IN_FRONT_OF_YOU:
{
value = 0.0;
Unit *targ = parent->Target();
if (targ) {
Vector Q;
Vector P;
Vector S;
Vector PosDelta = ( targ->Position() )-( parent->Position() );
PosDelta = PosDelta/PosDelta.Magnitude();
parent->GetOrientation(Q, P, S);
value = PosDelta.Dot(S);
}
}
break;
case TARGET_GOING_YOUR_DIRECTION:
{
value = 0.0;
Unit *targ = parent->Target();
if (targ) {
Vector Q;
Vector P;
Vector R;
Vector S;
parent->GetOrientation(Q, P, S);
targ->GetOrientation(Q, P, R);
value = S.Dot(R);
}
}
break;
case FACING:
//return parent->getAIState()->queryType (Order::FACING)==NULL;
return queryType(Order::FACING) == NULL;
case MOVEMENT:
//return parent->getAIState()->queryType (Order::MOVEMENT)==NULL;
return queryType(Order::MOVEMENT) == NULL;
case RANDOMIZ:
value = ( (float) rand() )/RAND_MAX;
break;
default:
return false;
}
return item.Eval(value);
}
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
... continuing ...
Damned crap! It still doesn't let me finish; I have to split yet again... So much work...
Code: Select all
bool AggressiveAI::ProcessLogic (AIEvents::ElemAttrMap &logi, bool inter)
{
//go through the logic.
bool retval = false;
//Unit * tmp = parent->Target();
//distance = tmp? (tmp->Position()-parent->Position()).Magnitude()-parent->rSize()-tmp->rSize() : FLT_MAX;
std::vector< std::list< AIEvents::AIEvresult > >::iterator i = logi.result.begin();
for (; i != logi.result.end(); i++) {
std::list< AIEvents::AIEvresult >::iterator j;
bool trueit = true;
for (j = i->begin(); j != i->end(); j++) {
if ( !ProcessLogicItem(*j) ) {
trueit = false;
break;
}
}
if ( trueit && j == i->end() ) {
//do it
if ( j != i->begin() ) j--;
if ( j != i->end() ) {
float priority = (*j).priority;
if (priority > this->currentpriority || !inter) {
if (inter) {
//parent->getAIState()->eraseType (Order::FACING);
//parent->getAIState()->eraseType (Order::MOVEMENT);
eraseType(Order::FACING);
eraseType(Order::MOVEMENT);
}
j = i->begin();
logiccurtime = 0;
interruptcurtime = 0;
if ( j != i->end() ) {
while ( j != i->end() ) {
if ( ExecuteLogicItem(*j) ) {
this->currentpriority = priority;
logiccurtime += (*j).timetofinish;
interruptcurtime += (*j).timetointerrupt;
//AIEvents::AIEvresult tmp = *j;
//i->erase(j);
retval = true;
//i->push_back (tmp);
}
j++;
}
if (retval) break;
}
}
}
}
}
return retval;
}
Unit * GetThreat (Unit *parent, Unit *leader)
{
Unit *th = NULL;
Unit *un = NULL;
bool targetted = false;
float mindist = FLT_MAX;
for (un_iter ui = _Universe->activeStarSystem()->getUnitList().createIterator();
(un = *ui);
++ui) {
if (parent->getRelation(un) < 0) {
float d = ( un->Position()-leader->Position() ).Magnitude();
bool thistargetted = (un->Target() == leader);
if ( !th || (thistargetted && !targetted) || ( ( thistargetted || (!targetted) ) && d < mindist ) ) {
th = un;
targetted = thistargetted;
mindist = d;
}
}
}
return th;
}
extern Cargo * GetMasterPartList (const char*);
bool AggressiveAI::ProcessCurrentFgDirective (Flightgroup *fg)
{
bool retval = false;
if (fg != NULL) {
Unit *leader = fg->leader.GetUnit();
if ( last_directive.empty() )
last_directive = fg->directive;
if (fg->directive != last_directive) {
static bool forceobedient = XMLSupport::parse_bool( vs_config->getVariable("AI", "always_obedient", "true") );
if (forceobedient) obedient = true;
else if ( float( rand() )/RAND_MAX < (obedient ? (1-logic->obedience) : logic->obedience) )
obedient = !obedient;
if (obedient) {
eraseType(Order::FACING);
eraseType(Order::MOVEMENT);
Unit *targ = parent->Target();
if (targ) {
bool attacking = fg->directive.length() > 0;
if (attacking) attacking = tolower(fg->directive[0]) == 'a';
if ( ( !isJumpablePlanet(targ) ) && attacking == false )
parent->Target(NULL);
}
} else {
CommunicationMessage c(parent, leader, NULL, 0);
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
Order *lo = leader->getAIState();
if (lo) lo->Communicate(c);
}
}
if (obedient) {
void *parentowner;
void *leaderowner = leader;
parentowner = parent->owner ? parent->owner : parent;
leaderowner = leader->owner ? leader->owner : leader;
if (fg->directive.find("k") != string::npos || fg->directive.find("K") != string::npos) {
Unit *targ = fg->target.GetUnit();
bool callme = false;
if ( targ && (targ->faction != parent->faction) ) {
if ( targ->InCorrectStarSystem( _Universe->activeStarSystem() ) ) {
CommunicationMessage c(parent, leader, NULL, 0);
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
if ( parent->InRange(targ, true, false) ) {
if ( targ != parent->Target() ) callme = true;
parent->Target(targ);
parent->SetTurretAI();
parent->TargetTurret(targ);
//if I am the capship, go into defensive mode.
if (parent == leaderowner) {
//get in front of me
parent->TurretFAW();
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
//MatchVelocity(parent->ClampVelocity(vec,true),Vector(0,0,0),true,true,false)
//Order * ord = new Orders::FormUp(QVector(position*parent->radial_size,0,fabs(dist)));
Order *ord = new Orders::MatchLinearVelocity(parent->ClampVelocity(Vector(0,
0,
0),
true), true, false, true);
ord->SetParent(parent);
ReplaceOrder(ord);
//facing forward
ord = new Orders::FaceTarget(false, 3);
ord->SetParent(parent);
ReplaceOrder(ord);
} else {
Order *ord = new Orders::FaceTarget(false, 3);
ord->SetParent(parent);
ReplaceOrder(ord);
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
}
} else
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
if (fg->directive != last_directive) {
Order *lo = leader->getAIState();
if (lo || callme) lo->Communicate(c);
}
}
} //a is now used for AI, for backward compatibility. do not use for player
} else if (fg->directive.find("a") != string::npos || fg->directive.find("A") != string::npos) {
Unit *targ = fg->leader.GetUnit();
targ = targ != NULL ? targ->Target() : NULL;
if (targ) {
if ( targ->InCorrectStarSystem( _Universe->activeStarSystem() ) ) {
CommunicationMessage c(parent, leader, NULL, 0);
if ( parent->InRange(targ, true, false) ) {
parent->Target(targ);
parent->TargetTurret(targ);
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
} else
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
if (fg->directive != last_directive) {
Order *lo = leader->getAIState();
if (lo) lo->Communicate(c);
}
}
}
} else if (fg->directive.find("f") != string::npos || fg->directive.find("F") != string::npos) {
if (leader != NULL) {
if ( leader->InCorrectStarSystem( _Universe->activeStarSystem() ) ) {
retval = true;
if ( fg->directive != last_directive || (!last_time_insys) ) {
last_time_insys = true;
CommunicationMessage c(parent, leader, NULL, 0);
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
//}else {
//c.SetCurrentState (c.fsm->GetNoNode(),NULL,0);
//}
Order *o = leader->getAIState();
if (o) o->Communicate(c);
static float esc_percent = XMLSupport::parse_float( vs_config->getVariable("AI",
"Targetting",
"EscortDistance",
"10.0") );
static float turn_leader = XMLSupport::parse_float( vs_config->getVariable("AI",
"Targetting",
"TurnLeaderDist",
"5.0") );
int fgnum = parent->getFgSubnumber();
if ( parent->getFlightgroup() ) {
int tempnum = 0;
string nam = parent->getFlightgroup()->name;
int i = nam.length()-1;
for (; i >= 0; --i) {
char digit = nam[i];
if (digit >= '0' && digit <= '9') {
tempnum *= 10;
tempnum += digit-'0';
} else break;
}
fgnum += tempnum;
}
float left = fgnum%2 ? 1 : -1;
double dist = esc_percent*(1+abs(fgnum-1)/2)*left*( parent->rSize()+leader->rSize() );
Order *ord = new Orders::FormUp( QVector( dist, 0, -fabs(dist) ) );
ord->SetParent(parent);
ReplaceOrder(ord);
ord = new Orders::FaceDirection(dist*turn_leader);
ord->SetParent(parent);
ReplaceOrder(ord);
}
} else
last_time_insys = false;
for (unsigned int i = 0; i < suborders.size(); i++)
suborders[i]->AttachSelfOrder(leader);
}
} else if (fg->directive.find("l") != string::npos || fg->directive.find("L") != string::npos) {
if (leader != NULL) {
if ( leader->InCorrectStarSystem( _Universe->activeStarSystem() ) ) {
retval = true;
if ( fg->directive != last_directive || (!last_time_insys) ) {
last_time_insys = true;
CommunicationMessage c(parent, leader, NULL, 0);
//this order is only valid for cargo wingmen, other wingmen will not comply
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
Order *o = leader->getAIState();
if (o) o->Communicate(c);
static float esc_percent = XMLSupport::parse_float( vs_config->getVariable("AI",
"Targetting",
"EscortDistance",
"10.0") );
static float turn_leader = XMLSupport::parse_float( vs_config->getVariable("AI",
"Targetting",
"TurnLeaderDist",
"5.0") );
int fgnum = parent->getFgSubnumber();
if ( parent->getFlightgroup() ) {
int tempnum = 0;
string nam = parent->getFlightgroup()->name;
int i = nam.length()-1;
for (; i >= 0; --i) {
char digit = nam[i];
if (digit >= '0' && digit <= '9') {
tempnum *= 10;
tempnum += digit-'0';
} else break;
}
fgnum += tempnum;
}
/*
// this does the job for real! "parent" is executor, "leader" is commander
// moves where you want it to
// moves flat out in front of parent unit (to allow for tractoring)
Order * ord = new Orders::FormUp(QVector(position*parent->radial_size,0,fabs(dist)));
ord->SetParent (parent);
ReplaceOrder (ord);
// faces same direction as leader
// ord = new Orders::FaceDirection(dist*turn_leader);
// faces opposite direction as leader, as in, stare at me in the face please
ord = new Orders::FaceDirection(-dist*turn_leader);
ord->SetParent (parent);
ReplaceOrder (ord);
*/
int alternate = fgnum%2 ? 1 : -1;
float psize = parent->radial_size;
int Ypos = 0;
int Xpos = 0;
int position = int( floor( (fgnum%3)*0.5*alternate ) );
//nice square formation, how many of these are you going to have anyway? Max 9, then go back. Should be enough.
switch (fgnum%9)
{
case 0:
Xpos = 0;
Ypos = 0;
break;
case 1:
Xpos = -1;
Ypos = 0;
break;
case 2:
Xpos = 1;
Ypos = 0;
break;
case 3:
Xpos = 0;
Ypos = -1;
break;
case 4:
Xpos = -1;
Ypos = -1;
break;
case 5:
Xpos = 1;
Ypos = -1;
break;
case 6:
Xpos = 0;
Ypos = 1;
break;
case 7:
Xpos = -1;
Ypos = 1;
break;
case 8:
Xpos = 1;
Ypos = 1;
break;
default:
Xpos = 0;
Ypos = 0;
}
float dist = (leader->radial_size+parent->radial_size);
float formdist = esc_percent*(1+fgnum*2)*alternate*(dist);
//if i am a cargo wingman, get into a dockable position
if (parentowner == leader) {
Order *ord = new Orders::FormUp( QVector( 1.1*Xpos*psize, 1.1*Ypos*psize, fabs(dist) ) );
ord->SetParent(parent);
ReplaceOrder(ord);
//facing me
ord = new Orders::FaceDirection(-dist*turn_leader);
ord->SetParent(parent);
ReplaceOrder(ord);
}
//if i am a cargo wingman and so is the player, get into a dockable position with the leader
else if ( parentowner && leaderowner && (parentowner == leaderowner) ) {
//float left= fgnum%2?1:-1;
Unit *leaderownerun =
( leaderowner
== leader ? leader : ( leaderowner == parent ? parent : findUnitInStarsystem(leaderowner) ) );
float qdist = ( parent->rSize()+leaderownerun->rSize() );
Order *ord =
new Orders::MoveTo(leaderownerun->Position()+Vector(0.5*Xpos*psize,
0.5*Ypos*psize,
0.5*qdist), true, 4);
ord->SetParent(parent);
ReplaceOrder(ord);
//facing it
ord = new Orders::FaceDirection(-qdist*turn_leader);
ord->SetParent(parent);
ReplaceOrder(ord);
}
//if i am the capship, go into defensive mode
else if (parent == leaderowner) {
//// parent->Target(parent);
parent->SetTurretAI();
TurretFAW(parent);
Order *ord = new Orders::MatchLinearVelocity(parent->ClampVelocity(Vector(0,
0,
0),
true), true, false, true);
ord->SetParent(parent);
ReplaceOrder(ord);
if (parent->Target() != NULL) ord = new Orders::FaceTarget(false, 3);
else ord = new Orders::FaceDirection(-dist*turn_leader);
ord->SetParent(parent);
ReplaceOrder(ord);
} else {
//if i'm not a cargo wingman, just form up somewhat loosely.
parentowner = parent;
Order *ord =
new Orders::FormUp( QVector(5*Xpos*psize, 5*Ypos*psize, -fabs(formdist)+Ypos*psize+Xpos
*psize) );
ord->SetParent(parent);
ReplaceOrder(ord);
ord = new Orders::FaceDirection(dist*turn_leader);
ord->SetParent(parent);
ReplaceOrder(ord);
}
}
} else
last_time_insys = false;
for (unsigned int i = 0; i < suborders.size(); i++)
suborders[i]->AttachSelfOrder(leader);
}
} else if (fg->directive.find("e") != string::npos || fg->directive.find("E") != string::npos) {
static QVector LeaderPosition = QVector(0, 0, 0);
if (LeaderPosition.Magnitude() > 0 || leader != NULL) {
if ( LeaderPosition.Magnitude() > 0 || leader->InCorrectStarSystem( _Universe->activeStarSystem() ) ) {
retval = true;
if (LeaderPosition.Magnitude() == 0) //only read the position the first time
LeaderPosition = leader->Position();
if ( fg->directive != last_directive || (!last_time_insys) ) {
last_time_insys = true;
CommunicationMessage c(parent, leader, NULL, 0);
//this order is only valid for cargo wingmen, other wingmen will not comply
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
static float esc_percent = XMLSupport::parse_float( vs_config->getVariable("AI",
"Targetting",
"EscortDistance",
"10.0") );
static float turn_leader = XMLSupport::parse_float( vs_config->getVariable("AI",
"Targetting",
"TurnLeaderDist",
"5.0") );
int fgnum = parent->getFgSubnumber();
if ( parent->getFlightgroup() ) {
int tempnum = 0;
string nam = parent->getFlightgroup()->name;
int i = nam.length()-1;
for (; i >= 0; --i) {
char digit = nam[i];
if (digit >= '0' && digit <= '9') {
tempnum *= 10;
tempnum += digit-'0';
} else break;
}
fgnum += tempnum;
}
/*
// this does the job for real! "parent" is executor, "leader" is commander
// moves where you want it to
// moves flat out in front of parent unit (to allow for tractoring)
Order * ord = new Orders::FormUp(QVector(position*parent->radial_size,0,fabs(dist)));
ord->SetParent (parent);
ReplaceOrder (ord);
// faces same direction as leader
// ord = new Orders::FaceDirection(dist*turn_leader);
// faces opposite direction as leader, as in, stare at me in the face please
ord = new Orders::FaceDirection(-dist*turn_leader);
ord->SetParent (parent);
ReplaceOrder (ord);
*/
int alternate = fgnum%2 ? 1 : -1;
float psize = parent->radial_size;
int Ypos = 0;
int Xpos = 0;
int position = int( floor( (fgnum%3)*0.5*alternate ) );
//nice square formation, how many of these are you going to have anyway? Max 9, then go back. Should be enough.
switch (fgnum%9)
{
case 0:
Xpos = 0;
Ypos = 0;
break;
case 1:
Xpos = -1;
Ypos = 0;
break;
case 2:
Xpos = 1;
Ypos = 0;
break;
case 3:
Xpos = 0;
Ypos = -1;
break;
case 4:
Xpos = -1;
Ypos = -1;
break;
case 5:
Xpos = 1;
Ypos = -1;
break;
case 6:
Xpos = 0;
Ypos = 1;
break;
case 7:
Xpos = -1;
Ypos = 1;
break;
case 8:
Xpos = 1;
Ypos = 1;
break;
default:
Xpos = 0;
Ypos = 0;
}
float dist = (leader->radial_size+parent->radial_size);
float formdist = esc_percent*(1+fgnum*2)*alternate*(dist);
//if i am a cargo wingman go close for pickup
//if i am the capship, go close for pickup
if ( (parent->owner == leader->owner) || parent->owner == leader ) {
//float left= fgnum%2?1:-1;
float qdist = ( 1.5*parent->rSize()+1.5*leader->rSize() );
Order *ord =
new Orders::MoveTo(LeaderPosition+Vector(0.5*Xpos*psize,
0.5*Ypos*psize,
0.5*qdist), true, 4);
ord->SetParent(parent);
ReplaceOrder(ord);
//facing it
ord = new Orders::FaceDirection(-qdist*turn_leader);
ord->SetParent(parent);
ReplaceOrder(ord);
}
//if i'm not a cargo wingman, IT'S NOT MY PROBLEM.
else {
parent->owner = parent;
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
Flightgroup *leave = new Flightgroup();
leave->directive = "b";
parent->SetFg(leave, 1);
}
Order *o = leader->getAIState();
if (o) o->Communicate(c);
}
} else
last_time_insys = false;
for (unsigned int i = 0; i < suborders.size(); i++)
suborders[i]->AttachSelfOrder(leader);
}
} else if (fg->directive.find("h") != string::npos || fg->directive.find("H") != string::npos) {
//VSFileSystem::vs_fprintf (stderr,"he wnats to help out");
if (fg->directive != last_directive && leader) {
if ( leader->InCorrectStarSystem( _Universe->activeStarSystem() ) ) {
//VSFileSystem::vs_fprintf (stderr,"%s he wnats to help out and hasn't died\n", parent->name.c_str());
Unit *th = NULL;
if ( ( th = leader->Threat() ) ) {
//VSFileSystem::vs_fprintf (stderr,"he wnats to help out and he has a threat\n");
CommunicationMessage c(parent, leader, NULL, 0);
if ( parent->InRange(th, true, false) ) {
parent->Target(th);
parent->TargetTurret(th);
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
} else
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
Order *oo = leader->getAIState();
if (oo) oo->Communicate(c);
} else {
//bool targetted=false;
//float mindist;
//Unit * un=NULL;
th = GetThreat(parent, leader);
CommunicationMessage c(parent, leader, NULL, 0);
//VSFileSystem::vs_fprintf (stderr,"he wnats to help out against threat %d",th);
if (th) {
if ( parent->InRange(th, true, false) ) {
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
parent->Target(th);
parent->TargetTurret(th);
//if I am the capship, go into defensive mode.
if (parent == leader->owner) {
//parent->Target(parent);
parent->SetTurretAI();
TurretFAW(parent);
//MatchVelocity(parent->ClampVelocity(vec,true),Vector(0,0,0),true,true,false)
//Order * ord = new Orders::FormUp(QVector(position*parent->radial_size,0,fabs(dist)));
Order *ord =
new Orders::MatchLinearVelocity(parent->ClampVelocity(Vector(0,
0,
0),
true), true, false, true);
ord->SetParent(parent);
ReplaceOrder(ord);
if (parent->Target() != NULL) {
ord = new Orders::FaceTarget(false, 3);
ord->SetParent(parent);
ReplaceOrder(ord);
}
}
} else {}
//VSFileSystem::vs_fprintf (stderr,"Helping out kill: %s",th->name.c_str());
} else
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
Order *loo = leader->getAIState();
if (loo) loo->Communicate(c);
}
}
}
} else if (fg->directive.find("p") != string::npos || fg->directive.find("P") != string::npos) {
//VSFileSystem::vs_fprintf (stderr,"he wnats to help out");
bool callme = false;
if (fg->directive != last_directive && leader) {
if ( leader->InCorrectStarSystem( _Universe->activeStarSystem() ) ) {
//VSFileSystem::vs_fprintf (stderr,"%s he wnats to help out and hasn't died\n", parent->name.c_str());
Unit *th = NULL;
Unit *targ = fg->target.GetUnit();
if ( targ && ( th = targ->Threat() ) ) {
//VSFileSystem::vs_fprintf (stderr,"he wnats to help out and he has a threat\n");
CommunicationMessage c(parent, leader, NULL, 0);
if ( parent->InRange(th, true, false) ) {
parent->Target(th);
parent->TargetTurret(th);
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
fg->directive = "";
} else
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
Order *oo = leader->getAIState();
if (oo) oo->Communicate(c);
} else {
//bool targetted=false;
//float mindist;
//Unit * un=NULL;
th = GetThreat(parent, targ);
CommunicationMessage c(parent, leader, NULL, 0);
//VSFileSystem::vs_fprintf (stderr,"he wnats to help out against threat %d",th);
if (th) {
if ( parent->InRange(th, true, false) ) {
c.SetCurrentState(c.fsm->GetYesNode(), NULL, 0);
if ( th != parent->Target() ) callme = true;
parent->Target(th);
parent->TargetTurret(th);
//if I am the capship, go into defensive mode.
if (parent == leaderowner) {
//parent->Target(parent);
parent->SetTurretAI();
parent->TurretFAW();
//MatchVelocity(parent->ClampVelocity(vec,true),Vector(0,0,0),true,true,false)
//Order * ord = new Orders::FormUp(QVector(position*parent->radial_size,0,fabs(dist)));
Order *ord =
new Orders::MatchLinearVelocity(parent->ClampVelocity(Vector(0,
0,
0),
true), true, false, true);
ord->SetParent(parent);
ReplaceOrder(ord);
if (parent->Target() != NULL) {
ord = new Orders::FaceTarget(false, 3);
ord->SetParent(parent);
ReplaceOrder(ord);
}
}
} else
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
//VSFileSystem::vs_fprintf (stderr,"Helping out kill: %s",th->name.c_str());
} else
c.SetCurrentState(c.fsm->GetNoNode(), NULL, 0);
Order *loo = leader->getAIState();
if (loo) loo->Communicate(c);
}
}
}
}
}
last_directive = fg->directive;
}
return retval;
}
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
... continuing again ...
This is with the config for the repo; with the config for myself it looks a lot nicer, of course
EDIT: The first of the three posts got orphaned in the previous page.
And I'm sorry I had to post the file this way; my pc is still broken, so I got no access to the junction
server; tomorrow I'll probably fix it.
Code: Select all
static bool overridable (const std::string &s)
{
if ( s.empty() ) return true;
return ( *s.begin() ) != toupper( *s.begin() );
}
extern void LeadMe (Unit *un, string directive, string speech, bool changetarget);
void AggressiveAI::ReCommandWing (Flightgroup *fg)
{
static float time_to_recommand_wing = XMLSupport::parse_float( vs_config->getVariable("AI",
"Targetting",
"TargetCommandierTime",
"100") );
static bool verbose_debug = XMLSupport::parse_bool( vs_config->getVariable("data", "verbose_debug", "false") );
if (fg != NULL) {
Unit *lead;
if ( overridable(fg->directive) ) {
//computer won't override capital orders
if ( NULL != ( lead = fg->leader.GetUnit() ) ) {
if (float( rand() )/RAND_MAX < SIMULATION_ATOM/time_to_recommand_wing) {
if ( parent->Threat() && (parent->FShieldData() < .2 || parent->RShieldData() < .2) ) {
fg->directive = string("h");
LeadMe(parent, "h", "I need help here!", false);
if (verbose_debug)
VSFileSystem::vs_fprintf( stderr, "he needs help %s", parent->name.get().c_str() );
} else {
if ( lead->getFgSubnumber() >= parent->getFgSubnumber() ) {
fg->directive = string("b");
LeadMe(parent, "b", "I'm taking over this wing. Break and attack", false);
}
}
}
}
}
}
}
static Unit * GetRandomNav (vector< UnitContainer >navs[3], unsigned int randnum)
{
size_t total_size = navs[0].size()+navs[1].size()+navs[2].size();
if (total_size == 0) return NULL;
randnum %= total_size;
if ( randnum >= navs[0].size() ) {
randnum -= navs[0].size();
if ( randnum >= navs[1].size() ) {
randnum -= navs[1].size();
return navs[2][randnum].GetUnit();
}
return navs[1][randnum].GetUnit();
}
return navs[0][randnum].GetUnit();
}
static std::string insysString("Insys");
static std::string arrowString("->");
static Unit * ChooseNavPoint (Unit *parent, Unit **otherdest, float *lurk_on_arrival)
{
static string script = vs_config->getVariable("AI", "ChooseDestinationScript", "");
*lurk_on_arrival = 0;
if (script.length() > 0) {
Unit *ret = NULL;
UniverseUtil::setScratchUnit(parent);
CompileRunPython(script);
ret = UniverseUtil::getScratchUnit();
UniverseUtil::setScratchUnit(NULL);
if (ret != NULL && ret != parent)
return ret;
}
StarSystem *ss = _Universe->activeStarSystem();
StarSystem::Statistics *stats = &ss->stats;
float sysrel = UnitUtil::getRelationFromFaction(parent, stats->system_faction);
static float lurk_time = XMLSupport::parse_float( vs_config->getVariable("AI", "lurk_time", "600") );
static float select_time =
XMLSupport::parse_float( vs_config->getVariable("AI", "fg_nav_select_time", "120") );
static float hostile_select_time =
XMLSupport::parse_float( vs_config->getVariable("AI", "pirate_nav_select_time", "400") );
static int num_ships_per_roid =
XMLSupport::parse_int( vs_config->getVariable("AI", "num_pirates_per_asteroid_field", "12") );
bool civilian = FactionUtil::isCitizenInt(parent->faction);
bool hostile = sysrel < 0;
bool anarchy = stats->enemycount > stats->friendlycount;
float timehash = select_time;
if (hostile && !anarchy) timehash = hostile_select_time;
unsigned int firstRand, thirdRand;
float secondRand;
const unsigned int maxrand = 5;
unsigned int additionalrand[maxrand];
if (civilian) {
firstRand = vsrandom.genrand_int31();
secondRand = vsrandom.uniformExc(0, 1);
thirdRand = vsrandom.genrand_int31();
for (unsigned int i = 0; i < maxrand; ++i)
additionalrand[i] = thirdRand+i;
} else {
int k = (int) (getNewTime()/timehash); //two minutes
string key = UnitUtil::getFlightgroupName(parent);
std::string::const_iterator start = key.begin();
for (; start != key.end(); start++)
k += (k*128)+*start;
VSRandom choosePlace(k);
firstRand = choosePlace.genrand_int31();
secondRand = choosePlace.uniformExc(0, 1);
thirdRand = choosePlace.genrand_int31();
for (unsigned int i = 0; i < maxrand; ++i)
additionalrand[i] = choosePlace.genrand_int31();
}
bool asteroidhide = false;
if (stats->friendlycount > 0 && stats->enemycount > 0)
asteroidhide = (secondRand < stats->enemycount/(float) stats->friendlycount)
&& (secondRand < num_ships_per_roid*stats->navs[2].size()/(float) stats->enemycount);
bool siege = stats->enemycount > 2*stats->friendlycount; //rough approx
int whichlist = 1; //friendly
std::string fgname = UnitUtil::getFlightgroupName(parent);
bool insys =
(parent->GetJumpStatus().drive == -2) || fgname.find(insysString) != std::string::npos;
std::string::size_type whereconvoy = fgname.find(arrowString);
bool convoy = (whereconvoy != std::string::npos);
size_t total_size = stats->navs[0].size()+stats->navs[whichlist].size(); //friendly and neutral
static bool bad_units_lurk = XMLSupport::parse_bool( vs_config->getVariable("AI", "hostile_lurk", "true") );
if (hostile && bad_units_lurk) {
if (anarchy && !siege) {
whichlist = 2;
total_size = stats->navs[0].size()+stats->navs[whichlist].size(); //asteroids and neutrals
} else {
whichlist = 2;
total_size = stats->navs[whichlist].size(); //just asteroids
}
} else if (civilian) {
if (anarchy || siege) {
whichlist = 0;
total_size = stats->navs[0].size();
} else if (insys || convoy) {
whichlist = 1;
total_size = stats->navs[1].size(); //don't go to jump point
}
}
if (hostile && ( (anarchy == false && asteroidhide == false) || total_size == 0 ) && civilian == false && bad_units_lurk) {
//hit and run
Unit *a = GetRandomNav(stats->navs, firstRand);
Unit *b = GetRandomNav(stats->navs, thirdRand);
if (a == b)
b = GetRandomNav(stats->navs, thirdRand+1);
if (a != b) {
int retrycount = maxrand;
while ( --retrycount > 0
&& (UnitUtil::getDistance(a, b) < parent->GetComputerData().radar.maxrange*4 || a == b) ) {
b = GetRandomNav(stats->navs, additionalrand[retrycount]);
}
if (retrycount != 0) {
*otherdest = b;
*lurk_on_arrival = lurk_time;
}
}
return a;
} else {
if (convoy) {
std::string srcdst[2] = {fgname.substr(0, whereconvoy), fgname.substr(whereconvoy+2)};
if ( srcdst[0] == ss->getFileName() ) srcdst[0] = srcdst[1];
if ( srcdst[1] == ss->getFileName() ) srcdst[1] = srcdst[0];
size_t rand8 = thirdRand%8;
if (thirdRand < 2) {
vsUMap< std::string, UnitContainer >::iterator i = stats->jumpPoints.find(srcdst[thirdRand]);
if ( i != stats->jumpPoints.end() ) {
Unit *un = i->second.GetUnit();
if (un)
return un;
} else {
total_size = stats->navs[whichlist].size()+stats->navs[0].size(); //no such jump point--have to random-walk it
//maybe one day we can incorporate some sort of route planning
}
}
}
if (total_size > 0) {
firstRand %= total_size;
if ( firstRand >= stats->navs[whichlist].size() ) {
firstRand -= stats->navs[whichlist].size();
whichlist = 0; //allows you to look for both neutral and ally lists
}
return stats->navs[whichlist][firstRand].GetUnit();
}
}
return NULL;
}
static Unit * ChooseNearNavPoint (Unit *parent, Unit *suggestion, QVector location, float locradius)
{
if (suggestion) return suggestion;
Unit *candidate = NULL;
float dist = FLT_MAX;
Unit *un;
NearestNavOrCapshipLocator nnl;
findObjects(_Universe->activeStarSystem()->collidemap[Unit::UNIT_ONLY],
parent->location[Unit::UNIT_ONLY],
&nnl);
return nnl.retval.unit;
//DEAD CODE
for (un_iter i = _Universe->activeStarSystem()->getUnitList().createIterator();
(un = *i) != NULL;
++i) {
if (UnitUtil::isSignificant(un) && un != parent) {
float newdist = ( location-un->Position() ).Magnitude()-un->rSize()-locradius;
if (candidate == NULL || newdist <= dist) {
candidate = un;
dist = newdist;
}
}
}
return candidate;
//END DEAD CODE
}
bool CloseEnoughToNavOrDest (Unit *parent, Unit *navUnit, QVector nav)
{
static float how_far_to_stop_moving =
XMLSupport::parse_float( vs_config->getVariable("AI", "how_far_to_stop_navigating", "100") );
if (navUnit && navUnit->isUnit() != PLANETPTR) {
float dist = UnitUtil::getDistance(navUnit, parent);
if (dist < SIMULATION_ATOM*parent->Velocity.Magnitude()*parent->predicted_priority*how_far_to_stop_moving) return true;
}
return ( nav-parent->Position() ).MagnitudeSquared() < 4*parent->rSize()*parent->rSize();
}
volatile Unit *uoif;
class FlyTo : public Orders::MoveTo
{
float creationtime;
UnitContainer destUnit;
public: FlyTo (const QVector &target,
bool aft,
bool terminating = true,
float creationtime = 0,
int leniency = 6,
Unit *destUnit = NULL) : MoveTo(target, aft, leniency, terminating)
{
this->creationtime = creationtime;
this->destUnit = destUnit;
}
virtual void Execute ()
{
if (parent == uoif)
printf("kewl");
MoveTo::Execute();
Unit *un = destUnit.GetUnit();
if ( CloseEnoughToNavOrDest(parent, un, targetlocation) ) done = true;
un = NULL;
static float mintime = XMLSupport::parse_float( vs_config->getVariable("AI", "min_time_to_auto", "25") );
if (getNewTime()-creationtime > mintime) {
if (_Universe->AccessCockpit()->autoInProgress() && ( !_Universe->AccessCockpit()->unitInAutoRegion(parent) )
&& ( un = ChooseNearNavPoint(parent, destUnit.GetUnit(), targetlocation, 0) ) != NULL)
WarpToP(parent, un, true);
else {
Unit *playa = _Universe->AccessCockpit()->GetParent();
if (playa == NULL || playa->Target() != parent || 1)
WarpToP(parent, targetlocation, 0, true);
}
}
}
};
static Vector randVector ()
{
return Vector( (rand()/(float) RAND_MAX)*2-1, (rand()/(float) RAND_MAX)*2-1, (rand()/(float) RAND_MAX)*2-1 );
}
static void GoTo (AggressiveAI *ai,
Unit *parent,
const QVector &nav,
float creationtime,
bool boonies = false,
Unit *destUnit = NULL)
{
static bool can_afterburn = XMLSupport::parse_bool( vs_config->getVariable("AI", "afterburn_to_no_enemies", "true") );
Order *mt = new FlyTo(nav, can_afterburn, true, creationtime, boonies ? 16 : 6, destUnit);
Order *ch = new Orders::ChangeHeading(nav, 32, .25f, false);
ai->eraseType(Order::FACING);
ai->eraseType(Order::MOVEMENT);
mt->SetParent(parent);
ch->SetParent(parent);
ai->ReplaceOrder(mt);
ai->EnqueueOrder(ch);
}
void AggressiveAI::ExecuteNoEnemies ()
{
static float safetyspacing = XMLSupport::parse_float( vs_config->getVariable("AI", "safetyspacing", "2500") );
static float randspacingfactor = XMLSupport::parse_float( vs_config->getVariable("AI", "randomspacingfactor", "4") );
if (nav.i == 0 && nav.j == 0 && nav.k == 0) {
Unit *otherdest = NULL;
Unit *dest = ChooseNavPoint(parent, &otherdest, &this->lurk_on_arrival);
if (dest) {
static bool can_warp_to = XMLSupport::parse_bool( vs_config->getVariable("AI", "warp_to_no_enemies", "true") );
static float mintime = XMLSupport::parse_float( vs_config->getVariable("AI", "min_time_to_auto", "25") );
if (getNewTime()-creationtime > mintime) {
if (can_warp_to)
WarpToP(parent, dest, true);
else if ( _Universe->AccessCockpit()->autoInProgress() && !_Universe->AccessCockpit()->unitInAutoRegion(parent) )
WarpToP(parent, dest, true);
}
Vector dir = parent->Position()-dest->Position();
Vector unitdir = dir.Normalize();
if (!otherdest) {
navDestination = dest;
dir = unitdir*( dest->rSize()+parent->rSize() );
if (dest->isUnit() == PLANETPTR) {
float planetpct = UniverseUtil::getPlanetRadiusPercent();
dir *= (planetpct+1.0f);
dir += randVector()*parent->rSize()*2*randspacingfactor;
} else {
dir *= 2;
dir += (unitdir*safetyspacing);
dir +=
( (randVector()*randspacingfactor
/4)
+(unitdir
*randspacingfactor) )
*( ( parent->rSize() > (safetyspacing/5) ) ? (safetyspacing/5) : ( parent->rSize() ) );
}
}
nav = dest->Position()+dir;
if (otherdest) {
nav += otherdest->Position();
nav = nav*.5;
}
#ifdef AGGDEBUG
std::string fgname = UnitUtil::getFlightgroupName(parent);
std::string pfullname = parent->getFullname();
std::string dfullname = dest->getFullname();
printf( "%s:%s %s going to %s:%s", parent->name.get().c_str(), pfullname.c_str(), fgname.c_str(),
dest->name.get().c_str(), dfullname.c_str() );
if (otherdest) {
std::string ofullname = otherdest->getFullname();
printf( " between %s:%s\n", otherdest->name.get().c_str(), ofullname.c_str() );
} else printf("\n");
#endif
GoTo(this, parent, nav, creationtime, otherdest != NULL, otherdest == NULL ? dest : NULL);
}
} else {
if (CloseEnoughToNavOrDest(parent, navDestination.GetUnit(), nav) && lurk_on_arrival == 0) {
std::string fgname = UnitUtil::getFlightgroupName(parent);
nav = QVector(0, 0, 0);
Unit *dest = ChooseNearNavPoint( parent, navDestination.GetUnit(), parent->Position(), parent->rSize() );
if (dest) {
if ( fgname.find(insysString) == string::npos && dest->GetDestinations().size() > 0
&& UniverseUtil::systemInMemory(dest->GetDestinations()[0]) ) {
parent->ActivateJumpDrive(0);
parent->Target(dest); //fly there, baby!
} else if ( dest->GetDestinations().size() == 0 && false == UnitUtil::isCapitalShip(parent)
&& UnitUtil::isDockableUnit(dest) ) {
//UnitUtil::performDockingOperations(parent,dest,0);//dock there, baby
Order *ai = parent->aistate;
parent->aistate = NULL;
parent->PrimeOrders( new Orders::DockingOps(dest, ai, true, false) );
} else
ExecuteNoEnemies(); //find a new place to go
} else
ExecuteNoEnemies(); //no suitable docking point found, recursive call which will take door1
//go dock to the nav point
} else if (lurk_on_arrival > 0) {
lurk_on_arrival -= SIMULATION_ATOM;
//slowdown
parent->Thrust(-parent->GetMass()*parent->UpCoordinateLevel( parent->GetVelocity() )/SIMULATION_ATOM, false);
parent->graphicOptions.InWarp = 0;
if (lurk_on_arrival <= 0) {
nav = QVector(0, 0, 0);
ExecuteNoEnemies(); //select new place to go
}
//have to do something while here.
} else
GoTo( this, parent, nav, creationtime, false, navDestination.GetUnit() );
}
/*
Order * ord = new Orders::MatchLinearVelocity (parent->ClampVelocity(Vector (0,0,10000),false),true,true,false);
ord->SetParent(parent);
EnqueueOrder (ord);
*/
}
void AggressiveAI::AfterburnerJumpTurnTowards (Unit *target)
{
AfterburnTurnTowards(this, parent);
static float jump_time_limit = XMLSupport::parse_float( vs_config->getVariable("AI", "force_jump_after_time", "120") );
if (jump_time_check == 0) {
float dist = ( target->Position()-parent->Position() ).MagnitudeSquared();
if (last_jump_distance < dist || last_jump_time > jump_time_limit) {
//force jump
last_jump_time = 0;
if ( target->GetDestinations().size() ) {
string dest = target->GetDestinations()[0];
UnitUtil::JumpTo(parent, dest);
}
} else
last_jump_distance = dist;
}
}
volatile Unit *uoi;
void AggressiveAI::Execute ()
{
if (parent == uoi)
printf("kewl");
extern double aggfire;
jump_time_check++; //just so we get a nicely often wrapping var;
jump_time_check %= 5;
Flightgroup *fg = parent->getFlightgroup();
//ReCommandWing(fg);
double firetime = queryTime();
static int pir = FactionUtil::GetFactionIndex("pirates");
if (parent->faction == pir) if (rand() == 0) printf("ahoy, a pirates!");
FireAt::Execute();
aggfire += queryTime()-firetime;
static bool resistance_to_side_movement =
XMLSupport::parse_bool( vs_config->getVariable("AI", "resistance_to_side_movement", "false") );
if (resistance_to_side_movement) {
Vector p, q, r;
parent->GetOrientation(p, q, r);
float forwardness = parent->Velocity.Dot(r);
Vector countervelocity = -parent->Velocity;
Vector counterforce = -parent->NetForce;
float forceforwardness = parent->NetForce.Dot(r);
if (forceforwardness > 0)
counterforce = forceforwardness*r-parent->NetForce;
if (forwardness > 0)
countervelocity = forwardness*r-parent->Velocity;
static float resistance_percent =
XMLSupport::parse_float( vs_config->getVariable("AI", "resistance_to_side_movement_percent", ".01") );
static float force_resistance_percent =
XMLSupport::parse_float( vs_config->getVariable("AI", "resistance_to_side_force_percent", "1") );
parent->Velocity += countervelocity*resistance_percent;
parent->NetForce += counterforce*force_resistance_percent;
counterforce = -parent->NetLocalForce;
counterforce.k = 0;
parent->NetLocalForce += counterforce*force_resistance_percent;
}
Unit *target = parent->Target();
bool isjumpable = target ? ( !target->GetDestinations().empty() ) : false;
if ( !ProcessCurrentFgDirective(fg) ) {
if (isjumpable) {
if (parent->GetJumpStatus().drive < 0) {
parent->ActivateJumpDrive(0);
if (parent->GetJumpStatus().drive == -2) {
static bool AIjumpCheat =
XMLSupport::parse_bool( vs_config->getVariable("AI", "always_have_jumpdrive_cheat", "false") );
if (AIjumpCheat) {
static int i = 0;
if (!i) {
VSFileSystem::vs_fprintf(stderr, "FIXME: warning ship not equipped to jump");
i = 1;
}
parent->jump.drive = -1;
} else {
//VSFileSystem::vs_fprintf (stderr,"warning ship not equipped to jump");
parent->Target(NULL);
}
} else if (parent->GetJumpStatus().drive < 0) {
static bool AIjumpCheat = XMLSupport::parse_bool( vs_config->getVariable("AI", "jump_cheat", "true") );
if (AIjumpCheat)
parent->jump.drive = 0;
}
}
last_jump_time += SIMULATION_ATOM;
} else
last_jump_time = 0;
if ( (!isjumpable) && interruptcurtime <= 0 && target ) {
//fprintf (stderr,"i");
ProcessLogic(*logic, true);
}
if (!target) {
logiccurtime -= SIMULATION_ATOM;
if (logiccurtime < 0) {
logiccurtime = 20;
currentpriority = -FLT_MAX;
//eraseType (Order::FACING);
//eraseType (Order::MOVEMENT);
}
}
//if (parent->getAIState()->queryType (Order::FACING)==NULL&&parent->getAIState()->queryType (Order::MOVEMENT)==NULL) {
if (queryAny(Order::FACING|Order::MOVEMENT) == NULL) {
if (isjumpable)
AfterburnerJumpTurnTowards(target);
else {
last_jump_distance = FLT_MAX;
if (target)
ProcessLogic(*logic, false);
else {}
}
if (!isjumpable) ExecuteNoEnemies();
} else {
if (target) {
static bool can_warp_to = XMLSupport::parse_bool( vs_config->getVariable("AI", "warp_to_enemies", "true") );
if ( can_warp_to || _Universe->AccessCockpit()->autoInProgress() )
WarpToP(parent, target, false);
logiccurtime -= SIMULATION_ATOM;
interruptcurtime -= SIMULATION_ATOM;
if (logiccurtime <= 0) {
//parent->getAIState()->eraseType (Order::FACING);
//parent->getAIState()->eraseType (Order::MOVEMENT);
eraseType(Order::FACING);
eraseType(Order::MOVEMENT);
if (isjumpable) {
AfterburnerJumpTurnTowards(target);
logiccurtime = logic->maxtime;
} else {
last_jump_distance = FLT_MAX;
ProcessLogic(*logic, false);
}
}
} else if (queryAny(Order::MOVEMENT) == NULL)
ExecuteNoEnemies();
}
}
#ifdef AGGDEBUG
VSFileSystem::vs_fprintf(stderr, "endagg");
fflush(stderr);
#endif
if (getTimeCompression() > 3) {
float mag = parent->GetVelocity().Magnitude();
if (mag > .01) mag = 1/mag;
parent->SetVelocity( parent->GetVelocity()*( mag*parent->GetComputerData().max_speed()/getTimeCompression() ) );
parent->NetLocalForce = parent->NetForce = Vector(0, 0, 0);
}
target = parent->Target();
isjumpable = target ? ( !target->GetDestinations().empty() ) : false;
if (!isjumpable) {
if (parent->GetJumpStatus().drive >= 0)
parent->ActivateJumpDrive(-1);
}
}
AggressiveAI *DONOTUSEAG = NULL;
EDIT: The first of the three posts got orphaned in the previous page.
And I'm sorry I had to post the file this way; my pc is still broken, so I got no access to the junction
server; tomorrow I'll probably fix it.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
By the way, these are my uncrustify configure settings for vs repo format:
and this is my configuration for myself:
Code: Select all
# Uncrustify 0.55
newlines = auto
input_tab_size = 8
output_tab_size = 8
string_escape_char = 92
string_escape_char2 = 0
indent_columns = 4
indent_continue = 0
indent_with_tabs = 0
indent_cmt_with_tabs = false
indent_align_string = false
indent_xml_string = 0
indent_brace = 0
indent_braces = false
indent_braces_no_func = false
indent_brace_parent = false
indent_namespace = false
indent_namespace_level = 0
indent_namespace_limit = 0
indent_extern = false
indent_class = true
indent_class_colon = false
indent_else_if = false
indent_var_def_blk = 0
indent_var_def_cont = false
indent_func_call_param = false
indent_func_def_param = false
indent_func_proto_param = false
indent_func_class_param = false
indent_func_ctor_var_param = false
indent_template_param = false
indent_func_param_double = false
indent_func_const = 1
indent_func_throw = 1
indent_member = 0
indent_sing_line_comments = 0
indent_relative_single_line_comments = false
indent_switch_case = 0
indent_case_shift = 0
indent_case_brace = 4
indent_col1_comment = false
indent_label = 1
indent_access_spec = 1
indent_access_spec_body = false
indent_paren_nl = false
indent_paren_close = 1
indent_comma_paren = false
indent_bool_paren = false
indent_first_bool_expr = false
indent_square_nl = false
indent_preserve_sql = false
indent_align_assign = true
sp_arith = remove
sp_assign = ignore
sp_before_assign = force
sp_after_assign = force
sp_enum_assign = ignore
sp_enum_before_assign = remove
sp_enum_after_assign = remove
sp_pp_concat = remove
sp_pp_stringify = remove
sp_bool = force
sp_compare = force
sp_inside_paren = remove
sp_paren_paren = remove
sp_balance_nested_parens = true
sp_paren_brace = force
sp_before_ptr_star = force
sp_before_unnamed_ptr_star = remove
sp_between_ptr_star = remove
sp_after_ptr_star = remove
sp_after_ptr_star_func = force
sp_before_ptr_star_func = force
sp_before_byref = force
sp_before_unnamed_byref = remove
sp_after_byref = remove
sp_after_byref_func = force
sp_before_byref_func = remove
sp_after_type = force
sp_template_angle = force
sp_before_angle = remove
sp_inside_angle = force
sp_after_angle = remove
sp_angle_paren = force
sp_angle_word = remove
sp_before_sparen = force
sp_inside_sparen = remove
sp_inside_sparen_close = remove
sp_after_sparen = force
sp_sparen_brace = force
sp_invariant_paren = ignore
sp_after_invariant_paren = ignore
sp_special_semi = remove
sp_before_semi = remove
sp_before_semi_for = remove
sp_before_semi_for_empty = remove
sp_after_semi = add
sp_after_semi_for = force
sp_after_semi_for_empty = remove
sp_before_square = remove
sp_before_squares = remove
sp_inside_square = remove
sp_after_comma = force
sp_before_comma = remove
sp_before_ellipsis = force
sp_after_class_colon = force
sp_before_class_colon = force
sp_before_case_colon = remove
sp_after_operator = remove
sp_after_operator_sym = remove
sp_after_cast = force
sp_inside_paren_cast = remove
sp_cpp_cast_paren = remove
sp_sizeof_paren = force
sp_after_tag = ignore
sp_inside_braces_enum = remove
sp_inside_braces_struct = remove
sp_inside_braces = remove
sp_inside_braces_empty = remove
sp_type_func = force
sp_func_proto_paren = force
sp_func_def_paren = force
sp_inside_fparens = remove
sp_inside_fparen = remove
sp_square_fparen = force
sp_fparen_brace = force
sp_func_call_paren = remove
sp_func_call_user_paren = ignore
sp_func_class_paren = force
sp_return_paren = force
sp_attribute_paren = force
sp_defined_paren = force
sp_throw_paren = force
sp_macro = force
sp_macro_func = force
sp_else_brace = force
sp_brace_else = force
sp_brace_typedef = force
sp_catch_brace = force
sp_brace_catch = force
sp_finally_brace = force
sp_brace_finally = force
sp_try_brace = force
sp_getset_brace = ignore
sp_before_dc = remove
sp_after_dc = remove
sp_d_array_colon = ignore
sp_not = remove
sp_inv = remove
sp_addr = remove
sp_member = remove
sp_deref = remove
sp_sign = remove
sp_incdec = remove
sp_before_nl_cont = force
sp_after_oc_scope = ignore
sp_after_oc_colon = ignore
sp_before_oc_colon = ignore
sp_after_send_oc_colon = ignore
sp_before_send_oc_colon = ignore
sp_after_oc_type = ignore
sp_after_oc_return_type = ignore
sp_after_oc_at_sel = ignore
sp_before_oc_block_caret = ignore
sp_after_oc_block_caret = ignore
sp_cond_colon = force
sp_cond_question = force
sp_case_label = force
sp_range = ignore
sp_cmt_cpp_start = remove
sp_endif_cmt = force
align_keep_tabs = false
align_with_tabs = false
align_on_tabstop = false
align_number_left = false
align_func_params = false
align_same_func_call_params = false
align_var_def_span = 7
align_var_def_star_style = 2
align_var_def_amp_style = 2
align_var_def_thresh = 0
align_var_def_gap = 0
align_var_def_colon = false
align_var_def_attribute = false
align_var_def_inline = false
align_assign_span = 7
align_assign_thresh = 0
align_enum_equ_span = 7
align_enum_equ_thresh = 0
align_var_struct_span = 7
align_var_struct_thresh = 0
align_var_struct_gap = 0
align_struct_init_span = 7
align_typedef_gap = 0
align_typedef_span = 7
align_typedef_func = 0
align_typedef_star_style = 2
align_typedef_amp_style = 2
align_right_cmt_span = 0
align_right_cmt_mix = false
align_right_cmt_gap = 0
align_right_cmt_at_col = 0
align_func_proto_span = 0
align_func_proto_gap = 0
align_on_operator = false
align_mix_var_proto = false
align_single_line_func = false
align_single_line_brace = false
align_single_line_brace_gap = 0
align_oc_msg_spec_span = 0
align_nl_cont = true
align_pp_define_gap = 0
align_pp_define_span = 0
align_left_shift = true
align_oc_msg_colon_span = 0
align_oc_decl_colon = false
nl_collapse_empty_body = true
nl_assign_leave_one_liners = true
nl_class_leave_one_liners = false
nl_enum_leave_one_liners = true
nl_getset_leave_one_liners = true
nl_func_leave_one_liners = true
nl_if_leave_one_liners = true
nl_start_of_file = remove
nl_start_of_file_min = 0
nl_end_of_file = force
nl_end_of_file_min = 0
nl_assign_brace = remove
nl_assign_square = ignore
nl_after_square_assign = ignore
nl_func_var_def_blk = 0
nl_fcall_brace = force
nl_enum_brace = force
nl_struct_brace = force
nl_union_brace = force
nl_if_brace = remove
nl_brace_else = remove
nl_elseif_brace = remove
nl_else_brace = remove
nl_else_if = remove
nl_brace_finally = force
nl_finally_brace = remove
nl_try_brace = remove
nl_getset_brace = remove
nl_for_brace = remove
nl_catch_brace = remove
nl_brace_catch = force
nl_while_brace = remove
nl_brace_brace = force
nl_do_brace = remove
nl_brace_while = remove
nl_switch_brace = force
nl_multi_line_cond = false
nl_multi_line_define = true
nl_before_case = false
nl_before_throw = remove
nl_after_case = true
nl_namespace_brace = force
nl_template_class = force
nl_class_brace = force
nl_class_init_args = force
nl_func_type_name = remove
nl_func_type_name_class = remove
nl_func_scope_name = remove
nl_func_proto_type_name = remove
nl_func_paren = remove
nl_func_decl_start = remove
nl_func_decl_start_single = remove
nl_func_decl_args = remove
nl_func_decl_end = remove
nl_func_decl_end_single = remove
nl_func_decl_empty = remove
nl_fdef_brace = force
nl_after_return = true
nl_return_expr = remove
nl_after_semicolon = true
nl_after_brace_open = true
nl_after_brace_open_cmt = true
nl_after_vbrace_open = true
nl_after_vbrace_open_empty = false
nl_after_brace_close = true
nl_after_vbrace_close = true
nl_define_macro = false
nl_squeeze_ifdef = true
nl_before_if = remove
nl_after_if = remove
nl_before_for = remove
nl_after_for = remove
nl_before_while = remove
nl_after_while = remove
nl_before_switch = remove
nl_after_switch = remove
nl_before_do = remove
nl_after_do = remove
nl_ds_struct_enum_cmt = false
nl_ds_struct_enum_close_brace = false
nl_class_colon = ignore
nl_create_if_one_liner = true
nl_create_for_one_liner = true
nl_create_while_one_liner = true
pos_arith = lead
pos_assign = trail
pos_bool = lead
pos_compare = lead
pos_conditional = lead
pos_comma = trail
pos_class_comma = lead
pos_class_colon = trail
code_width = 128
ls_for_split_full = true
ls_func_split_full = true
nl_max = 2
nl_after_func_proto = 0
nl_after_func_proto_group = 1
nl_after_func_body = 0
nl_after_func_body_one_liner = 0
nl_before_block_comment = 1
nl_before_c_comment = 0
nl_before_cpp_comment = 0
nl_after_multiline_comment = false
nl_before_access_spec = 0
nl_after_access_spec = 0
nl_comment_func_def = 0
nl_after_try_catch_finally = 0
nl_around_cs_property = 0
nl_between_get_set = 0
eat_blanks_after_open_brace = true
eat_blanks_before_close_brace = true
mod_full_brace_do = remove
mod_full_brace_for = remove
mod_full_brace_function = ignore
mod_full_brace_if = remove
mod_full_brace_if_chain = false
mod_full_brace_nl = 2
mod_full_brace_while = ignore
mod_paren_on_return = remove
mod_pawn_semicolon = false
mod_full_paren_if_bool = false
mod_remove_extra_semicolon = true
mod_add_long_function_closebrace_comment = 0
mod_add_long_switch_closebrace_comment = 0
mod_add_long_ifdef_endif_comment = 0
mod_add_long_ifdef_else_comment = 0
mod_sort_import = false
mod_sort_using = false
mod_sort_include = false
mod_move_case_break = false
mod_case_brace = remove
mod_remove_empty_return = true
cmt_width = 0
cmt_reflow_mode = 0
cmt_indent_multi = true
cmt_c_group = false
cmt_c_nl_start = false
cmt_c_nl_end = false
cmt_cpp_group = false
cmt_cpp_nl_start = false
cmt_cpp_nl_end = false
cmt_cpp_to_c = false
cmt_star_cont = false
cmt_sp_before_star_cont = 0
cmt_sp_after_star_cont = 0
cmt_multi_check_last = true
cmt_insert_file_header = ""
cmt_insert_file_footer = ""
cmt_insert_func_header = ""
cmt_insert_class_header = ""
cmt_insert_before_preproc = false
pp_indent = ignore
pp_indent_at_level = false
pp_indent_count = 1
pp_space = ignore
pp_space_count = 0
pp_indent_region = 0
pp_region_indent_code = false
pp_indent_if = 0
pp_if_indent_code = false
pp_define_at_level = false
Code: Select all
# Uncrustify 0.55
newlines = auto
input_tab_size = 8
output_tab_size = 8
string_escape_char = 92
string_escape_char2 = 0
indent_columns = 4
indent_continue = 0
indent_with_tabs = 0
indent_cmt_with_tabs = false
indent_align_string = false
indent_xml_string = 0
indent_brace = 0
indent_braces = false
indent_braces_no_func = false
indent_brace_parent = false
indent_namespace = false
indent_namespace_level = 0
indent_namespace_limit = 0
indent_extern = false
indent_class = true
indent_class_colon = false
indent_else_if = false
indent_var_def_blk = 0
indent_var_def_cont = false
indent_func_call_param = false
indent_func_def_param = false
indent_func_proto_param = false
indent_func_class_param = false
indent_func_ctor_var_param = false
indent_template_param = false
indent_func_param_double = false
indent_func_const = 1
indent_func_throw = 1
indent_member = 0
indent_sing_line_comments = 0
indent_relative_single_line_comments = false
indent_switch_case = 0
indent_case_shift = 0
indent_case_brace = 4
indent_col1_comment = false
indent_label = 1
indent_access_spec = 1
indent_access_spec_body = false
indent_paren_nl = false
indent_paren_close = 1
indent_comma_paren = false
indent_bool_paren = false
indent_first_bool_expr = false
indent_square_nl = false
indent_preserve_sql = false
indent_align_assign = true
sp_arith = remove
sp_assign = ignore
sp_before_assign = force
sp_after_assign = force
sp_enum_assign = ignore
sp_enum_before_assign = remove
sp_enum_after_assign = remove
sp_pp_concat = remove
sp_pp_stringify = remove
sp_bool = force
sp_compare = force
sp_inside_paren = force
sp_paren_paren = remove
sp_balance_nested_parens = true
sp_paren_brace = remove
sp_before_ptr_star = force
sp_before_unnamed_ptr_star = remove
sp_between_ptr_star = remove
sp_after_ptr_star = remove
sp_after_ptr_star_func = force
sp_before_ptr_star_func = force
sp_before_byref = force
sp_before_unnamed_byref = remove
sp_after_byref = remove
sp_after_byref_func = force
sp_before_byref_func = remove
sp_after_type = force
sp_template_angle = remove
sp_before_angle = remove
sp_inside_angle = force
sp_after_angle = force
sp_angle_paren = remove
sp_angle_word = remove
sp_before_sparen = remove
sp_inside_sparen = force
sp_inside_sparen_close = force
sp_after_sparen = remove
sp_sparen_brace = remove
sp_invariant_paren = ignore
sp_after_invariant_paren = ignore
sp_special_semi = force
sp_before_semi = remove
sp_before_semi_for = remove
sp_before_semi_for_empty = force
sp_after_semi = add
sp_after_semi_for = force
sp_after_semi_for_empty = force
sp_before_square = remove
sp_before_squares = remove
sp_inside_square = remove
sp_after_comma = force
sp_before_comma = remove
sp_before_ellipsis = force
sp_after_class_colon = force
sp_before_class_colon = force
sp_before_case_colon = remove
sp_after_operator = remove
sp_after_operator_sym = remove
sp_after_cast = force
sp_inside_paren_cast = remove
sp_cpp_cast_paren = remove
sp_sizeof_paren = remove
sp_after_tag = ignore
sp_inside_braces_enum = force
sp_inside_braces_struct = force
sp_inside_braces = force
sp_inside_braces_empty = remove
sp_type_func = force
sp_func_proto_paren = remove
sp_func_def_paren = remove
sp_inside_fparens = remove
sp_inside_fparen = force
sp_square_fparen = remove
sp_fparen_brace = remove
sp_func_call_paren = remove
sp_func_call_user_paren = ignore
sp_func_class_paren = remove
sp_return_paren = remove
sp_attribute_paren = remove
sp_defined_paren = remove
sp_throw_paren = remove
sp_macro = force
sp_macro_func = force
sp_else_brace = remove
sp_brace_else = remove
sp_brace_typedef = force
sp_catch_brace = remove
sp_brace_catch = remove
sp_finally_brace = remove
sp_brace_finally = remove
sp_try_brace = remove
sp_getset_brace = ignore
sp_before_dc = remove
sp_after_dc = remove
sp_d_array_colon = ignore
sp_not = remove
sp_inv = remove
sp_addr = remove
sp_member = remove
sp_deref = remove
sp_sign = remove
sp_incdec = remove
sp_before_nl_cont = force
sp_after_oc_scope = ignore
sp_after_oc_colon = ignore
sp_before_oc_colon = ignore
sp_after_send_oc_colon = ignore
sp_before_send_oc_colon = ignore
sp_after_oc_type = ignore
sp_after_oc_return_type = ignore
sp_after_oc_at_sel = ignore
sp_before_oc_block_caret = ignore
sp_after_oc_block_caret = ignore
sp_cond_colon = force
sp_cond_question = force
sp_case_label = force
sp_range = ignore
sp_cmt_cpp_start = remove
sp_endif_cmt = force
align_keep_tabs = false
align_with_tabs = false
align_on_tabstop = false
align_number_left = false
align_func_params = false
align_same_func_call_params = false
align_var_def_span = 7
align_var_def_star_style = 2
align_var_def_amp_style = 2
align_var_def_thresh = 0
align_var_def_gap = 0
align_var_def_colon = false
align_var_def_attribute = false
align_var_def_inline = false
align_assign_span = 7
align_assign_thresh = 0
align_enum_equ_span = 7
align_enum_equ_thresh = 0
align_var_struct_span = 7
align_var_struct_thresh = 0
align_var_struct_gap = 0
align_struct_init_span = 7
align_typedef_gap = 0
align_typedef_span = 7
align_typedef_func = 0
align_typedef_star_style = 2
align_typedef_amp_style = 2
align_right_cmt_span = 0
align_right_cmt_mix = false
align_right_cmt_gap = 0
align_right_cmt_at_col = 0
align_func_proto_span = 0
align_func_proto_gap = 0
align_on_operator = false
align_mix_var_proto = false
align_single_line_func = false
align_single_line_brace = false
align_single_line_brace_gap = 0
align_oc_msg_spec_span = 0
align_nl_cont = true
align_pp_define_gap = 0
align_pp_define_span = 0
align_left_shift = true
align_oc_msg_colon_span = 0
align_oc_decl_colon = false
nl_collapse_empty_body = true
nl_assign_leave_one_liners = true
nl_class_leave_one_liners = false
nl_enum_leave_one_liners = true
nl_getset_leave_one_liners = true
nl_func_leave_one_liners = true
nl_if_leave_one_liners = true
nl_start_of_file = remove
nl_start_of_file_min = 0
nl_end_of_file = force
nl_end_of_file_min = 0
nl_assign_brace = force
nl_assign_square = ignore
nl_after_square_assign = ignore
nl_func_var_def_blk = 0
nl_fcall_brace = force
nl_enum_brace = force
nl_struct_brace = force
nl_union_brace = force
nl_if_brace = force
nl_brace_else = force
nl_elseif_brace = force
nl_else_brace = force
nl_else_if = remove
nl_brace_finally = force
nl_finally_brace = force
nl_try_brace = force
nl_getset_brace = remove
nl_for_brace = force
nl_catch_brace = force
nl_brace_catch = force
nl_while_brace = force
nl_brace_brace = force
nl_do_brace = force
nl_brace_while = force
nl_switch_brace = force
nl_multi_line_cond = false
nl_multi_line_define = true
nl_before_case = false
nl_before_throw = remove
nl_after_case = true
nl_namespace_brace = force
nl_template_class = force
nl_class_brace = force
nl_class_init_args = force
nl_func_type_name = remove
nl_func_type_name_class = remove
nl_func_scope_name = remove
nl_func_proto_type_name = remove
nl_func_paren = remove
nl_func_decl_start = remove
nl_func_decl_start_single = remove
nl_func_decl_args = remove
nl_func_decl_end = remove
nl_func_decl_end_single = remove
nl_func_decl_empty = remove
nl_fdef_brace = force
nl_after_return = true
nl_return_expr = remove
nl_after_semicolon = true
nl_after_brace_open = true
nl_after_brace_open_cmt = true
nl_after_vbrace_open = true
nl_after_vbrace_open_empty = false
nl_after_brace_close = true
nl_after_vbrace_close = true
nl_define_macro = false
nl_squeeze_ifdef = true
nl_before_if = remove
nl_after_if = remove
nl_before_for = remove
nl_after_for = remove
nl_before_while = remove
nl_after_while = remove
nl_before_switch = remove
nl_after_switch = remove
nl_before_do = remove
nl_after_do = remove
nl_ds_struct_enum_cmt = false
nl_ds_struct_enum_close_brace = false
nl_class_colon = ignore
nl_create_if_one_liner = true
nl_create_for_one_liner = true
nl_create_while_one_liner = true
pos_arith = lead
pos_assign = trail
pos_bool = lead
pos_compare = lead
pos_conditional = lead
pos_comma = trail
pos_class_comma = lead
pos_class_colon = trail
code_width = 128
ls_for_split_full = true
ls_func_split_full = true
nl_max = 2
nl_after_func_proto = 0
nl_after_func_proto_group = 1
nl_after_func_body = 0
nl_after_func_body_one_liner = 0
nl_before_block_comment = 1
nl_before_c_comment = 0
nl_before_cpp_comment = 0
nl_after_multiline_comment = false
nl_before_access_spec = 0
nl_after_access_spec = 0
nl_comment_func_def = 0
nl_after_try_catch_finally = 0
nl_around_cs_property = 0
nl_between_get_set = 0
eat_blanks_after_open_brace = true
eat_blanks_before_close_brace = true
mod_full_brace_do = remove
mod_full_brace_for = remove
mod_full_brace_function = ignore
mod_full_brace_if = remove
mod_full_brace_if_chain = false
mod_full_brace_nl = 2
mod_full_brace_while = ignore
mod_paren_on_return = remove
mod_pawn_semicolon = false
mod_full_paren_if_bool = false
mod_remove_extra_semicolon = true
mod_add_long_function_closebrace_comment = 0
mod_add_long_switch_closebrace_comment = 0
mod_add_long_ifdef_endif_comment = 0
mod_add_long_ifdef_else_comment = 0
mod_sort_import = false
mod_sort_using = false
mod_sort_include = false
mod_move_case_break = false
mod_case_brace = remove
mod_remove_empty_return = true
cmt_width = 0
cmt_reflow_mode = 0
cmt_indent_multi = true
cmt_c_group = false
cmt_c_nl_start = false
cmt_c_nl_end = false
cmt_cpp_group = false
cmt_cpp_nl_start = false
cmt_cpp_nl_end = false
cmt_cpp_to_c = false
cmt_star_cont = false
cmt_sp_before_star_cont = 0
cmt_sp_after_star_cont = 0
cmt_multi_check_last = true
cmt_insert_file_header = ""
cmt_insert_file_footer = ""
cmt_insert_func_header = ""
cmt_insert_class_header = ""
cmt_insert_before_preproc = false
pp_indent = ignore
pp_indent_at_level = false
pp_indent_count = 1
pp_space = ignore
pp_space_count = 0
pp_indent_region = 0
pp_region_indent_code = false
pp_indent_if = 0
pp_if_indent_code = false
pp_define_at_level = false
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Re: AI re-devlopment thread
Code: Select all
bool AggressiveAI::ProcessLogic (AIEvents::ElemAttrMap &logi, bool inter)
{
//go through the logic.
bool retval = false;
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
Yeah, consider these configs experimental for now. I have really bold vertical alignment settings for like variable names and assignments; that's why you see so much space there; it's aligning it with some other var above or below.
In any case, I made a shell script to reformat a number of sample files to vs format, from that to my format, and again to vs format, and then diff the first and last vs format outputs. That should result in no differences, but there are; and the vast majority appear to be related to alignment settings; so I intend to keep playing around with the configs until I reach the Mecca of null diff. Also, I skipped the whole comments reformatting section, but intend to finish it.
In any case, I made a shell script to reformat a number of sample files to vs format, from that to my format, and again to vs format, and then diff the first and last vs format outputs. That should result in no differences, but there are; and the vast majority appear to be related to alignment settings; so I intend to keep playing around with the configs until I reach the Mecca of null diff. Also, I skipped the whole comments reformatting section, but intend to finish it.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
Klauss, the string ops i was considering part of the micro-ops. Since it appears that they dont have much of an effect despite their existence being in the ai code being highly annoying. Ie. Things like string.find() and comparing upper and lower case characters (we control these files that we're reading, why aren't we explicit with a single case?).
That being said, when i look at old profiles i did and i dont see basically anything in AI land anywhere near taking up time, my motivation for optimizing it dwindles. Obviously though, i didn't deal with many common cases.
Making the AI more complicated is thus, an easier argument to make, but keep in mind, The execution of the AI code is shared with the execution of everything else the game does in a physics frame and most of that other stuff is going to take up a chunk of time. Just because the ai doesn't take up time now, doesn't mean it's not taking up all the time we can afford to give it.
A good test to do would be to insert a usleep() in the process logic function in the AI. Then play the game, noting the framerate (either absolutely or just by eye). Then increase the value of usleep until we drop to below 60fps. I'd try this both in normal non-close space flight and around wormholes/stations where lots of units are interacting, and during combat. This should give you an idea of how much time we have available to add to the physics frame via AI.
That being said, when i look at old profiles i did and i dont see basically anything in AI land anywhere near taking up time, my motivation for optimizing it dwindles. Obviously though, i didn't deal with many common cases.
Making the AI more complicated is thus, an easier argument to make, but keep in mind, The execution of the AI code is shared with the execution of everything else the game does in a physics frame and most of that other stuff is going to take up a chunk of time. Just because the ai doesn't take up time now, doesn't mean it's not taking up all the time we can afford to give it.
A good test to do would be to insert a usleep() in the process logic function in the AI. Then play the game, noting the framerate (either absolutely or just by eye). Then increase the value of usleep until we drop to below 60fps. I'd try this both in normal non-close space flight and around wormholes/stations where lots of units are interacting, and during combat. This should give you an idea of how much time we have available to add to the physics frame via AI.
Ed Sweetman endorses this message.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Re: AI re-devlopment thread
Again, I will have to profile myself.safemode wrote:Klauss, the string ops i was considering part of the micro-ops. Since it appears that they dont have much of an effect despite their existence being in the ai code being highly annoying. Ie. Things like string.find() and comparing upper and lower case characters (we control these files that we're reading, why aren't we explicit with a single case?).
That being said, when i look at old profiles i did and i dont see basically anything in AI land anywhere near taking up time, my motivation for optimizing it dwindles. Obviously though, i didn't deal with many common cases.
In any case, that code is inefficient regardless of whether it's being run often enough to make a dent. AI is really dumb right now, and does little to nothing. So it's taking too much, any amount of time is too much for doing nothing.
But as you said there are some hot spots, like near jump points and big battles, and there things slow down to a crawl. It may be the AI or the physics, I'll profile.
I know unit creation is rather slow, so when something explodes and the game has to create a few dozen crates (with the cargo that was in the destroyed unit) there is a noticeable pause - so not all bottlenecks are AI or physics.
But even if a smart AI takes slightly more than we can afford, I'd be happy to reassign simulation time from other areas to devote to AI. AI is important enough.
So... lets first make a better AI and see how it performs. I'm pretty sure, if it's coded well, it will perform just as well as the current one despite being smarter, and we won't have to worry about doing all those timing tests. But if it comes to it, lets do it after we have a new AI, so we know how much is it worth - you may think a drop in the framerate is unacceptable without seeing the new AI in action, and accept it happily afterwards.
-
- Elite
- Posts: 8014
- Joined: Fri Sep 05, 2003 4:03 am
- Location: Montreal
- Contact:
Re: AI re-devlopment thread
@Safemode: You keep thinking that cpu side things affect fps; that's old school, from back in the days before T&L (Transform & Lighting accel). Nowadays, just about everything graphics is done by the gpu; all the cpu does is send meshes and textures to the videocard, once in a blue moon. and position updates and job requests. So you can't use fps as a test of cpu-side overloading. You need a cpu-side metric.
@All: Good news: I have both config sets ready (except for the comments section; couple more hours work). Conversion back and forth is seamless, albeit two anomalies that are definitely bugs in uncrustify (non-fatal), and I managed to get around them using a bash script. Alignments are now very moderate; --only up to a 4-column threshold within a 3-line span. Enough to make things look neater without adding tons of white space.
One of the two issues has to do with blocks of // comment lines under a } line. At each pass of uncrustify, one comment line jumps above the }. My bash script runs uncrustfy in a loop, multiple times, to give slow settling phenomena a chance to sort itself out; just in case... --this particular issue will probably go away after I finish with the comment block formatting settings (I'll probably have it convert multi-line // blocks to C-type comments).
The other issue is an extra space appearing in front of trailing //comments when I format to my settings and back to vs settings; --but not generally; only at two places in all of aggressive.cpp, and I can't tell what's special about them two lines... Anyways, what the bash script does is run uncrustify 10 times with vs settings, 10 times with my settings, then 10 times again with vs settings, and by then any and all issues are settled, and I can reformat back and forth transparently.
What I'm going to suggest we do is the exact opposite of what we were thinking, though: Rather than wait until we work with a file to reformat it, I think reformatting needs to be its own revision; --i.e.: we should avoid mixing formatting and code changes.
So, let me suggest a pilot project for testing:
Let's pick an area where nobody has work in progress (probably the AI), and when you give me the ok I can go in, reformat one file at a time (making sure it make's) and then commit with comment "REFORMAT --BATCH 01".
Well, not just yet; I'm going to finish the comment block configurations first, and post some files for comparisons and feedback.
@All: Good news: I have both config sets ready (except for the comments section; couple more hours work). Conversion back and forth is seamless, albeit two anomalies that are definitely bugs in uncrustify (non-fatal), and I managed to get around them using a bash script. Alignments are now very moderate; --only up to a 4-column threshold within a 3-line span. Enough to make things look neater without adding tons of white space.
One of the two issues has to do with blocks of // comment lines under a } line. At each pass of uncrustify, one comment line jumps above the }. My bash script runs uncrustfy in a loop, multiple times, to give slow settling phenomena a chance to sort itself out; just in case... --this particular issue will probably go away after I finish with the comment block formatting settings (I'll probably have it convert multi-line // blocks to C-type comments).
The other issue is an extra space appearing in front of trailing //comments when I format to my settings and back to vs settings; --but not generally; only at two places in all of aggressive.cpp, and I can't tell what's special about them two lines... Anyways, what the bash script does is run uncrustify 10 times with vs settings, 10 times with my settings, then 10 times again with vs settings, and by then any and all issues are settled, and I can reformat back and forth transparently.
What I'm going to suggest we do is the exact opposite of what we were thinking, though: Rather than wait until we work with a file to reformat it, I think reformatting needs to be its own revision; --i.e.: we should avoid mixing formatting and code changes.
So, let me suggest a pilot project for testing:
Let's pick an area where nobody has work in progress (probably the AI), and when you give me the ok I can go in, reformat one file at a time (making sure it make's) and then commit with comment "REFORMAT --BATCH 01".
Well, not just yet; I'm going to finish the comment block configurations first, and post some files for comparisons and feedback.
Latest version of Cinemut Opaque
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
Latest version of LaGrande noodleworks (scroll down).
An evolving La Grande How-To...
The non-working, but latest, CineMut test_bike
PU (Privateer: Parallel Universe's Home). WC or Privateer Drayman for you?
WCpedia --The Wing Commander Encyclopedia-- From Angel Deveraux through Belisarius to Zachary Banfeld...
WC Nexus forum, the Moonbase Tycho of WC fans.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Re: AI re-devlopment thread
Yep, never ever mix reformatting with code changes, it makes scanning the diffs for the code changes worse than impossible.chuck_starchaser wrote:What I'm going to suggest we do is the exact opposite of what we were thinking, though: Rather than wait until we work with a file to reformat it, I think reformatting needs to be its own revision; --i.e.: we should avoid mixing formatting and code changes.
So, let me suggest a pilot project for testing:
Let's pick an area where nobody has work in progress (probably the AI), and when you give me the ok I can go in, reformat one file at a time (making sure it make's) and then commit with comment "REFORMAT --BATCH 01".
Well, not just yet; I'm going to finish the comment block configurations first, and post some files for comparisons and feedback.
Even if it's two consecutive commits, it's best to keep them separate.
When you're about to reformat a piece of code, you could lock it with "svn lock". I'm not really sure how it works though, you'll have to read the svn book.
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
The tools you are using to format the code has to be cross platform or we wont be able to accept any changes from other OS developers without becoming their proxy.
Code formatting can't be a one time deal and then we go back to everyone doing their own thing. It has to become a rule that we pass any code through the formatter to normalize any patches prior to committing.
Code formatting can't be a one time deal and then we go back to everyone doing their own thing. It has to become a rule that we pass any code through the formatter to normalize any patches prior to committing.
Ed Sweetman endorses this message.
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
chuck_starchaser wrote: So, let me suggest a pilot project for testing:
Let's pick an area where nobody has work in progress (probably the AI), and when you give me the ok I can go in, reformat one file at a time (making sure it make's) and then commit with comment "REFORMAT --BATCH 01".
Well, not just yet; I'm going to finish the comment block configurations first, and post some files for comparisons and feedback.
In svn, this is a branch. Dont beta test stuff in /trunk
Make a branch, do your testing of reformatting and stuff there then once you have a finished product, merge it back to trunk when it's ready to be played with by everyone.
Ed Sweetman endorses this message.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Re: AI re-devlopment thread
@safemode: that would work with small changes, but reformatting touches every line. So you can't allow people to touch those files until reformatting is done. Granted, if all you're doing is playing with settings and seeing how it interacts with SVN, then branch away, but if you're actually formatting code and expect to merge back into trunk, you have to prevent changes in trunk since they'll most certainly result in conflicts.
And... formatting actually can be a one-time thing. Then all committers should pretty much respect the rules, and no code would require being reformatted again by automated tools. Minor discrepancies wouldn't really matter, as long as the overall format is respected (say, if you align too much or too little, as long as it's generally aligned and readable).
That's where code review comes in handy, you can review patches by committers that would otherwise simply get committed. Ie: pre-commit review instead of post-commit review, which is harder. And you can catch more than just formatting errors, you can catch actual errors, like logic errors, or bad practice (coding a bubblesort instead of using std::sort for instance).
And... formatting actually can be a one-time thing. Then all committers should pretty much respect the rules, and no code would require being reformatted again by automated tools. Minor discrepancies wouldn't really matter, as long as the overall format is respected (say, if you align too much or too little, as long as it's generally aligned and readable).
That's where code review comes in handy, you can review patches by committers that would otherwise simply get committed. Ie: pre-commit review instead of post-commit review, which is harder. And you can catch more than just formatting errors, you can catch actual errors, like logic errors, or bad practice (coding a bubblesort instead of using std::sort for instance).
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
Conflicts happen. If all you're doing is running a formatter over something, then it's trivial to use their copy (trunk) and then re-run your formatter on it in your working dir and commit back to your branch and then merge.klauss wrote:@safemode: that would work with small changes, but reformatting touches every line. So you can't allow people to touch those files until reformatting is done. Granted, if all you're doing is playing with settings and seeing how it interacts with SVN, then branch away, but if you're actually formatting code and expect to merge back into trunk, you have to prevent changes in trunk since they'll most certainly result in conflicts.
And... formatting actually can be a one-time thing. Then all committers should pretty much respect the rules, and no code would require being reformatted again by automated tools. Minor discrepancies wouldn't really matter, as long as the overall format is respected (say, if you align too much or too little, as long as it's generally aligned and readable).
That's where code review comes in handy, you can review patches by committers that would otherwise simply get committed. Ie: pre-commit review instead of post-commit review, which is harder. And you can catch more than just formatting errors, you can catch actual errors, like logic errors, or bad practice (coding a bubblesort instead of using std::sort for instance).
Why is doing something like this in a branch (which is purposely for large scale changes) less logical than locking trunk ? Either it will be an extended period of time between the start of committing the changes to the end, in which case you should be working in a branch, or it will be a short single merge in which case what are the chances you are going to be about to merge and someone is going to make a commit? That's like winning the lottery.
Branches aren't going to bite. And they let you do the whole source tree without having to rush and allows others to at least review a bit before you taint the trunk. Also lets you catch your own muck ups. There's absolutely no reason not to be committing something like to a branch first other than laziness in learning the ins and outs of merging.
edit: Also, we dont get that much traffic in terms of people making commits. The problem is and always has been how various editors display and write tabs. Tabs are highly customizeable, and as such, what looks nice on your screen, looks like crap everywhere else. If i mix my setup of turning tabs into spaces and making it 3 spaces for each tab, with a file that has real tabs then we're going to quickly return to files that look like aggressive.cpp. If we want to go through the trouble of formatting every file, then we should make sure that the effort isn't wasted and make sure all the code committed has been through the same sanitizer.
Like i said before, i dont care about personal brace placement issues or any other aspect of how a person wants to write their code. I just care that tabs are uniform. No matter what uniform format that may be, it should be the one thing we are setting in stone if we're bothering to do this at all, since it's the thing that controls the flow of the source the most and it's the most non-uniform aspect of text formatting across editors. And it can be much harder than just a visual check to see if a file has the correct indentation, since if the editor you are viewing in happens to make tabs the same length as the standard and say we make our standard convert tabs to spaces then it becomes very annoying to verify that the patch has converted it's tabs to spaces. etc etc.
Ed Sweetman endorses this message.
-
- Elite
- Posts: 7243
- Joined: Mon Apr 18, 2005 2:40 pm
- Location: LS87, Buenos Aires, República Argentina
Re: AI re-devlopment thread
Hm... makes sense.safemode wrote:Conflicts happen. If all you're doing is running a formatter over something, then it's trivial to use their copy (trunk) and then re-run your formatter on it in your working dir and commit back to your branch and then merge.
I'm not a fan of per-author branches (I know you are, since there's a safemode branch ), but I do use branches a lot. They're great.safemode wrote:There's absolutely no reason not to be committing something like to a branch first other than laziness in learning the ins and outs of merging.
Rather I'd pester people that have their editor set up the wrong way.safemode wrote:edit: Also, we dont get that much traffic in terms of people making commits. The problem is and always has been how various editors display and write tabs. Tabs are highly customizeable, and as such, what looks nice on your screen, looks like crap everywhere else. If i mix my setup of turning tabs into spaces and making it 3 spaces for each tab, with a file that has real tabs then we're going to quickly return to files that look like aggressive.cpp. If we want to go through the trouble of formatting every file, then we should make sure that the effort isn't wasted and make sure all the code committed has been through the same sanitizer.
It's simple: use spaces. All spaces. No tabs. Then what you see is what you get.
People should learn how to use their editor of choice, creating a whole workflow assuming people can't learn how to use their editor doesn't make sense IMO.
Mistaken commits can be fixed with the sanitizer.
-
- Developer
- Posts: 2150
- Joined: Mon Apr 23, 2007 1:17 am
- Location: Pennsylvania
- Contact:
Re: AI re-devlopment thread
Well that's the thing, Not all editors have the ability to convert tabs to spaces, in fact i would venture to say that most do not.
As for the branches thing, if you're gonna do frequent commits, and those commits sometimes get large, then it pays to keep an author branch. If what you mostly do is one liners or a file here and there, then no, keeping your own branch is more work than it's worth. But we're all talking about refactoring code, reformatting code, making sweeping changes to numerous files. That kind of stuff lends itself to branch work, and helps keep the trunk sane while you dont have to work your code around the trunk's schedule and more importantly, nobody else has to work around your schedule.
in the case of reformatting where you can't commit the files all sequentially at once, I would split them up by directory so you can merge them back to trunk every so many files. There's no need to wait until the whole thing is done, while at the same time, there is no need to lock trunk and thus interfere with other people who happen (doubtful as it may be) from making unrelated commits.
As for the branches thing, if you're gonna do frequent commits, and those commits sometimes get large, then it pays to keep an author branch. If what you mostly do is one liners or a file here and there, then no, keeping your own branch is more work than it's worth. But we're all talking about refactoring code, reformatting code, making sweeping changes to numerous files. That kind of stuff lends itself to branch work, and helps keep the trunk sane while you dont have to work your code around the trunk's schedule and more importantly, nobody else has to work around your schedule.
in the case of reformatting where you can't commit the files all sequentially at once, I would split them up by directory so you can merge them back to trunk every so many files. There's no need to wait until the whole thing is done, while at the same time, there is no need to lock trunk and thus interfere with other people who happen (doubtful as it may be) from making unrelated commits.
Ed Sweetman endorses this message.