initial import
This commit is contained in:
commit
22c16c8146
0
.agents/skills/.gitkeep
Normal file
0
.agents/skills/.gitkeep
Normal file
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
node_modules/
|
||||
dist/
|
||||
coverage/
|
||||
*.log
|
||||
.env
|
||||
.env.local
|
||||
**/*.iml
|
||||
**/.idea
|
||||
**/*.received.*
|
||||
**/DS_Store/*
|
||||
**/.DS_Store
|
||||
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
coverage/
|
||||
package-lock.json
|
||||
7
.prettierrc.json
Normal file
7
.prettierrc.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2
|
||||
}
|
||||
13
AGENTS.md
Normal file
13
AGENTS.md
Normal file
@ -0,0 +1,13 @@
|
||||
**ALWAYS** start replies with ⚔️.
|
||||
|
||||
## What this project is
|
||||
|
||||
An implementation of the RPG Combat rules engine. There are six user stories described in [user-stories.md](user-stories.md)
|
||||
|
||||
## Build and Test Scripts
|
||||
|
||||
- `npm test`: runs unit tests using vitest
|
||||
- `npm run lint:fix`: runs eslint with autofix
|
||||
- `npm run format:fix`: runs prettier with autofix
|
||||
- `npm run typecheck`: runs tsc without emit
|
||||
- `npm run checks`: runs the pre-commit gate (format:fix, lint:fix, typecheck, test)
|
||||
8
README.md
Normal file
8
README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# RPG Combat
|
||||
|
||||
Use this starting template for your implementation of the game rules. Requires Node.js and npm. Install dependencies, then run the tests:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm test
|
||||
```
|
||||
78
eslint.config.js
Normal file
78
eslint.config.js
Normal file
@ -0,0 +1,78 @@
|
||||
import js from '@eslint/js';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import prettier from 'eslint-config-prettier';
|
||||
|
||||
export default tseslint.config(
|
||||
{ ignores: ['dist', 'node_modules', 'coverage'] },
|
||||
|
||||
js.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
|
||||
{
|
||||
files: ['src/**/*.ts'],
|
||||
extends: [...tseslint.configs.recommendedTypeChecked],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/switch-exhaustiveness-check': 'warn',
|
||||
'@typescript-eslint/no-unnecessary-condition': 'warn',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
rules: {
|
||||
complexity: ['warn', 12],
|
||||
'max-depth': ['warn', 4],
|
||||
'max-params': ['warn', 4],
|
||||
'max-lines-per-function': [
|
||||
'warn',
|
||||
{ max: 60, skipBlankLines: true, skipComments: true, IIFEs: true },
|
||||
],
|
||||
|
||||
'no-else-return': ['warn', { allowElseIf: false }],
|
||||
'no-lonely-if': 'warn',
|
||||
'no-param-reassign': ['warn', { props: false }],
|
||||
eqeqeq: ['warn', 'always', { null: 'ignore' }],
|
||||
|
||||
'prefer-const': 'warn',
|
||||
'prefer-template': 'warn',
|
||||
'object-shorthand': 'warn',
|
||||
'no-console': 'warn',
|
||||
|
||||
'@typescript-eslint/explicit-function-return-type': [
|
||||
'warn',
|
||||
{
|
||||
allowExpressions: true,
|
||||
allowTypedFunctionExpressions: true,
|
||||
allowHigherOrderFunctions: true,
|
||||
allowDirectConstAssertionInArrowFunctions: true,
|
||||
allowIIFEs: true,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/consistent-type-imports': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'warn',
|
||||
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' },
|
||||
],
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
'@typescript-eslint/no-non-null-assertion': 'warn',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
files: ['**/*.test.ts', '**/*.spec.ts'],
|
||||
rules: {
|
||||
'max-lines-per-function': 'off',
|
||||
'max-params': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
prettier,
|
||||
);
|
||||
21
license.txt
Normal file
21
license.txt
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2026 Samman Technical Coaching Society
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
2489
package-lock.json
generated
Normal file
2489
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
package.json
Normal file
31
package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "rpg-combat",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "vitest run",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"format": "prettier --check .",
|
||||
"format:fix": "prettier --write .",
|
||||
"checks": "npm run format:fix && npm run lint:fix && npm run typecheck && npm test"
|
||||
},
|
||||
"keywords": [
|
||||
"kata"
|
||||
],
|
||||
"author": "<put your name here>",
|
||||
"license": "MIT",
|
||||
"description": "A TypeScript implementation of RPG Combat",
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@types/node": "^25.9.1",
|
||||
"eslint": "^10.4.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"prettier": "^3.8.3",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.60.0",
|
||||
"vitest": "^4.1.7"
|
||||
}
|
||||
}
|
||||
22
tsconfig.json
Normal file
22
tsconfig.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"target": "es2022",
|
||||
"types": [],
|
||||
"strict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitOverride": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"noUncheckedSideEffectImports": true,
|
||||
"moduleDetection": "force",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"noEmit": true,
|
||||
"allowImportingTsExtensions": true
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
70
user-stories.md
Normal file
70
user-stories.md
Normal file
@ -0,0 +1,70 @@
|
||||
# RPG Combat
|
||||
|
||||
This is a description of the business rules we should support in the game engine.
|
||||
|
||||
|
||||
## Damage and Health
|
||||
|
||||
1. All Characters, when created, have:
|
||||
- Health, starting at 1000
|
||||
- May be Alive or Dead, starting Alive
|
||||
|
||||
2. Characters can Deal Damage to Characters.
|
||||
- Damage is subtracted from Health
|
||||
- When damage received exceeds current Health, Health becomes 0 and the character dies
|
||||
- A Character cannot Deal Damage to itself
|
||||
|
||||
3. A Character can Heal themselves.
|
||||
- Dead characters cannot heal
|
||||
|
||||
## Levels
|
||||
|
||||
1. All characters have a Level, starting at 1
|
||||
- A Character cannot have a health above 1000 until they reach level 6, when the maximum increases to 1500
|
||||
|
||||
2. When dealing damage:
|
||||
- If the target is 5 or more Levels above the attacker, Damage is reduced by 50%
|
||||
- If the target is 5 or more Levels below the attacker, Damage is increased by 50%
|
||||
|
||||
## Factions
|
||||
|
||||
1. Characters may belong to one or more Factions.
|
||||
- Newly created Characters belong to no Faction.
|
||||
|
||||
2. A Character may Join or Leave one or more Factions.
|
||||
|
||||
3. Players belonging to the same Faction are considered Allies.
|
||||
- Allies cannot Deal Damage to one another.
|
||||
- Allies can Heal one another and non-allies cannot.
|
||||
|
||||
## Magical objects
|
||||
|
||||
1. As well as Characters there are also Magical Objects
|
||||
- Magical Objects have Health
|
||||
- The maximum amount of Health is fixed at the time the object is created
|
||||
- When reduced to 0 Health, Magical Objects are *Destroyed*
|
||||
- Magical Objects cannot be Healed by Characters
|
||||
- Magical Objects do not belong to Factions; they are neutral
|
||||
|
||||
2. Characters can gain health from a Healing Magical Object.
|
||||
- Characters can gain any amount of health from the Object, up to its maximum and theirs
|
||||
- Healing Magical Objects cannot deal Damage
|
||||
|
||||
3. Characters can deal Damage by using a Magical Weapon.
|
||||
- These Magical Objects deal a fixed amount of damage when they are used
|
||||
- The amount of damage is fixed at the time the weapon is created
|
||||
- Every time the weapon is used, the Health is reduced by 1
|
||||
- Magical Weapons cannot give Health to a Character
|
||||
|
||||
## Changing level
|
||||
|
||||
1. Level 1 Characters that survive 1000 damage points gain a level, (this may be counted over several battles)
|
||||
- a character cannot gain a level while receiving damage, it happens directly afterwards (if the player is still alive)
|
||||
- Level 2 Characters need to survive an additional 2000 damage points to gain a level, Level 3 Characters need to survive an additional 3000, and so on.
|
||||
|
||||
2. Level 1 Characters that have ever been part of 3 distinct factions gain a level
|
||||
- Level 2 Characters need to join an additional 3 distinct factions to gain a level, Level 3 Characters need to join an additional 3, and so on.
|
||||
|
||||
3. The maximum Level for Characters is 10
|
||||
- Characters cannot lose a level they have gained
|
||||
|
||||
7
vitest.config.ts
Normal file
7
vitest.config.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.ts'],
|
||||
},
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user