Skip to content

Commit ad5f77f

Browse files
author
zacaj
committed
attract mode
1 parent 1220e2d commit ad5f77f

21 files changed

+195
-137
lines changed

Diff for: __snapshots__/game.spec.ts.snap

+1
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ Object {
662662
"state": Object {
663663
"ballsInTrough": 3,
664664
"ballsLocked": 0,
665+
"game": "Game20",
665666
"lastSwitchHit": Switch {
666667
"_state": false,
667668
"column": 5,

Diff for: __snapshots__/recording.spec.ts.snap

+1
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ Object {
720720
"state": Object {
721721
"ballsInTrough": 3,
722722
"ballsLocked": 0,
723+
"game": "Game29",
723724
"lastSwitchHit": Switch {
724725
"_state": true,
725726
"column": 3,

Diff for: attract.ts

+52-9
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,67 @@
1-
import { Mode, Modes } from './mode';
2-
import { MachineOutputs, machine } from './machine';
3-
import { Outputs } from './outputs';
1+
import { Game } from './game';
2+
import { addToScreen, makeText, ModeGroup, Screen } from './gfx';
43
import { initMachine } from './init';
5-
import { ClearHoles, ResetAnyDropOnComplete } from './util-modes';
64
import { Log } from './log';
5+
import { machine } from './machine';
6+
import { Mode, Modes } from './mode';
77
import { fork } from './promises';
8+
import { onSwitchClose } from './switch-matrix';
9+
import { money, score } from './util';
10+
import { ClearHoles } from './util-modes';
811

912
export class AttractMode extends Mode {
1013

11-
constructor() {
14+
clearHoles = new ClearHoles();
15+
16+
get nodes() {
17+
return [this.clearHoles];
18+
}
19+
20+
constructor(
21+
public scores?: [number, number][],
22+
) {
1223
super(Modes.AttractMode);
1324

14-
// this.addTemp(new ClearHoles());
15-
// this.addTemp(new ResetAnyDropOnComplete());
25+
addToScreen(() => new AttractGfx(this));
26+
27+
this.listen(onSwitchClose(machine.sStartButton), async () => {
28+
const game = await Game.start();
29+
});
30+
}
31+
32+
end() {
33+
machine.attract = undefined;
34+
return super.end();
1635
}
1736
}
1837

1938
if (require.main === module) {
20-
fork(initMachine()).then(() => {
39+
fork(initMachine(true, true, false, false)).then(() => {
2140
Log.log(['console'], 'starting attract mode...');
22-
// machine.addTemp(new AttractMode());
41+
machine.attract = new AttractMode();
42+
machine.attract.started();
2343
});
44+
}
45+
46+
export class AttractGfx extends ModeGroup {
47+
constructor(
48+
public a: AttractMode,
49+
) {
50+
super(a);
51+
this.z(a.gPriority);
52+
53+
if (!a.scores)
54+
this.add(makeText('Attract Mode', 100, 'center'));
55+
else {
56+
this.add(makeText('Game Over', 100, 'center').y(-Screen.h*.3));
57+
let y = -Screen.h * .15;
58+
let i = 1;
59+
for (const [sc, bank] of a.scores) {
60+
this.add(makeText(`PLAYER ${i}:`, 50, 'left').x(-Screen.w*.4).y(y));
61+
this.add(makeText(`${score(sc)} | ${money(bank)}`, 50, 'right').x(Screen.w*.4).y(y));
62+
y += 75;
63+
i++;
64+
}
65+
}
66+
}
2467
}

Diff for: events.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { OrArray, assert, arrayify, getCallerLoc, isPromise } from './util';
2-
import { time, Timer } from './timer';
31
import { Log } from './log';
4-
import * as util from 'util';
52
import { fork } from './promises';
3+
import { Timer } from './timer';
4+
import { arrayify, assert, getCallerLoc, isPromise, OrArray } from './util';
65

76
export abstract class Event {
87
static eventCount = 0;
@@ -23,6 +22,21 @@ export abstract class Event {
2322
}
2423
}
2524

25+
26+
export class StateEvent<T, Prop extends keyof T> extends Event {//<T> extends Event {//
27+
constructor(
28+
// public on: any,
29+
// public prop: string,
30+
// public value: T,
31+
public on: T,
32+
public prop: Prop,
33+
public value: T[Prop],
34+
public oldValue: T[Prop],
35+
) {
36+
super();
37+
}
38+
}
39+
2640
export type EventPredicate<E extends Event = Event> = (e: E) => boolean;
2741
export type EventTypePredicate<E extends Event = Event> = (e: E) => boolean;//e is E;
2842
export type EventCallback<E extends Event = Event> = ((e: E) => 'remove'|any)|{[func: string]: {}};

Diff for: game.ts

+32-27
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
1-
import { SwitchEvent, onSwitchClose, onAnySwitchClose, resetSwitchMatrix, onAnyPfSwitchExcept, Switch, onClose } from './switch-matrix';
2-
import { Events, onType, Event } from './events';
3-
import { State, StateEvent, onChange } from './state';
4-
import { machine, MachineOutputs, resetMachine } from './machine';
5-
import { Mode, Modes } from './mode';
6-
import { Outputs, toggle } from './outputs';
7-
import { time, safeSetTimeout, Timer } from './timer';
8-
import { ClearHoles, ResetAnyDropOnComplete, KnockTarget } from './util-modes';
1+
import fs from 'fs';
2+
import { AttractMode } from './attract';
3+
import { Events } from './events';
4+
import { addToScreen, alert, gfx, screen } from './gfx';
5+
import { GameGfx } from './gfx/game';
96
import { initMachine } from './init';
107
import { Log } from './log';
11-
import { DropBankCompleteEvent } from './drop-bank';
12-
import { GameGfx } from './gfx/game';
13-
import { screen, alert, gfx, addToScreen } from './gfx';
8+
import { machine } from './machine';
9+
import { Mode, Modes } from './mode';
1410
import { Player } from './modes/player';
15-
import { assert, getFormattedTime } from './util';
16-
import { Ball } from './modes/ball';
17-
import { StraightMb } from './modes/straight.mb';
18-
import { fork } from './promises';
19-
import { Tree, TreeChangeEvent } from './tree';
2011
import { MPU } from './mpu';
21-
import fs from 'fs';
12+
import { Outputs } from './outputs';
13+
import { State } from './state';
14+
import { onClose, onSwitchClose, Switch } from './switch-matrix';
15+
import { time } from './timer';
16+
import { TreeChangeEvent } from './tree';
17+
import { assert, getFormattedTime } from './util';
18+
import { ClearHoles } from './util-modes';
2219

2320
export class Game extends Mode {
24-
get children() {
21+
get nodes() {
2522
return [this.curPlayer, ...this.tempNodes].truthy();
2623
}
2724

@@ -31,7 +28,7 @@ export class Game extends Mode {
3128
return this.players[this.playerUp];
3229
}
3330
ballNum = 1;
34-
ballCount = 3;
31+
ballCount = 1;
3532

3633
get ball() {
3734
return this.curPlayer.ball;
@@ -69,22 +66,30 @@ export class Game extends Mode {
6966
this.playerUp = 0;
7067
this.ballNum++;
7168
if (this.ballNum > this.ballCount) {
72-
alert('GAME OVER', 5000);
69+
// alert('GAME OVER', 5000);
7370
fs.writeFileSync(`./scores/game-${getFormattedTime()}.json`, JSON.stringify(this.totals, undefined, 2));
74-
// if (require.main === module) {
75-
// debugger;
76-
// process.exit(0);
77-
// }
78-
// else
79-
// this.end();
71+
if (require.main === module) {
72+
debugger;
73+
process.exit(0);
74+
}
75+
else
76+
this.end();
8077
}
8178
}
8279
Log.log('console', 'player %i starting ball %i', this.curPlayer.number, this.ballNum);
8380
Events.fire(new TreeChangeEvent(this));
8481
await this.curPlayer.startBall();
8582
}
8683

84+
end() {
85+
machine.attract = new AttractMode(this.players.map(p => [p.score, p.store.Poker!.bank]));
86+
machine.attract.started();
87+
machine.game = undefined;
88+
return super.end();
89+
}
90+
8791
static async start(): Promise<Game> {
92+
assert(!machine.game);
8893
if (gfx && !MPU.isConnected) {
8994
machine.sTroughFull.changeState(true, 'fake');
9095
}
@@ -99,13 +104,13 @@ export class Game extends Mode {
99104
pop.parent?.remove(pop);
100105
clear.end();
101106
}
107+
machine.attract?.end();
102108
const game = new Game();
103109
machine.game = game;
104110
game.started();
105111
game.players.push(new Player(game, 1));
106112
game.curPlayer.started();
107113
await game.curPlayer.startBall();
108-
game.watch(() => screen?.circle.x(time()%1000-500));
109114
return game;
110115
}
111116

Diff for: gfx.ts

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1-
import { AminoGfx, Property, Group, Circle, ImageView, Rect, AminoImage, fonts, Texture, Text, Node, Polygon } from 'aminogfx-gl';
2-
import { Log } from './log';
3-
import { initMachine } from './init';
4-
import { LightOutputs, ImageOutputs, resetMachine, Solenoid, machine } from './machine';
5-
import { Color, colorToHex, LightState, normalizeLight } from './light';
6-
import { Switch, onSwitchClose, onSwitch, matrix, getSwitchByName, resetSwitchMatrix } from './switch-matrix';
7-
import { Event, EventListener, Events, Priorities } from './events';
8-
import { assert, num, tryNum, getCallerLoc } from './util';
1+
import { AminoGfx, AminoImage, Circle, fonts, Group, ImageView, Node, Polygon, Rect, Text, Texture } from 'aminogfx-gl';
92
// import { Game } from './game';
103
// import { MPU } from './mpu';
114
import * as fs from 'fs';
12-
import { wait, Timer, time } from './timer';
13-
import { fork } from './promises';
14-
import { onChange } from './state';
5+
import { EventListener, Events } from './events';
6+
import { Color, colorToHex, LightState, normalizeLight } from './light';
7+
import { Log } from './log';
8+
import { ImageOutputs, LightOutputs, machine, resetMachine, Solenoid } from './machine';
159
import { Mode } from './mode';
10+
import { onChange } from './state';
11+
import { getSwitchByName, matrix, onSwitch, resetSwitchMatrix, Switch } from './switch-matrix';
12+
import { time, wait } from './timer';
1613
import { TreeChangeEvent } from './tree';
14+
import { assert } from './util';
1715
const argv = require('yargs').argv;
1816

1917
export let gfx: AminoGfx;

Diff for: log.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as fs from 'fs';
22
import * as util from 'util';
33
import { OrArray, arrayify, getCallerLoc, clone } from './util';
4-
import { time, Time } from './timer';
54
const truncate = require('truncate-logs');
65

76
enum Levels {
@@ -73,14 +72,14 @@ export class Log {
7372
}
7473
}
7574

76-
private static lastTrace: Time;
75+
private static lastTrace: number;
7776
static trace(categories: OrArray<LogCategory>, message: string, ...params: any[]) {
7877
if (!Log.files.trace) return;
7978
params = Log.cleanParams(params);
8079
// Log.write(Log.files.trace, JSON.stringify({categories, message, params: util.inspect(params)}));
8180
const ts = Log.timestamp()+' ';
8281
Log.write(Log.files.trace, ts+JSON.stringify(categories)+' '+Log.format(message, params)+'\t\t\t@'+getCallerLoc(true));
83-
if (time() - Log.lastTrace > 5*60*60*1000)
82+
if (new Date().getTime() - Log.lastTrace > 5*60*60*1000)
8483
truncate(['trace.log'], {lines: 50000});
8584
}
8685

@@ -107,7 +106,7 @@ export class Log {
107106
}
108107

109108
static init(trace = true) {
110-
Log.lastTrace = time();
109+
Log.lastTrace = new Date().getTime();
111110
for (const f of files) {
112111
Log.files[f] = fs.openSync(f+'.log', 'w');
113112
Log.write(Log.files[f], `${new Date()}`);

Diff for: machine.ts

+23-18
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
import { State, StateEvent } from './state';
1+
import { Node } from 'aminogfx-gl';
2+
import { AttractMode } from './attract';
23
import { Solenoid16 } from './boards';
3-
import { matrix, Switch, onSwitchClose, onClose, onAnyPfSwitchExcept, onAnySwitchClose, Lane, Drain, Bumper, Drop, Standup as StandupSet, Hole, onSwitch, SwitchEvent } from './switch-matrix';
4-
import { Events, Event, EventTypePredicate, EventListener, onAny } from './events';
5-
import { Mode, Modes } from './mode';
6-
import { Outputs, TreeOutputEvent, OwnOutputEvent, toggle } from './outputs';
7-
import { safeSetInterval, Time, time, Timer, TimerQueueEntry, wait } from './timer';
8-
import { assert, getTypeIn, then, eq as eq } from './util';
94
import { DropBank, DropTarget, Standup } from './drop-bank';
10-
import { Log } from './log';
5+
import { Event, Events, EventTypePredicate, onAny, StateEvent } from './events';
6+
import { Game } from './game';
7+
import { gfx, gfxImages, gfxLights, screen } from './gfx';
118
import { Color, light, LightState } from './light';
12-
import { gfxLights, gfxImages, gfx, screen } from './gfx';
13-
import { Tree } from './tree';
9+
import { Log } from './log';
10+
import { Mode, Modes } from './mode';
11+
import { Skillshot } from './modes/skillshot';
1412
import { MPU } from './mpu';
15-
import { Node } from 'aminogfx-gl';
16-
import { curRecording } from './recording';
13+
import { Outputs, TreeOutputEvent } from './outputs';
1714
import { fork } from './promises';
18-
import { Game } from './game';
19-
import { Skillshot } from './modes/skillshot';
15+
import { curRecording } from './recording';
16+
import { State } from './state';
17+
import { Bumper, Drain, Drop, Hole, Lane, onAnyPfSwitchExcept, onAnySwitchClose, onSwitch, onSwitchClose, Standup as StandupSet, Switch, SwitchEvent } from './switch-matrix';
18+
import { Time, time, Timer, TimerQueueEntry, wait } from './timer';
19+
import { Tree } from './tree';
20+
import { assert, eq as eq, getTypeIn, then } from './util';
2021

2122
abstract class MachineOutput<T, Outs = MachineOutputs> {
2223
static id = 1;
@@ -698,12 +699,14 @@ export class Machine extends Tree<MachineOutputs> {
698699
}
699700
}
700701

701-
game!: Game;
702+
game?: Game;
703+
attract?: AttractMode;
702704
overrides!: MachineOverrides;
703705

704-
get children() {
706+
get nodes() {
705707
return [
706708
...this.dropBanks,
709+
this.attract,
707710
this.game,
708711
...this.tempNodes,
709712
this.overrides,
@@ -722,7 +725,7 @@ export class Machine extends Tree<MachineOutputs> {
722725
constructor() {
723726
super();
724727
this.makeRoot();
725-
State.declare<Machine>(this, ['lockDown', 'miniDown', 'lastSwitchHit', 'ballsInTrough', 'ballsLocked']);
728+
State.declare<Machine>(this, ['lockDown', 'miniDown', 'lastSwitchHit', 'ballsInTrough', 'ballsLocked', 'game']);
726729

727730
this.out = new Outputs<MachineOutputs>(this, {
728731
rampUp: false,
@@ -851,6 +854,8 @@ export class Machine extends Tree<MachineOutputs> {
851854
this.listen(onAnySwitchClose(...this.standups.map(([sw]) => sw)), (e) => Events.fire(new StandupEvent(this.standups.find(([sw]) => e.sw === sw)!)));
852855

853856
this.overrides = new MachineOverrides(this);
857+
858+
this.watch(() => screen?.circle.x(time()%1000-500));
854859
}
855860
}
856861

@@ -877,7 +882,7 @@ export function expectMachineOutputs(...names: (keyof MachineOutputs)[]): jest.S
877882
class MachineOverrides extends Mode {
878883
eosPulse = new EosPulse(this.machine.cRamp, this.machine.sRampDown);
879884

880-
get children() {
885+
get nodes() {
881886
return [this.eosPulse];
882887
}
883888

0 commit comments

Comments
 (0)