<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>TRPGシナリオ自動生成&共有</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
background: #f4f4f4;
padding: 20px;
max-width: 800px;
margin: auto;
}
h1, h2 {
text-align: center;
}
select, button, textarea {
width: 100%;
padding: 10px;
margin-top: 10px;
font-size: 1rem;
}
.box {
background: #fff;
padding: 15px;
border-radius: 8px;
margin-top: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.scenario {
background: #f9f9f9;
border-left: 5px solid #4CAF50;
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
position: relative;
}
.btns {
margin-top: 10px;
display: flex;
gap: 10px;
}
.copy, .save, .delete {
cursor: pointer;
border: none;
padding: 8px 12px;
border-radius: 4px;
}
.copy { background: #2196F3; color: white; }
.save { background: #4CAF50; color: white; }
.delete { background: #f44336; color: white; }
</style>
</head>
<body>
<h1>🎲 TRPGシナリオ自動生成サイト</h1>
<div class="box">
<label>ジャンル選択:</label>
<select id="genre">
<option value="fantasy">ファンタジー</option>
<option value="horror">ホラー</option>
<option value="scifi">SF</option>
</select>
<button onclick="generateScenario()">📜 シナリオを生成する</button>
</div>
<div id="scenarioBox" class="box"></div>
<h2>🗃 保存済みシナリオ</h2>
<div id="savedScenarios" class="box"></div>
<script>
const data = {
fantasy: {
title: ["封印の迷宮", "聖騎士の試練", "魔王復活の予兆", "失われた王国"],
world: ["中世の王国", "古代の神殿", "天空都市", "エルフの森"],
incident: ["魔法の暴走", "伝説の剣の発見", "精霊の異変", "竜の襲撃"],
npc: ["若き魔導士", "忠義の騎士", "隠者の賢者", "裏切り者の巫女"],
goal: ["真実を解明せよ", "封印を強化せよ", "儀式を阻止せよ", "遺跡の謎を解け"]
},
horror: {
title: ["呪われた村", "深夜の廃病院", "封印されたビデオ", "血塗られた儀式"],
world: ["雨の山奥", "閉鎖された病院", "地下の儀式場", "忘れ去られた洋館"],
incident: ["突然の失踪事件", "見えない何かの影", "不気味な手紙", "鏡の中の誰か"],
npc: ["精神を病んだ神父", "警察官の幽霊", "語らぬ老婆", "首のない少女"],
goal: ["脱出せよ", "謎を暴け", "呪いを解け", "儀式を止めろ"]
},
scifi: {
title: ["星間戦争の火種", "機械反乱の夜", "消えた宇宙船", "記憶を失った地球"],
world: ["宇宙コロニー", "月面都市", "異星の遺跡", "サイバーパンク都市"],
incident: ["AIの暴走", "重力異常", "通信断絶", "テレポート事故"],
npc: ["サイボーグ兵士", "記憶を失った博士", "企業スパイ", "異星の子供"],
goal: ["原因を究明せよ", "AIを停止せよ", "人類を救え", "真実を暴け"]
}
};
function generateScenario() {
const genre = document.getElementById("genre").value;
const g = data[genre];
const title = rand(g.title);
const world = rand(g.world);
const incident = rand(g.incident);
const npc = rand(g.npc);
const goal = rand(g.goal);
const scenarioText = `【タイトル】${title}\n【舞台】${world}\n【事件】${incident}\n【NPC】${npc}\n【目的】${goal}`;
const html = `
<div class="scenario">
<pre>${scenarioText}</pre>
<div class="btns">
<button class="copy" onclick="copyText(\`${scenarioText.replace(/`/g, '\\`')}\`)">📋 コピー</button>
<button class="save" onclick="saveScenario(\`${scenarioText.replace(/`/g, '\\`')}\`)">💾 保存</button>
</div>
</div>
`;
document.getElementById("scenarioBox").innerHTML = html;
}
function rand(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
function copyText(text) {
navigator.clipboard.writeText(text).then(() => {
alert("コピーしました!");
});
}
function saveScenario(text) {
let saved = JSON.parse(localStorage.getItem("trpgScenarios") || "[]");
saved.push(text);
localStorage.setItem("trpgScenarios", JSON.stringify(saved));
alert("保存しました!");
showSaved();
}
function deleteScenario(index) {
let saved = JSON.parse(localStorage.getItem("trpgScenarios") || "[]");
saved.splice(index, 1);
localStorage.setItem("trpgScenarios", JSON.stringify(saved));
showSaved();
}
function showSaved() {
const box = document.getElementById("savedScenarios");
const saved = JSON.parse(localStorage.getItem("trpgScenarios") || "[]");
if (saved.length === 0) {
box.innerHTML = "<p>保存されているシナリオはありません。</p>";
return;
}
box.innerHTML = saved.map((s, i) => `
<div class="scenario">
<pre>${s}</pre>
<div class="btns">
<button class="copy" onclick="copyText(\`${s.replace(/`/g, '\\`')}\`)">📋 コピー</button>
<button class="delete" onclick="deleteScenario(${i})">🗑 削除</button>
</div>
</div>
`).join("");
}
// 初回ロード
showSaved();
</script>
</body>
</html>