├── .editorconfig
├── .gitignore
├── ADVENTURE-DESIGN.md
├── EVENT-HANDERS.md
├── LICENSE
├── PORTING-CLASSIC-ADVENTURES.md
├── PORTING-EDX-ADVENTURES.md
├── Pipfile
├── Pipfile.lock
├── README.md
├── adventure
├── __init__.py
├── admin.py
├── api
│ ├── __init__.py
│ ├── designer
│ │ ├── __init__.py
│ │ ├── serializers.py
│ │ └── views.py
│ └── game
│ │ ├── __init__.py
│ │ ├── serializers.py
│ │ └── views.py
├── apps.py
├── data
│ ├── 001-the-beginners-cave.json
│ ├── 002-lair-of-the-minotaur.json
│ ├── 003-the-cave-of-the-mind.json
│ ├── 008-abductors-quarters.json
│ ├── 010-the-magic-kingdom.json
│ ├── 013-the-caves-of-treasure-island.json
│ ├── 014-furioso.json
│ ├── 023-temple-of-ngurct.json
│ ├── 026-assault-on-the-mole-man.json
│ ├── 027-revenge-of-the-mole-man.json
│ ├── 033-orb-of-polaris.json
│ ├── 035-lair-of-mutants.json
│ ├── 044-escape-from-the-orc-lair.json
│ ├── 045-swordquest.json
│ ├── 052-the-devils-dungeon.json
│ ├── 057-manxome-foe.json
│ ├── 069-black-castle-of-nagog.json
│ ├── 077-temple-of-the-trolls.json
│ ├── 078-princes-tavern.json
│ ├── 107-last-dragon.json
│ ├── 108-mines-of-moria.json
│ ├── 109-forest-of-fear.json
│ ├── 115-ring-of-doom.json
│ ├── 140-beginners-forest.json
│ ├── 194-attack-of-the-kretons.json
│ ├── 195-the-training-ground.json
│ ├── 206-curse-of-the-hellsblade.json
│ ├── 213-demongate.json
│ ├── 215-treasure-island.json
│ ├── 216-pirates-cave.json
│ ├── 230-well-of-the-great-ones.json
│ ├── 245-draculas-chateau.json
│ ├── 246-sword-of-inari.json
│ ├── 252-cliffs-of-fire.json
│ ├── 268-eamon-deluxe-50-demo-adventure.json
│ ├── 273-stronghold-of-kahr-dur.json
│ ├── 274-treachery-of-zorag.json
│ ├── 275-clone-master.json
│ └── 277-malleus-maleficarum.json
├── import_utils.py
├── management
│ └── commands
│ │ ├── dump_adventure.py
│ │ ├── import.py
│ │ ├── import_classic.py
│ │ ├── import_classic7.py
│ │ ├── import_hints.py
│ │ └── import_json.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20160220_2256.py
│ ├── 0003_auto_20160223_0003.py
│ ├── 0004_auto_20160223_0044.py
│ ├── 0005_auto_20160305_1457.py
│ ├── 0006_effect_style.py
│ ├── 0007_auto_20160306_0055.py
│ ├── 0008_auto_20160320_2237.py
│ ├── 0009_adventure_slug.py
│ ├── 0010_auto_20160327_2227.py
│ ├── 0011_auto_20160327_2346.py
│ ├── 0012_adventure_edx_program_file.py
│ ├── 0013_auto_20160403_0015.py
│ ├── 0014_auto_20160419_2324.py
│ ├── 0015_auto_20160503_2339.py
│ ├── 0016_auto_20160504_0112.py
│ ├── 0017_adventure_active.py
│ ├── 0018_artifact_armor_type.py
│ ├── 0019_artifact_clothing_type.py
│ ├── 0020_auto_20160530_0036.py
│ ├── 0021_artifact_hidden.py
│ ├── 0023_auto_20160601_2350.py
│ ├── 0024_hint_hintanswer.py
│ ├── 0025_auto_20161029_2305.py
│ ├── 0026_player_uuid.py
│ ├── 0027_auto_20170114_1143.py
│ ├── 0028_auto_20170114_1230.py
│ ├── 0029_auto_20170114_1241.py
│ ├── 0030_adventure_full_description.py
│ ├── 0031_auto_20170119_2221.py
│ ├── 0032_artifact_armor_penalty.py
│ ├── 0033_playerartifact_value.py
│ ├── 0034_adventure_dead_body_id.py
│ ├── 0035_auto_20170206_0019.py
│ ├── 0036_activitylog.py
│ ├── 0037_auto_20170330_2232.py
│ ├── 0038_auto_20170330_2246.py
│ ├── 0039_auto_20170423_0043.py
│ ├── 0040_auto_20170423_0052.py
│ ├── 0041_auto_20170530_0035.py
│ ├── 0042_activitylog_value.py
│ ├── 0043_auto_20170813_1501.py
│ ├── 0044_auto_20180124_2241.py
│ ├── 0045_auto_20180127_1627.py
│ ├── 0046_auto_20180128_0913.py
│ ├── 0047_user.py
│ ├── 0048_auto_20180304_1832.py
│ ├── 0049_adventure_featured_month_squashed_0051_adventure_date_published.py
│ ├── 0050_monster_special.py
│ ├── 0051_hintanswer_spoiler.py
│ ├── 0052_auto_20190215_2228.py
│ ├── 0053_auto_20190217_2341.py
│ ├── 0054_auto_20190412_2346.py
│ ├── 0055_auto_20190522_2239.py
│ ├── 0056_auto_20190526_2048.py
│ ├── 0057_auto_20190526_2107.py
│ ├── 0058_auto_20190703_2149.py
│ ├── 0059_auto_20190706_1517.py
│ ├── 0060_auto_20191002_0102.py
│ ├── 0061_auto_20191213_0007.py
│ ├── 0062_auto_20200501_0144.py
│ ├── 0063_monster_combat_verbs.py
│ ├── 0064_auto_20200529_0136.py
│ ├── 0065_auto_20200529_1607.py
│ ├── 0066_auto_20200726_2318.py
│ ├── 0067_roomexit_hintanswer_adventure_id.py
│ └── __init__.py
├── models.py
├── static
│ ├── adventures
│ │ ├── malleus-maleficarum
│ │ │ └── virrat-map.jpg
│ │ └── the-caves-of-treasure-island
│ │ │ ├── Treasure-Island-map.jpg
│ │ │ └── treasure-island-map.png
│ ├── css
│ │ └── bootstrap.min.css
│ └── images
│ │ ├── Eamon_dragon_NEUC.png
│ │ ├── Eamon_dragon_facebook.png
│ │ ├── favicon
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon.ico
│ │ └── site.webmanifest
│ │ ├── parchment
│ │ ├── center.png
│ │ └── parchment-border.png
│ │ ├── ravenmore
│ │ └── 128
│ │ │ ├── Boots.png
│ │ │ ├── armor.png
│ │ │ ├── armor2.png
│ │ │ ├── axe.png
│ │ │ ├── axe2.png
│ │ │ ├── axeDouble.png
│ │ │ ├── axeDouble2.png
│ │ │ ├── backpack.png
│ │ │ ├── backpack_open.png
│ │ │ ├── bow.png
│ │ │ ├── bow2.png
│ │ │ ├── bow_arrow_only.png
│ │ │ ├── bow_bow_only.png
│ │ │ ├── coin.png
│ │ │ ├── dagger.png
│ │ │ ├── dagger2.png
│ │ │ ├── document.png
│ │ │ ├── envelope.png
│ │ │ ├── gem.png
│ │ │ ├── gemBlue.png
│ │ │ ├── gemGreen.png
│ │ │ ├── gemRed.png
│ │ │ ├── hammer.png
│ │ │ ├── hammer2.png
│ │ │ ├── heart.png
│ │ │ ├── helmet.png
│ │ │ ├── helmet2.png
│ │ │ ├── leather.png
│ │ │ ├── leather2.png
│ │ │ ├── map - Copy.png
│ │ │ ├── map.png
│ │ │ ├── map_empty.png
│ │ │ ├── necklace.png
│ │ │ ├── potion.png
│ │ │ ├── potion2.png
│ │ │ ├── potion3.png
│ │ │ ├── potion4.png
│ │ │ ├── potionBlue.png
│ │ │ ├── potionGreen.png
│ │ │ ├── potionRed.png
│ │ │ ├── potion_empty.png
│ │ │ ├── ring.png
│ │ │ ├── scroll.png
│ │ │ ├── shield.png
│ │ │ ├── shield2.png
│ │ │ ├── shieldSmall.png
│ │ │ ├── shieldSmall2.png
│ │ │ ├── shield_semi.png
│ │ │ ├── shield_wood.png
│ │ │ ├── star.png
│ │ │ ├── sword.png
│ │ │ ├── sword2.png
│ │ │ ├── swordWood.png
│ │ │ ├── tome.png
│ │ │ ├── tome_amber.png
│ │ │ ├── tome_azure.png
│ │ │ ├── tome_emerald.png
│ │ │ ├── tools.png
│ │ │ ├── tools_hammer.png
│ │ │ ├── upg_spear.png
│ │ │ ├── wand.png
│ │ │ ├── wand2.png
│ │ │ ├── woodSword.png
│ │ │ └── x.png
│ │ ├── sf_dustywall02.jpg
│ │ └── sf_dustywall02_border.jpg
├── templates
│ ├── _footer.html
│ ├── _google_analytics.html
│ ├── about.html
│ ├── adventure-list.html
│ ├── adventure.html
│ ├── base.html
│ ├── index.html
│ ├── main-hall.html
│ ├── manual.html
│ └── privacy.html
├── tests.py
├── urls.py
└── views.py
├── client
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── adventures
│ ├── abductors-quarters
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── assault-on-the-mole-man
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── attack-of-the-kretons
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── base-adventure
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── beginners-forest
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── black-castle-of-nagog
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── cliffs-of-fire
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── clone-master
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── curse-of-the-hellsblade
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── demo1
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ ├── index.ts
│ │ └── mock-data
│ │ │ └── rooms.ts
│ ├── demongate
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── draculas-chateau
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── eamon-deluxe-50-demo-adventure
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── escape-from-mt-moon
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── escape-from-the-orc-lair
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── forest-of-fear
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── furioso
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── iron-prison
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── lair-of-mutants
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── lair-of-the-minotaur
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── last-dragon
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── malleus-maleficarum
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── manxome-foe
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── mines-of-moria
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── museum-of-unnatural-history
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── orb-of-polaris
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── pirates-cave
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── princes-tavern
│ │ ├── commands.spec.ts
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── quest-for-the-holy-grail
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── revenge-of-the-mole-man
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── ring-of-doom
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── stronghold-of-kahr-dur
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── sword-of-inari
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── swordquest
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── temple-of-ngurct
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── temple-of-the-trolls
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── the-beginners-cave
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── the-cave-of-the-mind
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── the-caves-of-treasure-island
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── the-devils-dungeon
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── the-magic-kingdom
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── the-training-ground
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ ├── treachery-of-zorag
│ │ ├── commands.ts
│ │ ├── custom-data.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ ├── functions.ts
│ │ └── index.ts
│ ├── treasure-island
│ │ ├── commands.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
│ └── well-of-the-great-ones
│ │ ├── commands.ts
│ │ ├── event-handlers.spec.ts
│ │ ├── event-handlers.ts
│ │ └── index.ts
├── babel.config.js
├── build
│ └── static
│ │ └── mock-data
│ │ ├── adventure.json
│ │ ├── artifacts.json
│ │ ├── effects.json
│ │ ├── monsters.json
│ │ ├── player.json
│ │ └── rooms.json
├── core
│ ├── commands
│ │ ├── base-command.ts
│ │ ├── core-commands.ts
│ │ ├── event-handler.ts
│ │ └── optional-commands.ts
│ ├── components
│ │ ├── CommandList.tsx
│ │ ├── CommandPrompt.tsx
│ │ ├── Hints.tsx
│ │ ├── History.tsx
│ │ ├── HowToPlay.tsx
│ │ ├── IntroText.tsx
│ │ ├── MainProgram.tsx
│ │ ├── Question.tsx
│ │ ├── SamSlicker.tsx
│ │ └── Status.tsx
│ ├── index.tsx
│ ├── models
│ │ ├── artifact.spec.ts
│ │ ├── artifact.ts
│ │ ├── command-parser.ts
│ │ ├── effect.ts
│ │ ├── game-object.ts
│ │ ├── game.spec.ts
│ │ ├── game.ts
│ │ ├── hint.ts
│ │ ├── history-entry.spec.ts
│ │ ├── history-entry.ts
│ │ ├── history-manager.spec.ts
│ │ ├── history-manager.ts
│ │ ├── loadable.ts
│ │ ├── modal.ts
│ │ ├── monster.combat.spec.ts
│ │ ├── monster.group.spec.ts
│ │ ├── monster.spec.ts
│ │ ├── monster.ts
│ │ ├── operations-queue.ts
│ │ ├── room.spec.ts
│ │ └── room.ts
│ ├── repositories
│ │ ├── artifact-repo.spec.ts
│ │ ├── artifact.repo.ts
│ │ ├── effect.repo.ts
│ │ ├── hint.repo.ts
│ │ ├── monster-repo.spec.ts
│ │ ├── monster.repo.ts
│ │ └── room.repo.ts
│ ├── types.ts
│ └── utils
│ │ ├── command.exception.ts
│ │ ├── index.ts
│ │ ├── logger.interface.ts
│ │ ├── logger.ts
│ │ ├── saved-game.interface.ts
│ │ └── testing.ts
├── cypress.json
├── cypress
│ ├── fixtures
│ │ ├── adv1
│ │ │ ├── adventure.json
│ │ │ ├── artifacts.json
│ │ │ ├── effects.json
│ │ │ ├── monsters.json
│ │ │ ├── player.json
│ │ │ └── rooms.json
│ │ ├── adventures.json
│ │ ├── character.json
│ │ └── characters.json
│ ├── integration
│ │ ├── adventure-list.spec.js
│ │ ├── adventure.spec.js
│ │ ├── character-creation.spec.js
│ │ ├── main-hall.spec.js
│ │ └── shop.spec.js
│ ├── plugins
│ │ └── index.js
│ └── support
│ │ ├── commands.js
│ │ ├── index.js
│ │ └── page_objects
│ │ ├── adventurePage.js
│ │ ├── mainHallPage.js
│ │ └── shopPage.js
├── designer
│ ├── components
│ │ ├── AdventureDetail.tsx
│ │ ├── AdventureHeading.tsx
│ │ ├── AdventureList.test.tsx
│ │ ├── AdventureList.tsx
│ │ ├── AdventureMainMenu.tsx
│ │ ├── ArtifactDetail.tsx
│ │ ├── ArtifactList.tsx
│ │ ├── Designer.tsx
│ │ ├── EffectDetail.tsx
│ │ ├── EffectList.tsx
│ │ ├── Login.tsx
│ │ ├── MonsterDetail.tsx
│ │ ├── MonsterList.tsx
│ │ ├── RoomDetail.tsx
│ │ ├── RoomList.tsx
│ │ ├── common.test.tsx
│ │ ├── common.tsx
│ │ └── fields.tsx
│ ├── constants.ts
│ ├── contexts
│ │ ├── adventure.tsx
│ │ ├── form.ts
│ │ └── user.ts
│ ├── index.tsx
│ ├── models
│ │ ├── adventure.ts
│ │ ├── artifact.ts
│ │ ├── effect.ts
│ │ ├── game-object.ts
│ │ ├── hint.ts
│ │ ├── loadable.ts
│ │ ├── monster.ts
│ │ └── room.ts
│ ├── repositories
│ │ ├── artifact.repo.ts
│ │ ├── base.repo.ts
│ │ ├── effect.repo.ts
│ │ ├── hint.repo.ts
│ │ ├── monster.repo.ts
│ │ └── room.repo.ts
│ ├── test-utils.tsx
│ └── types.ts
├── jest.config.mjs
├── jest.setup.js
├── main-hall
│ ├── components
│ │ ├── AdventureList.tsx
│ │ ├── Bank.tsx
│ │ ├── MainHall.tsx
│ │ ├── PlayerCreate.tsx
│ │ ├── PlayerDetail.tsx
│ │ ├── PlayerList.tsx
│ │ ├── PlayerListItem.tsx
│ │ ├── PlayerMenu.tsx
│ │ ├── SavedGameTile.tsx
│ │ ├── Shop
│ │ │ ├── ArtifactTile.tsx
│ │ │ ├── Shop.tsx
│ │ │ └── shopItems.ts
│ │ ├── Status.tsx
│ │ ├── Witch
│ │ │ ├── AttributeRow.tsx
│ │ │ └── Witch.tsx
│ │ └── Wizard
│ │ │ ├── SpellListRow.tsx
│ │ │ └── Wizard.tsx
│ ├── hooks.ts
│ ├── index.tsx
│ ├── models
│ │ ├── adventure.ts
│ │ ├── artifact.ts
│ │ ├── game-object.ts
│ │ └── player.ts
│ ├── registerServiceWorker.ts
│ ├── store
│ │ ├── index.ts
│ │ └── player.ts
│ ├── tests
│ │ ├── MainHall.test.tsx
│ │ └── Player.test.ts
│ └── utils
│ │ ├── api.ts
│ │ ├── dice.ts
│ │ └── index.ts
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── scss
│ └── style.scss
├── tsconfig.json
├── tsconfig.prod.json
├── tsconfig.test.json
├── tslint.json
└── webpack.config.js
├── db
├── eamon.sqlite3.dist
├── post-import-fixes.sql
├── query magic wand type weapons.sql
└── room exits for adventure.sql
├── designer
├── __init__.py
├── apps.py
├── templates
│ └── designer.html
├── urls.py
└── views.py
├── eamon
├── local_settings_example.py
├── settings.py
├── urls.py
└── wsgi.py
├── fabfile.py
├── manage.py
├── news
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_auto_20170527_0125.py
│ └── __init__.py
├── models.py
├── templates
│ └── news.html
├── tests.py
├── urls.py
└── views.py
├── player
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_savedgame_created.py
│ ├── 0003_rating.py
│ ├── 0004_player_playerartifact_playerprofile.py
│ ├── 0005_move_player_data.py
│ ├── 0006_alter_savedgame_player.py
│ ├── 0007_playerprofile_slug.py
│ ├── 0008_activitylog.py
│ ├── 0009_move_activity_log.py
│ ├── 0010_alter_savedgame_player.py
│ └── __init__.py
├── models.py
├── serializers.py
├── urls.py
└── views.py
├── sample_import
├── README.md
├── artifacts.json
├── effects.json
├── monsters.json
└── rooms.json
├── static
└── .gitkeep
└── truncate.sql
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | # From the Django .editorconfig: https://github.com/django/django/blob/master/.editorconfig
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 4
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 | end_of_line = lf
13 | charset = utf-8
14 |
15 | # Use 2 spaces for the HTML files
16 | [*.html]
17 | indent_size = 2
18 |
19 | # The JSON files contain newlines inconsistently
20 | [*.json]
21 | indent_size = 2
22 | insert_final_newline = ignore
23 |
24 | [**/admin/js/vendor/**]
25 | indent_style = ignore
26 | indent_size = ignore
27 |
28 | # Minified JavaScript files shouldn't be changed
29 | [**.min.js]
30 | indent_style = ignore
31 | insert_final_newline = ignore
32 |
33 | # Makefiles always use tabs for indentation
34 | [Makefile]
35 | indent_style = tab
36 |
37 | # Batch files use tabs for indentation
38 | [*.bat]
39 | indent_style = tab
40 |
41 | # Custom settings for CSS
42 |
43 | # Use 2 spaces for SCSS files
44 | [*.scss]
45 | indent_size = 2
46 |
47 | # Compiled CSS files shouldn't be changed
48 | [*.css]
49 | indent_style = ignore
50 | insert_final_newline = ignore
51 |
52 | # From the Angular2 .editorconfig: https://github.com/angular/angular/blob/master/.editorconfig
53 |
54 | # Use 2 spaces for TypeScript files
55 | [*.js]
56 | indent_size = 2
57 | [*.ts]
58 | indent_size = 2
59 | [*.tsx]
60 | indent_size = 2
61 |
62 | [*.md]
63 | insert_final_newline = false
64 | trim_trailing_whitespace = false
65 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /nbproject/
2 | /static/node_modules/
3 | /static/build/
4 | /client/build/
5 | **/**/*.js
6 | !/client/cypress/**/*.js
7 | !/client/*.js
8 | **/**/*.js.map
9 | **/__pycache__/
10 | /.idea/
11 | venv
12 | db/*
13 | eamon/local_settings.py
14 | static/*
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2017 Keith Dechant http://terranok.com
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | url = "https://pypi.org/simple"
3 | verify_ssl = true
4 | name = "pypi"
5 |
6 | [packages]
7 | bleach = "~=3.2"
8 | chardet = "~=4.0"
9 | Django = "~=3.2.9"
10 | django-braces = "~=1.13"
11 | django-ckeditor = "~=6.1.0"
12 | django-cors-middleware = "~=1.5.0"
13 | django-debug-toolbar = "~=3.2.2"
14 | django-filter = "~=2.4"
15 | django-mptt = "~=0.12"
16 | django-rest-swagger = "~=2.2"
17 | django-settings-export = "==1.2.1"
18 | django-taggit = "~=1.3"
19 | django-taggit-serializer = "~=0.1"
20 | djangorestframework = "~=3.12.4"
21 | djangorestframework-simplejwt = "==4.8.0"
22 | "html5lib" = "==1.1"
23 | fabric = "~=3.2.2"
24 | regex = "~=2024.11.6"
25 | requests = "~=2.26.0"
26 | requests-oauthlib = "~=1.3.0"
27 | setuptools = "*"
28 | six = "~=1.17.0"
29 | sqlparse = "~=0.4.2"
30 | PyYAML = "~=6.0.2"
31 |
32 | [dev-packages]
33 |
34 | [pipenv]
35 | allow_prereleases = true
36 |
--------------------------------------------------------------------------------
/adventure/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/__init__.py
--------------------------------------------------------------------------------
/adventure/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/api/__init__.py
--------------------------------------------------------------------------------
/adventure/api/designer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/api/designer/__init__.py
--------------------------------------------------------------------------------
/adventure/api/game/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/api/game/__init__.py
--------------------------------------------------------------------------------
/adventure/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AdventureConfig(AppConfig):
5 | name = 'adventure'
6 |
--------------------------------------------------------------------------------
/adventure/import_utils.py:
--------------------------------------------------------------------------------
1 | import regex
2 |
3 |
4 | def sentence_case(string):
5 | """
6 | Converts a string to sentence case.
7 | From http://stackoverflow.com/questions/39969202/convert-uppercase-string-to-sentence-case-in-python
8 | Args:
9 | string: The input string
10 |
11 | Returns:
12 | The string, now in sentence case
13 | """
14 | return '. '.join(i.capitalize() for i in string.split('. '))
15 |
16 |
17 | def fix_40char_text(text):
18 | return sentence_case(regex.sub(r'\s{2,}', " ", text))
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0002_auto_20160220_2256.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.1 on 2016-02-21 06:56
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0001_initial'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='is_worn',
18 | field=models.BooleanField(default=False),
19 | ),
20 | migrations.AddField(
21 | model_name='monster',
22 | name='count',
23 | field=models.IntegerField(default=1),
24 | ),
25 | migrations.AddField(
26 | model_name='monster',
27 | name='original_group_size',
28 | field=models.IntegerField(default=1),
29 | ),
30 | migrations.AlterField(
31 | model_name='monster',
32 | name='room_id',
33 | field=models.IntegerField(null=True),
34 | ),
35 | ]
36 |
--------------------------------------------------------------------------------
/adventure/migrations/0004_auto_20160223_0044.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.1 on 2016-02-23 08:44
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0003_auto_20160223_0003'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='adventure',
17 | name='edx',
18 | field=models.CharField(max_length=50, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0005_auto_20160305_1457.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-03-05 22:57
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0004_auto_20160223_0044'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='directions',
18 | field=models.IntegerField(default=6),
19 | ),
20 | migrations.AddField(
21 | model_name='adventure',
22 | name='edx_version',
23 | field=models.FloatField(blank=True, default=0, null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0006_effect_style.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-03-06 08:02
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0005_auto_20160305_1457'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='effect',
17 | name='style',
18 | field=models.TextField(max_length=20, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0008_auto_20160320_2237.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-03-21 05:37
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0007_auto_20160306_0055'),
12 | ]
13 |
14 | operations = [
15 | migrations.RenameField(
16 | model_name='roomexit',
17 | old_name='key_id',
18 | new_name='door_id',
19 | ),
20 | migrations.AddField(
21 | model_name='artifact',
22 | name='key_id',
23 | field=models.IntegerField(help_text='If a container or door, the artifact ID of the key that opens it', null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0009_adventure_slug.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-03-24 06:15
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0008_auto_20160320_2237'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='slug',
18 | field=models.SlugField(null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0010_auto_20160327_2227.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-03-28 05:27
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0009_adventure_slug'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='guard_id',
18 | field=models.IntegerField(help_text='If a bound monster, the ID of a monster that prevents the player from freeing it', null=True),
19 | ),
20 | migrations.AlterField(
21 | model_name='artifact',
22 | name='key_id',
23 | field=models.IntegerField(help_text='If a container, door, or bound monster, the artifact ID of the key that opens it', null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0011_auto_20160327_2346.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-03-28 06:46
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0010_auto_20160327_2227'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='effect_id',
18 | field=models.IntegerField(help_text='First effect ID for Readable artifacts', null=True),
19 | ),
20 | migrations.AddField(
21 | model_name='artifact',
22 | name='num_effects',
23 | field=models.IntegerField(help_text='Number of effects for Readable artifacts (legacy)', null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0012_adventure_edx_program_file.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-04-03 04:11
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0011_auto_20160327_2346'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='edx_program_file',
18 | field=models.CharField(max_length=50, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0013_auto_20160403_0015.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-04-03 07:15
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0012_adventure_edx_program_file'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='synonyms',
18 | field=models.CharField(max_length=255, null=True),
19 | ),
20 | migrations.AddField(
21 | model_name='monster',
22 | name='synonyms',
23 | field=models.CharField(max_length=255, null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0014_auto_20160419_2324.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.2 on 2016-04-20 06:24
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0013_auto_20160403_0015'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='playerartifact',
17 | name='hands',
18 | field=models.IntegerField(choices=[(1, 'One-handed'), (2, 'Two-handed')], default=1),
19 | ),
20 | migrations.AddField(
21 | model_name='playerartifact',
22 | name='weight',
23 | field=models.IntegerField(default=0),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0015_auto_20160503_2339.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.5 on 2016-05-04 06:39
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0014_auto_20160419_2324'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='player',
17 | name='gender',
18 | field=models.CharField(choices=[('m', 'Male'), ('f', 'Female')], max_length=6),
19 | ),
20 | migrations.AlterField(
21 | model_name='playerartifact',
22 | name='dice',
23 | field=models.IntegerField(default=1, null=True),
24 | ),
25 | migrations.AlterField(
26 | model_name='playerartifact',
27 | name='odds',
28 | field=models.IntegerField(default=0, null=True),
29 | ),
30 | migrations.AlterField(
31 | model_name='playerartifact',
32 | name='sides',
33 | field=models.IntegerField(default=1, null=True),
34 | ),
35 | migrations.AlterField(
36 | model_name='playerartifact',
37 | name='weapon_type',
38 | field=models.IntegerField(choices=[(1, 'Axe'), (2, 'Bow'), (3, 'Club'), (4, 'Spear'), (5, 'Sword')], default=0, null=True),
39 | ),
40 | ]
41 |
--------------------------------------------------------------------------------
/adventure/migrations/0016_auto_20160504_0112.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.5 on 2016-05-04 08:12
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0015_auto_20160503_2339'),
12 | ]
13 |
14 | operations = [
15 | migrations.RenameField(
16 | model_name='playerartifact',
17 | old_name='odds',
18 | new_name='weapon_odds',
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0017_adventure_active.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.5 on 2016-05-08 07:41
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0016_auto_20160504_0112'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='active',
18 | field=models.BooleanField(default=0),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0018_artifact_armor_type.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-05-30 03:42
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0017_adventure_active'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='armor_type',
18 | field=models.IntegerField(choices=[(0, 'Armor'), (1, 'Shield')], null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0019_artifact_clothing_type.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-05-30 04:33
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0018_artifact_armor_type'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='clothing_type',
18 | field=models.IntegerField(choices=[(0, 'Clothes or Armor/Shield'), (1, 'Coats, Capes, etc.'), (2, 'Shoes, boots'), (3, 'Gloves'), (4, 'Hats, headwear'), (5, 'Jewelry'), (6, 'Undergarments')], null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0020_auto_20160530_0036.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-05-30 07:36
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0019_artifact_clothing_type'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='playerartifact',
17 | name='armor_class',
18 | field=models.IntegerField(default=0, null=True),
19 | ),
20 | migrations.AlterField(
21 | model_name='playerartifact',
22 | name='armor_penalty',
23 | field=models.IntegerField(default=0, null=True),
24 | ),
25 | migrations.AlterField(
26 | model_name='playerartifact',
27 | name='armor_type',
28 | field=models.IntegerField(choices=[(0, 'Armor'), (1, 'Shield')], default=0, null=True),
29 | ),
30 | ]
31 |
--------------------------------------------------------------------------------
/adventure/migrations/0021_artifact_hidden.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-05-30 08:11
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0020_auto_20160530_0036'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='hidden',
18 | field=models.BooleanField(default=False),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0023_auto_20160601_2350.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.9.6 on 2016-06-02 06:50
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0021_artifact_hidden'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='hardiness',
18 | field=models.IntegerField(help_text='If a door or container that must be smashed open, how much damage does it take to open it?', null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0024_hint_hintanswer.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.2 on 2016-10-29 06:13
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('adventure', '0023_auto_20160601_2350'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Hint',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('index', models.IntegerField(null=True)),
21 | ('edx', models.CharField(max_length=50, null=True)),
22 | ('question', models.CharField(max_length=255)),
23 | ('adventure', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hints', to='adventure.Adventure')),
24 | ],
25 | ),
26 | migrations.CreateModel(
27 | name='HintAnswer',
28 | fields=[
29 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
30 | ('index', models.IntegerField(null=True)),
31 | ('answer', models.TextField(max_length=1000)),
32 | ('hint', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='adventure.Hint')),
33 | ],
34 | ),
35 | ]
36 |
--------------------------------------------------------------------------------
/adventure/migrations/0025_auto_20161029_2305.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.2 on 2016-10-30 06:05
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0024_hint_hintanswer'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='first_hint',
18 | field=models.IntegerField(null=True),
19 | ),
20 | migrations.AddField(
21 | model_name='adventure',
22 | name='last_hint',
23 | field=models.IntegerField(null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0026_player_uuid.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2016-11-05 07:49
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0025_auto_20161029_2305'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='player',
17 | name='uuid',
18 | field=models.CharField(max_length=255, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0027_auto_20170114_1143.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-01-14 19:43
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import taggit.managers
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('taggit', '0002_auto_20150616_2121'),
13 | ('adventure', '0026_player_uuid'),
14 | ]
15 |
16 | operations = [
17 | migrations.AddField(
18 | model_name='adventure',
19 | name='intro_text',
20 | field=models.TextField(null=True),
21 | ),
22 | migrations.AddField(
23 | model_name='adventure',
24 | name='tags',
25 | field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
26 | ),
27 | ]
28 |
--------------------------------------------------------------------------------
/adventure/migrations/0028_auto_20170114_1230.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-01-14 20:30
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import taggit.managers
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('adventure', '0027_auto_20170114_1143'),
13 | ]
14 |
15 | operations = [
16 | migrations.AlterModelOptions(
17 | name='adventure',
18 | options={'ordering': ['name']},
19 | ),
20 | migrations.AlterField(
21 | model_name='adventure',
22 | name='description',
23 | field=models.TextField(blank=True, null=True),
24 | ),
25 | migrations.AlterField(
26 | model_name='adventure',
27 | name='intro_text',
28 | field=models.TextField(blank=True, null=True),
29 | ),
30 | migrations.AlterField(
31 | model_name='adventure',
32 | name='tags',
33 | field=taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
34 | ),
35 | ]
36 |
--------------------------------------------------------------------------------
/adventure/migrations/0029_auto_20170114_1241.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-01-14 20:41
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0028_auto_20170114_1230'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='adventure',
17 | name='description',
18 | field=models.TextField(blank=True, default=''),
19 | ),
20 | migrations.AlterField(
21 | model_name='adventure',
22 | name='intro_text',
23 | field=models.TextField(blank=True, default=''),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0030_adventure_full_description.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-01-14 21:38
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0029_auto_20170114_1241'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='full_description',
18 | field=models.TextField(blank=True, default=''),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0031_auto_20170119_2221.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-01-20 06:21
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0030_adventure_full_description'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='intro_question',
18 | field=models.TextField(blank=True, default='', help_text='If you want to ask the adventurer a question when they start the adventure, put the question text here. The answer will be available in the game object.'),
19 | ),
20 | migrations.AlterField(
21 | model_name='adventure',
22 | name='intro_text',
23 | field=models.TextField(blank=True, default='', help_text='Text shown to the adventurer when they begin the adventure. Use this to set up the story.'),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0032_artifact_armor_penalty.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-01-24 08:47
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0031_auto_20170119_2221'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='artifact',
17 | name='armor_penalty',
18 | field=models.IntegerField(default=0, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0033_playerartifact_value.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-01-31 07:08
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0032_artifact_armor_penalty'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='playerartifact',
17 | name='value',
18 | field=models.IntegerField(default=0),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0034_adventure_dead_body_id.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-02-02 06:28
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0033_playerartifact_value'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='adventure',
17 | name='dead_body_id',
18 | field=models.IntegerField(blank=True, default=0, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0035_auto_20170206_0019.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-02-06 08:19
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0034_adventure_dead_body_id'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='adventure',
17 | name='dead_body_id',
18 | field=models.IntegerField(blank=True, default=0, help_text='The artifact ID of the first dead body. Leave blank to not use dead body artifacts.', null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0036_activitylog.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-03-23 05:26
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('adventure', '0035_auto_20170206_0019'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='ActivityLog',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('type', models.CharField(max_length=255)),
21 | ('created', models.DateTimeField(auto_now_add=True, null=True)),
22 | ('adventure', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='activity_log', to='adventure.Adventure')),
23 | ('player', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activity_log', to='adventure.Player')),
24 | ],
25 | ),
26 | ]
27 |
--------------------------------------------------------------------------------
/adventure/migrations/0037_auto_20170330_2232.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-03-31 05:32
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0036_activitylog'),
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='Author',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('name', models.CharField(max_length=50)),
20 | ],
21 | ),
22 | migrations.AddField(
23 | model_name='adventure',
24 | name='authors',
25 | field=models.ManyToManyField(to='adventure.Author'),
26 | ),
27 | ]
28 |
--------------------------------------------------------------------------------
/adventure/migrations/0038_auto_20170330_2246.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.10.3 on 2017-03-31 05:46
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0037_auto_20170330_2232'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='adventure',
17 | name='first_hint',
18 | field=models.IntegerField(blank=True, null=True),
19 | ),
20 | migrations.AlterField(
21 | model_name='adventure',
22 | name='last_hint',
23 | field=models.IntegerField(blank=True, null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0040_auto_20170423_0052.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11 on 2017-04-23 07:52
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0039_auto_20170423_0043'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='artifact',
17 | name='armor_class',
18 | field=models.IntegerField(default=0, help_text='(Armor only) How many hits does this armor protect against?'),
19 | ),
20 | migrations.AlterField(
21 | model_name='artifact',
22 | name='armor_penalty',
23 | field=models.IntegerField(default=0, help_text='(Armor only) How much armor expertise does the player need to use this armor without penalty?', null=True),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/adventure/migrations/0042_activitylog_value.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11 on 2017-06-06 04:50
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ('adventure', '0041_auto_20170530_0035'),
12 | ]
13 |
14 | operations = [
15 | migrations.AddField(
16 | model_name='activitylog',
17 | name='value',
18 | field=models.IntegerField(blank=True, null=True),
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/adventure/migrations/0044_auto_20180124_2241.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0 on 2018-01-25 06:41
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0043_auto_20170813_1501'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='artifact',
15 | name='linked_door_id',
16 | field=models.IntegerField(blank=True, help_text='To make a two-sided door, enter the artifact ID of the other side of the door. They will open and close as a set.', null=True),
17 | ),
18 | migrations.AddField(
19 | model_name='monster',
20 | name='container_id',
21 | field=models.IntegerField(blank=True, help_text='Container artifact where this monster starts. The monster will enter the room as soon as the container is opened. e.g., a vampire who awakes when you open his coffin', null=True),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/adventure/migrations/0046_auto_20180128_0913.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0 on 2018-01-28 17:13
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('adventure', '0045_auto_20180127_1627'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='activitylog',
16 | name='player',
17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='activity_log', to='adventure.Player'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/adventure/migrations/0047_user.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.2 on 2018-02-13 07:38
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0046_auto_20180128_0913'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='User',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('social_id', models.CharField(max_length=100, null=True)),
18 | ('uuid', models.CharField(max_length=255, null=True)),
19 | ],
20 | ),
21 | ]
22 |
--------------------------------------------------------------------------------
/adventure/migrations/0048_auto_20180304_1832.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.2 on 2018-03-05 02:32
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0047_user'),
10 | ]
11 |
12 | operations = [
13 | migrations.RenameModel(
14 | old_name='User',
15 | new_name='PlayerProfile',
16 | ),
17 | ]
18 |
--------------------------------------------------------------------------------
/adventure/migrations/0049_adventure_featured_month_squashed_0051_adventure_date_published.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.2 on 2018-07-04 07:33
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0048_auto_20180304_1832'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='adventure',
15 | name='featured_month',
16 | field=models.CharField(blank=True, max_length=7, null=True),
17 | ),
18 | migrations.AddField(
19 | model_name='adventure',
20 | name='date_published',
21 | field=models.DateField(blank=True, null=True),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/adventure/migrations/0050_monster_special.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.1.1 on 2019-01-19 09:45
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0049_adventure_featured_month_squashed_0051_adventure_date_published'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='monster',
15 | name='special',
16 | field=models.CharField(blank=True, max_length=255, null=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0051_hintanswer_spoiler.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.1.1 on 2019-02-16 06:26
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0050_monster_special'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='hintanswer',
15 | name='spoiler',
16 | field=models.BooleanField(default=False, help_text='Obscure the answer until the user shows it.'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0052_auto_20190215_2228.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.1.1 on 2019-02-16 06:28
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0051_hintanswer_spoiler'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='hint',
15 | name='edx',
16 | field=models.CharField(blank=True, max_length=50, null=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0053_auto_20190217_2341.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.1.1 on 2019-02-18 07:41
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0052_auto_20190215_2228'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='artifact',
15 | name='armor_class',
16 | field=models.IntegerField(default=0, help_text='(Armor only) How many hits does this armor protect against?', null=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0054_auto_20190412_2346.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.1.7 on 2019-04-13 06:46
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0053_auto_20190217_2341'),
10 | ]
11 |
12 | operations = [
13 | migrations.RemoveField(
14 | model_name='monster',
15 | name='original_group_size',
16 | ),
17 | migrations.AddField(
18 | model_name='monster',
19 | name='name_plural',
20 | field=models.CharField(blank=True, help_text='The plural form of the name. Used only with group monsters.', max_length=255, null=True),
21 | ),
22 | ]
23 |
--------------------------------------------------------------------------------
/adventure/migrations/0055_auto_20190522_2239.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.1 on 2019-05-23 05:39
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0054_auto_20190412_2346'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='adventure',
15 | name='intro_text',
16 | field=models.TextField(blank=True, default='', help_text='Text shown to the adventurer when they begin the adventure. Use this to set up the story. Split it into multiple pages by using a line containing three hyphens as a break. Supports Markdown.'),
17 | ),
18 | migrations.AlterField(
19 | model_name='artifact',
20 | name='description',
21 | field=models.TextField(help_text='Supports Markdown.', max_length=1000),
22 | ),
23 | migrations.AlterField(
24 | model_name='effect',
25 | name='text',
26 | field=models.TextField(help_text='Supports Markdown.', max_length=65535),
27 | ),
28 | migrations.AlterField(
29 | model_name='hintanswer',
30 | name='answer',
31 | field=models.TextField(help_text='Supports Markdown.', max_length=1000),
32 | ),
33 | migrations.AlterField(
34 | model_name='monster',
35 | name='description',
36 | field=models.TextField(help_text='Supports Markdown.', max_length=1000),
37 | ),
38 | ]
39 |
--------------------------------------------------------------------------------
/adventure/migrations/0057_auto_20190526_2107.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.1 on 2019-05-27 04:07
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0056_auto_20190526_2048'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='artifact',
15 | name='is_markdown',
16 | field=models.BooleanField(choices=[(False, 'Plain text'), (True, 'Markdown')], default=0, verbose_name='Text format'),
17 | ),
18 | migrations.AlterField(
19 | model_name='effect',
20 | name='is_markdown',
21 | field=models.BooleanField(choices=[(False, 'Plain text'), (True, 'Markdown')], default=0, verbose_name='Text format'),
22 | ),
23 | migrations.AlterField(
24 | model_name='monster',
25 | name='is_markdown',
26 | field=models.BooleanField(choices=[(False, 'Plain text'), (True, 'Markdown')], default=0, verbose_name='Text format'),
27 | ),
28 | migrations.AlterField(
29 | model_name='room',
30 | name='is_markdown',
31 | field=models.BooleanField(choices=[(False, 'Plain text'), (True, 'Markdown')], default=0, verbose_name='Text format'),
32 | ),
33 | ]
34 |
--------------------------------------------------------------------------------
/adventure/migrations/0058_auto_20190703_2149.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.1 on 2019-07-04 04:49
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0057_auto_20190526_2107'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='monster',
15 | name='defense_bonus',
16 | field=models.IntegerField(default=0, help_text='Gives the monster an additional percent bonus to avoid being hit. (Rare)'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0059_auto_20190706_1517.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.1 on 2019-07-06 22:17
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0058_auto_20190703_2149'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='artifact',
15 | name='article',
16 | field=models.CharField(blank=True, help_text="Optional article or adjective that appears before the name, e.g., 'a', 'the', 'some'.", max_length=20, null=True),
17 | ),
18 | migrations.AddField(
19 | model_name='monster',
20 | name='article',
21 | field=models.CharField(blank=True, help_text="Optional article or adjective that appears before the name, e.g., 'a', 'the', 'some'. Does not apply to group monsters.", max_length=20, null=True),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/adventure/migrations/0060_auto_20191002_0102.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.5 on 2019-10-02 08:02
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0059_auto_20190706_1517'),
10 | ]
11 |
12 | operations = [
13 | migrations.RemoveField(
14 | model_name='roomexit',
15 | name='message',
16 | ),
17 | migrations.AddField(
18 | model_name='room',
19 | name='dark_description',
20 | field=models.TextField(blank=True, help_text="The description shown if the room is dark and the player doesn't have a light. Leave blank to use the standard 'it's too dark to see' message.", max_length=1000, null=True),
21 | ),
22 | migrations.AddField(
23 | model_name='room',
24 | name='dark_name',
25 | field=models.CharField(blank=True, help_text="The name shown if the room is dark and the player doesn't have a light. Leave blank to use the standard 'in the dark' message.", max_length=255, null=True),
26 | ),
27 | migrations.AddField(
28 | model_name='roomexit',
29 | name='effect_id',
30 | field=models.IntegerField(blank=True, help_text="The effect will be shown when the player moves in this direction. You can also enter a zero for the connection and an effect ID to set up a custom message on a non-existent exit, e.g., if the player can't go in the ocean without a boat, etc.", null=True),
31 | ),
32 | ]
33 |
--------------------------------------------------------------------------------
/adventure/migrations/0061_auto_20191213_0007.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.7 on 2019-12-13 08:07
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0060_auto_20191002_0102'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='artifact',
15 | name='armor_type',
16 | field=models.IntegerField(blank=True, choices=[(0, 'Armor'), (1, 'Shield'), (2, 'Helmet')], null=True),
17 | ),
18 | migrations.AlterField(
19 | model_name='playerartifact',
20 | name='armor_type',
21 | field=models.IntegerField(choices=[(0, 'Armor'), (1, 'Shield'), (2, 'Helmet')], default=0, null=True),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/adventure/migrations/0062_auto_20200501_0144.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.5 on 2020-05-01 08:44
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0061_auto_20191213_0007'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='artifact',
15 | name='armor_type',
16 | field=models.IntegerField(blank=True, choices=[(0, 'Armor'), (1, 'Shield'), (2, 'Helmet'), (3, 'Gloves'), (4, 'Ring')], null=True),
17 | ),
18 | migrations.AlterField(
19 | model_name='effect',
20 | name='style',
21 | field=models.CharField(blank=True, choices=[('', 'Normal'), ('emphasis', 'Bold'), ('success', 'Success (green)'), ('special', 'Special 1 (blue)'), ('special2', 'Special 1 (purple)'), ('warning', 'Warning (orange)'), ('danger', 'Danger (red)')], max_length=20, null=True),
22 | ),
23 | migrations.AlterField(
24 | model_name='playerartifact',
25 | name='armor_type',
26 | field=models.IntegerField(choices=[(0, 'Armor'), (1, 'Shield'), (2, 'Helmet'), (3, 'Gloves'), (4, 'Ring')], default=0, null=True),
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/adventure/migrations/0063_monster_combat_verbs.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.5 on 2020-05-29 08:27
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0062_auto_20200501_0144'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='monster',
15 | name='combat_verbs',
16 | field=models.CharField(blank=True, max_length=255, help_text="Custom combat verbs for this monster, e.g., 'stings' or 'breathes fire at'. Leave blank to use the standard verbs.", null=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0064_auto_20200529_0136.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.5 on 2020-05-29 08:36
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0063_monster_combat_verbs'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='monster',
15 | name='gender',
16 | field=models.CharField(blank=True, choices=[('male', 'Male'), ('female', 'Female'), ('none', 'None')], max_length=6, null=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0065_auto_20200529_1607.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.5 on 2020-05-29 23:07
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0064_auto_20200529_0136'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='artifact',
15 | name='data',
16 | field=models.TextField(blank=True, help_text='Adventure-specific data for this artifact, e.g., elemental weapon, etc.Enter as a JSON object.', max_length=1000, null=True),
17 | ),
18 | migrations.AddField(
19 | model_name='monster',
20 | name='data',
21 | field=models.TextField(blank=True, help_text='Adventure-specific data for this monster, e.g., type of monster like vampire, undead, soldier, frost, etc. Data can be used in custom code. Enter as a JSON object.', max_length=1000, null=True),
22 | ),
23 | migrations.AddField(
24 | model_name='room',
25 | name='data',
26 | field=models.TextField(blank=True, help_text='Adventure-specific data for this room, e.g., room type or environment (road, cave, snow, etc.). Data can be used in custom code. Enter as a JSON object.', max_length=1000, null=True),
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/adventure/migrations/0066_auto_20200726_2318.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.5 on 2020-07-27 06:18
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('adventure', '0065_auto_20200529_1607'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='artifact',
15 | name='guard_id',
16 | field=models.IntegerField(blank=True, help_text='If a bound monster, the ID of a monster that prevents the player from freeing it. For other artifact types, the ID of a monster that prevents the player from picking it up.', null=True),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/adventure/migrations/0067_roomexit_hintanswer_adventure_id.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.4 on 2021-07-28 08:39
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('adventure', '0066_auto_20200726_2318'),
11 | ]
12 |
13 | operations = [
14 | migrations.AddField(
15 | model_name='hintanswer',
16 | name='adventure',
17 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hint_answers', to='adventure.adventure'),
18 | ),
19 | migrations.AddField(
20 | model_name='roomexit',
21 | name='adventure',
22 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='room_exits', to='adventure.adventure'),
23 | ),
24 | # populate the fields added above
25 | migrations.RunSQL("update adventure_roomexit"
26 | " set adventure_id ="
27 | " (select adventure_id "
28 | " from adventure_room"
29 | " where adventure_room.id = adventure_roomexit.room_from_id)"),
30 | migrations.RunSQL("update adventure_hintanswer"
31 | " set adventure_id ="
32 | " (select adventure_id"
33 | " from adventure_hint"
34 | " where adventure_hint.id = adventure_hintanswer.hint_id)"),
35 | ]
36 |
--------------------------------------------------------------------------------
/adventure/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/migrations/__init__.py
--------------------------------------------------------------------------------
/adventure/static/adventures/malleus-maleficarum/virrat-map.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/adventures/malleus-maleficarum/virrat-map.jpg
--------------------------------------------------------------------------------
/adventure/static/adventures/the-caves-of-treasure-island/Treasure-Island-map.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/adventures/the-caves-of-treasure-island/Treasure-Island-map.jpg
--------------------------------------------------------------------------------
/adventure/static/adventures/the-caves-of-treasure-island/treasure-island-map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/adventures/the-caves-of-treasure-island/treasure-island-map.png
--------------------------------------------------------------------------------
/adventure/static/images/Eamon_dragon_NEUC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/Eamon_dragon_NEUC.png
--------------------------------------------------------------------------------
/adventure/static/images/Eamon_dragon_facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/Eamon_dragon_facebook.png
--------------------------------------------------------------------------------
/adventure/static/images/favicon/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/favicon/android-chrome-192x192.png
--------------------------------------------------------------------------------
/adventure/static/images/favicon/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/favicon/android-chrome-512x512.png
--------------------------------------------------------------------------------
/adventure/static/images/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/adventure/static/images/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/adventure/static/images/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/adventure/static/images/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/favicon/favicon.ico
--------------------------------------------------------------------------------
/adventure/static/images/favicon/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/adventure/static/images/parchment/center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/parchment/center.png
--------------------------------------------------------------------------------
/adventure/static/images/parchment/parchment-border.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/parchment/parchment-border.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/Boots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/Boots.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/armor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/armor.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/armor2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/armor2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/axe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/axe.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/axe2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/axe2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/axeDouble.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/axeDouble.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/axeDouble2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/axeDouble2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/backpack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/backpack.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/backpack_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/backpack_open.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/bow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/bow.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/bow2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/bow2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/bow_arrow_only.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/bow_arrow_only.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/bow_bow_only.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/bow_bow_only.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/coin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/coin.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/dagger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/dagger.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/dagger2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/dagger2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/document.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/document.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/envelope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/envelope.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/gem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/gem.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/gemBlue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/gemBlue.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/gemGreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/gemGreen.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/gemRed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/gemRed.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/hammer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/hammer.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/hammer2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/hammer2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/heart.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/helmet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/helmet.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/helmet2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/helmet2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/leather.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/leather.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/leather2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/leather2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/map - Copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/map - Copy.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/map.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/map_empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/map_empty.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/necklace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/necklace.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potion.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potion2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potion2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potion3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potion3.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potion4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potion4.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potionBlue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potionBlue.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potionGreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potionGreen.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potionRed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potionRed.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/potion_empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/potion_empty.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/ring.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/ring.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/scroll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/scroll.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/shield.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/shield.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/shield2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/shield2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/shieldSmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/shieldSmall.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/shieldSmall2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/shieldSmall2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/shield_semi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/shield_semi.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/shield_wood.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/shield_wood.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/star.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/sword.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/sword.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/sword2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/sword2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/swordWood.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/swordWood.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/tome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/tome.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/tome_amber.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/tome_amber.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/tome_azure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/tome_azure.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/tome_emerald.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/tome_emerald.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/tools.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/tools_hammer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/tools_hammer.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/upg_spear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/upg_spear.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/wand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/wand.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/wand2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/wand2.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/woodSword.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/woodSword.png
--------------------------------------------------------------------------------
/adventure/static/images/ravenmore/128/x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/ravenmore/128/x.png
--------------------------------------------------------------------------------
/adventure/static/images/sf_dustywall02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/sf_dustywall02.jpg
--------------------------------------------------------------------------------
/adventure/static/images/sf_dustywall02_border.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/adventure/static/images/sf_dustywall02_border.jpg
--------------------------------------------------------------------------------
/adventure/templates/_footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
18 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/adventure/templates/_google_analytics.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/adventure/templates/adventure.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load static %}
3 |
4 | {% block title %}{% endblock %}
5 |
6 | {% block heading %}
7 | {% endblock %}
8 |
9 | {% block content %}
10 |
11 |
12 |
13 | {% endblock %}
14 |
15 | {% block endscripts %}
16 | {% with adventure_root="adventures/" %}
17 |
18 |
19 |
33 |
34 |
35 | {% endwith %}
36 | {% endblock %}
37 |
38 |
--------------------------------------------------------------------------------
/adventure/templates/index.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load static %}
3 |
4 | {% block title %}Adventure List{% endblock %}
5 |
6 | {% block content %}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Welcome to EAMON!
14 |
Eamon is a computerized fantasy role-playing system. Create one character and go on dozens of different adventures!
15 |
Enter the Main Hall
16 |
17 |
18 |

19 |
20 |
21 |
Based on the Eamon Adventure Series, written by Donald Brown for the Apple ][, and on Eamon Deluxe by Frank Black.
22 |
23 |
24 |
25 |
26 |
27 |
28 | {% endblock %}
29 |
--------------------------------------------------------------------------------
/adventure/templates/main-hall.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load static %}
3 |
4 | {% block title %}Main Hall{% endblock %}
5 |
6 | {% block scripts %}
7 |
8 |
9 | {% endblock %}
10 |
11 | {% block content %}
12 |
13 | Welcome to the Wonderful World of Eamon...
14 |
15 |
16 | {% endblock %}
17 |
--------------------------------------------------------------------------------
/adventure/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | from .models import Adventure
4 |
5 |
6 | def index(request, path=''):
7 | """
8 | The home page
9 | """
10 | return render(request, 'index.html')
11 |
12 |
13 | def about(request):
14 | """
15 | The "about" page
16 | """
17 | return render(request, 'about.html')
18 |
19 |
20 | def privacy_policy(request):
21 | """
22 | The "privacy policy" page
23 | """
24 | return render(request, 'privacy.html')
25 |
26 |
27 | def main_hall(request):
28 | """
29 | The container for the "main hall" react app
30 | """
31 | return render(request, 'main-hall.html')
32 |
33 |
34 | def adventure(request, slug):
35 | """
36 | The container for the "core" a.k.a. "adventure" angular app
37 | """
38 | return render(request, 'adventure.html', {'slug': slug})
39 |
40 |
41 | def adventure_list(request):
42 | adventures = Adventure.objects.filter(active=True).order_by('name')
43 | return render(request, 'adventure-list.html', {'adventures': adventures})
44 |
45 |
46 | def manual(request):
47 | return render(request, 'manual.html')
48 |
--------------------------------------------------------------------------------
/client/.eslintignore:
--------------------------------------------------------------------------------
1 | .eslintrc.js
2 | build
3 | node_modules
4 | webpack.config.js
5 |
--------------------------------------------------------------------------------
/client/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | env: {
5 | browser: true,
6 | node: true,
7 | es2021: true,
8 | "cypress/globals": true
9 | },
10 | plugins: [
11 | '@typescript-eslint',
12 | 'cypress'
13 | ],
14 | extends: [
15 | 'eslint:recommended',
16 | 'plugin:@typescript-eslint/recommended',
17 | ],
18 | rules: {
19 | 'no-prototype-builtins': 'off',
20 | 'no-case-declarations': 'off',
21 | '@typescript-eslint/ban-ts-comment': 'off',
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/client/adventures/abductors-quarters/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/abductors-quarters/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/assault-on-the-mole-man/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {CommandException} from "../../core/utils/command.exception";
3 |
4 | declare let game: Game;
5 |
6 | export var custom_commands = [];
7 |
8 | custom_commands.push({
9 | name: "push",
10 | verbs: ["push", "hit"],
11 | description: "Used for pushing buttons on machinery.",
12 | examples: ['PUSH BUTTON', 'HIT BUTTON'],
13 | run: function(verb: string, arg: string): void {
14 | // this command is really just an alias for the "use" command
15 | const artifact = game.artifacts.getLocalByName(arg);
16 | if (artifact) {
17 | if ([8,9,14,15].indexOf(artifact.id) !== -1) {
18 | // buttons. "push x" is just a synonym for "use x"
19 | artifact.use();
20 | } else {
21 | game.history.write("Nothing happens.");
22 | }
23 | } else {
24 | throw new CommandException("You don't have it and it's not here.");
25 | }
26 | },
27 | });
28 |
29 |
--------------------------------------------------------------------------------
/client/adventures/assault-on-the-mole-man/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/attack-of-the-kretons/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/base-adventure/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare const game: Game;
7 |
8 | export const custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/base-adventure/event-handlers.spec.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Unit tests for {base adventure}
3 | */
4 | import Game from "../../core/models/game";
5 | import {Monster} from "../../core/models/monster";
6 | import {Artifact} from "../../core/models/artifact";
7 | import {initLiveGame, expectEffectSeen, expectEffectNotSeen, playerAttackMock, movePlayer} from "../../core/utils/testing";
8 | import {event_handlers} from "./event-handlers";
9 | import {custom_commands} from "./commands";
10 |
11 | // SETUP
12 |
13 | const game = new Game();
14 |
15 | beforeAll(() => { global['game'] = game; });
16 | afterAll(() => { delete global['game']; });
17 |
18 | // to initialize the test, we need to load the whole game data.
19 | // this requires that a real, live API is running.
20 | beforeEach(() => {
21 | game.registerAdventureLogic(event_handlers, custom_commands);
22 | game.slug = '{put your adventure slug here}';
23 | return initLiveGame(game);
24 | });
25 |
26 | // uncomment the following for debugging
27 | // afterEach(() => { game.history.history.map((h) => console.log(h.command, h.results)); });
28 |
29 | // TESTS
30 |
31 | test("effect 1", () => {
32 | // do some game actions and write assertions here
33 |
34 | // for example:
35 | expect(game.rooms.get(1)).not.toBeNull();
36 |
37 | });
38 |
39 | test("effect 2", () => {
40 | // do some game actions and write assertions here
41 |
42 | // for example:
43 | expect(game.rooms.get(1)).not.toBeNull();
44 |
45 | });
46 |
--------------------------------------------------------------------------------
/client/adventures/base-adventure/event-handlers.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Artifact} from "../../core/models/artifact";
3 | import {Monster} from "../../core/models/monster";
4 | import {RoomExit} from "../../core/models/room";
5 | import {Room} from "../../core/models/room";
6 |
7 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
8 | declare const game: Game;
9 |
10 | export const event_handlers = {
11 |
12 | "start": function(): void {
13 | // add your custom game start code here
14 | },
15 |
16 | // add your custom event handlers here
17 |
18 | // every adventure should have a "power" event handler.
19 | // 'power' event handler takes a 1d100 dice roll as an argument.
20 | // this event handler only runs if the spell was successful.
21 | "power": function(roll: number): void {
22 | if (roll <= 50) {
23 | game.history.write("You hear a loud sonic boom which echoes all around you!");
24 | } else if (roll <= 75) {
25 | // teleport to random room
26 | game.history.write("You are being teleported...");
27 | const room = game.rooms.getRandom();
28 | game.player.moveToRoom(room.id);
29 | game.skip_battle_actions = true;
30 | } else {
31 | game.history.write("All your wounds are healed!");
32 | game.player.heal(1000);
33 | }
34 | },
35 |
36 | }; // end event handlers
37 |
38 |
39 | // declare any functions used by event handlers and custom commands
40 |
--------------------------------------------------------------------------------
/client/adventures/base-adventure/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/beginners-forest/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 |
4 | export var custom_commands = [];
5 |
6 | // add your custom commands here
7 |
--------------------------------------------------------------------------------
/client/adventures/beginners-forest/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/black-castle-of-nagog/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/black-castle-of-nagog/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/cliffs-of-fire/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | declare let game: Game;
6 |
7 | export var custom_commands = [];
8 |
9 | custom_commands.push({
10 | name: "wave",
11 | verbs: ["wave"],
12 | description: "Waves something in the air.",
13 | examples: ['WAVE WAND'],
14 | run: function(verb: string, arg: string): void {
15 | // this command is really just a wrapper around the "use" command
16 | const artifact = game.artifacts.getLocalByName(arg);
17 | if (artifact) {
18 | if (artifact.id === 3) {
19 | // black wand. "wave x" is just a synonym for "use x"
20 | artifact.use();
21 | } else {
22 | throw new CommandException("Nothing happens.");
23 | }
24 | } else {
25 | throw new CommandException("Nothing happens.");
26 | }
27 | },
28 | });
29 |
--------------------------------------------------------------------------------
/client/adventures/cliffs-of-fire/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/clone-master/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/clone-master/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/curse-of-the-hellsblade/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 |
4 | export var custom_commands = [];
5 |
--------------------------------------------------------------------------------
/client/adventures/curse-of-the-hellsblade/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/demo1/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 |
3 | declare let game: Game;
4 |
5 | export var custom_commands = [];
6 |
7 | custom_commands.push({
8 | name: 'trollsfire',
9 | verbs: ['trollsfire'],
10 | run: function(verb, arg) {
11 | game.history.write('As you say the magic word (Trollsfire), green flames rise from the sword\'s blade');
12 | }
13 | });
14 |
15 | custom_commands.push({
16 | name: 'go',
17 | verbs: ['go'],
18 | run: function(verb, arg) {
19 | const exits = game.rooms.current_room.exits;
20 | const rand = exits[Math.floor(Math.random() * exits.length)];
21 | game.command_parser.run(rand.direction, false);
22 | }
23 | });
24 |
--------------------------------------------------------------------------------
/client/adventures/demo1/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/demongate/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/demongate/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/draculas-chateau/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | declare let game: Game;
6 |
7 | export var custom_commands = [];
8 |
9 | custom_commands.push({
10 | name: "dig",
11 | verbs: ["dig"],
12 | description: "Digs a hole.",
13 | examples: ['DIG'],
14 | run: function(verb: string, arg: string): void {
15 | if (game.artifacts.get(65).isHere()) {
16 | // shovel. "dig" is just a synonym for "use shovel"
17 | game.artifacts.get(65).use();
18 | } else {
19 | throw new CommandException("You don't have anything to dig with.");
20 | }
21 |
22 | },
23 | });
24 |
25 |
--------------------------------------------------------------------------------
/client/adventures/draculas-chateau/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/eamon-deluxe-50-demo-adventure/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 |
4 | export var custom_commands = [];
5 |
6 | // add your custom commands here
7 |
--------------------------------------------------------------------------------
/client/adventures/eamon-deluxe-50-demo-adventure/event-handlers.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 |
3 | declare let game: Game;
4 |
5 | export var event_handlers = {
6 |
7 | // NOTE: This adventure has no special event handlers (except POWER).
8 | // This adventure is meant as a test of the core logic.
9 |
10 | // every adventure should have a "power" event handler.
11 | // 'power' event handler takes a 1d100 dice roll as an argument
12 | "power": function(roll) {
13 | if (roll <= 50) {
14 | game.history.write("You hear a loud sonic boom which echoes all around you!");
15 | } else if (roll <= 75) {
16 | game.history.write('A fortune cookie appears in mid-air and explodes! The smoking paper left behind reads, "YOU SUDDENLY FIND YOU CANNOT CARRY ALL OF THE ITEMS YOU ARE CARRYING, AND THEY FALL TO THE GROUND." How strange...');
17 | } else {
18 | game.history.write('A fortune cookie appears in mid-air and explodes! The smoking paper left behind reads, "THE SECTION OF THE TUNNEL YOU ARE IN COLLAPSES AND YOU DIE." How strange...');
19 | }
20 | },
21 |
22 | }; // end event handlers
23 |
--------------------------------------------------------------------------------
/client/adventures/eamon-deluxe-50-demo-adventure/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/escape-from-mt-moon/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare const game: Game;
7 |
8 | export const custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/escape-from-mt-moon/event-handlers.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Artifact} from "../../core/models/artifact";
3 | import {Monster} from "../../core/models/monster";
4 | import {RoomExit} from "../../core/models/room";
5 | import {Room} from "../../core/models/room";
6 |
7 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
8 | declare const game: Game;
9 |
10 | export const event_handlers = {
11 |
12 | "start": function(): void {
13 | // add your custom game start code here
14 | },
15 |
16 | // add your custom event handlers here
17 |
18 | // every adventure should have a "power" event handler.
19 | // 'power' event handler takes a 1d100 dice roll as an argument.
20 | // this event handler only runs if the spell was successful.
21 | "power": function(roll: number): void {
22 | if (roll <= 50) {
23 | game.history.write("You hear a loud sonic boom which echoes all around you!");
24 | } else if (roll <= 75) {
25 | // teleport to random room
26 | game.history.write("You are being teleported...");
27 | const room = game.rooms.getRandom();
28 | game.player.moveToRoom(room.id);
29 | game.skip_battle_actions = true;
30 | } else {
31 | game.history.write("All your wounds are healed!");
32 | game.player.heal(1000);
33 | }
34 | },
35 |
36 | }; // end event handlers
37 |
38 |
39 | // declare any functions used by event handlers and custom commands
40 |
--------------------------------------------------------------------------------
/client/adventures/escape-from-mt-moon/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
9 |
--------------------------------------------------------------------------------
/client/adventures/escape-from-the-orc-lair/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 |
4 | export var custom_commands = [];
5 |
6 | // add your custom commands here
7 |
--------------------------------------------------------------------------------
/client/adventures/escape-from-the-orc-lair/event-handlers.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Artifact} from "../../core/models/artifact";
3 | import {Monster} from "../../core/models/monster";
4 | import {RoomExit} from "../../core/models/room";
5 | import {Room} from "../../core/models/room";
6 |
7 | // NOTE: nothing special here. This adventure runs on the base code.
8 | declare let game: Game;
9 |
10 | export var event_handlers = {
11 |
12 | // every adventure should have a "power" event handler.
13 | // 'power' event handler takes a 1d100 dice roll as an argument.
14 | // this event handler only runs if the spell was successful.
15 | "power": function(roll) {
16 | game.history.write("You hear a loud sonic boom which echoes all around you!");
17 | },
18 |
19 | }; // end event handlers
20 |
--------------------------------------------------------------------------------
/client/adventures/escape-from-the-orc-lair/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/forest-of-fear/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare const game: Game;
7 |
8 | export const custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/forest-of-fear/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/furioso/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 |
4 | export var custom_commands = [];
5 |
6 | // add your custom commands here
7 |
--------------------------------------------------------------------------------
/client/adventures/furioso/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/iron-prison/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare const game: Game;
7 |
8 | export const custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/iron-prison/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/lair-of-mutants/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/lair-of-the-minotaur/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | declare let game: Game;
6 |
7 | export var custom_commands = [];
8 |
9 | custom_commands.push({
10 | name: "dig",
11 | verbs: ["dig"],
12 | description: "Digs a hole.",
13 | examples: ['DIG'],
14 | run: function(verb: string, arg: string): void {
15 | if (game.artifacts.get(9).isHere()) {
16 | // shovel. "dig" is just a synonym for "use shovel"
17 | game.artifacts.get(9).use();
18 | } else {
19 | throw new CommandException("You don't have anything to dig with.");
20 | }
21 |
22 | },
23 | });
24 |
25 |
--------------------------------------------------------------------------------
/client/adventures/lair-of-the-minotaur/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/last-dragon/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/last-dragon/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/malleus-maleficarum/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/manxome-foe/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare let game;
7 |
8 | export var custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/manxome-foe/event-handlers.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Artifact} from "../../core/models/artifact";
3 | import {Monster} from "../../core/models/monster";
4 | import {RoomExit} from "../../core/models/room";
5 | import {Room} from "../../core/models/room";
6 |
7 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
8 | declare let game;
9 |
10 | export var event_handlers = {
11 |
12 | "seeMonster": function (monster: Monster): void {
13 | // tweedledee/tweedledum share a description, as do the raths
14 | if (monster.id === 4 || monster.id === 17) {
15 | game.history.suppressNextMessage = true;
16 | }
17 | },
18 |
19 | // every adventure should have a "power" event handler.
20 | // 'power' event handler takes a 1d100 dice roll as an argument.
21 | // this event handler only runs if the spell was successful.
22 | "power": function(roll) {
23 | if (roll <= 50) {
24 | game.history.write("You hear a loud sonic boom which echoes all around you!");
25 | } else if (roll <= 75) {
26 | // teleport to random room
27 | game.history.write("You are being teleported...");
28 | const room = game.rooms.getRandom();
29 | game.player.moveToRoom(room.id);
30 | game.skip_battle_actions = true;
31 | } else {
32 | game.history.write("All your wounds are healed!");
33 | game.player.heal(1000);
34 | }
35 | },
36 |
37 | }; // end event handlers
38 |
--------------------------------------------------------------------------------
/client/adventures/manxome-foe/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/mines-of-moria/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare let game: Game;
7 |
8 | export var custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/mines-of-moria/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/museum-of-unnatural-history/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 |
3 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
4 | declare const game: Game;
5 |
6 | export const custom_commands = [];
7 |
8 | custom_commands.push({
9 | name: "assemble",
10 | verbs: ["assemble"],
11 | description: "Puts something together. You'll need the required components first.",
12 | examples: ['ASSEMBLE something'],
13 | run: function(verb: string, arg: string): void {
14 | arg = arg.toLowerCase();
15 |
16 | if (arg === 'powder' || arg === 'gunpowder') {
17 | if (game.artifacts.allAreHere([1, 7, 19])) {
18 | game.effects.print(12);
19 | game.artifacts.get(35).moveToRoom();
20 | } else {
21 | game.effects.print(14);
22 | }
23 | }
24 |
25 | if (arg === 'bomb' || arg === 'device') {
26 | if (game.data.made_bomb) {
27 | game.history.write('You already did!');
28 | return;
29 | }
30 | if (game.artifacts.allAreHere([14, 16, 35])) {
31 | game.effects.print(13);
32 | game.artifacts.get(14).destroy();
33 | game.artifacts.get(16).destroy();
34 | game.artifacts.get(35).destroy();
35 | game.artifacts.get(34).moveToRoom();
36 | game.data.made_bomb = true;
37 | } else {
38 | game.effects.print(15);
39 | }
40 | }
41 | },
42 | });
43 |
--------------------------------------------------------------------------------
/client/adventures/museum-of-unnatural-history/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/orb-of-polaris/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/orb-of-polaris/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/pirates-cave/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // this file intentionally left blank
8 |
--------------------------------------------------------------------------------
/client/adventures/pirates-cave/event-handlers.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 |
3 | declare let game: Game;
4 |
5 | export var event_handlers = {
6 |
7 | "start": function() {
8 | game.exit_message = 'You return to the main hall.';
9 | },
10 |
11 | // every adventure should have a "power" event handler.
12 | // 'power' event handler takes a 1d100 dice roll as an argument.
13 | // this event handler only runs if the spell was successful.
14 | "power": function(roll) {
15 | if (roll <= 50) {
16 | game.history.write("You hear a loud sonic boom which echoes all around you!");
17 | } else if (roll <= 75) {
18 | // teleport to random room
19 | game.history.write("You are being teleported...");
20 | const room = game.rooms.getRandom();
21 | game.player.moveToRoom(room.id);
22 | game.skip_battle_actions = true;
23 | } else {
24 | game.history.write("All your wounds are healed!");
25 | game.player.heal(1000);
26 | }
27 | },
28 |
29 | }; // end event handlers
30 |
--------------------------------------------------------------------------------
/client/adventures/pirates-cave/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/princes-tavern/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/quest-for-the-holy-grail/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/revenge-of-the-mole-man/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/revenge-of-the-mole-man/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/ring-of-doom/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare const game: Game;
7 |
8 | export const custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/ring-of-doom/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/stronghold-of-kahr-dur/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/stronghold-of-kahr-dur/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/sword-of-inari/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/swordquest/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/swordquest/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/temple-of-ngurct/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // add your custom commands here
8 |
--------------------------------------------------------------------------------
/client/adventures/temple-of-ngurct/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/temple-of-the-trolls/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/the-beginners-cave/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {light_trollsfire, put_out_trollsfire} from "./event-handlers";
3 |
4 | declare let game: Game;
5 |
6 | export var custom_commands = [];
7 |
8 | custom_commands.push({
9 | name: "trollsfire",
10 | verbs: ["trollsfire"],
11 | description: "Activates a special item.",
12 | examples: ['TROLLSFIRE or SAY TROLLSFIRE'],
13 | run: function(verb: string, arg: string): void {
14 | const trollsfire = game.artifacts.get(10);
15 |
16 | if (game.player.hasArtifact(trollsfire.id)) {
17 | if (!trollsfire.is_lit) {
18 | game.effects.print(4, "success");
19 | if (game.player.weapon_id === trollsfire.id) {
20 | // player has trollsfire ready. increase its stats.
21 | light_trollsfire();
22 | } else {
23 | // turned on when carrying but not ready. Ouch.
24 | game.effects.print(5, "warning");
25 | game.player.injure(game.diceRoll(1, 5), true);
26 | }
27 | } else {
28 | game.effects.print(6, "success");
29 | put_out_trollsfire();
30 | }
31 | } else {
32 | game.history.write("Nothing happens.");
33 | }
34 | },
35 | });
36 |
--------------------------------------------------------------------------------
/client/adventures/the-beginners-cave/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/the-cave-of-the-mind/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | declare let game: Game;
6 |
7 | export var custom_commands = [];
8 |
9 | custom_commands.push({
10 | name: "play",
11 | verbs: ["play"],
12 | run: function(verb: string, arg: string): void {
13 | // this command is really just a wrapper around the "use" command
14 | const artifact = game.artifacts.getLocalByName(arg);
15 | if (artifact) {
16 | if (artifact.id === 21) {
17 | // harmonica. "play x" is just a synonym for "use x"
18 | artifact.use();
19 | } else {
20 | throw new CommandException("You can't play that.");
21 | }
22 | } else {
23 | throw new CommandException("You don't have it and it's not here.");
24 | }
25 |
26 | },
27 | });
28 |
--------------------------------------------------------------------------------
/client/adventures/the-cave-of-the-mind/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/the-caves-of-treasure-island/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | declare let game: Game;
6 |
7 | export var custom_commands = [];
8 |
9 | custom_commands.push({
10 | name: "dig",
11 | verbs: ["dig"],
12 | description: "Digs a hole.",
13 | examples: ['DIG'],
14 | run: function(verb: string, arg: string): void {
15 | if (game.artifacts.get(3).isHere()) {
16 | // shovel. "dig" is just a synonym for "use shovel"
17 | game.artifacts.get(3).use();
18 | } else {
19 | throw new CommandException("You don't have anything to dig with.");
20 | }
21 |
22 | },
23 | });
24 |
25 | custom_commands.push({
26 | name: "play",
27 | verbs: ["play"],
28 | description: "Plays a musical instrument.",
29 | examples: ['PLAY GUITAR'],
30 | run: function(verb: string, arg: string): void {
31 | // this command is really just a wrapper around the "use" command
32 | const artifact = game.artifacts.getLocalByName(arg);
33 | if (artifact) {
34 | if (artifact.id === 18 || artifact.id === 31) {
35 | // magic harp or flute. "play x" is just a synonym for "use x"
36 | artifact.use();
37 | } else {
38 | throw new CommandException("You can't play that.");
39 | }
40 | } else {
41 | throw new CommandException("You don't have it and it's not here.");
42 | }
43 | },
44 | });
45 |
--------------------------------------------------------------------------------
/client/adventures/the-caves-of-treasure-island/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/the-devils-dungeon/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/the-magic-kingdom/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 |
4 | export var custom_commands = [];
5 |
6 | // add your custom commands here
7 |
--------------------------------------------------------------------------------
/client/adventures/the-magic-kingdom/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/the-training-ground/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {CommandException} from "../../core/utils/command.exception";
3 |
4 | declare let game: Game;
5 |
6 | export var custom_commands = [];
7 |
8 | custom_commands.push({
9 | name: "buy",
10 | verbs: ["buy"],
11 | description: "Buys an item from a merchant. Items that are for sale will be listed in the game window.",
12 | examples: ['BUY POTION'],
13 | run: function(verb: string, arg: string): void {
14 | arg = arg.toLowerCase();
15 | const for_sale_here = game.artifacts.all.filter(a => a.data.for_sale && a.monster_id && game.monsters.get(a.monster_id).isHere());
16 | const artifact = for_sale_here.find(a => a.match(arg));
17 | if (!artifact) {
18 | throw new CommandException("No one here has that for sale.");
19 | }
20 | if (artifact.value > game.player.gold) {
21 | throw new CommandException(`That costs ${artifact.value} gold pieces and you only have ${game.player.gold}.`);
22 | }
23 |
24 | game.modal.confirm(`That costs ${artifact.value} gold pieces. Do you want to buy it?`, answer => {
25 | if (answer === 'Yes') {
26 | game.history.write(`You buy the ${artifact.name}.`);
27 | artifact.showDescription();
28 | artifact.moveToInventory();
29 | game.player.gold -= artifact.value;
30 | game.player.updateInventory();
31 | artifact.data.for_sale = false;
32 | } else {
33 | game.history.write(`"Maybe next time."`);
34 | }
35 | });
36 | }
37 | });
38 |
39 |
--------------------------------------------------------------------------------
/client/adventures/the-training-ground/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/treachery-of-zorag/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/treasure-island/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | export var custom_commands = [];
6 |
7 | // this file intentionally left blank
8 |
--------------------------------------------------------------------------------
/client/adventures/treasure-island/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/adventures/well-of-the-great-ones/commands.ts:
--------------------------------------------------------------------------------
1 | import Game from "../../core/models/game";
2 | import {Monster} from "../../core/models/monster";
3 | import {CommandException} from "../../core/utils/command.exception";
4 |
5 | // The "game" object contains the event handlers and custom commands defined for the loaded adventure.
6 | declare let game;
7 |
8 | export var custom_commands = [];
9 |
10 | // add your custom commands here
11 |
--------------------------------------------------------------------------------
/client/adventures/well-of-the-great-ones/index.ts:
--------------------------------------------------------------------------------
1 | // This file is the entry script for Webpack's ts-loader. Do not edit this file.
2 | import Game from '../../core/models/game';
3 | import { custom_commands } from './commands';
4 | import { event_handlers } from './event-handlers';
5 |
6 | export const game = new Game();
7 | game.registerAdventureLogic(event_handlers, custom_commands);
8 |
--------------------------------------------------------------------------------
/client/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | ['@babel/preset-env', {targets: {node: 'current'}}],
4 | '@babel/preset-react',
5 | '@babel/preset-typescript',
6 | ],
7 | };
8 |
--------------------------------------------------------------------------------
/client/build/static/mock-data/adventure.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 0,
3 | "name": "Demo adventure",
4 | "description": "Welcome to the demo! This is a simple adventure used for development and automated tests. You will be exploring a small castle.",
5 | "intro_text": ""
6 | }
7 |
--------------------------------------------------------------------------------
/client/build/static/mock-data/effects.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/client/core/commands/base-command.ts:
--------------------------------------------------------------------------------
1 | import Game from "../models/game";
2 |
3 | /**
4 | * Interface BaseCommand.
5 | * Interface for commands a player can give.
6 | */
7 | export interface BaseCommand {
8 | name: string;
9 | verbs: string[];
10 | category?: string;
11 | description?: string;
12 | examples?: string[];
13 | secret?: boolean;
14 | /**
15 | * Optional function to change what appears in the history window.
16 | * @param verb
17 | */
18 | history_display? (verb: string);
19 |
20 | /**
21 | * The main function that contains the command logic
22 | * @param verb
23 | * @param arg
24 | */
25 | run(verb, arg);
26 | }
27 |
28 | /**
29 | * Class CustomCommand.
30 | * A class used to define custom commands
31 | */
32 | export class CustomCommand implements BaseCommand {
33 | name: string;
34 | verbs: string[];
35 | category?: string;
36 | description?: string;
37 | examples?: string[];
38 | game: Game;
39 | run(verb: string, arg: string) { }
40 | }
41 |
--------------------------------------------------------------------------------
/client/core/commands/event-handler.ts:
--------------------------------------------------------------------------------
1 | import Game from "../models/game";
2 | import {Artifact} from "../models/artifact";
3 | import {Monster} from "../models/monster";
4 |
5 | /**
6 | * EventHandler class.
7 | * A class used to define a game event handler. This allows custom logic to
8 | * be defined in an adventure.
9 | *
10 | * When a game event is triggered during execution (usually during a command),
11 | * the game searches for a matching EventHandler and calls its run() method.
12 | *
13 | * The EventHandler objects should be instantiated in an adventure's "event-handlers" file.
14 | */
15 | export default class EventHandler {
16 | name: string;
17 | game: Game;
18 | run(arg1: number | string | Artifact | Monster, arg2?: Artifact | Monster, arg3?: Artifact | Monster) { }
19 | }
20 |
--------------------------------------------------------------------------------
/client/core/index.tsx:
--------------------------------------------------------------------------------
1 | // polyfills for IE 11
2 | import "core-js/stable";
3 | import "regenerator-runtime/runtime";
4 |
5 | import * as React from 'react';
6 | import * as ReactDOM from 'react-dom';
7 | import MainProgram from './components/MainProgram';
8 | // import registerServiceWorker from './registerServiceWorker';
9 |
10 | ReactDOM.render(
11 | ,
12 | document.getElementById('root') as HTMLElement
13 | );
14 | // registerServiceWorker();
15 |
--------------------------------------------------------------------------------
/client/core/models/effect.ts:
--------------------------------------------------------------------------------
1 | import {GameObject} from "./game-object";
2 |
3 | /**
4 | * Effect class. Represents special effect text that can be displayed
5 | * by scripts during game play.
6 | */
7 | export class Effect extends GameObject {
8 |
9 | id: number;
10 | text: string;
11 | style: string;
12 | next: number; // another effect chained onto this one
13 | next_inline: number; // a chained effect that is printed without a paragraph break
14 | replacements: object; // strings that will be replaced within the effect text
15 | }
16 |
--------------------------------------------------------------------------------
/client/core/models/game.spec.ts:
--------------------------------------------------------------------------------
1 | import Game from "./game";
2 |
3 | const game = new Game();
4 |
5 | describe("Game class", function() {
6 |
7 | test("should roll some dice", () => {
8 | let roll: number;
9 | // using sides = 1 to avoid having to worry about random numbers
10 | expect(game.diceRoll(1, 1)).toBe(1);
11 | expect(game.diceRoll(3, 1)).toBe(3);
12 | // edge cases
13 | expect(game.diceRoll(1, 0)).toBe(0);
14 | expect(game.diceRoll(3, -1)).toBe(-3);
15 | // test some random numbers
16 | for (let i = 0; i < 20; i++) {
17 | roll = game.diceRoll(1, 5);
18 | expect(roll).toBeGreaterThan(0);
19 | expect(roll).toBeLessThan(6);
20 | roll = game.diceRoll(1, -5);
21 | expect(roll).toBeGreaterThan(-6);
22 | expect(roll).toBeLessThan(0);
23 | }
24 |
25 | // test the mock random numbers feature
26 | game.mock_random_numbers = [42, 5, 99];
27 | expect(game.diceRoll(1, 100)).toBe(42);
28 | expect(game.diceRoll(1, 100)).toBe(5);
29 | expect(game.diceRoll(1, 100)).toBe(99);
30 |
31 | });
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/client/core/models/hint.ts:
--------------------------------------------------------------------------------
1 | import {Loadable} from "./loadable";
2 |
3 | export class Hint extends Loadable {
4 |
5 | public id: number;
6 | public question: string;
7 | public index: string;
8 | public answers: [{
9 | answer: string,
10 | spoiler: boolean,
11 | }];
12 |
13 | // these are used by the display logic
14 | public current_index = 0;
15 | public is_open = false;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/client/core/models/history-entry.spec.ts:
--------------------------------------------------------------------------------
1 | import {HistoryEntry} from "./history-entry";
2 |
3 | describe("History entry class", function() {
4 |
5 | test("command and result", function() {
6 | const h = new HistoryEntry("get all");
7 | expect(h.command).toEqual("get all");
8 |
9 | h.push("Sword taken", "normal");
10 | expect(h.results).toEqual([
11 | {markdown: false, text: "Sword taken", type: "normal"}
12 | ]);
13 |
14 | h.push("The dragon attacks you!", "danger");
15 | expect(h.results).toEqual([
16 | {markdown: false, text: "Sword taken", type: "normal"},
17 | {markdown: false, text: "The dragon attacks you!", type: "danger"}
18 | ]);
19 |
20 | });
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/client/core/models/history-entry.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Class HistoryEntry.
3 | * Holds the commands and results run previously.
4 | */
5 | export class HistoryEntry {
6 |
7 | public command: string;
8 | public results: {
9 | text: string,
10 | type: string,
11 | markdown: boolean
12 | }[] = [];
13 |
14 | constructor(command) {
15 | this.command = command;
16 | }
17 |
18 | public push(text: string, type: string, markdown = false) {
19 | if (text === null) {
20 | text = "";
21 | }
22 | const split_text = text.split(/\n/g);
23 | for (const i in split_text) {
24 | this.results.push({ text: split_text[i], type, markdown });
25 | }
26 | }
27 |
28 | public append(text: string) {
29 | // TODO: make appends not take any time
30 | this.results[this.results.length - 1].text += text;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/client/core/models/loadable.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Loadable class. Parent class for all objects loaded from the database.
3 | */
4 | export abstract class Loadable {
5 |
6 | /**
7 | * Loads data from JSON source into the object properties.
8 | * @param Object source an object, e.g., from JSON.
9 | */
10 | init(source) {
11 | for (const prop in source) {
12 | this[prop] = source[prop];
13 | }
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/client/core/models/room.spec.ts:
--------------------------------------------------------------------------------
1 | import {Room} from "./room";
2 | import {RoomExit} from "./room";
3 |
4 | import {ROOMS} from "../../adventures/demo1/mock-data/rooms";
5 |
6 | describe("Room exits", function() {
7 |
8 | const r1 = new Room();
9 | r1.init(ROOMS[0]);
10 |
11 | it("should get the room to the north", function() {
12 | const x = r1.getExit("n");
13 | expect(x.direction).toEqual("n");
14 | expect(x.room_to).toEqual(2);
15 | });
16 |
17 | it("should get the room to the south", function() {
18 | const x = r1.getExit("s");
19 | expect(x.direction).toEqual("s");
20 | expect(x.room_to).toEqual(RoomExit.EXIT);
21 | });
22 |
23 | it("should NOT get the room to the east", function() {
24 | expect(r1.getExit("e")).toEqual(null);
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/client/core/repositories/hint.repo.ts:
--------------------------------------------------------------------------------
1 | import {Hint} from "../models/hint";
2 |
3 | /**
4 | * Class HintRepository.
5 | * Storage class for all hint data.
6 | */
7 | export default class HintRepository {
8 |
9 | /**
10 | * An array of all the Hint objects
11 | */
12 | all: Hint[] = [];
13 |
14 | /**
15 | * The highest ID in the system
16 | */
17 | index = 0;
18 |
19 | constructor(hint_data: Array>) {
20 | for (const i of hint_data) {
21 | this.add(i);
22 | }
23 | }
24 |
25 | /**
26 | * Adds a hint.
27 | * @param {Object} hint_data
28 | */
29 | public add(hint_data): Hint {
30 | const h = new Hint();
31 |
32 | h.init(hint_data);
33 |
34 | // autonumber the ID if not provided
35 | if (h.id === undefined) {
36 | h.id = this.index + 1;
37 | }
38 |
39 | if (this.get(h.id) !== null) {
40 | throw new Error("Tried to create a hint #" + h.id + " but that ID is already taken.");
41 | }
42 |
43 | this.all.push(h);
44 |
45 | // update the autonumber index
46 | if (h.id > this.index) {
47 | this.index = h.id;
48 | }
49 | return h;
50 | }
51 |
52 | /**
53 | * Gets a hint by id.
54 | * @param {number} id
55 | * @return Monster
56 | */
57 | public get(id): Hint|null {
58 | const h = this.all.find(x => x.id === id);
59 | return h || null;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/client/core/types.ts:
--------------------------------------------------------------------------------
1 | import Game from "./models/game";
2 |
3 | /**
4 | * Common type for components that take the Game object as a prop
5 | */
6 | export type PropsWithGame = {
7 | game: Game;
8 | setGameState: (game: Game) => void;
9 | }
10 |
11 |
12 | /**
13 | * Props used by hints, command list, and how to play modal
14 | */
15 | export type ModalProps = {
16 | game: Game;
17 | visible: boolean;
18 | toggle: () => void;
19 | }
20 |
--------------------------------------------------------------------------------
/client/core/utils/command.exception.ts:
--------------------------------------------------------------------------------
1 | export declare class Error {
2 | public name: string;
3 | public message: string;
4 | public stack: string;
5 | constructor(message?: string);
6 | }
7 |
8 | export class CommandException extends Error {
9 |
10 | constructor(m: string) {
11 | super(m);
12 | this.name = "Exception";
13 |
14 | // Set the prototype explicitly.
15 | Object.setPrototypeOf(this, CommandException.prototype);
16 | }
17 |
18 | toString() {
19 | return this.name + ": " + this.message;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/client/core/utils/logger.interface.ts:
--------------------------------------------------------------------------------
1 | export interface ILoggerService {
2 | log(type: string, value?: number);
3 | }
4 |
5 | /**
6 | * Dummy logger used with automated tests
7 | */
8 | export class DummyLoggerService implements ILoggerService {
9 |
10 | public log(type = "", value: number = null) {
11 | // this logger class prints its log entries to the console. It doesn't save anything to the DB.
12 | console.log("Log: ", type, value);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/client/core/utils/logger.ts:
--------------------------------------------------------------------------------
1 | import {ILoggerService} from "./logger.interface";
2 | import {getAxios} from "../../main-hall/utils/api";
3 | import Game from "../models/game";
4 |
5 | declare let game: Game;
6 |
7 | /**
8 | * Real live logger class connected to API
9 | */
10 | export default class Logger implements ILoggerService {
11 |
12 | public log(type = "", value: number = null) {
13 | const body = {
14 | 'player': game.demo ? null : window.localStorage.getItem('player_id'),
15 | 'adventure': game.id,
16 | 'type': type,
17 | 'value': value
18 | };
19 | const axios = getAxios();
20 | axios.post('/log', body)
21 | .catch(err => {
22 | console.error('logger error', err);
23 | });
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/client/core/utils/saved-game.interface.ts:
--------------------------------------------------------------------------------
1 | // import { EMPTY } from 'rxjs';
2 |
3 | export interface ISavedGameService {
4 | saveGame(data: any);
5 | listSavedGames(player_id: any, adventure_id: number);
6 | loadSavedGame(saved_game: any);
7 | loadSavedGameById(id: number);
8 | deleteSavedGame(saved_game: any);
9 | }
10 |
11 | /**
12 | * Dummy service used with automated tests
13 | */
14 | export class DummySavedGameService implements ISavedGameService {
15 |
16 | public saveGame(data: any) {
17 | }
18 |
19 | public listSavedGames(player_id: any, adventure_id: number) {
20 | // this used to return an empty Observable, but that just confused Webpack, so
21 | // it got refactored to return undefined
22 | return undefined;
23 | // return EMPTY;
24 | }
25 |
26 | public loadSavedGame(saved_game: any) {
27 | }
28 |
29 | public loadSavedGameById(id: number) {
30 | }
31 |
32 | public deleteSavedGame(saved_game: any) {
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/client/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseUrl": "http://localhost:8000"
3 | }
4 |
--------------------------------------------------------------------------------
/client/cypress/fixtures/adv1/adventure.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 0,
3 | "name": "Test Adv 1",
4 | "description": "Welcome to the demo! This is a simple adventure used for development and automated tests. You will be exploring a small castle.",
5 | "intro_text": "This is some intro text"
6 | }
7 |
--------------------------------------------------------------------------------
/client/cypress/fixtures/adv1/artifacts.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "name": "rocket launcher",
5 | "description": "This is a rocket launcher.",
6 | "type": 3,
7 | "room_id": 1,
8 | "weight": 10,
9 | "value": 250
10 | }
11 | ]
12 |
--------------------------------------------------------------------------------
/client/cypress/fixtures/adv1/effects.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/client/cypress/fixtures/adv1/monsters.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/client/cypress/fixtures/adv1/rooms.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "name": "Entrance",
5 | "description": "You are standing at the entrance.",
6 | "exits": [
7 | {"direction": "s", "room_to": -999}
8 | ]
9 | }
10 | ]
11 |
--------------------------------------------------------------------------------
/client/cypress/fixtures/adventures.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "name": "Test Adv 1",
5 | "description": "This is the description",
6 | "full_description": "",
7 | "intro_text": "",
8 | "intro_question": "",
9 | "slug": "demo1",
10 | "edx": "n/a",
11 | "dead_body_id": 0,
12 | "featured_month": "",
13 | "date_published": "2021-01-01",
14 | "authors": [
15 | "Donald Brown"
16 | ],
17 | "tags": [
18 | "tag1"
19 | ],
20 | "times_played": 100,
21 | "avg_ratings": {
22 | "overall__avg": 4.1,
23 | "combat__avg": 3.2,
24 | "puzzle__avg": 3.2
25 | }
26 | },
27 |
28 | {
29 | "id": 2,
30 | "name": "Test Adv 2",
31 | "description": "This is the description",
32 | "full_description": "",
33 | "intro_text": "",
34 | "intro_question": "",
35 | "slug": "demo2",
36 | "edx": "n/a",
37 | "dead_body_id": 0,
38 | "featured_month": "",
39 | "date_published": "2022-01-01",
40 | "authors": [
41 | "Tom Zuchowski"
42 | ],
43 | "tags": [
44 | "tag2"
45 | ],
46 | "times_played": 200,
47 | "avg_ratings": {
48 | "overall__avg": 4.3,
49 | "combat__avg": 3.5,
50 | "puzzle__avg": 3.6
51 | }
52 | }
53 | ]
--------------------------------------------------------------------------------
/client/cypress/plugins/index.js:
--------------------------------------------------------------------------------
1 | ///
2 | // ***********************************************************
3 | // This example plugins/index.js can be used to load plugins
4 | //
5 | // You can change the location of this file or turn off loading
6 | // the plugins file with the 'pluginsFile' configuration option.
7 | //
8 | // You can read more here:
9 | // https://on.cypress.io/plugins-guide
10 | // ***********************************************************
11 |
12 | // This function is called when a project is opened or re-opened (e.g. due to
13 | // the project's config changing)
14 |
15 | /**
16 | * @type {Cypress.PluginConfig}
17 | */
18 | // eslint-disable-next-line no-unused-vars
19 | module.exports = (on, config) => {
20 | // `on` is used to hook into various events Cypress emits
21 | // `config` is the resolved Cypress config
22 | }
23 |
--------------------------------------------------------------------------------
/client/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
26 |
27 | import 'cypress-wait-until';
28 |
--------------------------------------------------------------------------------
/client/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/client/cypress/support/page_objects/adventurePage.js:
--------------------------------------------------------------------------------
1 | export class AdventurePage {
2 |
3 | enterCommand(command) {
4 | cy.get('#command').type(`${command}{enter}`);
5 | cy.wait(500);
6 | }
7 |
8 | clickModalButton(text) {
9 | cy.contains('.game-modal button', text).click();
10 | }
11 |
12 | clickReturnButton(text) {
13 | cy.get('button#return').click({force: true});
14 | }
15 |
16 | clickSaveButton(text) {
17 | cy.contains('button', 'Save and go to main hall').click();
18 | }
19 |
20 | }
21 |
22 | export const onAdventurePage = new AdventurePage();
23 |
--------------------------------------------------------------------------------
/client/cypress/support/page_objects/mainHallPage.js:
--------------------------------------------------------------------------------
1 | export class MainHallPage {
2 |
3 | goToAdventures() {
4 | cy.contains('a', 'Go on an adventure').click();
5 | }
6 |
7 | goToShop() {
8 | cy.contains('a', 'Visit the weapons shop').click();
9 | }
10 |
11 | goToBank() {
12 | cy.contains('a', 'Find the banker to deposit or withdraw some gold').click();
13 | }
14 |
15 | goToWizard() {
16 | cy.contains('a', 'Find a wizard to teach you some spells').click();
17 | }
18 |
19 | goToWitch() {
20 | cy.contains('a', 'Visit the witch to increase your attributes').click();
21 | }
22 |
23 | logOut() {
24 | cy.contains('a', 'Temporarily leave the universe').click();
25 | }
26 |
27 | }
28 |
29 | export const onMainHallPage = new MainHallPage();
30 |
--------------------------------------------------------------------------------
/client/cypress/support/page_objects/shopPage.js:
--------------------------------------------------------------------------------
1 | export class ShopPage {
2 |
3 | goToBuyPage() {
4 | cy.contains('a', 'Buy weapons').click();
5 | }
6 |
7 | goToSellPage() {
8 | cy.contains('a', 'Sell weapons').click();
9 | }
10 |
11 | returnToMenu() {
12 | cy.contains('a', 'Done').click();
13 | }
14 |
15 | leaveShop() {
16 | cy.contains('a', 'Go back to Main Hall').click();
17 | }
18 |
19 | expectGoldAmount(amount) {
20 | cy.get('[data-qa="goldAmount"]').should('have.text', amount);
21 | }
22 |
23 | }
24 |
25 | export const onShopPage = new ShopPage();
26 |
--------------------------------------------------------------------------------
/client/designer/components/AdventureHeading.tsx:
--------------------------------------------------------------------------------
1 | import {Link} from "react-router-dom";
2 | import * as React from "react";
3 | import AdventureContext from "../contexts/adventure";
4 | import {useParams} from "react-router-dom";
5 |
6 |
7 | const AdventureHeading: React.FC = () => {
8 | const adventureContext = React.useContext(AdventureContext);
9 | const params = useParams();
10 | const slug = params['*'].split('/')[0];
11 |
12 | if (!adventureContext.adventure) {
13 | return Loading {slug}...
;
14 | }
15 |
16 | return (
17 |
18 |
19 |

20 |
21 |
22 |
#{adventureContext.adventure.id}
24 |
{adventureContext.adventure.name}
25 |
{adventureContext.adventure.authors_display.length ? "By: " + adventureContext.adventure.authors_display : ""}
26 |
27 |
28 | );
29 |
30 | }
31 |
32 | export default AdventureHeading;
33 |
--------------------------------------------------------------------------------
/client/designer/components/EffectList.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Link } from "react-router-dom";
3 |
4 | import AdventureContext from "../contexts/adventure";
5 | import {TextStyleLabel} from "./common";
6 |
7 |
8 | const EffectList: React.FC = () => {
9 | const context = React.useContext(AdventureContext);
10 |
11 | if (!context.adventure) {
12 | return Loading...
;
13 | }
14 |
15 | let emptyMessage = '';
16 | if (!context.effects.all.length) {
17 | emptyMessage = 'no effects yet';
18 | }
19 |
20 | return (
21 |
22 |
Effects
23 |
24 |
Choose an effect:
25 |
26 |
27 |
28 | {emptyMessage}
29 |
30 |
31 |
32 | # |
33 | Text |
34 | Style |
35 |
36 |
37 |
38 | {context.effects?.all.map(eff => {
39 | return (
40 |
41 | {eff.id} |
42 | {eff.text} |
43 | |
44 |
45 | );
46 | })}
47 |
48 |
49 |
50 |
51 |
52 | );
53 | }
54 |
55 | export default EffectList;
56 |
--------------------------------------------------------------------------------
/client/designer/components/RoomList.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import AdventureContext from "../contexts/adventure";
4 | import {RoomLink} from "./common";
5 |
6 |
7 | const RoomList: React.FC = () => {
8 | const context = React.useContext(AdventureContext);
9 |
10 | if (!context.adventure) {
11 | return Loading...
;
12 | }
13 |
14 | let emptyMessage = '';
15 | if (!context.rooms.all.length) {
16 | emptyMessage = 'no rooms yet';
17 | }
18 |
19 | return (
20 |
21 |
Rooms
22 |
23 |
Choose a room:
24 |
25 |
26 |
27 | {emptyMessage}
28 |
29 |
30 |
31 | # |
32 | Name |
33 |
34 |
35 |
36 | {context.rooms.all.map((room) => {
37 | return (
38 |
39 | {room.id} |
40 | |
41 |
42 | );
43 | })}
44 |
45 |
46 |
47 |
48 |
49 | );
50 | }
51 |
52 | export default RoomList;
53 |
--------------------------------------------------------------------------------
/client/designer/constants.ts:
--------------------------------------------------------------------------------
1 | export enum ArtifactTypes {
2 | GOLD = 0,
3 | TREASURE = 1,
4 | WEAPON = 2,
5 | MAGIC_WEAPON = 3,
6 | CONTAINER = 4,
7 | LIGHT_SOURCE = 5,
8 | DRINKABLE = 6,
9 | READABLE = 7,
10 | DOOR = 8,
11 | EDIBLE = 9,
12 | BOUND_MONSTER = 10,
13 | WEARABLE = 11,
14 | DISGUISED_MONSTER = 12,
15 | DEAD_BODY = 13,
16 | USER_1 = 14,
17 | USER_2 = 15,
18 | USER_3 = 16
19 | }
20 |
21 | export enum ArtifactIcons {
22 | GOLD = 'coin',
23 | TREASURE = 'gem',
24 | WEAPON = 'sword',
25 | MAGIC_WEAPON = 'sword2',
26 | CONTAINER = 'backpack',
27 | LIGHT_SOURCE = 'star',
28 | DRINKABLE = 'potion',
29 | READABLE = 'tome',
30 | DOOR = 'tools',
31 | EDIBLE = 'star',
32 | BOUND_MONSTER = 'star',
33 | WEARABLE = 'boots',
34 | DISGUISED_MONSTER = 'star',
35 | DEAD_BODY = 'star',
36 | USER_1 = 'tools',
37 | USER_2 = 'tools',
38 | USER_3 = 'tools'
39 | }
40 |
--------------------------------------------------------------------------------
/client/designer/contexts/form.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | interface FormContextInterface {
4 | setField: (ev: React.ChangeEvent) => void,
5 | saveField: (ev: React.ChangeEvent) => void,
6 | }
7 | const FormContext = React.createContext(null);
8 |
9 | export default FormContext;
10 |
--------------------------------------------------------------------------------
/client/designer/contexts/user.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | interface UserContextInterface {
4 | username: string,
5 | token: string,
6 | changeUserState: (username: string, token: string, refresh_token: string) => void,
7 | getToken: () => Promise,
8 | }
9 | const UserContext = React.createContext(null);
10 |
11 | export default UserContext;
12 |
--------------------------------------------------------------------------------
/client/designer/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 | import Designer from './components/Designer';
4 |
5 | ReactDOM.render(
6 | ,
7 | document.getElementById('root') as HTMLElement
8 | );
9 |
--------------------------------------------------------------------------------
/client/designer/models/adventure.ts:
--------------------------------------------------------------------------------
1 | import GameObject from "./game-object";
2 |
3 | /**
4 | * Adventure class. Represents adventures the player can go on.
5 | */
6 | export default class Adventure extends GameObject {
7 |
8 | name_sort: string;
9 | description: string;
10 | full_description: string;
11 | intro_text: string;
12 | slug: string;
13 | featured_month: string;
14 | date_published: string;
15 | times_played: string;
16 | authors: string[];
17 | authors_display: string;
18 | tags: string[];
19 | active: boolean;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/client/designer/models/effect.ts:
--------------------------------------------------------------------------------
1 | import GameObject from "./game-object";
2 |
3 | /**
4 | * Effect class. Represents special effect text that can be displayed
5 | * by scripts during game play.
6 | */
7 | export class Effect extends GameObject {
8 |
9 | id: number;
10 | text: string;
11 | style: string;
12 | next: number; // another effect chained onto this one
13 | next_inline: number; // a chained effect that is printed without a paragraph break
14 | replacements: Record; // strings that will be replaced within the effect text
15 |
16 | public excerpt(): string {
17 | if (this.text.length <= 50) {
18 | return this.text;
19 | }
20 | return this.text.slice(0, 50) + '...';
21 | }
22 |
23 | }
24 |
25 | export const TEXT_STYLES = {
26 | '': 'Normal',
27 | 'emphasis': 'Bold',
28 | 'success': 'Success (green)',
29 | 'special': 'Special 1 (blue)',
30 | 'special2': 'Special 1 (purple)',
31 | 'warning': 'Warning (orange)',
32 | 'danger': 'Danger (red)',
33 | }
34 |
--------------------------------------------------------------------------------
/client/designer/models/game-object.ts:
--------------------------------------------------------------------------------
1 | import { v4 as uuidv4 } from 'uuid';
2 |
3 | /**
4 | * GameObject class. Parent class for monsters and artifacts.
5 | */
6 | export default class GameObject {
7 |
8 | /**
9 | * The "id" is the database ID. Objects will only have a value for this if
10 | * they were saved to the DB (e.g., adventures, rooms, player artifacts)
11 | * (Artifacts created in the shop in the mail hall won't have this until they are saved.)
12 | */
13 | id: number;
14 |
15 | /**
16 | * The UUID is a temporary identifier used as a key for React elements.
17 | * It is not persisted to the database and doesn't need to be.
18 | */
19 | uuid: string;
20 | article: string;
21 | name: string;
22 | description: string;
23 | is_markdown: boolean;
24 | effect: number;
25 | effect_inline: number;
26 | synonyms: string;
27 |
28 | /**
29 | * Loads data from JSON source into the object properties.
30 | * @param {Record} source an object, e.g., from JSON.
31 | */
32 | public init(source: Record): void {
33 | this.uuid = uuidv4();
34 | for (const prop in source) {
35 | if (source.hasOwnProperty(prop)) {
36 | this[prop] = source[prop];
37 | }
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/client/designer/models/hint.ts:
--------------------------------------------------------------------------------
1 | import {Loadable} from "./loadable";
2 |
3 | export default class Hint extends Loadable {
4 |
5 | public id: number;
6 | public question: string;
7 | public index: string;
8 | public answers: Array>;
9 |
10 | // these are used by the display logic
11 | public current_index = 0;
12 | public is_open = false;
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/client/designer/models/loadable.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Loadable class. Parent class for all objects loaded from the database.
3 | */
4 | export abstract class Loadable {
5 |
6 | /**
7 | * Loads data from JSON source into the object properties.
8 | * @param Object source an object, e.g., from JSON.
9 | */
10 | init(source) {
11 | for (const prop in source) {
12 | this[prop] = source[prop];
13 | }
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/client/designer/repositories/base.repo.ts:
--------------------------------------------------------------------------------
1 | export class BaseRepository {
2 |
3 | /**
4 | * An array of all the Artifact objects
5 | */
6 | all: any[];
7 |
8 | /**
9 | * Gets the array index of a numbered artifact.
10 | * @param {number} id
11 | * @return number
12 | */
13 | getIndex(id: number | string): number {
14 | if (typeof id === 'string') id = parseInt(id);
15 | return this.all.findIndex(x => x.id === id);
16 | }
17 |
18 | /**
19 | * Gets the index of the previous object in the repository. Can
20 | * handle sparse numbering.
21 | *
22 | * @param {number} id
23 | * @return number
24 | */
25 | getPrev(id: number | string): number {
26 | if (typeof id === 'string') id = parseInt(id);
27 | const ids = this.all
28 | .filter(a => a.id < id)
29 | .map(a => a.id)
30 | .sort((a, b) => b - a); // `b - a` sorts in reverse order
31 | return ids.length ? ids[0] : null;
32 | }
33 |
34 | /**
35 | * Gets the index of the next object in the repository. Can
36 | * handle sparse numbering.
37 | *
38 | * @param {number} id
39 | * @return number
40 | */
41 | getNext(id: number | string): number {
42 | if (typeof id === 'string') id = parseInt(id);
43 | const ids = this.all
44 | .filter(a => a.id > id)
45 | .map(a => a.id)
46 | .sort((a, b) => a - b);
47 | return ids.length ? ids[0] : null;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/client/designer/repositories/hint.repo.ts:
--------------------------------------------------------------------------------
1 | import Hint from "../models/hint";
2 |
3 | /**
4 | * Class HintRepository.
5 | * Storage class for all hint data.
6 | */
7 | export default class HintRepository {
8 |
9 | /**
10 | * An array of all the Hint objects
11 | */
12 | all: Hint[] = [];
13 |
14 | /**
15 | * The highest ID in the system
16 | */
17 | index = 0;
18 |
19 | constructor(hint_data: Array>) {
20 | for (const i of hint_data) {
21 | this.add(i);
22 | }
23 | }
24 |
25 | /**
26 | * Adds a hint.
27 | * @param {Record} hint_data
28 | */
29 | public add(hint_data: Record): Hint {
30 | const h = new Hint();
31 |
32 | h.init(hint_data);
33 |
34 | // autonumber the ID if not provided
35 | if (h.id === undefined) {
36 | h.id = this.index + 1;
37 | }
38 |
39 | if (this.get(h.id) !== null) {
40 | throw new Error("Tried to create a hint #" + h.id + " but that ID is already taken.");
41 | }
42 |
43 | this.all.push(h);
44 |
45 | // update the autonumber index
46 | if (h.id > this.index) {
47 | this.index = h.id;
48 | }
49 | return h;
50 | }
51 |
52 | /**
53 | * Gets a hint by id.
54 | * @param {number} id
55 | * @return Hint
56 | */
57 | public get(id: number): Hint|null {
58 | const h = this.all.find(x => x.id === id);
59 | return h || null;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/client/designer/repositories/room.repo.ts:
--------------------------------------------------------------------------------
1 | import {Room} from "../models/room";
2 | import {BaseRepository} from "./base.repo";
3 | import {roomSource} from "../types";
4 |
5 | /**
6 | * Class RoomRepository.
7 | * Storage class for all room data.
8 | */
9 | export default class RoomRepository extends BaseRepository {
10 |
11 | /**
12 | * An array of all the Room objects
13 | */
14 | all: Room[] = [];
15 |
16 | /**
17 | * The object representing the room the player is currently in
18 | */
19 | current_room: Room;
20 |
21 | constructor(room_data: Array) {
22 | super();
23 | for (const i of room_data) {
24 | const r = new Room();
25 | r.init(i);
26 | this.all.push(r);
27 | }
28 | }
29 |
30 | /**
31 | * Gets a numbered room.
32 | * @param {number} id
33 | * @return Room
34 | */
35 | get(id: number|string): Room {
36 | if (typeof id === 'string') id = parseInt(id);
37 | const r = this.all.find(x => x.id === id);
38 | return r || null;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/client/designer/types.ts:
--------------------------------------------------------------------------------
1 |
2 | export type RouteParams = {
3 | slug: string,
4 | id?: string
5 | }
6 |
7 | export type roomSource = {
8 | id: number,
9 | name: string,
10 | exits: Record[]
11 | }
12 |
--------------------------------------------------------------------------------
/client/jest.config.mjs:
--------------------------------------------------------------------------------
1 | const config = {
2 | "maxWorkers": 1,
3 | "moduleFileExtensions": [
4 | "js",
5 | "jsx",
6 | "ts",
7 | "tsx"
8 | ],
9 | "preset": "ts-jest",
10 | "setupFiles": ['./jest.setup.js'],
11 | "setupFilesAfterEnv": ["jest-expect-message"],
12 | "testEnvironment": "jsdom",
13 | "testMatch": [
14 | "**/__tests__/**/*.ts?(x)",
15 | "**/?(*.)+(spec|test).ts?(x)"
16 | ],
17 | "testPathIgnorePatterns": [
18 | "/node_modules/",
19 | "/adventures/base-adventure/"
20 | ],
21 | "transformIgnorePatterns": [
22 | "/node_modules/(?!(axios|uuid))"
23 | ],
24 | "testEnvironmentOptions": {
25 | "url": "http://localhost:8000/"
26 | }
27 | }
28 |
29 | export default config;
30 |
--------------------------------------------------------------------------------
/client/jest.setup.js:
--------------------------------------------------------------------------------
1 | // This ensures you can use `window.fetch()` in your Jest tests.
2 | require('whatwg-fetch')
3 |
--------------------------------------------------------------------------------
/client/main-hall/components/MainHall.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {BrowserRouter as Router, Route, Routes} from "react-router-dom";
3 | import PlayerCreate from "./PlayerCreate";
4 | import PlayerDetail from "./PlayerDetail";
5 | import PlayerList from "./PlayerList";
6 |
7 | const MainHall = () => {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 | }/>
15 | }/>
16 | {/* non-exact route below is used so we can have child routes inside the component */}
17 | }/>
18 |
19 |
20 |
21 |
22 |
23 | );
24 | }
25 |
26 | export default MainHall;
27 |
--------------------------------------------------------------------------------
/client/main-hall/hooks.ts:
--------------------------------------------------------------------------------
1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
2 | import type { RootState, AppDispatch } from './store'
3 |
4 | // Use throughout your app instead of plain `useDispatch` and `useSelector`
5 | export const useAppDispatch = () => useDispatch()
6 | export const useAppSelector: TypedUseSelectorHook = useSelector
7 |
8 | export const usePlayer = () => {
9 | const dispatch = useAppDispatch();
10 | const player = useAppSelector((state) => state.player);
11 | const genderLabel = useAppSelector((state) => {
12 | return state.player.gender === 'm' ? "mighty" : "fair";
13 | })
14 |
15 | return {
16 | dispatch,
17 | player,
18 | genderLabel,
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/client/main-hall/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import MainHall from './components/MainHall';
5 | import registerServiceWorker from './registerServiceWorker';
6 | import store from './store/index';
7 |
8 | ReactDOM.render(
9 |
10 |
11 | ,
12 | document.getElementById('root') as HTMLElement
13 | );
14 | registerServiceWorker();
15 |
--------------------------------------------------------------------------------
/client/main-hall/models/adventure.ts:
--------------------------------------------------------------------------------
1 | import GameObject from "./game-object";
2 |
3 | /**
4 | * Adventure class. Represents adventures the player can go on.
5 | */
6 | export default interface Adventure extends GameObject {
7 |
8 | name_sort: string;
9 | description: string;
10 | full_description: string;
11 | slug: string;
12 | featured_month: string;
13 | date_published: string;
14 | times_played: string;
15 | authors: string[];
16 | authors_display: string;
17 | tags: string[];
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/client/main-hall/models/game-object.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * GameObject class. Parent class for monsters and artifacts.
3 | */
4 | export default interface GameObject {
5 | /**
6 | * The "id" is the database ID. Objects will only have a value for this if
7 | * they were saved to the DB (e.g., adventures, rooms, player artifacts)
8 | * (Artifacts created in the shop in the mail hall won't have this until they are saved.)
9 | */
10 | id: number;
11 |
12 | /**
13 | * The UUID is a temporary identifier used as a key for React elements.
14 | * It is not persisted to the database and doesn't need to be.
15 | */
16 | uuid: string;
17 | name: string;
18 | description: string;
19 | }
20 |
--------------------------------------------------------------------------------
/client/main-hall/store/index.ts:
--------------------------------------------------------------------------------
1 | import { configureStore } from '@reduxjs/toolkit';
2 |
3 | import playerReducer from './player';
4 | // import authReducer from './auth';
5 |
6 |
7 | const store = configureStore({
8 | reducer: { player: playerReducer },
9 | middleware: (getDefaultMiddleware) =>
10 | getDefaultMiddleware({
11 | serializableCheck: {
12 | // Ignore these action types
13 | ignoredActions: ['player/setPlayer'],
14 | // Ignore these paths in the state
15 | ignoredPaths: ['player'],
16 | },
17 | }),
18 | });
19 |
20 | export default store;
21 |
22 | // Infer the `RootState` and `AppDispatch` types from the store itself
23 | export type RootState = ReturnType
24 | // Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
25 | export type AppDispatch = typeof store.dispatch
26 |
--------------------------------------------------------------------------------
/client/main-hall/tests/MainHall.test.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 | import MainHall from '../components/MainHall';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/client/main-hall/tests/Player.test.ts:
--------------------------------------------------------------------------------
1 | import Player, {updateCachedInfo} from "../models/player";
2 | import Artifact, {ARMOR_TYPES, ARTIFACT_TYPES} from "../models/artifact";
3 |
4 | let player;
5 |
6 | beforeEach(() => {
7 | player = {} as Player;
8 | const artifact1 = {
9 | 'name': 'trollsfire',
10 | 'type': ARTIFACT_TYPES.WEAPON,
11 | 'dice': 2,
12 | 'sides': 10
13 | } as Artifact;
14 | const artifact2 = {
15 | 'name': 'axe',
16 | 'type': ARTIFACT_TYPES.WEAPON,
17 | 'dice': 1,
18 | 'sides': 6
19 | } as Artifact;
20 | const artifact3 = {
21 | 'name': 'leather armor',
22 | 'type': ARTIFACT_TYPES.WEARABLE,
23 | 'armor_type': ARMOR_TYPES.ARMOR,
24 | 'armor_class': 1
25 | } as Artifact;
26 | player.inventory = [artifact1, artifact2, artifact3];
27 | updateCachedInfo(player);
28 | });
29 |
30 | it('can determine best weapon and armor', () => {
31 | expect(player.best_weapon.name).toBe('trollsfire');
32 | expect(player.best_armor.name).toBe('leather armor');
33 | });
34 |
--------------------------------------------------------------------------------
/client/main-hall/utils/dice.ts:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Rolls a set of dice
4 | */
5 | export default function diceRoll(dice: number, sides: number): number {
6 | let result = 0;
7 | for (let i = 0; i < dice; i++) {
8 | result += Math.floor(Math.random() * sides + 1);
9 | }
10 | return result;
11 | }
12 |
--------------------------------------------------------------------------------
/client/main-hall/utils/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Main utilities file. Contains a bunch of utility functions like "titleCase" and "percentOrNone".
3 | */
4 |
5 | /**
6 | * Title Case function.
7 | *
8 | * Example of usage:
9 | *
10 | * ```
11 | * import { titleCase } from "../utils"
12 | * const str = 'foo bar';
13 | * console.log(titleCase(str)); // outputs "Foo Bar"
14 | * ```
15 | *
16 | * @param {string} input
17 | * @return {string}
18 | */
19 | export function titleCase(input: string): string {
20 | if (!input) {
21 | return '';
22 | } else {
23 | return input.replace(/\w\S*/g, (txt => txt[0].toUpperCase() + txt.substr(1).toLowerCase() ));
24 | }
25 | }
26 |
27 | /**
28 | * Capitalizes the first letter of a string.
29 | * From https://dzone.com/articles/how-to-capitalize-the-first-letter-of-a-string-in
30 | * @return string
31 | * @param {string} str
32 | */
33 | export function ucFirst(str: string): string {
34 | return str.charAt(0).toUpperCase() + str.slice(1);
35 | }
36 |
37 | /**
38 | * Outputs the input as a number shown with a percent sign, unless the input is
39 | * zero or not a valid number, in which case it outputs "none"
40 | *
41 | * @param {string} input
42 | * @return string
43 | */
44 | export function percentOrNone(input: string): string {
45 | const n = parseFloat(input);
46 | if (n === 0 || isNaN(n)) {
47 | return 'none';
48 | } else {
49 | return n + "%";
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/client/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "jsx": "react",
5 | "lib": ["es5", "es6", "dom"],
6 | "module": "commonjs",
7 | "noImplicitAny": false,
8 | "outDir": "./dist/",
9 | "sourceMap": true,
10 | "target": "es5",
11 | },
12 | "include": [
13 | "./main-hall/**/*",
14 | "./core/**/*"
15 | ],
16 | "files": ["node_modules/jest-expect-message/types/index.d.ts"]
17 | }
18 |
--------------------------------------------------------------------------------
/client/tsconfig.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json"
3 | }
--------------------------------------------------------------------------------
/client/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs"
5 | }
6 | }
--------------------------------------------------------------------------------
/client/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
3 | "linterOptions": {
4 | "exclude": [
5 | "config/**/*.js",
6 | "node_modules/**/*.ts",
7 | "coverage/lcov-report/*.js"
8 | ]
9 | },
10 | "rules": {
11 | "forin": false,
12 | "jsx-no-lambda": false,
13 | "member-access": false,
14 | "member-ordering": false,
15 | "no-console": false,
16 | "no-debugger": false,
17 | "no-empty": false,
18 | "object-literal-sort-keys": false,
19 | "ordered-imports": false,
20 | "prefer-const": false,
21 | "variable-name": false
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/db/eamon.sqlite3.dist:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/db/eamon.sqlite3.dist
--------------------------------------------------------------------------------
/db/query magic wand type weapons.sql:
--------------------------------------------------------------------------------
1 | SELECT * FROM adventure_artifact WHERE (NAME LIKE '%magic%' OR NAME LIKE '%wand%' OR NAME LIKE '%orb%') AND TYPE IN (2,3) AND weapon_type = 2 AND NAME != 'magic bow'
2 | UNION
3 | SELECT * FROM adventure_artifact WHERE NAME = 'Magic blue sphere' -- from prince's tavern
--------------------------------------------------------------------------------
/db/room exits for adventure.sql:
--------------------------------------------------------------------------------
1 | SELECT r.room_id, r.name, re.direction, re.room_from_id, re.room_to, re.door_id, re.effect_id, re.id
2 | FROM adventure_roomexit re
3 | INNER JOIN adventure_room r ON re.room_from_id = r.id
4 | WHERE r.adventure_id = 1
5 |
--------------------------------------------------------------------------------
/designer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/designer/__init__.py
--------------------------------------------------------------------------------
/designer/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class DesignerConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'designer'
7 |
--------------------------------------------------------------------------------
/designer/templates/designer.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load static %}
3 |
4 | {% block title %}Adventure Designer{% endblock %}
5 |
6 | {% block scripts %}
7 |
8 | {% endblock %}
9 |
10 | {% block content %}
11 |
12 | Welcome to the Eamon Adventure Designer...
13 |
14 |
15 | {% endblock %}
16 |
--------------------------------------------------------------------------------
/designer/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from . import views
3 |
4 | urlpatterns = [
5 | # The following route will match anything starting with "designer" with or without a trailing slash.
6 | # Any routes matched here will be sent to the "designer" react app.
7 | # Additional path info in the route will be handled by the react router.
8 | url(r'^designer', views.designer, name='designer'),
9 | ]
10 |
--------------------------------------------------------------------------------
/designer/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 |
4 | def designer(request):
5 | """
6 | The container for the "designer" react app
7 | """
8 | return render(request, 'designer.html')
9 |
--------------------------------------------------------------------------------
/eamon/local_settings_example.py:
--------------------------------------------------------------------------------
1 | DEBUG = True
2 |
3 | # Uncomment the following if you want to use a MySQL database
4 | # instead of SQLite.
5 | # You also need to run `pip install mysqlclient` (But don't freeze it. That package
6 | # should not be listed in Pipfile.)
7 | DATABASES = {
8 | 'default': {
9 | 'ENGINE': 'django.db.backends.mysql',
10 | 'HOST': 'localhost',
11 | 'USER': 'root',
12 | 'PASSWORD': 'root',
13 | 'NAME': 'eamon',
14 | 'OPTIONS': {
15 | 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/eamon/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import include, url
2 | from django.contrib import admin
3 |
4 | from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
5 |
6 | urlpatterns = [
7 | url(r'^admin/', admin.site.urls),
8 |
9 | url('api/token/$', TokenObtainPairView.as_view(), name='token_obtain_pair'),
10 | url('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
11 |
12 | url(r'^', include('adventure.urls')),
13 | url(r'^', include('designer.urls')),
14 | ]
15 |
--------------------------------------------------------------------------------
/eamon/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for eamonproj project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 | import time
12 | import traceback
13 | import signal
14 | import sys
15 |
16 | from django.core.wsgi import get_wsgi_application
17 |
18 | sys.path.append('/var/www/vhosts/eamon')
19 | sys.path.append('/var/www/vhosts/eamon/venv/lib/python3.5/site-packages')
20 |
21 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "eamon.settings")
22 |
23 | application = get_wsgi_application()
24 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "eamon.settings")
7 |
8 | from django.core.management import execute_from_command_line
9 |
10 | execute_from_command_line(sys.argv)
11 |
--------------------------------------------------------------------------------
/news/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/news/__init__.py
--------------------------------------------------------------------------------
/news/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import Article
3 |
4 |
5 | @admin.register(Article)
6 | class ArticleAdmin(admin.ModelAdmin):
7 | list_display = ('__str__', 'created_at')
8 |
--------------------------------------------------------------------------------
/news/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class NewsConfig(AppConfig):
5 | name = 'news'
6 |
--------------------------------------------------------------------------------
/news/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11 on 2017-05-27 07:19
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Article',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('title', models.CharField(max_length=255)),
21 | ('body', models.TextField()),
22 | ('created_at', models.DateField()),
23 | ],
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/news/migrations/0002_auto_20170527_0125.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11 on 2017-05-27 08:25
3 | from __future__ import unicode_literals
4 |
5 | import ckeditor.fields
6 | from django.db import migrations
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('news', '0001_initial'),
13 | ]
14 |
15 | operations = [
16 | migrations.AlterField(
17 | model_name='article',
18 | name='body',
19 | field=ckeditor.fields.RichTextField(),
20 | ),
21 | ]
22 |
--------------------------------------------------------------------------------
/news/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/news/migrations/__init__.py
--------------------------------------------------------------------------------
/news/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from ckeditor.fields import RichTextField
3 |
4 |
5 | class Article(models.Model):
6 | title = models.CharField(max_length=255)
7 | body = RichTextField()
8 | created_at = models.DateField()
9 |
10 | def __str__(self):
11 | return self.title
12 |
--------------------------------------------------------------------------------
/news/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 | from django.urls import reverse
3 | from .models import Article
4 |
5 |
6 | class ModelsTest(TestCase):
7 | def setUp(self):
8 | Article.objects.create(id=1, title="Clone army invades west coast",
9 | created_at="2019-01-01")
10 |
11 | def test_object(self):
12 | a1 = Article.objects.get(pk=1)
13 | self.assertEqual(str(a1), "Clone army invades west coast")
14 |
15 |
16 | class ViewTests(TestCase):
17 |
18 | def test_news(self):
19 | Article.objects.create(id=1, title="Clone army invades west coast", body="Lorem ipsum...",
20 | created_at="2019-01-01")
21 | Article.objects.create(id=2, title="Pirates spotted in Eamon Harbor", body="more text here",
22 | created_at="2019-01-01")
23 | response = self.client.get(reverse('news'))
24 | self.assertEqual(response.status_code, 200)
25 | self.assertContains(response, "Clone army invades west coast")
26 | self.assertContains(response, "Lorem ipsum")
27 | self.assertContains(response, "Pirates spotted in Eamon Harbor")
28 | self.assertContains(response, "more text here")
29 |
--------------------------------------------------------------------------------
/news/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url, include
2 |
3 | from . import views
4 |
5 | urlpatterns = [
6 | url(r'^$', views.news, name='news'),
7 | ]
8 |
--------------------------------------------------------------------------------
/news/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
3 |
4 | from .models import Article
5 |
6 |
7 | def news(request):
8 | article_list = Article.objects.order_by('-created_at')
9 | page = request.GET.get('page', 1)
10 | paginator = Paginator(article_list, 3)
11 |
12 | try:
13 | articles = paginator.page(page)
14 | except PageNotAnInteger:
15 | articles = paginator.page(1)
16 | except EmptyPage:
17 | articles = paginator.page(paginator.num_pages)
18 |
19 | return render(request, 'news.html', {'articles': articles})
20 |
--------------------------------------------------------------------------------
/player/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/player/__init__.py
--------------------------------------------------------------------------------
/player/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/player/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class PlayerConfig(AppConfig):
5 | name = 'player'
6 |
--------------------------------------------------------------------------------
/player/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.2 on 2018-04-15 19:02
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | ('adventure', '0048_auto_20180304_1832'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='SavedGame',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('slot', models.IntegerField(null=True)),
21 | ('description', models.CharField(blank=True, default='', max_length=255)),
22 | ('data', models.TextField(max_length=1000000, null=True)),
23 | ('adventure', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='saved_games', to='adventure.Adventure')),
24 | ('player', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='saved_games', to='adventure.Player')),
25 | ],
26 | ),
27 | ]
28 |
--------------------------------------------------------------------------------
/player/migrations/0002_savedgame_created.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.4 on 2018-04-30 04:54
2 |
3 | from django.db import migrations, models
4 | import django.utils.timezone
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('player', '0001_initial'),
11 | ]
12 |
13 | operations = [
14 | migrations.AddField(
15 | model_name='savedgame',
16 | name='created',
17 | field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
18 | preserve_default=False,
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/player/migrations/0003_rating.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.1 on 2019-07-04 04:49
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('adventure', '0058_auto_20190703_2149'),
11 | ('player', '0002_savedgame_created'),
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='Rating',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('uuid', models.CharField(max_length=255, null=True)),
20 | ('overall', models.IntegerField(blank=True, null=True)),
21 | ('combat', models.IntegerField(blank=True, null=True)),
22 | ('puzzle', models.IntegerField(blank=True, null=True)),
23 | ('created', models.DateTimeField(auto_now_add=True, null=True)),
24 | ('adventure', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ratings', to='adventure.Adventure')),
25 | ],
26 | ),
27 | ]
28 |
--------------------------------------------------------------------------------
/player/migrations/0006_alter_savedgame_player.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.12 on 2022-05-15 08:52
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('player', '0005_move_player_data'),
11 | ]
12 |
13 | operations = [
14 | # migrations.AlterField(
15 | # model_name='savedgame',
16 | # name='player',
17 | # field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='saved_games', to='player.player'),
18 | # ),
19 | ]
20 |
--------------------------------------------------------------------------------
/player/migrations/0007_playerprofile_slug.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.6 on 2022-05-21 13:39
2 |
3 | from django.db import migrations, models
4 | from player.models import generate_slug
5 |
6 |
7 | def populate_slug(apps, schema_editor):
8 | Player = apps.get_model('player', 'Player')
9 | PlayerProfile = apps.get_model('player', 'PlayerProfile')
10 |
11 | uuids = Player.objects.values_list('uuid', flat=True).distinct()
12 | for uuid in uuids:
13 | profile = PlayerProfile.objects.get_or_create(uuid=uuid)[0]
14 | print(repr(profile))
15 | slug = generate_slug()
16 | while PlayerProfile.objects.filter(slug=slug).exists():
17 | slug = generate_slug()
18 | profile.slug = slug
19 | profile.save()
20 |
21 |
22 | class Migration(migrations.Migration):
23 |
24 | dependencies = [
25 | ('player', '0006_alter_savedgame_player'),
26 | ]
27 |
28 | operations = [
29 | migrations.AddField(
30 | model_name='playerprofile',
31 | name='slug',
32 | field=models.CharField(max_length=6, null=True),
33 | ),
34 | migrations.RunPython(populate_slug, migrations.RunPython.noop)
35 | ]
36 |
--------------------------------------------------------------------------------
/player/migrations/0008_activitylog.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.6 on 2022-05-21 14:37
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('adventure', '0067_roomexit_hintanswer_adventure_id'),
11 | ('player', '0007_playerprofile_slug'),
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='ActivityLog',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('type', models.CharField(max_length=255)),
20 | ('value', models.IntegerField(blank=True, null=True)),
21 | ('created', models.DateTimeField(auto_now_add=True, null=True)),
22 | ('adventure', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='new_activity_log', to='adventure.adventure')),
23 | ('player', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='activity_log', to='player.player')),
24 | ],
25 | ),
26 | ]
27 |
--------------------------------------------------------------------------------
/player/migrations/0009_move_activity_log.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.12 on 2022-05-15 08:36
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('player', '0008_activitylog'),
10 | ]
11 |
12 | operations = [
13 | migrations.RunSQL('SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0'),
14 |
15 | migrations.RunSQL(
16 | 'REPLACE INTO eamon.player_activitylog '
17 | '(id, `type`, value, created, adventure_id, player_id) '
18 | ' SELECT id, `type`, value, created, adventure_id, player_id '
19 | ' FROM adventure_activitylog'),
20 |
21 | migrations.RunSQL('SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS')
22 | ]
23 |
--------------------------------------------------------------------------------
/player/migrations/0010_alter_savedgame_player.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.12 on 2022-05-15 08:52
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('player', '0009_move_activity_log'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='savedgame',
16 | name='player',
17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='saved_games', to='player.player'),
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/player/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/player/migrations/__init__.py
--------------------------------------------------------------------------------
/player/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url, include
2 | from rest_framework import routers
3 |
4 | from .views import LogViewSet, PlayerViewSet, PlayerProfileViewSet, RatingViewSet, SavedGameViewSet
5 |
6 | # Note: This file is not currently used. See /adventure/urls.py
7 |
8 | router = routers.DefaultRouter(trailing_slash=False)
9 | router.register(r'players', PlayerViewSet)
10 | router.register(r'profiles', PlayerProfileViewSet)
11 | router.register(r'saves', SavedGameViewSet)
12 | router.register(r'ratings', RatingViewSet)
13 | router.register(r'log', LogViewSet)
14 |
15 | urlpatterns = [
16 | # REST API routes
17 | url(r'^api/player', include(router.urls)),
18 | ]
19 |
--------------------------------------------------------------------------------
/sample_import/effects.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "text": "this is sample text"
5 | },
6 | {
7 | "id": 2,
8 | "text": "this is sample text"
9 | }
10 | ]
11 |
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdechant/eamon/3c39dfea70cc7b71d1bc42b21df4e6f586383d34/static/.gitkeep
--------------------------------------------------------------------------------
/truncate.sql:
--------------------------------------------------------------------------------
1 | SET FOREIGN_KEY_CHECKS = 0;
2 | TRUNCATE `adventure_adventure`;
3 | TRUNCATE `adventure_artifact`;
4 | TRUNCATE `adventure_artifactmarking`;
5 | TRUNCATE `adventure_effect`;
6 | TRUNCATE `adventure_monster`;
7 | TRUNCATE `adventure_room`;
8 | SET FOREIGN_KEY_CHECKS = 1;
--------------------------------------------------------------------------------