Skip to content

Commit

Permalink
fix: friendly can be used for allies (close #157)
Browse files Browse the repository at this point in the history
  • Loading branch information
valentine195 committed May 2, 2023
1 parent 6fea212 commit 114896f
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 69 deletions.
16 changes: 11 additions & 5 deletions src/encounter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,13 @@ export class EncounterParser {
hidden = true;
monster = monster.replace(/,\s*hidden/, "");
}
if (monster.match(/,\s+friend/) || monster.match(/,\s+ally/)) {
if (
monster.match(/,\s+friend(?:ly)?/) ||
monster.match(/,\s+ally/)
) {
friendly = true;
monster = monster
.replace(/,\s*friend/, "")
.replace(/,\s*friend(?:ly)?/, "")
.replace(/,\s*ally/, "");
}
name = monster.split(/,\s?/)[0];
Expand All @@ -246,12 +249,15 @@ export class EncounterParser {
hidden = monster.slice(1).find((v) => v == "hidden") != undefined;

friendly =
monster.slice(1).find((v) => v == "friend" || v == "ally") !=
undefined;
monster
.slice(1)
.find(
(v) => v == "friend" || v == "friendly" || v == "ally"
) != undefined;

[hp, ac, mod, xp] = monster
.slice(1)
.filter((v) => v != "hidden" && v != "friend" && v != "ally")
.filter((v) => v != "hidden" && v != "friend" && v != "friendly" && v != "ally")
.map((v) => (isNaN(Number(v)) ? null : Number(v)));
} else if (typeof monster == "object") {
({ creature: name, name: display, hp, ac, mod, xp } = monster);
Expand Down
146 changes: 82 additions & 64 deletions test/parseEncounter.test.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
import { App, PluginManifest, parseYaml } from 'obsidian';
import YAML from 'yaml';
import InitiativeTracker from '../src/main';
import { EncounterParameters, EncounterParser, ParsedParams } from '../src/encounter';
import { DEFAULT_SETTINGS } from '../src/utils/constants';
import { BESTIARY } from '../src/utils/srd-bestiary';
import type { Creature } from '../src/utils/creature';
import { App, PluginManifest, parseYaml } from "obsidian";
import YAML from "yaml";
import InitiativeTracker from "../src/main";
import {
EncounterParameters,
EncounterParser,
ParsedParams
} from "../src/encounter";
import { DEFAULT_SETTINGS } from "../src/utils/constants";
import { BESTIARY } from "../src/utils/srd-bestiary";
import type { Creature } from "../src/utils/creature";

export const MANIFEST: PluginManifest = {
"id": "initiative-tracker",
"name": "Initiative Tracker",
"version": "9.5.0",
"minAppVersion": "0.15.0",
"author": "Jeremy Valentine",
"description": ""
}

jest.mock('obsidian', () => ({
id: "initiative-tracker",
name: "Initiative Tracker",
version: "9.5.0",
minAppVersion: "0.15.0",
author: "Jeremy Valentine",
description: ""
};

jest.mock("obsidian", () => ({
App: jest.fn().mockImplementation(),
Platform: jest.fn().mockImplementation(() => {
return {
isMobile: false,
isMobile: false
};
}),
MarkdownRenderChild: jest.fn().mockImplementation(),
parseYaml: (yaml: string) => YAML.parse(yaml),
parseYaml: (yaml: string) => YAML.parse(yaml)
}));

jest.mock('../src/main', () => {
jest.mock("../src/main", () => {
return jest.fn().mockImplementation(() => {
return {
defaultParty: [],
Expand All @@ -37,58 +41,57 @@ jest.mock('../src/main', () => {
});
});

describe('Encounter Parser', () => {
describe("Encounter Parser", () => {
const plugin = new InitiativeTracker(new App(), MANIFEST);
const parser = new EncounterParser(plugin);

test('parseEncounter: single line', async () => {
test("parseEncounter: single line", async () => {
// Rat, Giant is not in the SRD, so it should be treated as a custom creature
// will use the name Snuggletooth (adorable), but no other stats
const encounter = `2: [["Rat, Giant", Snuggletooth]]`;

const params: EncounterParameters = {};
params.creatures = parseYaml('[' + encounter + ']');
params.creatures = parseYaml("[" + encounter + "]");

const result: ParsedParams = await parser.parse(params);
expect(result).toHaveProperty('creatures');
expect(result).toHaveProperty("creatures");
expect(result.creatures.size).toBe(1);

const creature: Creature = result.creatures.keys().next().value;
const amount = result.creatures.get(creature);
expect(creature.name).toBe('Rat, Giant');
expect(creature.display).toBe('Snuggletooth');
expect(creature.hp).toBeUndefined();
expect(creature.ac).toBeUndefined();
expect(creature.name).toBe("Rat, Giant");
expect(creature.display).toBe("Snuggletooth");
expect(creature.hp).toBeFalsy();
expect(creature.ac).toBeFalsy();
expect(creature.modifier).toBe(0); // 0 is the default
expect(creature.friendly).toBe(false);
expect(amount).toBe(2);
});

test('parseEncounter: single line friend', async () => {
test("parseEncounter: single line friend", async () => {
// Rat, Giant is not in the SRD, so it should be treated as a custom creature
// will use assigned values and the name Snuggletooth
const encounter = `2: [["Rat, Giant", Snuggletooth], 12, 13,ally]`;

const params: EncounterParameters = {};
params.creatures = parseYaml('[' + encounter + ']');
params.creatures = parseYaml("[" + encounter + "]");

const result: ParsedParams = await parser.parse(params);
expect(result).toHaveProperty('creatures');
expect(result).toHaveProperty("creatures");
expect(result.creatures.size).toBe(1);

const creature: Creature = result.creatures.keys().next().value;
const amount = result.creatures.get(creature);
expect(creature.name).toBe('Rat, Giant');
expect(creature.display).toBe('Snuggletooth');
expect(creature.name).toBe("Rat, Giant");
expect(creature.display).toBe("Snuggletooth");
expect(creature.hp).toBe(12);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(0); // 0 is the default
expect(creature.friendly).toBe(true);
expect(amount).toBe(2);
});


test('parseEncounter: creature stats', async () => {
test("parseEncounter: creature stats", async () => {
// Goblins are found in the SRD (7 hp, 15, ac, +2 modifier)
// goblins w/ the same stats are combined

Expand All @@ -102,23 +105,23 @@ creatures:
const params: EncounterParameters = parseYaml(encounter);

const result = await parser.parse(params);
expect(result).toHaveProperty('creatures');
expect(result.creatures.size).toBe(3);
expect(result).toHaveProperty("creatures");
expect(result.creatures.size).toBe(3);

const k = result.creatures.keys();

let creature: Creature = k.next().value;
let amount = result.creatures.get(creature);
expect(creature.name).toBe('My Monster');
expect(creature.hp).toBeUndefined();
expect(creature.ac).toBeUndefined();
expect(creature.name).toBe("My Monster");
expect(creature.hp).toBeFalsy();
expect(creature.ac).toBeFalsy();
expect(creature.modifier).toBe(0); // 0 is the default
expect(creature.friendly).toBe(false);
expect(amount).toBe(1);

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Goblin');
expect(creature.name).toBe("Goblin");
expect(creature.hp).toBe(7);
expect(creature.ac).toBe(15);
expect(creature.modifier).toBe(2);
Expand All @@ -127,16 +130,15 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Goblin');
expect(creature.name).toBe("Goblin");
expect(creature.hp).toBe(5);
expect(creature.ac).toBe(15);
expect(creature.modifier).toBe(2);
expect(creature.friendly).toBe(false);
expect(amount).toBe(3);
});


test('parseEncounter: creature names', async () => {
test("parseEncounter: creature names", async () => {
// Giant Rat called TeddyBear is in the SRD
// Giant Rat called Snuggletooth overrides those stats (and is combined across two formats)
// Giant Rat called Sarah uses same stats as Snuggletooth, but is not combined
Expand All @@ -158,14 +160,14 @@ creatures:

const params: EncounterParameters = parseYaml(encounter);
const result = await parser.parse(params);
expect(result).toHaveProperty('creatures');
expect(result).toHaveProperty("creatures");
expect(result.creatures.size).toBe(3); // goblins w/ the same stats are combined

const k = result.creatures.keys();

let creature: Creature = k.next().value;
let amount = result.creatures.get(creature);
expect(creature.name).toBe('Giant Rat');
expect(creature.name).toBe("Giant Rat");
expect(creature.hp).toBe(7);
expect(creature.ac).toBe(12);
expect(creature.modifier).toBe(2);
Expand All @@ -174,8 +176,8 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Giant Rat');
expect(creature.display).toBe('Snuggletooth');
expect(creature.name).toBe("Giant Rat");
expect(creature.display).toBe("Snuggletooth");
expect(creature.hp).toBe(12);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(2);
Expand All @@ -184,8 +186,8 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Giant Rat');
expect(creature.display).toBe('Sarah');
expect(creature.name).toBe("Giant Rat");
expect(creature.display).toBe("Sarah");
expect(creature.hp).toBe(12);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(2);
Expand All @@ -194,8 +196,7 @@ creatures:
expect(amount).toBeLessThan(6);
});


test('parseEncounter: creature names', async () => {
test("parseEncounter: creature names", async () => {
// Hobgoblins are found in the SRD
// Most have different names and/or stats.. some gotchas
const encounter = `
Expand Down Expand Up @@ -233,8 +234,8 @@ creatures:

let creature: Creature = k.next().value;
let amount = result.creatures.get(creature);
expect(creature.name).toBe('Hobgoblin');
expect(creature.display).toBe('Bob');
expect(creature.name).toBe("Hobgoblin");
expect(creature.display).toBe("Bob");
expect(creature.hp).toBe(11);
expect(creature.ac).toBe(18);
expect(creature.modifier).toBe(1);
Expand All @@ -244,8 +245,8 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Hobgoblin');
expect(creature.display).toBe('Jim');
expect(creature.name).toBe("Hobgoblin");
expect(creature.display).toBe("Jim");
expect(creature.hp).toBe(12);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(2);
Expand All @@ -255,8 +256,8 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Hobgoblin');
expect(creature.display).toBe('Jeff');
expect(creature.name).toBe("Hobgoblin");
expect(creature.display).toBe("Jeff");
expect(creature.hp).toBe(21);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(1);
Expand All @@ -266,8 +267,8 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Hobgoblin');
expect(creature.display).toBe('Jim');
expect(creature.name).toBe("Hobgoblin");
expect(creature.display).toBe("Jim");
expect(creature.hp).toBe(12);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(1);
Expand All @@ -277,8 +278,8 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Hobgoblin');
expect(creature.display).toBe('Ted');
expect(creature.name).toBe("Hobgoblin");
expect(creature.display).toBe("Ted");
expect(creature.hp).toBe(12);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(1);
Expand All @@ -288,8 +289,8 @@ creatures:

creature = k.next().value;
amount = result.creatures.get(creature);
expect(creature.name).toBe('Hobgoblin');
expect(creature.display).toBe('Sarah');
expect(creature.name).toBe("Hobgoblin");
expect(creature.display).toBe("Sarah");
expect(creature.hp).toBe(36);
expect(creature.ac).toBe(13);
expect(creature.modifier).toBe(1);
Expand All @@ -298,4 +299,21 @@ creatures:
expect(amount).toBeGreaterThan(0);
expect(amount).toBeLessThan(6);
});
});

test("parseEncounter: just friendly", async () => {
const encounter = `name: Sample Encounter
creatures:
- Arik, friendly`;

const params: EncounterParameters = parseYaml(encounter);
const result = await parser.parse(params);

let k = result.creatures.keys();
let creature: Creature = k.next().value;
let amount = result.creatures.get(creature);
expect(creature.name).toBe("Arik");
expect(creature.display).toBeUndefined();
expect(creature.friendly).toBe(true);
expect(amount).toBe(1);
});
});

0 comments on commit 114896f

Please sign in to comment.