game_logic 정의

This commit is contained in:
2023-09-23 18:34:27 +00:00
parent cea888573c
commit e084835249
14 changed files with 215 additions and 0 deletions
+1
View File
@@ -11,6 +11,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@sammo/api_def": "workspace:^", "@sammo/api_def": "workspace:^",
"@sammo/crypto": "workspace:^",
"@sammo/server_util": "workspace:^", "@sammo/server_util": "workspace:^",
"@sammo/util": "workspace:^", "@sammo/util": "workspace:^",
"@strpc/express": "workspace:^", "@strpc/express": "workspace:^",
+3
View File
@@ -0,0 +1,3 @@
export class GameEnv{
}
+3
View File
@@ -0,0 +1,3 @@
export class General {
}
+25
View File
@@ -0,0 +1,25 @@
import type { RandUtil } from "@sammo/crypto";
import type { General } from "./General.js";
import type { GeneralTriggerCaller } from "./TriggerCaller/GeneralTriggerCaller.js";
import type { WarUnitTriggerCaller } from "./TriggerCaller/WarUnitTriggerCaller.js";
import type { WarUnit } from "./WarUnit.js";
export interface IAction {
getName(): string;
getInfo(): string;
getPreTurnExecuteTriggerList(general: General):GeneralTriggerCaller | undefined;
//TODO: turnType, varType이 string이면 안됨. enum에 가까워야함!
onCalcDomestic(turnType: string, varType: string, value: number, aux?: unknown[]): number;
onCalcStat(general: General, statName: string, value: number, aux?: unknown[]): number;
onCalcOpposeStat(general: General, statName: string, value: number, aux?: unknown[]): number;
onCalcStrategic(turnType: string, varType: string, value: number): number;
onCalcNationalIncome(type: string, value: number): number;
getWarPowerMultiplier(unit: WarUnit): [number, number];
getBattleInitSkillTriggerList(unit: WarUnit): WarUnitTriggerCaller | undefined;
getBattlePhaseSkillTriggerList(unit: WarUnit): WarUnitTriggerCaller | undefined;
onArbitraryAction(general: General, rng: RandUtil, actionType: string, phase?: string, aux?: unknown[]): null | string[];
}
@@ -0,0 +1,11 @@
import type { General } from "../General.js";
import { ObjectTrigger } from "./ObjectTrigger.js";
export abstract class BaseGeneralTrigger extends ObjectTrigger<General> {
constructor(
protected object: General,
protected priority: number
) {
super();
}
}
@@ -0,0 +1,43 @@
import type { RandUtil } from "@sammo/crypto";
import type { WarUnit, WarUnitEnv } from "../WarUnit.js";
import { ObjectTrigger, PRIORITY } from "./ObjectTrigger.js";
import type { GameEnv } from "../GameEnv.js";
import { NotYetImplemented } from "@sammo/util";
export const RaiseType = {
None: 0,
Item: 1,
ConsumableItem: 3,
DedupTypeBase: 1024,
} as const;
export abstract class BaseWarUnitTrigger extends ObjectTrigger<WarUnit> {
protected priority = PRIORITY.BODY;
constructor(
protected object: WarUnit,
protected raiseType: number
) {
super();
}
override getUniqueID(): string {
const priority = this.getPriority();
const name = this.constructor.name;
const unitName = this.object?.constructor.name ?? "undefined";
return `${priority}:${name}:${unitName}`;
}
action(rng: RandUtil, env: GameEnv, arg: unknown[]): void {
throw new NotYetImplemented();
console.log(rng, env, arg);
}
abstract actionWar(self: WarUnit, oppose: WarUnit, selfEnv: WarUnitEnv, opposeEnv: WarUnitEnv, rng: RandUtil): boolean;
processConsumableItem(): boolean {
throw new NotYetImplemented();
}
}
@@ -0,0 +1,37 @@
import type { RandUtil } from "@sammo/crypto";
import type { GameEnv } from "../GameEnv.js";
export const PRIORITY = {
MIN: 0,
BEGIN: 10000,
PRE: 20000,
BODY: 30000,
POST: 40000,
FINAL: 50000,
} as const;
export abstract class ObjectTrigger<T extends object> {
protected abstract priority: number;
protected abstract object?: T;
getPriority(): number {
return this.priority;
}
setPriority(priority: number): this {
this.priority = priority;
return this;
}
//FIXME: arg array. generic이어야하나?
abstract action(rng: RandUtil, env: GameEnv, arg: unknown[]): void;
//FIXME: 재설계 필요.
getUniqueID(): string{
const priority = this.getPriority();
//FIXME: PHP 버전에서 namespace 개념도 옮겨와야하는가?
const objName = this.constructor.name;
return `${priority}:${objName}`;
}
}
@@ -0,0 +1,9 @@
import { BaseGeneralTrigger } from "../Trigger/BaseGeneralTrigger.js";
import type { ObjectTrigger } from "../Trigger/ObjectTrigger.js";
import { TriggerCaller } from "./TriggerCaller.js";
export class GeneralTriggerCaller extends TriggerCaller<BaseGeneralTrigger> {
checkValidTrigger(trigger: ObjectTrigger<object>): boolean {
return trigger instanceof BaseGeneralTrigger;
}
}
@@ -0,0 +1,54 @@
import { ObjectTrigger, PRIORITY } from "../Trigger/ObjectTrigger.js";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export abstract class TriggerCaller<T extends ObjectTrigger<any>> {
protected triggerListByPriority: Map<number, Map<string, T>>;
abstract checkValidTrigger(trigger: T): boolean;
isEmpty(): boolean {
return this.triggerListByPriority.size === 0;
}
constructor(...triggerList: T[]) {
if(triggerList.length === 0){
this.triggerListByPriority = new Map();
return;
}
this.triggerListByPriority = new Map();
let sorted = true;
let maxPriority: number = PRIORITY.MIN;
for (const trigger of triggerList) {
const priority = trigger.getPriority();
const uniqueID = trigger.getUniqueID();
if(sorted){
if(maxPriority < priority){
maxPriority = priority;
}
else if(maxPriority > priority){
sorted = false;
}
}
if(this.triggerListByPriority.has(priority)){
const subTriggerList = this.triggerListByPriority.get(priority) as Map<string, T>;
if(subTriggerList.has(uniqueID)){
//TODO: 완성되기 전까진..
throw `Duplicated trigger: ${uniqueID}`;
}
subTriggerList.set(uniqueID, trigger);
}
else {
this.triggerListByPriority.set(priority, new Map([[uniqueID, trigger]]));
}
}
if(!sorted){
this.triggerListByPriority = new Map([...this.triggerListByPriority.entries()].sort((a, b) => b[0] - a[0]));
}
}
}
@@ -0,0 +1,9 @@
import { BaseGeneralTrigger } from "../Trigger/BaseGeneralTrigger.js";
import type { ObjectTrigger } from "../Trigger/ObjectTrigger.js";
import { TriggerCaller } from "./TriggerCaller.js";
export class WarUnitTriggerCaller extends TriggerCaller<BaseGeneralTrigger> {
checkValidTrigger(trigger: ObjectTrigger<object>): boolean {
return trigger instanceof BaseGeneralTrigger;
}
}
+7
View File
@@ -0,0 +1,7 @@
export class WarUnitEnv {
}
export abstract class WarUnit{
}
+5
View File
@@ -0,0 +1,5 @@
import { WarUnit } from "./WarUnit.js";
export class WarUnitCity extends WarUnit{
}
+5
View File
@@ -0,0 +1,5 @@
import { WarUnit } from "./WarUnit.js";
export class WarUnitGeneral extends WarUnit{
}
+3
View File
@@ -212,6 +212,9 @@ importers:
'@sammo/api_def': '@sammo/api_def':
specifier: workspace:^ specifier: workspace:^
version: link:../api_def version: link:../api_def
'@sammo/crypto':
specifier: workspace:^
version: link:../crypto
'@sammo/server_util': '@sammo/server_util':
specifier: workspace:^ specifier: workspace:^
version: link:../server_util version: link:../server_util