38d0ba2734
Utiliser les différents repères de cases: - coordonnées TMR A5 - oddq pour les coordonnées de case (ligne, colonne) - axial (q,r) pour effectuer les calculs de distance utiliser x, y rend la distinction de positions de pixels vs position dans la grille parfois ardue. Utilisation des coordonnées axiales pour le calcul de distance.
506 lines
19 KiB
JavaScript
506 lines
19 KiB
JavaScript
import { TMRRencontres } from "./tmr-rencontres.js";
|
||
import { Misc } from "./misc.js";
|
||
import { Grammar } from "./grammar.js";
|
||
import { RdDDice } from "./rdd-dice.js";
|
||
import { tmrConstants } from "./tmr-constants.js";
|
||
|
||
/* -------------------------------------------- */
|
||
const TMRMapping = {
|
||
A1: { type: "cite", label: "Cité Vide" },
|
||
B1: { type: "plaines", label: "Plaines d’Assorh" },
|
||
C1: { type: "necropole", label: "Nécropole de Kroak" },
|
||
D1: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
E1: { type: "monts", label: "Monts de Kanaï" },
|
||
F1: { type: "cite", label: "Cité Glauque" },
|
||
G1: { type: "desolation", label: "Désolation de Demain" },
|
||
H1: { type: "lac", label: "Lac d’Anticalme" },
|
||
I1: { type: "plaines", label: "Plaines Grises" },
|
||
J1: { type: "monts", label: "Monts Fainéants" },
|
||
K1: { type: "cite", label: "Cité d’Onkause" },
|
||
L1: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
M1: { type: "cite", label: "Cité Jalouse" },
|
||
|
||
A2: { type: "desert", label: "Désert de Mieux" },
|
||
B2: { type: "collines", label: "Collines de Dawell" },
|
||
C2: { type: "marais", label: "Marais Glignants" },
|
||
D2: { type: "cite", label: "Cité de Frost" },
|
||
E2: { type: "plaines", label: "Plaines de Fiask" },
|
||
F2: { type: "lac", label: "Lac de Misère" },
|
||
G2: { type: "marais", label: "Marais Nuisants" },
|
||
H2: { type: "collines", label: "Collines de Parta" },
|
||
I2: { type: "foret", label: "Forêt Fade" },
|
||
J2: { type: "desert", label: "Désert de Poly" },
|
||
K2: { type: "foret", label: "Forêt Tamée" },
|
||
L2: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
M2: { type: "necropole", label: "Nécropole de Logos" },
|
||
|
||
A3: { type: "desolation", label: "Désolation de Demain" },
|
||
B3: { type: "plaines", label: "Plaines de Rubéga" },
|
||
C3: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
D3: { type: "gouffre", label: "Gouffre d’Oki" },
|
||
E3: { type: "foret", label: "Forêt d’Estoubh" },
|
||
F3: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
G3: { type: "gouffre", label: "Gouffre de Sun" },
|
||
H3: { type: "foret", label: "Forêt de Ganna" },
|
||
I3: { type: "monts", label: "Monts Grinçants" },
|
||
J3: { type: "cite", label: "Cité Venin" },
|
||
K3: { type: "plaines", label: "Plaines de Dois" },
|
||
L3: { type: "lac", label: "Lac Laineux" },
|
||
M3: { type: "monts", label: "Monts de Vdah" },
|
||
|
||
A4: { type: "foret", label: "Forêt de Falconax" },
|
||
B4: { type: "monts", label: "Monts Crâneurs" },
|
||
C4: { type: "pont", label: "Pont de Giolii" },
|
||
D4: { type: "lac", label: "Lac de Foam" },
|
||
E4: { type: "plaines", label: "Plaines d’Orti" },
|
||
F4: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
G4: { type: "sanctuaire", label: "Sanctuaire Blanc" },
|
||
H4: { type: "plaines", label: "Plaines de Psark" },
|
||
I4: { type: "plaines", label: "Plaines de Xiax" },
|
||
J4: { type: "collines", label: "Collines d’Encre" },
|
||
K4: { type: "pont", label: "Pont de Fah" },
|
||
L4: { type: "sanctuaire", label: "Sanctuaire Mauve" },
|
||
M4: { type: "gouffre", label: "Gouffre Grisant" },
|
||
|
||
A5: { type: "plaines", label: "Plaines de Trilkh" },
|
||
B5: { type: "collines", label: "Collines de Tanegy" },
|
||
C5: { type: "marais", label: "Marais Flouants" },
|
||
D5: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
E5: { type: "monts", label: "Monts Brûlants" },
|
||
F5: { type: "cite", label: "Cité de Panople" },
|
||
G5: { type: "pont", label: "Pont d’Ik" },
|
||
H5: { type: "desert", label: "Désert de Krane" },
|
||
I5: { type: "desolation", label: "Désolation de Demain" },
|
||
J5: { type: "marais", label: "Marais de Jab" },
|
||
K5: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
L5: { type: "collines", label: "Collines Suaves" },
|
||
M5: { type: "cite", label: "Cité Rimarde" },
|
||
|
||
A6: { type: "necropole", label: "Nécropole de Zniak" },
|
||
B6: { type: "foret", label: "Forêt de Bust" },
|
||
C6: { type: "cite", label: "Cité Pavois" },
|
||
D6: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
E6: { type: "sanctuaire", label: "Sanctuaire de Plaine" },
|
||
F6: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
G6: { type: "marais", label: "Marais Glutants" },
|
||
H6: { type: "monts", label: "Monts Gurdes" },
|
||
I6: { type: "necropole", label: "Nécropole de Xotar" },
|
||
J6: { type: "lac", label: "Lac d’Iaupe" },
|
||
K6: { type: "desolation", label: "Désolation de Demain" },
|
||
L6: { type: "foret", label: "Forêt Gueuse" },
|
||
M6: { type: "desolation", label: "Désolation de Demain" },
|
||
|
||
A7: { type: "plaines", label: "Plaines de l’Arc" },
|
||
B7: { type: "marais", label: "Marais Bluants" },
|
||
C7: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
D7: { type: "plaines", label: "Plaines d’Affa" },
|
||
E7: { type: "foret", label: "Forêt de Glusks" },
|
||
F7: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
G7: { type: "cite", label: "Cité de Terwa" },
|
||
H7: { type: "gouffre", label: "Gouffre de Kapfa" },
|
||
I7: { type: "plaines", label: "Plaines de Troo" },
|
||
J7: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
K7: { type: "cite", label: "Cité de Kolix" },
|
||
L7: { type: "gouffre", label: "Gouffre d’Episophe" },
|
||
M7: { type: "desert", label: "Désert de Lave" },
|
||
|
||
A8: { type: "gouffre", label: "Gouffre de Shok" },
|
||
B8: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
C8: { type: "foret", label: "Forêt Turmide" },
|
||
D8: { type: "cite", label: "Cité d’Olak" },
|
||
E8: { type: "plaines", label: "Plaines d’Iolise" },
|
||
F8: { type: "lac", label: "Lac des Chats" },
|
||
G8: { type: "plaines", label: "Plaines Sans Joie" },
|
||
H8: { type: "foret", label: "Forêt d’Ourf" },
|
||
I8: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
J8: { type: "monts", label: "Monts Barask" },
|
||
K8: { type: "desert", label: "Désert de Fumée" },
|
||
L8: { type: "monts", label: "Monts Tavelés" },
|
||
M8: { type: "plaines", label: "Plaines Lavées" },
|
||
|
||
A9: { type: "collines", label: "Collines de Korrex" },
|
||
B9: { type: "lac", label: "Lac de Lucre" },
|
||
C9: { type: "monts", label: "Monts Tuméfiés" },
|
||
D9: { type: "pont", label: "Pont d’Orx" },
|
||
E9: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
F9: { type: "plaines", label: "Plaines de Foe" },
|
||
G9: { type: "desolation", label: "Désolation de Demain" },
|
||
H9: { type: "collines", label: "Collines de Noirseul" },
|
||
I9: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
J9: { type: "marais", label: "Marais Gronchants" },
|
||
K9: { type: "sanctuaire", label: "Sanctuaire Noir" },
|
||
L9: { type: "collines", label: "Collines Cornues" },
|
||
M9: { type: "necropole", label: "Nécropole de Zonar" },
|
||
|
||
A10: { type: "sanctuaire", label: "Sanctuaire d’Olis" },
|
||
B10: { type: "monts", label: "Monts Salés" },
|
||
C10: { type: "marais", label: "Marais de Dom" },
|
||
D10: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
E10: { type: "gouffre", label: "Gouffre de Junk" },
|
||
F10: { type: "marais", label: "Marais Zultants" },
|
||
G10: { type: "cite", label: "Cité de Sergal" },
|
||
H10: { type: "plaines", label: "Plaines Noires" },
|
||
I10: { type: "lac", label: "Lac Wanito" },
|
||
J10: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
K10: { type: "plaines", label: "Plaines Jaunes" },
|
||
L10: { type: "desert", label: "Désert de Nicrop" },
|
||
M10: { type: "foret", label: "Forêt de Jajou" },
|
||
|
||
A11: { type: "desolation", label: "Désolation de Demain" },
|
||
B11: { type: "cite", label: "Cité de Brilz" },
|
||
C11: { type: "pont", label: "Pont de Roï" },
|
||
D11: { type: "desolation", label: "Désolation de Demain" },
|
||
E11: { type: "lac", label: "Lac de Glinster" },
|
||
F11: { type: "cite", label: "Cité de Noape" },
|
||
G11: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
H11: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
I11: { type: "pont", label: "Pont de Yalm" },
|
||
J11: { type: "plaines", label: "Plaines de Miltiar" },
|
||
K11: { type: "cite", label: "Cité Tonnerre" },
|
||
L11: { type: "collines", label: "Collines de Kol" },
|
||
M11: { type: "cite", label: "Cité Crapaud" },
|
||
|
||
A12: { type: "plaines", label: "Plaines Sages" },
|
||
B12: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
C12: { type: "lac", label: "Lac de Fricassa" },
|
||
D12: { type: "collines", label: "Collines d’Huaï" },
|
||
E12: { type: "monts", label: "Monts Ajourés" },
|
||
F12: { type: "necropole", label: "Nécropole de Troat" },
|
||
G12: { type: "plaines", label: "Plaines de Lufmil" },
|
||
H12: { type: "collines", label: "Collines de Tooth" },
|
||
I12: { type: "gouffre", label: "Gouffre Abimeux" },
|
||
J12: { type: "cite", label: "Cité Folle" },
|
||
K12: { type: "desolation", label: "Désolation de Demain" },
|
||
L12: { type: "plaines", label: "Plaines Venteuses" },
|
||
M12: { type: "collines", label: "Collines Révulsantes" },
|
||
|
||
A13: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||
B13: { type: "gouffre", label: "Gouffre des Litiges" },
|
||
C13: { type: "desert", label: "Désert de Neige" },
|
||
D13: { type: "cite", label: "Cité Sordide" },
|
||
E13: { type: "plaines", label: "Plaines de Xnez" },
|
||
F13: { type: "foret", label: "Forêt des Cris" },
|
||
G13: { type: "plaines", label: "Plaines Calcaires" },
|
||
H13: { type: "desolation", label: "Désolation de Demain" },
|
||
I13: { type: "monts", label: "Monts Bigleux" },
|
||
J13: { type: "gouffre", label: "Gouffre de Gromph" },
|
||
K13: { type: "foret", label: "Forêt de Kluth" },
|
||
L13: { type: "monts", label: "Monts Dormants" },
|
||
M13: { type: "plaines", label: "Plaines d’Anjou" },
|
||
|
||
A14: { type: "collines", label: "Collines de Stolis" },
|
||
B14: { type: "necropole", label: "Nécropole de Gorlo" },
|
||
C14: { type: "foret", label: "Forêt de Bissam" },
|
||
D14: { type: "sanctuaire", label: "Sanctuaire Plat" },
|
||
E14: { type: "monts", label: "Monts de Quath" },
|
||
F14: { type: "plaines", label: "Plaines Brisées" },
|
||
G14: { type: "desert", label: "Désert de Sek" },
|
||
H14: { type: "plaines", label: "Plaines Blanches" },
|
||
I14: { type: "cite", label: "Cité Destituée" },
|
||
J14: { type: "desert", label: "Désert de Sank" },
|
||
K14: { type: "necropole", label: "Nécropole d’Antinéar" },
|
||
L14: { type: "plaines", label: "Plaines de Jislith" },
|
||
M14: { type: "desolation", label: "Désolation de Demain" },
|
||
|
||
A15: { type: "cite", label: "Cité de Mielh" },
|
||
C15: { type: "plaines", label: "Plaines de Toué" },
|
||
E15: { type: "foret", label: "Forêt des Furies" },
|
||
G15: { type: "plaines", label: "Plaines des Soupirs" },
|
||
I15: { type: "monts", label: "Monts des Dragées" },
|
||
K15: { type: "collines", label: "Collines Pourpres" },
|
||
M15: { type: "cite", label: "Cité de Klana" }
|
||
}
|
||
|
||
export const TMRType = {
|
||
cite: { name: "cité", genre: "f" },
|
||
sanctuaire: { name: "sanctuaire", genre: 'm' },
|
||
plaines: { name: "plaines", genre: "fp" },
|
||
pont: { name: "pont", genre: "m" },
|
||
collines: { name: "collines", genre: "p" },
|
||
foret: { name: "forêt", genre: "f" },
|
||
monts: { name: "monts", genre: "p" },
|
||
desert: { name: "désert", genre: "m" },
|
||
fleuve: { name: "fleuve", genre: "m" },
|
||
lac: { name: "lac", genre: "m" },
|
||
marais: { name: "marais", genre: "m" },
|
||
gouffre: { name: "gouffre", genre: "m" },
|
||
necropole: { name: "nécropole", genre: "f" },
|
||
desolation: { name: "désolation", genre: "f" }
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
const caseSpecificModes = ["attache", "trounoir", "debordement", "reserve_extensible", "maitrisee"];
|
||
|
||
/* -------------------------------------------- */
|
||
const tmrRandomMovePatten =
|
||
[{ name: 'top', col: 0, row: -1 },
|
||
{ name: 'topright', col: 1, row: -1 },
|
||
{ name: 'botright', col: 1, row: 1 },
|
||
{ name: 'bot', col: 0, row: 1 },
|
||
{ name: 'botleft', col: -1, row: 1 },
|
||
{ name: 'topleft', col: -1, row: -1 }
|
||
]
|
||
|
||
/* -------------------------------------------- */
|
||
|
||
/* -------------------------------------------- */
|
||
export class TMRUtility {
|
||
static init() {
|
||
for (let coord in TMRMapping) {
|
||
const tmr = TMRMapping[coord];
|
||
tmr.coord = coord;
|
||
tmr.oddq = TMRUtility.coordTMRToOddq(coord);
|
||
tmr.genre = TMRType[tmr.type].genre;
|
||
}
|
||
let tmrByType = Misc.classify(Object.values(TMRMapping));
|
||
for (const [type, list] of Object.entries(tmrByType)) {
|
||
TMRType[type].list = list;
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static verifyTMRCoord(coord) {
|
||
let TMRregexp = new RegExp(/([A-M])(\d+)/g);
|
||
let res = TMRregexp.exec(coord);
|
||
if (res && res[1] && res[2]) {
|
||
if (res[2] > 0 && res[2] < 16) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static getTMR(coord) {
|
||
return TMRMapping[coord];
|
||
}
|
||
|
||
static getTMRLabel(coord) {
|
||
return TMRMapping[coord]?.label ?? (coord + ": case inconnue");
|
||
}
|
||
|
||
static getTMRType(coord) {
|
||
const tmr = TMRMapping[coord];
|
||
return Misc.upperFirst(TMRType[tmr.type].name);
|
||
}
|
||
|
||
static getTMRDescr(coord) {
|
||
const tmr = TMRMapping[coord];
|
||
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
||
}
|
||
|
||
static typeTmrName(type) {
|
||
return Misc.upperFirst(TMRType[Grammar.toLowerCaseNoAccent(type)].name);
|
||
}
|
||
static listSelectedTMR(typesTMR) {
|
||
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
|
||
.sort()
|
||
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
|
||
}
|
||
|
||
static isCaseHumide(tmr) {
|
||
return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais';
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
/** Some debug functions */
|
||
static async setForceRencontre(index, force = undefined) {
|
||
this.prochaineRencontre = TMRRencontres.getRencontre(index);
|
||
if (this.prochaineRencontre) {
|
||
if (force) {
|
||
this.prochaineRencontre.force = force;
|
||
}
|
||
else {
|
||
await TMRRencontres.evaluerForceRencontre(this.prochaineRencontre);
|
||
}
|
||
console.log("La prochaine rencontre sera:", this.prochaineRencontre.name, " force:", this.prochaineRencontre.force);
|
||
}
|
||
else {
|
||
ui.notifications.warn("Pas de prochaine rencontre valide pour " + index);
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static isForceRencontre() {
|
||
return this.prochaineRencontre;
|
||
}
|
||
/* -------------------------------------------- */
|
||
static utiliseForceRencontre() {
|
||
const rencontre = this.prochaineRencontre;
|
||
this.prochaineRencontre = undefined;
|
||
return rencontre;
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static async getDirectionPattern() {
|
||
return await RdDDice.rollOneOf(tmrRandomMovePatten);
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static async deplaceTMRAleatoire(actor, coord) {
|
||
return TMRUtility.deplaceTMRSelonPattern(actor, coord, await TMRUtility.getDirectionPattern(), 1);
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static async deplaceTMRSelonPattern(actor, coordTMR, direction, nTime) {
|
||
let coord;
|
||
for (let i = 0; i < nTime; i++) {
|
||
let currentOddq = TMRUtility.coordTMRToOddq(coordTMR);
|
||
currentOddq.col = currentOddq.col + direction.col;
|
||
currentOddq.row = currentOddq.row + direction.row;
|
||
if (this.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire
|
||
coord = TMRUtility.getTMR(TMRUtility.oddqToCoordTMR(currentOddq));
|
||
} else {
|
||
coord = await actor.reinsertionAleatoire('Sortie de carte');
|
||
}
|
||
console.log("Nouvelle case iteration !!!", i, coord);
|
||
}
|
||
return coord;
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static getListTMR(terrain) {
|
||
return TMRType[terrain].list;
|
||
}
|
||
|
||
static filterTMR(filter) {
|
||
return Object.values(TMRMapping).filter(filter);
|
||
}
|
||
|
||
static findTMR(search) {
|
||
const labelSearch = Grammar.toLowerCaseNoAccent(search)
|
||
return TMRUtility.filterTMR(it => Grammar.toLowerCaseNoAccent(it.label).match(labelSearch) || it.coord == search);
|
||
}
|
||
|
||
static filterTMRCoord(filter) {
|
||
return TMRUtility.filterTMR(filter).map(it => it.coord);
|
||
}
|
||
|
||
static async getTMRAleatoire(filter = it => true) {
|
||
return await RdDDice.rollOneOf(TMRUtility.filterTMR(filter))
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static getSortsReserve(reserveList, coord) {
|
||
// TODO : Gérer les têtes spéciales réserve!
|
||
let tmrDescr = this.getTMR(coord);
|
||
//console.log("Sort réserve : ", tmrDescr);
|
||
if (tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve
|
||
return reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve');
|
||
}
|
||
// Reserve sur un case "normale"
|
||
return reserveList.filter(it => it.coord == coord);
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
/** Returns a list of case inside a given distance
|
||
*
|
||
*/
|
||
static getTMRPortee(coord, portee) {
|
||
let centerOddq = this.coordTMRToOddq(coord);
|
||
let caseList = [];
|
||
for (let dcol = -portee; dcol <= portee; dcol++) { // rows
|
||
for (let drow = -portee; drow <= portee; drow++) { // columns
|
||
const currentOddq = { col: centerOddq.col + dcol, row: centerOddq.row + drow };
|
||
if (this.isOddqInTMR(currentOddq)) {
|
||
let dist = this.distanceOddq(centerOddq, currentOddq);
|
||
if (dist <= portee) {
|
||
caseList.push(this.oddqToCoordTMR(currentOddq)); // Inside the area
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return caseList;
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
// https://www.redblobgames.com/grids/hexagons/#distances
|
||
// TMR Letter-row correspond to "odd-q" grid (letter => col, numeric => row )
|
||
|
||
/* -------------------------------------------- */
|
||
static coordTMRToOddq(coordTMR) {
|
||
let col = coordTMR.charCodeAt(0) - 65;
|
||
let row = coordTMR.substr(1) - 1;
|
||
return { col: col, row: row }
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static oddqToCoordTMR(oddq) {
|
||
let letterX = String.fromCharCode(65 + (oddq.col));
|
||
return letterX + (oddq.row + 1)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static isOddqInTMR(oddq) {
|
||
const col = oddq.col;
|
||
const row = oddq.row;
|
||
return (
|
||
col >= 0 && col < 13 &&
|
||
row >= 0 &&
|
||
(row + col % 2 <= 14)
|
||
);
|
||
// if (x >= 0 && x < 13 && y >= 0 && y < 14) return true;
|
||
// if (x >= 0 && x < 13 && x % 2 == 0 && y == 14) return true;
|
||
// return false;
|
||
}
|
||
|
||
|
||
/* -------------------------------------------- */
|
||
static distanceCoordTMR(coord1, coord2) {
|
||
let oddq1 = this.coordTMRToOddq(coord1);
|
||
let oddq2 = this.coordTMRToOddq(coord2);
|
||
return this.distanceOddq(oddq1, oddq2);
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
static distanceOddq(oddq1, oddq2) {
|
||
const axial1 = TMRUtility.oddqToAxial(oddq1);
|
||
const axial2 = TMRUtility.oddqToAxial(oddq2);
|
||
return TMRUtility.distanceAxial(axial1, axial2);
|
||
|
||
// const dx = oddq2.col - oddq1.col;
|
||
// const dy = oddq2.row - oddq1.row;
|
||
// const abs_dx = Math.abs(dx);
|
||
// const abs_dy = Math.abs(dy);
|
||
// const distance = Math.sign(dx) == Math.sign(dy) ? Math.max(abs_dx, abs_dy) : (abs_dx + abs_dy);
|
||
// return distance;
|
||
}
|
||
|
||
static oddqToAxial(pos) {
|
||
return {
|
||
q: pos.col,
|
||
r: pos.row - (pos.col - (pos.col & 1)) / 2
|
||
}
|
||
}
|
||
|
||
static distanceAxial(a, b) {
|
||
const vector = TMRUtility.axial_subtract(a, b)
|
||
return (Math.abs(vector.q)
|
||
+ Math.abs(vector.q + vector.r)
|
||
+ Math.abs(vector.r)) / 2
|
||
}
|
||
|
||
static axial_subtract(a, b) {
|
||
return {
|
||
q: a.q- b.q,
|
||
r: a.r - b.r
|
||
};
|
||
}
|
||
|
||
// function axial_to_cube(hex):
|
||
// var q = hex.q
|
||
// var r = hex.r
|
||
// var s = -q - r
|
||
// return Cube(q, r, s)
|
||
// }
|
||
|
||
|
||
// /* -------------------------------------------- */
|
||
// static computeRealPictureCoordinates(coordOddq) {
|
||
// let decallagePairImpair = (coordOddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||
// return {
|
||
// x: tmrConstants.gridx + (coordOddq.col * tmrConstants.cellw),
|
||
// y: tmrConstants.gridy + (coordOddq.row * tmrConstants.cellh) + decallagePairImpair
|
||
// }
|
||
// }
|
||
} |