Compare commits

...

1043 Commits
0.2.0b ... main

Author SHA1 Message Date
Alberto Xamin
4d2a222f93
fix replacement 2024-12-30 17:29:30 +01:00
Alberto Xamin
61fa295f8d
Update docker-image.yml 2024-12-30 17:23:51 +01:00
Alberto Xamin
0a2bbce2da
Update docker-image.yml 2024-12-30 17:13:44 +01:00
Alberto Xamin
6bc10f1bff
Update docker-image.yml 2024-12-30 16:16:12 +01:00
Alberto Xamin
123e569010
speedup image compile 2024-12-30 16:10:12 +01:00
Alberto Xamin
b45d04bf30
allow keeping owner 2024-10-29 16:37:04 +00:00
Alberto Xamin
b2b9eac1cd
really fix bandidos 2024-10-29 15:25:31 +00:00
Alberto Xamin
345e04ef06
fix big spencer 2024-10-22 15:43:24 +01:00
Alberto Xamin
2af8e5ec54
fxi bandidos 2024-10-22 15:41:16 +01:00
Alberto Xamin
3642c0dbb5
fix blood brothers desc 2024-10-22 15:37:25 +01:00
Alberto Xamin
86441f92c8
fix tornado 2024-10-22 15:36:44 +01:00
Alberto Xamin
df65a97225
fix disabled cursor 2024-07-03 10:12:14 +01:00
Alberto Xamin
d2bddb9eda
fix broken card descriptions 2024-06-26 14:08:17 +03:00
Alberto Xamin
dd84d91b43
Merge pull request #507 from albertoxamin/train-robbery
add better info screen
2024-06-15 18:59:41 +03:00
Alberto Xamin
bae85b7508
add better info screen 2024-06-15 18:58:06 +03:00
Alberto Xamin
5d0e46f205
Merge pull request #505 from albertoxamin/train-robbery
Add Train robbery expansion
2024-06-14 18:16:09 +03:00
Alberto Xamin
7dab001bb0
fix duello 2024-06-14 18:11:20 +03:00
Alberto Xamin
a474dfbc24
also add new animations 2024-06-14 18:09:24 +03:00
Alberto Xamin
c171739db8
add circus wagon 2024-06-13 15:57:13 +03:00
Alberto Xamin
344b7cc043
add cattletruck 2024-06-13 15:32:52 +03:00
Alberto Xamin
db98f88db0
add localized str 2024-06-13 14:19:15 +03:00
Alberto Xamin
c2b123b482
make it for trains aswell 2024-06-10 17:28:37 +01:00
Alberto Xamin
da7e4834b7
refactor pending action 2024-06-10 17:22:30 +01:00
Alberto Xamin
399645de27
add express car, lumber, mail 2024-06-10 17:02:47 +01:00
Alberto Xamin
beff8151c2
add train robbery cards to help 2024-06-10 14:25:05 +01:00
Alberto Xamin
b72319f335
fix potential bugs 2024-06-10 14:04:06 +01:00
Alberto Xamin
64feee23ae
fix lint 2024-06-08 17:51:38 +01:00
Alberto Xamin
0691780472
fix recursive import 2024-06-08 17:48:02 +01:00
Alberto Xamin
3707b24f8c wip 2024-06-08 17:34:49 +01:00
Alberto Xamin
9d5ac5b166 stations and train info 2024-06-08 17:34:49 +01:00
Alberto Xamin
f716a96334 buy trains 2024-06-08 17:34:49 +01:00
Alberto Xamin
a6029cdb0d tab completion 2024-06-08 17:34:49 +01:00
Alberto Xamin
14534997e8 progress 2024-06-08 17:34:49 +01:00
Alberto Xamin
1ee92afb9a add trains 2024-06-08 17:34:49 +01:00
Alberto Xamin
9e89092090 stations in the deck 2024-06-08 17:34:49 +01:00
Alberto Xamin
ca74f692ec train robbery deck display 2024-06-08 17:34:49 +01:00
Alberto Xamin
9bc1922e76
allow tequila to be played on self always 2024-06-08 15:36:34 +01:00
Alberto Xamin
b4d04d081f
be sure mira does -2 2024-06-08 15:30:59 +01:00
Alberto Xamin
ad5c10249c
Update README.md 2024-06-03 09:10:24 +01:00
Alberto Xamin
689725fe5c
fix ritorno di fiamma con roulette russa 2024-06-02 16:27:32 +01:00
Alberto Xamin
e08c7162a1
fix Mira 2024-06-02 16:24:37 +01:00
Alberto Xamin
72dc942901
fix miniera abbandonata 2024-06-02 16:15:48 +01:00
Alberto Xamin
c9df3d0b78
update cz translation 2024-05-28 10:13:16 +01:00
Alberto Xamin
7071e85f1b
Merge pull request #496 from albertoxamin/dependabot/npm_and_yarn/frontend/vite-4.5.3
Bump vite from 4.5.2 to 4.5.3 in /frontend
2024-05-26 20:06:26 +01:00
Alberto Xamin
1a839db4c8
Merge pull request #497 from albertoxamin/dependabot/pip/backend/eventlet-0.35.2
Bump eventlet from 0.33.3 to 0.35.2 in /backend
2024-05-26 20:06:13 +01:00
Alberto Xamin
3c5300e5da
fix sventagliata 2024-05-26 20:04:46 +01:00
Alberto Xamin
ade95b4818
Merge pull request #500 from albertoxamin/dependabot/npm_and_yarn/frontend/ejs-3.1.10
Bump ejs from 3.1.9 to 3.1.10 in /frontend
2024-05-21 13:46:37 +01:00
Alberto Xamin
763bd10b7c
Merge pull request #502 from albertoxamin/dependabot/pip/backend/requests-2.32.0
Bump requests from 2.31.0 to 2.32.0 in /backend
2024-05-21 13:46:23 +01:00
dependabot[bot]
1f57d1a700
---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 08:01:34 +00:00
Alberto Xamin
6aa3d6508f
add russian localization 2024-05-17 16:28:52 +01:00
Alberto Xamin
6b178d952a
add Spanish translation 2024-05-17 16:19:42 +01:00
Alberto Xamin
3252fdbf34
Add French language 2024-05-17 12:40:28 +01:00
Alberto Xamin
424d88e7b8
Update index.js 2024-05-16 22:33:40 +01:00
Alberto Xamin
7a793d902f
Create fr.json 2024-05-16 22:33:13 +01:00
dependabot[bot]
bd3c666703
Bump ejs from 3.1.9 to 3.1.10 in /frontend
Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-02 17:32:42 +00:00
dependabot[bot]
e6dc40bc57
Bump eventlet from 0.33.3 to 0.35.2 in /backend
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.33.3 to 0.35.2.
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.33.3...v0.35.2)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-12 21:53:39 +00:00
dependabot[bot]
359089c4c6
Bump vite from 4.5.2 to 4.5.3 in /frontend
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.5.2 to 4.5.3.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v4.5.3/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.5.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-04 01:53:56 +00:00
Alberto Xamin
ae36bbcec6
Merge pull request #471 from albertoxamin/dependabot/pip/backend/requests-2.31.0
Bump requests from 2.28.2 to 2.31.0 in /backend
2024-03-25 11:16:00 +00:00
Alberto Xamin
442e58effd
update npm packages 2024-02-27 10:51:48 +00:00
Alberto Xamin
badd8ebbf6
update npm lock file 2024-02-23 11:19:29 +00:00
Alberto Xamin
73c5b1573a
fix outdated docker build 2024-02-23 11:09:43 +00:00
Alberto Xamin
4eb1a82ab7
expire and remove secrets 2024-02-23 10:45:52 +00:00
dependabot[bot]
6995714835
Bump requests from 2.28.2 to 2.31.0 in /backend
Bumps [requests](https://github.com/psf/requests) from 2.28.2 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.2...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-23 05:53:48 +00:00
Alberto Xamin
2ddf18b8c0
user rng instead of random 2023-04-18 19:58:48 +01:00
Alberto Xamin
06069462ae
fix gary looter and big spencer 2023-04-18 19:52:18 +01:00
Alberto Xamin
c0dc2b799b
better visibility 2023-04-15 12:20:59 +01:00
Alberto Xamin
8a5e25385f
small readability updates 2023-04-15 11:19:21 +01:00
Alberto Xamin
9ea0a49c2e
fix flint westwood 2023-04-10 14:24:29 +01:00
Alberto Xamin
674a25bcf3
more details to chat 2023-04-10 14:16:13 +01:00
Alberto Xamin
6b233b652d
fix manette 2023-04-10 10:33:59 +01:00
Alberto Xamin
980774e51e
fix some animations 2023-04-10 00:56:53 +01:00
Alberto Xamin
25f5f5062e
add some effects on some actions 2023-04-09 21:08:14 +01:00
Alberto Xamin
95ca45b059
add suggest expansion 2023-04-09 20:45:04 +01:00
Alberto Xamin
ad1db9e0dc
fix broken password login 2023-04-09 19:46:51 +01:00
Alberto Xamin
340c86b5db
fix username renaming 2023-04-09 12:22:42 +01:00
Alberto Xamin
bda273849b
add option to set characters to distribute 2023-04-09 12:10:06 +01:00
Alberto Xamin
2501b96185
minor ui improvements 2023-04-09 11:43:06 +01:00
Alberto Xamin
cd16c9022f
shariff health yellow 2023-04-09 11:16:49 +01:00
Alberto Xamin
55c90ddd56
add gary looter 2023-04-09 11:05:33 +01:00
Alberto Xamin
a5a6e2d8b9
localize en cards 2023-04-09 10:49:26 +01:00
Alberto Xamin
475972bf05
add event desc to chat 2023-04-09 10:44:22 +01:00
Alberto Xamin
c81a806a6b
fix regolamento di conti 2023-04-09 10:24:44 +01:00
Alberto Xamin
1ebc4b4bd0
enable heatmaps ddog 2023-04-09 10:16:02 +01:00
Alberto Xamin
6c611aec0b
no double prigione 2023-04-04 16:41:36 +01:00
Alberto Xamin
f3f515318a
new wild-west-show css 2023-04-02 23:19:54 +01:00
Alberto Xamin
a936f44099
add Lee Van Kliff 2023-04-02 22:36:26 +01:00
Alberto Xamin
744bc44950
card refactor 2023-04-02 17:34:31 +01:00
Alberto Xamin
21b7c261bf
rename bots 2023-04-02 17:21:11 +01:00
Alberto Xamin
7692c7818f
add henry block 2023-04-02 17:05:49 +01:00
Alberto Xamin
0d960390be
fix bot overusing self panico 2023-04-02 16:38:30 +01:00
Alberto Xamin
ba6d8ddecb
fix mira for bots 2023-04-02 15:09:25 +01:00
Alberto Xamin
72bb52d037
fix Lemat 2023-04-02 14:56:52 +01:00
Alberto Xamin
cadabeb5f4
characters refactor 2023-04-02 14:37:14 +01:00
Alberto Xamin
c76cdc4fb1
add click on the card text 2023-04-02 14:24:26 +01:00
Alberto Xamin
e3b168ff57
card event refactoring and moved wild-west-show to its own pile 2023-04-02 13:47:08 +01:00
Alberto Xamin
f56120d44e
show wild west show cards in help screen 2023-04-01 08:38:58 +02:00
Alberto Xamin
4e0839350b
Merge pull request #456 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-9.10.0
Bump eslint-plugin-vue from 9.9.0 to 9.10.0 in /frontend
2023-03-28 19:05:19 +02:00
Alberto Xamin
543c08a865
Merge pull request #457 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.36.0
Bump @datadog/browser-rum from 4.35.0 to 4.36.0 in /frontend
2023-03-28 19:05:06 +02:00
Alberto Xamin
2bcb4b4ff6
Merge pull request #458 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001470
Bump caniuse-lite from 1.0.30001469 to 1.0.30001470 in /frontend
2023-03-28 19:04:58 +02:00
dependabot[bot]
e13883663c
Bump caniuse-lite from 1.0.30001469 to 1.0.30001470 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001469 to 1.0.30001470.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001469...1.0.30001470)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 05:02:32 +00:00
dependabot[bot]
32cb76d155
Bump @datadog/browser-rum from 4.35.0 to 4.36.0 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.35.0 to 4.36.0.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.36.0/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 05:02:18 +00:00
dependabot[bot]
8d3f4cfdf5
Bump eslint-plugin-vue from 9.9.0 to 9.10.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 9.9.0 to 9.10.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v9.9.0...v9.10.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-24 05:01:59 +00:00
dependabot[bot]
246125691a Bump vite-plugin-pwa from 0.14.5 to 0.14.6 in /frontend
Bumps [vite-plugin-pwa](https://github.com/antfu/vite-plugin-pwa) from 0.14.5 to 0.14.6.
- [Release notes](https://github.com/antfu/vite-plugin-pwa/releases)
- [Commits](https://github.com/antfu/vite-plugin-pwa/compare/v0.14.5...v0.14.6)

---
updated-dependencies:
- dependency-name: vite-plugin-pwa
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 23:18:45 +01:00
dependabot[bot]
8eb5b334a1 Bump vite from 4.1.4 to 4.2.1 in /frontend
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.1.4 to 4.2.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.2.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 23:03:02 +01:00
dependabot[bot]
bb3b66a182 Bump eslint from 8.35.0 to 8.36.0 in /frontend
Bumps [eslint](https://github.com/eslint/eslint) from 8.35.0 to 8.36.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.35.0...v8.36.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 23:02:58 +01:00
dependabot[bot]
b47ff20624 Bump datadog from 0.44.0 to 0.45.0 in /backend
Bumps [datadog](https://github.com/DataDog/datadogpy) from 0.44.0 to 0.45.0.
- [Release notes](https://github.com/DataDog/datadogpy/releases)
- [Changelog](https://github.com/DataDog/datadogpy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/datadogpy/compare/v0.44.0...v0.45.0)

---
updated-dependencies:
- dependency-name: datadog
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 23:02:53 +01:00
dependabot[bot]
302e131cde Bump python-socketio from 5.7.2 to 5.8.0 in /backend
Bumps [python-socketio](https://github.com/miguelgrinberg/python-socketio) from 5.7.2 to 5.8.0.
- [Release notes](https://github.com/miguelgrinberg/python-socketio/releases)
- [Changelog](https://github.com/miguelgrinberg/python-socketio/blob/main/CHANGES.md)
- [Commits](https://github.com/miguelgrinberg/python-socketio/compare/v5.7.2...v5.8.0)

---
updated-dependencies:
- dependency-name: python-socketio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 23:02:47 +01:00
dependabot[bot]
19e7d1f005 Bump caniuse-lite from 1.0.30001462 to 1.0.30001469 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001462 to 1.0.30001469.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001462...1.0.30001469)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 23:02:41 +01:00
dependabot[bot]
98f65aaf76 Bump vite-plugin-pwa from 0.14.4 to 0.14.5 in /frontend
Bumps [vite-plugin-pwa](https://github.com/antfu/vite-plugin-pwa) from 0.14.4 to 0.14.5.
- [Release notes](https://github.com/antfu/vite-plugin-pwa/releases)
- [Commits](https://github.com/antfu/vite-plugin-pwa/compare/v0.14.4...v0.14.5)

---
updated-dependencies:
- dependency-name: vite-plugin-pwa
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-23 23:02:37 +01:00
Alberto Xamin
5186fd2a8c
add translation of base game 2023-03-12 12:24:18 +00:00
Alberto Xamin
0bf2354605
add localizations 2023-03-12 12:03:31 +00:00
Alberto Xamin
d98c7de4b9
Merge branch 'wild-west-show' into dev 2023-03-12 11:44:42 +00:00
Alberto Xamin
555e48a10a
allow for alpha status 2023-03-12 11:44:09 +00:00
Alberto Xamin
d3a056cc6a
add terenkill and youlgrinner 2023-03-11 22:51:34 +02:00
dependabot[bot]
cdab162c06 Bump pytest from 7.2.1 to 7.2.2 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.1 to 7.2.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.2.1...7.2.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 10:17:54 +01:00
dependabot[bot]
33b1fd205e Bump @datadog/browser-rum from 4.34.2 to 4.35.0 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.34.2 to 4.35.0.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.35.0/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 10:17:45 +01:00
dependabot[bot]
03225b234a Bump caniuse-lite from 1.0.30001458 to 1.0.30001462 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001458 to 1.0.30001462.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001458...1.0.30001462)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 10:17:34 +01:00
Giulio
e69f214959 Merge branch 'main' into dev 2023-03-09 10:13:06 +01:00
Alberto Xamin
e4f9cfc886
fix johnpain, bigspencer and tests 2023-03-05 19:49:34 +00:00
Alberto Xamin
499763ffca
add john pain 2023-03-05 18:30:05 +00:00
Alberto Xamin
8f645cf82a
add bigspencer 2023-03-05 18:22:15 +00:00
Alberto Xamin
3b568c987f
add Lady Rosa del Texas 2023-03-05 18:08:01 +00:00
Alberto Xamin
e33c2c3c48
add RegolamentoDiConti 2023-03-05 17:57:31 +00:00
Alberto Xamin
47a099d624
add wild-west-show endgame 2023-03-05 17:46:26 +00:00
Alberto Xamin
9f5d037437
add miss suzanna 2023-03-05 17:31:23 +00:00
Alberto Xamin
9598a6f811
add Sacagaway 2023-03-05 17:14:52 +00:00
Alberto Xamin
5811821ccf
add tests 2023-03-05 16:49:52 +00:00
Alberto Xamin
1f28c9b715
Merge pull request #430 from albertoxamin/dependabot/pip/backend/dev/discord-webhook-1.1.0
Bump discord-webhook from 0.15.0 to 1.1.0 in /backend
2023-03-01 16:01:51 +01:00
Alberto Xamin
cab83b45a8
Merge pull request #436 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vite-4.1.4
Bump vite from 4.1.1 to 4.1.4 in /frontend
2023-03-01 16:01:35 +01:00
Alberto Xamin
01de0beb55
Merge pull request #437 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001458
Bump caniuse-lite from 1.0.30001451 to 1.0.30001458 in /frontend
2023-03-01 16:01:16 +01:00
Alberto Xamin
31becfdf70
Merge pull request #438 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-8.35.0
Bump eslint from 8.34.0 to 8.35.0 in /frontend
2023-03-01 16:01:03 +01:00
Alberto Xamin
8bd293fcbf
Merge pull request #439 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.34.2
Bump @datadog/browser-rum from 4.34.0 to 4.34.2 in /frontend
2023-03-01 16:00:39 +01:00
dependabot[bot]
572941c4a1
Bump @datadog/browser-rum from 4.34.0 to 4.34.2 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.34.0 to 4.34.2.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.34.2/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-28 05:00:54 +00:00
dependabot[bot]
b61a93e201
Bump eslint from 8.34.0 to 8.35.0 in /frontend
Bumps [eslint](https://github.com/eslint/eslint) from 8.34.0 to 8.35.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.34.0...v8.35.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 05:10:39 +00:00
dependabot[bot]
794127a4f3
Bump caniuse-lite from 1.0.30001451 to 1.0.30001458 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001451 to 1.0.30001458.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001451...1.0.30001458)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 05:08:52 +00:00
Alberto Xamin
c4d23b6e37 add elena zontero 2023-02-26 16:39:36 +00:00
Alberto Xamin
d089cce48d add camposanto DarlingValentine 2023-02-26 16:14:56 +00:00
Annalisa Xamin
e68be77edc add choose_flint_special localization 2023-02-26 10:55:37 +00:00
Annalisa Xamin
d1bd07c717 add Flint Westwood 2023-02-26 10:54:58 +00:00
Annalisa Xamin
035fbb161d register expansion 2023-02-26 10:54:58 +00:00
Annalisa Xamin
dd2b7be199 add cards definitions 2023-02-26 10:54:58 +00:00
dependabot[bot]
60abb38cd5
Bump vite from 4.1.1 to 4.1.4 in /frontend
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.1.1 to 4.1.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.1.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-22 04:19:59 +00:00
Alberto Xamin
aed05b5439 fix deck layout issues 2023-02-20 20:52:19 +00:00
Alberto Xamin
5d25e8708e hopefully fix again broken service worker 2023-02-19 12:12:31 +00:00
Alberto Xamin
bb7f1a7157 replace checkbox for expansions 2023-02-19 11:24:08 +00:00
Alberto Xamin
c269c950e7 add emojis to lobbies 2023-02-18 17:35:16 +00:00
dependabot[bot]
d08ff81c59
Bump discord-webhook from 0.15.0 to 1.1.0 in /backend
Bumps [discord-webhook](https://github.com/lovvskillz/python-discord-webhook) from 0.15.0 to 1.1.0.
- [Release notes](https://github.com/lovvskillz/python-discord-webhook/releases)
- [Changelog](https://github.com/lovvskillz/python-discord-webhook/blob/master/CHANGES.md)
- [Commits](https://github.com/lovvskillz/python-discord-webhook/compare/0.15.0...1.1.0)

---
updated-dependencies:
- dependency-name: discord-webhook
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-16 04:59:01 +00:00
dependabot[bot]
276b52ffd1 Bump certifi from 2021.10.8 to 2022.12.7 in /backend
Bumps [certifi](https://github.com/certifi/python-certifi) from 2021.10.8 to 2022.12.7.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/compare/2021.10.08...2022.12.07)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 09:52:48 +01:00
dependabot[bot]
8df9718cca
Bump vite-plugin-pwa from 0.14.3 to 0.14.4 in /frontend
Bumps [vite-plugin-pwa](https://github.com/antfu/vite-plugin-pwa) from 0.14.3 to 0.14.4.
- [Release notes](https://github.com/antfu/vite-plugin-pwa/releases)
- [Commits](https://github.com/antfu/vite-plugin-pwa/compare/v0.14.3...v0.14.4)

---
updated-dependencies:
- dependency-name: vite-plugin-pwa
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 05:04:48 +00:00
dependabot[bot]
161d01054a
Bump eslint from 8.33.0 to 8.34.0 in /frontend
Bumps [eslint](https://github.com/eslint/eslint) from 8.33.0 to 8.34.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.33.0...v8.34.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-10 22:46:58 +00:00
Giulio
d0fdf3fe7e Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/json5-2.2.3' into dev 2023-02-10 23:23:59 +01:00
GM
41e694d87b fix static files 2023-02-10 22:11:02 +00:00
dependabot[bot]
79855bbf9a
Bump json5 from 1.0.1 to 2.2.3 in /frontend
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v2.2.3)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-10 18:28:29 +00:00
Alberto Xamin
42a85025a3
change node builder 2023-02-10 17:05:40 +00:00
Alberto Xamin
485f4066df
bump vue version 2023-02-10 16:21:35 +00:00
Alberto Xamin
4472576f11
update devcontainer 2023-02-10 16:19:47 +00:00
Alberto Xamin
2701e682b4
migrate vue-cli to vite 2023-02-10 16:15:28 +00:00
Giulio
26869b79e0 Merge branch 'dev' into main 2023-02-10 00:12:19 +01:00
Giulio
85c18bcb82 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001451' into dev 2023-02-10 00:08:43 +01:00
Giulio
6ca4e70edc Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.33.0' into dev 2023-02-10 00:07:50 +01:00
Giulio
31bdeb3436 Merge branch 'main' into dev 2023-02-10 00:07:00 +01:00
Alberto Xamin
840677f839 make the valley of shadows generally available 2023-02-09 16:40:45 +00:00
Alberto Xamin
d3f70454be fix no players in range 2023-02-09 16:39:29 +00:00
Alberto Xamin
005ec8dd3c add link for backend switching 2023-02-09 15:41:30 +00:00
Alberto Xamin
cbe1945f5d add possibility to use a different backend 2023-02-09 14:40:11 +00:00
Alberto Xamin
621739546e add lemat 2023-02-09 11:45:32 +00:00
Alberto Xamin
8d06cc2a77 fix discord login errors 2023-02-09 10:56:48 +00:00
Alberto Xamin
84d4dcd98e blackflower to choose_play_as_bang 2023-02-09 10:43:22 +00:00
dependabot[bot]
e8fcafd4a1
Bump caniuse-lite from 1.0.30001450 to 1.0.30001451 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001450 to 1.0.30001451.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001450...1.0.30001451)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-09 04:06:53 +00:00
dependabot[bot]
90b0f033e3
Bump @datadog/browser-rum from 4.32.0 to 4.33.0 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.32.0 to 4.33.0.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.33.0/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-09 04:06:17 +00:00
Alberto Xamin
62ac700c5b minor refactor 2023-02-08 15:56:53 +00:00
Alberto Xamin
3262580592 fix blackflower 2023-02-08 13:54:43 +00:00
Alberto Xamin
2418f7cc53 use dict instead of list 2023-02-05 09:27:30 +00:00
Alberto Xamin
7de4fb1135 fix typo 2023-02-04 22:12:17 +00:00
Alberto Xamin
1f17560729 improve load handling 2023-02-04 22:06:04 +00:00
Alberto Xamin
17a3568ba5 bullet holes in card borders and less tidy equipments 2023-02-02 12:41:58 +00:00
dependabot[bot]
d346400f51 Bump caniuse-lite from 1.0.30001449 to 1.0.30001450 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001449 to 1.0.30001450.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001449...1.0.30001450)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 12:37:38 +01:00
Giulio
768a5239e3 Bump caniuse-lite from 1.0.30001447 to 1.0.30001449 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001447 to 1.0.30001449.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001447...1.0.30001449)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 12:35:05 +01:00
dependabot[bot]
1b552fdf19 Bump @datadog/browser-rum from 4.30.1 to 4.32.0 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.30.1 to 4.32.0.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.32.0/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 12:34:03 +01:00
Alberto Xamin
cc936fb3b9 improve feedback experience 2023-02-01 10:36:39 +00:00
Alberto Xamin
ff27d2a5b2 fix hastebin changing apis 2023-02-01 10:27:28 +00:00
Alberto Xamin
bfb65e3e33 check for boundaries in scrap 2023-02-01 10:13:45 +00:00
Alberto Xamin
c1d3eaea86 disable rewards for hitting ghosts 2023-02-01 10:06:32 +00:00
Alberto Xamin
766ce0c5c5 fix sventagliata showing roles 2023-02-01 10:00:57 +00:00
Alberto Xamin
9ab96088b9 add mira, fix sventagliata 2023-01-30 13:50:53 +00:00
Alberto Xamin
cd1d1a0e2d make duel response less confusing 2023-01-30 12:11:48 +00:00
Alberto Xamin
f774a10e04 bring back functionality in development 2023-01-30 12:07:27 +00:00
Alberto Xamin
a4272f83d9 fix died_role localization 2023-01-30 11:33:56 +00:00
Alberto Xamin
c9c6101eef add fuga and MickDefender 2023-01-29 15:45:26 +00:00
Alberto Xamin
373954bc71 add comments to card 2023-01-29 09:48:06 +00:00
Alberto Xamin
c5bb95714d add czech language 2023-01-28 19:55:43 +00:00
Alberto Xamin
e11acd4c32 update localizations 2023-01-28 19:15:09 +00:00
Alberto Xamin
fc603dcba3 add black flower 2023-01-28 19:05:17 +00:00
Alberto Xamin
89f5de47c7 add Der Spot Burst Ringer 2023-01-28 18:36:37 +00:00
Alberto Xamin
a4876a3b17 fix service worker 2023-01-27 19:27:41 +00:00
Alberto Xamin
983e1cb9cd remove workbox references to service worker 2023-01-27 15:20:30 +00:00
Alberto Xamin
decd959328 add colorado bill 2023-01-27 15:08:23 +00:00
Alberto Xamin
2a69f8ba7c update gitignore for save 2023-01-27 14:49:55 +00:00
Alberto Xamin
11dc392d70 fix manette for green cards and fix must_be_used for equipment 2023-01-27 14:48:47 +00:00
Alberto Xamin
c4a2d67a29 add test for borraccia 2023-01-27 14:29:59 +00:00
Alberto Xamin
c163e6405d remove vulnerabilities from devdependencies 2023-01-27 14:00:22 +00:00
Alberto Xamin
af588b368d cleaner discord button 2023-01-26 17:39:30 +00:00
Alberto Xamin
9fea8bcae0 add true black theme 2023-01-26 17:27:42 +00:00
Alberto Xamin
a6ae613927 reduce discord button size and add link to /help to improve seo 2023-01-26 16:05:28 +00:00
Alberto Xamin
f7d793c929 safari ui fix 2023-01-26 15:50:41 +00:00
Alberto Xamin
53137eea9f safari tab group color 2023-01-26 15:44:45 +00:00
Alberto Xamin
b998405578 add tuco tests and strings 2023-01-26 15:39:52 +00:00
Alberto Xamin
bc143190c3 add tucoFranziskaner Logic 2023-01-26 15:30:15 +00:00
Alberto Xamin
3a6bbb2427 add characters definitions for valley of shadows 2023-01-26 15:29:59 +00:00
Alberto Xamin
9487a59750 update dummy socket 2023-01-25 18:36:48 +00:00
Alberto Xamin
4f08874c9a add animations for cards against someone 2023-01-25 18:33:57 +00:00
Alberto Xamin
33f90901de remove redundant call in can can 2023-01-25 17:57:22 +00:00
Alberto Xamin
a7ef721f1b enable draw animation from other players 2023-01-25 17:46:16 +00:00
Alberto Xamin
e5072d7db9 add avatar to self in panico and cat balou 2023-01-25 17:40:09 +00:00
Alberto Xamin
3815cc719f add animation for scrap 2023-01-25 15:56:12 +00:00
GM
7c36bd9014 hastebin link on report 2023-01-25 15:28:36 +00:00
GM
33f51eac96 competitive replay 2023-01-25 15:25:21 +00:00
Alberto Xamin
fdda9457ca add draw from deck animation 2023-01-25 15:09:21 +00:00
Alberto Xamin
3cc94dafd7
improve seo 2023-01-25 12:58:15 +01:00
GM
bea9529912 typo 2023-01-25 11:10:38 +00:00
GM
28baebb6d1 remove replay players on reset 2023-01-25 11:09:31 +00:00
GM
0dd284c9d6 show sid on status 2023-01-25 10:33:19 +00:00
Alberto Xamin
1146df0571
remove players once replay is done 2023-01-25 11:21:19 +01:00
GM
323b6b773c send error to room or to admins 2023-01-25 09:28:08 +00:00
Alberto Xamin
1e5c645c5e
don't notify role if people are winning 2023-01-24 21:48:01 +01:00
Alberto Xamin
18d46f3ffc
check if can select and cancel rum errors 2023-01-24 21:00:59 +01:00
Alberto Xamin
19be866323
add more tips and fix translations 2023-01-24 20:52:52 +01:00
Alberto Xamin
37eaa751c9 fix password check for empty password 2023-01-24 19:28:41 +00:00
Alberto Xamin
9639b6a43b fix molly slab the killer index 2023-01-24 17:48:21 +00:00
Alberto Xamin
6112a99ed8 more info on report and autofix 2023-01-24 17:24:34 +00:00
Alberto Xamin
51430c771d add rum version tracking 2023-01-24 17:15:39 +00:00
Alberto Xamin
992513d850 balance update 2023-01-24 14:24:42 +00:00
Alberto Xamin
24ff63d4c2 fix tooltip for english and emporio 2023-01-24 14:13:30 +00:00
Alberto Xamin
ab22c3d52d rebalance chuck wengam 2023-01-24 13:59:21 +00:00
Alberto Xamin
5193c5aa47 fix fantasma dead man 2023-01-24 13:56:28 +00:00
Alberto Xamin
4c337c560c
Merge pull request #414 from albertoxamin/dev
merge upgrade socketio
2023-01-24 12:51:43 +00:00
Alberto Xamin
74eb84ed08 remove unused greenlet 2023-01-24 12:14:39 +00:00
Alberto Xamin
1955d66c7c update socketio on main.js 2023-01-24 11:54:11 +00:00
Alberto Xamin
20b0db20e6
packages upgrade 2023-01-24 12:39:36 +01:00
Alberto Xamin
8e58492930
add check for non player disconnect 2023-01-24 12:37:07 +01:00
dependabot[bot]
0d74b829b0 Bump caniuse-lite from 1.0.30001446 to 1.0.30001447 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001446 to 1.0.30001447.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001446...1.0.30001447)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-24 12:26:16 +01:00
Alberto Xamin
65a3705e25
update github actions 2023-01-23 16:05:57 +00:00
Alberto Xamin
ad9007628c
update even for the setevent 2023-01-23 14:54:57 +00:00
Alberto Xamin
6ae2360adb
change is none checks 2023-01-23 14:50:03 +00:00
Alberto Xamin
1b8690a5c6
remove spectators from gamesaves 2023-01-23 14:39:59 +00:00
Alberto Xamin
5a0abfea54
simplify server logic with assignment expressions 2023-01-23 14:38:53 +00:00
GM
da28f045a3 default settings and extensions on codespaces 2023-01-23 13:46:58 +00:00
GM
99c89aa845 yarn 2023-01-23 13:05:54 +00:00
GM
bf0df3b1ef python 3.11.1 on codespaces 2023-01-23 12:53:39 +00:00
Alberto Xamin
7e7483c10b
migrate to python 3.11 2023-01-23 10:38:44 +00:00
Alberto Xamin
9be6b0f387
Merge pull request #412 from albertoxamin/test-save
Add some form of persistency during restarts
2023-01-23 10:36:27 +00:00
GM
10ea588a16 fix status page 2023-01-23 10:23:03 +00:00
GM
218e348a53 view the expansion valley_of_shadows only once 2023-01-23 09:08:09 +00:00
GM
c888632fa7 create the folder if it doesn't exist 2023-01-23 08:59:48 +00:00
Giulio
65339b5435 Merge branch 'dev' into test-save 2023-01-23 09:00:09 +01:00
Alberto Xamin
c3a53b7ace
add more importance to a dead role 2023-01-22 23:03:26 +00:00
GM
953a024ff1 just for commit 2023-01-22 21:44:34 +00:00
GM
a7ec4935e0 fix folder 2023-01-22 21:17:18 +00:00
GM
292fbe4dde volume save 2023-01-22 20:51:44 +00:00
Giulio
8b0b5228de Merge branch 'test-save' into dev 2023-01-22 20:34:04 +01:00
GM
ee7e02a525 fix deadman and fantasma 2023-01-22 18:36:14 +00:00
GM
a5e827c882 fix name desc for Players - frontend 2023-01-22 18:35:36 +00:00
Alberto Xamin
87dcbedc29
don't save hidden games 2023-01-22 11:52:34 +00:00
Alberto Xamin
fee3171e8a
reduce times that the player is forced to change name 2023-01-22 11:44:55 +00:00
Alberto Xamin
e2b78a37e9
block disconnect only while with debugger 2023-01-22 11:24:43 +00:00
GM
867a079341 fix bot logic with The Judge and green cards 2023-01-21 18:09:07 +01:00
GM
fc16756805 fix bot logic with The Judge and green cards 2023-01-21 17:07:48 +00:00
Alberto Xamin
08c81c4a21 fix error if no player is alive 2023-01-21 17:16:19 +01:00
Alberto Xamin
3c4357eaac
fix error if no player is alive 2023-01-21 16:13:03 +00:00
Alberto Xamin
ca342f0106
prevent infinite loop 2023-01-21 14:53:08 +00:00
Alberto Xamin
28a093d337
remove recursion 2023-01-21 14:41:53 +00:00
Alberto Xamin
1b263adc80
fix players becoming bots 2023-01-21 14:28:34 +00:00
Alberto Xamin
461dfb8841
fix debug disconnect 2023-01-21 14:16:48 +00:00
Alberto Xamin
699c976c75
fix replays 2023-01-21 14:03:27 +00:00
Alberto Xamin
13ab981c59
introduce back delay 2023-01-21 13:40:41 +00:00
Alberto Xamin
ec48007377
add save lock 2023-01-21 13:15:20 +00:00
Alberto Xamin
8e745fa796
update gitignore 2023-01-21 13:03:00 +00:00
Alberto Xamin
d7187dbc61
add reset button 2023-01-21 11:50:11 +00:00
Alberto Xamin
5d7f833916
prevent debugger disconnect 2023-01-21 11:07:30 +00:00
Alberto Xamin
babc4f3f48
start bot disconnect on restart 2023-01-21 10:56:11 +00:00
Alberto Xamin
5eafa4fa18 remove reference to sio in replay 2023-01-20 21:03:39 +00:00
Alberto Xamin
2b4643b237 add game save 2023-01-20 20:57:30 +00:00
Alberto Xamin
3f44093560
handle audio errors 2023-01-20 17:29:04 +00:00
Alberto Xamin
0574117028
add username in rum 2023-01-20 17:28:38 +00:00
GM
ce0611cf8d fix scrap cards of the dead players
with Vulture Sam
2023-01-20 11:48:07 +00:00
GM
89dfb533b5 fix game freeze when a ghost kill himself 2023-01-20 11:03:43 +00:00
dependabot[bot]
6f21f5885f Bump dnspython from 2.2.1 to 2.3.0 in /backend
Bumps [dnspython](https://github.com/rthalley/dnspython) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/rthalley/dnspython/releases)
- [Changelog](https://github.com/rthalley/dnspython/blob/master/doc/whatsnew.rst)
- [Commits](https://github.com/rthalley/dnspython/compare/v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: dnspython
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-20 09:47:14 +01:00
Alberto Xamin
d9c3493661
add spectate button 2023-01-19 10:56:38 +00:00
Alberto Xamin
c05e2a69e2
add ffw to replay 2023-01-19 10:04:02 +00:00
Giulio
c5dab6fde7 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001446' into dev 2023-01-19 09:45:38 +01:00
Giulio
70ff973f77 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/eventlet-0.33.3' into dev 2023-01-19 09:45:34 +01:00
dependabot[bot]
bb94de0f0b
Bump caniuse-lite from 1.0.30001445 to 1.0.30001446 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001445 to 1.0.30001446.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001445...1.0.30001446)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-19 04:04:51 +00:00
dependabot[bot]
96abdfe60d
Bump eventlet from 0.33.2 to 0.33.3 in /backend
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.33.2 to 0.33.3.
- [Release notes](https://github.com/eventlet/eventlet/releases)
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.33.2...v0.33.3)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-19 04:04:10 +00:00
Alberto Xamin
9d849d4343
better chat log 2023-01-18 14:01:40 +00:00
GM
42187a0698 rum config update 2023-01-17 09:38:01 +00:00
GM
536ceead77 fix undefined length 2023-01-17 09:37:04 +00:00
Alberto Xamin
9e2b6263f2
add sventagliata 2023-01-16 17:13:53 +00:00
Alberto Xamin
a7098bca97
add tornado, bandidos, poker cards to log 2023-01-16 16:34:20 +00:00
Giulio
5cc8eec606 Merge branch 'dev' into main 2023-01-16 09:40:37 +01:00
Giulio
b769e53bfd Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001445' into dev 2023-01-16 09:30:32 +01:00
Giulio
1336e61109 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/pytest-7.2.1' into dev 2023-01-16 09:30:26 +01:00
dependabot[bot]
63a3036d92
Bump caniuse-lite from 1.0.30001443 to 1.0.30001445 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001443 to 1.0.30001445.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001443...1.0.30001445)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 04:12:58 +00:00
dependabot[bot]
3b8594482f
Bump pytest from 7.2.0 to 7.2.1 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.0 to 7.2.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.2.0...7.2.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 04:10:05 +00:00
GM
ad05f82ffa comments 2023-01-14 18:19:08 +00:00
Giulio
159481df4b Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/requests-2.28.2' into dev 2023-01-14 18:55:04 +01:00
GM
e966c82d5f fix equipment usable on equipment slot 2023-01-14 17:46:19 +00:00
GM
cea89bf9b4 fix taglia usable on equipment 2023-01-14 15:59:38 +00:00
GM
e400ab22ba fix player desc 2023-01-14 15:58:23 +00:00
Alberto Xamin
edeefa28c6
add attack queue 2023-01-13 17:50:50 +00:00
Alberto Xamin
63e0892cc3
add test for poker and tornado 2023-01-13 16:01:44 +00:00
Alberto Xamin
3972df1809
fix bandidos and add taglia test 2023-01-13 15:52:58 +00:00
GM
473cb2a207 fix avatar none & change beta expansions 2023-01-13 14:47:48 +00:00
GM
5fb53a7be6 report text on discord 2023-01-13 11:01:07 +00:00
GM
14a8c00dff Lazo again 2023-01-13 09:18:02 +00:00
Giulio
49512056e3 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001443' into dev 2023-01-13 09:40:09 +01:00
Giulio
457a04ee10 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.30.1' into dev 2023-01-13 09:39:29 +01:00
Giulio
f835a74ded Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.28.2' into dev 2023-01-13 09:39:22 +01:00
Giulio
d6fa20923b Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/greenlet-1.1.3.post0' into dev 2023-01-13 09:39:11 +01:00
dependabot[bot]
2cf39aac1b
Bump caniuse-lite from 1.0.30001441 to 1.0.30001443 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001441 to 1.0.30001443.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001441...1.0.30001443)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-13 04:06:20 +00:00
dependabot[bot]
6b4cfff2fe
Bump @datadog/browser-rum from 4.30.0 to 4.30.1 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.30.0 to 4.30.1.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.30.1/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-13 04:04:46 +00:00
dependabot[bot]
df09fbf79f
Bump vue-i18n from 8.27.1 to 8.28.2 in /frontend
Bumps [vue-i18n](https://github.com/intlify/vue-i18n-next/tree/HEAD/packages/vue-i18n) from 8.27.1 to 8.28.2.
- [Release notes](https://github.com/intlify/vue-i18n-next/releases)
- [Changelog](https://github.com/intlify/vue-i18n-next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/intlify/vue-i18n-next/commits/HEAD/packages/vue-i18n)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-13 04:04:30 +00:00
dependabot[bot]
33b7cd41ca
Bump greenlet from 1.1.2 to 1.1.3.post0 in /backend
Bumps [greenlet](https://github.com/python-greenlet/greenlet) from 1.1.2 to 1.1.3.post0.
- [Release notes](https://github.com/python-greenlet/greenlet/releases)
- [Changelog](https://github.com/python-greenlet/greenlet/blob/master/CHANGES.rst)
- [Commits](https://github.com/python-greenlet/greenlet/compare/1.1.2...1.1.3.post0)

---
updated-dependencies:
- dependency-name: greenlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-13 04:03:45 +00:00
dependabot[bot]
a42fb55bed
Bump requests from 2.27.1 to 2.28.2 in /backend
Bumps [requests](https://github.com/psf/requests) from 2.27.1 to 2.28.2.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.27.1...v2.28.2)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-13 04:03:39 +00:00
Alberto Xamin
8b33aeaf1c
fix valley cards interfering with card events damage 2023-01-12 20:43:26 +00:00
Alberto Xamin
4ca6bda07a
Change simeon picos emoji 2023-01-12 20:28:25 +00:00
GM
389c2da37a fix lazo with bounty and shotgun 2023-01-12 16:07:00 +00:00
Alberto Xamin
bbf87a59c4
add poker 2023-01-12 15:27:57 +00:00
GM
f2d6e2315c fix chat ui 2023-01-12 14:35:21 +00:00
Alberto Xamin
812d8d8a1e
more ai generate robots avatars 2023-01-12 14:17:56 +00:00
GM
18ce61c3c4 Merge branch dev into main 2023-01-12 11:50:57 +00:00
Giulio
48c04dabfe Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue-router-3.6.5' into dev 2023-01-12 12:18:52 +01:00
Giulio
98a1c83f30 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/eventlet-0.33.2' into dev 2023-01-12 12:12:52 +01:00
Giulio
c9003e12be Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.5.4' into dev 2023-01-12 11:59:00 +01:00
Giulio
8808e24e25 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/pytest-7.2.0' into dev 2023-01-12 11:54:56 +01:00
Giulio
56bec9cbaf Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.30.0' into dev 2023-01-12 11:52:29 +01:00
dependabot[bot]
95e3ef4dc7
Bump vue-router from 3.5.4 to 3.6.5 in /frontend
Bumps [vue-router](https://github.com/vuejs/router) from 3.5.4 to 3.6.5.
- [Release notes](https://github.com/vuejs/router/releases)
- [Commits](https://github.com/vuejs/router/commits)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-12 10:47:45 +00:00
dependabot[bot]
30c626e6e4
Bump eventlet from 0.33.1 to 0.33.2 in /backend
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.33.1 to 0.33.2.
- [Release notes](https://github.com/eventlet/eventlet/releases)
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.33.1...v0.33.2)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-12 10:47:23 +00:00
dependabot[bot]
1affb63c97
Bump workbox-webpack-plugin from 6.5.3 to 6.5.4 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.5.3...v6.5.4)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-12 10:47:04 +00:00
dependabot[bot]
ae7a30fdae
Bump pytest from 7.1.2 to 7.2.0 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.2 to 7.2.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.2...7.2.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-12 10:46:54 +00:00
dependabot[bot]
4eab9f6c6c
Bump @datadog/browser-rum from 4.11.4 to 4.30.0 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.11.4 to 4.30.0.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.30.0/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-12 10:44:23 +00:00
Giulio
f6bdbd2040 Merge branch 'dev' into main 2023-01-12 11:38:12 +01:00
Giulio
408c53ff43 removed dd-trace 2023-01-12 11:37:40 +01:00
Giulio
5b51ed5e95 Merge branch 'main' into dev 2023-01-12 11:11:05 +01:00
GM
c8a6e36023 sync dependencies from main to dev 2023-01-12 10:09:33 +00:00
Alberto Xamin
7767f75604 fix ghost card on ghost town 2023-01-10 20:16:49 +00:00
Alberto Xamin
47c2d2e297 fix ui issues 2023-01-10 17:10:06 +00:00
Giulio
5a309aeac5 Merge branch 'main' into dev 2023-01-10 18:00:43 +01:00
Alberto Xamin
8734c01843 improve character visual 2023-01-09 18:00:28 +00:00
Alberto Xamin
feedc5c784 fix bots 2023-01-09 17:40:43 +00:00
Alberto Xamin
a85b42d5b5
fix bugs 2023-01-09 18:09:23 +01:00
Alberto Xamin
888725a6ec
Update players.py 2023-01-09 17:45:50 +01:00
Alberto Xamin
33bc725eea add bandidos 2023-01-09 16:02:31 +00:00
Alberto Xamin
c5525527f4 fix admin status page color 2023-01-09 15:37:25 +00:00
Alberto Xamin
02311e7cec add player shuffling 2023-01-09 15:31:56 +00:00
Alberto Xamin
c13b79c38b add tornado 2023-01-09 14:10:38 +00:00
Alberto Xamin
e1fe906dbf hurt indicator 2023-01-09 13:31:34 +00:00
Alberto Xamin
8a622def7a even less allocations 2023-01-09 13:04:47 +00:00
Alberto Xamin
e03883bf7c reduce allocations 2023-01-09 12:52:47 +00:00
Alberto Xamin
0470e20cbb pylint happy 2023-01-09 10:36:46 +00:00
Alberto Xamin
60ef42f98a
write errors in the chat during debug 2023-01-09 10:14:27 +01:00
Alberto Xamin
1ea91af237 add taglia 2023-01-07 12:11:18 +00:00
Alberto Xamin
4958a2c7dc tweak timer 2023-01-07 12:03:55 +00:00
Alberto Xamin
30b3e826a0 add shotgun 2023-01-07 12:03:23 +00:00
Alberto Xamin
ed057502d6 add ritorno di fiamma 2023-01-07 11:15:40 +00:00
Alberto Xamin
1facfb354d fix broken bot spin 2023-01-07 09:43:54 +00:00
Alberto Xamin
8ffae000ef add hand count 2023-01-07 09:43:07 +00:00
Alberto Xamin
96edc77efe fix found bugs 2023-01-06 18:38:57 +00:00
Alberto Xamin
352f7f006f reduce memory allocations for checks 2023-01-06 17:24:16 +00:00
Alberto Xamin
0668fbf670 add fantasma, serpente a sonagli 2023-01-06 17:16:18 +00:00
Alberto Xamin
e7bfcb02ff valley cards definitions 2023-01-04 21:34:18 +00:00
Alberto Xamin
e4f3976c24 fix lint 2023-01-04 14:14:33 +00:00
Alberto Xamin
916d9af322 add valley of shadows under feature flag 2023-01-04 14:09:17 +00:00
Alberto Xamin
f6e8d193af add cards of valley of shadows 2023-01-04 12:04:37 +00:00
Alberto Xamin
63515c1d5f easier replayes 2023-01-03 20:51:51 +00:00
Alberto Xamin
7cba6fc7ef fix login flow 2023-01-03 16:15:11 +00:00
Alberto Xamin
8d90935e7d improved admin tools 2023-01-03 15:29:46 +00:00
Alberto Xamin
4d48a4bd69 add discord login 2023-01-03 13:50:41 +00:00
Alberto Xamin
e97c0d4bda fix broken report 2023-01-02 12:42:23 +00:00
Alberto Xamin
30f1251b3c fix manette 2022-12-30 16:45:21 +00:00
Alberto Xamin
7e2c218c3d notify scrap pile on reconnection 2022-12-29 16:36:45 +00:00
Alberto Xamin
0138c8b4fd speedup pull request tests 2022-12-29 15:43:52 +00:00
Alberto Xamin
5dacbc0c76
Merge pull request #395 from albertoxamin/dependabot/npm_and_yarn/frontend/minimatch-3.1.2
Bump minimatch from 3.0.4 to 3.1.2 in /frontend
2022-12-29 16:38:39 +01:00
dependabot[bot]
2c1d223cde
Bump minimatch from 3.0.4 to 3.1.2 in /frontend
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-29 13:52:39 +00:00
Alberto Xamin
eb2a6d28bc
Merge pull request #393 from albertoxamin/dependabot/npm_and_yarn/frontend/express-4.18.2
Bump express from 4.17.2 to 4.18.2 in /frontend
2022-12-29 14:52:08 +01:00
Alberto Xamin
a6edde725a Merge branch 'main' into dev 2022-12-29 13:36:24 +00:00
dependabot[bot]
eb7c323cfc
Bump express from 4.17.2 to 4.18.2 in /frontend
Bumps [express](https://github.com/expressjs/express) from 4.17.2 to 4.18.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.2...4.18.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-29 13:33:17 +00:00
Alberto Xamin
1c2864531b remove discord from pullrequests 2022-12-29 13:31:53 +00:00
Alberto Xamin
0d73ec86b7 show turn arrows 2022-12-28 16:20:16 +00:00
Alberto Xamin
cc8cd52c6b add info about which card is attacking you 2022-12-28 13:38:40 +00:00
Alberto Xamin
f9d2d48d8a fix chat color 2022-12-28 13:02:29 +00:00
Alberto Xamin
16c213a842 add devcontainer config 2022-12-27 17:24:10 +00:00
Alberto Xamin
984ce50ad8
chat improvements 2022-12-14 11:57:23 +01:00
Alberto Xamin
e16f89d0f6
fix broken build 2022-12-13 22:33:17 +01:00
Alberto Xamin
5dcfc884c9
add chat background so it is easier to see 2022-12-13 22:24:13 +01:00
Alberto Xamin
35c241d9cf fix jacky murieta description 2022-12-13 21:10:19 +01:00
Giulio
d4f13014f9 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/requests-2.28.0' into dev 2022-06-14 11:14:51 +02:00
Giulio
ef90855b12 Merge remote-tracking branch 'origin/dependabot/github_actions/dev/actions/setup-python-4' into dev 2022-06-14 11:14:28 +02:00
Giulio
c0e16f9472 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001352' into dev 2022-06-14 11:14:22 +02:00
Giulio
7a2d2ee834 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.11.4' into dev 2022-06-14 11:11:24 +02:00
Giulio
307a61a2c6 Emporio writes the drawn cards in the chat 2022-06-14 11:07:44 +02:00
Giulio
37cd396a9c Emporio writes the drawn cards in the chat 2022-06-14 11:07:27 +02:00
dependabot[bot]
fda5e78c34
Bump @datadog/browser-rum from 4.11.2 to 4.11.4 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.11.2 to 4.11.4.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.11.4/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-14 04:26:57 +00:00
dependabot[bot]
9272e18ac0
Bump caniuse-lite from 1.0.30001344 to 1.0.30001352 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001344 to 1.0.30001352.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001344...1.0.30001352)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-10 04:26:03 +00:00
dependabot[bot]
dbe6592236
Bump requests from 2.27.1 to 2.28.0 in /backend
Bumps [requests](https://github.com/psf/requests) from 2.27.1 to 2.28.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.27.1...v2.28.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-10 04:15:47 +00:00
dependabot[bot]
d7f28f3053
Bump actions/setup-python from 3 to 4
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-09 04:17:29 +00:00
Giulio
02070f5e55 fix Josh McCloud 2022-06-02 11:26:02 +02:00
Giulio
e1dfff2118 fix Josh McCloud 2022-06-02 11:25:36 +02:00
Giulio
7fe4d3680d fix ghost draw
dutch will & Kit Carlson
2022-06-02 10:29:04 +02:00
Giulio
469c2c0d57 Bump eventsource from 1.1.0 to 1.1.1 in /frontend 2022-06-02 09:59:36 +02:00
Giulio
d4aa03c85e Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/eventsource-1.1.1' into dev 2022-06-02 09:51:12 +02:00
Giulio
c83cf498c9 yarn update 2022-06-02 09:39:50 +02:00
Giulio
3e6f09cea1 fix ghost draw
dutch will & Kit Carlson
2022-06-02 09:39:30 +02:00
dependabot[bot]
1ba473d777
Bump eventsource from 1.1.0 to 1.1.1 in /frontend
Bumps [eventsource](https://github.com/EventSource/eventsource) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/EventSource/eventsource/releases)
- [Changelog](https://github.com/EventSource/eventsource/blob/master/HISTORY.md)
- [Commits](https://github.com/EventSource/eventsource/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: eventsource
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-01 22:49:52 +00:00
Giulio
1411be11fe Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001344' into dev 2022-06-01 16:11:33 +02:00
Giulio
a9151b0beb Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/ddtrace-1.1.4' into dev 2022-06-01 16:11:01 +02:00
Giulio
862ef0fab8 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/socket.io-client-4.5.1' into dev 2022-06-01 16:10:46 +02:00
Giulio
a541b17de8 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/certifi-2022.5.18.1' into dev 2022-06-01 16:09:04 +02:00
Giulio
b84b932607 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.11.2' into dev 2022-06-01 16:08:34 +02:00
dependabot[bot]
11c339afe8
Bump @datadog/browser-rum from 4.10.3 to 4.11.2 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.10.3 to 4.11.2.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.11.2/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-31 04:19:56 +00:00
dependabot[bot]
b319231dfe
Bump caniuse-lite from 1.0.30001341 to 1.0.30001344 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001341 to 1.0.30001344.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001341...1.0.30001344)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 04:25:40 +00:00
dependabot[bot]
bff3b4ec95
Bump ddtrace from 1.1.3 to 1.1.4 in /backend
Bumps [ddtrace](https://github.com/DataDog/dd-trace-py) from 1.1.3 to 1.1.4.
- [Release notes](https://github.com/DataDog/dd-trace-py/releases)
- [Changelog](https://github.com/DataDog/dd-trace-py/blob/1.x/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-py/compare/v1.1.3...v1.1.4)

---
updated-dependencies:
- dependency-name: ddtrace
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 04:18:13 +00:00
dependabot[bot]
d05a1e48b5
Bump certifi from 2022.5.18 to 2022.5.18.1 in /backend
Bumps [certifi](https://github.com/certifi/python-certifi) from 2022.5.18 to 2022.5.18.1.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/compare/2022.05.18...2022.05.18.1)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-20 04:23:01 +00:00
dependabot[bot]
acb977b9ba
Bump socket.io-client from 4.5.0 to 4.5.1 in /frontend
Bumps [socket.io-client](https://github.com/socketio/socket.io-client) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/socketio/socket.io-client/releases)
- [Changelog](https://github.com/socketio/socket.io-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-client/compare/4.5.0...4.5.1)

---
updated-dependencies:
- dependency-name: socket.io-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-19 13:01:13 +00:00
Giulio
a5a5ca741b Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.10.3' into dev 2022-05-19 14:54:34 +02:00
Giulio
fd104414eb Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/certifi-2022.5.18' into dev 2022-05-19 14:53:28 +02:00
Giulio
91ce954c9e Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/ddtrace-1.1.3' into dev 2022-05-19 14:53:24 +02:00
Giulio
aa69d2c525 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue-router-3.5.4' into dev 2022-05-19 14:53:14 +02:00
Giulio
8ba40a48e5 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001341' into dev 2022-05-19 14:53:02 +02:00
Giulio
9757bdda35 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/discord-webhook-0.16.3' into dev 2022-05-19 14:52:56 +02:00
Giulio
390a03e033 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/eventlet-0.33.1' into dev 2022-05-19 14:52:46 +02:00
dependabot[bot]
f885203606
Bump @datadog/browser-rum from 4.8.1 to 4.10.3 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.8.1 to 4.10.3.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.10.3/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-19 04:17:01 +00:00
dependabot[bot]
0502304c78
Bump certifi from 2021.10.8 to 2022.5.18 in /backend
Bumps [certifi](https://github.com/certifi/python-certifi) from 2021.10.8 to 2022.5.18.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/commits)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-19 04:13:18 +00:00
dependabot[bot]
3804b6e92d
Bump ddtrace from 1.1.2 to 1.1.3 in /backend
Bumps [ddtrace](https://github.com/DataDog/dd-trace-py) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/DataDog/dd-trace-py/releases)
- [Changelog](https://github.com/DataDog/dd-trace-py/blob/1.x/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-py/compare/v1.1.2...v1.1.3)

---
updated-dependencies:
- dependency-name: ddtrace
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-18 04:13:12 +00:00
dependabot[bot]
dd521c483a
Bump vue-router from 3.5.3 to 3.5.4 in /frontend
Bumps [vue-router](https://github.com/vuejs/router) from 3.5.3 to 3.5.4.
- [Release notes](https://github.com/vuejs/router/releases)
- [Changelog](https://github.com/vuejs/router/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/router/commits)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-17 04:19:38 +00:00
dependabot[bot]
5919138616
Bump caniuse-lite from 1.0.30001338 to 1.0.30001341 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001338 to 1.0.30001341.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001338...1.0.30001341)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 04:23:01 +00:00
dependabot[bot]
207b0a2dbd
Bump discord-webhook from 0.16.0 to 0.16.3 in /backend
Bumps [discord-webhook](https://github.com/lovvskillz/python-discord-webhook) from 0.16.0 to 0.16.3.
- [Release notes](https://github.com/lovvskillz/python-discord-webhook/releases)
- [Changelog](https://github.com/lovvskillz/python-discord-webhook/blob/master/CHANGES.md)
- [Commits](https://github.com/lovvskillz/python-discord-webhook/compare/0.16.0...0.16.3)

---
updated-dependencies:
- dependency-name: discord-webhook
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 04:16:34 +00:00
dependabot[bot]
73aa4e16db
Bump eventlet from 0.33.0 to 0.33.1 in /backend
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.33.0 to 0.33.1.
- [Release notes](https://github.com/eventlet/eventlet/releases)
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.33.0...v0.33.1)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-13 04:14:07 +00:00
Giulio
770792f224 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001338' into dev 2022-05-09 10:27:46 +02:00
Giulio
84772ddabf Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/discord-webhook-0.16.0' into dev 2022-05-09 10:27:40 +02:00
Giulio
e4ffbff8e4 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/ddtrace-1.1.2' into dev 2022-05-09 10:27:33 +02:00
Giulio
659199439a Merge remote-tracking branch 'origin/dependabot/github_actions/dev/docker/login-action-2' into dev 2022-05-09 10:27:17 +02:00
dependabot[bot]
8e1431fef0
Bump caniuse-lite from 1.0.30001336 to 1.0.30001338 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001336 to 1.0.30001338.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001336...1.0.30001338)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 04:29:55 +00:00
dependabot[bot]
f0814a3c58
Bump discord-webhook from 0.15.0 to 0.16.0 in /backend
Bumps [discord-webhook](https://github.com/lovvskillz/python-discord-webhook) from 0.15.0 to 0.16.0.
- [Release notes](https://github.com/lovvskillz/python-discord-webhook/releases)
- [Changelog](https://github.com/lovvskillz/python-discord-webhook/blob/master/CHANGES.md)
- [Commits](https://github.com/lovvskillz/python-discord-webhook/compare/0.15.0...0.16.0)

---
updated-dependencies:
- dependency-name: discord-webhook
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 04:24:26 +00:00
dependabot[bot]
3a07fda0c8
Bump ddtrace from 1.1.1 to 1.1.2 in /backend
Bumps [ddtrace](https://github.com/DataDog/dd-trace-py) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/DataDog/dd-trace-py/releases)
- [Changelog](https://github.com/DataDog/dd-trace-py/blob/1.x/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-py/compare/v1.1.1...v1.1.2)

---
updated-dependencies:
- dependency-name: ddtrace
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 04:24:23 +00:00
dependabot[bot]
0244220079
Bump docker/login-action from 1 to 2
Bumps [docker/login-action](https://github.com/docker/login-action) from 1 to 2.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-06 04:16:07 +00:00
Giulio
efd4e20037 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001336' into dev 2022-05-05 11:30:06 +02:00
Giulio
de878c3144 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/socket.io-client-4.5.0' into dev 2022-05-05 11:29:58 +02:00
GM
8efe598fde
Merge branch 'dev' into dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001336 2022-05-05 11:17:04 +02:00
dependabot[bot]
0c3c5bc1dd
Bump socket.io-client from 4.4.1 to 4.5.0 in /frontend
Bumps [socket.io-client](https://github.com/socketio/socket.io-client) from 4.4.1 to 4.5.0.
- [Release notes](https://github.com/socketio/socket.io-client/releases)
- [Changelog](https://github.com/socketio/socket.io-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-client/compare/4.4.1...4.5.0)

---
updated-dependencies:
- dependency-name: socket.io-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-05 09:12:35 +00:00
dependabot[bot]
d4d48a6e4a
Bump caniuse-lite from 1.0.30001335 to 1.0.30001336 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001335 to 1.0.30001336.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001335...1.0.30001336)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-05 09:12:11 +00:00
Giulio
7ea60057c7 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/ddtrace-1.1.1' into dev 2022-05-05 11:05:03 +02:00
Giulio
909df6802b Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001335' into dev 2022-05-05 11:04:57 +02:00
Giulio
ecd6861856 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/datadog/browser-rum-4.8.1' into dev 2022-05-05 11:04:02 +02:00
Giulio
3324ccd5da Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/pytest-7.1.2' into dev 2022-05-05 11:03:56 +02:00
Giulio
78f2b47ef6 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.5.3' into dev 2022-05-05 11:03:49 +02:00
dependabot[bot]
f9830644a9
Bump ddtrace from 0.60.1 to 1.1.1 in /backend
Bumps [ddtrace](https://github.com/DataDog/dd-trace-py) from 0.60.1 to 1.1.1.
- [Release notes](https://github.com/DataDog/dd-trace-py/releases)
- [Changelog](https://github.com/DataDog/dd-trace-py/blob/1.x/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-py/compare/v0.60.1...v1.1.1)

---
updated-dependencies:
- dependency-name: ddtrace
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-04 04:15:05 +00:00
dependabot[bot]
9a52cfba53
Bump caniuse-lite from 1.0.30001325 to 1.0.30001335 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001325 to 1.0.30001335.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001325...1.0.30001335)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-03 04:17:52 +00:00
dependabot[bot]
1d225390cb
Bump @datadog/browser-rum from 4.7.0 to 4.8.1 in /frontend
Bumps [@datadog/browser-rum](https://github.com/DataDog/browser-sdk/tree/HEAD/packages/rum) from 4.7.0 to 4.8.1.
- [Release notes](https://github.com/DataDog/browser-sdk/releases)
- [Changelog](https://github.com/DataDog/browser-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/browser-sdk/commits/v4.8.1/packages/rum)

---
updated-dependencies:
- dependency-name: "@datadog/browser-rum"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-29 04:53:14 +00:00
dependabot[bot]
a5fc835b95
Bump pytest from 7.1.1 to 7.1.2 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.1 to 7.1.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.1...7.1.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 04:18:27 +00:00
dependabot[bot]
16ee653a5b
Bump workbox-webpack-plugin from 6.5.2 to 6.5.3 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.5.2...v6.5.3)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-13 04:22:18 +00:00
Giulio
b3dd149014 docker buildx typo 2022-04-11 16:16:23 +02:00
Giulio
7dd59e09ed docker buildx typo 2022-04-11 16:11:23 +02:00
Giulio
f492f3995d remove armv-7 2022-04-11 16:10:56 +02:00
Alberto Xamin
ee5f91fcad more tracing 2022-04-11 14:51:55 +02:00
Alberto Xamin
19bea99961 add datadog proxy 2022-04-10 19:09:27 +02:00
Alberto Xamin
468b439dd4 add datadog proxy 2022-04-10 19:08:36 +02:00
Giulio
9af8a85df3 fix ddtrace PATH 2022-04-07 23:45:15 +02:00
Giulio
67e49e82dd Merge remote-tracking branch 'origin/main' into dev 2022-04-07 16:26:06 +02:00
Alberto Xamin
a56ff25105 add ddog rum 2022-04-07 11:23:42 +02:00
Alberto Xamin
78b0f9fe7c change the right dockerfile 2022-04-07 09:44:11 +02:00
Alberto Xamin
94735d1775 remove armv7 and add ddtrace command to docker 2022-04-06 16:19:03 +02:00
Alberto Xamin
df1a381909 add ddtrace 2022-04-06 12:11:02 +02:00
Giulio
38d0244793 exclude replays from metrics 2022-04-05 15:18:12 +02:00
dependabot[bot]
89917a7824
Bump caniuse-lite from 1.0.30001323 to 1.0.30001325 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001323 to 1.0.30001325.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001323...1.0.30001325)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-05 04:23:15 +00:00
Giulio
24daac2859 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001323' into dev 2022-04-01 11:22:02 +02:00
dependabot[bot]
87fb52ff1e
Bump caniuse-lite from 1.0.30001322 to 1.0.30001323 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001322 to 1.0.30001323.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001322...1.0.30001323)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-01 04:23:56 +00:00
Giulio
433209f75b Merge branch 'dev' into main 2022-03-31 23:29:56 +02:00
Giulio
90b138d70a fixed rangeless card 2022-03-31 23:11:07 +02:00
Giulio
91a1d2122d fix for belle star and event cards 2022-03-31 13:10:17 +02:00
Giulio
3c6dc912c8 minor changes 2022-03-31 13:09:41 +02:00
Giulio
1e526a0175 Merge branch 'dev' into main 2022-03-30 15:00:39 +02:00
Giulio
b90c5553e3 fix rissa 2 2022-03-30 14:30:12 +02:00
Giulio
0818bfbf22 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.27.1' into dev 2022-03-30 12:35:28 +02:00
Giulio
dc40adbf32 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001322' into dev 2022-03-30 12:33:42 +02:00
Giulio
4bed4484b5 fix rissa 2022-03-30 12:29:46 +02:00
Giulio
f985d84483 fast forward in replay 2022-03-30 12:22:27 +02:00
Giulio
7aebb2318b typo in rpc_log 2022-03-30 12:21:14 +02:00
dependabot[bot]
fdf4c97176
Bump caniuse-lite from 1.0.30001320 to 1.0.30001322 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001320 to 1.0.30001322.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001320...1.0.30001322)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-30 04:20:56 +00:00
dependabot[bot]
0c3ff913b1
Bump vue-i18n from 8.27.0 to 8.27.1 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.27.0 to 8.27.1.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.27.0...v8.27.1)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-29 04:22:55 +00:00
Giulio
744759f224 Merge branch 'dev' into main 2022-03-28 20:54:36 +02:00
Giulio
d0159ea0e1 fix ghost in player death check win status 2022-03-28 15:33:26 +02:00
Giulio
ff758c2a39 fix end of replay 2022-03-28 15:31:43 +02:00
Giulio
b564b8e504 herb hunter fix when sheriff kills deputy 2022-03-28 14:11:12 +02:00
Alberto Xamin
99970d0df9 add metric polling 2022-03-27 14:33:54 +02:00
Alberto Xamin
803d144c6d
Merge pull request #200 from albertoxamin/dev
metrics for more things!
2022-03-27 11:13:25 +02:00
Alberto Xamin
05e0babad5 fix broken tests 2022-03-26 12:17:16 +01:00
Alberto Xamin
20819cedd0 add more metrics 2022-03-26 12:12:16 +01:00
Giulio
bdaa848b5b Merge branch 'dev' into main 2022-03-25 17:51:24 +01:00
Giulio
dcfdacc6df metric of the number of players 2022-03-25 17:50:16 +01:00
Giulio
4af54f79dd import refactor 2022-03-25 17:49:13 +01:00
Alberto Xamin
88b8e26734
Merge pull request #199 from albertoxamin/dev
refactor metrics ands add metrics on cards usage
2022-03-25 15:44:16 +01:00
Alberto Xamin
fd6c4cca1d add cards metrics 2022-03-25 15:42:44 +01:00
Alberto Xamin
50fd2b5b06 refactor metric collection 2022-03-25 15:29:28 +01:00
Giulio
eaf3d374ad Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.5.2' into dev 2022-03-25 13:58:07 +01:00
Giulio
4893f69e27 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-router-5.0.4' into dev 2022-03-25 13:58:03 +01:00
Giulio
e8b236073f Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001320' into dev 2022-03-25 13:57:59 +01:00
Giulio
0231d0a507 Merge remote-tracking branch 'origin/dependabot/github_actions/dev/actions/setup-python-3' into dev 2022-03-25 13:57:53 +01:00
Giulio
25aeee6354 Merge branch 'dev' into main 2022-03-25 13:30:19 +01:00
Giulio
56529f505e Merge branch 'main' into dev 2022-03-25 13:29:58 +01:00
Giulio
207818bc41 fix don bell 2022-03-25 13:08:14 +01:00
Alberto Xamin
ccb35606e1 fix not closing lobbies 2022-03-25 12:39:45 +01:00
Giulio
4847aee1f6 typo 2022-03-25 11:55:30 +01:00
Giulio
7c55939e6a Merge branch 'main' into dev 2022-03-25 11:45:47 +01:00
Alberto Xamin
3bc4bd200f fix error 2022-03-25 11:12:29 +01:00
Alberto Xamin
8a45186ecb add more metrics 2022-03-25 11:07:36 +01:00
dependabot[bot]
111934e728
Bump workbox-webpack-plugin from 6.5.1 to 6.5.2 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.5.1 to 6.5.2.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.5.1...v6.5.2)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-25 04:23:33 +00:00
dependabot[bot]
c799ba8e26
Bump @vue/cli-plugin-router from 5.0.3 to 5.0.4 in /frontend
Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 5.0.3 to 5.0.4.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v5.0.4/packages/@vue/cli-plugin-router)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-router"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-25 04:22:38 +00:00
dependabot[bot]
63c8b1ab02
Bump caniuse-lite from 1.0.30001317 to 1.0.30001320 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001317 to 1.0.30001320.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001317...1.0.30001320)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-25 04:21:06 +00:00
dependabot[bot]
53b4cf0125
Bump actions/setup-python from 2 to 3
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 3.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-25 04:17:01 +00:00
Giulio
9f1ec34d73 fix il giudice 2022-03-25 01:55:45 +01:00
Giulio
1bddd3c135 Merge branch 'dev' into main 2022-03-25 01:11:37 +01:00
Giulio
e7a79b0858 variable initialization pylint 2022-03-25 01:05:23 +01:00
Alberto Xamin
bc1d18d91c
Merge pull request #194 from albertoxamin/dev
Add datadog monitoring
2022-03-25 00:36:58 +01:00
Alberto Xamin
11f916649d
Merge branch 'main' into dev 2022-03-25 00:36:29 +01:00
Alberto Xamin
95a3061f74 add more metrics 2022-03-25 00:35:18 +01:00
Alberto Xamin
4473886486 add requirements to pylint 2022-03-24 20:30:44 +01:00
Alberto Xamin
68122a78e7 fix pylint 2022-03-24 20:28:58 +01:00
Alberto Xamin
2cc441ea7e Create pylint.yml 2022-03-24 20:20:04 +01:00
Alberto Xamin
3916408614 fix issues 2022-03-24 20:19:41 +01:00
Alberto Xamin
2743d0b9ce
Create pylint.yml 2022-03-24 20:15:57 +01:00
Alberto Xamin
e88a8f8f12 fix typo 2022-03-24 19:51:05 +01:00
Alberto Xamin
1e8c399c3b add datadog monitoring 2022-03-24 19:22:09 +01:00
Giulio
c88c71feb0 Merge branch 'dev' into main 2022-03-22 22:05:25 +01:00
Giulio
8ca795f680 restore bad fix for roulette event 2022-03-22 22:05:00 +01:00
Giulio
bd84d07562 fix dsh 2022-03-22 22:04:04 +01:00
Giulio
4fe7d09a8e Merge branch 'dev' into main 2022-03-22 14:18:20 +01:00
Giulio
0ed50022f1 fix heal in roulette event 2022-03-22 13:55:55 +01:00
Giulio
2e0bfc240c fix gold rush equipment on roulette 2022-03-22 13:09:44 +01:00
Giulio
2cda50e825 choose a random card when it is face down 2022-03-22 12:42:20 +01:00
Giulio
ab5a684822 Merge remote-tracking branch 'origin/dependabot/github_actions/dev/actions/cache-3' into dev 2022-03-22 11:03:44 +01:00
Giulio
6b77122778 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/pytest-7.1.1' into dev 2022-03-22 11:03:37 +01:00
dependabot[bot]
2181d1355d
Bump actions/cache from 2 to 3
Bumps [actions/cache](https://github.com/actions/cache) from 2 to 3.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-22 04:14:25 +00:00
dependabot[bot]
ca6c396c45
Bump pytest from 7.1.0 to 7.1.1 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.1.0 to 7.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.1.0...7.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-18 04:15:11 +00:00
Giulio
bef592c36a Merge branch 'dev' into main 2022-03-17 00:21:25 +01:00
Giulio
7e98b98b1c fix again panic + scope 2022-03-17 00:18:42 +01:00
Giulio
4ac7721b4c Merge branch 'dev' into main 2022-03-16 13:33:24 +01:00
Giulio
81e3dfb635 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-router-5.0.3' into dev 2022-03-16 11:33:51 +01:00
dependabot[bot]
e34ef050b3
Bump @vue/cli-plugin-router from 5.0.1 to 5.0.3 in /frontend
Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 5.0.1 to 5.0.3.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v5.0.3/packages/@vue/cli-plugin-router)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-router"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-16 10:18:45 +00:00
Giulio
a7e1e7c8ed fix panic + scope 2022-03-16 11:12:44 +01:00
Giulio
513fc00d49 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/pytest-7.1.0' into dev 2022-03-16 11:11:25 +01:00
Giulio
590b9e0b18 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001317' into dev 2022-03-16 11:11:08 +01:00
Giulio
8cace87776 Merge branch 'main' into dev 2022-03-16 11:11:00 +01:00
Alberto Xamin
8a1e5f84ca make icon more visible 2022-03-16 10:20:01 +01:00
Alberto Xamin
3ebff62a4a responsive language and theme buttons 2022-03-16 09:36:53 +01:00
dependabot[bot]
fb8e9f6fb5
Bump caniuse-lite from 1.0.30001314 to 1.0.30001317 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001314 to 1.0.30001317.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001314...1.0.30001317)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-16 04:20:48 +00:00
dependabot[bot]
cbe4490549
Bump pytest from 7.0.1 to 7.1.0 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.0.1 to 7.1.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.0.1...7.1.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-14 04:12:35 +00:00
Giulio
594e74e111 Merge branch 'dev' into main 2022-03-11 10:42:18 +01:00
Giulio
7d92ca0f41 user friendly bug report 2022-03-10 23:56:07 +01:00
Giulio
604aa8410e Merge branch 'dev' into main 2022-03-10 15:01:44 +01:00
Giulio
8d63835541 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/url-parse-1.5.10' into dev 2022-03-10 15:00:44 +01:00
Giulio
400e301c19 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001314' into dev 2022-03-10 14:59:03 +01:00
Giulio
341ef3aef7 fix duplicated choose in log 2022-03-10 14:58:42 +01:00
dependabot[bot]
c26ab71a95
Bump url-parse from 1.5.3 to 1.5.10 in /frontend
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-10 12:48:14 +00:00
Alberto Xamin
ae941ba2af
Merge pull request #179 from albertoxamin/dev
Add gold rush and replay capabilities
2022-03-10 13:46:42 +01:00
dependabot[bot]
a9fbc0da12
Bump caniuse-lite from 1.0.30001313 to 1.0.30001314 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001313 to 1.0.30001314.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001313...1.0.30001314)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-09 04:28:43 +00:00
Giulio
84c71262e0 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/dnspython-2.2.1' into dev 2022-03-07 19:23:33 +01:00
Giulio
d2035ed4b3 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001313' into dev 2022-03-07 19:23:29 +01:00
Giulio
49ab88b007 fix replay for Vera Custer 2022-03-07 19:21:58 +01:00
dependabot[bot]
daeea7a74a
Bump caniuse-lite from 1.0.30001312 to 1.0.30001313 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001312 to 1.0.30001313.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001312...1.0.30001313)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-07 04:24:04 +00:00
dependabot[bot]
99ffc649b6
Bump dnspython from 2.2.0 to 2.2.1 in /backend
Bumps [dnspython](https://github.com/rthalley/dnspython) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/rthalley/dnspython/releases)
- [Changelog](https://github.com/rthalley/dnspython/blob/v2.2.1/doc/whatsnew.rst)
- [Commits](https://github.com/rthalley/dnspython/compare/v2.2.0...v2.2.1)

---
updated-dependencies:
- dependency-name: dnspython
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-07 04:19:04 +00:00
Giulio
ab112165f0 fix replayspeed 2022-03-05 20:48:43 +01:00
Giulio
fa231dade2 fix renegade death win 2022-03-05 20:48:17 +01:00
Giulio
453c15cf3a Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.5.1' into dev 2022-03-05 03:50:55 +01:00
Giulio
909c02de53 minor fix
bug with Russian roulette as attacker
2022-03-05 03:46:22 +01:00
dependabot[bot]
631ef2627b
Bump workbox-webpack-plugin from 6.5.0 to 6.5.1 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.5.0 to 6.5.1.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.5.0...v6.5.1)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-04 04:21:07 +00:00
Giulio
b3626dd662 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/discord-webhook-0.15.0' into dev 2022-03-04 01:50:26 +01:00
Giulio
995853e046 fix outlaw and victory from death 2022-03-04 01:49:04 +01:00
dependabot[bot]
d161d14ec3
Bump discord-webhook from 0.14.0 to 0.15.0 in /backend
Bumps [discord-webhook](https://github.com/lovvskillz/python-discord-webhook) from 0.14.0 to 0.15.0.
- [Release notes](https://github.com/lovvskillz/python-discord-webhook/releases)
- [Changelog](https://github.com/lovvskillz/python-discord-webhook/blob/master/CHANGES.md)
- [Commits](https://github.com/lovvskillz/python-discord-webhook/compare/0.14.0...0.15.0)

---
updated-dependencies:
- dependency-name: discord-webhook
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-03 04:14:56 +00:00
Giulio
1c95327b83 fix distance with sight_mod card
also handled the hangover event
2022-03-02 23:15:32 +01:00
Giulio
767febb512 filter log in gameinfo 2022-03-02 23:12:22 +01:00
Giulio
7d6746c687 fix equipment
equipment could be reused from the equipment slot
2022-03-02 16:40:04 +01:00
Giulio
1c565e2ccc fix for don bell and green card
when don bell used his ability green cards could not be used
2022-03-02 15:43:53 +01:00
Giulio
34ed060b5c Merge remote-tracking branch 'origin/dependabot/github_actions/dev/actions/checkout-3' into dev 2022-03-02 15:06:14 +01:00
Giulio
39fbd9d711 Merge remote-tracking branch 'origin/dependabot/github_actions/dev/actions/setup-python-3' into dev 2022-03-02 15:06:06 +01:00
Giulio
43c88f0198 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.5.0' into dev 2022-03-02 15:05:55 +01:00
dependabot[bot]
abe684efa7
Bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-02 04:21:48 +00:00
dependabot[bot]
0e88c5b493
Bump actions/setup-python from 2 to 3
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 3.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-01 04:18:44 +00:00
Giulio
dd6fa92af8 fix desc in roles cards 2022-02-27 23:22:35 +01:00
Alberto Xamin
019396e615
fix replay bug with non ascii chars in characters names 2022-02-25 16:27:55 +02:00
dependabot[bot]
e2cbbd0550
Bump workbox-webpack-plugin from 6.4.2 to 6.5.0 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.4.2 to 6.5.0.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.4.2...v6.5.0)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-24 04:21:57 +00:00
Giulio
adeb9f1d06 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-router-5.0.1' into dev 2022-02-21 19:06:25 +01:00
dependabot[bot]
eae7e4d030
Bump @vue/cli-plugin-router from 4.5.15 to 5.0.1 in /frontend
Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 4.5.15 to 5.0.1.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v5.0.1/packages/@vue/cli-plugin-router)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-router"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 17:46:11 +00:00
Giulio
3a222eb3b2 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001312' into dev 2022-02-21 18:27:40 +01:00
Giulio
e12cce1c68 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/pytest-7.0.1' into dev 2022-02-21 18:27:32 +01:00
Giulio
9f54531f2a Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.27.0' into dev 2022-02-21 18:27:18 +01:00
Giulio
e49002b039 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/dnspython-2.2.0' into dev 2022-02-21 18:27:03 +01:00
dependabot[bot]
a2da913291
Bump caniuse-lite from 1.0.30001297 to 1.0.30001312 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001297 to 1.0.30001312.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001297...1.0.30001312)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 04:24:05 +00:00
dependabot[bot]
2f3fc812b1
Bump pytest from 6.2.5 to 7.0.1 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.5 to 7.0.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.5...7.0.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 04:17:06 +00:00
dependabot[bot]
594fc158f5
Bump vue-i18n from 8.26.8 to 8.27.0 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.26.8 to 8.27.0.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.26.8...v8.27.0)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-24 04:21:32 +00:00
dependabot[bot]
8657456a73
Bump dnspython from 1.16.0 to 2.2.0 in /backend
Bumps [dnspython]() from 1.16.0 to 2.2.0.

---
updated-dependencies:
- dependency-name: dnspython
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-19 04:17:41 +00:00
Giulio
15b3f1b751 Merge branch 'main' into dev 2022-01-18 01:14:03 +01:00
Alberto Xamin
3a292efd3c
Merge pull request #141 from albertoxamin/dependabot/npm_and_yarn/frontend/follow-redirects-1.14.7
Bump follow-redirects from 1.13.0 to 1.14.7 in /frontend
2022-01-17 17:41:47 +01:00
dependabot[bot]
d322446af7
Bump follow-redirects from 1.13.0 to 1.14.7 in /frontend
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.13.0 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.13.0...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-15 08:59:07 +00:00
GM
8952a6638e
Merge pull request #135 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/socket.io-client-4.4.1
Bump socket.io-client from 4.4.0 to 4.4.1 in /frontend
2022-01-08 03:15:17 +01:00
GM
14f5c80b58
Merge pull request #136 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/caniuse-lite-1.0.30001297
Bump caniuse-lite from 1.0.30001287 to 1.0.30001297 in /frontend
2022-01-08 03:05:13 +01:00
dependabot[bot]
563a7efaf4
Bump caniuse-lite from 1.0.30001287 to 1.0.30001297 in /frontend
Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001287 to 1.0.30001297.
- [Release notes](https://github.com/browserslist/caniuse-lite/releases)
- [Commits](https://github.com/browserslist/caniuse-lite/compare/1.0.30001287...1.0.30001297)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-08 01:58:37 +00:00
dependabot[bot]
a0c75d3f64
Bump socket.io-client from 4.4.0 to 4.4.1 in /frontend
Bumps [socket.io-client](https://github.com/socketio/socket.io-client) from 4.4.0 to 4.4.1.
- [Release notes](https://github.com/socketio/socket.io-client/releases)
- [Changelog](https://github.com/socketio/socket.io-client/blob/master/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-client/compare/4.4.0...4.4.1)

---
updated-dependencies:
- dependency-name: socket.io-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-08 01:58:24 +00:00
GM
21f080f809
Merge pull request #134 from albertoxamin/dependabot/pip/backend/dev/requests-2.27.1
Bump requests from 2.26.0 to 2.27.1 in /backend
2022-01-08 02:55:53 +01:00
GM
a248493589
Merge pull request #129 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.26.8
Bump vue-i18n from 8.26.7 to 8.26.8 in /frontend
2022-01-08 02:55:23 +01:00
dependabot[bot]
314a0faac1
Bump requests from 2.26.0 to 2.27.1 in /backend
Bumps [requests](https://github.com/psf/requests) from 2.26.0 to 2.27.1.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.26.0...v2.27.1)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-06 04:18:09 +00:00
dependabot[bot]
202360cec7
Bump vue-i18n from 8.26.7 to 8.26.8 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.26.7 to 8.26.8.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.26.7...v8.26.8)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-29 04:20:57 +00:00
Giulio
697e597cf9 fix pytest to work locally 2021-12-19 17:37:46 +01:00
Giulio
70a2c0609a fix setaccio 2021-12-18 15:38:15 +01:00
Giulio
c043c2036f update node dependencies 2021-12-18 02:52:31 +01:00
Giulio
3ce7913e47 fix apache kid - sbornia - cat balou 2021-12-18 02:50:19 +01:00
Giulio
a83869f9bc fix report and replay 2021-12-18 01:15:14 +01:00
Giulio
852701bc03 update hastebin api
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-12-17 23:56:41 +01:00
Giulio
88b5db2afe chat emit report confirm 2021-12-17 22:47:03 +01:00
Giulio
93794671f3 fix report webhook 2021-12-13 18:01:01 +01:00
Giulio
d14afb495e Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.4.2' into dev 2021-12-12 15:51:54 +01:00
Giulio
0e02343da9 better 2021-12-12 15:50:58 +01:00
dependabot[bot]
93343f3090
Bump workbox-webpack-plugin from 6.3.0 to 6.4.2 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.3.0 to 6.4.2.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.3.0...v6.4.2)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-12 09:56:30 +00:00
Giulio
32feae4601 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/eventlet-0.33.0' into dev 2021-12-12 10:52:13 +01:00
Giulio
966d327c50 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue/cli-service-4.5.15' into dev 2021-12-12 10:51:53 +01:00
Giulio
0cea402a4d Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-babel-4.5.15' into dev 2021-12-12 10:51:39 +01:00
Giulio
8002801cde Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.26.7' into dev 2021-12-12 10:51:14 +01:00
Giulio
cec0f060c1 making robots file optional 2021-12-12 10:43:28 +01:00
Giulio
190d872e29 fix miniera abbandonata 2021-12-11 19:02:41 +01:00
dependabot[bot]
161cde9498
Bump eventlet from 0.32.0 to 0.33.0 in /backend
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.32.0 to 0.33.0.
- [Release notes](https://github.com/eventlet/eventlet/releases)
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.32.0...v0.33.0)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-17 04:16:40 +00:00
dependabot[bot]
5aa446dc47
Bump @vue/cli-service from 4.5.14 to 4.5.15 in /frontend
Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.14 to 4.5.15.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.15/packages/@vue/cli-service)

---
updated-dependencies:
- dependency-name: "@vue/cli-service"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-09 10:35:11 +00:00
dependabot[bot]
1301af8edf
Bump @vue/cli-plugin-babel from 4.5.14 to 4.5.15 in /frontend
Bumps [@vue/cli-plugin-babel](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-babel) from 4.5.14 to 4.5.15.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.15/packages/@vue/cli-plugin-babel)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-babel"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-09 10:34:55 +00:00
dependabot[bot]
b0efec761f
Bump vue-i18n from 8.26.5 to 8.26.7 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.26.5 to 8.26.7.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.26.5...v8.26.7)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-09 10:34:49 +00:00
Alberto Xamin
d1fe45095b
Merge pull request #117 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-pwa-4.5.15 2021-11-09 12:32:04 +02:00
dependabot[bot]
007f865c38
Bump @vue/cli-plugin-pwa from 4.5.14 to 4.5.15 in /frontend
Bumps [@vue/cli-plugin-pwa](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-pwa) from 4.5.14 to 4.5.15.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.15/packages/@vue/cli-plugin-pwa)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-pwa"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-08 16:34:17 +00:00
Alberto Xamin
c0054ab353
Merge pull request #116 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-router-4.5.15
Bump @vue/cli-plugin-router from 4.5.14 to 4.5.15 in /frontend
2021-11-08 18:29:32 +02:00
dependabot[bot]
47f9b99d0c
Bump @vue/cli-plugin-router from 4.5.14 to 4.5.15 in /frontend
Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 4.5.14 to 4.5.15.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.15/packages/@vue/cli-plugin-router)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-router"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-07 08:23:40 +00:00
Alberto Xamin
8272a7505b
Merge pull request #114 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-eslint-4.5.15
Bump @vue/cli-plugin-eslint from 4.5.14 to 4.5.15 in /frontend
2021-11-07 10:20:34 +02:00
dependabot[bot]
ea98f95714
Bump @vue/cli-plugin-eslint from 4.5.14 to 4.5.15 in /frontend
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.14 to 4.5.15.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.15/packages/@vue/cli-plugin-eslint)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-eslint"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-29 04:23:42 +00:00
Alberto Xamin
b3d00033dc
Merge pull request #113 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-router-3.5.3
Bump vue-router from 3.5.2 to 3.5.3 in /frontend
2021-10-27 10:30:39 +03:00
dependabot[bot]
1042d43904
Bump vue-router from 3.5.2 to 3.5.3 in /frontend
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.5.2...v3.5.3)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-27 04:24:42 +00:00
Alberto Xamin
be535704a1
Merge pull request #112 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.20.0
Bump eslint-plugin-vue from 7.19.1 to 7.20.0 in /frontend
2021-10-24 15:03:28 +03:00
dependabot[bot]
4970b7f7e4
Bump eslint-plugin-vue from 7.19.1 to 7.20.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.19.1 to 7.20.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.19.1...v7.20.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-21 04:21:36 +00:00
Alberto Xamin
82e9e1fe8b
Merge pull request #111 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-pwa-4.5.14 2021-10-20 10:17:54 +03:00
dependabot[bot]
d0b9f31a55
Bump @vue/cli-plugin-pwa from 4.5.13 to 4.5.14 in /frontend
Bumps [@vue/cli-plugin-pwa](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-pwa) from 4.5.13 to 4.5.14.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.14/packages/@vue/cli-plugin-pwa)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-pwa"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 04:31:28 +00:00
Alberto Xamin
4c04460de0
Merge pull request #107 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-babel-4.5.14
Bump @vue/cli-plugin-babel from 4.5.13 to 4.5.14 in /frontend
2021-10-15 14:02:05 +03:00
dependabot[bot]
63ced4b014
Bump @vue/cli-plugin-babel from 4.5.13 to 4.5.14 in /frontend
Bumps [@vue/cli-plugin-babel](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-babel) from 4.5.13 to 4.5.14.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.14/packages/@vue/cli-plugin-babel)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-babel"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-15 10:56:29 +00:00
Alberto Xamin
71f32bbfea
Merge pull request #105 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-service-4.5.14
Bump @vue/cli-service from 4.5.13 to 4.5.14 in /frontend
2021-10-15 13:52:41 +03:00
Alberto Xamin
ab57537c17
Merge pull request #108 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-eslint-4.5.14
Bump @vue/cli-plugin-eslint from 4.5.13 to 4.5.14 in /frontend
2021-10-15 13:51:55 +03:00
dependabot[bot]
3f1859a137
Bump @vue/cli-plugin-eslint from 4.5.13 to 4.5.14 in /frontend
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.13 to 4.5.14.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.14/packages/@vue/cli-plugin-eslint)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-eslint"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-15 04:26:46 +00:00
dependabot[bot]
d58a38c169
Bump @vue/cli-service from 4.5.13 to 4.5.14 in /frontend
Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.13 to 4.5.14.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.14/packages/@vue/cli-service)

---
updated-dependencies:
- dependency-name: "@vue/cli-service"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-15 04:25:07 +00:00
Alberto Xamin
949ba1a5e6
Merge pull request #104 from albertoxamin/dependabot/pip/backend/dev/certifi-2021.10.8 2021-10-11 08:14:00 +03:00
dependabot[bot]
de39971caf
Bump certifi from 2021.5.30 to 2021.10.8 in /backend
Bumps [certifi](https://github.com/certifi/python-certifi) from 2021.5.30 to 2021.10.8.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/compare/2021.05.30...2021.10.08)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-11 04:25:36 +00:00
Giulio
1cdb524255 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.19.1' into dev 2021-10-07 16:25:52 +02:00
Alberto Xamin
7f9e0bd964
work on replays
Co-authored-by: GM <giulio.migani@studenti.unitn.it>
2021-10-07 16:53:53 +03:00
dependabot[bot]
d2223aafcb
Bump eslint-plugin-vue from 7.19.0 to 7.19.1 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.19.0 to 7.19.1.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.19.0...v7.19.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-07 04:25:36 +00:00
Alberto Xamin
fa983d44dc
Merge pull request #102 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.19.0
Bump eslint-plugin-vue from 7.18.0 to 7.19.0 in /frontend
2021-10-05 07:58:26 +03:00
dependabot[bot]
4b8e036751
Bump eslint-plugin-vue from 7.18.0 to 7.19.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.18.0 to 7.19.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.18.0...v7.19.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-05 04:28:20 +00:00
Alberto Xamin
ac8129b22f
Merge pull request #101 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.26.5
Bump vue-i18n from 8.26.4 to 8.26.5 in /frontend
2021-10-04 14:36:58 +03:00
dependabot[bot]
56fbae07ea
Bump vue-i18n from 8.26.4 to 8.26.5 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.26.4 to 8.26.5.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.26.4...v8.26.5)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-04 04:28:09 +00:00
Alberto Xamin
d4a6ca48af
Merge pull request #99 from albertoxamin/dependabot/pip/backend/dev/greenlet-1.1.2
Bump greenlet from 1.1.1 to 1.1.2 in /backend
2021-10-01 20:51:34 +03:00
Alberto Xamin
cbc8619cf5
Merge pull request #100 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.26.4
Bump vue-i18n from 8.26.2 to 8.26.4 in /frontend
2021-10-01 20:51:13 +03:00
dependabot[bot]
8e0d291307
Bump vue-i18n from 8.26.2 to 8.26.4 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.26.2 to 8.26.4.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.26.2...v8.26.4)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-01 04:25:04 +00:00
dependabot[bot]
89bfd34abe
Bump greenlet from 1.1.1 to 1.1.2 in /backend
Bumps [greenlet](https://github.com/python-greenlet/greenlet) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/python-greenlet/greenlet/releases)
- [Changelog](https://github.com/python-greenlet/greenlet/blob/master/CHANGES.rst)
- [Commits](https://github.com/python-greenlet/greenlet/compare/1.1.1...1.1.2)

---
updated-dependencies:
- dependency-name: greenlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-30 04:25:19 +00:00
Alberto Xamin
225a18d1a5
Merge pull request #95 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.18.0
Bump eslint-plugin-vue from 7.17.0 to 7.18.0 in /frontend
2021-09-29 14:40:40 +03:00
Alberto Xamin
6755b06fc7
Merge pull request #98 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.26.2
Bump vue-i18n from 8.25.1 to 8.26.2 in /frontend
2021-09-29 14:40:30 +03:00
dependabot[bot]
3522bf804d
Bump vue-i18n from 8.25.1 to 8.26.2 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.25.1 to 8.26.2.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.25.1...v8.26.2)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-29 04:23:32 +00:00
Alberto Xamin
878333746e
show desc if there is only one card, makes it easier on mobile 2021-09-23 18:02:49 +03:00
dependabot[bot]
70b6f6a8e3
Bump eslint-plugin-vue from 7.17.0 to 7.18.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.17.0 to 7.18.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.17.0...v7.18.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-20 04:31:59 +00:00
Alberto Xamin
b43e26805c
Merge pull request #94 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-clipboard2-0.3.3
Bump vue-clipboard2 from 0.3.2 to 0.3.3 in /frontend
2021-09-17 14:54:31 +03:00
dependabot[bot]
2fa748ded8
Bump vue-clipboard2 from 0.3.2 to 0.3.3 in /frontend
Bumps [vue-clipboard2](https://github.com/Inndy/vue-clipboard2) from 0.3.2 to 0.3.3.
- [Release notes](https://github.com/Inndy/vue-clipboard2/releases)
- [Changelog](https://github.com/Inndy/vue-clipboard2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Inndy/vue-clipboard2/compare/v0.3.2...v0.3.3)

---
updated-dependencies:
- dependency-name: vue-clipboard2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-16 04:20:57 +00:00
Alberto Xamin
64f4fef568
Merge pull request #93 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.25.1
Bump vue-i18n from 8.25.0 to 8.25.1 in /frontend
2021-09-14 17:01:05 +03:00
dependabot[bot]
10824ed1a3
Bump vue-i18n from 8.25.0 to 8.25.1 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.25.0 to 8.25.1.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.25.0...v8.25.1)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-14 04:22:52 +00:00
Alberto Xamin
45fcb4db5e
Merge pull request #92 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-clipboard2-0.3.2
Bump vue-clipboard2 from 0.3.1 to 0.3.2 in /frontend
2021-09-13 16:48:51 +03:00
dependabot[bot]
e12e53d38a
Bump vue-clipboard2 from 0.3.1 to 0.3.2 in /frontend
Bumps [vue-clipboard2](https://github.com/Inndy/vue-clipboard2) from 0.3.1 to 0.3.2.
- [Release notes](https://github.com/Inndy/vue-clipboard2/releases)
- [Changelog](https://github.com/Inndy/vue-clipboard2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Inndy/vue-clipboard2/compare/v0.3.1...v0.3.2)

---
updated-dependencies:
- dependency-name: vue-clipboard2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-13 04:27:44 +00:00
Giulio
25a2b2a143 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.3.0' into dev 2021-09-10 11:55:20 +02:00
Giulio
560f8cd69a Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/socket.io-client-4.2.0' into dev 2021-09-10 11:55:16 +02:00
Giulio
ab5494bac8 Merge remote-tracking branch 'origin/dependabot/pip/backend/dev/pytest-6.2.5' into dev 2021-09-10 11:55:10 +02:00
dependabot[bot]
41a8abcb1e
Bump workbox-webpack-plugin from 6.2.4 to 6.3.0 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.2.4 to 6.3.0.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.2.4...v6.3.0)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-10 04:27:21 +00:00
dependabot[bot]
accd168124
Bump pytest from 6.2.4 to 6.2.5 in /backend
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.4 to 6.2.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.4...6.2.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-02 19:44:09 +00:00
Alberto Xamin
7779066e9b
replay on hastebin and discord 2021-09-02 22:39:26 +03:00
Alberto Xamin
1fe7f05680
Merge pull request #90 from albertoxamin/dependabot/pip/backend/dev/eventlet-0.32.0
Bump eventlet from 0.31.1 to 0.32.0 in /backend
2021-09-02 11:03:27 +03:00
dependabot[bot]
bde6bc0557
Bump eventlet from 0.31.1 to 0.32.0 in /backend
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.31.1 to 0.32.0.
- [Release notes](https://github.com/eventlet/eventlet/releases)
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.31.1...v0.32.0)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-02 04:15:49 +00:00
Alberto Xamin
acc6532648
replay logic 2021-09-01 14:36:24 +03:00
Alberto Xamin
ad27e067e9
add rng to init for tests 2021-09-01 12:33:39 +03:00
Alberto Xamin
ac55dadc9d
each game has now a different rng 2021-09-01 12:28:15 +03:00
Alberto Xamin
aaec015a6c
fix private lobbies 2021-09-01 12:07:27 +03:00
dependabot[bot]
ef6c43a9ad
Bump socket.io-client from 4.1.3 to 4.2.0 in /frontend
Bumps [socket.io-client](https://github.com/socketio/socket.io-client) from 4.1.3 to 4.2.0.
- [Release notes](https://github.com/socketio/socket.io-client/releases)
- [Changelog](https://github.com/socketio/socket.io-client/blob/master/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-client/compare/4.1.3...4.2.0)

---
updated-dependencies:
- dependency-name: socket.io-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-31 04:22:58 +00:00
Alberto Xamin
76621efb40
Merge pull request #87 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.17.0 2021-08-27 08:44:30 +03:00
dependabot[bot]
3205388d1d
Bump eslint-plugin-vue from 7.16.0 to 7.17.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.16.0 to 7.17.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.16.0...v7.17.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-27 04:23:42 +00:00
Alberto Xamin
518a7092c7
add startwith seed 2021-08-24 20:05:04 +03:00
Giulio
2175b6a9ff fix ricercato 2021-08-21 16:40:23 +02:00
Giulio
bab8a10b25 fix mebot when a bot must remain bot 2021-08-21 12:40:03 +02:00
Giulio
88defd46a8 fix Elena Fuente & Sbornia 2021-08-21 11:47:19 +02:00
Alberto Xamin
1871030bf1 fix username input 2021-08-20 14:36:37 +03:00
Alberto Xamin
6922470fea fix elena fuente duello/indiani 2021-08-20 14:28:28 +03:00
Alberto Xamin
a8ffa008af add card purchase sound 2021-08-20 12:23:18 +03:00
Alberto Xamin
be7656d091 add suit color for windows 2021-08-20 12:03:04 +03:00
Alberto Xamin
c3d3cf8171 add tests for all the base players 2021-08-20 11:36:26 +03:00
Alberto Xamin
7825a7ac85 add some character test 2021-08-19 11:18:08 +03:00
Alberto Xamin
80a9a61251 add discord notifications 2021-08-19 10:36:28 +03:00
Giulio
6e8d038a6a Merge branch 'main' into dev 2021-08-18 21:27:08 +02:00
Alberto Xamin
4c00131f32
Merge pull request #83 from albertoxamin/dependabot/npm_and_yarn/frontend/socket.io-parser-3.3.2
Bump socket.io-parser from 3.3.1 to 3.3.2 in /frontend
2021-08-18 10:30:11 +03:00
Alberto Xamin
ab32cca43c
Merge pull request #82 from albertoxamin/dependabot/npm_and_yarn/frontend/url-parse-1.5.3
Bump url-parse from 1.5.1 to 1.5.3 in /frontend
2021-08-18 10:29:01 +03:00
Alberto Xamin
1182e50bcd
Merge pull request #84 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/core-js-3.16.2
Bump core-js from 3.16.1 to 3.16.2 in /frontend
2021-08-18 10:28:34 +03:00
dependabot[bot]
20aa04cd28
Bump core-js from 3.16.1 to 3.16.2 in /frontend
Bumps [core-js](https://github.com/zloirock/core-js) from 3.16.1 to 3.16.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.16.1...v3.16.2)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-18 04:25:43 +00:00
Alberto Xamin
bee1ba6986
fix kit carlson 2021-08-14 22:49:31 +03:00
dependabot[bot]
18bba8c4be
Bump socket.io-parser from 3.3.1 to 3.3.2 in /frontend
Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/socketio/socket.io-parser/releases)
- [Changelog](https://github.com/socketio/socket.io-parser/blob/3.3.2/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-parser/compare/3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: socket.io-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-13 06:17:19 +00:00
dependabot[bot]
60537ca168
Bump url-parse from 1.5.1 to 1.5.3 in /frontend
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-13 06:16:58 +00:00
Alberto Xamin
782a15d394
Merge pull request #78 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.16.0 2021-08-13 09:16:03 +03:00
Alberto Xamin
7c4cf5abf7
Merge pull request #80 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.2.4 2021-08-13 09:15:36 +03:00
Alberto Xamin
3027e68eb5
Merge pull request #81 from albertoxamin/dependabot/npm_and_yarn/frontend/path-parse-1.0.7 2021-08-13 09:15:25 +03:00
dependabot[bot]
5b5975c253
Bump path-parse from 1.0.6 to 1.0.7 in /frontend
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-13 01:44:25 +00:00
dependabot[bot]
8b4537cabb
Bump workbox-webpack-plugin from 6.2.2 to 6.2.4 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.2.2 to 6.2.4.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.2.2...v6.2.4)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-12 04:27:58 +00:00
dependabot[bot]
1dd991ee17
Bump eslint-plugin-vue from 7.15.1 to 7.16.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.15.1 to 7.16.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.15.1...v7.16.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-11 04:20:04 +00:00
Alberto Xamin
e94561afb3
Merge pull request #74 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.2.2
Bump workbox-webpack-plugin from 6.1.5 to 6.2.2 in /frontend
2021-08-09 18:26:54 +03:00
Alberto Xamin
9d4cb3f7ee
Merge pull request #75 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/core-js-3.16.1
Bump core-js from 3.16.0 to 3.16.1 in /frontend
2021-08-09 18:15:37 +03:00
dependabot[bot]
1214624ac0
Bump workbox-webpack-plugin from 6.1.5 to 6.2.2 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.1.5 to 6.2.2.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.1.5...v6.2.2)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 15:15:19 +00:00
dependabot[bot]
92758b94e5
Bump core-js from 3.16.0 to 3.16.1 in /frontend
Bumps [core-js](https://github.com/zloirock/core-js) from 3.16.0 to 3.16.1.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.16.0...v3.16.1)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 15:13:49 +00:00
Alberto Xamin
9e5b29f0b9
Merge pull request #73 from albertoxamin/dependabot/pip/backend/dev/greenlet-1.1.1
Bump greenlet from 1.1.0 to 1.1.1 in /backend
2021-08-09 18:13:12 +03:00
dependabot[bot]
db682a8f1b
Bump greenlet from 1.1.0 to 1.1.1 in /backend
Bumps [greenlet](https://github.com/python-greenlet/greenlet) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/python-greenlet/greenlet/releases)
- [Changelog](https://github.com/python-greenlet/greenlet/blob/master/CHANGES.rst)
- [Commits](https://github.com/python-greenlet/greenlet/compare/1.1.0...1.1.1)

---
updated-dependencies:
- dependency-name: greenlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 15:11:47 +00:00
Alberto Xamin
b77c56763d
Fix multi death
Co-authored-by: GM <giulio.migani@studenti.unitn.it>
2021-08-09 17:58:36 +03:00
Alberto Xamin
87f37dbf90
Merge pull request #71 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.15.1
Bump eslint-plugin-vue from 7.14.0 to 7.15.1 in /frontend
2021-08-03 11:21:51 +03:00
dependabot[bot]
2ab8540894
Bump eslint-plugin-vue from 7.14.0 to 7.15.1 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.14.0 to 7.15.1.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.14.0...v7.15.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-03 04:26:32 +00:00
Alberto Xamin
4a1b67c2bc
Merge pull request #67 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/core-js-3.16.0
Bump core-js from 3.15.2 to 3.16.0 in /frontend
2021-07-30 09:24:33 +02:00
dependabot[bot]
b72f14c69f
Bump core-js from 3.15.2 to 3.16.0 in /frontend
Bumps [core-js](https://github.com/zloirock/core-js) from 3.15.2 to 3.16.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.15.2...v3.16.0)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-30 04:31:53 +00:00
Alberto Xamin
c0728f0225
add test gatling win 2021-07-21 08:33:38 +03:00
Alberto Xamin
ef99a55685
allow bots to use panico and cat balou on self 2021-07-20 15:38:43 +03:00
Alberto Xamin
655fde3e2b
add tests on win conditions 2021-07-20 14:10:34 +03:00
Giulio
1842b2c412 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.14.0' into dev 2021-07-20 11:31:54 +02:00
Alberto Xamin
d85788c43c
Merge pull request #66 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.25.0
Bump vue-i18n from 8.24.5 to 8.25.0 in /frontend
2021-07-19 21:08:54 +03:00
dependabot[bot]
e933265851
Bump vue-i18n from 8.24.5 to 8.25.0 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.24.5 to 8.25.0.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.24.5...v8.25.0)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-19 04:22:50 +00:00
dependabot[bot]
c0923cdbf7
Bump eslint-plugin-vue from 7.13.0 to 7.14.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.13.0 to 7.14.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.13.0...v7.14.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-19 04:22:19 +00:00
Giulio
0b114817e2 Merge branch 'dependabot/npm_and_yarn/frontend/dev/socket.io-client-4.1.3' into dev 2021-07-16 11:33:21 +02:00
Giulio
f3e2015939 Merge branch 'dependabot/pip/backend/dev/eventlet-0.31.1' into dev 2021-07-16 11:33:16 +02:00
GM
db87fecf6f
Merge pull request #62 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.13.0
Bump eslint-plugin-vue from 7.12.1 to 7.13.0 in /frontend
2021-07-16 11:03:57 +02:00
dependabot[bot]
3d2a9b5922
Bump eventlet from 0.31.0 to 0.31.1 in /backend
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.31.0 to 0.31.1.
- [Release notes](https://github.com/eventlet/eventlet/releases)
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.31.0...v0.31.1)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-13 04:20:07 +00:00
dependabot[bot]
a3c5917302
Bump socket.io-client from 4.1.2 to 4.1.3 in /frontend
Bumps [socket.io-client](https://github.com/socketio/socket.io-client) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/socketio/socket.io-client/releases)
- [Changelog](https://github.com/socketio/socket.io-client/blob/master/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-client/compare/4.1.2...4.1.3)

---
updated-dependencies:
- dependency-name: socket.io-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-12 04:30:29 +00:00
Alberto Xamin
cc4975851d
fix zaino save 2021-07-10 10:40:42 +02:00
dependabot[bot]
8309958a75
Bump eslint-plugin-vue from 7.12.1 to 7.13.0 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.12.1 to 7.13.0.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.12.1...v7.13.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-07 04:29:00 +00:00
Alberto Xamin
285cd28660
tests for all base cards 2021-07-04 17:29:04 +02:00
Alberto Xamin
b9d8fc5f7f
add more tests 2021-07-04 14:48:22 +02:00
Alberto Xamin
2be82a7535
fix tests 2021-07-04 14:15:55 +02:00
Alberto Xamin
b307f2bb34
add more tests 2021-07-04 12:20:38 +02:00
Giulio
70740b8493 fix diamond panico 2021-07-03 17:59:50 +02:00
Alberto Xamin
22720c8e12
add bang filter apache 2021-07-02 19:08:27 +02:00
Alberto Xamin
3c3bcfbea4
Legge del west
Co-authored-by: GM <giulio.migani@studenti.unitn.it>
2021-07-02 18:57:17 +02:00
Alberto Xamin
e6dda2b04b
fix tests 2021-07-01 18:11:02 +02:00
Alberto Xamin
109400d217
add room name to debug 2021-07-01 18:02:15 +02:00
Alberto Xamin
276e1c8275
can't play card message 2021-07-01 17:46:16 +02:00
Alberto Xamin
bab5e47041
test barile 2021-07-01 10:06:55 +02:00
Alberto Xamin
8f12f95679
add game tests 2021-07-01 09:48:37 +02:00
Giulio
6185d506c3 refactor & fix of all ways of drawing cards 2021-06-30 23:39:37 +02:00
Alberto Xamin
3e752b352c
Merge pull request #61 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/core-js-3.15.2
Bump core-js from 3.15.1 to 3.15.2 in /frontend
2021-06-30 17:06:24 +02:00
dependabot[bot]
b2faf89ef3
Bump core-js from 3.15.1 to 3.15.2 in /frontend
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.15.1 to 3.15.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.15.2/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-29 14:29:30 +00:00
Alberto Xamin
bae36ccb35
fix dev image compilation 2021-06-29 14:51:28 +02:00
Alberto Xamin
9ca62bd5ba
fix imports 2021-06-29 14:48:33 +02:00
Alberto Xamin
2c794723c7
add backend tests 2021-06-29 14:30:05 +02:00
Giulio
afe14909b0 we write the role of who wins 2021-06-28 12:00:52 +02:00
Giulio
8f1f8a9698 excluding the sheriff from the wanted card 2021-06-28 11:04:50 +02:00
Giulio
03c3af44d9 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.12.1' into dev 2021-06-28 10:13:20 +02:00
dependabot[bot]
a83d1262b3
Bump eslint-plugin-vue from 7.11.1 to 7.12.1 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 7.11.1 to 7.12.1.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v7.11.1...v7.12.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-28 04:28:42 +00:00
Alberto Xamin
003e27222d
fix bang-bottiglia 2021-06-27 20:49:25 +02:00
Giulio
348e6a7f9c reset nuggets on death 2021-06-27 17:31:10 +02:00
Giulio
a61615c24e fix lucky duke & Rum 2021-06-27 16:32:31 +02:00
Giulio
1ce16a0753 use panico and cat balou on itself 2021-06-27 16:17:23 +02:00
Giulio
7f81276052 ricercato can target self 2021-06-27 14:35:37 +02:00
Giulio
4bb0ac2344 fix Dutch Will 2021-06-27 12:16:24 +02:00
Giulio
f01d31ed2d fix - sheriff kills deputy and loses gold rush equipment 2021-06-27 12:11:20 +02:00
Giulio
185984c364 fix give nuggets 2021-06-26 21:57:17 +02:00
Giulio
dc5cb286c0 edit & fix beer in gold rush 2021-06-26 16:44:14 +02:00
Giulio
83a61b7466 fix gold rush discard 2021-06-26 16:43:24 +02:00
Alberto Xamin
bdd38efcdc
Zaino save 2021-06-26 14:32:14 +02:00
Alberto Xamin
fc485642db
add gold rush to help 2021-06-26 14:24:08 +02:00
Alberto Xamin
0b3f726a60
update github actions and comments to the Dockerfile 2021-06-26 12:53:23 +02:00
Alberto Xamin
4e317728a4
test new slim docker image 2021-06-26 12:18:50 +02:00
Alberto Xamin
57e18a1121
separate builds 2021-06-26 11:25:19 +02:00
Alberto Xamin
35315516e3
pretty luzena frontend 2021-06-26 11:20:02 +02:00
Alberto Xamin
4d8fbb242a
fix ricercato and write more card usage 2021-06-26 11:00:19 +02:00
Alberto Xamin
5ff9b68e14
fix gold rush discard 2021-06-26 10:43:38 +02:00
Giulio
384ddce5dc updated the number of shop cards 2021-06-26 10:09:39 +02:00
Alberto Xamin
305efac192
fix cinturone and text 2021-06-25 18:55:28 +02:00
Alberto Xamin
283c732880
fix emporio 2021-06-25 17:26:34 +02:00
Alberto Xamin
8f8deb2f1c
fix cinturone 2021-06-25 17:21:31 +02:00
Alberto Xamin
24723faee3
chat write discard 2021-06-25 17:21:05 +02:00
Alberto Xamin
7dba5e6ada
fix ricercato 2021-06-25 17:14:33 +02:00
Alberto Xamin
2bb39311c3
emporio faster 2021-06-25 17:13:15 +02:00
Alberto Xamin
62863b38a0
scrap gold rush equipment 2021-06-25 17:02:15 +02:00
Alberto Xamin
38224af408
don't show players with high cost cards 2021-06-25 16:52:47 +02:00
Alberto Xamin
fcc5fa8bbd
disable autocomplete chat 2021-06-25 16:02:16 +02:00
Alberto Xamin
ec3b7bd356
don't recover from large damage 2021-06-25 15:52:53 +02:00
Alberto Xamin
49bb5ee4e5
sid choose cards before death 2021-06-25 15:51:21 +02:00
Alberto Xamin
847ae5187e
fix dottore 2021-06-25 15:13:58 +02:00
Alberto Xamin
a3db6169e6
better command suggestion 2021-06-25 14:52:59 +02:00
Alberto Xamin
abe6d1573d
add disconnected tip 2021-06-25 14:21:30 +02:00
Alberto Xamin
4fc3d57426
add beta label 2021-06-25 14:18:11 +02:00
Alberto Xamin
c1ba77d478
fix equipment layout bug 2021-06-24 18:13:22 +02:00
Alberto
1bbea0c7aa
Merge remote-tracking branch 'origin/gold-rush' into gold-rush 2021-06-24 18:02:49 +02:00
Alberto Xamin
4db85b0980
fix bicchierino bug and add birra missing text 2021-06-24 18:02:17 +02:00
Alberto Xamin
8bc8c025b5
bot purchasing cards 2021-06-24 18:01:44 +02:00
Giulio
edcc3085ad Merge branch 'dev' into main 2021-06-24 17:57:07 +02:00
Giulio
ca55909579 fix merge 2021-06-24 17:55:53 +02:00
Alberto Xamin
3954dcc804
Merge branch 'dev'
Conflicts:
	frontend/src/components/Player.vue
2021-06-24 17:49:55 +02:00
Alberto Xamin
843f8ee363
fix sid ketchum 2021-06-24 17:39:51 +02:00
Giulio
e5c629b5e5 cant-play ability 2021-06-24 17:33:04 +02:00
Giulio
82ca28b99d fix usage of ability 2021-06-24 15:57:33 +02:00
Giulio
9236a415d5 Merge branch 'dev' into gold-rush 2021-06-24 10:40:34 +02:00
Giulio
eeec08e0cc Merge branch 'dev' into main 2021-06-24 10:27:55 +02:00
Giulio
7a4e939eaf fix draw manette indentation again 2021-06-24 10:22:27 +02:00
Giulio
98c9f592b5 Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/frontend/dev/core-js-3.15.1' into dev 2021-06-24 09:58:39 +02:00
dependabot[bot]
88a5998056
Bump core-js from 3.15.0 to 3.15.1 in /frontend
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.15.0 to 3.15.1.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.15.1/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 04:29:46 +00:00
Giulio
be18263b8d Merge branch 'dev' into gold-rush 2021-06-22 16:45:35 +02:00
GM
40c60ff000
Merge pull request #58 from albertoxamin/dependabot/npm_and_yarn/frontend/color-string-1.5.5
Bump color-string from 1.5.4 to 1.5.5 in /frontend
2021-06-22 16:06:48 +02:00
Giulio
33b0158558 fix starting error 2021-06-22 16:03:41 +02:00
Alberto Xamin
14919ae476
Update docker-image.yml 2021-06-22 15:08:29 +02:00
Alberto Xamin
1f82ed8324
Update docker-image.yml 2021-06-22 15:06:43 +02:00
Alberto
8d839f1d57
update base docker image 2021-06-22 15:04:12 +02:00
dependabot[bot]
8193e81148
Bump color-string from 1.5.4 to 1.5.5 in /frontend
Bumps [color-string](https://github.com/Qix-/color-string) from 1.5.4 to 1.5.5.
- [Release notes](https://github.com/Qix-/color-string/releases)
- [Changelog](https://github.com/Qix-/color-string/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Qix-/color-string/compare/1.5.4...1.5.5)

---
updated-dependencies:
- dependency-name: color-string
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-22 09:03:01 +00:00
Alberto
f89ba22435
update github action for main image 2021-06-22 11:01:21 +02:00
Alberto Xamin
ebab3b49d1
Merge pull request #57 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-router-3.5.2
Bump vue-router from 3.5.1 to 3.5.2 in /frontend
2021-06-22 10:59:25 +02:00
Alberto
102dc3873e
add back other stuff 2021-06-22 10:35:45 +02:00
Alberto Xamin
63842fea2a
Update Dockerfile 2021-06-22 10:32:18 +02:00
Alberto Xamin
5b6ac76d24
Update Dockerfile 2021-06-22 10:28:59 +02:00
Alberto
0a548e5a30
Merge remote-tracking branch 'origin/dev' into dev 2021-06-22 10:24:25 +02:00
Alberto
c39e323fd0
test smaller dockerfile 2021-06-22 10:24:02 +02:00
Alberto Xamin
a263fe83a9
Update dev-image.yml 2021-06-22 10:16:53 +02:00
Alberto
d35adf482f
push the right docker file 2021-06-22 10:13:26 +02:00
Alberto Xamin
401fe96988
Update dev-image.yml 2021-06-22 10:06:54 +02:00
Alberto
63b6437248
add apt get install dependencies 2021-06-22 10:03:37 +02:00
dependabot[bot]
06325154c9
Bump vue-router from 3.5.1 to 3.5.2 in /frontend
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.5.1...v3.5.2)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-22 04:26:49 +00:00
Alberto Xamin
242d1a8fc5
Update dev-image.yml 2021-06-21 17:27:25 +02:00
Alberto Xamin
d730bb64dd
Update dev-image.yml 2021-06-21 17:25:27 +02:00
Alberto Xamin
1edf0d72ec
Update dev-image.yml 2021-06-21 17:24:11 +02:00
Alberto Xamin
9d412e35ee
Update dev-image.yml 2021-06-21 16:07:24 +02:00
Alberto Xamin
9f1dc376f4
Update dev-image.yml 2021-06-21 15:22:43 +02:00
Alberto Xamin
068ce5da00
Update dev-image.yml 2021-06-21 15:20:19 +02:00
Alberto Xamin
0c1659a4ca
Merge pull request #56 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/core-js-3.15.0
Bump core-js from 3.14.0 to 3.15.0 in /frontend
2021-06-21 15:10:08 +02:00
Alberto Xamin
ad13dc085e
Merge pull request #55 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.24.5
Bump vue-i18n from 8.24.4 to 8.24.5 in /frontend
2021-06-21 15:09:42 +02:00
dependabot[bot]
c9114493ee
Bump core-js from 3.14.0 to 3.15.0 in /frontend
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.14.0 to 3.15.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.15.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 04:29:29 +00:00
dependabot[bot]
dc1d39a66e
Bump vue-i18n from 8.24.4 to 8.24.5 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.24.4 to 8.24.5.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.24.4...v8.24.5)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-21 04:29:20 +00:00
Alberto Xamin
f11f5dde0a
usability fixes for small screens 2021-06-20 20:06:13 +02:00
Giulio
29aca8ecbb fix indentation again 2021-06-20 19:49:31 +02:00
Giulio
b2ea62bce9 Merge branch 'dev' into gold-rush 2021-06-20 18:56:11 +02:00
Alberto Xamin
11363a898f
fix vice ricercato 2021-06-20 18:48:42 +02:00
Alberto Xamin
9c0183ea78
disable cancel for bottiglia e complice 2021-06-20 18:44:21 +02:00
Alberto
7c34761f65
Merge remote-tracking branch 'origin/main' into main 2021-06-20 18:29:29 +02:00
Alberto
f3857311d5
add translation tip 2021-06-20 18:29:05 +02:00
Alberto Xamin
a0e8e28c20
fix breaking bug gold rush 2021-06-20 18:23:06 +02:00
Giulio
47ea9c6903 fix icon logic 2021-06-20 18:22:24 +02:00
Giulio
307ce461db localize theme 2021-06-20 17:45:19 +02:00
Alberto Xamin
9b057bb468
discard others cards 2021-06-20 17:44:29 +02:00
Giulio
40197d486a fix draw manette indentation 2021-06-20 16:25:17 +02:00
Giulio
997337581e fix draw notify indentation 2021-06-20 16:21:00 +02:00
Alberto Xamin
09298f8d10
fix return indentation 2021-06-20 15:11:07 +02:00
Alberto Xamin
8fd0ea3fb6
return special success 2021-06-20 15:06:09 +02:00
Alberto Xamin
1b5edfa736
show player money 2021-06-20 15:04:41 +02:00
Alberto Xamin
4a8ff39000
add menu tips and auto set the language based on the browser lang 2021-06-20 11:37:57 +02:00
Alberto
26e9e4c7ce
Merge remote-tracking branch 'origin/dev' into gold-rush 2021-06-20 11:04:07 +02:00
Alberto Xamin
564c5d6821
refactor special abilities 2021-06-20 11:00:17 +02:00
Alberto Xamin
293b458529
Pretty luzena, gold rush new turn and verbose rum 2021-06-20 10:32:36 +02:00
Giulio
467162eb6e reset more card 2021-06-20 03:22:12 +02:00
Giulio
1149aa9dc7 fix multiple gregs and herbs 2021-06-20 02:42:06 +02:00
Giulio
7c4eb60808 fix bot in status page 2021-06-20 00:02:00 +02:00
Alberto Xamin
5948a7ad74
more mobile safari fixes + username suggestions 2021-06-19 19:56:10 +02:00
Alberto Xamin
b984c55f40
fix for mobile safari 2021-06-19 19:25:43 +02:00
Giulio
62174ee74e Merge branch 'dev' into gold-rush 2021-06-19 19:09:57 +02:00
Alberto Xamin
cb1824c0e4
add desc and bug fixes
Co-authored-by: GM <giulio.migani@studenti.unitn.it>
2021-06-19 18:48:39 +02:00
Alberto Xamin
98cf684b3f
some improvements to status page 2021-06-19 17:32:54 +02:00
Alberto Xamin
2e4d7c5ede
blacklist 2021-06-19 17:12:18 +02:00
Alberto Xamin
413f3ae54b
superpowers
Co-authored-by: GM <giulio.migani@studenti.unitn.it>
2021-06-19 16:46:50 +02:00
Alberto Xamin
1ac37f9039
hide bad rooms 2021-06-19 14:00:42 +02:00
Alberto Xamin
87896298f3
Merge pull request #54 from albertoxamin/dev
dependency resolution
2021-06-18 22:26:05 +02:00
Giulio
679403aed2 fix engine socket
The client is using an unsupported version of the Socket.IO or Engine.IO protocols
2021-06-18 11:06:09 +02:00
GM
79420cc7cf
Merge pull request #50 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-service-4.5.13
Bump @vue/cli-service from 4.5.9 to 4.5.13 in /frontend
2021-06-18 01:57:09 +02:00
GM
bffe7c61e7
Merge pull request #51 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/workbox-webpack-plugin-6.1.5
Bump workbox-webpack-plugin from 6.0.2 to 6.1.5 in /frontend
2021-06-18 01:56:57 +02:00
dependabot[bot]
e9aba90db5
Bump workbox-webpack-plugin from 6.0.2 to 6.1.5 in /frontend
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 6.0.2 to 6.1.5.
- [Release notes](https://github.com/googlechrome/workbox/releases)
- [Commits](https://github.com/googlechrome/workbox/compare/v6.0.2...v6.1.5)

---
updated-dependencies:
- dependency-name: workbox-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 23:54:37 +00:00
dependabot[bot]
776f13696e
Bump @vue/cli-service from 4.5.9 to 4.5.13 in /frontend
Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.9 to 4.5.13.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.13/packages/@vue/cli-service)

---
updated-dependencies:
- dependency-name: "@vue/cli-service"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 23:54:21 +00:00
GM
570032dd90
Merge pull request #48 from albertoxamin/dependabot/pip/backend/dev/greenlet-1.1.0
Bump greenlet from 0.4.17 to 1.1.0 in /backend
2021-06-18 01:52:46 +02:00
dependabot[bot]
ef5834e269
Bump greenlet from 0.4.17 to 1.1.0 in /backend
Bumps [greenlet](https://github.com/python-greenlet/greenlet) from 0.4.17 to 1.1.0.
- [Release notes](https://github.com/python-greenlet/greenlet/releases)
- [Changelog](https://github.com/python-greenlet/greenlet/blob/master/CHANGES.rst)
- [Commits](https://github.com/python-greenlet/greenlet/compare/0.4.17...1.1.0)

---
updated-dependencies:
- dependency-name: greenlet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 23:48:52 +00:00
GM
112b9fe64e
Merge pull request #47 from albertoxamin/dependabot/npm_and_yarn/frontend/elliptic-6.5.4
Bump elliptic from 6.5.3 to 6.5.4 in /frontend
2021-06-18 01:47:54 +02:00
GM
dc7bc7ed81
Merge pull request #44 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-router-3.5.1
Bump vue-router from 3.4.9 to 3.5.1 in /frontend
2021-06-18 00:59:05 +02:00
GM
6ac1bc6f74
Merge pull request #42 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/socket.io-client-4.1.2
Bump socket.io-client from 3.0.3 to 4.1.2 in /frontend
2021-06-18 00:58:52 +02:00
dependabot[bot]
cb93e713e9
Bump socket.io-client from 3.0.3 to 4.1.2 in /frontend
Bumps [socket.io-client](https://github.com/socketio/socket.io-client) from 3.0.3 to 4.1.2.
- [Release notes](https://github.com/socketio/socket.io-client/releases)
- [Changelog](https://github.com/socketio/socket.io-client/blob/master/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-client/compare/3.0.3...4.1.2)

---
updated-dependencies:
- dependency-name: socket.io-client
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 22:56:27 +00:00
GM
f148fa0ce5
Merge pull request #43 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-pwa-4.5.13
Bump @vue/cli-plugin-pwa from 4.5.9 to 4.5.13 in /frontend
2021-06-18 00:53:39 +02:00
GM
fc4c63cdce
Merge pull request #45 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/eslint-plugin-vue-7.11.1
Bump eslint-plugin-vue from 6.2.2 to 7.11.1 in /frontend
2021-06-18 00:53:24 +02:00
GM
4b5a5df6b5
Merge pull request #46 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/register-service-worker-1.7.2
Bump register-service-worker from 1.7.1 to 1.7.2 in /frontend
2021-06-18 00:53:09 +02:00
dependabot[bot]
c1af1971df
Bump register-service-worker from 1.7.1 to 1.7.2 in /frontend
Bumps [register-service-worker](https://github.com/yyx990803/register-service-worker) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/yyx990803/register-service-worker/releases)
- [Changelog](https://github.com/yyx990803/register-service-worker/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yyx990803/register-service-worker/compare/v1.7.1...v1.7.2)

---
updated-dependencies:
- dependency-name: register-service-worker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 22:45:26 +00:00
dependabot[bot]
7aaf73c90f
Bump eslint-plugin-vue from 6.2.2 to 7.11.1 in /frontend
Bumps [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) from 6.2.2 to 7.11.1.
- [Release notes](https://github.com/vuejs/eslint-plugin-vue/releases)
- [Commits](https://github.com/vuejs/eslint-plugin-vue/compare/v6.2.2...v7.11.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-vue
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 22:45:17 +00:00
dependabot[bot]
dec219c86e
Bump vue-router from 3.4.9 to 3.5.1 in /frontend
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.4.9 to 3.5.1.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.4.9...v3.5.1)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 22:45:03 +00:00
dependabot[bot]
2eda81144c
Bump @vue/cli-plugin-pwa from 4.5.9 to 4.5.13 in /frontend
Bumps [@vue/cli-plugin-pwa](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-pwa) from 4.5.9 to 4.5.13.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.13/packages/@vue/cli-plugin-pwa)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-pwa"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 22:44:53 +00:00
GM
a64742e69f
Merge pull request #39 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-eslint-4.5.13
Bump @vue/cli-plugin-eslint from 4.5.9 to 4.5.13 in /frontend
2021-06-17 20:52:56 +02:00
dependabot[bot]
5b0878323f
Bump @vue/cli-plugin-eslint from 4.5.9 to 4.5.13 in /frontend
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.9 to 4.5.13.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.13/packages/@vue/cli-plugin-eslint)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-eslint"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 18:45:46 +00:00
GM
6566453bb0
Merge pull request #38 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-and-vue-template-compiler-2.6.14
Bump vue and vue-template-compiler in /frontend
2021-06-17 20:43:34 +02:00
dependabot[bot]
784bc57b66
Bump vue and vue-template-compiler in /frontend
Bumps [vue](https://github.com/vuejs/vue) and [vue-template-compiler](https://github.com/vuejs/vue). These dependencies needed to be updated together.

Updates `vue` from 2.6.12 to 2.6.14
- [Release notes](https://github.com/vuejs/vue/releases)
- [Commits](https://github.com/vuejs/vue/compare/v2.6.12...v2.6.14)

Updates `vue-template-compiler` from 2.6.12 to 2.6.14
- [Release notes](https://github.com/vuejs/vue/releases)
- [Commits](https://github.com/vuejs/vue/compare/v2.6.12...v2.6.14)

---
updated-dependencies:
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: vue-template-compiler
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 18:42:00 +00:00
GM
3cb2aef51c
Merge pull request #36 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue/cli-plugin-babel-4.5.13
Bump @vue/cli-plugin-babel from 4.5.9 to 4.5.13 in /frontend
2021-06-17 20:41:07 +02:00
GM
c32663a808
Merge pull request #37 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/core-js-3.14.0
Bump core-js from 3.7.0 to 3.14.0 in /frontend
2021-06-17 20:36:50 +02:00
Giulio
2a60e40501 Merge branch 'main' into dev 2021-06-17 19:43:11 +02:00
GM
089319a5f1
Merge pull request #40 from albertoxamin/dependabot/npm_and_yarn/frontend/y18n-4.0.3
Bump y18n from 4.0.0 to 4.0.3 in /frontend
2021-06-17 19:39:49 +02:00
GM
9ee1c5b3aa
Merge pull request #35 from albertoxamin/dependabot/npm_and_yarn/frontend/dev/vue-i18n-8.24.4
Bump vue-i18n from 8.22.2 to 8.24.4 in /frontend
2021-06-17 19:39:28 +02:00
GM
1f73ec17eb
Merge pull request #33 from albertoxamin/dependabot/pip/backend/dev/python-socketio-5.3.0
Bump python-socketio from 4.6.0 to 5.3.0 in /backend
2021-06-17 19:39:08 +02:00
dependabot[bot]
923325a356
Bump python-socketio from 4.6.0 to 5.3.0 in /backend
Bumps [python-socketio](https://github.com/miguelgrinberg/python-socketio) from 4.6.0 to 5.3.0.
- [Release notes](https://github.com/miguelgrinberg/python-socketio/releases)
- [Changelog](https://github.com/miguelgrinberg/python-socketio/blob/main/CHANGES.md)
- [Commits](https://github.com/miguelgrinberg/python-socketio/compare/v4.6.0...v5.3.0)

---
updated-dependencies:
- dependency-name: python-socketio
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:33:48 +00:00
GM
b88ed670e1
Merge pull request #27 from albertoxamin/dependabot/pip/dev/python-engineio-4.2.0
Bump python-engineio from 3.13.2 to 4.2.0
2021-06-17 19:33:21 +02:00
GM
612c05273a
Merge pull request #28 from albertoxamin/dependabot/pip/dev/certifi-2021.5.30
Bump certifi from 2020.11.8 to 2021.5.30
2021-06-17 19:33:01 +02:00
dependabot[bot]
4428b2d51d
Bump python-engineio from 3.13.2 to 4.2.0
Bumps [python-engineio](https://github.com/miguelgrinberg/python-engineio) from 3.13.2 to 4.2.0.
- [Release notes](https://github.com/miguelgrinberg/python-engineio/releases)
- [Changelog](https://github.com/miguelgrinberg/python-engineio/blob/main/CHANGES.md)
- [Commits](https://github.com/miguelgrinberg/python-engineio/compare/v3.13.2...v4.2.0)

---
updated-dependencies:
- dependency-name: python-engineio
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:29:28 +00:00
dependabot[bot]
245ffa2191
Bump certifi from 2020.11.8 to 2021.5.30
Bumps [certifi](https://github.com/certifi/python-certifi) from 2020.11.8 to 2021.5.30.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/compare/2020.11.08...2021.05.30)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:29:26 +00:00
GM
f7c0298832
Merge pull request #26 from albertoxamin/dependabot/pip/dev/six-1.16.0
Bump six from 1.15.0 to 1.16.0
2021-06-17 19:29:15 +02:00
GM
e301cd9169
Merge pull request #25 from albertoxamin/dependabot/pip/dev/eventlet-0.31.0
Bump eventlet from 0.29.1 to 0.31.0
2021-06-17 19:28:50 +02:00
dependabot[bot]
11d4b4e6e9
Bump elliptic from 6.5.3 to 6.5.4 in /frontend
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

---
updated-dependencies:
- dependency-name: elliptic
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:27:35 +00:00
dependabot[bot]
33040204b3
Bump y18n from 4.0.0 to 4.0.3 in /frontend
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.3.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/y18n-v4.0.3/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/compare/v4.0.0...y18n-v4.0.3)

---
updated-dependencies:
- dependency-name: y18n
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:27:17 +00:00
GM
a4bd427bc9
Merge pull request #24 from albertoxamin/dependabot/npm_and_yarn/frontend/url-parse-1.5.1
Bump url-parse from 1.4.7 to 1.5.1 in /frontend
2021-06-17 19:26:57 +02:00
GM
03418da608
Merge pull request #23 from albertoxamin/dependabot/npm_and_yarn/frontend/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21 in /frontend
2021-06-17 19:26:39 +02:00
dependabot[bot]
14b6a9057c
Bump core-js from 3.7.0 to 3.14.0 in /frontend
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.7.0 to 3.14.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.14.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:26:30 +00:00
dependabot[bot]
2a47f402aa
Bump @vue/cli-plugin-babel from 4.5.9 to 4.5.13 in /frontend
Bumps [@vue/cli-plugin-babel](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-babel) from 4.5.9 to 4.5.13.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.13/packages/@vue/cli-plugin-babel)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-babel"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:26:10 +00:00
dependabot[bot]
0c2930ec36
Bump vue-i18n from 8.22.2 to 8.24.4 in /frontend
Bumps [vue-i18n](https://github.com/kazupon/vue-i18n) from 8.22.2 to 8.24.4.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/v8.x/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/compare/v8.22.2...v8.24.4)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:25:43 +00:00
GM
162e11fc79 Update dependabot.yml 2021-06-17 19:21:45 +02:00
dependabot[bot]
09bc06ac1f
Bump six from 1.15.0 to 1.16.0
Bumps [six](https://github.com/benjaminp/six) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/benjaminp/six/releases)
- [Changelog](https://github.com/benjaminp/six/blob/master/CHANGES)
- [Commits](https://github.com/benjaminp/six/compare/1.15.0...1.16.0)

---
updated-dependencies:
- dependency-name: six
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:17:28 +00:00
dependabot[bot]
e281979ca4
Bump eventlet from 0.29.1 to 0.31.0
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.29.1 to 0.31.0.
- [Release notes](https://github.com/eventlet/eventlet/releases)
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/v0.29.1...v0.31.0)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:17:24 +00:00
GM
9efbdb2c8a
edit dependabot.yml 2021-06-17 19:02:00 +02:00
dependabot[bot]
c9fd9193c6
Bump url-parse from 1.4.7 to 1.5.1 in /frontend
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.1.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.1)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 16:54:40 +00:00
dependabot[bot]
2a9e737a63
Bump lodash from 4.17.20 to 4.17.21 in /frontend
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

---
updated-dependencies:
- dependency-name: lodash
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 16:54:22 +00:00
Alberto Xamin
d4ac6f7b2a
Merge pull request #18 from albertoxamin/dependabot/npm_and_yarn/frontend/hosted-git-info-2.8.9 2021-06-17 18:54:16 +02:00
Alberto Xamin
fd65ea5f86
Merge pull request #19 from albertoxamin/dependabot/npm_and_yarn/frontend/postcss-7.0.36 2021-06-17 18:54:05 +02:00
Alberto Xamin
22c040dc72
Merge pull request #20 from albertoxamin/dependabot/npm_and_yarn/frontend/ssri-6.0.2 2021-06-17 18:53:44 +02:00
Alberto Xamin
a16ce4c55b
Merge pull request #21 from albertoxamin/dependabot/npm_and_yarn/frontend/browserslist-4.16.6 2021-06-17 18:53:36 +02:00
Alberto Xamin
d55d7effe3
Merge pull request #22 from albertoxamin/dependabot/npm_and_yarn/frontend/dns-packet-1.3.4 2021-06-17 18:53:24 +02:00
dependabot[bot]
1fb77e6dfb
Bump dns-packet from 1.3.1 to 1.3.4 in /frontend
Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 1.3.1 to 1.3.4.
- [Release notes](https://github.com/mafintosh/dns-packet/releases)
- [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mafintosh/dns-packet/compare/v1.3.1...v1.3.4)

---
updated-dependencies:
- dependency-name: dns-packet
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 16:49:42 +00:00
dependabot[bot]
a5aca2bf34
Bump ssri from 6.0.1 to 6.0.2 in /frontend
Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

---
updated-dependencies:
- dependency-name: ssri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 16:49:41 +00:00
dependabot[bot]
ccbbfb0e7b
Bump browserslist from 4.14.7 to 4.16.6 in /frontend
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.14.7 to 4.16.6.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.14.7...4.16.6)

---
updated-dependencies:
- dependency-name: browserslist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 16:49:41 +00:00
dependabot[bot]
14cac2d41f
Bump postcss from 7.0.35 to 7.0.36 in /frontend
Bumps [postcss](https://github.com/postcss/postcss) from 7.0.35 to 7.0.36.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/7.0.35...7.0.36)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 16:49:40 +00:00
dependabot[bot]
fc91740bd7
Bump hosted-git-info from 2.8.8 to 2.8.9 in /frontend
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

---
updated-dependencies:
- dependency-name: hosted-git-info
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 16:49:39 +00:00
Alberto Xamin
a6174fee95
fix password bug 2021-06-17 18:32:55 +02:00
Alberto Xamin
a3d33827a7
dual birra 2021-06-17 18:02:48 +02:00
Alberto Xamin
d03afcbf0c
fix bottiglia bang 2021-06-17 17:49:55 +02:00
Giulio
7874446d40 Merge branch 'dev' into main 2021-06-17 17:48:52 +02:00
Alberto Xamin
9d6cf7a5fa
snake special 2021-06-17 17:45:25 +02:00
Alberto Xamin
2978da9e94
cloud special 2021-06-17 17:41:34 +02:00
Giulio
000cd93cb1 minor error while closing or destroying game 2021-06-17 17:37:34 +02:00
Alberto Xamin
a88d3ad802
Jacky Murieta special 2021-06-17 17:32:11 +02:00
Alberto Xamin
5fe7de3be7
SimeonPicos 2021-06-17 17:07:47 +02:00
Alberto Xamin
15bb99996c
Madam Yto 2021-06-17 15:51:45 +02:00
Alberto Xamin
28555509a3
Dutch Will 2021-06-17 15:45:20 +02:00
Alberto Xamin
e86de193c7
don bell 2021-06-17 15:37:04 +02:00
Alberto Xamin
ac438ec190
add characters 2021-06-17 15:32:05 +02:00
Giulio
09579b2239 Merge branch 'dev' into main 2021-06-17 10:23:39 +02:00
Alberto Xamin
8002a1e71b
getnuggets suggestion 2021-06-16 23:04:09 +02:00
Alberto
abdc6fe290
Merge branch 'dev' into gold-rush 2021-06-16 23:03:34 +02:00
Alberto Xamin
38b8a40655
bottiglia e complice 2021-06-16 22:58:55 +02:00
Alberto Xamin
374e963cec
Bicchierino working 2021-06-16 21:52:29 +02:00
Alberto Xamin
7e644cd456
all black cards working 2021-06-16 21:19:26 +02:00
Alberto Xamin
dab5718eab
command suggestion 2021-06-16 20:27:39 +02:00
Alberto
f65ffbd5d5
Merge branch 'dev' into gold-rush 2021-06-16 18:15:54 +02:00
Alberto Xamin
86656c4942
wait to close and other quality of life fixes 2021-06-16 18:15:08 +02:00
Alberto Xamin
7a1a2c64d5
gold rush equipment 2021-06-16 18:14:01 +02:00
Alberto Xamin
3e9e1d5d35
open and close shop 2021-06-16 17:38:11 +02:00
Alberto
849aaabb79
Merge branch 'dev' into gold-rush 2021-06-16 16:49:35 +02:00
Alberto
a4a5c61eba
working on usable black cards 2021-06-16 16:47:06 +02:00
Alberto Xamin
7f0f8bb5c1
fix doc holyday 2021-06-16 16:43:38 +02:00
Alberto Xamin
0e9c8ad028
easy debug room 2021-06-16 16:34:03 +02:00
Giulio
8cf1d536ca disable google translate 2021-06-16 13:11:33 +02:00
Alberto Xamin
b5ded346fb
Talismano e stivali 2021-06-15 23:13:37 +02:00
Alberto Xamin
a139a310fe
Piccone 2021-06-15 23:06:32 +02:00
Alberto Xamin
860d6ce3ca
Ferro di Cavallo 2021-06-15 23:04:19 +02:00
Alberto Xamin
8c57e87532
Cinturone 2021-06-15 23:01:39 +02:00
Alberto Xamin
f030808343
calumet 2021-06-15 22:34:15 +02:00
Alberto Xamin
682a9ed463
add some of the cards logic 2021-06-15 22:26:34 +02:00
Giulio
40e4d1df83 fix Cecchino 2021-06-15 22:13:38 +02:00
Alberto Xamin
445399d7b3
buy cards and earn nuggets on other player damage 2021-06-15 18:52:30 +02:00
Alberto Xamin
46456ed433
show cards in frontend 2021-06-15 18:10:48 +02:00
Alberto Xamin
8b9f095e4b
add black cards 2021-06-15 16:57:35 +02:00
Alberto Xamin
03557557b1
add brown cards in backend 2021-06-15 16:43:52 +02:00
Giulio
572ce3bc4c fix bot usable cards 2021-06-15 14:45:06 +02:00
Giulio
343af0a437 modify postMessage text 2021-06-13 00:35:47 +02:00
Giulio
2101e42661 Merge branch 'dev' into main 2021-06-12 23:35:22 +02:00
Giulio
19a8dcc17c add event on Help
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-12 16:31:01 +02:00
Giulio
b779cb21d0 add manette card event
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-12 16:02:09 +02:00
Giulio
3bb7db8e33 fixing bot, Whisky & Rissa
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-12 13:10:38 +02:00
Giulio
f7a527fcaf simplifying init
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-12 13:09:12 +02:00
Giulio
3aa786395a fix lang
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-12 13:07:46 +02:00
Giulio
01f0992363 fix setevent
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-12 13:07:11 +02:00
Giulio
cc01daa6e2 Merge branch 'dev' into main 2021-06-12 11:12:03 +02:00
Giulio
e636ee513e change the language of the HTML document dynamically 2021-06-12 11:11:48 +02:00
Giulio
1783fe5774 Merge branch 'dev' into main 2021-06-12 10:30:01 +02:00
Giulio
a506e0245d fix Elena Fuente & green cards 2021-06-12 10:27:18 +02:00
Giulio
bbd676e9bc managing touch to search 2021-06-12 10:17:50 +02:00
Giulio
b1b1456429 Merge branch 'dev' into main 2021-06-12 00:07:12 +02:00
Giulio
41dceb8e1e fix flip event with 3 players 2021-06-11 15:56:03 +02:00
Giulio
c446a02aac Merge branch 'dev' into main 2021-06-08 12:25:04 +02:00
Giulio
7ed97d5bc0 bug mezzogiorno di fuoco attacker 2021-06-08 12:24:51 +02:00
Giulio
5979221478 show the right icon when playing with three players 2021-06-08 12:24:19 +02:00
Giulio
069236286c unused function 2021-06-08 12:22:31 +02:00
Giulio
38d5048496 fix some bug 2021-06-08 11:03:01 +02:00
Giulio
5210638275 fix bot speed
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-07 23:52:14 +02:00
Giulio
e3e8316e85 fix miniera eng desc
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-07 23:51:57 +02:00
Giulio
baa31a8892 added nuova identità event
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-06-07 23:50:44 +02:00
Alberto Xamin
104daf2e4d
change vue logos and pictures 2021-06-07 22:18:56 +02:00
Alberto Xamin
7ff3895433
avoid bots taking over the server 2021-06-07 21:47:12 +02:00
Alberto Xamin
5f8b23e8f4
fix a bug with dark mode 2021-06-07 21:39:38 +02:00
Alberto Xamin
eecb42f337
fix dockerfile 2021-06-07 21:25:30 +02:00
Alberto Xamin
e37ab81206
fix build error 2021-06-07 20:40:24 +02:00
Alberto Xamin
6a23a1212a
trying to fix service worker 2021-06-07 20:08:02 +02:00
Alberto Xamin
98d64800fc
try adding update button again 2021-06-07 19:46:14 +02:00
Alberto Xamin
b7096d8646
tests on service worker 2021-06-07 18:40:05 +02:00
Alberto Xamin
ae6b6fbae4
server worker fix
Co-authored-by: GM <giulio.migani@studenti.unitn.it>
2021-06-07 18:28:04 +02:00
Alberto Xamin
4f4007873a
add discord btn 2021-06-07 17:35:14 +02:00
Giulio
b54956f672 respond fix 2021-06-06 19:24:44 +02:00
Giulio
74e4900dfa fix molly stark 2021-06-05 12:44:27 +02:00
Giulio
a8c1816c36 fix name and description of José 2021-05-30 12:11:54 +02:00
Alberto Xamin
ec2da4892a
add version to main menu 2021-05-28 12:24:05 +02:00
Alberto Xamin
8103a532cf
show legge del west card 2021-05-28 11:58:32 +02:00
Alberto Xamin
7dfcdc9e7d
fix not resetting cards 2021-05-28 11:25:52 +02:00
Giulio
cae194aa6d Merge branch 'dev' into main 2021-05-25 15:30:35 +02:00
Giulio
f68c9b2cec minor fix on reset 2021-05-25 15:21:10 +02:00
Giulio
20f09a2559 fix belle star ability with barile and visibility
Co-authored-by: Alberto Xamin <alberto@xamin.it>
2021-05-25 14:57:42 +02:00
Giulio
8119ff2e45 fix molly stark with Slab The Killer 2021-05-24 00:47:08 +02:00
Giulio
b7195004f0 Merge branch 'dev' into main 2021-05-23 15:53:30 +02:00
Giulio
63db5d6bb9 fix belle star 2021-05-23 15:52:32 +02:00
Giulio
80e641ffed fix gold rush desc 2021-05-23 15:14:16 +02:00
Alberto Xamin
4f8b5ea0c8
visual fixes 2021-05-22 20:05:12 +02:00
Alberto Xamin
cae7f2dfcb
add themese 2021-05-22 18:41:59 +02:00
Alberto Xamin
7a6d8b31d6
add debug mode 2021-05-22 17:59:30 +02:00
Alberto Xamin
5354986f63
put back per un pugno di carte 2021-05-22 17:23:24 +02:00
Giulio
5cb11555b2 Merge branch 'dev' into main 2021-05-22 17:12:45 +02:00
Alberto Xamin
5b394a2b86
fix missing mezzogiorno di fuoco 2021-05-22 17:08:55 +02:00
Alberto Xamin
9853719ea3
fix hidden cards for spectators
Co-authored-by: GM <giulio.migani@studenti.unitn.it>
2021-05-22 17:01:54 +02:00
Giulio
16800e6079 fix desc card on chooser one more time 2021-05-22 16:27:39 +02:00
Alberto Xamin
50b6269b35
fix broken service worker 2021-05-22 16:25:28 +02:00
Alberto Xamin
2ee0eabc72
change service worker registration 2021-05-22 16:05:41 +02:00
Alberto Xamin
8dd4e8d5e2
card events as i18n 2021-05-22 15:35:18 +02:00
Giulio
e681957581 Merge branch 'dev' into main 2021-05-21 19:48:00 +02:00
Giulio
0f86409859 announce event in chat 2021-05-21 19:47:26 +02:00
Giulio
ef052d7012 made a function for announce winners 2021-05-21 18:49:53 +02:00
Giulio
41b6f388f6 fix lazo frontend 2021-05-21 17:44:45 +02:00
Giulio
c375924f31 Merge branch 'dev' into main 2021-05-19 16:04:04 +02:00
Giulio
af1b0b6978 fix spectator 2021-05-19 15:58:17 +02:00
Giulio
821c2bed11 visual fix lobby
add draw click player
2021-05-19 15:58:04 +02:00
Giulio
11e94c8302 comment 2021-05-19 15:56:45 +02:00
Giulio
a59be2e6b8 Merge branch 'dev' into main 2021-05-19 12:14:35 +02:00
Giulio
b83b3d21a3 better fix for calamity janet 2021-05-19 12:13:42 +02:00
Giulio
9f71b00952 fix Dinamite attacker 2021-05-19 12:09:12 +02:00
Giulio
8a4eec5002 fix lazo and calamity janet's ability 2021-05-19 11:30:57 +02:00
Giulio
02ef834c98 fix event
per un pugno di carte
2021-05-19 00:21:03 +02:00
Giulio
4223badeb6 Merge branch 'dev' into main 2021-05-18 23:15:32 +02:00
Giulio
98a6d10873 fix elena fuente
elena fuente's ability only applies to the cards she has in her hand
2021-05-18 23:06:21 +02:00
Giulio
1b90fc5a0c revision help text 2021-05-18 18:37:45 +02:00
101 changed files with 21398 additions and 10967 deletions

View File

@ -0,0 +1,45 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
{
"name": "BangCodespace",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/javascript-node:0-18",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers/features/python:1": {
"version": "3.11.1"
}
},
// Use 'settings' to set *default* container specific settings.json values on container create.
// You can edit these settings after create using File > Preferences > Settings > Remote.
"settings": {
"python.testing.pytestArgs": [
"--rootdir=backend",
"backend/tests/"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.linting.enabled": true
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [5001, 8080],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "cd frontend;npm i;cd ../backend;pip install -r requirements.txt",
// Configure tool-specific properties.
// "customizations": {},
// Add the IDs of extensions you want installed when the container is created in the array below.
"extensions": [
"Vue.volar",
"ms-python.python",
"Gruntfuggly.todo-tree"
]
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

25
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,25 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
target-branch: "dev"
- package-ecosystem: "npm"
directory: "/frontend"
schedule:
interval: "daily"
target-branch: "dev"
- package-ecosystem: "pip"
directory: "/backend"
schedule:
interval: "daily"
target-branch: "dev"

View File

@ -1,17 +1,72 @@
name: Docker Images CI
on:
push:
branches: [ dev ]
branches: dev
jobs:
build:
buildx:
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: '1'
steps:
- uses: actions/checkout@v2
- name: Build the Unified Docker image
run: docker build . --file Dockerfile --tag albertoxamin/bang:dev
- name: Log into registry
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Push images
run: docker push albertoxamin/bang:dev
-
name: Checkout
uses: actions/checkout@v3
-
name: Set up Docker Buildx
uses: crazy-max/ghaction-docker-buildx@v3
-
name: Cache Docker layers
uses: actions/cache@v3
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
-
name: Docker Buildx (build amd64)
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/amd64 \
--output "type=image,push=false" \
--tag albertoxamin/bang:dev \
--file ./Dockerfile ./
-
name: Docker Buildx (build armv-7)
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/arm/v7 \
--output "type=image,push=false" \
--tag albertoxamin/bang:dev \
--file ./Dockerfile ./
-
name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Docker Buildx (push)
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--platform linux/amd64,linux/arm/v7 \
--output "type=image,push=true" \
--tag albertoxamin/bang:dev \
--file ./Dockerfile ./
-
name: Inspect image
run: |
docker buildx imagetools inspect albertoxamin/bang:dev
- name: Notify discord
uses: th0th/notify-discord@v0.4.1
if: ${{ always() }}
env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_JOB_NAME: "Docker image :dev"
GITHUB_JOB_STATUS: ${{ job.status }}

View File

@ -1,17 +1,71 @@
name: Docker Images CI
on:
push:
branches: [ main ]
branches: main
jobs:
build:
build-platform:
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: '1'
strategy:
matrix:
platform: [linux/amd64, linux/arm/v7, linux/arm64/v8]
steps:
- uses: actions/checkout@v2
- name: Build the Unified Docker image
run: docker build . --file Dockerfile --tag albertoxamin/bang:latest
- name: Log into registry
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Push images
run: docker push albertoxamin/bang:latest
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache Docker layers
uses: actions/cache@v4
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Prepare Platform Tag
id: platform_tag
run: echo "platform_tag=$(echo ${{ matrix.platform }} | sed 's|/|-|g')" >> $GITHUB_ENV
- name: Build and push platform-specific image
uses: docker/build-push-action@v5
with:
context: .
platforms: ${{ matrix.platform }}
push: true
tags: albertoxamin/bang:${{ env.platform_tag }}
cache-from: type=registry,ref=albertoxamin/bang:${{ env.platform_tag }}
cache-to: type=inline
create-manifest:
runs-on: ubuntu-latest
needs: build-platform
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Create and push multi-arch manifest
run: |
docker buildx imagetools create \
--tag albertoxamin/bang:latest \
albertoxamin/bang:linux-amd64 \
albertoxamin/bang:linux-arm-v7 \
albertoxamin/bang:linux-arm64-v8

25
.github/workflows/pylint.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Pylint
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
cd backend
pip install --user -r requirements.txt
pip install pylint
- name: Analysing the code with pylint
run: |
pylint $(git ls-files '*.py') -E

28
.github/workflows/test-backend.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: Python package
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.11]
defaults:
run:
working-directory: ./backend
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Test with pytest
run: |
python -m pytest -p no:warnings

View File

@ -1,12 +1,89 @@
name: Test Pull requests
on:
pull_request:
jobs:
test_build:
build-amd64:
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: '1'
steps:
- uses: actions/checkout@v2
- name: Build the Unified Docker image
run: docker build . --file Dockerfile
-
name: Checkout
uses: actions/checkout@v3
-
name: Set up Docker Buildx
uses: crazy-max/ghaction-docker-buildx@v3
-
name: Cache Docker layers
uses: actions/cache@v3
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
-
name: Docker Buildx (test build amd64)
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/amd64 \
--output "type=image,push=false" \
--tag albertoxamin/bang:test \
--file ./Dockerfile ./
# build-arm64:
# runs-on: ubuntu-latest
# steps:
# -
# name: Checkout
# uses: actions/checkout@v3
# -
# name: Set up Docker Buildx
# uses: crazy-max/ghaction-docker-buildx@v3
# -
# name: Cache Docker layers
# uses: actions/cache@v3
# id: cache
# with:
# path: /tmp/.buildx-cache
# key: ${{ runner.os }}-buildx-${{ github.sha }}
# restore-keys: |
# ${{ runner.os }}-buildx-
# -
# name: Docker Buildx (test build arm64)
# run: |
# docker buildx build \
# --cache-from "type=local,src=/tmp/.buildx-cache" \
# --cache-to "type=local,dest=/tmp/.buildx-cache" \
# --platform linux/arm64 \
# --output "type=image,push=false" \
# --tag albertoxamin/bang:test \
# --file ./Dockerfile ./
build-armv-7:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Set up Docker Buildx
uses: crazy-max/ghaction-docker-buildx@v3
-
name: Cache Docker layers
uses: actions/cache@v3
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
-
name: Docker Buildx (test build armv-7)
run: |
docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/arm/v7 \
--output "type=image,push=false" \
--tag albertoxamin/bang:test \
--file ./Dockerfile ./

2
.gitignore vendored
View File

@ -141,3 +141,5 @@ frontend/package-lock.json
bang-workspace.code-workspace
.vscode/
backend/save/*
save/

View File

@ -1,11 +1,30 @@
FROM node:lts-alpine as builder
# build Vue frontend
FROM node:18 as builder
COPY ./frontend .
RUN npm install
RUN npm run build
FROM python:3.7-slim-stretch
# now we should have a dist folder containing the static website
FROM python:3.11.1-bullseye as pybuilder
WORKDIR /code
COPY ./backend /code/
RUN pip install --user -r requirements.txt
# We get the dependencies with the full python image so we can compile the one with missing binaries
ENV UseRobots=false
FROM python:3.11.1-slim-bullseye as app
# copy the dependencies from the pybuilder
COPY --from=pybuilder /root/.local /root/.local
# copy the backend python files from the pybuilder
COPY --from=pybuilder /code /dist
# copy the frontend static files from the builder
COPY --from=builder ./dist /dist/
COPY ./backend /dist/
WORKDIR /dist
RUN pip install -r requirements.txt
# create dir for save
RUN mkdir save
EXPOSE 5001
ENTRYPOINT ["python", "/dist/__init__.py"]
ENV PATH=/root/.local/bin:${PATH}
VOLUME /dist/save
ENTRYPOINT ["python", "/dist/server.py"]

View File

@ -1 +1,14 @@
# bang
This is the repo for the PewPew! game, which is a replica of BANG!.
BANG! is a trademark owned by DVGiochi.
[Frontend Readme](./frontend/README.md)
[Backend Readme](./backend/Readme.md)
<img width="1326" alt="bang-lobby" src="https://github.com/albertoxamin/bang/assets/6067659/853a4182-aace-4f5d-92c3-ad63f309c37a">
<img width="1316" alt="bang-in-game" src="https://github.com/albertoxamin/bang/assets/6067659/fa4ad9f3-2012-4a38-b3eb-97fd0b4b8f2b">

View File

@ -2,6 +2,9 @@ FROM python:3.7-slim-stretch
WORKDIR /code
COPY * /code/
RUN RUN apt-get update && apt-get install -y \
libevent-dev \
python-all-dev
RUN pip install -r requirements.txt
EXPOSE 5001

View File

@ -1,415 +0,0 @@
import os
import json
import random
from typing import List
import eventlet
import socketio
from bang.game import Game
from bang.players import Player, PendingAction
import sys
sys.setrecursionlimit(10**6) # this should prevents bots from stopping
sio = socketio.Server(cors_allowed_origins="*")
static_files={
'/': {'content_type': 'text/html', 'filename': 'index.html'},
'/game': {'content_type': 'text/html', 'filename': 'index.html'},
# '/robots.txt': {'content_type': 'text/html', 'filename': 'robots.txt'},
'/favicon.ico': {'filename': 'favicon.ico'},
'/img/icons': './img/icons',
'/manifest.json': {'filename': 'manifest.json'},
'/css': './css',
'/media': './media',
'/js': './js',
}
for file in [f for f in os.listdir('.') if '.js' in f or '.map' in f or '.html' in f]:
static_files[f'/{file}'] = f'./{file}'
app = socketio.WSGIApp(sio, static_files=static_files)
games: List[Game] = []
online_players = 0
def advertise_lobbies():
sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 10])
sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if g.started])
@sio.event
def connect(sid, environ):
global online_players
online_players += 1
print('connect ', sid)
sio.enter_room(sid, 'lobby')
sio.emit('players', room='lobby', data=online_players)
@sio.event
def get_online_players(sid):
global online_players
sio.emit('players', room='lobby', data=online_players)
@sio.event
def set_username(sid, username):
ses = sio.get_session(sid)
if not isinstance(ses, Player):
sio.save_session(sid, Player(username, sid, sio))
print(f'{sid} is now {username}')
advertise_lobbies()
elif ses.game == None or not ses.game.started:
print(f'{sid} changed username to {username}')
prev = ses.name
if len([p for p in ses.game.players if p.name == username]) > 0:
ses.name = f"{username}_{random.randint(0,100)}"
else:
ses.name = username
sio.emit('chat_message', room=ses.game.name, data=f'_change_username|{prev}|{ses.name}')
sio.emit('me', data=ses.name, room=sid)
ses.game.notify_room()
@sio.event
def get_me(sid, room):
if isinstance(sio.get_session(sid), Player):
sio.emit('me', data=sio.get_session(sid).name, room=sid)
if sio.get_session(sid).game:
sio.get_session(sid).game.notify_room()
else:
sio.save_session(sid, Player('player', sid, sio))
de_games = [g for g in games if g.name == room['name']]
if len(de_games) == 1 and not de_games[0].started:
join_room(sid, room)
elif len(de_games) == 1 and de_games[0].started:
print('room exists')
if room['username'] != None and any([p.name == room['username'] for p in de_games[0].players if p.is_bot]):
print('getting inside the bot')
bot = [p for p in de_games[0].players if p.is_bot and p.name == room['username'] ][0]
bot.sid = sid
bot.is_bot = False
sio.enter_room(sid, de_games[0].name)
sio.save_session(sid, bot)
de_games[0].notify_room(sid)
eventlet.sleep(0.1)
de_games[0].notify_all()
sio.emit('role', room=sid, data=json.dumps(bot.role, default=lambda o: o.__dict__))
bot.notify_self()
if len(bot.available_characters) > 0:
bot.set_available_character(bot.available_characters)
else: #spectate
de_games[0].spectators.append(sio.get_session(sid))
sio.get_session(sid).game = de_games[0]
sio.enter_room(sid, de_games[0].name)
de_games[0].notify_room(sid)
de_games[0].notify_all()
de_games[0].notify_event_card()
else:
create_room(sid, room['name'])
if sio.get_session(sid).game == None:
sio.emit('me', data={'error':'Wrong password/Cannot connect'}, room=sid)
else:
sio.emit('me', data=sio.get_session(sid).name, room=sid)
if room['username'] == None or any([p.name == room['username'] for p in sio.get_session(sid).game.players]):
sio.emit('change_username', room=sid)
else:
sio.emit('chat_message', room=sio.get_session(sid).game.name, data=f"_change_username|{sio.get_session(sid).name}|{room['username']}")
sio.get_session(sid).name = room['username']
sio.emit('me', data=sio.get_session(sid).name, room=sid)
if not sio.get_session(sid).game.started:
sio.get_session(sid).game.notify_room()
@sio.event
def disconnect(sid):
global online_players
online_players -= 1
if sio.get_session(sid):
sio.emit('players', room='lobby', data=online_players)
if sio.get_session(sid).game and sio.get_session(sid).disconnect():
sio.close_room(sio.get_session(sid).game.name)
games.pop(games.index(sio.get_session(sid).game))
print('disconnect ', sid)
advertise_lobbies()
@sio.event
def create_room(sid, room_name):
if sio.get_session(sid).game == None:
while len([g for g in games if g.name == room_name]):
room_name += f'_{random.randint(0,100)}'
sio.leave_room(sid, 'lobby')
sio.enter_room(sid, room_name)
g = Game(room_name, sio)
g.add_player(sio.get_session(sid))
games.append(g)
print(f'{sid} created a room named {room_name}')
advertise_lobbies()
@sio.event
def private(sid):
g = sio.get_session(sid).game
g.set_private()
advertise_lobbies()
@sio.event
def toggle_expansion(sid, expansion_name):
g = sio.get_session(sid).game
g.toggle_expansion(expansion_name)
@sio.event
def toggle_comp(sid):
sio.get_session(sid).game.toggle_competitive()
@sio.event
def toggle_replace_with_bot(sid):
sio.get_session(sid).game.toggle_disconnect_bot()
@sio.event
def join_room(sid, room):
room_name = room['name']
i = [g.name for g in games].index(room_name)
if games[i].password != '' and games[i].password != room['password'].upper():
return
if not games[i].started:
print(f'{sid} joined a room named {room_name}')
sio.leave_room(sid, 'lobby')
sio.enter_room(sid, room_name)
while len([p for p in games[i].players if p.name == sio.get_session(sid).name]):
sio.get_session(sid).name += f'_{random.randint(0,100)}'
sio.emit('me', data=sio.get_session(sid).name, room=sid)
games[i].add_player(sio.get_session(sid))
advertise_lobbies()
else:
games[i].spectators.append(sio.get_session(sid))
sio.get_session(sid).game = games[i]
sio.get_session(sid).pending_action = PendingAction.WAIT
sio.enter_room(sid, games[0].name)
games[i].notify_room(sid)
eventlet.sleep(0.5)
games[i].notify_room(sid)
games[i].notify_all()
@sio.event
def chat_message(sid, msg):
ses: Player = sio.get_session(sid)
if len(msg) > 0:
if msg[0] == '/':
if '/addbot' in msg and not ses.game.started:
if len(msg.split()) > 1:
# for _ in range(int(msg.split()[1])):
# ses.game.add_player(Player(f'AI_{random.randint(0,1000)}', 'bot', sio, bot=True))
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'Only 1 bot at the time'})
else:
bot = Player(f'AI_{random.randint(0,10)}', 'bot', sio, bot=True)
while any([p for p in ses.game.players if p.name == bot.name]):
bot = Player(f'AI_{random.randint(0,10)}', 'bot', sio, bot=True)
ses.game.add_player(bot)
bot.bot_spin()
elif '/removebot' in msg and not ses.game.started:
if any([p.is_bot for p in ses.game.players]):
[p for p in ses.game.players if p.is_bot][-1].disconnect()
elif '/suicide' in msg and ses.game.started and ses.lives > 0:
ses.lives = 0
ses.notify_self()
elif '/nextevent' in msg and ses.game.started:
ses.game.deck.flip_event()
elif '/notify' in msg and ses.game.started:
cmd = msg.split()
if len(cmd) >= 3:
if cmd[1] in ses.game.players_map:
ses.game.get_player_named(cmd[1]).notify_card(ses, {
'name': ' '.join(cmd[2:]),
'icon': '🚨',
'suit': 4,
'number': ' '.join(cmd[2:])
})
else:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'})
elif '/debug_show_cards' in msg and ses.game.started:
cmd = msg.split()
if len(cmd) == 2:
if cmd[1] in ses.game.players_map:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and is looking at {cmd[1]} hand'})
for c in ses.game.get_player_named(cmd[1]).hand:
ses.notify_card(ses, c)
eventlet.sleep(0.3)
else:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'})
elif '/ddc' in msg and ses.game.started: #/ddc *
cmd = msg.split()
if len(cmd) == 2:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode destroyed {cmd[1]} cards'})
if cmd[1] == "*":
for p in ses.game.players_map:
ses.game.get_player_named(p).hand = []
ses.game.get_player_named(p).equipment = []
ses.game.get_player_named(p).notify_self()
elif cmd[1] in ses.game.players_map:
ses.game.get_player_named(cmd[1]).hand = []
ses.game.get_player_named(cmd[1]).equipment = []
ses.game.get_player_named(cmd[1]).notify_self()
else:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'})
elif '/dsh' in msg and ses.game.started: #/dsh * 1
cmd = msg.split()
if len(cmd) == 3:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and is changing {cmd[1]} health'})
if cmd[1] == "*":
for p in ses.game.players_map:
ses.game.get_player_named(p).lives = int(cmd[2])
ses.game.get_player_named(p).notify_self()
elif cmd[1] in ses.game.players_map:
ses.game.get_player_named(cmd[1]).lives = int(cmd[2])
ses.game.get_player_named(cmd[1]).notify_self()
else:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'})
elif '/togglecomp' in msg and ses.game:
ses.game.toggle_competitive()
elif '/togglebot' in msg and ses.game:
ses.game.toggle_disconnect_bot()
elif '/cancelgamesudo' in msg and ses.game.started:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} stopped the current game'})
ses.game.reset()
elif '/cancelgame' in msg and ses.game.started:
if (ses == ses.game.players[0]):
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} stopped the current game'})
ses.game.reset()
elif '/startgame' in msg and not ses.game.started:
ses.game.start_game()
elif '/setbotspeed' in msg:
ses.game.bot_speed = float(msg.split()[1])
elif '/addex' in msg and not ses.game.started:
cmd = msg.split()
if len(cmd) == 2:
cmd[1] = cmd[1].replace('foc', 'fistful_of_cards')
if cmd[1] not in ses.game.available_expansions:
ses.game.available_expansions.append(cmd[1])
ses.game.notify_room()
else:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} bad format'})
elif '/setcharacter' in msg:
import bang.characters as characters
cmd = msg.split()
if len(cmd) >= 2:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and changed character'})
chs = characters.all_characters(ses.game.expansions)
ses.character = [c for c in chs if c.name == ' '.join(cmd[1:])][0]
ses.real_character = ses.character
ses.notify_self()
elif '/setevent' in msg and ses.game and ses.game.deck:
cmd = msg.split()
if len(cmd) >= 3:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and changed event'})
chs = ses.game.deck.event_cards
ses.game.deck.event_cards.insert(int(cmd[1]), [c for c in chs if c!=None and c.name == ' '.join(cmd[2:])][0])
ses.game.notify_event_card()
elif '/removecard' in msg:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and removed a card'})
cmd = msg.split()
if len(cmd) == 2:
if int(cmd[1]) < len(ses.hand):
ses.hand.pop(int(cmd[1]))
else:
ses.equipment.pop(int(cmd[1])-len(ses.hand))
ses.notify_self()
elif '/getcard' in msg:
sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and got a card'})
import bang.cards as cs
cmd = msg.split()
if len(cmd) >= 2:
cards = cs.get_starting_deck(ses.game.expansions)
card_names = ' '.join(cmd[1:]).split(',')
for cn in card_names:
ses.hand.append([c for c in cards if c.name == cn][0])
ses.notify_self()
elif '/gameinfo' in msg:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'info: {ses.game.__dict__}'})
elif '/meinfo' in msg:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'info: {ses.__dict__}'})
elif '/mebot' in msg:
ses.is_bot = not ses.is_bot
ses.bot_spin()
elif '/arcadekick' in msg and ses.game.started:
if len([p for p in ses.game.players if p.pending_action != PendingAction.WAIT]) == 0:
sio.emit('chat_message', room=ses.game.name, data={'color': f'','text':f'KICKING THE ARCADE CABINET'})
ses.game.next_turn()
else:
sio.emit('chat_message', room=sid, data={'color': f'','text':f'{msg} COMMAND NOT FOUND'})
else:
color = sid.encode('utf-8').hex()[-3:]
sio.emit('chat_message', room=ses.game.name, data={'color': f'#{color}','text':f'[{ses.name}]: {msg}'})
@sio.event
def start_game(sid):
ses: Player = sio.get_session(sid)
ses.game.start_game()
advertise_lobbies()
@sio.event
def set_character(sid, name):
ses: Player = sio.get_session(sid)
ses.set_character(name)
@sio.event
def refresh(sid):
ses: Player = sio.get_session(sid)
ses.notify_self()
@sio.event
def draw(sid, pile):
ses: Player = sio.get_session(sid)
ses.draw(pile)
@sio.event
def pick(sid):
ses: Player = sio.get_session(sid)
ses.pick()
@sio.event
def end_turn(sid):
ses: Player = sio.get_session(sid)
ses.end_turn()
@sio.event
def play_card(sid, data):
ses: Player = sio.get_session(sid)
ses.play_card(data['index'], data['against'], data['with'])
@sio.event
def respond(sid, data):
ses: Player = sio.get_session(sid)
ses.respond(data)
@sio.event
def choose(sid, card_index):
ses: Player = sio.get_session(sid)
ses.choose(card_index)
@sio.event
def scrap(sid, card_index):
ses: Player = sio.get_session(sid)
ses.scrap(card_index)
@sio.event
def chuck_lose_hp_draw(sid):
ses: Player = sio.get_session(sid)
ses.chuck_lose_hp_draw()
@sio.event
def holyday_special(sid, data):
ses: Player = sio.get_session(sid)
ses.holyday_special(data)
@sio.event
def get_cards(sid):
import bang.cards as c
cards = c.get_starting_deck(['dodge_city'])
cards_dict = {}
for ca in cards:
if ca.name not in cards_dict:
cards_dict[ca.name] = ca
cards = [cards_dict[i] for i in cards_dict]
sio.emit('cards_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__))
@sio.event
def get_characters(sid):
import bang.characters as ch
cards = ch.all_characters(['dodge_city'])
sio.emit('characters_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__))
if __name__ == '__main__':
eventlet.wsgi.server(eventlet.listen(('', 5001)), app)

View File

@ -1,28 +1,49 @@
from typing import List, Set, Dict, Tuple, Optional
from __future__ import annotations
from typing import List, Set, Dict, Tuple, Optional, TYPE_CHECKING
import bang.expansions.fistful_of_cards.card_events as ce
import bang.expansions.high_noon.card_events as ceh
from abc import ABC, abstractmethod
from enum import IntEnum
import bang.roles as r
from globals import G
if TYPE_CHECKING:
from bang.players import Player
from bang.game import Game
class Suit(IntEnum):
"""Enum for card suits"""
DIAMONDS = 0 # ♦
CLUBS = 1 # ♣
HEARTS = 2 # ♥
SPADES = 3 # ♠
GOLD = 4 # 🤑
TRAIN = 5 # 🚂
class Card(ABC):
sym = {
'A': 1,
'J': 11,
'Q': 12,
'K': 13
}
"""Base class for all cards"""
def __init__(self, suit: Suit, name: str, number, is_equipment: bool = False, is_weapon: bool = False, vis_mod: int = 0, sight_mod: int = 0, range: int = 99, desc: str = ''):
sym = {"A": 1, "J": 11, "Q": 12, "K": 13}
def __init__(
self,
suit: Suit,
name: str,
number,
is_equipment: bool = False,
is_weapon: bool = False,
vis_mod: int = 0,
sight_mod: int = 0,
range: int = 99,
desc: str = "",
):
super().__init__()
self.name = name
self.suit = suit
if type(number) == int:
if isinstance(number, int):
self.number = number
else:
self.number = self.sym[number]
@ -32,54 +53,102 @@ class Card(ABC):
self.sight_mod = sight_mod
self.range = range
if self.range != 0 and self.range != 99:
self.alt_text = f'{self.range} 🔍'
self.desc = desc
self.need_target = False
self.can_target_self = False
self.can_be_used_now = True
self.usable_next_turn = False
self.need_with = False
self.alt_text = f"{self.range} 🔍"
self.desc = desc # deprecated, has been replaced by the card's description in the localization files (see i18n folder)
self.need_target = False # Cards that need a target like Bang
self.can_target_self = False # for example Panico and CatBalou
self.can_be_used_now = True # to check wether the green card can be used now
self.usable_next_turn = False # it will be True for Green Cards
self.need_with = (
False # it will be true for cards that require a card to be discarded with
)
self.need_with_only = "" # names of the cards allowed to be discarded with
self.must_be_used = False # used by LeggeDelWest
def __str__(self):
char = ['♦️', '♣️', '♥️', '♠️'][int(self.suit)]
return f'{self.name} {char}{self.number}'
return super().__str__()
def __str__(self) -> str:
if str(self.suit).isnumeric():
char = ["♦️", "♣️", "♥️", "♠️", "🤑", "🚋"][int(self.suit)]
else:
char = self.suit
return f"{self.name} {char}{self.number}"
def num_suit(self):
return f"{['♦️', '♣️', '♥️', '♠️'][int(self.suit)]}{self.number}"
def num_suit(self) -> str:
"""Returns the card's number and suit as a string"""
return f"{['♦️', '♣️', '♥️', '♠️', '🤑'][int(self.suit)]}{self.number}"
def play_card(self, player, against=None, _with=None):#self --> carta
def reset_card(self) -> None:
"""Resets the card's attributes"""
if self.usable_next_turn:
self.can_be_used_now = False
else:
self.can_be_used_now = True
if self.must_be_used:
self.must_be_used = False
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
"""Plays the card and returns True if the card was played successfully, False otherwise"""
if (
(player.game.check_event(ce.IlGiudice))
and self.usable_next_turn
and not self.can_be_used_now
):
return False
if self.is_equipment:
if (player.game.check_event(ce.IlGiudice)) or not self.can_be_used_now:
return False
if self.is_weapon:
has_weapon = False
for i in range(len(player.equipment)):
if player.equipment[i].is_weapon:
player.game.deck.scrap(player.equipment[i])
for i, card in enumerate(player.equipment):
if card.is_weapon:
player.game.deck.scrap(card, player=player)
player.equipment[i] = self
has_weapon = True
break
if not has_weapon:
player.equipment.append(self)
elif self.name in [c.name for c in player.equipment if not isinstance(c, Dinamite)]:
elif self.name in [
c.name for c in player.equipment if not isinstance(c, Dinamite)
]:
return False
else:
player.equipment.append(self)
self.must_be_used = False
self.can_be_used_now = False
if against:
player.sio.emit('chat_message', room=player.game.name,
data=f'_play_card_against|{player.name}|{self.name}|{against}')
G.sio.emit(
"card_against",
room=player.game.name,
data={"player": player.name, "target": against, "card": self.__dict__},
)
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_against{'_with' if _with else ''}|{player.name}|{self.name}|{against}|{_with.name if _with else ''}",
)
else:
player.sio.emit('chat_message', room=player.game.name,
data=f'_play_card|{player.name}|{self.name}')
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card{'_with' if _with else ''}|{player.name}|{self.name}|{_with.name if _with else ''}",
)
return True
def use_card(self, player):
pass
def is_duplicate_card(self, player):
return self.name in [c.name for c in player.equipment]
def is_duplicate_card(self, player: Player):
"""Checks if the card is already in the player's equipment"""
return any(c.name == self.name for c in player.equipment) or any(
c.name == self.name for c in player.gold_rush_equipment
)
def check_suit(self, game, accepted):
import bang.expansions.high_noon.card_events as ceh
def check_suit(self, game: Game, accepted: List[Suit]):
"""Checks if the card's suit is in the list of accepted suits
(also checks for the events Benedizione and Maledizione)
returns True if it is, False otherwise"""
if game.check_event(ceh.Benedizione):
return Suit.HEARTS in accepted
elif game.check_event(ceh.Maledizione):
@ -87,205 +156,323 @@ class Card(ABC):
return self.suit in accepted
class Barile(Card):
"""Quando sei bersagliato da un Bang puoi estrarre la prima carta dalla cima del mazzo, se la carta estratta è del seme Cuori allora vale come un Mancato
When someone plays a Bang against you. You can flip the first card from the deck, if the suit is Hearts then it counts as a Missed card
"""
def __init__(self, suit, number):
super().__init__(suit, 'Barile', number, is_equipment=True)
self.icon = '🛢'
super().__init__(suit, "Barile", number, is_equipment=True)
self.icon = "🛢"
self.alt_text = "♥️=😅"
# self.desc = "Quando sei bersagliato da un Bang puoi estrarre la prima carta dalla cima del mazzo, se la carta estratta è del seme Cuori allora vale come un Mancato"
# self.desc_eng = "When someone plays a Bang against you. You can flip the first card from the deck, if the suit is Hearts then it counts as a Missed card"
class Dinamite(Card):
"""Giocando la Dinamite, posizionala davanti a te, resterà innocua per un intero giro. All'inizio del prossimo turno prima di pescare e prima di una eventuale estrazione (es. Prigione), estrai una carta dalla cima del mazzo. Se esce una carta tra il 2 il 9 di picche (compresi) allora la dinamite esplode: perdi 3 vite e scarta la carta, altrimenti passa la dinamite al giocatore successivo, il quale estrarà a sua volta dopo che tu avrai passato il tuo turno
When playing Dynamite, place it in front of you, it will remain harmless for a whole round. At the beginning of the next turn before drawing and before any card flip (eg Prison), flip a card from the top of the deck. If a card is between 2 and 9 of spades (inclusive) then the dynamite explodes: you lose 3 lives and discard the card, otherwise pass the dynamite to the next player, who will draw in turn after you have ended your turn
"""
def __init__(self, suit, number):
super().__init__(suit, 'Dinamite', number, is_equipment=True)
self.icon = '🧨'
super().__init__(suit, "Dinamite", number, is_equipment=True)
self.icon = "🧨"
self.alt_text = "2-9♠ = 🤯"
# self.desc = "Giocando la Dinamite, posizionala davanti a te, resterà innocua per un intero giro. All'inizio del prossimo turno prima di pescare e prima di una eventuale estrazione (es. Prigione), estrai una carta dalla cima del mazzo. Se esce una carta tra il 2 il 9 di picche (compresi) allora la dinamite esplode: perdi 3 vite e scarta la carta, altrimenti passa la dinamite al giocatore successivo, il quale estrarà a sua volta dopo che tu avrai passato il tuo turno"
# self.desc_eng = "When playing Dynamite, place it in front of you, it will remain harmless for a whole round. At the beginning of the next turn before drawing and before any card flip (eg Prison), flip a card from the top of the deck. If a card is between 2 and 9 of spades (inclusive) then the dynamite explodes: you lose 3 lives and discard the card, otherwise pass the dynamite to the next player, who will draw in turn after you have ended your turn"
class Mirino(Card):
"""Tu vedi gli altri giocatori a distanza -1
You see the other players at distance -1"""
def __init__(self, suit, number):
super().__init__(suit, 'Mirino', number, is_equipment=True, sight_mod=1)
self.icon = '🔎'
super().__init__(suit, "Mirino", number, is_equipment=True, sight_mod=1)
self.icon = "🔎"
self.alt_text = "-1"
# self.desc = "Tu vedi gli altri giocatori a distanza -1"
# self.desc_eng = "You see the other players at distance -1"
class Mustang(Card):
"""Gli altri giocatori ti vedono a distanza +1
The other players see you at distance +1"""
def __init__(self, suit, number):
super().__init__(suit, 'Mustang', number, is_equipment=True, vis_mod=1)
self.icon = '🐎'
super().__init__(suit, "Mustang", number, is_equipment=True, vis_mod=1)
self.icon = "🐎"
self.alt_text = "+1"
# self.desc = "Gli altri giocatori ti vedono a distanza +1"
# self.desc_eng = "The other players see you at distance +1"
class Prigione(Card):
"""Equipaggia questa carta a un altro giocatore, tranne lo Sceriffo. Il giocatore scelto all'inizio del suo turno, prima di pescare dovrà estrarre: se esce Cuori scarta questa carta e gioca normalmente il turno, altrimenti scarta questa carta e salta il turno
Equip this card to another player, except the Sheriff. The player chosen at the beginning of his turn, must flip a card before drawing: if it's Hearts, discard this card and play the turn normally, otherwise discard this card and skip the turn
"""
def __init__(self, suit, number):
super().__init__(suit, 'Prigione', number, is_equipment=True)
self.icon = ''
# self.desc = "Equipaggia questa carta a un altro giocatore, tranne lo Sceriffo. Il giocatore scelto all'inizio del suo turno, prima di pescare dovrà estrarre: se esce Cuori scarta questa carta e gioca normalmente il turno, altrimenti scarta questa carta e salta il turno"
# self.desc_eng = "Equip this card to another player, except the Sheriff. The player chosen at the beginning of his turn, must flip a card before drawing: if it's Hearts, discard this card and play the turn normally, otherwise discard this card and skip the turn"
super().__init__(suit, "Prigione", number, is_equipment=True)
self.icon = ""
self.need_target = True
self.alt_text = "♥️= 🆓"
def play_card(self, player, against, _with=None):
if against != None and not isinstance(player.game.get_player_named(against).role, r.Sheriff):
player.sio.emit('chat_message', room=player.game.name,
data=f'_play_card_against|{player.name}|{self.name}|{against}')
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
if player.game.check_event(ce.IlGiudice):
return False
if (
against is not None
and not isinstance(player.game.get_player_named(against).role, r.Sheriff)
and not self.is_duplicate_card(player.game.get_player_named(against))
):
self.can_be_used_now = False
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_against|{player.name}|{self.name}|{against}",
)
player.game.get_player_named(against).equipment.append(self)
player.game.get_player_named(against).notify_self()
return True
return False
class Remington(Card):
"""Puoi sparare a un giocatore che sia distante 3 o meno
You can shoot another player at distance 3 or less"""
def __init__(self, suit, number):
super().__init__(suit, 'Remington', number,
is_equipment=True, is_weapon=True, range=3)
self.icon = '🔫'
# self.desc = "Puoi sparare a un giocatore che sia distante 3 o meno"
# self.desc_eng = "You can shoot another player at distance 3 or less"
super().__init__(
suit, "Remington", number, is_equipment=True, is_weapon=True, range=3
)
self.icon = "🔫"
class RevCarabine(Card):
"""Puoi sparare a un giocatore che sia distante 4 o meno
You can shoot another player at distance 4 or less"""
def __init__(self, suit, number):
super().__init__(suit, 'Rev Carabine', number,
is_equipment=True, is_weapon=True, range=4)
self.icon = '🔫'
# self.desc = "Puoi sparare a un giocatore che sia distante 4 o meno"
# self.desc_eng = "You can shoot another player at distance 4 or less"
super().__init__(
suit, "Rev Carabine", number, is_equipment=True, is_weapon=True, range=4
)
self.icon = "🔫"
class Schofield(Card):
"""Puoi sparare a un giocatore che sia distante 2 o meno
You can shoot another player at distance 2 or less"""
def __init__(self, suit, number):
super().__init__(suit, 'Schofield', number,
is_equipment=True, is_weapon=True, range=2)
self.icon = '🔫'
# self.desc = "Puoi sparare a un giocatore che sia distante 2 o meno"
# self.desc_eng = "You can shoot another player at distance 2 or less"
super().__init__(
suit, "Schofield", number, is_equipment=True, is_weapon=True, range=2
)
self.icon = "🔫"
class Volcanic(Card):
"""Puoi sparare a un giocatore che sia distante 1 o meno, tuttavia puoi giocare quanti bang vuoi
You can shoot another player at distance 1 or less, however you no longer have the limit of 1 Bang
"""
def __init__(self, suit, number):
super().__init__(suit, 'Volcanic', number,
is_equipment=True, is_weapon=True, range=1)
self.icon = '🔫'
# self.desc = "Puoi sparare a un giocatore che sia distante 1 o meno, tuttavia puoi giocare quanti bang vuoi"
# self.desc_eng = "You can shoot another player at distance 1 or less, however you no longer have the limit of 1 Bang"
super().__init__(
suit, "Volcanic", number, is_equipment=True, is_weapon=True, range=1
)
self.icon = "🔫"
class Winchester(Card):
"""Puoi sparare a un giocatore che sia distante 5 o meno
You can shoot another player at distance 5 or less"""
def __init__(self, suit, number):
super().__init__(suit, 'Winchester', number,
is_equipment=True, is_weapon=True, range=5)
self.icon = '🔫'
# self.desc = "Puoi sparare a un giocatore che sia distante 5 o meno"
# self.desc_eng = "You can shoot another player at distance 5 or less"
super().__init__(
suit, "Winchester", number, is_equipment=True, is_weapon=True, range=5
)
self.icon = "🔫"
class Bang(Card):
"""Spara a un giocatore a distanza raggiungibile. Se non hai armi la distanza di default è 1
Shoot a player in sight. If you do not have weapons, your is sight is 1"""
def __init__(self, suit, number):
super().__init__(suit, 'Bang!', number)
self.icon = '💥'
# self.desc = "Spara a un giocatore a distanza raggiungibile. Se non hai armi la distanza di default è 1"
# self.desc_eng = "Shoot a player in sight. If you do not have weapons, your is sight is 1"
super().__init__(suit, "Bang!", number)
self.icon = "💥"
self.need_target = True
def play_card(self, player, against, _with=None):
import bang.expansions.fistful_of_cards.card_events as ce
import bang.expansions.high_noon.card_events as ceh
if player.game.check_event(ceh.Sermone):
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
if (
player.game.check_event(ceh.Sermone) and not self.number == 42
): # 42 gold rush
return False
if player.has_played_bang and (not any([isinstance(c, Volcanic) for c in player.equipment]) or player.game.check_event(ce.Lazo)) and against != None:
if (
(player.has_played_bang and not self.number == 42)
and (
not any((isinstance(c, Volcanic) for c in player.equipment))
or player.game.check_event(ce.Lazo)
)
and against is not None
): # 42 gold rush:
return False
elif against != None:
elif against is not None:
import bang.characters as chars
super().play_card(player, against=against)
player.bang_used += 1
player.has_played_bang = True if not player.game.check_event(ceh.Sparatoria) else player.bang_used > 1
if not (self.number == 42 and self.suit == Suit.GOLD): # 42 gold rush
player.bang_used += 1
player.has_played_bang = (
True
if not player.game.check_event(ceh.Sparatoria)
else player.bang_used > 1
)
if player.character.check(player.game, chars.WillyTheKid):
player.has_played_bang = False
player.game.attack(player, against, double=player.character.check(player.game, chars.SlabTheKiller))
player.game.attack(
player,
against,
double=player.character.check(player.game, chars.SlabTheKiller),
card_name=self.name,
)
return True
return False
class Birra(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Birra', number)
self.icon = '🍺'
# self.desc = "Gioca questa carta per recuperare un punto vita. Non puoi andare oltre al limite massimo del tuo personaggio. Se stai per perdere l'ultimo punto vita puoi giocare questa carta anche nel turno dell'avversario. La birra non ha più effetto se ci sono solo due giocatori"
# self.desc_eng = "Play this card to regain a life point. You cannot heal more than your character's maximum limit. If you are about to lose your last life point, you can also play this card on your opponent's turn. Beer no longer takes effect if there are only two players"
"""Gioca questa carta per recuperare un punto vita. Non puoi andare oltre al limite massimo del tuo personaggio. Se stai per perdere l'ultimo punto vita puoi giocare questa carta anche nel turno dell'avversario. La birra non ha più effetto se ci sono solo due giocatori
def play_card(self, player, against, _with=None):
import bang.expansions.high_noon.card_events as ceh
Play this card to regain a life point. You cannot heal more than your character's maximum limit. If you are about to lose your last life point, you can also play this card on your opponent's turn. Beer no longer takes effect if there are only two players
"""
def __init__(self, suit, number):
super().__init__(suit, "Birra", number)
self.icon = "🍺"
def play_card(self, player, against=None, _with=None, skipChecks=False):
if player.game.check_event(ceh.IlReverendo):
return False
if len(player.game.get_alive_players()) != 2:
if not skipChecks:
import bang.expansions.gold_rush.characters as grch
madamYto = [
p
for p in player.game.get_alive_players()
if p.character.check(player.game, grch.MadamYto) and self.number != 42
]
for p in madamYto:
player.game.deck.draw(True, player=p)
p.notify_self()
if "gold_rush" in player.game.expansions and self.number != 42:
player.set_choose_action(
"choose_birra_function",
[
{
"name": "Pepita",
"icon": "💵️",
"alt_text": "1",
"noDesc": True,
},
self,
],
)
player.notify_self()
return True
if (
len(player.game.get_alive_players()) != 2 or self.number == 42
) and player.lives < player.max_lives:
super().play_card(player, against=against)
player.lives = min(player.lives+1, player.max_lives)
player.lives = min(player.lives + 1, player.max_lives)
import bang.expansions.dodge_city.characters as chd
if player.character.check(player.game, chd.TequilaJoe):
player.lives = min(player.lives+1, player.max_lives)
player.lives = min(player.lives + 1, player.max_lives)
return True
elif len(player.game.get_alive_players()) == 2:
player.sio.emit('chat_message', room=player.game.name,
data=f'_spilled_beer|{player.name}|{self.name}')
elif (
len(player.game.get_alive_players()) == 2
or player.lives == player.max_lives
):
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_spilled_beer|{player.name}|{self.name}",
)
return True
return False
class CatBalou(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Cat Balou', number)
self.icon = '💃'
# self.desc = "Fai scartare una carta a un qualsiasi giocatore, scegli a caso dalla mano, oppure fra quelle che ha in gioco"
# self.desc_eng = "Choose and discard a card from any other player."
self.need_target = True
"""Fai scartare una carta a un qualsiasi giocatore, scegli a caso dalla mano, oppure fra quelle che ha in gioco
def play_card(self, player, against, _with=None):
if against != None and (len(player.game.get_player_named(against).hand) + len(player.game.get_player_named(against).equipment)) > 0:
if self.name == 'Cat Balou':
super().play_card(player, against=against)
from bang.players import PendingAction
player.pending_action = PendingAction.CHOOSE
player.choose_action = 'discard'
player.target_p = against
print('choose now')
Choose and discard a card from any other player."""
def __init__(self, suit, number):
super().__init__(suit, "Cat Balou", number)
self.icon = "💃"
self.need_target = True
self.can_target_self = True
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
if (
against is not None
and (
len(player.game.get_player_named(against).hand)
+ len(player.game.get_player_named(against).equipment)
)
> 0
and (player.name != against or len(player.equipment) > 0)
):
super().play_card(player, against=against)
player.game.steal_discard(player, against, self)
return True
return False
class Diligenza(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Diligenza', number)
self.icon = '🚡'
self.alt_text = "🎴🎴"
# self.desc = "Pesca 2 carte dalla cima del mazzo"
# self.desc_eng = "Draw 2 cards from the deck."
"""Pesca 2 carte dalla cima del mazzo
def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name,
data=f'_diligenza|{player.name}|{self.name}')
Draw 2 cards from the deck."""
def __init__(self, suit, number):
super().__init__(suit, "Diligenza", number)
self.icon = "🚡"
self.alt_text = "🎴🎴"
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_diligenza|{player.name}|{self.name}",
)
for i in range(2):
player.hand.append(player.game.deck.draw())
player.game.deck.draw(True, player)
player.game.deck.flip_wildwestshow()
return True
class Duello(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Duello', number)
super().__init__(suit, "Duello", number)
self.need_target = True
self.icon = '⚔️'
self.icon = "⚔️"
# self.desc = "Gioca questa carta contro un qualsiasi giocatore. A turno, cominciando dal tuo avversario, potete scartare una carta Bang!, il primo giocatore che non lo fa perde 1 vita"
# self.desc_eng = "Play this card against any player. In turn, starting with your opponent, you can discard a Bang! Card, the first player who does not do so loses 1 life."
def play_card(self, player, against, _with=None):
if against != None:
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
if against is not None:
super().play_card(player, against=against)
player.game.duel(player, against)
return True
@ -293,144 +480,197 @@ class Duello(Card):
class Emporio(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Emporio', number)
self.icon = '🏪'
# self.desc = "Scopri dal mazzo tante carte quanto il numero di giocatori vivi, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano"
# self.desc_eng = "Put on the table N cards from the deck, where N is the number of alive players, in turn, starting with you, choose a card and add it to your hand"
"""Scopri dal mazzo tante carte quanto il numero di giocatori vivi, a turno, partendo da te, scegliete una carta e aggiungetela alla vostra mano
def play_card(self, player, against, _with=None):
Put on the table N cards from the deck, where N is the number of alive players, in turn, starting with you, choose a card and add it to your hand
"""
def __init__(self, suit, number):
super().__init__(suit, "Emporio", number)
self.icon = "🏪"
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
super().play_card(player, against=against)
player.game.emporio()
return True
class Gatling(Card):
"""Spara a tutti gli altri giocatori
Shoot all the other players"""
def __init__(self, suit, number):
super().__init__(suit, 'Gatling', number)
self.icon = '🛰'
# self.desc = "Spara a tutti gli altri giocatori"
# self.desc_eng = "Shoot all the other players"
super().__init__(suit, "Gatling", number)
self.icon = "🛰"
self.alt_text = "👥💥"
def play_card(self, player, against, _with=None):
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
super().play_card(player, against=against)
player.game.attack_others(player)
player.game.attack_others(player, card_name=self.name)
return True
class Indiani(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Indiani!', number)
self.icon = '🏹'
# self.desc = "Tutti gli altri giocatori devono scartare un Bang! o perdere una vita"
# self.desc_eng = "All the other players must discard a Bang! or lose 1 Health Point"
"""Tutti gli altri giocatori devono scartare un Bang! o perdere una vita
def play_card(self, player, against, _with=None):
All the other players must discard a Bang! or lose 1 Health Point"""
def __init__(self, suit, number):
super().__init__(suit, "Indiani!", number)
self.icon = "🏹"
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
super().play_card(player, against=against)
player.game.indian_others(player)
return True
class Mancato(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Mancato!', number)
self.icon = '😅'
# self.desc = "Usa questa carta per annullare un bang"
# self.desc_eng = "Use this card to cancel the effect of a bang"
"""Usa questa carta per annullare un bang
def play_card(self, player, against, _with=None):
Use this card to cancel the effect of a bang"""
def __init__(self, suit, number):
super().__init__(suit, "Mancato!", number)
self.icon = "😅"
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
import bang.characters as chars
if against != None and player.character.check(player.game, chars.CalamityJanet):
import bang.expansions.fistful_of_cards.card_events as ce
if player.has_played_bang and (not any([isinstance(c, Volcanic) for c in player.equipment]) or player.game.check_event(ce.Lazo)):
if against is not None and player.character.check(
player.game, chars.CalamityJanet
):
if player.has_played_bang and (
not any((isinstance(c, Volcanic) for c in player.equipment))
or player.game.check_event(ce.Lazo)
):
return False
import bang.expansions.high_noon.card_events as ceh
if player.game.check_event(ceh.Sermone):
return False
player.sio.emit('chat_message', room=player.game.name,
data=f'_special_calamity|{player.name}|{self.name}|{against}')
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_special_calamity|{player.name}|{self.name}|{against}",
)
player.bang_used += 1
player.has_played_bang = True if not player.game.check_event(ceh.Sparatoria) else player.bang_used > 1
player.game.attack(player, against)
player.has_played_bang = (
True
if not player.game.check_event(ceh.Sparatoria)
else player.bang_used > 1
)
player.game.attack(player, against, card_name=self.name)
return True
return False
class Panico(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Panico!', number, range=1)
self.icon = '😱'
self.need_target = True
# self.desc = "Pesca una carta da un giocatore a distanza 1, scegli a caso dalla mano, oppure fra quelle che ha in gioco"
# self.desc_eng = "Steal a card from a player at distance 1"
"""Pesca una carta da un giocatore a distanza 1, scegli a caso dalla mano, oppure fra quelle che ha in gioco
def play_card(self, player, against, _with=None):
if against != None and (len(player.game.get_player_named(against).hand) + len(player.game.get_player_named(against).equipment)) > 0:
Steal a card from a player at distance 1"""
def __init__(self, suit, number):
super().__init__(suit, "Panico!", number, range=1)
self.icon = "😱"
self.need_target = True
self.can_target_self = True
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
if (
against is not None
and (
len(player.game.get_player_named(against).hand)
+ len(player.game.get_player_named(against).equipment)
)
> 0
and (player.name != against or len(player.equipment) > 0)
):
super().play_card(player, against=against)
from bang.players import PendingAction
player.pending_action = PendingAction.CHOOSE
player.choose_action = 'steal'
player.target_p = against
print('choose now')
player.game.steal_discard(player, against, self)
return True
return False
class Saloon(Card):
"""Tutti i giocatori recuperano un punto vita compreso chi gioca la carta
Everyone heals 1 Health point"""
def __init__(self, suit, number):
super().__init__(suit, 'Saloon', number)
# self.desc = "Tutti i giocatori recuperano un punto vita compreso chi gioca la carta"
# self.desc_eng = "Everyone heals 1 Health point"
self.icon = '🍻'
super().__init__(suit, "Saloon", number)
self.icon = "🍻"
self.alt_text = "👥🍺"
def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name,
data=f'_saloon|{player.name}|{self.name}')
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_saloon|{player.name}|{self.name}",
)
for p in player.game.get_alive_players():
p.lives = min(p.lives+1, p.max_lives)
p.lives = min(p.lives + 1, p.max_lives)
p.notify_self()
return True
class WellsFargo(Card):
"""Pesca 3 carte dalla cima del mazzo
Draw 3 cards from the deck"""
def __init__(self, suit, number):
super().__init__(suit, 'WellsFargo', number)
# self.desc = "Pesca 3 carte dalla cima del mazzo"
# self.desc_eng = "Draw 3 cards from the deck"
self.icon = '💸'
super().__init__(suit, "WellsFargo", number)
self.icon = "💸"
self.alt_text = "🎴🎴🎴"
def play_card(self, player, against, _with=None):
player.sio.emit('chat_message', room=player.game.name,
data=f'_wellsfargo|{player.name}|{self.name}')
for i in range(3):
player.hand.append(player.game.deck.draw())
def play_card(
self, player: Player, against: str = None, _with: Card = None
) -> bool:
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_wellsfargo|{player.name}|{self.name}",
)
for _ in range(3):
player.game.deck.draw(True, player)
player.game.deck.flip_wildwestshow()
return True
def get_starting_deck(expansions:List[str]) -> List[Card]:
from bang.expansions import DodgeCity
def get_starting_deck(expansions: List[str]) -> List[Card]:
from bang.expansions import DodgeCity, TheValleyOfShadows
base_cards = [
Barile(Suit.SPADES, 'Q'),
Barile(Suit.SPADES, 'K'),
Barile(Suit.SPADES, "Q"),
Barile(Suit.SPADES, "K"),
Dinamite(Suit.HEARTS, 2),
Mirino(Suit.SPADES, 'A'),
Mirino(Suit.SPADES, "A"),
Mustang(Suit.HEARTS, 8),
Mustang(Suit.HEARTS, 9),
Prigione(Suit.SPADES, 'J'),
Prigione(Suit.SPADES, "J"),
Prigione(Suit.HEARTS, 4),
Prigione(Suit.SPADES, 10),
Remington(Suit.CLUBS, 'K'),
RevCarabine(Suit.CLUBS, 'A'),
Schofield(Suit.CLUBS, 'J'),
Schofield(Suit.CLUBS, 'Q'),
Schofield(Suit.SPADES, 'K'),
Remington(Suit.CLUBS, "K"),
RevCarabine(Suit.CLUBS, "A"),
Schofield(Suit.CLUBS, "J"),
Schofield(Suit.CLUBS, "Q"),
Schofield(Suit.SPADES, "K"),
Volcanic(Suit.SPADES, 10),
Volcanic(Suit.CLUBS, 10),
Winchester(Suit.SPADES, 8),
Bang(Suit.SPADES, 'A'),
Bang(Suit.SPADES, "A"),
Bang(Suit.DIAMONDS, 2),
Bang(Suit.DIAMONDS, 3),
Bang(Suit.DIAMONDS, 4),
@ -440,10 +680,10 @@ def get_starting_deck(expansions:List[str]) -> List[Card]:
Bang(Suit.DIAMONDS, 8),
Bang(Suit.DIAMONDS, 9),
Bang(Suit.DIAMONDS, 10),
Bang(Suit.DIAMONDS, 'J'),
Bang(Suit.DIAMONDS, 'Q'),
Bang(Suit.DIAMONDS, 'K'),
Bang(Suit.DIAMONDS, 'A'),
Bang(Suit.DIAMONDS, "J"),
Bang(Suit.DIAMONDS, "Q"),
Bang(Suit.DIAMONDS, "K"),
Bang(Suit.DIAMONDS, "A"),
Bang(Suit.CLUBS, 2),
Bang(Suit.CLUBS, 3),
Bang(Suit.CLUBS, 4),
@ -452,34 +692,34 @@ def get_starting_deck(expansions:List[str]) -> List[Card]:
Bang(Suit.CLUBS, 7),
Bang(Suit.CLUBS, 8),
Bang(Suit.CLUBS, 9),
Bang(Suit.HEARTS, 'Q'),
Bang(Suit.HEARTS, 'K'),
Bang(Suit.HEARTS, 'A'),
Bang(Suit.HEARTS, "Q"),
Bang(Suit.HEARTS, "K"),
Bang(Suit.HEARTS, "A"),
Birra(Suit.HEARTS, 6),
Birra(Suit.HEARTS, 7),
Birra(Suit.HEARTS, 8),
Birra(Suit.HEARTS, 9),
Birra(Suit.HEARTS, 10),
Birra(Suit.HEARTS, 'J'),
CatBalou(Suit.HEARTS, 'K'),
Birra(Suit.HEARTS, "J"),
CatBalou(Suit.HEARTS, "K"),
CatBalou(Suit.DIAMONDS, 9),
CatBalou(Suit.DIAMONDS, 10),
CatBalou(Suit.DIAMONDS, 'J'),
CatBalou(Suit.DIAMONDS, "J"),
Diligenza(Suit.SPADES, 9),
Diligenza(Suit.SPADES, 9),
Duello(Suit.DIAMONDS, 'Q'),
Duello(Suit.SPADES, 'J'),
Duello(Suit.DIAMONDS, "Q"),
Duello(Suit.SPADES, "J"),
Duello(Suit.CLUBS, 8),
Emporio(Suit.CLUBS, 9),
Emporio(Suit.SPADES, 'Q'),
Emporio(Suit.SPADES, "Q"),
Gatling(Suit.HEARTS, 10),
Indiani(Suit.DIAMONDS, 'K'),
Indiani(Suit.DIAMONDS, 'A'),
Indiani(Suit.DIAMONDS, "K"),
Indiani(Suit.DIAMONDS, "A"),
Mancato(Suit.CLUBS, 10),
Mancato(Suit.CLUBS, 'J'),
Mancato(Suit.CLUBS, 'Q'),
Mancato(Suit.CLUBS, 'K'),
Mancato(Suit.CLUBS, 'A'),
Mancato(Suit.CLUBS, "J"),
Mancato(Suit.CLUBS, "Q"),
Mancato(Suit.CLUBS, "K"),
Mancato(Suit.CLUBS, "A"),
Mancato(Suit.SPADES, 2),
Mancato(Suit.SPADES, 3),
Mancato(Suit.SPADES, 4),
@ -487,14 +727,15 @@ def get_starting_deck(expansions:List[str]) -> List[Card]:
Mancato(Suit.SPADES, 6),
Mancato(Suit.SPADES, 7),
Mancato(Suit.SPADES, 8),
Panico(Suit.HEARTS, 'J'),
Panico(Suit.HEARTS, 'Q'),
Panico(Suit.HEARTS, 'A'),
Panico(Suit.HEARTS, "J"),
Panico(Suit.HEARTS, "Q"),
Panico(Suit.HEARTS, "A"),
Panico(Suit.DIAMONDS, 8),
Saloon(Suit.HEARTS, 5),
WellsFargo(Suit.HEARTS, 3),
]
if 'dodge_city' in expansions:
if "dodge_city" in expansions:
base_cards.extend(DodgeCity.get_cards())
if "the_valley_of_shadows" in expansions:
base_cards.extend(TheValleyOfShadows.get_cards())
return base_cards

View File

@ -1,143 +1,228 @@
from abc import ABC, abstractmethod
from typing import List
from __future__ import annotations
from abc import ABC
from bang.expansions import *
from typing import List, TYPE_CHECKING
from globals import G
if TYPE_CHECKING:
from bang.players import Player
from bang.game import Game
class Character(ABC):
def __init__(self, name: str, max_lives: int, sight_mod: int = 0, visibility_mod: int = 0, pick_mod: int = 0, desc: str = ''):
"""Base class for all characters"""
def __init__(
self,
name: str,
max_lives: int,
sight_mod: int = 0,
visibility_mod: int = 0,
pick_mod: int = 0,
desc: str = "",
):
super().__init__()
self.name = name
self.max_lives = max_lives
self.sight_mod = sight_mod
self.visibility_mod = visibility_mod
self.is_character = True
self.pick_mod = pick_mod
self.desc = desc
self.icon = '🤷‍♂️'
self.number = ''.join(['❤️']*self.max_lives)
self.icon = "🤷‍♂️"
self.number = "".join(["❤️"] * self.max_lives)
def check(self, game, character):
def check(self, game: Game, character: Character):
"""Check character type and if Sbornia is active"""
import bang.expansions.high_noon.card_events as ceh
if game.check_event(ceh.Sbornia):
return False
return isinstance(self, character)
def special(self, player: Player, data):
"""Base for special actions that can be performed by a character"""
import bang.expansions.high_noon.card_events as ceh
if player.game.check_event(ceh.Sbornia):
return False
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_use_special|{player.name}|{self.name}",
)
return True
class BartCassidy(Character):
"""Ogni volta che viene ferito, pesca una carta
Each time he is hurt, he draws a card"""
def __init__(self):
super().__init__("Bart Cassidy", max_lives=4)
# self.desc = "Ogni volta che viene ferito, pesca una carta"
# self.desc_eng = "Each time he is hurt, he draws a card"
self.icon = '💔'
self.icon = "💔"
def on_hurt(self, dmg):
pass
class BlackJack(Character):
"""All'inizio del suo turno, quando deve pescare, mostra a tutti la seconda carta, se è Cuori o Quadri pesca una terza carta senza farla vedere
At the beginning of his turn, when he has to draw, he shows everyone the second card, if it is Hearts or Diamonds he draws a third card without showing it
"""
def __init__(self):
super().__init__("Black Jack", max_lives=4)
# self.desc = "All'inizio del suo turno, quando deve pescare, mostra a tutti la seconda carta, se è Cuori o Quadri pesca una terza carta senza farla vedere"
# self.desc_eng = "At the beginning of his turn, when he has to draw, he shows everyone the second card, if it is Hearts or Diamonds he draws a third card without showing it"
self.icon = '🎰'
self.icon = "🎰"
class CalamityJanet(Character):
"""Può usare i Mancato! come Bang! e viceversa
She can use the Missed! as Bang! and the other way around"""
def __init__(self):
super().__init__("Calamity Janet", max_lives=4)
self.icon = '🔀'
# self.desc = "Può usare i Mancato! come Bang! e viceversa"
# self.desc_eng = "She can use the Missed! as Bang! and the other way around"
self.icon = "🔀"
class ElGringo(Character):
"""Ogni volta che perde un punto vita pesca una carta dalla mano del giocatore responsabile ma solo se il giocatore in questione ha carte in mano (una carta per ogni punto vita)
Each time he is hurt, he draws a card from the hand of the attacking player"""
def __init__(self):
super().__init__("El Gringo", max_lives=3)
# self.desc = "Ogni volta che perde un punto vita pesca una carta dalla mano del giocatore responsabile ma solo se il giocatore in questione ha carte in mano (una carta per ogni punto vita)"
# self.desc_eng = "Each time he is hurt, he draws a card from the hand of the attacking player"
self.icon = '🤕'
self.icon = "🤕"
# ovviamente la dinamite non è considerata danno inferto da un giocatore
class JesseJones(Character):
"""All'inizio del suo turno, quando deve pescare, può prendere la prima carta a caso dalla mano di un giocatore e la seconda dal mazzo
When he has to draw his cards, he may draw the first card from the hand of another player
"""
def __init__(self):
super().__init__("Jesse Jones", max_lives=4)
# self.desc = "All'inizio del suo turno, quando deve pescare, può prendere la prima carta a caso dalla mano di un giocatore e la seconda dal mazzo"
# self.desc_eng = "When he has to draw his cards, he may draw the first card from the hand of another player"
self.icon = '😜'
self.icon = "😜"
class Jourdonnais(Character):
"""Gioca come se avesse un Barile sempre attivo, nel caso in cui metta in gioco un Barile 'Reale' può estrarre due volte
He plays as he had a Barrel always active, if he equips another Barrel, he can flip 2 cards
"""
def __init__(self):
super().__init__("Jourdonnais", max_lives=4)
# self.desc = "Gioca come se avesse un Barile sempre attivo, nel caso in cui metta in gioco un Barile 'Reale' può estrarre due volte"
# self.desc_eng = "He plays as he had a Barrel always active, if he equips another Barrel, he can flip 2 cards"
self.icon = '🛢'
self.icon = "🛢"
class KitCarlson(Character):
"""All'inizio del suo turno, quando deve pescare, pesca tre carte, ne sceglie due da tenere in mano e la rimanente la rimette in cima la mazzo
When he has to draw, he peeks 3 cards and chooses 2, putting the other card on the top of the deck
"""
def __init__(self):
super().__init__("Kit Carlson", max_lives=4)
# self.desc = "All'inizio del suo turno, quando deve pescare, pesca tre carte, ne sceglie due da tenere in mano e la rimanente la rimette in cima la mazzo"
# self.desc_eng = "When he has to draw, he peeks 3 cards and chooses 2, putting the other card on the top of the deck"
self.icon = '🤔'
self.icon = "🤔"
class LuckyDuke(Character):
"""Ogni volta che deve estrarre, prende due carte dal mazzo, sceglie una delle due carte per l'estrazione, infine le scarta entrambe
Every time he has to flip a card, he can flip 2 times"""
def __init__(self):
super().__init__("Lucky Duke", max_lives=4, pick_mod=1)
# self.desc = "Ogni volta che deve estrarre, prende due carte dal mazzo, sceglie una delle due carte per l'estrazione, infine le scarta entrambe"
# self.desc_eng = "Every time he has to flip a card, he can flip 2 times"
self.icon = '🍀'
self.icon = "🍀"
class PaulRegret(Character):
"""Gioca come se avesse una Mustang sempre attiva, nel caso in cui metta in gioco una Mustang 'Reale' l'effetto si somma tranquillamente
The other players see him at distance +1"""
def __init__(self):
super().__init__("Paul Regret", max_lives=3, visibility_mod=1)
# self.desc = "Gioca come se avesse una Mustang sempre attiva, nel caso in cui metta in gioco una Mustang 'Reale' l'effetto si somma tranquillamente"
# self.desc_eng = "The other players see him at distance +1"
self.icon = '🏇'
self.icon = "🏇"
class PedroRamirez(Character):
"""All'inizio del suo turno, quando deve pescare, può prendere la prima carta dalla cima degli scarti e la seconda dal mazzo
When he has to draw, he may pick the first card from the discarded cards"""
def __init__(self):
super().__init__("Pedro Ramirez", max_lives=4)
# self.desc = "All'inizio del suo turno, quando deve pescare, può prendere la prima carta dalla cima degli scarti e la seconda dal mazzo"
# self.desc_eng = "When he has to draw, he may pick the first card from the discarded cards"
self.icon = '🚮'
self.icon = "🚮"
class RoseDoolan(Character):
"""Gioca come se avesse un Mirino sempre attivo, nel caso in cui metta in gioco una Mirino 'Reale' l'effetto si somma tranquillamente
She sees the other players at distance -1"""
def __init__(self):
super().__init__("Rose Doolan", max_lives=4, sight_mod=1)
self.icon = '🕵️‍♀️'
# self.desc = "Gioca come se avesse un Mirino sempre attivo, nel caso in cui metta in gioco una Mirino 'Reale' l'effetto si somma tranquillamente"
# self.desc_eng = "She sees the other players at distance -1"
self.icon = "🕵️‍♀️"
class SidKetchum(Character):
"""Può scartare due carte per recuperare un punto vita anche più volte di seguito a patto di avere carte da scartare, può farlo anche nel turno dell'avversario se stesse per morire
He can discard 2 cards to regain 1HP"""
def __init__(self):
super().__init__("Sid Ketchum", max_lives=4)
# self.desc = "Può scartare due carte per recuperare un punto vita anche più volte di seguito a patto di avere carte da scartare, può farlo anche nel turno dell'avversario se stesse per morire"
# self.desc_eng = "He can discard 2 cards to regain 1HP"
self.icon = '🤤'
self.icon = "🤤"
class SlabTheKiller(Character):
"""Per evitare i suoi Bang servono due Mancato, un eventuale barile vale solo come un Mancato
To dodge his Bang! cards other players need 2 Missed!"""
def __init__(self):
super().__init__("Slab The Killer", max_lives=4)
# self.desc = "Per evitare i suoi Bang servono due Mancato, un eventuale barile vale solo come un Mancato"
# self.desc_eng = "To dodge his Bang! cards other players need 2 Missed!"
self.icon = '🔪'
#vale per tutte le carte bang non solo per la carta che si chiama Bang!
self.icon = "🔪"
# vale per tutte le carte bang non solo per la carta che si chiama Bang!
class SuzyLafayette(Character):
"""Appena rimane senza carte in mano pesca immediatamente una carta dal mazzo
Whenever she has an empty hand, she draws a card"""
def __init__(self):
super().__init__("Suzy Lafayette", max_lives=4)
# self.desc = "Appena rimane senza carte in mano pesca immediatamente una carta dal mazzo"
# self.desc_eng = "Whenever she has an empty hand, she draws a card"
self.icon = '🔂'
self.icon = "🔂"
class VultureSam(Character):
"""Quando un personaggio viene eliminato prendi tutte le carte di quel giocatore e aggiungile alla tua mano, sia le carte in mano che quelle in gioco
When a player dies, he gets all the cards in the dead's hand and equipments"""
def __init__(self):
super().__init__("Vulture Sam", max_lives=4)
# self.desc = "Quando un personaggio viene eliminato prendi tutte le carte di quel giocatore e aggiungile alla tua mano, sia le carte in mano che quelle in gioco"
# self.desc_eng = "When a player dies, he gets all the cards in the dead's hand and equipments"
self.icon = '🦉'
self.icon = "🦉"
class WillyTheKid(Character):
"""Questo personaggio può giocare quanti bang vuole nel suo turno
He doesn't have limits to the amounts of bang he can use"""
def __init__(self):
super().__init__("Willy The Kid", max_lives=4)
# self.desc = "Questo personaggio può giocare quanti bang vuole nel suo turno"
# self.desc_eng = "He doesn't have limits to the amounts of bang he can use"
self.icon = '🎉'
self.icon = "🎉"
def all_characters(expansions: List[str]):
from bang.expansions import DodgeCity
from bang.expansions import DodgeCity, TheValleyOfShadows, WildWestShow, GoldRush
base_chars = [
BartCassidy(),
BlackJack(),
@ -156,6 +241,12 @@ def all_characters(expansions: List[str]):
VultureSam(),
WillyTheKid(),
]
if 'dodge_city' in expansions:
if "dodge_city" in expansions:
base_chars.extend(DodgeCity.get_characters())
if "gold_rush" in expansions:
base_chars.extend(GoldRush.get_characters())
if "the_valley_of_shadows" in expansions:
base_chars.extend(TheValleyOfShadows.get_characters())
if "wild_west_show" in expansions:
base_chars.extend(WildWestShow.get_characters())
return base_chars

View File

@ -1,60 +1,152 @@
from typing import List, Set, Dict, Tuple, Optional
import random
from typing import List, Set, Dict, Tuple, Optional, TYPE_CHECKING
import bang.cards as cs
import bang.expansions.fistful_of_cards.card_events as ce
import bang.expansions.high_noon.card_events as ceh
import bang.expansions.wild_west_show.card_events as cew
import bang.expansions.wild_west_show.characters as chw
import bang.expansions.gold_rush.shop_cards as grc
import bang.expansions.train_robbery.stations as trs
import bang.expansions.train_robbery.trains as trt
from globals import G
if TYPE_CHECKING:
from bang.game import Game
from bang.players import Player
class Deck:
def __init__(self, game):
"""Class that handles all deck dealing information"""
def __init__(self, game: "Game"):
super().__init__()
self.cards: List[cs.Card] = cs.get_starting_deck(game.expansions)
self.mancato_cards: List[str] = []
self.mancato_cards_not_green_or_blue: List[str] = []
self.green_cards: Set[str] = set()
for c in self.cards:
if isinstance(c, cs.Mancato) and c.name not in self.mancato_cards:
self.mancato_cards.append(c.name)
if not (c.usable_next_turn or c.is_equipment):
self.mancato_cards_not_green_or_blue.append(c.name)
elif c.usable_next_turn:
self.green_cards.add(c.name)
self.all_cards_str: List[str] = []
for c in self.cards:
if c.name not in self.all_cards_str:
self.all_cards_str.append(c.name)
self.game = game
self.event_cards: List[ce.CardEvent] = []
endgame_cards = []
if 'fistful_of_cards' in game.expansions:
self.event_cards.extend(ce.get_all_events())
self.event_cards_wildwestshow: List[ce.CardEvent] = []
self.stations: List[trs.StationCard] = []
self.train_pile: List[trt.TrainCard] = []
self.current_train: List[trt.TrainCard] = []
endgame_cards: List[ce.CardEvent] = []
if "fistful_of_cards" in game.expansions:
self.event_cards.extend(ce.get_all_events(game.rng))
endgame_cards.append(ce.get_endgame_card())
if 'high_noon' in game.expansions:
self.event_cards.extend(ceh.get_all_events())
if "high_noon" in game.expansions:
self.event_cards.extend(ceh.get_all_events(game.rng))
endgame_cards.append(ceh.get_endgame_card())
if "wild_west_show" in game.expansions:
self.event_cards_wildwestshow.extend(cew.get_all_events(game.rng))
game.rng.shuffle(self.event_cards_wildwestshow)
self.event_cards_wildwestshow.insert(0, None)
self.event_cards_wildwestshow.append(cew.get_endgame_card())
if "train_robbery" in game.expansions:
self.stations = game.rng.sample(trs.get_all_stations(), len(game.players))
self.train_pile = trt.get_all_cards(game.rng)
self.current_train = [trt.get_locomotives(game.rng)[0]] + self.train_pile[
:3
]
if len(self.event_cards) > 0:
random.shuffle(self.event_cards)
game.rng.shuffle(self.event_cards)
self.event_cards = self.event_cards[:12]
self.event_cards.insert(0, None)
self.event_cards.insert(0, None) # 2 perchè iniziale, e primo flip dallo sceriffo
self.event_cards.append(random.choice(endgame_cards))
random.shuffle(self.cards)
self.event_cards.insert(
0, None
) # 2 perchè iniziale, e primo flip dallo sceriffo
self.event_cards.append(game.rng.choice(endgame_cards))
game.rng.shuffle(self.cards)
self.shop_deck: List[grc.ShopCard] = []
self.shop_cards: List[grc.ShopCard] = []
if "gold_rush" in game.expansions:
self.shop_cards = [None, None, None]
self.shop_deck = grc.get_cards()
game.rng.shuffle(self.shop_deck)
self.fill_gold_rush_shop()
self.scrap_pile: List[cs.Card] = []
print(f'Deck initialized with {len(self.cards)} cards')
print(f"Deck initialized with {len(self.cards)} cards")
def flip_event(self):
if len(self.event_cards) > 0 and not (isinstance(self.event_cards[0], ce.PerUnPugnoDiCarte) or isinstance(self.event_cards[0], ceh.MezzogiornoDiFuoco)):
"""Flip event for regular Sheriff turn (High Noon, Fistful of Cards)"""
if len(self.event_cards) > 0 and not (
isinstance(self.event_cards[0], ce.PerUnPugnoDiCarte)
or isinstance(self.event_cards[0], ceh.MezzogiornoDiFuoco)
):
self.event_cards.append(self.event_cards.pop(0))
if len(self.event_cards) > 0 and self.event_cards[0] is not None:
self.event_cards[0].on_flipped(self.game)
self.game.notify_event_card()
self.game.notify_all()
def flip_wildwestshow(self):
"""Flip event for Wild West Show only"""
if len(self.event_cards_wildwestshow) > 0 and not isinstance(
self.event_cards_wildwestshow[0], cew.WildWestShow
):
self.event_cards_wildwestshow.append(self.event_cards_wildwestshow.pop(0))
if (
len(self.event_cards_wildwestshow) > 0
and self.event_cards_wildwestshow[0] is not None
):
self.event_cards_wildwestshow[0].on_flipped(self.game)
self.game.notify_event_card_wildwestshow()
self.game.notify_all()
def fill_gold_rush_shop(self):
"""
As gold_rush shop cards are stored in a fixed 3 space array,
this function replaces the None values with new cards.
"""
if not any((c is None for c in self.shop_cards)):
return
for i in range(3):
if self.shop_cards[i] is None:
print(f"replacing gr-card {i}")
self.shop_cards[i] = self.shop_deck.pop(0)
self.shop_cards[i].reset_card()
self.game.notify_gold_rush_shop()
def move_train_forward(self):
if len(self.stations) == 0:
return
if len(self.current_train) == len(self.stations) + 4:
return
if len(self.current_train) > 0:
self.current_train.append(None)
self.game.notify_stations()
def peek(self, n_cards: int) -> list:
return self.cards[:n_cards]
def peek_scrap_pile(self) -> cs.Card:
def peek_scrap_pile(self, n_cards: int=1) -> List[cs.Card]:
if len(self.scrap_pile) > 0:
return self.scrap_pile[-1]
return self.scrap_pile[-n_cards:]
else:
return None
def pick_and_scrap(self) -> cs.Card:
card = self.cards.pop(0)
self.scrap_pile.append(card)
jpain = None
for p in self.game.players:
if p.character.check(self.game, chw.JohnPain) and len(p.hand) < 6:
jpain = p
break
if jpain:
jpain.hand.append(card)
jpain.notify_self()
else:
self.scrap_pile.append(card)
if len(self.cards) == 0:
self.reshuffle()
self.game.notify_scrap_pile()
@ -63,32 +155,66 @@ class Deck:
def put_on_top(self, card: cs.Card):
self.cards.insert(0, card)
def draw(self, ignore_event = False) -> cs.Card:
if self.game.check_event(ce.MinieraAbbandonata) and len(self.scrap_pile) > 0 and not ignore_event:
return self.draw_from_scrap_pile()
def draw(self, ignore_event=False, player=None) -> cs.Card:
if (
self.game.check_event(ce.MinieraAbbandonata)
and len(self.scrap_pile) > 0
and not ignore_event
):
card = self.draw_from_scrap_pile()
if player is not None and self.game.replay_speed > 0:
G.sio.emit(
"card_drawn",
room=self.game.name,
data={"player": player.name, "pile": "scrap"},
)
player.hand.append(card)
return card
card = self.cards.pop(0)
if len(self.cards) == 0:
self.reshuffle()
if player is not None and self.game.replay_speed > 0:
G.sio.emit(
"card_drawn",
room=self.game.name,
data={"player": player.name, "pile": "deck"},
)
player.hand.append(card)
return card
def reshuffle(self):
self.cards = self.scrap_pile[:-1].copy()
random.shuffle(self.cards)
self.game.rng.shuffle(self.cards)
self.scrap_pile = self.scrap_pile[-1:]
def draw_from_scrap_pile(self) -> cs.Card:
if len(self.scrap_pile) > 0:
card = self.scrap_pile.pop(-1)
self.game.notify_scrap_pile()
card.reset_card()
return card
else:
return self.draw()
def scrap(self, card: cs.Card, ignore_event = False):
if card.usable_next_turn:
card.can_be_used_now = False
def scrap(self, card: cs.Card, ignore_event:bool=False, player:'Player'=None):
if card.number == 42:
return
card.reset_card()
if self.game.check_event(ce.MinieraAbbandonata) and not ignore_event:
self.put_on_top(card)
else:
self.scrap_pile.append(card)
self.game.notify_scrap_pile()
if player is not None and self.game.replay_speed > 0:
G.sio.emit(
"card_scrapped",
room=self.game.name,
data={
"player": player.name,
"card": card.__dict__,
"pile": "scrap",
},
)
G.sio.sleep(0.6)
self.game.notify_scrap_pile()
else:
self.game.notify_scrap_pile()

View File

@ -1,3 +1,4 @@
# pylint: skip-file
class DodgeCity():
def get_characters():
@ -7,3 +8,139 @@ class DodgeCity():
def get_cards():
from bang.expansions.dodge_city import cards
return cards.get_starting_deck()
def get_expansion_info(self):
return {
"id": "dodge_city",
"name": "Dodge City",
"cards": [
{"type": "characters", "cards": DodgeCity.get_characters()},
{"type": "cards", "cards": DodgeCity.get_cards()}
]
}
class HighNoon():
def get_events():
from bang.expansions.high_noon import card_events
return card_events.get_all_events() + [card_events.get_endgame_card()]
def get_expansion_info(self):
return {
"id": "high_noon",
"name": "High Noon",
"cards": [
{"type": "events", "cards": HighNoon.get_events()}
]
}
class FistfulOfCards():
def get_events():
from bang.expansions.fistful_of_cards import card_events
return card_events.get_all_events() + [card_events.get_endgame_card()]
def get_expansion_info(self):
return {
"id": "fistful_of_cards",
"name": "Fistful of Cards",
"cards": [
{"type": "events", "cards": FistfulOfCards.get_events()}
]
}
class GoldRush():
def get_characters():
from bang.expansions.gold_rush import characters
return characters.all_characters()
def get_shop_cards():
from bang.expansions.gold_rush import shop_cards
return shop_cards.get_cards()
def get_expansion_info(self):
return {
"id": "gold_rush",
"name": "Gold Rush",
"cards": [
{"type": "characters", "cards": GoldRush.get_characters()},
{"type": "cards", "cards": GoldRush.get_shop_cards()}
]
}
class TheValleyOfShadows():
def get_characters():
from bang.expansions.the_valley_of_shadows import characters
return characters.all_characters()
def get_cards():
from bang.expansions.the_valley_of_shadows import cards
return cards.get_starting_deck()
def get_expansion_info(self):
return {
"id": "the_valley_of_shadows",
"name": "The Valley of Shadows",
"cards": [
{"type": "characters", "cards": TheValleyOfShadows.get_characters()},
{"type": "cards", "cards": TheValleyOfShadows.get_cards()}
]
}
class WildWestShow():
def get_characters():
from bang.expansions.wild_west_show import characters
return characters.all_characters()
def get_events():
from bang.expansions.wild_west_show import card_events
return card_events.get_all_events() + [card_events.get_endgame_card()]
def get_expansion_info(self):
return {
"id": "wild_west_show",
"name": "Wild West Show",
"cards": [
{"type": "characters", "cards": WildWestShow.get_characters()},
{"type": "events", "cards": WildWestShow.get_events()}
]
}
class TrainRobbery():
def get_stations():
from bang.expansions.train_robbery import stations
return stations.get_all_stations()
def get_trains():
from bang.expansions.train_robbery import trains
return trains.get_all_cards() + trains.get_locomotives()
def get_expansion_info(self):
return {
"id": "train_robbery",
"name": "Train Robbery",
"cards": [
{"type": "stations", "cards": TrainRobbery.get_stations()},
{"type": "trains", "cards": TrainRobbery.get_trains()}
]
}
def get_expansion_info(expansion_id):
expansion_map = {
"dodge_city": DodgeCity(),
"high_noon": HighNoon(),
"fistful_of_cards": FistfulOfCards(),
"gold_rush": GoldRush(),
"the_valley_of_shadows": TheValleyOfShadows(),
"wild_west_show": WildWestShow(),
"train_robbery": TrainRobbery()
}
expansion_info = expansion_map[expansion_id].get_expansion_info()
for section in expansion_info["cards"]:
unique_cards = []
seen_card = set()
for card in section["cards"]:
if card.name not in seen_card:
unique_cards.append(card)
seen_card.add(card.name)
section["cards"] = unique_cards
return expansion_info

View File

@ -1,38 +1,44 @@
from bang.cards import *
import bang.expansions.fistful_of_cards.card_events as ce
from globals import G
class Binocolo(Mirino):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Binocolo'
self.icon = '🔍'
self.name = "Binocolo"
self.icon = "🔍"
class Riparo(Mustang):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Riparo'
self.icon = ''
self.name = "Riparo"
self.icon = ""
class Pugno(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Pugno!', number, range=1)
self.icon = '👊'
super().__init__(suit, "Pugno!", number, range=1)
self.icon = "👊"
self.alt_text = "1🔎 💥"
# self.desc = "Spara a un giocatore a distanza 1"
# self.desc_eng = "Shoot a player at distance 1"
self.need_target = True
def play_card(self, player, against, _with=None):
if against != None:
if against is not None:
super().play_card(player, against=against)
player.game.attack(player, against)
player.game.attack(player, against, card_name=self.name)
return True
return False
class Schivata(Mancato):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Schivata'
self.icon = '🙅‍♂️'
self.name = "Schivata"
self.icon = "🙅‍♂️"
# self.desc += " e poi pesca una carta"
# self.desc_eng += " and then draw a card."
self.alt_text = "😅 | 🎴"
@ -41,71 +47,93 @@ class Schivata(Mancato):
return False
def use_card(self, player):
player.hand.append(player.game.deck.draw())
player.game.deck.draw(True, player=player)
player.notify_self()
class RagTime(Panico):
def __init__(self, suit, number):
Card.__init__(self, suit, 'Rag Time', number)
self.icon = '🎹'
Card.__init__(self, suit, "Rag Time", number)
self.icon = "🎹"
# self.desc = "Ruba 1 carta da un giocatore a prescindere dalla distanza"
# self.desc_eng = "Steal a card from another player at any distance"
self.need_target = True
self.need_with = True
self.alt_text = '2🃏 | 👤😱'
self.alt_text = "2🃏 | 👤😱"
def play_card(self, player, against, _with):
if against != None and _with != None:
if against is not None and _with is not None:
player.game.deck.scrap(_with)
super().play_card(player, against=against)
super().play_card(player, against=against, _with=_with)
return True
return False
class Rissa(CatBalou):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Rissa'
self.icon = '🥊'
self.name = "Rissa"
self.icon = "🥊"
# self.desc = "Fai scartare una carta a tutti gli altri giocatori, scegli a caso dalla mano, oppure fra quelle che hanno in gioco"
# self.desc_eng = "Choose a card to discard from the hand/equipment of all the other players"
self.need_with = True
self.need_target = False
self.alt_text = '2🃏 | 👤💃'
self.alt_text = "2🃏 | 👤💃"
def play_card(self, player, against, _with):
if _with != None:
players_with_cards = [p.name for p in player.game.players if p != player and (len(p.hand)+len(p.equipment)) > 0]
if len(players_with_cards) == 0:
if _with is not None:
if not any(
(
p != player and (len(p.hand) + len(p.equipment)) > 0
for p in player.game.players
)
):
return False
# se sono qui vuol dire che ci sono giocatori con carte in mano oltre a me
player.rissa_targets = []
target = player.game.get_player_named(player.name, next=True)
while target != player:
if len(target.hand) + len(target.equipment) > 0:
player.rissa_targets.append(target)
target = player.game.get_player_named(target.name, next=True)
player.game.deck.scrap(_with)
player.event_type = 'rissa'
super().play_card(player, against=players_with_cards[0])
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}')
player.event_type = "rissa"
print(f"rissa targets: {player.rissa_targets}")
super().play_card(
player, against=player.rissa_targets.pop(0).name, _with=_with
)
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card|{player.name}|{self.name}",
)
return True
return False
class SpringField(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Springfield', number)
self.icon = '🌵'
super().__init__(suit, "Springfield", number)
self.icon = "🌵"
# self.desc = "Spara a un giocatore a prescindere dalla distanza"
# self.desc_eng = "Shoot a player at any distance"
self.need_target = True
self.need_with = True
self.alt_text = '2🃏 | 👤💥'
self.alt_text = "2🃏 | 👤💥"
def play_card(self, player, against, _with=None):
if against != None and _with != None:
if against is not None and _with is not None:
player.game.deck.scrap(_with)
super().play_card(player, against=against)
player.game.attack(player, against)
super().play_card(player, against=against, _with=_with)
player.game.attack(player, against, card_name=self.name)
return True
return False
class Tequila(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Tequila', number)
self.icon = '🍹'
super().__init__(suit, "Tequila", number)
self.icon = "🍹"
# self.desc = "Fai recuperare 1 vita a un giocatore a tua scelta, anche te stesso"
# self.desc_eng = "Heal 1 HP to a player of your choice (can be you)"
self.need_target = True
@ -114,37 +142,46 @@ class Tequila(Card):
self.alt_text = "2🃏 | 👤🍺"
def play_card(self, player, against, _with=None):
if against != None and _with != None:
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card_for|{player.name}|{self.name}|{against}')
if against is not None and _with is not None:
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_for|{player.name}|{self.name}|{against}",
)
player.game.deck.scrap(_with)
player.game.get_player_named(against).lives = min(player.game.get_player_named(against).lives+1, player.game.get_player_named(against).max_lives)
player.game.get_player_named(against).lives = min(
player.game.get_player_named(against).lives + 1,
player.game.get_player_named(against).max_lives,
)
player.game.get_player_named(against).notify_self()
return True
return False
class Whisky(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Whisky', number)
self.icon = '🥃'
super().__init__(suit, "Whisky", number)
self.icon = "🥃"
# self.desc = "Gioca questa carta per recuperare fino a 2 punti vita"
# self.desc_eng = "Heal 2 HP"
self.need_with = True
self.alt_text = '2🃏 | 🍺🍺'
self.alt_text = "2🃏 | 🍺🍺"
def play_card(self, player, against, _with=None):
if _with != None:
super().play_card(player, against=against)
if _with is not None:
super().play_card(player, against=against, _with=_with)
player.game.deck.scrap(_with)
player.lives = min(player.lives+2, player.max_lives)
player.lives = min(player.lives + 2, player.max_lives)
player.notify_self()
return True
return False
class Bibbia(Schivata):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Bibbia'
self.icon = '📖'
self.name = "Bibbia"
self.icon = "📖"
self.usable_next_turn = True
self.can_be_used_now = False
@ -153,17 +190,26 @@ class Bibbia(Schivata):
pass
return False
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class Cappello(Mancato):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Cappello'
self.icon = '🧢'
self.name = "Cappello"
self.icon = "🧢"
self.usable_next_turn = True
self.can_be_used_now = False
self.alt_text = "😅"
@ -173,29 +219,41 @@ class Cappello(Mancato):
pass
return False
else:
if not self.is_duplicate_card(player):
self.reset_card()
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class PlaccaDiFerro(Cappello):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Placca Di Ferro'
self.icon = '🛡'
self.name = "Placca Di Ferro"
self.icon = "🛡"
class Sombrero(Cappello):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Sombrero'
self.icon = '👒'
self.name = "Sombrero"
self.icon = "👒"
class Pugnale(Pugno):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Pugnale'
self.icon = '🗡'
self.name = "Pugnale"
self.icon = "🗡"
self.usable_next_turn = True
self.can_be_used_now = False
@ -203,40 +261,59 @@ class Pugnale(Pugno):
if self.can_be_used_now:
return super().play_card(player, against=against)
else:
if not self.is_duplicate_card(player):
self.reset_card()
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class Derringer(Pugnale):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Derringer'
self.icon = '🚬'
self.alt_text += ' 🎴'
self.name = "Derringer"
self.icon = "🚬"
self.alt_text += " 🎴"
# self.desc += ' e poi pesca una carta'
# self.desc_eng += ' and then draw a card.'
def play_card(self, player, against, _with=None):
if self.can_be_used_now:
player.hand.append(player.game.deck.draw())
player.game.deck.draw(True, player=player)
return super().play_card(player, against=against)
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
def use_card(self, player):
player.hand.append(player.game.deck.draw())
player.game.deck.draw(True, player=player)
player.notify_self()
class Borraccia(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Borraccia', number)
self.icon = '🍼'
super().__init__(suit, "Borraccia", number)
self.icon = "🍼"
# self.desc = 'Recupera 1 vita'
# self.desc_eng = 'Regain 1 HP'
self.alt_text = "🍺"
@ -246,21 +323,30 @@ class Borraccia(Card):
def play_card(self, player, against, _with=None):
if self.can_be_used_now:
super().play_card(player, against)
player.lives = min(player.lives+1, player.max_lives)
player.lives = min(player.lives + 1, player.max_lives)
player.notify_self()
return True
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class PonyExpress(WellsFargo):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Pony Express'
self.icon = '🦄'
self.name = "Pony Express"
self.icon = "🦄"
self.alt_text = "🎴🎴🎴"
self.usable_next_turn = True
self.can_be_used_now = False
@ -269,17 +355,26 @@ class PonyExpress(WellsFargo):
if self.can_be_used_now:
return super().play_card(player, against)
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class Howitzer(Gatling):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Howitzer'
self.icon = '📡'
self.name = "Howitzer"
self.icon = "📡"
self.alt_text = "👥💥"
self.usable_next_turn = True
self.can_be_used_now = False
@ -288,12 +383,21 @@ class Howitzer(Gatling):
if self.can_be_used_now:
return super().play_card(player, against)
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class CanCan(CatBalou):
def __init__(self, suit, number):
super().__init__(suit, number)
@ -305,18 +409,26 @@ class CanCan(CatBalou):
def play_card(self, player, against, _with=None):
if self.can_be_used_now:
player.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{player.name}|{self.name}|{against}')
return super().play_card(player, against)
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class Conestoga(Panico):
def __init__(self, suit, number):
Card.__init__(self, suit, 'Conestoga', number)
Card.__init__(self, suit, "Conestoga", number)
self.icon = "🏕"
# self.desc = "Ruba 1 carta da un giocatore a prescindere dalla distanza"
# self.desc_eng = "Steal a card from another player at any distance"
@ -329,39 +441,57 @@ class Conestoga(Panico):
if self.can_be_used_now:
return super().play_card(player, against)
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class Pepperbox(Bang):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = 'Pepperbox'
self.icon = '🌶'
self.name = "Pepperbox"
self.icon = "🌶"
self.alt_text = "💥"
self.usable_next_turn = True
self.can_be_used_now = False
def play_card(self, player, against, _with=None):
if self.can_be_used_now:
if against != None:
if against is not None:
Card.play_card(self, player, against=against)
player.game.attack(player, against)
player.game.attack(player, against, card_name=self.name)
return True
return False
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
class FucileDaCaccia(Card):
def __init__(self, suit, number):
super().__init__(suit, 'Fucile Da Caccia', number)
self.icon = '🌂'
super().__init__(suit, "Fucile Da Caccia", number)
self.icon = "🌂"
# self.desc = "Spara a un giocatore a prescindere dalla distanza"
self.alt_text = "👤💥"
self.need_target = True
@ -370,61 +500,72 @@ class FucileDaCaccia(Card):
def play_card(self, player, against, _with=None):
if self.can_be_used_now:
if against != None:
if against is not None:
super().play_card(player, against=against)
player.game.attack(player, against)
player.game.attack(player, against, card_name=self.name)
return True
return False
else:
if not self.is_duplicate_card(player):
if not self.is_duplicate_card(player) and not player.game.check_event(
ce.IlGiudice
):
self.reset_card()
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_green|{player.name}|{self.name}",
)
player.equipment.append(self)
return True
else:
return False
# pylint: disable=function-redefined
def get_starting_deck() -> List[Card]:
cards = [
Barile(Suit.CLUBS, 'A'),
Barile(Suit.CLUBS, "A"),
Binocolo(Suit.DIAMONDS, 10),
Dinamite(Suit.CLUBS, 10),
Mustang(Suit.HEARTS, 5),
Remington(Suit.DIAMONDS, 6),
RevCarabine(Suit.SPADES, 5),
Riparo(Suit.DIAMONDS, 'K'),
Riparo(Suit.DIAMONDS, "K"),
Bang(Suit.SPADES, 8),
Bang(Suit.CLUBS, 5),
Bang(Suit.CLUBS, 6),
Bang(Suit.CLUBS, 'K'),
Bang(Suit.CLUBS, "K"),
Birra(Suit.HEARTS, 6),
Birra(Suit.SPADES, 6),
CatBalou(Suit.CLUBS, 8),
Emporio(Suit.SPADES, 'A'),
Emporio(Suit.SPADES, "A"),
Indiani(Suit.DIAMONDS, 5),
Mancato(Suit.DIAMONDS, 8),
Panico(Suit.HEARTS, 'J'),
Panico(Suit.HEARTS, "J"),
Pugno(Suit.SPADES, 10),
RagTime(Suit.HEARTS, 9),
Rissa(Suit.SPADES, 'J'),
Rissa(Suit.SPADES, "J"),
Schivata(Suit.DIAMONDS, 7),
Schivata(Suit.HEARTS, 'K'),
SpringField(Suit.SPADES, 'K'),
Schivata(Suit.HEARTS, "K"),
SpringField(Suit.SPADES, "K"),
Tequila(Suit.CLUBS, 9),
Whisky(Suit.HEARTS, 'Q'),
Whisky(Suit.HEARTS, "Q"),
Bibbia(Suit.HEARTS, 10),
Cappello(Suit.DIAMONDS, 'J'),
PlaccaDiFerro(Suit.DIAMONDS, 'A'),
PlaccaDiFerro(Suit.SPADES, 'Q'),
Cappello(Suit.DIAMONDS, "J"),
PlaccaDiFerro(Suit.DIAMONDS, "A"),
PlaccaDiFerro(Suit.SPADES, "Q"),
Sombrero(Suit.CLUBS, 7),
Pugnale(Suit.HEARTS, 8),
Derringer(Suit.SPADES, 7),
Borraccia(Suit.HEARTS, 7),
CanCan(Suit.CLUBS, 'J'),
CanCan(Suit.CLUBS, "J"),
Conestoga(Suit.DIAMONDS, 9),
FucileDaCaccia(Suit.CLUBS, 'Q'),
PonyExpress(Suit.DIAMONDS, 'Q'),
Pepperbox(Suit.HEARTS, 'A'),
FucileDaCaccia(Suit.CLUBS, "Q"),
PonyExpress(Suit.DIAMONDS, "Q"),
Pepperbox(Suit.HEARTS, "A"),
Howitzer(Suit.SPADES, 9),
]
for c in cards:
c.expansion_icon = '🐄️'
c.expansion_icon = "🐄️"
c.expansion = "dodge_city"
return cards

View File

@ -1,111 +1,186 @@
from typing import List
from bang.characters import *
from bang.characters import Character
from globals import PendingAction
class PixiePete(Character):
"""All'inizio del turno pesca 3 carte invece che 2
He draws 3 cards instead of 2"""
def __init__(self):
super().__init__("Pixie Pete", max_lives=3)
# self.desc = "All'inizio del turno pesca 3 carte invece che 2"
# self.desc_eng = "He draws 3 cards instead of 2"
self.icon = '☘️'
self.icon = "☘️"
class TequilaJoe(Character):
"""Se gioca la carta Birra recupera 2 vite invece che una sola
When he plays Beer, he regains 2 Health Points"""
def __init__(self):
super().__init__("Tequila Joe", max_lives=4)
# self.desc = "Se gioca la carta Birra recupera 2 vite invece che una sola"
# self.desc_eng = "When he plays Beer, he regains 2 Health Points"
self.icon = '🍻'
self.icon = "🍻"
class GregDigger(Character):
"""Quando un giocatore muore, recupera fino a 2 vite
Whenever a player dies, he regains up to 2 lives"""
def __init__(self):
super().__init__("Greg Digger", max_lives=4)
# self.desc = "Quando un giocatore muore, recupera fino a 2 vite"
# self.desc_eng = "Whenever a player dies, he regains up to 2 lives"
self.icon = '🦴'
self.icon = "🦴"
class HerbHunter(Character):
"""Quando un giocatore muore, pesca 2 carte
Whenever a player dies, he draws 2 cards"""
def __init__(self):
super().__init__("Herb Hunter", max_lives=4)
# self.desc = "Quando un giocatore muore, pesca 2 carte"
# self.desc_eng = "Whenever a player dies, he draws 2 cards"
self.icon = '⚰️'
self.icon = "⚰️"
class ElenaFuente(Character):
"""Può usare una carta qualsiasi nella sua mano come mancato
She can use any card of her hand as missed"""
def __init__(self):
super().__init__("Elena Fuente", max_lives=3)
# self.desc = "Può usare una carta qualsiasi nella sua mano come mancato"
# self.desc_eng = "She can use any card of her hand as missed"
self.icon = '🧘‍♀️'
self.icon = "🧘‍♀️"
class BillNoface(Character):
"""All'inizio del turno pesca 1 carta + 1 carta per ogni ferita che ha
Draw 1 card + 1 card for each wound he has"""
def __init__(self):
super().__init__("Bill Noface", max_lives=4)
# self.desc = "All'inizio del turno pesca 1 carta + 1 carta per ogni ferita che ha"
# self.desc_eng = "Draw 1 card + 1 card for each wound he has"
self.icon = '🙈'
self.icon = "🙈"
class MollyStark(Character):
"""Quando usa volontariamente una carta che ha in mano, fuori dal suo turno, ne ottiene un'altra dal mazzo
When she uses a card from her hand outside her turn, she draws a card."""
def __init__(self):
super().__init__("Molly Stark", max_lives=4)
# self.desc = "Quando usa volontariamente una carta che ha in mano, fuori dal suo turno, ne ottiene un'altra dal mazzo"
# self.desc_eng = "When she uses a card from her hand outside her turn, she draws a card."
self.icon = '🙅‍♀️'
self.icon = "🙅‍♀️"
class ApacheKid(Character):
"""Le carte di quadri ♦️ giocate contro di lui non hanno effetto (non vale durante i duelli)
Cards of diamonds played against him, do no have effect (doesn't work in duels).
"""
def __init__(self):
super().__init__("Apache Kid", max_lives=3)
# self.desc = "Le carte di quadri ♦️ giocate contro di lui non hanno effetto (non vale durante i duelli)"
# self.desc_eng = "Cards of diamonds ♦️ played against him, do no have effect (doesn't work in duels)."
self.icon = '♦️'
self.icon = "♦️"
class SeanMallory(Character):
"""Quando finisce il suo turno può tenere fino a 10 carte in mano
He can keep up to 10 cards in his hand when ending the turn."""
def __init__(self):
super().__init__("Sean Mallory", max_lives=3)
# self.desc = "Quando finisce il suo turno può tenere fino a 10 carte in mano"
# self.desc_eng = "He can keep up to 10 cards in his hand when ending the turn."
self.icon = '🍟'
self.icon = "🍟"
class BelleStar(Character):
"""Nel suo turno le carte verdi degli altri giocatori non hanno effetto.
During her turn the green cards of the other players do not work."""
def __init__(self):
super().__init__("Belle Star", max_lives=4)
# self.desc = "Nel suo turno le carte verdi degli altri giocatori non hanno effetto."
# self.desc_eng = "During her turn the green cards of the other players do not work."
self.icon = ''
self.icon = ""
class VeraCuster(Character):
"""Prima di pescare le sue carte può scegliere l'abilità speciale di un altro giocatore fino al prossimo turno.
Before drawing, she may choose the special ability on another alive player. This ability is used until next turn.
"""
def __init__(self):
super().__init__("Vera Custer", max_lives=3)
# self.desc = "Prima di pescare le sue carte può scegliere l'abilità speciale di un altro giocatore fino al prossimo turno."
# self.desc_eng = "Before drawing, she may choose the special ability on another alive player. This ability is used until next turn."
self.icon = '🎭'
self.icon = "🎭"
class ChuckWengam(Character):
"""Durante il suo turno può perdere una vita per pescare 2 carte dal mazzo.
On his turn he may decide to lose 1 HP to draw 2 cards from the deck."""
def __init__(self):
super().__init__("Chuck Wengam", max_lives=4)
# self.desc = "Durante il suo turno può perdere una vita per pescare 2 carte dal mazzo."
# self.desc_eng = "On his turn he may decide to lose 1 HP to draw 2 cards from the deck."
self.icon = '💰'
self.icon = "💰"
def special(self, player, data):
if super().special(player, data):
if player.lives > 1 and player.is_my_turn:
player.lives -= 1
player.game.deck.draw(True, player=player)
player.game.deck.draw(True, player=player)
player.notify_self()
return True
return False
class PatBrennan(Character):
"""Invece di pescare può prendere una carta dall'equipaggiamento di un altro giocatore.
Instead of drawing he can steal a card from the equipment of another player."""
def __init__(self):
super().__init__("Pat Brennan", max_lives=4)
# self.desc = "Invece di pescare può prendere una carta dall'equipaggiamento di un altro giocatore."
# self.desc_eng = "Instead of drawing he can steal a card from the equipment of another player."
self.icon = '🤗'
self.icon = "🤗"
class JoseDelgado(Character):
"""Può scartare una carta blu per pescare 2 carte.
He can discard a blue card to draw 2 cards."""
class JoseDelgrado(Character):
def __init__(self):
super().__init__("José Delgrado", max_lives=4)
# self.desc = "Può scartare una carta blu per pescare 2 carte."
# self.desc_eng = "He can discard a blue card to draw 2 cards."
self.icon = '🎒'
super().__init__("José Delgado", max_lives=4)
self.icon = "🎒"
class DocHolyday(Character):
"""Nel suo turno può scartare 2 carte per fare un bang.
He can discard 2 cards to play a bang."""
def __init__(self):
super().__init__("Doc Holyday", max_lives=4)
# self.desc = "Nel suo turno può scartare 2 carte per fare un bang."
# self.desc_eng = "He can discard 2 cards to play a bang."
self.icon = '✌🏻'
self.icon = "✌🏻"
def special(self, player, data):
if super().special(player, data):
if (
player.special_use_count < 1
and player.pending_action == PendingAction.PLAY
):
player.special_use_count += 1
cards = sorted(data["cards"], reverse=True)
for c in cards:
player.game.deck.scrap(player.hand.pop(c), True)
player.notify_self()
player.game.attack(player, data["against"])
return True
return False
# pylint: disable=function-redefined
def all_characters() -> List[Character]:
cards = [
PixiePete(),
@ -121,23 +196,25 @@ def all_characters() -> List[Character]:
VeraCuster(),
ChuckWengam(),
PatBrennan(),
JoseDelgrado(),
JoseDelgado(),
DocHolyday(),
]
for c in cards:
c.expansion_icon = '🐄️'
for card in cards:
card.expansion_icon = "🐄️" # pylint: disable=attribute-defined-outside-init
card.expansion = "dodge_city" # pylint: disable=attribute-defined-outside-init
return cards
#Apache Kid: il suo effetto non conta nei duelli
#belle star: vale solo per le carte blu e verdi
#chuck wengam: può usarlo più volte in un turno, ma non può suicidarsi
#doc holiday: il suo effetto non conta nel limite di un bang per turno,
# Apache Kid: il suo effetto non conta nei duelli
# belle star: vale solo per le carte blu e verdi
# chuck wengam: può usarlo più volte in un turno, ma non può suicidarsi
# doc holiday: il suo effetto non conta nel limite di un bang per turno,
# se deve sparare a Apache Kid una delle due carte scartate non deve essere di quadri
#molly stark: le carte scartate che valgono sono solo quelle scartate volontariamente,
# molly stark: le carte scartate che valgono sono solo quelle scartate volontariamente,
# carte scartate per colpa di can can, cat balou, rissa, panico non valgono,
# invece carte scartata per indiani, birra(in caso di morte), o un mancato valgono,
# in un duello pesca solo quando il duello è finito (una carta x ogni bang scartato)
#pat brennan: quando pesca con il suo effetto, pesca solo la carta del giocatore non anche dal mazzo
#vera custer: la scelta può essere fatta solo appena prima di pescare,
# pat brennan: quando pesca con il suo effetto, pesca solo la carta del giocatore non anche dal mazzo
# vera custer: la scelta può essere fatta solo appena prima di pescare,
# quando inizia la partita serve farle scegliere, poi può rimanere quello finchè non decide di cambiarlo
# eventualmente fare una schermata dove vede tutti i personaggi

View File

@ -1,108 +1,203 @@
from typing import TYPE_CHECKING
from abc import ABC, abstractmethod
import random
import bang.players as players
import bang.roles as r
import bang.cards as cs
from globals import G
if TYPE_CHECKING:
from bang.game import Game
class CardEvent(ABC):
"""Base class for all event cards"""
def __init__(self, name, icon):
self.name = name
self.icon = icon
def on_flipped(self, game: "Game"):
"""Default on flipped event
Args:
game (Game): the game object
"""
print(f"{game.name}: flip new event {self.name}")
G.sio.emit(
"chat_message",
room=game.name,
data={
"color": "orange",
"text": f"_flip_event|{self.name}",
},
)
return
def on_clicked(self, game, player):
"""Default on clicked event
Args:
game (Game): the game object
player (Player): the player that clicked the card
"""
print(f"{game.name}: {player.name} clicked event {self.name}")
return
class Agguato(CardEvent):
"""La distanza base tra 2 qualsiasi giocatori è 1
The distance between 2 players is always 1"""
def __init__(self):
super().__init__("Agguato", "🛁")
self.desc = "La distanza base tra 2 qualsiasi giocatori è 1"
self.desc_eng = "The base distance from any 2 players is 1"
class Cecchino(CardEvent):
"""Nel proprio turno i giocatori possono
scartare 2 Bang assieme per sparare un bang che necessita 2 mancato (clicca la carta)
In your turn you can discard 2 Bang together to shoot a bang that needs 2 miss (click the card)
"""
def __init__(self):
super().__init__("Cecchino", "👁")
self.desc = "Nel proprio turno i giocatori possono scartare 2 Bang assieme per sparare un bang che necessita 2 mancato (clicca la carta)"
self.desc_eng = "During their turn, players can discard 2 Bang! to shoot a bang that requires 2 missed (click the card)"
class DeadMan(CardEvent):
"""Al proprio turno il giocatore che è morto per primo torna in vita con 2 vite e 2 carte
The first player that died returns back to life with 2 hp and 2 cards"""
def __init__(self):
super().__init__("Dead Man", "⚰️")
self.desc = "Al proprio turno il giocatore che è morto per primo torna in vita con 2 vite e 2 carte"
self.desc_eng = "The first player that died returns back to life with 2 hp and 2 cards"
def on_flipped(self, game):
game.did_resuscitate_deadman = False
return super().on_flipped(game)
class FratelliDiSangue(CardEvent):
"""All'inizio del proprio turno, i giocatori possono perdere 1 vita (tranne l'ultimo) per darla a un altro giocatore"""
def __init__(self):
super().__init__("Fratelli Di Sangue", "💉")
self.desc = "All'inizio del proprio turno, i giocatori possono perdere 1 vita (tranne l'ultimo) per darla a un altro giocatore"
self.desc_eng = "At the begin of their turn, payers can lose 1 hp (except the last one) to give it to another player"
class IlGiudice(CardEvent):
"""Non si possono equipaggiare carte a se stessi o agli altri"""
def __init__(self):
super().__init__("Il Giudice", "👨‍⚖️")
self.desc = "Non si possono equipaggiare carte a se stessi o agli altri"
self.desc_eng = "You can't equip cards on your or other players"
class Lazo(CardEvent):
"""Le carte equipaggiate non hanno effetto"""
def __init__(self):
super().__init__("Lazo", "📿")
self.desc = "Le carte equipaggiate non hanno effetto"
self.desc_eng = "Cards in the equipment slot do not work"
class LeggeDelWest(CardEvent):
"""I giocatori mostrano la seconda carta che pescano e sono obbligati a usarla in quel turno (se possibile)"""
def __init__(self):
super().__init__("Legge Del West", "⚖️")
self.desc = "I giocatori mostrano la seconda carta che pescano e sono obbligati a usarla in quel turno (se possibile)"
self.desc_eng = "Every player shows the second card that they draw and must use it in that round (if it is possible)"
class LiquoreForte(CardEvent):
"""I giocatori possono evitare di pescare per recuperare 1 vita (clicca sulla carta evento per farlo)"""
def __init__(self):
super().__init__("Liquore Forte", "🥃")
self.desc = "I giocatori possono evitare di pescare per recuperare 1 vita (clicca sulla carta evento per farlo)"
self.desc_eng = "Players can skip drawing to regain 1 HP (click on the event card to use)"
class MinieraAbbandonata(CardEvent):
"""I giocatori pescano dagli scarti nella loro fase 1 e scartano in cima al mazzo nella loro fase 3 (se gli scarti finiscono, è necessario pescare e scartare in cima al mazzo)"""
def __init__(self):
super().__init__("Miniera Abbandonata", "")
self.desc = "I giocatori pescano dagli scarti nella loro fase 1 e scartano in cima al mazzo nella loro fase 3 (se gli scarti finiscono, è necessario pescare e scartare in cima al mazzo)"
#TODO: cambiare anche la descrizione inglese
self.desc_eng = "Players draw from the discarded pile and discard to the top of the deck (if the discards run out, they must draw and discard on top of the deck)"
class PerUnPugnoDiCarte(CardEvent):
"""All'inizio del proprio turno, il giocatore subisce tanti bang quante carte ha in mano"""
def __init__(self):
super().__init__("Per Un Pugno Di Carte", "🎴")
self.desc = "All'inizio del proprio turno, il giocatore subisce tanti bang quante carte ha in mano"
self.desc_eng = "On the beginning of his turn, the player is target of as many Bang as how many cards he has in his hand"
class Peyote(CardEvent):
"""Invece che pescare il giocatore prova a indovinare il colore del seme, se lo indovina aggiunge la carta alla mano e continua provando ad indovinare la carta successiva"""
def __init__(self):
super().__init__("Peyote", "🌵")
self.desc = "Invece che pescare il giocatore prova a indovinare il colore del seme, se lo indovina aggiunge la carta alla mano e continua provando ad indovinare la carta successiva"
self.desc_eng = "Instead of drawing, the player tries to guess the color of the suit, if he's right he adds the card to the hand and continues trying to guess the next card"
class Ranch(CardEvent):
"""Dopo aver pescato il giocatore può scartare quante carte vuole dalla mano e pescarne altrettante dal mazzo"""
def __init__(self):
super().__init__("Ranch", "🐮")
self.desc = "Dopo aver pescato il giocatore può scartare quante carte vuole dalla mano e pescarne altrettante dal mazzo"
self.desc_eng = "After drawing, the player can discard as many cards as he wants from his hand and draw as many from the deck"
class Rimbalzo(CardEvent):
"""Il giocatore di turno può giocare bang contro le carte equipaggiate dagli altri giocatori, se non giocano mancato vengono scartate (clicca la carta evento)"""
def __init__(self):
super().__init__("Rimbalzo", "")
self.desc = "Il giocatore di turno può giocare bang contro le carte equipaggiate dagli altri giocatori, se non giocano mancato vengono scartate (clicca la carta evento)"
self.desc_eng = "The player can play bang against the cards equipped by the other players, if they do not play miss they are discarded (click the event card)"
def on_clicked(self, game, player):
super().on_clicked(game, player)
if any((c.name == cs.Bang(0, 0).name for c in player.hand)):
player.available_cards = [
{
"name": p.name,
"icon": p.role.icon
if (game.initial_players == 3)
else "⭐️"
if isinstance(p.role, r.Sheriff)
else "🤠",
"is_character": True,
"avatar": p.avatar,
"is_player": True,
}
for p in game.get_alive_players()
if len(p.equipment) > 0 and p != player
]
player.available_cards.append({"icon": "", "noDesc": True})
player.choose_text = "choose_rimbalzo_player"
player.pending_action = players.PendingAction.CHOOSE
player.using_rimbalzo = 1
player.notify_self()
class RouletteRussa(CardEvent):
"""A partire dallo sceriffo, ogni giocatore scarta 1 mancato, il primo che non lo fa perde 2 vite"""
def __init__(self):
super().__init__("Roulette Russa", "🇷🇺")
self.desc = "A partire dallo sceriffo, ogni giocatore scarta 1 mancato, il primo che non lo fa perde 2 vite"
self.desc_eng = "Starting from the sheriff, every player discards 1 missed, the first one that doesn't loses 2 HP"
# self.desc_eng = "Starting from the sheriff, every player discards 1 missed, the first one that doesn't loses 2 HP"
class Vendetta(CardEvent):
"""Alla fine del proprio turno il giocatore estrae dal mazzo, se esce ♥️ gioca un altro turno (ma non estrae di nuovo)"""
def __init__(self):
super().__init__("Vendetta", "😤")
self.desc = "Alla fine del proprio turno il giocatore estrae dal mazzo, se esce ♥️ gioca un altro turno (ma non estrae di nuovo)"
self.desc_eng = "When ending the turn, the player flips a card from the deck, if it's ♥️ he plays another turn (but he does not flip another card)"
# self.desc_eng = "When ending the turn, the player flips a card from the deck, if it's ♥️ he plays another turn (but he does not flip another card)"
def get_endgame_card():
end_game = PerUnPugnoDiCarte()
end_game.expansion = 'fistful-of-cards'
end_game.expansion = ( # pylint: disable=attribute-defined-outside-init
"fistful-of-cards"
)
return end_game
def get_all_events():
def get_all_events(rng=random):
cards = [
Agguato(),
Cecchino(),
@ -119,7 +214,9 @@ def get_all_events():
RouletteRussa(),
Vendetta(),
]
random.shuffle(cards)
for c in cards:
c.expansion = 'fistful-of-cards'
rng.shuffle(cards)
for card in cards:
card.expansion = ( # pylint: disable=attribute-defined-outside-init
"fistful-of-cards"
)
return cards

View File

@ -0,0 +1,113 @@
from typing import List
from bang.characters import Character
class DonBell(Character):
def __init__(self):
super().__init__("Don Bell", max_lives=4)
# A fine turno estrae, ❤️ o ♦️ gioca di nuovo
self.icon = "🔔️"
class DutchWill(Character):
def __init__(self):
super().__init__("Dutch Will", max_lives=4)
# Pesca 2 ne scarta 1 e prende 1 pepita
self.icon = "🧐️"
class JackyMurieta(Character):
def __init__(self):
super().__init__("Jacky Murieta", max_lives=4)
# puo pagare 2 pepite per sparare 1 bang extra
self.icon = "💆‍♂️️"
def special(self, player, data):
if super().special(player, data):
if player.gold_nuggets >= 2 and player.is_my_turn:
player.gold_nuggets -= 2
player.has_played_bang = False
player.bang_used -= 1
player.notify_self()
return True
return False
class JoshMcCloud(Character):
def __init__(self):
super().__init__("Josh McCloud", max_lives=4)
# puo pagare 2 pepite per pescare il primo equipaggiamento dalla pila gold rush
self.icon = "⛅️"
def special(self, player, data):
if super().special(player, data):
if player.gold_nuggets >= 2 and player.is_my_turn:
player.gold_nuggets -= 2
card = player.game.deck.shop_deck.pop(0)
print(
f"{player.name} ha comprato usando la abilità speciale {card.name}"
)
if card.play_card(player):
player.game.deck.shop_deck.append(card)
player.notify_self()
return True
return False
class MadamYto(Character):
def __init__(self):
super().__init__("Madam Yto", max_lives=4)
# quando viene giocata 1 birra pesca 1 carta
self.icon = "💃️"
class PrettyLuzena(Character):
def __init__(self):
super().__init__("Pretty Luzena", max_lives=4)
# una volta per turno ha 1 sconto di 1 pepita sugli equipaggiamenti
self.icon = "👛️"
class RaddieSnake(Character):
def __init__(self):
super().__init__("Raddie Snake", max_lives=4)
# può scartare 1 pepita per pescare 1 carta (2 volte per turno)
self.icon = "🐍️"
def special(self, player, data):
if super().special(player, data):
if (
player.gold_nuggets >= 1
and player.is_my_turn
and player.special_use_count < 2
):
player.gold_nuggets -= 1
player.special_use_count += 1
player.game.deck.draw(True, player=player)
player.notify_self()
return True
return False
class SimeonPicos(Character):
def __init__(self):
super().__init__("Simeon Picos", max_lives=4)
# ottiene 1 pepita ogni volta che perde 1 punto vita
self.icon = "🥲"
def all_characters() -> List[Character]:
cards = [
DonBell(),
DutchWill(),
JackyMurieta(),
JoshMcCloud(),
MadamYto(),
PrettyLuzena(),
RaddieSnake(),
SimeonPicos(),
]
for c in cards:
c.expansion_icon = "🤑️"
c.expansion = "gold_rush"
return cards

View File

@ -0,0 +1,265 @@
from bang.cards import *
import bang.roles as r
import bang.players as pl
from globals import G, PendingAction
class ShopCardKind(IntEnum):
BROWN = 0 # Se lequipaggiamento ha il bordo marrone, applicane subito leffetto e poi scartalo.
BLACK = 1 # Se lequipaggiamento ha il bordo nero, tienilo scoperto di fronte a te.
class ShopCard(Card):
def __init__(self, name:str, cost:int, kind:ShopCardKind):
super().__init__(suit='💵', number=cost, name=name)
self.kind = kind
self.expansion_icon = '🤑️'
self.expansion = 'gold_rush'
self.reset_card()
def play_card(self, player, against, _with=None):
if self.kind == ShopCardKind.BROWN:
G.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}')
return True
elif self.kind == ShopCardKind.BLACK: # equip it
if not self.is_duplicate_card(player):
self.reset_card()
self.can_be_used_now = True
player.gold_rush_equipment.append(self)
G.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}')
return True
else:
return False
def reset_card(self):
if self.kind == ShopCardKind.BLACK:
self.can_be_used_now = False
class Bicchierino(ShopCard):
def __init__(self):
super().__init__('Bicchierino', 1, ShopCardKind.BROWN)
self.icon = '🍸️'
def play_card(self, player, against=None, _with=None):
player.available_cards = [{
'name': p.name,
'icon': p.role.icon if(player.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠',
'alt_text': ''.join(['❤️']*p.lives)+''.join(['💀']*(p.max_lives-p.lives)),
'is_character': True,
'is_player': True
} for p in player.game.get_alive_players()]
player.choose_text = 'choose_bicchierino'
player.pending_action = PendingAction.CHOOSE
player.notify_self()
return super().play_card(player, against, _with)
class Bottiglia(ShopCard):
def __init__(self):
super().__init__('Bottiglia', 2, ShopCardKind.BROWN)
self.icon = '🍾️'
def play_card(self, player, against=None, _with=None):
# bang, birra, panico
player.available_cards = [Bang(4,42), Birra(4,42), Panico(4,42)]
if not any((player.get_sight() >= p['dist'] for p in player.game.get_visible_players(player))):
player.available_cards.pop(0)
for i in range(len(player.available_cards)):
player.available_cards[i].must_be_used = True
player.choose_text = 'choose_bottiglia'
player.pending_action = PendingAction.CHOOSE
player.notify_self()
return super().play_card(player, against, _with)
class Complice(ShopCard):
def __init__(self):
super().__init__('Complice', 2, ShopCardKind.BROWN)
self.icon = '😉️'
def play_card(self, player, against=None, _with=None):
# emporio, duello, Cat balou
player.available_cards = [Emporio(4,42), Duello(4,42), CatBalou(4,42)]
for i in range(len(player.available_cards)):
player.available_cards[i].must_be_used = True
player.choose_text = 'choose_complice'
player.pending_action = PendingAction.CHOOSE
player.notify_self()
return super().play_card(player, against, _with)
class CorsaAllOro(ShopCard):
def __init__(self):
super().__init__("Corsa All Oro_gr", 5, ShopCardKind.BROWN)
self.icon = '🤑️'
def play_card(self, player, against=None, _with=None):
player.lives = player.max_lives
player.play_turn()
return super().play_card(player, against, _with)
class Rum(ShopCard):
def __init__(self):
super().__init__("Rum", 3, ShopCardKind.BROWN)
self.icon = '🍷️'
def play_card(self, player, against=None, _with=None):
# Estrai 4 carte e ottieni 1 hp per ogni seme diverso
import bang.characters as c
suits = set()
num = 5 if player.character.check(player.game, c.LuckyDuke) else 4
for i in range(num):
c = player.game.deck.pick_and_scrap()
G.sio.emit('chat_message', room=player.game.name, data=f'_flipped|{player.name}|{c.name}|{c.num_suit()}')
suits.add(c.suit)
player.lives = min(player.lives+len(suits), player.max_lives)
return super().play_card(player, against, _with)
class UnionPacific(ShopCard):
def __init__(self):
super().__init__("Union Pacific", 4, ShopCardKind.BROWN)
self.icon = '🚆️'
def play_card(self, player, against=None, _with=None):
G.sio.emit('chat_message', room=player.game.name,
data=f'_UnionPacific|{player.name}|{self.name}')
for i in range(4):
player.game.deck.draw(True, player=player)
return super().play_card(player, against, _with)
class Calumet(ShopCard):
def __init__(self):
super().__init__("Calumet", 3, ShopCardKind.BLACK)
self.icon = '🚭️'
def play_card(self, player, against=None, _with=None):
return super().play_card(player, against, _with)
# ti rende immuni ai quadri
class Cinturone(ShopCard):
def __init__(self):
super().__init__("Cinturone", 2, ShopCardKind.BLACK)
self.icon = '🥡'
def play_card(self, player, against=None, _with=None):
return super().play_card(player, against, _with)
# max carte a fine turno 8
class FerroDiCavallo(ShopCard):
def __init__(self):
super().__init__("Ferro di Cavallo", 2, ShopCardKind.BLACK)
self.icon = '🎠'
def play_card(self, player, against=None, _with=None):
return super().play_card(player, against, _with)
# estrai come luky duke
class Piccone(ShopCard):
def __init__(self):
super().__init__("Piccone", 4, ShopCardKind.BLACK)
self.icon = '⛏️'
def play_card(self, player, against=None, _with=None):
return super().play_card(player, against, _with)
# peschi una carta in piu a inizio turno
class Ricercato(ShopCard):
def __init__(self):
super().__init__("Ricercato", 2, ShopCardKind.BLACK)
self.icon = '🤠️'
self.can_target_self = True
def play_card(self, player, against=None, _with=None):
G.sio.emit('chat_message', room=player.game.name, data=f'_purchase_card|{player.name}|{self.name}')
player.available_cards = [{
'name': p.name,
'icon': p.role.icon if(player.game.initial_players == 3) else '🤠',
'alt_text': ''.join(['❤️']*p.lives)+''.join(['💀']*(p.max_lives-p.lives)),
'is_character': True,
'is_player': True
} for p in player.game.get_alive_players() if p != player and not isinstance(p.role, r.Sheriff)]
player.available_cards.append({'name': player.name, 'number':0,'icon': 'you', 'is_character': True})
player.choose_text = 'choose_ricercato'
player.pending_action = PendingAction.CHOOSE
player.notify_self()
return True
# la giochi su un altro giocatore, ricompensa di 2 carte e 1 pepita a chi lo uccide
class Setaccio(ShopCard):
def __init__(self):
super().__init__("Setaccio", 3, ShopCardKind.BLACK)
self.icon = '🥘️'
def play_card(self, player, against=None, _with=None):
if not self.can_be_used_now:
return super().play_card(player, against, _with)
else:
if player.gold_nuggets >= 1 and player.setaccio_count < 2:
G.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}')
player.gold_nuggets -= 1
player.setaccio_count += 1
player.game.deck.draw(True, player=player)
player.notify_self()
return True
return False
# paghi 1 pepita per pescare 1 carta durante il tuo turno (max 2 volte per turno)
class Stivali(ShopCard):
def __init__(self):
super().__init__("Stivali", 3, ShopCardKind.BLACK)
self.icon = '🥾️'
def play_card(self, player, against=None, _with=None):
return super().play_card(player, against, _with)
# peschi una carta ogni volta che vieni ferito
class Talismano(ShopCard):
def __init__(self):
super().__init__("Talismano", 3, ShopCardKind.BLACK)
self.icon = '🧿'
def play_card(self, player, against=None, _with=None):
return super().play_card(player, against, _with)
# ottieni una pepita ogni volta che vieni ferito
class Zaino(ShopCard):
def __init__(self):
super().__init__("Zaino", 3, ShopCardKind.BLACK)
self.icon = '🎒️'
def play_card(self, player, against=None, _with=None):
if not self.can_be_used_now:
return super().play_card(player, against, _with)
else:
if player.gold_nuggets >= 2:
G.sio.emit('chat_message', room=player.game.name, data=f'_play_card|{player.name}|{self.name}')
player.gold_nuggets -= 2
player.lives = min(player.lives + 1, player.max_lives)
player.notify_self()
return True
return False
# paga 2 pepite per recuperare 1 vita
def get_cards() -> List[Card]:
cards = [
Bicchierino(),
Bicchierino(),
Bicchierino(),
Bottiglia(),
Bottiglia(),
Bottiglia(),
Complice(),
Complice(),
Complice(),
CorsaAllOro(),
Rum(),
Rum(),
UnionPacific(),
Calumet(),
Cinturone(),
FerroDiCavallo(),
Piccone(),
Ricercato(),
Ricercato(),
Ricercato(),
Setaccio(),
Stivali(),
Talismano(),
Zaino(),
]
return cards

View File

@ -1,119 +1,184 @@
import random
from globals import G
from bang.expansions.fistful_of_cards.card_events import CardEvent
class Benedizione(CardEvent):
"""Tutte le carte sono considerate di cuori ♥️"""
def __init__(self):
super().__init__("Benedizione", "🙏")
self.desc = "Tutte le carte sono considerate di cuori ♥️"
self.desc_eng = "All cards are of hearts ♥️"
# self.desc_eng = "All cards are of hearts ♥️"
class Maledizione(CardEvent):
"""Tutte le carte sono considerate di picche ♠"""
def __init__(self):
super().__init__("Maledizione", "🤬")
self.desc = "Tutte le carte sono considerate di picche ♠"
self.desc_eng = "All cards are of spades ♠"
# self.desc_eng = "All cards are of spades ♠"
class Sbornia(CardEvent):
"""I personaggi perdono le loro abilità speciali"""
def __init__(self):
super().__init__("Sbornia", "🥴")
self.desc = "I personaggi perdono le loro abilità speciali"
self.desc_eng = "The characters lose their special abilities"
# self.desc_eng = "The characters lose their special abilities"
class Sete(CardEvent):
"""I giocatori pescano 1 carta in meno nella loro fase 1"""
def __init__(self):
super().__init__("Sete", "🥵")
self.desc = "I giocatori pescano 1 carta in meno nella loro fase 1"
self.desc_eng = "Players only draw 1 card at the start of their turn"
# self.desc_eng = "Players only draw 1 card at the start of their turn"
class IlTreno(CardEvent):
"""I giocatori pescano 1 carta extra nella loro fase 1"""
def __init__(self):
super().__init__("Il Treno", "🚂")
self.desc = "I giocatori pescano 1 carta extra nella loro fase 1"
self.desc_eng = "Players draw 1 extra card"
# self.desc_eng = "Players draw 1 extra card"
class IlReverendo(CardEvent):
"""Non si possono giocare le carte Birra"""
def __init__(self):
super().__init__("Il Reverendo", "⛪️")
self.desc = "Non si possono giocare le carte Birra"
self.desc_eng = "Beers can't be played"
# self.desc_eng = "Beers can't be played"
class IlDottore(CardEvent):
"""Il/i giocatore/i con meno vite ne recupera/no una"""
def __init__(self):
super().__init__("Il Dottore", "👨‍⚕️")
self.desc = "Il/i giocatore/i con meno vite ne recupera/no una"
self.desc_eng = "The player with the least amount of HP gets healed 1"
# self.desc_eng = "The player with the least amount of HP gets healed 1"
def on_flipped(self, game):
super().on_flipped(game)
most_hurt = [
p.lives for p in game.players if p.lives > 0 and p.max_lives > p.lives
]
if len(most_hurt) > 0:
hurt_players = [p for p in game.players if p.lives == min(most_hurt)]
for p in hurt_players:
if p.lives != p.max_lives:
p.lives += 1
G.sio.emit(
"chat_message",
room=game.name,
data=f"_doctor_heal|{p.name}",
)
p.notify_self()
return
class Sermone(CardEvent):
"""I giocatori non possono giocare Bang! durante il loro turno"""
def __init__(self):
super().__init__("Sermone", "✝️")
self.desc = "I giocatori non possono giocare Bang! durante il loro turno"
self.desc_eng = "Players can't play Bang! during their turn"
# self.desc_eng = "Players can't play Bang! during their turn"
class Sparatoria(CardEvent):
"""Il limite di Bang! per turno è 2 invece che 1"""
def __init__(self):
super().__init__("Sparatoria", "🔫🔫")
self.desc = "Il limite di Bang! per turno è 2 invece che 1"
self.desc_eng = "The turn Bang! limit is 2"
# self.desc_eng = "The turn Bang! limit is 2"
class CorsaAllOro(CardEvent):
"""Si gioca per un intero giro in senso antiorario, tuttavia gli effetti delle carte rimangono invariati"""
def __init__(self):
super().__init__("Corsa All'Oro", "🌟")
self.desc = "Si gioca per un intero giro in senso antiorario, tuttavia gli effetti delle carte rimangono invariati"
self.desc_eng = "Turns are played counter clockwise"
super().__init__("Corsa All Oro", "🌟")
# self.desc_eng = "Turns are played counter clockwise"
class IDalton(CardEvent):
"""Chi ha carte blu in gioco ne scarta 1 a sua scelta"""
def __init__(self):
super().__init__("I Dalton", "🙇‍♂️")
self.desc = "Chi ha carte blu in gioco ne scarta 1 a sua scelta"
self.desc_eng = "Players that have blue cards equipped, discard 1 of those card of their choice"
# self.desc_eng = "Players that have blue cards equipped, discard 1 of those card of their choice"
def on_flipped(self, game):
game.waiting_for = 0
game.ready_count = 0
game.dalton_on = True
for p in game.players:
if p.get_dalton():
game.waiting_for += 1
p.notify_self()
if game.waiting_for != 0:
return
game.dalton_on = False
return super().on_flipped(game)
class Manette(CardEvent):
"""Dopo aver pescato in fase 1, il giocatore di turno dichiara un seme: potrà usare solamente carte di quel seme nel suo turno"""
def __init__(self):
super().__init__("Manette", "🔗")
self.desc = "Dopo aver pescato in fase 1, il giocatore di turno dichiara un seme: potrà usare solamente carte di quel seme nel suo turno"
self.desc_eng = ""
# self.desc_eng = "After drawing in phase 1, the player declares a suit. He will be able to use only cards of that suit for that turn"
class NuovaIdentita(CardEvent):
"""All'inizio del proprio turno, ogni giocatore potrà decidere se sostituire il suo personaggio attuale con quello era stato proposto ad inizio partita, se lo fa riparte con 2 punti vita"""
def __init__(self):
super().__init__("Nuova Identità", "🕶")
self.desc = "All'inizio del proprio turno, ogni giocatore potrà decidere se sostituire il suo personaggio attuale con quello era stato proposto ad inizio partita, se lo fa riparte con 2 punti vita"
self.desc_eng = ""
super().__init__("Nuova Identita", "🕶")
# self.desc_eng = "At the beginning of their turn, each player can choose to change its character with the other shown at the game start. If he does so he restarts from 2 HP."
class CittaFantasma(CardEvent):
"""Tutti i giocatori morti tornano in vita al proprio turno, non possono morire e pescano 3 carte invece che 2. Quando terminano il turno tornano morti."""
def __init__(self):
super().__init__("Città Fantasma", "👻")
self.desc = "Tutti i giocatori morti tornano in vita al proprio turno, non possono morire e pescano 3 carte invece che 2. Quando terminano il turno tornano morti."
self.desc_eng = "All dead players come back to life in their turn, they can't die and draw 3 cards instead of 2. When they end their turn the die."
# self.desc_eng = "All dead players come back to life in their turn, they can't die and draw 3 cards instead of 2. When they end their turn the die."
class MezzogiornoDiFuoco(CardEvent):
"""Ogni giocatore perde 1 punto vita all'inizio del turno"""
def __init__(self):
super().__init__("Mezzogiorno di Fuoco", "🔥")
self.desc = "Ogni giocatore perde 1 punto vita all'inizio del turno"
self.desc_eng = "Every player loses 1 HP when their turn starts"
# self.desc_eng = "Every player loses 1 HP when their turn starts"
def get_endgame_card():
end_game = MezzogiornoDiFuoco()
end_game.expansion = 'high-noon'
end_game.expansion = "high-noon" # pylint: disable=attribute-defined-outside-init
return end_game
def get_all_events():
def get_all_events(rng=random):
cards = [
Benedizione(),
Maledizione(),
CittaFantasma(),
CorsaAllOro(),
IDalton(),
IlDottore(),
IlReverendo(),
IlTreno(),
Sbornia(),
Sermone(),
Sete(),
Sparatoria(),
# Manette(),
# NuovaIdentita(),
Benedizione(),
Maledizione(),
CittaFantasma(),
CorsaAllOro(),
IDalton(),
IlDottore(),
IlReverendo(),
IlTreno(),
Sbornia(),
Sermone(),
Sete(),
Sparatoria(),
Manette(),
NuovaIdentita(),
]
random.shuffle(cards)
rng.shuffle(cards)
for c in cards:
c.expansion = 'high-noon'
c.expansion = "high-noon" # pylint: disable=attribute-defined-outside-init
return cards

View File

@ -0,0 +1,303 @@
from typing import List
import bang.roles as r
import bang.players as pl
from bang.cards import Card, Suit, Bang, Mancato
import bang.expansions.fistful_of_cards.card_events as ce
from globals import G, PendingAction
class Fantasma(Card):
def __init__(self, suit, number):
super().__init__(suit, "Fantasma", number, is_equipment=True)
self.icon = "👻️" # porta in vita i giocatori morti ma non
def play_card(self, player, against, _with=None):
if (player.game.check_event(ce.IlGiudice)) or not self.can_be_used_now:
return False
if len(player.game.get_dead_players(include_ghosts=False)) > 0:
player.pending_action = PendingAction.CHOOSE
player.choose_text = "choose_fantasma"
player.available_cards = [
{
"name": p.name,
"icon": p.role.icon
if (player.game.initial_players == 3)
else "⭐️"
if isinstance(p.role, r.Sheriff)
else "🤠",
"avatar": p.avatar,
"alt_text": "".join(["❤️"] * p.lives)
+ "".join(["💀"] * (p.max_lives - p.lives)),
"is_character": True,
"is_player": True,
}
for p in player.game.get_dead_players(include_ghosts=False)
]
self.can_be_used_now = False
player.game.deck.scrap(self, True)
return True
return False
class Lemat(Card):
def __init__(self, suit, number):
super().__init__(
suit, "Lemat", number, is_equipment=True, is_weapon=True, range=1
)
self.icon = "🔫" # ogni carta può essere usata come bang, conta per il conteggio dei bang per turno
def play_card(self, player, against, _with=None):
if not self.can_be_used_now and player.game.check_event(ce.Lazo):
return False
if self.can_be_used_now:
if not super().play_card(player, against, _with):
return False
self.can_be_used_now = False
return True
elif not player.has_played_bang and any(
(
player.get_sight() >= p["dist"]
for p in player.game.get_visible_players(player)
)
):
player.set_choose_action("choose_play_as_bang", player.hand.copy())
player.notify_self()
return False
class SerpenteASonagli(Card):
def __init__(self, suit, number):
super().__init__(suit, "SerpenteASonagli", number, is_equipment=True)
self.need_target = True
self.icon = "🐍️" # Ogni turno pesca se il seme picche -1hp
self.alt_text = "♠️ =💔"
def play_card(self, player, against, _with=None):
if (player.game.check_event(ce.IlGiudice)) or not self.can_be_used_now:
return False
if against is not None:
self.can_be_used_now = False
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_against|{player.name}|{self.name}|{against}",
)
player.game.get_player_named(against).equipment.append(self)
player.game.get_player_named(against).notify_self()
return True
return False
class Shotgun(Card):
def __init__(self, suit, number):
super().__init__(
suit, "Shotgun", number, is_equipment=True, is_weapon=True, range=1
)
self.icon = "🔫" # Ogni volta che colpisci un giocatore deve scartare una carta
class Taglia(Card):
def __init__(self, suit, number):
super().__init__(suit, "Taglia", number, is_equipment=True)
self.need_target = True
self.icon = "💰" # chiunque colpisca il giocatore con la taglia pesca una carta dal mazzo, si toglie solo con panico, cat balou, dalton
def play_card(self, player, against, _with=None):
if (player.game.check_event(ce.IlGiudice)) or not self.can_be_used_now:
return False
if against is not None:
self.can_be_used_now = False
G.sio.emit(
"chat_message",
room=player.game.name,
data=f"_play_card_against|{player.name}|{self.name}|{against}",
)
player.game.get_player_named(against).equipment.append(self)
player.game.get_player_named(against).notify_self()
return True
return False
class UltimoGiro(Card):
def __init__(self, suit, number):
super().__init__(suit, "UltimoGiro", number)
self.icon = "🥂"
# self.desc = 'Recupera 1 vita'
# self.desc_eng = 'Regain 1 HP'
self.alt_text = "🍺"
def play_card(self, player, against, _with=None):
super().play_card(player, against)
player.lives = min(player.lives + 1, player.max_lives)
player.notify_self()
return True
class Tomahawk(Card):
def __init__(self, suit, number):
super().__init__(suit, "Tomahawk", number, range=2)
self.icon = "🪓️"
self.alt_text = "2🔎 💥"
# "Spara a un giocatore a distanza 2"
self.need_target = True
def play_card(self, player, against, _with=None):
if against is not None and player.game.can_card_reach(self, player, against):
super().play_card(player, against=against)
player.game.attack(player, against, card_name=self.name)
return True
return False
class Tornado(Card):
def __init__(self, suit, number):
super().__init__(suit, "Tornado", number)
self.icon = "🌪️"
def play_card(self, player, against, _with=None):
super().play_card(player, against=against)
player.game.discard_others(player, card_name=self.name)
return True
class Sventagliata(
Bang
): # : conta come un normale BANG! del turno. Il BANG! secondario è obbligatorio ed è sparato anche se il primo viene annullato, se si può, tu sei escluso come target
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = "Sventagliata"
self.icon = "🎏"
self.alt_text = "💥💥" # spara al target e anche, a uno a distanza 1 dal target
self.need_target = True
def play_card(self, player, against, _with=None):
if against is not None:
if player.has_played_bang:
return False
t = player.game.get_player_named(against)
player.available_cards = [
dict(p, **{"original_target": against})
for p in player.game.get_visible_players(t)
if p["name"] != player.name and p["name"] != t.name and p["dist"]
]
if len(player.available_cards) > 0:
player.pending_action = PendingAction.CHOOSE
player.choose_text = "choose_sventagliata"
else:
player.available_cards = []
super().play_card(player, against=against)
return True
return False
class Salvo(Card): # puoi anche prevenire un danno inferto da te, duello?
def __init__(self, suit, number):
super().__init__(suit, "Salvo", number)
self.icon = "😇️"
self.alt_text = "👤😅"
self.need_target = True
def play_card(self, player, against, _with=None):
if against is not None:
# TODO
# super().play_card(player, against=against)
# player.game.attack(player, against, card_name=self.name)
return True
return False
class Mira(Card):
def __init__(self, suit, number):
super().__init__(suit, "Mira", number)
self.icon = "👌🏻"
self.need_with_only = "Bang"
self.alt_text = "💥🃏💔💔"
self.need_target = True
self.need_with = True
def play_card(self, player, against, _with=None):
if against is not None and _with is not None and _with.name == "Bang!":
super().play_card(player, against=against, _with=_with)
player.game.attack(player, against, card_name=self.name)
return True
return False
class Bandidos(Card):
def __init__(self, suit, number):
super().__init__(suit, "Bandidos", number)
self.icon = "🤠️"
self.alt_text = "👤🃏🃏/💔"
def play_card(self, player, against, _with=None):
super().play_card(player, against=against)
player.game.discard_others(player, card_name=self.name)
return True
class Fuga(
Card
): # comprende indiani gatling etc, ma solo se carte marroni, le carte verdi valgono, attenzione alla classi ereditate
def __init__(self, suit, number):
super().__init__(suit, "Fuga", number)
self.icon = "🏃🏻"
self.alt_text = ""
def play_card(self, player, against, _with=None):
return False
class Poker(Card):
def __init__(self, suit, number):
super().__init__(suit, "Poker", number)
self.icon = "🃏"
self.alt_text = "👤🃏 🃏🃏"
def play_card(self, player, against, _with=None):
super().play_card(player, against=against)
player.game.discard_others(player, card_name=self.name)
return True
class RitornoDiFiamma(Mancato):
def __init__(self, suit, number):
super().__init__(suit, number)
self.name = "RitornoDiFiamma"
self.icon = "🔥"
self.alt_text = "😅 | 💥"
def play_card(self, player, against, _with=None):
return False
def use_card(self, player):
player.notify_self()
def get_starting_deck() -> List[Card]:
cards = [
Fantasma(Suit.SPADES, 9),
Fantasma(Suit.SPADES, 10),
Lemat(Suit.DIAMONDS, 4),
SerpenteASonagli(Suit.HEARTS, 7),
Shotgun(Suit.SPADES, "K"),
Taglia(Suit.CLUBS, 9),
UltimoGiro(Suit.DIAMONDS, 8),
Tomahawk(Suit.DIAMONDS, "A"),
Sventagliata(Suit.SPADES, 2),
# Salvo(Suit.HEARTS, 5),
Bandidos(
Suit.DIAMONDS, "Q"
), # gli altri giocatori scelgono se scartare 2 carte o perdere 1 punto vita
Fuga(
Suit.HEARTS, 3
), # evita l'effetto di carte marroni (tipo panico cat balou) di cui sei bersaglio
Mira(Suit.CLUBS, 6),
Poker(
Suit.HEARTS, "J"
), # tutti gli altri scartano 1 carta a scelta, se non ci sono assi allora pesca 2
RitornoDiFiamma(Suit.CLUBS, "Q"), # un mancato che fa bang
Tornado(Suit.CLUBS, "A"),
]
for c in cards:
c.expansion_icon = "👻️"
return cards

View File

@ -0,0 +1,125 @@
from typing import List
from bang.characters import Character
import bang.cards as cs
class BlackFlower(Character):
"""Una volta nel tuo turno, puoi usare una carta di fiori per sparare un BANG! extra."""
def __init__(self):
super().__init__("Black Flower", max_lives=4)
self.icon = "🥀"
def special(self, player, data): # fiori = suit.Clubs
if player.special_use_count > 0 or not any(
(c.suit == cs.Suit.CLUBS for c in player.hand)
):
return False
if any(
(
player.get_sight() >= p["dist"]
for p in player.game.get_visible_players(player)
)
) and super().special(player, data):
player.special_use_count += 1
player.set_choose_action(
"choose_play_as_bang",
[c for c in player.hand if c.suit == cs.Suit.CLUBS],
)
player.notify_self()
class ColoradoBill(Character):
"""Ogni volta che giochi una carta BANG!, "estrai!": se è Picche, il colpo non può essere evitato.
Whenever you play a BANG! card, "draw!": if it's a Spade, the shot can't be avoided.
"""
def __init__(self):
super().__init__("Colorado Bill", max_lives=4)
self.icon = "♠️"
class DerSpotBurstRinger(Character):
"""Una volta nel tuo turno, puoi usare una carta BANG! come Gatling.
Once per turn, you can use a BANG! card as a Gatling."""
def __init__(self):
super().__init__("Der Spot Burst Ringer", max_lives=4)
self.icon = "🫧"
def special(self, player, data):
if (
player.special_use_count == 0
and any((c.name == "Bang!" for c in player.hand))
and super().special(player, data)
):
player.special_use_count += 1
# get cards from hand of type Bang and sort them by suit
cards = sorted(
[c for c in player.hand if c.name == "Bang!"], key=lambda c: c.suit
)
player.hand.remove(cards[0])
player.game.deck.scrap(cards[0], True, player=player)
player.notify_self()
player.game.attack_others(player, cs.Gatling(0, 0).name)
class EvelynShebang(Character):
"""Puoi rinunciare a pescare carte nella tua fase di pesca. Per ogni carta non pescata, spari un BANG! a distanza raggiungibile, a un diverso bersaglio."""
def __init__(self):
super().__init__("Evelyn Shebang", max_lives=4)
self.icon = "📵"
class HenryBlock(Character):
"""Chiunque peschi o scarti una tua cartain gioco o in mano) è bersaglio di un BANG!"""
def __init__(self):
super().__init__("Henry Block", max_lives=4)
self.icon = "🚯"
class LemonadeJim(Character):
"""Ogni volta che un altro giocatore gioca una Birra, puoi scartare una carta dalla mano per riguadagnare anche tu 1 punto vita."""
def __init__(self):
super().__init__("Lemonade Jim", max_lives=4)
self.icon = "🍋"
class MickDefender(Character):
"""Se sei bersaglio di una carta marrone (non BANG!), puoi usare una carta Mancato! evitarne 1 gli effetti."""
def __init__(self):
super().__init__("Mick Defender", max_lives=4)
self.icon = ""
class TucoFranziskaner(Character):
"""Durante la tua fase di pesca, se non hai carte blu in gioco, pesca 2 carte extra."""
def __init__(self):
super().__init__("Tuco Franziskaner", max_lives=4)
self.icon = "🥬"
def all_characters() -> List[Character]:
cards = [
BlackFlower(),
ColoradoBill(),
DerSpotBurstRinger(),
# EvelynShebang(),
HenryBlock(),
# LemonadeJim(),
MickDefender(),
TucoFranziskaner(),
]
for card in cards:
card.expansion_icon = "👻️" # pylint: disable=attribute-defined-outside-init
card.expansion = ( # pylint: disable=attribute-defined-outside-init
"the_valley_of_shadows"
)
return cards

View File

@ -0,0 +1,315 @@
from typing import TYPE_CHECKING
import bang.cards as cs
from globals import PendingAction
if TYPE_CHECKING:
from bang.players import Player
class StationCard:
def __init__(self, name: str):
self.name = name
self.expansion = "train_robbery"
self.price: list[dict] = []
self.attached_train = None
def discard_and_buy_train(self, player: "Player", card_index: int):
"""Discard the card and buy the train"""
if self.attached_train is None:
return
card = player.available_cards.pop(card_index)
for i, card in enumerate(player.hand):
if card == self:
player.hand.pop(i)
break
else:
player.lives -= 1
card = player.hand.pop(card_index)
player.game.deck.scrap(card, True, player=player)
player.equipment.append(self.attached_train)
self.attached_train = None
player.pending_action = PendingAction.PLAY
def check_price(self, player: "Player") -> bool:
"""Check if the card can be used to rob the train"""
return len(player.hand) > 0
class BoomTown(StationCard):
"""Discard a Bang! to rob the train"""
def __init__(self):
super().__init__("Boom Town")
self.price = [cs.Bang(0, 0).__dict__]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
not isinstance(c, cs.Bang) for c in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if isinstance(c, cs.Bang)],
self.discard_and_buy_train,
)
return True
class Caticor(StationCard):
"""Discard a Cat Balou or Panico to rob the train"""
def __init__(self):
super().__init__("Caticor")
self.price = [cs.CatBalou(0, 0).__dict__, cs.Panico(0, 0).__dict__]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
not (isinstance(card, cs.CatBalou) or isinstance(card, cs.Panico))
for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[
c
for c in player.hand
if isinstance(c, cs.CatBalou) or isinstance(c, cs.Panico)
],
self.discard_and_buy_train,
)
return True
class CreepyCreek(StationCard):
"""Discard a card of spades to rob the train"""
def __init__(self):
super().__init__("Creepy Creek")
self.price = [{"icon": "♠️"}]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
card.suit != cs.Suit.SPADES for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.SPADES],
self.discard_and_buy_train,
)
return True
class CrownsHole(StationCard):
"""Discard a beer to rob the train"""
def __init__(self):
super().__init__("Crowns Hole")
self.price = [cs.Birra(0, 0).__dict__]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
not isinstance(card, cs.Birra) for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if isinstance(c, cs.Birra)],
self.discard_and_buy_train,
)
return True
class Deadwood(StationCard):
"""Discard an equipment card to rob the train"""
def __init__(self):
super().__init__("Deadwood")
self.price = [{"is_equipment": True}]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
not card.is_equipment for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.is_equipment],
self.discard_and_buy_train,
)
return True
class Dodgeville(StationCard):
"""Discard a Missed! to rob the train"""
def __init__(self):
super().__init__("Dodgeville")
self.price = [cs.Mancato(0, 0).__dict__]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
not isinstance(card, cs.Mancato) for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if isinstance(c, cs.Mancato)],
self.discard_and_buy_train,
)
return True
class FortWorth(StationCard):
"""Discard a card with number 10, J, Q, K, A to rob the train"""
def __init__(self):
super().__init__("Fort Worth")
self.price = [{"icon": "10\nJ\nQ\nK\nA"}]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
card.number not in {1, 10, 11, 12, 13} for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.number in {1, 10, 11, 12, 13}],
self.discard_and_buy_train,
)
return True
class Frisco(StationCard):
"""Discard a card of clubs to rob the train"""
def __init__(self):
super().__init__("Frisco")
self.price = [{"icon": "♣️"}]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
card.suit != cs.Suit.CLUBS for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.CLUBS],
self.discard_and_buy_train,
)
return True
class MinersOath(StationCard):
"""Discard a card of diamonds to rob the train"""
def __init__(self):
super().__init__("Miners Oath")
self.price = [{"icon": "♦️"}]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
card.suit != cs.Suit.DIAMONDS for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.DIAMONDS],
self.discard_and_buy_train,
)
return True
class SanTafe(StationCard):
"""Discard a card of hearts to rob the train"""
def __init__(self):
super().__init__("San Tafe")
self.price = [{"icon": "♥️"}]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
card.suit != cs.Suit.HEARTS for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if c.suit == cs.Suit.HEARTS],
self.discard_and_buy_train,
)
return True
class Tombrock(StationCard):
"""Lose 1 life point to rob the train"""
def __init__(self):
super().__init__("Tombrock")
self.price = [{"icon": "💔"}]
def check_price(self, player: "Player"):
if player.lives <= 1:
return False
player.set_choose_action(
"choose_buy_train",
[{"icon": "💔"}],
self.discard_and_buy_train,
)
return True
class Yooma(StationCard):
"""Discard a card with number between 2 and 9 to rob the train"""
def __init__(self):
super().__init__("Yooma")
self.price = [{"icon": "2-9"}]
def check_price(self, player: "Player"):
if super().check_price(player) and all(
not (2 <= card.number <= 9) for card in player.hand
):
return False
player.set_choose_action(
"choose_buy_train",
[c for c in player.hand if 2 <= c.number <= 9],
self.discard_and_buy_train,
)
return True
class VirginiaTown(StationCard):
"""Discard two cards to rob the train"""
def __init__(self):
super().__init__("Virginia Town")
self.price = [{}, {}]
def check_price(self, player: "Player"):
if super().check_price(player) and len(player.hand) < 2:
return False
player.set_choose_action(
"choose_buy_train",
player.hand.copy(),
self.discard_and_buy_train,
)
return True
def get_all_stations():
"""Return a list of all the station cards"""
return [
BoomTown(),
Caticor(),
CreepyCreek(),
CrownsHole(),
Deadwood(),
Dodgeville(),
FortWorth(),
Frisco(),
MinersOath(),
SanTafe(),
Tombrock(),
Yooma(),
VirginiaTown(),
]

View File

@ -0,0 +1,406 @@
import random
from bang.cards import Card, Bang, Panico, CatBalou, Mancato
from typing import TYPE_CHECKING
from globals import G, PendingAction
if TYPE_CHECKING:
from bang.players import Player
class TrainCard(Card):
def __init__(self, name: str, is_locomotive: bool = False):
super().__init__(suit=5, number=0, name=name)
self.expansion_icon = "🚂"
self.is_equipment = True
self.is_locomotive = is_locomotive
self.expansion = "train_robbery"
self.type = "train"
self.implemented = True
# Circus Wagon: gli altri giocatori
# scartano una carta, in senso orario, a
# partire dal giocatore alla tua sinistra.
# Express Car: non puoi svolgere
# un altro turno extra dopo quello
# ottenuto da questo effetto, anche se
# riesci a giocare di nuovo Express Car.
# Ghost Car: giocabile su un
# qualsiasi giocatore, anche se già
# eliminato, te compreso. Non può
# essere giocato sullo Sceriffo.
# Se quel giocatore è/viene eliminato,
# invece ritorna/resta in gioco, senza
# punti vita. Non può guadagnare né
# perdere punti vita, e viene considerato
# un personaggio in gioco per tutti gli
# effetti (condizioni di vittoria, distanza
# tra giocatori, abilità dei personaggi,
# ecc.). Non avendo punti vita, deve
# scartare la sua intera mano alla fine
# del turno, ma può tenere qualsiasi
# carta in gioco di fronte a sé, incluso
# Ghost Car. Tuttavia, è eliminato
# dal gioco non appena Ghost Car
# viene scartato: nessuna ricompensa
# viene assegnata in questo caso se il
# giocatore è un Fuorilegge, e le abilità
# dei personaggi (ad es. Vulture Sam)
# non si attivano
# Lounge Car: i vagoni che peschi
# non contano per il normale limite di
# acquisizione di 1 vagone per turno. Se
# sei lo Sceriffo e peschi Ghost Car, devi
# darlo a un altro giocatore.
# Lumber Flatcar: gioca su un
# qualsiasi giocatore (compreso te).
# Finché questa carta è in gioco, quel
# giocatore vede gli altri giocatori a
# distanza aumentata di 1.
# Private Car: questo effetto non
# ti protegge da Gatling, Knife Revolver,
# labilità di Evan Babbit, e così via.
# Sleeper Car: puoi anche usare
# leffetto una volta per turno con
# Indiani!, Duello, ecc.
class Ironhorse(TrainCard):
"""LOCOMOTIVA:
Ogni giocatore, incluso colui che ha attivato l'effetto, è bersaglio di un BANG!
Nessun giocatore è responsabile dell'eventuale perdita di punti vita.
Se tutti i giocatori vengono eliminati allo stesso tempo, i Fuorilegge vincono.
"""
def __init__(self):
super().__init__("Ironhorse", is_locomotive=True)
self.icon = "🚂"
def play_card(self, player, against=None, _with=None) -> bool:
player.game.attack(player, player.name, card_name=self.name)
player.game.attack_others(player, card_name=self.name)
return True
class Leland(TrainCard):
"""
LOCOMOTIVA: svolgi l'effetto dell'Emporio, cominciando dal giocatore di turno e procedendo in senso orario.
"""
def __init__(self):
super().__init__("Leland", is_locomotive=True)
self.icon = "🚂"
def play_card(self, player, against=None, _with=None) -> bool:
player.game.emporio(player)
return True
class BaggageCar(TrainCard):
"""Scartalo: ottieni l'effetto di un Mancato!, Panico!, Cat Balou o di un BANG! extra.
Discard this for a Missed! Panic!, Cat Balou, or an extra BANG!"""
def __init__(self):
super().__init__("Baggage Car")
self.icon = "🚋🛄"
def choose_callback(self, player: 'Player', card_index):
player.hand.append(player.available_cards[card_index])
player.pending_action = PendingAction.PLAY
def play_card(self, player, against=None, _with=None) -> bool:
player.set_choose_action(
"choose_baggage_car",
[Bang(4, 42), Mancato(4, 42), CatBalou(4, 42), Panico(4, 42)],
self.choose_callback,
)
return True
class Caboose(TrainCard):
"""Puoi scartare un altra tua carta bordo blu incuso un vagone come se fosse un Mancato!"""
def __init__(self):
super().__init__("Caboose")
self.icon = "🚋"
def play_card(self, player, against=None, _with=None) -> bool:
return False
class CattleTruck(TrainCard):
"""Scartalo: guarda le 3 carte in cima agli scarti e pescane I"""
def __init__(self):
super().__init__("Cattle Truck")
self.icon = "🚋🐄"
def choose_card_callback(self, player: 'Player', card_index):
chosen_card = player.available_cards.pop(card_index)
player.game.deck.scrap_pile.pop(-card_index)
player.hand.append(chosen_card)
player.pending_action = PendingAction.PLAY
player.notify_self()
def play_card(self, player, against=None, _with=None) -> bool:
drawn_cards = player.game.deck.peek_scrap_pile(n_cards=3)
player.set_choose_action(
"choose_cattle_truck",
drawn_cards,
self.choose_card_callback,
)
return True
class CircusWagon(TrainCard):
"""Scartalo: ogni altro giocatore deve scartare una carta che ha in gioco."""
def __init__(self):
super().__init__("Circus Wagon", is_locomotive=True)
self.icon = "🚋🎪"
def play_card(self, player, against=None, _with=None) -> bool:
player.game.discard_others(player, card_name=self.name)
return True
@classmethod
def choose_circus_wagon(cls, player: 'Player', card_index):
player.game.deck.scrap(player.hand.pop(card_index), player=player)
player.pending_action = PendingAction.WAIT
player.game.responders_did_respond_resume_turn()
player.notify_self()
class CoalHopper(TrainCard):
"""Scartalo: pesca una carta e scarta un vagone in gioco davanti a un giocatore a tua scelta."""
def __init__(self):
super().__init__("Coal Hopper")
self.icon = "🚋🔥"
self.need_target = True
def play_card(self, player, against=None, _with=None) -> bool:
if against is not None and len(player.game.get_player_named(against).equipment) > 0:
player.game.steal_discard(player, against, self)
return True
class DiningCar(TrainCard):
"""A inizio turno, "estrai!": se è Cuori, recuperi I punto vita."""
def __init__(self):
super().__init__("Dining Car")
self.icon = "🚋🍽"
def play_card(self, player, against=None, _with=None) -> bool:
return False
class ExpressCar(TrainCard):
"""Scarta tutte le carte in mano, poi gioca un altro turno"""
def __init__(self):
super().__init__("Express Car")
self.icon = "🚋⚡"
def play_card(self, player, against=None, _with=None) -> bool:
while len(player.hand) > 0:
player.game.deck.scrap(player.hand.pop(0), player=player)
player.notify_self()
player.play_turn()
return True
class GhostCar(TrainCard):
"""Giocalo su chiunque tranne lo Sceritfo. Se vieni eliminato, invece resta in gioco, ma non puo guadagnare ne perdere punti vita."""
def __init__(self):
super().__init__("Ghost Car")
self.icon = "🚋👻"
self.implemented = False
def play_card(self, player, against=None, _with=None) -> bool:
return False
class LoungeCar(TrainCard):
"""Scartalo: pesca 2 vagoni dal mazzo, mettine I in gioco di fronte a te e 1 di fronte a un altro giocatore."""
def __init__(self):
super().__init__("Lounge Car")
self.icon = "🚋🛋"
self.implemented = False
def play_card(self, player, against=None, _with=None) -> bool:
return True
class LumberFlatcar(TrainCard):
"""Giocalo su un qualsiasi giocatore (compreso te). Finché questa carta è in gioco, quel giocatore vede gli altri giocatori a distanza aumentata di 1."""
def __init__(self):
super().__init__("Lumber Flatcar")
self.icon = "🚋🪵"
self.sight_mod = -1
def play_card(self, player, against=None, _with=None) -> bool:
return False
class MailCar(TrainCard):
"""Scartalo: pesca 3 carte e dai 1 di esse a un altro giocatore a tua scelta."""
def __init__(self):
super().__init__("Mail Car")
self.icon = "🚋📮"
def choose_card_callback(self, player: 'Player', card_index):
chosen_card = player.available_cards.pop(card_index)
player.hand.extend(player.available_cards)
player.set_choose_action(
"choose_other_player",
player.game.get_other_players(player),
lambda p, other_player_index: self.choose_player_callback(p, other_player_index, chosen_card)
)
def choose_player_callback(self, player: 'Player', other_player_index, chosen_card):
pl_name = player.game.get_other_players(player)[other_player_index]["name"]
other_player = player.game.get_player_named(pl_name)
other_player.hand.append(chosen_card)
G.sio.emit(
"card_drawn",
room=player.game.name,
data={"player": pl_name, "pile": player.name},
)
other_player.notify_self()
player.pending_action = PendingAction.PLAY
def play_card(self, player, against=None, _with=None) -> bool:
drawn_cards = [player.game.deck.draw(player=player) for _ in range(3)]
player.set_choose_action(
"choose_mail_car",
drawn_cards,
self.choose_card_callback,
)
return True
class ObservationCar(TrainCard):
"""Tu vedi gli altri a distanza -1. Gli altri a vedono a distanza +1."""
def __init__(self):
super().__init__("Observation Car")
self.icon = "🚋👀"
self.sight_mod = 1
self.vis_mod = 1
def play_card(self, player, against=None, _with=None) -> bool:
return False
class PassengerCar(TrainCard):
"""Scartalo: pesca una carta (o in mano o in gioco) da un altro giocatore"""
def __init__(self):
super().__init__("Passenger Car")
self.icon = "🚋🚶"
self.range = 99
self.need_target = True
def play_card(self, player, against=None, _with=None) -> bool:
if (
against is not None
and (len(player.equipment) > 0 or len(player.equipment) > 0)
):
player.game.steal_discard(player, against, self)
return True
return False
class PrisonerCar(TrainCard):
"""Le carte Duello e Indiani! giocate dagli altri giocatori non hanno effetto su di te."""
def __init__(self):
super().__init__("Prisoner Car")
self.icon = "🚋👮🏻‍♂️"
def play_card(self, player, against=None, _with=None) -> bool:
return False
class PrivateCar(TrainCard):
"""Se non hai carte in mano, non puoi essere bersaglio di carte BANG"""
def __init__(self):
super().__init__("Private Car")
self.icon = "🚋💁🏻"
def play_card(self, player, against=None, _with=None) -> bool:
return False
class SleeperCar(TrainCard):
"""Una volta per turno, puoi scartare un'altra tua carta a bordo blu incluso."""
def __init__(self):
super().__init__("Sleeper Car")
self.icon = "🚋🛌"
def choose_card_callback(self, player: 'Player', card_index):
player.game.deck.scrap(player.equipment.pop(card_index), player=player)
player.pending_action = PendingAction.PLAY
self.usable_next_turn = True
self.can_be_used_now = False
player.notify_self()
def play_card(self, player, against=None, _with=None) -> bool:
if not self.can_be_used_now:
return False
player.set_choose_action(
"choose_sleeper_car",
player.equipment,
self.choose_card_callback,
)
return False
def get_all_cards(rng=random):
"""Return a list of all train cards in the expansion"""
cars = [
BaggageCar(),
Caboose(),
CattleTruck(),
CircusWagon(),
CoalHopper(),
DiningCar(),
ExpressCar(),
GhostCar(),
LoungeCar(),
LumberFlatcar(),
MailCar(),
ObservationCar(),
PassengerCar(),
PrisonerCar(),
PrivateCar(),
SleeperCar(),
]
cars = [c for c in cars if c.implemented]
rng.shuffle(cars)
return cars
def get_locomotives(rng=random):
"""Return a list of all locomotive cards in the expansion"""
locs = [
Ironhorse(),
Leland(),
]
rng.shuffle(locs)
return locs

View File

@ -0,0 +1,178 @@
import random
import bang.cards as cs
import bang.roles as roles
import bang.players as players
from globals import G
from bang.expansions.fistful_of_cards.card_events import CardEvent
class WildWestShowCardEvent(CardEvent):
"""
Base class for all card events in the Wild West Show expansion
"""
def __init__(self, name, icon):
super().__init__(name, icon)
self.expansion = "wild-west-show"
# class Bavaglio(CardEvent):
# def __init__(self):
# super().__init__("Bavaglio", "🤐")
# # I giocatori non possono parlare (ma possono gesticolare, mugugnare...). Chi parla perde 1 punto vita.
# # NOT IMPLEMENTED
class Camposanto(WildWestShowCardEvent):
"""
All'inizio del proprio turno, ogni giocatore eliminato torna in gioco con 1 punto vita. Pesca il ruolo a caso fra quelli dei giocatori eliminati.
"""
def __init__(self):
super().__init__("Camposanto", "")
class DarlingValentine(WildWestShowCardEvent):
"""
All'inizio del proprio turno, ogni giocatore scarta le carte in mano e ne pesca dal mazzo altrettante.
"""
def __init__(self):
super().__init__("Darling Valentine", "💋")
class DorothyRage(WildWestShowCardEvent):
"""
Nel proprio turno, ogni giocatore può obbligarne un altro a giocare una carta.
"""
def __init__(self):
super().__init__("Dorothy Rage", "👩‍⚖️")
class HelenaZontero(WildWestShowCardEvent):
"""
Quando Helena entra in gioco, "estrai!": se esce Cuori o Quadri, rimescola i ruoli attivi tranne lo Sceriffo, e ridistribuiscili a caso.
"""
def __init__(self):
super().__init__("Helena Zontero", "💞")
def on_flipped(self, game):
c = game.deck.pick_and_scrap()
G.sio.emit(
"chat_message",
room=game.name,
data=f"_flipped|Helena Zontero|{c.name}|{c.num_suit()}",
)
if c.check_suit(game, [cs.Suit.HEARTS, cs.Suit.DIAMONDS]):
G.sio.emit(
"chat_message",
room=game.name,
data=f"_swapped_roles|Helena Zontero|{c.name}|{c.num_suit()}",
)
pls = [p for p in game.players if not isinstance(p.role, roles.Sheriff)]
newroles = [p.role for p in pls]
game.rng.shuffle(newroles)
for p in pls:
p.set_role(newroles.pop(game.rng.randint(0, len(newroles) - 1)))
return super().on_flipped(game)
class LadyRosaDelTexas(WildWestShowCardEvent):
"""
Nel proprio turno, ogni giocatore può scambiarsi di posto con quello alla sua destra, il quale salta il prossimo turno.
"""
def __init__(self):
super().__init__("Lady Rosa del Texas", "🩰")
def on_clicked(self, game, player):
super().on_clicked(game, player)
nextp = game.next_player()
i, j = game.players_map[player.name], game.players_map[nextp.name]
game.players[i], game.players[j] = nextp, player
game.players_map[player.name], game.players_map[nextp.name] = j, i
game.turn = j
game.notify_all()
class MissSusanna(WildWestShowCardEvent):
"""
Nel proprio turno ogni giocatore deve giocare almeno 3 carte. Se non lo fa, perde 1 punto vita.
"""
def __init__(self):
super().__init__("Miss Susanna", "👩‍🎤")
class RegolamentoDiConti(WildWestShowCardEvent):
"""
Tutte le carte possono essere giocate come se fossero BANG!. Le carte BANG! come se fossero Mancato!
"""
def __init__(self):
super().__init__("Regolamento di Conti", "🤠")
def on_clicked(self, game, player):
super().on_clicked(game, player)
if (
len(player.hand) > 0
and not player.has_played_bang
and any(
(
player.get_sight() >= p["dist"]
for p in game.get_visible_players(player)
)
)
):
player.available_cards = player.hand.copy()
player.pending_action = players.PendingAction.CHOOSE
player.choose_text = "choose_play_as_bang"
player.notify_self()
class Sacagaway(WildWestShowCardEvent):
"""
Tutti i giocatori giocano a carte scoperte (tranne il ruolo!).
"""
def __init__(self):
super().__init__("Sacagaway", "🌄")
class WildWestShow(WildWestShowCardEvent):
"""
L'obiettivo di ogni giocatore diventa: "Rimani l'ultimo in gioco!"
"""
def __init__(self):
super().__init__("Wild West Show", "🎪")
def on_flipped(self, game):
for player in game.players:
player.set_role(roles.Renegade())
return super().on_flipped(game)
def get_endgame_card():
"""Return the endgame card for this expansion"""
return WildWestShow()
def get_all_events(rng=random):
"""Return all the events for this expansion shuffled, excluding the endgame card"""
cards = [
Camposanto(),
DarlingValentine(),
# DorothyRage(),
HelenaZontero(),
LadyRosaDelTexas(),
MissSusanna(),
RegolamentoDiConti(),
Sacagaway(),
]
rng.shuffle(cards)
return cards

View File

@ -0,0 +1,144 @@
from typing import List
import bang.cards as cs
from bang.characters import Character
class BigSpencer(Character):
"""
Inizia con 5 carte. Non può giocare Mancato!
"""
def __init__(self):
super().__init__("Big Spencer", max_lives=9)
self.icon = "🫘"
class FlintWestwood(Character):
"""
Nel suo turno può scambiare una carta dalla mano con 2 carte a caso dalla mano di un altro giocatore.
> NOTE: La carta dalla tua mano è a scelta, non a caso. Se il giocatore bersaglio ha una sola carta, ne ricevi solo una.
"""
def __init__(self):
super().__init__("Flint Westwood", max_lives=4)
self.icon = "🔫"
def special(self, player, data):
if (
not player.is_my_turn
or not any((len(p.hand) > 0 for p in player.game.get_alive_players()))
or not super().special(player, data)
):
return False
import bang.players as pls
player.available_cards = player.hand.copy()
player.choose_text = "choose_flint_special"
player.pending_action = pls.PendingAction.CHOOSE
player.special_use_count += 1
player.notify_self()
class GaryLooter(Character):
"""
Pesca tutte le carte in eccesso scartate dagli altri giocatori a fine turno.
"""
def __init__(self):
super().__init__("Gary Looter", max_lives=5)
self.icon = "🥲"
class GreygoryDeckard(Character):
"""
All'inizio del suo turno può pescare 2 personaggi a caso. Ha tutte le abilità dei personaggi pescati.
"""
def __init__(self):
super().__init__("Greygory Deckard", max_lives=4)
self.icon = "👨‍🦳"
class JohnPain(Character):
"""
Se ha meno di 6 carte in mano, quando un giocatore "estrae!" John aggiunge alla mano la carta appena estratta.
"""
def __init__(self):
super().__init__("John Pain", max_lives=4)
self.icon = "🤕"
class LeeVanKliff(Character):
"""
Nel suo turno, può scartare un BANG! per ripetere l'effetto di una carta a bordo marrone che ha appena giocato.
"""
def __init__(self):
super().__init__("Lee Van Kliff", max_lives=4)
self.icon = "👨‍🦲"
def special(self, player, data):
if player.last_played_card is None:
return False
if (
player.last_played_card.is_equipment
or player.last_played_card.usable_next_turn
or player.last_played_card.number == 42
or not any(isinstance(c, cs.Bang) for c in player.hand)
or not super().special(player, data)
):
return False
bang_index = next(
(i for i, card in enumerate(player.hand) if isinstance(card, cs.Bang)), -1
)
bang_card = player.hand.pop(bang_index)
print(f"{bang_card=}")
player.game.deck.scrap(bang_card, player=player)
player.last_played_card.must_be_used = True
player.last_played_card.number = 42
player.hand.append(player.last_played_card)
print(f"{player.hand=}")
player.notify_self()
class TerenKill(Character):
"""
Ogni volta che sarebbe eliminato "estrai!": se non è Picche, Teren resta a 1 punto vita e pesca 1 carta.
"""
def __init__(self):
super().__init__("Teren Kill", max_lives=3)
self.icon = "👨‍🦰"
class YoulGrinner(Character):
"""
Prima di pescare, i giocatori con più carte in mano di lui devono dargli una carta a scelta.
"""
def __init__(self):
super().__init__("Youl Grinner", max_lives=4)
self.icon = "🤡"
def all_characters() -> List[Character]:
"""
Returns a list of all characters in this expansion.
"""
cards = [
BigSpencer(),
FlintWestwood(),
GaryLooter(),
# GreygoryDeckard(),
JohnPain(),
LeeVanKliff(),
TerenKill(),
YoulGrinner(),
]
for card in cards:
card.expansion_icon = "🎪" # pylint: disable=attribute-defined-outside-init
card.expansion = ( # pylint: disable=attribute-defined-outside-init
"wild_west_show"
)
return cards

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@ class Sheriff(Role):
def on_player_death(self, alive_players: list, initial_players: int, dead_role=None, attacker_role=None):
if initial_players == 3 and len(alive_players) == 1:
return True
elif initial_players != 3 and not any([isinstance(p.role, Outlaw) or isinstance(p.role, Renegade) for p in alive_players]):
elif initial_players != 3 and not any((isinstance(p.role, Outlaw) or isinstance(p.role, Renegade) for p in alive_players)):
print("The Sheriff won!")
return True
return False
@ -40,9 +40,9 @@ class Vice(Role):
def on_player_death(self, alive_players: list, initial_players: int, dead_role=None, attacker_role=None):
if initial_players == 3 and len(alive_players) == 1:
return True
elif initial_players == 3 and attacker_role != None:
elif initial_players == 3 and attacker_role is not None:
return isinstance(dead_role, Renegade) and isinstance(attacker_role, Vice)
elif initial_players != 3 and not any([isinstance(p.role, Outlaw) or isinstance(p.role, Renegade) for p in alive_players]):
elif initial_players != 3 and not any((isinstance(p.role, Outlaw) or isinstance(p.role, Renegade) for p in alive_players)):
print("The Vice won!")
return True
return False
@ -60,9 +60,11 @@ class Outlaw(Role):
def on_player_death(self, alive_players: list, initial_players: int, dead_role=None, attacker_role=None):
if initial_players == 3 and len(alive_players) == 1:
return True
elif initial_players == 3 and attacker_role != None:
elif initial_players == 3 and attacker_role is not None:
return isinstance(dead_role, Vice) and isinstance(attacker_role, Outlaw)
elif initial_players != 3 and not any([isinstance(p.role, Sheriff) for p in alive_players]):
elif (initial_players != 3 and (not any((isinstance(p.role, Sheriff) for p in alive_players)))
and (any((isinstance(p.role, Outlaw) for p in alive_players))
or any((isinstance(p.role, Renegade) for p in alive_players)) and len(alive_players) > 1)):
print("The Outlaw won!")
return True
return False
@ -80,9 +82,9 @@ class Renegade(Role):
def on_player_death(self, alive_players: list, initial_players: int, dead_role=None, attacker_role=None):
if initial_players == 3 and len(alive_players) == 1:
return True
elif initial_players == 3 and attacker_role != None:
elif initial_players == 3 and attacker_role is not None:
return isinstance(dead_role, Outlaw) and isinstance(attacker_role, Renegade)
elif initial_players != 3 and len(alive_players) == 1 and alive_players[0].role == self:
elif initial_players != 3 and len(alive_players) == 1 and isinstance(alive_players[0].role, Renegade):
print("The Renegade won!")
return True
return False

17
backend/globals.py Normal file
View File

@ -0,0 +1,17 @@
from enum import IntEnum
class G:
sio = None
def __init__(self):
pass
class PendingAction(IntEnum):
PICK = 0
DRAW = 1
PLAY = 2
RESPOND = 3
WAIT = 4
CHOOSE = 5

28
backend/metrics.py Normal file
View File

@ -0,0 +1,28 @@
import os
import time
from datadog import initialize, api
class Metrics:
send_metrics = False
@classmethod
def init(cls):
if "DATADOG_API_KEY" in os.environ and "DATADOG_APP_KEY" in os.environ and "HOST" in os.environ:
Metrics.send_metrics = True
initialize()
api.Event.create(title="Backend start", text="", tags=["server:backend", f"host:{os.environ['HOST']}"], alert_type="info")
else:
print("Datadog not configured")
@classmethod
def send_metric(cls, metric_name, **kwargs):
if Metrics.send_metrics:
kwargs['tags'] = ["server:backend", f"host:{os.environ['HOST']}"] + kwargs.get('tags', [])
kwargs['points'][0] = (int(time.time()) , kwargs['points'][0])
api.Metric.send(metric=metric_name, **kwargs)
@classmethod
def send_event(cls, event_name, event_data, **kwargs):
if Metrics.send_metrics:
kwargs['tags'] = ["server:backend", f"host:{os.environ['HOST']}"] + kwargs.get('tags', [])
api.Event.create(title=event_name, text=event_data, tags=kwargs['tags'], alert_type=kwargs.get('alert_type', "info"))

View File

@ -1,7 +1,10 @@
certifi==2020.11.8
dnspython==1.16.0
eventlet==0.29.1
greenlet==0.4.17
python-engineio==3.13.2
python-socketio==4.6.0
six==1.15.0
certifi==2022.12.7
dnspython==2.3.0
eventlet==0.35.2
python-engineio==4.3.4
python-socketio==5.8.0
six==1.16.0
pytest==7.2.2
requests==2.32.0
discord-webhook==1.1.0
datadog==0.45.0

1421
backend/server.py Normal file

File diff suppressed because it is too large Load Diff

43
backend/tests/__init__.py Normal file
View File

@ -0,0 +1,43 @@
from typing import Any, List
import pytest
from bang.characters import Character
from bang.game import Game
from bang.players import Player
from tests.dummy_socket import DummySocket
from globals import G
G.sio = DummySocket()
def started_game(expansions=[], players=4, character=Character("test_char", 4)) -> Game:
g = Game("test")
g.expansions = expansions
ps = [Player(f"p{i}", f"p{i}") for i in range(players)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [character]
if "high_noon" in expansions:
p.available_characters.append(Character("test_char2", 4))
p.set_character(p.available_characters[0].name)
return g
def set_events(g: Game, event_cards) -> None:
g.deck.event_cards = event_cards
def current_player(g: Game) -> Player:
return g.players[g.turn]
def next_player(g: Game) -> Player:
return g.players[(g.turn + 1) % len(g.players)]
def current_player_with_cards(g: Game, cards: List[Any]) -> Player:
p = current_player(g)
p.draw("")
p.hand = cards
return p

495
backend/tests/cards_test.py Normal file
View File

@ -0,0 +1,495 @@
from random import randint
from bang.characters import Character
from bang.cards import *
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
from globals import PendingAction
# test card Barile
def test_barile():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 2)]
p.set_character(p.available_characters[0].name)
barrel_guy = g.players[g.turn]
barrel_guy.draw('')
barrel_guy.hand = [Barile(0,0)]
barrel_guy.play_card(0)
assert isinstance(barrel_guy.equipment[0], Barile)
barrel_guy.end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Volcanic(0,0), Bang(0,0), Bang(0,0)]
g.players[g.turn].play_card(0)
g.players[g.turn].play_card(0, barrel_guy.name)
assert g.players[g.turn].pending_action == PendingAction.WAIT
assert barrel_guy.pending_action == PendingAction.PICK
g.deck.cards[0] = Bang(Suit.HEARTS, 5)
barrel_guy.pick()
assert barrel_guy.pending_action == PendingAction.WAIT
assert barrel_guy.lives == barrel_guy.max_lives
assert g.players[g.turn].pending_action == PendingAction.PLAY
g.players[g.turn].play_card(0, barrel_guy.name)
g.deck.cards[0] = Bang(Suit.SPADES, 5)
barrel_guy.pick()
assert barrel_guy.pending_action == PendingAction.WAIT
assert barrel_guy.lives == barrel_guy.max_lives - 1
assert g.players[g.turn].pending_action == PendingAction.PLAY
#test card Volcanic
def test_volcanic():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 3)]
p.set_character(p.available_characters[0].name)
for p in ps:
p.hand = []
volcanic_guy = g.players[g.turn]
volcanic_guy.draw('')
volcanic_guy.hand = [Volcanic(0,0), Bang(0,0), Bang(0,0)]
volcanic_guy.play_card(0)
assert isinstance(volcanic_guy.equipment[0], Volcanic)
assert volcanic_guy.get_sight() == 1
volcanic_guy.play_card(0, g.players[(g.turn+1)%3].name)
assert len(volcanic_guy.hand) == 1
volcanic_guy.play_card(0, g.players[(g.turn+1)%3].name)
assert len(volcanic_guy.hand) == 0
# test card Dinamite
def test_dinamite():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
for p in ps:
p.hand = []
dinamite_guy = g.players[g.turn]
dinamite_guy.draw('')
dinamite_guy.hand = [Dinamite(0,0)]
dinamite_guy.play_card(0)
assert isinstance(dinamite_guy.equipment[0], Dinamite)
dinamite_guy.end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.deck.cards.insert(0, Dinamite(Suit.HEARTS, 5))
dinamite_guy.pick()
assert len(dinamite_guy.equipment) == 0
dinamite_guy.draw('')
dinamite_guy.end_turn()
assert len(g.players[g.turn].equipment) == 1
g.deck.cards.insert(0, Dinamite(Suit.SPADES, 5))
g.players[g.turn].pick()
assert len(g.players[g.turn].equipment) == 0
assert g.players[g.turn].lives == 1
# test mirino
def test_mirino():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
mirino_guy = g.players[g.turn]
mirino_guy.draw('')
mirino_guy.hand = [Mirino(0,0)]
assert mirino_guy.get_sight(countWeapon=False) == 1
mirino_guy.play_card(0)
assert mirino_guy.get_sight(countWeapon=False) == 2
# test mustang
def test_mustang():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
mustang_guy = g.players[g.turn]
mustang_guy.draw('')
mustang_guy.hand = [Mustang(0,0)]
assert mustang_guy.get_visibility() == 0
mustang_guy.play_card(0)
assert mustang_guy.get_visibility() == 1
# test Prigione
def test_prigione():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
sheriff = g.players[g.turn]
sheriff.draw('')
sheriff.hand = [Prigione(0,0)]
sheriff.play_card(0, g.players[(g.turn+1)%4].name)
assert len(sheriff.hand) == 0
sheriff.end_turn()
g.deck.cards.insert(0, Prigione(Suit.CLUBS, 5))
skip_check = g.turn
g.players[g.turn].pick()
assert g.turn != skip_check
g.players[g.turn].draw('')
g.players[g.turn].hand = [Prigione(0,0)]
g.players[g.turn].play_card(0, sheriff.name)
assert len(g.players[g.turn].hand) == 1
g.players[g.turn].play_card(0, g.players[(g.turn+1)%4].name)
g.players[g.turn].end_turn()
g.deck.cards.insert(0, Prigione(Suit.HEARTS, 5))
skip_check = g.turn
g.players[g.turn].pick()
assert g.turn == skip_check
# test all weapons ranges
def test_all_weapons():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].draw('')
g.players[g.turn].hand = [Volcanic(0,0), Schofield(0,0), Remington(0,0), RevCarabine(0,0), Winchester(0,0)]
g.players[g.turn].play_card(0)
assert g.players[g.turn].get_sight() == 1
g.players[g.turn].play_card(0)
assert g.players[g.turn].get_sight() == 2
g.players[g.turn].play_card(0)
assert g.players[g.turn].get_sight() == 3
g.players[g.turn].play_card(0)
assert g.players[g.turn].get_sight() == 4
g.players[g.turn].play_card(0)
assert g.players[g.turn].get_sight() == 5
# test bang
def test_bang():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0), Bang(0,0)]
assert len(g.players[g.turn].hand) == 2
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert len(g.players[g.turn].hand) == 1
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert len(g.players[g.turn].hand) == 1
# test birra
def test_birra_2p():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].draw('')
g.players[g.turn].hand = [Birra(0,0)]
g.players[g.turn].lives = 1
g.players[g.turn].play_card(0)
assert g.players[g.turn].lives == 1
# test birra
def test_birra_3p():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
initial_p = g.players[g.turn]
g.players[g.turn].draw('')
g.players[g.turn].hand = [Birra(0,0)]
g.players[g.turn].lives = 1
g.players[g.turn].play_card(0)
assert g.players[g.turn].lives == 2
# test beer save
g.players[g.turn].hand = [Birra(0,0)]
g.players[g.turn].lives = 1
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, initial_p.name)
assert initial_p.lives == 1
# test non overflow
g.players[g.turn].lives = g.players[g.turn].max_lives
g.players[g.turn].hand = [Birra(0,0)]
g.players[g.turn].play_card(0)
assert g.players[g.turn].lives == g.players[g.turn].max_lives
# test CatBalou
def test_catbalou():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].draw('')
g.players[g.turn].hand = [CatBalou(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
g.players[g.turn].choose(0)
assert len(g.players[g.turn].hand) == 0
assert len(g.deck.scrap_pile) == 2
assert len(g.players[(g.turn+1)%2].hand) == 3
# test Diligenza
def test_diligenza():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].draw('')
g.players[g.turn].hand = [Diligenza(0,0)]
g.players[g.turn].play_card(0)
assert len(g.players[g.turn].hand) == 2
# test Duello
def test_duello():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
for p in ps:
p.hand = []
g.players[g.turn].draw('')
# winning duello
g.players[g.turn].hand = [Duello(0,0), Duello(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert len(g.players[g.turn].hand) == 1
assert g.players[(g.turn+1)%2].lives == g.players[(g.turn+1)%2].max_lives - 1
# losing duello
g.players[(g.turn+1)%2].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[g.turn].pending_action == PendingAction.WAIT
assert g.players[(g.turn+1)%2].pending_action == PendingAction.RESPOND
g.players[(g.turn+1)%2].respond(0)
assert g.players[(g.turn+1)%2].pending_action == PendingAction.WAIT
assert g.players[g.turn].lives == g.players[g.turn].max_lives - 1
# test Emporio
def test_emporio():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(7)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
for p in ps:
p.hand = []
g.players[g.turn].draw('')
g.players[g.turn].hand = [Emporio(0,0)]
g.players[g.turn].play_card(0)
assert g.players[g.turn].pending_action == PendingAction.CHOOSE
g.players[g.turn].choose(0)
print(g.players[g.turn].name)
for i in range(1, len(g.players)-1):
assert g.players[(g.turn+i)%7].pending_action == PendingAction.CHOOSE
g.players[(g.turn+i)%7].choose(0)
for p in ps:
assert len(p.hand) == 1
assert g.players[g.turn].pending_action == PendingAction.PLAY
# test Gatling
def test_gatling():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(7)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
# test lose gatling
for p in ps:
p.hand = []
g.players[g.turn].draw('')
g.players[g.turn].hand = [Gatling(0,0), Gatling(0,0)]
g.players[g.turn].play_card(0)
for p in ps:
if p != g.players[g.turn]:
assert p.lives == p.max_lives - 1
# test win gatling
for p in ps:
if p != g.players[g.turn]:
p.hand = [Mancato(0,0)]
g.players[g.turn].play_card(0)
assert g.players[g.turn].pending_action == PendingAction.WAIT
for p in ps:
if p != g.players[g.turn]:
p.respond(0)
assert g.players[g.turn].pending_action == PendingAction.PLAY
for p in ps:
if p != g.players[g.turn]:
assert p.lives == p.max_lives - 1
# test Indiani
def test_indiani():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(7)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
# test lose indiani
for p in ps:
p.hand = []
g.players[g.turn].draw('')
g.players[g.turn].hand = [Indiani(0,0), Indiani(0,0)]
g.players[g.turn].play_card(0)
for p in ps:
if p != g.players[g.turn]:
assert p.lives == p.max_lives - 1
# test win indiani
for p in ps:
if p != g.players[g.turn]:
p.hand = [Bang(0,0)]
g.players[g.turn].play_card(0)
assert g.players[g.turn].pending_action == PendingAction.WAIT
for p in ps:
if p != g.players[g.turn]:
p.respond(0)
assert g.players[g.turn].pending_action == PendingAction.PLAY
for p in ps:
if p != g.players[g.turn]:
assert p.lives == p.max_lives - 1
# test Mancato
def test_mancato():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
for p in ps:
p.hand = [Mancato(0,0)]
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].pending_action == PendingAction.RESPOND
g.players[(g.turn+1)%2].respond(0)
assert g.players[(g.turn+1)%2].lives == g.players[(g.turn+1)%2].max_lives
assert g.players[(g.turn+1)%2].pending_action == PendingAction.WAIT
assert g.players[g.turn].pending_action == PendingAction.PLAY
# test Panico
def test_panico():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].draw('')
g.players[g.turn].hand = [Panico(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
g.players[g.turn].choose(0)
assert len(g.players[g.turn].hand) == 1
assert len(g.deck.scrap_pile) == 1
assert len(g.players[(g.turn+1)%2].hand) == 3
# test Saloon
def test_saloon():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(8)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
for p in ps:
p.lives = randint(p.max_lives-1, p.max_lives)
g.players[g.turn].draw('')
g.players[g.turn].hand = [Saloon(0,0)]
g.players[g.turn].play_card(0)
for p in ps:
assert p.lives == p.max_lives
# test WellsFargo
def test_wells_fargo():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(4)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].draw('')
g.players[g.turn].hand = [WellsFargo(0,0)]
g.players[g.turn].play_card(0)
assert len(g.players[g.turn].hand) == 3

View File

@ -0,0 +1,365 @@
from random import randint
from bang.characters import *
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
from globals import PendingAction
from bang.cards import *
def test_bartcassidy():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 2), BartCassidy()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if isinstance(g.players[g.turn].character, BartCassidy):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[(g.turn+1)%2].hand = []
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
assert len(g.players[(g.turn+1)%2].hand) == 0
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert len(g.players[(g.turn+1)%2].hand) == 1
def test_blackjack():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(1)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [BlackJack()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
g.players[g.turn].hand = []
g.deck.cards.insert(1, Bang(Suit.HEARTS, 1))
g.players[g.turn].draw('')
assert len(g.players[g.turn].hand) == 3
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.deck.cards.insert(1, Bang(Suit.CLUBS, 1))
g.players[g.turn].draw('')
assert len(g.players[g.turn].hand) == 2
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.deck.cards.insert(1, Bang(Suit.DIAMONDS, 1))
g.players[g.turn].draw('')
assert len(g.players[g.turn].hand) == 3
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.deck.cards.insert(1, Bang(Suit.SPADES, 1))
g.players[g.turn].draw('')
assert len(g.players[g.turn].hand) == 2
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
def test_calamityjanet():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 2), CalamityJanet()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if isinstance(g.players[g.turn].character, CalamityJanet):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[(g.turn+1)%2].hand = [Bang(0,0)]
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].pending_action == PendingAction.RESPOND
g.players[(g.turn+1)%2].respond(0)
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Mancato(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].lives == 1
def test_ElGringo():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 2), ElGringo()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if isinstance(g.players[g.turn].character, ElGringo):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[(g.turn+1)%2].hand = []
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0), Bang(0,0)]
assert len(g.players[(g.turn+1)%2].hand) == 0
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert len(g.players[(g.turn+1)%2].hand) == 1
assert len(g.players[g.turn].hand) == 0
def test_JesseJones():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 2), JesseJones()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if not isinstance(g.players[g.turn].character, JesseJones):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[(g.turn+1)%2].hand = [Bang(0,0)]
g.players[g.turn].draw('p1' if g.turn == 0 else 'p0')
g.players[g.turn].hand = [Bang(0,0), Bang(0,0)]
assert len(g.players[(g.turn+1)%2].hand) == 0
assert len(g.players[g.turn].hand) == 2
def test_Jourdonnais():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 2), Jourdonnais()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if isinstance(g.players[g.turn].character, Jourdonnais):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].pending_action == PendingAction.PICK
def test_KitCarlson():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 4), KitCarlson()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if not isinstance(g.players[g.turn].character, KitCarlson):
g.players[g.turn].draw('')
g.players[g.turn].hand = [Mancato(0,0)]
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
assert g.players[g.turn].pending_action == PendingAction.CHOOSE
assert len(g.players[g.turn].available_cards) == 3
g.players[g.turn].choose(0)
assert len(g.players[g.turn].available_cards) == 2
g.players[g.turn].choose(1)
assert g.players[g.turn].pending_action == PendingAction.PLAY
def test_LuckyDuke():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [LuckyDuke(), LuckyDuke()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
g.players[0].equipment = [Prigione(0,0)]
g.players[1].equipment = [Prigione(0,0)]
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
assert g.players[g.turn].pending_action == PendingAction.PICK
g.deck.cards.insert(0, Bang(Suit.SPADES,0))
g.deck.cards.insert(1, Bang(Suit.HEARTS,0))
g.players[g.turn].pick()
assert g.players[g.turn].pending_action == PendingAction.DRAW
def test_PaulRegret():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 2), PaulRegret()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
pls = g.get_visible_players(g.players[0])
assert len(pls) == 1
assert pls[0]['name'] == g.players[1].name
assert pls[0]['dist'] > g.players[0].get_sight()
def test_PedroRamirez():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 4), PedroRamirez()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if not isinstance(g.players[g.turn].character, PedroRamirez):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.deck.scrap_pile.append(Bang(0,0))
g.players[g.turn].hand = []
g.players[g.turn].draw('scrap')
assert len(g.players[g.turn].hand) == 2
assert g.players[g.turn].hand[0].number == 0
assert g.players[g.turn].hand[0].suit == 0
assert isinstance(g.players[g.turn].hand[0], Bang)
def test_RoseDoolan():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 2), RoseDoolan()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
g.players[0].equipment = [Mustang(0,0)]
g.players[0].notify_self()
pls = g.get_visible_players(g.players[1])
print(pls)
assert len(pls) == 1
assert pls[0]['name'] != g.players[1].name
assert pls[0]['dist'] <= g.players[1].get_sight()
def test_SidKetchum():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 4), SidKetchum()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if not isinstance(g.players[g.turn].character, SidKetchum):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
g.players[g.turn].lives = 1
g.players[g.turn].scrap(0)
assert g.players[g.turn].lives == 1
g.players[g.turn].scrap(0)
assert g.players[g.turn].lives == 2
def test_SlabTheKiller():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 4), SlabTheKiller()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if not isinstance(g.players[g.turn].character, SlabTheKiller):
g.players[g.turn].draw('')
g.players[g.turn].hand = [Mancato(0,0)]
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].pending_action == PendingAction.RESPOND
g.players[(g.turn+1)%2].respond(0)
assert g.players[(g.turn+1)%2].pending_action == PendingAction.WAIT
assert g.players[(g.turn+1)%2].lives == 3
def test_SuzyLafayette():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 4), SuzyLafayette()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
g.players[1].hand = []
assert len(g.players[1].hand) == 0
g.players[1].notify_self()
assert len(g.players[1].hand) == 1
g.players[g.turn].end_turn()
def test_VultureSam():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 4), Character('test_char', 4), VultureSam()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if isinstance(g.players[g.turn].character, VultureSam):
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0), Bang(0,0), Bang(0,0), Bang(0,0)]
g.players[g.turn].end_turn()
while not isinstance(g.players[g.turn].character, VultureSam):
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0), Bang(0,0), Bang(0,0), Bang(0,0)]
g.players[g.turn].lives = 0
g.players[g.turn].notify_self()
assert len(g.players[2].hand) == 8
return
def test_WillyTheKid():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
test_chars = [Character('test_char', 4), WillyTheKid()]
for p in ps:
p.available_characters = [test_chars.pop(0)]
p.set_character(p.available_characters[0].name)
if not isinstance(g.players[g.turn].character, WillyTheKid):
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0), Bang(0,0), Bang(0,0)]
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].lives == 3
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].lives == 2
g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name)
assert g.players[(g.turn+1)%2].lives == 1

View File

@ -0,0 +1,37 @@
from tests.dummy_socket import DummySocket
from bang.deck import Deck
from bang.game import Game
def test_card_flip():
g = Game('test')
g.deck = Deck(g)
l = len(g.deck.cards)
assert g.deck.pick_and_scrap() is not None
assert len(g.deck.cards) == l - 1
assert len(g.deck.scrap_pile) == 1
def test_draw():
g = Game('test')
g.deck = Deck(g)
l = len(g.deck.cards)
assert g.deck.draw(True) is not None
assert len(g.deck.cards) == l - 1
assert len(g.deck.scrap_pile) == 0
def test_reshuffle():
g = Game('test')
g.deck = Deck(g)
l = len(g.deck.cards)
for i in range(80):
assert g.deck.pick_and_scrap() is not None
assert len(g.deck.cards) == 79
assert len(g.deck.scrap_pile) == 1
def test_draw_from_scrap():
g = Game('test')
g.deck = Deck(g)
l = len(g.deck.cards)
assert g.deck.pick_and_scrap() is not None
assert g.deck.draw_from_scrap_pile() is not None
assert len(g.deck.cards) == 79
assert len(g.deck.scrap_pile) == 0

View File

@ -0,0 +1,40 @@
from random import randint
from bang.characters import Character
from bang.expansions.dodge_city.cards import *
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
import bang.cards as cs
# test Borraccia
def test_Borraccia():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
borraccia_guy = g.players[g.turn]
borraccia_guy.draw('')
borraccia_guy.lives = 3
borraccia_guy.hand = [Borraccia(0,0)]
assert len(borraccia_guy.hand) == 1
borraccia_guy.play_card(0)
assert len(borraccia_guy.hand) == 0
assert len(borraccia_guy.equipment) == 1
assert not borraccia_guy.equipment[0].can_be_used_now
borraccia_guy.play_card(0)
assert len(borraccia_guy.hand) == 0
assert len(borraccia_guy.equipment) == 1
borraccia_guy.end_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = []
g.players[g.turn].end_turn()
borraccia_guy.draw('')
assert borraccia_guy.equipment[0].can_be_used_now
borraccia_guy.hand = []
borraccia_guy.play_card(0)
assert len(borraccia_guy.equipment) == 0
assert borraccia_guy.lives == 4

View File

@ -0,0 +1,16 @@
class DummySocket():
def __init__(self, sio=None):
self.true_sio = sio
def emit(self, event, data=None, to=None, room=None, skip_sid=None, namespace=None, callback=None, **kwargs):
# print(f'event: {event}, data: {data}, to: {to}, room: {room}')
if self.true_sio and event == 'chat_message':
self.true_sio.emit(event, data, to, room, skip_sid, namespace, callback, **kwargs)
elif event == 'chat_message':
print(f'event: {event}, data: {data}, to: {to}, room: {room}')
return True
def sleep(self, seconds):
return seconds
is_fake = True

103
backend/tests/game_test.py Normal file
View File

@ -0,0 +1,103 @@
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
from bang.roles import *
from bang.cards import *
from globals import PendingAction
from tests import started_game
# test that game can start
def test_game_start():
g = Game("test")
p1 = Player("p1", "p1")
g.add_player(p1)
p2 = Player("p2", "p2")
g.add_player(p2)
p3 = Player("p3", "p3")
g.add_player(p3)
assert p1.role is None
assert p2.role is None
assert p3.role is None
assert not g.started
g.start_game()
assert g.started
assert p1.role is not None
assert p2.role is not None
assert p3.role is not None
assert len(p1.available_characters) == g.characters_to_distribute
assert len(p2.available_characters) == g.characters_to_distribute
assert len(p3.available_characters) == g.characters_to_distribute
p1.set_character(p1.available_characters[0].name)
assert p1.character is not None
p2.set_character(p2.available_characters[0].name)
assert p2.character is not None
p3.set_character(p3.available_characters[0].name)
assert p3.character is not None
assert g.players[g.turn].pending_action == PendingAction.DRAW
# test that dodge_city is added to games with more than 8 players
def test_dodge_city():
g = Game("test")
for i in range(9):
p = Player(f"p{i}", f"p{i}")
g.add_player(p)
assert "dodge_city" in g.expansions
# test that a game with 2 players has only renegade as role
def test_renegade_only():
g = Game("test")
p1 = Player("p1", "p1")
g.add_player(p1)
p2 = Player("p2", "p2")
g.add_player(p2)
g.start_game()
assert isinstance(g.players[0].role, Renegade)
assert isinstance(g.players[1].role, Renegade)
# test that a game with 3 player has Renegade, Vice and Outlaw as roles
def test_renegade_vice_outlaw():
g = Game("test")
for i in range(3):
p = Player(f"p{i}", f"p{i}")
g.add_player(p)
g.start_game()
roles = {p.role.name for p in g.players}
assert len(roles) == 3
# test that a game with 4 players has all roles except the deputy
def test_4_players_roles():
g = Game("test")
for i in range(4):
p = Player(f"p{i}", f"p{i}")
g.add_player(p)
g.start_game()
roles = {p.role.name for p in g.players}
assert len(roles) == 3
# test that a game with 5 players has all roles
def test_5_players_roles():
g = Game("test")
for i in range(5):
p = Player(f"p{i}", f"p{i}")
g.add_player(p)
g.start_game()
roles = {p.role.name for p in g.players}
assert len(roles) == 4
def test_expansions():
started_game(
[
"high_noon",
"dodge_city",
"gold_rush",
"the_valley_of_shadows",
"wild_west_show",
]
)

206
backend/tests/roles_test.py Normal file
View File

@ -0,0 +1,206 @@
from bang.characters import Character
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
from globals import PendingAction
from bang.roles import *
from bang.cards import *
# test that a game with 3 player the deputy kills renegade and wins
def test_3p_deputy_win():
g = Game('test')
for i in range(3):
p = Player(f'p{i}', f'p{i}')
g.add_player(p)
g.start_game()
for p in g.players:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
roles = {g.players[i].role.name:i for i in range(len(g.players))}
print(roles)
assert len(roles) == 3
assert isinstance(g.players[g.turn].role, Vice)
for i in range(3):
g.players[i].lives = 1
g.players[i].hand = []
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, against=g.players[roles['Rinnegato']].name)
assert (hasattr(g.players[g.turn], 'win_status') and g.players[g.turn].win_status)
assert not (hasattr(g.players[roles['Rinnegato']], 'win_status') and g.players[roles['Rinnegato']].win_status)
assert not (hasattr(g.players[roles['Fuorilegge']], 'win_status') and g.players[roles['Fuorilegge']].win_status)
# test that a game with 3 player the renegade kills the outlaw and wins
def test_3p_renegade_win():
g = Game('test')
for i in range(3):
p = Player(f'p{i}', f'p{i}')
g.add_player(p)
g.start_game()
for p in g.players:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
roles = {g.players[i].role.name:i for i in range(len(g.players))}
print(roles)
assert len(roles) == 3
assert isinstance(g.players[g.turn].role, Vice)
for i in range(3):
g.players[i].lives = 1
g.players[i].hand = []
g.turn = roles['Rinnegato']
g.play_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, against=g.players[roles['Fuorilegge']].name)
assert (hasattr(g.players[g.turn], 'win_status') and g.players[g.turn].win_status)
assert not (hasattr(g.players[roles['Vice']], 'win_status') and g.players[roles['Vice']].win_status)
assert not (hasattr(g.players[roles['Fuorilegge']], 'win_status') and g.players[roles['Fuorilegge']].win_status)
# test that a game with 3 player the outlaw kills the deputy and wins
def test_3p_outlaw_win():
g = Game('test')
for i in range(3):
p = Player(f'p{i}', f'p{i}')
g.add_player(p)
g.start_game()
for p in g.players:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
roles = {g.players[i].role.name:i for i in range(len(g.players))}
print(roles)
assert len(roles) == 3
assert isinstance(g.players[g.turn].role, Vice)
for i in range(3):
g.players[i].lives = 1
g.players[i].hand = []
g.turn = roles['Fuorilegge']
g.play_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, against=g.players[roles['Vice']].name)
assert (hasattr(g.players[g.turn], 'win_status') and g.players[g.turn].win_status)
assert not (hasattr(g.players[roles['Vice']], 'win_status') and g.players[roles['Vice']].win_status)
assert not (hasattr(g.players[roles['Rinnegato']], 'win_status') and g.players[roles['Rinnegato']].win_status)
# test that a game with 4 player the outlaw kills the sheriff and win
def test_4p_outlaw_win():
g = Game('test')
for i in range(4):
p = Player(f'p{i}', f'p{i}')
g.add_player(p)
g.start_game()
for p in g.players:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
roles = {g.players[i].role.name:i for i in range(len(g.players))}
print(roles)
assert len(roles) == 3
assert isinstance(g.players[g.turn].role, Sheriff)
for i in range(4):
g.players[i].lives = 1
g.players[i].hand = []
g.turn = roles['Fuorilegge']
g.play_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Bang(0,0)]
g.players[g.turn].play_card(0, against=g.players[roles['Sceriffo']].name)
for i in range(4):
if isinstance(g.players[i].role, Outlaw):
assert (hasattr(g.players[i], 'win_status') and g.players[i].win_status)
else:
assert not (hasattr(g.players[i], 'win_status') and g.players[i].win_status)
# test that a game with 5 player the renegade kills all the other players and wins
def test_5p_renegade_gatling_win():
g = Game('test')
for i in range(5):
p = Player(f'p{i}', f'p{i}')
g.add_player(p)
g.start_game()
for p in g.players:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
roles = {g.players[i].role.name:i for i in range(len(g.players))}
print(roles)
assert len(roles) == 4
assert isinstance(g.players[g.turn].role, Sheriff)
g.players[g.turn].is_my_turn = False
for i in range(len(g.players)):
g.players[i].lives = 1
g.players[i].hand = []
g.turn = roles['Rinnegato']
g.play_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Gatling(0,0)]
g.players[g.turn].play_card(0)
for i in range(len(g.players)):
if isinstance(g.players[i].role, Renegade):
print (g.players[i].role.name, 'win_status:', hasattr(g.players[i], 'win_status') and g.players[i].win_status)
assert (hasattr(g.players[i], 'win_status') and g.players[i].win_status)
else:
print(g.players[i].role.name, 'win_status:', (hasattr(g.players[i], 'win_status') and g.players[i].win_status))
assert not (hasattr(g.players[i], 'win_status') and g.players[i].win_status)
# test that a game with 5 player the renegade kills all the other players and wins
def test_5p_renegade_indiani_win():
g = Game('test')
for i in range(5):
p = Player(f'p{i}', f'p{i}')
g.add_player(p)
g.start_game()
for p in g.players:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
roles = {g.players[i].role.name:i for i in range(len(g.players))}
print(roles)
assert len(roles) == 4
assert isinstance(g.players[g.turn].role, Sheriff)
g.players[g.turn].is_my_turn = False
for i in range(len(g.players)):
g.players[i].lives = 1
g.players[i].hand = []
g.turn = roles['Rinnegato']
g.play_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Indiani(0,0)]
g.players[g.turn].play_card(0)
for i in range(len(g.players)):
if isinstance(g.players[i].role, Renegade):
print (g.players[i].role.name, 'win_status:', hasattr(g.players[i], 'win_status') and g.players[i].win_status)
assert (hasattr(g.players[i], 'win_status') and g.players[i].win_status)
else:
print(g.players[i].role.name, 'win_status:', (hasattr(g.players[i], 'win_status') and g.players[i].win_status))
assert not (hasattr(g.players[i], 'win_status') and g.players[i].win_status)
# test that a game with 5 player the renegade kills the sheriff but it isn't the last alive player and the outlaws wins
def test_5p_outlaw_death_win():
g = Game('test')
for i in range(5):
p = Player(f'p{i}', f'p{i}')
g.add_player(p)
g.start_game()
for p in g.players:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
roles = {g.players[i].role.name:i for i in range(len(g.players))}
print(roles)
assert len(roles) == 4
assert isinstance(g.players[g.turn].role, Sheriff)
g.players[g.turn].is_my_turn = False
for i in range(len(g.players)):
g.players[i].lives = 1
g.players[i].hand = []
g.players[roles['Vice']].lives = 2
g.turn = roles['Rinnegato']
g.play_turn()
g.players[g.turn].draw('')
g.players[g.turn].hand = [Gatling(0,0)]
g.players[g.turn].play_card(0)
for i in range(len(g.players)):
if isinstance(g.players[i].role, Outlaw):
print (g.players[i].role.name, 'win_status:', hasattr(g.players[i], 'win_status') and g.players[i].win_status)
assert (hasattr(g.players[i], 'win_status') and g.players[i].win_status)
assert (hasattr(g.players[i], 'is_dead') and g.players[i].is_dead)
else:
print(g.players[i].role.name, 'win_status:', (hasattr(g.players[i], 'win_status') and g.players[i].win_status))
assert not (hasattr(g.players[i], 'win_status') and g.players[i].win_status)

View File

@ -0,0 +1,24 @@
from tests import started_game, set_events, current_player, next_player, current_player_with_cards
from bang.expansions.fistful_of_cards.card_events import *
import bang.cards as cs
def test_miniera_abbandonata():
g = started_game(['fistful_of_cards'])
set_events(g, [MinieraAbbandonata()])
p = current_player(g)
starting_cards = len(p.hand)
g.deck.scrap_pile = [
cs.Bang(0, 0),
cs.Bang(0, 1),
cs.Bang(0, 2),
cs.Bang(0, 3),
]
p.draw("")
assert len(p.hand) == starting_cards + 2
# check the last two cards are the ones from the scrap pile
assert p.hand[-2].name == cs.Bang(0, 0).name
assert p.hand[-2].number == 3
assert p.hand[-1].name == cs.Bang(0, 0).name
assert p.hand[-1].number == 2

View File

@ -0,0 +1,24 @@
from random import randint
from bang.characters import Character
from bang.expansions.train_robbery.trains import *
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
import bang.cards as cs
from globals import PendingAction
from tests import started_game, set_events, current_player, next_player, current_player_with_cards
def test_cattle_truck():
g = started_game()
g.deck.scrap_pile = [cs.CatBalou(0,1), cs.CatBalou(0,2), cs.CatBalou(0,3)]
p = current_player_with_cards(g, [CattleTruck()])
p.play_card(0)
assert p.pending_action == PendingAction.CHOOSE
p.choose(0)
assert p.pending_action == PendingAction.PLAY
assert len(p.hand) == 1
assert len(g.deck.scrap_pile) == 2

View File

@ -0,0 +1,72 @@
from random import randint
from bang.characters import Character
from bang.expansions.the_valley_of_shadows.characters import *
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
import bang.cards as cs
from globals import PendingAction
# test TucoFranziskaner
def test_TucoFranziskaner():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [TucoFranziskaner()]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p.hand = []
p.draw('')
assert len(p.hand) == 4
p.end_turn()
p = g.players[g.turn]
p.hand = []
p.equipment = [cs.Barile(0,0)]
p.draw('')
assert len(p.hand) == 2
# test ColoradoBill
def test_ColoradoBill():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [ColoradoBill()]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%2]
p.draw('')
p.hand = [cs.Volcanic(0,0), cs.Bang(0,0), cs.Bang(0,0)]
p.play_card(0)
g.deck.cards.insert(0, cs.Bang(cs.Suit.SPADES,0))
g.deck.cards.insert(1, cs.Bang(cs.Suit.HEARTS,0))
p1.hand = [cs.Mancato(0,0)]
p.play_card(0, p1.name)
assert len(p1.hand) == 1
assert p1.lives == 3
p.play_card(0, p1.name)
assert p1.pending_action == PendingAction.RESPOND
# test BlackFlower
def test_BlackFlower():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [BlackFlower()]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p.draw('')
p.hand = [cs.Volcanic(cs.Suit.DIAMONDS,0)]
p.special('')
assert p.pending_action == PendingAction.PLAY
p.hand = [cs.Volcanic(cs.Suit.CLUBS,0)]
p.special('')
assert p.pending_action == PendingAction.CHOOSE

View File

@ -0,0 +1,366 @@
from random import randint
from bang.characters import Character
from bang.expansions.the_valley_of_shadows.cards import *
from bang.deck import Deck
from bang.game import Game
from bang.players import Player
import bang.cards as cs
from globals import PendingAction
from tests import started_game, set_events, current_player, next_player, current_player_with_cards
# test UltimoGiro
def test_ultimo_giro():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
ultimo_giro_guy = g.players[g.turn]
ultimo_giro_guy.draw('')
ultimo_giro_guy.lives = 3
ultimo_giro_guy.hand = [UltimoGiro(0,0)]
assert ultimo_giro_guy.lives == 3
ultimo_giro_guy.play_card(0)
assert ultimo_giro_guy.lives == 4
# test Tomahawk
def test_tomahawk():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(6)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
tomahawk_guy = g.players[g.turn]
tomahawk_guy.draw('')
tomahawk_guy.hand = [Tomahawk(0,0)]
assert len(tomahawk_guy.hand) == 1
tomahawk_guy.play_card(0, g.players[(g.turn+3)%6].name)
assert len(tomahawk_guy.hand) == 1
tomahawk_guy.play_card(0, g.players[(g.turn+1)%6].name)
assert len(tomahawk_guy.hand) == 0
# test Fantasma
def test_fantasma():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
fantasma_guy = g.players[g.turn]
fantasma_guy.lives = 0
fantasma_guy.notify_self()
pl = g.players[g.turn]
pl.draw('')
pl.hand = [Fantasma(0,0)]
pl.play_card(0)
assert pl.pending_action == PendingAction.CHOOSE
assert pl.available_cards[0]['name'] == fantasma_guy.name
pl.choose(0)
assert pl.pending_action == PendingAction.PLAY
assert len(fantasma_guy.equipment) == 1 and isinstance(fantasma_guy.equipment[0], Fantasma)
# test SerpenteASonagli
def test_serpente_a_sonagli():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
serp = g.players[(g.turn+1)%3]
p.draw('')
p.hand = [SerpenteASonagli(0,0)]
assert len(p.hand) == 1
p.play_card(0, serp.name)
assert len(p.hand) == 0
assert len(serp.equipment) == 1 and isinstance(serp.equipment[0], SerpenteASonagli)
p.end_turn()
assert serp.pending_action == PendingAction.PICK
g.deck.cards[0] = Bang(Suit.SPADES, 5)
serp.pick()
assert serp.lives == 3
serp.draw('')
serp.hand = [SerpenteASonagli(0,0)]
serp.play_card(0, g.players[(g.turn+1)%3].name)
assert len(serp.hand) == 0
serp.end_turn()
assert g.players[g.turn].pending_action == PendingAction.PICK
g.deck.cards[0] = Bang(Suit.HEARTS, 5)
g.players[g.turn].pick()
assert g.players[g.turn].lives == 4
# test RitornoDiFiamma
def test_ritorno_di_fiamma():
g = Game('test')
g.expansions = ['the_valley_of_shadows']
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%3]
p.draw('')
p.hand = [Bang(1, 1)]
p1.hand = [RitornoDiFiamma(0,0)]
p.play_card(0, p1.name)
assert len(p.hand) == 0
assert len(p1.hand) == 1
p1.respond(0)
assert len(p1.hand) == 0
assert p.lives == 3
p.end_turn()
assert p1.is_my_turn
p1.draw('')
p1.hand = [Bang(1, 1)]
p.equipment = [cs.Barile(0,0)]
p.hand = [RitornoDiFiamma(0,0)]
p1.play_card(0, p.name)
assert p.pending_action == PendingAction.PICK
g.deck.cards[0] = Bang(Suit.SPADES, 5)
p.pick()
assert p.pending_action == PendingAction.RESPOND
p.respond(0)
assert p1.lives == 3
# test RitornoDiFiamma with gatling
def test_ritorno_di_fiamma_gatling():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
g.expansions = ['the_valley_of_shadows']
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%3]
p2 = g.players[(g.turn+2)%3]
p.draw('')
p.hand = [cs.Gatling(1, 1), Mancato(0,0)]
p1.hand = [RitornoDiFiamma(0,0)]
p2.hand = [Mancato(0,0)]
p.play_card(0)
assert len(p.hand) == 1
assert p1.pending_action == PendingAction.RESPOND
assert p2.pending_action == PendingAction.RESPOND
p1.respond(0)
assert p2.pending_action == PendingAction.RESPOND
assert p.pending_action == PendingAction.WAIT
p2.respond(0)
# end of gatling
assert p.pending_action == PendingAction.RESPOND
p.respond(0)
assert len(p.hand) == 0
assert p.pending_action == PendingAction.PLAY
# test Taglia
def test_taglia():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%3]
p.draw('')
p.hand = [Taglia(0,0), Bang(1, 1)]
p1.hand = []
p.play_card(0, p1.name)
assert len(p.hand) == 1
assert len(p1.equipment) == 1
assert len(p1.hand) == 0
p.play_card(0, p1.name)
assert p1.lives == 3
assert len(p.hand) == 1
# test Bandidos
def test_bandidos():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%3]
p.draw('')
p.hand = [Bandidos(0,0), Bandidos(0,0)]
p.play_card(0)
assert len(p.hand) == 1
assert p.pending_action == PendingAction.WAIT
assert p1.pending_action == PendingAction.CHOOSE
p1.choose(len(p1.hand))
assert p1.lives == 3
assert p.pending_action == PendingAction.PLAY
p.play_card(0)
assert len(p.hand) == 0
assert p.pending_action == PendingAction.WAIT
assert p1.pending_action == PendingAction.CHOOSE
p1.choose(0)
assert p1.pending_action == PendingAction.CHOOSE
p1.choose(0)
assert p1.pending_action == PendingAction.WAIT
assert p.pending_action == PendingAction.PLAY
def test_bandidos_with_gold_rush():
g = Game('test')
g.expansions = ['gold_rush']
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%3]
p.draw('')
p.hand = [Bandidos(0,0), Bandidos(0,0)]
p.play_card(0)
assert len(p.hand) == 1
assert p.pending_action == PendingAction.WAIT
assert p1.pending_action == PendingAction.CHOOSE
p1.choose(len(p1.hand))
assert p1.lives == 3
assert p.pending_action == PendingAction.PLAY
assert p.gold_nuggets == 1
# test Poker
def test_poker():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%3]
p.draw('')
p.hand = [Poker(0,0), Poker(0,0)]
p1.hand = [Bang(1, 1), Bang(2, 2)]
p.play_card(0)
assert len(p.hand) == 1
assert p.pending_action == PendingAction.WAIT
assert p1.pending_action == PendingAction.CHOOSE
p1.choose(0)
assert p.pending_action == PendingAction.PLAY
p.play_card(0)
assert p.pending_action == PendingAction.WAIT
assert p1.pending_action == PendingAction.CHOOSE
p1.choose(0)
assert p.pending_action == PendingAction.CHOOSE
p.choose(0)
assert p1.pending_action == PendingAction.WAIT
assert p.pending_action == PendingAction.PLAY
assert len(p.hand) == 1
# test Tornado
def test_tornado():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn+1)%3]
p.draw('')
p.hand = [Tornado(0,0), Bang(1, 1)]
p1.hand = [Bang(2, 2)]
p.play_card(0)
assert len(p.hand) == 1
assert p.pending_action == PendingAction.CHOOSE
assert p1.pending_action == PendingAction.CHOOSE
p.choose(0)
p1.choose(0)
assert p.pending_action == PendingAction.PLAY
assert len(p.hand) == 2
assert len(p1.hand) == 2
def test_sventagliata():
g = Game('test')
ps = [Player(f'p{i}', f'p{i}') for i in range(3)]
for p in ps:
g.add_player(p)
g.start_game()
for p in ps:
p.available_characters = [Character('test_char', 4)]
p.set_character(p.available_characters[0].name)
p = g.players[g.turn]
p1 = g.players[(g.turn + 1) % 3]
p2 = g.players[(g.turn + 2) % 3]
p.draw('')
p.hand = [Sventagliata('Hearts', 10), Bang('Hearts', 10)]
p1.hand = [Mancato('Spades', 2)]
p2.hand = [Mancato('Clubs', 5)]
# Play Sventagliata
p.play_card(0, against=p1.name)
assert p.pending_action == PendingAction.CHOOSE
assert len(p.available_cards) > 0 # Ensure there are available targets
# Simulate choosing a secondary target
secondary_target = p.available_cards[0]['name']
assert secondary_target != p.name and secondary_target != p1.name # Ensure the secondary target is correct
p.choose(0) # Choose the first available target
assert p.pending_action == PendingAction.WAIT
assert p1.pending_action == PendingAction.RESPOND
# Simulate p1 responding to the Bang
p1.respond(0) # Assuming p1 plays a Mancato card in response
assert p1.pending_action == PendingAction.WAIT
assert p.pending_action == PendingAction.WAIT
p2.respond(0) # Assuming p2 plays a Mancato card in response
assert p2.pending_action == PendingAction.WAIT
assert p.pending_action == PendingAction.PLAY
# check bang cannot be played
assert len(p.hand) == 1
p.play_card(0, against=p2.name)
assert p.pending_action == PendingAction.PLAY
assert len(p.hand) == 1
def test_mira():
g = started_game(['the_valley_of_shadows'])
p = current_player(g)
p.draw('')
p.hand = [Mira(0, 0), Bang(0, 0)]
target = next_player(g)
target.hand = []
target_health = target.lives
p.play_card(0, against=target.name, _with=1)
assert target.lives == target_health - 2

View File

@ -0,0 +1,34 @@
from tests import started_game, set_events, current_player, next_player, current_player_with_cards
from bang.expansions.wild_west_show.characters import *
from bang.cards import Card, Suit
import bang.roles as roles
from globals import PendingAction
# test TerenKill
def test_TerenKill():
g = started_game(['wild_west_show'], 4, TerenKill())
p = current_player_with_cards(g, [])
p.lives = 0
g.deck.cards = [Card(Suit.HEARTS, 'card', 0), Card(Suit.HEARTS, 'card', 0)]
p.notify_self()
assert p.lives == 1
assert len(p.hand) == 1
p.lives = 0
g.deck.cards = [Card(Suit.SPADES, 'card', 0), Card(Suit.HEARTS, 'card', 0)]
p.notify_self()
assert p.lives == 0
# test YoulGrinner
def test_YoulGrinner():
g = started_game(['wild_west_show'], 4, YoulGrinner())
p = current_player(g)
p.hand = []
p.draw('')
assert len(p.hand) == 5
for pl in g.players:
if pl != p:
assert len(pl.hand) == 3

View File

@ -0,0 +1,98 @@
from tests import started_game, set_events, current_player, next_player, current_player_with_cards
from bang.expansions.wild_west_show.card_events import *
from bang.cards import Card, Suit
import bang.roles as roles
from globals import PendingAction
# test Camposanto
def test_camposanto():
g = started_game(['wild_west_show'], 4)
set_events(g, [Camposanto()])
current_player_with_cards(g, []).end_turn()
p = current_player_with_cards(g, [])
p.lives = 0
p.notify_self()
p1 = current_player_with_cards(g, [])
p1.lives = 0
p1.notify_self()
current_player_with_cards(g, []).end_turn()
current_player_with_cards(g, []).end_turn()
assert p.is_my_turn
assert p.lives == 1
current_player_with_cards(g, []).end_turn()
assert p1.is_my_turn
assert p1.lives == 1
# test DarlingValentine
def test_darling_valentine():
g = started_game(['wild_west_show'], 4)
set_events(g, [DarlingValentine()])
p = next_player(g)
hand = p.hand.copy()
current_player_with_cards(g, []).end_turn()
assert hand != current_player(g).hand
# test DorothyRage
# test HelenaZontero
def test_helena_zontero():
g = started_game(['wild_west_show'], 8)
set_events(g, [None, HelenaZontero()])
roles = [p.role.name for p in g.players]
for i in range(len(g.players)-1):
current_player_with_cards(g, []).end_turn()
g.deck.cards = [Card(Suit.HEARTS, 'card', 0)]*5
current_player_with_cards(g, []).end_turn()
roles2 = [p.role.name for p in g.players]
assert roles != roles2
# test LadyRosaDelTexas
def test_LadyRosaDelTexas():
g = started_game(['wild_west_show'], 4)
set_events(g, [LadyRosaDelTexas()])
p = current_player_with_cards(g, [Card(0,'card',0)]*4)
t = g.turn
p.draw('event')
assert g.turn == (t+1)%len(g.players)
# test MissSusanna
def test_miss_suzanna():
g = started_game(['wild_west_show'], 4)
set_events(g, [MissSusanna()])
p = current_player_with_cards(g, [])
p.end_turn()
assert p.lives == 4 # sceriffo 5-1
p = current_player_with_cards(g, [Card(0,'card',0)]*4)
p.play_card(0)
p.play_card(0)
p.play_card(0)
p.end_turn()
assert p.lives == 4
p = current_player_with_cards(g, [])
p.end_turn()
assert p.lives == 3
# test RegolamentoDiConti
def test_RegolamentoDiConti():
g = started_game(['wild_west_show'], 4)
set_events(g, [RegolamentoDiConti()])
p = current_player_with_cards(g, [Card(0,'card',0)]*4)
p.draw('event')
assert p.pending_action == PendingAction.CHOOSE
p.choose(0)
# test WildWestShow
def test_WildWestShow():
g = started_game(['wild_west_show'], 8)
set_events(g, [None, WildWestShow()])
for i in range(len(g.players)):
current_player_with_cards(g, []).end_turn()
for p in g.players:
assert isinstance(p.role, roles.Renegade)

View File

@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

35
frontend/index.html Normal file
View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en" translate="no" class="notranslate" data-build-timestamp-utc="<%= new Date().toISOString() %>">
<head>
<meta name="google" content="notranslate" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<meta name="keywords" content="bang, bang online, bang game, bang multiplayer, bang card game, bang card game online, Bang! card game rules online, play Bang! online, bang online with friends, high noon, dodge city, gold rush"/>
<link rel="icon" href="/favicon.ico">
<meta name="theme-color" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="PewPew!">
<meta name="description" content="Wanna play Bang with your friends but you cannot meet in person? Play Bang! the online multiplayer card game. It includes expansion like Gold Rush, Dodge City, Fistful of Cards and High Noon">
<title>PewPew! The online Bang card game!</title>
<!-- Twitter Card data -->
<meta name="twitter:card" value="Wanna play Bang with your friends but you cannot meet in person? Play Bang! the online multiplayer card game. It includes expansion like Gold Rush, Dodge City, Fistful of Cards and High Noon">
<!-- Open Graph data -->
<meta property="og:title" content="PewPew! The online bang card game!" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://bang.xamin.it/" />
<!-- <meta property="og:image" content="http://example.com/image.jpg" /> -->
<meta property="og:description" content="Wanna play Bang with your friends but you cannot meet in person? Play Bang! the online multiplayer card game. It includes expansion like Gold Rush, Dodge City, Fistful of Cards and High Noon" />
<script type="module" src="/src/main.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but to play Bang! you need JavaScript enabqled. Please enable it to play.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,34 +1,32 @@
{
"name": "frontend",
"name": "bang-frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"serve": "vite",
"build": "vite build",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"
},
"dependencies": {
"core-js": "^3.6.5",
"@datadog/browser-rum": "^4.36.0",
"bang-vue-socket.io": "^4.0.0",
"caniuse-lite": "^1.0.30001470",
"pretty-checkbox-vue": "^1.1.9",
"register-service-worker": "^1.7.1",
"socket.io-client": "^3.0.3",
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.1",
"vue-i18n": "^8.22.2",
"vue-router": "^3.2.0",
"vue-socket.io": "^3.0.10"
"register-service-worker": "^1.7.2",
"vue": "^2.7.16",
"vue-clipboard2": "^0.3.3",
"vue-i18n": "^8.28.2",
"vue-json-viewer": "^2.2.22",
"vue-router": "^3.6.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-pwa": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11",
"workbox-webpack-plugin": "^6.0.2"
"eslint": "^8.36.0",
"eslint-plugin-vue": "^9.10.0",
"vite": "^4.5.3",
"vite-plugin-html": "^3.2.0",
"vite-plugin-pwa": "^0.14.6",
"vite-plugin-vue2": "^2.0.3",
"vue-template-compiler": "^2.7.14"
},
"eslintConfig": {
"root": true,
@ -39,9 +37,6 @@
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.00251 14.9297L0 1.07422H6.14651L8.00251 4.27503L9.84583 1.07422H16L8.00251 14.9297Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 215 B

View File

@ -1,32 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-build-timestamp-utc="<%= new Date().toISOString() %>">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="keywords" content="bang, bang online, bang game, bang multiplayer, bang card game, bang card game online"/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="PewPew!">
<meta name="description" content="Wanna play Bang with your friends but you cannot meet in person? Play Bang! multiplayer online.">
<title>PewPew!</title>
<!-- Twitter Card data -->
<meta name="twitter:card" value="Wanna play Bang with your friends but you cannot meet in person? Play Bang! multiplayer online.">
<!-- Open Graph data -->
<meta property="og:title" content="PewPew!" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://bang.xamin.it/" />
<!-- <meta property="og:image" content="http://example.com/image.jpg" /> -->
<meta property="og:description" content="Wanna play Bang with your friends but you cannot meet in person? Play Bang! multiplayer online." />
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,2 +1,2 @@
User-agent: *
Disallow:
Allow: /

View File

@ -1,18 +1,35 @@
<template>
<div id="app" class="dark-mode">
<div id="app">
<div v-if="isConnected">
<router-view></router-view>
</div>
<div v-else class="center-stuff">
<h2>{{$t("warning")}}</h2>
<p>{{$t("connection_error")}}</p>
<ul v-if="shouldShowBackendSuggestions">
Connect to one of these backends:
<li v-for="suggestion in backendSuggestions" :key="suggestion.name" @click="changeBackend(suggestion)">
{{suggestion.name}}
</li>
</ul>
</div>
<help v-if="showHelp"/>
<div style="position:fixed;bottom:4pt;right:4pt;display:flex;">
<input type="button" :value="(showHelp?'X':'?')" style="min-width:28pt;border-radius:100%;cursor:pointer;" @click="getHelp"/>
<select id="lang" v-model="$i18n.locale" @change="storeLangPref">
<help :inGame="true" v-if="showHelp"/>
<div style="position:fixed;bottom:4pt;right:4pt;display:flex;z-index:10">
<input v-if="connect_dev" type=button class="btn" style="min-width:28pt;cursor:pointer;" @click="resetConnection" :value="'💚'+connect_dev" />
<input type=button class="btn" style="min-width:28pt;cursor:pointer;" @click="()=>{sending_report = true}" :value=" $t('report') " />
<input type="button" class="btn" value="" style="min-width:28pt;cursor:pointer;background-position:center;background-image:url('https://img.icons8.com/color/48/discord-logo.png');background-size:1.5em;background-repeat: no-repeat;" @click="joinDiscord"/>
<input type="button" class="btn" :value="(showHelp?'X':'?')" style="min-width:28pt;border-radius:100%;cursor:pointer;" @click="getHelp"/>
<select id="theme" class="btn" v-model="theme">
<option
v-for="(lang, i) in ['it.🇮🇹.Italiano', 'en.🇬🇧.English']"
v-for="(theme, i) in ['light.☀️', 'dark.🌙️', 'sepia.🌇️', 'grayscale.📰️', 'black.⬛']"
:key="`theme-${i}`"
:value="theme.split('.')[0]">
{{theme.split('.')[1]}} {{$t(`theme.${theme.split('.')[0]}`)}}
</option>
</select>
<select id="lang" class="btn" v-model="$i18n.locale" @change="storeLangPref">
<option
v-for="(lang, i) in ['it.🇮🇹.Italiano', 'en.🇬🇧.English', 'cs.🇨🇿.Čeština', 'fr.🇫🇷.Français', 'es.🇪🇸.Español', 'ru.🇷🇺.Русский']"
:key="`lang-${i}`"
:value="lang.split('.')[0]">
{{lang.split('.')[1]}} {{lang.split('.')[2]}}
@ -29,23 +46,41 @@
<button @click="showUpdateUI = false">Cancel</button>
</div>
</div>
<transition name="bounce">
<full-screen-input v-if="sending_report" :defaultValue="''" :text="$t('report_bug')" :val="report" :cancel="cancelReport" :send="sendReport" :canCancel="true"/>
</transition>
</div>
</template>
<script>
import FullScreenInput from './components/FullScreenInput.vue'
import Help from './components/Help.vue';
// import Vue from 'vue'
import Vue from 'vue'
import { datadogRum } from '@datadog/browser-rum';
export default {
components: { Help },
components: { Help, FullScreenInput },
name: 'App',
data: () => ({
isConnected: false,
c: false,
registration: null,
showUpdateUI: false,
showHelp:false,
theme: 'light',
report: '',
sending_report: false,
connect_dev: undefined,
backendSuggestions: [
{ name: 'Bang Xamin', url: 'https://bang.xamin.it' },
{ name: 'Bang Miga', url: 'https://bang.migani.synology.me/' },
{ name: 'Localhost', url: 'http://localhost:5001' },
],
}),
computed: {
shouldShowBackendSuggestions() {
return window.location.origin.indexOf('vercel') !== -1 || window.location.origin.indexOf('localhost') !== -1
},
},
sockets: {
connect() {
@ -69,18 +104,99 @@ export default {
// window.open(`${window.location.origin}/help`, '_blank')
},
storeLangPref() {
localStorage.setItem('lang', this.$i18n.locale)
localStorage.setItem('lang', this.$i18n.locale);
document.documentElement.lang = this.$i18n.locale;
},
async update() {
update() {
this.showUpdateUI = false;
await this.$workbox.messageSW({ type: "SKIP_WAITING" });
// Make sure we only send a 'skip waiting' message if the SW is waiting
if (!this.registration || !this.registration.waiting) return
// Send message to SW to skip the waiting and activate the new SW
this.registration.waiting.postMessage({ type: 'SKIP_WAITING' })
},
changeBackend(suggestion) {
this.$socket.disconnect();
window.localStorage.setItem('connect-dev', suggestion.url);
window.location.reload();
},
resetConnection() {
this.$socket.disconnect();
window.localStorage.removeItem('connect-dev');
window.navigation.reload();
},
detectColorScheme() {
if(localStorage.getItem("theme")){
this.theme = localStorage.getItem("theme")
console.log("Found theme preference: " + this.theme)
} else if(!window.matchMedia) {
console.log("Auto theme not supported")
} else if(window.matchMedia("(prefers-color-scheme: dark)").matches) {
console.log("Prefers dark mode")
this.theme = "dark";
}
var style = getComputedStyle(document.body);
document.querySelector("meta[name='theme-color']").setAttribute("content", style.getPropertyValue('--bg-color'));
},
joinDiscord() {
window.open('https://discord.gg/Dr58dZ2na8', '_blank');
},
cancelReport(){
this.sending_report = false
},
sendReport(text){
if (text.trim().length > 0){
this.sending_report = false
this.$socket.emit('report', text)
}
},
updateAvailable(event) {
this.registration = event.detail
this.showUpdateUI = true
}
},
watch: {
theme() {
document.documentElement.setAttribute("data-theme", this.theme);
localStorage.setItem('theme', this.theme);
var style = getComputedStyle(document.body);
document.querySelector("meta[name='theme-color']").setAttribute("content", style.getPropertyValue('--bg-color'));
}
},
mounted() {
if (localStorage.getItem('lang'))
this.$i18n.locale = localStorage.getItem('lang')
if (localStorage.getItem('lang')) {
this.$i18n.locale = localStorage.getItem('lang');
document.documentElement.lang = this.$i18n.locale;
} else {
let userLang = navigator.language || navigator.userLanguage;
if (['it', 'en'].indexOf(userLang) == -1)
userLang = 'en';
this.$i18n.locale = userLang.split('-')[0]
}
if (window.localStorage.getItem('connect-dev')) {
this.connect_dev = window.localStorage.getItem('connect-dev')
}
this.detectColorScheme()
if (window.location.origin.indexOf('localhost') !== -1) return;
datadogRum.init({
applicationId: '076b1a5e-16a9-44eb-b320-27afd32c57a5',
clientToken: 'pub1cc4d0d6ea0a7235aa1eab86e7a192d4',
site: 'datadoghq.com',
version: document.getElementsByTagName("html")[0].getAttribute("data-build-timestamp-utc").replace(/[-|:|T]/g,'.').substring(0,16),
service:'bang-frontend',
sessionSampleRate: 100,
sessionReplaySampleRate: 100,
trackUserInteractions: true,
trackResources: true, //non so cosa faccia, proviamo
trackLongTasks: true, //non so cosa faccia, proviamo
defaultPrivacyLevel: 'allow',
enableExperimentalFeatures: ['clickmap'],
proxyUrl: (Vue.config.devtools ? `http://${window.location.hostname}:5001` : window.location.origin) + '/ddproxy',
});
datadogRum.setUser({name: localStorage.getItem('username')})
datadogRum.startSessionReplayRecording();
},
created() {
document.addEventListener('swUpdated', this.updateAvailable, { once: true })
if (this.$workbox) {
this.$workbox.addEventListener("waiting", () => {
this.showUpdateUI = true;
@ -119,7 +235,14 @@ html {
#app {
margin: 4pt;
margin-top: -16pt;
zoom: 0.8;
zoom: 0.75;
}
#lang,#theme{
max-width: 26pt;
min-width: 0;
padding: 0;
padding-left: 4px;
word-spacing: 20pt;
}
}
h1,h2,h3,h4,p,span,b,label{
@ -188,10 +311,50 @@ input, select {
input:disabled {
opacity: 0.5;
}
@media (prefers-color-scheme: dark) {
:root, #app, input, select {
background-color: #181a1b;
color: rgb(174, 194, 211);
}
:root {
--font-color: #2c3e50;
--bg-color: white;
--muted-color: #ccc;
}
[data-theme="dark"] {
--font-color: rgb(174, 194, 211);
--bg-color: #181a1b;
}
[data-theme="black"] {
--font-color: rgb(174, 194, 211);
--bg-color: #000000;
}
[data-theme="sepia"] {
--font-color: rgb(54, 43, 33);
--bg-color: #e7d6bb;
--muted-color: rgba(54, 43, 33, 0.5);
}
[data-theme="grayscale"] {
--font-color: rgb(66, 66, 66);
--bg-color: #e2e0e0;
--muted-color: rgba(66, 66, 66, 0.5);
}
html, #app, input, select {
background-color: var(--bg-color);
color: var(--font-color);
}
.btn {
background-color: var(--bg-color);
color: var(--font-color);
border: 2px solid var(--font-color);
border-radius: 12pt;
cursor: pointer;
transition: all 0.13s ease-in-out;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.btn:hover:not([disabled]) {
background-color: var(--font-color); /* Green */
color: var(--bg-color);
}
.btn:disabled {
cursor: not-allowed;
}
</style>

Binary file not shown.

View File

@ -0,0 +1,53 @@
<template>
<Card v-if="card" :card="card" :class="{back:card.back}" :style="style"/>
</template>
<script>
import Card from '@/components/Card.vue'
export default {
name: 'AnimatedCard',
components: {
Card,
},
props: {
card: Object,
startPosition: Object,
midPosition: Object,
endPosition: Object,
},
data: () => ({
style: ''
}),
computed: {
},
methods: {
},
mounted() {
this.style = `position: absolute;top:${this.startPosition.top}px;left: ${this.startPosition.left}px`
if (this.midPosition) {
setTimeout(() => {
this.style = `position: absolute;top:${this.midPosition.top}px;left: ${this.midPosition.left}px;transform: scale(0.5);`
}, 200)
setTimeout(() => {
this.style = `position: absolute;top:${this.endPosition.top}px;left: ${this.endPosition.left}px;transform: scale(0.5);`
}, 800)
}
else {
setTimeout(() => {
this.style = `position: absolute;top:${this.endPosition.top}px;left: ${this.endPosition.left}px;transform: scale(0.5);`
}, 200)
}
setTimeout(() => {
this.style = `display:none;`
}, this.midPosition ? 1600 : 800)
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.card {
position: absolute;
}
</style>

View File

@ -0,0 +1,49 @@
<template>
<p class="animated" :style="style">{{text}}</p>
</template>
<script>
export default {
name: 'AnimatedEffect',
props: {
text: String,
startPosition: Object,
},
data: () => ({
style: ''
}),
computed: {
},
methods: {
},
mounted() {
let startPosition = {
top: this.startPosition.top + Math.random() * 100 - 50,
left: this.startPosition.left + Math.random() * 100 - 25,
}
let endPosition = {
top: startPosition.top + Math.random() * 50 - 25,
left: startPosition.left + Math.random() * 50 - 25,
}
this.style = `position: absolute;top:${startPosition.top}px;left: ${startPosition.left}px;`
setTimeout(() => {
this.style = `position:absolute;;top:${endPosition.top}px;left:${endPosition.left}px;`
}, 400)
setTimeout(() => {
this.style = `position:absolute;;top:${endPosition.top}px;left:${endPosition.left}px;opacity:0;`
}, 900)
setTimeout(() => {
this.style = `display:none;`
}, 1500)
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.animated {
position: absolute;
font-size: 26pt;
transition: all 0.5s;
}
</style>

View File

@ -1,199 +1,384 @@
<template>
<div :class="{ card: true, equipment: card.is_equipment, character:card.is_character, back:card.is_back, 'usable-next-turn':card.usable_next_turn}">
<h4>{{cardName}}</h4>
<div class="emoji">{{card.icon}}</div>
<div class="alt_text">{{card.alt_text}}</div>
<div class="suit">{{number}}{{suit}}</div>
<div class="expansion" v-if="card.expansion_icon">{{card.expansion_icon}}</div>
</div>
<div
:class="{
card: true,
avatarred: card.avatar,
equipment: card.is_equipment,
character: card.is_character,
back: card.is_back,
'usable-next-turn': card.usable_next_turn,
'must-be-used': card.must_be_used,
'gold-rush': card.expansion === 'gold_rush',
brown: card.kind === 0,
black: card.kind === 1,
'train-piece': card.type && card.type === 'train',
}"
>
<h4>{{ cardName }}</h4>
<div
v-if="card.avatar"
class="avatar"
:style="`background-image: url(${card.avatar});`"
></div>
<div :class="{ emoji: true, bottomed: card.avatar }">{{ emoji }}</div>
<div v-if="card.isMe" :class="{ emoji: true, bottomed: card.avatar, isMe: true }"></div>
<div class="alt_text">{{ card.alt_text }}</div>
<div class="suit">
{{ number
}}<span
:style="`${
card.suit !== undefined && card.suit % 2 === 0 ? 'color:red' : ''
}`"
>{{ suit }}</span
>
</div>
<div class="expansion" v-if="card.expansion_icon">
{{ card.expansion_icon }}
</div>
</div>
</template>
<script>
export default {
name: 'Card',
props: {
card: Object,
donotlocalize: Boolean
},
computed: {
cardName(){
// console.log(this.$t(`cards.${this.card.name}.name`))
if (!this.donotlocalize && this.$t(`cards.${this.card.name}.name`) !== `cards.${this.card.name}.name`) {
return this.$t(`cards.${this.card.name}.name`)
}
return this.card.name
},
suit() {
if (this.card && !isNaN(this.card.suit)) {
let x = ['♦️','♣️','♥️','♠️']
return x[this.card.suit];
}
return '';
},
number() {
if (this.card.number === 1) return 'A'
else if (this.card.number === 11) return 'J'
else if (this.card.number === 12) return 'Q'
else if (this.card.number === 13) return 'K'
else return this.card.number
}
}
}
name: "Card",
props: {
card: Object,
donotlocalize: Boolean,
},
computed: {
cardName() {
// console.log(this.$t(`cards.${this.card.name}.name`))
if (
!this.donotlocalize &&
this.$t(`cards.${this.card.name}.name`) !==
`cards.${this.card.name}.name`
) {
return this.$t(`cards.${this.card.name}.name`);
}
if (this.card.name == "you") {
return this.$t("you");
}
return this.card.name;
},
emoji() {
return this.card.icon != "you" ? this.card.icon : this.$t("you");
},
suit() {
if (this.card && !isNaN(this.card.suit)) {
let x = ["♦️", "♣️", "♥️", "♠️", "🤑", "🚂"];
return x[this.card.suit];
} else if (this.card.suit) {
return this.card.suit;
}
return "";
},
number() {
if (isNaN(this.card.suit)) return this.card.number;
if (this.card.number === 1) return "A";
else if (this.card.number === 11) return "J";
else if (this.card.number === 12) return "Q";
else if (this.card.number === 13) return "K";
else return this.card.number;
},
},
};
</script>
<style>
.card {
cursor: pointer;
width: 60pt;
min-width:60pt;
height: 100pt;
margin: 12pt;
background: white;
box-shadow:
0 0 0 3pt #987e51,
0 0 0 6pt white,
0 0 5pt 6pt #aaa;
border-radius: 6pt;
position: relative;
transition: all 0.5s ease-in-out;
color: #333;
/* overflow: hidden; */
text-overflow: ellipsis;
word-wrap: normal;
/* word-wrap: break-word; */
cursor: pointer;
width: 60pt;
min-width: 60pt;
height: 100pt;
margin: 12pt;
background: var(--bg-color);
box-shadow: 0 0 0 3pt #987e51, 0 0 0 6pt var(--bg-color), 0 0 5pt 6pt #aaa;
border-radius: 6pt;
position: relative;
transition: all 0.5s ease-in-out;
color: var(--font-color);
text-overflow: ellipsis;
word-wrap: normal;
}
.card.back{
color:white;
background: repeating-linear-gradient(
45deg,
#987e51,
#987e51 5px,
#816b45 5px,
#816b45 10px
);
.avatarred {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
.card.back {
color: white;
background: repeating-linear-gradient(
45deg,
#987e51,
#987e51 5px,
#816b45 5px,
#816b45 10px
);
}
.card:not(.back, .fistful-of-cards, .high-noon, .gold-rush, .train-piece):before {
content: "";
background-image: radial-gradient(var(--bg-color) 13%, #0000 5%),
radial-gradient(var(--bg-color) 14%, transparent 5%),
radial-gradient(var(--bg-color) 8%, transparent 5%);
background-position: -12px 0, 12px 14px, 0 -12pt;
background-size: 50px 50px;
position: absolute;
top: -10px;
left: -10px;
bottom: -4px;
right: -4px;
}
.card.equipment {
box-shadow:
0 0 0 3pt #5c5e83,
0 0 0 6pt white,
0 0 5pt 6pt #aaa;
box-shadow: 0 0 0 3pt #5c5e83, 0 0 0 6pt var(--bg-color), 0 0 5pt 6pt #aaa;
}
.card.character {
box-shadow:
0 0 0 3pt #7c795b,
0 0 0 6pt white,
0 0 5pt 6pt #aaa;
box-shadow: 0 0 0 3pt #7c795b, 0 0 0 6pt var(--bg-color), 0 0 5pt 6pt #aaa;
}
.card.usable-next-turn {
box-shadow:
0 0 0 3pt #6aa16e, 0 0 0 6pt white, 0 0 5pt 6pt #aaa
box-shadow: 0 0 0 3pt #6aa16e, 0 0 0 6pt var(--bg-color), 0 0 5pt 6pt #aaa;
}
.card.high-noon{
box-shadow: 0 0 0pt 4pt white, 0 0 5pt 4pt #aaa;
border: 2pt dotted rgb(198 78 45);
.card.wild-west-show {
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
border: 2pt dotted #987e51;
}
.card.fistful-of-cards{
box-shadow: 0 0 0pt 4pt white, 0 0 5pt 4pt #aaa;
border: 2pt dashed rgb(50 122 172);
.card.high-noon {
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
border: 2pt dotted rgb(198 78 45);
}
.card.back.fistful-of-cards{
color:white;
background: repeating-linear-gradient(
45deg,
rgb(50 122 172),
rgb(50 122 172) 5px,
rgb(30 102 152) 5px,
rgb(30 102 152) 10px
);
border: 2pt solid rgb(50 122 172);
.card.fistful-of-cards {
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
border: 2pt dashed rgb(50 122 172);
}
.card.back.fistful-of-cards {
background: repeating-linear-gradient(
45deg,
rgb(50 122 172),
rgb(50 122 172) 5px,
rgb(30 102 152) 5px,
rgb(30 102 152) 10px
);
border: 2pt solid rgb(50 122 172);
}
.card.back.high-noon {
background: repeating-linear-gradient(
45deg,
rgb(198 78 45),
rgb(198 78 45) 5px,
rgb(178 58 25) 5px,
rgb(178 58 25) 10px
);
border: 2pt solid rgb(198 78 45);
}
.card.back.the-valley-of-shadows {
background: repeating-linear-gradient(
45deg,
rgb(98 88 85),
rgb(98 88 85) 5px,
rgb(78 68 65) 5px,
rgb(78 68 65) 10px
);
border: 2pt solid rgb(98 88 85);
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
}
.card.back.wild-west-show {
color: white;
background: repeating-linear-gradient(
90deg,
#816b45,
#816b45 3px,
#987e51 3px,
#987e51 6px
);
border: 2pt solid #987e51;
}
.card.back.dodge-city {
color: white;
border: 2pt solid #987e51;
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
}
.card.back.cant-play {
transform: scale(0.9);
filter: grayscale(1);
opacity: 0.5;
}
.card.back.cant-play:hover {
transform: scale(0.95);
filter: grayscale(0.6);
opacity: 0.8;
}
.beta::after {
content: "Beta";
position: absolute;
bottom: -12pt;
right: -12pt;
background: red;
font-size: 10pt;
color: white;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-weight: bold;
padding: 4pt;
border-radius: 12pt;
}
.alpha::after {
content: "Alpha";
position: absolute;
bottom: -12pt;
right: -12pt;
background: red;
font-size: 10pt;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-weight: bold;
padding: 4pt;
border-radius: 12pt;
}
.wip::after {
content: "WIP";
position: absolute;
bottom: -12pt;
right: -12pt;
background: red;
font-size: 10pt;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-weight: bold;
padding: 4pt;
border-radius: 12pt;
}
.avatar {
position: absolute;
width: 36pt;
margin: auto;
top: 25%;
background-position: center;
background-size: contain;
background-repeat: no-repeat;
border-radius: 36pt;
height: 36pt;
}
.card.brown.gold-rush {
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
border: 2pt dotted #9c7340;
}
.card.black.gold-rush {
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
border: 2pt dotted #000;
}
.card.back.gold-rush {
border: 2pt solid #987e51;
box-shadow: 0 0 0pt 4pt var(--bg-color), 0 0 5pt 4pt #aaa;
background: repeating-linear-gradient(347deg, #ffb32f, #987e51);
}
.card h4 {
position: absolute;
text-align: center;
width: 100%;
top: -10pt;
font-size: 11pt;
position: absolute;
text-align: center;
width: 100%;
top: -10pt;
font-size: 11pt;
}
.card.back h4 {
font-size: 12pt;
}
.card .emoji {
position: absolute;
text-align: center;
width: 100%;
font-size:26pt;
top: 35%;
position: absolute;
text-align: center;
width: 100%;
font-size: 26pt;
top: 35%;
}
.fistful-of-cards .emoji, .high-noon .emoji{
top:auto !important;
bottom:15% !important;
.card .emoji.isMe {
position: absolute;
text-align: center;
width: 100%;
font-size: 16pt;
top: 52%;
right: 12pt;
}
.emoji.isMe::after {
content: "🫵";
display: block;
}
.card:HOVER .isMe::after {
content: "👋";
animation: wave 0.5s infinite;
will-change: transform;
}
@keyframes wave {
0% {
transform: translate(-5px, 0px) rotate(0deg);
}
50% {
transform: translate(-5px, -5px) rotate(25deg);
}
100% {
transform: translate(-5px, 0) rotate(0deg);
}
}
.emoji.bottomed {
top: 45%;
left: 8pt;
}
.emoji.bottomed.emoji.isMe {
top: 60%;
left: -5pt;
}
.card.must-be-used {
filter: drop-shadow(0 0 5px red);
}
.fistful-of-cards .emoji,
.high-noon .emoji,
.card.wild-west-show .emoji,
.exp-pack .emoji {
top: auto !important;
bottom: 15% !important;
}
.card .suit {
position: absolute;
bottom: 3pt;
left:3pt;
position: absolute;
bottom: 3pt;
left: 3pt;
}
.card.character .suit {
font-size: x-small;
right: 3pt;
text-align: center;
font-size: small;
right: 3pt;
text-align: center;
}
.alt_text {
right: 3pt;
text-align: center;
position: absolute;
font-size: small;
bottom: 20pt;
left: 3pt;
right: 3pt;
text-align: center;
position: absolute;
font-size: small;
bottom: 20pt;
left: 3pt;
}
.cant-play {
filter: brightness(0.5);
filter: brightness(0.5);
cursor: not-allowed;
}
.expansion {
position: absolute;
bottom: -5pt;
right: -5pt;
background: white;
border-radius: 100%;
transform: scale(0.8);
position: absolute;
bottom: -5pt;
right: -5pt;
background: var(--bg-color);
border-radius: 100%;
transform: scale(0.8);
}
@media (prefers-color-scheme: dark) {
.expansion {
background: #181a1b;
}
:root, #app {
background-color: #181a1b;
color: rgb(174, 194, 211);
}
.card {
background-color: #181a1b;
color: rgb(174, 194, 211);
box-shadow:
0 0 0 3pt #987e51,
0 0 0 6pt #181a1b,
0 0 5pt 6pt #aaa;
}
.card.back{
color:#181a1b;
}
.card.equipment {
box-shadow:
0 0 0 3pt #5c5e83,
0 0 0 6pt #181a1b,
0 0 5pt 6pt #aaa;
}
.card.character {
box-shadow:
0 0 0 3pt #7c795b,
0 0 0 6pt #181a1b,
0 0 5pt 6pt #aaa;
}
.card.usable-next-turn {
box-shadow:
0 0 0 3pt #6aa16e, 0 0 0 6pt #181a1b, 0 0 5pt 6pt #aaa
}
.card.high-noon{
box-shadow: 0 0 0pt 4pt #181a1b, 0 0 5pt 4pt #aaa;
}
.card.fistful-of-cards{
box-shadow: 0 0 0pt 4pt #181a1b, 0 0 5pt 4pt #aaa;
}
.train-piece {
background: linear-gradient(180deg, rgba(218,101,64,1) 0%, rgba(217,197,184,1) 13%, rgba(217,197,184,1) 53%, rgba(235,169,95,1) 61%, rgba(158,81,55,1) 91%, rgba(158,81,55,1) 100%);
box-shadow: 0 0 0pt 2pt var(--font-color), 0 0 5pt 2pt #aaa;
}
.train-piece .emoji {
transform: scaleX(-1);
/* filter: grayscale(1); */
}
.train-piece .suit, .train-piece .expansion {
display: none;
}
.train-piece h4 {
position: absolute;
text-align: center;
width: 100%;
bottom: -10pt;
top: unset;
font-size: 11pt;
color: #FFE27E;
}
</style>

View File

@ -1,17 +1,34 @@
<template>
<div class="chat">
<h4 v-if="spectators > 0">{{$tc("chat.spectators", spectators)}}</h4>
<h3>{{$t("chat.chat")}}</h3>
<transition-group name="message" tag="div" id="chatbox">
<!-- <div id="chatbox"> -->
<p style="margin:1pt;" class="chat-message" v-for="(msg, i) in messages" v-bind:key="`${i}-c`" :style="`color:${msg.color}`">{{msg.text}}</p>
<p class="end" key="end" style="color:#0000">.</p>
<!-- </div> -->
<div :class="{chat:true, chat_spectators:spectators > 0}" :style="`${collapsed?'min-width:0':''}`">
<div class="chat-header">
<div style="display:flex;align-items: center;max-height: 20pt;">
<h3>{{$t("chat.chat")}}</h3>
<button class="btn" @click="collapsed = !collapsed" style="max-height:20pt;">{{collapsed?">>":"X"}}</button>
</div>
<h4 v-if="spectators > 0" style="margin:0">{{$tc("chat.spectators", spectators)}}</h4>
</div>
<div :class="{cont:true, cont_spectators:spectators > 0}">
<transition-group name="message" tag="div" id="chatbox" :style="`${collapsed?'display:none':''}`">
<p style="margin:1pt;" class="chat-message" v-for="(msg, i) in messages" v-bind:key="`${i}-c`" :style="`color:${msg.color};background:${msg.bgcolor}${msg.bgcolor?';border-left: medium solid '+msg.color+';padding-left:2pt;':''}`">
<JsonViewer v-if="msg.type == 'json'" :value="msg.json"/>
<span v-else-if="msg.parts" v-for="(part, i) in msg.parts" v-bind:key="`${i}-p`" :style="`${i%2!=0?'font-weight: bold;':''}${part.desc?'text-decoration: dotted underline':''}`" class="msg-part" :title="part.desc">{{part.text}}</span>
<span v-else class="msg-text">{{msg.text}}</span>
</p>
<p class="end" key="end" style="color:#0000">.</p>
</transition-group>
<div v-if="commandSuggestion.length > 0">
<p style="margin:1pt 15pt;cursor:pointer;" class="chat-message" v-for="(msg, i) in commandSuggestion" v-bind:key="`${i}-c`" :style="`color:orange`"
@click="fillCmd(msg.cmd)">{{msg.cmd}} <i class="std-text" style="font-size:8pt;">{{msg.help}}</i></p>
</div>
<form @submit="sendChatMessage" id="msg-form">
<input id="my-msg" autocomplete="off" v-model="text" style="flex-grow:2;"
@keydown.tab.prevent="tabComplete($event.target.value)"/>
<input id="submit-message" type="submit" class="btn" :value="$t('submit')"/>
</form>
</div>
<transition-group name="message" tag="div" id="toast-chatbox">
<p style="margin:1pt;" class="chat-message" v-for="msg in toasts" v-bind:key="`${msg.text}-c`" :style="`width:fit-content;color:${msg.color};background:${msg.bgcolor}${msg.bgcolor?';border-left: medium solid '+msg.color+';padding-left:2pt;padding-right:4pt;':''}`">{{msg.text}}</p>
</transition-group>
<form @submit="sendChatMessage" id="msg-form">
<input v-model="text" style="flex-grow:2;"/>
<input type="submit" :value="$t('submit')"/>
</form>
</div>
</template>
@ -22,26 +39,61 @@ import dynamite_sfx from '@/assets/sounds/dynamite.mp3'
import prison_sfx from '@/assets/sounds/prison.mp3'
import turn_sfx from '@/assets/sounds/turn.mp3'
import death_sfx from '@/assets/sounds/death.mp3'
import cash_sfx from '@/assets/sounds/cash.mp3'
import JsonViewer from 'vue-json-viewer'
export default {
name: 'Chat',
props: {
username: String
},
components: {
JsonViewer
},
data: () => ({
messages: [],
toasts: [],
text: '',
spectators: 0,
commands: [{cmd:'/debug', help:'Toggles the debug mode'}],
collapsed: false,
}),
computed: {
commandSuggestion() {
this.text;
if (this.text.length < 1) {
return [];
}
return this.commands.filter(x => x.cmd.slice(0, this.text.length) == this.text);
},
},
sockets: {
chat_message(msg) {
// console.log(msg)
if ((typeof msg === "string") && msg.indexOf('_') === 0) {
if ((typeof msg === "string" && msg.indexOf('_') === 0) || (msg.color != null && msg.text.indexOf('_') === 0)) {
let t_color = null
let bg_color = null
if (msg.color != null) {
t_color = msg.color
bg_color = msg.bgcolor
msg = msg.text
}
let desc = undefined
let desc_pos = -1
let params = msg.split('|')
let type = params.shift().substring(1)
if (["flipped", "respond", "play_card", "play_card_against", "play_card_for", "spilled_beer", "diligenza", "wellsfargo", "saloon", "special_calamity"].indexOf(type) !== -1){
if (["flipped", "scrapped", "respond", "play_card", "play_card_green", "play_card_with", "purchase_card", "play_card_against", "play_card_against_with", "play_card_for", "spilled_beer", "diligenza", "wellsfargo", "saloon", "special_calamity", "won", "choose_emporio", "died_role"].indexOf(type) !== -1) {
if (type.indexOf("_with") !== -1) {
params[params.length - 1] = this.$t(`cards.${params[params.length - 1]}.name`)
}
desc = this.$t(`cards.${params[1]}.desc`)
desc_pos = 3
params[1] = this.$t(`cards.${params[1]}.name`)
} else if (type === "choose_character"){
params.push(this.$t(`cards.${params[1]}.desc`))
} else if (type === "flip_event"){
desc = this.$t(`cards.${params[0]}.desc`)
params[0] = this.$t(`cards.${params[0]}.name`);
desc_pos = 1
} else if (type === "allroles") {
params.forEach((p,i)=>{
if (i%2 === 0) {
@ -54,27 +106,44 @@ export default {
type += "4"
}
}
this.messages.push({text:this.$t(`chat.${type}`, params)});
if (type == 'turn' && params[0] == this.username) {
(new Audio(turn_sfx)).play();
} else if (type == 'died_role') {
(new Audio(death_sfx)).play();
} else if (type == 'explode') {
(new Audio(dynamite_sfx)).play();
} else if (type == 'prison_turn') {
(new Audio(prison_sfx)).play();
let parts = this.$t(`chat.${type}`, params).split(';').map((x, i)=>({text:x, desc:(i===desc_pos&&desc?desc:null)}))
if (t_color != null) {
this.messages.push({color:t_color, bgcolor: bg_color, text:false, parts: parts})
} else {
(new Audio(notification_sfx)).play();
this.messages.push({text:false, parts: parts});
}
if (type == 'turn' && params[0] == this.username) {
this.playEffects(turn_sfx);
} else if (type == 'died_role') {
this.playEffects(death_sfx);
} else if (type == 'explode') {
this.playEffects(dynamite_sfx);
} else if (type == 'prison_turn') {
this.playEffects(prison_sfx);
} else if (type == 'purchase_card') {
this.playEffects(cash_sfx);
} else {
this.playEffects(notification_sfx);
}
} else { // a chat message
(new Audio(message_sfx)).play();
this.playEffects(message_sfx);
this.messages.push(msg);
if (msg.type && msg.type === 'json') {
msg.json = JSON.parse(msg.text);
}
if (this.collapsed || window.innerWidth < 1000) {
this.toasts.push(msg);
setTimeout(() => this.toasts.shift(), 5000);
}
}
let container = this.$el.querySelector("#chatbox");
container.scrollTop = container.scrollHeight;
},
spectators(val) {
this.spectators = val
},
commands(list) {
this.commands = list;
}
},
methods: {
@ -92,6 +161,24 @@ export default {
}
e.preventDefault();
},
fillCmd(cmd) {
this.text = cmd;
document.getElementById('my-msg').focus();
},
tabComplete() {
if (this.commandSuggestion.length > 0) {
let cmd = this.commandSuggestion[0].cmd;
this.text = cmd + ' ';
}
},
playEffects(path) {
const promise = (new Audio(path)).play();
if(promise !== undefined){
promise.catch(err => {
console.log(err)
});
}
}
},
}
</script>
@ -103,7 +190,7 @@ export default {
overflow-x: hidden;
overflow-wrap: break-word;
overflow-wrap: normal;
border: 2pt solid #ccc;
border: 2pt solid var(--muted-color);
border-radius: 4pt;
}
input {
@ -113,13 +200,21 @@ input {
height: 0pt;
margin-top: -1.5pt;
}
.chat {
.std-text {
color: var(--font-color);
}
.chat, .cont {
display: flex;
flex-direction: column;
max-height: 90vh;
}
.chat_spectators, .cont_spectators {
max-height: 84vh;
}
#msg-form {
width:100%;
padding:0;
margin-top: 6pt;
display:flex;
}
.message-enter-active, .message-leave-active {
@ -130,14 +225,34 @@ input {
transform: translateX(30px);
}
@media only screen and (min-width:1000px) {
.chat {
height: 90vh;
.chat-header {
margin-left: 10pt;
}
.chat, .cont {
height: 88vh;
margin-left: 10pt;
}
.chat_spectators, .cont_spectators {
max-height: 84vh;
}
#submit-message {
margin-left: 6pt;
margin-right: -5pt;
}
}
#toast-chatbox {
position: fixed;
bottom: 30pt;
left: 0;
background: --var(--bg-color);
}
@media only screen and (max-width:1000px) {
#msg-form {
flex-direction: column;
margin-bottom: 50pt;
}
#submit-message {
margin-top: 6pt;
}
#chatbox {
max-height:150px;

View File

@ -3,12 +3,13 @@
<h1>{{text}}</h1>
<div>
<transition-group name="list" tag="div">
<Card v-for="(c, i) in cards" v-bind:key="c.name ? (c.name+c.number) : i" :card="c" @click.native="select(c)" @pointerenter.native="showDesc(c)" @pointerleave.native="desc=''"/>
<Card v-for="(c, i) in cards" v-bind:key="c.name ? (c.name+c.number) : i" :card="c" @click.native="internalSelect(c)" @pointerenter.native="showDesc(c)" @pointerleave.native="desc=''"/>
</transition-group>
</div>
<p v-if="hintText">{{hintText}}</p>
<div style="margin-top:6pt;" class="button center-stuff" v-if="showCancelBtn" @click="cancel"><span>{{realCancelText}}</span></div>
<p v-if="desc" style="bottom:10pt;right:0;left:0;position:absolute;margin:16pt;font-size:18pt">{{desc}}</p>
<h2 v-if="timer > 0 && remainingTime > 0 && !showCancelBtn">{{remainingTime}}</h2>
<div style="margin-top:6pt;" class="button center-stuff" v-if="showCancelBtn" @click="internalCancel"><span>{{realCancelText}}</span> <span v-if="timer > 0 && remainingTime > 0"> ({{remainingTime}})</span></div>
<p v-if="desc" style="bottom:28pt;right:0;left:0;position:absolute;margin:16pt;font-size:18pt">{{desc}}</p>
</div>
</template>
@ -29,13 +30,19 @@ export default {
type: String,
default: '',
},
timer: {
type: Number,
default: 0,
},
text: String,
hintText: String,
playAudio: Boolean,
},
data: () => ({
desc: '',
realCancelText: ''
realCancelText: '',
remainingTime: 0,
intervalID: '',
}),
computed: {
showCancelBtn() {
@ -47,24 +54,51 @@ export default {
methods: {
showDesc(card) {
//console.log(card)
if (card.name == null || card.name == "PewPew!")
if (card.noDesc || card.name == null || card.name == "PewPew!")
this.desc = ""
else if (card.is_player)
this.desc = card.name
else if (card.goal)
this.desc = this.$t(`cards.${card.name}.name`)
else if (card.desc)
this.desc = (this.$i18n.locale=='it'?card.desc:card.desc_eng)
else if (card.is_character)
this.desc = card.name
else
this.desc = this.$t(`cards.${card.name}.desc`)
}
},
countDown() {
if (this.remainingTime > 0) {
this.remainingTime--;
} else {
if (this.select) this.select(this.cards[0]);
else if (this.cancel) this.cancel();
window.clearInterval(this.intervalID);
}
},
internalCancel() {
if (this.intervalID) window.clearInterval(this.intervalID);
this.cancel();
},
internalSelect(card) {
if (this.intervalID) window.clearInterval(this.intervalID);
this.select(card);
},
},
mounted() {
this.realCancelText = this.cancelText
if (this.realCancelText == '') {
this.realCancelText = this.$t('cancel')
}
if (this.cards && this.cards.length == 1) {
this.showDesc(this.cards[0])
}
if (this.playAudio) {
(new Audio(show_sfx)).play();
}
this.remainingTime = this.timer;
if (this.timer != 0 && this.remainingTime == this.timer) {
if (this.intervalID) window.clearInterval(this.intervalID);
this.intervalID = window.setInterval(this.countDown, 1000);
}
},
}
</script>

View File

@ -0,0 +1,153 @@
<template>
<div id="overlay" class="center-stuff">
<h1>{{text}}</h1>
<div>
<Card v-if="playerCard" :card="playerCard" />
<Card v-if="playerRole" :card="playerRole" class="back"/>
</div>
</div>
</template>
<script>
import Card from '@/components/Card.vue'
export default {
name: 'DeadRoleNotification',
components: {
Card,
},
props: {
playerCard: Object,
playerRole: Object
},
data: () => ({
}),
computed: {
},
methods: {
},
mounted() {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#overlay {
position: fixed; /* Sit on top of the page content */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.7); /* Black background with opacity */
z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
/* display: flex; */
color: white;
justify-content: center;
text-align: center;
}
#overlay>div {
margin:auto;
position: relative;
top:35%;
text-align: center;
width: 72pt;
transform: scale(1.5);
}
.card {
width: 72pt;
min-width:72pt;
height: 120pt;
position: absolute;
}
.card.avatarred{
animation: slide-in-fwd-bottom 2s ease, puff-out-center 1s ease 2s, make-invisible 10s step-start 3s;
}
.card.back {
animation: make-visible 3s step-end, wobble-ver-left 2s ease 3s;
}
@keyframes make-invisible {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes make-visible {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes wobble-ver-left {
0% {
transform:translateY(0) rotate(0);
transform-origin:50% 50%;
}
15% {
transform:translateY(-30px) rotate(-6deg);
}
30% {
transform:translateY(15px) rotate(6deg);
}
45% {
transform:translateY(-15px) rotate(-3.6deg);
}
60% {
transform:translateY(9px) rotate(2.4deg);
}
75% {
transform:translateY(-6px) rotate(-1.2deg);
}
100% {
transform:translateY(0) rotate(0);
transform-origin:50% 50%;
}
}
@keyframes slide-in-fwd-bottom {
0% {
transform:translateZ(-1400px) translateY(800px);
opacity:0;
}
100% {
transform:translateZ(0) translateY(0);
opacity:1;
}
}
@keyframes puff-out-center {
0% {
transform:scale(1);
filter:blur(0);
opacity:1;
}
100% {
transform:scale(2);
filter:blur(4px);
opacity:0;
}
}
.button {
background-color: #0000;
color: white;
border: 2px solid white;
transition-duration: 0.2s;
width: 100pt;
height: 24pt;
border-radius: 12pt;
cursor: pointer;
}
.button:hover {
background-color: white; /* Green */
color: black;
}
</style>

View File

@ -1,27 +1,65 @@
<template>
<div>
<div >
<div class="deck">
<card v-if="endTurnAction && isPlaying" :donotlocalize="true" v-show="pending_action == 2" :card="endTurnCard" class="end-turn" @click.native="endTurnAction"/>
<div class="deck" id="gold-rush-deck" :style="`position:relative;${goldRushShopOpen?'border: 2px dashed #6a6a6a42;border-radius:8pt':''}`" v-if="goldRushCards.length > 0" >
<card @pointerenter.native="()=>{setGoldRushDesc(goldRushCards[0])}" @pointerleave.native="goldRushDesc=null" :style="goldRushShopOpen?``:`position:absolute; top:0; right:0; transform: rotate(95deg) translate(30px, -40px) scale(0.6)`" v-if="goldRushCards.length > 0" :key="goldRushCards[0].name" :card="goldRushCards[0]" :class="{'shop-open':goldRushShopOpen, 'cant-play': pending_action !==2 || gold_nuggets < goldRushCards[0].number - gold_rush_discount}" @click.native="() => {buy_gold_rush_card(0)}"/>
<card @pointerenter.native="()=>{setGoldRushDesc(goldRushCards[1])}" @pointerleave.native="goldRushDesc=null" :style="goldRushShopOpen?``:`position:absolute; top:0; right:0; transform: rotate(90deg) translate(0, -40px) scale(0.6)`" v-if="goldRushCards.length > 1" :key="goldRushCards[1].name" :card="goldRushCards[1]" :class="{'shop-open':goldRushShopOpen, 'cant-play': pending_action !==2 || gold_nuggets < goldRushCards[1].number - gold_rush_discount}" @click.native="() => {buy_gold_rush_card(1)}"/>
<card @pointerenter.native="()=>{setGoldRushDesc(goldRushCards[2])}" @pointerleave.native="goldRushDesc=null" :style="goldRushShopOpen?``:`position:absolute; top:0; right:0; transform: rotate(85deg) translate(-30px, -40px) scale(0.6)`" v-if="goldRushCards.length > 2" :key="goldRushCards[2].name" :card="goldRushCards[2]" :class="{'shop-open':goldRushShopOpen, 'cant-play': pending_action !==2 || gold_nuggets < goldRushCards[2].number - gold_rush_discount}" @click.native="() => {buy_gold_rush_card(2)}"/>
<div style="position:relative">
<div class="card gold-rush back" style="position:relative; bottom:-3pt;right:-3pt;"/>
<div class="card gold-rush back" style="position:absolute; bottom:-1.5pt;right:-1.5pt;"/>
<card :card="goldRushCardBack" :donotlocalize="true" class="gold-rush back last-event" @click.native="goldRushShopOpen = !goldRushShopOpen"/>
</div>
</div>
<div v-if="currentStations.length > 0" id="train-robbery-deck" class="deck" :style="`position:relative;border: 2px dashed #6a6a6a42;border-radius:8pt;align-items: flex-end;flex-direction:row;`" >
<station-card @click.native="()=>{buyTrain(i)}" v-for="station, i in currentStations" :key="station.name" :card="station" :price="station.price" :trainPiece="trainPieceForStation(i)"
@pointerenter.native="()=>{setStationDesc(i)}" @pointerleave.native="stationDesc = null"/>
</div>
<div v-if="eventCard" style="position:relative">
<div class="card fistful-of-cards" style="position:relative; bottom:-3pt;right:-3pt;"/>
<div class="card fistful-of-cards" style="position:absolute; bottom:-1.5pt;right:-1.5pt;"/>
<card :card="eventCard" :key="eventCard.name" :class="eventClasses" @click.native="event"/>
<card :card="eventCard" :key="eventCard.name" :class="eventClasses" @click.native="() => event('event')"/>
</div>
<div style="position:relative">
<div class="card back" style="position:absolute; bottom:-3pt;right:-3pt;"/>
<div class="card back" style="position:absolute; bottom:-1.5pt;right:-1.5pt;"/>
<card :card="card" :donotlocalize="true" :class="{back:true, pick:pending_action === 0, draw:pending_action === 1}" @click.native="action"/>
<div v-if="eventCardWildWestShow" style="position:relative">
<div class="card wild-west-show back" style="position:relative; bottom:-3pt;right:-3pt;"/>
<div class="card wild-west-show back" style="position:absolute; bottom:-1.5pt;right:-1.5pt;"/>
<card :card="eventCardWildWestShow" :key="eventCardWildWestShow.name" :class="eventWwsClasses" @click.native="() => event('event_wildwestshow')"/>
</div>
<div style="position:relative;">
<card v-if="previousScrap" :card="previousScrap" style="top: 1.5pt;right: -1.5pt;"/>
<card v-else :card="card" class="back" style="opacity:0"/>
<card v-if="lastScrap" :card="lastScrap" :key="lastScrap.name+lastScrap.number" class="last-scrap" @click.native="action('scrap')"
@pointerenter.native="setdesc" @pointerleave.native="desc=''" />
<div style="position:relative" class="deck">
<div style="position:relative" id="actual-deck">
<div class="card back" style="position:absolute; bottom:-3pt;right:-3pt;"/>
<div class="card back" style="position:absolute; bottom:-1.5pt;right:-1.5pt;"/>
<card :card="card" :donotlocalize="true" :class="{back:true, pick:pending_action === 0, draw:pending_action === 1}" @click.native="action"/>
</div>
<div style="position:relative;" id="actual-scrap">
<card v-if="previousScrap" :card="previousScrap" style="top: 1.5pt;right: -1.5pt;"/>
<card v-else :card="card" class="back" style="opacity:0"/>
<card v-if="lastScrap" :card="lastScrap" :key="lastScrap.name+lastScrap.number" class="last-scrap" @click.native="action('scrap')"
@pointerenter.native="setdesc" @pointerleave.native="desc=''" />
</div>
<card v-if="endTurnAction && isPlaying" :donotlocalize="true" v-show="pending_action == 2" :card="endTurnCard" class="end-turn" @click.native="endTurnAction"/>
</div>
</div>
<transition name="list">
<p v-if="eventCard" class="center-stuff"><i>{{($i18n.locale=='it'?eventCard.desc:eventCard.desc_eng)}}</i></p>
<p v-if="eventCard" class="center-stuff">🔥 <b>{{eventDesc}}</b> 🎴</p>
</transition>
<transition name="list">
<p v-if="eventCardWildWestShow && !eventCardWildWestShow.back" class="center-stuff">🎪 <b>{{eventDescWildWestShow}}</b> 🎪</p>
</transition>
<transition name="list">
<div v-if="goldRushDesc">
<p class="center-stuff">🤑 <i>{{$t(`cards.${goldRushDesc.name}.desc`)}}</i> 🤑</p>
<p class="center-stuff">🤑 <b>{{goldRushDesc.number - gold_rush_discount}} 💵</b> 🤑</p>
</div>
</transition>
<transition name="list">
<div v-if="stationDesc">
<p class="center-stuff"><i>{{stationDesc}}</i></p>
</div>
</transition>
<div style="margin-bottom:6pt;margin-bottom: 6pt;display: flex;flex-direction: column;">
<button class="btn" v-if="pending_action == 2 && can_gold_rush_discard" @click="$socket.emit('gold_rush_discard')">{{$t('gold_rush_discard')}}</button>
</div>
<transition name="list">
<p v-if="desc" class="center-stuff"><i>{{desc}}</i></p>
</transition>
@ -30,6 +68,7 @@
<script>
import Card from '@/components/Card.vue'
import StationCard from '@/components/StationCard.vue'
export default {
name: 'Deck',
@ -38,24 +77,42 @@ export default {
},
components: {
Card,
StationCard
},
data: () => ({
card: {
name: 'PewPew!',
icon: '💥',
},
goldRushCardBack: {
name: 'GoldRush!',
icon: '🤑️',
},
lastScrap: null,
eventCard: null,
eventCardWildWestShow: null,
previousScrap: null,
pending_action: false,
isPlaying: true,
desc: '',
goldRushShopOpen: true,
goldRushCards: [],
gold_nuggets: 0,
goldRushDesc: null,
stationDesc: null,
can_gold_rush_discard: false,
gold_rush_discount: 0,
currentStations: [],
currentTrain: [],
}),
sockets: {
self(self){
self = JSON.parse(self)
this.isPlaying = self.lives > 0 || self.is_ghost
this.pending_action = self.pending_action
this.gold_nuggets = self.gold_nuggets
this.can_gold_rush_discard = self.can_gold_rush_discard
this.gold_rush_discount = self.gold_rush_discount
},
scrap(card) {
this.lastScrap = card
@ -68,6 +125,23 @@ export default {
expansion: 'fistful-of-cards',
} : card
},
event_card_wildwestshow(card) {
this.eventCardWildWestShow = card == false ? {
name: 'Wild West Show',
icon: '🎪',
back: true,
expansion: 'wild-west-show',
} : card
},
gold_rush_shop(cards) {
console.log('GOLD RUSH:'+ cards)
this.goldRushCards = JSON.parse(cards)
},
stations(stations) {
let msg = JSON.parse(stations)
this.currentStations = msg.stations
this.currentTrain = msg.current_train
},
},
computed: {
endTurnCard() {
@ -83,9 +157,40 @@ export default {
}
classes[this.eventCard.expansion] = true
return classes
}
},
eventWwsClasses() {
let classes = {
'last-event':true,
'back':this.eventCardWildWestShow.back,
'wild-west-show':true,
}
return classes
},
eventDesc() {
this.eventCard;
if (this.eventCard.name !== 'PewPew!'){
return this.$t(`cards.${this.eventCard.name}.desc`)
}
return ""
},
eventDescWildWestShow() {
this.eventCardWildWestShow;
if (this.eventCardWildWestShow.name !== 'PewPew!'){
return this.$t(`cards.${this.eventCardWildWestShow.name}.desc`)
}
return ""
},
},
methods: {
trainPieceForStation(i) {
let index = this.currentTrain.length-5-i;
if (index < 0 || index >= this.currentTrain.length)
return null;
return this.currentTrain[index];
},
buyTrain(i) {
this.$socket.emit('buy_train', i)
},
action(pile) {
if (this.pending_action !== false && this.pending_action < 2) {
// console.log('action')
@ -95,9 +200,12 @@ export default {
this.$socket.emit('draw', pile)
}
},
event() {
buy_gold_rush_card(index) {
this.$socket.emit('buy_gold_rush_card', index)
},
event(pile='event') {
if (this.pending_action !== false) {
this.$socket.emit('draw', 'event')
this.$socket.emit('draw', pile)
}
},
setdesc() {
@ -105,6 +213,22 @@ export default {
this.desc = (this.$i18n.locale=='it'?this.lastScrap.desc:this.lastScrap.desc_eng)
else
this.desc = this.$t(`cards.${this.lastScrap.name}.desc`)
},
setGoldRushDesc(card) {
this.goldRushDesc = card
},
setStationDesc(index) {
console.log('setStationDesc', index)
this.stationDesc = this.$t(`cards.${this.currentStations[index].name}.desc`)
const trainPiece = this.trainPieceForStation(index)
if (trainPiece) {
this.stationDesc += '\n\n🚂' + this.$t(`cards.${trainPiece.name}.desc`) + '🚋'
}
},
},
mounted() {
if (window.innerWidth < 1000) {
this.goldRushShopOpen = false;
}
},
watch: {
@ -122,6 +246,7 @@ export default {
align-items: center;
justify-content: center;
flex-direction: row-reverse;
flex-wrap: wrap-reverse;
}
.last-scrap {
position: absolute;
@ -133,6 +258,10 @@ export default {
opacity: 0.8;
transform: translateY(-10px);
}
.gold-rush:not(.back) {
animation-duration: 0.8s;
animation-name: slidein;
}
@keyframes slidein {
from {
transform: translate(-100px, 10px) scale(1.3) rotate(-10deg);
@ -204,12 +333,8 @@ export default {
.end-turn {
box-shadow:
0 0 0 3pt rgb(138, 12, 12),
0 0 0 6pt white,
0 0 0 6pt var(--bg-color),
0 0 5pt 6pt #aaa !important;
}
@media (prefers-color-scheme: dark) {
.end-turn {
box-shadow: 0 0 0 3pt rgb(138, 12, 12), 0 0 0 6pt #181a1b, 0 0 5pt 6pt #aaa !important;
}
}
</style>

View File

@ -0,0 +1,117 @@
<template>
<div class="popup-overlay" v-if="show" @click="handleOverlayClick">
<div class="popup-content" @click.stop>
<button class="close-button" @click="close">×</button>
<h2>{{ expansion.name }}</h2>
<div v-for="section in expansion.cards" :key="section.type" class="section">
<h3>{{ section.type }}</h3>
<div class="cards-container flexy-cards-wrapper">
<div v-for="card in section.cards" :key="card.name" class="flexy-cards">
<Card :card="card" v-if="section.type !== 'stations'" :class="getClass(expansion, section)"/>
<StationCard :card="card" :price="card.price" v-else-if="section.type === 'stations'"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${card.name}.desc`)}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Card from '@/components/Card.vue';
import StationCard from './StationCard.vue';
export default {
props: {
show: Boolean,
expansion: Object, // Expecting an object with id, name, and cards
},
components: {
Card,
StationCard,
},
methods: {
close() {
this.$emit('close');
},
handleOverlayClick() {
this.close();
},
getClass(expansion, section) {
let classes = ''
if (section.type == 'events') {
classes += 'last-event';
}
if (expansion.id == 'fistful_of_cards') {
classes += ' fistful-of-cards';
} else if (expansion.id == 'high_noon') {
classes += ' high-noon';
} else if (expansion.id == 'gold_rush') {
classes += ' gold-rush';
} else if (expansion.id == 'train_robbery') {
classes += ' train-robbery';
} else if (expansion.id == 'the_valley_of_shadows') {
classes += ' valley-of-shadows';
} else if (expansion.id == 'wild_west_show') {
classes += ' wild-west-show';
}
console.log(classes);
return classes;
}
},
};
</script>
<style scoped>
.popup-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.popup-content {
position: relative;
background: white;
padding: 20px;
border-radius: 5px;
max-width: 80%;
max-height: 80%;
overflow-y: auto;
}
.close-button {
position: absolute;
top: 10px;
right: 10px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
}
.section {
margin-bottom: 20px;
}
.cards-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.card {
box-sizing: border-box;
margin-bottom: 10px;
}
.flexy-cards-wrapper {
display: flex;
flex-flow: wrap;
}
.flexy-cards {
flex: 30%;
display:flex;
}
</style>

View File

@ -2,10 +2,14 @@
<div id="overlay" class="center-stuff">
<h1>{{text}}</h1>
<form @submit="submit">
<input v-model="val" class="chooserInput"/>
<input v-if="val.length < 20" v-model="val" class="chooserInput" v-focus/>
<textarea v-else v-model="val" class="chooserInput" cols="38" rows="15" v-focus/>
</form>
<p v-if="hintText">{{hintText}}</p>
<div style="margin-top:6pt;" class="button center-stuff" v-if="showCancelBtn && val" @click="cancel(val)"><span>{{realCancelText}}</span></div>
<div class="center-stuff">
<div style="margin-top:6pt;margin-right:6pt;" class="button center-stuff" v-if="canCancel" @click="cancel()"><span>{{realCancelText}}</span></div>
<div style="margin-top:6pt;margin-left:6pt;" class="button center-stuff" v-if="showSendBtn && val" @click="send(val)"><span>{{realSendText}}</span></div>
</div>
</div>
</template>
@ -14,21 +18,31 @@ export default {
name: 'FullScreenInput',
props: {
cancel: Function,
send: Function,
defaultValue: String,
cancelText: {
type: String,
default: '',
},
sendText: {
type: String,
default: '',
},
text: String,
hintText: String,
canCancel: {
type: Boolean,
default: false,
},
},
data: () => ({
val: '',
realCancelText: ''
realCancelText: '',
realSendText: ''
}),
computed: {
showCancelBtn() {
if (this.cancel)
showSendBtn() {
if (this.send)
return true
return false
}
@ -36,15 +50,19 @@ export default {
methods: {
submit(e) {
e.preventDefault();
this.cancel(this.val);
this.send(this.val);
}
},
mounted() {
this.realCancelText = this.cancelText
this.realSendText = this.sendText
this.val = this.defaultValue
if (this.realCancelText == '') {
this.realCancelText = this.$t('cancel')
}
if (this.realSendText == '') {
this.realSendText = this.$t('send')
}
},
}
</script>

View File

@ -1,6 +1,11 @@
<template>
<div>
<a v-if="!inGame" href=".."><p>Home</p></a>
<h1 id="help">{{$t('help.title')}}</h1>
<a href="#thecards"><p>{{$t('help.gotocards')}}</p></a>
<a href="#highnooncards"><p>{{$t('help.gotohighnoon')}}</p></a>
<a href="#foccards"><p>{{$t('help.gotofoc')}}</p></a>
<a href="#goldrushcards"><p>{{$t('help.gotogoldrush')}}</p></a>
<h2>{{$t('help.character')}}</h2>
<p>{{$t('help.characters_special')}}</p>
<a href="#basecharacters"><p>{{$t('help.gotoallcharacters')}}</p></a>
@ -19,7 +24,7 @@
<li><p>{{$t('help.turndiscard')}}</p></li>
</ol>
<h3>{{$t('help.drawthecards')}}</h3>
<p>{{$t('help.drawinstructions')}}<p>
<p>{{$t('help.drawinstructions')}}</p>
<div style="display:flex" class="center-stuff">
<div style="position:relative">
<div class="card back" style="position:absolute; bottom:-3pt;right:-3pt;"/>
@ -55,21 +60,83 @@
<li><p>{{$t('help.endgameshriffdeath')}}</p></li>
<li><p>{{$t('help.endgamesheriffwin')}}</p></li>
</ul>
<h2>{{$t('help.thecards')}}</h2>
<div>
<div v-for="(c, i) in cards" v-bind:key="c.name ? (c.name+c.number) : i" style="display:flex">
<h2 id="thecards">{{$t('help.thecards')}}</h2>
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in cards" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
<p v-if="c.is_equipment"><b>{{$t('help.equipment')}}</b></p>
<p v-if="c.is_weapon"><b>{{$t('help.weapon')}}</b></p>
<p v-if="c.expansion"><b>{{c.expansion}}</b></p>
</div>
</div>
</div>
<h2 id="basecharacters">{{$t('help.allcharacters')}}</h2>
<div>
<div v-for="(c, i) in characters" v-bind:key="c.name ? (c.name+c.number) : i" style="display:flex">
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in characters" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
<p v-if="c.expansion"><b>{{c.expansion}}</b></p>
</div>
</div>
</div>
<h2 id="highnooncards">{{$t('help.highnooncards')}}</h2>
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in highnooncards" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" :class="'high-noon last-event'" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
</div>
</div>
</div>
<h2 id="foccards">{{$t('help.foccards')}}</h2>
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in foccards" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" :class="'fistful-of-cards last-event'" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
</div>
</div>
</div>
<h2 id="goldrushcards">{{$t('help.goldrushcards')}}</h2>
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in goldrushcards" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" class="gold-rush" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
</div>
</div>
</div>
<h2 id="valleyofshadowscards">{{$t('help.valleyofshadowscards')}}</h2>
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in valleyofshadowscards" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" class="valley-of-shadows" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
</div>
</div>
</div>
<h2 id="wildwestshowcards">{{$t('help.wildwestshowcards')}}</h2>
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in wildwestshowcards" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" class="wild-west-show" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
</div>
</div>
</div>
<h2 id="trainrobberycards">{{$t('help.trainrobberycards')}}</h2>
<div class="flexy-cards-wrapper">
<div v-for="(c, i) in trainrobberycards" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<Card :card="c" class="train-robbery" @pointerenter.native="''" @pointerleave.native="''"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
</div>
</div>
<div v-for="(c, i) in trainrobberystations" v-bind:key="c.name ? (c.name+c.number) : i" class="flexy-cards">
<StationCard :card="c" class="train-robbery" @pointerenter.native="''" @pointerleave.native="''" :price="c.price"/>
<div style="margin-left:6pt;">
<p>{{$t(`cards.${c.name}.desc`)}}</p>
</div>
@ -78,11 +145,17 @@
</div>
</template>
<script>
import Card from './Card'
import Card from '@/components/Card.vue'
import StationCard from './StationCard.vue'
export default {
name: 'Help',
components: {
Card,
StationCard,
},
props: {
inGame: Boolean
},
data:()=>({
cardBack: {
@ -91,6 +164,13 @@ export default {
},
cards: [],
characters: [],
highnooncards: [],
foccards: [],
goldrushcards: [],
valleyofshadowscards: [],
wildwestshowcards: [],
trainrobberycards: [],
trainrobberystations: [],
}),
computed: {
endTurnCard() {
@ -110,15 +190,72 @@ export default {
is_character:true,
}))
},
highnooncards_info(cardsJson) {
this.highnooncards = JSON.parse(cardsJson).map(x=>({
...x,
}))
},
foccards_info(cardsJson) {
this.foccards = JSON.parse(cardsJson).map(x=>({
...x,
}))
},
goldrushcards_info(cardsJson) {
this.goldrushcards = JSON.parse(cardsJson).map(x=>({
...x,
}))
},
valleyofshadows_info(cardsJson) {
this.valleyofshadowscards = JSON.parse(cardsJson).map(x=>({
...x,
}))
},
wwscards_info(cardsJson) {
this.wildwestshowcards = JSON.parse(cardsJson).map(x=>({
...x,
}))
},
trainrobberycards_info(cardsJson) {
this.trainrobberycards = JSON.parse(cardsJson).cards.map(x=>({
...x,
}))
this.trainrobberystations = JSON.parse(cardsJson).stations.map(x=>({
...x,
}))
},
},
mounted() {
this.$socket.emit('get_cards')
this.$socket.emit('get_characters')
this.$socket.emit('get_highnooncards')
this.$socket.emit('get_foccards')
this.$socket.emit('get_goldrushcards')
this.$socket.emit('get_valleyofshadowscards')
this.$socket.emit('get_wildwestshowcards')
this.$socket.emit('get_trainrobberycards')
document.getElementById('help').scrollIntoView();
}
}
</script>
<style scoped>
.flexy-cards-wrapper {
display: flex;
flex-flow: wrap;
}
.flexy-cards {
flex: 30%;
display:flex;
}
@media only screen and (max-width:500px) {
.flexy-cards {
flex: 100%;
}
}
@media only screen and (max-width:800px) {
.flexy-cards {
flex: 50%;
}
}
@keyframes pick {
0% {
transform: translate(0,0);
@ -160,7 +297,7 @@ export default {
.end-turn {
box-shadow:
0 0 0 3pt rgb(138, 12, 12),
0 0 0 6pt white,
0 0 0 6pt var(--bg-color),
0 0 5pt 6pt #aaa !important;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -2,19 +2,22 @@
<div id="app" class="dark-mode">
<div v-if="!isInLobby" id="logo" class="center-stuff" style="margin-bottom:10pt">
<h1 style="margin-bottom:0pt;">PewPew!</h1>
<p id="tip" style="margin-top: auto; color:darkorange">{{$t(randomTip)}}</p>
<p style="transform: scale(0.7);margin-top: auto;">v-{{version}}</p>
<div style="display:flex;justify-content: space-evenly;;min-height:140pt;">
<span style="font-size:48pt;transform:scaleX(-1) translateY(25%);">🔫</span>
<TinyHand :ncards="5" ismyturn="true" style="position:none;transform:scale(1);bottom:none;width:120pt;"/>
<TinyHand :ncards="5" :ismyturn="true" style="position:none;transform:scale(1);bottom:none;width:120pt;"/>
<span style="font-size:48pt;transform:translateY(25%);">🔫</span>
</div>
<i style="font-size: x-small;">{{$t("trademark")}}</i>
</div>
<div>
<div v-if="!didSetUsername">
<p>{{$t("choose_username")}}</p>
<form @submit="setUsername">
<input id="username" v-model="username" />
<input type="submit" :value="$t('submit')"/>
<p id="choose_username">{{$t("choose_username")}}</p>
<form @submit="setUsername" class="form" style="display:flex">
<input id="_username" v-model="username" />
<input type="submit" class="btn" :value="$t('submit')"/>
<input type="button" class="btn" @click="discordLogin" value="Login with Discord"/>
</form>
<p v-if="onlinePlayers > 0">{{$t("online_players")}}{{onlinePlayers}}</p>
</div>
@ -23,10 +26,10 @@
<p>{{$t("online_players")}}{{onlinePlayers}}</p>
<Card :card="getSelfCard" :donotlocalize="true" style="position:absolute; top:10pt; left: 10pt;"/>
<h2>{{$t("create_lobby")}}</h2>
<form @submit="createLobby" style="display:flex">
<form @submit="createLobby" class="form" style="display:flex">
<p>{{$t("lobby_name")}}</p>
<input id="lobbyname" v-model="lobbyName"/>
<input type="submit" :value="$t('submit')"/>
<input type="submit" class="btn" :value="$t('submit')"/>
</form>
<h2>{{$t("available_lobbies")}}</h2>
<div style="display: flex">
@ -41,8 +44,11 @@
</div>
</div>
</div>
<label for="username" style="opacity:0">Username</label>
<label for="_username" style="opacity:0">Username</label>
<label for="lobbyname" style="opacity:0">Lobby Name</label>
<div>
Still new to the game? Read the rules <a href="./help">here</a> or press the question mark in the bottom right corner anytime during your matches.
</div>
</div>
</template>
@ -51,6 +57,8 @@
import Card from '@/components/Card.vue'
import TinyHand from '@/components/TinyHand.vue'
// import Lobby from './components/Lobby.vue'
import { datadogRum } from '@datadog/browser-rum';
import { emojiMap } from '@/utils/emoji-map.js'
export default {
name: 'App',
@ -68,8 +76,13 @@ export default {
lobbyName: '',
isInLobby: false,
onlinePlayers: 0,
randomTip: '',
discordPic: '',
}),
computed: {
redirectUrl() {
return 'https://discordapp.com/api/oauth2/authorize?client_id=1059452581027532880&response_type=code&scope=identify&redirect_uri=' + window.location.origin;
},
noLobbyAvailable() {
return this.openLobbies && this.openLobbies.length == 0
},
@ -82,8 +95,13 @@ export default {
number: this.$t('you'),
icon: '🤠',
is_character: true,
avatar: this.discordPic,
is_player: true
}
},
version() {
return document.getElementsByTagName("html")[0].getAttribute("data-build-timestamp-utc").replace(/[-|:|T]/g,'.').substring(0,16)
}
},
sockets: {
lobbies(data) {
@ -99,22 +117,33 @@ export default {
players(num) {
this.onlinePlayers = num;
// console.log('PLAYERS:' + num)
}
},
discord_auth_succ(data) {
if (data.access_token) {
localStorage.setItem('discord_token', data.access_token)
this.login()
}
},
},
methods: {
setUsername(e){
if (this.username.trim().length > 0){
this.didSetUsername = true
localStorage.setItem('username', this.username)
this.$socket.emit('set_username', this.username)
this.$socket.emit('set_username', {name:this.username})
datadogRum.setUser({name: localStorage.getItem('username')})
e.preventDefault();
}
},
discordLogin() {
window.location = this.redirectUrl;
},
getLobbyCard(lobby) {
return {
name: lobby.name,
icon: "💥",
number: `${lobby.players}🤠 ${lobby.locked?'🔐':''}`,
number: `${lobby.players-lobby.bots}🤠${lobby.bots > 0 ? ' '+lobby.bots+'🤖':''} ${lobby.locked?'🔐':''}`,
alt_text: lobby.expansions?.map(e => emojiMap[e]).join(''),
is_equipment: true,
}
},
@ -122,7 +151,8 @@ export default {
return {
name: lobby.name,
icon: "👁️",
number: `${lobby.players}🤠 ${lobby.locked?'🔐':''}`,
number: `${lobby.players-lobby.bots}🤠${lobby.bots > 0 ? ' '+lobby.bots+'🤖':''} ${lobby.locked?'🔐':''}`,
alt_text: lobby.expansions?.map(e => emojiMap[e]).join(''),
usable_next_turn: true,
}
},
@ -139,14 +169,76 @@ export default {
init() {
location.reload();
},
login() {
fetch('https://discordapp.com/api/users/@me', {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('discord_token')
}
})
.then((res) => {
if (res.status !== 200) throw new Error(res.status)
return res
})
.then(response => response.json())
.then(data => {
console.log(data)
this.username = data.username
this.didSetUsername = true
this.discordPic = `https://cdn.discordapp.com/avatars/${data.id}/${data.avatar}.png`
localStorage.setItem('username', this.username)
this.$socket.emit('set_username', {name: this.username, discord_token: localStorage.getItem('discord_token')})
}).catch(err => {
console.error(err)
localStorage.removeItem('discord_token')
this.$router.replace({query: []})
})
}
},
mounted() {
if (localStorage.getItem('discord_token')) {
this.login()
} else if (this.$route.query.code) {
this.$socket.emit('discord_auth', {code:this.$route.query.code, origin:window.location.origin})
this.$router.replace({query: []})
}
this.randomTip = `tip_${1+Math.floor(Math.random() * 10)}`
if (localStorage.getItem('username'))
this.username = localStorage.getItem('username')
else {
let names = ['player', 'cowboy', 'madman', 'horseshoe', 'mustang', '🤠️', 'dog lover', 'random', 'cows', 'seagull', 'pewneer', 'pioneer', 'django', 'tarantined', 'horse', 'cinnamom', 'toast', 'notPewDiePie', 'username', 'caveman', 'cat', 'gold', 'chicken', 'nugget', 'bullet', 'fire', 'scott', 'emiliano', 'apple', 'pear', 'pencil', 'youtuber', 'hi mom', 'discord guy', '🥰️', 'somebody', 'AAAAA', 'BBBB', 'pain', 'help?', 'gg', 'gigi', 'lmao', 'yikes', 'you?', 'kid', 'cowgirl', 'bite', 'hungry', 'joe', 'limbo', 'leeeroy', 'jenkins', 'batman', 'spiderman', 'luke skywalker', 'nemo', 'zemo', 'ironman', 'butterman', 'postman', 'father', 'son', 'sven', 'mike', 'straw', 'saaay', 'whaaaat', 'rick', 'morty', 'wubbalubbadubdub']
this.username = names[Math.floor(Math.random() * names.length)]
}
this.$socket.emit('get_online_players')
},
}
</script>
<style>
@media only screen and (max-width:1000px) {
.form {
flex-direction: column;
}
.form > input, .form>p{
font-size: 20pt;
}
#choose_username{
font-size: 20pt;
}
}
#tip {
animation-name: zoom;
animation-duration: 2s;
animation-iteration-count: infinite;
}
@keyframes zoom {
0% {
transform: scale(1);
}
50% {
transform: scale(0.95);
}
100% {
transform: scale(1);
}
}
</style>

View File

@ -3,31 +3,44 @@
<p v-if="instruction && (lives > 0 || is_ghost)" class="center-stuff">{{instruction}}</p>
<!-- <button v-if="canEndTurn" @click="end_turn">Termina Turno</button> -->
<div class="equipment-slot">
<Card v-if="my_role" :card="my_role" class="back"
<Card v-if="my_role" :card="my_role" class="back" style="transform:rotate(-2deg)"
@pointerenter.native="desc=($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" @pointerleave.native="desc=''"/>
<Card v-if="character" :card="character" style="margin-left: -30pt;margin-right: 0pt;"
@pointerenter.native="setDesc(character)" @pointerleave.native="desc=''"/>
<transition-group name="list" tag="div" style="display: flex;flex-direction:column; justify-content: space-evenly; margin-left: 12pt;margin-right:-10pt;">
<span v-for="(n, i) in lives" v-bind:key="i" :alt="i"></span>
<span v-for="(n, i) in (max_lives-lives)" v-bind:key="`${i}-sk`" :alt="i">💀</span>
<span v-for="(n, i) in lives" v-bind:key="i" :alt="i"></span>
</transition-group>
<transition-group v-if="lives > 0 || is_ghost" name="list" tag="div" style="margin: 0 0 0 10pt; display:flex;">
<Card v-for="card in equipment" v-bind:key="card.name+card.number" :card="card"
<div v-if="gold_nuggets > 0" style="position:relative;left:-90pt;top:65pt;justify-content: space-evenly;width: 25pt;">
<h3 style="background:gold;border-radius:15pt;padding:2pt 2pt;color:black;text-align:center"> 💵 {{ gold_nuggets }} </h3>
</div>
<transition-group v-if="lives > 0 || is_ghost" name="list" id="equipment" tag="div" style="margin: 0 0 0 10pt; display:flex;">
<Card v-for="card in equipmentComputed" v-bind:key="card.name+card.number" :card="card"
@pointerenter.native="setDesc(card)" @pointerleave.native="desc=''"
@click.native="play_card(card, true)" :class="{'cant-play':((eventCard && eventCard.name == 'Lazo') || !card.can_be_used_now)}"/>
@click.native="play_card(card, true)" :class="{'cant-play':((eventCard && eventCard.name == 'Lazo') || (!card.can_be_used_now && !card.is_equipment))}"/>
</transition-group>
</div>
<transition name="list">
<p v-if="desc"><i>{{desc}}</i></p>
</transition>
<button v-if="is_my_turn && character.name === 'Sid Ketchum' && lives < max_lives && hand.length > 1" @click="sidWantsScrapForHealth=true">{{$t('special_ability')}}</button>
<button v-if="is_my_turn && character.name === 'Chuck Wengam' && lives > 1" @click="chuckSpecial">{{$t('special_ability')}}</button>
<button v-if="is_my_turn && character.name === 'José Delgrado' && special_use_count < 2 && hand.filter(x => x.is_equipment).length > 0" @click="joseScrap=true">{{$t('special_ability')}}</button>
<button v-if="is_my_turn && character.name === 'Doc Holyday' && special_use_count < 1 && hand.length > 1" @click="holydayScrap=true">{{$t('special_ability')}}</button>
<div style="margin-bottom:6pt;margin-bottom: 6pt;display: flex;flex-direction: column;">
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Sid Ketchum' && lives < max_lives && hand.length > 1" @click="sidWantsScrapForHealth=true">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Chuck Wengam' && lives > 1" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'José Delgado' && special_use_count < 2 && hand.filter(x => x.is_equipment).length > 0" @click="joseScrap=true">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Doc Holyday' && special_use_count < 1 && hand.length > 1" @click="holydayScrap=true">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Jacky Murieta' && gold_nuggets >=2" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Josh McCloud' && gold_nuggets >=2" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Raddie Snake' && special_use_count < 2 && gold_nuggets >=1" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Der Spot Burst Ringer' && special_use_count < 1" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Black Flower' && special_use_count < 1" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Flint Westwood' && special_use_count < 1" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
<button :class="{'btn': true, 'cant-play':(pending_action != 2)}" :disabled="pending_action != 2" v-if="!(eventCard && eventCard.name == 'Sbornia') && is_my_turn && character.name === 'Lee Van Kliff' && special_use_count < 1" @click="()=>{$socket.emit('special', {})}">{{$t('special_ability')}}</button>
</div>
<div v-if="lives > 0 || is_ghost" style="position:relative">
<span id="hand_text">{{$t('hand')}}</span>
<span id="hand_text" style="bottom:40pt;">{{hand.length}}/{{maxHandLength()}}</span>
<transition-group name="list" tag="div" :class="{hand:true, 'play-cards':pending_action===2}">
<Card v-for="card in handComputed" v-bind:key="card.name+card.number" :card="card"
<Card v-for="card in handComputed" v-bind:key="card.name+card.number+card.suit" :card="card"
@click.native="play_card(card, false)"
@pointerenter.native="setHint(card)" @pointerleave.native="hint=''"
:class="{'cant-play':card.cantBePlayed}"/>
@ -37,18 +50,19 @@
<p v-if="hint"><i>{{hint}}</i></p>
</transition>
<Chooser v-if="is_my_turn && pending_action == 4 && (lives > 0 || is_ghost) && !(emporioCards && emporioCards.cards && emporioCards.cards.length > 0)" :text="$t('wait')" :cards="[]"/>
<Chooser v-if="card_against" :text="$t('card_against')" :hint-text="visiblePlayers.length === 0 ? $t('no_players_in_range'):''" :cards="visiblePlayers" :select="selectAgainst" :cancel="cancelCardAgainst"/>
<Chooser v-if="pending_action == 3" :text="respondText" :cards="respondCards" :select="respond" :playAudio="true"/>
<Chooser v-if="shouldChooseCard" :text="$t(choose_text)" :cards="available_cards" :select="choose" :playAudio="true"/>
<Chooser v-if="card_against" :text="$t('card_against')" :hint-text="visiblePlayers.length === 0 ? $t('no_players_in_range'):''" :cards="visiblePlayers" :select="selectAgainst" :cancel="card_against.number !== 42 ? cancelCardAgainst : null"/>
<Chooser v-if="pending_action == 3" :text="respondText" :cards="respondCards" :select="respond" :playAudio="true" :timer="30"/>
<Chooser v-if="shouldChooseCard" :text="$t(choose_text)" :cards="available_cards" :select="choose" :playAudio="true" :timer="30"/>
<Chooser v-if="lives <= 0 && max_lives > 0 && !is_ghost && !spectator" :text="$t('you_died')" :cancelText="$t('spectate')" :cancel="()=>{max_lives = 0; spectator = true}"/>
<Chooser v-if="win_status !== undefined" :text="win_status?$t('you_win'):$t('you_lose')" />
<Chooser v-if="show_role" :text="$t('you_are')" :cards="[my_role]" :hintText="($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" :select="() => {show_role=false}" :cancel="() => {show_role=false}" :cancelText="$t('ok')" />
<Chooser v-if="show_role" :text="$t('you_are')" :cards="[my_role]" :hintText="($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" :select="() => {show_role=false}" :cancel="() => {show_role=false}" :cancelText="$t('ok')"/>
<Chooser v-if="notifycard" :key="notifycard.card" :text="`${notifycard.player} ${$t('did_pick_as')}:`" :cards="[notifycard.card]" :hintText="$t(notifycard.message)" class="turn-notify-4s"/>
<Chooser v-if="cantplaycard" :key="cantplaycard" :text="`${$t('cantplaycard')}`" class="turn-notify-4s"/>
<Chooser v-if="!show_role && is_my_turn && pending_action < 2" :text="$t('play_your_turn')" :key="is_my_turn" class="turn-notify" />
<Chooser v-if="!show_role && availableCharacters.length > 0" :text="$t('choose_character')" :cards="availableCharacters" :select="setCharacter"/>
<Chooser v-if="!show_role && availableCharacters.length > 0" :text="$t('choose_character')" :cards="availableCharacters" :select="setCharacter" :timer="45"/>
<Chooser v-if="hasToPickResponse" :playAudio="true" :text="`${$t('pick_a_card')} ${attacker?($t('to_defend_from')+' '+attacker):''}`" :key="hasToPickResponse" class="turn-notify" />
<Chooser v-if="!card_against && card_with" :text="`${$t('choose_scarp_card_to')} ${card_with.name.toUpperCase()}`" :cards="handComputed.filter(x => x !== card_with)" :select="selectWith" :cancel="()=>{card_with = null}"/>
<Chooser v-if="showScrapScreen" :text="`${$t('discard')} ${hand.length}/${lives}`" :cards="hand" :select="scrap" :cancel="cancelEndingTurn"/>
<Chooser v-if="!card_against && card_with" :text="`${$t('choose_scarp_card_to')} ${card_with.name.toUpperCase()}`" :cards="handComputed.filter(x => x !== card_with && (x.name.indexOf(card_with.need_with_only) > -1))" :select="selectWith" :cancel="()=>{card_with = null}"/>
<Chooser v-if="showScrapScreen" :text="`${$t('discard')} ${hand.length}/${maxHandLength()}`" :cards="hand" :select="scrap" :cancel="cancelEndingTurn"/>
<Chooser v-if="sidWantsScrapForHealth && scrapHand.length < 2" :text="`${$t('discard')} ${2 - scrapHand.length} ${$t('to_regain_1_hp')}`"
:cards="notScrappedHand" :select="sidScrap" :cancel="() => {sidWantsScrapForHealth = false;scrapHand=[]}"/>
<Chooser v-if="joseScrap" :text="`${$t('discard')}`"
@ -56,7 +70,8 @@
<Chooser v-if="holydayScrap && scrapHand.length < 2" :text="`${$t('discard')} ${2 - scrapHand.length}`"
:cards="notScrappedHand" :select="holydayScrapAdd" :cancel="() => {holydayScrap = false;scrapHand=[]}"/>
<Chooser v-if="holydayScrap && scrapHand.length == 2" :text="$t('card_against')" :cards="visiblePlayers" :select="holydayScrapBang" :cancel="() => {holydayScrap = false;scrapHand=[]}"/>
<Chooser style="filter: grayscale(1);" v-if="emporioCards && emporioCards.cards && emporioCards.cards.length > 0 && pending_action === 4" :text="$t('emporio_others', [emporioCards.name])" :cards="emporioCards.cards"/>
<Chooser style="filter: grayscale(1);" v-if="emporioCards && emporioCards.cards && emporioCards.cards.length > 0 && (pending_action === 4 || pending_action === null)" :text="$t('emporio_others', [emporioCards.name])" :cards="emporioCards.cards"/>
<div style="position: fixed;width: 100%;height: 100%;background: #ff000070;top: 0;left: 0;" v-if="hurt" class="hurt-notify"/>
</div>
</template>
@ -81,6 +96,7 @@ export default {
character: null,
availableCharacters: [],
equipment: [],
gold_rush_equipment: [],
hand: [],
lives: 0,
max_lives: 0,
@ -97,9 +113,12 @@ export default {
win_status: undefined,
range: 1,
sight: 1,
sight_extra: 1,
norangecard: false,
can_target_sheriff: true,
show_role: false,
attacker: undefined,
attacking_card: undefined,
notifycard: null,
desc: '',
scrapHand: [],
@ -114,6 +133,12 @@ export default {
eventCard: false,
emporioCards: {},
spectator: false,
noStar: false,
committed_suit_manette: null,
gold_nuggets: 0,
cantplaycard: false,
avatar: '',
hurt: false,
}),
sockets: {
role(role) {
@ -130,26 +155,34 @@ export default {
self(self) {
self = JSON.parse(self)
this.name = self.name
this.avatar = self.avatar
this.pending_action = self.pending_action
this.character = self.character
this.character.is_character = true
if (this.character != null) {
this.character.is_character = true
}
this.hand = self.hand
this.equipment = self.equipment
this.gold_rush_equipment = self.gold_rush_equipment
this.lives = self.lives
this.max_lives = self.max_lives
this.has_played_bang = self.has_played_bang
this.special_use_count = self.special_use_count
this.choose_text = self.choose_text
this.choose_text = self.choose_text.split('|')[0]
this.is_my_turn = self.is_my_turn
this.committed_suit_manette = self.committed_suit_manette
if (this.is_my_turn) document.title = this.$t('your_turn')+' | PewPew!'
else if (this.pending_action == 3) document.title = this.$t('your_response')+' | PewPew!'
else if (this.pending_action == 5) document.title = this.$t('your_choose')+' | PewPew!'
else document.title = 'PewPew!'
if ((this.live > 0 || this.is_ghost) && this.spectator) this.spectator = false
this.expected_response = self.expected_response
this.available_cards = self.available_cards
this.win_status = self.win_status
this.sight = self.sight
this.sight_extra = self.sight_extra
this.attacker = self.attacker
this.attacking_card = self.attacking_card
this.mancato_needed = self.mancato_needed
this.is_ghost = self.is_ghost
if (this.pending_action == 5 && self.target_p) {
@ -160,6 +193,12 @@ export default {
this.cancelChooseCardFromPlayer()
this.shouldChooseCard = false
}
this.noStar = self.noStar
this.gold_nuggets = self.gold_nuggets
let mustplay = this.handComputed.filter(x => x.number == 42);
if (mustplay.length > 0) {
this.play_card(mustplay[0], false)
}
},
self_vis(vis) {
// console.log('received visibility update')
@ -172,13 +211,26 @@ export default {
this.notifycard = null
}.bind(this), 4000)
},
hurt() {
this.hurt = true
setTimeout(function(){
this.hurt = false
}.bind(this), 500)
},
cant_play_card() {
this.cantplaycard = true
setTimeout(function(){
this.cantplaycard = false
}.bind(this), 1000)
},
event_card(card) {
this.eventCard = card
},
},
computed:{
respondText() {
return `${this.$t('choose_response')}${this.attacker?(this.$t('choose_response_to')+this.attacker):''}${(this.mancato_needed>1)?(` (${this.$t('choose_response_needed')} ` + this.mancato_needed + ')'):''}`
let attCard = this.attacking_card ? ' ('+this.$t('cards.'+this.attacking_card+'.name')+')' : '';
return `${this.$t('choose_response')}${this.attacker?(this.$t('choose_response_to')+this.attacker+attCard):''}${(this.mancato_needed>1)?(` (${this.$t('choose_response_needed')} ` + this.mancato_needed + ')'):''}`
},
showScrapScreen() {
return this.isEndingTurn && !this.canEndTurn && this.is_my_turn;
@ -193,8 +245,10 @@ export default {
return {
name: player.name,
number: player.dist !== undefined ? `${player.dist}` : '',
icon: player.is_sheriff ? '⭐' : '🤠',
icon: this.noStar ? player.icon : player.is_sheriff ? '⭐' : '🤠',
avatar: player.avatar,
is_character: true,
is_player: true
}})
return vis
},
@ -204,21 +258,30 @@ export default {
if (!this.can_target_sheriff && x.is_sheriff)
return false
else
return x.dist <= this.range
//console.log(x.name +" dist:" +x.dist +" range:" +this.range +" sight:" +this.sight +" sight_extra:" +this.sight_extra)
if (this.norangecard)
return x.dist <= this.range
else
return x.dist <= this.range + this.sight_extra
}).map(player => {
return {
name: player.name,
number: player.dist !== undefined ? `${player.dist}` : '',
icon: player.is_sheriff ? '⭐' : '🤠',
icon: this.noStar ? player.icon : player.is_sheriff ? '⭐' : '🤠',
alt_text: Array(player.lives+1).join('❤️')+Array(player.max_lives-player.lives+1).join('💀'),
avatar: player.avatar,
is_character: true,
is_player: true
}})
if (this.card_against && this.card_against.can_target_self) {
if (this.card_against && this.card_against.can_target_self && (this.equipment.length > 0 || this.card_against.name === 'Tequila')) {
vis.push({
name: this.name,
number: 0,
icon: this.$t('you'),
number: '0⛰',
alt_text: this.$t('you'),
avatar: this.avatar,
icon: '🤳',
is_character: true,
is_player: true
})
}
return vis
@ -233,15 +296,18 @@ export default {
return x[this.pending_action]
},
canEndTurn() {
return (this.pending_action == 2 && this.hand.length <= (this.character.name === "Sean Mallory" && !(this.eventCard && this.eventCard.name == "Sbornia")?10:this.lives))
return (this.pending_action == 2 && this.hand.length <= this.maxHandLength())
},
respondCards() {
let cc = [{
name: this.$t('take_dmg'),
icon: '❌',
is_equipment: true,
noDesc: true,
}]
this.hand.filter(x => x.can_be_used_now && this.expected_response.indexOf(x.name) !== -1).forEach(x=>{
let expectedBangResponse = this.expected_response.indexOf('Bang!') !== -1
let sborniaEvent = this.eventCard && this.eventCard.name == "Sbornia"
this.hand.filter(x => (x.can_be_used_now && this.expected_response.indexOf(x.name) !== -1) || (!expectedBangResponse && this.character.name === "Elena Fuente" && !sborniaEvent)).forEach(x=>{
cc.push(x)
})
this.equipment.filter(x => x.usable_next_turn && x.can_be_used_now && this.expected_response.indexOf(x.name) !== -1).forEach(x=>{
@ -249,15 +315,22 @@ export default {
})
return cc
},
equipmentComputed() {
let eq = []
this.equipment.forEach(x => eq.push(x));
this.gold_rush_equipment.forEach(x => eq.push(x));
return eq
},
handComputed() {
return this.hand.map(x=> {
return this.hand.map(x => {
let cantBePlayed = false
let calamity_special = (x.name === 'Mancato!' && this.character.name === 'Calamity Janet')
let cant_play_bang = (this.has_played_bang && this.equipment.filter(x => x.name == 'Volcanic').length == 0)
if ((x.name == 'Bang!' || (calamity_special && x.name=='Mancato!')) && (cant_play_bang || (this.eventCard && this.eventCard.name == "Sermone"))) cantBePlayed = true;
if ((x.name == 'Bang!' || x.name == 'Sventagliata' || (calamity_special && x.name=='Mancato!')) && (cant_play_bang || (this.eventCard && this.eventCard.name == "Sermone"))) cantBePlayed = true;
else if (this.eventCard && this.eventCard.name == "Il Giudice" && (x.is_equipment || !x.can_be_used_now)) cantBePlayed = true;
else if (this.eventCard && this.eventCard.name == "Il Reverendo" && (x.name == "Birra")) cantBePlayed = true;
else if (this.need_with && this.hand.length === 1) cantBePlayed = true;
else if (this.committed_suit_manette !== null && this.committed_suit_manette !== x.suit) cantBePlayed = true;
return {
...x,
cantBePlayed: cantBePlayed
@ -266,6 +339,9 @@ export default {
}
},
methods: {
maxHandLength() {
return (this.character.name === "Sean Mallory" && !(this.eventCard && this.eventCard.name == "Sbornia")?10:(this.gold_rush_equipment.filter(x => x.name == 'Cinturone').length>0?8:this.lives))
},
setCharacter(char) {
this.availableCharacters = []
this.$socket.emit('set_character', char.name)
@ -273,7 +349,7 @@ export default {
sidScrap(c) {
this.scrapHand.push(this.hand.indexOf(c))
if (this.scrapHand.length == 2) {
let x = [this.hand.indexOf(this.scrapHand[0]), this.hand.indexOf(this.scrapHand[1])].sort().reverse()
let x = [this.scrapHand[0], this.scrapHand[1]].sort().reverse()
this.$socket.emit('scrap', x[0])
this.$socket.emit('scrap', x[1])
this.scrapHand = []
@ -296,16 +372,13 @@ export default {
this.scrapHand.push(this.hand.indexOf(c))
},
holydayScrapBang(other) {
this.$socket.emit('holyday_special', {
cards : [this.hand.indexOf(this.scrapHand[0]), this.hand.indexOf(this.scrapHand[1])],
this.$socket.emit('special', {
cards : [this.scrapHand[0], this.scrapHand[1]],
against: other.name
})
this.scrapHand = []
this.holydayScrap = false
},
chuckSpecial(){
this.$socket.emit('chuck_lose_hp_draw')
},
end_turn(){
// console.log('ending turn')
this.cancelEndingTurn()
@ -315,19 +388,23 @@ export default {
this.$socket.emit('scrap', this.hand.indexOf(c))
},
play_card(card, from_equipment) {
if (from_equipment && (!card.usable_next_turn || !card.can_be_used_now)) return;
console.log('play ' + card.name)
if (from_equipment && ((!card.can_be_used_now && !card.name == 'Lemat') || (this.eventCard && this.eventCard.name == "Lazo"))) return;
else if (card.usable_next_turn && !card.can_be_used_now) return this.really_play_card(card, null);
let calamity_special = (card.name === 'Mancato!' && this.character.name === 'Calamity Janet')
let cant_play_bang = (this.has_played_bang && this.equipment.filter(x => x.name == 'Volcanic').length == 0)
let cant_play_bang = (this.has_played_bang && card.number !==42 && this.equipment.filter(x => x.name == 'Volcanic').length == 0)
if (this.pending_action == 2) {
this.can_target_sheriff = (card.name !== 'Prigione')
if (card.need_with && !this.card_with) {
this.card_with = card
} else if ((card.need_target || calamity_special) && !((card.name == 'Bang!' || (calamity_special && card.name=='Mancato!')) && cant_play_bang)) {
if (card.name == 'Bang!' || card.name == "Pepperbox" || calamity_special)
if (card.name == 'Bang!' || card.name == "Pepperbox" || calamity_special) {
this.range = this.sight
else
this.norangecard = true
} else {
this.range = card.range
this.norangecard = false
}
if (this.visiblePlayers.length == 0 && this.hand.length > this.lives) {
this.really_play_card(card, null)
}
@ -353,6 +430,7 @@ export default {
if (this.card_with.need_target) {
this.card_against = this.card_with
this.range = this.card_against.range
this.norangecard = false
this.card_with = card
} else {
let card_data = {
@ -371,7 +449,7 @@ export default {
really_play_card(card, against) {
let res = this.handComputed.indexOf(card)
if (res === -1) {
res = this.equipment.indexOf(card)
res = this.equipmentComputed.indexOf(card)
if (res !== -1) res += this.hand.length
}
let card_data = {
@ -418,11 +496,11 @@ export default {
.hand {
position: relative;
display:flex;
border: 2px dashed #ccc;
border: 2px dashed var(--muted-color);
padding: 10pt 40pt 0pt 40pt;
overflow:auto;
border-radius: 4pt;
min-height: 40pt;
min-height: 122pt;
}
@media not all and (min-resolution:.001dpcm)
{ @supports (-webkit-appearance:none) and (stroke-color:transparent) {
@ -435,13 +513,18 @@ export default {
margin-left: -30pt;
}
.hand>.card:hover {
margin-right:35pt;
transform: translateY(-15px);
transform: translateY(-15px) translateX(-15px) rotate(-2deg);
z-index: 1;
}
.hand>.card:nth-child(1):hover, .hand>.card:last-child:hover {
transform: translateY(-15px) translateX(0) rotate(2deg);
z-index: 1;
}
#hand_text{
color: #ccc;
color: var(--muted-color);
position: absolute;
font-size: xxx-large;
font-size: -webkit-xxx-large;
font-weight: 300;
bottom: 0;
right: 10pt;
@ -451,6 +534,16 @@ export default {
margin: 10pt 0pt;
overflow:auto;
}
#equipment .card:nth-child(even) {
transform: rotate(1deg);
}
#equipment .card:nth-child(odd) {
transform: rotate(-1deg);
}
.hurt-notify {
pointer-events: none;
animation: disappear 0.5s ease-in forwards;
}
.turn-notify {
pointer-events: none;
animation: disappear 2s ease-in forwards;

View File

@ -0,0 +1,126 @@
<template>
<div>
<div :class="{stationcard:true, 'cant-play':!trainPiece || trainPiece.is_locomotive}">
<h4>{{ cardName }}</h4>
<div :class="{ emoji: true, bottomed: card.avatar }">{{ emoji }}</div>
<div class="alt_text">{{ card.alt_text }}</div>
<div class="price">
<card v-for="c, i in price" :key="i" :card="c"/>
</div>
</div>
<card v-if="trainPiece" :card="trainPiece" :class="{'cant-play':trainPiece.is_locomotive}"/>
</div>
</template>
<script>
import Card from '@/components/Card.vue'
export default {
name: "StationCard",
props: {
card: Object,
price: Array,
trainPiece: Object,
donotlocalize: Boolean,
},
components: {
Card
},
computed: {
cardName() {
if (
!this.donotlocalize &&
this.$t(`cards.${this.card.name}.name`) !==
`cards.${this.card.name}.name`
) {
return this.$t(`cards.${this.card.name}.name`);
}
if (this.card.name == "you") {
return this.$t("you");
}
return this.card.name;
},
emoji() {
return this.card.icon != "you" ? this.card.icon : this.$t("you");
},
suit() {
if (this.card && !isNaN(this.card.suit)) {
let x = ["♦️", "♣️", "♥️", "♠️", "🤑", "🚂"];
return x[this.card.suit];
} else if (this.card.suit) {
return this.card.suit;
}
return "";
},
number() {
if (isNaN(this.card.suit)) return this.card.number;
if (this.card.number === 1) return "A";
else if (this.card.number === 11) return "J";
else if (this.card.number === 12) return "Q";
else if (this.card.number === 13) return "K";
else return this.card.number;
},
},
};
</script>
<style scoped>
.stationcard {
cursor: pointer;
width: 60pt;
min-width: 60pt;
height: 60pt;
margin: 6pt;
border-radius: 16pt 16pt 2pt 2pt;
position: relative;
transition: all 0.5s ease-in-out;
text-overflow: ellipsis;
word-wrap: normal;
color: white;
background: repeating-linear-gradient(
0deg,
rgb(198 78 45),
rgb(198 78 45) 5px,
rgb(178 58 25) 5px,
rgb(178 58 25) 10px
);
border: 2pt solid rgb(198 78 45);
box-shadow: 0 0 0pt 2pt var(--font-color), 0 0 5pt 2pt #aaa;
}
.stationcard h4 {
position: absolute;
text-align: center;
width: 100%;
top: -15pt;
font-size: 10pt;
}
.alt_text {
right: 3pt;
text-align: center;
position: absolute;
font-size: small;
bottom: 20pt;
left: 3pt;
}
.stationcard .price {
justify-content: center;
/* left: -12pt; */
margin-top: -20pt;
/* left: 0; */
display: flex;
width: 60pt;
transform: scale(0.3);
}
.price .card {
transform: rotate(14deg);
}
.train-piece {
margin: 6pt;
}
.cant-play {
cursor: not-allowed;
}
.stationcard .card {
cursor: unset;
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<div>
<h1 id="status">PewPew! Server Status</h1>
<h2>Rooms {{rooms.length}}</h2>
<button @click="refresh">reload</button>
<button @click="reset">RESET</button>
<ul>
<li v-for="r in rooms" :key="r">
<p style="margin:0"><b>name:</b> {{r.name}}</p>
<p style="margin:0"><b>hidden:</b> {{r.hidden}}</p>
<button @click="hide(r.name)">toggle hide</button>
<p style="margin:0"><b>password:</b> {{r.password}}</p>
<p style="margin:0"><b>mods:</b> {{r.expansions}}</p>
<p style="margin:0"><b>started:</b> {{r.started}}</p>
<p style="margin:0"><b>turn:</b> {{r.current_turn}}</p>
<p style="margin:0"><b>incremental_turn:</b> {{r.incremental_turn}}</p>
<p style="margin:0"><b>debug:</b> {{r.debug}}</p>
<p style="margin:0"><b>spectators:</b> {{r.spectators}}</p>
<p style="margin:0"><b>players:</b></p>
<ul style="margin:0">
<li v-for="p in r.players" :key="p">
<p style="margin:0"><b>name:</b> {{p.name}}</p>
<p style="margin:0"><b>is_bot:</b> {{p.bot}}</p>
<p style="margin:0"><b>health:</b> {{p.health}}</p>
<p style="margin:0"><b>sid:</b> {{p.sid}}</p>
<button v-if="!p.bot" @click="kick(p.sid)">Kick</button>
</li>
</ul>
<br>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Status',
components: {
},
props: {
onpage: {
type: Boolean,
default: true
}
},
data:()=>({
rooms: [],
deploy_key: ''
}),
computed: {
},
sockets: {
all_rooms(data) {
this.rooms = data;
},
},
mounted() {
if (this.deploy_key == "" && this.onpage)
this.deploy_key = prompt('Write the key');
this.refresh();
},
methods: {
refresh(){
this.$socket.emit('get_all_rooms', this.deploy_key)
},
reset(){
if (confirm('ARE YOU SURE? KICK EVERYONE AND RESET LOBBIES?'))
this.$socket.emit('reset', {'key':this.deploy_key})
this.refresh();
},
hide(room_name){
this.$socket.emit('hide_toogle', {'key':this.deploy_key, 'room':room_name})
setTimeout((()=>{
this.refresh()
}).bind(this), 500)
},
kick(sid){
this.$socket.emit('kick', {'key':this.deploy_key, 'sid':sid})
setTimeout((()=>{
this.refresh()
}).bind(this), 500)
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,20 +1,30 @@
<template>
<div style="position:absolute;transform:scale(0.4);bottom:52pt;">
<div :class="{card:true, back:true, delay:ismyturn}" v-for="(n, i) in ncards"
:style="`position:absolute; transform:rotate(${(i-ncards/2)*2}deg) translate(${i*15}px,0); animation-delay:${0.1*i}s`"
v-bind:key="n" :alt="i">
<h4 v-if="n==ncards">PewPew!</h4>
<div class="emoji" v-if="n==ncards">💥</div>
<div v-if="!(cards && cards.length >0)">
<div :class="{card:true, back:true, delay:ismyturn}" v-for="(n, i) in ncards"
:style="`position:absolute; transform:rotate(${(i-ncards/2)*2}deg) translate(${i*15}px,0); animation-delay:${0.1*i}s`"
v-bind:key="n" :alt="i">
<h4 v-if="n==ncards">PewPew!</h4>
<div class="emoji" v-if="n==ncards">💥</div>
</div>
</div>
<div v-else>
<card :card="c" :key="c" v-for="(c, i) in cards"
:class="{delay:ismyturn, zoomable:true}"
:style="`position:absolute; transform:rotate(${(i-ncards/2)*5}deg) translate(${(i-ncards/3)*40}px,0); animation-delay:${0.1*i}s`"/>
</div>
</div>
</template>
<script>
import Card from './Card.vue'
export default {
components: { Card },
name: 'TinyHand',
props: {
ncards: Number,
ismyturn: Boolean
cards: Array,
ismyturn: Boolean,
},
}
</script>
@ -24,6 +34,9 @@ export default {
animation-duration: 2s;
animation-iteration-count: infinite;
}
.zoomable:hover {
z-index: 1;
}
@keyframes updown {
0% {
top: 0;

918
frontend/src/i18n/cs.json Normal file
View File

@ -0,0 +1,918 @@
{
"trademark": "Bang! je ochranná známka vlastněná DVGiochi",
"tip_1": "Lepší s přáteli!",
"tip_2": "Ikonka 🤖️ znamená, že hráč je bot!",
"tip_3": "Klikněte na karty postav a vybavení ostatních hráčů, pokud chcete vědět více!",
"tip_4": "Obsahuje Dodge City, High Noon, Fistful Of Cards!",
"tip_5": "Našli jste chybu? Napište nám na Discord!",
"tip_6": "Nyní máme Discord server!",
"tip_7": "Chcete nám pomoci s překladem hry do vašeho jazyka? Napište nám na Discord!",
"tip_8": "Pokud se během hry odpojíte, budete nahrazeni botem (dokud se nevrátíte)!",
"tip_9": "Pokud jste na mobilu, podržte kartu, abyste si přečetli popis!",
"tip_10": "Pokud si nejste jistí, střílejte na všechny ostatní hráče!",
"online_players": "Hráči online: ",
"shuffle_players": "Přeskupit hráče",
"choose_username": "Vyberte si uživatelské jméno:",
"report_bug": "Popište chybu",
"report": "Nahlásit chybu",
"available_lobbies": "Dostupné místnosti:",
"spectate_lobbies": "Sledovat probíhající hry:",
"no_lobby_available": "Žádné dostupné místnosti",
"create_lobby": "Vytvořit místnost:",
"characters_to_distribute": "Postavy k rozdělení: ",
"lobby_name": "Název:",
"leave_room": "Opustit místnost",
"warning": "Varování!",
"connection_error": "Nelze se připojit k serveru.",
"end_turn": "Konec tahu!",
"start_game": "Začít!",
"expansions": "Rozšíření",
"click_to_toggle": "Klikněte pro přepnutí",
"details": "Podrobnosti",
"ok": "OK",
"you": "VY",
"owner": "MAJITEL",
"cancel": "ZRUŠIT",
"send": "ODESLAT",
"password": "Heslo: ",
"room_password_prompt": "Heslo místnosti: ",
"private_room": "Soukromá místnost",
"room": "Místnost: ",
"room_players": "Hráči (jste {username})",
"choose_character": "Vyberte si svou postavu",
"choose_card": "Vyberte kartu",
"choose_card_from": " z ",
"flip_card": "↙️ Otočit kartu",
"draw_cards": "⏬ Vytáhněte své karty z balíčku",
"play_cards": "▶️ Hrajte své karty",
"respond_card": "↩️ Odpovězte na kartu",
"wait": "⏸ Počkejte",
"choose_cards": "🔽 Vyberte kartu",
"take_dmg": "Utrpět poškození",
"choose_response": "Vyberte svou odpověď ",
"choose_response_to": "na ",
"choose_response_needed": "POTŘEBNÉ ",
"choose_manette": "Vyberte si barvu, můžete hrát pouze karty této barvy v tomto tahu.",
"hand": "RUKA",
"card_against": "Proti komu budete hrát kartu?",
"choose_sid_scrap": "Odhoďte 2 karty, abyste nezemřeli",
"choose_card_to_get": "Vyberte kartu",
"choose_guess": "Hádáte barvu karty",
"choose_ranch": "Vyberte karty k výměně",
"choose_dalton": "Vyberte, které vybavení odhodit",
"choose_fratelli_di_sangue": "Vyberte, komu chcete darovat jeden svůj život",
"choose_fantasma": "Vyberte, koho přivést zpět k životu",
"choose_sventagliata": "Vyberte jiný cíl pro Fanning",
"choose_tornado": "Vyberte kartu k odhození do tornáda",
"choose_bandidos": "Vyberte mezi odhozením 2 karet nebo ztrátou života (1 karta, pokud máte pouze 1)",
"choose_poker": "Každý odhodí 1 kartu (pokud není žádný eso, hráč, který hrál poker, si vybere 2 karty)",
"choose_from_poker;2": "Vyberte karty k získání (max 2)",
"choose_from_poker;1": "Vyberte kartu k získání",
"choose_cecchino": "Vyberte, na koho střílet",
"choose_rimbalzo_player": "Vyberte cíl pro odraženou střelu",
"choose_rimbalzo_card": "Vyberte kartu k odhození odražené střely",
"choose_nuova_identita": "Vyberte, zda chcete ponechat svou současnou postavu, nebo ji změnit a začít s 2 životy",
"choose_bicchierino": "Hráč podle vašeho výběru získá 1 život",
"choose_bottiglia": "Vyberte, jak hrát Láhev!",
"choose_complice": "Vyberte, jak hrát Komplic!",
"choose_ricercato": "Vyberte, proti komu hrát Hledaný.",
"choose_birra_function": "Vyberte mezi získáním 1 zlatého nugetu za odhození piva nebo hraním piva.",
"choose_play_as_bang": "Vyberte, kterou kartu hrát jako Bang!",
"choose_flint_special": "Vyberte, kterou kartu vyměnit.",
"emporio_others": "{0} vybírá, kterou kartu si vzít z Obecného obchodu",
"you_died": "ZEMŘELI JSTE",
"spectate": "SLEDOVAT",
"you_win": "VYHRÁLI JSTE",
"you_lose": "PROHRÁLI JSTE",
"special_ability": "ZVLÁŠTNÍ SCHOPNOST",
"gold_rush_discard": "Odhodit vybavení zlaté horečky jiného hráče (platí cenu + 1)",
"gold_rush_discard_2": "Odhodit vybavení zlaté horečky jiného hráče (platí cenu + 1)",
"discard": "ODHODIT",
"to_regain_1_hp": "ZÍSKAT 1 ŽIVOT",
"play_your_turn": "HRAJTE SVŮJ TAH",
"you_are": "Jste",
"did_pick_as": "vybral jako druhou kartu",
"blackjack_special": "Pokud je karta křížová nebo srdcová, vezme si další kartu.",
"choose_scarp_card_to": "VYBERTE KARTU K ODHODENÍ K POUŽITÍ",
"pick_a_card": "OTEVŘÍT KARTU",
"to_defend_from": "K OBRANĚ PŘED",
"submit": "Odeslat",
"copy": "Kopírovat pozvánku",
"no_players_in_range": "Nevidíte ostatní hráče, vybavte zbraň nebo dalekohled!",
"cantplaycard": "Nemůžete tuto kartu hrát takto!",
"chat": {
"spectators": " | Divák sleduje hru | {n} diváků sleduje hru",
"chat": "Chat",
"joined": "👋 ;{0}; se připojil do místnosti",
"died": "☠️ ;{0}; zemřel",
"died_role": "☠️ ;{0}; byl ;{1};!",
"won": "🏆 ;{0}; vyhrál! Jeho role byla ;{1};",
"choose_character": ";{0}; má ;{1}; jako postavu, jeho zvláštní schopnost je: ;{2};!",
"starting": "Hra začíná!",
"sheriff": "⭐ ;{0}; je šerif!",
"did_choose_character": ";{0}; si vybral postavu.",
"turn": "⏩ Nyní je tah ;{0};.",
"draw_from_scrap": ";{0}; vzal první kartu z odhazovacího balíčku.",
"draw_from_player": ";{0}; vzal první kartu z ruky ;{1};.",
"flipped": ";{0}; otočil ;{1}; ;{2};.",
"scrapped": ";{0}; odhodil ;{1}; ;{2};.",
"explode": "💥 ;{0}; odpálil dynamit.",
"beer_save": ";{0}; použil pivo k záchraně svého života.",
"get_nugget": ";{0}; získal zlatý nuget použitím Piva.",
"play_card": ";{0}; zahrál ;{1};.",
"play_card_green": ";{0}; uvedl do hry ;{1};.",
"play_card_with": ";{0}; zahrál ;{1};, odhodil ;{2};.",
"purchase_card": ";{0}; koupil ;{1};.",
"play_card_against": ";{0}; zahrál ;{1}; proti ;{2};.",
"play_card_against_with": ";{0}; zahrál ;{1}; proti ;{2};, odhodil ;{3};.",
"play_card_for": ";{0}; zahrál ;{1}; pro ;{2};.",
"spilled_beer": ";{0}; rozlil ;{1};.",
"diligenza": ";{0}; zahrál ;{1}; a vzal 2 karty.",
"wellsfargo": ";{0}; zahrál ;{1}; a vzal 3 karty.",
"saloon": "🍻 ;{0}; zahrál ;{1}; a vyléčil 1 HP všem živým.",
"special_bart_cassidy": ";{0}; dostal kompenzaci, protože byl zraněn.",
"special_el_gringo": ";{0}; ukradl kartu od ;{1};, když byl zraněn.",
"special_calamity": ";{0}; zahrál ;{1}; jako Bang! proti ;{2};.",
"allroles3": "Ve hře jsou: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};.",
"allroles4": "Ve hře jsou: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};, ;{7}; ;{6};.",
"guess": "🤔 ;{0}; hádá ;{1};.",
"guess_right": ";{0}; měl pravdu.",
"guess_wrong": ";{0}; se mýlil.",
"fratelli_sangue": ";{0}; dal jeden ze svých životů ;{1};.",
"doctor_heal": ";{0}; byl vyléčen doktorem.",
"respond": "↩️ ;{0}; odpověděl ;{1};.",
"change_username": "✏️ ;{0}; nyní ;{1};.",
"lobby_reset": "Návrat do místnosti za ;{0}; sekund...",
"prison_free": "🆓 ;{0}; se dostal z vězení",
"prison_turn": "🔐 ;{0}; zůstal tento tah ve vězení",
"flip_event": "🎴 UDÁLOST: ;{0}; 🎴",
"choose_manette": ";{0}; se zavázal hrát pouze karty barvy ;{1}; v tomto tahu.",
"UnionPacific": ";{0}; zahrál Union Pacific a vzal 4 karty z balíčku",
"use_special": ";{0}; použil zvláštní schopnost své postavy (;{1};)",
"gold_rush_pay_discard": ";{0}; odhodil ;{2}; od ;{1};.",
"choose_emporio": ";{0}; si vybral ;{1}; z Obecného obchodu.",
"shotgun_scrap": "Když brokovnice zasáhla ;{0};, karta mu vypadla z ruky (;{1};)",
"taglia_reward": "💰 ;{1}; získal kartu za odměnu za ;{0};",
"snake_bit": "🐍 ;{0}; byl uštknut chřestýšem."
},
"foc": {
"leggedelwest": "Musí tuto kartu zahrát v tomto tahu, pokud je to možné."
},
"mods": "Mody",
"bots": "Boti",
"add_bot": "Přidat bota",
"remove_bot": "Odebrat bota",
"minimum_players": "Hra potřebuje alespoň 3 hráče, aby mohla začít",
"mod_comp": "Soutěžní mód (deaktivuje automatické přijímání poškození)",
"disconnect_bot": "Nahradit odpojené hráče boty",
"your_turn": "Hrajte svůj tah!",
"your_response": "Odpovězte!",
"your_choose": "Vyberte kartu!",
"cards": {
"Barile": {
"name": "Sud",
"desc": "Když někdo hraje Bang proti vám. Můžete otočit první kartu z balíčku, pokud je barva srdcová, počítá se jako karta Minulo"
},
"Dinamite": {
"name": "Dynamit",
"desc": "Když hrajete Dynamit, položte ho před sebe, zůstane neškodný po celý tah. Na začátku dalšího tahu před tažením a před jakýmkoli otočením karty (např. Vězení), otočte kartu z vrchu balíčku. Pokud je karta mezi 2 a 9 pikami (včetně), dynamit exploduje: ztratíte 3 životy a kartu odhodíte, jinak předáte dynamit dalšímu hráči, který si kartu vezme po skončení vašeho tahu"
},
"Mirino": {
"name": "Zaměřovač",
"desc": "Vidíte ostatní hráče na vzdálenost -1"
},
"Mustang": {
"name": "Mustang",
"desc": "Ostatní hráči vás vidí na vzdálenost +1"
},
"Prigione": {
"name": "Vězení",
"desc": "Vybavte tuto kartu jinému hráči, kromě šerifa. Vybraný hráč na začátku svého tahu musí otočit kartu před tažením: pokud je to srdcová, kartu odhodí a hraje normálně, jinak kartu odhodí a tah přeskočí"
},
"Remington": {
"name": "Remington",
"desc": "Můžete střílet na jiného hráče na vzdálenost 3 nebo méně"
},
"Rev Carabine": {
"name": "Karabina Rev.",
"desc": "Můžete střílet na jiného hráče na vzdálenost 4 nebo méně"
},
"Schofield": {
"name": "Schofield",
"desc": "Můžete střílet na jiného hráče na vzdálenost 2 nebo méně"
},
"Volcanic": {
"name": "Volcanic",
"desc": "Můžete střílet na jiného hráče na vzdálenost 1 nebo méně, avšak již nemáte limit 1 Bang"
},
"Winchester": {
"name": "Winchester",
"desc": "Můžete střílet na jiného hráče na vzdálenost 5 nebo méně"
},
"Bang!": {
"name": "Bang!",
"desc": "Střílejte na hráče v dohledu. Pokud nemáte zbraň, váš dohled je 1"
},
"Birra": {
"name": "Pivo",
"desc": "Zahrajte tuto kartu, abyste získali jeden život. Nemůžete se vyléčit více, než je maximální limit vašeho postavy. Pokud se chystáte ztratit svůj poslední život, můžete tuto kartu zahrát i v tahu vašeho protivníka. Pivo přestává působit, pokud jsou ve hře jen dva hráči"
},
"Cat Balou": {
"name": "Cat Balou",
"desc": "Vyberte a odhoďte kartu jiného hráče."
},
"Diligenza": {
"name": "Diligence",
"desc": "Vezměte 2 karty z balíčku."
},
"Duello": {
"name": "Souboj",
"desc": "Zahrajte tuto kartu proti libovolnému hráči. Střídavě, počínaje vaším protivníkem, můžete odhodit kartu Bang!, první hráč, který tak neučiní, ztratí 1 život."
},
"Emporio": {
"name": "Obchod",
"desc": "Položte na stůl N karet z balíčku, kde N je počet živých hráčů, střídavě, počínaje vámi, vyberte kartu a přidejte ji do své ruky"
},
"Gatling": {
"name": "Gatling",
"desc": "Střílejte na všechny ostatní hráče"
},
"Indiani!": {
"name": "Indiáni!",
"desc": "Všichni ostatní hráči musí odhodit kartu Bang! nebo ztratí 1 život"
},
"Mancato!": {
"name": "Minulo!",
"desc": "Použijte tuto kartu k zrušení účinku Bang"
},
"Panico!": {
"name": "Panika!",
"desc": "Ukradněte kartu hráči na vzdálenost 1"
},
"Saloon": {
"name": "Saloon",
"desc": "Všichni získají 1 život"
},
"WellsFargo": {
"name": "Wells Fargo",
"desc": "Vezměte 3 karty z balíčku"
},
"Binocolo": {
"name": "Dalekohled",
"desc": "Vidíte ostatní hráče na vzdálenost -1"
},
"Riparo": {
"name": "Úkryt",
"desc": "Ostatní hráči vás vidí na vzdálenost +1"
},
"Pugno!": {
"name": "Pěst!",
"desc": "Střílejte na hráče na vzdálenost 1"
},
"Rag Time": {
"name": "Rag Time",
"desc": "Ukradněte kartu jinému hráči na libovolnou vzdálenost"
},
"Rissa": {
"name": "Rvačka",
"desc": "Vyberte kartu k odhození z ruky/vybavení všech ostatních hráčů"
},
"Schivata": {
"name": "Vyhnutí",
"desc": "Použijte tuto kartu k zrušení účinku Bang a poté si vezměte kartu."
},
"Springfield": {
"name": "Springfield",
"desc": "Střílejte na hráče na libovolnou vzdálenost"
},
"Tequila": {
"name": "Tequila",
"desc": "Vyléčte 1 život hráči dle vašeho výběru (můžete být i vy)"
},
"Whisky": {
"name": "Whisky",
"desc": "Vyléčte 2 životy"
},
"Bibbia": {
"name": "Bible",
"desc": "Použijte tuto kartu k zrušení účinku Bang a poté si vezměte kartu."
},
"Cappello": {
"name": "Desetigalónový Klobouk",
"desc": "Použijte tuto kartu k zrušení účinku Bang"
},
"Placca Di Ferro": {
"name": "Železná Deska",
"desc": "Použijte tuto kartu k zrušení účinku Bang"
},
"Sombrero": {
"name": "Sombrero",
"desc": "Použijte tuto kartu k zrušení účinku Bang"
},
"Pugnale": {
"name": "Dýka",
"desc": "Střílejte na hráče na vzdálenost 1"
},
"Derringer": {
"name": "Derringer",
"desc": "Střílejte na hráče na vzdálenost 1 a poté si vezměte kartu."
},
"Borraccia": {
"name": "Čutora",
"desc": "Získejte 1 život"
},
"Can Can": {
"name": "Can Can",
"desc": "Vyberte a odhoďte kartu jiného hráče."
},
"Conestoga": {
"name": "Conestoga",
"desc": "Ukradněte kartu jinému hráči na libovolnou vzdálenost"
},
"Fucile Da Caccia": {
"name": "Lovecká Puška",
"desc": "Střílejte na hráče na libovolnou vzdálenost"
},
"Pony Express": {
"name": "Pony Express",
"desc": "Vezměte 3 karty z balíčku"
},
"Pepperbox": {
"name": "Pepperbox",
"desc": "Střílejte na hráče v dohledu. Pokud nemáte zbraň, váš dohled je 1"
},
"Howitzer": {
"name": "Houfnice",
"desc": "Střílejte na všechny ostatní hráče"
},
"Bart Cassidy": {
"name": "Bart Cassidy",
"desc": "Pokaždé, když je zraněn, vezme si kartu."
},
"Black Jack": {
"name": "Black Jack",
"desc": "Na začátku svého tahu, když má vzít kartu, ukáže všem druhou kartu, pokud je to srdcová nebo křížová, vezme si třetí kartu, aniž by ji ukázal."
},
"Calamity Janet": {
"name": "Calamity Janet",
"desc": "Může použít karty Minulo! jako Bang! a naopak."
},
"El Gringo": {
"name": "El Gringo",
"desc": "Pokaždé, když je zraněn, vezme si kartu z ruky útočícího hráče."
},
"Jesse Jones": {
"name": "Jesse Jones",
"desc": "Když má vzít karty, může vzít první kartu z ruky jiného hráče. (klikněte na karty nepřátelského hráče, pokud chcete tuto schopnost použít)"
},
"Jourdonnais": {
"name": "Jourdonnais",
"desc": "Hraje, jako by měl vždy aktivní Sud, pokud vybaví další Sud, může otočit 2 karty."
},
"Kit Carlson": {
"name": "Kit Carlson",
"desc": "Když má vzít kartu, prohlédne si 3 karty a vybere 2, třetí kartu položí na vrch balíčku."
},
"Lucky Duke": {
"name": "Lucky Duke",
"desc": "Pokaždé, když má otočit kartu, může otočit 2x."
},
"Paul Regret": {
"name": "Paul Regret",
"desc": "Ostatní hráči ho vidí na vzdálenost +1."
},
"Pedro Ramirez": {
"name": "Pedro Ramirez",
"desc": "Když má vzít kartu, může vzít první kartu z odhazovacího balíčku. (klikněte na karty v odhazovacím balíčku, pokud chcete tuto schopnost použít)"
},
"Rose Doolan": {
"name": "Rose Doolan",
"desc": "Vidí ostatní hráče na vzdálenost -1."
},
"Sid Ketchum": {
"name": "Sid Ketchum",
"desc": "Může odhodit 2 karty, aby získal 1 život."
},
"Slab The Killer": {
"name": "Slab Zabiják",
"desc": "Aby se vyhnuli jeho kartám Bang!, ostatní hráči potřebují 2 karty Minulo!"
},
"Suzy Lafayette": {
"name": "Suzy Lafayette",
"desc": "Kdykoliv má prázdnou ruku, vezme si kartu."
},
"Vulture Sam": {
"name": "Vulture Sam",
"desc": "Když hráč zemře, získá všechny karty z ruky a vybavení mrtvého."
},
"Willy The Kid": {
"name": "Willy The Kid",
"desc": "Nemá omezení na počet Bang, které může použít."
},
"Pixie Pete": {
"name": "Pixie Pete",
"desc": "Vezme si 3 karty místo 2."
},
"Tequila Joe": {
"name": "Tequila Joe",
"desc": "Když hraje Pivo, získá 2 životy."
},
"Greg Digger": {
"name": "Greg Digger",
"desc": "Kdykoliv hráč zemře, získá až 2 životy."
},
"Herb Hunter": {
"name": "Herb Hunter",
"desc": "Kdykoliv hráč zemře, vezme si 2 karty."
},
"Elena Fuente": {
"name": "Elena Fuente",
"desc": "Může použít jakoukoliv kartu ze své ruky jako Minulo."
},
"Bill Noface": {
"name": "Bill Noface",
"desc": "Vezme si 1 kartu + 1 kartu za každé zranění, které má."
},
"Molly Stark": {
"name": "Molly Stark",
"desc": "Když použije kartu ze své ruky mimo svůj tah, vezme si kartu."
},
"Apache Kid": {
"name": "Apache Kid",
"desc": "Karty křížů ♦️, které jsou proti němu hrány, nemají účinek (nefunguje v duelech)."
},
"Sean Mallory": {
"name": "Sean Mallory",
"desc": "Může držet až 10 karet v ruce, když končí tah."
},
"Belle Star": {
"name": "Belle Star",
"desc": "Během svého tahu zelené a modré karty ostatních hráčů nefungují."
},
"Vera Custer": {
"name": "Vera Custer",
"desc": "Před tažením karet si může vybrat zvláštní schopnost jiného živého hráče. Tato schopnost se používá do dalšího tahu."
},
"Chuck Wengam": {
"name": "Chuck Wengam",
"desc": "Během svého tahu se může rozhodnout ztratit 1 život, aby vzal 2 karty z balíčku."
},
"Pat Brennan": {
"name": "Pat Brennan",
"desc": "Místo tažení si může ukrást kartu z vybavení jiného hráče. (klikněte na nepřátelského hráče, pokud chcete tuto schopnost použít)"
},
"José Delgado": {
"name": "José Delgado",
"desc": "Během svého tahu může odhodit modrou kartu, aby vzal 2 karty, až dvakrát za tah."
},
"Doc Holyday": {
"name": "Doc Holyday",
"desc": "Může odhodit 2 karty, aby zahrál Bang."
},
"Fuorilegge": {
"name": "Bandita"
},
"Rinnegato": {
"name": "Renegát"
},
"Sceriffo": {
"name": "Šerif"
},
"Vice": {
"name": "Zástupce"
},
"Miniera Abbandonata": {
"name": "Opuštěný Důl",
"desc": "Hráči táhnou z odhazovacího balíčku v 1. fázi a odhazují na vrch balíčku v 3. fázi (pokud odhazovací balíček dojde, musí táhnout a odhazovat na vrch balíčku)"
},
"Il Giudice": {
"name": "Soudce",
"desc": "Nemůžete vybavit karty sobě ani jiným hráčům"
},
"Agguato": {
"name": "Přepadení",
"desc": "Základní vzdálenost mezi dvěma hráči je 1"
},
"Rimbalzo": {
"name": "Odražená Střela",
"desc": "Hráč může hrát Bang proti kartám vybaveným jinými hráči, pokud nebudou hrát Minulo, budou odhozeny (klikněte na kartu události)"
},
"Cecchino": {
"name": "Sniper",
"desc": "Během svého tahu mohou hráči odhodit 2 Bang!, aby stříleli Bang!, který vyžaduje 2 Minulo (klikněte na kartu)"
},
"Lazo": {
"name": "Laso",
"desc": "Karty ve slotu vybavení nefungují"
},
"Ranch": {
"name": "Ranč",
"desc": "Po tažení si hráč může odhodit libovolný počet karet z ruky a vzít si stejný počet z balíčku"
},
"Dead Man": {
"name": "Mrtvý Muž",
"desc": "První hráč, který zemře, se vrací k životu s 2 životy a 2 kartami"
},
"Liquore Forte": {
"name": "Silný Likér",
"desc": "Hráči mohou přeskočit tažení, aby získali 1 život (klikněte na kartu události k použití)"
},
"Vendetta": {
"name": "Pomsta",
"desc": "Na konci tahu hráč otočí kartu z balíčku, pokud je to srdcová, hraje další tah (ale neotáčí další kartu)"
},
"Roulette Russa": {
"name": "Ruská Ruleta",
"desc": "Počínaje šerifem každý hráč odhodí 1 Minulo, první, kdo tak neučiní, ztratí 2 životy"
},
"Legge Del West": {
"name": "Zákon Západu",
"desc": "Každý hráč ukáže druhou kartu, kterou táhne, a musí ji použít v tomto kole (pokud je to možné)"
},
"Peyote": {
"name": "Peyote",
"desc": "Místo tažení hráč hádá barvu karty, pokud je správně, přidá kartu do ruky a pokračuje v hádání další karty"
},
"Fratelli Di Sangue": {
"name": "Krvaví Bratři",
"desc": "Na začátku svého tahu mohou hráči ztratit 1 život (kromě posledního), aby ho dali jinému hráči"
},
"I Dalton": {
"name": "Daltonové",
"desc": "Hráči, kteří mají vybavené modré karty, odhodí jednu z těchto karet dle svého výběru"
},
"Sermone": {
"name": "Kázání",
"desc": "Hráči nemohou hrát Bang! během svého tahu"
},
"Città Fantasma": {
"name": "Město Duchů",
"desc": "Všichni mrtví hráči se vracejí k životu ve svém tahu, nemohou zemřít a táhnou 3 karty místo 2. Když končí svůj tah, umírají."
},
"Il Reverendo": {
"name": "Reverend",
"desc": "Piva nemohou být hrána"
},
"Sbornia": {
"name": "Kocovina",
"desc": "Postavy ztrácejí své zvláštní schopnosti"
},
"Il Dottore": {
"name": "Doktor",
"desc": "Hráč s nejmenším počtem životů získává 1 život"
},
"Corsa All Oro": {
"name": "Zlatá Horečka",
"desc": "Tahy se hrají proti směru hodinových ručiček"
},
"Maledizione": {
"name": "Kletba",
"desc": "Všechny karty jsou piky ♠️"
},
"Sparatoria": {
"name": "Přestřelka",
"desc": "Limit Bang! na tah je 2"
},
"Benedizione": {
"name": "Požehnání",
"desc": "Všechny karty jsou srdcové ❤️"
},
"Il Treno": {
"name": "Příjezd Vlaku",
"desc": "Hráči táhnou 1 extra kartu"
},
"Sete": {
"name": "Žízeň",
"desc": "Hráči táhnou pouze 1 kartu na začátku svého tahu"
},
"Nuova Identita": {
"name": "Nová Identita",
"desc": "Na začátku svého tahu si každý hráč může vybrat změnu své postavy na jinou, zobrazenou na začátku hry. Pokud to udělá, začne s 2 životy"
},
"Manette": {
"name": "Pouta",
"desc": "Po tažení v 1. fázi hráč vyhlásí barvu. Bude moci použít pouze karty této barvy v tomto tahu"
},
"Mezzogiorno di Fuoco": {
"name": "Poledne",
"desc": "Každý hráč ztrácí 1 život, když začne jeho tah"
},
"Per Un Pugno Di Carte": {
"name": "Za Hrsti Karet",
"desc": "Na začátku svého tahu je hráč cílem tolika Bang, kolik má karet v ruce"
},
"Pepita": {
"name": "Zlatý Nuget"
},
"Bicchierino": {
"name": "Sklenička",
"desc": "Můžete vybrat hráče, který získá 1 život (i sebe)"
},
"Bottiglia": {
"name": "Láhev",
"desc": "Lze hrát jako Panika!, Pivo nebo Bang!"
},
"Complice": {
"name": "Komplic",
"desc": "Lze hrát jako Obchod, Souboj nebo Cat Balou."
},
"Corsa All Oro_gr": {
"name": "Zlatá Horečka",
"desc": "Koncíte tah, získáváte všechny své životy zpět a začínáte nový tah."
},
"Rum": {
"name": "Rum",
"desc": "Otočte 4 karty, za každou jinou barvu získáte 1 život."
},
"Union Pacific": {
"name": "Union Pacific",
"desc": "Vezměte 4 karty z balíčku."
},
"Calumet": {
"name": "Kalumet",
"desc": "Karty křížů hrané jinými hráči na vás nemají účinek."
},
"Cinturone": {
"name": "Opasek",
"desc": "Můžete držet až 8 karet, když končíte tah."
},
"Ferro di Cavallo": {
"name": "Podkova",
"desc": "Pokaždé, když máte otočit kartu, otočte dvakrát!"
},
"Piccone": {
"name": "Krumpáč",
"desc": "Získáváte 1 kartu navíc, když táhnete na začátku tahu."
},
"Ricercato": {
"name": "Hledaný",
"desc": "Zahrajte na jiného hráče, kdo zabije cíl, získá 2 extra karty a 1 zlatý nuget."
},
"Setaccio": {
"name": "Prosévač",
"desc": "Zaplaťte 1 zlatý nuget, abyste vzali 1 kartu z balíčku, až dvakrát za tah. (Klikněte na vybavenou kartu k použití)"
},
"Stivali": {
"name": "Boty",
"desc": "Pokaždé, když ztratíte 1 život, vezměte si 1 kartu z balíčku."
},
"Talismano": {
"name": "Šťastný Amulet",
"desc": "Pokaždé, když ztratíte 1 život, získáte 1 zlatý nuget."
},
"Zaino": {
"name": "Batoh",
"desc": "Zaplaťte 2 zlaté nugety, abyste získali 1 život. (Klikněte na vybavenou kartu k použití)"
},
"Don Bell": {
"name": "Don Bell",
"desc": "Když končí tah, otočí kartu, pokud je to srdcová ❤️ nebo křížová ♦️, hraje znovu."
},
"Dutch Will": {
"name": "Dutch Will",
"desc": "Vezme 2 karty, odhodí 1 a získá 1 zlatý nuget."
},
"Jacky Murieta": {
"name": "Jacky Murieta",
"desc": "Během svého tahu může zaplatit 2 zlaté nugety, aby mohl střílet další Bang!"
},
"Josh McCloud": {
"name": "Josh McCloud",
"desc": "Může zaplatit 2 zlaté nugety, aby získal první kartu z balíčku zlaté horečky."
},
"Madam Yto": {
"name": "Madam Yto",
"desc": "Bere si 1 kartu z balíčku pokaždé, když se hraje Pivo."
},
"Pretty Luzena": {
"name": "Krásná Luzena",
"desc": "Jednou za tah může mít slevu 1 v obchodě s kartami zlaté horečky."
},
"Raddie Snake": {
"name": "Raddie Snake",
"desc": "Může zahodit 1 zlatý nuget, aby si vzal 1 kartu z balíčku během svého tahu (maximálně 2x za tah)."
},
"Simeon Picos": {
"name": "Simeon Picos",
"desc": "Získává 1 zlatý nuget pokaždé, když ztratí 1 život."
},
"Fantasma": {
"name": "Duch",
"desc": "Zahrajte na jakéhokoliv vyřazeného hráče: Tento hráč se vrátí do hry, ale nemůže získat ani ztratit životy."
},
"Lemat": {
"name": "Lemat",
"desc": "Během svého tahu můžete použít jakoukoliv kartu jako Bang! (Klikněte na kartu po vybavení)."
},
"SerpenteASonagli": {
"name": "Chřestýš",
"desc": "Zahrajte na jakéhokoliv hráče. Na začátku svého tahu, pokud tento hráč táhne Piky, ztratí 1 život."
},
"Shotgun": {
"name": "Brokovnice",
"desc": "Pokaždé, když zraníte hráče, musí odhodit kartu z ruky."
},
"Taglia": {
"name": "Odměna",
"desc": "Zahrajte na jakéhokoliv hráče. Pokud tento hráč je zasažen Bang!, osoba, která střílela, získá kartu z balíčku."
},
"Mira": {
"name": "Zamíření",
"desc": "Zahrajte tuto kartu spolu s Bang!. Pokud je cíl zasažen, ztratí 2 životy."
},
"RitornoDiFiamma": {
"name": "Oplácení",
"desc": "Počítá se jako Minulo!. Hráč, který střílel, se stává cílem Bang!."
},
"Bandidos": {
"name": "Bandidos",
"desc": "Každý hráč si může vybrat mezi odhozením 2 karet z ruky (nebo 1, pokud má jen 1) nebo ztrátou 1 života."
},
"Fuga": {
"name": "Útěk",
"desc": "Lze hrát mimo tah. Vyhne se účinku hnědé karty (ne Bang!), kterou jste cílem."
},
"Sventagliata": {
"name": "Sekání",
"desc": "Počítá se jako jediný Bang! za tah. Hráč podle vašeho výběru na vzdálenost 1 od cíle (pokud existuje, kromě vás) se také stává cílem Bang."
},
"UltimoGiro": {
"name": "Poslední Kolo",
"desc": "Obnoví 1 život"
},
"Poker": {
"name": "Poker",
"desc": "Všichni ostatní hráči odhodí kartu z ruky současně. Pokud nejsou žádná esa, vezměte si až 2 z těchto karet."
},
"Salvo": {
"name": "Zachráněn!",
"desc": "Lze hrát mimo tah. Zabrání jinému hráči ve ztrátě 1 života. Pokud přežije, vezměte si 2 karty z jeho ruky nebo z balíčku (podle vašeho výběru)."
},
"Tomahawk": {
"name": "Tomahawk",
"desc": "Útočí na hráče do vzdálenosti 2."
},
"Tornado": {
"name": "Tornádo",
"desc": "Všichni odhodí kartu z ruky (pokud je to možné), poté vezmou 2 karty z balíčku."
},
"Black Flower": {
"name": "Černý Květ",
"desc": "Jednou za tah můžete použít kartu Piky, abyste stříleli další Bang!"
},
"Colorado Bill": {
"name": "Colorado Bill",
"desc": "Pokaždé, když hrajete kartu Bang!, pokud táhnete Piky, střela se nedá vyhnout."
},
"Der Spot Burst Ringer": {
"name": "Der Spot Burst Ringer",
"desc": "Jednou za tah můžete použít kartu Bang! jako Gatling."
},
"Evelyn Shebang": {
"name": "Evelyn Shebang",
"desc": "Můžete se rozhodnout netáhnout karty během své fáze tažení. Za každou nevytaženou kartu střílíte Bang! na dosažitelný cíl, do různých cílů."
},
"Henry Block": {
"name": "Henry Block",
"desc": "Kdokoliv, kdo táhne nebo odhazuje jednu z vašich karet ve hře nebo v ruce, se stává cílem Bang!."
},
"Lemonade Jim": {
"name": "Lemonade Jim",
"desc": "Kdykoliv jiný hráč hraje Pivo, můžete odhodit kartu z ruky, abyste také získali 1 život."
},
"Mick Defender": {
"name": "Mick Defender",
"desc": "Pokud se stáváte cílem hnědé karty (ne Bang!), můžete použít kartu Minulo!, abyste se vyhnuli 1 účinku."
},
"Tuco Franziskaner": {
"name": "Tuco Franziskaner",
"desc": "Pokud nemáte vybavené modré karty, táhnete 2 další karty."
},
"Big Spencer": {
"name": "Big Spencer",
"desc": "Začíná s 5 kartami. Nemůže hrát Minulo!"
},
"Flint Westwood": {
"name": "Flint Westwood",
"desc": "Může vyměnit kartu ze své ruky za 2 náhodné karty z ruky jiného hráče během svého tahu."
},
"Gary Looter": {
"name": "Gary Looter",
"desc": "Vezme všechny přebytečné karty odhozené jinými hráči na konci každého tahu."
},
"Greygory Deckard": {
"name": "Greygory Deckard",
"desc": "Na začátku svého tahu může vzít 2 náhodné postavy a získá všechny jejich schopnosti."
},
"John Pain": {
"name": "John Pain",
"desc": "Pokud má méně než 6 karet v ruce, když hráč \"táhne!\", John přidá vytaženou kartu do své ruky."
},
"Lee Van Kliff": {
"name": "Lee Van Kliff",
"desc": "Během svého tahu může odhodit kartu Bang!, aby zopakoval účinek hnědé karty, kterou právě hrál."
},
"Teren Kill": {
"name": "Teren Kill",
"desc": "Pokaždé, když má být vyřazen, \"táhne!\": pokud to nejsou Piky, Teren zůstane s 1 životem a vezme si 1 kartu."
},
"Youl Grinner": {
"name": "Youl Grinner",
"desc": "Před tažením karet hráči s více kartami v ruce než Youl mu musí dát kartu dle svého výběru."
},
"Camposanto": {
"name": "Hřbitov",
"desc": "Na začátku svého tahu se každý vyřazený hráč vrací do hry s 1 životem. Vezměte si kartu role náhodně z vyřazených hráčů."
},
"Darling Valentine": {
"name": "Darling Valentine",
"desc": "Na začátku svého tahu každý hráč odhodí svou ruku a vezme si stejný počet karet z balíčku."
},
"Dorothy Rage": {
"name": "Dorothy Rage",
"desc": "Během svého tahu může každý hráč přinutit jiného hráče hrát kartu."
},
"Helena Zontero": {
"name": "Helena Zontero",
"desc": "Když Helena vstoupí do hry, \"táhne!\": pokud táhne Srdce nebo Kříže, zamíchejte aktivní karty rolí kromě šerifa a přerozdělte je náhodně."
},
"Lady Rosa del Texas": {
"name": "Lady Rosa z Texasu",
"desc": "Během svého tahu může každý hráč vyměnit místo s hráčem napravo, který přeskočí svůj další tah. (Klikněte na kartu)"
},
"Miss Susanna": {
"name": "Miss Susanna",
"desc": "Během svého tahu musí každý hráč zahrát alespoň 3 karty. Pokud to neudělá, ztrácí 1 život."
},
"Regolamento di Conti": {
"name": "Vyrovnání Účtů",
"desc": "Všechny karty mohou být hrány, jako by byly Bang!. Karty Bang! mohou být hrány, jako by byly Minulo! (Klikněte na kartu)"
},
"Sacagaway": {
"name": "Sacagaway",
"desc": "Všichni hráči hrají s kartami lícem nahoru (kromě karty role!)."
},
"Wild West Show": {
"name": "Představení Divokého Západu",
"desc": "Cíl každého hráče se stává: \"Buď poslední, kdo zůstane stát!\""
}
},
"help": {
"character": "Postavy",
"characters_special": "Každá postava má zvláštní schopnosti a počet životů, které je činí jedinečnými. \nŽivoty jsou počet životních bodů, které můžete ztratit před smrtí, a také označují maximální počet karet, které můžete držet v ruce.",
"deathnobeer": "Když ztratíte poslední životní bod a nemáte v ruce pivo 🍺️, zemřete. \nVaše karty jsou odhozeny a vaše role je odhalena všem.",
"discard": "Odhodit",
"distance": "Vzdálenost",
"distancecalc": "Vzdálenost je automaticky vypočítána hrou a odpovídá minimální vzdálenosti mezi hráči vlevo a vpravo.",
"drawinstructions": "Chcete-li vzít karty, musíte kliknout na balíček, když vidíte tuto animaci.",
"drawthecards": "Vytáhněte karty",
"endgame": "Konec hry",
"endgameconditions": "Hra končí, když je splněna jedna z následujících podmínek:",
"endgamesheriffwin": "Všichni bandité 🐺️ a renegáti 🦅️ jsou mrtví. \nV tomto případě šerif ⭐️ a zástupci 🎖️ vyhrávají.",
"endgameshriffdeath": "Šerif ⭐️ zemře. \nPokud je renegát 🦅️ posledním přeživším hráčem, vyhrává, jinak vyhrávají bandité.",
"endingturn": "Když jste skončili hrát své karty, tedy když nechcete nebo nemůžete hrát více karet, musíte odhodit karty, které přesahují vaše aktuální množství životů.\n\nPoté předáte tah dalšímu hráči kliknutím na konec tahu.",
"equipment": "VYBAVENÍ",
"justoneweapon": "Můžete mít vybavenou pouze jednu zbraň.",
"maxtwocardsequip": "Nemůžete mít vybavené 2 karty se stejným názvem.",
"outlawreward": "Kdo zabije banditu 🐺️, vezme si 3 karty z balíčku (ostatní bandité také 🐺️).",
"playerdeath": "Smrt hráče",
"playingcards": "Hrajte karty",
"playingdmg": "Můžete hrát své karty pro sebe nebo k ublížení ostatním hráčům, snažíc se je eliminovat.",
"playingduringturn": "Můžete hrát karty pouze ve svém tahu. Chcete-li hrát karty, klikněte na karty ze své ruky.\nS výjimkou karet použitých jako odpověď, jako Minulo 😅️.",
"playingifyouwant": "Nejste povinni hrát karty.",
"playlimit": "Existují pouze 3 omezení:",
"playonlyonebang": "Můžete hrát pouze 1 Bang! \nza tah (týká se pouze karet pojmenovaných Bang!)",
"rewardspen": "Tresty a odměny",
"roles": "Role",
"sheriffkillsvice": "Pokud šerif ⭐️ zabije zástupce, ztratí všechny karty v ruce i v hře před ním.",
"thecards": "Karty",
"title": "Jak hrát",
"turndiscard": "Odhodit přebytečné karty",
"turndraw": "Vezměte 2 karty",
"turnplay": "Hrajte libovolný počet karet",
"turns": "Tahy",
"turnstart": "Vždy začíná šerif ⭐️, a hra pokračuje po směru hodinových ručiček, tahy se dělí na 3 fáze.",
"weapon": "ZBRAŇ",
"renegade": "Renegát",
"vice": "Zástupce",
"outlaw": "Bandita",
"sheriff": "Šerif",
"allcharacters": "Všechny postavy",
"gotoallcharacters": "Přejít na všechny postavy",
"gotocards": "Přejít na karty",
"gotohighnoon": "Přejít na Poledne",
"gotofoc": "Přejít na Hrsti Karet",
"gotogoldrush": "Přejít na Zlatou Horečku",
"highnooncards": "Poledne - Karty Událostí",
"foccards": "Hrsti Karet - Karty Událostí",
"goldrushcards": "Karty Zlaté Horečky",
"valleyofshadowscards": "Karty Údolí Stínů"
},
"theme": {
"sepia": "Sépie",
"light": "Světlo",
"dark": "Tma",
"grayscale": "Černobílé",
"black": "Černá"
}
}

View File

@ -1,11 +1,25 @@
{
"trademark": "Bang! is a trademark owned by DVGiochi",
"tip_1": "Better with friends!",
"tip_2": "The 🤖️ icon means that a player is a bot!",
"tip_3": "You can click on the cards of characters and equipments of the other players if you wish to know more!",
"tip_4": "Dodge City, High Noon, Fistful Of Cards included!",
"tip_5": "Found a bug? Message us on discord!",
"tip_6": "Now with a discord server!",
"tip_7": "If you want to help us translate the game in your language, ping us on discord!",
"tip_8": "If you disconnect during in an ongoing game you will be replaced by a bot (while you are gone)!",
"tip_9": "If you are on mobile hold on a card to read the description!",
"tip_10": "If in doubt shoot all the other players!",
"online_players": "Online players: ",
"shuffle_players": "Shuffle Players",
"choose_username": "Pick an username:",
"report_bug": "Write what the bug consists of",
"report": "Report a bug",
"available_lobbies": "Available Lobbies:",
"spectate_lobbies": "Spectate ongoing games:",
"no_lobby_available": "No lobbies available",
"create_lobby": "Open a lobby:",
"characters_to_distribute": "Characters to distribute: ",
"lobby_name": "Name:",
"leave_room": "Leave lobby",
"warning": "Warning!",
@ -13,11 +27,13 @@
"end_turn": "End Turn!",
"start_game": "Start!",
"expansions": "Expansions",
"click_to_toggle": "Click to toggle",
"details": "Details",
"ok": "OK",
"you": "YOU",
"owner": "OWNER",
"cancel": "CANCEL",
"send": "SEND",
"password": "Password: ",
"room_password_prompt": "Lobby Password: ",
"private_room": "Private Lobby",
@ -36,22 +52,41 @@
"choose_response": "Choose your response ",
"choose_response_to": "to ",
"choose_response_needed": "NEEDED ",
"choose_manette": "Choose a suit, you will be able to play only cards with that suit on this turn.",
"hand": "HAND",
"card_against": "Who will you play your card against?",
"choose_sid_scrap": "Discard 2 cards to not die",
"choose_card_to_get": "Choose a card",
"choose_guess": "Guess the color of the suit",
"choose_ranch": "Choose the cards to replace",
"choose_dalton": "Choose which equipment to discard",
"choose_fratelli_di_sangue": "Choose who you want to donate one of your lives",
"choose_fantasma": "Choose who to bring back to life",
"choose_sventagliata": "Choose another target to hit with Fanning",
"choose_tornado": "Choose a card to discard for the tornado",
"choose_bandidos": "Choose between discarding 2 cards or losing a life (1 card if you only have 1)",
"choose_poker": "Everyone discards 1 card (if there's no Ace, the player who played poker chooses 2 cards)",
"choose_from_poker;2": "Choose which cards to get (max 2)",
"choose_from_poker;1": "Choose which card to get",
"choose_cecchino": "Choose who to shoot",
"choose_rimbalzo_player": "Choose the target of the bang",
"choose_rimbalzo_card": "Choose the card to discard the bang to",
"choose_nuova_identita": "Choose if you want to keep your current character, or if you want to change it and start from 2 HP",
"choose_bicchierino": "A player of your choice regains 1 hp",
"choose_bottiglia": "Choose how you will play Bottle!",
"choose_complice": "Choose how you will play Pardner!",
"choose_ricercato": "Choose who you will play Wanted against.",
"choose_birra_function": "Choose between getting 1 gold nugget by discarding beer or if you want to play the beer.",
"choose_play_as_bang": "Choose which card to play as Bang!",
"choose_flint_special": "Choose which card to swap.",
"emporio_others": "{0} is choosing which card to get from the General Store",
"you_died": "YOU DIED",
"spectate": "SPECTATE",
"you_win": "YOU WON",
"you_lose": "YOU LOST",
"special_ability": "SPECIAL ABILITY",
"gold_rush_discard": "Discard another player's gold rush equipment (paying the price + 1)",
"gold_rush_discard_2": "Discard another player's gold rush equipment (paying the price + 1)",
"discard": "DISCARD",
"to_regain_1_hp": "TO REGAIN 1 HP",
"play_your_turn": "PLAY YOUR TURN",
@ -64,45 +99,68 @@
"submit": "Submit",
"copy": "Copy invite",
"no_players_in_range": "You can't see the other players, equip a weapon or a scope!",
"cantplaycard": "You can't play this card like that!",
"choose_baggage_car": "Discard this for a Missed! Panic!, Cat Balou, or an extra BANG!",
"choose_mail_car": "Choose which card to give to another player",
"choose_other_player": "Choose the player to give the card to",
"choose_sleeper_car": "Choose a card to discard for Sleeper Car",
"choose_buy_train": "Discard a card to rob the train, and get the carriage",
"chat": {
"spectators": " | A spectator is watching the game | {n} spectators are watching the game",
"chat": "Chat",
"joined": "{0} joined the lobby",
"died": "{0} died",
"died_role": "{0} was a {1}!",
"won": "{0} won!",
"choose_character": "{0} has {1} as character, his special ability is: {2}!",
"joined": "👋 ;{0}; joined the lobby",
"died": "☠️ ;{0}; died",
"died_role": "☠️ ;{0}; was a ;{1};!",
"won": "🏆 ;{0}; won! Their role was ;{1};",
"choose_character": ";{0}; has ;{1}; as character, his special ability is: ;{2};!",
"starting": "The game is starting!",
"sheriff": "{0} is the sheriff!",
"did_choose_character": "{0} did choose the character.",
"turn": "It is the turn of {0}.",
"draw_from_scrap": "{0} did draw the first card from the scrap pile.",
"draw_from_player": "{0} did draw the first card from the hand of {1}.",
"flipped": "{0} flipped a {1} {2}.",
"explode": "{0} blew up the dynamite.",
"beer_save": "{0} used a beer to save his life.",
"play_card": "{0} played {1}.",
"play_card_against": "{0} played {1} against {2}.",
"play_card_for": "{0} played {1} for {2}.",
"spilled_beer": "{0} spilled a {1}.",
"diligenza": "{0} played {1} and draws 2 cards.",
"wellsfargo": "{0} played {1} and draws 3 cards.",
"saloon": "{0} player {1} and heals 1 HP to everyone alive.",
"special_bart_cassidy": "{0} received a compensation because he was injured.",
"special_el_gringo": "{0} stole a card from {1} when he was was injured.",
"special_calamity": "{0} played {1} as Bang! against {2}.",
"allroles3": "In the game there are: {1} {0}, {3} {2}, {5} {4}.",
"allroles4": "In the game there are: {1} {0}, {3} {2}, {5} {4}, {7} {6}.",
"guess": "{0} guesses {1}.",
"guess_right": "{0} was right.",
"guess_wrong": "{0} was wrong.",
"fratelli_sangue": "{0} gave one of his lives to {1}.",
"doctor_heal": "{0} was healed by the doctor.",
"respond": "{0} responded with {1}.",
"change_username": "{0} is now {1}.",
"lobby_reset": "Going back to lobby in {0} seconds...",
"prison_free": "{0} got out of prison",
"prison_turn": "{0} stayed in prison this turn"
"sheriff": "⭐ ;{0}; is the sheriff!",
"did_choose_character": ";{0}; did choose the character.",
"turn": "⏩ It is the turn of ;{0};.",
"draw_from_scrap": ";{0}; did draw the first card from the scrap pile.",
"draw_from_player": ";{0}; did draw the first card from the hand of ;{1};.",
"flipped": ";{0}; flipped a ;{1}; ;{2};.",
"scrapped": ";{0}; discarded a ;{1}; ;{2};.",
"explode": "💥 ;{0}; blew up the dynamite.",
"beer_save": ";{0}; used a beer to save his life.",
"get_nugget": ";{0}; got a gold nugget using a Beer.",
"play_card": ";{0}; played ;{1};.",
"play_card_green": ";{0}; put in game ;{1};.",
"play_card_with": ";{0}; played ;{1};, discarding ;{2};.",
"purchase_card": ";{0}; purchased ;{1};.",
"play_card_against": ";{0}; played ;{1}; against ;{2};.",
"play_card_against_with": ";{0}; played ;{1}; against ;{2};, discarding ;{3};.",
"play_card_for": ";{0}; played ;{1}; for ;{2};.",
"spilled_beer": ";{0}; spilled a ;{1};.",
"diligenza": ";{0}; played ;{1}; and draws 2 cards.",
"wellsfargo": ";{0}; played ;{1}; and draws 3 cards.",
"saloon": "🍻 ;{0}; played ;{1}; and heals 1 HP to everyone alive.",
"special_bart_cassidy": ";{0}; received a compensation because he was injured.",
"special_el_gringo": ";{0}; stole a card from ;{1}; when he was was injured.",
"special_calamity": ";{0}; played ;{1}; as Bang! against ;{2};.",
"allroles3": "In the game there are: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};.",
"allroles4": "In the game there are: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};, ;{7}; ;{6};.",
"guess": "🤔 ;{0}; guesses ;{1};.",
"guess_right": ";{0}; was right.",
"guess_wrong": ";{0}; was wrong.",
"fratelli_sangue": ";{0}; gave one of his lives to ;{1};.",
"doctor_heal": ";{0}; was healed by the doctor.",
"respond": "↩️ ;{0}; responded with ;{1};.",
"change_username": "✏️ ;{0}; is now ;{1};.",
"lobby_reset": "Going back to lobby in ;{0}; seconds...",
"prison_free": "🆓 ;{0}; got out of prison",
"prison_turn": "🔐 ;{0}; stayed in prison this turn",
"flip_event": "🎴 EVENT: ;{0}; 🎴",
"choose_manette": ";{0}; committed to play only cards of suit ;{1}; in this turn.",
"UnionPacific": ";{0}; played Union Pacific and draws 4 cards from the deck",
"use_special": ";{0}; used the special ability of their character (;{1};)",
"gold_rush_pay_discard": ";{0}; discarded ;{2}; from ;{1};.",
"choose_emporio": ";{0}; has chosen ;{1}; from General Store.",
"shotgun_scrap": "When the shotgun hit ;{0}; a card flew away from his hand (;{1};)",
"taglia_reward": "💰 ;{1}; got a card from the bounty on ;{0};",
"snake_bit": "🐍 ;{0}; was bitten by the Rattle Snake.",
"in_private_car": "🚋💁🏻 ;{0}; is in a private car and couldn't get Bang!ed by ;{1};",
"bought_train": "🚂 ;{0}; robbed the train at ;{1}; and got the ;{2};"
},
"foc": {
"leggedelwest": "He must play this card on this turn if possible."
@ -160,7 +218,7 @@
},
"Bang!": {
"name": "Bang!",
"desc": "Shoot a player in sight. If you do not have weapons, your is sight is 1"
"desc": "Shoot a player in sight. If you do not have weapons, your sight is 1"
},
"Birra": {
"name": "Beer",
@ -288,7 +346,7 @@
},
"Pepperbox": {
"name": "Pepperbox",
"desc": "Shoot a player in sight. If you do not have weapons, your is sight is 1"
"desc": "Shoot a player in sight. If you do not have weapons, your sight is 1"
},
"Howitzer": {
"name": "Howitzer",
@ -312,7 +370,7 @@
},
"Jesse Jones": {
"name": "Jesse Jones",
"desc": "When he has to draw his cards, he may draw the first card from the hand of another player. (click on the enemy player if you want to use the ability)"
"desc": "When he has to draw his cards, he may draw the first card from the hand of another player. (click on the enemy player's card's if you want to use the ability)"
},
"Jourdonnais": {
"name": "Jourdonnais",
@ -410,9 +468,9 @@
"name": "Pat Brennan",
"desc": "Instead of drawing he can steal a card from the equipment of another player. (click on the enemy player if you want to use the ability)"
},
"José Delgrado": {
"name": "José Delgrado",
"desc": "He can discard a blue card to draw 2 cards."
"José Delgado": {
"name": "José Delgado",
"desc": "On his turn he can discard a blue card to draw 2 cards, up to twice per turn."
},
"Doc Holyday": {
"name": "Doc Holyday",
@ -429,6 +487,505 @@
},
"Vice": {
"name": "Deputy"
},
"Miniera Abbandonata": {
"name": "Abandoned Mine",
"desc": "Players draw from the discarded pile in their phase 1 and discard to the top of the deck during phase 3 (if the discaded pile runs out, they must draw and discard on top of the deck)"
},
"Il Giudice": {
"name": "The Judge",
"desc": "You can't equip cards on yourself or other players"
},
"Agguato": {
"name": "Ambush",
"desc": "The base distance from any 2 players is 1"
},
"Rimbalzo": {
"name": "Ricochet",
"desc": "The player can play bang against the cards equipped by the other players, if they do not play miss they are discarded (click the event card)"
},
"Cecchino": {
"name": "Sniper",
"desc": "During their turn, players can discard 2 Bang! to shoot a bang that requires 2 missed (click the card)"
},
"Lazo": {
"name": "Lasso",
"desc": "Cards in the equipment slot do not work"
},
"Ranch": {
"name": "Ranch",
"desc": "After drawing, the player can discard as many cards as he wants from his hand and draw as many from the deck"
},
"Dead Man": {
"name": "Dead Man",
"desc": "The first player that died returns back to life with 2 hp and 2 cards"
},
"Liquore Forte": {
"name": "Hard Liquor",
"desc": "Players can skip drawing to regain 1 HP (click on the event card to use)"
},
"Vendetta": {
"name": "Vendetta",
"desc": "When ending the turn, the player flips a card from the deck, if it's \u2665\ufe0f he plays another turn (but he does not flip another card)"
},
"Roulette Russa": {
"name": "Russian Roulette",
"desc": "Starting from the sheriff, every player discards 1 missed, the first one that doesn't loses 2 HP"
},
"Legge Del West": {
"name": "Law Of The West",
"desc": "Every player shows the second card that they draw and must use it in that round (if it is possible)"
},
"Peyote": {
"name": "Peyote",
"desc": "Instead of drawing, the player tries to guess the color of the suit, if he's right he adds the card to the hand and continues trying to guess the next card"
},
"Fratelli Di Sangue": {
"name": "Blood Brothers",
"desc": "At the begin of their turn, players can lose 1 hp (except the last one) to give it to another player"
},
"I Dalton": {
"name": "The Daltons",
"desc": "Players that have blue cards equipped, discard 1 of those card of their choice"
},
"Sermone": {
"name": "The Sermon",
"desc": "Players can't play Bang! during their turn"
},
"Citt\u00e0 Fantasma": {
"name": "Ghost Town",
"desc": "All dead players come back to life in their turn, they can't die and draw 3 cards instead of 2. When they end their turn the die."
},
"Il Reverendo": {
"name": "The Reverend",
"desc": "Beers can't be played"
},
"Sbornia": {
"name": "Hangover",
"desc": "The characters lose their special abilities"
},
"Il Dottore": {
"name": "The Doctor",
"desc": "The player with the least amount of HP gets healed 1"
},
"Corsa All Oro": {
"name": "Gold Rush",
"desc": "Turns are played counter clockwise"
},
"Maledizione": {
"name": "Curse",
"desc": "All cards are of spades \u2660"
},
"Sparatoria": {
"name": "Shootout",
"desc": "The turn Bang! limit is 2"
},
"Benedizione": {
"name": "Blessing",
"desc": "All cards are of hearts \u2665\ufe0f"
},
"Il Treno": {
"name": "Train Arrival",
"desc": "Players draw 1 extra card"
},
"Sete": {
"name": "Thirst",
"desc": "Players only draw 1 card at the start of their turn"
},
"Nuova Identita": {
"name": "New Identity",
"desc": "At the beginning of their turn, each player can choose to change its character with the other shown at the game start. If he does so he restarts from 2 HP"
},
"Manette": {
"name": "Handcuffs",
"desc": "After drawing in phase 1, the player declares a suit. He will be able to use only cards of that suit for that turn"
},
"Mezzogiorno di Fuoco": {
"name": "High Noon",
"desc": "Every player loses 1 HP when their turn starts"
},
"Per Un Pugno Di Carte": {
"name": "A Fistful of Cards",
"desc": "On the beginning of his turn, the player is target of as many Bang as how many cards he has in his hand"
},
"Pepita": {
"name": "Gold Nugget"
},
"Bicchierino": {
"name": "Shot Glass",
"desc": "You can choose a player that regains 1 HP (even you)"
},
"Bottiglia": {
"name": "Bottle",
"desc": "Can be played as Panic!, Beer or BANG!"
},
"Complice": {
"name": "Pardner",
"desc": "Can be played as General Store, Duel or Cat Balou."
},
"Corsa All Oro_gr": {
"name": "Gold Rush",
"desc": "You end your turn, regain all your HP and start a new turn."
},
"Rum": {
"name": "Rhum",
"desc": "Flip 4 cards, for each different suit you gain 1 HP."
},
"Union Pacific": {
"name": "Union Pacific",
"desc": "Draw 4 cards from the deck."
},
"Calumet": {
"name": "Calumet",
"desc": "Cards of diamonds played by other players have no effect on you."
},
"Cinturone": {
"name": "Gun Belt",
"desc": "You can keep up to 8 cards when you end your turn."
},
"Ferro di Cavallo": {
"name": "Horseshoe",
"desc": "Every time you have to flip a card you flip twice!"
},
"Piccone": {
"name": "Pickaxe",
"desc": "You get 1 more card when you draw at the beginning of the turn."
},
"Ricercato": {
"name": "Wanted",
"desc": "Play it on another player, who kills the target gets 2 extra cards and 1 gold nugget."
},
"Setaccio": {
"name": "Gold Pan",
"desc": "Pay 1 gold nugget to draw 1 card from the deck, up to twice per turn. (Click on the equipped card to use)"
},
"Stivali": {
"name": "Boots",
"desc": "Each time you lose 1 hp, you draw 1 card from the deck."
},
"Talismano": {
"name": "Lucky Charm",
"desc": "Each time you lose 1 hp, you get 1 gold nugget."
},
"Zaino": {
"name": "Rucksack",
"desc": "Pay 2 gold nugget to heal 1 HP. (Click on the equipped card to use)"
},
"Don Bell": {
"name": "Don Bell",
"desc": "When he ends his turn, he flips a card, if it flips Hearts ❤️ or Diamonds ♦️ he plays again."
},
"Dutch Will": {
"name": "Dutch Will",
"desc": "He draws 2 cards, discards 1 and takes 1 gold nugget."
},
"Jacky Murieta": {
"name": "Jacky Murieta",
"desc": "During his turn he can pay 2 gold nuggets for the ability to shoot another BANG!"
},
"Josh McCloud": {
"name": "Josh McCloud",
"desc": "He can pay 2 gold nuggets to get the first card from the Gold Rush deck."
},
"Madam Yto": {
"name": "Madam Yto",
"desc": "She draws 1 card from the deck each time a beer is played."
},
"Pretty Luzena": {
"name": "Pretty Luzena",
"desc": "Once per turn she can have a discount of 1 on the gold rush cards shop."
},
"Raddie Snake": {
"name": "Raddie Snake",
"desc": "He can throw away 1 gold nugget to draw 1 card from the deck during his turn (2 times max per turn)."
},
"Simeon Picos": {
"name": "Simeon Picos",
"desc": "He gets 1 gold nugget every time he loses 1 hp."
},
"Fantasma": {
"name": "Ghost",
"desc": "Play on any eliminated player: That player is back in the game, but can't gain nor lose life points."
},
"Lemat": {
"name": "Lemat",
"desc": "During your turn you can use any card as BANG! (Click on the card once equipped)."
},
"SerpenteASonagli": {
"name": "Rattle Snake",
"desc": "Play on any player. At the beginning of his turn. if that player draws on Spades, he loses I life point."
},
"Shotgun": {
"name": "Shotgun",
"desc": "Every time you wound a player, they must discard a card from their hand."
},
"Taglia": {
"name": "Bounty",
"desc": "Play on anyone. If that player is hit by BANG!, the person who shot gets a card from the deck."
},
"Mira": {
"name": "Aim",
"desc": "Play this card along with a BANG! card. If the target is hit, they lose 2 life points."
},
"RitornoDiFiamma": {
"name": "Backfire",
"desc": "Counts as a Missed! card. The player who shot is the target of a BANG!."
},
"Bandidos": {
"name": "Bandidos",
"desc": "Each player chooses to discard 2 cards from their hand (or 1 if they only have 1) or lose 1 life point."
},
"Fuga": {
"name": "Escape",
"desc": "Can be played out of turn. Avoids the effect of a brown (not BANG!) card you are a target of."
},
"Sventagliata": {
"name": "Fanning",
"desc": "Counts as the only BANG! of the turn. A player of your choice at distance 1 from the target (if any, excluding yourself) is also a target of a BANG.."
},
"UltimoGiro": {
"name": "Last Call",
"desc": "Recovers 1 life point"
},
"Poker": {
"name": "Poker",
"desc": "All other players discard a card from their hand, at the same time. If there are no Aces, draw up to 2 of those cards."
},
"Salvo": {
"name": "Saved!",
"desc": "Can be played out of turn. Prevents another player from losing 1 life point. If they survive, they draw 2 cards from their hand or deck (your choice)."
},
"Tomahawk": {
"name": "Tomahawk",
"desc": "Attacks a player up to distance 2."
},
"Tornado": {
"name": "Tornado",
"desc": "Everyone discards a card from their hand (if possible), then draws 2 cards from the deck."
},
"Black Flower": {
"name": "Black Flower",
"desc": "Once per turn, you can use a Clubs card to shoot an extra BANG!"
},
"Colorado Bill": {
"name": "Colorado Bill",
"desc": "Whenever you play a BANG! card, if you draw a Spades, the shot cannot be avoided."
},
"Der Spot Burst Ringer": {
"name": "Der Spot Burst Ringer",
"desc": "Once per turn, you can use a BANG! card as a Gatling."
},
"Evelyn Shebang": {
"name": "Evelyn Shebang",
"desc": "You can choose not to draw cards during your draw phase. For each card not drawn, you shoot a BANG! at a reachable target, to a different target."
},
"Henry Block": {
"name": "Henry Block",
"desc": "Anyone who draws or discards one of your cards in play or in hand is a target of a BANG!."
},
"Lemonade Jim": {
"name": "Lemonade Jim",
"desc": "Whenever another player plays a Beer, you can discard a card from your hand to regain 1 life point as well."
},
"Mick Defender": {
"name": "Mick Defender",
"desc": "If you are targeted by a brown card (not BANG!), you can use a Missed! card to avoid 1 effect."
},
"Tuco Franziskaner": {
"name": "Tuco Franziskaner",
"desc": "If you don't have blue cards equipped you draw 2 extra cards."
},
"Big Spencer": {
"name": "Big Spencer",
"desc": "Starts with 5 cards. Cannot play Missed!"
},
"Flint Westwood": {
"name": "Flint Westwood",
"desc": "Can swap a card from their hand with 2 random cards from another player's hand during their turn."
},
"Gary Looter": {
"name": "Gary Looter",
"desc": "Draws all excess cards discarded by other players at the end of each turn."
},
"Greygory Deckard": {
"name": "Greygory Deckard",
"desc": "At the beginning of their turn, can draw 2 random characters and gains all of their abilities."
},
"John Pain": {
"name": "John Pain",
"desc": "If they have less than 6 cards in their hand, when a player \"draws!\", John adds the drawn card to their hand."
},
"Lee Van Kliff": {
"name": "Lee Van Kliff",
"desc": "During their turn, can discard a BANG! card to repeat the effect of a brown-bordered card they just played."
},
"Teren Kill": {
"name": "Teren Kill",
"desc": "Every time they would be eliminated, \"draw!\": if it's not a Spades card, Teren remains at 1 health and draws 1 card."
},
"Youl Grinner": {
"name": "Youl Grinner",
"desc": "Before drawing, players with more cards in their hand than Youl must give him a card of their choice."
},
"Camposanto": {
"name": "Bone Orchard",
"desc": "At the beginning of their turn, each eliminated player comes back to the game with 1 health point. Draw a role card at random from the eliminated players."
},
"Darling Valentine": {
"name": "Darling Valentine",
"desc": "At the beginning of their turn, each player discards their hand and draws the same number of cards from the deck."
},
"Dorothy Rage": {
"name": "Dorothy Rage",
"desc": "During their turn, each player can force another player to play a card."
},
"Helena Zontero": {
"name": "Helena Zontero",
"desc": "When Helena enters the game, \"draw!\": if Hearts or Diamonds are drawn, shuffle the active role cards except for the Sheriff, and redistribute them at random."
},
"Lady Rosa del Texas": {
"name": "Lady Rose of Texas",
"desc": "During their turn, each player can switch places with the player on their right, who skips their next turn. (Click the card)"
},
"Miss Susanna": {
"name": "Miss Susanna",
"desc": "During their turn, each player must play at least 3 cards. If they don't, they lose 1 health point."
},
"Regolamento di Conti": {
"name": "Showdown",
"desc": "All cards can be played as if they were BANG!. BANG! cards can be played as if they were Missed! (Click the card)"
},
"Sacagaway": {
"name": "Sacagaway",
"desc": "All players play with their cards face up (except for their role card!)."
},
"Wild West Show": {
"name": "Wild West Show",
"desc": "The goal for each player becomes: \"Be the last one standing!\""
},
"Boom Town": {
"name": "Boom Town",
"desc": "Discard a Bang! to rob the train"
},
"Caticor": {
"name": "Caticor",
"desc": "Discard a Cat Balou or Panico to rob the train"
},
"Creepy Creek": {
"name": "Creepy Creek",
"desc": "Discard a card of spades to rob the train"
},
"Crowns Hole": {
"name": "Crown's Hole",
"desc": "Discard a beer to rob the train"
},
"Deadwood": {
"name": "Deadwood",
"desc": "Discard an equipment card to rob the train"
},
"Dodgeville": {
"name": "Dodgeville",
"desc": "Discard a Missed! to rob the train"
},
"Fort Worth": {
"name": "Fort Worth",
"desc": "Discard a card with number 10, J, Q, K, A to rob the train"
},
"Frisco": {
"name": "Frisco",
"desc": "Discard a card of clubs to rob the train"
},
"Miners Oath": {
"name": "Miner's Oath",
"desc": "Discard a card of diamonds to rob the train"
},
"San Tafe": {
"name": "San Tafe",
"desc": "Discard a card of hearts to rob the train"
},
"Tombrock": {
"name": "Tombrock",
"desc": "Lose 1 life point to rob the train"
},
"Yooma": {
"name": "Yooma",
"desc": "Discard a card with number between 2 and 9 to rob the train"
},
"Virginia Town": {
"name": "Virginia Town",
"desc": "Discard two cards to rob the train"
},
"Ironhorse": {
"name": "Ironhorse",
"desc": "Each player, including the one who activated the effect, is targeted by a BANG!\nNo player is responsible for any loss of life points.\nIf all players are eliminated at the same time, the Outlaws win."
},
"Leland": {
"name": "Leland",
"desc": "LOCOMOTIVE: perform the effect of the Emporium, starting with the current player and proceeding clockwise."
},
"Baggage Car": {
"name": "Baggage Car",
"desc": "Discard this card to gain the effect of a Missed!, Panic!, Cat Balou, or an extra BANG! card."
},
"Caboose": {
"name": "Caboose",
"desc": "To discard one of your blue-bordered cards, include a car as if it were a Missed!"
},
"Cattle Truck": {
"name": "Cattle Truck",
"desc": "Discard this card to look at the top 3 cards of the discard pile and choose 1 to add to your hand."
},
"Circus Wagon": {
"name": "Circus Wagon",
"desc": "Discard this card. Each other player must discard a card that he has in play."
},
"Coal Hopper": {
"name": "Coal Hopper",
"desc": "Discard this card to draw a card and discard a car in play in front of any player of your choice."
},
"Dining Car": {
"name": "Dining Car",
"desc": "At the beginning of your turn, \"pick!\": if it's Hearts, regain 1 life point."
},
"Express Car": {
"name": "Express Car",
"desc": "Discard all your hand cards and take another turn."
},
"Ghost Car": {
"name": "Ghost Car",
"desc": "Play it on any player except the Sheriff. If you are eliminated, you remain in play, but cannot look at or lose any life points."
},
"Lounge Car": {
"name": "Lounge Car",
"desc": "Discard this card to draw 2 cards from the deck and put 1 of them in play in front of you and 1 in front of another player."
},
"Lumber Flatcar": {
"name": "Lumber Flatcar",
"desc": "Play this card on any player (including yourself). While this card is in play, that player sees all other players at a distance increased by 1."
},
"Mail Car": {
"name": "Mail Car",
"desc": "Discard this card to draw 3 cards and give 1 of them to another player of your choice."
},
"Observation Car": {
"name": "Observation Car",
"desc": "You see other players at a distance reduced by 1. Other players see you at a distance increased by 1."
},
"Passenger Car": {
"name": "Passenger Car",
"desc": "Discard this card to draw a card (from hand or in play) from another player."
},
"Prisoner Car": {
"name": "Prisoner Car",
"desc": "Duel and Indians! cards played by other players have no effect on you."
},
"Private Car": {
"name": "Private Car",
"desc": "If you have no cards in hand, you cannot be targeted by BANG! cards."
},
"Sleeper Car": {
"name": "Sleeper Car",
"desc": "Once per turn, you may discard another of your blue-bordered cards in play."
}
},
"help": {
@ -472,6 +1029,23 @@
"outlaw": "Outlaw",
"sheriff": "Sheriff",
"allcharacters": "All characters",
"gotoallcharacters": "Jump to all characters"
"gotoallcharacters": "Jump to all characters",
"gotocards": "Jump to cards",
"gotohighnoon": "Jump to High Noon",
"gotofoc": "Jump to Fistful Of Cards",
"gotogoldrush": "Jump to Gold Rush",
"highnooncards": "High Noon - Event Cards",
"foccards": "Fistful of Cards - Event Cards",
"goldrushcards": "Gold Rush Cards",
"valleyofshadowscards": "The Valley of Shadows Cards",
"wildwestshowcards": "Wild West Show Cards",
"trainrobberycards": "Train Robbery Cards"
},
"theme": {
"sepia": "Sepia",
"light": "Light",
"dark": "Dark",
"grayscale": "Grayscale",
"black": "True Black"
}
}

918
frontend/src/i18n/es.json Normal file
View File

@ -0,0 +1,918 @@
{
"trademark": "¡Bang! es una marca registrada propiedad de DVGiochi",
"tip_1": "¡Mejor con amigos!",
"tip_2": "¡El icono 🤖️ significa que un jugador es un bot!",
"tip_3": "¡Puedes hacer clic en las cartas de personajes y equipos de otros jugadores si deseas saber más!",
"tip_4": "¡Incluye Dodge City, High Noon, Fistful Of Cards!",
"tip_5": "¿Encontraste un error? ¡Envíanos un mensaje en Discord!",
"tip_6": "¡Ahora con un servidor de Discord!",
"tip_7": "¡Si quieres ayudarnos a traducir el juego a tu idioma, contáctanos en Discord!",
"tip_8": "¡Si te desconectas durante una partida en curso, serás reemplazado por un bot (mientras estás ausente)!",
"tip_9": "¡Si estás en el móvil, mantén pulsada una carta para leer la descripción!",
"tip_10": "¡En caso de duda, dispara a todos los demás jugadores!",
"online_players": "Jugadores en línea: ",
"shuffle_players": "Mezclar jugadores",
"choose_username": "Elige un nombre de usuario:",
"report_bug": "Escribe en qué consiste el error",
"report": "Reportar un error",
"available_lobbies": "Salas disponibles:",
"spectate_lobbies": "Ver partidas en curso:",
"no_lobby_available": "No hay salas disponibles",
"create_lobby": "Abrir una sala:",
"characters_to_distribute": "Personajes a distribuir: ",
"lobby_name": "Nombre:",
"leave_room": "Salir de la sala",
"warning": "¡Advertencia!",
"connection_error": "No se puede conectar al servidor.",
"end_turn": "¡Terminar turno!",
"start_game": "¡Empezar!",
"expansions": "Expansiones",
"click_to_toggle": "Haz clic para alternar",
"details": "Detalles",
"ok": "OK",
"you": "TÚ",
"owner": "PROPIETARIO",
"cancel": "CANCELAR",
"send": "ENVIAR",
"password": "Contraseña: ",
"room_password_prompt": "Contraseña de la sala: ",
"private_room": "Sala privada",
"room": "Sala: ",
"room_players": "Jugadores (tú eres {username})",
"choose_character": "Elige tu personaje",
"choose_card": "Elige una carta",
"choose_card_from": " de ",
"flip_card": "↙️ Voltear una carta",
"draw_cards": "⏬ Roba tus cartas del mazo",
"play_cards": "▶️ Juega tus cartas",
"respond_card": "↩️ Responder a la carta",
"wait": "⏸ Espera",
"choose_cards": "🔽 Elige una carta",
"take_dmg": "Recibir daño",
"choose_response": "Elige tu respuesta ",
"choose_response_to": "a ",
"choose_response_needed": "NECESARIA ",
"choose_manette": "Elige un palo, solo podrás jugar cartas con ese palo en este turno.",
"hand": "MANO",
"card_against": "¿Contra quién jugarás tu carta?",
"choose_sid_scrap": "Descarta 2 cartas para no morir",
"choose_card_to_get": "Elige una carta",
"choose_guess": "Adivina el color del palo",
"choose_ranch": "Elige las cartas para reemplazar",
"choose_dalton": "Elige qué equipo descartar",
"choose_fratelli_di_sangue": "Elige a quién quieres donar una de tus vidas",
"choose_fantasma": "Elige a quién resucitar",
"choose_sventagliata": "Elige otro objetivo para golpear con Fanning",
"choose_tornado": "Elige una carta para descartar por el tornado",
"choose_bandidos": "Elige entre descartar 2 cartas o perder una vida (1 carta si solo tienes 1)",
"choose_poker": "Todos descartan 1 carta (si no hay As, el jugador que jugó poker elige 2 cartas)",
"choose_from_poker;2": "Elige qué cartas obtener (máx. 2)",
"choose_from_poker;1": "Elige qué carta obtener",
"choose_cecchino": "Elige a quién disparar",
"choose_rimbalzo_player": "Elige el objetivo del rebote",
"choose_rimbalzo_card": "Elige la carta para descartar el rebote",
"choose_nuova_identita": "Elige si quieres mantener tu personaje actual o si quieres cambiarlo y empezar con 2 PV",
"choose_bicchierino": "Un jugador de tu elección recupera 1 PV",
"choose_bottiglia": "¡Elige cómo jugar la Botella!",
"choose_complice": "¡Elige cómo jugar el Cómplice!",
"choose_ricercato": "Elige contra quién jugar Se Busca.",
"choose_birra_function": "Elige entre obtener 1 pepita de oro descartando la cerveza o si quieres jugar la cerveza.",
"choose_play_as_bang": "Elige qué carta jugar como Bang!",
"choose_flint_special": "Elige qué carta intercambiar.",
"emporio_others": "{0} está eligiendo qué carta obtener de la Tienda General",
"you_died": "ESTÁS MUERTO",
"spectate": "ESPECTAR",
"you_win": "HAS GANADO",
"you_lose": "HAS PERDIDO",
"special_ability": "HABILIDAD ESPECIAL",
"gold_rush_discard": "Descarta el equipo de la fiebre del oro de otro jugador (pagando el precio + 1)",
"gold_rush_discard_2": "Descarta el equipo de la fiebre del oro de otro jugador (pagando el precio + 1)",
"discard": "DESCARTAR",
"to_regain_1_hp": "PARA RECUPERAR 1 PV",
"play_your_turn": "JUEGA TU TURNO",
"you_are": "Eres",
"did_pick_as": "eligió esto como segunda carta",
"blackjack_special": "Si la carta es de diamantes o corazones, roba otra carta.",
"choose_scarp_card_to": "ELIGE QUÉ CARTA DESCARTAR PARA USAR",
"pick_a_card": "VOLTEAR UNA CARTA",
"to_defend_from": "PARA DEFENDERTE DE",
"submit": "Enviar",
"copy": "Copiar invitación",
"no_players_in_range": "No puedes ver a los otros jugadores, equipa un arma o un visor!",
"cantplaycard": "¡No puedes jugar esta carta así!",
"chat": {
"spectators": " | Un espectador está viendo la partida | {n} espectadores están viendo la partida",
"chat": "Chat",
"joined": "👋 ;{0}; se unió a la sala",
"died": "☠️ ;{0}; murió",
"died_role": "☠️ ;{0}; era un ;{1};!",
"won": "🏆 ;{0}; ganó! Su rol era ;{1};",
"choose_character": ";{0}; tiene ;{1}; como personaje, su habilidad especial es: ;{2};!",
"starting": "¡El juego está comenzando!",
"sheriff": "⭐ ;{0}; es el sheriff!",
"did_choose_character": ";{0}; eligió el personaje.",
"turn": "⏩ Es el turno de ;{0};.",
"draw_from_scrap": ";{0}; robó la primera carta del montón de descartes.",
"draw_from_player": ";{0}; robó la primera carta de la mano de ;{1};.",
"flipped": ";{0}; volteó un ;{1}; ;{2};.",
"scrapped": ";{0}; descartó un ;{1}; ;{2};.",
"explode": "💥 ;{0}; hizo explotar la dinamita.",
"beer_save": ";{0}; usó una cerveza para salvar su vida.",
"get_nugget": ";{0}; obtuvo una pepita de oro usando una Cerveza.",
"play_card": ";{0}; jugó ;{1};.",
"play_card_green": ";{0}; puso en juego ;{1};.",
"play_card_with": ";{0}; jugó ;{1};, descartando ;{2};.",
"purchase_card": ";{0}; compró ;{1};.",
"play_card_against": ";{0}; jugó ;{1}; contra ;{2};.",
"play_card_against_with": ";{0}; jugó ;{1}; contra ;{2};, descartando ;{3};.",
"play_card_for": ";{0}; jugó ;{1}; para ;{2};.",
"spilled_beer": ";{0}; derramó una ;{1};.",
"diligenza": ";{0}; jugó ;{1}; y roba 2 cartas.",
"wellsfargo": ";{0}; jugó ;{1}; y roba 3 cartas.",
"saloon": "🍻 ;{0}; jugó ;{1}; y cura 1 PV a todos los vivos.",
"special_bart_cassidy": ";{0}; recibió una compensación porque fue herido.",
"special_el_gringo": ";{0}; robó una carta de ;{1}; cuando fue herido.",
"special_calamity": ";{0}; jugó ;{1}; como Bang! contra ;{2};.",
"allroles3": "En el juego hay: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};.",
"allroles4": "En el juego hay: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};, ;{7}; ;{6};.",
"guess": "🤔 ;{0}; adivina ;{1};.",
"guess_right": ";{0}; tenía razón.",
"guess_wrong": ";{0}; estaba equivocado.",
"fratelli_sangue": ";{0}; dio una de sus vidas a ;{1};.",
"doctor_heal": ";{0}; fue curado por el doctor.",
"respond": "↩️ ;{0}; respondió con ;{1};.",
"change_username": "✏️ ;{0}; ahora es ;{1};.",
"lobby_reset": "Volviendo a la sala en ;{0}; segundos...",
"prison_free": "🆓 ;{0}; salió de la prisión",
"prison_turn": "🔐 ;{0}; se quedó en prisión este turno",
"flip_event": "🎴 EVENTO: ;{0}; 🎴",
"choose_manette": ";{0}; se comprometió a jugar solo cartas del palo ;{1}; en este turno.",
"UnionPacific": ";{0}; jugó Union Pacific y roba 4 cartas del mazo",
"use_special": ";{0}; usó la habilidad especial de su personaje (;{1};)",
"gold_rush_pay_discard": ";{0}; descartó ;{2}; de ;{1};.",
"choose_emporio": ";{0}; eligió ;{1}; de la Tienda General.",
"shotgun_scrap": "Cuando la escopeta golpeó a ;{0};, una carta voló de su mano (;{1};)",
"taglia_reward": "💰 ;{1}; obtuvo una carta de la recompensa por ;{0};",
"snake_bit": "🐍 ;{0}; fue mordido por la serpiente de cascabel."
},
"foc": {
"leggedelwest": "Debe jugar esta carta en este turno si es posible."
},
"mods": "Modificadores",
"bots": "Bots",
"add_bot": "Añadir un bot",
"remove_bot": "Eliminar un bot",
"minimum_players": "El juego necesita al menos 3 jugadores para empezar",
"mod_comp": "Modo competitivo (desactiva recibir daño automáticamente)",
"disconnect_bot": "Reemplazar jugadores que se desconecten por bots",
"your_turn": "¡Juega tu turno!",
"your_response": "¡Responde!",
"your_choose": "¡Elige una carta!",
"cards": {
"Barile": {
"name": "Barril",
"desc": "Cuando alguien juega un Bang contra ti. Puedes voltear la primera carta del mazo, si el palo es corazones, cuenta como una carta Fallaste"
},
"Dinamite": {
"name": "Dinamita",
"desc": "Al jugar la dinamita, colócala frente a ti, permanecerá inofensiva durante toda una ronda. Al comienzo del siguiente turno antes de robar y antes de cualquier volteo de carta (ej. Prisión), voltea una carta de la parte superior del mazo. Si una carta está entre 2 y 9 de picas (inclusive), la dinamita explota: pierdes 3 vidas y descartas la carta, de lo contrario, pasa la dinamita al siguiente jugador, quien robará a su vez después de haber terminado su turno"
},
"Mirino": {
"name": "Mira",
"desc": "Ves a los otros jugadores a una distancia de -1"
},
"Mustang": {
"name": "Mustang",
"desc": "Los otros jugadores te ven a una distancia de +1"
},
"Prigione": {
"name": "Prisión",
"desc": "Equipa esta carta a otro jugador, excepto el Sheriff. El jugador elegido al comienzo de su turno, debe voltear una carta antes de robar: si es corazones, descarta esta carta y juega el turno normalmente, de lo contrario, descarta esta carta y salta el turno"
},
"Remington": {
"name": "Remington",
"desc": "Puedes disparar a otro jugador a una distancia de 3 o menos"
},
"Rev Carabine": {
"name": "Rev. Carabina",
"desc": "Puedes disparar a otro jugador a una distancia de 4 o menos"
},
"Schofield": {
"name": "Schofield",
"desc": "Puedes disparar a otro jugador a una distancia de 2 o menos"
},
"Volcanic": {
"name": "Volcánica",
"desc": "Puedes disparar a otro jugador a una distancia de 1 o menos, sin embargo, ya no tienes el límite de 1 Bang"
},
"Winchester": {
"name": "Winchester",
"desc": "Puedes disparar a otro jugador a una distancia de 5 o menos"
},
"Bang!": {
"name": "Bang!",
"desc": "Dispara a un jugador a la vista. Si no tienes armas, tu vista es de 1"
},
"Birra": {
"name": "Cerveza",
"desc": "Juega esta carta para recuperar un punto de vida. No puedes curarte más allá del límite máximo de tu personaje. Si estás a punto de perder tu último punto de vida, también puedes jugar esta carta en el turno de tu oponente. La cerveza ya no tiene efecto si solo quedan dos jugadores"
},
"Cat Balou": {
"name": "Cat Balou",
"desc": "Elige y descarta una carta de otro jugador."
},
"Diligenza": {
"name": "Diligencia",
"desc": "Roba 2 cartas del mazo."
},
"Duello": {
"name": "Duelo",
"desc": "Juega esta carta contra cualquier jugador. Por turnos, comenzando con tu oponente, puedes descartar una carta Bang!, el primer jugador que no lo haga pierde 1 vida."
},
"Emporio": {
"name": "Tienda General",
"desc": "Pon sobre la mesa N cartas del mazo, donde N es el número de jugadores vivos, por turnos, comenzando contigo, elige una carta y agrégala a tu mano"
},
"Gatling": {
"name": "Gatling",
"desc": "Dispara a todos los otros jugadores"
},
"Indiani!": {
"name": "¡Indios!",
"desc": "Todos los demás jugadores deben descartar una carta Bang! o perder 1 punto de vida"
},
"Mancato!": {
"name": "¡Fallaste!",
"desc": "Usa esta carta para cancelar el efecto de un Bang"
},
"Panico!": {
"name": "¡Pánico!",
"desc": "Roba una carta a un jugador a una distancia de 1"
},
"Saloon": {
"name": "Saloon",
"desc": "Todos recuperan 1 punto de vida"
},
"WellsFargo": {
"name": "Wells Fargo",
"desc": "Roba 3 cartas del mazo"
},
"Binocolo": {
"name": "Binoculares",
"desc": "Ves a los otros jugadores a una distancia de -1"
},
"Riparo": {
"name": "Escondite",
"desc": "Los otros jugadores te ven a una distancia de +1"
},
"Pugno!": {
"name": "¡Puñetazo!",
"desc": "Dispara a un jugador a una distancia de 1"
},
"Rag Time": {
"name": "Rag Time",
"desc": "Roba una carta de otro jugador a cualquier distancia"
},
"Rissa": {
"name": "Pelea",
"desc": "Elige una carta para descartar de la mano/equipo de todos los demás jugadores"
},
"Schivata": {
"name": "Esquiva",
"desc": "Usa esta carta para cancelar el efecto de un Bang y luego roba una carta."
},
"Springfield": {
"name": "Springfield",
"desc": "Dispara a un jugador a cualquier distancia"
},
"Tequila": {
"name": "Tequila",
"desc": "Cura 1 PV a un jugador de tu elección (puede ser tú)"
},
"Whisky": {
"name": "Whisky",
"desc": "Cura 2 PV"
},
"Bibbia": {
"name": "Biblia",
"desc": "Usa esta carta para cancelar el efecto de un Bang y luego roba una carta."
},
"Cappello": {
"name": "Sombrero de Diez Galones",
"desc": "Usa esta carta para cancelar el efecto de un Bang"
},
"Placca Di Ferro": {
"name": "Placa de Hierro",
"desc": "Usa esta carta para cancelar el efecto de un Bang"
},
"Sombrero": {
"name": "Sombrero",
"desc": "Usa esta carta para cancelar el efecto de un Bang"
},
"Pugnale": {
"name": "Cuchillo",
"desc": "Dispara a un jugador a una distancia de 1"
},
"Derringer": {
"name": "Derringer",
"desc": "Dispara a un jugador a una distancia de 1 y luego roba una carta."
},
"Borraccia": {
"name": "Cantimplora",
"desc": "Recupera 1 PV"
},
"Can Can": {
"name": "Can Can",
"desc": "Elige y descarta una carta de otro jugador."
},
"Conestoga": {
"name": "Conestoga",
"desc": "Roba una carta de otro jugador a cualquier distancia"
},
"Fucile Da Caccia": {
"name": "Rifle de Búfalo",
"desc": "Dispara a un jugador a cualquier distancia"
},
"Pony Express": {
"name": "Pony Express",
"desc": "Roba 3 cartas del mazo"
},
"Pepperbox": {
"name": "Pepperbox",
"desc": "Dispara a un jugador a la vista. Si no tienes armas, tu vista es de 1"
},
"Howitzer": {
"name": "Howitzer",
"desc": "Dispara a todos los otros jugadores"
},
"Bart Cassidy": {
"name": "Bart Cassidy",
"desc": "Cada vez que es herido, roba una carta."
},
"Black Jack": {
"name": "Black Jack",
"desc": "Al comienzo de su turno, cuando tiene que robar, muestra a todos la segunda carta, si es corazones o diamantes, roba una tercera carta sin mostrarla."
},
"Calamity Janet": {
"name": "Calamity Janet",
"desc": "Puede usar las cartas Fallaste! como Bang! y viceversa."
},
"El Gringo": {
"name": "El Gringo",
"desc": "Cada vez que es herido, roba una carta de la mano del jugador atacante."
},
"Jesse Jones": {
"name": "Jesse Jones",
"desc": "Cuando tiene que robar sus cartas, puede robar la primera carta de la mano de otro jugador. (haz clic en las cartas del jugador enemigo si deseas usar la habilidad)"
},
"Jourdonnais": {
"name": "Jourdonnais",
"desc": "Juega como si tuviera un Barril siempre activo, si equipa otro Barril, puede voltear 2 cartas."
},
"Kit Carlson": {
"name": "Kit Carlson",
"desc": "Cuando tiene que robar, mira 3 cartas y elige 2, colocando la otra carta en la parte superior del mazo."
},
"Lucky Duke": {
"name": "Lucky Duke",
"desc": "Cada vez que tiene que voltear una carta, puede voltear 2 veces."
},
"Paul Regret": {
"name": "Paul Regret",
"desc": "Los otros jugadores lo ven a una distancia de +1."
},
"Pedro Ramirez": {
"name": "Pedro Ramirez",
"desc": "Cuando tiene que robar, puede tomar la primera carta del montón de descartes. (haz clic en las cartas descartadas para usar la habilidad)"
},
"Rose Doolan": {
"name": "Rose Doolan",
"desc": "Ve a los otros jugadores a una distancia de -1."
},
"Sid Ketchum": {
"name": "Sid Ketchum",
"desc": "Puede descartar 2 cartas para recuperar 1 PV."
},
"Slab The Killer": {
"name": "Slab The Killer",
"desc": "Para esquivar sus cartas Bang!, los otros jugadores necesitan 2 cartas Fallaste!"
},
"Suzy Lafayette": {
"name": "Suzy Lafayette",
"desc": "Siempre que tiene la mano vacía, roba una carta."
},
"Vulture Sam": {
"name": "Vulture Sam",
"desc": "Cuando un jugador muere, obtiene todas las cartas en la mano y los equipos del muerto."
},
"Willy The Kid": {
"name": "Willy The Kid",
"desc": "No tiene límites en la cantidad de Bang que puede usar."
},
"Pixie Pete": {
"name": "Pixie Pete",
"desc": "Roba 3 cartas en lugar de 2."
},
"Tequila Joe": {
"name": "Tequila Joe",
"desc": "Cuando juega una Cerveza, recupera 2 PV."
},
"Greg Digger": {
"name": "Greg Digger",
"desc": "Siempre que un jugador muere, recupera hasta 2 vidas."
},
"Herb Hunter": {
"name": "Herb Hunter",
"desc": "Siempre que un jugador muere, roba 2 cartas."
},
"Elena Fuente": {
"name": "Elena Fuente",
"desc": "Puede usar cualquier carta de su mano como Fallaste."
},
"Bill Noface": {
"name": "Bill Noface",
"desc": "Roba 1 carta + 1 carta por cada herida que tiene."
},
"Molly Stark": {
"name": "Molly Stark",
"desc": "Cuando usa una carta de su mano fuera de su turno, roba una carta."
},
"Apache Kid": {
"name": "Apache Kid",
"desc": "Las cartas de diamantes ♦️ jugadas contra él no tienen efecto (no funciona en duelos)."
},
"Sean Mallory": {
"name": "Sean Mallory",
"desc": "Puede mantener hasta 10 cartas en su mano al terminar el turno."
},
"Belle Star": {
"name": "Belle Star",
"desc": "Durante su turno, las cartas verdes y azules de los otros jugadores no funcionan."
},
"Vera Custer": {
"name": "Vera Custer",
"desc": "Antes de robar, puede elegir la habilidad especial de otro jugador vivo. Esta habilidad se usa hasta el próximo turno."
},
"Chuck Wengam": {
"name": "Chuck Wengam",
"desc": "En su turno, puede decidir perder 1 PV para robar 2 cartas del mazo."
},
"Pat Brennan": {
"name": "Pat Brennan",
"desc": "En lugar de robar, puede robar una carta del equipo de otro jugador. (haz clic en el jugador enemigo si deseas usar la habilidad)"
},
"José Delgado": {
"name": "José Delgado",
"desc": "En su turno, puede descartar una carta azul para robar 2 cartas, hasta dos veces por turno."
},
"Doc Holyday": {
"name": "Doc Holyday",
"desc": "Puede descartar 2 cartas para jugar un Bang."
},
"Fuorilegge": {
"name": "Forajido"
},
"Rinnegato": {
"name": "Renegado"
},
"Sceriffo": {
"name": "Sheriff"
},
"Vice": {
"name": "Ayudante"
},
"Miniera Abbandonata": {
"name": "Mina Abandonada",
"desc": "Los jugadores roban del montón de descartes en su fase 1 y descartan en la parte superior del mazo durante la fase 3 (si el montón de descartes se agota, deben robar y descartar en la parte superior del mazo)"
},
"Il Giudice": {
"name": "El Juez",
"desc": "No puedes equipar cartas a ti mismo ni a otros jugadores"
},
"Agguato": {
"name": "Emboscada",
"desc": "La distancia base entre dos jugadores es de 1"
},
"Rimbalzo": {
"name": "Rebote",
"desc": "El jugador puede jugar Bang contra las cartas equipadas por los otros jugadores, si no juegan Fallaste, se descartan (haz clic en la carta de evento)"
},
"Cecchino": {
"name": "Francotirador",
"desc": "Durante su turno, los jugadores pueden descartar 2 Bang! para disparar un Bang! que requiere 2 Fallaste (haz clic en la carta)"
},
"Lazo": {
"name": "Lazo",
"desc": "Las cartas en la ranura de equipo no funcionan"
},
"Ranch": {
"name": "Rancho",
"desc": "Después de robar, el jugador puede descartar tantas cartas como quiera de su mano y robar tantas del mazo"
},
"Dead Man": {
"name": "Hombre Muerto",
"desc": "El primer jugador que muera vuelve a la vida con 2 PV y 2 cartas"
},
"Liquore Forte": {
"name": "Licor Fuerte",
"desc": "Los jugadores pueden saltar el robo para recuperar 1 PV (haz clic en la carta de evento para usar)"
},
"Vendetta": {
"name": "Venganza",
"desc": "Al terminar el turno, el jugador voltea una carta del mazo, si es un ❤️ juega otro turno (pero no voltea otra carta)"
},
"Roulette Russa": {
"name": "Ruleta Rusa",
"desc": "Comenzando por el sheriff, cada jugador descarta 1 Fallaste, el primero que no lo haga pierde 2 PV"
},
"Legge Del West": {
"name": "Ley del Oeste",
"desc": "Cada jugador muestra la segunda carta que roba y debe usarla en esa ronda (si es posible)"
},
"Peyote": {
"name": "Peyote",
"desc": "En lugar de robar, el jugador intenta adivinar el color del palo, si acierta, agrega la carta a su mano y continúa intentando adivinar la siguiente carta"
},
"Fratelli Di Sangue": {
"name": "Hermanos de Sangre",
"desc": "Al comienzo de su turno, los jugadores pueden perder 1 PV (excepto el último) para dárselo a otro jugador"
},
"I Dalton": {
"name": "Los Dalton",
"desc": "Los jugadores que tengan cartas azules equipadas, descartan una de esas cartas a su elección"
},
"Sermone": {
"name": "El Sermón",
"desc": "Los jugadores no pueden jugar Bang! durante su turno"
},
"Città Fantasma": {
"name": "Ciudad Fantasma",
"desc": "Todos los jugadores muertos vuelven a la vida en su turno, no pueden morir y roban 3 cartas en lugar de 2. Cuando terminan su turno, mueren."
},
"Il Reverendo": {
"name": "El Reverendo",
"desc": "Las cervezas no se pueden jugar"
},
"Sbornia": {
"name": "Resaca",
"desc": "Los personajes pierden sus habilidades especiales"
},
"Il Dottore": {
"name": "El Doctor",
"desc": "El jugador con la menor cantidad de PV recupera 1 PV"
},
"Corsa All Oro": {
"name": "Fiebre del Oro",
"desc": "Los turnos se juegan en sentido antihorario"
},
"Maledizione": {
"name": "Maldición",
"desc": "Todas las cartas son de picas ♠️"
},
"Sparatoria": {
"name": "Tiroteo",
"desc": "El límite de Bang! del turno es de 2"
},
"Benedizione": {
"name": "Bendición",
"desc": "Todas las cartas son de corazones ❤️"
},
"Il Treno": {
"name": "Llegada del Tren",
"desc": "Los jugadores roban 1 carta extra"
},
"Sete": {
"name": "Sed",
"desc": "Los jugadores solo roban 1 carta al comienzo de su turno"
},
"Nuova Identita": {
"name": "Nueva Identidad",
"desc": "Al comienzo de su turno, cada jugador puede elegir cambiar su personaje con el otro mostrado al comienzo del juego. Si lo hace, comienza con 2 PV"
},
"Manette": {
"name": "Esposas",
"desc": "Después de robar en la fase 1, el jugador declara un palo. Solo podrá usar cartas de ese palo durante ese turno"
},
"Mezzogiorno di Fuoco": {
"name": "Mediodía de Fuego",
"desc": "Cada jugador pierde 1 PV al comenzar su turno"
},
"Per Un Pugno Di Carte": {
"name": "Por un Puñado de Cartas",
"desc": "Al comienzo de su turno, el jugador es objetivo de tantos Bang como cartas tenga en su mano"
},
"Pepita": {
"name": "Pepita de Oro"
},
"Bicchierino": {
"name": "Chupito",
"desc": "Puedes elegir a un jugador que recupere 1 PV (incluso tú)"
},
"Bottiglia": {
"name": "Botella",
"desc": "Se puede jugar como Pánico!, Cerveza o Bang!"
},
"Complice": {
"name": "Cómplice",
"desc": "Se puede jugar como Tienda General, Duelo o Cat Balou."
},
"Corsa All Oro_gr": {
"name": "Fiebre del Oro",
"desc": "Terminas tu turno, recuperas todos tus PV y comienzas un nuevo turno."
},
"Rum": {
"name": "Ron",
"desc": "Voltea 4 cartas, por cada palo diferente, ganas 1 PV."
},
"Union Pacific": {
"name": "Union Pacific",
"desc": "Roba 4 cartas del mazo."
},
"Calumet": {
"name": "Calumet",
"desc": "Las cartas de diamantes jugadas por otros jugadores no tienen efecto sobre ti."
},
"Cinturone": {
"name": "Cinturón",
"desc": "Puedes mantener hasta 8 cartas cuando terminas tu turno."
},
"Ferro di Cavallo": {
"name": "Herradura",
"desc": "Cada vez que tienes que voltear una carta, ¡volteas dos veces!"
},
"Piccone": {
"name": "Pico",
"desc": "Obtienes 1 carta más cuando robas al comienzo del turno."
},
"Ricercato": {
"name": "Se Busca",
"desc": "Juega sobre otro jugador, quien mate al objetivo obtiene 2 cartas extra y 1 pepita de oro."
},
"Setaccio": {
"name": "Cazador de Oro",
"desc": "Paga 1 pepita de oro para robar 1 carta del mazo, hasta dos veces por turno. (Haz clic en la carta equipada para usar)"
},
"Stivali": {
"name": "Botas",
"desc": "Cada vez que pierdes 1 PV, robas 1 carta del mazo."
},
"Talismano": {
"name": "Amuleto de la Suerte",
"desc": "Cada vez que pierdes 1 PV, obtienes 1 pepita de oro."
},
"Zaino": {
"name": "Mochila",
"desc": "Paga 2 pepitas de oro para curar 1 PV. (Haz clic en la carta equipada para usar)"
},
"Don Bell": {
"name": "Don Bell",
"desc": "Cuando termina su turno, voltea una carta, si es Corazones ❤️ o Diamantes ♦️, juega nuevamente."
},
"Dutch Will": {
"name": "Dutch Will",
"desc": "Roba 2 cartas, descarta 1 y toma 1 pepita de oro."
},
"Jacky Murieta": {
"name": "Jacky Murieta",
"desc": "Durante su turno puede pagar 2 pepitas de oro para tener la capacidad de disparar otro Bang!"
},
"Josh McCloud": {
"name": "Josh McCloud",
"desc": "Puede pagar 2 pepitas de oro para obtener la primera carta del mazo de fiebre del oro."
},
"Madam Yto": {
"name": "Madam Yto",
"desc": "Roba 1 carta del mazo cada vez que se juega una cerveza."
},
"Pretty Luzena": {
"name": "Pretty Luzena",
"desc": "Una vez por turno, puede tener un descuento de 1 en la tienda de cartas de fiebre del oro."
},
"Raddie Snake": {
"name": "Raddie Snake",
"desc": "Puede descartar 1 pepita de oro para robar 1 carta del mazo durante su turno (máximo 2 veces por turno)."
},
"Simeon Picos": {
"name": "Simeon Picos",
"desc": "Obtiene 1 pepita de oro cada vez que pierde 1 PV."
},
"Fantasma": {
"name": "Fantasma",
"desc": "Juega sobre cualquier jugador eliminado: ese jugador vuelve al juego, pero no puede ganar ni perder puntos de vida."
},
"Lemat": {
"name": "Lemat",
"desc": "Durante tu turno puedes usar cualquier carta como Bang! (Haz clic en la carta una vez equipada)."
},
"SerpenteASonagli": {
"name": "Serpiente de Cascabel",
"desc": "Juega sobre cualquier jugador. Al comienzo de su turno, si ese jugador roba en Picas, pierde 1 punto de vida."
},
"Shotgun": {
"name": "Escopeta",
"desc": "Cada vez que hieres a un jugador, debe descartar una carta de su mano."
},
"Taglia": {
"name": "Recompensa",
"desc": "Juega sobre cualquier jugador. Si ese jugador es golpeado por Bang!, la persona que disparó obtiene una carta del mazo."
},
"Mira": {
"name": "Apuntar",
"desc": "Juega esta carta junto con una carta Bang!. Si el objetivo es golpeado, pierde 2 puntos de vida."
},
"RitornoDiFiamma": {
"name": "Retroceso",
"desc": "Cuenta como una carta Fallaste!. El jugador que disparó es el objetivo de un Bang!."
},
"Bandidos": {
"name": "Bandidos",
"desc": "Cada jugador elige entre descartar 2 cartas de su mano (o 1 si solo tiene 1) o perder 1 punto de vida."
},
"Fuga": {
"name": "Fuga",
"desc": "Puede jugarse fuera de turno. Evita el efecto de una carta marrón (no Bang!) de la que eres objetivo."
},
"Sventagliata": {
"name": "Acribillar",
"desc": "Cuenta como el único Bang! del turno. Un jugador de tu elección a una distancia de 1 del objetivo (si lo hay, excluyéndote a ti mismo) también es objetivo de un Bang."
},
"UltimoGiro": {
"name": "Última Ronda",
"desc": "Recupera 1 punto de vida"
},
"Poker": {
"name": "Póker",
"desc": "Todos los demás jugadores descartan una carta de su mano, al mismo tiempo. Si no hay Ases, roba hasta 2 de esas cartas."
},
"Salvo": {
"name": "¡Salvado!",
"desc": "Puede jugarse fuera de turno. Evita que otro jugador pierda 1 punto de vida. Si sobrevive, roba 2 cartas de su mano o del mazo (a tu elección)."
},
"Tomahawk": {
"name": "Tomahawk",
"desc": "Ataca a un jugador hasta una distancia de 2."
},
"Tornado": {
"name": "Tornado",
"desc": "Todos descartan una carta de su mano (si es posible), luego roban 2 cartas del mazo."
},
"Black Flower": {
"name": "Flor Negra",
"desc": "Una vez por turno, puedes usar una carta de Picas para disparar un Bang! extra"
},
"Colorado Bill": {
"name": "Colorado Bill",
"desc": "Cada vez que juegas una carta Bang!, si robas una Picas, el disparo no puede ser evitado."
},
"Der Spot Burst Ringer": {
"name": "Der Spot Burst Ringer",
"desc": "Una vez por turno, puedes usar una carta Bang! como una Gatling."
},
"Evelyn Shebang": {
"name": "Evelyn Shebang",
"desc": "Puedes elegir no robar cartas durante tu fase de robo. Por cada carta no robada, disparas un Bang! a un objetivo alcanzable, a un objetivo diferente."
},
"Henry Block": {
"name": "Henry Block",
"desc": "Cualquiera que robe o descarte una de tus cartas en juego o en mano es objetivo de un Bang!."
},
"Lemonade Jim": {
"name": "Lemonade Jim",
"desc": "Cada vez que otro jugador juega una Cerveza, puedes descartar una carta de tu mano para recuperar también 1 punto de vida."
},
"Mick Defender": {
"name": "Mick Defender",
"desc": "Si eres objetivo de una carta marrón (no Bang!), puedes usar una carta Fallaste! para evitar 1 efecto."
},
"Tuco Franziskaner": {
"name": "Tuco Franziskaner",
"desc": "Si no tienes cartas azules equipadas, robas 2 cartas adicionales."
},
"Big Spencer": {
"name": "Big Spencer",
"desc": "Comienza con 5 cartas. No puede jugar Fallaste!"
},
"Flint Westwood": {
"name": "Flint Westwood",
"desc": "Puede intercambiar una carta de su mano con 2 cartas aleatorias de la mano de otro jugador durante su turno."
},
"Gary Looter": {
"name": "Gary Looter",
"desc": "Roba todas las cartas sobrantes descartadas por otros jugadores al final de cada turno."
},
"Greygory Deckard": {
"name": "Greygory Deckard",
"desc": "Al comienzo de su turno, puede robar 2 personajes aleatorios y gana todas sus habilidades."
},
"John Pain": {
"name": "John Pain",
"desc": "Si tiene menos de 6 cartas en su mano, cuando un jugador \"¡roba!\", John agrega la carta robada a su mano."
},
"Lee Van Kliff": {
"name": "Lee Van Kliff",
"desc": "Durante su turno, puede descartar una carta Bang! para repetir el efecto de una carta marrón que acaba de jugar."
},
"Teren Kill": {
"name": "Teren Kill",
"desc": "Cada vez que va a ser eliminado, \"¡roba!\": si no es una carta de Picas, Teren se queda en 1 punto de vida y roba 1 carta."
},
"Youl Grinner": {
"name": "Youl Grinner",
"desc": "Antes de robar, los jugadores con más cartas en su mano que Youl deben darle una carta de su elección."
},
"Camposanto": {
"name": "Cementerio",
"desc": "Al comienzo de su turno, cada jugador eliminado vuelve al juego con 1 punto de vida. Roba una carta de rol al azar de los jugadores eliminados."
},
"Darling Valentine": {
"name": "Darling Valentine",
"desc": "Al comienzo de su turno, cada jugador descarta su mano y roba el mismo número de cartas del mazo."
},
"Dorothy Rage": {
"name": "Dorothy Rage",
"desc": "Durante su turno, cada jugador puede forzar a otro jugador a jugar una carta."
},
"Helena Zontero": {
"name": "Helena Zontero",
"desc": "Cuando Helena entra en el juego, \"¡roba!\": si se roba un Corazón o un Diamante, baraja las cartas de rol activas excepto el Sheriff y redistribúyelas al azar."
},
"Lady Rosa del Texas": {
"name": "Lady Rose of Texas",
"desc": "Durante su turno, cada jugador puede cambiar de lugar con el jugador a su derecha, quien se salta su próximo turno. (Haz clic en la carta)"
},
"Miss Susanna": {
"name": "Miss Susanna",
"desc": "Durante su turno, cada jugador debe jugar al menos 3 cartas. Si no lo hacen, pierden 1 punto de vida."
},
"Regolamento di Conti": {
"name": "Rendición de Cuentas",
"desc": "Todas las cartas pueden jugarse como si fueran Bang!. Las cartas Bang! pueden jugarse como si fueran Fallaste! (Haz clic en la carta)"
},
"Sacagaway": {
"name": "Sacagaway",
"desc": "Todos los jugadores juegan con sus cartas boca arriba (excepto su carta de rol!)."
},
"Wild West Show": {
"name": "Wild West Show",
"desc": "El objetivo de cada jugador se convierte en: \"¡Sé el último en pie!\""
}
},
"help": {
"character": "Personajes",
"characters_special": "Cada personaje tiene habilidades especiales y una cantidad de vidas que los hacen únicos. \nLas vidas son el número de puntos de vida que puedes perder antes de morir e indican también el número máximo de cartas que puedes mantener en tu mano.",
"deathnobeer": "Cuando pierdes tu último punto de vida y no tienes una cerveza 🍺️ en tu mano, mueres. \nTus cartas se descartan y tu rol se revela a todos.",
"discard": "Descartar",
"distance": "Distancia",
"distancecalc": "La distancia se calcula automáticamente por el juego y corresponde a la distancia mínima entre los jugadores a la izquierda y a la derecha.",
"drawinstructions": "Para robar cartas, debes hacer clic en el mazo cuando veas esta animación.",
"drawthecards": "Roba las cartas",
"endgame": "Fin del juego",
"endgameconditions": "El juego termina cuando se cumple una de las siguientes condiciones:",
"endgamesheriffwin": "Todos los forajidos 🐺️ y renegados 🦅️ están muertos. \nEn este caso, el sheriff ⭐️ y los ayudantes 🎖️ ganan.",
"endgameshriffdeath": "El sheriff ⭐️ muere. \nSi el renegado 🦅️ es el último jugador en pie, gana, de lo contrario, los forajidos ganan.",
"endingturn": "Cuando hayas terminado de jugar tus cartas, es decir, cuando no quieras o no puedas jugar más cartas, debes descartar las cartas que excedan tu número actual de vidas.\n\nLuego pasas el turno al siguiente jugador haciendo clic en terminar turno.",
"equipment": "EQUIPO",
"justoneweapon": "Solo puedes tener 1 arma equipada.",
"maxtwocardsequip": "No puedes tener 2 cartas con el mismo nombre equipadas.",
"outlawreward": "Cualquiera que mate a un forajido 🐺️ roba 3 cartas del mazo (otros forajidos también 🐺️).",
"playerdeath": "La muerte de un jugador",
"playingcards": "Jugar las cartas",
"playingdmg": "Puedes jugar tus cartas para ti mismo o para dañar a otros jugadores intentando eliminarlos.",
"playingduringturn": "Solo puedes jugar las cartas en tu turno. Para jugar cartas, haz clic en las cartas de tu mano.\nCon la excepción de cartas usadas como respuesta, como Fallaste 😅️.",
"playingifyouwant": "No estás obligado a jugar cartas.",
"playlimit": "Solo hay 3 limitaciones:",
"playonlyonebang": "Solo puedes jugar 1 Bang! \npor turno (se refiere solo a cartas llamadas Bang!)",
"rewardspen": "Penalidades y recompensas",
"roles": "Roles",
"sheriffkillsvice": "Si el sheriff ⭐️ mata a un ayudante, pierde todas las cartas en su mano y en juego frente a él.",
"thecards": "Cartas",
"title": "Cómo jugar",
"turndiscard": "Descarta las cartas sobrantes",
"turndraw": "Roba 2 cartas",
"turnplay": "Juega cualquier cantidad de cartas",
"turns": "Turnos",
"turnstart": "Siempre comienza con el Sheriff ⭐️, y el juego continúa en el sentido de las agujas del reloj, los turnos se dividen en 3 fases.",
"weapon": "ARMA",
"renegade": "Renegado",
"vice": "Ayudante",
"outlaw": "Forajido",
"sheriff": "Sheriff",
"allcharacters": "Todos los personajes",
"gotoallcharacters": "Ir a todos los personajes",
"gotocards": "Ir a las cartas",
"gotohighnoon": "Ir al Mediodía",
"gotofoc": "Ir a Un Puñado de Cartas",
"gotogoldrush": "Ir a Fiebre del Oro",
"highnooncards": "Mediodía - Cartas de Evento",
"foccards": "Un Puñado de Cartas - Cartas de Evento",
"goldrushcards": "Cartas de Fiebre del Oro",
"valleyofshadowscards": "Cartas del Valle de las Sombras"
},
"theme": {
"sepia": "Sepia",
"light": "Claro",
"dark": "Oscuro",
"grayscale": "Escala de Grises",
"black": "Negro"
}
}

918
frontend/src/i18n/fr.json Normal file
View File

@ -0,0 +1,918 @@
{
"trademark": "Bang! est une marque déposée détenue par DVGiochi",
"tip_1": "C'est mieux avec des amis !",
"tip_2": "L'icône 🤖️ signifie qu'un joueur est un bot !",
"tip_3": "Vous pouvez cliquer sur les cartes des personnages et des équipements des autres joueurs si vous souhaitez en savoir plus !",
"tip_4": "Dodge City, High Noon, Fistful Of Cards inclus !",
"tip_5": "Trouvé un bug ? Envoyez-nous un message sur Discord !",
"tip_6": "Maintenant avec un serveur Discord !",
"tip_7": "Si vous voulez nous aider à traduire le jeu dans votre langue, contactez-nous sur Discord !",
"tip_8": "Si vous vous déconnectez pendant une partie en cours, vous serez remplacé par un bot (pendant votre absence) !",
"tip_9": "Si vous êtes sur mobile, maintenez une carte pour lire la description !",
"tip_10": "En cas de doute, tirez sur tous les autres joueurs !",
"online_players": "Joueurs en ligne : ",
"shuffle_players": "Mélanger les joueurs",
"choose_username": "Choisissez un nom d'utilisateur :",
"report_bug": "Décrivez le bug",
"report": "Signaler un bug",
"available_lobbies": "Salles disponibles :",
"spectate_lobbies": "Observer les parties en cours :",
"no_lobby_available": "Aucune salle disponible",
"create_lobby": "Ouvrir une salle :",
"characters_to_distribute": "Personnages à distribuer : ",
"lobby_name": "Nom :",
"leave_room": "Quitter la salle",
"warning": "Attention !",
"connection_error": "Impossible de se connecter au serveur.",
"end_turn": "Terminer le tour !",
"start_game": "Commencer !",
"expansions": "Extensions",
"click_to_toggle": "Cliquez pour basculer",
"details": "Détails",
"ok": "OK",
"you": "VOUS",
"owner": "PROPRIÉTAIRE",
"cancel": "ANNULER",
"send": "ENVOYER",
"password": "Mot de passe : ",
"room_password_prompt": "Mot de passe de la salle : ",
"private_room": "Salle privée",
"room": "Salle : ",
"room_players": "Joueurs (vous êtes {username})",
"choose_character": "Choisissez votre personnage",
"choose_card": "Choisissez une carte",
"choose_card_from": " de ",
"flip_card": "↙️ Retourner une carte",
"draw_cards": "⏬ Piochez vos cartes du paquet",
"play_cards": "▶️ Jouez vos cartes",
"respond_card": "↩️ Répondez à la carte",
"wait": "⏸ Attendre",
"choose_cards": "🔽 Choisissez une carte",
"take_dmg": "Subir des dégâts",
"choose_response": "Choisissez votre réponse ",
"choose_response_to": "à ",
"choose_response_needed": "NÉCESSAIRE ",
"choose_manette": "Choisissez une couleur, vous ne pourrez jouer que des cartes de cette couleur ce tour.",
"hand": "MAIN",
"card_against": "Contre qui jouez-vous votre carte ?",
"choose_sid_scrap": "Défaussez 2 cartes pour ne pas mourir",
"choose_card_to_get": "Choisissez une carte",
"choose_guess": "Devinez la couleur de la carte",
"choose_ranch": "Choisissez les cartes à remplacer",
"choose_dalton": "Choisissez quel équipement défausser",
"choose_fratelli_di_sangue": "Choisissez à qui donner une de vos vies",
"choose_fantasma": "Choisissez qui ramener à la vie",
"choose_sventagliata": "Choisissez une autre cible pour le tir",
"choose_tornado": "Choisissez une carte à défausser pour le tornade",
"choose_bandidos": "Choisissez entre défausser 2 cartes ou perdre une vie (1 carte si vous n'avez qu'une)",
"choose_poker": "Tout le monde défausse 1 carte (s'il n'y a pas d'As, le joueur ayant joué le poker choisit 2 cartes)",
"choose_from_poker;2": "Choisissez quelles cartes récupérer (max 2)",
"choose_from_poker;1": "Choisissez quelle carte récupérer",
"choose_cecchino": "Choisissez qui tirer",
"choose_rimbalzo_player": "Choisissez la cible du rebond",
"choose_rimbalzo_card": "Choisissez la carte à défausser pour le rebond",
"choose_nuova_identita": "Choisissez si vous voulez garder votre personnage actuel ou en changer et repartir de 2 PV",
"choose_bicchierino": "Un joueur de votre choix regagne 1 PV",
"choose_bottiglia": "Choisissez comment jouer la Bouteille !",
"choose_complice": "Choisissez comment jouer Complice !",
"choose_ricercato": "Choisissez contre qui jouer Recherché.",
"choose_birra_function": "Choisissez entre obtenir 1 pépite d'or en défaussant la bière ou jouer la bière.",
"choose_play_as_bang": "Choisissez quelle carte jouer comme Bang !",
"choose_flint_special": "Choisissez quelle carte échanger.",
"emporio_others": "{0} choisit quelle carte récupérer du Magasin général",
"you_died": "VOUS ÊTES MORT",
"spectate": "SPECTATEUR",
"you_win": "VOUS AVEZ GAGNÉ",
"you_lose": "VOUS AVEZ PERDU",
"special_ability": "CAPACITÉ SPÉCIALE",
"gold_rush_discard": "Défaussez l'équipement de ruée vers l'or d'un autre joueur (en payant le prix + 1)",
"gold_rush_discard_2": "Défaussez l'équipement de ruée vers l'or d'un autre joueur (en payant le prix + 1)",
"discard": "DÉFAUSSER",
"to_regain_1_hp": "POUR REGAINER 1 PV",
"play_your_turn": "JOUEZ VOTRE TOUR",
"you_are": "Vous êtes",
"did_pick_as": "a choisi cette carte comme deuxième",
"blackjack_special": "Si la carte est un carreau ou un cœur, il pioche une autre carte.",
"choose_scarp_card_to": "CHOISISSEZ QUELLE CARTE DÉFAUSSER POUR UTILISER",
"pick_a_card": "RETIRER UNE CARTE",
"to_defend_from": "POUR VOUS DÉFENDRE DE",
"submit": "Soumettre",
"copy": "Copier l'invitation",
"no_players_in_range": "Vous ne voyez pas les autres joueurs, équipez une arme ou une lunette !",
"cantplaycard": "Vous ne pouvez pas jouer cette carte de cette façon !",
"chat": {
"spectators": " | Un spectateur regarde la partie | {n} spectateurs regardent la partie",
"chat": "Chat",
"joined": "👋 ;{0}; a rejoint la salle",
"died": "☠️ ;{0}; est mort",
"died_role": "☠️ ;{0}; était un ;{1}; !",
"won": "🏆 ;{0}; a gagné ! Leur rôle était ;{1};",
"choose_character": ";{0}; a ;{1}; comme personnage, sa capacité spéciale est : ;{2}; !",
"starting": "La partie commence !",
"sheriff": "⭐ ;{0}; est le shérif !",
"did_choose_character": ";{0}; a choisi le personnage.",
"turn": "⏩ C'est le tour de ;{0};.",
"draw_from_scrap": ";{0}; a pioché la première carte de la pile de défausse.",
"draw_from_player": ";{0}; a pioché la première carte de la main de ;{1};.",
"flipped": ";{0}; a retourné un ;{1}; ;{2};.",
"scrapped": ";{0}; a défaussé un ;{1}; ;{2};.",
"explode": "💥 ;{0}; a fait exploser la dynamite.",
"beer_save": ";{0}; a utilisé une bière pour sauver sa vie.",
"get_nugget": ";{0}; a obtenu une pépite d'or en utilisant une bière.",
"play_card": ";{0}; a joué ;{1};.",
"play_card_green": ";{0}; a mis en jeu ;{1};.",
"play_card_with": ";{0}; a joué ;{1};, en défaussant ;{2};.",
"purchase_card": ";{0}; a acheté ;{1};.",
"play_card_against": ";{0}; a joué ;{1}; contre ;{2};.",
"play_card_against_with": ";{0}; a joué ;{1}; contre ;{2};, en défaussant ;{3};.",
"play_card_for": ";{0}; a joué ;{1}; pour ;{2};.",
"spilled_beer": ";{0}; a renversé une ;{1};.",
"diligenza": ";{0}; a joué ;{1}; et pioche 2 cartes.",
"wellsfargo": ";{0}; a joué ;{1}; et pioche 3 cartes.",
"saloon": "🍻 ;{0}; a joué ;{1}; et soigne 1 PV à tous les vivants.",
"special_bart_cassidy": ";{0}; a reçu une compensation car il a été blessé.",
"special_el_gringo": ";{0}; a volé une carte à ;{1}; lorsqu'il a été blessé.",
"special_calamity": ";{0}; a joué ;{1}; comme Bang ! contre ;{2};.",
"allroles3": "Dans le jeu il y a : ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};.",
"allroles4": "Dans le jeu il y a : ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};, ;{7}; ;{6};.",
"guess": "🤔 ;{0}; devine ;{1};.",
"guess_right": ";{0}; avait raison.",
"guess_wrong": ";{0}; avait tort.",
"fratelli_sangue": ";{0}; a donné une de ses vies à ;{1};.",
"doctor_heal": ";{0}; a été soigné par le docteur.",
"respond": "↩️ ;{0}; a répondu avec ;{1};.",
"change_username": "✏️ ;{0}; est maintenant ;{1};.",
"lobby_reset": "Retour à la salle dans ;{0}; secondes...",
"prison_free": "🆓 ;{0}; est sorti de prison",
"prison_turn": "🔐 ;{0}; est resté en prison ce tour",
"flip_event": "🎴 ÉVÉNEMENT : ;{0}; 🎴",
"choose_manette": ";{0}; s'est engagé à ne jouer que des cartes de couleur ;{1}; ce tour.",
"UnionPacific": ";{0}; a joué Union Pacific et pioche 4 cartes du paquet",
"use_special": ";{0}; a utilisé la capacité spéciale de son personnage (;{1};)",
"gold_rush_pay_discard": ";{0}; a défaussé ;{2}; de ;{1};.",
"choose_emporio": ";{0}; a choisi ;{1}; du Magasin général.",
"shotgun_scrap": "Lorsque le fusil a touché ;{0}; une carte a volé de sa main (;{1};)",
"taglia_reward": "💰 ;{1}; a obtenu une carte de la prime sur ;{0};",
"snake_bit": "🐍 ;{0}; a été mordu par le serpent à sonnettes."
},
"foc": {
"leggedelwest": "Il doit jouer cette carte ce tour si possible."
},
"mods": "Modificateurs",
"bots": "Bots",
"add_bot": "Ajouter un bot",
"remove_bot": "Supprimer un bot",
"minimum_players": "Le jeu nécessite au moins 3 joueurs pour commencer",
"mod_comp": "Mode compétitif (désactive la prise de dégâts automatique)",
"disconnect_bot": "Remplacer les joueurs qui se déconnectent par des bots",
"your_turn": "Jouez votre tour !",
"your_response": "Répondez !",
"your_choose": "Choisissez une carte !",
"cards": {
"Barile": {
"name": "Baril",
"desc": "Quand quelqu'un joue un Bang contre vous. Vous pouvez retourner la première carte du paquet, si la couleur est Cœur alors elle compte comme une carte Raté"
},
"Dinamite": {
"name": "Dynamite",
"desc": "Lorsque vous jouez la Dynamite, placez-la devant vous, elle restera inoffensive pendant un tour complet. Au début du prochain tour avant de piocher et avant tout retournement de carte (par exemple Prison), retournez une carte du dessus du paquet. Si une carte est entre 2 et 9 de pique (inclus), la dynamite explose : vous perdez 3 vies et défaussez la carte, sinon passez la dynamite au joueur suivant, qui piochera à son tour après avoir terminé son tour"
},
"Mirino": {
"name": "Lunette",
"desc": "Vous voyez les autres joueurs à une distance de -1"
},
"Mustang": {
"name": "Mustang",
"desc": "Les autres joueurs vous voient à une distance de +1"
},
"Prigione": {
"name": "Prison",
"desc": "Équipez cette carte à un autre joueur, sauf le Shérif. Le joueur choisi au début de son tour, doit retourner une carte avant de piocher : si c'est Cœur, défaussez cette carte et jouez le tour normalement, sinon défaussez cette carte et passez le tour"
},
"Remington": {
"name": "Remington",
"desc": "Vous pouvez tirer sur un autre joueur à une distance de 3 ou moins"
},
"Rev Carabine": {
"name": "Rev. Carabine",
"desc": "Vous pouvez tirer sur un autre joueur à une distance de 4 ou moins"
},
"Schofield": {
"name": "Schofield",
"desc": "Vous pouvez tirer sur un autre joueur à une distance de 2 ou moins"
},
"Volcanic": {
"name": "Volcanic",
"desc": "Vous pouvez tirer sur un autre joueur à une distance de 1 ou moins, cependant vous n'avez plus la limite d'un Bang"
},
"Winchester": {
"name": "Winchester",
"desc": "Vous pouvez tirer sur un autre joueur à une distance de 5 ou moins"
},
"Bang!": {
"name": "Bang!",
"desc": "Tirez sur un joueur en vue. Si vous n'avez pas d'armes, votre vue est de 1"
},
"Birra": {
"name": "Bière",
"desc": "Jouez cette carte pour regagner un point de vie. Vous ne pouvez pas soigner plus que la limite maximale de votre personnage. Si vous êtes sur le point de perdre votre dernier point de vie, vous pouvez également jouer cette carte pendant le tour de votre adversaire. La bière ne fait plus effet s'il ne reste que deux joueurs"
},
"Cat Balou": {
"name": "Cat Balou",
"desc": "Choisissez et défaussez une carte d'un autre joueur."
},
"Diligenza": {
"name": "Diligence",
"desc": "Piochez 2 cartes du paquet."
},
"Duello": {
"name": "Duel",
"desc": "Jouez cette carte contre n'importe quel joueur. À tour de rôle, en commençant par votre adversaire, vous pouvez défausser une carte Bang!, le premier joueur qui ne le fait pas perd 1 vie."
},
"Emporio": {
"name": "Magasin Général",
"desc": "Mettez sur la table N cartes du paquet, où N est le nombre de joueurs vivants, à tour de rôle, en commençant par vous, choisissez une carte et ajoutez-la à votre main"
},
"Gatling": {
"name": "Gatling",
"desc": "Tirez sur tous les autres joueurs"
},
"Indiani!": {
"name": "Indiens !",
"desc": "Tous les autres joueurs doivent défausser une carte Bang! ou perdre 1 point de vie"
},
"Mancato!": {
"name": "Raté !",
"desc": "Utilisez cette carte pour annuler l'effet d'un Bang"
},
"Panico!": {
"name": "Panique !",
"desc": "Volez une carte à un joueur à une distance de 1"
},
"Saloon": {
"name": "Saloon",
"desc": "Tout le monde regagne 1 point de vie"
},
"WellsFargo": {
"name": "Wells Fargo",
"desc": "Piochez 3 cartes du paquet"
},
"Binocolo": {
"name": "Jumelles",
"desc": "Vous voyez les autres joueurs à une distance de -1"
},
"Riparo": {
"name": "Cachette",
"desc": "Les autres joueurs vous voient à une distance de +1"
},
"Pugno!": {
"name": "Coup de Poing !",
"desc": "Tirez sur un joueur à une distance de 1"
},
"Rag Time": {
"name": "Rag Time",
"desc": "Volez une carte à un autre joueur à n'importe quelle distance"
},
"Rissa": {
"name": "Bagarre",
"desc": "Choisissez une carte à défausser de la main/équipement de tous les autres joueurs"
},
"Schivata": {
"name": "Esquive",
"desc": "Utilisez cette carte pour annuler l'effet d'un Bang et ensuite piochez une carte."
},
"Springfield": {
"name": "Springfield",
"desc": "Tirez sur un joueur à n'importe quelle distance"
},
"Tequila": {
"name": "Tequila",
"desc": "Soignez 1 PV à un joueur de votre choix (cela peut être vous)"
},
"Whisky": {
"name": "Whisky",
"desc": "Soignez 2 PV"
},
"Bibbia": {
"name": "Bible",
"desc": "Utilisez cette carte pour annuler l'effet d'un Bang et ensuite piochez une carte."
},
"Cappello": {
"name": "Chapeau de Dix Gallons",
"desc": "Utilisez cette carte pour annuler l'effet d'un Bang"
},
"Placca Di Ferro": {
"name": "Plaque de Fer",
"desc": "Utilisez cette carte pour annuler l'effet d'un Bang"
},
"Sombrero": {
"name": "Sombrero",
"desc": "Utilisez cette carte pour annuler l'effet d'un Bang"
},
"Pugnale": {
"name": "Couteau",
"desc": "Tirez sur un joueur à une distance de 1"
},
"Derringer": {
"name": "Derringer",
"desc": "Tirez sur un joueur à une distance de 1 et ensuite piochez une carte."
},
"Borraccia": {
"name": "Gourde",
"desc": "Regagnez 1 PV"
},
"Can Can": {
"name": "Can Can",
"desc": "Choisissez et défaussez une carte d'un autre joueur."
},
"Conestoga": {
"name": "Conestoga",
"desc": "Volez une carte à un autre joueur à n'importe quelle distance"
},
"Fucile Da Caccia": {
"name": "Fusil de Buffle",
"desc": "Tirez sur un joueur à n'importe quelle distance"
},
"Pony Express": {
"name": "Pony Express",
"desc": "Piochez 3 cartes du paquet"
},
"Pepperbox": {
"name": "Pepperbox",
"desc": "Tirez sur un joueur en vue. Si vous n'avez pas d'armes, votre vue est de 1"
},
"Howitzer": {
"name": "Howitzer",
"desc": "Tirez sur tous les autres joueurs"
},
"Bart Cassidy": {
"name": "Bart Cassidy",
"desc": "Chaque fois qu'il est blessé, il pioche une carte."
},
"Black Jack": {
"name": "Black Jack",
"desc": "Au début de son tour, lorsqu'il doit piocher, il montre à tout le monde la deuxième carte, si c'est un Cœur ou un Carreau, il pioche une troisième carte sans la montrer."
},
"Calamity Janet": {
"name": "Calamity Janet",
"desc": "Elle peut utiliser les cartes Raté ! comme Bang ! et vice versa."
},
"El Gringo": {
"name": "El Gringo",
"desc": "Chaque fois qu'il est blessé, il vole une carte de la main du joueur attaquant."
},
"Jesse Jones": {
"name": "Jesse Jones",
"desc": "Lorsqu'il doit piocher ses cartes, il peut piocher la première carte de la main d'un autre joueur. (cliquez sur les cartes des joueurs ennemis si vous voulez utiliser la capacité)"
},
"Jourdonnais": {
"name": "Jourdonnais",
"desc": "Il joue comme s'il avait un Baril toujours actif, s'il équipe un autre Baril, il peut retourner 2 cartes."
},
"Kit Carlson": {
"name": "Kit Carlson",
"desc": "Lorsqu'il doit piocher, il regarde 3 cartes et en choisit 2, mettant l'autre carte sur le dessus du paquet."
},
"Lucky Duke": {
"name": "Lucky Duke",
"desc": "Chaque fois qu'il doit retourner une carte, il peut retourner 2 fois."
},
"Paul Regret": {
"name": "Paul Regret",
"desc": "Les autres joueurs le voient à une distance de +1."
},
"Pedro Ramirez": {
"name": "Pedro Ramirez",
"desc": "Lorsqu'il doit piocher, il peut prendre la première carte de la pile de défausse. (cliquez sur les cartes défaussées pour utiliser la capacité)"
},
"Rose Doolan": {
"name": "Rose Doolan",
"desc": "Elle voit les autres joueurs à une distance de -1."
},
"Sid Ketchum": {
"name": "Sid Ketchum",
"desc": "Il peut défausser 2 cartes pour regagner 1 PV."
},
"Slab The Killer": {
"name": "Slab The Killer",
"desc": "Pour esquiver ses cartes Bang !, les autres joueurs ont besoin de 2 cartes Raté !"
},
"Suzy Lafayette": {
"name": "Suzy Lafayette",
"desc": "Chaque fois qu'elle a une main vide, elle pioche une carte."
},
"Vulture Sam": {
"name": "Vulture Sam",
"desc": "Lorsqu'un joueur meurt, il obtient toutes les cartes dans la main et les équipements du mort."
},
"Willy The Kid": {
"name": "Willy The Kid",
"desc": "Il n'a pas de limite au nombre de Bang qu'il peut utiliser."
},
"Pixie Pete": {
"name": "Pixie Pete",
"desc": "Il pioche 3 cartes au lieu de 2."
},
"Tequila Joe": {
"name": "Tequila Joe",
"desc": "Lorsqu'il joue une Bière, il regagne 2 PV."
},
"Greg Digger": {
"name": "Greg Digger",
"desc": "Chaque fois qu'un joueur meurt, il regagne jusqu'à 2 vies."
},
"Herb Hunter": {
"name": "Herb Hunter",
"desc": "Chaque fois qu'un joueur meurt, il pioche 2 cartes."
},
"Elena Fuente": {
"name": "Elena Fuente",
"desc": "Elle peut utiliser n'importe quelle carte de sa main comme Raté."
},
"Bill Noface": {
"name": "Bill Noface",
"desc": "Pioche 1 carte + 1 carte pour chaque blessure qu'il a."
},
"Molly Stark": {
"name": "Molly Stark",
"desc": "Lorsqu'elle utilise une carte de sa main en dehors de son tour, elle pioche une carte."
},
"Apache Kid": {
"name": "Apache Kid",
"desc": "Les cartes de carreaux ♦️ jouées contre lui n'ont aucun effet (ne fonctionne pas en duel)."
},
"Sean Mallory": {
"name": "Sean Mallory",
"desc": "Il peut garder jusqu'à 10 cartes dans sa main lorsqu'il termine le tour."
},
"Belle Star": {
"name": "Belle Star",
"desc": "Pendant son tour, les cartes vertes et bleues des autres joueurs ne fonctionnent pas."
},
"Vera Custer": {
"name": "Vera Custer",
"desc": "Avant de piocher, elle peut choisir la capacité spéciale d'un autre joueur vivant. Cette capacité est utilisée jusqu'au prochain tour."
},
"Chuck Wengam": {
"name": "Chuck Wengam",
"desc": "Lors de son tour, il peut décider de perdre 1 PV pour piocher 2 cartes du paquet."
},
"Pat Brennan": {
"name": "Pat Brennan",
"desc": "Au lieu de piocher, il peut voler une carte de l'équipement d'un autre joueur. (cliquez sur le joueur ennemi si vous voulez utiliser la capacité)"
},
"José Delgado": {
"name": "José Delgado",
"desc": "Lors de son tour, il peut défausser une carte bleue pour piocher 2 cartes, jusqu'à deux fois par tour."
},
"Doc Holyday": {
"name": "Doc Holyday",
"desc": "Il peut défausser 2 cartes pour jouer un Bang."
},
"Fuorilegge": {
"name": "Hors-la-loi"
},
"Rinnegato": {
"name": "Renégat"
},
"Sceriffo": {
"name": "Shérif"
},
"Vice": {
"name": "Adjoint"
},
"Miniera Abbandonata": {
"name": "Mine Abandonnée",
"desc": "Les joueurs piochent dans la pile de défausse pendant leur phase 1 et défaussent sur le dessus du paquet pendant la phase 3 (si la pile de défausse est épuisée, ils doivent piocher et défausser sur le dessus du paquet)"
},
"Il Giudice": {
"name": "Le Juge",
"desc": "Vous ne pouvez pas équiper des cartes sur vous-même ou sur d'autres joueurs"
},
"Agguato": {
"name": "Embuscade",
"desc": "La distance de base entre deux joueurs est de 1"
},
"Rimbalzo": {
"name": "Rebond",
"desc": "Le joueur peut jouer Bang contre les cartes équipées par les autres joueurs, s'ils ne jouent pas Raté, elles sont défaussées (cliquez sur la carte d'événement)"
},
"Cecchino": {
"name": "Sniper",
"desc": "Pendant leur tour, les joueurs peuvent défausser 2 Bang! pour tirer un Bang! qui nécessite 2 Raté (cliquez sur la carte)"
},
"Lazo": {
"name": "Lasso",
"desc": "Les cartes dans la fente d'équipement ne fonctionnent pas"
},
"Ranch": {
"name": "Ranch",
"desc": "Après avoir pioché, le joueur peut défausser autant de cartes qu'il veut de sa main et en piocher autant du paquet"
},
"Dead Man": {
"name": "Mort",
"desc": "Le premier joueur qui est mort revient à la vie avec 2 PV et 2 cartes"
},
"Liquore Forte": {
"name": "Liqueur Forte",
"desc": "Les joueurs peuvent sauter la pioche pour regagner 1 PV (cliquez sur la carte d'événement pour utiliser)"
},
"Vendetta": {
"name": "Vengeance",
"desc": "Lorsqu'il termine son tour, le joueur retourne une carte du paquet, si c'est un ❤️, il joue un autre tour (mais il ne retourne pas une autre carte)"
},
"Roulette Russa": {
"name": "Roulette Russe",
"desc": "En commençant par le shérif, chaque joueur défausse un Raté, le premier qui ne le fait pas perd 2 PV"
},
"Legge Del West": {
"name": "La Loi de l'Ouest",
"desc": "Chaque joueur montre la deuxième carte qu'il pioche et doit l'utiliser dans ce tour (si c'est possible)"
},
"Peyote": {
"name": "Peyote",
"desc": "Au lieu de piocher, le joueur essaie de deviner la couleur de la carte, s'il a raison, il ajoute la carte à sa main et continue d'essayer de deviner la carte suivante"
},
"Fratelli Di Sangue": {
"name": "Frères de Sang",
"desc": "Au début de leur tour, les joueurs peuvent perdre 1 PV (sauf le dernier) pour le donner à un autre joueur"
},
"I Dalton": {
"name": "Les Dalton",
"desc": "Les joueurs ayant des cartes bleues équipées, en défaussent une de leur choix"
},
"Sermone": {
"name": "Le Sermon",
"desc": "Les joueurs ne peuvent pas jouer Bang! pendant leur tour"
},
"Città Fantasma": {
"name": "Ville Fantôme",
"desc": "Tous les joueurs morts reviennent à la vie à leur tour, ils ne peuvent pas mourir et piochent 3 cartes au lieu de 2. Lorsqu'ils terminent leur tour, ils meurent."
},
"Il Reverendo": {
"name": "Le Révérend",
"desc": "Les bières ne peuvent pas être jouées"
},
"Sbornia": {
"name": "Gueule de Bois",
"desc": "Les personnages perdent leurs capacités spéciales"
},
"Il Dottore": {
"name": "Le Docteur",
"desc": "Le joueur avec le moins de PV récupère 1 PV"
},
"Corsa All Oro": {
"name": "Ruée vers l'Or",
"desc": "Les tours sont joués dans le sens inverse des aiguilles d'une montre"
},
"Maledizione": {
"name": "Malédiction",
"desc": "Toutes les cartes sont des ♠️"
},
"Sparatoria": {
"name": "Fusillade",
"desc": "La limite de Bang! du tour est de 2"
},
"Benedizione": {
"name": "Bénédiction",
"desc": "Toutes les cartes sont des ❤️"
},
"Il Treno": {
"name": "Arrivée du Train",
"desc": "Les joueurs piochent 1 carte supplémentaire"
},
"Sete": {
"name": "Soif",
"desc": "Les joueurs ne piochent qu'une seule carte au début de leur tour"
},
"Nuova Identita": {
"name": "Nouvelle Identité",
"desc": "Au début de leur tour, chaque joueur peut choisir de changer de personnage avec celui montré au début du jeu. S'il le fait, il repart avec 2 PV"
},
"Manette": {
"name": "Menottes",
"desc": "Après avoir pioché en phase 1, le joueur déclare une couleur. Il ne pourra utiliser que des cartes de cette couleur pour ce tour"
},
"Mezzogiorno di Fuoco": {
"name": "Midi de Feu",
"desc": "Chaque joueur perd 1 PV lorsqu'il commence son tour"
},
"Per Un Pugno Di Carte": {
"name": "Pour une Poignée de Cartes",
"desc": "Au début de son tour, le joueur est la cible de Bang aussi nombreux que le nombre de cartes qu'il a en main"
},
"Pepita": {
"name": "Pépite d'Or"
},
"Bicchierino": {
"name": "Verre",
"desc": "Vous pouvez choisir un joueur qui regagne 1 PV (même vous)"
},
"Bottiglia": {
"name": "Bouteille",
"desc": "Peut être jouée comme Panique !, Bière ou Bang !"
},
"Complice": {
"name": "Complice",
"desc": "Peut être joué comme Magasin Général, Duel ou Cat Balou."
},
"Corsa All Oro_gr": {
"name": "Ruée vers l'Or",
"desc": "Vous terminez votre tour, regagnez tous vos PV et commencez un nouveau tour."
},
"Rum": {
"name": "Rhum",
"desc": "Retournez 4 cartes, pour chaque couleur différente, vous gagnez 1 PV."
},
"Union Pacific": {
"name": "Union Pacific",
"desc": "Piochez 4 cartes du paquet."
},
"Calumet": {
"name": "Calumet",
"desc": "Les cartes de carreaux jouées par les autres joueurs n'ont aucun effet sur vous."
},
"Cinturone": {
"name": "Ceinture",
"desc": "Vous pouvez garder jusqu'à 8 cartes lorsque vous terminez votre tour."
},
"Ferro di Cavallo": {
"name": "Fer à Cheval",
"desc": "Chaque fois que vous devez retourner une carte, vous retournez deux fois !"
},
"Piccone": {
"name": "Pioche",
"desc": "Vous obtenez 1 carte supplémentaire lorsque vous piochez au début du tour."
},
"Ricercato": {
"name": "Recherché",
"desc": "Jouez-le sur un autre joueur, qui tue la cible obtient 2 cartes supplémentaires et 1 pépite d'or."
},
"Setaccio": {
"name": "Pan d'Or",
"desc": "Payez 1 pépite d'or pour piocher 1 carte du paquet, jusqu'à deux fois par tour. (Cliquez sur la carte équipée pour utiliser)"
},
"Stivali": {
"name": "Bottes",
"desc": "Chaque fois que vous perdez 1 PV, vous piochez 1 carte du paquet."
},
"Talismano": {
"name": "Porte-Bonheur",
"desc": "Chaque fois que vous perdez 1 PV, vous obtenez 1 pépite d'or."
},
"Zaino": {
"name": "Sac à Dos",
"desc": "Payez 2 pépites d'or pour soigner 1 PV. (Cliquez sur la carte équipée pour utiliser)"
},
"Don Bell": {
"name": "Don Bell",
"desc": "Lorsqu'il termine son tour, il retourne une carte, si elle retourne Cœur ❤️ ou Carreau ♦️, il joue à nouveau."
},
"Dutch Will": {
"name": "Dutch Will",
"desc": "Il pioche 2 cartes, en défausse 1 et prend 1 pépite d'or."
},
"Jacky Murieta": {
"name": "Jacky Murieta",
"desc": "Pendant son tour, il peut payer 2 pépites d'or pour avoir la capacité de tirer un autre Bang !"
},
"Josh McCloud": {
"name": "Josh McCloud",
"desc": "Il peut payer 2 pépites d'or pour obtenir la première carte du paquet de ruée vers l'or."
},
"Madam Yto": {
"name": "Madam Yto",
"desc": "Elle pioche 1 carte du paquet chaque fois qu'une bière est jouée."
},
"Pretty Luzena": {
"name": "Pretty Luzena",
"desc": "Une fois par tour, elle peut bénéficier d'une réduction de 1 sur la boutique des cartes ruée vers l'or."
},
"Raddie Snake": {
"name": "Raddie Snake",
"desc": "Il peut jeter 1 pépite d'or pour piocher 1 carte du paquet pendant son tour (2 fois max par tour)."
},
"Simeon Picos": {
"name": "Simeon Picos",
"desc": "Il obtient 1 pépite d'or chaque fois qu'il perd 1 PV."
},
"Fantasma": {
"name": "Fantôme",
"desc": "Jouez sur un joueur éliminé : Ce joueur revient dans le jeu, mais ne peut ni gagner ni perdre des points de vie."
},
"Lemat": {
"name": "Lemat",
"desc": "Pendant votre tour, vous pouvez utiliser n'importe quelle carte comme Bang ! (Cliquez sur la carte une fois équipée)."
},
"SerpenteASonagli": {
"name": "Serpent à Sonnettes",
"desc": "Jouez sur n'importe quel joueur. Au début de son tour. si ce joueur pioche sur Piques, il perd 1 point de vie."
},
"Shotgun": {
"name": "Fusil",
"desc": "Chaque fois que vous blessez un joueur, il doit défausser une carte de sa main."
},
"Taglia": {
"name": "Prime",
"desc": "Jouez sur n'importe qui. Si ce joueur est touché par Bang !, la personne qui a tiré obtient une carte du paquet."
},
"Mira": {
"name": "Viser",
"desc": "Jouez cette carte avec une carte Bang!. Si la cible est touchée, elle perd 2 points de vie."
},
"RitornoDiFiamma": {
"name": "Retour de Flamme",
"desc": "Compte comme une carte Raté!. Le joueur qui a tiré est la cible d'un Bang!."
},
"Bandidos": {
"name": "Bandidos",
"desc": "Chaque joueur choisit de défausser 2 cartes de sa main (ou 1 s'il n'en a qu'une) ou de perdre 1 point de vie."
},
"Fuga": {
"name": "Fuite",
"desc": "Peut être jouée hors tour. Évite l'effet d'une carte brune (pas Bang!) dont vous êtes la cible."
},
"Sventagliata": {
"name": "Ventilateur",
"desc": "Compte comme le seul Bang! du tour. Un joueur de votre choix à une distance de 1 de la cible (s'il y en a un, à l'exclusion de vous-même) est également une cible d'un Bang."
},
"UltimoGiro": {
"name": "Dernière Tournée",
"desc": "Récupère 1 point de vie"
},
"Poker": {
"name": "Poker",
"desc": "Tous les autres joueurs défaussent une carte de leur main, en même temps. S'il n'y a pas d'As, piochez jusqu'à 2 de ces cartes."
},
"Salvo": {
"name": "Sauvé !",
"desc": "Peut être jouée hors tour. Empêche un autre joueur de perdre 1 point de vie. S'il survit, il pioche 2 cartes de sa main ou du paquet (votre choix)."
},
"Tomahawk": {
"name": "Tomahawk",
"desc": "Attaque un joueur jusqu'à une distance de 2."
},
"Tornado": {
"name": "Tornade",
"desc": "Tout le monde défausse une carte de leur main (si possible), puis pioche 2 cartes du paquet."
},
"Black Flower": {
"name": "Fleur Noire",
"desc": "Une fois par tour, vous pouvez utiliser une carte de Pique pour tirer un Bang ! supplémentaire"
},
"Colorado Bill": {
"name": "Colorado Bill",
"desc": "Chaque fois que vous jouez une carte Bang!, si vous piochez un Pique, le tir ne peut pas être évité."
},
"Der Spot Burst Ringer": {
"name": "Der Spot Burst Ringer",
"desc": "Une fois par tour, vous pouvez utiliser une carte Bang! comme une Gatling."
},
"Evelyn Shebang": {
"name": "Evelyn Shebang",
"desc": "Vous pouvez choisir de ne pas piocher de cartes pendant votre phase de pioche. Pour chaque carte non piochée, vous tirez un Bang! sur une cible atteignable, sur une cible différente."
},
"Henry Block": {
"name": "Henry Block",
"desc": "Quiconque pioche ou défausse une de vos cartes en jeu ou en main est la cible d'un Bang!."
},
"Lemonade Jim": {
"name": "Lemonade Jim",
"desc": "Chaque fois qu'un autre joueur joue une Bière, vous pouvez défausser une carte de votre main pour regagner également 1 point de vie."
},
"Mick Defender": {
"name": "Mick Defender",
"desc": "Si vous êtes la cible d'une carte brune (pas Bang!), vous pouvez utiliser une carte Raté! pour éviter un effet."
},
"Tuco Franziskaner": {
"name": "Tuco Franziskaner",
"desc": "Si vous n'avez pas de cartes bleues équipées, vous piochez 2 cartes supplémentaires."
},
"Big Spencer": {
"name": "Big Spencer",
"desc": "Commence avec 5 cartes. Ne peut pas jouer Raté!"
},
"Flint Westwood": {
"name": "Flint Westwood",
"desc": "Peut échanger une carte de sa main avec 2 cartes aléatoires de la main d'un autre joueur pendant son tour."
},
"Gary Looter": {
"name": "Gary Looter",
"desc": "Pioche toutes les cartes excédentaires défaussées par les autres joueurs à la fin de chaque tour."
},
"Greygory Deckard": {
"name": "Greygory Deckard",
"desc": "Au début de son tour, peut piocher 2 personnages aléatoires et gagne toutes leurs capacités."
},
"John Pain": {
"name": "John Pain",
"desc": "S'il a moins de 6 cartes en main, lorsqu'un joueur « pioche! », John ajoute la carte piochée à sa main."
},
"Lee Van Kliff": {
"name": "Lee Van Kliff",
"desc": "Pendant son tour, peut défausser une carte Bang! pour répéter l'effet d'une carte à bordure brune qu'il vient de jouer."
},
"Teren Kill": {
"name": "Teren Kill",
"desc": "Chaque fois qu'il serait éliminé, « piochez! » : si ce n'est pas une carte de Pique, Teren reste à 1 point de vie et pioche 1 carte."
},
"Youl Grinner": {
"name": "Youl Grinner",
"desc": "Avant de piocher, les joueurs ayant plus de cartes en main que Youl doivent lui donner une carte de leur choix."
},
"Camposanto": {
"name": "Cimetière",
"desc": "Au début de leur tour, chaque joueur éliminé revient dans le jeu avec 1 point de vie. Piochez une carte de rôle au hasard parmi les joueurs éliminés."
},
"Darling Valentine": {
"name": "Darling Valentine",
"desc": "Au début de leur tour, chaque joueur défausse sa main et pioche le même nombre de cartes du paquet."
},
"Dorothy Rage": {
"name": "Dorothy Rage",
"desc": "Pendant leur tour, chaque joueur peut forcer un autre joueur à jouer une carte."
},
"Helena Zontero": {
"name": "Helena Zontero",
"desc": "Quand Helena entre dans le jeu, « pioche! » : si un Cœur ou un Carreau est pioché, mélangez les cartes de rôle actives sauf le Shérif, et redistribuez-les au hasard."
},
"Lady Rosa del Texas": {
"name": "Lady Rose of Texas",
"desc": "Pendant leur tour, chaque joueur peut échanger sa place avec le joueur à sa droite, qui passe son prochain tour. (Cliquez sur la carte)"
},
"Miss Susanna": {
"name": "Miss Susanna",
"desc": "Pendant leur tour, chaque joueur doit jouer au moins 3 cartes. S'ils ne le font pas, ils perdent 1 point de vie."
},
"Regolamento di Conti": {
"name": "Règlement de Comptes",
"desc": "Toutes les cartes peuvent être jouées comme si elles étaient Bang!. Les cartes Bang! peuvent être jouées comme si elles étaient Raté! (Cliquez sur la carte)"
},
"Sacagaway": {
"name": "Sacagaway",
"desc": "Tous les joueurs jouent avec leurs cartes face visible (sauf leur carte de rôle!)."
},
"Wild West Show": {
"name": "Wild West Show",
"desc": "Le but de chaque joueur devient : « Soyez le dernier debout ! »"
}
},
"help": {
"character": "Personnages",
"characters_special": "Chaque personnage a des capacités spéciales et un nombre de vies qui les rendent uniques. \nLes vies sont le nombre de points de vie que vous pouvez perdre avant de mourir et indiquent également le nombre maximum de cartes que vous pouvez garder en main.",
"deathnobeer": "Lorsque vous perdez votre dernier point de vie et que vous n'avez pas de bière 🍺️ en main, vous mourrez. \nVos cartes sont défaussées et votre rôle est révélé à tout le monde.",
"discard": "Défausser",
"distance": "Distance",
"distancecalc": "La distance est automatiquement calculée par le jeu et correspond à la distance minimale entre les joueurs à gauche et à droite.",
"drawinstructions": "Pour piocher des cartes, vous devez cliquer sur le paquet lorsque vous voyez cette animation.",
"drawthecards": "Piochez les cartes",
"endgame": "Fin du jeu",
"endgameconditions": "Le jeu se termine lorsque l'une des conditions suivantes est remplie :",
"endgamesheriffwin": "Tous les hors-la-loi 🐺️ et les renégats 🦅️ sont morts. \nDans ce cas, le shérif ⭐️ et les adjoints 🎖️ gagnent.",
"endgameshriffdeath": "Le shérif ⭐️ meurt. \nSi le renégat 🦅️ est le dernier joueur en vie, il gagne, sinon les hors-la-loi gagnent.",
"endingturn": "Lorsque vous avez fini de jouer vos cartes, c'est-à-dire lorsque vous ne voulez plus ou ne pouvez plus jouer de cartes, vous devez défausser les cartes qui dépassent votre nombre actuel de vies.\n\nEnsuite, vous passez le tour au joueur suivant en cliquant sur terminer le tour.",
"equipment": "ÉQUIPEMENT",
"justoneweapon": "Vous ne pouvez avoir qu'une seule arme équipée.",
"maxtwocardsequip": "Vous ne pouvez pas avoir 2 cartes avec le même nom équipées.",
"outlawreward": "Quiconque tue un hors-la-loi 🐺️ pioche 3 cartes du paquet (les autres hors-la-loi aussi 🐺️).",
"playerdeath": "La mort d'un joueur",
"playingcards": "Jouer les cartes",
"playingdmg": "Vous pouvez jouer vos cartes pour vous-même ou pour nuire à d'autres joueurs en essayant de les éliminer.",
"playingduringturn": "Vous ne pouvez jouer les cartes que pendant votre tour. Pour jouer des cartes, cliquez sur les cartes de votre main.\nÀ l'exception des cartes utilisées en réponse, comme Raté 😅️.",
"playingifyouwant": "Vous n'êtes pas obligé de jouer des cartes.",
"playlimit": "Il n'y a que 3 limitations :",
"playonlyonebang": "Vous ne pouvez jouer qu'un seul Bang! \npar tour (se réfère uniquement aux cartes nommées Bang!)",
"rewardspen": "Pénalités et récompenses",
"roles": "Rôles",
"sheriffkillsvice": "Si le shérif ⭐️ tue un adjoint, il perd toutes les cartes de sa main et en jeu devant lui.",
"thecards": "Cartes",
"title": "Comment jouer",
"turndiscard": "Défaussez toutes les cartes excédentaires",
"turndraw": "Piochez 2 cartes",
"turnplay": "Jouez autant de cartes que vous le souhaitez",
"turns": "Tours",
"turnstart": "Cela commence toujours par le Shérif ⭐️, et le jeu continue dans le sens des aiguilles d'une montre, les tours sont divisés en 3 phases.",
"weapon": "ARME",
"renegade": "Renégat",
"vice": "Adjoint",
"outlaw": "Hors-la-loi",
"sheriff": "Shérif",
"allcharacters": "Tous les personnages",
"gotoallcharacters": "Aller à tous les personnages",
"gotocards": "Aller aux cartes",
"gotohighnoon": "Aller à Midi",
"gotofoc": "Aller à Une Poignée de Cartes",
"gotogoldrush": "Aller à Ruée vers l'Or",
"highnooncards": "Midi - Cartes Événements",
"foccards": "Une Poignée de Cartes - Cartes Événements",
"goldrushcards": "Cartes Ruée vers l'Or",
"valleyofshadowscards": "Cartes Vallée des Ombres"
},
"theme": {
"sepia": "Sépia",
"light": "Clair",
"dark": "Sombre",
"grayscale": "Gris",
"black": "Noir"
}
}

View File

@ -1,9 +1,19 @@
import it from './it.json'
import en from './en.json'
import cs from './cs.json'
import fr from './fr.json'
import es from './es.json'
import ru from './ru.json'
export const defaultLocale = 'it'
export const fallbackLocale = 'en'
export const languages = {
it: it,
en: en,
it: it,
en: en,
cs: cs,
fr: fr,
es: es,
ru: ru,
}

View File

@ -1,11 +1,25 @@
{
"trademark": "Bang! è un marchio registrato DVGiochi",
"tip_1": "Con gli amici è meglio!",
"tip_2": "Il simbolo 🤖️ vuol dire che il giocatore è un bot!",
"tip_3": "Puoi cliccare sulle carte dei personaggi o equipaggiamento degli altri per vedere cosa fanno!",
"tip_4": "Dodge City, High Noon, Fistful Of Cards inclusi!",
"tip_5": "Se trovi un bug comunicacelo su discord!",
"tip_6": "Adesso con un server discord!",
"tip_7": "Se vuoi aiutarci a tradurre il gioco nella tua lingua scrivicelo su discord!",
"tip_8": "Se ti disconnetti durante una partita verrai sostituito da un bot (durante la tua assenza)!",
"tip_9": "Se sei da cellulare tieni premuto su una carta per vedere la descrizione!",
"tip_10": "Se in dubbio spara a tutti gli altri giocatori!",
"online_players": "Giocatori online: ",
"shuffle_players": "Riordina Giocatori",
"choose_username": "Scegli un username:",
"report_bug": "Scrivi in cosa consiste il bug",
"report": "Segnala un bug",
"available_lobbies": "Stanze disponibili:",
"spectate_lobbies": "Osserva le partite in corso:",
"no_lobby_available": "Nessuna stanza disponibile",
"create_lobby": "Crea una stanza:",
"characters_to_distribute": "Personaggi da distribuire: ",
"lobby_name": "Nome:",
"leave_room": "Esci dalla stanza",
"warning": "Attenzione!",
@ -13,11 +27,13 @@
"end_turn": "Termina turno!",
"start_game": "Avvia!",
"expansions": "Espansioni",
"click_to_toggle": "Clicca per attivare/disattivare",
"details": "Dettagli",
"ok": "OK",
"you": "TU",
"owner": "GESTORE",
"cancel": "ANNULLA",
"send": "INVIA",
"password": "Password: ",
"room_password_prompt": "Password Stanza: ",
"private_room": "Stanza Privata",
@ -36,22 +52,41 @@
"choose_response": "Scegli come rispondere ",
"choose_response_to": "a ",
"choose_response_needed": "NE OCCORRONO ",
"choose_manette": "Scegli un seme, potrai giocare solo carte di quel seme questo turno.",
"hand": "MANO",
"card_against": "Contro chi vuoi giocare la carta",
"choose_card_to_get": "Scegli che carta pescare",
"choose_sid_scrap": "Scarta 2 carte per non morire",
"choose_guess": "Indovina il colore del seme",
"choose_ranch": "Scegli le carte da sostituire",
"choose_dalton": "Scegli che equipaggiamento scartare",
"choose_fratelli_di_sangue": "Scegli a chi donare una delle tue vite",
"choose_fantasma": "Scegli chi riportare in vita",
"choose_sventagliata": "Scegli chi altro colpire con sventagliata",
"choose_tornado": "Scegli una carta da scartare per il tornado",
"choose_bandidos": "Scegli tra scartare 2 carte o perdere una vita (1 carta se ne hai solo 1)",
"choose_poker": "Tutti scartano 1 carta (se non c'è un Asso, il giocatore che ha giocato poker sceglie 2 carte tra quelle appena scartate)",
"choose_from_poker;2": "Scegli quali carte pescare (max 2)",
"choose_from_poker;1": "Scegli quale carte pescare",
"choose_cecchino": "Scegli contro chi sparare",
"choose_rimbalzo_player": "Scegli contro chi scartare il bang",
"choose_rimbalzo_card": "Scegli contro che carta scartare il bang",
"choose_nuova_identita": "Scegli se rimanere con il tuo personaggio corrente o se cambiarlo e ripartire con 2 vite.",
"choose_bicchierino": "Scegli a chi far recuperare 1 punto vita",
"choose_bottiglia": "Scegli come giocare Bottiglia!",
"choose_complice": "Scegli come giocare Complice!",
"choose_ricercato": "Scegli il giocatore su cui vuoi giocare Ricercato",
"choose_birra_function": "Scegli tra ottenere 1 pepita scartando la birra oppure giocare la birra.",
"choose_play_as_bang": "Scegli che carta giocare come Bang!",
"choose_flint_special": "Scegli che carta scabiare.",
"emporio_others": "{0} sta scegliendo che carta prendere dall'emporio",
"you_died": "SEI MORTO",
"spectate": "SPETTATORE",
"you_win": "HAI VINTO",
"you_lose": "HAI PERSO",
"special_ability": "ABILITÀ SPECIALE",
"gold_rush_discard": "Fai scartare equipaggiamento gold rush (pagando pepite + 1)",
"gold_rush_discard_2": "Fai scartare equipaggiamento gold rush (pagando pepite + 1)",
"discard": "SCARTA",
"to_regain_1_hp": "PER RECUPERARE 1 VITA",
"play_your_turn": "GIOCA IL TUO TURNO",
@ -64,45 +99,62 @@
"submit": "Invia",
"copy": "Copia invito",
"no_players_in_range": "Non vedi nessun giocatore, equipaggia un arma o un mirino!",
"cantplaycard": "Non puoi giocare questa carta in questo modo!",
"chat": {
"spectators": " | Uno spettatore sta guardando la partita | {n} spettatori stanno guardando la partita",
"chat": "Chat",
"joined": "{0} è entrato nella stanza",
"died": "{0} è morto",
"died_role": "{0} era {1}!",
"won": "{0} ha vinto!",
"choose_character": "{0} ha come personaggio {1}, la sua abilità speciale è: {2}!",
"joined": "👋 ;{0}; è entrato nella stanza",
"died": "☠️ ;{0}; è morto",
"died_role": "☠️ ;{0}; era ;{1};!",
"won": "🏆 ;{0}; ha vinto! Il suo ruolo era ;{1};",
"choose_character": ";{0}; ha come personaggio ;{1};, la sua abilità speciale è: ;{2};!",
"starting": "La partita sta iniziando!",
"sheriff": "{0} è lo sceriffo!",
"did_choose_character": "{0} ha scelto il personaggio.",
"turn": "È il turno di {0}.",
"draw_from_scrap": "{0} ha pescato la prima carta dalla pila delle carte scartate.",
"draw_from_player": "{0} ha pescato la prima carta dalla mano di {1}.",
"flipped": "{0} ha estratto {1} {2}.",
"explode": "{0} ha fatto esplodere la dinamite.",
"beer_save": "{0} ha usato una birra per recuperare una vita.",
"play_card": "{0} ha giocato {1}.",
"play_card_against": "{0} ha giocato {1} contro {2}.",
"play_card_for": "{0} ha giocato {1} per {2}.",
"spilled_beer": "{0} ha rovesciato una {1}.",
"diligenza": "{0} ha giocato {1} e ha pescato 2 carte.",
"wellsfargo": "{0} ha giocato {1} e ha pescato 3 carte.",
"saloon": "{0} ha giocato {1} e ha curato 1 punto vita a tutti.",
"special_bart_cassidy": "{0} ha ricevuto un risarcimento perchè è stato ferito.",
"special_el_gringo": "{0} rubato una carta a {1} mentre veniva colpito.",
"special_calamity": "{0} ha giocato {1} come un Bang! contro {2}.",
"allroles3": "Nella partita ci sono: {1} {0}, {3} {2} e {5} {4}.",
"allroles4": "Nella partita ci sono: {1} {0}, {3} {2}, {5} {4} e {7} {6}.",
"guess": "{0} pensa sia {1}.",
"guess_right": "{0} ha indovinato.",
"guess_wrong": "{0} ha sbagliato.",
"fratelli_sangue": "{0} ha donato una delle sue vite a {1}.",
"doctor_heal": "{0} è stato curato dal dottore.",
"respond": "{0} ha risposto con {1}.",
"change_username": "{0} ha cambiato nome in {1}.",
"lobby_reset": "Si ritorna alla stanza in {0} secondi...",
"prison_free": "{0} è uscito di prigione",
"prison_turn": "{0} rimane in prigione questo turno"
"sheriff": "⭐ ;{0}; è lo sceriffo!",
"did_choose_character": ";{0}; ha scelto il personaggio.",
"turn": "⏩ È il turno di ;{0};.",
"draw_from_scrap": ";{0}; ha pescato la prima carta dalla pila delle carte scartate.",
"draw_from_player": ";{0}; ha pescato la prima carta dalla mano di ;{1};.",
"flipped": ";{0}; ha estratto ;{1}; ;{2};.",
"scrapped": ";{0}; ha scartato ;{1}; ;{2};.",
"explode": "💥 ;{0}; ha fatto esplodere la dinamite.",
"beer_save": ";{0}; ha usato una birra per recuperare una vita.",
"get_nugget": ";{0}; ha ottenuto una pepita d'oro usando una Birra.",
"play_card": ";{0}; ha giocato ;{1};.",
"play_card_green": ";{0}; ha messo in gioco ;{1};.",
"play_card_with": ";{0}; ha giocato ;{1};, scartando ;{2};.",
"purchase_card": ";{0}; ha comprato ;{1};.",
"play_card_against": ";{0}; ha giocato ;{1}; contro ;{2};.",
"play_card_against_with": ";{0}; ha giocato ;{1}; contro ;{2};, scartando ;{3};.",
"play_card_for": ";{0}; ha giocato ;{1}; per ;{2};.",
"spilled_beer": ";{0}; ha rovesciato una ;{1};.",
"diligenza": ";{0}; ha giocato ;{1}; e ha pescato 2 carte.",
"wellsfargo": ";{0}; ha giocato ;{1}; e ha pescato 3 carte.",
"saloon": "🍻 ;{0}; ha giocato ;{1}; e ha curato 1 punto vita a tutti.",
"special_bart_cassidy": ";{0}; ha ricevuto un risarcimento perchè è stato ferito.",
"special_el_gringo": ";{0}; rubato una carta a ;{1}; mentre veniva colpito.",
"special_calamity": ";{0}; ha giocato ;{1}; come un Bang! contro ;{2};.",
"allroles3": "Nella partita ci sono: ;{1}; ;{0};, ;{3}; ;{2}; e ;{5}; ;{4};.",
"allroles4": "Nella partita ci sono: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4}; e ;{7}; ;{6};.",
"guess": "🤔 ;{0}; pensa sia ;{1};.",
"guess_right": ";{0}; ha indovinato.",
"guess_wrong": ";{0}; ha sbagliato.",
"fratelli_sangue": ";{0}; ha donato una delle sue vite a ;{1};.",
"doctor_heal": ";{0}; è stato curato dal dottore.",
"respond": "↩️ ;{0}; ha risposto con ;{1};.",
"change_username": "✏️ ;{0}; ha cambiato nome in ;{1};.",
"lobby_reset": "Si ritorna alla stanza in ;{0}; secondi...",
"prison_free": "🆓 ;{0}; è uscito di prigione",
"prison_turn": "🔐 ;{0}; rimane in prigione questo turno",
"flip_event": "🎴 EVENTO: ;{0}; 🎴",
"choose_manette": ";{0}; si è impegnato ad usare solo carte di seme ;{1}; in questo turno.",
"UnionPacific": ";{0}; ha giocato Union Pacific e ha pescato 4 carte.",
"use_special": ";{0}; ha usato l'abilità speciale del suo personaggio (;{1};)",
"gold_rush_pay_discard": ";{0}; ha fatto scartare ;{2}; a ;{1};.",
"choose_emporio": ";{0}; ha scelto ;{1}; da Emporio.",
"shotgun_scrap": "Quando lo shotgun ha colpito ;{0}; gli ha tolto una carta (;{1};)",
"taglia_reward": "💰 ;{1}; ha ottenuto ricompensa dalla taglia su ;{0};",
"snake_bit": "🐍 ;{0}; è stato morso dal Serpente a Sonagli.",
"in_private_car": "🚋💁🏻 ;{0}; è in una carrozza privata e non è stato attaccato da ;{1};"
},
"foc": {
"leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile"
@ -312,7 +364,7 @@
},
"Jesse Jones": {
"name": "Jesse Jones",
"desc": "All'inizio del suo turno, quando deve pescare, può prendere la prima carta a caso dalla mano di un giocatore e la seconda dal mazzo. (clicca sul giocatore avversario se vuoi usare l'abilità)"
"desc": "All'inizio del suo turno, quando deve pescare, può prendere la prima carta a caso dalla mano di un giocatore e la seconda dal mazzo. (clicca sulle carte del giocatore avversario se vuoi usare l'abilità)"
},
"Jourdonnais": {
"name": "Jourdonnais",
@ -410,9 +462,9 @@
"name": "Pat Brennan",
"desc": "Invece di pescare può prendere una carta dall'equipaggiamento di un altro giocatore. (clicca sul giocatore avversario se vuoi usare l'abilità)"
},
"José Delgrado": {
"name": "José Delgrado",
"desc": "Può scartare una carta blu per pescare 2 carte."
"José Delgado": {
"name": "José Delgado",
"desc": "Nel suo turno può scartare una carta blu per pescare 2 carte, fino a due volte per turno."
},
"Doc Holyday": {
"name": "Doc Holyday",
@ -429,6 +481,505 @@
},
"Vice": {
"name": "Vice"
},
"Peyote": {
"name": "Peyote",
"desc": "Invece che pescare il giocatore prova a indovinare il colore del seme, se lo indovina aggiunge la carta alla mano e continua provando ad indovinare la carta successiva"
},
"Legge Del West": {
"name": "Legge Del West",
"desc": "I giocatori mostrano la seconda carta che pescano e sono obbligati a usarla in quel turno (se possibile)"
},
"Cecchino": {
"name": "Cecchino",
"desc": "Nel proprio turno i giocatori possono scartare 2 Bang assieme per sparare un bang che necessita 2 mancato (clicca la carta)"
},
"Ranch": {
"name": "Ranch",
"desc": "Dopo aver pescato il giocatore pu\u00f2 scartare quante carte vuole dalla mano e pescarne altrettante dal mazzo"
},
"Miniera Abbandonata": {
"name": "Miniera Abbandonata",
"desc": "I giocatori pescano dagli scarti nella loro fase 1 e scartano in cima al mazzo nella loro fase 3 (se gli scarti finiscono, \u00e8 necessario pescare e scartare in cima al mazzo)"
},
"Lazo": {
"name": "Lazo",
"desc": "Le carte equipaggiate non hanno effetto"
},
"Vendetta": {
"name": "Vendetta",
"desc": "Alla fine del proprio turno il giocatore estrae dal mazzo, se esce \u2665\ufe0f gioca un altro turno (ma non estrae di nuovo)"
},
"Rimbalzo": {
"name": "Rimbalzo",
"desc": "Il giocatore di turno pu\u00f2 giocare bang contro le carte equipaggiate dagli altri giocatori, se non giocano mancato vengono scartate (clicca la carta evento)"
},
"Agguato": {
"name": "Agguato",
"desc": "La distanza base tra 2 qualsiasi giocatori \u00e8 1"
},
"Fratelli Di Sangue": {
"name": "Fratelli Di Sangue",
"desc": "All'inizio del proprio turno, i giocatori possono perdere 1 vita (tranne l'ultimo) per darla a un altro giocatore"
},
"Dead Man": {
"name": "Dead Man",
"desc": "Al proprio turno il giocatore che \u00e8 morto per primo torna in vita con 2 vite e 2 carte"
},
"Roulette Russa": {
"name": "Roulette Russa",
"desc": "A partire dallo sceriffo, ogni giocatore scarta 1 mancato, il primo che non lo fa perde 2 vite"
},
"Liquore Forte": {
"name": "Liquore Forte",
"desc": "I giocatori possono evitare di pescare per recuperare 1 vita (clicca sulla carta evento per farlo)"
},
"Il Giudice": {
"name": "Il Giudice",
"desc": "Non si possono equipaggiare carte a se stessi o agli altri"
},
"Maledizione": {
"name": "Maledizione",
"desc": "Tutte le carte sono considerate di picche \u2660"
},
"Corsa All Oro": {
"name": "Corsa All\u0027Oro",
"desc": "Si gioca per un intero giro in senso antiorario, tuttavia gli effetti delle carte rimangono invariati"
},
"Il Reverendo": {
"name": "Il Reverendo",
"desc": "Non si possono giocare le carte Birra"
},
"Sete": {
"name": "Sete",
"desc": "I giocatori pescano 1 carta in meno nella loro fase 1"
},
"I Dalton": {
"name": "I Dalton",
"desc": "Chi ha carte blu in gioco ne scarta 1 a sua scelta"
},
"Citt\u00e0 Fantasma": {
"name": "Citt\u00e0 Fantasma",
"desc": "Tutti i giocatori morti tornano in vita al proprio turno, non possono morire e pescano 3 carte invece che 2. Quando terminano il turno tornano morti."
},
"Sermone": {
"name": "Sermone",
"desc": "I giocatori non possono giocare Bang! durante il loro turno"
},
"Il Treno": {
"name": "Il Treno",
"desc": "I giocatori pescano 1 carta extra nella loro fase 1"
},
"Benedizione": {
"name": "Benedizione",
"desc": "Tutte le carte sono considerate di cuori \u2665\ufe0f"
},
"Il Dottore": {
"name": "Il Dottore",
"desc": "Il/i giocatore/i con meno vite ne recupera/no una"
},
"Sparatoria": {
"name": "Sparatoria",
"desc": "Il limite di Bang! per turno \u00e8 2 invece che 1"
},
"Sbornia": {
"name": "Sbornia",
"desc": "I personaggi perdono le loro abilit\u00e0 speciali"
},
"Nuova Identita": {
"name": "Nuova Identit\u00e0",
"desc": "All'inizio del proprio turno, ogni giocatore potrà decidere se sostituire il suo personaggio attuale con quello era stato proposto ad inizio partita, se lo fa riparte con 2 punti vita"
},
"Manette": {
"name": "Manette",
"desc": "Dopo aver pescato in fase 1, il giocatore di turno dichiara un seme: potrà usare solamente carte di quel seme nel suo turno"
},
"Mezzogiorno di Fuoco": {
"name": "Mezzogiorno di Fuoco",
"desc": "Ogni giocatore perde 1 punto vita all'inizio del turno"
},
"Per Un Pugno Di Carte": {
"name": "Per Un Pugno Di Carte",
"desc": "All'inizio del proprio turno, il giocatore subisce tanti bang quante carte ha in mano"
},
"Pepita": {
"name": "Pepita D'oro"
},
"Bicchierino": {
"name": "Bicchierino",
"desc": "Un giocatore a scelta recupera una vita (anche se stessi)"
},
"Bottiglia": {
"name": "Bottiglia",
"desc": "Usa questa carta come Panico!, Birra o Bang!"
},
"Complice": {
"name": "Complice",
"desc": "Usa questa carta come Emporio, Duello o Cat Balou"
},
"Corsa All Oro_gr": {
"name": "Corsa All'Oro",
"desc": "Il tuo turno termina subito. Recuperi tutti i tuoi punti vita, poi gioca un altro turno"
},
"Rum": {
"name": "Rum",
"desc": "Estrai 4 carte dal mazzo, guadagni 1 vita per ogni seme diverso"
},
"Union Pacific": {
"name": "Union Pacific",
"desc": "Pesca 4 carte dal mazzo"
},
"Calumet": {
"name": "Calumet",
"desc": "Le carte di quadri giocate dagli altri giocatori non hanno effetto su di te"
},
"Cinturone": {
"name": "Cinturone",
"desc": "Alla fine del tuo turno puoi tenere in mano fino a 8 carte"
},
"Ferro di Cavallo": {
"name": "Ferro di Cavallo",
"desc": "Ogni volta che estrai scegli la migliore tra due carte"
},
"Piccone": {
"name": "Piccone",
"desc": "Pesca una carta in più nella tua fase 1"
},
"Ricercato": {
"name": "Ricercato",
"desc": "Scegli un giocatore qualsiasi, chi elimina quel giocatore pesca 2 carte in più e pesca una pepita"
},
"Setaccio": {
"name": "Setaccio",
"desc": "Fino a due volte in un turno puoi pagare una pepita per pescare una carta dal mazzo (Clicca sulla carta per usare l'abilità)"
},
"Stivali": {
"name": "Stivali",
"desc": "Ogni volta che perdi un punto vita peschi una carta dal mazzo"
},
"Talismano": {
"name": "Talismano",
"desc": "Ogni volta che perdi un punto vita prendi una pepita"
},
"Zaino": {
"name": "Zaino",
"desc": "Paga 2 pepite per recuperare un punto vita"
},
"Don Bell": {
"name": "Don Bell",
"desc": "Alla fine del suo turno estrae, se esce Cuori ❤️ o Quadri ♦️ gioca un altro turno"
},
"Dutch Will": {
"name": "Dutch Will",
"desc": "Pesca 2 carte, ne scarta 1 e pesca una pepita."
},
"Jacky Murieta": {
"name": "Jacky Murieta",
"desc": "Durante il suo turno può pagare 2 pepite per poter sparare un altro bang, può farlo più volte per turno"
},
"Josh McCloud": {
"name": "Josh McCloud",
"desc": "Può pescare la prima carta del mazzetto pagando solo due pepite"
},
"Madam Yto": {
"name": "Madam Yto",
"desc": "Ogni volta che viene giocata una Birra pesca 1 carta dal mazzo"
},
"Pretty Luzena": {
"name": "Pretty Luzena",
"desc": "Una volta per turno può pagare una carta del mazzetto a costo diminuito di 1"
},
"Raddie Snake": {
"name": "Raddie Snake",
"desc": "Durante il suo turno, può pagare una pepita per pescare 1 carta dal mazzo (fino a due volte per turno)"
},
"Simeon Picos": {
"name": "Simeon Picos",
"desc": "Ogni volta che viene ferito, prende una pepita"
},
"Fantasma": {
"name": "Fantasma",
"desc": "Gioca su un giocatore eliminato. Quel giocatore torna in gioco, ma non può guadagnare né perdere punti vita."
},
"Lemat": {
"name": "Lemat",
"desc": "Puoi usare ogni carta in mano come BANG! (Clicca la carta una volta equipaggiata)."
},
"SerpenteASonagli": {
"name": "Serpente a Sonagli",
"desc": "Gioca su chiunque. All'inizio del turno, quel giocatore estrae una carta, e se è Picche, perde 1 punto vita."
},
"Shotgun": {
"name": "Shotgun",
"desc": "Ogni volta che ferisci un giocatore, deve scartare una carta a dalla sua mano."
},
"Taglia": {
"name": "Taglia",
"desc": "Gioca su chiunque. Se quel giocatore è colpito da BANG!, chi ha sparato ottiene una carta dal mazzo."
},
"Mira": {
"name": "Mira",
"desc": "Gioca questa carta assieme a una carta BANG!. Se il bersaglio viene colpito, perde 2 punti vita."
},
"RitornoDiFiamma": {
"name": "Ritorno di Fiamma",
"desc": "Vale una carta Mancato! Il giocatore che ha sparato è bersaglio di un BANG!."
},
"Bandidos": {
"name": "Bandidos",
"desc": "Ogni giocatore sceglie se scartare 2 carte dalla mano (o 1 se ne ha solo 1) o perdere 1 punto vita."
},
"Fuga": {
"name": "Fuga",
"desc": "Può essere giocata fuori turno. Evita l'effetto di una carta marrone (non BANG!) di cui sei uno dei bersagli."
},
"Sventagliata": {
"name": "Sventagliata",
"desc": "Conta come l'unico BANG! del turno. Anche un giocatore a tua scelta a distanza 1 dal bersaglio (se ce, te escluso) è bersaglio di un BANG."
},
"UltimoGiro": {
"name": "Ultimo Giro",
"desc": "Recupera 1 vita"
},
"Poker": {
"name": "Poker",
"desc": "Tutti gli altri scartano una carta dalla mano, allo stesso tempo. Se non c'è alcun Asso, pesca fino a 2 di quelle carte."
},
"Salvo": {
"name": "Salvo!",
"desc": "Può essere giocata fuori turno. Previeni la perdita di 1 punto vita di un altro giocatore. Se sopravvive, pesca 2 carte dalla sua mano o dal mazzo (scegli)."
},
"Tomahawk": {
"name": "Tomahawk",
"desc": "Attacca un giocatore fino a distanza 2."
},
"Tornado": {
"name": "Tornado",
"desc": "Tutti scartano una carta dalla mano (se possibile), poi ottengono 2 carte dal mazzo."
},
"Black Flower": {
"name": "Black Flower",
"desc": "Una volta nel tuo turno, puoi usare una carta di fiori per sparare un BANG! extra."
},
"Colorado Bill": {
"name": "Colorado Bill",
"desc": "Ogni volta che giochi una carta BANG!, estrai, se è Picche, il colpo non può essere evitato."
},
"Der Spot Burst Ringer": {
"name": "Der Spot Burst Ringer",
"desc": "Una volta nel tuo turno, puoi usare una carta BANG! come Gatling."
},
"Evelyn Shebang": {
"name": "Evelyn Shebang",
"desc": "Puoi rinunciare a pescare carte nella tua fase di pesca. Per ogni carta non pescata, spari un BANG! a distanza raggiungibile, a un diverso bersaglio."
},
"Henry Block": {
"name": "Henry Block",
"desc": "hiunque peschi o scarti una tua cartain gioco o in mano è bersaglio di un BANG!."
},
"Lemonade Jim": {
"name": "Lemonade Jim",
"desc": "Ogni volta che un altro giocatore gioca una Birra, puoi scartare una carta dalla mano per riguadagnare anche tu 1 punto vita."
},
"Mick Defender": {
"name": "Mick Defender",
"desc": "Se sei bersaglio di una carta marrone (non BANG!), puoi usare una carta Mancato! evitarne 1 gli effetti."
},
"Tuco Franziskaner": {
"name": "Tuco Franziskaner",
"desc": "Durante la tua fase di pesca, se non hai carte blu in gioco, pesca 2 carte extra."
},
"Big Spencer": {
"name": "Big Spencer",
"desc": "Inizia con 5 carte. Non può giocare Mancato!"
},
"Flint Westwood": {
"name": "Flint Westwood",
"desc": "Nel suo turno può scambiare una carta dalla mano con 2 carte a caso dalla mano di un altro giocatore."
},
"Gary Looter": {
"name": "Gary Looter",
"desc": "Pesca tutte le carte in eccesso scartate dagli altri giocatori a fine turno."
},
"Greygory Deckard": {
"name": "Greygory Deckard",
"desc": "All'inizio del suo turno può pescare 2 personaggi a caso. Ha tutte le abilità dei personaggi pescati."
},
"John Pain": {
"name": "John Pain",
"desc": "Se ha meno di 6 carte in mano, quando un giocatore \"estrae!\" John aggiunge alla mano la carta appena estratta."
},
"Lee Van Kliff": {
"name": "Lee Van Kliff",
"desc": "Nel suo turno, può scartare un BANG! per ripetere l'effetto di una carta a bordo marrone che ha appena giocato."
},
"Teren Kill": {
"name": "Teren Kill",
"desc": "Ogni volta che sarebbe eliminato \"estrai!\": se non è Picche, Teren resta a 1 punto vita e pesca 1 carta."
},
"Youl Grinner": {
"name": "Youl Grinner",
"desc": "Prima di pescare, i giocatori con più carte in mano di lui devono dargli una carta a scelta."
},
"Camposanto": {
"name": "Camposanto",
"desc": "All'inizio del proprio turno, ogni giocatore eliminato torna in gioco con 1 punto vita. Pesca il ruolo a caso fra quelli dei giocatori eliminati."
},
"Darling Valentine": {
"name": "Darling Valentine",
"desc": "All'inizio del proprio turno, ogni giocatore scarta le carte in mano e ne pesca dal mazzo altrettante."
},
"Dorothy Rage": {
"name": "Dorothy Rage",
"desc": "Nel proprio turno, ogni giocatore può obbligarne un altro a giocare una carta."
},
"Helena Zontero": {
"name": "Helena Zontero",
"desc": "Quando Helena entra in gioco, \"estrai!\": se esce Cuori o Quadri, rimescola i ruoli attivi tranne lo Sceriffo, e ridistribuiscili a caso."
},
"Lady Rosa del Texas": {
"name": "Lady Rosa del Texas",
"desc": "Nel proprio turno, ogni giocatore può scambiarsi di posto con quello alla sua destra, il quale salta il prossimo turno. (Clicca la carta)"
},
"Miss Susanna": {
"name": "Miss Susanna",
"desc": "Nel proprio turno ogni giocatore deve giocare almeno 3 carte. Se non lo fa, perde 1 punto vita."
},
"Regolamento di Conti": {
"name": "Regolamento di Conti",
"desc": "Tutte le carte possono essere giocate come se fossero BANG!. Le carte BANG! come se fossero Mancato! (Clicca la carta)"
},
"Sacagaway": {
"name": "Sacagaway",
"desc": "Tutti i giocatori giocano a carte scoperte (tranne il ruolo!)."
},
"Wild West Show": {
"name": "Wild West Show",
"desc": "L'obiettivo di ogni giocatore diventa: \"Rimani l'ultimo in gioco!\""
},
"Boom Town": {
"name": "Boom Town",
"desc": "Scarta una Bang! per derubare il treno"
},
"Caticor": {
"name": "Caticor",
"desc": "Scarta una Cat Balou o un Panico per derubare il treno"
},
"Creepy Creek": {
"name": "Creepy Creek",
"desc": "Scarta una carta di picche per derubare il treno"
},
"Crowns Hole": {
"name": "Crown's Hole",
"desc": "Scarta una birra per derubare il treno"
},
"Deadwood": {
"name": "Deadwood",
"desc": "Scarta una carta equipaggiamento per derubare il treno"
},
"Dodgeville": {
"name": "Dodgeville",
"desc": "Scarta un Mancato! per derubare il treno"
},
"Fort Worth": {
"name": "Fort Worth",
"desc": "Scarta una carta con il numero 10, J, Q, K, A per derubare il treno"
},
"Frisco": {
"name": "Frisco",
"desc": "Scarta una carta di fiori per derubare il treno"
},
"Miners Oath": {
"name": "Miner's Oath",
"desc": "Scarta una carta di quadri per derubare il treno"
},
"San Tafe": {
"name": "San Tafe",
"desc": "Scarta una carta di cuori per derubare il treno"
},
"Tombrock": {
"name": "Tombrock",
"desc": "Per derubare il treno, perdi 1 punto vita"
},
"Yooma": {
"name": "Yooma",
"desc": "Scarta una carta con un numero compreso tra 2 e 9 per derubare il treno"
},
"Virginia Town": {
"name": "Virginia Town",
"desc": "Scarta due carte per derubare il treno"
},
"Ironhorse": {
"name": "Ironhorse",
"desc": "LOCOMOTIVA: Ogni giocatore, incluso colui che ha attivato l'effetto, è bersaglio di un BANG!\nNessun giocatore è responsabile dell'eventuale perdita di punti vita.\nSe tutti i giocatori vengono eliminati allo stesso tempo, i Fuorilegge vincono."
},
"Leland": {
"name": "Leland",
"desc": "LOCOMOTIVA: svolgi l'effetto dell'Emporio, cominciando dal giocatore di turno e procedendo in senso orario."
},
"Baggage Car": {
"name": "Baggage Car",
"desc": "Scartalo: ottieni l'effetto di un Mancato!, Panico!, Cat Balou o di un BANG! extra.\nDiscard this for a Missed!Panic!, Cat Balou, or an extra BANG!"
},
"Caboose": {
"name": "Caboose",
"desc": "Pro scartare un aura tua carta bordo bin incuso un vagone come se fosse un Mancato!"
},
"Cattle Truck": {
"name": "Cattle Truck",
"desc": "Scartalo: guarda le 3 carte in cima agli scarti e pescane I"
},
"Circus Wagon": {
"name": "Circus Wagon",
"desc": "Scartalo: ogni altro giocatore deve scartare una carta che ha in gioco."
},
"Coal Hopper": {
"name": "Coal Hopper",
"desc": "Scartalo: pesca una carta e scarta un vagone in gioco davanti a un giocatore a ma scelta."
},
"Dining Car": {
"name": "Dining Car",
"desc": "A inizio turno, \"estrai!\": se è Cuori, recuperi I punto vita."
},
"Express Car": {
"name": "Express Car",
"desc": "Scarta tutte le carte in mano, poi gioca un altro turno"
},
"Ghost Car": {
"name": "Ghost Car",
"desc": "Giocalo su chiunque tranne lo Sceritfo. Se vieni eliminato, invece resti in gioco, ma non puol guada nare ne perdere punk vita."
},
"Lounge Car": {
"name": "Lounge Car",
"desc": "Scartalo: pesca 2 vagoni dal mazzo, mettine I in gioco di fronte a te e 1 di fronte a un altro giocatore."
},
"Lumber Flatcar": {
"name": "Lumber Flatcar",
"desc": "Giocalo su un qualsiasi giocatore (compreso te). Finché questa carta è in gioco, quel giocatore vede gli altri giocatori a distanza aumentata di 1."
},
"Mail Car": {
"name": "Mail Car",
"desc": "Scartalo: pesca 3 carte e dai 1 di esse a un altro giocatore a tua scelta."
},
"Observation Car": {
"name": "Observation Car",
"desc": "Tu vedi gli altri a distanza -1. Gli altri a vedono a distanza +1."
},
"Passenger Car": {
"name": "Passenger Car",
"desc": "Scartalo: pesca una carta (in mano o in gioco) da un altro giocatore"
},
"Prisoner Car": {
"name": "Prisoner Car",
"desc": "Le carte Duello e Indiani! giocate dagli altri giocatori non hanno effetto su di te."
},
"Private Car": {
"name": "Private Car",
"desc": "se non hai carte in mano. non puoi essere bersaelio di carte BANG"
},
"Sleeper Car": {
"name": "Sleeper Car",
"desc": "Una volta per turno, puoi scartare un'altra tua carta a bordo blu incluso."
}
},
"help": {
@ -472,6 +1023,21 @@
"renegade": "Rinnegato",
"vice": "Vice",
"gotoallcharacters": "Visualizza tutti i personaggi",
"allcharacters": "Tutti i personaggi"
"gotocards": "Visualizza le carte",
"gotohighnoon": "Visualizza le carte High Noon",
"gotofoc": "Visualizza le carte Fistful Of Cards",
"gotogoldrush": "Visualizza le carte Gold Rush",
"allcharacters": "Tutti i personaggi",
"highnooncards": "Carte Evento High Noon",
"foccards": "Carte Evento Fistful of Cards",
"goldrushcards": "Carte Gold Rush",
"valleyofshadowscards": "Carte The Valley of Shadows"
},
"theme": {
"sepia": "Seppia",
"light": "Chiaro",
"dark": "Scuro",
"grayscale": "Scala di Grigi",
"black": "Nero Puro"
}
}

918
frontend/src/i18n/ru.json Normal file
View File

@ -0,0 +1,918 @@
{
"trademark": "Bang! является торговой маркой, принадлежащей DVGiochi",
"tip_1": "Лучше с друзьями!",
"tip_2": "Иконка 🤖️ означает, что игрок - бот!",
"tip_3": "Вы можете нажать на карты персонажей и оборудования других игроков, если хотите узнать больше!",
"tip_4": "Включает Dodge City, High Noon, Fistful Of Cards!",
"tip_5": "Нашли ошибку? Напишите нам в Discord!",
"tip_6": "Теперь у нас есть сервер Discord!",
"tip_7": "Если вы хотите помочь нам перевести игру на ваш язык, свяжитесь с нами в Discord!",
"tip_8": "Если вы отключитесь во время игры, вас заменит бот (пока вы отсутствуете)!",
"tip_9": "Если вы на мобильном устройстве, удерживайте карту, чтобы прочитать описание!",
"tip_10": "Если сомневаетесь, стреляйте во всех других игроков!",
"online_players": "Онлайн-игроки: ",
"shuffle_players": "Перемешать игроков",
"choose_username": "Выберите имя пользователя:",
"report_bug": "Опишите ошибку",
"report": "Сообщить об ошибке",
"available_lobbies": "Доступные лобби:",
"spectate_lobbies": "Наблюдать за играми:",
"no_lobby_available": "Нет доступных лобби",
"create_lobby": "Создать лобби:",
"characters_to_distribute": "Персонажи для распределения: ",
"lobby_name": "Название:",
"leave_room": "Покинуть лобби",
"warning": "Внимание!",
"connection_error": "Не удается подключиться к серверу.",
"end_turn": "Конец хода!",
"start_game": "Начать!",
"expansions": "Дополнения",
"click_to_toggle": "Нажмите, чтобы переключить",
"details": "Детали",
"ok": "OK",
"you": "ВЫ",
"owner": "ВЛАДЕЛЕЦ",
"cancel": "ОТМЕНА",
"send": "ОТПРАВИТЬ",
"password": "Пароль: ",
"room_password_prompt": "Пароль для лобби: ",
"private_room": "Частное лобби",
"room": "Лобби: ",
"room_players": "Игроки (вы - {username})",
"choose_character": "Выберите своего персонажа",
"choose_card": "Выберите карту",
"choose_card_from": " из ",
"flip_card": "↙️ Перевернуть карту",
"draw_cards": "⏬ Возьмите свои карты из колоды",
"play_cards": "▶️ Сыграйте свои карты",
"respond_card": "↩️ Ответить на карту",
"wait": "⏸ Подождите",
"choose_cards": "🔽 Выберите карту",
"take_dmg": "Получить урон",
"choose_response": "Выберите ваш ответ ",
"choose_response_to": "на ",
"choose_response_needed": "ТРЕБУЕТСЯ ",
"choose_manette": "Выберите масть, вы сможете играть только карты с этой мастью в этом ходу.",
"hand": "РУКА",
"card_against": "Против кого вы сыграете карту?",
"choose_sid_scrap": "Сбросьте 2 карты, чтобы не умереть",
"choose_card_to_get": "Выберите карту",
"choose_guess": "Угадайте цвет масти",
"choose_ranch": "Выберите карты для замены",
"choose_dalton": "Выберите, какое оборудование сбросить",
"choose_fratelli_di_sangue": "Выберите, кому вы хотите пожертвовать одну из своих жизней",
"choose_fantasma": "Выберите, кого воскресить",
"choose_sventagliata": "Выберите другую цель для попадания с Fanning",
"choose_tornado": "Выберите карту для сброса в торнадо",
"choose_bandidos": "Выберите между сбросом 2 карт или потерей жизни (1 карта, если у вас только 1)",
"choose_poker": "Все сбрасывают 1 карту (если нет туза, игрок, который сыграл покер, выбирает 2 карты)",
"choose_from_poker;2": "Выберите карты для получения (макс. 2)",
"choose_from_poker;1": "Выберите карту для получения",
"choose_cecchino": "Выберите, в кого стрелять",
"choose_rimbalzo_player": "Выберите цель для рикошета",
"choose_rimbalzo_card": "Выберите карту для сброса рикошета",
"choose_nuova_identita": "Выберите, хотите ли вы сохранить текущего персонажа или изменить его и начать с 2 жизнями",
"choose_bicchierino": "Игрок по вашему выбору восстанавливает 1 жизнь",
"choose_bottiglia": "Выберите, как играть Бутылку!",
"choose_complice": "Выберите, как играть Подельника!",
"choose_ricercato": "Выберите, против кого играть Разыскивается.",
"choose_birra_function": "Выберите между получением 1 золотого самородка, сбросив пиво, или игрой пива.",
"choose_play_as_bang": "Выберите, какую карту сыграть как Bang!",
"choose_flint_special": "Выберите, какую карту обменять.",
"emporio_others": "{0} выбирает, какую карту получить из Общего магазина",
"you_died": "ВЫ УМЕРЛИ",
"spectate": "НАБЛЮДАТЬ",
"you_win": "ВЫ ВЫИГРАЛИ",
"you_lose": "ВЫ ПРОИГРАЛИ",
"special_ability": "ОСОБАЯ СПОСОБНОСТЬ",
"gold_rush_discard": "Сбросьте оборудование золотой лихорадки другого игрока (уплачивая цену + 1)",
"gold_rush_discard_2": "Сбросьте оборудование золотой лихорадки другого игрока (уплачивая цену + 1)",
"discard": "СБРОСИТЬ",
"to_regain_1_hp": "ВОССТАНОВИТЬ 1 ЖИЗНЬ",
"play_your_turn": "СЫГРАЙТЕ СВОЙ ХОД",
"you_are": "Вы",
"did_pick_as": "выбрал это как вторую карту",
"blackjack_special": "Если карта - бубны или черви, он берет еще одну карту.",
"choose_scarp_card_to": "ВЫБЕРИТЕ КАРТУ ДЛЯ СБРОСА, ЧТОБЫ ИСПОЛЬЗОВАТЬ",
"pick_a_card": "ПЕРЕВЕРНИТЕ КАРТУ",
"to_defend_from": "ЗАЩИЩАЙТЕСЬ ОТ",
"submit": "Отправить",
"copy": "Скопировать приглашение",
"no_players_in_range": "Вы не видите других игроков, экипируйте оружие или прицел!",
"cantplaycard": "Вы не можете играть эту карту таким образом!",
"chat": {
"spectators": " | Один зритель смотрит игру | {n} зрителей смотрят игру",
"chat": "Чат",
"joined": "👋 ;{0}; присоединился к лобби",
"died": "☠️ ;{0}; умер",
"died_role": "☠️ ;{0}; был ;{1};!",
"won": "🏆 ;{0}; выиграл! Их роль была ;{1};",
"choose_character": ";{0}; имеет ;{1}; как персонажа, его особая способность: ;{2};!",
"starting": "Игра начинается!",
"sheriff": "⭐ ;{0}; шериф!",
"did_choose_character": ";{0}; выбрал персонажа.",
"turn": "⏩ Сейчас ход ;{0};.",
"draw_from_scrap": ";{0}; взял первую карту из кучи сброса.",
"draw_from_player": ";{0}; взял первую карту из руки ;{1};.",
"flipped": ";{0}; перевернул ;{1}; ;{2};.",
"scrapped": ";{0}; сбросил ;{1}; ;{2};.",
"explode": "💥 ;{0}; взорвал динамит.",
"beer_save": ";{0}; использовал пиво, чтобы спасти свою жизнь.",
"get_nugget": ";{0}; получил золотой самородок, используя Пиво.",
"play_card": ";{0}; сыграл ;{1};.",
"play_card_green": ";{0}; ввел в игру ;{1};.",
"play_card_with": ";{0}; сыграл ;{1};, сбросив ;{2};.",
"purchase_card": ";{0}; купил ;{1};.",
"play_card_against": ";{0}; сыграл ;{1}; против ;{2};.",
"play_card_against_with": ";{0}; сыграл ;{1}; против ;{2};, сбросив ;{3};.",
"play_card_for": ";{0}; сыграл ;{1}; для ;{2};.",
"spilled_beer": ";{0}; пролил ;{1};.",
"diligenza": ";{0}; сыграл ;{1}; и взял 2 карты.",
"wellsfargo": ";{0}; сыграл ;{1}; и взял 3 карты.",
"saloon": "🍻 ;{0}; сыграл ;{1}; и исцелил 1 HP всем живым.",
"special_bart_cassidy": ";{0}; получил компенсацию, потому что был ранен.",
"special_el_gringo": ";{0}; украл карту у ;{1};, когда был ранен.",
"special_calamity": ";{0}; сыграл ;{1}; как Bang! против ;{2};.",
"allroles3": "В игре есть: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};.",
"allroles4": "В игре есть: ;{1}; ;{0};, ;{3}; ;{2};, ;{5}; ;{4};, ;{7}; ;{6};.",
"guess": "🤔 ;{0}; угадывает ;{1};.",
"guess_right": ";{0}; был прав.",
"guess_wrong": ";{0}; ошибся.",
"fratelli_sangue": ";{0}; дал одну из своих жизней ;{1};.",
"doctor_heal": ";{0}; был исцелен доктором.",
"respond": "↩️ ;{0}; ответил ;{1};.",
"change_username": "✏️ ;{0}; теперь ;{1};.",
"lobby_reset": "Возвращение в лобби через ;{0}; секунд...",
"prison_free": "🆓 ;{0}; вышел из тюрьмы",
"prison_turn": "🔐 ;{0}; остался в тюрьме в этот ход",
"flip_event": "🎴 СОБЫТИЕ: ;{0}; 🎴",
"choose_manette": ";{0}; обязался играть только карты масти ;{1}; в этом ходу.",
"UnionPacific": ";{0}; сыграл Union Pacific и взял 4 карты из колоды",
"use_special": ";{0}; использовал особую способность своего персонажа (;{1};)",
"gold_rush_pay_discard": ";{0}; сбросил ;{2}; у ;{1};.",
"choose_emporio": ";{0}; выбрал ;{1}; из Общего магазина.",
"shotgun_scrap": "Когда дробовик попал в ;{0};, карта улетела из его руки (;{1};)",
"taglia_reward": "💰 ;{1}; получил карту за награду за ;{0};",
"snake_bit": "🐍 ;{0}; был укушен гремучей змеей."
},
"foc": {
"leggedelwest": "Он должен сыграть эту карту в этот ход, если возможно."
},
"mods": "Модификаторы",
"bots": "Боты",
"add_bot": "Добавить бота",
"remove_bot": "Удалить бота",
"minimum_players": "Для начала игры нужно как минимум 3 игрока",
"mod_comp": "Соревновательный режим (отключает автоматическое получение урона)",
"disconnect_bot": "Заменить отключившихся игроков ботами",
"your_turn": "Сыграйте свой ход!",
"your_response": "Ответьте!",
"your_choose": "Выберите карту!",
"cards": {
"Barile": {
"name": "Бочка",
"desc": "Когда кто-то играет Bang против вас. Вы можете перевернуть первую карту из колоды, если масть - червы, то это считается картой Промах"
},
"Dinamite": {
"name": "Динамит",
"desc": "Когда играете Динамит, положите его перед собой, он будет безвреден в течение всего раунда. В начале следующего хода перед взятием карт и перед любым переворотом карты (например, Тюрьма), переверните карту с верха колоды. Если карта между 2 и 9 пиками (включительно), динамит взрывается: вы теряете 3 жизни и сбрасываете карту, иначе передайте динамит следующему игроку, который возьмет карту после окончания вашего хода"
},
"Mirino": {
"name": "Прицел",
"desc": "Вы видите других игроков на расстоянии -1"
},
"Mustang": {
"name": "Мустанг",
"desc": "Другие игроки видят вас на расстоянии +1"
},
"Prigione": {
"name": "Тюрьма",
"desc": "Экипируйте эту карту другому игроку, кроме шерифа. Выбранный игрок в начале своего хода должен перевернуть карту перед взятием: если это червы, сбросьте эту карту и играйте ход нормально, иначе сбросьте эту карту и пропустите ход"
},
"Remington": {
"name": "Ремингтон",
"desc": "Вы можете стрелять в другого игрока на расстоянии 3 или меньше"
},
"Rev Carabine": {
"name": "Карабин Рев.",
"desc": "Вы можете стрелять в другого игрока на расстоянии 4 или меньше"
},
"Schofield": {
"name": "Шофилд",
"desc": "Вы можете стрелять в другого игрока на расстоянии 2 или меньше"
},
"Volcanic": {
"name": "Вулканик",
"desc": "Вы можете стрелять в другого игрока на расстоянии 1 или меньше, однако у вас больше нет ограничения в 1 Bang"
},
"Winchester": {
"name": "Винчестер",
"desc": "Вы можете стрелять в другого игрока на расстоянии 5 или меньше"
},
"Bang!": {
"name": "Bang!",
"desc": "Стреляйте в игрока на виду. Если у вас нет оружия, ваша дальность - 1"
},
"Birra": {
"name": "Пиво",
"desc": "Сыграйте эту карту, чтобы восстановить одно очко жизни. Вы не можете исцелиться более чем на максимальный предел вашего персонажа. Если вы собираетесь потерять свою последнюю жизнь, вы также можете сыграть эту карту в ход вашего противника. Пиво больше не действует, если осталось только два игрока"
},
"Cat Balou": {
"name": "Кэт Баллоу",
"desc": "Выберите и сбросьте карту любого другого игрока."
},
"Diligenza": {
"name": "Дилижанс",
"desc": "Возьмите 2 карты из колоды."
},
"Duello": {
"name": "Дуэль",
"desc": "Сыграйте эту карту против любого игрока. По очереди, начиная с вашего противника, вы можете сбросить карту Bang!, первый игрок, который этого не сделает, теряет 1 жизнь."
},
"Emporio": {
"name": "Общий магазин",
"desc": "Положите на стол N карт из колоды, где N - количество живых игроков, по очереди, начиная с вас, выберите карту и добавьте ее в свою руку"
},
"Gatling": {
"name": "Гатлинг",
"desc": "Стреляйте во всех остальных игроков"
},
"Indiani!": {
"name": "Индейцы!",
"desc": "Все остальные игроки должны сбросить карту Bang! или потерять 1 очко здоровья"
},
"Mancato!": {
"name": "Промах!",
"desc": "Используйте эту карту, чтобы отменить эффект Bang"
},
"Panico!": {
"name": "Паника!",
"desc": "Украдите карту у игрока на расстоянии 1"
},
"Saloon": {
"name": "Салун",
"desc": "Все восстанавливают 1 очко здоровья"
},
"WellsFargo": {
"name": "Веллс Фарго",
"desc": "Возьмите 3 карты из колоды"
},
"Binocolo": {
"name": "Бинокль",
"desc": "Вы видите других игроков на расстоянии -1"
},
"Riparo": {
"name": "Укрытие",
"desc": "Другие игроки видят вас на расстоянии +1"
},
"Pugno!": {
"name": "Удар!",
"desc": "Стреляйте в игрока на расстоянии 1"
},
"Rag Time": {
"name": "Регтайм",
"desc": "Украдите карту у другого игрока на любом расстоянии"
},
"Rissa": {
"name": "Драка",
"desc": "Выберите карту для сброса из руки/оборудования всех остальных игроков"
},
"Schivata": {
"name": "Уклонение",
"desc": "Используйте эту карту, чтобы отменить эффект Bang и затем взять карту."
},
"Springfield": {
"name": "Спрингфилд",
"desc": "Стреляйте в игрока на любом расстоянии"
},
"Tequila": {
"name": "Текила",
"desc": "Исцелите 1 HP игроку по вашему выбору (можете быть вы)"
},
"Whisky": {
"name": "Виски",
"desc": "Исцелите 2 HP"
},
"Bibbia": {
"name": "Библия",
"desc": "Используйте эту карту, чтобы отменить эффект Bang и затем взять карту."
},
"Cappello": {
"name": "Шляпа Десяти Галлонов",
"desc": "Используйте эту карту, чтобы отменить эффект Bang"
},
"Placca Di Ferro": {
"name": "Железная Пластина",
"desc": "Используйте эту карту, чтобы отменить эффект Bang"
},
"Sombrero": {
"name": "Сомбреро",
"desc": "Используйте эту карту, чтобы отменить эффект Bang"
},
"Pugnale": {
"name": "Нож",
"desc": "Стреляйте в игрока на расстоянии 1"
},
"Derringer": {
"name": "Дерринджер",
"desc": "Стреляйте в игрока на расстоянии 1 и затем возьмите карту."
},
"Borraccia": {
"name": "Фляга",
"desc": "Восстановите 1 HP"
},
"Can Can": {
"name": "Канкан",
"desc": "Выберите и сбросьте карту любого другого игрока."
},
"Conestoga": {
"name": "Конесто",
"desc": "Украдите карту у другого игрока на любом расстоянии"
},
"Fucile Da Caccia": {
"name": "Охотничий Ружьё",
"desc": "Стреляйте в игрока на любом расстоянии"
},
"Pony Express": {
"name": "Пони Экспресс",
"desc": "Возьмите 3 карты из колоды"
},
"Pepperbox": {
"name": "Пеппербокс",
"desc": "Стреляйте в игрока на виду. Если у вас нет оружия, ваша дальность - 1"
},
"Howitzer": {
"name": "Гаубица",
"desc": "Стреляйте во всех остальных игроков"
},
"Bart Cassidy": {
"name": "Барт Кэссиди",
"desc": "Каждый раз, когда он ранен, он берет карту."
},
"Black Jack": {
"name": "Блэк Джек",
"desc": "В начале своего хода, когда он должен взять карту, он показывает всем вторую карту, если это червы или бубны, он берет третью карту, не показывая ее."
},
"Calamity Janet": {
"name": "Каламити Джанет",
"desc": "Она может использовать карты Промах! как Bang! и наоборот."
},
"El Gringo": {
"name": "Эль Гринго",
"desc": "Каждый раз, когда он ранен, он берет карту из руки атакующего игрока."
},
"Jesse Jones": {
"name": "Джесси Джонс",
"desc": "Когда он должен взять свои карты, он может взять первую карту из руки другого игрока. (нажмите на карты вражеского игрока, если хотите использовать эту способность)"
},
"Jourdonnais": {
"name": "Журдонэ",
"desc": "Он играет, как если бы у него всегда была активная Бочка, если он экипирует другую Бочку, он может перевернуть 2 карты."
},
"Kit Carlson": {
"name": "Кит Карлсон",
"desc": "Когда он должен взять карту, он смотрит 3 карты и выбирает 2, положив другую карту на верх колоды."
},
"Lucky Duke": {
"name": "Счастливчик Дюк",
"desc": "Каждый раз, когда он должен перевернуть карту, он может перевернуть 2 раза."
},
"Paul Regret": {
"name": "Пол Регрет",
"desc": "Другие игроки видят его на расстоянии +1."
},
"Pedro Ramirez": {
"name": "Педро Рамирес",
"desc": "Когда он должен взять карту, он может взять первую карту из кучи сброса. (нажмите на карты в куче сброса, чтобы использовать эту способность)"
},
"Rose Doolan": {
"name": "Роуз Дулан",
"desc": "Она видит других игроков на расстоянии -1."
},
"Sid Ketchum": {
"name": "Сид Кетчум",
"desc": "Он может сбросить 2 карты, чтобы восстановить 1 HP."
},
"Slab The Killer": {
"name": "Слэб Убийца",
"desc": "Чтобы уклониться от его Bang! карт, другим игрокам нужны 2 Промах!"
},
"Suzy Lafayette": {
"name": "Сьюзи Лафайет",
"desc": "Каждый раз, когда у нее пустая рука, она берет карту."
},
"Vulture Sam": {
"name": "Волчер Сэм",
"desc": "Когда игрок умирает, он получает все карты из руки и экипировку умершего."
},
"Willy The Kid": {
"name": "Вилли Кид",
"desc": "У него нет ограничений на количество Bang, которые он может использовать."
},
"Pixie Pete": {
"name": "Пикси Пит",
"desc": "Он берет 3 карты вместо 2."
},
"Tequila Joe": {
"name": "Текила Джо",
"desc": "Когда он играет Пиво, он восстанавливает 2 HP."
},
"Greg Digger": {
"name": "Грег Диггер",
"desc": "Каждый раз, когда игрок умирает, он восстанавливает до 2 жизней."
},
"Herb Hunter": {
"name": "Херб Хантер",
"desc": "Каждый раз, когда игрок умирает, он берет 2 карты."
},
"Elena Fuente": {
"name": "Елена Фуэнте",
"desc": "Она может использовать любую карту из своей руки как Промах."
},
"Bill Noface": {
"name": "Билл Безликий",
"desc": "Он берет 1 карту + 1 карту за каждую рану, которую он имеет."
},
"Molly Stark": {
"name": "Молли Старк",
"desc": "Когда она использует карту из своей руки вне своего хода, она берет карту."
},
"Apache Kid": {
"name": "Апачи Кид",
"desc": "Карты бубен ♦️, сыгранные против него, не имеют эффекта (не работает в дуэлях)."
},
"Sean Mallory": {
"name": "Шон Мэллори",
"desc": "Он может держать до 10 карт в руке, заканчивая ход."
},
"Belle Star": {
"name": "Белль Стар",
"desc": "Во время ее хода зеленые и синие карты других игроков не работают."
},
"Vera Custer": {
"name": "Вера Кастер",
"desc": "Перед взятием карт она может выбрать особую способность другого живого игрока. Эта способность используется до следующего хода."
},
"Chuck Wengam": {
"name": "Чак Венгам",
"desc": "Во время своего хода он может решить потерять 1 HP, чтобы взять 2 карты из колоды."
},
"Pat Brennan": {
"name": "Пэт Бреннан",
"desc": "Вместо того чтобы брать карты, он может украсть карту из экипировки другого игрока. (нажмите на вражеского игрока, если хотите использовать эту способность)"
},
"José Delgado": {
"name": "Хосе Дельгадо",
"desc": "Во время своего хода он может сбросить синюю карту, чтобы взять 2 карты, до двух раз за ход."
},
"Doc Holyday": {
"name": "Док Холидей",
"desc": "Он может сбросить 2 карты, чтобы сыграть Bang."
},
"Fuorilegge": {
"name": "Бандит"
},
"Rinnegato": {
"name": "Ренегат"
},
"Sceriffo": {
"name": "Шериф"
},
"Vice": {
"name": "Помощник"
},
"Miniera Abbandonata": {
"name": "Заброшенная Шахта",
"desc": "Игроки берут карты из кучи сброса в фазе 1 и сбрасывают на верх колоды в фазе 3 (если куча сброса заканчивается, они должны брать и сбрасывать на верх колоды)"
},
"Il Giudice": {
"name": "Судья",
"desc": "Вы не можете экипировать карты на себя или других игроков"
},
"Agguato": {
"name": "Засада",
"desc": "Базовое расстояние между двумя игроками - 1"
},
"Rimbalzo": {
"name": "Рикошет",
"desc": "Игрок может играть Bang против карт, экипированных другими игроками, если они не играют Промах, они сбрасываются (нажмите на карту события)"
},
"Cecchino": {
"name": "Снайпер",
"desc": "Во время своего хода игроки могут сбросить 2 Bang!, чтобы стрелять Bang!, который требует 2 Промах (нажмите на карту)"
},
"Lazo": {
"name": "Лассо",
"desc": "Карты в слоте экипировки не работают"
},
"Ranch": {
"name": "Ранчо",
"desc": "После взятия карт игрок может сбросить любое количество карт из руки и взять столько же из колоды"
},
"Dead Man": {
"name": "Мертвец",
"desc": "Первый игрок, который умрет, вернется к жизни с 2 HP и 2 картами"
},
"Liquore Forte": {
"name": "Крепкий Ликёр",
"desc": "Игроки могут пропустить взятие карт, чтобы восстановить 1 HP (нажмите на карту события, чтобы использовать)"
},
"Vendetta": {
"name": "Месть",
"desc": "Заканчивая ход, игрок переворачивает карту из колоды, если это ❤️, он играет еще один ход (но не переворачивает другую карту)"
},
"Roulette Russa": {
"name": "Русская Рулетка",
"desc": "Начиная с шерифа, каждый игрок сбрасывает 1 Промах, первый, кто этого не сделает, теряет 2 HP"
},
"Legge Del West": {
"name": "Закон Запада",
"desc": "Каждый игрок показывает вторую карту, которую он берет, и должен использовать ее в этом раунде (если это возможно)"
},
"Peyote": {
"name": "Пейот",
"desc": "Вместо взятия карт игрок пытается угадать цвет масти, если он прав, добавляет карту в руку и продолжает пытаться угадать следующую карту"
},
"Fratelli Di Sangue": {
"name": "Кровные Братья",
"desc": "В начале своего хода игроки могут потерять 1 HP (кроме последнего), чтобы отдать его другому игроку"
},
"I Dalton": {
"name": "Дальтоны",
"desc": "Игроки, у которых экипированы синие карты, сбрасывают одну из этих карт по своему выбору"
},
"Sermone": {
"name": "Проповедь",
"desc": "Игроки не могут играть Bang! во время своего хода"
},
"Città Fantasma": {
"name": "Город Призрак",
"desc": "Все умершие игроки возвращаются к жизни в свой ход, они не могут умереть и берут 3 карты вместо 2. Когда они заканчивают ход, они умирают."
},
"Il Reverendo": {
"name": "Преподобный",
"desc": "Пиво не может быть сыграно"
},
"Sbornia": {
"name": "Похмелье",
"desc": "Персонажи теряют свои особые способности"
},
"Il Dottore": {
"name": "Доктор",
"desc": "Игрок с наименьшим количеством HP получает 1 HP"
},
"Corsa All Oro": {
"name": "Золотая Лихорадка",
"desc": "Ходы играются против часовой стрелки"
},
"Maledizione": {
"name": "Проклятие",
"desc": "Все карты - пики ♠️"
},
"Sparatoria": {
"name": "Перестрелка",
"desc": "Лимит Bang! за ход - 2"
},
"Benedizione": {
"name": "Благословение",
"desc": "Все карты - червы ❤️"
},
"Il Treno": {
"name": "Прибытие Поезда",
"desc": "Игроки берут 1 дополнительную карту"
},
"Sete": {
"name": "Жажда",
"desc": "Игроки берут только 1 карту в начале своего хода"
},
"Nuova Identita": {
"name": "Новая Личность",
"desc": "В начале своего хода каждый игрок может выбрать сменить персонажа на другого, показанного в начале игры. Если он это делает, он начинает с 2 HP"
},
"Manette": {
"name": "Наручники",
"desc": "После взятия карт в фазе 1 игрок объявляет масть. Он сможет использовать только карты этой масти в этом ходу"
},
"Mezzogiorno di Fuoco": {
"name": "Полдень",
"desc": "Каждый игрок теряет 1 HP, когда начинается его ход"
},
"Per Un Pugno Di Carte": {
"name": "За Горсть Карт",
"desc": "В начале своего хода игрок становится целью стольких Bang, сколько карт у него в руке"
},
"Pepita": {
"name": "Золотой Самородок"
},
"Bicchierino": {
"name": "Стаканчик",
"desc": "Вы можете выбрать игрока, который восстанавливает 1 HP (даже себя)"
},
"Bottiglia": {
"name": "Бутылка",
"desc": "Можно сыграть как Паника!, Пиво или Bang!"
},
"Complice": {
"name": "Подельник",
"desc": "Можно сыграть как Общий магазин, Дуэль или Кэт Баллоу."
},
"Corsa All Oro_gr": {
"name": "Золотая Лихорадка",
"desc": "Вы заканчиваете ход, восстанавливаете все HP и начинаете новый ход."
},
"Rum": {
"name": "Ром",
"desc": "Переверните 4 карты, за каждую масть вы получаете 1 HP."
},
"Union Pacific": {
"name": "Union Pacific",
"desc": "Возьмите 4 карты из колоды."
},
"Calumet": {
"name": "Калюмет",
"desc": "Карты бубен, сыгранные другими игроками, не имеют на вас эффекта."
},
"Cinturone": {
"name": "Ремень",
"desc": "Вы можете держать до 8 карт, когда заканчиваете ход."
},
"Ferro di Cavallo": {
"name": "Подкова",
"desc": "Каждый раз, когда вы должны перевернуть карту, переворачивайте дважды!"
},
"Piccone": {
"name": "Кирка",
"desc": "Вы получаете 1 карту больше, когда берете в начале хода."
},
"Ricercato": {
"name": "Разыскивается",
"desc": "Сыграйте на другого игрока, кто убьет цель, получит 2 дополнительные карты и 1 золотой самородок."
},
"Setaccio": {
"name": "Золотодобытчик",
"desc": "Заплатите 1 золотой самородок, чтобы взять 1 карту из колоды, до двух раз за ход. (Нажмите на экипированную карту, чтобы использовать)"
},
"Stivali": {
"name": "Сапоги",
"desc": "Каждый раз, когда вы теряете 1 HP, вы берете 1 карту из колоды."
},
"Talismano": {
"name": "Амулет Удачи",
"desc": "Каждый раз, когда вы теряете 1 HP, вы получаете 1 золотой самородок."
},
"Zaino": {
"name": "Рюкзак",
"desc": "Заплатите 2 золотых самородка, чтобы исцелить 1 HP. (Нажмите на экипированную карту, чтобы использовать)"
},
"Don Bell": {
"name": "Дон Белл",
"desc": "Когда он заканчивает ход, он переворачивает карту, если это Червы ❤️ или Бубны ♦️, он играет снова."
},
"Dutch Will": {
"name": "Датч Вилл",
"desc": "Он берет 2 карты, сбрасывает 1 и берет 1 золотой самородок."
},
"Jacky Murieta": {
"name": "Джекки Мурьета",
"desc": "Во время своего хода он может заплатить 2 золотых самородка, чтобы иметь возможность стрелять еще раз!"
},
"Josh McCloud": {
"name": "Джош МакКлауд",
"desc": "Он может заплатить 2 золотых самородка, чтобы получить первую карту из колоды золотой лихорадки."
},
"Madam Yto": {
"name": "Мадам Ито",
"desc": "Она берет 1 карту из колоды каждый раз, когда играется Пиво."
},
"Pretty Luzena": {
"name": "Красотка Лузена",
"desc": "Один раз за ход она может получить скидку 1 на магазине карт золотой лихорадки."
},
"Raddie Snake": {
"name": "Рэдди Снейк",
"desc": "Он может выбросить 1 золотой самородок, чтобы взять 1 карту из колоды во время своего хода (максимум 2 раза за ход)."
},
"Simeon Picos": {
"name": "Симеон Пикос",
"desc": "Он получает 1 золотой самородок каждый раз, когда теряет 1 HP."
},
"Fantasma": {
"name": "Призрак",
"desc": "Сыграйте на любом выбывшем игроке: этот игрок возвращается в игру, но не может получить или потерять очки жизни."
},
"Lemat": {
"name": "Лемат",
"desc": "Во время своего хода вы можете использовать любую карту как Bang! (Нажмите на карту после экипировки)."
},
"SerpenteASonagli": {
"name": "Гремучая Змея",
"desc": "Сыграйте на любом игроке. В начале своего хода, если этот игрок берет в Пики, он теряет 1 HP."
},
"Shotgun": {
"name": "Дробовик",
"desc": "Каждый раз, когда вы раните игрока, он должен сбросить карту из руки."
},
"Taglia": {
"name": "Награда",
"desc": "Сыграйте на любом игроке. Если этот игрок попадает под Bang!, тот, кто стрелял, получает карту из колоды."
},
"Mira": {
"name": "Прицел",
"desc": "Сыграйте эту карту вместе с Bang!. Если цель поражена, она теряет 2 HP."
},
"RitornoDiFiamma": {
"name": "Отдача",
"desc": "Считается как Промах!. Игрок, который стрелял, становится целью Bang!."
},
"Bandidos": {
"name": "Бандитос",
"desc": "Каждый игрок выбирает между сбросом 2 карт из руки (или 1, если у него только 1) или потерей 1 HP."
},
"Fuga": {
"name": "Побег",
"desc": "Может быть сыграно вне хода. Избегает эффекта коричневой карты (не Bang!), направленной на вас."
},
"Sventagliata": {
"name": "Стрельба В Ряд",
"desc": "Считается единственным Bang! за ход. Игрок по вашему выбору на расстоянии 1 от цели (если есть, кроме вас) также становится целью Bang."
},
"UltimoGiro": {
"name": "Последний Вздох",
"desc": "Восстанавливает 1 HP"
},
"Poker": {
"name": "Покер",
"desc": "Все остальные игроки сбрасывают карту из руки одновременно. Если нет тузов, возьмите до 2 из этих карт."
},
"Salvo": {
"name": "Спасение!",
"desc": "Может быть сыграно вне хода. Предотвращает потерю 1 HP другим игроком. Если он выживает, возьмите 2 карты из его руки или из колоды (по вашему выбору)."
},
"Tomahawk": {
"name": "Томагавк",
"desc": "Атакует игрока на расстоянии до 2."
},
"Tornado": {
"name": "Торнадо",
"desc": "Все сбрасывают карту из руки (если возможно), затем берут 2 карты из колоды."
},
"Black Flower": {
"name": "Черный Цветок",
"desc": "Один раз за ход вы можете использовать карту Пик, чтобы стрелять еще раз Bang!"
},
"Colorado Bill": {
"name": "Колорадо Билл",
"desc": "Каждый раз, когда вы играете карту Bang!, если вы берете Пики, выстрел не может быть уклонен."
},
"Der Spot Burst Ringer": {
"name": "Дер Спот Бурст Рингер",
"desc": "Один раз за ход вы можете использовать карту Bang! как Гатлинг."
},
"Evelyn Shebang": {
"name": "Эвелин Шебанг",
"desc": "Вы можете выбрать не брать карты во время фазы взятия. За каждую не взятую карту вы стреляете Bang! в достижимую цель, в разных целях."
},
"Henry Block": {
"name": "Генри Блок",
"desc": "Любой, кто берет или сбрасывает одну из ваших карт в игре или в руке, становится целью Bang!."
},
"Lemonade Jim": {
"name": "Лимонад Джим",
"desc": "Каждый раз, когда другой игрок играет Пиво, вы можете сбросить карту из руки, чтобы также восстановить 1 HP."
},
"Mick Defender": {
"name": "Мик Защитник",
"desc": "Если вы становитесь целью коричневой карты (не Bang!), вы можете использовать карту Промах!, чтобы избежать 1 эффекта."
},
"Tuco Franziskaner": {
"name": "Туко Францисканер",
"desc": "Если у вас нет экипированных синих карт, вы берете 2 дополнительные карты."
},
"Big Spencer": {
"name": "Большой Спенсер",
"desc": "Начинает с 5 картами. Не может играть Промах!"
},
"Flint Westwood": {
"name": "Флинт Вествуд",
"desc": "Он может обменять карту из своей руки на 2 случайные карты из руки другого игрока во время своего хода."
},
"Gary Looter": {
"name": "Гэри Лутер",
"desc": "Он берет все избыточные карты, сброшенные другими игроками в конце каждого хода."
},
"Greygory Deckard": {
"name": "Грейгори Декард",
"desc": "В начале своего хода он может взять 2 случайных персонажа и получает все их способности."
},
"John Pain": {
"name": "Джон Пейн",
"desc": "Если у него меньше 6 карт в руке, когда игрок \"берет!\", Джон добавляет взятую карту в свою руку."
},
"Lee Van Kliff": {
"name": "Ли Ван Клифф",
"desc": "Во время своего хода он может сбросить карту Bang!, чтобы повторить эффект коричневой карты, которую он только что сыграл."
},
"Teren Kill": {
"name": "Терен Килл",
"desc": "Каждый раз, когда он должен быть устранен, \"берет!\": если это не Пики, Терен остается с 1 HP и берет 1 карту."
},
"Youl Grinner": {
"name": "Юл Гриннер",
"desc": "Перед взятием карт игроки с большим количеством карт в руке, чем у Юла, должны дать ему карту по своему выбору."
},
"Camposanto": {
"name": "Кладбище",
"desc": "В начале своего хода каждый устраненный игрок возвращается в игру с 1 HP. Возьмите карту роли случайным образом из устраненных игроков."
},
"Darling Valentine": {
"name": "Дарлинг Валентайн",
"desc": "В начале своего хода каждый игрок сбрасывает свою руку и берет столько же карт из колоды."
},
"Dorothy Rage": {
"name": "Дороти Рейдж",
"desc": "Во время своего хода каждый игрок может заставить другого игрока сыграть карту."
},
"Helena Zontero": {
"name": "Хелена Зонтеро",
"desc": "Когда Хелена вступает в игру, \"берет!\": если берутся Червы или Бубны, перетасуйте активные карты ролей, кроме шерифа, и перераспределите их случайным образом."
},
"Lady Rosa del Texas": {
"name": "Леди Роза из Техаса",
"desc": "Во время своего хода каждый игрок может поменяться местами с игроком справа, который пропускает свой следующий ход. (Нажмите на карту)"
},
"Miss Susanna": {
"name": "Мисс Сюзанна",
"desc": "Во время своего хода каждый игрок должен сыграть как минимум 3 карты. Если они этого не сделают, они теряют 1 HP."
},
"Regolamento di Conti": {
"name": "Сворачивание Счетов",
"desc": "Все карты могут быть сыграны, как если бы они были Bang!. Карты Bang! могут быть сыграны, как если бы они были Промах! (Нажмите на карту)"
},
"Sacagaway": {
"name": "Сакаджавея",
"desc": "Все игроки играют с картами лицом вверх (кроме карты роли!)."
},
"Wild West Show": {
"name": "Шоу Дикого Запада",
"desc": "Цель каждого игрока становится: \"Будь последним стоящим!\""
}
},
"help": {
"character": "Персонажи",
"characters_special": "У каждого персонажа есть особые способности и количество жизней, которые делают их уникальными. \nЖизни - это количество очков жизни, которые вы можете потерять до смерти, а также указывают на максимальное количество карт, которые вы можете держать в руке.",
"deathnobeer": "Когда вы теряете последнее очко жизни и у вас нет пива 🍺️ в руке, вы умираете. \nВаши карты сбрасываются, и ваша роль раскрывается всем.",
"discard": "Сбросить",
"distance": "Расстояние",
"distancecalc": "Расстояние автоматически рассчитывается игрой и соответствует минимальному расстоянию между игроками слева и справа.",
"drawinstructions": "Чтобы взять карты, вам нужно нажать на колоду, когда вы видите эту анимацию.",
"drawthecards": "Возьмите карты",
"endgame": "Конец игры",
"endgameconditions": "Игра заканчивается, когда выполняется одно из следующих условий:",
"endgamesheriffwin": "Все бандиты 🐺️ и ренегаты 🦅️ мертвы. \nВ этом случае шериф ⭐️ и помощники 🎖️ выигрывают.",
"endgameshriffdeath": "Шериф ⭐️ умирает. \nЕсли ренегат 🦅️ - последний оставшийся в живых игрок, он выигрывает, иначе выигрывают бандиты.",
"endingturn": "Когда вы закончили играть свои карты, то есть, когда вы не хотите или не можете играть больше карт, вы должны сбросить карты, превышающие ваше текущее количество жизней.\n\nЗатем вы передаете ход следующему игроку, нажав на конец хода.",
"equipment": "ОБОРУДОВАНИЕ",
"justoneweapon": "Вы можете иметь только одно оружие экипировано.",
"maxtwocardsequip": "Вы не можете иметь 2 карты с одинаковым названием экипированы.",
"outlawreward": "Кто убьет бандита 🐺️ берет 3 карты из колоды (другие бандиты тоже 🐺️).",
"playerdeath": "Смерть игрока",
"playingcards": "Играйте карты",
"playingdmg": "Вы можете играть свои карты для себя или для нанесения вреда другим игрокам, пытаясь их устранить.",
"playingduringturn": "Вы можете играть карты только в свой ход. Чтобы играть карты, нажмите на карты из вашей руки.\nЗа исключением карт, используемых как ответ, таких как Промах 😅️.",
"playingifyouwant": "Вы не обязаны играть карты.",
"playlimit": "Существуют только 3 ограничения:",
"playonlyonebang": "Вы можете играть только 1 Bang! \nза ход (относится только к картам, названным Bang!)",
"rewardspen": "Наказания и награды",
"roles": "Роли",
"sheriffkillsvice": "Если шериф ⭐️ убивает помощника, он теряет все карты в руке и в игре перед ним.",
"thecards": "Карты",
"title": "Как играть",
"turndiscard": "Сбросьте лишние карты",
"turndraw": "Возьмите 2 карты",
"turnplay": "Играйте любое количество карт",
"turns": "Ходы",
"turnstart": "Всегда начинается с шерифа ⭐️, и игра продолжается по часовой стрелке, ходы делятся на 3 фазы.",
"weapon": "ОРУЖИЕ",
"renegade": "Ренегат",
"vice": "Помощник",
"outlaw": "Бандит",
"sheriff": "Шериф",
"allcharacters": "Все персонажи",
"gotoallcharacters": "Перейти ко всем персонажам",
"gotocards": "Перейти к картам",
"gotohighnoon": "Перейти к Полдню",
"gotofoc": "Перейти к Горсти Карт",
"gotogoldrush": "Перейти к Золотой Лихорадке",
"highnooncards": "Полдень - Карты Событий",
"foccards": "Горсть Карт - Карты Событий",
"goldrushcards": "Карты Золотой Лихорадки",
"valleyofshadowscards": "Карты Долины Теней"
},
"theme": {
"sepia": "Сепия",
"light": "Светлый",
"dark": "Темный",
"grayscale": "Черно-белый",
"black": "Черный"
}
}

View File

@ -1,34 +1,47 @@
import Vue from 'vue'
import App from './App.vue'
import { registerSW } from 'virtual:pwa-register'
registerSW({ immediate: true })
Vue.config.productionTip = false
import VueSocketIO from 'vue-socket.io'
Vue.use(new VueSocketIO({
debug: Vue.config.devtools,
connection: Vue.config.devtools ? `http://${window.location.hostname}:5001` : window.location.origin,
}))
import VueSocketIO from 'bang-vue-socket.io'
if (window.localStorage.getItem('connect-dev')) {
Vue.use(new VueSocketIO({
debug: true,
connection: window.localStorage.getItem('connect-dev'),
}))
} else {
Vue.use(new VueSocketIO({
debug: Vue.config.devtools,
connection: (Vue.config.devtools) ? `http://${window.location.hostname}:5001` : window.location.origin,
}))
}
import PrettyCheckbox from 'pretty-checkbox-vue';
Vue.use(PrettyCheckbox)
import VueClipboard from 'vue-clipboard2'
Vue.use(VueClipboard)
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
import { languages, defaultLocale } from './i18n';
import { languages, defaultLocale, fallbackLocale } from './i18n';
import router from './router'
const messages = Object.assign(languages)
const i18n = new VueI18n({
locale: defaultLocale,
messages
messages,
fallbackLocale: fallbackLocale
})
import wb from "./registerServiceWorker";
Vue.prototype.$workbox = wb;
new Vue({
i18n,
router,

View File

@ -1,15 +0,0 @@
import { Workbox } from 'workbox-window';
if ('serviceWorker' in navigator) {
const wb = new Workbox('service-worker.js');
wb.addEventListener('installed', event => {
if (event.isUpdate) {
if (confirm(`Update available. Click OK to update`)) {
window.location.reload();
}
}
});
wb.register();
}

View File

@ -12,7 +12,12 @@ const routes = [
{
path: '/help',
name: 'Help',
component: () => import(/* webpackChunkName: "helep" */ '../components/Help.vue')
component: () => import(/* webpackChunkName: "help" */ '../components/Help.vue')
},
{
path: '/status',
name: 'Status',
component: () => import(/* webpackChunkName: "status" */ '../components/Status.vue')
},
{
path: '/',
@ -22,8 +27,8 @@ const routes = [
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
mode: import.meta.env.NODE_ENV === "development" ? 'hash' : 'history',
base: import.meta.env.BASE_URL,
routes
})

View File

@ -0,0 +1,9 @@
export const emojiMap = {
'dodge_city': '🐄',
'gold_rush': '🤑',
'high_noon': '🔥',
'fistful_of_cards': '🎴',
'the_valley_of_shadows': '👻',
'wild_west_show': '🎪',
'train_robbery': '🚂',
}

View File

@ -0,0 +1,46 @@
export const expansionsMap = {
'dodge_city': {
name: 'Dodge City',
icon: '🐄',
back: true,
expansion: 'dodge-city',
},
'fistful_of_cards': {
name: 'Fistful of Cards',
icon: '🎴',
back: true,
expansion: 'fistful-of-cards',
},
'high_noon': {
name: 'High Noon',
icon: '🔥',
back: true,
expansion: 'high-noon',
},
'gold_rush': {
name: 'Gold Rush',
icon: '🤑',
back: true,
expansion: 'gold-rush',
},
'the_valley_of_shadows': {
name: 'The Valley of Shadows',
icon: '👻',
back: true,
expansion: 'the-valley-of-shadows',
},
'wild_west_show': {
name: 'Wild West Show',
icon: '🎪',
back: true,
expansion: 'wild-west-show',
status: 'beta',
},
'train_robbery': {
name: 'The Great Train Robbery',
icon: '🚂',
back: true,
expansion: 'train-roobbery',
status: 'wip',
}
}

26
frontend/vite.config.js Normal file
View File

@ -0,0 +1,26 @@
import { defineConfig } from "vite";
// import vue from '@vitejs/plugin-vue' // vue 3
import { createVuePlugin as vue } from "vite-plugin-vue2"; //vue 2
import { createHtmlPlugin } from 'vite-plugin-html'
import { VitePWA } from 'vite-plugin-pwa'
const path = require("path");
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VitePWA({ registerType: 'autoUpdate' }),
createHtmlPlugin({
minify: true,
inject: {
data: {}
}
}),
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});

View File

@ -1,19 +1,18 @@
const { GenerateSW } = require("workbox-webpack-plugin");
module.exports = {
publicPath: "./",
pwa: {
name: 'PewPew!',
name: 'Bang!',
appleMobileWebAppCache: "yes",
manifestOptions: {
display: 'standalone',
},
workboxPluginMode: 'GenerateSW',
workboxOptions: {
navigateFallback: '/index.html',
cleanupOutdatedCaches: true,
}
},
configureWebpack: {
plugins: [new GenerateSW({
clientsClaim: true,
skipWaiting: true,
navigateFallback: 'index.html',
})],
output: {
crossOriginLoading: 'anonymous'
},

Some files were not shown because too many files have changed in this diff Show More