void MissionInsert(struct MissionEngine* _Engine, struct Mission* _Mission) { if(RBSearch(&_Engine->MissionId, _Mission) != NULL) { Log(ELOG_WARNING, "Mission cannot be loaded id %f is already in use.", _Mission->Id); return; } RBInsert(&_Engine->MissionId, _Mission); if((_Mission->Flags & MISSION_FEVENT) != 0) { LnkLstPushBack(&_Engine->EventMissions[_Mission->TriggerEvent], _Mission); } if((_Mission->Flags & MISSION_FONLYTRIGGER) == 0) { LnkLstPushBack(&_Engine->MissionsTrigger, _Mission); } }
END_TEST START_TEST(LinkedListPushBackTest) { struct LinkedList _List = {0}; int _Tbl[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; LnkLstPushBack(&_List, &_Tbl[0]); ck_assert_ptr_eq(_List.Front->Data, &_Tbl[0]); ck_assert_ptr_eq(_List.Back->Data, &_Tbl[0]); LnkLstPushBack(&_List, &_Tbl[1]); ck_assert_ptr_eq(_List.Front->Data, &_Tbl[0]); ck_assert_ptr_eq(_List.Back->Data, &_Tbl[1]); LnkLstPushBack(&_List, &_Tbl[2]); ck_assert_ptr_eq(_List.Front->Data, &_Tbl[0]); ck_assert_ptr_eq(_List.Back->Data, &_Tbl[2]); }
void PlotJoin(struct Plot* _Plot, int _Side, struct BigGuy* _Guy) { if(_Guy == NULL) return; assert(PlotCanAsk(_Plot, _Side, _Guy) == 1); assert(_Side == PLOT_ATTACKERS || _Side == PLOT_DEFENDERS); LnkLstPushBack(&_Plot->Side[_Side], _Guy); _Plot->SidePower[_Side] += BigGuyPlotPower(_Guy); }
void LnkLstMerge(struct LinkedList* _List, const struct LinkedList* _Other) { struct LnkLst_Node* _Itr = _Other->Front; while(_Itr != NULL) { LnkLstPushBack(_List, _Itr->Data); _Itr = _Itr->Next; } }
END_TEST START_TEST(LinkedListPopBackTest) { struct LinkedList _List = {0}; int _Tbl[] = {0, 1, 2}; LnkLstPushBack(&_List, &_Tbl[0]); ck_assert_ptr_eq(LnkLstPopBack(&_List), &_Tbl[0]); ck_assert_int_eq(_List.Size, 0); ck_assert_ptr_eq(_List.Front, NULL); ck_assert_ptr_eq(_List.Back, NULL); LnkLstPushBack(&_List, &_Tbl[1]); LnkLstPushBack(&_List, &_Tbl[2]); ck_assert_ptr_eq(LnkLstPopBack(&_List), &_Tbl[2]); ck_assert_ptr_eq(LnkLstPopBack(&_List), &_Tbl[1]); ck_assert_int_eq(_List.Size, 0); ck_assert_ptr_eq(_List.Front, NULL); ck_assert_ptr_eq(_List.Back, NULL); }
struct MissionFrame* CreateMissionFrame(struct BigGuy* _From, struct BigGuy* _Target, const struct Mission* _Mission) { struct MissionFrame* _MissionFrame = (struct MissionFrame*) malloc(sizeof(struct MissionFrame)); _MissionFrame->From = _From; _MissionFrame->Owner = _Target; LnkLstPushBack(&g_GameWorld.MissionFrame, _MissionFrame); _MissionFrame->StackSz = 0; _MissionFrame->Mission = _Mission; _MissionFrame->IsOptSel = 0; return _MissionFrame; }
void ITreeQuery_Aux(const struct IntervalTree* _Tree, int _NodeIdx, int _Val, struct LinkedList* _List, int _Min, int _Max) { /*const struct ITreeNode* _Node = NULL; if(_NodeIdx >= _Tree->TableSz) return; _Node = &_Tree->Table[_NodeIdx]; if(_Val >= _Min && _Val <= _Max) { for(int i = 0; i < _Node->TableSz; ++i) { if(_Node->Table[i] != NULL) { for(const struct LnkLst_Node* _Itr = _List->Front; _Itr != NULL; _Itr = _Itr->Next) { if(_Itr->Data == _Node->Table[i]) goto escape_insert; } LnkLstPushBack(_List, _Node->Table[i]); } escape_insert: continue; } } if(_Val <= _Node->Split) { ITreeQuery_Aux(_Tree, ITreeLeft(_NodeIdx), _Val, _List, _Min, _Node->Split); } if(_Val >= _Node->Split) { ITreeQuery_Aux(_Tree, ITreeRight(_NodeIdx), _Val, _List, _Node->Split, _Max); }*/ const struct ITreeNode* _Node = NULL; //int _NodeIdx = 0; if(_Tree->TableSz <= 0) return; do { _Node = &_Tree->Table[_NodeIdx]; for(int i = 0; i < _Node->TableSz; ++i) LnkLstPushBack(_List, _Node->Table[i]); if(_Val < _Node->Split) _NodeIdx = ITreeLeft(_NodeIdx); else _NodeIdx = ITreeRight(_NodeIdx); } while(_NodeIdx < _Tree->TableSz); }
struct Population* PopulationLoad(lua_State* _State, int _Index) { int i; const char* _Key = NULL; const char* _Name = NULL; struct Constraint** _Ages = NULL; struct LinkedList _List = {0, NULL, NULL}; struct Population* _Pop = NULL; struct FoodBase** _Eats = NULL; struct LnkLst_Node* _Itr = NULL; int _Young = 0; int _Old = 0; int _Death = 0; int _Nutrition = 0; int _Meat = 0; int _Milk = 0; int _IsShearable = 0; int _FMRatio = 0; int _SpaceReq = 0; const struct GoodBase* _SkinGood = NULL; const struct GoodBase* _HairGood = NULL; double _SkinPounds = 0.0; double _HairPounds = 0.0; double _MaleRatio = 0; double _ReproduceMin = 0.0f; double _ReproduceMax = 0.0f; int _Return = -2; int _Top = lua_gettop(_State); lua_getmetatable(_State, _Index); lua_pushnil(_State); while(lua_next(_State, -2) != 0) { if(lua_isstring(_State, -2)) _Key = lua_tostring(_State, -2); else continue; if (!strcmp("Nutrition", _Key)) _Return = LuaGetInteger(_State, -1, &_Nutrition); else if(!strcmp("Name", _Key)) _Return = LuaGetString(_State, -1, &_Name); else if(!strcmp("MaleRatio", _Key)) _Return = LuaGetNumber(_State, -1, &_MaleRatio); else if(!strcmp("Meat", _Key)) _Return = LuaGetInteger(_State, -1, &_Meat); else if(!strcmp("Milk", _Key)) _Return = LuaGetInteger(_State, -1, &_Milk); else if(!strcmp("MatureAge", _Key)) { _Return = LuaIntPair(_State, -1, &_Young, &_Old); _Young = YearToDays(_Young); _Old = YearToDays(_Old); } else if(!strcmp("DeathAge", _Key)) { _Return = LuaGetInteger(_State, -1, &_Death); _Death = YearToDays(_Death); } else if (!strcmp("SpaceReq", _Key)) { _Return = LuaGetInteger(_State, -1, &_SpaceReq); } else if(!strcmp("FMRatio", _Key)) { _Return = LuaGetInteger(_State, -1, &_FMRatio); } else if(!strcmp("Reproduce", _Key)) { if(lua_type(_State, -1) != LUA_TTABLE) _Return = 0; lua_rawgeti(_State, -1, 1); if((_Return = LuaGetNumber(_State, -1, &_ReproduceMin)) <= 0) goto loop_end; lua_rawgeti(_State, -2, 2); if((_Return = LuaGetNumber(_State, -1, &_ReproduceMax)) <= 0) goto loop_end; lua_pop(_State, 2); } else if(!strcmp("Eats", _Key)) { _Return = 1; lua_pushnil(_State); while(lua_next(_State, -2) != 0) { void* _Data = NULL; if(lua_isstring(_State, -1) == 0) goto EatsEnd; if((_Data = HashSearch(&g_Goods, lua_tostring(_State, -1))) == NULL) { Log(ELOG_WARNING, "Food %s could not be found.", lua_tostring(_State, -1)); goto EatsEnd; } LnkLstPushBack(&_List, _Data); EatsEnd: lua_pop(_State, 1); } } else if(!strcmp("Skin", _Key)) { if(lua_type(_State, -1) != LUA_TTABLE) { if(lua_isnil(_State, -1) == 0) Log(ELOG_INFO, "Population skin variable is not a table."); goto loop_end; } lua_pushstring(_State, "Type"); lua_rawget(_State, -2); if(lua_type(_State, -1) != LUA_TSTRING) { Log(ELOG_INFO, "Population skin.Type variable is not a table."); goto loop_end; } if((_SkinGood = HashSearch(&g_Goods, lua_tostring(_State, -1))) == NULL) { Log(ELOG_INFO, "Population skin.Type: %s is not a good.", lua_tostring(_State, -1)); lua_pop(_State, 2); continue; } lua_pop(_State, 1); lua_pushstring(_State, "Pounds"); lua_rawget(_State, -2); if(lua_type(_State, LUA_TNUMBER) == 0) { Log(ELOG_INFO, "Population skin.Pounds variable is not a number."); lua_pop(_State, 2); continue;; } _SkinPounds = lua_tonumber(_State, -1); lua_pop(_State, 1); } else if(!strcmp("Hair", _Key)) { if(lua_type(_State, -1) != LUA_TTABLE) { if(lua_isnil(_State, -1) == 0) Log(ELOG_INFO, "Population hair variable is not a table."); goto loop_end; } lua_pushstring(_State, "Type"); lua_rawget(_State, -2); if(lua_type(_State, -1) != LUA_TSTRING) { Log(ELOG_INFO, "Population hair.Type variable is not a table."); goto loop_end; } if((_HairGood = HashSearch(&g_Goods, lua_tostring(_State, -1))) == NULL) { Log(ELOG_INFO, "Population hair.Type: %s is not a good.", lua_tostring(_State, -1)); goto loop_end; } lua_pop(_State, 1); lua_pushstring(_State, "Pounds"); lua_rawget(_State, -2); if(lua_type(_State, LUA_TNUMBER) == 0) { Log(ELOG_INFO, "Population hair.Pounds variable is not a number."); lua_pop(_State, 2); continue; } _HairPounds = lua_tonumber(_State, -1); lua_pop(_State, 1); lua_pushstring(_State, "IsShearable"); lua_rawget(_State, -2); if(lua_type(_State, -1) != LUA_TBOOLEAN) { Log(ELOG_INFO, "Population hair.IsShearable variable is not a number."); lua_pop(_State, 2); continue; } _IsShearable = lua_toboolean(_State, -1); lua_pop(_State, 1); } else { Log(ELOG_WARNING, "%s is not a field of a Population.", _Key); goto fail; } if(!(_Return > 0)) { Log(ELOG_WARNING, "%s contains invalid data for a Population.", _Key); goto fail; } loop_end: lua_pop(_State, 1); } if(_Young > _Old || _Old > _Death || _Death < 0) { Log(ELOG_WARNING, "%s age limits are invalid.", _Name); goto fail; } _Ages = CreateConstrntBnds(4, 0, _Young, _Old, _Death); _Pop = CreatePopulation(_Name, _Nutrition, _Meat, _Milk, _Ages, _MaleRatio, _FMRatio, _ReproduceMin, _ReproduceMax, _SpaceReq); _Eats = calloc(_List.Size, sizeof(struct FoodBase*)); _Itr = _List.Front; i = 0; while(_Itr != NULL) { _Eats[i] =_Itr->Data; InsertionSort(_Eats, i + 1, GoodBaseCmp, sizeof(*_Eats)); _Itr = _Itr->Next; ++i; } _Pop->Skin.Skin = _SkinGood; _Pop->Skin.Pounds = _SkinPounds; _Pop->Hair.Hair = _HairGood; _Pop->Hair.Pounds = _HairPounds; _Pop->Hair.Shearable = _IsShearable; _Pop->Outputs = malloc(sizeof(struct Good*)); _Pop->Outputs[0] = NULL; _Pop->Eats = _Eats; _Pop->EatsSize = _List.Size; if(_Pop->EatsSize == 0) Log(ELOG_WARNING, "Population %s has zero food types to consume.", _Name); return _Pop; fail: lua_settop(_State, _Top); return NULL; }
void LnkLstCatNode(struct LinkedList* _List, struct LnkLst_Node* _Node) { while(_Node != NULL) { LnkLstPushBack(_List, _Node->Data); _Node = _Node->Next; } }
/* * Pathfind takes ownership of _Path and then releases ownership of _Path when it calls _Path's callback. */ int PathfindNext(struct PathData* _Path, void* _None) { const struct Tile* _StartTile = MapGetTile(g_GameWorld.MapRenderer, &_Path->Start); const struct Tile* _Goal = MapGetTile(g_GameWorld.MapRenderer, &_Path->End); struct Tile* _Neighbors[TILE_SIZE]; /* * TODO: Remove LinkedList from PathfindNext to remove malloc calls from PathfindNext. */ struct LinkedList _ClosedList = {0, NULL, NULL}; struct LnkLst_Node* _Itr = NULL; struct BinaryHeap _OpenList = {NULL, PATHFIND_OPENSIZE, 0, PathNodeScoreCmp}; struct PathNodeScore* _Current = NULL; _OpenList.Table = PathStackNext(); BinaryHeapInsert(&_OpenList, CreatePathNodeScore(_StartTile, 0, _Path->Heuristic(_StartTile, _Goal), TILE_SIZE, NULL)); while(_OpenList.Size > 0 && _OpenList.Size <= _OpenList.TblSz) { _Current = BinaryHeapTop(&_OpenList); LnkLstPushBack(&_ClosedList, BinaryHeapPop(&_OpenList)); if(_Current->Node->TilePos.x == _Goal->TilePos.x && _Current->Node->TilePos.y == _Goal->TilePos.y) break; /* * Fill the open list with _Tile's neighbors. */ TileGetAdjTiles(g_GameWorld.MapRenderer, _Current->Node, _Neighbors); for(int i = 0; i < TILE_SIZE; ++i) { if(_Neighbors[i] != NULL) { const struct LnkLst_Node* CloseItr = _ClosedList.Front; while(CloseItr != NULL) { const struct PathNodeScore* _Node = (struct PathNodeScore*)CloseItr->Data; if(_Node->Node == _Neighbors[i]) { goto loop_end; } CloseItr = CloseItr->Next; } /* * Check if neighbors are already in open list. */ for(int j = 0; j < _OpenList.Size; ++j) { struct PathNodeScore* _OpenTemp = (struct PathNodeScore*)_OpenList.Table[j]; if(_OpenTemp->Node == _Neighbors[i]) { int _gCost = _Current->g + _Path->Heuristic(_OpenTemp->Node, _Neighbors[i]); if(_gCost < _OpenTemp->g) { _OpenTemp->g = _gCost; BinaryHeapIncrease(&_OpenList, j); } goto loop_end; } } BinaryHeapInsert(&_OpenList, CreatePathNodeScore(_Neighbors[i], _Current->g + 1, _Path->Heuristic(_Neighbors[i], _Goal), i, _Current)); loop_end: continue; } } } while(_OpenList.Size > 0) { DestroyPathNodeScore((struct PathNodeScore*)BinaryHeapPop(&_OpenList)); } PathStackFree(_OpenList.Table); _Itr = _ClosedList.Front; //ListToPath(&_ClosedList, _Path->Path); const struct PathNodeScore* _Temp = _Current; struct LinkedList _TempList = {0, NULL, NULL}; while(_Temp != NULL) { LnkLstPushFront(&_TempList, (struct PathNodeScore*)_Temp); _Temp = _Temp->Parent; } ListToPath(&_TempList, _Path->Path); while(_Itr != NULL) { DestroyPathNodeScore((struct PathNodeScore*)_Itr->Data); _Itr = _Itr->Next; } LnkLstClear(&_ClosedList); _Path->Callback(_Path->Data, _Path->Path); MemPoolFree(g_PathDataPool, _Path); return 0; }