исзмени код все запросы к Lm studio будут через php  и напиши целиком
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DnD Приключение в Элендриэль</title>
    <style>
        /* Общие стили */
        body {
            font-family: 'Arial', sans-serif;
            background-color: #2b2b2b;
            color: #e0e0e0;
            margin: 0;
            padding: 20px;
            transition: background-color 0.5s;
        }

        header {
            text-align: center;
            margin-bottom: 20px;
        }

        h1 {
            color: #f39c12;
            font-size: 2.5em;
            margin-bottom: 10px;
        }

        /* Кнопки */
        button {
            margin: 5px;
            padding: 12px 24px;
            font-size: 16px;
            background-color: #27ae60;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s, transform 0.3s;
            min-width: 150px;
        }

        button:hover {
            background-color: #219653;
            transform: scale(1.05);
        }

        /* Журнал событий */
        #eventLog {
            margin: 20px 0;
            padding: 15px;
            background-color: #34495e;
            border: 1px solid #2980b9;
            border-radius: 5px;
            height: 300px;
            overflow-y: auto;
            animation: fadeIn 0.5s;
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        /* Кнопки действий */
        #actionButtons {
            margin: 20px 0;
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            justify-content: center;
        }

        /* Инвентарь и магазин */
        .inventory, #shop {
            margin-top: 50px;
            background-color: #8e44ad;
            border: 1px solid #9b59b6;
            border-radius: 5px;
            padding: 10px;
        }

        #inventory h2, #shop h2 {
            color: #f1c40f;
            text-align: center;
        }

        #inventoryList, #shopItems {
            list-style-type: none;
            padding: 0;
            max-height: 200px;
            overflow-y: auto;
        }

        #inventoryList li, #shopItems li {
            padding: 10px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            background-color: #2ecc71;
            margin: 5px 0;
            border-radius: 3px;
            transition: background-color 0.3s;
            cursor: pointer;
        }

        #inventoryList li:hover, #shopItems li:hover {
            background-color: #27ae60;
        }

        .selected {
            border: 2px solid #f1c40f;
        }

        @media (min-width: 600px) {
            body {
                padding: 40px;
            }
            #eventLog {
                height: 400px;
            }
        }

        /* Модальное окно */
        .modal {
            display: none; 
            position: fixed; 
            z-index: 1000; 
            left: 0;
            top: 0;
            width: 100%; 
            height: 100%; 
            overflow: auto; 
            background-color: rgba(0,0,0,0.8);
        }

        .modal-content {
            background-color: #2b2b2b;
            margin: 10% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 500px;
            border-radius: 10px;
            color: #e0e0e0;
            position: relative;
        }

        .close {
            color: #aaa;
            position: absolute;
            right: 20px;
            top: 10px;
            font-size: 28px;
            font-weight: bold;
            cursor: pointer;
        }

        .close:hover, .close:focus {
            color: #fff;
            text-decoration: none;
        }

        .character-selection {
            display: flex;
            flex-direction: column;
            gap: 15px;
            margin: 20px 0;
        }

        .character-selection label {
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 1.1em;
        }

        /* Улучшенный интерфейс */
        #currentStats {
            display: flex;
            justify-content: space-around;
            margin-top: 20px;
            padding: 10px;
            background-color: #2980b9;
            border-radius: 5px;
        }

        #currentStats div {
            text-align: center;
        }

        /* Загрузочный индикатор */
        .loader {
            border: 8px solid #f3f3f3;
            border-top: 8px solid #27ae60;
            border-radius: 50%;
            width: 60px;
            height: 60px;
            animation: spin 1s linear infinite;
            margin: 20px auto;
            display: none;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        /* История игры */
        #historyToggle {
            margin-top: 20px;
            padding: 10px 20px;
            background-color: #8e44ad;
            color: #fff;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s;
        }

        #historyToggle:hover {
            background-color: #71368a;
        }

        #history {
            display: none;
            margin-top: 20px;
            padding: 15px;
            background-color: #34495e;
            border: 1px solid #2980b9;
            border-radius: 5px;
            max-height: 300px;
            overflow-y: auto;
        }

        #history h2 {
            text-align: center;
            color: #f1c40f;
        }

        #historyList {
            list-style-type: none;
            padding: 0;
        }

        #historyList li {
            padding: 5px 0;
            border-bottom: 1px solid #2980b9;
        }
    </style>
</head>
<body>
    <header>
        <h1>ДНД Приключение в Элендриэль</h1>
        <button id="startGame">Начать игру</button>
    </header>
    <main>
        <div id="currentStats">
            <div>
                <strong>Раса:</strong>
                <span id="currentRace">-</span>
            </div>
            <div>
                <strong>Класс:</strong>
                <span id="currentClass">-</span>
            </div>
            <div>
                <strong>Уровень:</strong>
                <span id="currentLevel">1</span>
            </div>
            <div>
                <strong>Опыт:</strong>
                <span id="currentXP">0</span>
            </div>
        </div>

        <div class="loader" id="loader"></div>

        <div id="eventLog"></div>
        <div id="actionButtons"></div>
        <button id="historyToggle">Показать Историю</button>
        <div id="history">
            <h2>История Игры</h2>
            <ul id="historyList"></ul>
        </div>
        <div class="inventory">
            <h2>Инвентарь:</h2>
            <ul id="inventoryList"></ul>
        </div>
        <div id="shop" style="display: none;">
            <h2>Магазин:</h2>
            <ul id="shopItems"></ul>
            <button id="buyItem">Купить выбранный предмет</button>
        </div>
    </main>

    <!-- Модальное окно для выбора персонажа -->
    <div id="characterModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <h2>Выберите вашего персонажа</h2>
            <div class="character-selection">
                <div>
                    <strong>Раса:</strong>
                    <label><input type="radio" name="race" value="человек" checked> Человек</label>
                    <label><input type="radio" name="race" value="эльф"> Эльф</label>
                    <label><input type="radio" name="race" value="дворф"> Дворф</label>
                </div>
                <div>
                    <strong>Класс:</strong>
                    <label><input type="radio" name="class" value="маг" checked> Маг</label>
                    <label><input type="radio" name="class" value="воин"> Воин</label>
                    <label><input type="radio" name="class" value="лучник"> Лучник</label>
                </div>
                <button id="confirmCharacter">Подтвердить</button>
            </div>
        </div>
    </div>

    <!-- Подключение внешнего файла script.js -->
    <script >document.addEventListener("DOMContentLoaded", function () {
    // Состояния игры
    const gameState = {
        active: false,
        inventory: [],
        experience: 0,
        level: 1,
        currentLocation: "Амарин",
        playerRace: "человек",
        playerClass: "маг",
        reputation: 0,
        selectedItem: null,
        quests: [],
        history: [] // Для хранения истории и выборов
    };

    // Элементы DOM
    const startGameBtn = document.getElementById('startGame');
    const buyItemBtn = document.getElementById('buyItem');
    const eventLog = document.getElementById('eventLog');
    const actionButtonsDiv = document.getElementById('actionButtons');
    const inventoryList = document.getElementById('inventoryList');
    const shop = document.getElementById('shop');
    const shopItemsList = document.getElementById('shopItems');
    const loader = document.getElementById('loader');
    const historyToggle = document.getElementById('historyToggle');
    const historyDiv = document.getElementById('history');
    const historyList = document.getElementById('historyList');
    const currentRace = document.getElementById('currentRace');
    const currentClass = document.getElementById('currentClass');
    const currentLevel = document.getElementById('currentLevel');
    const currentXP = document.getElementById('currentXP');

    // Модальное окно
    const characterModal = document.getElementById('characterModal');
    const closeModal = document.querySelector('.close');
    const confirmCharacterBtn = document.getElementById('confirmCharacter');

    // Предметы магазина
    const shopItems = [
        { name: "Зелье здоровья", price: 10 },
        { name: "Меч", price: 25 },
        { name: "Лук", price: 20 },
        { name: "Щит", price: 30 },
        { name: "Кольцо силы", price: 50 },
        { name: "Магический посох", price: 40 }
    ];

    // Промты для нейросети
    const systemPrompt = `
        Ты играешь роль мастера игры в DnD и взаимодействуешь с игроком.
        Твоя задача описывать события и предоставлять варианты действий.
        Отвечай строго в следующем формате:

        <Dialog>Тут текст диалога</Dialog>
        <button>Вариант действия 1</button>
        <button>Вариант действия 2</button>
        <button>Вариант действия 3</button>

        Пример:

        <Dialog>Вы входите в тёмный лес. Вокруг слышны звуки ночных животных.</Dialog>
        <button>Осмотреться вокруг</button>
        <button>Пойти вперёд</button>
        <button>Вернуться назад</button>
    `;

    const userPrompt = (player, location, quests) => `
        Ты находишься в ${location}. ${getLocationDescription(location)} У тебя есть квесты: ${quests}.
        Опиши события вокруг и предложи действия, которые может предпринять ${capitalizeFirstLetter(player.playerRace)} ${capitalizeFirstLetter(player.playerClass)}.

        Отвечай строго в формате:

        <Dialog>Тут текст диалога</Dialog>
        <button>Вариант действия 1</button>
        <button>Вариант действия 2</button>
        <button>Вариант действия 3</button>
    `;

    // Инициализация
    startGameBtn.addEventListener('click', openCharacterModal);
    buyItemBtn.addEventListener('click', buyItem);
    closeModal.addEventListener('click', () => {
        characterModal.style.display = 'none';
    });
    window.addEventListener('click', (e) => {
        if (e.target == characterModal) {
            characterModal.style.display = 'none';
        }
    });
    confirmCharacterBtn.addEventListener('click', confirmCharacter);
    historyToggle.addEventListener('click', toggleHistory);

    function openCharacterModal() {
        characterModal.style.display = 'block';
    }

    function confirmCharacter() {
        const selectedRaceElem = document.querySelector('input[name="race"]:checked');
        const selectedClassElem = document.querySelector('input[name="class"]:checked');

        if (!selectedRaceElem || !selectedClassElem) {
            alert("Пожалуйста, выберите расу и класс.");
            return;
        }

        const selectedRace = selectedRaceElem.value;
        const selectedClass = selectedClassElem.value;

        gameState.playerRace = selectedRace;
        gameState.playerClass = selectedClass;

        characterModal.style.display = 'none';
        startGame();
    }

    function startGame() {
        gameState.active = true;
        gameState.inventory = [];
        gameState.experience = 0;
        gameState.level = 1;
        gameState.reputation = 0;
        gameState.currentLocation = "Амарин";
        gameState.quests = [];
        gameState.history = []; // Сброс истории

        updateStatsUI();
        updateInventoryUI();
        clearEventLog();
        clearHistoryUI();
        appendEventLog("Игра началась!");
        getEvent();
    }

    async function getEvent() {
        if (!gameState.active) {
            alert("Сначала начните игру!");
            return;
        }

        showLoader(true);
        appendEventLog("Получение события...");

        const locationDescription = getLocationDescription(gameState.currentLocation);
        const activeQuests = gameState.quests.filter(q => !q.completed).map(q => q.description).join(", ");

        try {
            const response = await fetch('http://90.189.110.130/:1234/v1/chat/completions', { // Замените URL на правильный
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    model: "gpt-4", // Замените на ваш идентификатор модели
                    messages: [
                        { role: "system", content: generateFullPrompt() },
                        { role: "user", content: userPrompt(gameState, gameState.currentLocation, activeQuests) }
                    ],
                    temperature: 0.7,
                    max_tokens: 500
                })
            });

            if (!response.ok) {
                throw new Error(`Ошибка сервера: ${response.status}`);
            }

            const data = await response.json();
            const eventText = data.choices[0].message.content.trim();
            await processEventText(eventText);
        } catch (error) {
            console.error(error);
            appendEventLog("Произошла ошибка при получении события. Попробуйте ещё раз.");
        } finally {
            showLoader(false);
        }
    }

    async function performAction(action) {
        if (!gameState.active) {
            alert("Сначала начните игру!");
            return;
        }

        appendEventLog(`Вы выбрали: "${action}"`);

        showLoader(true);
        appendEventLog("Обработка вашего выбора...");

        const locationDescription = getLocationDescription(gameState.currentLocation);

        try {
            // Формируем промт для выполнения действия, включая историю
            const actionUserPrompt = `
                Я решил "${action}" в ${gameState.currentLocation}. ${locationDescription} Каковы последствия этого действия, учитывая, что я ${capitalizeFirstLetter(gameState.playerRace)} ${capitalizeFirstLetter(gameState.playerClass)}?
            `;

            const response = await fetch('http://90.189.110.130/:1234/v1/chat/completions', { // Замените URL на правильный
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    model: "gpt-4", // Замените на ваш идентификатор модели
                    messages: [
                        { role: "system", content: generateFullPrompt() },
                        { role: "user", content: actionUserPrompt }
                    ],
                    temperature: 0.7,
                    max_tokens: 500
                })
            });

            if (!response.ok) {
                throw new Error(`Ошибка сервера: ${response.status}`);
            }

            const data = await response.json();
            const actionText = data.choices[0].message.content.trim();
            await processEventText(actionText);

            // Пример обработки последствий: начисление опыта
            rewardExperience(10); // Вы можете заменить это на динамическую логику
            checkLevelUp();
        } catch (error) {
            console.error(error);
            appendEventLog("Произошла ошибка при выполнении действия. Попробуйте ещё раз.");
        } finally {
            showLoader(false);
            // Убираем вызов getEvent() здесь, чтобы избежать автоматического перехода к следующему событию
        }
    }

    function processEventText(eventText) {
        // Используем DOMParser для парсинга ответа
        const parser = new DOMParser();
        const htmlDoc = parser.parseFromString(eventText, 'text/html');

        const dialog = htmlDoc.querySelector('dialog');
        const buttons = htmlDoc.querySelectorAll('button');

        let dialogText = "";
        if (dialog) {
            dialogText = dialog.textContent.trim();
            appendEventLog(dialogText);
        } else {
            dialogText = "Не удалось получить описание события.";
            appendEventLog(dialogText);
        }

        let choices = [];
        if (buttons.length > 0) {
            choices = Array.from(buttons).map(btn => btn.textContent.trim());
            generateActionButtons(choices);
        } else {
            appendEventLog("Нет доступных действий.");
        }

        // Добавление в историю
        if (gameState.active) {
            addToHistory(dialogText, choices);
            updateHistoryUI(dialogText, choices);
        }
    }

    function generateActionButtons(actions) {
        actionButtonsDiv.innerHTML = '';

        actions.forEach(action => {
            const button = document.createElement('button');
            button.innerText = action;
            button.onclick = () => performAction(action);
            actionButtonsDiv.appendChild(button);
        });

        // Добавляем кнопку для посещения магазина
        if (gameState.currentLocation !== "Магазин") {
            const shopBtn = document.createElement('button');
            shopBtn.innerText = "Посетить магазин";
            shopBtn.onclick = visitShop;
            actionButtonsDiv.appendChild(shopBtn);
        }
    }

    function addToHistory(dialog, choices) {
        gameState.history.push({
            dialog: dialog,
            choices: choices
        });

        // Ограничиваем размер истории для предотвращения длинных промтов
        const maxHistory = 50;
        if (gameState.history.length > maxHistory) {
            gameState.history.shift();
        }
    }

    function generateFullPrompt() {
        let prompt = systemPrompt;

        // Добавляем историю (например, последние 10 записей)
        gameState.history.slice(-10).forEach(entry => {
            if (entry.dialog) {
                prompt += `<Dialog>${entry.dialog}</Dialog>\n`;
            }
            if (entry.choices && entry.choices.length > 0) {
                entry.choices.forEach(choice => {
                    prompt += `<button>${choice}</button>\n`;
                });
            }
        });

        return prompt;
    }

    function getLocationDescription(location) {
        const descriptions = {
            "Амарин": "Это королевство света, знаменитое своими величественными храмами.",
            "Скала Гневных Ветров": "Суровое королевство, где морозные ветра бушуют.",
            "Теневый Лес": "Загадочное место, полное опасностей и магии природы.",
            "Пески Вечности": "Жаркое и сухое царство, скрывающее древние тайны.",
            "Страна Кровавых Облаков": "Темное королевство, полное хаоса и беззакония."
        };
        return descriptions[location] || "Неизвестное место.";
    }

    function clearEventLog() {
        eventLog.innerHTML = '';
        actionButtonsDiv.innerHTML = '';
    }

    function appendEventLog(message) {
        const p = document.createElement('p');
        p.textContent = message;
        eventLog.appendChild(p);
        eventLog.scrollTop = eventLog.scrollHeight;
    }

    function rewardExperience(points) {
        gameState.experience += points;
        updateStatsUI();
        appendEventLog(`Вы получили ${points} опыта!`);
    }

    function checkLevelUp() {
        const requiredXP = gameState.level * 100;
        if (gameState.experience >= requiredXP) {
            gameState.level++;
            gameState.experience -= requiredXP;
            updateStatsUI();
            appendEventLog(`Поздравляем! Вы достигли уровня ${gameState.level}!`);
        }
    }

    function updateInventoryUI() {
        inventoryList.innerHTML = '';
        gameState.inventory.forEach(item => {
            const li = document.createElement('li');
            li.textContent = item;
            inventoryList.appendChild(li);
        });
    }

    function handlePurchase(itemName) {
        const item = shopItems.find(i => i.name === itemName);
        if (item) {
            gameState.inventory.push(item.name);
            updateInventoryUI();
            appendEventLog(`Вы купили: ${item.name}`);
        } else {
            alert("Предмет не найден.");
        }
    }

    function visitShop() {
        shop.style.display = 'block';
        shopItemsList.innerHTML = '';
        gameState.selectedItem = null;
        shopItems.forEach(item => {
            const listItem = document.createElement('li');
            listItem.textContent = `${item.name} - Цена: ${item.price}`;
            listItem.onclick = () => selectItem(item, listItem);
            shopItemsList.appendChild(listItem);
        });
    }

    function selectItem(item, element) {
        if (gameState.selectedItem === item) {
            gameState.selectedItem = null;
            element.classList.remove('selected');
        } else {
            gameState.selectedItem = item;
            document.querySelectorAll('#shopItems li').forEach(li => li.classList.remove('selected'));
            element.classList.add('selected');
        }
    }

    function buyItem() {
        if (!gameState.selectedItem) {
            alert("Сначала выберите предмет для покупки!");
            return;
        }
        handlePurchase(gameState.selectedItem.name);
        shop.style.display = 'none';
    }

    // Функции для управления историей
    function updateHistoryUI(dialog, choices) {
        const li = document.createElement('li');
        li.innerHTML = `<strong>Новое событие:</strong> ${dialog}`;
        if (choices && choices.length > 0) {
            const choicesList = document.createElement('ul');
            choices.forEach(choice => {
                const choiceLi = document.createElement('li');
                choiceLi.textContent = `• ${choice}`;
                choicesList.appendChild(choiceLi);
            });
            li.appendChild(choicesList);
        }
        historyList.appendChild(li);
    }

    function toggleHistory() {
        if (historyDiv.style.display === 'none' || historyDiv.style.display === '') {
            historyDiv.style.display = 'block';
            historyToggle.textContent = "Скрыть Историю";
            populateHistoryUI();
        } else {
            historyDiv.style.display = 'none';
            historyToggle.textContent = "Показать Историю";
        }
    }

    function populateHistoryUI() {
        historyList.innerHTML = '';
        gameState.history.forEach((entry, index) => {
            const li = document.createElement('li');
            li.innerHTML = `<strong>Событие ${index + 1}:</strong> ${entry.dialog || 'Нет описания.'}`;
            if (entry.choices && entry.choices.length > 0) {
                const choicesList = document.createElement('ul');
                entry.choices.forEach(choice => {
                    const choiceLi = document.createElement('li');
                    choiceLi.textContent = `• ${choice}`;
                    choicesList.appendChild(choiceLi);
                });
                li.appendChild(choicesList);
            }
            historyList.appendChild(li);
        });
    }

    function clearHistoryUI() {
        historyList.innerHTML = '';
        historyDiv.style.display = 'none';
        historyToggle.textContent = "Показать Историю";
    }

    // Функция загрузки
    function showLoader(show) {
        loader.style.display = show ? 'block' : 'none';
    }

    // Улучшенный интерфейс: обновление статистики
    function updateStatsUI() {
        currentRace.textContent = capitalizeFirstLetter(gameState.playerRace);
        currentClass.textContent = capitalizeFirstLetter(gameState.playerClass);
        currentLevel.textContent = gameState.level;
        currentXP.textContent = gameState.experience;
    }

    // Вспомогательная функция для капитализации первой буквы
    function capitalizeFirstLetter(string) {
        return string.charAt(0).toUpperCase() + string.slice(1);
    }

});</script>
</body>
</html>