From 92ed2d9e453cb01e69dc3604bd908cef219aa6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 13 May 2019 19:57:12 +0200 Subject: [PATCH] Added BattlePlanning structure to hold player/ai choices --- src/common/RObject.ts | 4 +- src/core/BattlePlanning.spec.ts | 58 +++++++++++++++++++++++++++++ src/core/BattlePlanning.ts | 66 +++++++++++++++++++++++++++++++++ src/ui/battle/ActionIcon.ts | 2 +- src/ui/battle/Arena.ts | 1 - src/ui/battle/BattleView.ts | 33 +++++++---------- src/ui/battle/LogProcessor.ts | 2 +- 7 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 src/core/BattlePlanning.spec.ts create mode 100644 src/core/BattlePlanning.ts diff --git a/src/common/RObject.ts b/src/common/RObject.ts index 049b2dd..4549d90 100644 --- a/src/common/RObject.ts +++ b/src/common/RObject.ts @@ -26,8 +26,8 @@ module TK { /** * Check that two objects are the same (only by comparing their ID) */ - is(other: RObject | RObjectId | null): boolean { - if (other === null) { + is(other: RObject | RObjectId | null | undefined): boolean { + if (other === null || typeof other === "undefined") { return false; } else if (other instanceof RObject) { return this.id === other.id; diff --git a/src/core/BattlePlanning.spec.ts b/src/core/BattlePlanning.spec.ts new file mode 100644 index 0000000..df8cab9 --- /dev/null +++ b/src/core/BattlePlanning.spec.ts @@ -0,0 +1,58 @@ +module TK.SpaceTac.Specs { + testing("BattlePlanning", test => { + test.case("initializes from a battle state", check => { + let battle = new Battle(); + let planning = new BattlePlanning(battle); + check.equals(planning.getBattlePlan(), { + fleets: [ + { fleet: battle.fleets[0].id, ships: [] }, + { fleet: battle.fleets[1].id, ships: [] }, + ] + }); + + battle.fleets[0].addShip(); + planning = new BattlePlanning(battle); + check.equals(planning.getBattlePlan(), { + fleets: [ + { + fleet: battle.fleets[0].id, ships: [ + { ship: battle.fleets[0].ships[0].id, actions: [] }, + ] + }, + { fleet: battle.fleets[1].id, ships: [] }, + ] + }); + }); + + test.case("gets child fleet and ship plans", check => { + const battle = new Battle(); + battle.fleets[0].addShip(); + battle.fleets[1].addShip(); + battle.fleets[1].addShip(); + const planning = new BattlePlanning(battle); + + check.equals(planning.getFleetPlan(battle.fleets[0]).fleet, battle.fleets[0].id); + check.equals(planning.getFleetPlan(battle.fleets[1]).fleet, battle.fleets[1].id); + check.equals(planning.getFleetPlan(new Fleet()).fleet, -1); + + check.equals(planning.getShipPlan(battle.fleets[0].ships[0]).ship, battle.fleets[0].ships[0].id); + check.equals(planning.getShipPlan(battle.fleets[1].ships[0]).ship, battle.fleets[1].ships[0].id); + check.equals(planning.getShipPlan(battle.fleets[1].ships[1]).ship, battle.fleets[1].ships[1].id); + check.equals(planning.getShipPlan(new Ship()).ship, -1); + }); + + test.case("adds an action and target to a ship plan", check => { + const battle = new Battle(); + const ship = battle.fleets[0].addShip(); + const action1 = ship.actions.addCustom(new BaseAction()); + const planning = new BattlePlanning(battle); + + check.equals(planning.getShipPlan(ship).actions, []); + + planning.addAction(ship, action1, Target.newFromShip(ship)); + check.equals(planning.getShipPlan(ship).actions, [ + { action: action1.id, target: Target.newFromShip(ship) } + ]); + }); + }); +} diff --git a/src/core/BattlePlanning.ts b/src/core/BattlePlanning.ts new file mode 100644 index 0000000..f337b67 --- /dev/null +++ b/src/core/BattlePlanning.ts @@ -0,0 +1,66 @@ +namespace TK.SpaceTac { + /** + * A tool to manipulate battle plans (action plans for all involved ships, for one turn) + */ + export class BattlePlanning { + private plan: BattlePlan + + constructor(private battle: Battle, readonly player?: Player) { + this.plan = { + fleets: battle.fleets.map(fleet => ({ + fleet: fleet.id, + ships: fleet.ships.map(ship => ({ + ship: ship.id, + actions: [] + })) + })) + }; + } + + getBattlePlan(): BattlePlan { + return this.plan; + } + + getFleetPlan(fleet: Fleet): FleetPlan { + const fplan = first(this.plan.fleets, ifleet => fleet.is(ifleet.fleet)); + return fplan || { fleet: -1, ships: [] }; + } + + getShipPlan(ship: Ship): ShipPlan { + const fplan = this.getFleetPlan(ship.fleet); + const splan = first(fplan.ships, iship => ship.is(iship.ship)); + return splan || { ship: -1, actions: [] }; + } + + /** + * Add an action to a ship plan + */ + addAction(ship: Ship, action: BaseAction, target?: Target) { + const plan = this.getShipPlan(ship); + if (any(plan.actions, iaction => action.is(iaction.action))) { + // TODO replace (or remove if toggle action ?) + } else { + plan.actions.push({ action: action.id, target }); + } + } + } + + export type BattlePlan = { + fleets: FleetPlan[] + } + + export type FleetPlan = { + fleet: RObjectId, + ships: ShipPlan[] + } + + export type ShipPlan = { + ship: RObjectId + actions: ActionPlan[] + } + + export type ActionPlan = { + action: RObjectId + target?: Target + } +} diff --git a/src/ui/battle/ActionIcon.ts b/src/ui/battle/ActionIcon.ts index 4372520..a9cd662 100644 --- a/src/ui/battle/ActionIcon.ts +++ b/src/ui/battle/ActionIcon.ts @@ -148,7 +148,7 @@ module TK.SpaceTac.UI { * This will effectively apply the action */ processSelection(target: Target): void { - if (this.view.applyAction(this.action, target)) { + if (this.view.applyPlayerAction(this.action, target)) { this.bar.actionEnded(); } } diff --git a/src/ui/battle/Arena.ts b/src/ui/battle/Arena.ts index 4f2a4b6..524e80f 100644 --- a/src/ui/battle/Arena.ts +++ b/src/ui/battle/Arena.ts @@ -91,7 +91,6 @@ module TK.SpaceTac.UI { // Capture clicks zone.on("pointerdown", (pointer: Phaser.Input.Pointer) => { - console.error(pointer); button_down = (pointer.buttons == 1); }); zone.on("pointerup", () => { diff --git a/src/ui/battle/BattleView.ts b/src/ui/battle/BattleView.ts index e169664..2a871bf 100644 --- a/src/ui/battle/BattleView.ts +++ b/src/ui/battle/BattleView.ts @@ -26,6 +26,9 @@ module TK.SpaceTac.UI { // Multiplayer sharing multi!: MultiBattle + // Battle planning for each fleets + plannings: BattlePlanning[] = [] + // Layers layer_background!: UIContainer layer_arena!: UIContainer @@ -76,6 +79,7 @@ module TK.SpaceTac.UI { this.player = data.player; this.actual_battle = data.battle; this.battle = duplicate(data.battle, TK.SpaceTac); + this.plannings = this.battle.fleets.map(fleet => new BattlePlanning(this.battle, fleet.player)); this.ship_hovered = null; this.background = null; this.multi = new MultiBattle(); @@ -90,7 +94,6 @@ module TK.SpaceTac.UI { create() { super.create(); - var game = this.game; this.interacting = false; this.log_processor = new LogProcessor(this); @@ -188,30 +191,20 @@ module TK.SpaceTac.UI { } /** - * Apply an action to the actual battle + * Apply a player action to the actual battle (this will add it to the current battle plan) */ - applyAction(action: BaseAction, target?: Target): boolean { + applyPlayerAction(action: BaseAction, target?: Target): boolean { if (this.session.spectator) { return false; } - let ship = this.actual_battle.playing_ship; - if (ship) { - let ship_action = ship.actions.getById(action.id); - if (ship_action) { - let result = this.actual_battle.applyOneAction(action.id, target); - if (result) { - this.setInteractionEnabled(false); - } - return result; - } else { - console.error("Action not found in available list", action, ship.actions); - return false; + this.plannings.forEach(planning => { + if (this.action_bar.ship && this.player.is(planning.player)) { + planning.addAction(this.action_bar.ship, action, target); } - } else { - console.error("Action not applied - ship not playing"); - return false; - } + }); + + return false; } /** @@ -245,7 +238,7 @@ module TK.SpaceTac.UI { */ validationPressed(): void { if (this.targetting.active) { - this.targetting.validate((action, target) => this.applyAction(action, target)); + this.targetting.validate((action, target) => this.applyPlayerAction(action, target)); } else { this.action_bar.keyActionPressed(-1); } diff --git a/src/ui/battle/LogProcessor.ts b/src/ui/battle/LogProcessor.ts index 74d30a9..1f55412 100644 --- a/src/ui/battle/LogProcessor.ts +++ b/src/ui/battle/LogProcessor.ts @@ -224,7 +224,7 @@ module TK.SpaceTac.UI { } else if (!this.ai_disabled) { this.view.playAI(); } else { - this.view.applyAction(EndTurnAction.SINGLETON); + this.view.applyPlayerAction(EndTurnAction.SINGLETON); } } else { this.view.setInteractionEnabled(false);