00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039
00040 #include "stratagus.h"
00041 #include "unit_manager.h"
00042 #include "unittype.h"
00043 #include "upgrade.h"
00044 #include "script.h"
00045 #include "ai.h"
00046 #include "pathfinder.h"
00047 #include "ai_local.h"
00048 #include "player.h"
00049 #include "interface.h"
00050
00058 static void AiHelperInsert(std::vector<std::vector<CUnitType *> > &table,
00059 unsigned int n, CUnitType *base)
00060 {
00061 Assert(base != NULL);
00062
00063 if (n >= table.size()) {
00064 table.resize(n + 1);
00065 }
00066
00067
00068 std::vector<CUnitType *>::const_iterator i;
00069 for (i = table[n].begin(); i != table[n].end(); ++i) {
00070 if (*i == base) {
00071 return;
00072 }
00073 }
00074 table[n].push_back(base);
00075 }
00076
00080 static std::vector<CUnitType *> getUnitTypeFromString(const std::string& list)
00081 {
00082 std::vector<CUnitType *> res;
00083
00084 if (list == "*") {
00085 return UnitTypes;
00086 }
00087 int begin = 1;
00088 int end = 0;
00089 std::string unitName;
00090 end = list.find(",", begin);
00091 while (end != -1) {
00092 unitName = list.substr(begin, end - begin);
00093 begin = end + 1;
00094 end = list.find(",", begin);
00095 if (!unitName.empty()) {
00096 Assert(unitName[0] != ',');
00097 res.push_back(UnitTypeByIdent(unitName));
00098 }
00099 }
00100 return res;
00101 }
00102
00106 static std::vector<CUnitType *> getReparableUnits()
00107 {
00108 std::vector<CUnitType *> res;
00109
00110 for (std::vector<CUnitType *>::const_iterator i = UnitTypes.begin(); i != UnitTypes.end(); ++i) {
00111 CUnitType *type = *i;
00112
00113 if (type->RepairHP > 0) {
00114 res.push_back(type);
00115 }
00116 }
00117 return res;
00118 }
00119
00127 static void InitAiHelper(AiHelper &aiHelper)
00128 {
00129 extern std::vector<ButtonAction *> UnitButtonTable;
00130
00131 std::vector<CUnitType *> reparableUnits = getReparableUnits();
00132
00133 for (int i = 0; i < (int)UnitButtonTable.size(); ++i) {
00134 const ButtonAction &button = *UnitButtonTable[i];
00135 const std::vector<CUnitType *> &unitmask = getUnitTypeFromString(button.UnitMask);
00136
00137 switch (button.Action) {
00138 case ButtonRepair :
00139 for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
00140 for (std::vector<CUnitType *>::const_iterator k = reparableUnits.begin(); k != reparableUnits.end(); ++k) {
00141 AiHelperInsert(aiHelper.Repair, (*k)->Slot, *j);
00142 }
00143 }
00144 break;
00145 case ButtonBuild:
00146 {
00147 CUnitType *buildingType = UnitTypeByIdent(button.ValueStr);
00148
00149 for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
00150 AiHelperInsert(aiHelper.Build, buildingType->Slot, (*j));
00151 }
00152 break;
00153 }
00154 case ButtonTrain :
00155 {
00156 CUnitType *trainingType = UnitTypeByIdent(button.ValueStr);
00157
00158 for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) {
00159 AiHelperInsert(aiHelper.Train, trainingType->Slot, (*j));
00160 }
00161 break;
00162 }
00163 default:
00164 break;
00165 }
00166 }
00167 }
00168
00176 static int CclDefineAiHelper(lua_State *l)
00177 {
00178 const char *value;
00179 int what;
00180 CUnitType *base;
00181 CUnitType *type = NULL;
00182 int args;
00183 int j;
00184 int subargs;
00185 int k;
00186
00187 InitAiHelper(AiHelpers);
00188
00189 args = lua_gettop(l);
00190 for (j = 0; j < args; ++j) {
00191 if (!lua_istable(l, j + 1)) {
00192 LuaError(l, "incorrect argument");
00193 }
00194 subargs = lua_objlen(l, j + 1);
00195 k = 0;
00196 lua_rawgeti(l, j + 1, k + 1);
00197 value = LuaToString(l, -1);
00198 lua_pop(l, 1);
00199 ++k;
00200
00201
00202
00203
00204 if (!strcmp(value, "build")) {
00205 what = -1;
00206 } else if (!strcmp(value, "train")) {
00207 what = -1;
00208 } else if (!strcmp(value, "unit-limit")) {
00209 what = -1;
00210 } else if (!strcmp(value, "unit-equiv")) {
00211 what = 5;
00212 } else if (!strcmp(value, "repair")) {
00213 what = -1;
00214 } else {
00215 LuaError(l, "unknown tag: %s" _C_ value);
00216 what = -1;
00217 }
00218 if (what == -1) {
00219 continue;
00220 }
00221
00222
00223
00224
00225
00226 lua_rawgeti(l, j + 1, k + 1);
00227 value = LuaToString(l, -1);
00228 lua_pop(l, 1);
00229 ++k;
00230 base = UnitTypeByIdent(value);
00231 if (!base) {
00232 LuaError(l, "unknown unittype: %s" _C_ value);
00233 }
00234
00235
00236
00237
00238 for (; k < subargs; ++k) {
00239 lua_rawgeti(l, j + 1, k + 1);
00240 value = LuaToString(l, -1);
00241 lua_pop(l, 1);
00242 type = UnitTypeByIdent(value);
00243 if (!type) {
00244 LuaError(l, "unknown unittype: %s" _C_ value);
00245 }
00246 AiHelperInsert(AiHelpers.Equiv, base->Slot, type);
00247 AiNewUnitTypeEquiv(base, type);
00248 }
00249 }
00250 return 0;
00251 }
00252
00258 static int CclDefineAi(lua_State *l)
00259 {
00260 CAiType *aitype;
00261 #ifdef DEBUG
00262 const CAiType *ait;
00263 #endif
00264
00265 LuaCheckArgs(l, 3);
00266 if (!lua_isfunction(l, 3)) {
00267 LuaError(l, "incorrect argument");
00268 }
00269
00270 aitype = new CAiType;
00271 AiTypes.insert(AiTypes.begin(), aitype);
00272
00273
00274
00275
00276 aitype->Name = LuaToString(l, 1);
00277
00278 #ifdef DEBUG
00279 for (int i = 1; i < (int)AiTypes.size(); ++i) {
00280 ait = AiTypes[i];
00281 if (aitype->Name == ait->Name) {
00282 DebugPrint("Warning two or more AI's with the same name '%s'\n" _C_ ait->Name.c_str());
00283 }
00284 }
00285 #endif
00286
00287
00288
00289
00290 aitype->Class = LuaToString(l, 2);
00291
00292
00293
00294
00295 lua_pushstring(l, "_ai_scripts_");
00296 lua_gettable(l, LUA_GLOBALSINDEX);
00297 if (lua_isnil(l, -1)) {
00298 lua_pop(l, 1);
00299 lua_pushstring(l, "_ai_scripts_");
00300 lua_newtable(l);
00301 lua_settable(l, LUA_GLOBALSINDEX);
00302 lua_pushstring(l, "_ai_scripts_");
00303 lua_gettable(l, LUA_GLOBALSINDEX);
00304 }
00305 aitype->Script = aitype->Name + aitype->Class;
00306 lua_pushstring(l, aitype->Script.c_str());
00307 lua_pushvalue(l, 3);
00308 lua_rawset(l, 4);
00309 lua_pop(l, 1);
00310
00311 return 0;
00312 }
00313
00314
00315
00316
00317
00324 static void InsertUnitTypeRequests(CUnitType *type, int count)
00325 {
00326 AiRequestType ait;
00327
00328 ait.Type = type;
00329 ait.Count = count;
00330
00331 AiPlayer->UnitTypeRequests.push_back(ait);
00332 }
00333
00339 static AiRequestType *FindInUnitTypeRequests(const CUnitType *type)
00340 {
00341 int i;
00342 int n;
00343
00344 n = AiPlayer->UnitTypeRequests.size();
00345 for (i = 0; i < n; ++i) {
00346 if (AiPlayer->UnitTypeRequests[i].Type == type) {
00347 return &AiPlayer->UnitTypeRequests[i];
00348 }
00349 }
00350 return NULL;
00351 }
00352
00353
00354
00362 static int CclAiGetSleepCycles(lua_State *l)
00363 {
00364 LuaCheckArgs(l, 0);
00365 lua_pushnumber(l, AiSleepCycles);
00366 return 1;
00367 }
00368
00369
00370
00378 static int CclAiDebug(lua_State *l)
00379 {
00380 LuaCheckArgs(l, 1);
00381 AiPlayer->ScriptDebug = LuaToBoolean(l, 1);
00382 return 0;
00383 }
00384
00395 static int CclAiDebugPlayer(lua_State *l)
00396 {
00397 const char *item;
00398 int playerid;
00399 int args;
00400 int j;
00401
00402 args = lua_gettop(l);
00403 for (j = 0; j < args; ++j) {
00404 if (lua_isstring(l, j + 1)) {
00405 item = LuaToString(l, j + 1);
00406 } else {
00407 item = NULL;
00408 }
00409
00410 if (item && !strcmp(item, "none")) {
00411 for (playerid = 0; playerid < NumPlayers; ++playerid) {
00412 if (!Players[playerid].AiEnabled || !Players[playerid].Ai) {
00413 continue;
00414 }
00415 ((PlayerAi *)Players[playerid].Ai)->ScriptDebug = 0;
00416 }
00417 } else {
00418 if (item && !strcmp(item, "self")) {
00419 if (!ThisPlayer) {
00420 continue;
00421 }
00422 playerid = ThisPlayer->Index;
00423 } else {
00424 playerid = LuaToNumber(l, j + 1);
00425 }
00426
00427 if (!Players[playerid].AiEnabled || !Players[playerid].Ai) {
00428 continue;
00429 }
00430 ((PlayerAi *)Players[playerid].Ai)->ScriptDebug = 1;
00431 }
00432 }
00433 return 0;
00434 }
00435
00443 static int CclAiNeed(lua_State *l)
00444 {
00445 LuaCheckArgs(l, 1);
00446 InsertUnitTypeRequests(CclGetUnitType(l), 1);
00447
00448 lua_pushboolean(l, 0);
00449 return 1;
00450 }
00451
00459 static int CclAiSet(lua_State *l)
00460 {
00461 AiRequestType *autt;
00462 CUnitType *type;
00463
00464 LuaCheckArgs(l, 2);
00465 lua_pushvalue(l, 1);
00466 type = CclGetUnitType(l);
00467 lua_pop(l, 1);
00468 if ((autt = FindInUnitTypeRequests(type))) {
00469 autt->Count = LuaToNumber(l, 2);
00470
00471 } else {
00472 InsertUnitTypeRequests(type, LuaToNumber(l, 2));
00473 }
00474
00475 lua_pushboolean(l, 0);
00476 return 1;
00477 }
00478
00486 static int CclAiWait(lua_State *l)
00487 {
00488 const AiRequestType *autt;
00489 const CUnitType *type;
00490 const int *unit_types_count;
00491 int j;
00492 int n;
00493
00494 LuaCheckArgs(l, 1);
00495 type = CclGetUnitType(l);
00496 unit_types_count = AiPlayer->Player->UnitTypesCount;
00497 if (!(autt = FindInUnitTypeRequests(type))) {
00498
00499
00500
00501 if (unit_types_count[type->Slot]) {
00502 lua_pushboolean(l, 0);
00503 return 1;
00504 }
00505
00506
00507
00508
00509 if (type->Slot < (int)AiHelpers.Equiv.size()) {
00510 for (j = 0; j < (int)AiHelpers.Equiv[type->Slot].size(); ++j) {
00511 if (unit_types_count[AiHelpers.Equiv[type->Slot][j]->Slot]) {
00512 lua_pushboolean(l, 0);
00513 return 1;
00514 }
00515 }
00516 }
00517 DebugPrint("Broken? waiting on %s which wasn't requested.\n" _C_ type->Ident.c_str());
00518 lua_pushboolean(l, 0);
00519 return 1;
00520 }
00521
00522
00523
00524 n = unit_types_count[type->Slot];
00525 if (type->Slot < (int)AiHelpers.Equiv.size()) {
00526 for (j = 0; j < (int)AiHelpers.Equiv[type->Slot].size(); ++j) {
00527 n += unit_types_count[AiHelpers.Equiv[type->Slot][j]->Slot];
00528 }
00529 }
00530
00531
00532 if (n >= autt->Count) {
00533 lua_pushboolean(l, 0);
00534 return 1;
00535 }
00536
00537 lua_pushboolean(l, 1);
00538 return 1;
00539 }
00540
00546 static int CclAiForce(lua_State *l)
00547 {
00548 AiUnitType *aiut;
00549 CUnitType *type;
00550 int count;
00551 int force;
00552 int args;
00553 int j;
00554 int i;
00555
00556 LuaCheckArgs(l, 2);
00557 if (!lua_istable(l, 2)) {
00558 LuaError(l, "incorrect argument");
00559 }
00560 force = LuaToNumber(l, 1);
00561 if (force < 0 || force >= AI_MAX_FORCES) {
00562 LuaError(l, "Force out of range: %d" _C_ force);
00563 }
00564
00565 args = lua_objlen(l, 2);
00566 for (j = 0; j < args; ++j) {
00567 lua_rawgeti(l, 2, j + 1);
00568 type = CclGetUnitType(l);
00569 lua_pop(l, 1);
00570 ++j;
00571 lua_rawgeti(l, 2, j + 1);
00572 count = LuaToNumber(l, -1);
00573 lua_pop(l, 1);
00574
00575 if (!type) {
00576 continue;
00577 }
00578
00579
00580 type = UnitTypes[UnitTypeEquivs[type->Slot]];
00581
00582
00583
00584
00585 for (i = 0; i < (int)AiPlayer->Force[force].UnitTypes.size(); ++i) {
00586 aiut = &AiPlayer->Force[force].UnitTypes[i];
00587 if (aiut->Type->Slot == type->Slot) {
00588 if (count) {
00589 aiut->Want = count;
00590 } else {
00591 AiPlayer->Force[force].UnitTypes.erase(
00592 AiPlayer->Force[force].UnitTypes.begin() + i);
00593 }
00594 break;
00595 }
00596 }
00597
00598
00599
00600
00601 if (i == (int)AiPlayer->Force[force].UnitTypes.size()) {
00602 AiUnitType newaiut;
00603 newaiut.Want = count;
00604 newaiut.Type = type;
00605 AiPlayer->Force[force].UnitTypes.push_back(newaiut);
00606 }
00607 }
00608
00609 AiAssignFreeUnitsToForce();
00610
00611 lua_pushboolean(l, 0);
00612 return 1;
00613 }
00614
00620 static int CclAiForceRole(lua_State *l)
00621 {
00622 int force;
00623 const char *flag;
00624
00625 LuaCheckArgs(l, 2);
00626 force = LuaToNumber(l, 1);
00627 if (force < 0 || force >= AI_MAX_FORCES) {
00628 LuaError(l, "Force %i out of range" _C_ force);
00629 }
00630 flag = LuaToString(l, 2);
00631 if (!strcmp(flag, "attack")) {
00632 AiPlayer->Force[force].Role = AiForceRoleAttack;
00633 } else if (!strcmp(flag, "defend")) {
00634 AiPlayer->Force[force].Role = AiForceRoleDefend;
00635 } else {
00636 LuaError(l, "Unknown force role '%s'" _C_ flag);
00637 }
00638
00639 lua_pushboolean(l, 0);
00640 return 1;
00641 }
00642
00648 static int CclAiCheckForce(lua_State *l)
00649 {
00650 int force;
00651
00652 LuaCheckArgs(l, 1);
00653 force = LuaToNumber(l, 1);
00654 if (force < 0 || force >= AI_MAX_FORCES) {
00655 lua_pushfstring(l, "Force out of range: %d", force);
00656 }
00657 if (AiPlayer->Force[force].Completed) {
00658 lua_pushboolean(l, 1);
00659 return 1;
00660 }
00661 lua_pushboolean(l, 0);
00662 return 1;
00663 }
00664
00670 static int CclAiWaitForce(lua_State *l)
00671 {
00672 int force;
00673
00674 LuaCheckArgs(l, 1);
00675 force = LuaToNumber(l, 1);
00676 if (force < 0 || force >= AI_MAX_FORCES) {
00677 LuaError(l, "Force out of range: %d" _C_ force);
00678 }
00679 if (AiPlayer->Force[force].Completed) {
00680 lua_pushboolean(l, 0);
00681 return 1;
00682 }
00683
00684 #if 0
00685
00686 AiCleanForces();
00687 Assert(!AiPlayer->Force[force].Completed);
00688 #endif
00689
00690 lua_pushboolean(l, 1);
00691 return 1;
00692 }
00693
00699 static int CclAiAttackWithForce(lua_State *l)
00700 {
00701 int force;
00702
00703 LuaCheckArgs(l, 1);
00704 force = LuaToNumber(l, 1);
00705 if (force < 0 || force >= AI_MAX_FORCES) {
00706 LuaError(l, "Force out of range: %d" _C_ force);
00707 }
00708
00709 AiAttackWithForce(force);
00710
00711 lua_pushboolean(l, 0);
00712 return 1;
00713 }
00714
00720 static int CclAiSleep(lua_State *l)
00721 {
00722 int i;
00723
00724 LuaCheckArgs(l, 1);
00725 i = LuaToNumber(l, 1);
00726 if (AiPlayer->SleepCycles || i == 0) {
00727 if (AiPlayer->SleepCycles < GameCycle) {
00728 AiPlayer->SleepCycles = 0;
00729 lua_pushboolean(l, 0);
00730 return 1;
00731 }
00732 } else {
00733 AiPlayer->SleepCycles = GameCycle + i;
00734 }
00735
00736 lua_pushboolean(l, 1);
00737 return 1;
00738 }
00739
00747 static int CclAiPlayer(lua_State *l)
00748 {
00749 LuaCheckArgs(l, 0);
00750 lua_pushnumber(l, AiPlayer->Player->Index);
00751 return 1;
00752 }
00753
00759 static int CclAiDump(lua_State *l)
00760 {
00761 int i;
00762 int n;
00763 const AiUnitType *aut;
00764 const AiBuildQueue *queue;
00765
00766 LuaCheckArgs(l, 0);
00767
00768
00769
00770 printf("------\n");
00771 printf("%d:", AiPlayer->Player->Index);
00772 #if 0
00773 gh_display(gh_car(AiPlayer->Script));
00774 #endif
00775
00776
00777
00778 n = (int)AiPlayer->UnitTypeRequests.size();
00779 printf("UnitTypeRequests(%d):\n", n);
00780 for (i = 0; i < n; ++i) {
00781 printf("%s ", AiPlayer->UnitTypeRequests[i].Type->Ident.c_str());
00782 }
00783 printf("\n");
00784
00785
00786
00787
00788 printf("Building queue:\n");
00789 for (i = 0; i < (int)AiPlayer->UnitTypeBuilt.size(); ++i) {
00790 queue = &AiPlayer->UnitTypeBuilt[i];
00791 printf("%s(%d/%d) ", queue->Type->Ident.c_str(), queue->Made, queue->Want);
00792 }
00793 printf("\n");
00794
00795
00796
00797
00798 for (i = 0; i < AI_MAX_FORCES; ++i) {
00799 printf("Force(%d%s%s):\n", i,
00800 AiPlayer->Force[i].Completed ? ",complete" : ",recruit",
00801 AiPlayer->Force[i].Attacking ? ",attack" : "");
00802 for (int j = 0; j < (int)AiPlayer->Force[i].UnitTypes.size(); ++j) {
00803 aut = &AiPlayer->Force[i].UnitTypes[j];
00804 printf("%s(%d) ", aut->Type->Ident.c_str(), aut->Want);
00805 }
00806 printf("\n");
00807 }
00808
00809 lua_pushboolean(l, 0);
00810 return 1;
00811 }
00812
00820 static int DefaultResourceNumber(const char *name)
00821 {
00822 int i;
00823
00824 for (i = 0; i < MaxCosts; ++i) {
00825 if (DefaultResourceNames[i] == name) {
00826 return i;
00827 }
00828 }
00829
00830 Assert(0);
00831 return -1;
00832 }
00833
00839 static int CclDefineAiPlayer(lua_State *l)
00840 {
00841 const char *value;
00842 int i;
00843 PlayerAi *ai;
00844 int args;
00845 int j;
00846 int subargs;
00847 int k;
00848
00849 args = lua_gettop(l);
00850 j = 0;
00851
00852 i = LuaToNumber(l, j + 1);
00853 ++j;
00854
00855 Assert(i >= 0 && i <= PlayerMax);
00856 DebugPrint("%p %d\n" _C_ Players[i].Ai _C_ Players[i].AiEnabled );
00857
00858
00859
00860 ai = Players[i].Ai = new PlayerAi;
00861 ai->Player = &Players[i];
00862
00863
00864
00865
00866 for (; j < args; ++j) {
00867 value = LuaToString(l, j + 1);
00868 ++j;
00869
00870 if (!strcmp(value, "ai-type")) {
00871 CAiType *ait = NULL;
00872
00873 value = LuaToString(l, j + 1);
00874 for (k = 0; k < (int)AiTypes.size(); ++k) {
00875 ait = AiTypes[k];
00876 if (ait->Name == value) {
00877 break;
00878 }
00879 }
00880 if (k == (int)AiTypes.size()) {
00881 lua_pushfstring(l, "ai-type not found: %s", value);
00882 }
00883 ai->AiType = ait;
00884 ai->Script = ait->Script;
00885 } else if (!strcmp(value, "script")) {
00886 ai->Script = LuaToString(l, j + 1);
00887 } else if (!strcmp(value, "script-debug")) {
00888 ai->ScriptDebug = LuaToBoolean(l, j + 1);
00889 } else if (!strcmp(value, "sleep-cycles")) {
00890 ai->SleepCycles = LuaToNumber(l, j + 1);
00891 } else if (!strcmp(value, "force")) {
00892 if (!lua_istable(l, j + 1)) {
00893 LuaError(l, "incorrect argument");
00894 }
00895 subargs = lua_objlen(l, j + 1);
00896 k = 0;
00897 lua_rawgeti(l, j + 1, k + 1);
00898 i = LuaToNumber(l, -1);
00899 lua_pop(l, 1);
00900 ++k;
00901 for (; k < subargs; ++k) {
00902 lua_rawgeti(l, j + 1, k + 1);
00903 value = LuaToString(l, -1);
00904 lua_pop(l, 1);
00905 ++k;
00906 if (!strcmp(value, "complete")) {
00907 ai->Force[i].Completed = true;
00908 --k;
00909 } else if (!strcmp(value, "recruit")) {
00910 ai->Force[i].Completed = false;
00911 --k;
00912 } else if (!strcmp(value, "attack")) {
00913 ai->Force[i].Attacking = true;
00914 --k;
00915 } else if (!strcmp(value, "defend")) {
00916 ai->Force[i].Defending = true;
00917 --k;
00918 } else if (!strcmp(value, "role")) {
00919 lua_rawgeti(l, j + 1, k + 1);
00920 value = LuaToString(l, -1);
00921 lua_pop(l, 1);
00922 if (!strcmp(value, "attack")) {
00923 ai->Force[i].Role = AiForceRoleAttack;
00924 } else if (!strcmp(value, "defend")) {
00925 ai->Force[i].Role = AiForceRoleDefend;
00926 } else {
00927 LuaError(l, "Unsupported force tag: %s" _C_ value);
00928 }
00929 } else if (!strcmp(value, "types")) {
00930 int subsubargs;
00931 int subk;
00932
00933 lua_rawgeti(l, j + 1, k + 1);
00934 if (!lua_istable(l, -1)) {
00935 LuaError(l, "incorrect argument");
00936 }
00937 subsubargs = lua_objlen(l, -1);
00938 for (subk = 0; subk < subsubargs; ++subk) {
00939 int num;
00940 const char *ident;
00941 AiUnitType queue;
00942
00943 lua_rawgeti(l, -1, subk + 1);
00944 num = LuaToNumber(l, -1);
00945 lua_pop(l, 1);
00946 ++subk;
00947 lua_rawgeti(l, -1, subk + 1);
00948 ident = LuaToString(l, -1);
00949 lua_pop(l, 1);
00950 queue.Want = num;
00951 queue.Type = UnitTypeByIdent(ident);
00952 ai->Force[i].UnitTypes.push_back(queue);
00953 }
00954 lua_pop(l, 1);
00955 } else if (!strcmp(value, "units")) {
00956 int subsubargs;
00957 int subk;
00958
00959 lua_rawgeti(l, j + 1, k + 1);
00960 if (!lua_istable(l, -1)) {
00961 LuaError(l, "incorrect argument");
00962 }
00963 subsubargs = lua_objlen(l, -1);
00964 for (subk = 0; subk < subsubargs; ++subk) {
00965 int num;
00966 const char *ident;
00967
00968 lua_rawgeti(l, -1, subk + 1);
00969 num = LuaToNumber(l, -1);
00970 lua_pop(l, 1);
00971 ++subk;
00972 lua_rawgeti(l, -1, subk + 1);
00973 ident = LuaToString(l, -1);
00974 lua_pop(l, 1);
00975 ai->Force[i].Units.push_back(UnitSlots[num]);
00976 }
00977 lua_pop(l, 1);
00978 } else if (!strcmp(value, "state")) {
00979 lua_rawgeti(l, j + 1, k + 1);
00980 ai->Force[i].State = LuaToNumber(l, -1);
00981 lua_pop(l, 1);
00982 } else if (!strcmp(value, "goalx")) {
00983 lua_rawgeti(l, j + 1, k + 1);
00984 ai->Force[i].GoalX = LuaToNumber(l, -1);
00985 lua_pop(l, 1);
00986 } else if (!strcmp(value, "goaly")) {
00987 lua_rawgeti(l, j + 1, k + 1);
00988 ai->Force[i].GoalY = LuaToNumber(l, -1);
00989 lua_pop(l, 1);
00990 } else if (!strcmp(value, "must-transport")) {
00991 lua_rawgeti(l, j + 1, k + 1);
00992 ai->Force[i].MustTransport = LuaToNumber(l, -1) ? true : false;
00993 lua_pop(l, 1);
00994 } else {
00995 LuaError(l, "Unsupported tag: %s" _C_ value);
00996 }
00997 }
00998 } else if (!strcmp(value, "needed")) {
00999 if (!lua_istable(l, j + 1)) {
01000 LuaError(l, "incorrect argument");
01001 }
01002 subargs = lua_objlen(l, j + 1);
01003 for (k = 0; k < subargs; ++k) {
01004 const char *type;
01005 int num;
01006
01007 lua_rawgeti(l, j + 1, k + 1);
01008 type = LuaToString(l, -1);
01009 lua_pop(l, 1);
01010 ++k;
01011 lua_rawgeti(l, j + 1, k + 1);
01012 num = LuaToNumber(l, -1);
01013 lua_pop(l, 1);
01014 ai->Needed[DefaultResourceNumber(type)] = num;
01015 }
01016 } else if (!strcmp(value, "need-mask")) {
01017 if (!lua_istable(l, j + 1)) {
01018 LuaError(l, "incorrect argument");
01019 }
01020 subargs = lua_objlen(l, j + 1);
01021 for (k = 0; k < subargs; ++k) {
01022 const char *type;
01023
01024 lua_rawgeti(l, j + 1, k + 1);
01025 type = LuaToString(l, -1);
01026 lua_pop(l, 1);
01027 ai->NeededMask |= (1 << DefaultResourceNumber(type));
01028 }
01029 } else if (!strcmp(value, "exploration")) {
01030 if (!lua_istable(l, j + 1)) {
01031 LuaError(l, "incorrect argument");
01032 }
01033 subargs = lua_objlen(l, j + 1);
01034 for (k = 0; k < subargs; ++k) {
01035 int x;
01036 int y;
01037 int mask;
01038 AiExplorationRequest queue;
01039
01040 lua_rawgeti(l, j + 1, k + 1);
01041 if (!lua_istable(l, -1) || lua_objlen(l, -1) != 3) {
01042 LuaError(l, "incorrect argument");
01043 }
01044 lua_rawgeti(l, -1, 1);
01045 x = LuaToNumber(l, -1);
01046 lua_pop(l, 1);
01047 lua_rawgeti(l, -1, 2);
01048 y = LuaToNumber(l, -1);
01049 lua_pop(l, 1);
01050 lua_rawgeti(l, -1, 3);
01051 mask = LuaToNumber(l, -1);
01052 lua_pop(l, 1);
01053 lua_pop(l, 1);
01054 queue.X = x;
01055 queue.Y = y;
01056 queue.Mask = mask;
01057 ai->FirstExplorationRequest.push_back(queue);
01058 }
01059 } else if (!strcmp(value, "last-exploration-cycle")) {
01060 ai->LastExplorationGameCycle = LuaToNumber(l, j + 1);
01061 } else if (!strcmp(value, "transport")) {
01062 if (!lua_istable(l, j + 1)) {
01063 LuaError(l, "incorrect argument");
01064 }
01065 subargs = lua_objlen(l, j + 1);
01066 for (k = 0; k < subargs; ++k) {
01067 int unit;
01068 AiTransportRequest queue;
01069
01070 lua_rawgeti(l, j + 1, k + 1);
01071 if (!lua_istable(l, -1) || lua_objlen(l, -1) != 2) {
01072 LuaError(l, "incorrect argument");
01073 }
01074 lua_rawgeti(l, -1, 1);
01075 unit = LuaToNumber(l, -1);
01076 lua_pop(l, 1);
01077 queue.Unit = UnitSlots[unit];
01078 lua_rawgeti(l, -1, 2);
01079 CclParseOrder(l, &queue.Order);
01080 lua_pop(l, 1);
01081 lua_pop(l, 1);
01082 ai->TransportRequests.push_back(queue);
01083 }
01084 } else if (!strcmp(value, "last-can-not-move-cycle")) {
01085 ai->LastCanNotMoveGameCycle = LuaToNumber(l, j + 1);
01086 } else if (!strcmp(value, "unit-type")) {
01087 if (!lua_istable(l, j + 1)) {
01088 LuaError(l, "incorrect argument");
01089 }
01090 subargs = lua_objlen(l, j + 1);
01091 i = 0;
01092 if (subargs) {
01093 ai->UnitTypeRequests.resize(subargs / 2);
01094 }
01095 for (k = 0; k < subargs; ++k) {
01096 const char *ident;
01097 int count;
01098
01099 lua_rawgeti(l, j + 1, k + 1);
01100 ident = LuaToString(l, -1);
01101 lua_pop(l, 1);
01102 ++k;
01103 lua_rawgeti(l, j + 1, k + 1);
01104 count = LuaToNumber(l, -1);
01105 lua_pop(l, 1);
01106 ai->UnitTypeRequests[i].Type = UnitTypeByIdent(ident);
01107 ai->UnitTypeRequests[i].Count = count;
01108 ++i;
01109 }
01110 } else if (!strcmp(value, "building")) {
01111 if (!lua_istable(l, j + 1)) {
01112 LuaError(l, "incorrect argument");
01113 }
01114 subargs = lua_objlen(l, j + 1);
01115 for (k = 0; k < subargs; ++k) {
01116 const char *ident;
01117 int made;
01118 int want;
01119 AiBuildQueue queue;
01120
01121 lua_rawgeti(l, j + 1, k + 1);
01122 ident = LuaToString(l, -1);
01123 lua_pop(l, 1);
01124 ++k;
01125 lua_rawgeti(l, j + 1, k + 1);
01126 made = LuaToNumber(l, -1);
01127 lua_pop(l, 1);
01128 ++k;
01129 lua_rawgeti(l, j + 1, k + 1);
01130 want = LuaToNumber(l, -1);
01131 lua_pop(l, 1);
01132 queue.Type = UnitTypeByIdent(ident);
01133 queue.Want = want;
01134 queue.Made = made;
01135 ai->UnitTypeBuilt.push_back(queue);
01136 }
01137 } else if (!strcmp(value, "repair-building")) {
01138 ai->LastRepairBuilding = LuaToNumber(l, j + 1);
01139 } else if (!strcmp(value, "repair-workers")) {
01140 if (!lua_istable(l, j + 1)) {
01141 LuaError(l, "incorrect argument");
01142 }
01143 subargs = lua_objlen(l, j + 1);
01144 for (k = 0; k < subargs; ++k) {
01145 int num;
01146 int workers;
01147
01148 lua_rawgeti(l, j + 1, k + 1);
01149 num = LuaToNumber(l, -1);
01150 lua_pop(l, 1);
01151 ++k;
01152 lua_rawgeti(l, j + 1, k + 1);
01153 workers = LuaToNumber(l, -1);
01154 lua_pop(l, 1);
01155 ai->TriedRepairWorkers[num] = workers;
01156 ++i;
01157 }
01158 } else {
01159 LuaError(l, "Unsupported tag: %s" _C_ value);
01160 }
01161 }
01162
01163 return 0;
01164 }
01165
01169 void AiCclRegister(void)
01170 {
01171
01172
01173
01174 lua_register(Lua, "DefineAiHelper", CclDefineAiHelper);
01175 lua_register(Lua, "DefineAi", CclDefineAi);
01176
01177 lua_register(Lua, "AiGetSleepCycles", CclAiGetSleepCycles);
01178
01179 lua_register(Lua, "AiDebug", CclAiDebug);
01180 lua_register(Lua, "AiDebugPlayer", CclAiDebugPlayer);
01181 lua_register(Lua, "AiNeed", CclAiNeed);
01182 lua_register(Lua, "AiSet", CclAiSet);
01183 lua_register(Lua, "AiWait", CclAiWait);
01184
01185 lua_register(Lua, "AiForce", CclAiForce);
01186
01187 lua_register(Lua, "AiForceRole", CclAiForceRole);
01188 lua_register(Lua, "AiCheckForce", CclAiCheckForce);
01189 lua_register(Lua, "AiWaitForce", CclAiWaitForce);
01190
01191 lua_register(Lua, "AiAttackWithForce", CclAiAttackWithForce);
01192 lua_register(Lua, "AiSleep", CclAiSleep);
01193
01194 lua_register(Lua, "AiPlayer", CclAiPlayer);
01195
01196 lua_register(Lua, "AiDump", CclAiDump);
01197
01198 lua_register(Lua, "DefineAiPlayer", CclDefineAiPlayer);
01199 }
01200
01201