### Install APK on Emulator Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/06 - Ciclo_06_Build_Android_Real/02 - Plano_de_Implementacao.md After a successful debug build, use this ADB command to install the generated APK onto an connected Android emulator. Verify the app launches and basic interactions function. ```bash adb install app/build/outputs/apk/debug/app-debug.apk ``` -------------------------------- ### Complete Game Cycle Simulation in Kotlin Source: https://context7.com/walbarellos/vitaacre/llms.txt Simulates a full game of Vitahacre, including setup, move execution, and checking win/loss conditions. Requires importing domain, data, and presentation components. ```kotlin import com.vitahacre.domain.model.* import com.vitahacre.data.generator.GeneratorFactory import com.vitahacre.presentation.controller.DefaultGameController // 1. Configurar e iniciar partida val config = BoardConfiguration( columns = 4, rows = 2, layers = 1, totalTiles = 8, seed = 12345L ) val (initialState, _) = GeneratorFactory.createInitialGameState(config) val controller = DefaultGameController(initialState, cellSize = 100f) println("=== PARTIDA INICIADA ===") println("Peças: ${controller.state.activeTiles.size}") println("Status: ${controller.state.status}") // 2. Loop de jogo simulado fun findEligiblePair(state: GameState): Pair? { val eligible = state.activeTiles.filter { com.vitahacre.domain.rules.DomainRules.isEligible(it, state.tiles) } for (i in eligible.indices) { for (j in i + 1 until eligible.size) { if (eligible[i].pairKey == eligible[j].pairKey) { return Pair(eligible[i], eligible[j]) } } } return null } var moveCount = 0 while (controller.state.status == GameStatus.PRONTO || controller.state.status == GameStatus.SELECIONANDO_1) { val pair = findEligiblePair(controller.state) if (pair == null) { println("Sem pares disponíveis!") break } // Primeiro toque val (tile1, tile2) = pair val touch1 = InputEvent( x = tile1.x * 100f + 50f, y = tile1.y * 100f + 50f, type = InputEventType.TOUCH ) controller.onInput(touch1) // Segundo toque val touch2 = InputEvent( x = tile2.x * 100f + 50f, y = tile2.y * 100f + 50f, type = InputEventType.TOUCH ) controller.onInput(touch2) moveCount++ println("Jogada $moveCount: removeu par (${tile1.id}, ${tile2.id}) - pairKey=${tile1.pairKey}") println(" Peças restantes: ${controller.state.activeTiles.size}") } // 3. Verificar resultado final println("\n=== RESULTADO FINAL ===") when (controller.state.status) { GameStatus.VITORIA -> { println("VITÓRIA em $moveCount jogadas!") } GameStatus.SEM_JOGADAS -> { println("BLOQUEADO - ${controller.state.activeTiles.size} peças restantes") } else -> { println("Status: ${controller.state.status}") } } // 4. Reiniciar para nova partida controller.onInput(InputEvent(type = InputEventType.RESTART)) println("\n=== NOVA PARTIDA ===") println("Status: ${controller.state.status}") println("Peças: ${controller.state.activeTiles.size}") ``` -------------------------------- ### Manage GameState and Board Configuration Source: https://context7.com/walbarellos/vitaacre/llms.txt Shows how to initialize the game board configuration and manage the immutable GameState object. ```kotlin import com.vitahacre.domain.model.* // Criar configuração do tabuleiro val config = BoardConfiguration( columns = 8, rows = 4, layers = 2, totalTiles = 32, seed = 12345L // Opcional: para geração determinística ) // Criar estado inicial vazio val initialState = GameState.initial(config) println("Status: ${initialState.status}") // Status: INICIALIZANDO println("Peças: ${initialState.tiles.size}") // Peças: 0 // Estado com peças carregadas val tiles = listOf( Tile(id = 0, pairKey = 0, x = 0, y = 0, layer = 0), Tile(id = 1, pairKey = 0, x = 2, y = 0, layer = 0), Tile(id = 2, pairKey = 1, x = 4, y = 0, layer = 0), Tile(id = 3, pairKey = 1, x = 6, y = 0, layer = 0) ) val gameState = GameState( tiles = tiles, selection = SelectionState.EMPTY, status = GameStatus.PRONTO, boardConfiguration = config ) // Acessores derivados println("Peças ativas: ${gameState.activeTiles.size}") // Peças ativas: 4 println("Tabuleiro vazio: ${gameState.isBoardEmpty}") // Tabuleiro vazio: false // Buscar peça por ID val tile = gameState.tileById(2) println("Peça ID 2: pairKey=${tile?.pairKey}") // Peça ID 2: pairKey=1 // Atualizar estado (imutável) val newState = gameState.copy( selection = SelectionState(firstSelectedTileId = 0), status = GameStatus.SELECIONANDO_1 ) ``` -------------------------------- ### Instantiate and Manipulate Tile Models Source: https://context7.com/walbarellos/vitaacre/llms.txt Demonstrates creating a Tile instance and using the copy method to handle state immutability. ```kotlin import com.vitahacre.domain.model.Tile // Criar uma peça na posição (4, 2) da camada 0 com pairKey = 5 val tile = Tile( id = 1, pairKey = 5, x = 4, y = 2, layer = 0, isRemoved = false ) // Verificar propriedades da peça println("ID: ${tile.id}") // ID: 1 println("PairKey: ${tile.pairKey}") // PairKey: 5 println("Posição: (${tile.x}, ${tile.y}, layer=${tile.layer})") // Posição: (4, 2, layer=0) println("Removida: ${tile.isRemoved}") // Removida: false // Marcar peça como removida (imutável - cria nova instância) val removedTile = tile.copy(isRemoved = true) println("Original removida: ${tile.isRemoved}") // false println("Nova instância removida: ${removedTile.isRemoved}") // true ``` -------------------------------- ### Manage SelectionState Source: https://context7.com/walbarellos/vitaacre/llms.txt Demonstrates how to initialize and inspect the selection state of tiles, including empty, single-selection, and pair-selection scenarios. ```kotlin import com.vitahacre.domain.model.SelectionState // Nenhuma seleção val empty = SelectionState.EMPTY println("Primeira: ${empty.firstSelectedTileId}") // null println("Segunda: ${empty.secondSelectedTileId}") // null // Primeira peça selecionada val oneSelected = SelectionState(firstSelectedTileId = 5) println("Primeira seleção: ${oneSelected.firstSelectedTileId}") // 5 // Par formado aguardando avaliação val pairSelected = SelectionState( firstSelectedTileId = 5, secondSelectedTileId = 12 ) println("Par: (${pairSelected.firstSelectedTileId}, ${pairSelected.secondSelectedTileId})") // Par: (5, 12) ``` -------------------------------- ### VitahAcre Game State Machine Diagram Source: https://github.com/walbarellos/vitaacre/blob/master/docs/2 - Diagrama/05 - Diagrama_de_Maquina_de_Estados_da_Partida.md This diagram visualizes the official state machine for the VitahAcre game session. It formalizes possible session states, shows valid transitions, prevents illegal states, and guides controller implementation and flow testing. ```mermaid [*] --> INICIALIZANDO INICIALIZANDO --> PRONTO: tabuleiro valido gerado PRONTO --> SELECIONANDO_1: primeira peca elegivel selecionada PRONTO --> PRONTO: toque invalido / area vazia / peca inelegivel SELECIONANDO_1 --> SELECIONANDO_2: segunda peca elegivel selecionada SELECIONANDO_1 --> SELECIONANDO_1: toque invalido / area vazia / peca inelegivel SELECIONANDO_1 --> PRONTO: selecao resolvida / cancelada SELECIONANDO_2 --> PROCESSANDO_MATCH: iniciar avaliacao do par PROCESSANDO_MATCH --> PRONTO: match invalido e partida continua PROCESSANDO_MATCH --> PRONTO: match valido sem estado terminal PROCESSANDO_MATCH --> VITORIA: todas as pecas removidas PROCESSANDO_MATCH --> SEM_JOGADAS: sem pares validos restantes VITORIA --> PRONTO: reinicio da partida SEM_JOGADAS --> PRONTO: reinicio da partida ``` -------------------------------- ### Base Generator Algorithm Reference Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/02 - Ciclo_02_Gerador_Procedural/00 - Visao_do_Ciclo.md Outlines the reference algorithm for the base board generator, detailing steps from calculating tile count to returning the final generation result. ```pseudocode 1. Calcular N = boardConfiguration.totalTiles 2. Criar lista de pairKeys = [0, 1, 2, ..., N/2 - 1] (cada um 2 vezes) 3. Embaralhar lista com boardConfiguration.seed (se presente) 4. Gerar posições válidas no grid (x múltiplo de TILE_UNIT, y múltiplo de TILE_UNIT) respeitando layers, columns, rows 5. Associar cada pairKey a uma posição (sem colisão de posição absoluta) 6. Construir lista de Tile com ids sequenciais (0, 1, 2, ...) 7. Verificar isPlayable (unicidade de posição) 8. Verificar hasAtLeastOneInitialMove usando DomainRules.hasAvailableMoves 9. Se (8) = false → tentar reorganizar ou nova seed 10. Retornar BoardGenerationResult ``` -------------------------------- ### Create Initial Game State with GeneratorFactory Source: https://context7.com/walbarellos/vitaacre/llms.txt Configure board parameters and generate the initial game state. Use the seed for reproducible results. The generation result provides audit information. ```kotlin import com.vitahacre.domain.model.BoardConfiguration import com.vitahacre.domain.model.GameStatus import com.vitahacre.data.generator.GeneratorFactory // Configurar e criar estado inicial val config = BoardConfiguration( columns = 8, rows = 4, layers = 2, totalTiles = 32, seed = 42L ) // Gerar estado inicial da partida val (gameState, generationResult) = GeneratorFactory.createInitialGameState(config) // Verificar estado criado println("Status: ${gameState.status}") // PRONTO println("Peças carregadas: ${gameState.tiles.size}") // 32 println("Seleção: ${gameState.selection}") // SelectionState(null, null) // Resultado da geração disponível para auditoria println("Geração bem-sucedida: ${generationResult.isPlayable}") println("Jogável desde o início: ${generationResult.hasAtLeastOneInitialMove}") // Criar novo jogo com configuração diferente val smallConfig = BoardConfiguration( columns = 4, rows = 2, layers = 1, totalTiles = 8 ) val (smallGame, _) = GeneratorFactory.createInitialGameState(smallConfig) println("Jogo pequeno - peças: ${smallGame.tiles.size}") // 8 ``` -------------------------------- ### Interface SelectionHighlightRenderer Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/04 - Ciclo_04_Renderizacao_Procedural/01 - Contrato_Tecnico_do_Ciclo.md Define o contrato para renderizar o destaque visual da peça selecionada. ```kotlin interface SelectionHighlightRenderer { fun render(selectedTileId: String?, tiles: List, canvas: Canvas) } ``` -------------------------------- ### Execute Debug Build Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/06 - Ciclo_06_Build_Android_Real/02 - Plano_de_Implementacao.md Run this command in the project's root directory to generate a debug APK. Ensure Gradle is executable. ```bash ./gradlew assembleDebug ``` -------------------------------- ### Handle GameStatus Transitions Source: https://context7.com/walbarellos/vitaacre/llms.txt Illustrates the use of a when expression to handle different states within the game's state machine. ```kotlin import com.vitahacre.domain.model.GameStatus // Estados disponíveis e suas transições val status = GameStatus.PRONTO when (status) { GameStatus.INICIALIZANDO -> { // Sistema preparando a partida - sem interação permitida println("Aguardando geração do tabuleiro...") } GameStatus.PRONTO -> { // Aguardando primeira seleção do usuário println("Selecione a primeira peça") } GameStatus.SELECIONANDO_1 -> { // Uma peça selecionada - aguardando segunda println("Selecione a segunda peça para formar o par") } GameStatus.SELECIONANDO_2 -> { // Duas peças indicadas - aguardando avaliação println("Avaliando par...") } GameStatus.PROCESSANDO_MATCH -> { // Sistema avaliando compatibilidade das peças println("Processando match...") } GameStatus.VITORIA -> { // Todas as peças removidas - estado terminal positivo println("Parabéns! Você venceu!") } GameStatus.SEM_JOGADAS -> { // Peças restantes mas sem pares válidos - estado terminal negativo println("Sem jogadas disponíveis. Reinicie a partida.") } } ``` -------------------------------- ### Use DomainRules Facade Source: https://context7.com/walbarellos/vitaacre/llms.txt Provides a unified entry point for checking tile eligibility and blocking status using the DomainRules facade. ```kotlin import com.vitahacre.domain.model.Tile import com.vitahacre.domain.rules.DomainRules // Criar cenário de teste com tabuleiro simples val tiles = listOf( Tile(id = 0, pairKey = 0, x = 0, y = 0, layer = 0), // Livre à esquerda Tile(id = 1, pairKey = 0, x = 2, y = 0, layer = 0), // Bloqueada dos dois lados Tile(id = 2, pairKey = 1, x = 4, y = 0, layer = 0), // Livre à direita Tile(id = 3, pairKey = 1, x = 0, y = 0, layer = 1) // Camada superior - bloqueia tile 0 ) // Verificar bloqueio superior (RN-05) val tile0 = tiles[0] val isBlockedTop = DomainRules.hasBlockedTop(tile0, tiles) println("Tile 0 bloqueada por cima: $isBlockedTop") // true (tile 3 está acima) // Verificar lado livre (RN-06) val tile1 = tiles[1] val hasFreeSide = DomainRules.hasFreeSide(tile1, tiles) println("Tile 1 tem lado livre: $hasFreeSide") // false (bloqueada dos dois lados) // Verificar elegibilidade completa (RN-07/RN-08) val isEligible = DomainRules.isEligible(tile0, tiles) println("Tile 0 elegível: $isEligible") // false (bloqueada por cima) val tile2 = tiles[2] val isEligible2 = DomainRules.isEligible(tile2, tiles) println("Tile 2 elegível: $isEligible2") // true (livre à direita, sem bloqueio superior) ``` -------------------------------- ### Executar testes de regressão com Gradle Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/05 - Ciclo_05_Testes_e_Regressao/03 - Checklist_de_Conclusao.md Comando utilizado para executar a suíte de testes do projeto e validar a configuração. ```bash ./gradlew test ``` -------------------------------- ### GameController - Orchestrate Game Flow Source: https://context7.com/walbarellos/vitaacre/llms.txt Initialize the game state and controller, then process user input events to evolve the game. Handles touch events for selection and matching, and restart events. ```kotlin import com.vitahacre.domain.model.* import com.vitahacre.data.generator.GeneratorFactory import com.vitahacre.presentation.controller.DefaultGameController // Criar estado inicial val config = BoardConfiguration( columns = 4, rows = 2, layers = 1, totalTiles = 8, seed = 42L ) val (initialState, _) = GeneratorFactory.createInitialGameState(config) // Criar controlador val controller = DefaultGameController( initialState = initialState, cellSize = 100f // Tamanho de cada unidade em pixels ) // Verificar estado inicial println("Estado inicial: ${controller.state.status}") // PRONTO // Simular toque em uma peça (coordenadas em pixels) val touchEvent = InputEvent( x = 50f, // Centro da primeira coluna y = 50f, // Centro da primeira linha type = InputEventType.TOUCH ) // Processar evento val newState = controller.onInput(touchEvent) println("Após primeiro toque: ${newState.status}") // SELECIONANDO_1 println("Peça selecionada: ${newState.selection.firstSelectedTileId}") // Simular segundo toque para tentar match val secondTouch = InputEvent( x = 250f, // Terceira coluna y = 50f, type = InputEventType.TOUCH ) val matchState = controller.onInput(secondTouch) // Verificar resultado do match if (matchState.status == GameStatus.PRONTO) { println("Match processado, voltou para PRONTO") val removedCount = matchState.tiles.count { it.isRemoved } println("Peças removidas: $removedCount") } // Reiniciar partida val restartEvent = InputEvent(type = InputEventType.RESTART) val freshState = controller.onInput(restartEvent) println("Após reinício: ${freshState.status}") // PRONTO println("Peças ativas: ${freshState.activeTiles.size}") // 8 (todas restauradas) ``` -------------------------------- ### Interface BoardRenderer Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/04 - Ciclo_04_Renderizacao_Procedural/01 - Contrato_Tecnico_do_Ciclo.md Define o contrato para desenhar a malha espacial do tabuleiro. ```kotlin interface BoardRenderer { fun render(boardConfiguration: BoardConfiguration, canvas: Canvas) } ``` -------------------------------- ### Interface BoardGenerator Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/02 - Ciclo_02_Gerador_Procedural/01 - Contrato_Tecnico_do_Ciclo.md Contrato para a implementação de geradores de tabuleiro, exigindo a implementação do método generate. ```kotlin interface BoardGenerator { fun generate(configuration: BoardConfiguration): BoardGenerationResult } ``` -------------------------------- ### TileRenderer Interface Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/04 - Ciclo_04_Renderizacao_Procedural/01 - Contrato_Tecnico_do_Ciclo.md Minimum signature and behavior for the TileRenderer. ```APIDOC ## TileRenderer Interface ### Description Renders an individual tile. ### Method ```kotlin fun render(tile: Tile, position: Offset, isSelected: Boolean, canvas: Canvas) ``` ### Parameters - **tile** (`Tile`) - The tile data to render. - **position** (`Offset`) - The calculated (x, y) coordinates for the tile. - **isSelected** (`Boolean`) - Flag to indicate if the tile is currently selected. - **canvas** (`Canvas`) - The canvas to draw on. ### Behavior - Draws the tile's base color based on `tile.pairKey`. - Renders the tile's border. - Optionally renders a textual identifier. ``` -------------------------------- ### Restart Technical Flow Source: https://github.com/walbarellos/vitaacre/blob/master/docs/1 - Waterfall/08 - Implementacao_Tecnica.md Details the minimum technical steps required to restart the game. ```APIDOC ## 8.14 Fluxo Técnico do Reinício O fluxo técnico mínimo do reinício deve obedecer à seguinte ordem: 1. receber evento de reinício; 2. construir ou recuperar BoardConfiguration; 3. gerar novo tabuleiro; 4. criar novo GameState; 5. definir estado PRONTO; 6. refletir nova sessão na interface. ``` -------------------------------- ### Define Board Configuration Source: https://github.com/walbarellos/vitaacre/blob/master/docs/1 - Waterfall/05 - Modelo_de_Dados.md Specifies the structural parameters for generating or characterizing the game board, including dimensions and tile counts. Includes an optional seed for deterministic generation. ```kotlin data class BoardConfiguration( val columns: Int, val rows: Int, val layers: Int, val totalTiles: Int, val seed: Long? = null ) ``` -------------------------------- ### Check Tile Compatibility and Match Rules Source: https://context7.com/walbarellos/vitaacre/llms.txt Use `canMatch` for a quick check of tile compatibility based on pairKey and identity. Use `evaluateMatch` for a full validation including tile availability and board state. ```kotlin import com.vitahacre.domain.model.* import com.vitahacre.domain.rules.MatchRules // Criar peças para teste val tileA = Tile(id = 0, pairKey = 5, x = 0, y = 0, layer = 0) val tileB = Tile(id = 1, pairKey = 5, x = 4, y = 0, layer = 0) val tileC = Tile(id = 2, pairKey = 7, x = 6, y = 0, layer = 0) val tiles = listOf(tileA, tileB, tileC) // Verificação rápida de compatibilidade (apenas pairKey e distinção) val canMatchAB = MatchRules.canMatch(tileA, tileB) val canMatchAC = MatchRules.canMatch(tileA, tileC) val canMatchAA = MatchRules.canMatch(tileA, tileA) println("A-B compatíveis: $canMatchAB") // true (mesmo pairKey) println("A-C compatíveis: $canMatchAC") // false (pairKeys diferentes) println("A-A compatíveis: $canMatchAA") // false (mesma peça) // Avaliação completa de match (inclui elegibilidade) val resultAB = MatchRules.evaluateMatch(tileA, tileB, tiles) println("Match A-B válido: ${resultAB.isValid}") // true println("Motivo: ${resultAB.reason}") // VALID_MATCH val resultAC = MatchRules.evaluateMatch(tileA, tileC, tiles) println("Match A-C válido: ${resultAC.isValid}") // false println("Motivo: ${resultAC.reason}") // DIFFERENT_PAIR_KEY // Tentar match com peça removida val removedTile = tileB.copy(isRemoved = true) val tilesWithRemoved = listOf(tileA, removedTile, tileC) val resultRemoved = MatchRules.evaluateMatch(tileA, removedTile, tilesWithRemoved) println("Match com removida: ${resultRemoved.isValid}") // false println("Motivo: ${resultRemoved.reason}") // TILE_REMOVED ``` -------------------------------- ### Rendering Data Flow Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/04 - Ciclo_04_Renderizacao_Procedural/01 - Contrato_Tecnico_do_Ciclo.md Illustrates how data flows from the GameState to the various rendering components. ```APIDOC ## Rendering Data Flow ``` GameState (source of truth) │ ├── boardConfiguration → BoardRenderer │ └── draws mesh │ ├── tiles → TileRenderer │ ├── filter isRemoved == false │ └── draws each tile │ ├── selection.firstSelectedTileId → SelectionHighlightRenderer │ └── applies visual highlight │ └── status → StateOverlayRenderer └── draws overlay if applicable ``` ``` -------------------------------- ### Select First Tile Function Signature Source: https://github.com/walbarellos/vitaacre/blob/master/docs/1 - Waterfall/08 - Implementacao_Tecnica.md Reference signature for a function that registers the first tile selected by the user. Updates the game state to reflect the initial selection. ```kotlin fun selectFirstTile(tile: Tile, state: GameState): GameState ``` -------------------------------- ### Implement Game Screen State Adapter Source: https://github.com/walbarellos/vitaacre/blob/master/docs/3 - Execucao_Real/04 - Ciclo_04_Renderizacao_Procedural/02 - Plano_de_Implementacao.md Adapter class to orchestrate the rendering process by calling various renderer interfaces in the correct order. It adapts game state to canvas rendering calls. ```kotlin class GameScreenStateAdapter( private val boardRenderer: BoardRenderer, private val tileRenderer: TileRenderer, private val selectionHighlightRenderer: SelectionHighlightRenderer, private val stateOverlayRenderer: StateOverlayRenderer ) { fun render(gameState: GameState, cellSize: Float, canvas: Canvas) } ```