trucoshi 0.0.1 → 0.0.4

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 (55) hide show
  1. package/.prettierrc.json +4 -0
  2. package/LICENSE +674 -0
  3. package/README.md +36 -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 +175 -0
  8. package/build/lib/classes/Match.d.ts +2 -0
  9. package/build/lib/classes/Match.js +116 -0
  10. package/build/lib/classes/Play.d.ts +2 -0
  11. package/build/lib/classes/Play.js +45 -0
  12. package/build/lib/classes/Player.d.ts +2 -0
  13. package/build/lib/classes/Player.js +26 -0
  14. package/build/lib/classes/Round.d.ts +2 -0
  15. package/build/lib/classes/Round.js +29 -0
  16. package/build/lib/classes/Table.d.ts +2 -0
  17. package/build/lib/classes/Table.js +37 -0
  18. package/build/lib/classes/Team.d.ts +2 -0
  19. package/build/lib/classes/Team.js +34 -0
  20. package/build/lib/constants.d.ts +30 -28
  21. package/build/lib/constants.js +90 -12
  22. package/build/lib/index.d.ts +11 -0
  23. package/build/lib/index.js +88 -0
  24. package/build/lib/types.d.ts +75 -29
  25. package/build/lib/types.js +22 -12
  26. package/build/lib/utils.d.ts +3 -3
  27. package/build/lib/utils.js +29 -19
  28. package/build/server/index.js +13 -5
  29. package/build/server/types.d.ts +11 -0
  30. package/build/server/types.js +15 -0
  31. package/build/test/autoplay.js +43 -31
  32. package/build/test/play.js +127 -81
  33. package/package.json +9 -8
  34. package/src/lib/classes/Deck.ts +25 -0
  35. package/src/lib/classes/Hand.ts +151 -0
  36. package/src/lib/classes/Match.ts +80 -0
  37. package/src/lib/classes/Play.ts +48 -0
  38. package/src/lib/classes/Player.ts +25 -0
  39. package/src/lib/classes/Round.ts +26 -0
  40. package/src/lib/classes/Table.ts +37 -0
  41. package/src/lib/classes/Team.ts +34 -0
  42. package/src/lib/constants.ts +97 -11
  43. package/src/lib/index.ts +57 -0
  44. package/src/lib/types.ts +140 -80
  45. package/src/lib/utils.ts +70 -52
  46. package/src/server/index.ts +34 -22
  47. package/src/server/types.ts +12 -0
  48. package/src/test/autoplay.ts +47 -41
  49. package/src/test/play.ts +113 -70
  50. package/build/lib/trucoshi.d.ts +0 -10
  51. package/build/lib/trucoshi.js +0 -363
  52. package/build/test/legacy.d.ts +0 -1
  53. package/build/test/legacy.js +0 -146
  54. package/src/lib/trucoshi.ts +0 -342
  55. package/src/test/legacy.ts +0 -68
@@ -58,91 +58,137 @@ 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 types_1 = require("../lib/types");
74
+ var command = function (title, onLine) {
75
+ var promise = function () {
76
+ return new Promise(function (resolve) {
77
+ var rl = readline.createInterface(process.stdin, process.stdout);
78
+ rl.setPrompt(title);
79
+ rl.prompt();
80
+ rl.on("line", function (line) { return __awaiter(void 0, void 0, void 0, function () {
81
+ var e_1;
82
+ return __generator(this, function (_a) {
83
+ switch (_a.label) {
84
+ case 0:
85
+ _a.trys.push([0, 2, , 3]);
86
+ return [4 /*yield*/, onLine(line, function () { return rl.close(); })];
87
+ case 1:
88
+ _a.sent();
89
+ rl.close();
90
+ resolve();
91
+ return [3 /*break*/, 3];
92
+ case 2:
93
+ e_1 = _a.sent();
94
+ rl.close();
95
+ return [2 /*return*/, (function () { return __awaiter(void 0, void 0, void 0, function () {
96
+ return __generator(this, function (_a) {
97
+ switch (_a.label) {
98
+ case 0: return [4 /*yield*/, promise()];
99
+ case 1:
100
+ _a.sent();
101
+ resolve();
102
+ return [2 /*return*/];
116
103
  }
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
104
  });
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); })));
105
+ }); })()];
106
+ case 3: return [2 /*return*/];
107
+ }
108
+ });
109
+ }); });
110
+ });
111
+ };
112
+ return promise;
113
+ };
114
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
115
+ return __generator(this, function (_a) {
116
+ (0, lib_1.Trucoshi)(["lukini", "guada"], ["denoph", "juli"], 9)
117
+ .onTurn(function (play) { return __awaiter(void 0, void 0, void 0, function () {
118
+ var name, canPlay, sayCommand, playCommand;
119
+ var _a, _b, _d, _e, _f, _g;
120
+ return __generator(this, function (_h) {
121
+ switch (_h.label) {
122
+ case 0:
123
+ name = (_a = play.player) === null || _a === void 0 ? void 0 : _a.id.toUpperCase();
124
+ console.log("=== Mano ".concat(play.handIdx, " === Ronda ").concat(play.roundIdx, " === Turno de ").concat(name, " ==="));
125
+ play.teams.map(function (team, id) {
126
+ return console.log("=== Team ".concat(id, " = ").concat(team.points.malas, " malas ").concat(team.points.buenas, " buenas"));
127
+ });
128
+ canPlay = play.state === types_1.EHandState.WAITING_PLAY;
129
+ console.log(play.rounds && play.rounds.length
130
+ ? play.rounds.map(function (round) {
131
+ return round.cards.length ? round.cards.map(function (c) { return [c.player.id, c.card]; }) : "";
132
+ })
133
+ : "");
134
+ sayCommand = command("".concat((_b = play.player) === null || _b === void 0 ? void 0 : _b.id, " elije una accion [").concat(canPlay ? "0," : "").concat((_d = play.commands) === null || _d === void 0 ? void 0 : _d.map(function (_c, i) { return i + 1; }), "]: ").concat(canPlay
135
+ ? JSON.stringify(__spreadArray(["CARTA"], (play.commands || []), true))
136
+ : 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()];
150
+ case 1:
151
+ _b.sent();
152
+ return [2 /*return*/, Promise.resolve()];
153
+ case 2: return [2 /*return*/, Promise.reject()];
154
+ }
155
+ });
156
+ }); });
157
+ playCommand = command("".concat((_e = play.player) === null || _e === void 0 ? void 0 : _e.id, " elije una carta [").concat((_f = play.player) === null || _f === void 0 ? void 0 : _f.hand.map(function (_c, i) { return i + 1; }), "]: ").concat(JSON.stringify((_g = play.player) === null || _g === void 0 ? void 0 : _g.hand), "\n"), function (idx) { return __awaiter(void 0, void 0, void 0, function () {
158
+ var playedCard, handString;
159
+ var _a;
160
+ return __generator(this, function (_b) {
161
+ playedCard = play.use(Number(idx) - 1);
162
+ if (!playedCard) {
163
+ return [2 /*return*/, Promise.reject()];
164
+ }
165
+ handString = JSON.stringify((_a = play.player) === null || _a === void 0 ? void 0 : _a.hand);
166
+ console.log("\n".concat(handString, "\nUsing ").concat(playedCard));
167
+ console.log(play.rounds && play.rounds.length
168
+ ? play.rounds.map(function (round) {
169
+ return round.cards.length ? round.cards.map(function (c) { return [c.player.id, c.card]; }) : "";
170
+ })
171
+ : "");
172
+ return [2 /*return*/, Promise.resolve()];
173
+ });
174
+ }); });
175
+ return [4 /*yield*/, sayCommand()];
176
+ case 1:
177
+ _h.sent();
178
+ return [2 /*return*/];
179
+ }
180
+ });
181
+ }); })
182
+ .onWinner(function (winner, teams) { return __awaiter(void 0, void 0, void 0, function () {
183
+ return __generator(this, function (_a) {
184
+ teams.map(function (t, i) {
185
+ 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"));
186
+ });
187
+ console.log("\nEquipo Ganador:".concat(winner === null || winner === void 0 ? void 0 : winner.players.map(function (p) { return " ".concat(p.id); })));
145
188
  return [2 /*return*/];
146
- }
189
+ });
190
+ }); })
191
+ .start();
192
+ return [2 /*return*/];
147
193
  });
148
194
  }); })();
package/package.json CHANGED
@@ -1,23 +1,24 @@
1
1
  {
2
2
  "name": "trucoshi",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
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": {
14
15
  "@types/node": "^18.11.18",
15
- "nodemon": "^2.0.20",
16
+ "nodemon": "^2.0.20"
17
+ },
18
+ "dependencies": {
19
+ "socket.io": "^4.5.4",
16
20
  "rimraf": "^4.1.1",
17
21
  "ts-node": "^10.9.1",
18
22
  "typescript": "^4.9.4"
19
- },
20
- "dependencies": {
21
- "socket.io": "^4.5.4"
22
23
  }
23
24
  }
@@ -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,151 @@
1
+ import {
2
+ EEnvidoCommand,
3
+ EHandState,
4
+ ESayCommand,
5
+ IDeck,
6
+ IHand,
7
+ IHandCommands,
8
+ IMatch,
9
+ IPlayer,
10
+ } from "../types"
11
+ import { checkHandWinner } from "../utils"
12
+ import { PlayInstance } from "./Play"
13
+ import { Round } from "./Round"
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.setHand(["5c", "4c", "6c"])
21
+ })
22
+ })
23
+
24
+ function* roundsGeneratorSequence() {
25
+ let currentRoundIdx = 0
26
+ let forehandTeamIdx = match.table.player(hand.turn).teamIdx as 0 | 1
27
+
28
+ while (currentRoundIdx < 3 && !hand.finished()) {
29
+ let i = 0
30
+
31
+ const round = Round()
32
+ hand.setCurrentRound(round)
33
+ hand.pushRound(round)
34
+
35
+ let previousRound = hand.rounds[currentRoundIdx - 1]
36
+
37
+ // Put previous round winner as forehand
38
+ if (previousRound && previousRound.winner && !previousRound.tie) {
39
+ const newTurn = match.table.getPlayerPosition(previousRound.winner.id)
40
+ if (newTurn !== -1) {
41
+ hand.setTurn(newTurn)
42
+ }
43
+ }
44
+
45
+ while (i < match.table.players.length) {
46
+ const player = match.table.player(hand.turn)
47
+ hand.setCurrentPlayer(player)
48
+ if (hand.disabledPlayerIds.includes(player.id)) {
49
+ hand.setCurrentPlayer(null)
50
+ }
51
+
52
+ if (hand.turn >= match.table.players.length - 1) {
53
+ hand.setTurn(0)
54
+ } else {
55
+ hand.setTurn(hand.turn + 1)
56
+ }
57
+
58
+ i++
59
+
60
+ yield hand
61
+ }
62
+
63
+ const teamIdx = checkHandWinner(hand.rounds, forehandTeamIdx, hand.disabledPlayerIds, match.teams)
64
+
65
+ if (teamIdx !== null) {
66
+ hand.addPoints(teamIdx, hand.truco.state)
67
+ hand.setState(EHandState.FINISHED)
68
+ }
69
+ currentRoundIdx++
70
+ }
71
+ yield hand
72
+ }
73
+
74
+ const roundsGenerator = roundsGeneratorSequence()
75
+
76
+ const commands: IHandCommands = {
77
+ [ESayCommand.MAZO]: (player) => {
78
+ hand.disablePlayer(player)
79
+ },
80
+ [ESayCommand.TRUCO]: (player) => {
81
+ const { teamIdx } = hand.truco
82
+ if (teamIdx === null || teamIdx !== player.teamIdx) {
83
+ hand.setState(EHandState.WAITING_FOR_TRUCO_ANSWER)
84
+ }
85
+ },
86
+ [ESayCommand.FLOR]: () => {},
87
+ [ESayCommand.CONTRAFLOR]: () => {},
88
+ [EEnvidoCommand.ENVIDO]: () => {},
89
+ [EEnvidoCommand.ENVIDO_ENVIDO]: () => {},
90
+ [EEnvidoCommand.REAL_ENVIDO]: () => {},
91
+ [EEnvidoCommand.FALTA_ENVIDO]: () => {},
92
+ }
93
+
94
+ const hand: IHand = {
95
+ idx,
96
+ turn: Number(match.table.forehandIdx),
97
+ state: EHandState.WAITING_PLAY,
98
+ rounds: [],
99
+ truco: {
100
+ state: 1,
101
+ teamIdx: null,
102
+ },
103
+ envido: {
104
+ accept: 1,
105
+ decline: 2,
106
+ teamIdx: null,
107
+ },
108
+ points: [0, 0],
109
+ disabledPlayerIds: [],
110
+ currentRound: null,
111
+ currentPlayer: null,
112
+ commands,
113
+ play() {
114
+ return PlayInstance(hand, match.teams)
115
+ },
116
+ getNextPlayer() {
117
+ return roundsGenerator.next()
118
+ },
119
+ disablePlayer(player) {
120
+ hand.disabledPlayerIds.push(player.id)
121
+ },
122
+ addPoints(team, points) {
123
+ hand.points[team] = hand.points[team] + points
124
+ },
125
+ pushRound(round) {
126
+ hand.rounds.push(round)
127
+ return round
128
+ },
129
+ setTurn(turn) {
130
+ hand.turn = turn
131
+ return match.table.player(hand.turn)
132
+ },
133
+ setCurrentRound(round) {
134
+ hand.currentRound = round
135
+ return hand.currentRound
136
+ },
137
+ setCurrentPlayer(player) {
138
+ hand.currentPlayer = player
139
+ return hand.currentPlayer
140
+ },
141
+ setState(state) {
142
+ hand.state = state
143
+ return hand.state
144
+ },
145
+ finished: () => {
146
+ return hand.state === EHandState.FINISHED
147
+ },
148
+ }
149
+
150
+ return hand
151
+ }
@@ -0,0 +1,80 @@
1
+ import { IHand, IMatch, ITeam } from "../types"
2
+ import { Deck } from "./Deck"
3
+ import { Hand } from "./Hand"
4
+ import { Table } from "./Table"
5
+
6
+ export function Match(teams: Array<ITeam> = [], matchPoint: number = 9): IMatch {
7
+ const deck = Deck().shuffle()
8
+
9
+ const size = teams[0].players.length
10
+
11
+ if (size !== teams[1].players.length) {
12
+ throw new Error("Team size mismatch")
13
+ }
14
+
15
+ function* handsGeneratorSequence() {
16
+ while (!match.winner) {
17
+ deck.shuffle()
18
+ const hand = match.setCurrentHand(Hand(match, deck, match.hands.length + 1)) as IHand
19
+ match.pushHand(hand)
20
+ while (!hand.finished()) {
21
+ const { value } = hand.getNextPlayer()
22
+ if (value && value.finished()) {
23
+ continue
24
+ }
25
+ match.setCurrentHand(value as IHand)
26
+ yield match
27
+ }
28
+
29
+ match.setCurrentHand(null)
30
+
31
+ const teams = match.addPoints(hand.points)
32
+ const winner = teams.find((team) => team.points.winner)
33
+
34
+ if (winner) {
35
+ match.setWinner(winner)
36
+ match.setCurrentHand(null)
37
+ break
38
+ }
39
+ match.table.nextTurn()
40
+ }
41
+ yield match
42
+ }
43
+
44
+ const handsGenerator = handsGeneratorSequence()
45
+
46
+ const match: IMatch = {
47
+ winner: null,
48
+ teams: teams as [ITeam, ITeam],
49
+ hands: [],
50
+ table: Table(teams, size),
51
+ currentHand: null,
52
+ play() {
53
+ match.getNextTurn()
54
+ if (!match.currentHand) {
55
+ return null
56
+ }
57
+ return match.currentHand.play()
58
+ },
59
+ addPoints(points) {
60
+ match.teams[0].addPoints(matchPoint, points[0])
61
+ match.teams[1].addPoints(matchPoint, points[1])
62
+ return match.teams
63
+ },
64
+ pushHand(hand) {
65
+ match.hands.push(hand)
66
+ },
67
+ setCurrentHand(hand) {
68
+ match.currentHand = hand
69
+ return match.currentHand
70
+ },
71
+ setWinner(winner) {
72
+ match.winner = winner
73
+ },
74
+ getNextTurn() {
75
+ return handsGenerator.next()
76
+ },
77
+ }
78
+
79
+ return match
80
+ }
@@ -0,0 +1,48 @@
1
+ import { EEnvidoCommand, ESayCommand, IHand, IPlayInstance, ITeam } from "../types"
2
+
3
+ export function PlayInstance(hand: IHand, teams: [ITeam, ITeam]) {
4
+
5
+ const instance: IPlayInstance = {
6
+ state: hand.state,
7
+ teams,
8
+ truco: hand.truco,
9
+ envido: hand.envido,
10
+ handIdx: hand.idx,
11
+ roundIdx: hand.rounds.length,
12
+ player: hand.currentPlayer,
13
+ commands: [],
14
+ rounds: hand.rounds,
15
+ use(idx) {
16
+ const player = hand.currentPlayer
17
+ const round = hand.currentRound
18
+ if (!player || !round) {
19
+ return null
20
+ }
21
+
22
+ const card = player.useCard(idx)
23
+ if (card) {
24
+ return round.use({ player, card })
25
+ }
26
+
27
+ return null
28
+ },
29
+ say(command) {
30
+ if (!hand.currentPlayer || !instance.commands?.includes(command)) {
31
+ return null
32
+ }
33
+
34
+ hand.commands[command](hand.currentPlayer)
35
+
36
+ return command
37
+ },
38
+ }
39
+
40
+ instance.commands?.push(ESayCommand.MAZO)
41
+ instance.commands?.push(ESayCommand.TRUCO)
42
+
43
+ if (hand.rounds.length === 1) {
44
+ instance.commands?.push(EEnvidoCommand.ENVIDO)
45
+ }
46
+
47
+ return instance
48
+ }
@@ -0,0 +1,25 @@
1
+ import { ICard, IPlayer } from "../types"
2
+
3
+ export function Player(id: string, teamIdx: number) {
4
+ const player: IPlayer = {
5
+ id,
6
+ teamIdx,
7
+ hand: [],
8
+ usedHand: [],
9
+ setHand(hand) {
10
+ player.hand = hand
11
+ player.usedHand = []
12
+ return hand
13
+ },
14
+ useCard(idx) {
15
+ if (player.hand[idx]) {
16
+ const card = player.hand.splice(idx, 1)[0]
17
+ player.usedHand.push(card)
18
+ return card
19
+ }
20
+ return null
21
+ },
22
+ }
23
+
24
+ return player
25
+ }
@@ -0,0 +1,26 @@
1
+ import { IRound } from "../types"
2
+ import { getCardValue } from "../utils"
3
+
4
+ export function Round(): IRound {
5
+ const round: IRound = {
6
+ highest: -1,
7
+ winner: null,
8
+ cards: [],
9
+ tie: false,
10
+ use({ card, player }) {
11
+ const value = getCardValue(card)
12
+ if (value === round.highest && player.teamIdx !== round.winner?.teamIdx) {
13
+ round.tie = true
14
+ }
15
+ if (value > round.highest) {
16
+ round.tie = false
17
+ round.highest = value
18
+ round.winner = player
19
+ }
20
+ round.cards.push({ card, player })
21
+ return card
22
+ },
23
+ }
24
+
25
+ return round
26
+ }
@@ -0,0 +1,37 @@
1
+ import { ITable, ITeam } from "../types"
2
+
3
+ export function Table(teams: Array<ITeam>, size: number): ITable {
4
+ const table: ITable = {
5
+ players: [],
6
+ cards: [],
7
+ forehandIdx: 0,
8
+ nextTurn() {
9
+ if (table.forehandIdx < size * 2 - 1) {
10
+ table.forehandIdx++
11
+ } else {
12
+ table.forehandIdx = 0
13
+ }
14
+ return table.player()
15
+ },
16
+ getPlayerPosition(id) {
17
+ return table.players.findIndex((p) => p.id === id)
18
+ },
19
+ player(idx) {
20
+ if (idx !== undefined) {
21
+ return table.players[idx]
22
+ }
23
+ return table.players[table.forehandIdx]
24
+ },
25
+ }
26
+
27
+ if (teams[0].players.length != size || teams[1].players.length != size) {
28
+ throw new Error("Unexpected team size")
29
+ }
30
+
31
+ for (let i = 0; i < size; i++) {
32
+ table.players.push(teams[0].players[i])
33
+ table.players.push(teams[1].players[i])
34
+ }
35
+
36
+ return table
37
+ }