]> Stephen's Gitweb - donsol-js.git/commitdiff
Added old files master
authorneauoire <aliceffekt@gmail.com>
Thu, 16 Apr 2020 10:53:23 +0000 (19:53 +0900)
committerneauoire <aliceffekt@gmail.com>
Thu, 16 Apr 2020 10:53:23 +0000 (19:53 +0900)
86 files changed:
icon.icns [new file with mode: 0644]
icon.ico [new file with mode: 0644]
main.js [new file with mode: 0644]
package.json [new file with mode: 0644]
sources/index.html [new file with mode: 0644]
sources/links/fonts.css [new file with mode: 0644]
sources/links/main.css [new file with mode: 0644]
sources/links/reset.css [new file with mode: 0644]
sources/links/theme.css [new file with mode: 0644]
sources/media/audio/effect/click1.ogg [new file with mode: 0644]
sources/media/audio/effect/click2.ogg [new file with mode: 0644]
sources/media/audio/effect/click3.ogg [new file with mode: 0644]
sources/media/audio/effect/click4.ogg [new file with mode: 0644]
sources/media/audio/effect/denied.ogg [new file with mode: 0644]
sources/media/audio/effect/done.ogg [new file with mode: 0644]
sources/media/audio/effect/flip.ogg [new file with mode: 0644]
sources/media/clove/10.svg [new file with mode: 0644]
sources/media/clove/11.svg [new file with mode: 0644]
sources/media/clove/13.svg [new file with mode: 0644]
sources/media/clove/15.svg [new file with mode: 0644]
sources/media/clove/17.svg [new file with mode: 0644]
sources/media/clove/2.svg [new file with mode: 0644]
sources/media/clove/3.svg [new file with mode: 0644]
sources/media/clove/4.svg [new file with mode: 0644]
sources/media/clove/5.svg [new file with mode: 0644]
sources/media/clove/6.svg [new file with mode: 0644]
sources/media/clove/7.svg [new file with mode: 0644]
sources/media/clove/8.svg [new file with mode: 0644]
sources/media/clove/9.svg [new file with mode: 0644]
sources/media/diamond/10.svg [new file with mode: 0644]
sources/media/diamond/11.svg [new file with mode: 0644]
sources/media/diamond/2.svg [new file with mode: 0644]
sources/media/diamond/3.svg [new file with mode: 0644]
sources/media/diamond/4.svg [new file with mode: 0644]
sources/media/diamond/5.svg [new file with mode: 0644]
sources/media/diamond/6.svg [new file with mode: 0644]
sources/media/diamond/7.svg [new file with mode: 0644]
sources/media/diamond/8.svg [new file with mode: 0644]
sources/media/diamond/9.svg [new file with mode: 0644]
sources/media/fonts/input_mono_medium.ttf [new file with mode: 0644]
sources/media/fonts/input_mono_regular.ttf [new file with mode: 0644]
sources/media/heart/10.svg [new file with mode: 0644]
sources/media/heart/11.svg [new file with mode: 0644]
sources/media/heart/2.svg [new file with mode: 0644]
sources/media/heart/3.svg [new file with mode: 0644]
sources/media/heart/4.svg [new file with mode: 0644]
sources/media/heart/5.svg [new file with mode: 0644]
sources/media/heart/6.svg [new file with mode: 0644]
sources/media/heart/7.svg [new file with mode: 0644]
sources/media/heart/8.svg [new file with mode: 0644]
sources/media/heart/9.svg [new file with mode: 0644]
sources/media/icon.finder [new file with mode: 0644]
sources/media/icon.svg [new file with mode: 0644]
sources/media/icon180x180.png [new file with mode: 0644]
sources/media/joker/21.svg [new file with mode: 0644]
sources/media/spade/10.svg [new file with mode: 0644]
sources/media/spade/11.svg [new file with mode: 0644]
sources/media/spade/13.svg [new file with mode: 0644]
sources/media/spade/15.svg [new file with mode: 0644]
sources/media/spade/17.svg [new file with mode: 0644]
sources/media/spade/2.svg [new file with mode: 0644]
sources/media/spade/3.svg [new file with mode: 0644]
sources/media/spade/4.svg [new file with mode: 0644]
sources/media/spade/5.svg [new file with mode: 0644]
sources/media/spade/6.svg [new file with mode: 0644]
sources/media/spade/7.svg [new file with mode: 0644]
sources/media/spade/8.svg [new file with mode: 0644]
sources/media/spade/9.svg [new file with mode: 0644]
sources/scripts/board.js [new file with mode: 0644]
sources/scripts/card.js [new file with mode: 0644]
sources/scripts/card.monster.js [new file with mode: 0644]
sources/scripts/card.potion.js [new file with mode: 0644]
sources/scripts/card.shield.js [new file with mode: 0644]
sources/scripts/deck.js [new file with mode: 0644]
sources/scripts/donsol.js [new file with mode: 0644]
sources/scripts/gage.health.js [new file with mode: 0644]
sources/scripts/gage.js [new file with mode: 0644]
sources/scripts/gage.progress.js [new file with mode: 0644]
sources/scripts/gage.shield.js [new file with mode: 0644]
sources/scripts/icon.js [new file with mode: 0644]
sources/scripts/lib/controller.js [new file with mode: 0644]
sources/scripts/lib/theme.js [new file with mode: 0644]
sources/scripts/player.js [new file with mode: 0644]
sources/scripts/speaker.js [new file with mode: 0644]
sources/scripts/timeline.js [new file with mode: 0644]
sources/scripts/walkthrough.js [new file with mode: 0644]

diff --git a/icon.icns b/icon.icns
new file mode 100644 (file)
index 0000000..ea8b11c
Binary files /dev/null and b/icon.icns differ
diff --git a/icon.ico b/icon.ico
new file mode 100644 (file)
index 0000000..d6ceaa3
Binary files /dev/null and b/icon.ico differ
diff --git a/main.js b/main.js
new file mode 100644 (file)
index 0000000..44febaf
--- /dev/null
+++ b/main.js
@@ -0,0 +1,76 @@
+const { app, BrowserWindow, webFrame, Menu, dialog } = require('electron')
+const path = require('path')
+const url = require('url')
+const shell = require('electron').shell
+
+let isShown = true
+
+app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required')
+
+app.on('ready', () => {
+  app.win = new BrowserWindow({
+    width: 860,
+    height: 420,
+    minWidth: 860,
+    minHeight: 420,
+    backgroundColor: '#000',
+    icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
+    resizable: true,
+    frame: process.platform !== 'darwin',
+    skipTaskbar: process.platform === 'darwin',
+    autoHideMenuBar: process.platform === 'darwin',
+    webPreferences: { zoomFactor: 1.0, nodeIntegration: true, backgroundThrottling: false }
+  })
+
+  app.win.loadURL(`file://${__dirname}/sources/index.html`)
+  // app.inspect();
+
+  app.win.on('closed', () => {
+    win = null
+    app.quit()
+  })
+
+  app.win.on('hide', function () {
+    isShown = false
+  })
+
+  app.win.on('show', function () {
+    isShown = true
+  })
+
+  app.on('window-all-closed', () => {
+    app.quit()
+  })
+
+  app.on('activate', () => {
+    if (app.win === null) {
+      createWindow()
+    } else {
+      app.win.show()
+    }
+  })
+})
+
+app.inspect = function () {
+  app.win.toggleDevTools()
+}
+
+app.toggle_fullscreen = function () {
+  app.win.setFullScreen(!app.win.isFullScreen())
+}
+
+app.toggle_visible = function () {
+  if (process.platform == 'win32') {
+    if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() }
+  } else {
+    if (isShown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() }
+  }
+}
+
+app.inject_menu = function (menu) {
+  try {
+    Menu.setApplicationMenu(Menu.buildFromTemplate(menu))
+  } catch (err) {
+    console.warn('Cannot inject menu.')
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644 (file)
index 0000000..9b54b72
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "name": "Donsol",
+  "version": "0.1.0",
+  "main": "main.js",
+  "scripts": {
+    "start": "electron .",
+    "clean": "rm -r ~/Desktop/Donsol-darwin-x64/ ; rm -r ~/Desktop/Donsol-linux-x64/ ; rm -r ~/Desktop/Donsol-win32-x64/ ; rm -r ~/Desktop/Donsol-linux-armv7l/ ; echo 'cleaned build location'",
+    "build_osx": "electron-packager . Donsol --platform=darwin --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.icns ; echo 'Built for OSX'",
+    "build_linux": "electron-packager . Donsol --platform=linux  --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for LINUX'",
+    "build_win": "electron-packager . Donsol --platform=win32  --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for WIN'",
+    "build_pi": "electron-packager . Donsol --platform=linux  --arch=armv7l --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for PI'",
+    "build": "npm run clean ; npm run build_osx ; npm run build_linux ; npm run build_win",
+    "push_osx": "~/butler push ~/Desktop/Donsol-darwin-x64/ hundredrabbits/donsol:osx-64",
+    "push_linux": "~/butler push ~/Desktop/Donsol-linux-x64/ hundredrabbits/donsol:linux-64",
+    "push_win": "~/butler push ~/Desktop/Donsol-win32-x64/ hundredrabbits/donsol:windows-64",
+    "push_pi": "~/butler push ~/Desktop/Donsol-linux-armv7l/ hundredrabbits/donsol:linux-pi",
+    "push_status": "~/butler status hundredrabbits/donsol",
+    "push_theme": "~/butler push ~/Github/HundredRabbits/Themes/themes/ hundredrabbits/donsol:themes",
+    "push": "npm run build ; npm run push_theme ; npm run push_osx ; npm run push_linux ; npm run push_win ; npm run clean ; npm run push_status"
+  },
+  "devDependencies": {
+    "electron": "^7.1.12",
+    "electron-packager": "^14.2.1"
+  }
+}
diff --git a/sources/index.html b/sources/index.html
new file mode 100644 (file)
index 0000000..9560a1e
--- /dev/null
@@ -0,0 +1,85 @@
+<html>
+  <head>    
+    <script type="text/javascript" src="scripts/lib/theme.js"></script>
+    <script type="text/javascript" src="scripts/lib/controller.js"></script>
+
+    <script type="text/javascript" src="scripts/card.js"></script>
+    <script type="text/javascript" src="scripts/card.potion.js"></script>
+    <script type="text/javascript" src="scripts/card.monster.js"></script>
+    <script type="text/javascript" src="scripts/card.shield.js"></script>
+    
+    <script type="text/javascript" src="scripts/deck.js"></script>
+    <script type="text/javascript" src="scripts/icon.js"></script>
+    <script type="text/javascript" src="scripts/gage.js"></script>
+    <script type="text/javascript" src="scripts/gage.shield.js"></script>
+    <script type="text/javascript" src="scripts/gage.health.js"></script>
+    <script type="text/javascript" src="scripts/gage.progress.js"></script>
+    
+    <script type="text/javascript" src="scripts/board.js"></script>
+    <script type="text/javascript" src="scripts/donsol.js"></script>
+    <script type="text/javascript" src="scripts/player.js"></script>
+    <script type="text/javascript" src="scripts/timeline.js"></script>
+    <script type="text/javascript" src="scripts/speaker.js"></script>
+
+    <script type="text/javascript" src="scripts/walkthrough.js"></script>
+    
+    <link rel="stylesheet" type="text/css" href="links/reset.css"/>
+    <link rel="stylesheet" type="text/css" href="links/fonts.css"/>
+    <link rel="stylesheet" type="text/css" href="links/main.css"/>
+    <link rel="stylesheet" type="text/css" href="links/theme.css"/>
+    
+    <link rel="apple-touch-icon" sizes="180x180" href="media/icon180x180.png">
+    
+    <title>Donsol</title>
+  </head>
+  <body>
+    <div id='wrapper'>
+      <div id='player'></div>
+      <div id='board'></div>
+      <div id='table'>
+        <card><span class='shortcut'>1</span></card>
+        <card><span class='shortcut'>2</span></card>
+        <card><span class='shortcut'>3</span></card>
+        <card><span class='shortcut'>4</span></card>
+      </div>
+    </div>
+    <script type="text/javascript">
+      const {dialog,app} = require('electron').remote;
+      const fs = require('fs');
+
+      let donsol = new Donsol();
+
+      donsol.controller.add("default","*","About",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Donsol'); },"CmdOrCtrl+,");
+      donsol.controller.add("default","*","Fullscreen",() => { app.toggle_fullscreen(); },"CmdOrCtrl+Enter");
+      donsol.controller.add("default","*","Hide",() => { app.toggle_visible(); },"CmdOrCtrl+H");
+      donsol.controller.add("default","*","Inspect",() => { app.inspect(); },"CmdOrCtrl+.");
+      donsol.controller.add("default","*","Documentation",() => { donsol.controller.docs(); },"CmdOrCtrl+Esc");
+      donsol.controller.add("default","*","Reset",() => { donsol.theme.reset(); },"CmdOrCtrl+Backspace");
+      donsol.controller.add("default","*","Quit",() => { app.exit(); },"CmdOrCtrl+Q");
+
+      donsol.controller.add("default","File","New",() => { donsol.new_game(); },"CmdOrCtrl+N");
+
+      donsol.controller.add("default","Difficulty","Easy",() => { donsol.set_difficulty(0); },"CmdOrCtrl+1");
+      donsol.controller.add("default","Difficulty","Normal",() => { donsol.set_difficulty(1); },"CmdOrCtrl+2");
+      donsol.controller.add("default","Difficulty","Hard",() => { donsol.set_difficulty(2); },"CmdOrCtrl+3");
+      donsol.controller.add("default","Difficulty","Expert",() => { donsol.set_difficulty(3); },"CmdOrCtrl+4");
+
+      donsol.controller.add("default","Cards","Pick 1",() => { donsol.board.room[0].touch(); },"1");
+      donsol.controller.add("default","Cards","Pick 2",() => { donsol.board.room[1].touch(); },"2");
+      donsol.controller.add("default","Cards","Pick 3",() => { donsol.board.room[2].touch(); },"3");
+      donsol.controller.add("default","Cards","Pick 4",() => { donsol.board.room[3].touch(); },"4");
+
+      donsol.controller.add("default","Room","Escape",() => { donsol.skip(); },"Space");
+      donsol.controller.add("default","Room","Restart",() => { donsol.new_game(); },"Esc");
+
+      donsol.controller.add("default","Theme","Open Theme",() => { donsol.theme.open(); },"CmdOrCtrl+Shift+o")
+      donsol.controller.add("default","Theme","Reset Theme",() => { donsol.theme.reset(); },"CmdOrCtrl+Shift+Backspace")
+      donsol.controller.add("default","Theme","Download Themes..",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes'); })
+
+      donsol.controller.commit();
+
+      donsol.install(document.body)
+      donsol.start();
+    </script>
+  </body>
+</html>
diff --git a/sources/links/fonts.css b/sources/links/fonts.css
new file mode 100644 (file)
index 0000000..be688de
--- /dev/null
@@ -0,0 +1,15 @@
+/* Input */
+
+@font-face {
+    font-family: 'input_mono_regular';
+    src: url('../media/fonts/input_mono_regular.ttf') format('truetype');
+    font-weight: normal;
+    font-style: normal;
+}
+
+@font-face {
+    font-family: 'input_mono_medium';
+    src: url('../media/fonts/input_mono_medium.ttf') format('truetype');
+    font-weight: normal;
+    font-style: normal;
+}
\ No newline at end of file
diff --git a/sources/links/main.css b/sources/links/main.css
new file mode 100644 (file)
index 0000000..b127901
--- /dev/null
@@ -0,0 +1,37 @@
+body { background:black; font-family: 'input_mono_regular',monospace; min-width:750px; overflow-y: hidden; user-select: none; cursor: default; -webkit-app-region: drag; padding:30px;}
+
+#wrapper { display: block;max-width: 900px; height: calc(25vw * 1.25 + 90px);max-height:400px;margin:0px auto;position: relative;width:100%; -webkit-app-region: drag;}
+
+#player { display: block; font-size:12px; height:30px; line-height:20px; max-width:890px; -webkit-user-select: none;-webkit-app-region: drag; position: fixed; bottom:30px; width:calc(100% - 60px);}
+#player > * { vertical-align: top }
+#player .gage { width: 120px;display: block;height:30px;position: relative; float:right; margin-left:2px;width:70px; padding-right: 50px; text-align: right}
+#player .gage .value { display: inline-block;line-height: 20px;font-family: 'input_mono_medium';padding-left: 5px;}
+#player .gage .event { display: inline-block;position: absolute;top: -20px;left: 0px; transition: all 250ms; opacity: 0; margin-left:5px; display: none}
+#player .gage .progress { display: block;width: 40px;position: absolute; top:7px;overflow: hidden;height: 4px;border-radius: 20px;right:0px;}
+#player .gage .progress .bar{ height:5px; display:block !important; transition: width 300ms}
+#player a.escape { -webkit-app-region: no-drag;padding: 0px 8px;border-radius: 20px;display: inline-block;margin-right: 10px;line-height: 20px; border:2px solid white; margin-top:0px; color:white;}
+#player a.escape:hover { cursor: pointer; }
+#player div#timeline { display: inline-block;color:white; transition: opacity 250ms; opacity: 0 }
+#player div#timeline b { font-family: 'input_mono_medium',monospace; }
+
+#player.locked a.escape { display:none;}
+
+#board, #table { display:block; position: absolute; width: calc(100% + 15px)}
+#board card, #table card { display: inline-block !important;height: calc(25vw * 1.25);max-height:300px;max-width:200px;width: calc(25% - 15px);margin-right: 15px;border-radius: 7px; position:relative; overflow:hidden;min-height: 300px;}
+#board card { top:10px; opacity:0.01; z-index:900; transition: opacity 250ms, top 150ms }
+#board card:hover { cursor:pointer; top:5px !important;}
+#board card .face { display:block;width: 100%;height: calc(100% - 5px);border-radius: 7px;}
+#board card .face img { width:100%; position: absolute;bottom:0px; }
+#board card .face .value   { display: block;position: absolute;width: 30px;height: 30px;left: 15px;top: 60px;font-size: 12px;text-align: center;}
+#board card .face .graphic svg { display: block;position: absolute;left: calc(50% - 100px);bottom: calc(50% - 150px);}
+#board card .face .icon    { display: block;position: absolute;width: 30px;height: 30px;left: 15px;top: 15px;font-size: 11px; z-index:900;}
+#board card .face .name    { display: block;position: absolute;bottom: 20px;text-align: center;font-size: 11px;width: 100%;}
+
+#table card { }
+#table card .shortcut { position:absolute; right:20px; bottom:15px; color:#555;}
+
+#board card:nth-child(2), #table card:nth-child(2) { position:absolute; left:25%;}
+#board card:nth-child(3), #table card:nth-child(3) { position:absolute; left:50%;}
+#board card:nth-child(4), #table card:nth-child(4) { position:absolute; left:75%;}
+
+#difficulty:hover { text-decoration: underline; cursor: pointer; }
\ No newline at end of file
diff --git a/sources/links/reset.css b/sources/links/reset.css
new file mode 100644 (file)
index 0000000..9f57584
--- /dev/null
@@ -0,0 +1 @@
+* { margin:0;padding:0;border:0;outline:0;text-decoration:none;font-weight:inherit;font-style:inherit;color:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;list-style:none;border-collapse:collapse;border-spacing:0; -webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}
\ No newline at end of file
diff --git a/sources/links/theme.css b/sources/links/theme.css
new file mode 100644 (file)
index 0000000..9430a8b
--- /dev/null
@@ -0,0 +1,54 @@
+body { background-color:var(--background) !important };
+.fh { color:var(--f_high) !important; stroke:var(--f_high) !important };
+.fm { color:var(--f_med) !important ; stroke:var(--f_med) !important };
+.fl { color:var(--f_low) !important ; stroke:var(--f_low) !important };
+.f_inv { color:var(--f_inv) !important ; stroke:var(--f_inv) !important };
+.bh { background-color:var(--b_high) !important; fill:var(--b_high) !important };
+.bm { background-color:var(--b_med) !important ; fill:var(--b_med) !important };
+.bl { background-color:var(--b_low) !important ; fill:var(--b_low) !important };
+.b_inv { background-color:var(--b_inv) !important ; fill:var(--b_inv) !important };
+.b { background-color:var(--background) !important; }
+
+/* Donsol Theme Scheme */
+
+/* Red */
+svg .fill_red { fill:var(--f_med) !important }
+#board card.heart .face { color:var(--f_med) !important;}
+#board card.diamond .face { color:var(--f_med) !important;}
+
+/* Black */
+svg .fill_black { fill:var(--f_high) !important }
+#board card.clove .face { color:var(--f_high) !important;}
+#board card.spade .face { color:var(--f_high) !important;}
+#board card.joker .face { color:var(--f_high) !important;}
+svg .stroke_black { stroke:var(--f_high) !important }
+
+/* Grey */
+svg .stroke_grey { stroke:var(--f_low) !important }
+svg .fill_grey { opacity:0.25; fill:var(--f_low) !important }
+
+/* White */
+svg .fill_white { fill:var(--b_high) !important }
+#player a.escape { border:2px solid var(--b_high) !important; color: var(--b_high); }
+#player a.escape:hover { background-color:var(--b_high) !important; color:var(--background); }
+#board card .face { background-color:var(--b_high)}
+.card_11 .face .name,.card_13 .face .name,.card_15 .face .name,.card_17 .face .name { color:var(--b_high);}
+#player .gage { color:var(--b_high) }
+svg .stroke_white { stroke:var(--b_high) !important }
+
+/* Dark Grey */
+#table card { background-color:var(--b_low) !important}
+#player .gage .value .unit { color:var(--b_low) !important}
+#player .gage .progress { background-color:var(--b_low) !important }
+
+/* EXTRAS*/
+#player .gage.health .progress .bar { background-color:var(--b_inv) !important  }
+#player .gage.shield .progress .bar { background-color:var(--b_high) !important  }
+#player .gage.experience .progress .bar { background-color:var(--b_med) !important  }
+#table card .shortcut { color:var(--background) !important}
+#difficulty { color:var(--f_high) !important  }
+
+/* DEATH*/
+
+#player.death a.escape { border-color:var(--b_inv) !important;  }
+#player.death a.escape:hover { background-color:var(--b_inv) !important;  }
\ No newline at end of file
diff --git a/sources/media/audio/effect/click1.ogg b/sources/media/audio/effect/click1.ogg
new file mode 100644 (file)
index 0000000..76c0125
Binary files /dev/null and b/sources/media/audio/effect/click1.ogg differ
diff --git a/sources/media/audio/effect/click2.ogg b/sources/media/audio/effect/click2.ogg
new file mode 100644 (file)
index 0000000..8a9a061
Binary files /dev/null and b/sources/media/audio/effect/click2.ogg differ
diff --git a/sources/media/audio/effect/click3.ogg b/sources/media/audio/effect/click3.ogg
new file mode 100644 (file)
index 0000000..d0de84b
Binary files /dev/null and b/sources/media/audio/effect/click3.ogg differ
diff --git a/sources/media/audio/effect/click4.ogg b/sources/media/audio/effect/click4.ogg
new file mode 100644 (file)
index 0000000..19669ae
Binary files /dev/null and b/sources/media/audio/effect/click4.ogg differ
diff --git a/sources/media/audio/effect/denied.ogg b/sources/media/audio/effect/denied.ogg
new file mode 100644 (file)
index 0000000..00c1a17
Binary files /dev/null and b/sources/media/audio/effect/denied.ogg differ
diff --git a/sources/media/audio/effect/done.ogg b/sources/media/audio/effect/done.ogg
new file mode 100644 (file)
index 0000000..d116c94
Binary files /dev/null and b/sources/media/audio/effect/done.ogg differ
diff --git a/sources/media/audio/effect/flip.ogg b/sources/media/audio/effect/flip.ogg
new file mode 100644 (file)
index 0000000..ddd33ae
Binary files /dev/null and b/sources/media/audio/effect/flip.ogg differ
diff --git a/sources/media/clove/10.svg b/sources/media/clove/10.svg
new file mode 100644 (file)
index 0000000..4eee6b7
--- /dev/null
@@ -0,0 +1,3 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="100" cy="175" r="50" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/11.svg b/sources/media/clove/11.svg
new file mode 100644 (file)
index 0000000..572d55d
--- /dev/null
@@ -0,0 +1,25 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  
+  <circle cx="100" cy="125" r="70" class="fill_black"/>
+  <!-- Head -->
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,180 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_black"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/13.svg b/sources/media/clove/13.svg
new file mode 100644 (file)
index 0000000..f5359bb
--- /dev/null
@@ -0,0 +1,25 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="125" cy="125" r="60" class="fill_black"/>
+  <circle cx="75" cy="125" r="60" class="fill_black"/>
+  <!-- Head -->
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <circle cx="100" cy="185" r="3" class="fill_black" stroke-width="0px"/>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/15.svg b/sources/media/clove/15.svg
new file mode 100644 (file)
index 0000000..c333ba2
--- /dev/null
@@ -0,0 +1,26 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="125" cy="125" r="50" class="fill_black"/>
+  <circle cx="75" cy="125" r="50" class="fill_black"/>
+  <circle cx="100" cy="100" r="50" class="fill_black"/>
+  <!-- Head -->
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,185 a5,5 0 0,1 10,0" stroke-width="0px" class="fill_black"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/17.svg b/sources/media/clove/17.svg
new file mode 100644 (file)
index 0000000..fd44480
--- /dev/null
@@ -0,0 +1,26 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="125" cy="125" r="40" class="fill_black"/>
+  <circle cx="75" cy="125" r="40" class="fill_black"/>
+  <circle cx="100" cy="100" r="40" class="fill_black"/>
+  <!-- Head -->
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,185 a5,5 0 0,1 10,0" stroke-width="2px" class="stroke_black" stroke-linecap="round" fill="none"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/2.svg b/sources/media/clove/2.svg
new file mode 100644 (file)
index 0000000..924050c
--- /dev/null
@@ -0,0 +1,4 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="100" cy="200" r="25" class="fill_black"/>
+  <circle cx="100" cy="150" r="25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/3.svg b/sources/media/clove/3.svg
new file mode 100644 (file)
index 0000000..b7f123a
--- /dev/null
@@ -0,0 +1,5 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="100" cy="175" r="25" class="fill_black"/>
+  <circle cx="150" cy="175" r="25" class="fill_black"/>
+  <circle cx="50" cy="175" r="25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/4.svg b/sources/media/clove/4.svg
new file mode 100644 (file)
index 0000000..c9ae445
--- /dev/null
@@ -0,0 +1,6 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="75" cy="200" r="25" class="fill_black"/>
+  <circle cx="125" cy="200" r="25" class="fill_black"/>
+  <circle cx="75" cy="150" r="25" class="fill_black"/>
+  <circle cx="125" cy="150" r="25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/5.svg b/sources/media/clove/5.svg
new file mode 100644 (file)
index 0000000..245f266
--- /dev/null
@@ -0,0 +1,7 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="50" cy="175" r="25" class="fill_black"/>
+  <circle cx="100" cy="175" r="25" class="fill_black"/>
+  <circle cx="150" cy="175" r="25" class="fill_black"/>
+  <circle cx="100" cy="125" r="25" class="fill_black"/>
+  <circle cx="100" cy="225" r="25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/clove/6.svg b/sources/media/clove/6.svg
new file mode 100644 (file)
index 0000000..60a0c64
--- /dev/null
@@ -0,0 +1,8 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="100" cy="200" r="25" class="fill_black"/>
+  <circle cx="150" cy="200" r="25" class="fill_black"/>
+  <circle cx="50" cy="200" r="25" class="fill_black"/>
+  <circle cx="100" cy="150" r="25" class="fill_black"/>
+  <circle cx="150" cy="150" r="25" class="fill_black"/>
+  <circle cx="50" cy="150" r="25" class="fill_black"/>
+</svg>
diff --git a/sources/media/clove/7.svg b/sources/media/clove/7.svg
new file mode 100644 (file)
index 0000000..dd0518e
--- /dev/null
@@ -0,0 +1,9 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="150" cy="125" r="25" class="fill_black"/>
+  <circle cx="50"  cy="125" r="25" class="fill_black"/>
+  <circle cx="100" cy="175" r="25" class="fill_black"/>
+  <circle cx="150" cy="175" r="25" class="fill_black"/>
+  <circle cx="50"  cy="175" r="25" class="fill_black"/>
+  <circle cx="150" cy="225" r="25" class="fill_black"/>
+  <circle cx="50"  cy="225" r="25" class="fill_black"/>
+</svg>
diff --git a/sources/media/clove/8.svg b/sources/media/clove/8.svg
new file mode 100644 (file)
index 0000000..5cdd9be
--- /dev/null
@@ -0,0 +1,10 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="100" cy="125" r="25" class="fill_black"/>
+  <circle cx="150" cy="125" r="25" class="fill_black"/>
+  <circle cx="50"  cy="125" r="25" class="fill_black"/>
+  <circle cx="150" cy="175" r="25" class="fill_black"/>
+  <circle cx="50"  cy="175" r="25" class="fill_black"/>
+  <circle cx="100" cy="225" r="25" class="fill_black"/>
+  <circle cx="150" cy="225" r="25" class="fill_black"/>
+  <circle cx="50"  cy="225" r="25" class="fill_black"/>
+</svg>
diff --git a/sources/media/clove/9.svg b/sources/media/clove/9.svg
new file mode 100644 (file)
index 0000000..5521485
--- /dev/null
@@ -0,0 +1,11 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <circle cx="100" cy="125" r="25" class="fill_black"/>
+  <circle cx="150" cy="125" r="25" class="fill_black"/>
+  <circle cx="50"  cy="125" r="25" class="fill_black"/>
+  <circle cx="100" cy="175" r="25" class="fill_black"/>
+  <circle cx="150" cy="175" r="25" class="fill_black"/>
+  <circle cx="50"  cy="175" r="25" class="fill_black"/>
+  <circle cx="100" cy="225" r="25" class="fill_black"/>
+  <circle cx="150" cy="225" r="25" class="fill_black"/>
+  <circle cx="50"  cy="225" r="25" class="fill_black"/>
+</svg>
diff --git a/sources/media/diamond/10.svg b/sources/media/diamond/10.svg
new file mode 100644 (file)
index 0000000..8bd13b5
--- /dev/null
@@ -0,0 +1,3 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M50,175 l50,50 l50,-50 l-50,-50" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/11.svg b/sources/media/diamond/11.svg
new file mode 100644 (file)
index 0000000..b3ad935
--- /dev/null
@@ -0,0 +1,28 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <!-- Head -->
+  <circle cx="125" cy="160" r="25" class="fill_red"/>
+  <circle cx="75" cy="160" r="25" class="fill_red"/>
+  <path d="M25,140 l75,75 l75,-75 l-75,-75" class="fill_red"/>
+  <path d="M25,175 l75,75 l75,-75 l-75,-75 l-75,75" fill="none" class="stroke_white" stroke-width="2px"/>
+  <circle cx="100" cy="160" r="25" class="fill_white"/>
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_red"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,180 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_black"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/2.svg b/sources/media/diamond/2.svg
new file mode 100644 (file)
index 0000000..4c3450b
--- /dev/null
@@ -0,0 +1,4 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,150 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,200 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/3.svg b/sources/media/diamond/3.svg
new file mode 100644 (file)
index 0000000..d3e6b3d
--- /dev/null
@@ -0,0 +1,5 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/4.svg b/sources/media/diamond/4.svg
new file mode 100644 (file)
index 0000000..43a6e6d
--- /dev/null
@@ -0,0 +1,6 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M50,150 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M100,150 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M50,200 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M100,200 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/5.svg b/sources/media/diamond/5.svg
new file mode 100644 (file)
index 0000000..178db49
--- /dev/null
@@ -0,0 +1,7 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/6.svg b/sources/media/diamond/6.svg
new file mode 100644 (file)
index 0000000..5115652
--- /dev/null
@@ -0,0 +1,8 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,200 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,200 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,200 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,150 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,150 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,150 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/7.svg b/sources/media/diamond/7.svg
new file mode 100644 (file)
index 0000000..4c8f6f9
--- /dev/null
@@ -0,0 +1,9 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M25,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/8.svg b/sources/media/diamond/8.svg
new file mode 100644 (file)
index 0000000..ff8b120
--- /dev/null
@@ -0,0 +1,10 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/diamond/9.svg b/sources/media/diamond/9.svg
new file mode 100644 (file)
index 0000000..f152698
--- /dev/null
@@ -0,0 +1,11 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,125 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,175 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M75,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M25,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+  <path d="M125,225 l25,25 l25,-25 l-25,-25" class="fill_red"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/fonts/input_mono_medium.ttf b/sources/media/fonts/input_mono_medium.ttf
new file mode 100644 (file)
index 0000000..0d488bf
Binary files /dev/null and b/sources/media/fonts/input_mono_medium.ttf differ
diff --git a/sources/media/fonts/input_mono_regular.ttf b/sources/media/fonts/input_mono_regular.ttf
new file mode 100644 (file)
index 0000000..c19c287
Binary files /dev/null and b/sources/media/fonts/input_mono_regular.ttf differ
diff --git a/sources/media/heart/10.svg b/sources/media/heart/10.svg
new file mode 100644 (file)
index 0000000..a92edbf
--- /dev/null
@@ -0,0 +1,3 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M50,175 a25,25 0 0,1 100,0 l-50,50 l-50,-50" class="fill_red"></path>
+</svg>
diff --git a/sources/media/heart/11.svg b/sources/media/heart/11.svg
new file mode 100644 (file)
index 0000000..1f9c63c
--- /dev/null
@@ -0,0 +1,25 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <!-- Head -->
+  <circle cx="125" cy="125" r="50" class="fill_red"/>
+  <circle cx="75" cy="125" r="50" class="fill_red"/>
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_red"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 l-37.5,-37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,180 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_black"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/heart/2.svg b/sources/media/heart/2.svg
new file mode 100644 (file)
index 0000000..8251e06
--- /dev/null
@@ -0,0 +1,4 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,200 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,150 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
diff --git a/sources/media/heart/3.svg b/sources/media/heart/3.svg
new file mode 100644 (file)
index 0000000..94b07d4
--- /dev/null
@@ -0,0 +1,5 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
diff --git a/sources/media/heart/4.svg b/sources/media/heart/4.svg
new file mode 100644 (file)
index 0000000..4630cd4
--- /dev/null
@@ -0,0 +1,6 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,200 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M50,200 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M100,150 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M50,150 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
diff --git a/sources/media/heart/5.svg b/sources/media/heart/5.svg
new file mode 100644 (file)
index 0000000..6cea6af
--- /dev/null
@@ -0,0 +1,7 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
diff --git a/sources/media/heart/6.svg b/sources/media/heart/6.svg
new file mode 100644 (file)
index 0000000..ee09a6b
--- /dev/null
@@ -0,0 +1,8 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,150 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,150 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,150 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,200 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,200 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,200 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
diff --git a/sources/media/heart/7.svg b/sources/media/heart/7.svg
new file mode 100644 (file)
index 0000000..21e7219
--- /dev/null
@@ -0,0 +1,9 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M125,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
diff --git a/sources/media/heart/8.svg b/sources/media/heart/8.svg
new file mode 100644 (file)
index 0000000..a9b8579
--- /dev/null
@@ -0,0 +1,10 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
\ No newline at end of file
diff --git a/sources/media/heart/9.svg b/sources/media/heart/9.svg
new file mode 100644 (file)
index 0000000..585af2e
--- /dev/null
@@ -0,0 +1,11 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,125 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,175 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M75,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M125,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+  <path d="M25,225 a15,15 0 0,1 50,0 l-25,25 l-25,-25" class="fill_red"></path>
+</svg>
diff --git a/sources/media/icon.finder b/sources/media/icon.finder
new file mode 100644 (file)
index 0000000..5bc12e7
--- /dev/null
@@ -0,0 +1,22 @@
+How to use this icon:
+
+Step 1: Copy the icon to the clipboard
+a) Click on this file from the Finder
+b) Choose 'Get Info' from the 'File' menu.
+c) In the info window that pops up, click on the icon
+d) Choose 'Copy' from the 'Edit' menu.
+e) Close the info window
+
+Step 2: Paste the icon to the desired item
+a) Go to the item in the Finder that you want a custom icon
+b) Click the item (file, folder, disk, etc) 
+b) Choose 'Get Info' from the 'File' menu.
+c) In the info window that pops up, click on the icon
+d) Choose 'Paste' from the 'Edit' menu.
+e) Close the info window
+
+Step 3: 
+Enjoy your newly customized icon!
+
+For more thorough directions, see Apple's website at:
+http://www.apple.com/support/mac101/customize/6/
diff --git a/sources/media/icon.svg b/sources/media/icon.svg
new file mode 100644 (file)
index 0000000..d888d0e
--- /dev/null
@@ -0,0 +1 @@
+<svg class="vector" width="300px" height="300px" xmlns="http://www.w3.org/2000/svg" baseProfile="full" version="1.1" style="width: 300px; height: 300px; stroke: rgb(0, 0, 0); stroke-width: 10px; fill: none; stroke-linecap: square;"><path d="M101,150 A48,48 0 0,0 53,198"></path><path d="M53,198 A-48,48 0 0,0 101,246"></path><path d="M101,246 A-49,-48 0 0,0 150,198"></path><path d="M150,198 A49,-48 0 0,0 101,150"></path><line x1="150" y1="198" x2="150" y2="246"></line><path d="M150,237 A10,9 0 0,1 140,246"></path><path d="M159,246 A9,-9 0 0,1 150,237"></path><line x1="159" y1="246" x2="140" y2="246"></line><path d="M150,198 A-48,-48 0 0,1 198,150"></path><path d="M198,150 A-48,48 0 0,1 246,198"></path><path d="M246,198 A48,48 0 0,1 198,246"></path><path d="M198,246 A48,-48 0 0,1 150,198"></path><path d="M101,111 A-49,-49 0 0,1 150,62"></path><path d="M150,62 A-48,49 0 0,1 198,111"></path><path d="M198,111 A48,48 0 0,1 150,159"></path><path d="M150,159 A49,-48 0 0,1 101,111"></path></svg>
\ No newline at end of file
diff --git a/sources/media/icon180x180.png b/sources/media/icon180x180.png
new file mode 100644 (file)
index 0000000..80fdc22
Binary files /dev/null and b/sources/media/icon180x180.png differ
diff --git a/sources/media/joker/21.svg b/sources/media/joker/21.svg
new file mode 100644 (file)
index 0000000..4613569
--- /dev/null
@@ -0,0 +1,5 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M25,175 a100,120 0 0,0 150,0 a100,120 0 0,0 -150,0 " class="fill_red"></path>
+  <circle cx="100" cy="175" r="25" class="fill_white"/>
+  <circle cx="100" cy="175" r="15" class="fill_black"/>
+</svg>
diff --git a/sources/media/spade/10.svg b/sources/media/spade/10.svg
new file mode 100644 (file)
index 0000000..96e30de
--- /dev/null
@@ -0,0 +1,3 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,125 l-50,50 a50,50 0 0,1 50,50 a50,50 0 0,1 50,-50" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/11.svg b/sources/media/spade/11.svg
new file mode 100644 (file)
index 0000000..075b9f9
--- /dev/null
@@ -0,0 +1,24 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <!-- Head -->
+  <path d="M100,50 l-75,75 a15,15 0 1,0 75,50 a15,15 0 1,0 75,-50" class="fill_black"></path>
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,180 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_black"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/13.svg b/sources/media/spade/13.svg
new file mode 100644 (file)
index 0000000..c18853f
--- /dev/null
@@ -0,0 +1,24 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <!-- Head -->
+  <path d="M100,50 l-75,75 a15,15 0 1,0 75,50 a15,15 0 1,0 75,-50" class="fill_black"></path>
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <circle cx="100" cy="185" r="3" class="fill_black" stroke-width="0px"/>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/15.svg b/sources/media/spade/15.svg
new file mode 100644 (file)
index 0000000..195dfde
--- /dev/null
@@ -0,0 +1,24 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <!-- Head -->
+  <path d="M100,50 l-75,75 a15,15 0 1,0 75,50 a15,15 0 1,0 75,-50" class="fill_black"></path>
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,185 a5,5 0 0,1 10,0" stroke-width="0px" class="fill_black"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/17.svg b/sources/media/spade/17.svg
new file mode 100644 (file)
index 0000000..de40de6
--- /dev/null
@@ -0,0 +1,24 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <!-- Head -->
+  <path d="M100,50 l-75,75 a15,15 0 1,0 75,50 a15,15 0 1,0 75,-50" class="fill_black"></path>
+  <!-- Body -->
+  <path d="M20,310 l0,-50 a15,15 0 0,1 15,-15 l25,0 a25,25 0 0,0 25,-25 l0,-50 l30,0 l0,50 a25,25 0 0,0 25,25 l25,0 a15,15 0 0,1 15,15 l0,50" class="fill_black"></path>
+  <line x1="0" y1="210" x2="300" y2="210" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <line x1="0" y1="220" x2="300" y2="220" stroke-width="2px" class="stroke_white" stroke-linecap="round"/>
+  <path d="M95,220 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_white"></path>
+  <!-- Face -->
+  <path d="M62.5,155 a15,15 0 1,0 75,0 a37.5,37.5 0 0,1 -37.5,-37.5 a37.5,37.5 0 0,1 -37.5,37.5" class="fill_white"></path>
+  <!-- Eyes -->
+  <line x1="70" y1="160" x2="90" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <line x1="110" y1="160" x2="130" y2="160" stroke-width="2px" class="stroke_black" stroke-linecap="round"/>
+  <path d="M75,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <path d="M115,160 a5,5 0 1,0 10,0" stroke-width="2px" class="stroke_black fill_black" stroke-linecap="butt"></path>
+  <circle cx="90" cy="150" r="3" class="fill_grey"/>
+  <circle cx="110" cy="150" r="3" class="fill_grey"/>
+  <!-- nose -->
+  <path d="M95,170 a5,5 0 1,0 10,0" stroke-width="0px" class="fill_grey"></path>
+  <!-- mouth -->
+  <path d="M95,185 a5,5 0 0,1 10,0" stroke-width="2px" class="stroke_black" stroke-linecap="round" fill="none"></path>
+  <!-- dot -->
+  <circle cx="100" cy="100" r="5" class="fill_white"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/2.svg b/sources/media/spade/2.svg
new file mode 100644 (file)
index 0000000..a251e86
--- /dev/null
@@ -0,0 +1,4 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,175 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,125 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
diff --git a/sources/media/spade/3.svg b/sources/media/spade/3.svg
new file mode 100644 (file)
index 0000000..3dff615
--- /dev/null
@@ -0,0 +1,5 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
diff --git a/sources/media/spade/4.svg b/sources/media/spade/4.svg
new file mode 100644 (file)
index 0000000..0c95fad
--- /dev/null
@@ -0,0 +1,6 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M75,125 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M125,125 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M75,175 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M125,175 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
diff --git a/sources/media/spade/5.svg b/sources/media/spade/5.svg
new file mode 100644 (file)
index 0000000..9b3b57d
--- /dev/null
@@ -0,0 +1,7 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/6.svg b/sources/media/spade/6.svg
new file mode 100644 (file)
index 0000000..e0404b3
--- /dev/null
@@ -0,0 +1,8 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M50,175 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,175 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,175 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,125 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,125 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,125 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
diff --git a/sources/media/spade/7.svg b/sources/media/spade/7.svg
new file mode 100644 (file)
index 0000000..7a9f1bf
--- /dev/null
@@ -0,0 +1,9 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/8.svg b/sources/media/spade/8.svg
new file mode 100644 (file)
index 0000000..1b68e9c
--- /dev/null
@@ -0,0 +1,10 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/media/spade/9.svg b/sources/media/spade/9.svg
new file mode 100644 (file)
index 0000000..5adf324
--- /dev/null
@@ -0,0 +1,11 @@
+<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="200" height="300">
+  <path d="M100,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M100,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M50,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,200 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,150 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+  <path d="M150,100 l-25,25 a25,25 0 0,1 25,25 a25,25 0 0,1 25,-25" class="fill_black"/>
+</svg>
\ No newline at end of file
diff --git a/sources/scripts/board.js b/sources/scripts/board.js
new file mode 100644 (file)
index 0000000..c00416a
--- /dev/null
@@ -0,0 +1,122 @@
+'use strict'
+
+function Board (element) {
+  this.element = element
+  this.room = []
+
+  this.enter_room = function (starting_hand = null) {
+    this.remove_cards()
+
+    if (donsol.deck.cards.length > 0) {
+      this.add_card(0, donsol.deck.draw_card(starting_hand ? DIAMOND : null))
+      setTimeout(() => {
+        this.room[0].element.style.opacity = 1
+        this.room[0].element.style.top = 0
+        donsol.speaker.play_effect('click2')
+      }, 100)
+    }
+    if (donsol.deck.cards.length > 0) {
+      this.add_card(1, donsol.deck.draw_card(starting_hand ? CLOVE : null))
+      setTimeout(() => {
+        this.room[1].element.style.opacity = 1
+        this.room[1].element.style.top = 0
+        donsol.speaker.play_effect('click2')
+      }, 150)
+    }
+    if (donsol.deck.cards.length > 0) {
+      this.add_card(2, donsol.deck.draw_card(starting_hand ? HEART : null))
+      setTimeout(() => {
+        this.room[2].element.style.opacity = 1
+        this.room[2].element.style.top = 0
+        donsol.speaker.play_effect('click2')
+      }, 200)
+    }
+    if (donsol.deck.cards.length > 0) {
+      this.add_card(3, donsol.deck.draw_card(starting_hand ? SPADE : null))
+      setTimeout(() => {
+        this.room[3].element.style.opacity = 1
+        this.room[3].element.style.top = 0
+        donsol.speaker.play_effect('click2')
+      }, 250)
+    }
+
+    donsol.player.update()
+    this.update()
+  }
+
+  this.add_card = function (index, card) {
+    this.element.appendChild(card.install())
+    this.room.push(card)
+  }
+
+  this.remove_cards = function () {
+    this.room = []
+    this.element.innerHTML = ''
+  }
+
+  this.return_cards = function () {
+    if (!this.room[0].is_flipped) { donsol.deck.return_card(this.room[0]) }
+    if (!this.room[1].is_flipped) { donsol.deck.return_card(this.room[1]) }
+    if (!this.room[2].is_flipped) { donsol.deck.return_card(this.room[2]) }
+    if (!this.room[3].is_flipped) { donsol.deck.return_card(this.room[3]) }
+  }
+
+  this.update = function () {
+    // Don't draw if the player is dead
+    if (donsol.player.health.value < 1) {
+      return
+    }
+
+    if (donsol.player.experience.value === donsol.player.experience.limit) {
+      this.dungeon_complete()
+      return
+    }
+    if (this.room[0].is_flipped && this.room[1].is_flipped && this.room[2].is_flipped && this.room[3].is_flipped) {
+      setTimeout(function () { donsol.board.is_complete() }, 250)
+    }
+  }
+
+  // Checks
+
+  this.is_complete = function () {
+    donsol.player.has_escaped = false
+    this.enter_room()
+  }
+
+  this.is_started = function () {
+    return this.cards_flipped().length > 0
+  }
+
+  this.has_monsters = function () {
+    return this.cards_monsters().length > 0
+  }
+
+  this.cards_flipped = function () {
+    const a = []
+    if (this.room[0] && this.room[0].is_flipped) { a.push(this.room[0]) }
+    if (this.room[1] && this.room[1].is_flipped) { a.push(this.room[1]) }
+    if (this.room[2] && this.room[2].is_flipped) { a.push(this.room[2]) }
+    if (this.room[3] && this.room[3].is_flipped) { a.push(this.room[3]) }
+    return a
+  }
+
+  this.cards_monsters = function () {
+    const a = []
+    if (this.room[0] && this.room[0].constructor.name == 'Card_Monster' && this.room[0].is_flipped === false) { a.push(this.room[0]) }
+    if (this.room[1] && this.room[1].constructor.name == 'Card_Monster' && this.room[1].is_flipped === false) { a.push(this.room[1]) }
+    if (this.room[2] && this.room[2].constructor.name == 'Card_Monster' && this.room[2].is_flipped === false) { a.push(this.room[2]) }
+    if (this.room[3] && this.room[3].constructor.name == 'Card_Monster' && this.room[3].is_flipped === false) { a.push(this.room[3]) }
+    return a
+  }
+
+  this.dungeon_complete = function () {
+    donsol.is_complete = true
+    donsol.player.escape_button.innerHTML = 'Restart'
+    donsol.player.element.setAttribute('class', 'done')
+    donsol.timeline.add_event('Completed dungeon!')
+  }
+
+  this.dungeon_failed = function () {
+
+  }
+}
diff --git a/sources/scripts/card.js b/sources/scripts/card.js
new file mode 100644 (file)
index 0000000..a2d325e
--- /dev/null
@@ -0,0 +1,69 @@
+'use strict'
+
+function Card (sym, value, type, name = 'Unknown') {
+  this.symbol = sym
+  this.value = value
+  this.type = type
+  this.name = name
+
+  this.element = null
+  this.is_flipped = false
+
+  this.install = function () {
+    const e = document.createElement('card')
+    e.setAttribute('class', this.type + ' card_' + this.value)
+
+    // Face
+    const face = document.createElement('div')
+    face.setAttribute('class', 'face')
+    e.appendChild(face)
+
+    // Value
+    const value = document.createElement('span')
+    value.setAttribute('class', 'value')
+    value.innerHTML = this.symbol
+    face.appendChild(value)
+
+    const graphic = document.createElement('div')
+    graphic.className = 'graphic'
+    graphic.innerHTML = require('fs').readFileSync(`${__dirname}/media/${this.type}/${this.value}.svg`)
+    face.appendChild(graphic)
+
+    // Name
+    const name_element = document.createElement('span')
+    name_element.setAttribute('class', 'name')
+    name_element.innerHTML = this.name + ' ' + this.value
+    face.appendChild(name_element)
+
+    // Icon
+    face.appendChild(new Icon(this.type).install())
+
+    addClickHandler(e, this, this.value)
+
+    this.element = e
+
+    return e
+  }
+
+  function addClickHandler (elem, object) {
+    elem.addEventListener('click', function (e) { object.touch() }, false)
+  }
+
+  this.touch = function () {
+    console.log('??')
+  }
+
+  this.flip = function () {
+    donsol.speaker.play_effect('flip')
+
+    this.is_flipped = true
+    donsol.player.experience.value += 1
+    donsol.player.experience.update()
+
+    this.element.style.opacity = '0'
+    this.element.style.top = '-5px'
+    donsol.speaker.play_effect('click2')
+
+    donsol.player.update()
+  }
+}
diff --git a/sources/scripts/card.monster.js b/sources/scripts/card.monster.js
new file mode 100644 (file)
index 0000000..2644db7
--- /dev/null
@@ -0,0 +1,13 @@
+'use strict'
+
+function Card_Monster (sym, value, type, name = 'Unknown') {
+  Card.call(this, sym, value, type, name)
+
+  this.touch = function () {
+    if (this.is_flipped) { console.log('Card is already flipped'); return }
+    if (donsol.player.health.value < 1) { console.log('Player is dead'); return }
+    this.flip()
+    donsol.player.attack(this)
+    donsol.board.update()
+  }
+}
diff --git a/sources/scripts/card.potion.js b/sources/scripts/card.potion.js
new file mode 100644 (file)
index 0000000..aa3d600
--- /dev/null
@@ -0,0 +1,13 @@
+'use strict'
+
+function Card_Potion (sym, value, type, name = 'Unknown') {
+  Card.call(this, sym, value, type, name)
+
+  this.touch = function () {
+    if (this.is_flipped) { console.log('Card is already flipped'); return }
+    if (donsol.player.health.value < 1) { console.log('Player is dead'); return }
+    this.flip()
+    donsol.player.drink_potion(this.value)
+    donsol.board.update()
+  }
+}
diff --git a/sources/scripts/card.shield.js b/sources/scripts/card.shield.js
new file mode 100644 (file)
index 0000000..19cd345
--- /dev/null
@@ -0,0 +1,13 @@
+'use strict'
+
+function Card_Shield (sym, value, type, name = 'Unknown') {
+  Card.call(this, sym, value, type, name)
+
+  this.touch = function () {
+    if (this.is_flipped == true) { console.log('Card is already flipped'); return }
+    if (donsol.player.health.value < 1) { console.log('Player is dead'); return }
+    this.flip()
+    donsol.player.equip_shield(this.value)
+    donsol.board.update()
+  }
+}
diff --git a/sources/scripts/deck.js b/sources/scripts/deck.js
new file mode 100644 (file)
index 0000000..acf974e
--- /dev/null
@@ -0,0 +1,103 @@
+'use strict'
+
+function Deck () {
+  this.cards = [
+    new Card_Potion('A', 11, HEART, 'White Mage'),
+    new Card_Potion('2', 2, HEART, 'Small Potion'),
+    new Card_Potion('3', 3, HEART, 'Small Potion'),
+    new Card_Potion('4', 4, HEART, 'Medium Potion'),
+    new Card_Potion('5', 5, HEART, 'Medium Potion'),
+    new Card_Potion('6', 6, HEART, 'Medium Potion'),
+    new Card_Potion('7', 7, HEART, 'Medium Potion'),
+    new Card_Potion('8', 8, HEART, 'Medium Potion'),
+    new Card_Potion('9', 9, HEART, 'Large Potion'),
+    new Card_Potion('10', 10, HEART, 'Large Potion'),
+    new Card_Potion('V', 11, HEART, 'White Mage'),
+    new Card_Potion('Q', 11, HEART, 'White Mage'),
+    new Card_Potion('K', 11, HEART, 'White Mage'),
+    new Card_Shield('A', 11, DIAMOND, 'Red Mage'),
+    new Card_Shield('2', 2, DIAMOND, 'Buckler'),
+    new Card_Shield('3', 3, DIAMOND, 'Buckler'),
+    new Card_Shield('4', 4, DIAMOND, 'Shield'),
+    new Card_Shield('5', 5, DIAMOND, 'Shield'),
+    new Card_Shield('6', 6, DIAMOND, 'Shield'),
+    new Card_Shield('7', 7, DIAMOND, 'Shield'),
+    new Card_Shield('8', 8, DIAMOND, 'Shield'),
+    new Card_Shield('9', 9, DIAMOND, 'Large Shield'),
+    new Card_Shield('10', 10, DIAMOND, 'Large Shield'),
+    new Card_Shield('V', 11, DIAMOND, 'Red Mage'),
+    new Card_Shield('Q', 11, DIAMOND, 'Red Mage'),
+    new Card_Shield('K', 11, DIAMOND, 'Red Mage'),
+    new Card_Monster('A', 17, CLOVE, 'Empress'),
+    new Card_Monster('2', 2, CLOVE, 'Rat'),
+    new Card_Monster('3', 3, CLOVE, 'Bat'),
+    new Card_Monster('4', 4, CLOVE, 'Imp'),
+    new Card_Monster('5', 5, CLOVE, 'Goblin'),
+    new Card_Monster('6', 6, CLOVE, 'Orc'),
+    new Card_Monster('7', 7, CLOVE, 'Ogre'),
+    new Card_Monster('8', 8, CLOVE, 'Beholder'),
+    new Card_Monster('9', 9, CLOVE, 'Medusa'),
+    new Card_Monster('10', 10, CLOVE, 'Demon'),
+    new Card_Monster('V', 11, CLOVE, 'Consort'),
+    new Card_Monster('Q', 13, CLOVE, 'Queen'),
+    new Card_Monster('K', 15, CLOVE, 'Regnant'),
+    new Card_Monster('A', 17, SPADE, 'Empress'),
+    new Card_Monster('2', 2, SPADE, 'Slime'),
+    new Card_Monster('3', 3, SPADE, 'Tunneler'),
+    new Card_Monster('4', 4, SPADE, 'Fiend'),
+    new Card_Monster('5', 5, SPADE, 'Drake'),
+    new Card_Monster('6', 6, SPADE, 'Specter'),
+    new Card_Monster('7', 7, SPADE, 'Ghost'),
+    new Card_Monster('8', 8, SPADE, 'Elemental'),
+    new Card_Monster('9', 9, SPADE, 'Witch'),
+    new Card_Monster('10', 10, SPADE, 'Familiar'),
+    new Card_Monster('V', 11, SPADE, 'Consort'),
+    new Card_Monster('Q', 13, SPADE, 'Queen'),
+    new Card_Monster('K', 15, SPADE, 'Regnant'),
+    new Card_Monster('J', 21, JOKER, 'First Donsol'),
+    new Card_Monster('J', 21, JOKER, 'Second Donsol')
+  ]
+
+  let draw_pile = []
+
+  this.start = function () {
+    draw_pile = this.cards
+    donsol.timeline.add_event(`Entered Donsol, at <b>${donsol.get_difficulty()}</b> difficulty.`)
+  }
+
+  this.shuffle = function () {
+    draw_pile = shuffle(this.cards)
+    donsol.timeline.add_event(`Entered Donsol, at <b>${donsol.get_difficulty()}</b> difficulty.`)
+  }
+
+  this.draw_card = function (type) {
+    let i = 0
+    switch (type) {
+      case HEART:
+        i = Math.floor((Math.random() * 10) + 0); break
+      case DIAMOND:
+        i = Math.floor((Math.random() * 10) + 13); break
+      case CLOVE:
+        i = Math.floor((Math.random() * 10) + 25); break
+      case SPADE:
+        i = Math.floor((Math.random() * 10) + 36); break
+    }
+
+    return draw_pile.splice(i, 1)[0]
+  }
+
+  this.return_card = function (card) {
+    draw_pile.push(card)
+    draw_pile = shuffle(draw_pile)
+  }
+
+  function shuffle (array) {
+    for (let i = array.length - 1; i > 0; i--) {
+      const j = Math.floor(Math.random() * (i + 1))
+      const temp = array[i]
+      array[i] = array[j]
+      array[j] = temp
+    }
+    return array
+  }
+}
diff --git a/sources/scripts/donsol.js b/sources/scripts/donsol.js
new file mode 100644 (file)
index 0000000..2553a1a
--- /dev/null
@@ -0,0 +1,91 @@
+'use strict'
+
+const HEART = 'heart'
+const DIAMOND = 'diamond'
+const CLOVE = 'clove'
+const SPADE = 'spade'
+const JOKER = 'joker'
+
+function Donsol () {
+  const defaultTheme = {
+    background: '#000000',
+    f_high: '#000000',
+    f_med: '#a93232',
+    f_low: '#aaaaaa',
+    f_inv: '#ffffff',
+    b_high: '#ffffff',
+    b_med: '#cccccc',
+    b_low: '#333333',
+    b_inv: '#a93232'
+  }
+
+  this.theme = new Theme(defaultTheme)
+
+  this.deck = new Deck()
+  this.board = new Board()
+  this.player = new Player()
+  this.timeline = new Timeline()
+  this.controller = new Controller()
+  this.speaker = new Speaker()
+  this.walkthrough = new Walkthrough()
+
+  this.is_complete = false
+  this.difficulty = 1
+
+  this.install = function (host = document.body) {
+    this.theme.install(host)
+  }
+
+  this.start = function () {
+    donsol.board.element = document.getElementById('board')
+    donsol.player.element = document.getElementById('player')
+
+    this.theme.start()
+    this.deck.start()
+    this.player.install()
+    donsol.timeline.install(donsol.player.element)
+    this.player.start()
+
+    this.board.enter_room(true)
+    donsol.deck.shuffle()
+
+    this.update()
+  }
+
+  this.new_game = function () {
+    this.deck = new Deck()
+    this.deck.start()
+
+    this.player.start()
+    this.board.enter_room(true)
+    donsol.deck.shuffle()
+
+    this.update()
+  }
+
+  this.toggle_difficulty = function () {
+    this.difficulty = this.difficulty < 3 ? this.difficulty + 1 : 0
+    donsol.new_game()
+  }
+
+  this.set_difficulty = function (id) {
+    this.difficulty = id
+    donsol.new_game()
+  }
+
+  this.get_difficulty = function () {
+    return this.difficulty == 3 ? 'Expert' : this.difficulty == 2 ? 'Hard' : this.difficulty == 1 ? 'Normal' : 'Easy'
+  }
+
+  this.update = function () {
+    console.log('Difficulty', this.get_difficulty())
+  }
+
+  this.skip = function () {
+    if (donsol.player.experience.value < 1) {
+      donsol.new_game()
+    } else {
+      donsol.player.escape_room()
+    }
+  }
+}
diff --git a/sources/scripts/gage.health.js b/sources/scripts/gage.health.js
new file mode 100644 (file)
index 0000000..6d19008
--- /dev/null
@@ -0,0 +1,15 @@
+'use strict'
+
+function Gage_Health (name, limit, color) {
+  Gage.call(this, name, limit, color)
+
+  this.update = function () {
+         this.progress.update(this.value, this.limit)
+
+    if (donsol.player.can_drink === false) {
+      this.value_element.innerHTML = `<span>${this.value}</span> <span class='unit'>HP</span>`
+    } else {
+      this.value_element.innerHTML = `${this.value} <span class='unit'>HP</span>`
+    }
+  }
+}
diff --git a/sources/scripts/gage.js b/sources/scripts/gage.js
new file mode 100644 (file)
index 0000000..9303f23
--- /dev/null
@@ -0,0 +1,66 @@
+'use strict'
+
+function Gage (name, limit, color) {
+  this.name = name
+  this.color = color
+  this.limit = limit
+  this.value = limit
+  this.value_element = null
+  this.event_element = null
+  this.element = document.createElement('div')
+  this.progress = new Progress(15, color)
+
+  this.show_limit = true
+  this.units = ''
+
+  this.start = function () {
+    this.install()
+  }
+
+  this.install = function () {
+    this.element.setAttribute('class', 'gage ' + this.name.toLowerCase())
+
+    this.value_element = document.createElement('span')
+    this.value_element.setAttribute('class', 'value')
+    this.value_element.innerHTML = this.value + '(' + this.limit + ')'
+    this.element.appendChild(this.value_element)
+
+    this.event_element = document.createElement('span')
+    this.event_element.setAttribute('class', 'event')
+    this.element.appendChild(this.event_element)
+
+    this.element.appendChild(this.progress.install())
+
+    return this.element
+  }
+
+  this.update = function (value) {
+    this.value = typeof value === 'number' ? value : this.value
+    if (this.value > this.limit) { this.value = this.limit }
+    if (this.value < 0) { this.value = 0 }
+
+    this.progress.update(this.value, this.limit)
+
+    if (this.name == 'Shield' && this.value == 0) {
+      this.value_element.innerHTML = "0<span class='unit'>DP</span>"
+    } else if (this.name == 'Shield' && this.limit == 25) {
+      this.value_element.innerHTML = this.value + "<span class='unit'>DP</span>"
+    } else {
+      this.value_element.innerHTML = this.show_limit ? this.value + ' < ' + this.limit + "<span class='unit'>" + this.units + '</span>' : this.value + " <span class='unit'>" + this.units + '</span>'
+    }
+  }
+
+  this.add_event = function (value) {
+    this.event_element.innerHTML = "<span class='name'>" + value + '</span>'
+    this.event_element.style.marginTop = '5px'
+    this.event_element.style.opacity = '0'
+    setTimeout(() => {
+      this.event_element.style.marginTop = '0px'
+      this.event_element.style.opacity = 1
+    }, 250)
+  }
+
+  this.clear_event = function () {
+    this.event_element.innerHTML = ''
+  }
+}
diff --git a/sources/scripts/gage.progress.js b/sources/scripts/gage.progress.js
new file mode 100644 (file)
index 0000000..a73c734
--- /dev/null
@@ -0,0 +1,29 @@
+'use strict'
+
+function Progress (radius = 15) {
+  this.wrapper = null
+  this.progress_bar = null
+
+  this.install = function () {
+    this.wrapper = document.createElement('div')
+    this.wrapper.setAttribute('class', 'progress')
+
+    this.progress_bar = document.createElement('div')
+    this.progress_bar.setAttribute('class', 'bar')
+
+    this.wrapper.appendChild(this.progress_bar)
+
+    return this.wrapper
+  }
+
+  this.update = function (value, limit = 0) {
+    if (limit === 0) { value = 0; limit = 1 }
+    const min = 0
+    const max = 130
+    const pixels = Math.floor(((value / limit) * max) + min)
+    const ratio = (value / limit)
+    const perc = ratio * 100
+
+    this.progress_bar.style.width = `${perc}%`
+  }
+}
diff --git a/sources/scripts/gage.shield.js b/sources/scripts/gage.shield.js
new file mode 100644 (file)
index 0000000..ffff279
--- /dev/null
@@ -0,0 +1,25 @@
+'use strict'
+
+function Gage_Shield (name, limit, color) {
+  Gage.call(this, name, limit, color)
+
+  this.break_limit = null
+
+  this.update = function () {
+    if (this.is_damaged() === true) {
+      this.value_element.innerHTML = `${this.break_limit - 1}/${this.value} <span class='unit'>DP</span>`
+      this.progress.update(this.value < this.break_limit ? this.value : this.break_limit - 1, 11)
+    } else if (this.value == 0) {
+      this.value_element.innerHTML = "0 <span class='unit'>DP</span>"
+      this.progress.update(0, 11)
+    } else {
+      this.value_element.innerHTML = '<span>' + this.value + "</span> <span class='unit'>DP</span>"
+      this.progress.update(this.value, 11)
+    }
+  }
+
+  this.is_damaged = function () {
+    if (this.break_limit === null) { return false }
+    return true
+  }
+}
diff --git a/sources/scripts/icon.js b/sources/scripts/icon.js
new file mode 100644 (file)
index 0000000..415edea
--- /dev/null
@@ -0,0 +1,105 @@
+'use strict'
+
+function Icon (type) {
+  this.type = type
+
+  this.install = function () {
+    switch (this.type) {
+      case HEART:
+        return this.heart()
+      case DIAMOND:
+        return this.diamond()
+      case CLOVE:
+        return this.clove()
+      case SPADE:
+        return this.spade()
+      case JOKER:
+        return this.joker()
+    }
+  }
+
+  this.heart = function () {
+    const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+    e.setAttribute('class', 'icon')
+
+    const s = document.createElementNS('http://www.w3.org/2000/svg', 'path')
+    s.setAttribute('d', 'M0,15 a15,15 0 0,1 30,0 l-15,15 l-15,-15')
+    s.setAttribute('class', 'fill_red')
+
+    e.appendChild(s)
+    return e
+  }
+
+  this.diamond = function () {
+    const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+    e.setAttribute('class', 'icon')
+
+    const s = document.createElementNS('http://www.w3.org/2000/svg', 'path')
+    s.setAttribute('d', 'M15 0 L 30 15 L 15 30 L 0 15')
+    s.setAttribute('class', 'fill_red')
+
+    e.appendChild(s)
+    return e
+  }
+
+  this.clove = function () {
+    const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+    e.setAttribute('class', 'icon')
+
+    const s = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
+    s.setAttribute('cx', '15px')
+    s.setAttribute('cy', '6px')
+    s.setAttribute('r', '5px')
+    s.setAttribute('class', 'fill_black')
+    e.appendChild(s)
+
+    const s2 = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
+    s2.setAttribute('cx', '24px')
+    s2.setAttribute('cy', '15px')
+    s2.setAttribute('r', '5px')
+    s2.setAttribute('class', 'fill_black')
+    e.appendChild(s2)
+
+    const s3 = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
+    s3.setAttribute('cx', '6px')
+    s3.setAttribute('cy', '15px')
+    s3.setAttribute('r', '5px')
+    s3.setAttribute('class', 'fill_black')
+    e.appendChild(s3)
+
+    const s4 = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
+    s4.setAttribute('cx', '15px')
+    s4.setAttribute('cy', '24px')
+    s4.setAttribute('r', '5px')
+    s4.setAttribute('class', 'fill_black')
+    e.appendChild(s4)
+
+    return e
+  }
+
+  this.spade = function () {
+    const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+    e.setAttribute('class', 'icon')
+
+    const s = document.createElementNS('http://www.w3.org/2000/svg', 'path')
+    s.setAttribute('d', 'M15,0 L0,15 a15,15 0 0,1 15,15 a15,15 0 0,1 15,-15')
+    s.setAttribute('class', 'fill_black')
+
+    e.appendChild(s)
+    return e
+  }
+
+  this.joker = function () {
+    const e = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+    e.setAttribute('class', 'icon')
+
+    const s = document.createElementNS('http://www.w3.org/2000/svg', 'circle')
+    s.setAttribute('cx', '15px')
+    s.setAttribute('cy', '15px')
+    s.setAttribute('r', '15px')
+    s.setAttribute('class', 'fill_black')
+    e.appendChild(s)
+
+    return e
+  }
+}
diff --git a/sources/scripts/lib/controller.js b/sources/scripts/lib/controller.js
new file mode 100644 (file)
index 0000000..365c368
--- /dev/null
@@ -0,0 +1,185 @@
+'use strict'
+
+function Controller () {
+  this.menu = { default: {} }
+  this.mode = 'default'
+
+  this.app = require('electron').remote.app
+
+  this.start = function () {
+  }
+
+  this.add = function (mode, cat, label, fn, accelerator) {
+    if (!this.menu[mode]) { this.menu[mode] = {} }
+    if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} }
+    this.menu[mode][cat][label] = { fn: fn, accelerator: accelerator }
+    console.log(`${mode}/${cat}/${label} <${accelerator}>`)
+  }
+
+  this.add_role = function (mode, cat, label) {
+    if (!this.menu[mode]) { this.menu[mode] = {} }
+    if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} }
+    this.menu[mode][cat][label] = { role: label }
+  }
+
+  this.set = function (mode = 'default') {
+    this.mode = mode
+    this.commit()
+  }
+
+  this.format = function () {
+    const f = []
+    const m = this.menu[this.mode]
+    for (const cat in m) {
+      const submenu = []
+      for (name in m[cat]) {
+        const option = m[cat][name]
+        if (option.role) {
+          submenu.push({ role: option.role })
+        } else {
+          submenu.push({ label: name, accelerator: option.accelerator, click: option.fn })
+        }
+      }
+      f.push({ label: cat, submenu: submenu })
+    }
+    return f
+  }
+
+  this.commit = function () {
+    this.app.inject_menu(this.format())
+  }
+
+  this.docs = function () {
+    console.log('Generating docs..')
+    const svg = this.generate_svg(this.format())
+    const txt = this.documentation(this.format())
+    dialog.showSaveDialog((fileName) => {
+      if (fileName === undefined) { return }
+      fileName = fileName.substr(-4, 4) != '.svg' ? fileName + '.svg' : fileName
+      fs.writeFile(fileName, svg)
+      fs.writeFile(fileName.replace('.svg', '.md'), txt)
+    })
+  }
+
+  this.generate_svg = function (m) {
+    let svg_html = ''
+
+    for (id in this.layout) {
+      const key = this.layout[id]
+      const acc = this.accelerator_for_key(key.name, m)
+      svg_html += `<rect x="${key.x + 1}" y="${key.y + 1}" width="${key.width - 2}" height="${key.height - 2}" rx="4" ry="4" title="${key.name}" stroke="#ccc" fill="none" stroke-width="1"/>`
+      svg_html += `<rect x="${key.x + 3}" y="${key.y + 3}" width="${key.width - 6}" height="${key.height - 12}" rx="3" ry="3" title="${key.name}" stroke="${acc.basic ? '#000' : acc.ctrl ? '#ccc' : '#fff'}" fill="${acc.basic ? '#000' : acc.ctrl ? '#ccc' : '#fff'}" stroke-width="1"/>`
+      svg_html += `<text x="${key.x + 10}" y="${key.y + 20}" font-size='11' font-family='Input Mono' stroke-width='0' fill='${acc.basic ? '#fff' : '#000'}'>${key.name.toUpperCase()}</text>`
+      svg_html += acc && acc.basic ? `<text x="${key.x + 10}" y="${key.y + 35}" font-size='7' font-family='Input Mono' stroke-width='0' fill='#fff'>${acc.basic}</text>` : ''
+      svg_html += acc && acc.ctrl ? `<text x="${key.x + 10}" y="${key.y + 45}" font-size='7' font-family='Input Mono' stroke-width='0' fill='#000'>${acc.ctrl}</text>` : ''
+    }
+    return `<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="900" height="300" version="1.0" style="fill:none;stroke:black;stroke-width:2px;">${svg_html}</svg>`
+  }
+
+  this.documentation = function () {
+    let txt = ''
+
+    txt += this.documentation_for_mode('default', this.menu.default)
+
+    for (name in this.menu) {
+      if (name == 'default') { continue }
+      txt += this.documentation_for_mode(name, this.menu[name])
+    }
+    return txt
+  }
+
+  this.documentation_for_mode = function (name, mode) {
+    let txt = `## ${name} Mode\n\n`
+
+    for (id in mode) {
+      if (id == '*') { continue }
+      txt += `### ${id}\n`
+      for (name in mode[id]) {
+        const option = mode[id][name]
+        txt += `- ${name}: \`${option.accelerator}\`\n`
+      }
+      txt += '\n'
+    }
+
+    return txt + '\n'
+  }
+
+  this.accelerator_for_key = function (key, menu) {
+    const acc = { basic: null, ctrl: null }
+    for (cat in menu) {
+      const options = menu[cat]
+      for (id in options.submenu) {
+        const option = options.submenu[id]; if (option.role) { continue }
+        acc.basic = (option.accelerator.toLowerCase() == key.toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.basic
+        acc.ctrl = (option.accelerator.toLowerCase() == ('CmdOrCtrl+' + key).toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.ctrl
+      }
+    }
+    return acc
+  }
+
+  this.layout = [
+    { x: 0, y: 0, width: 60, height: 60, name: 'esc' },
+    { x: 60, y: 0, width: 60, height: 60, name: '1' },
+    { x: 120, y: 0, width: 60, height: 60, name: '2' },
+    { x: 180, y: 0, width: 60, height: 60, name: '3' },
+    { x: 240, y: 0, width: 60, height: 60, name: '4' },
+    { x: 300, y: 0, width: 60, height: 60, name: '5' },
+    { x: 360, y: 0, width: 60, height: 60, name: '6' },
+    { x: 420, y: 0, width: 60, height: 60, name: '7' },
+    { x: 480, y: 0, width: 60, height: 60, name: '8' },
+    { x: 540, y: 0, width: 60, height: 60, name: '9' },
+    { x: 600, y: 0, width: 60, height: 60, name: '0' },
+    { x: 660, y: 0, width: 60, height: 60, name: '-' },
+    { x: 720, y: 0, width: 60, height: 60, name: 'plus' },
+    { x: 780, y: 0, width: 120, height: 60, name: 'backspace' },
+    { x: 0, y: 60, width: 90, height: 60, name: 'tab' },
+    { x: 90, y: 60, width: 60, height: 60, name: 'q' },
+    { x: 150, y: 60, width: 60, height: 60, name: 'w' },
+    { x: 210, y: 60, width: 60, height: 60, name: 'e' },
+    { x: 270, y: 60, width: 60, height: 60, name: 'r' },
+    { x: 330, y: 60, width: 60, height: 60, name: 't' },
+    { x: 390, y: 60, width: 60, height: 60, name: 'y' },
+    { x: 450, y: 60, width: 60, height: 60, name: 'u' },
+    { x: 510, y: 60, width: 60, height: 60, name: 'i' },
+    { x: 570, y: 60, width: 60, height: 60, name: 'o' },
+    { x: 630, y: 60, width: 60, height: 60, name: 'p' },
+    { x: 690, y: 60, width: 60, height: 60, name: '[' },
+    { x: 750, y: 60, width: 60, height: 60, name: ']' },
+    { x: 810, y: 60, width: 90, height: 60, name: '|' },
+    { x: 0, y: 120, width: 105, height: 60, name: 'caps' },
+    { x: 105, y: 120, width: 60, height: 60, name: 'a' },
+    { x: 165, y: 120, width: 60, height: 60, name: 's' },
+    { x: 225, y: 120, width: 60, height: 60, name: 'd' },
+    { x: 285, y: 120, width: 60, height: 60, name: 'f' },
+    { x: 345, y: 120, width: 60, height: 60, name: 'g' },
+    { x: 405, y: 120, width: 60, height: 60, name: 'h' },
+    { x: 465, y: 120, width: 60, height: 60, name: 'j' },
+    { x: 525, y: 120, width: 60, height: 60, name: 'k' },
+    { x: 585, y: 120, width: 60, height: 60, name: 'l' },
+    { x: 645, y: 120, width: 60, height: 60, name: ';' },
+    { x: 705, y: 120, width: 60, height: 60, name: "'" },
+    { x: 765, y: 120, width: 135, height: 60, name: 'enter' },
+    { x: 0, y: 180, width: 135, height: 60, name: 'shift' },
+    { x: 135, y: 180, width: 60, height: 60, name: 'z' },
+    { x: 195, y: 180, width: 60, height: 60, name: 'x' },
+    { x: 255, y: 180, width: 60, height: 60, name: 'c' },
+    { x: 315, y: 180, width: 60, height: 60, name: 'v' },
+    { x: 375, y: 180, width: 60, height: 60, name: 'b' },
+    { x: 435, y: 180, width: 60, height: 60, name: 'n' },
+    { x: 495, y: 180, width: 60, height: 60, name: 'm' },
+    { x: 555, y: 180, width: 60, height: 60, name: ',' },
+    { x: 615, y: 180, width: 60, height: 60, name: '.' },
+    { x: 675, y: 180, width: 60, height: 60, name: '/' },
+    { x: 735, y: 180, width: 165, height: 60, name: 'capslock' },
+    { x: 0, y: 240, width: 90, height: 60, name: 'ctrl' },
+    { x: 90, y: 240, width: 90, height: 60, name: 'cmd' },
+    { x: 180, y: 240, width: 90, height: 60, name: 'alt' },
+    { x: 270, y: 240, width: 270, height: 60, name: 'space' },
+    { x: 810, y: 240, width: 90, height: 60, name: 'ctrl' },
+    { x: 720, y: 240, width: 90, height: 60, name: 'pn' },
+    { x: 630, y: 240, width: 90, height: 60, name: 'fn' },
+    { x: 540, y: 240, width: 90, height: 60, name: 'alt' }
+  ]
+}
+
+module.exports = new Controller()
diff --git a/sources/scripts/lib/theme.js b/sources/scripts/lib/theme.js
new file mode 100644 (file)
index 0000000..7482596
--- /dev/null
@@ -0,0 +1,128 @@
+'use strict'
+
+function Theme (_default) {
+  const themer = this
+
+  this.active = _default
+
+  this.el = document.createElement('style')
+  this.el.type = 'text/css'
+
+  this.install = function (host = document.body, callback) {
+    console.log('Theme', 'Installing..')
+    host.appendChild(this.el)
+    this.callback = callback
+  }
+
+  this.start = function () {
+    console.log('Theme', 'Starting..')
+    if (isJson(localStorage.theme)) {
+      const storage = JSON.parse(localStorage.theme)
+      if (validate(storage)) {
+        console.log('Theme', 'Found theme in localStorage!')
+        this.load(storage)
+        return
+      }
+    }
+    this.load(_default)
+  }
+
+  this.load = function (data) {
+    const theme = parse(data)
+    if (!validate(theme)) { console.warn('Theme', 'Not a theme', theme); return }
+    console.log('Theme', `Loading theme with background ${theme.background}.`)
+    this.el.innerHTML = `:root { --background: ${theme.background}; --f_high: ${theme.f_high}; --f_med: ${theme.f_med}; --f_low: ${theme.f_low}; --f_inv: ${theme.f_inv}; --b_high: ${theme.b_high}; --b_med: ${theme.b_med}; --b_low: ${theme.b_low}; --b_inv: ${theme.b_inv}; }`
+    localStorage.setItem('theme', JSON.stringify(theme))
+    this.active = theme
+    if (this.callback) {
+      this.callback()
+    }
+  }
+
+  this.reset = function () {
+    this.load(_default)
+  }
+
+  function parse (any) {
+    if (any && any.background) { return any } else if (any && any.data) { return any.data } else if (any && isJson(any)) { return JSON.parse(any) } else if (any && isHtml(any)) { return extract(any) }
+    return null
+  }
+
+  // Drag
+
+  this.drag = function (e) {
+    e.stopPropagation()
+    e.preventDefault()
+    e.dataTransfer.dropEffect = 'copy'
+  }
+
+  this.drop = function (e) {
+    e.preventDefault()
+    e.stopPropagation()
+    const file = e.dataTransfer.files[0]
+    if (!file || !file.name) { console.warn('Theme', 'Unnamed file.'); return }
+    if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { console.warn('Theme', 'Skipped, not a theme'); return }
+    const reader = new FileReader()
+    reader.onload = function (e) {
+      themer.load(e.target.result)
+    }
+    reader.readAsText(file)
+  }
+
+  this.open = function () {
+    const fs = require('fs')
+    const { dialog, app } = require('electron').remote
+    const paths = dialog.showOpenDialog(app.win, { properties: ['openFile'], filters: [{ name: 'Themes', extensions: ['svg'] }] })
+    if (!paths) { console.log('Nothing to load') }
+    fs.readFile(paths[0], 'utf8', function (err, data) {
+      if (err) throw err
+      themer.load(data)
+    })
+  }
+
+  window.addEventListener('dragover', this.drag)
+  window.addEventListener('drop', this.drop)
+
+  // Helpers
+
+  function validate (json) {
+    if (!json) { return false }
+    if (!json.background) { return false }
+    if (!json.f_high) { return false }
+    if (!json.f_med) { return false }
+    if (!json.f_low) { return false }
+    if (!json.f_inv) { return false }
+    if (!json.b_high) { return false }
+    if (!json.b_med) { return false }
+    if (!json.b_low) { return false }
+    if (!json.b_inv) { return false }
+    return true
+  }
+
+  function extract (text) {
+    const svg = new DOMParser().parseFromString(text, 'text/xml')
+    try {
+      return {
+        background: svg.getElementById('background').getAttribute('fill'),
+        f_high: svg.getElementById('f_high').getAttribute('fill'),
+        f_med: svg.getElementById('f_med').getAttribute('fill'),
+        f_low: svg.getElementById('f_low').getAttribute('fill'),
+        f_inv: svg.getElementById('f_inv').getAttribute('fill'),
+        b_high: svg.getElementById('b_high').getAttribute('fill'),
+        b_med: svg.getElementById('b_med').getAttribute('fill'),
+        b_low: svg.getElementById('b_low').getAttribute('fill'),
+        b_inv: svg.getElementById('b_inv').getAttribute('fill')
+      }
+    } catch (err) {
+      console.warn('Theme', 'Incomplete SVG Theme', err)
+    }
+  }
+
+  function isJson (text) {
+    try { JSON.parse(text); return true } catch (error) { return false }
+  }
+
+  function isHtml (text) {
+    try { new DOMParser().parseFromString(text, 'text/xml'); return true } catch (error) { return false }
+  }
+}
diff --git a/sources/scripts/player.js b/sources/scripts/player.js
new file mode 100644 (file)
index 0000000..bf7ef5e
--- /dev/null
@@ -0,0 +1,209 @@
+'use strict'
+
+function Player () {
+  this.element = null
+  this.health = new Gage_Health('Health', 21, '#ff0000')
+  this.shield = new Gage_Shield('Shield', 0, '#72dec2')
+  this.experience = new Gage('Experience', 0, '#ffffff')
+
+  this.can_drink = true
+  this.has_escaped = false
+  this.escape_button = document.createElement('a')
+  this.timeline_element = document.createElement('div')
+
+  this.escape_button.addEventListener('mousedown', () => { donsol.player.escape_room() })
+
+  this.start = function () {
+    this.health.show_limit = false
+    this.health.units = 'HP'
+    this.shield.units = 'DP'
+    this.experience.units = 'XP'
+    this.experience.show_limit = false
+
+    this.health.value = 21
+    this.shield.value = 0
+    this.shield.break_limit = null
+    this.experience.limit = 54
+    this.experience.value = 0
+
+    this.can_drink = true
+    this.has_escaped = false
+
+    this.update()
+  }
+
+  this.install = function () {
+    this.element.appendChild(this.experience.install())
+    this.element.appendChild(this.shield.install())
+    this.element.appendChild(this.health.install())
+
+    this.escape_button.setAttribute('class', 'escape')
+    this.escape_button.innerHTML = 'Escape'
+    this.element.appendChild(this.escape_button)
+    this.timeline_element.setAttribute('class', 'timeline')
+    this.timeline_element.innerHTML = ''
+    this.update()
+  }
+
+  this.attack = function (card) {
+    console.log('<attack>' + card.value)
+    const attack_value = card.value
+    let damages = attack_value
+    let shield_event = ''
+
+    // Shield
+    if (this.shield.value > 0) {
+      // Damaged shield
+      if (this.shield.is_damaged() === true && attack_value >= this.shield.break_limit) {
+        this.shield.value = 0
+        this.shield.break_limit = null
+        shield_event = 'your shield broke'
+      } else {
+        this.shield.break_limit = attack_value
+        damages = attack_value > this.shield.value ? Math.abs(attack_value - this.shield.value) : 0
+        shield_event = `your shield absorbed ${damages < 1 ? 'everything' : attack_value > this.shield.value ? this.shield.value : attack_value}`
+      }
+    }
+
+    // Damages went through
+    if (damages > 0) {
+      this.health.value -= damages
+    }
+
+    // Timeline
+    if (this.health.value < 1) {
+      donsol.player.health.add_event('-' + damages)
+      donsol.timeline.add_event('<span>The ' + card.name + ' killed you!</span>')
+      donsol.board.dungeon_failed()
+      this.update()
+    } else {
+      donsol.timeline.add_event(`${damages > 0 ? 'Battled' : 'Killed'} the ${card.name}${shield_event !== '' ? ', ' + shield_event : ''}.`)
+    }
+
+    // Experience
+    donsol.player.experience.add_event('+1')
+
+    this.can_drink = true
+    donsol.is_complete = false
+    this.shield.update()
+    this.health.update()
+  }
+
+  this.equip_shield = function (shield_value) {
+    console.log('<shield>' + shield_value)
+
+    this.shield.value = shield_value
+    this.shield.break_limit = null
+
+    // donsol.player.shield.add_event(shield_value);
+    donsol.player.experience.add_event('+1')
+    donsol.timeline.add_event('Equipped shield ' + shield_value + '.')
+    this.can_drink = true
+    donsol.is_complete = false
+    this.shield.update()
+    this.health.update()
+  }
+
+  this.drink_potion = function (potion_value) {
+    console.log('<potion>' + potion_value)
+
+    if (this.can_drink === false) {
+      donsol.timeline.add_event('Wasted potion!')
+      donsol.player.health.add_event('Wasted')
+      return
+    }
+    const before_health = this.health.value
+    let new_health = this.health.value + potion_value; new_health = new_health > 21 ? 21 : new_health
+
+    const mod = new_health - before_health
+    donsol.player.health.value = new_health
+    donsol.player.health.add_event(mod > 0 ? '+' + mod : 'Wasted')
+    donsol.player.experience.add_event('+1')
+    donsol.timeline.add_event('Drank potion.')
+    this.can_drink = false
+    donsol.is_complete = false
+    this.health.update()
+    this.shield.update()
+  }
+
+  this.escape_room = function () {
+    donsol.speaker.play_effect('click2')
+    if (this.health.value < 1 || donsol.is_complete === true || this.experience.value == 0) {
+      donsol.new_game()
+      return
+    }
+    if (this.can_escape() !== true) {
+      donsol.timeline.add_event('Cannot escape the room!')
+      return
+    }
+
+    this.has_escaped = true
+    this.can_drink = true
+
+    donsol.board.return_cards()
+    donsol.board.enter_room()
+    donsol.timeline.add_event('Escaped the room!')
+  }
+
+  this.update = function () {
+    if (this.health.value < 1) {
+      this.escape_button.innerHTML = 'Restart'
+      this.element.setAttribute('class', 'death')
+    } else if (this.can_escape() === true) {
+      this.escape_button.innerHTML = 'Run'
+      this.element.setAttribute('class', 'unlocked')
+    } else {
+      this.escape_button.innerHTML = 'Locked'
+      this.element.setAttribute('class', 'locked')
+    }
+
+    this.health.clear_event()
+    this.shield.clear_event()
+    this.experience.clear_event()
+
+    this.health.update()
+    this.shield.update()
+    this.experience.update()
+  }
+
+  this.can_escape = function () {
+    // Basic Overrides
+    if (this.health.value < 1) { return true } // Death
+    if (this.experience.value === 0) { return true } // New Game
+
+    // - All monsters have been delt with. (Easy Mode)
+    // - The player has not escaped the previous room. (Normal Mode)
+    // - There is only one card left in the room. (Hard Mode)
+    // - Can never escape. (Expert Mode)
+
+    // Easy
+    if (donsol.difficulty == 0) {
+      if (!this.has_escaped) { return true }
+      if (donsol.board.has_monsters()) { console.warn('Monsters present.'); return false }
+      return true
+    }
+
+    // Normal
+    if (donsol.difficulty == 1) {
+      if (!this.has_escaped) { return true }
+      if (donsol.board.has_monsters()) { console.warn('Monsters present.'); return false }
+      return true
+    }
+
+    // Hard
+    if (donsol.difficulty == 2) {
+      if (!this.has_escaped) { return true }
+      if (!donsol.board.cards_flipped().length != 3) { console.warn('Cards remain.'); return false }
+      if (donsol.board.has_monsters()) { console.warn('Monsters present.'); return false }
+      return true
+    }
+
+    // Expert
+    if (donsol.difficulty == 3) {
+      console.warn('Cannot escape(expert).')
+      return false
+    }
+
+    return false
+  }
+}
diff --git a/sources/scripts/speaker.js b/sources/scripts/speaker.js
new file mode 100644 (file)
index 0000000..672ce0d
--- /dev/null
@@ -0,0 +1,28 @@
+'use strict'
+
+function Speaker () {
+  this.effect = new Audio()
+
+  this.audio_catalog = {}
+
+  this.is_muted = false
+
+  this.play_effect = function (name) {
+    this.effect = this.load(name, 'effect', `media/audio/effect/${name}.ogg`)
+    this.effect.play()
+  }
+
+  this.load = function (name, role, src, loop = false) {
+    const audio_id = role + '_' + name
+    if (!(audio_id in this.audio_catalog)) {
+      const audio = new Audio()
+      audio.name = name
+      audio.src = src
+      audio.loop = loop
+      audio.mute = 'muted'
+      this.audio_catalog[audio_id] = audio
+    }
+    this.audio_catalog[audio_id].currentTime = 0
+    return this.audio_catalog[audio_id]
+  }
+}
diff --git a/sources/scripts/timeline.js b/sources/scripts/timeline.js
new file mode 100644 (file)
index 0000000..bc10843
--- /dev/null
@@ -0,0 +1,16 @@
+'use strict'
+
+function Timeline () {
+  this.el = document.createElement('div')
+  this.el.id = 'timeline'
+
+  this.install = function (host) {
+    host.appendChild(this.el)
+  }
+
+  this.add_event = function (message) {
+    this.el.className = ''
+    this.el.style.opacity = '0'
+    setTimeout(() => { this.el.style.opacity = 1; this.el.innerHTML = message }, 100)
+  }
+}
diff --git a/sources/scripts/walkthrough.js b/sources/scripts/walkthrough.js
new file mode 100644 (file)
index 0000000..d033d88
--- /dev/null
@@ -0,0 +1,103 @@
+'use strict'
+
+function Walkthrough () {
+  this.is_running = false
+  this.speed = 2500
+
+  this.start = function () {
+    console.log('Started walkthrough')
+    this.is_running = true
+  }
+
+  this.run = function (force = false) {
+    if (!this.is_running && !force) { return } // Idle
+    if (donsol.player.health.value < 1) { this.is_running = false; return }
+
+    const results = this.rate_room(donsol.board.room)
+    const target = results[0]
+
+    // Return if going to waste potions
+    if (target && target[1] < -10 && donsol.player.can_escape()) {
+      donsol.player.escape_room()
+      return
+    }
+
+    if (target) {
+      donsol.board.room[target[[0]]].touch()
+    }
+  }
+
+  this.rate_room = function (room) {
+    const a = []
+    for (const id in room) {
+      const card = room[id]
+      if (card.is_flipped) { continue }
+      a.push(this.rate_card(id, card))
+    }
+    return a.sort(function (a, b) {
+      return a[1] - b[1]
+    }).reverse()
+  }
+
+  this.rate_card = function (id, card) {
+    let rating = 0
+    if (card.type == 'diamond') {
+      if (donsol.player.shield.value > 0) {
+        rating = donsol.player.shield.value - card.value
+      } else {
+        rating = card.value
+      }
+    }
+    if (card.type == 'heart') {
+      // Will waste
+      if (!donsol.player.can_drink || donsol.player.health.value == 21) {
+        rating = -card.value * 4
+      } else {
+        const after = clamp(donsol.player.health.value + card.value, 0, 21)
+        const actual = (donsol.player.health.value - after)
+        rating = actual - card.value
+      }
+    }
+    if (card.type == 'clove' || card.type == 'spade') {
+      const strongest = this.find_strongest(id)
+      if (card.value < strongest.value) {
+        rating = -strongest.value - card.value
+      } else {
+        rating = -card.value
+      }
+
+      if (donsol.player.shield.limit > card.value) {
+        rating = donsol.player.shield.limit
+      }
+    }
+    // TODO: Run
+    // TODO: Attack in descending order
+    // TODO: Don't waste shields
+    return [parseInt(id), rating, card]
+  }
+
+  this.find_strongest = function () {
+    let strongest = null
+
+    for (const id in donsol.board.room) {
+      const card = donsol.board.room[id]
+      if (card.type == 'diamond' || card.type == 'heart') { continue }
+      if (card.is_flipped) { continue }
+      if (!strongest) { strongest = card; continue }
+      if (card.value > strongest.value) { strongest = card }
+    }
+    return strongest
+  }
+
+  setInterval(() => { donsol.walkthrough.run() }, this.speed)
+  function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
+}
+
+document.onkeyup = (e) => {
+  if (e.ctrlKey && e.key.toLowerCase() == 'k') {
+    donsol.walkthrough.start()
+  }
+  if (e.ctrlKey && e.key.toLowerCase() == 'l') {
+    donsol.walkthrough.run(true)
+  }
+}