My experience with this model - bad results on code generation

#1
by robert1968 - opened

hi

i've tried IQuest-Coder-V1-40B-Instruct.Q6_K.gguf and it is slow (~20.30 tok/sec) (using 2xRTX 3090 - 24GB=48GB) - Q6 reserved 32.65 GB
and never got working results for first shot (even second or third) :
-prompt1: make html pong game with score. opponent is the computer.
-prompt2: make a html based minesweeper game
-prompt3: make a html based snake game

As a clear contrast to it, above (easy) tasks are solved at first shot, with
-devstral-small-2-24b-instruct-2512
-qwen3-coder-30b-a3b-instruct
-qwen3-next-80b-a3b-instruct@iq4_xs

I've used LM Studio, Open Webui and tried Claude Code (with CC Router) to generate a playwright test but failed at very beginning step.
so conclusion: it is slow and bad model.

You can try another sampling parameters.
The sampling parameters are temperature=0.6 and top_p=0.95.

I tried IQuest-Coder-V1-40B-Instruct.Q6_K.gguf on llama.cpp with the above sampling parameters.

  • For pong game

image

  • For snake game

image

  • For minesweeper game

image

There are multiple files are generated for minesweeper game , then I append a single file into minesweeper game and I got the following game. The user prompt is:

user_prompt = "make a html based minesweeper game. a single file"

image

You can try sampling parameters based on IQuestCoder repo.

The sampling parameters are on Benchmark Parameter section

image

Great, thanks for share your results.
I was really curious why I have so bad results. I will try temperature and top_p parameters.

How is your experience about the speed?
20 tokens/sec is poor, because on my machine Qwen3 coder 30B A3 provides ~120 tokens/s.
Can you pls try a playwright test? With Claude code router it started agentic steps, but under a few steps it started repeating same response.

I launched an llama.cpp server on H200 device. It would be faster than your devices.

I had played snake and minesweeper game. These games are OK. But I did not play the ping-pong game well because the speed is too fast for me.

Qwen3 coder 30B A3 is a model with MoE architecture. If the rate of requests is small, Qwen3 coder 30B-A3B is equivalent to a 3-billion-parameter model. But IQuest-Coder-V1 40B model is a dense model. Therefore, the inference speed for IQuest-Coder-V1 40B is slower than Qwen3 coder 30B-A3B

i redownload the iquestlab.iquest-coder-v1-40b-instruct model again (Q6_K) set Temperature to 0.6 and top_k to 0.95
And first it make a html and css, java file, and then i gave the same instruction: "make a html based minesweeper game. a single file" as you.

but still not running. i can change difficulty level but New game button does not start the game.

image

These are the LM studio settings:
image

LM Studio also using LLama.cpp.

image

I cant imagine why i have this bad results...

Can you upload the generated HTML file? Let me check if I can review the generated content.

I tried to generated minesweeper game for many times. It's OK for me

Maybe you can try more prompts, such as:

prompt1: make a html based minesweeper game. a single file
prompt2: make a html based minesweeper game. a single file, including easy, medium and hard mode

image

image

The mode is quantized by 6-bit and Instruction following has somewhat weakened.

Can you upload the generated HTML file? Let me check if I can review the generated content.

Hi,
Sure here you are. This was the prompt: "make a html based minesweeper game. a single file"

HTML Minesweeper

Here is a complete, playable Minesweeper game contained in a single HTML file. It includes the game logic, CSS styling for the classic look, and supports right-clicking (to flag) and left-clicking (to reveal).

Save this code as an .html file (e.g., minesweeper.html) and open it in your browser.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML Minesweeper</title>
    <style>
        :root {
            --cell-size: 30px;
            --grid-border: 10px solid #b8b8b8;
            --btn-bg: #e5e5e5;
            --btn-hover: #d4d4d4;
            --text-color: black;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #202020;
            color: white;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
            user-select: none; /* Prevent text selection */
        }

        h1 { margin-bottom: 10px; font-size: 2rem; color: #f0c36e; }

        .controls {
            display: flex;
            gap: 15px;
            margin-bottom: 20px;
        }

        button {
            padding: 8px 16px;
            background-color: var(--btn-bg);
            border: none;
            cursor: pointer;
            font-weight: bold;
            color: #333;
            border-radius: 4px;
            transition: background 0.2s;
        }

        button:hover { background-color: var(--btn-hover); }

        .stats {
            display: flex;
            gap: 20px;
            margin-bottom: 15px;
            font-size: 1.2rem;
        }

        #game-board {
            display: grid;
            background-color: var(--grid-border);
            padding: 10px;
            border-radius: 8px;
        }

        .cell {
            width: var(--cell-size);
            height: var(--cell-size);
            border: 1px solid #808080;
            background-color: #d3d3d3;
            display: flex;
            justify-content: center;
            align-items: center;
            font-weight: bold;
            cursor: pointer;
            box-sizing: border-box;
        }

        .cell.clicked { background-color: #f0f0f0; transform: scale(1); transition: none;}
        /* The :not(:hover) ensures we don't override the hover state */
        .cell:not(.clicked):hover { cursor: pointer; }

        /* Numbers colors (Standard Minesweeper palette) */
        .n-1 { color: blue; }
        .n-2 { color: green; }
        .n-3 { color: red; }
        .n-4 { color: purple; }
        .n-5 { color: maroon; }
        .n-6 { color: turquoise; }
        .n-7, .n-8 { color: black; } /* Usually both are black/gray */
        .n-10 { background-color: red; color: white; } /* Flag or Mine indicator */

    </style>
</head>
<body>

    <h1>Minesweeper</h1>
    
    <div class="controls">
        <!-- Difficulty selector -->
        <select id="difficulty" style="padding: 5px; font-weight: bold;">
            <option value="easy">Easy (10x8)</option>
            <option value="medium" selected>Medium (16x12)</option>
            <option value="hard">Hard (30x16)</option>
        </select>
        <!-- Reset Button -->
        <button id="reset-btn" style="background:#f0c36e;">New Game</button>
    </div>

    <div class="stats">
        <span id="mines-count">Mines: 40</span>
        <span id="timer" style="color:#f0c36e;">Time: 0s</span>
    </div>

    <div id="game-board"></div>

<script>
    const board = document.getElementById('game-board');
    const minesCountDisplay = document.getElementById('mines-count');
    const timerDisplay = document.getElementById('timer');
    const resetBtn = document.getElementById('reset-btn');
    const difficultySelect = document.getElementById('difficulty');

    // Game Configurations
    let rows, cols;
    let mineCount;
    let flagsPlaced = 0;
    let isGameOver = false;
    let timerInterval;
    let timeElapsed = 0;
    let gridData = []; // Stores status: { isMine, revealed, flagged }

    function initGame() {
        clearInterval(timerInterval);
        resetStats();
        generateGrid();
        renderBoard();
    }

    function resetStats() {
        timeElapsed = 0;
        timerDisplay.innerText = `Time: ${timeElapsed}s`;
        flagsPlaced = 0;
        isGameOver = false;
    }

    function getDifficultySettings() {
        switch(difficultySelect.value) {
            case 'easy': return { rows: 8, cols: 10, mines: 10 };
            case 'hard': return { rows: 16, cols: 30, mines: 99 }; // Standard hard is roughly this ratio or more
            default: return { rows: 12, cols: 16, mines: 40 };
        }
    }

    function resetStatsUI() {
        const settings = getDifficultySettings();
        mineCountDisplay.innerText = `Mines: ${settings.mines}`;
    }

    function generateGrid() {
        board.innerHTML = ''; // Clear UI
        gridData = [];
        const settings = getDifficultySettings();
        rows = settings.rows;
        cols = settings.cols;
        mineCount = settings.mines;

        // Set grid CSS columns dynamically based on size to keep cells square
        board.style.gridTemplateColumns = `repeat(${cols}, var(--cell-size))`;

        resetStatsUI();

        // Initialize Grid Data (Empty)
        for (let r = 0; r < rows; r++) {
            const rowData = [];
            for (let c = 0; c < cols; c++) {
                rowData.push({ isMine: false, revealed: false, flagged: false });
            }
            gridData.push(rowData);
        }
    }

    function renderBoard() {
        board.innerHTML = ''; // Clear current view to redraw (simplest approach for vanilla JS)
        gridData.forEach((row, rIndex) => {
            row.forEach((cellObj, cIndex) => {
                const cell = document.createElement('div');
                cell.classList.add('cell');
                cell.dataset.r = rIndex;
                cell.dataset.c = cIndex;
                updateCellVisuals(cell, cellObj);
                board.appendChild(cell);
            });
        });
    }

    function updateCellVisuals(cell, cellObj) {
        if (isGameOver && !cell.classList.contains('clicked')) return;

        // Logic for what to show in the cell content and classes
        const neighbors = getNeighbors(parseInt(cell.dataset.r), parseInt(cell.dataset.c));
        let count = 0;
        if (!isGameOver) { // Only calculate numbers on live board, or keep logic simple for end game visualization
           neighbors.forEach(n => {
               if (gridData[n.r][n.c].isMine) count++;
           });
       } else {
           // If game over, we show the truth regardless of flags to reveal board (optional: hide unrevealed mines)
           neighbors.forEach(n => { if(!gridData[n.r][n.c].isMine && gridData[n.r][n.c].revealed) count++; }); // Simplified for end state visual check
       }

        cell.innerText = '';
        if (cellObj.flagged) {
            cell.innerText = '🚩'; // Flag emoji
        } else if (!isGameOver && count > 0) {
            cell.classList.add(`n-${count}`);
            cell.innerText = count;
        } else if (cellObj.isMine && isGameOver) {
            // Reveal mines only on game over or click directly? Logic handles click separately.
            cell.innerText = '💣';
            cell.style.backgroundColor = '#ff0000';
        } else if (cellObj.isMine && !isGameOver) {
           // Don't show mine until exploded or game over, but we need to handle the "clicked on a mine" case in click handler logic specifically.
       } else if (cellObj.revealed && count === 0) {
           cell.classList.add('empty'); // No specific style needed, but logically empty
           cell.style.backgroundColor = '#e8e8e8';
       } else if (cellObj.revealed) {
           // Number revealed logic handled above, but this catches the case where it's just an empty click reveal
           cell.style.backgroundColor = '#e8e8e8';
       } else {
           // Unclicked hidden state (default CSS handles this)
       }
        
        if(cellObj.revealed || cellObj.flagged) cell.classList.add('clicked');
    }

    // Helper: Get list of valid neighbor coordinates {r, c}
    function getNeighbors(row, col) {
        let neighbors = [];
        for (let dr = -1; dr <= 1; dr++) {
            for (let dc = -1; dc <= 1; dc++) {
                if (dr === 0 && dc === 0) continue; // Skip self
                const nr = row + dr;
                const nc = col + dc;
                if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) {
                    neighbors.push({ r: nr, c: nc });
                }
            }
        }
        return neighbors;
    }

    // Logic: Place Mines randomly ensuring first click is safe (simplified for standard grid)
    function placeMines(firstR, firstC) {
        let minesPlaced = 0;
        while (minesPlaced < mineCount) {
            const r = Math.floor(Math.random() * rows);
            const c = Math.floor(Math.random() * cols);
            // Don't place mine on first clicked cell or neighbors of it (optional: makes game start easier)
            if (!gridData[r][c].isMine && !(Math.abs(r-firstR)<2 && Math.abs(c-firstC)<2)) {
               gridData[r][c].isMine = true;
               minesPlaced++;
            }
        }
    }

    function startTimer() {
        clearInterval(timerInterval);
        timerInterval = setInterval(() => {
            timeElapsed++;
            timerDisplay.innerText = `Time: ${timeElapsed}s`;
        }, 1000);
    }

    function gameWin() {
        isGameOver = true;
        clearInterval(timerInterval);
        // Reveal all mines as flags or safe
        gridData.forEach((row, r) => {
            row.forEach((cellObj, c) => {
                if(cellObj.isMine && !cellObj.flagged) {
                   // Auto flag remaining mines for visual flair? Or just leave them beaded red later in updateCellVisuals logic above.
                   const cell = document.querySelector(`.cell[data-r="${r}"][data-c="${c}"]`);
                   if(!isGameOver) { // Hacky check, but works for this scope
                   }
                }
            });
        });
        alert("You Win! Time: " + timeElapsed);
    }

    function gameLose() {
        isGameOver = true;
        clearInterval(timerInterval);
        // Show all mines and flags
        gridData.forEach((row, r) => {
            row.forEach((cellObj, c) => {
                const cell = document.querySelector(`.cell[data-r="${r}"][data-c="${c}"]`);
                if (cellObj.isMine && !cellObj.flagged) {
                   cell.innerText = '💣'; // Exploded mine
                   cell.style.backgroundColor = '#ff0000';
                } else if (cellObj.flagged && !cellObj.isMine) {
                   cell.innerText = '❌'; // Wrong flag
                   cell.style.backgroundColor = '#ffcccc';
                } else if (cellObj.isMine && cellObj.flagged) {
                   // Correct flag, leave as is or highlight?
                   cell.innerText = '🚩'; 
                } else if (!cellObj.revealed) {
                   // Reveal hidden safe cells? Usually just leave them or fade them out in CSS
                  cell.style.backgroundColor = '#d3d3d3'; // Reset to default
                } else {
                   updateCellVisuals(cell, cellObj);
                }
            });
        });
        alert("Game Over! You hit a mine.");
    }

    // --- Event Listeners & Interaction Logic ---

    board.addEventListener('click', (e) => {
        if(isGameOver) return;
        const cell = e.target.closest('.cell');
        if(!cell || !board.contains(cell)) return;

        // Start timer on first click of the game
        startTimer();

        const r = parseInt(cell.dataset.r);
        const c = parseInt(cell.dataset.c);
        const cellObj = gridData[r][c];

        if (cellObj.flagged || cellObj.revealed) return; // Ignore clicks on flags/revealed cells unless right clicking to unflag is supported (not implemented here for simplicity: usually click=reveal, rclick=flag).

        // First Click Logic: Place mines only when first non-mine cell is clicked? 
        // Standard Minesweeper places mines immediately or on first click. Let's do "on first click" to ensure safe start zone.
        if (cellObj.isMine === false && document.querySelectorAll('.clicked').length === 0) {
           placeMines(r, c);
       }

        // Hit a mine? Game Over!
        if (cellObj.isMine) {
            cellObj.revealed = true;
            updateCellVisuals(cell, cellObj); // Shows mine/explosion
            gameLose();
            return;
        }

        revealCell(r, c);
    });

    board.addEventListener('contextmenu', (e) => {
        e.preventDefault(); // Stop context menu from appearing on right click
        if(isGameOver || !board.contains(e.target)) return;

        const cell = document.elementFromPoint(e.clientX, e.clientY);
        // Safety check to ensure we clicked the grid div specifically or its children
        if(!board.contains(cell)) return;
        const cellDiv = cell.closest('.cell');
        if (!cellDiv) return; // Clicked gap between cells maybe?

        toggleFlag(parseInt(cellDiv.dataset.r), parseInt(cellDiv.dataset.c));
    });

    function revealCell(r, c) {
        const cellObj = gridData[r][c];
        if (cellObj.revealed || cellObj.flagged) return;

        // Bounds check just in case
        if(r < 0 || r >= rows || c < 0 || c >= cols) return;

        const neighbors = getNeighbors(r, c);
        let count = 0;
        neighbors.forEach(n => { if (gridData[n.r][n.c].isMine) count++; });

        cellObj.revealed = true;
        const domCell = document.querySelector(`.cell[data-r="${r}"][data-c="${c}"]`);
        updateCellVisuals(domCell, cellObj); // This updates innerText and classes based on 'count' logic inside function

        if (count === 0) {
            // Flood fill: Reveal neighbors automatically if count is 0
            neighbors.forEach(n => revealCell(n.r, n.c));
        } else {
            // If numbers > 0, just show number and stop recursion for that branch
        }

        checkWinCondition();
    }

    function toggleFlag(r, c) {
        const cellObj = gridData[r][c];
        if (cellObj.revealed) return; // Can't flag revealed cells usually? Some versions allow it but let's keep strict rules.

        if (!cellObj.flagged && flagsPlaced < mineCount) {
            cellObj.flagged = true;
            flagsPlaced++;
        } else if (cellObj.flagged) {
            cellObj.flagged = false;
            flagsPlaced--;
        }
        updateMineCounter();
        const domCell = document.querySelector(`.cell[data-r="${r}"][data-c="${c}"]`);
        // Note: Right click logic doesn't trigger the visual refresh of neighbor counts like left clicking does in complex implementations, but for this game it is sufficient to toggle flag.
        updateCellVisuals(domCell, cellObj);
        checkWinCondition(); // Check if last mine was found or board cleared
    }

    function updateMineCounter() {
        const remaining = (mineCount - flagsPlaced) > 0 ? (mineCount - flagsPlaced) : 0;
        mineCountDisplay.innerText = `Mines: ${remaining}`;
    }

    function checkWinCondition() {
        // Win if all non-mine cells are revealed? Or just flags equal mines and board cleared logic handled by revealCell.
        // Simplest: Check every cell that is NOT a mine, IS it REVEALED?
        let safeCellsHidden = false;
        gridData.forEach(row => {
            row.forEach(cellObj => {
                if (!cellObj.isMine && !cellObj.revealed) safeCellsHidden = true;
            });
        });

        // Also win immediately if flags == mines (if we don't have hidden cells logic bug)? No, standard is clear all.
        if (!safeCellsHidden) {
           gameWin();
       } else if ((mineCount - flagsPlaced) === (gridData.flat().filter(c => c.isMine).length)) {
           // Optional win condition: Flags match total mines count exactly? No, usually requires clearing the board or flagging correctly without hitting a mine.
       }
    }

    resetBtn.addEventListener('click', initGame);
    difficultySelect.addEventListener('change', () => { updateMineCounter(); renderBoard(); }); // Re-render to adjust grid size

    // Start initial game state (but don't place mines until first click)
    generateGrid();
    resetStatsUI();

</script>
</body>
</html>

I tried with above generated html and open it with chrome. There are some errors on console

image

Then I append the error message into the generated html and send a new prompt:

user_prompt = """
$ generated_html

help me fix bug on the game and give me the new html. The error is the following:
Uncaught ReferenceError: mineCountDisplay is not defined
at resetStatsUI (test-q6-minter-hf.html:155:9)
at generateGrid (test-q6-minter-hf.html:169:9)
at test-q6-minter-hf.html:433:5
"""

After that, I got a new html:

image

Now I can play the Minesweeper game

I tried different prompts to generate Minesweeper game. The following prompts I think are more useful:

prompt1: "make a html based minesweeper game. a single file. including easy, medium and hard mode"
prompt2: "make a html based minesweeper game. a single file."
prompt3: "make a html based minesweeper game and save it as a single file. At the same time, I want to add timer. The color of game board and digits should be suitable."

The generated html would be more better if you add more details in prompt.

At the same time, I fix bugs in generated html by this Q6 instruct model

Sign up or log in to comment