1
0
Fork 0

Started work on turn resolution

This commit is contained in:
Michaël Lemaire 2019-05-16 19:33:40 +02:00
parent c3c88449fb
commit 906322003f
10 changed files with 179 additions and 27 deletions

View File

@ -61,6 +61,14 @@ module TK.SpaceTac {
return bool(this.outcome);
}
/**
* Apply a turn plan through a resolution
*/
applyTurnPlan(plan: TurnPlan): void {
const resolution = new TurnResolution(this, plan);
resolution.resolve();
}
/**
* Apply a list of diffs to the game state, and add them to the log.
*

View File

@ -111,8 +111,9 @@ module TK.SpaceTac {
}
// Make an initiative throw, to resolve play order in a battle
throwInitiative(gen: RandomGenerator): void {
throwInitiative(gen: RandomGenerator): number {
this.play_priority = gen.random() * this.attributes.initiative.get();
return this.play_priority;
}
/**

View File

@ -0,0 +1,53 @@
module TK.SpaceTac {
testing("TurnResolution", test => {
test.case("defines play order by initiative throws", check => {
const fleet1 = new Fleet();
const fleet2 = new Fleet();
const ship1 = new Ship(fleet1, "F1S1");
TestTools.setAttribute(ship1, "initiative", 2);
const ship2 = new Ship(fleet1, "F1S2");
TestTools.setAttribute(ship2, "initiative", 4);
const ship3 = new Ship(fleet1, "F1S3");
TestTools.setAttribute(ship3, "initiative", 1);
const ship4 = new Ship(fleet2, "F2S1");
TestTools.setAttribute(ship4, "initiative", 8);
const ship5 = new Ship(fleet2, "F2S2");
TestTools.setAttribute(ship5, "initiative", 2);
const battle = new Battle(fleet1, fleet2);
const random = new SkewedRandomGenerator([1.0, 0.1, 1.0, 0.2, 0.6]);
const resolution = new TurnResolution(battle, { fleets: [] }, random);
check.equals(resolution.play_order, []);
resolution.throwInitiative();
check.equals(resolution.play_order, [ship1, ship4, ship5, ship3, ship2]);
});
test.case("logs a turn start diff", check => {
const battle = new Battle();
const resolution = new TurnResolution(battle, { fleets: [] });
const ships = [new Ship(), new Ship()]
resolution.play_order = ships;
check.equals(battle.log.count(), 0);
resolution.logStart();
check.equals(battle.log.count(), 1);
const diff = battle.log.get(0);
if (check.instance(diff, TurnStartDiff, "diff should be a TurnStartDiff")) {
check.equals(diff.play_order, [ships[0].id, ships[1].id]);
}
});
test.case("logs a turn end diff", check => {
const battle = new Battle();
const resolution = new TurnResolution(battle, { fleets: [] });
check.equals(battle.log.count(), 0);
resolution.logEnd();
check.equals(battle.log.count(), 1);
const diff = battle.log.get(0);
check.instance(diff, TurnEndDiff, "diff should be a TurnEndDiff");
});
});
}

View File

@ -0,0 +1,70 @@
namespace TK.SpaceTac {
/**
* The machinery to apply a turn plan, in order to resolve the current turn
*/
export class TurnResolution {
play_order: Ship[] = []
constructor(readonly battle: Battle, readonly plan: TurnPlan, readonly random = new RandomGenerator()) {
}
/**
* Perform the whole resolution
*/
resolve(): void {
this.throwInitiative();
this.logStart();
this.performActions(ActionCategory.PASSIVE);
this.performActions(ActionCategory.MOVE);
this.performActions(ActionCategory.ACTIVE);
this.logEnd();
}
/**
* Perform an initiative throw, to obtain an order in which the ships will play
*/
throwInitiative(): void {
const with_thrown = this.battle.ships.list().map(ship => [ship, ship.throwInitiative(this.random)] as [Ship, number]);
const sorted_by_thrown = sortedBy(with_thrown, ([_, thrown]) => thrown);
this.play_order = sorted_by_thrown.reverse().map(([ship, _]) => ship);
}
/**
* Log a turn start diff
*/
logStart(): void {
this.battle.applyDiffs([new TurnStartDiff(this.play_order)]);
}
/**
* Perform all actions of a given category, for all ships in the initiative order
*/
performActions(category: ActionCategory): void {
this.play_order.forEach(ship => this.performActionsForShip(ship, category));
}
/**
* Perform all actions of a given category, for one given ship
*/
performActionsForShip(ship: Ship, category: ActionCategory): void {
this.plan.fleets.forEach(fleetplan => {
fleetplan.ships.forEach(shipplan => {
if (ship.is(shipplan.ship)) {
shipplan.actions.forEach(actionplan => {
if (actionplan.category === category) {
this.battle.applyOneAction(actionplan.action, actionplan.target);
}
});
}
});
});
}
/**
* Log a turn end diff
*/
logEnd(): void {
this.battle.applyDiffs([new TurnEndDiff()]);
}
}
}

View File

@ -0,0 +1,9 @@
/// <reference path="BaseBattleDiff.ts"/>
module TK.SpaceTac {
/**
* A turn has ended
*/
export class TurnEndDiff extends BaseBattleDiff {
}
}

View File

@ -0,0 +1,16 @@
/// <reference path="BaseBattleDiff.ts"/>
module TK.SpaceTac {
/**
* A turn has started
*/
export class TurnStartDiff extends BaseBattleDiff {
readonly play_order: RObjectId[]
constructor(play_order: Ship[]) {
super();
this.play_order = play_order.map(ship => ship.id);
}
}
}

View File

@ -4,7 +4,7 @@ module TK.SpaceTac.UI.Specs {
test.case("shows turn counter and current phase", check => {
const parent = testgame.view.getLayer("test");
const bar = new BattleInfoBar(parent.getBuilder());
const bar = new BattleInfoBar(parent.getBuilder(), { startResolution: () => null });
expect(collectTexts(parent)).toEqual(["Battle"]);

View File

@ -26,20 +26,7 @@ module TK.SpaceTac.UI {
this.title = builder.in(this.container).text("Battle", 0, 0, { center: true, size: 30, shadow: true, color: "#dbeff9" });
this.planning = new BattleInfoBarPlanning(this.container, () => {
});
}
startResolution(): void {
const startResolution = this.config.startResolution;
if (startResolution) {
const message = "Validate all your ship's planning, and proceed to turn resolution?";
UIConfirmDialog.ask(this.builder.view, message).then(ok => {
if (ok) {
startResolution();
}
});
}
this.planning = new BattleInfoBarPlanning(this.container, config.startResolution);
}
setPhase(turn: number, phase: BattleInfoBarPhase): void {
@ -60,16 +47,18 @@ module TK.SpaceTac.UI {
container: UIContainer
turns: UIText
constructor(parent: UIContainer, startResolution: Function) {
constructor(parent: UIContainer, startResolution?: Function) {
this.container = parent.getBuilder().container("planning", 0, 0, false);
const builder = this.container.getBuilder();
builder.button("battle-buttons-medium", 604, 0, startResolution, "Confirm your planning and start the turn resolution", undefined, {
center: true,
text: "Ready",
text_x: 12,
text_style: { size: 24, color: "#9fc4d6" }
});
if (startResolution) {
builder.button("battle-buttons-medium", 604, 0, startResolution, "Confirm your planning and start the turn resolution", undefined, {
center: true,
text: "Ready",
text_x: 12,
text_style: { size: 24, color: "#9fc4d6" }
});
}
builder.image("battle-infobar-turncounter", 450, 0, true);
this.turns = builder.text("Turn", 450, 0, { center: true, size: 24, color: "#9fc4d6" });

View File

@ -225,9 +225,15 @@ module TK.SpaceTac.UI {
* Start the turn resolution
*/
startResolution(): void {
// TODO Check we are in planning phase
// TODO Wait for AI
// TODO
const message = "Validate your whole fleet planning, and proceed to turn resolution?";
UIConfirmDialog.ask(this, message).then(ok => {
if (ok) {
// TODO Check we are in planning phase
// TODO Wait for AI
// TODO Merge plans
this.actual_battle.applyTurnPlan(this.turn_plannings[0].getTurnPlan());
}
});
}
/**

View File

@ -9,7 +9,7 @@ module TK.SpaceTac.UI {
constructor(view: BaseView, message: string) {
super(view);
this.content.text(message, this.width * 0.5, this.height * 0.4, { color: "#9FC4D6", size: 32, shadow: true });
this.content.text(message, this.width * 0.5, this.height * 0.4, { color: "#9FC4D6", size: 32, shadow: true, width: 800 });
this.result = new Promise(resolve => {
this.result_resolver = resolve;