Added end battle conditions and event
This commit is contained in:
parent
30e6323bf3
commit
de81186faf
|
@ -3,6 +3,9 @@ module SpaceTac.Game {
|
|||
|
||||
// A turn-based battle between fleets
|
||||
export class Battle {
|
||||
// Flag indicating if the battle is ended
|
||||
ended: boolean;
|
||||
|
||||
// Log of all battle events
|
||||
log: BattleLog;
|
||||
|
||||
|
@ -27,6 +30,7 @@ module SpaceTac.Game {
|
|||
this.playing_ship_index = null;
|
||||
this.playing_ship = null;
|
||||
this.first_turn = true;
|
||||
this.ended = false;
|
||||
|
||||
this.fleets.forEach((fleet: Fleet) => {
|
||||
fleet.setBattle(this);
|
||||
|
@ -69,26 +73,76 @@ module SpaceTac.Game {
|
|||
this.placeFleetShips(this.fleets[1], 800, 300, Math.PI);
|
||||
}
|
||||
|
||||
// Count the number of fleets still alive
|
||||
countAliveFleets(): number {
|
||||
var result = 0;
|
||||
this.fleets.forEach((fleet: Fleet) => {
|
||||
if (fleet.isAlive()) {
|
||||
result += 1;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Checks end battle conditions, returns true if the battle ended
|
||||
checkEndBattle(log: boolean = true) {
|
||||
if (this.ended) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var alive_fleets = this.countAliveFleets();
|
||||
|
||||
if (alive_fleets == 0) {
|
||||
// It's a draw
|
||||
this.ended = true;
|
||||
this.log.add(new EndBattleEvent(null));
|
||||
} else if (alive_fleets == 1) {
|
||||
// We have a winner
|
||||
var winner: Player = null;
|
||||
this.fleets.forEach((fleet: Fleet) => {
|
||||
if (fleet.isAlive()) {
|
||||
winner = fleet.player;
|
||||
}
|
||||
});
|
||||
this.ended = true;
|
||||
this.log.add(new EndBattleEvent(winner));
|
||||
}
|
||||
|
||||
return this.ended;
|
||||
}
|
||||
|
||||
// End the current ship turn, passing control to the next one in play order
|
||||
// If at the end of the play order, next turn will start automatically
|
||||
// Member 'play_order' must be defined before calling this function
|
||||
advanceToNextShip(log: boolean = true): void {
|
||||
var previous_ship = this.playing_ship;
|
||||
|
||||
if (this.checkEndBattle(log)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.play_order.length === 0) {
|
||||
this.playing_ship_index = null;
|
||||
this.playing_ship = null;
|
||||
} else {
|
||||
if (this.playing_ship_index == null) {
|
||||
this.playing_ship_index = 0;
|
||||
} else {
|
||||
this.playing_ship_index += 1;
|
||||
var i = 0;
|
||||
do {
|
||||
if (this.playing_ship_index == null) {
|
||||
this.playing_ship_index = 0;
|
||||
} else {
|
||||
this.playing_ship_index += 1;
|
||||
}
|
||||
if (this.playing_ship_index >= this.play_order.length) {
|
||||
this.playing_ship_index = 0;
|
||||
this.first_turn = false;
|
||||
}
|
||||
this.playing_ship = this.play_order[this.playing_ship_index];
|
||||
i++;
|
||||
} while (!this.playing_ship.alive && i < 1000);
|
||||
|
||||
if (i >= 1000) {
|
||||
throw new Error("Infinite loop in advanceToNextShip");
|
||||
}
|
||||
if (this.playing_ship_index >= this.play_order.length) {
|
||||
this.playing_ship_index = 0;
|
||||
this.first_turn = false;
|
||||
}
|
||||
this.playing_ship = this.play_order[this.playing_ship_index];
|
||||
}
|
||||
|
||||
if (this.playing_ship) {
|
||||
|
@ -104,6 +158,7 @@ module SpaceTac.Game {
|
|||
// This will call all necessary initialization steps (initiative, placement...)
|
||||
// This will not add any event to the battle log
|
||||
start(): void {
|
||||
this.ended = false;
|
||||
this.placeShips();
|
||||
this.throwInitiative();
|
||||
this.play_order.forEach((ship: Ship) => {
|
||||
|
|
|
@ -29,5 +29,16 @@ module SpaceTac.Game {
|
|||
setBattle(battle: Battle): void {
|
||||
this.battle = battle;
|
||||
}
|
||||
|
||||
// Check if the fleet still has living ships
|
||||
isAlive(): boolean {
|
||||
var count = 0;
|
||||
this.ships.forEach((ship: Ship) => {
|
||||
if (ship.alive) {
|
||||
count += 1;
|
||||
}
|
||||
});
|
||||
return (count > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -228,6 +228,14 @@ module SpaceTac.Game {
|
|||
}
|
||||
}
|
||||
|
||||
// Set the death status on this ship
|
||||
setDead(log: boolean = true): void {
|
||||
this.alive = false;
|
||||
if (log) {
|
||||
this.addBattleEvent(new DeathEvent(this));
|
||||
}
|
||||
}
|
||||
|
||||
// Apply damages to hull and/or shield
|
||||
addDamage(hull: number, shield: number, log: boolean = true): void {
|
||||
this.setAttribute(this.hull, -hull, true, log);
|
||||
|
@ -239,10 +247,7 @@ module SpaceTac.Game {
|
|||
|
||||
if (this.hull.current === 0) {
|
||||
// Ship is dead
|
||||
this.alive = false;
|
||||
if (log) {
|
||||
this.addBattleEvent(new DeathEvent(this));
|
||||
}
|
||||
this.setDead(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/// <reference path="BaseLogEvent.ts"/>
|
||||
|
||||
module SpaceTac.Game {
|
||||
"use strict";
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/// <reference path="BaseLogEvent.ts"/>
|
||||
|
||||
module SpaceTac.Game {
|
||||
"use strict";
|
||||
|
||||
|
|
18
src/scripts/game/events/EndBattleEvent.ts
Normal file
18
src/scripts/game/events/EndBattleEvent.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/// <reference path="BaseLogEvent.ts"/>
|
||||
|
||||
module SpaceTac.Game {
|
||||
"use strict";
|
||||
|
||||
// Event logged when the battle ended
|
||||
// This is always the last event of a battle log
|
||||
export class EndBattleEvent extends BaseLogEvent {
|
||||
// Winner of the battle
|
||||
winner: Player;
|
||||
|
||||
constructor(winner: Player) {
|
||||
super("endbattle");
|
||||
|
||||
this.winner = winner;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/// <reference path="BaseLogEvent.ts"/>
|
||||
|
||||
module SpaceTac.Game {
|
||||
"use strict";
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/// <reference path="BaseLogEvent.ts"/>
|
||||
|
||||
module SpaceTac.Game {
|
||||
"use strict";
|
||||
|
||||
|
|
|
@ -106,6 +106,14 @@ module SpaceTac.Game {
|
|||
|
||||
expect(battle.playing_ship).toBe(ship2);
|
||||
expect(battle.playing_ship_index).toBe(0);
|
||||
|
||||
// A dead ship is skipped
|
||||
ship1.alive = false;
|
||||
|
||||
battle.advanceToNextShip();
|
||||
|
||||
expect(battle.playing_ship).toBe(ship3);
|
||||
expect(battle.playing_ship_index).toBe(2);
|
||||
});
|
||||
|
||||
it("calls startTurn on ships, with first turn indicator", function () {
|
||||
|
@ -138,5 +146,57 @@ module SpaceTac.Game {
|
|||
battle.advanceToNextShip();
|
||||
expect(ship1.startTurn).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it("detects victory condition and logs a final EndBattleEvent", function () {
|
||||
var fleet1 = new Fleet();
|
||||
var fleet2 = new Fleet();
|
||||
|
||||
var ship1 = new Ship(fleet1, "F1S1");
|
||||
var ship2 = new Ship(fleet1, "F1S2");
|
||||
var ship3 = new Ship(fleet2, "F2S1");
|
||||
|
||||
var battle = new Battle(fleet1, fleet2);
|
||||
|
||||
battle.start();
|
||||
expect(battle.ended).toBe(false);
|
||||
|
||||
ship1.setDead();
|
||||
ship2.setDead();
|
||||
|
||||
battle.log.clear();
|
||||
battle.advanceToNextShip();
|
||||
|
||||
expect(battle.ended).toBe(true);
|
||||
expect(battle.log.events.length).toBe(1);
|
||||
expect(battle.log.events[0].code).toBe("endbattle");
|
||||
expect((<EndBattleEvent>battle.log.events[0]).winner).not.toBeNull();
|
||||
expect((<EndBattleEvent>battle.log.events[0]).winner).toBe(fleet2.player);
|
||||
});
|
||||
|
||||
it("handles a draw in end battle", function () {
|
||||
var fleet1 = new Fleet();
|
||||
var fleet2 = new Fleet();
|
||||
|
||||
var ship1 = new Ship(fleet1, "F1S1");
|
||||
var ship2 = new Ship(fleet1, "F1S2");
|
||||
var ship3 = new Ship(fleet2, "F2S1");
|
||||
|
||||
var battle = new Battle(fleet1, fleet2);
|
||||
|
||||
battle.start();
|
||||
expect(battle.ended).toBe(false);
|
||||
|
||||
ship1.setDead();
|
||||
ship2.setDead();
|
||||
ship3.setDead();
|
||||
|
||||
battle.log.clear();
|
||||
battle.advanceToNextShip();
|
||||
|
||||
expect(battle.ended).toBe(true);
|
||||
expect(battle.log.events.length).toBe(1);
|
||||
expect(battle.log.events[0].code).toBe("endbattle");
|
||||
expect((<EndBattleEvent>battle.log.events[0]).winner).toBeNull();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue