void makeNullMove(Board_t self) { pushList(self->hashHistory, self->hash); pushList(self->pkHashHistory, self->pawnKingHash); pushList(self->materialHistory, self->materialKey); self->hash ^= zobristTurn[0]; preparePushList(self->undoStack, maxMoveUndo); signed char *sp = &self->undoStack.v[self->undoStack.len]; *sp++ = sentinel; push(offsetof_halfmoveClock, self->halfmoveClock); self->halfmoveClock = 1; if (self->enPassantPawn) { push(offsetof_enPassantPawn, self->enPassantPawn); self->hash ^= hashEnPassant(self->enPassantPawn); self->enPassantPawn = 0; } self->undoStack.len = sp - self->undoStack.v; self->plyNumber++; }
/** * \fn bool manageEvent(SDL_Event event, Viewport* viewport) * \brief Manage an event. * * \param event The event to manage. * \param viewport The viewport that can be moved. * \return False if the the game ends, true if not. */ bool manageEvent(SDL_Event event, Viewport* viewport, Events *flags) { bool isInPlay = true; switch(event.type) { // Quit game case SDL_QUIT: isInPlay = false; break; // Key pressed case SDL_KEYDOWN: switch(event.key.keysym.sym) { // Quit game case SDLK_ESCAPE: isInPlay = false; break; // Move view case SDLK_UP: moveViewport(viewport, UP); break; case SDLK_DOWN: moveViewport(viewport, DOWN); break; case SDLK_LEFT: moveViewport(viewport, LEFT); break; case SDLK_RIGHT: moveViewport(viewport, RIGHT); break; default: break; } break; // Mouse left click case SDL_MOUSEBUTTONDOWN: if(event.button.button == SDL_BUTTON_LEFT) { Case* caseClicked = whichCase(event.button.x, event.button.y); TypeTo* simpleTowerType = flags->selectedTower; Case *viewportOffset = whichCase(viewport->mapsurface.x,viewport->mapsurface.y); int mapPositionX = caseClicked->xx + viewportOffset->xx; int mapPositionY = caseClicked->yy + viewportOffset->yy; Tower *tower = createTower(mapPositionX, mapPositionY, simpleTowerType); if(tower){ flags->enemy_Path_Calculation = true; pushList((void*)flags->towerList,tower); drawTower(tower); } } break; default: break; } return isInPlay; }
extern void makeMove(Board_t self, int move) { int to = to(move), from = from(move); pushList(self->hashHistory, self->hash); pushList(self->pkHashHistory, self->pawnKingHash); pushList(self->materialHistory, self->materialKey); preparePushList(self->undoStack, maxMoveUndo); signed char *sp = &self->undoStack.v[self->undoStack.len]; *sp++ = sentinel; #define push(offset, value) Statement( \ *sp++ = (value); \ *sp++ = (offset); \ ) #define makeSimpleMove(from, to) Statement( \ int _piece = self->squares[from]; \ int _victim = self->squares[to]; \ \ /* Update the undo stack */ \ push(from, _piece); \ push(to, _victim); /* last for recaptureSquare */ \ \ /* Make the simple move */ \ self->squares[to] = _piece; \ self->squares[from] = empty; \ \ /* Update the incremental hash */ \ self->hash ^= zobristPiece[_piece][from] \ ^ zobristPiece[_piece][to] \ ^ zobristPiece[_victim][to]; \ \ /* And the pawn/king/etc hash */ \ self->pawnKingHash ^= subHash[_piece][from] \ ^ subHash[_piece][to] \ ^ subHash[_victim][to]; \ \ /* Update the material key */ \ self->materialKey -= materialKeys[_victim][squareColor(to)];\ ) // Always clear en passant info if (self->enPassantPawn) { push(offsetof_enPassantPawn, self->enPassantPawn); self->hash ^= hashEnPassant(self->enPassantPawn); self->enPassantPawn = 0; } // Handle special moves first if (move & specialMoveFlag) { switch (rank(from)) { case rank8: // Black castles. Insert the corresponding rook move if (to == g8) makeSimpleMove(h8, f8); else makeSimpleMove(a8, d8); break; case rank7: if (self->squares[from] == blackPawn) { // Set en passant flag push(offsetof_enPassantPawn, 0); self->enPassantPawn = to; self->hash ^= hashEnPassant(to); } else { push(from, self->squares[from]); // White promotes int promoPiece = whiteQueen + ((move >> promotionBits) & 3); self->squares[from] = promoPiece; self->hash ^= zobristPiece[whitePawn][from] ^ zobristPiece[promoPiece][from]; self->pawnKingHash ^= zobristPiece[whitePawn][from]; self->materialKey += materialKeys[promoPiece][squareColor(to)] - materialKeys[whitePawn][0]; } break; case rank5: // White captures en passant case rank4: { // Black captures en passant int square = square(file(to), rank(from)); int victim = self->squares[square]; push(square, victim); self->squares[square] = empty; self->hash ^= zobristPiece[victim][square]; self->pawnKingHash ^= zobristPiece[victim][square]; self->materialKey -= materialKeys[victim][0]; break; } case rank2: if (self->squares[from] == whitePawn) { // Set en passant flag push(offsetof_enPassantPawn, 0); self->enPassantPawn = to; self->hash ^= hashEnPassant(to); } else { push(from, self->squares[from]); // Black promotes int promoPiece = blackQueen + ((move >> promotionBits) & 3); self->squares[from] = promoPiece; self->hash ^= zobristPiece[blackPawn][from] ^ zobristPiece[promoPiece][from]; self->pawnKingHash ^= zobristPiece[blackPawn][from]; self->materialKey += materialKeys[promoPiece][squareColor(to)] - materialKeys[blackPawn][0]; } break; case rank1: // White castles. Insert the corresponding rook move if (to == g1) makeSimpleMove(h1, f1); else makeSimpleMove(a1, d1); break; default: break; } } self->plyNumber++; self->hash ^= zobristTurn[0]; if (self->squares[to] != empty || self->squares[from] == whitePawn || self->squares[from] == blackPawn) { push(offsetof_halfmoveClock, self->halfmoveClock); // This is why it is a byte self->halfmoveClock = 0; } else self->halfmoveClock++; // Can overflow the byte, but don't worry int flagsToClear = (castleFlagsClear[from] | castleFlagsClear[to]) & self->castleFlags; if (flagsToClear) { push(offsetof_castleFlags, self->castleFlags); self->castleFlags ^= flagsToClear; uint64_t deltaHash = hashCastleFlags(flagsToClear); self->hash ^= deltaHash; self->pawnKingHash ^= deltaHash; } // The real move always as last makeSimpleMove(from, to); self->undoStack.len = sp - self->undoStack.v; // Finalize en passant (this is only safe after the update of self->undoStack.len) if (self->enPassantPawn) normalizeEnPassantStatus(self); }
int main(int argc, char* argv[]) { // Init initPath(argv[0]); SDL_Surface* screen = NULL; SDL_Event event; int *seed; srand((int)seed); int previousTime = 0, currentTime = 0; Events *flags = createEventFlags(); SDL_Init(SDL_INIT_VIDEO); SDL_SetEventFilter(eventFilter); screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_DOUBLEBUF | SDL_NOFRAME); SDL_WM_SetCaption("Tower Defense", NULL); Action *actionList = initAction(); Map* map = createMap(getPath("resources/Forest.png")); _map = map; SDL_Rect surface = {0, 0, 720, 600}; Viewport* viewport = createViewport(screen, surface, map); _viewport = viewport; // FIXME uh? what's this thing? surface.x = 800 - 80; surface.y = 0; surface.h = 80; surface.w = 600; // Creation of the enemies TypeEn *whiteCat = createTypeEn(100, 5, false, true, true, false, 1,getPath("resources/white_transparent_cat.png")); TypeEn *blackCat = createTypeEn(100, 5, false, true, true, false, 1,getPath("resources/black_transparent_cat.png")); Enemy *cat1 = createEnemy(1,1,whiteCat); Enemy *cat2 = createEnemy(1,10,whiteCat); Enemy *cat3 = createEnemy(5,5,blackCat); Enemy *cat4 = createEnemy(21,4,blackCat); TypeEn *zombie = createTypeEn(100,5,false,true,true,false,1,getPath("resources/zombie.png")); Enemy *zombie1 = createEnemy(4,4,zombie); Enemy *zombie2 = createEnemy(9,4,zombie); Enemy *zombie3 = createEnemy(9,9,zombie); Enemy *zombie4 = createEnemy(7,14,zombie); //Add enemy in the List List *catList = newList(cat4); pushList((void*)catList,cat2); pushList((void*)catList,cat3); // pushList((void*)catList,cat1); List *zombieList = newList(zombie1); /* pushList((void*)zombieList,zombie2);*/ /* pushList((void*)zombieList,zombie3);*/ /* pushList((void*)zombieList,zombie4);*/ // removeEnemyFromList(cat4,catList); //TOWER TypeBul *bullet = createTypeBul(getPath("resources/bullet.png"), 1); TypeTo *tower = createTypeTo(0,5,0,0,false,false,false,false,bullet,NULL,getPath("resources/tower.png")); upgradeTypeTo(tower,0.5,getPath("resources/towerUP.png")); flags->selectedTower = tower->nextType; Tower *tower1 = createTower(7,7,tower); List *towerList = newList(tower1); flags->towerList = towerList; // Create and Renders the right panel game menu SDL_Rect surfaceMenu = {720, 0, 800, 600}; Menu* menu = menu_create(screen, surfaceMenu); menu_loadBackground(menu, "resources/enemyFont.gif"); // For testing only, we add a few random buttons menu_addButton(menu, button_createBuildButton(tower)); menu_addButton(menu, button_createBuildButton(tower)); menu_addButton(menu, button_createBuildButton(tower)); menu_render(menu); _cell = *getCase(20,11); // Main loop while(actionList[QUIT].boolean == NULL) { // Managing the events manageEvents(viewport, flags,actionList); for(int i=1; i<ACTION_LENGTH; i++) { if(actionList[i].boolean) { int repeat = (*actionList[i].action)(viewport,flags,actionList[i].boolean); if(!repeat) { actionList[i].boolean = NULL; } } } // Redraws the map (viewport contents) before blitting stuff on it updateViewport(viewport); ///////////////////////////// DEBUG WALL ///////////////////////////// SDL_Rect position; for(int i=0; i < _map->nbCaseW; i++) { for(int j=0; j < _map->nbCaseH; j++) { Case cell = *getCase(i,j); position.x = cell.x; position.y = cell.y; if(map->matrice[i][j].hasTower == 2) { SDL_Surface *wall = IMG_Load(getPath("resources/brick.png")); blitToViewport(viewport, wall, NULL, &position); } } } position.x = _cell.x; position.y = _cell.y; blitToViewport(viewport, IMG_Load(getPath("resources/candy_cane.png")), NULL, &position); ///////////////////////////////////////////////////////////////////// // Move enemies if(flags->enemy_Path_Calculation) { pathReCalculation(catList); pathReCalculation(zombieList); flags->enemy_Path_Calculation = false; } moveEnemyList(zombieList); moveEnemyList(catList); // Blit enemies drawEnemyList(zombieList); drawEnemyList(catList); //Blit TOWER /* if(event.key.keysym.sym == SDLK_u){*/ /* upgrade(tower1);*/ /* }*/ Bullet *bullet1 = createBullet(tower1); animateBullet(bullet1); drawTowerList(towerList); /* This should be handled by event.c switch(event.key.keysym.sym){ case SDLK_a: flags->selectedTower = tower; break; case SDLK_b: flags->selectedTower = tower->nextType; break; default: break; }*/ /* */ // Ask SDL to swap framebuffers to update the displayed screen SDL_Flip(screen); // Managing frames currentTime = SDL_GetTicks(); if (currentTime - previousTime <= 20) { SDL_Delay(20 - (currentTime - previousTime)); } // DEBUG printf("Frame %i : %ims\n", framecounter++, currentTime - previousTime); previousTime = SDL_GetTicks(); } free(actionList); SDL_Quit(); return EXIT_SUCCESS; }