trucoshi 0.0.2 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.prettierrc.json +4 -0
  2. package/LICENSE +674 -0
  3. package/README.md +37 -0
  4. package/build/lib/classes/Deck.d.ts +2 -0
  5. package/build/lib/classes/Deck.js +27 -0
  6. package/build/lib/classes/Hand.d.ts +2 -0
  7. package/build/lib/classes/Hand.js +233 -0
  8. package/build/lib/classes/Match.d.ts +2 -0
  9. package/build/lib/classes/Match.js +115 -0
  10. package/build/lib/classes/Play.d.ts +2 -0
  11. package/build/lib/classes/Play.js +39 -0
  12. package/build/lib/classes/Player.d.ts +2 -0
  13. package/build/lib/classes/Player.js +38 -0
  14. package/build/lib/classes/Round.d.ts +2 -0
  15. package/build/lib/classes/Round.js +33 -0
  16. package/build/lib/classes/Table.d.ts +2 -0
  17. package/build/lib/classes/Table.js +30 -0
  18. package/build/lib/classes/Team.d.ts +2 -0
  19. package/build/lib/classes/Team.js +42 -0
  20. package/build/lib/classes/Truco.d.ts +2 -0
  21. package/build/lib/classes/Truco.js +110 -0
  22. package/build/lib/constants.d.ts +36 -28
  23. package/build/lib/constants.js +97 -12
  24. package/build/lib/index.d.ts +18 -0
  25. package/build/lib/index.js +161 -0
  26. package/build/lib/types.d.ts +121 -30
  27. package/build/lib/types.js +24 -12
  28. package/build/lib/utils.d.ts +3 -3
  29. package/build/lib/utils.js +11 -18
  30. package/build/server/index.js +13 -5
  31. package/build/server/match.d.ts +0 -0
  32. package/build/server/match.js +1 -0
  33. package/build/server/types.d.ts +11 -0
  34. package/build/server/types.js +15 -0
  35. package/build/test/autoplay.js +52 -31
  36. package/build/test/play.js +146 -81
  37. package/package.json +5 -4
  38. package/src/lib/classes/Deck.ts +25 -0
  39. package/src/lib/classes/Hand.ts +207 -0
  40. package/src/lib/classes/Match.ts +79 -0
  41. package/src/lib/classes/Play.ts +40 -0
  42. package/src/lib/classes/Player.ts +37 -0
  43. package/src/lib/classes/Round.ts +30 -0
  44. package/src/lib/classes/Table.ts +32 -0
  45. package/src/lib/classes/Team.ts +41 -0
  46. package/src/lib/classes/Truco.ts +72 -0
  47. package/src/lib/constants.ts +105 -11
  48. package/src/lib/index.ts +135 -0
  49. package/src/lib/types.ts +186 -80
  50. package/src/lib/utils.ts +50 -53
  51. package/src/server/index.ts +34 -22
  52. package/src/server/match.ts +0 -0
  53. package/src/server/types.ts +12 -0
  54. package/src/test/autoplay.ts +57 -41
  55. package/src/test/play.ts +122 -70
  56. package/build/lib/trucoshi.d.ts +0 -10
  57. package/build/lib/trucoshi.js +0 -363
  58. package/build/test/legacy.d.ts +0 -1
  59. package/build/test/legacy.js +0 -146
  60. package/src/lib/trucoshi.ts +0 -342
  61. package/src/test/legacy.ts +0 -68
@@ -58,91 +58,156 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
58
58
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
59
  }
60
60
  };
61
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
62
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
63
+ if (ar || !(i in from)) {
64
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
65
+ ar[i] = from[i];
66
+ }
67
+ }
68
+ return to.concat(ar || Array.prototype.slice.call(from));
69
+ };
61
70
  Object.defineProperty(exports, "__esModule", { value: true });
62
71
  var readline = __importStar(require("readline"));
63
- var constants_1 = require("../lib/constants");
64
- var trucoshi_1 = require("../lib/trucoshi");
65
- (function () { return __awaiter(void 0, void 0, void 0, function () {
66
- var player1, player2, player3, player4, team1, team2, match, _loop_1, state_1;
67
- var _a;
68
- return __generator(this, function (_b) {
69
- switch (_b.label) {
70
- case 0:
71
- player1 = (0, trucoshi_1.Player)('lukini', 0);
72
- player2 = (0, trucoshi_1.Player)('guada', 0);
73
- player3 = (0, trucoshi_1.Player)('denoph', 1);
74
- player4 = (0, trucoshi_1.Player)('juli', 1);
75
- team1 = (0, trucoshi_1.Team)(constants_1.COLORS[0], [player1, player2]);
76
- team2 = (0, trucoshi_1.Team)(constants_1.COLORS[1], [player3, player4]);
77
- match = (0, trucoshi_1.Match)([team1, team2], 9);
78
- _loop_1 = function () {
79
- var play, name, prom;
80
- return __generator(this, function (_c) {
81
- switch (_c.label) {
82
- case 0:
83
- play = match.play();
84
- if (!play || !play.player) {
85
- return [2 /*return*/, "break"];
86
- }
87
- name = play.player.id.toUpperCase();
88
- process.stdout.write('\u001B[2J\u001B[0;0f');
89
- process.stdout.write('\u001B[0;0f');
90
- console.log("=== Mano ".concat(play.handIdx, " === Ronda ").concat(play.roundIdx, " === Turno de ").concat(name, " ==="));
91
- process.stdout.write('\u001B[2;0f');
92
- match.teams.map(function (team, id) { return console.log("=== Team ".concat(id, " = ").concat(team.points, " Puntos ===")); });
93
- process.stdout.write('\u001B[5;0f');
94
- console.log(play.rounds && play.rounds.length ? (play.rounds.map(function (round) { return round.cards.length ? round.cards.map(function (c) { return [c.player.id, c.card]; }) : ''; })) : '');
95
- prom = function () { return new Promise(function (resolve) {
96
- var _a, _b;
97
- var rl = readline.createInterface(process.stdin, process.stdout);
98
- rl.setPrompt("\n".concat((_a = play.player) === null || _a === void 0 ? void 0 : _a.id, " elije una carta [1, 2, 3]: ").concat(JSON.stringify((_b = play.player) === null || _b === void 0 ? void 0 : _b.hand), "\n"));
99
- rl.prompt();
100
- rl.on('line', function (idx) {
101
- var _a;
102
- var playedCard = play.use(Number(idx) - 1);
103
- if (!playedCard) {
104
- rl.close();
105
- return (function () { return __awaiter(void 0, void 0, void 0, function () {
106
- return __generator(this, function (_a) {
107
- switch (_a.label) {
108
- case 0: return [4 /*yield*/, prom()];
109
- case 1:
110
- _a.sent();
111
- resolve();
112
- return [2 /*return*/];
113
- }
114
- });
115
- }); })();
72
+ var lib_1 = require("../lib");
73
+ var command = function (title, onLine) {
74
+ var promise = function () {
75
+ return new Promise(function (resolve) {
76
+ var rl = readline.createInterface(process.stdin, process.stdout);
77
+ rl.setPrompt(title);
78
+ rl.prompt();
79
+ rl.on("line", function (line) { return __awaiter(void 0, void 0, void 0, function () {
80
+ var e_1;
81
+ return __generator(this, function (_a) {
82
+ switch (_a.label) {
83
+ case 0:
84
+ _a.trys.push([0, 2, , 3]);
85
+ return [4 /*yield*/, onLine(line, function () { return rl.close(); })];
86
+ case 1:
87
+ _a.sent();
88
+ rl.close();
89
+ resolve();
90
+ return [3 /*break*/, 3];
91
+ case 2:
92
+ e_1 = _a.sent();
93
+ rl.close();
94
+ return [2 /*return*/, (function () { return __awaiter(void 0, void 0, void 0, function () {
95
+ return __generator(this, function (_a) {
96
+ switch (_a.label) {
97
+ case 0: return [4 /*yield*/, promise()];
98
+ case 1:
99
+ _a.sent();
100
+ resolve();
101
+ return [2 /*return*/];
116
102
  }
117
- process.stdout.write('\u001B[7;0f');
118
- console.log("\n".concat(JSON.stringify((_a = play.player) === null || _a === void 0 ? void 0 : _a.hand), "\nUsing ").concat(playedCard));
119
- process.stdout.write('\u001B[10;0f');
120
- console.log(play.rounds && play.rounds.length ? (play.rounds.map(function (round) { return round.cards.length ? round.cards.map(function (c) { return [c.player.id, c.card]; }) : ''; })) : '');
121
- rl.close();
122
- resolve();
123
103
  });
124
- }); };
125
- return [4 /*yield*/, prom()];
126
- case 1:
127
- _c.sent();
128
- return [2 /*return*/];
129
- }
130
- });
131
- };
132
- _b.label = 1;
133
- case 1:
134
- if (!!match.winner) return [3 /*break*/, 3];
135
- return [5 /*yield**/, _loop_1()];
136
- case 2:
137
- state_1 = _b.sent();
138
- if (state_1 === "break")
139
- return [3 /*break*/, 3];
140
- return [3 /*break*/, 1];
141
- case 3:
142
- process.stdout.write('\u001B[2J\u001B[2;0f');
143
- match.teams.map(function (t, i) { return console.log("Equipo ".concat(i, ": ").concat(t.players.map(function (p) { return " ".concat(p.id); }), " === ").concat(t.points, " puntos")); });
144
- console.log("\nEquipo Ganador:".concat((_a = match.winner) === null || _a === void 0 ? void 0 : _a.players.map(function (p) { return " ".concat(p.id); })));
104
+ }); })()];
105
+ case 3: return [2 /*return*/];
106
+ }
107
+ });
108
+ }); });
109
+ });
110
+ };
111
+ return promise;
112
+ };
113
+ var playCommand = function (play) {
114
+ var _a, _b, _d;
115
+ return command("".concat((_a = play.player) === null || _a === void 0 ? void 0 : _a.id, " elije una carta [").concat((_b = play.player) === null || _b === void 0 ? void 0 : _b.hand.map(function (_c, i) { return i + 1; }), "]: ").concat(JSON.stringify((_d = play.player) === null || _d === void 0 ? void 0 : _d.hand), "\n"), function (idx) { return __awaiter(void 0, void 0, void 0, function () {
116
+ var playedCard, handString;
117
+ var _a;
118
+ return __generator(this, function (_b) {
119
+ playedCard = play.use(Number(idx) - 1);
120
+ if (!playedCard) {
121
+ return [2 /*return*/, Promise.reject()];
122
+ }
123
+ handString = JSON.stringify((_a = play.player) === null || _a === void 0 ? void 0 : _a.hand);
124
+ console.log("\n".concat(handString, "\nUsing ").concat(playedCard));
125
+ console.log(play.rounds && play.rounds.length
126
+ ? play.rounds.map(function (round) {
127
+ return round.cards.length ? round.cards.map(function (c) { return [c.player.id, c.card]; }) : "";
128
+ })
129
+ : "");
130
+ return [2 /*return*/, Promise.resolve()];
131
+ });
132
+ }); });
133
+ };
134
+ var sayCommand = function (play, canPlay) {
135
+ var _a, _b;
136
+ return command("".concat((_a = play.player) === null || _a === void 0 ? void 0 : _a.id, " elije una accion [").concat(canPlay ? "0," : "").concat((_b = play.commands) === null || _b === void 0 ? void 0 : _b.map(function (_c, i) { return i + 1; }), "]: ").concat(canPlay ? JSON.stringify(__spreadArray(["CARTA"], (play.commands || []), true)) : JSON.stringify(play.commands), "\n"), function (idx, close) { return __awaiter(void 0, void 0, void 0, function () {
137
+ var selectedCommand;
138
+ var _a;
139
+ return __generator(this, function (_b) {
140
+ switch (_b.label) {
141
+ case 0:
142
+ selectedCommand = (_a = play.commands) === null || _a === void 0 ? void 0 : _a[Number(idx) - 1];
143
+ if (selectedCommand) {
144
+ play.say(selectedCommand);
145
+ return [2 /*return*/, Promise.resolve()];
146
+ }
147
+ if (!(idx === "0" && canPlay)) return [3 /*break*/, 2];
148
+ close();
149
+ return [4 /*yield*/, playCommand(play)()];
150
+ case 1:
151
+ _b.sent();
152
+ return [2 /*return*/, Promise.resolve()];
153
+ case 2: return [2 /*return*/, Promise.reject()];
154
+ }
155
+ });
156
+ }); });
157
+ };
158
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
159
+ var trucoshi;
160
+ return __generator(this, function (_a) {
161
+ trucoshi = (0, lib_1.Trucoshi)();
162
+ trucoshi.addPlayer("lukini", 0).setReady(true);
163
+ trucoshi.addPlayer("guada", 0).setReady(true);
164
+ trucoshi.addPlayer("denoph", 1).setReady(true);
165
+ trucoshi.addPlayer("juli", 1).setReady(true);
166
+ trucoshi
167
+ .startMatch()
168
+ .onTruco(function (play) { return __awaiter(void 0, void 0, void 0, function () {
169
+ return __generator(this, function (_a) {
170
+ switch (_a.label) {
171
+ case 0: return [4 /*yield*/, sayCommand(play, false)()];
172
+ case 1:
173
+ _a.sent();
174
+ return [2 /*return*/];
175
+ }
176
+ });
177
+ }); })
178
+ .onTurn(function (play) { return __awaiter(void 0, void 0, void 0, function () {
179
+ var name;
180
+ var _a;
181
+ return __generator(this, function (_b) {
182
+ switch (_b.label) {
183
+ case 0:
184
+ name = (_a = play.player) === null || _a === void 0 ? void 0 : _a.id.toUpperCase();
185
+ console.log("=== Mano ".concat(play.handIdx, " === Ronda ").concat(play.roundIdx, " === Turno de ").concat(name, " ==="));
186
+ play.teams.map(function (team, id) {
187
+ return console.log("=== Team ".concat(id, " = ").concat(team.points.malas, " malas ").concat(team.points.buenas, " buenas"));
188
+ });
189
+ console.log(play.rounds && play.rounds.length
190
+ ? play.rounds.map(function (round) {
191
+ return round.cards.length ? round.cards.map(function (c) { return [c.player.id, c.card]; }) : "";
192
+ })
193
+ : "");
194
+ return [4 /*yield*/, sayCommand(play, true)()];
195
+ case 1:
196
+ _b.sent();
197
+ return [2 /*return*/];
198
+ }
199
+ });
200
+ }); })
201
+ .onWinner(function (winner, teams) { return __awaiter(void 0, void 0, void 0, function () {
202
+ return __generator(this, function (_a) {
203
+ teams.map(function (t, i) {
204
+ return console.log("Equipo ".concat(i, ": ").concat(t.players.map(function (p) { return " ".concat(p.id); }), " === ").concat(t.points.malas, " malas ").concat(t.points.buenas, " buenas"));
205
+ });
206
+ console.log("\nEquipo Ganador:".concat(winner === null || winner === void 0 ? void 0 : winner.players.map(function (p) { return " ".concat(p.id); })));
145
207
  return [2 /*return*/];
146
- }
208
+ });
209
+ }); })
210
+ .begin();
211
+ return [2 /*return*/];
147
212
  });
148
213
  }); })();
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "trucoshi",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "main": "build/lib/trucoshi.js",
5
- "license": "GPL3",
5
+ "license": "GPL-3.0",
6
6
  "scripts": {
7
7
  "install": "yarn build",
8
8
  "dev": "nodemon",
9
- "test:autoplay": "yarn build && yarn run ts-node build/test/autoplay",
10
- "test:play": "yarn build && yarn run ts-node build/test/play",
9
+ "test:autoplay": "yarn run ts-node src/test/autoplay",
10
+ "test:play": "yarn run ts-node src/test/play",
11
+ "test:legacy": "yarn run ts-node src/test/legacy",
11
12
  "build": "yarn run rimraf ./build && yarn run tsc --project ."
12
13
  },
13
14
  "devDependencies": {
@@ -0,0 +1,25 @@
1
+ import { CARDS } from "../constants"
2
+ import { ICard, IDeck } from "../types"
3
+ import { shuffleArray } from "../utils"
4
+
5
+ export function Deck(): IDeck {
6
+ const deck: IDeck = {
7
+ cards: Object.keys(CARDS) as Array<ICard>,
8
+ usedCards: [],
9
+ takeCard() {
10
+ const card = deck.cards.shift() as ICard
11
+ deck.usedCards.push(card)
12
+ return card
13
+ },
14
+ shuffle() {
15
+ deck.cards = deck.cards.concat(deck.usedCards)
16
+ deck.usedCards = []
17
+ deck.cards = shuffleArray(deck.cards)
18
+ if (deck.cards.length !== 40) {
19
+ throw new Error("This is not good")
20
+ }
21
+ return deck
22
+ },
23
+ }
24
+ return deck
25
+ }
@@ -0,0 +1,207 @@
1
+ import {
2
+ EEnvidoCommand,
3
+ EHandState,
4
+ ESayCommand,
5
+ IDeck,
6
+ IHand,
7
+ IHandCommands,
8
+ IMatch,
9
+ } from "../types"
10
+ import { checkHandWinner } from "../utils"
11
+ import { PlayInstance } from "./Play"
12
+ import { Round } from "./Round"
13
+ import { Truco } from "./Truco"
14
+
15
+ export function Hand(match: IMatch, deck: IDeck, idx: number) {
16
+ match.teams.forEach((team) => {
17
+ team.players.forEach((player) => {
18
+ const playerHand = [deck.takeCard(), deck.takeCard(), deck.takeCard()]
19
+ player.setHand(playerHand)
20
+ player.enable()
21
+ // player.setHand(["5c", "4c", "6c"])
22
+ })
23
+ })
24
+
25
+ function* roundsGeneratorSequence() {
26
+ let currentRoundIdx = 0
27
+ let forehandTeamIdx = match.table.player(hand.turn).teamIdx as 0 | 1
28
+
29
+ while (currentRoundIdx < 3 && !hand.finished()) {
30
+ const round = Round(0)
31
+ hand.setCurrentRound(round)
32
+ hand.pushRound(round)
33
+
34
+ let previousRound = hand.rounds[currentRoundIdx - 1]
35
+
36
+ // Put previous round winner as forehand
37
+ if (previousRound && previousRound.winner && !previousRound.tie) {
38
+ const newTurn = match.table.getPlayerPosition(previousRound.winner.id)
39
+ if (newTurn !== -1) {
40
+ hand.setTurn(newTurn)
41
+ }
42
+ }
43
+
44
+ while (round.turn < match.table.players.length) {
45
+
46
+ while (hand.state === EHandState.WAITING_FOR_TRUCO_ANSWER) {
47
+ const { value } = hand.truco.getNextPlayer()
48
+ if (value && value.currentPlayer) {
49
+ console.log({ value: value.currentPlayer })
50
+ hand.setCurrentPlayer(value.currentPlayer)
51
+ yield hand
52
+ }
53
+ }
54
+
55
+ const player = match.table.player(hand.turn)
56
+ hand.setCurrentPlayer(player)
57
+ if (player.disabled) {
58
+ hand.setCurrentPlayer(null)
59
+ }
60
+
61
+ yield hand
62
+ }
63
+
64
+ if (match.teams[0].isTeamDisabled() && match.teams[1].isTeamDisabled()) {
65
+ hand.setState(EHandState.FINISHED)
66
+ break
67
+ }
68
+
69
+ let winnerTeamIdx = checkHandWinner(hand.rounds, forehandTeamIdx)
70
+
71
+ if (match.teams[0].isTeamDisabled()) {
72
+ winnerTeamIdx = 1
73
+ }
74
+ if (match.teams[1].isTeamDisabled()) {
75
+ winnerTeamIdx = 0
76
+ }
77
+
78
+ if (winnerTeamIdx !== null) {
79
+ hand.addPoints(winnerTeamIdx, hand.truco.state)
80
+ hand.setState(EHandState.FINISHED)
81
+ }
82
+
83
+ currentRoundIdx++
84
+ }
85
+ yield hand
86
+ }
87
+
88
+ const roundsGenerator = roundsGeneratorSequence()
89
+
90
+ const commands: IHandCommands = {
91
+ [ESayCommand.MAZO]: (player) => {
92
+ hand.disablePlayer(player)
93
+ },
94
+ [ESayCommand.TRUCO]: (player) => {
95
+ const { teamIdx } = hand.truco
96
+ if (teamIdx === null || teamIdx !== player.teamIdx) {
97
+ hand.setState(EHandState.WAITING_FOR_TRUCO_ANSWER)
98
+ hand.truco.sayTruco(player.teamIdx as 0 | 1, match.teams[Number(!player.teamIdx)].players)
99
+ }
100
+ },
101
+ [ESayCommand.QUIERO]: () => {
102
+ if (hand.state === EHandState.WAITING_FOR_TRUCO_ANSWER) {
103
+ hand.truco.setAnswer(true)
104
+ hand.setState(EHandState.WAITING_PLAY)
105
+ }
106
+ },
107
+ [ESayCommand.NO_QUIERO]: (player) => {
108
+ if (hand.state === EHandState.WAITING_FOR_TRUCO_ANSWER) {
109
+ hand.truco.setAnswer(false)
110
+ hand.setState(EHandState.WAITING_PLAY)
111
+ }
112
+ },
113
+ [ESayCommand.FLOR]: () => {},
114
+ [ESayCommand.CONTRAFLOR]: () => {},
115
+ [EEnvidoCommand.ENVIDO]: () => {},
116
+ [EEnvidoCommand.ENVIDO_ENVIDO]: () => {},
117
+ [EEnvidoCommand.REAL_ENVIDO]: () => {},
118
+ [EEnvidoCommand.FALTA_ENVIDO]: () => {},
119
+ }
120
+
121
+ const hand: IHand = {
122
+ idx,
123
+ turn: Number(match.table.forehandIdx),
124
+ state: EHandState.WAITING_PLAY,
125
+ rounds: [],
126
+ truco: Truco(),
127
+ envido: {
128
+ accept: 1,
129
+ decline: 2,
130
+ teamIdx: null,
131
+ },
132
+ points: [0, 0],
133
+ currentRound: null,
134
+ _currentPlayer: null,
135
+ set currentPlayer(player) {
136
+ hand._currentPlayer = player
137
+ },
138
+ get currentPlayer() {
139
+ if (hand.state === EHandState.WAITING_FOR_TRUCO_ANSWER) {
140
+ return hand.truco.currentPlayer
141
+ }
142
+ return hand._currentPlayer
143
+ },
144
+ commands,
145
+ play() {
146
+ return PlayInstance(hand, match.teams)
147
+ },
148
+ use(idx: number) {
149
+ const player = hand.currentPlayer
150
+ const round = hand.currentRound
151
+ if (!player || !round) {
152
+ return null
153
+ }
154
+
155
+ const card = player.useCard(idx)
156
+ if (card) {
157
+ hand.nextTurn()
158
+ return round.use({ player, card })
159
+ }
160
+
161
+ return null
162
+ },
163
+ nextTurn() {
164
+ if (hand.turn >= match.table.players.length - 1) {
165
+ hand.setTurn(0)
166
+ } else {
167
+ hand.setTurn(hand.turn + 1)
168
+ }
169
+
170
+ hand.currentRound?.nextTurn()
171
+ },
172
+ getNextPlayer() {
173
+ return roundsGenerator.next()
174
+ },
175
+ disablePlayer(player) {
176
+ match.teams[player.teamIdx].disable(player)
177
+ },
178
+ addPoints(team, points) {
179
+ hand.points[team] = hand.points[team] + points
180
+ },
181
+ pushRound(round) {
182
+ hand.rounds.push(round)
183
+ return round
184
+ },
185
+ setTurn(turn) {
186
+ hand.turn = turn
187
+ return match.table.player(hand.turn)
188
+ },
189
+ setCurrentRound(round) {
190
+ hand.currentRound = round
191
+ return hand.currentRound
192
+ },
193
+ setCurrentPlayer(player) {
194
+ hand._currentPlayer = player
195
+ return hand._currentPlayer
196
+ },
197
+ setState(state) {
198
+ hand.state = state
199
+ return hand.state
200
+ },
201
+ finished: () => {
202
+ return hand.state === EHandState.FINISHED
203
+ },
204
+ }
205
+
206
+ return hand
207
+ }
@@ -0,0 +1,79 @@
1
+ import { IHand, IMatch, ITable, ITeam } from "../types"
2
+ import { Deck } from "./Deck"
3
+ import { Hand } from "./Hand"
4
+
5
+ export function Match(table: ITable, teams: Array<ITeam> = [], matchPoint: number = 9): IMatch {
6
+ const deck = Deck().shuffle()
7
+
8
+ const size = teams[0].players.length
9
+
10
+ if (size !== teams[1].players.length) {
11
+ throw new Error("Team size mismatch")
12
+ }
13
+
14
+ function* handsGeneratorSequence() {
15
+ while (!match.winner) {
16
+ deck.shuffle()
17
+ const hand = match.setCurrentHand(Hand(match, deck, match.hands.length + 1)) as IHand
18
+ match.pushHand(hand)
19
+ while (!hand.finished()) {
20
+ const { value } = hand.getNextPlayer()
21
+ if (value && value.finished()) {
22
+ continue
23
+ }
24
+ match.setCurrentHand(value as IHand)
25
+ yield match
26
+ }
27
+
28
+ match.setCurrentHand(null)
29
+
30
+ const teams = match.addPoints(hand.points)
31
+ const winner = teams.find((team) => team.points.winner)
32
+
33
+ if (winner) {
34
+ match.setWinner(winner)
35
+ match.setCurrentHand(null)
36
+ break
37
+ }
38
+ match.table.nextTurn()
39
+ }
40
+ yield match
41
+ }
42
+
43
+ const handsGenerator = handsGeneratorSequence()
44
+
45
+ const match: IMatch = {
46
+ winner: null,
47
+ teams: teams as [ITeam, ITeam],
48
+ hands: [],
49
+ table,
50
+ currentHand: null,
51
+ play() {
52
+ match.getNextTurn()
53
+ if (!match.currentHand) {
54
+ return null
55
+ }
56
+ return match.currentHand.play()
57
+ },
58
+ addPoints(points) {
59
+ match.teams[0].addPoints(matchPoint, points[0])
60
+ match.teams[1].addPoints(matchPoint, points[1])
61
+ return match.teams
62
+ },
63
+ pushHand(hand) {
64
+ match.hands.push(hand)
65
+ },
66
+ setCurrentHand(hand) {
67
+ match.currentHand = hand
68
+ return match.currentHand
69
+ },
70
+ setWinner(winner) {
71
+ match.winner = winner
72
+ },
73
+ getNextTurn() {
74
+ return handsGenerator.next()
75
+ },
76
+ }
77
+
78
+ return match
79
+ }
@@ -0,0 +1,40 @@
1
+ import { EEnvidoCommand, EHandState, ESayCommand, IHand, IPlayInstance, ITeam } from "../types"
2
+
3
+ export function PlayInstance(hand: IHand, teams: [ITeam, ITeam]) {
4
+ const instance: IPlayInstance = {
5
+ state: hand.state,
6
+ teams,
7
+ truco: hand.truco,
8
+ envido: hand.envido,
9
+ handIdx: hand.idx,
10
+ roundIdx: hand.rounds.length,
11
+ player: hand.currentPlayer,
12
+ commands: [],
13
+ rounds: hand.rounds,
14
+ use(idx) {
15
+ return hand.use(idx)
16
+ },
17
+ say(command) {
18
+ if (!hand._currentPlayer || !instance.commands?.includes(command)) {
19
+ return null
20
+ }
21
+
22
+ hand.commands[command](hand._currentPlayer)
23
+
24
+ return command
25
+ },
26
+ }
27
+
28
+ instance.commands?.push(ESayCommand.MAZO)
29
+ instance.commands?.push(ESayCommand.TRUCO)
30
+
31
+ if (hand.rounds.length === 1) {
32
+ instance.commands?.push(EEnvidoCommand.ENVIDO)
33
+ }
34
+
35
+ if (hand.state === EHandState.WAITING_FOR_TRUCO_ANSWER) {
36
+ instance.commands = [ESayCommand.TRUCO, ESayCommand.QUIERO, ESayCommand.NO_QUIERO]
37
+ }
38
+
39
+ return instance
40
+ }
@@ -0,0 +1,37 @@
1
+ import { IPlayer } from "../types"
2
+
3
+ export function Player(id: string, teamIdx: number) {
4
+ const player: IPlayer = {
5
+ id,
6
+ teamIdx,
7
+ hand: [],
8
+ commands: [],
9
+ usedHand: [],
10
+ disabled: false,
11
+ ready: false,
12
+ enable() {
13
+ player.disabled = false
14
+ },
15
+ disable() {
16
+ player.disabled = true
17
+ },
18
+ setReady(ready) {
19
+ player.ready = ready
20
+ },
21
+ setHand(hand) {
22
+ player.hand = hand
23
+ player.usedHand = []
24
+ return hand
25
+ },
26
+ useCard(idx) {
27
+ if (player.hand[idx]) {
28
+ const card = player.hand.splice(idx, 1)[0]
29
+ player.usedHand.push(card)
30
+ return card
31
+ }
32
+ return null
33
+ },
34
+ }
35
+
36
+ return player
37
+ }
@@ -0,0 +1,30 @@
1
+ import { IRound } from "../types"
2
+ import { getCardValue } from "../utils"
3
+
4
+ export function Round(turn: number): IRound {
5
+ const round: IRound = {
6
+ turn,
7
+ highest: -1,
8
+ winner: null,
9
+ cards: [],
10
+ tie: false,
11
+ nextTurn() {
12
+ round.turn++
13
+ },
14
+ use({ card, player }) {
15
+ const value = getCardValue(card)
16
+ if (value === round.highest && player.teamIdx !== round.winner?.teamIdx) {
17
+ round.tie = true
18
+ }
19
+ if (value > round.highest) {
20
+ round.tie = false
21
+ round.highest = value
22
+ round.winner = player
23
+ }
24
+ round.cards.push({ card, player })
25
+ return card
26
+ },
27
+ }
28
+
29
+ return round
30
+ }