From 79ff6d7da71c5baa76b11bd2b04e2302a589b605 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 27 Jul 2020 03:06:25 -0500 Subject: [PATCH 01/74] Docker rough draft works Created a docker-compose script with 2 containers, one for the app/web, and one for the db. This will in the future ideally be split into 3, one each for app/db/web, but baby steps. Committing before I accidentally break it again. --- .gitignore | 15 + gemp-lotr/docker/Dockerfile | 37 ++ gemp-lotr/docker/conf2.txt | 481 +++++++++++++++ gemp-lotr/docker/docker-compose.yml | 111 ++++ gemp-lotr/docker/gemp_app.Dockerfile | 292 +++++++++ gemp-lotr/docker/gemp_db.Dockerfile | 4 + gemp-lotr/docker/gemp_web.Dockerfile | 15 + gemp-lotr/docker/httpd.conf | 553 ++++++++++++++++++ .../src/main/resources/gemp-lotr.properties | 11 +- 9 files changed, 1514 insertions(+), 5 deletions(-) create mode 100644 .gitignore create mode 100644 gemp-lotr/docker/Dockerfile create mode 100644 gemp-lotr/docker/conf2.txt create mode 100644 gemp-lotr/docker/docker-compose.yml create mode 100644 gemp-lotr/docker/gemp_app.Dockerfile create mode 100644 gemp-lotr/docker/gemp_db.Dockerfile create mode 100644 gemp-lotr/docker/gemp_web.Dockerfile create mode 100644 gemp-lotr/docker/httpd.conf diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..8ede39039 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +database/ +replay/ +replays/ \ No newline at end of file diff --git a/gemp-lotr/docker/Dockerfile b/gemp-lotr/docker/Dockerfile new file mode 100644 index 000000000..e968a83c0 --- /dev/null +++ b/gemp-lotr/docker/Dockerfile @@ -0,0 +1,37 @@ +#FROM store/oracle/jdk:11 AS Java +# copy files manually from the FROM statement image into the new container +FROM maven AS MavenJavaBuildTools +#FROM mariadb AS MariaDB +#FROM httpd AS ApacheWebServer + +ENV LANG en_US.UTF-8 + +ENV JAVA_HOME /usr/java/openjdk-14 +ENV PATH $JAVA_HOME/bin:$PATH +ENV JAVA_VERSION 14.0.2 + +ENV MAVEN_HOME /usr/share/maven +ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" + +WORKDIR /usr/java/ +COPY ./openjdk-14 /usr/java/openjdk-14 +#RUN apt-get update && apt-get -y install git + +#WORKDIR /etc/ + +#RUN git clone https://github.com/MarcinSc/gemp-lotr.git && \ + # The github files are all nested way too deep + #cp -R /etc/gemp-lotr/gemp-lotr/* /etc/gemp-lotr && \ + #rm -rf /etc/gemp-lotr/gemp-lotr/ + + +#WORKDIR /etc/gemp-lotr + +CMD ["/bin/bash"] +#"/bin/bash" +#ENTRYPOINT ["/bin/bash"] + +#ENV JAVA_HOME /usr/java/openjdk-14 +# 1. Install tools that are needed to build your application. +# 2. Install dependencies, libraries and packages. +# 3. Build your application. diff --git a/gemp-lotr/docker/conf2.txt b/gemp-lotr/docker/conf2.txt new file mode 100644 index 000000000..f36a3ac5d --- /dev/null +++ b/gemp-lotr/docker/conf2.txt @@ -0,0 +1,481 @@ +# +# This is the main Apache HTTP server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information. +# In particular, see +# +# for a discussion of each configuration directive. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "logs/access_log" +# with ServerRoot set to "/usr/local/apache2" will be interpreted by the +# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" +# will be interpreted as '/logs/access_log'. + +# +# ServerTokens +# This directive configures what you return as the Server HTTP response +# Header. The default is 'Full' which sends information about the OS-Type +# and compiled in modules. +# Set to one of: Full | OS | Minor | Minimal | Major | Prod +# where Full conveys the most information, and Prod the least. +# +ServerTokens OS + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# Do not add a slash at the end of the directory path. If you point +# ServerRoot at a non-local disk, be sure to specify a local disk on the +# Mutex directive, if file-based mutexes are used. If you wish to share the +# same ServerRoot for multiple httpd daemons, you will need to change at +# least PidFile. +# +ServerRoot /var/www + +# +# Mutex: Allows you to set the mutex mechanism and mutex file directory +# for individual mutexes, or change the global defaults +# +# Uncomment and change the directory if mutexes are file-based and the default +# mutex file directory is not on a local disk or is not appropriate for some +# other reason. +# +# Mutex default:/run/apache2 + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, instead of the default. See also the +# directive. +# +# Change this to Listen on specific IP addresses as shown below to +# prevent Apache from glomming onto all bound IP addresses. +# +#Listen 12.34.56.78:80 +Listen 80 + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Statically compiled modules (those listed by `httpd -l') do not need +# to be loaded here. +# +# Example: +# LoadModule foo_module modules/mod_foo.so +# +#LoadModule mpm_event_module modules/mod_mpm_event.so +LoadModule mpm_prefork_module modules/mod_mpm_prefork.so +#LoadModule mpm_worker_module modules/mod_mpm_worker.so +LoadModule authn_file_module modules/mod_authn_file.so +#LoadModule authn_dbm_module modules/mod_authn_dbm.so +#LoadModule authn_anon_module modules/mod_authn_anon.so +#LoadModule authn_dbd_module modules/mod_authn_dbd.so +#LoadModule authn_socache_module modules/mod_authn_socache.so +LoadModule authn_core_module modules/mod_authn_core.so +LoadModule authz_host_module modules/mod_authz_host.so +LoadModule authz_groupfile_module modules/mod_authz_groupfile.so +LoadModule authz_user_module modules/mod_authz_user.so +#LoadModule authz_dbm_module modules/mod_authz_dbm.so +#LoadModule authz_owner_module modules/mod_authz_owner.so +#LoadModule authz_dbd_module modules/mod_authz_dbd.so +LoadModule authz_core_module modules/mod_authz_core.so +LoadModule access_compat_module modules/mod_access_compat.so +LoadModule auth_basic_module modules/mod_auth_basic.so +#LoadModule auth_form_module modules/mod_auth_form.so +#LoadModule auth_digest_module modules/mod_auth_digest.so +#LoadModule allowmethods_module modules/mod_allowmethods.so +#LoadModule file_cache_module modules/mod_file_cache.so +#LoadModule cache_module modules/mod_cache.so +#LoadModule cache_disk_module modules/mod_cache_disk.so +#LoadModule cache_socache_module modules/mod_cache_socache.so +#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so +#LoadModule socache_dbm_module modules/mod_socache_dbm.so +#LoadModule socache_memcache_module modules/mod_socache_memcache.so +#LoadModule socache_redis_module modules/mod_socache_redis.so +#LoadModule watchdog_module modules/mod_watchdog.so +#LoadModule macro_module modules/mod_macro.so +#LoadModule dbd_module modules/mod_dbd.so +#LoadModule dumpio_module modules/mod_dumpio.so +#LoadModule echo_module modules/mod_echo.so +#LoadModule buffer_module modules/mod_buffer.so +#LoadModule data_module modules/mod_data.so +#LoadModule ratelimit_module modules/mod_ratelimit.so +LoadModule reqtimeout_module modules/mod_reqtimeout.so +#LoadModule ext_filter_module modules/mod_ext_filter.so +#LoadModule request_module modules/mod_request.so +#LoadModule include_module modules/mod_include.so +LoadModule filter_module modules/mod_filter.so +#LoadModule reflector_module modules/mod_reflector.so +#LoadModule substitute_module modules/mod_substitute.so +#LoadModule sed_module modules/mod_sed.so +#LoadModule charset_lite_module modules/mod_charset_lite.so +#LoadModule deflate_module modules/mod_deflate.so +LoadModule mime_module modules/mod_mime.so +LoadModule log_config_module modules/mod_log_config.so +#LoadModule log_debug_module modules/mod_log_debug.so +#LoadModule log_forensic_module modules/mod_log_forensic.so +#LoadModule logio_module modules/mod_logio.so +LoadModule env_module modules/mod_env.so +#LoadModule mime_magic_module modules/mod_mime_magic.so +#LoadModule expires_module modules/mod_expires.so +LoadModule headers_module modules/mod_headers.so +#LoadModule usertrack_module modules/mod_usertrack.so +#LoadModule unique_id_module modules/mod_unique_id.so +LoadModule setenvif_module modules/mod_setenvif.so +LoadModule version_module modules/mod_version.so +#LoadModule remoteip_module modules/mod_remoteip.so +#LoadModule session_module modules/mod_session.so +#LoadModule session_cookie_module modules/mod_session_cookie.so +#LoadModule session_crypto_module modules/mod_session_crypto.so +#LoadModule session_dbd_module modules/mod_session_dbd.so +#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so +#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so +#LoadModule dialup_module modules/mod_dialup.so +#LoadModule http2_module modules/mod_http2.so +LoadModule unixd_module modules/mod_unixd.so +#LoadModule heartbeat_module modules/mod_heartbeat.so +#LoadModule heartmonitor_module modules/mod_heartmonitor.so +LoadModule status_module modules/mod_status.so +LoadModule autoindex_module modules/mod_autoindex.so +#LoadModule asis_module modules/mod_asis.so +#LoadModule info_module modules/mod_info.so +#LoadModule suexec_module modules/mod_suexec.so + + #LoadModule cgid_module modules/mod_cgid.so + + + #LoadModule cgi_module modules/mod_cgi.so + +#LoadModule vhost_alias_module modules/mod_vhost_alias.so +#LoadModule negotiation_module modules/mod_negotiation.so +LoadModule dir_module modules/mod_dir.so +#LoadModule actions_module modules/mod_actions.so +#LoadModule speling_module modules/mod_speling.so +#LoadModule userdir_module modules/mod_userdir.so +LoadModule alias_module modules/mod_alias.so +#LoadModule rewrite_module modules/mod_rewrite.so + +LoadModule negotiation_module modules/mod_negotiation.so + + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. +# +# User/Group: The name (or #number) of the user/group to run httpd as. +# It is usually good practice to create a dedicated user and group for +# running httpd, as with most system services. +# +User apache +Group apache + + + +# 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. e.g. admin@your-domain.com +# +ServerAdmin you@example.com + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (internal error documents, FTP directory +# listings, mod_status and mod_info output etc., but not CGI generated +# documents or custom error documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of: On | Off | EMail +# +ServerSignature On + +# +# ServerName gives the name and port that the server uses to identify itself. +# This can often be determined automatically, but we recommend you specify +# it explicitly to prevent problems during startup. +# +# If your host doesn't have a registered DNS name, enter its IP address here. +# +#ServerName www.example.com:80 + +# +# Deny access to the entirety of your server's filesystem. You must +# explicitly permit access to web content directories in other +# blocks below. +# + + AllowOverride none + Require all denied + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "/var/www/localhost/htdocs" + + # + # Possible values for the Options directive are "None", "All", + # or any combination of: + # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews + # + # Note that "MultiViews" must be named *explicitly* --- "Options All" + # doesn't give it to you. + # + # The Options directive is both complicated and important. Please see + # http://httpd.apache.org/docs/2.4/mod/core.html#options + # for more information. + # + Options Indexes FollowSymLinks + + # + # AllowOverride controls what directives may be placed in .htaccess files. + # It can be "All", "None", or any combination of the keywords: + # AllowOverride FileInfo AuthConfig Limit + # + AllowOverride None + + # + # Controls who can get stuff from this server. + # + Require all granted + + +# +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# + + DirectoryIndex index.html + + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog logs/error.log + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + + + # + # The following directives define some format nicknames for use with + # a CustomLog directive (see below). + # + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + # You need to enable mod_logio.c to use %I and %O + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + # + # The location and format of the access logfile (Common Logfile Format). + # If you do not define any access logfiles within a + # container, they will be logged here. Contrariwise, if you *do* + # define per- access logfiles, transactions will be + # logged therein and *not* in this file. + # + #CustomLog logs/access.log common + + # + # If you prefer a logfile with access, agent, and referer information + # (Combined Logfile Format) you can use the following directive. + # + CustomLog logs/access.log combined + + + + # + # Redirect: Allows you to tell clients about documents that used to + # exist in your server's namespace, but do not anymore. The client + # will make a new request for the document at its new location. + # Example: + # Redirect permanent /foo http://www.example.com/bar + + # + # Alias: Maps web paths into filesystem paths and is used to + # access content that does not live under the DocumentRoot. + # Example: + # Alias /webpath /full/filesystem/path + # + # If you include a trailing / on /webpath then the server will + # require it to be present in the URL. You will also likely + # need to provide a section to allow access to + # the filesystem path. + + # + # ScriptAlias: This controls which directories contain server scripts. + # ScriptAliases are essentially the same as Aliases, except that + # documents in the target directory are treated as applications and + # run by the server when requested rather than as documents sent to the + # client. The same rules about trailing "/" apply to ScriptAlias + # directives as to Alias. + # + ScriptAlias /cgi-bin/ "/var/www/localhost/cgi-bin/" + + + + + # + # ScriptSock: On threaded servers, designate the path to the UNIX + # socket used to communicate with the CGI daemon of mod_cgid. + # + #Scriptsock cgisock + + +# +# "/var/www/localhost/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# + + AllowOverride None + Options None + Require all granted + + + + # + # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied + # backend servers which have lingering "httpoxy" defects. + # 'Proxy' request header is undefined by the IETF, not listed by IANA + # + RequestHeader unset Proxy early + + + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + TypesConfig /etc/apache2/mime.types + + # + # AddType allows you to add to or override the MIME configuration + # file specified in TypesConfig for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # For type maps (negotiated resources): + #AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + #AddType text/html .shtml + #AddOutputFilter INCLUDES .shtml + + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type. The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# + + MIMEMagicFile /etc/apache2/magic + + +# +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html +# + +# +# MaxRanges: Maximum number of Ranges in a request before +# returning the entire resource, or one of the special +# values 'default', 'none' or 'unlimited'. +# Default setting is to accept 200 Ranges. +#MaxRanges unlimited + +# +# EnableMMAP and EnableSendfile: On systems that support it, +# memory-mapping or the sendfile syscall may be used to deliver +# files. This usually improves server performance, but must +# be turned off when serving from networked-mounted +# filesystems or if support for these functions is otherwise +# broken on your system. +# Defaults: EnableMMAP On, EnableSendfile Off +# +#EnableMMAP off +#EnableSendfile on + +# Load config files from the config directory "/etc/apache2/conf.d". +# +IncludeOptional /etc/apache2/conf.d/*.conf \ No newline at end of file diff --git a/gemp-lotr/docker/docker-compose.yml b/gemp-lotr/docker/docker-compose.yml new file mode 100644 index 000000000..11da8a043 --- /dev/null +++ b/gemp-lotr/docker/docker-compose.yml @@ -0,0 +1,111 @@ +version: "3.4" + +services: + build: + container_name: gemp_app + build: + context: . + dockerfile: gemp_app.Dockerfile + image: gemp_app + expose: + - "80" + - "8080" + restart: always + ports: + # target means in the container + - target: 80 + # published is what's on the host machine + published: 1337 + #- "8080:108080" + volumes: + # - type: bind + # source: X:/Projects/gemp-lotr/replays + # target: /etc/gemp + - type: bind + source: X:/Projects/gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web + target: /etc/gemp-lotr/web + - type: bind + source: X:/Projects/gemp-lotr/gemp-lotr + target: /etc/gemp-lotr + - type: bind + source: X:/Projects/gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web + target: /var/www/localhost/htdocs/gemp-lotr #/etc/apache2/htdocs/gemp-lotr + networks: + gemp_net: + ipv4_address: 172.28.1.1 + tty: true + #command: /usr/sbin/httpd -D FOREGROUND + command: nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & + + + db: + #image: mariadb + container_name: gemp_db + build: + context: .. + dockerfile: docker/gemp_db.Dockerfile + image: gemp_db + ports: + # target means in the container + - target: 3306 + # published is what's on the host machine + published: 3307 + restart: always + volumes: + - type: bind + source: X:/Projects/gemp-lotr/database + target: /var/lib/mysql + networks: + gemp_net: + ipv4_address: 172.28.1.2 + environment: + MYSQL_ROOT_PASSWORD: rootpass + MYSQL_DATABASE: gemp_db + MYSQL_USER: gempuser + MYSQL_PASSWORD: gemppassword + + + # web: + # container_name: gemp_web + # build: + # context: . + # dockerfile: gemp_web.Dockerfile + # image: gemp_web + # expose: + # - "80" + # - "8080" + # ports: + # # target means in the container + # - target: 80 + # # published is what's on the host machine + # published: 1337 + # #- "8080:108080" + # volumes: + # - type: bind + # source: X:/Projects/gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web + # target: /usr/local/apache2/htdocs/gemp-lotr + # networks: + # gemp_net: + # ipv4_address: 172.28.1.3 + # extra_hosts: + # # by overridding localhost to go to the app container, we avoid issues with AJAX + # - "localhost:172.28.1.1" + + # wiki: + # container_name: lotr_wiki + # image: mediawiki + # ports: + # # target means in the container + # - target: 80 + # # published is what's on the host machine + # published: 1338 + # volumes: + # - type: bind + # source: X:/Projects/gemp-lotr/gemp-lotr/docker/wiki + # target: /usr/wiki +networks: + gemp_net: + ipam: + driver: default + config: + - subnet: 172.28.0.0/16 \ No newline at end of file diff --git a/gemp-lotr/docker/gemp_app.Dockerfile b/gemp-lotr/docker/gemp_app.Dockerfile new file mode 100644 index 000000000..4a5b9554d --- /dev/null +++ b/gemp-lotr/docker/gemp_app.Dockerfile @@ -0,0 +1,292 @@ +#FROM store/oracle/jdk:11 AS Java +# copy files manually from the FROM statement image into the new container +#FROM maven AS JavaBuild +#FROM mariadb AS MariaDB +#FROM httpd AS ApacheWebServer + + + + +##################################################################### +# The following is pulled from the openjdk dockerfile: +# https://github.com/docker-library/openjdk/blob/29c17de6c8c0df6304d0c80f569deea1d4b6a23e/14/jdk/oracle/Dockerfile +##################################################################### + + +#RUN apt-get update +# +#RUN set -eux; \ + #apt-get install -y \ + #gzip \ + #curl \ + #tar \ +# +## jlink --strip-debug on 13+ needs objcopy: https://github.com/docker-library/openjdk/issues/351 +## Error: java.io.IOException: Cannot run program "objcopy": error=2, No such file or directory + #binutils \ +## java.lang.UnsatisfiedLinkError: /usr/java/openjdk-12/lib/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory +## https://github.com/docker-library/openjdk/pull/235#issuecomment-424466077 + #libfreetype6 fontconfig \ + #; \ + #rm -rf /var/cache/yum +# +## Default to UTF-8 file.encoding +#ENV LANG en_US.UTF-8 +# +#ENV JAVA_HOME /usr/java/openjdk-14 +#ENV PATH $JAVA_HOME/bin:$PATH +# +## https://jdk.java.net/ +## > Java Development Kit builds, from Oracle +#ENV JAVA_VERSION 14.0.2 +# +#RUN set -eux; \ +## amd64 + #downloadUrl=https://download.java.net/java/GA/jdk14.0.2/205943a0976c4ed48cb16f1043c5c647/12/GPL/openjdk-14.0.2_linux-x64_bin.tar.gz; \ + #downloadSha256=91310200f072045dc6cef2c8c23e7e6387b37c46e9de49623ce0fa461a24623d; \ +# + #curl -fkL -o /openjdk.tgz "$downloadUrl"; \ + #echo "$downloadSha256 */openjdk.tgz" | sha256sum -c -; \ +# + #mkdir -p "$JAVA_HOME"; \ + #tar --extract --file /openjdk.tgz --directory "$JAVA_HOME" --strip-components 1; \ + #rm /openjdk.tgz; \ +# +## https://github.com/oracle/docker-images/blob/a56e0d1ed968ff669d2e2ba8a1483d0f3acc80c0/OracleJava/java-8/Dockerfile#L17-L19 + #ln -sfT "$JAVA_HOME" /usr/java/default; \ + #ln -sfT "$JAVA_HOME" /usr/java/latest; \ + #for bin in "$JAVA_HOME/bin/"*; do \ + #base="$(basename "$bin")"; \ + #[ ! -e "/usr/bin/$base" ]; \ + #update-alternatives --install "/usr/bin/$base" "$base" "$bin" 20000; \ + #done; \ +# +## https://github.com/docker-library/openjdk/issues/212#issuecomment-420979840 +## https://openjdk.java.net/jeps/341 + #java -Xshare:dump; \ +# +## see "update-ca-trust" script which creates/maintains this cacerts bundle + #rm -rf "$JAVA_HOME/lib/security/cacerts"; \ + #ln -sT /etc/pki/ca-trust/extracted/java/cacerts "$JAVA_HOME/lib/security/cacerts"; \ +# +## basic smoke test + #java --version; \ + #javac --version +# +## https://docs.oracle.com/javase/10/tools/jshell.htm +## https://docs.oracle.com/javase/10/jshell/ +## https://en.wikipedia.org/wiki/JShell +##CMD ["jshell"] +# +###################################################################### +# +# +# +###################################################################### +## The following is pulled from the maven dockerfile: +## https://github.com/carlossg/docker-maven/blob/26ba49149787c85b9c51222b47c00879b2a0afde/openjdk-14/Dockerfile +###################################################################### +# +#ARG MAVEN_VERSION=3.6.3 +#ARG USER_HOME_DIR="/root" +#ARG SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0 +#ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries +# +#RUN mkdir -p /usr/share/maven /usr/share/maven/ref \ + #&& curl -fsSkL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \ + #&& echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c - \ + #&& tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \ + #&& rm -f /tmp/apache-maven.tar.gz \ + #&& ln -s /usr/share/maven/bin/mvn /usr/bin/mvn +# +#ENV MAVEN_HOME /usr/share/maven +#ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" +# +##COPY mvn-entrypoint.sh /usr/local/bin/mvn-entrypoint.sh +##COPY settings-docker.xml /usr/share/maven/ref/ +# +###################################################################### + + +FROM alpine + +RUN apk update; \ + apk update --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing; \ + apk add --no-cache procps; \ + apk add --no-cache net-tools; \ + apk add --no-cache iputils; \ + apk add --no-cache bash; \ + apk add --no-cache util-linux; \ + apk add --no-cache dpkg; \ + apk add --no-cache gzip; \ + apk add --no-cache curl; \ + apk add --no-cache tar; \ + apk add --no-cache binutils; \ + apk add --no-cache freetype; \ + apk add --no-cache fontconfig; \ + apk add --no-cache openjdk14-jdk --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing; + + + +##################################################################### +# The following is pulled from the maven dockerfile: +# https://github.com/carlossg/docker-maven/blob/26ba49149787c85b9c51222b47c00879b2a0afde/openjdk-14/Dockerfile +##################################################################### + +ARG MAVEN_VERSION=3.6.3 +ARG USER_HOME_DIR="/root" +ARG SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0 +ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries + +RUN mkdir -p /usr/share/maven /usr/share/maven/ref \ + && curl -fsSkL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \ + && echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c - \ + && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \ + && rm -f /tmp/apache-maven.tar.gz \ + && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn + +ENV MAVEN_HOME /usr/share/maven +ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" + +#COPY mvn-entrypoint.sh /usr/local/bin/mvn-entrypoint.sh +#COPY settings-docker.xml /usr/share/maven/ref/ + +##################################################################### + + +RUN apk add --no-cache openrc; \ + apk add --no-cache apache2 + +RUN nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & + + # java prereqs + #gzip \ + #curl \ + #tar \ + #libfreetype6 fontconfig \ + #openjdk14 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community + + # apache prereqs + #bzip2 \ + #ca-certificates \ + #dirmngr \ + #dpkg-dev \ + #gcc \ + #gnupg \ + #libbrotli-dev \ + #libcurl4-openssl-dev \ + #libjansson-dev \ + #liblua5.2-dev \ + #libnghttp2-dev \ + #libpcre3-dev \ + #libssl-dev \ + #libxml2-dev \ + #make \ + #wget \ + #zlib1g-dev + + +##################################################################### +# The following is pulled from the openjdk dockerfile: +# https://github.com/docker-library/openjdk/blob/29c17de6c8c0df6304d0c80f569deea1d4b6a23e/14/jdk/oracle/Dockerfile +##################################################################### + + +## Default to UTF-8 file.encoding +#ENV LANG en_US.UTF-8 +# +#ENV JAVA_HOME /usr/java/openjdk-14 +#ENV PATH $JAVA_HOME/bin:$PATH +# +## https://jdk.java.net/ +## > Java Development Kit builds, from Oracle +#ENV JAVA_VERSION 14.0.2 +# +#RUN set -eux; \ +## amd64 + #downloadUrl=https://download.java.net/java/GA/jdk14.0.2/205943a0976c4ed48cb16f1043c5c647/12/GPL/openjdk-14.0.2_linux-x64_bin.tar.gz; \ + #downloadSha256=91310200f072045dc6cef2c8c23e7e6387b37c46e9de49623ce0fa461a24623d; \ +# + #curl -fkL -o /openjdk.tgz "$downloadUrl"; \ + #echo "$downloadSha256 */openjdk.tgz" | sha256sum -c -; \ +# + #mkdir -p "$JAVA_HOME"; \ + #tar --extract --file /openjdk.tgz --directory "$JAVA_HOME" --strip-components 1; \ + #rm /openjdk.tgz; + +## https://github.com/oracle/docker-images/blob/a56e0d1ed968ff669d2e2ba8a1483d0f3acc80c0/OracleJava/java-8/Dockerfile#L17-L19 + #ln -sfT "$JAVA_HOME" /usr/java/default; \ + #ln -sfT "$JAVA_HOME" /usr/java/latest; \ + #for bin in "$JAVA_HOME/bin/"*; do \ + #base="$(basename "$bin")"; \ + #[ ! -e "/usr/bin/$base" ]; \ + #update-alternatives --install "/usr/bin/$base" "$base" "$bin" 20000; \ + #done; \ +# + +# https://github.com/docker-library/openjdk/issues/212#issuecomment-420979840 +# https://openjdk.java.net/jeps/341 + #java -Xshare:dump; \ + +# see "update-ca-trust" script which creates/maintains this cacerts bundle + #rm -rf "$JAVA_HOME/lib/security/cacerts"; \ + #ln -sT /etc/pki/ca-trust/extracted/java/cacerts "$JAVA_HOME/lib/security/cacerts"; + +# basic smoke test + #java --version; \ + #javac --version + +# https://docs.oracle.com/javase/10/tools/jshell.htm +# https://docs.oracle.com/javase/10/jshell/ +# https://en.wikipedia.org/wiki/JShell +#CMD ["jshell"] + +##################################################################### + + + + + + + +#RUN yum install -y telnet && \ + #yum install -y iputils +# +# +#RUN yum install -y socat && \ + #socat TCP-LISTEN:3306,fork TCP:db:3306 & +#RUN socat TCP-LISTEN:80,fork TCP:web:80 & +#RUN yum install -y websocat && \ + #websocat WS-LISTEN:8080,fork WS:web:8080 & + +#RUN apt-get install -y websocat && \ +# websocat WS-LISTEN:8080,fork WS:build:8080 & + + + + + +#WORKDIR /usr/java/ +#COPY ./openjdk-14 /usr/java/openjdk-14 +#RUN apt-get update && apt-get -y install git + +#WORKDIR /etc/ + +#RUN git clone https://github.com/MarcinSc/gemp-lotr.git && \ + # The github files are all nested way too deep + #cp -R /etc/gemp-lotr/gemp-lotr/* /etc/gemp-lotr && \ + #rm -rf /etc/gemp-lotr/gemp-lotr/ + + +#WORKDIR /etc/gemp-lotr + +#CMD java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & +#"/bin/bash" +#ENTRYPOINT ["/bin/bash"] + +#ENV JAVA_HOME /usr/java/openjdk-14 +# 1. Install tools that are needed to build your application. +# 2. Install dependencies, libraries and packages. +# 3. Build your application. + + diff --git a/gemp-lotr/docker/gemp_db.Dockerfile b/gemp-lotr/docker/gemp_db.Dockerfile new file mode 100644 index 000000000..b18d1f928 --- /dev/null +++ b/gemp-lotr/docker/gemp_db.Dockerfile @@ -0,0 +1,4 @@ +FROM mariadb AS MariaDB + +#COPY ./database_script.sql /etc/gemp/database_script.sql +COPY ./database_script.sql /docker-entrypoint-initdb.d diff --git a/gemp-lotr/docker/gemp_web.Dockerfile b/gemp-lotr/docker/gemp_web.Dockerfile new file mode 100644 index 000000000..d0cad1161 --- /dev/null +++ b/gemp-lotr/docker/gemp_web.Dockerfile @@ -0,0 +1,15 @@ +FROM httpd AS ApacheWebServer + +RUN apt-get install -y socat && \ + socat TCP-LISTEN:80,fork TCP:build:80 & +RUN apt-get install -y websocat && \ + websocat WS-LISTEN:8080,fork WS:build:8080 & +RUN apt-get update && \ + apt-get install -y watch && \ + apt-get install -y net-tools && \ + apt-get install -y iputils-ping && \ + apt-get install -y telnet + + + +COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf \ No newline at end of file diff --git a/gemp-lotr/docker/httpd.conf b/gemp-lotr/docker/httpd.conf new file mode 100644 index 000000000..7cf1dc3b6 --- /dev/null +++ b/gemp-lotr/docker/httpd.conf @@ -0,0 +1,553 @@ +# +# This is the main Apache HTTP server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information. +# In particular, see +# +# for a discussion of each configuration directive. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "logs/access_log" +# with ServerRoot set to "/usr/local/apache2" will be interpreted by the +# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" +# will be interpreted as '/logs/access_log'. + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# Do not add a slash at the end of the directory path. If you point +# ServerRoot at a non-local disk, be sure to specify a local disk on the +# Mutex directive, if file-based mutexes are used. If you wish to share the +# same ServerRoot for multiple httpd daemons, you will need to change at +# least PidFile. +# +ServerRoot "/usr/local/apache2" + +# +# Mutex: Allows you to set the mutex mechanism and mutex file directory +# for individual mutexes, or change the global defaults +# +# Uncomment and change the directory if mutexes are file-based and the default +# mutex file directory is not on a local disk or is not appropriate for some +# other reason. +# +# Mutex default:logs + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, instead of the default. See also the +# directive. +# +# Change this to Listen on specific IP addresses as shown below to +# prevent Apache from glomming onto all bound IP addresses. +# +#Listen 12.34.56.78:80 +Listen 80 + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Statically compiled modules (those listed by `httpd -l') do not need +# to be loaded here. +# +# Example: +# LoadModule foo_module modules/mod_foo.so +# +LoadModule mpm_event_module modules/mod_mpm_event.so +#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so +#LoadModule mpm_worker_module modules/mod_mpm_worker.so +LoadModule authn_file_module modules/mod_authn_file.so +#LoadModule authn_dbm_module modules/mod_authn_dbm.so +#LoadModule authn_anon_module modules/mod_authn_anon.so +#LoadModule authn_dbd_module modules/mod_authn_dbd.so +#LoadModule authn_socache_module modules/mod_authn_socache.so +LoadModule authn_core_module modules/mod_authn_core.so +LoadModule authz_host_module modules/mod_authz_host.so +LoadModule authz_groupfile_module modules/mod_authz_groupfile.so +LoadModule authz_user_module modules/mod_authz_user.so +#LoadModule authz_dbm_module modules/mod_authz_dbm.so +#LoadModule authz_owner_module modules/mod_authz_owner.so +#LoadModule authz_dbd_module modules/mod_authz_dbd.so +LoadModule authz_core_module modules/mod_authz_core.so +#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so +#LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so +LoadModule access_compat_module modules/mod_access_compat.so +LoadModule auth_basic_module modules/mod_auth_basic.so +#LoadModule auth_form_module modules/mod_auth_form.so +#LoadModule auth_digest_module modules/mod_auth_digest.so +#LoadModule allowmethods_module modules/mod_allowmethods.so +#LoadModule isapi_module modules/mod_isapi.so +#LoadModule file_cache_module modules/mod_file_cache.so +#LoadModule cache_module modules/mod_cache.so +#LoadModule cache_disk_module modules/mod_cache_disk.so +#LoadModule cache_socache_module modules/mod_cache_socache.so +#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so +#LoadModule socache_dbm_module modules/mod_socache_dbm.so +#LoadModule socache_memcache_module modules/mod_socache_memcache.so +#LoadModule socache_redis_module modules/mod_socache_redis.so +#LoadModule watchdog_module modules/mod_watchdog.so +#LoadModule macro_module modules/mod_macro.so +#LoadModule dbd_module modules/mod_dbd.so +#LoadModule bucketeer_module modules/mod_bucketeer.so +#LoadModule dumpio_module modules/mod_dumpio.so +#LoadModule echo_module modules/mod_echo.so +#LoadModule example_hooks_module modules/mod_example_hooks.so +#LoadModule case_filter_module modules/mod_case_filter.so +#LoadModule case_filter_in_module modules/mod_case_filter_in.so +#LoadModule example_ipc_module modules/mod_example_ipc.so +#LoadModule buffer_module modules/mod_buffer.so +#LoadModule data_module modules/mod_data.so +#LoadModule ratelimit_module modules/mod_ratelimit.so +LoadModule reqtimeout_module modules/mod_reqtimeout.so +#LoadModule ext_filter_module modules/mod_ext_filter.so +#LoadModule request_module modules/mod_request.so +#LoadModule include_module modules/mod_include.so +LoadModule filter_module modules/mod_filter.so +#LoadModule reflector_module modules/mod_reflector.so +#LoadModule substitute_module modules/mod_substitute.so +#LoadModule sed_module modules/mod_sed.so +#LoadModule charset_lite_module modules/mod_charset_lite.so +#LoadModule deflate_module modules/mod_deflate.so +#LoadModule xml2enc_module modules/mod_xml2enc.so +#LoadModule proxy_html_module modules/mod_proxy_html.so +#LoadModule brotli_module modules/mod_brotli.so +LoadModule mime_module modules/mod_mime.so +#LoadModule ldap_module modules/mod_ldap.so +LoadModule log_config_module modules/mod_log_config.so +#LoadModule log_debug_module modules/mod_log_debug.so +#LoadModule log_forensic_module modules/mod_log_forensic.so +#LoadModule logio_module modules/mod_logio.so +#LoadModule lua_module modules/mod_lua.so +LoadModule env_module modules/mod_env.so +#LoadModule mime_magic_module modules/mod_mime_magic.so +#LoadModule cern_meta_module modules/mod_cern_meta.so +#LoadModule expires_module modules/mod_expires.so +LoadModule headers_module modules/mod_headers.so +#LoadModule ident_module modules/mod_ident.so +#LoadModule usertrack_module modules/mod_usertrack.so +#LoadModule unique_id_module modules/mod_unique_id.so +LoadModule setenvif_module modules/mod_setenvif.so +LoadModule version_module modules/mod_version.so +#LoadModule remoteip_module modules/mod_remoteip.so +#LoadModule proxy_module modules/mod_proxy.so +#LoadModule proxy_connect_module modules/mod_proxy_connect.so +#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so +#LoadModule proxy_http_module modules/mod_proxy_http.so +#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so +#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so +#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so +#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so +#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so +#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so +#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so +#LoadModule proxy_express_module modules/mod_proxy_express.so +#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so +#LoadModule session_module modules/mod_session.so +#LoadModule session_cookie_module modules/mod_session_cookie.so +#LoadModule session_crypto_module modules/mod_session_crypto.so +#LoadModule session_dbd_module modules/mod_session_dbd.so +#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so +#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so +#LoadModule ssl_module modules/mod_ssl.so +#LoadModule optional_hook_export_module modules/mod_optional_hook_export.so +#LoadModule optional_hook_import_module modules/mod_optional_hook_import.so +#LoadModule optional_fn_import_module modules/mod_optional_fn_import.so +#LoadModule optional_fn_export_module modules/mod_optional_fn_export.so +#LoadModule dialup_module modules/mod_dialup.so +#LoadModule http2_module modules/mod_http2.so +#LoadModule proxy_http2_module modules/mod_proxy_http2.so +#LoadModule md_module modules/mod_md.so +#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so +#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so +#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so +#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so +LoadModule unixd_module modules/mod_unixd.so +#LoadModule heartbeat_module modules/mod_heartbeat.so +#LoadModule heartmonitor_module modules/mod_heartmonitor.so +#LoadModule dav_module modules/mod_dav.so +LoadModule status_module modules/mod_status.so +LoadModule autoindex_module modules/mod_autoindex.so +#LoadModule asis_module modules/mod_asis.so +#LoadModule info_module modules/mod_info.so +#LoadModule suexec_module modules/mod_suexec.so + + #LoadModule cgid_module modules/mod_cgid.so + + + #LoadModule cgi_module modules/mod_cgi.so + +#LoadModule dav_fs_module modules/mod_dav_fs.so +#LoadModule dav_lock_module modules/mod_dav_lock.so +#LoadModule vhost_alias_module modules/mod_vhost_alias.so +#LoadModule negotiation_module modules/mod_negotiation.so +LoadModule dir_module modules/mod_dir.so +#LoadModule imagemap_module modules/mod_imagemap.so +#LoadModule actions_module modules/mod_actions.so +#LoadModule speling_module modules/mod_speling.so +#LoadModule userdir_module modules/mod_userdir.so +LoadModule alias_module modules/mod_alias.so +#LoadModule rewrite_module modules/mod_rewrite.so + + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. +# +# User/Group: The name (or #number) of the user/group to run httpd as. +# It is usually good practice to create a dedicated user and group for +# running httpd, as with most system services. +# +User daemon +Group daemon + + + +# 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. e.g. admin@your-domain.com +# +ServerAdmin you@example.com + +# +# ServerName gives the name and port that the server uses to identify itself. +# This can often be determined automatically, but we recommend you specify +# it explicitly to prevent problems during startup. +# +# If your host doesn't have a registered DNS name, enter its IP address here. +# +#ServerName www.example.com:80 + +# +# Deny access to the entirety of your server's filesystem. You must +# explicitly permit access to web content directories in other +# blocks below. +# + + AllowOverride none + Require all denied + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "/usr/local/apache2/htdocs" + + # + # Possible values for the Options directive are "None", "All", + # or any combination of: + # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews + # + # Note that "MultiViews" must be named *explicitly* --- "Options All" + # doesn't give it to you. + # + # The Options directive is both complicated and important. Please see + # http://httpd.apache.org/docs/2.4/mod/core.html#options + # for more information. + # + Options Indexes FollowSymLinks + + # + # AllowOverride controls what directives may be placed in .htaccess files. + # It can be "All", "None", or any combination of the keywords: + # AllowOverride FileInfo AuthConfig Limit + # + AllowOverride None + + # + # Controls who can get stuff from this server. + # + Require all granted + + +# +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# + + DirectoryIndex index.html + + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog /proc/self/fd/2 + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + + + # + # The following directives define some format nicknames for use with + # a CustomLog directive (see below). + # + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + # You need to enable mod_logio.c to use %I and %O + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + # + # The location and format of the access logfile (Common Logfile Format). + # If you do not define any access logfiles within a + # container, they will be logged here. Contrariwise, if you *do* + # define per- access logfiles, transactions will be + # logged therein and *not* in this file. + # + CustomLog /proc/self/fd/1 common + + # + # If you prefer a logfile with access, agent, and referer information + # (Combined Logfile Format) you can use the following directive. + # + #CustomLog "logs/access_log" combined + + + + # + # Redirect: Allows you to tell clients about documents that used to + # exist in your server's namespace, but do not anymore. The client + # will make a new request for the document at its new location. + # Example: + # Redirect permanent /foo http://www.example.com/bar + + # + # Alias: Maps web paths into filesystem paths and is used to + # access content that does not live under the DocumentRoot. + # Example: + # Alias /webpath /full/filesystem/path + # + # If you include a trailing / on /webpath then the server will + # require it to be present in the URL. You will also likely + # need to provide a section to allow access to + # the filesystem path. + + # + # ScriptAlias: This controls which directories contain server scripts. + # ScriptAliases are essentially the same as Aliases, except that + # documents in the target directory are treated as applications and + # run by the server when requested rather than as documents sent to the + # client. The same rules about trailing "/" apply to ScriptAlias + # directives as to Alias. + # + ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/" + + + + + # + # ScriptSock: On threaded servers, designate the path to the UNIX + # socket used to communicate with the CGI daemon of mod_cgid. + # + #Scriptsock cgisock + + +# +# "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# + + AllowOverride None + Options None + Require all granted + + + + # + # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied + # backend servers which have lingering "httpoxy" defects. + # 'Proxy' request header is undefined by the IETF, not listed by IANA + # + RequestHeader unset Proxy early + + + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + TypesConfig conf/mime.types + + # + # AddType allows you to add to or override the MIME configuration + # file specified in TypesConfig for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # For type maps (negotiated resources): + #AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + #AddType text/html .shtml + #AddOutputFilter INCLUDES .shtml + + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type. The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# +#MIMEMagicFile conf/magic + +# +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html +# + +# +# MaxRanges: Maximum number of Ranges in a request before +# returning the entire resource, or one of the special +# values 'default', 'none' or 'unlimited'. +# Default setting is to accept 200 Ranges. +#MaxRanges unlimited + +# +# EnableMMAP and EnableSendfile: On systems that support it, +# memory-mapping or the sendfile syscall may be used to deliver +# files. This usually improves server performance, but must +# be turned off when serving from networked-mounted +# filesystems or if support for these functions is otherwise +# broken on your system. +# Defaults: EnableMMAP On, EnableSendfile Off +# +#EnableMMAP off +#EnableSendfile on + +# Supplemental configuration +# +# The configuration files in the conf/extra/ directory can be +# included to add extra features or to modify the default configuration of +# the server, or you may simply copy their contents here and change as +# necessary. + +# Server-pool management (MPM specific) +#Include conf/extra/httpd-mpm.conf + +# Multi-language error messages +#Include conf/extra/httpd-multilang-errordoc.conf + +# Fancy directory listings +#Include conf/extra/httpd-autoindex.conf + +# Language settings +#Include conf/extra/httpd-languages.conf + +# User home directories +#Include conf/extra/httpd-userdir.conf + +# Real-time info on requests and configuration +#Include conf/extra/httpd-info.conf + +# Virtual hosts +#Include conf/extra/httpd-vhosts.conf + +# Local access to the Apache HTTP Server Manual +#Include conf/extra/httpd-manual.conf + +# Distributed authoring and versioning (WebDAV) +#Include conf/extra/httpd-dav.conf + +# Various default settings +#Include conf/extra/httpd-default.conf + +# Configure mod_proxy_html to understand HTML4/XHTML1 + +Include conf/extra/proxy-html.conf + + +# Secure (SSL/TLS) connections +#Include conf/extra/httpd-ssl.conf +# +# Note: The following must must be present to support +# starting without SSL on platforms with no /dev/random equivalent +# but a statically compiled-in mod_ssl. +# + +SSLRandomSeed startup builtin +SSLRandomSeed connect builtin + + + +RedirectMatch "^/gemp-lotr-server/(.*)" "http://gemp_app/gemp-lotr-server/$1" \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-common/src/main/resources/gemp-lotr.properties b/gemp-lotr/gemp-lotr-common/src/main/resources/gemp-lotr.properties index da8be4e79..16a2cbd53 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/resources/gemp-lotr.properties +++ b/gemp-lotr/gemp-lotr-common/src/main/resources/gemp-lotr.properties @@ -3,13 +3,14 @@ application.root=/etc/gemp-lotr ## DB connection db.connection.class=org.gjt.mm.mysql.Driver -db.connection.url=jdbc:mysql://localhost/gemp-lotr -db.connection.username=gemp-lotr -db.connection.password=gemp-lotr +db.connection.url=jdbc:mysql://db:3306/gemp_db +db.connection.username=gempuser +db.connection.password=gemppassword db.connection.validateQuery=/* ping */ select 1 port=80 websocket.port=8080 -web.path=/env/gemp-lotr/web/ +web.path=/etc/gemp-lotr/web/ +card.path=/etc/gemp-lotr/web/cards/ -origin.allowed.pattern=^http://www\\.gempukku\\.com$ +origin.allowed.pattern=^.*$ From 96828398d2016285b232736e8237c4e2cd463b19 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 12 Dec 2020 00:48:58 -0600 Subject: [PATCH 02/74] Committing missed *.env file and including a readme explaining how to set up docker and how to host/compile/run gemp using this repository. --- gemp-lotr/docker/gemp.env | 1 + gemp-lotr/docker/readme.txt | 106 ++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 gemp-lotr/docker/gemp.env create mode 100644 gemp-lotr/docker/readme.txt diff --git a/gemp-lotr/docker/gemp.env b/gemp-lotr/docker/gemp.env new file mode 100644 index 000000000..aa185ea04 --- /dev/null +++ b/gemp-lotr/docker/gemp.env @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME=gemp-lotr-sandbox \ No newline at end of file diff --git a/gemp-lotr/docker/readme.txt b/gemp-lotr/docker/readme.txt new file mode 100644 index 000000000..458ed5f7c --- /dev/null +++ b/gemp-lotr/docker/readme.txt @@ -0,0 +1,106 @@ + +Welcome to the wonderful world of containerized installation! + +Using Docker, all the fiddly installation details can be coded into scripts so that people like you looking to set up an instance of the software don't have to worry about the database, server, Java installation, and all the hokey prerequisites that go along with it. Just copy the files, open docker, run the docker-compose, and your instance is ready to be accessed. + +The current state of the docker files is somewhere just north of "shambles". There were a lot of quirks that had to be figured out, and so as a result the files here are very messy, and have a *ton* of commented-out versions of the code that didn't work. Eventually this will all be cleaned up, but for now take it as a statement of how many ways there are /not/ to create a container. + +As a result, however, there are a few files that currently need to be modified with respect to the host's machine to get these to work. Nothing complicated, just pointing to the location of where some of the subfolders of gemp's source code are. + +So let's get right into it. The entry point is the docker-compose.yml, which defines two containers and all of their interfaces that are exposed to the outside world and to each other. These files call gemp_app.Dockerfile and gemp_db.Dockerfile which are concerned with actually constructing the environments on these two containers. + +gemp_db is straightforward: it's a bare-bones linux instance using the official MariaDB docker image (MariaDB is a variant of MySQL, if you weren't aware). It hosts the gemp database and doesn't do anything else. + +gemp_app is slightly more complicated. Gemp is a Java server, is built using Maven, and utilizes Apache to serve http. All of those have to be installed and available. Unfortunately, Gemp expects its environment to be slightly different from what the defaults of either the official Apache or Maven images create, so this image starts with the Alpine Linux image (which includes Apache) and frankensteins the rest together to get both Maven and Java installed properly. + +That's probably enough background. Here is the checklist to actually getting it all to run: + +1- install Docker (Docker Desktop if on Windows). If you are on Windows, make sure that when you install it you check all boxes that have Docker behave more like it does on Linux. If you're installing this on Linux, I assume you know more than I do about how to set it up properly. + +2- install your container manager of choice. I would HIGHLY recommend portainer.io, which itself runs in a docker container and exposes itself as an interactable web page. This will give you a graphical readout of all your currently running containers, registered images, networks, volumes, and just about anything else you might want, PLUS have interactive command lines for when the GUI just doesn't cut it. The manager that comes with Docker Desktop by default is pretty much only just barely enough to run portainer with, so don't bother with it otherwise. + +3- pull the git repository down to your host machine and put it where you want the code to go. You will not be able to easily move this later, so choose a spot you want to work with permanently. Git repo here: https://github.com/ketura/gemp-lotr + +4- navigate to gemp-lotr/gemp-lotr/docker. There are some modifications that will need to be made before you can actually boot up the containers. + +5- open up docker-compose.yml. Every location that you see an X:/Projects/... hard-coded absolute file path you will need to replace with your own hard-coded absolute file path to the corresponding locations. It should be possible later to modify this to be a relative path and no longer require this step, but for now absolute paths are required. There are 4 lines that need edited, three under gemp_app and one under gemp_db. Don't forget to save. + +6- open a command line and navigate to the location you placed gemp-lotr, and navigate to gemp-lotr/gemp-lotr/docker. Run the following command: + + docker-compose up -d + +You should see "Starting gemp_app....done" and "Starting gemp_db....done" at the very end. This process will take a while the first time you do it, and will be near instantaneous every time after. + +7- the database should have automatically created the gemp databases that are needed. You can verify this by connecting to the database on your host machine with your DB manager of choice (I recommend DBeaver). It is exposed on localhost:3307 and uses the user/pass of gempuser/gemppassword. If you can see the gemp_db database with league_participation and other tables, you're golden. + +Otherwise, run the script at gemp-lotr/gemp-lotr/database_script.sql manually in your database manager. This should not be necessary though and is an indication of a problem if it is. + +8- Now we need to compile the gemp code. To do this, open a command line session in the gemp_app container (if using portainer.io, then log in, select your 'Local' endpoint, click the Containers tab on the left, click the >_ icon next to gemp_app, then click the Connect button). + +Navigate to the gemp codebase (which is bound to the path on your host machine that you edited in step 5): + + cd etc/gemp-lotr + +Now tell Maven to compile the project: + + mvn install + +This process will take upwards of 5-10 minutes. You should see a green "BUILD SUCCESS" when it is successfully done. In portainer.io or another rich command line context, you should see lots of red text if it failed. + +9- At this point the gemp server needs to be ran. You could run the jar file directly in your command line session, but I find that this is sensitive to you closing that session. Instead, we'll shut the docker container down and bring it back up, as the docker-compose is set up to run the appropriate jar command on startup and leave it up in the background. + +Navigate in a command line on your host machine to gemp-lotr/gemp-lotr/docker and run the following commands: + + docker-compose down + docker-compose up -d + +10- if all has gone as planned, you should now be able to navigate to your own personal instance of Gemp. Open your browser of choice and navigate to http://localhost:1337/gemp-lotr/ . (If you need a different port to be bound to, then repeat step 5 and edit the exposed port.) + +If you're presented with the home page, register a new user and log in. It's possible for the login page to present but login itself to fail if configured incorrectly, so don't celebrate until you see the (empty) lobby. If you get that far, then congrats, you now have a working local version of Gemp. + + +-------------- + + +At this point, editing the code is a matter of changing the files on your local machine and re-running step 8. As you have seen how long a process this is, choose carefully what you edit. + + + +The rest of this document may be safely ignored and is only in place to preserve the original documentation I received on how to get gemp to run. The information in this post is useful but has already been incorporated into the docker files and does not need to be performed manually. + + +~~~~~~~~~~~~~~ + + +Yeah, I've set up a low-key instance to test bug fixes and some new features: http://[REDACTED-IP]/gemp-lotr/ + +This guide is to roughly set up one of your own, but you can also submit changes to me and I'll reset afterwards. Really depends on what you want to do, I guess. I typed this up a while back for someone with less experience than you and made some changes, so it's possible some sections are way over-explained and others got edited into confusion :P + +Gemp's file structure expects Apache, so if you don't already have Linus available to you somewhere (could work on a Mac I guess) you'll want to do that. Easiest way IMO would be to install a distro on a flash drive, but you seem in-the-know enough to get dual boot going if you wanted. You can download Gemp from Github, although taking the day or two to learn Git and do it from the command line will pay off. + +Once you've got that, you'll need to install the Java Development Kit and some IDE or build tool. MarcinS uses Maven (and so do I), you can read the "Download, Install, Run Maven" guides here: https://maven.apache.org/. You also need to install SQL for the database. There's not much that needs to be done with this, it's kind of "set up and forget" so I've forgotten many of the details haha. MariaDB came standard on the OS I'm using, which appears to be a version of MySQL. Once you set it all up, you'll need to run "database_script.sql" in gemp-lotr/gemp-lotr/ to create the database that will store decks, user information, etc. + +Now that you've got everything ready, go to gemp-lotr/gemp-lotr/gemp-lotr-common/src/main/resources/gemp-lotr.properties and change it this way (my comments are in parenthesis): + + +## Application root, used for example for storing replay files +application.root=/etc/gemp-lotr (Should point to wherever you installed the source files) + +## DB connection +db.connection.class=org.gjt.mm.mysql.Driver +db.connection.url=jdbc:mysql://localhost/gemp-lotr +db.connection.username=gemp-lotr (whatever you set the SQL username to) +db.connection.password=gemp-lotr (whatever you set the SQL password to) +db.connection.validateQuery=/* ping */ select 1 + +port=80 +web.path=/env/gemp-lotr/web/ (change this to wherever the /web/ folder is on your computer. I kept mine in .../gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web/, but technically it's more secure to move the web files to its own location) +card.path= .../gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web/cards/ (this line you'll need to add, since MarcinS is currently moving all of the cards from one format to another) + + + +The stage is set, now the server has to be compiled. Open up the command line and navigate to the folder gemp-lotr/gemp-lotr/. The command "sudo mvn install" will compile all of the code of the server. This should not fail, since you haven't made any changes to the java. You should be able to start the server now. I do it from the command line, "sudo java -jar .../gemp-lotr/gemp-lotr/gemp-lotr-async/target/web.jar" (Maven will create the folder "/target/" for you). If you get the message "No appenders could be found for logger," just ignore it -- as long as that's the only error, that means it is working. + +If everything worked, you can open up a browser and go to "localhost/gemp-lotr" and see the Gemp server. I've gone through this process a few times trying to get everything to work, but not recently. Let me know if you hit any snags and I'll figure out what I forgot to mention. I've also been rooting around the code for a while now, if you need help on that front. I recommend using Git to keep track of it all, I did everything on Github for a while and you don't notice how much extra work you're doing until you stop doing it. Git makes it so much easier, if you're planning on sticking with this for any length of time I'd advise you (again) to figure that out. It's really not too hard, I just use a handful of commands and the world is a simpler place for it. + +Cheers!ā˜ŗā˜»ā™„ From 55e7fc16455f98df7f04b8ee33190f79e589db45 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 5 Jan 2021 14:06:41 -0600 Subject: [PATCH 03/74] Docker file cleanup Cleaned up and simplified all docker files to remove all commented-out lines (now that they are in VC). Removed obsolete files. Cleaned up the readme.txt to make all the specific steps clearer and to remove excess chatty language. --- .gitignore | 7 +- database/.placeholder | 0 gemp-lotr/docker/Dockerfile | 37 -- gemp-lotr/docker/conf2.txt | 481 ----------------------- gemp-lotr/docker/docker-compose.yml | 54 +-- gemp-lotr/docker/gemp_app.Dockerfile | 246 +----------- gemp-lotr/docker/gemp_web.Dockerfile | 15 - gemp-lotr/docker/httpd.conf | 553 --------------------------- gemp-lotr/docker/readme.txt | 107 ++---- 9 files changed, 51 insertions(+), 1449 deletions(-) create mode 100644 database/.placeholder delete mode 100644 gemp-lotr/docker/Dockerfile delete mode 100644 gemp-lotr/docker/conf2.txt delete mode 100644 gemp-lotr/docker/gemp_web.Dockerfile delete mode 100644 gemp-lotr/docker/httpd.conf diff --git a/.gitignore b/.gitignore index 8ede39039..3edffecd8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ buildNumber.properties # https://github.com/takari/maven-wrapper#usage-without-binary-jar .mvn/wrapper/maven-wrapper.jar -database/ -replay/ -replays/ \ No newline at end of file +database/* +!database/.placeholder +.idea/ +*.iml \ No newline at end of file diff --git a/database/.placeholder b/database/.placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/gemp-lotr/docker/Dockerfile b/gemp-lotr/docker/Dockerfile deleted file mode 100644 index e968a83c0..000000000 --- a/gemp-lotr/docker/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -#FROM store/oracle/jdk:11 AS Java -# copy files manually from the FROM statement image into the new container -FROM maven AS MavenJavaBuildTools -#FROM mariadb AS MariaDB -#FROM httpd AS ApacheWebServer - -ENV LANG en_US.UTF-8 - -ENV JAVA_HOME /usr/java/openjdk-14 -ENV PATH $JAVA_HOME/bin:$PATH -ENV JAVA_VERSION 14.0.2 - -ENV MAVEN_HOME /usr/share/maven -ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" - -WORKDIR /usr/java/ -COPY ./openjdk-14 /usr/java/openjdk-14 -#RUN apt-get update && apt-get -y install git - -#WORKDIR /etc/ - -#RUN git clone https://github.com/MarcinSc/gemp-lotr.git && \ - # The github files are all nested way too deep - #cp -R /etc/gemp-lotr/gemp-lotr/* /etc/gemp-lotr && \ - #rm -rf /etc/gemp-lotr/gemp-lotr/ - - -#WORKDIR /etc/gemp-lotr - -CMD ["/bin/bash"] -#"/bin/bash" -#ENTRYPOINT ["/bin/bash"] - -#ENV JAVA_HOME /usr/java/openjdk-14 -# 1. Install tools that are needed to build your application. -# 2. Install dependencies, libraries and packages. -# 3. Build your application. diff --git a/gemp-lotr/docker/conf2.txt b/gemp-lotr/docker/conf2.txt deleted file mode 100644 index f36a3ac5d..000000000 --- a/gemp-lotr/docker/conf2.txt +++ /dev/null @@ -1,481 +0,0 @@ -# -# This is the main Apache HTTP server configuration file. It contains the -# configuration directives that give the server its instructions. -# See for detailed information. -# In particular, see -# -# for a discussion of each configuration directive. -# -# Do NOT simply read the instructions in here without understanding -# what they do. They're here only as hints or reminders. If you are unsure -# consult the online docs. You have been warned. -# -# Configuration and logfile names: If the filenames you specify for many -# of the server's control files begin with "/" (or "drive:/" for Win32), the -# server will use that explicit path. If the filenames do *not* begin -# with "/", the value of ServerRoot is prepended -- so "logs/access_log" -# with ServerRoot set to "/usr/local/apache2" will be interpreted by the -# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" -# will be interpreted as '/logs/access_log'. - -# -# ServerTokens -# This directive configures what you return as the Server HTTP response -# Header. The default is 'Full' which sends information about the OS-Type -# and compiled in modules. -# Set to one of: Full | OS | Minor | Minimal | Major | Prod -# where Full conveys the most information, and Prod the least. -# -ServerTokens OS - -# -# ServerRoot: The top of the directory tree under which the server's -# configuration, error, and log files are kept. -# -# Do not add a slash at the end of the directory path. If you point -# ServerRoot at a non-local disk, be sure to specify a local disk on the -# Mutex directive, if file-based mutexes are used. If you wish to share the -# same ServerRoot for multiple httpd daemons, you will need to change at -# least PidFile. -# -ServerRoot /var/www - -# -# Mutex: Allows you to set the mutex mechanism and mutex file directory -# for individual mutexes, or change the global defaults -# -# Uncomment and change the directory if mutexes are file-based and the default -# mutex file directory is not on a local disk or is not appropriate for some -# other reason. -# -# Mutex default:/run/apache2 - -# -# Listen: Allows you to bind Apache to specific IP addresses and/or -# ports, instead of the default. See also the -# directive. -# -# Change this to Listen on specific IP addresses as shown below to -# prevent Apache from glomming onto all bound IP addresses. -# -#Listen 12.34.56.78:80 -Listen 80 - -# -# Dynamic Shared Object (DSO) Support -# -# To be able to use the functionality of a module which was built as a DSO you -# have to place corresponding `LoadModule' lines at this location so the -# directives contained in it are actually available _before_ they are used. -# Statically compiled modules (those listed by `httpd -l') do not need -# to be loaded here. -# -# Example: -# LoadModule foo_module modules/mod_foo.so -# -#LoadModule mpm_event_module modules/mod_mpm_event.so -LoadModule mpm_prefork_module modules/mod_mpm_prefork.so -#LoadModule mpm_worker_module modules/mod_mpm_worker.so -LoadModule authn_file_module modules/mod_authn_file.so -#LoadModule authn_dbm_module modules/mod_authn_dbm.so -#LoadModule authn_anon_module modules/mod_authn_anon.so -#LoadModule authn_dbd_module modules/mod_authn_dbd.so -#LoadModule authn_socache_module modules/mod_authn_socache.so -LoadModule authn_core_module modules/mod_authn_core.so -LoadModule authz_host_module modules/mod_authz_host.so -LoadModule authz_groupfile_module modules/mod_authz_groupfile.so -LoadModule authz_user_module modules/mod_authz_user.so -#LoadModule authz_dbm_module modules/mod_authz_dbm.so -#LoadModule authz_owner_module modules/mod_authz_owner.so -#LoadModule authz_dbd_module modules/mod_authz_dbd.so -LoadModule authz_core_module modules/mod_authz_core.so -LoadModule access_compat_module modules/mod_access_compat.so -LoadModule auth_basic_module modules/mod_auth_basic.so -#LoadModule auth_form_module modules/mod_auth_form.so -#LoadModule auth_digest_module modules/mod_auth_digest.so -#LoadModule allowmethods_module modules/mod_allowmethods.so -#LoadModule file_cache_module modules/mod_file_cache.so -#LoadModule cache_module modules/mod_cache.so -#LoadModule cache_disk_module modules/mod_cache_disk.so -#LoadModule cache_socache_module modules/mod_cache_socache.so -#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so -#LoadModule socache_dbm_module modules/mod_socache_dbm.so -#LoadModule socache_memcache_module modules/mod_socache_memcache.so -#LoadModule socache_redis_module modules/mod_socache_redis.so -#LoadModule watchdog_module modules/mod_watchdog.so -#LoadModule macro_module modules/mod_macro.so -#LoadModule dbd_module modules/mod_dbd.so -#LoadModule dumpio_module modules/mod_dumpio.so -#LoadModule echo_module modules/mod_echo.so -#LoadModule buffer_module modules/mod_buffer.so -#LoadModule data_module modules/mod_data.so -#LoadModule ratelimit_module modules/mod_ratelimit.so -LoadModule reqtimeout_module modules/mod_reqtimeout.so -#LoadModule ext_filter_module modules/mod_ext_filter.so -#LoadModule request_module modules/mod_request.so -#LoadModule include_module modules/mod_include.so -LoadModule filter_module modules/mod_filter.so -#LoadModule reflector_module modules/mod_reflector.so -#LoadModule substitute_module modules/mod_substitute.so -#LoadModule sed_module modules/mod_sed.so -#LoadModule charset_lite_module modules/mod_charset_lite.so -#LoadModule deflate_module modules/mod_deflate.so -LoadModule mime_module modules/mod_mime.so -LoadModule log_config_module modules/mod_log_config.so -#LoadModule log_debug_module modules/mod_log_debug.so -#LoadModule log_forensic_module modules/mod_log_forensic.so -#LoadModule logio_module modules/mod_logio.so -LoadModule env_module modules/mod_env.so -#LoadModule mime_magic_module modules/mod_mime_magic.so -#LoadModule expires_module modules/mod_expires.so -LoadModule headers_module modules/mod_headers.so -#LoadModule usertrack_module modules/mod_usertrack.so -#LoadModule unique_id_module modules/mod_unique_id.so -LoadModule setenvif_module modules/mod_setenvif.so -LoadModule version_module modules/mod_version.so -#LoadModule remoteip_module modules/mod_remoteip.so -#LoadModule session_module modules/mod_session.so -#LoadModule session_cookie_module modules/mod_session_cookie.so -#LoadModule session_crypto_module modules/mod_session_crypto.so -#LoadModule session_dbd_module modules/mod_session_dbd.so -#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so -#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so -#LoadModule dialup_module modules/mod_dialup.so -#LoadModule http2_module modules/mod_http2.so -LoadModule unixd_module modules/mod_unixd.so -#LoadModule heartbeat_module modules/mod_heartbeat.so -#LoadModule heartmonitor_module modules/mod_heartmonitor.so -LoadModule status_module modules/mod_status.so -LoadModule autoindex_module modules/mod_autoindex.so -#LoadModule asis_module modules/mod_asis.so -#LoadModule info_module modules/mod_info.so -#LoadModule suexec_module modules/mod_suexec.so - - #LoadModule cgid_module modules/mod_cgid.so - - - #LoadModule cgi_module modules/mod_cgi.so - -#LoadModule vhost_alias_module modules/mod_vhost_alias.so -#LoadModule negotiation_module modules/mod_negotiation.so -LoadModule dir_module modules/mod_dir.so -#LoadModule actions_module modules/mod_actions.so -#LoadModule speling_module modules/mod_speling.so -#LoadModule userdir_module modules/mod_userdir.so -LoadModule alias_module modules/mod_alias.so -#LoadModule rewrite_module modules/mod_rewrite.so - -LoadModule negotiation_module modules/mod_negotiation.so - - -# -# If you wish httpd to run as a different user or group, you must run -# httpd as root initially and it will switch. -# -# User/Group: The name (or #number) of the user/group to run httpd as. -# It is usually good practice to create a dedicated user and group for -# running httpd, as with most system services. -# -User apache -Group apache - - - -# 'Main' server configuration -# -# The directives in this section set up the values used by the 'main' -# server, which responds to any requests that aren't handled by a -# definition. These values also provide defaults for -# any containers you may define later in the file. -# -# All of these directives may appear inside containers, -# in which case these default settings will be overridden for the -# virtual host being defined. -# - -# -# ServerAdmin: Your address, where problems with the server should be -# e-mailed. This address appears on some server-generated pages, such -# as error documents. e.g. admin@your-domain.com -# -ServerAdmin you@example.com - -# -# Optionally add a line containing the server version and virtual host -# name to server-generated pages (internal error documents, FTP directory -# listings, mod_status and mod_info output etc., but not CGI generated -# documents or custom error documents). -# Set to "EMail" to also include a mailto: link to the ServerAdmin. -# Set to one of: On | Off | EMail -# -ServerSignature On - -# -# ServerName gives the name and port that the server uses to identify itself. -# This can often be determined automatically, but we recommend you specify -# it explicitly to prevent problems during startup. -# -# If your host doesn't have a registered DNS name, enter its IP address here. -# -#ServerName www.example.com:80 - -# -# Deny access to the entirety of your server's filesystem. You must -# explicitly permit access to web content directories in other -# blocks below. -# - - AllowOverride none - Require all denied - - -# -# Note that from this point forward you must specifically allow -# particular features to be enabled - so if something's not working as -# you might expect, make sure that you have specifically enabled it -# below. -# - -# -# DocumentRoot: The directory out of which you will serve your -# documents. By default, all requests are taken from this directory, but -# symbolic links and aliases may be used to point to other locations. -# -DocumentRoot "/var/www/localhost/htdocs" - - # - # Possible values for the Options directive are "None", "All", - # or any combination of: - # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews - # - # Note that "MultiViews" must be named *explicitly* --- "Options All" - # doesn't give it to you. - # - # The Options directive is both complicated and important. Please see - # http://httpd.apache.org/docs/2.4/mod/core.html#options - # for more information. - # - Options Indexes FollowSymLinks - - # - # AllowOverride controls what directives may be placed in .htaccess files. - # It can be "All", "None", or any combination of the keywords: - # AllowOverride FileInfo AuthConfig Limit - # - AllowOverride None - - # - # Controls who can get stuff from this server. - # - Require all granted - - -# -# DirectoryIndex: sets the file that Apache will serve if a directory -# is requested. -# - - DirectoryIndex index.html - - -# -# The following lines prevent .htaccess and .htpasswd files from being -# viewed by Web clients. -# - - Require all denied - - -# -# ErrorLog: The location of the error log file. -# If you do not specify an ErrorLog directive within a -# container, error messages relating to that virtual host will be -# logged here. If you *do* define an error logfile for a -# container, that host's errors will be logged there and not here. -# -ErrorLog logs/error.log - -# -# LogLevel: Control the number of messages logged to the error_log. -# Possible values include: debug, info, notice, warn, error, crit, -# alert, emerg. -# -LogLevel warn - - - # - # The following directives define some format nicknames for use with - # a CustomLog directive (see below). - # - LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined - LogFormat "%h %l %u %t \"%r\" %>s %b" common - - - # You need to enable mod_logio.c to use %I and %O - LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio - - - # - # The location and format of the access logfile (Common Logfile Format). - # If you do not define any access logfiles within a - # container, they will be logged here. Contrariwise, if you *do* - # define per- access logfiles, transactions will be - # logged therein and *not* in this file. - # - #CustomLog logs/access.log common - - # - # If you prefer a logfile with access, agent, and referer information - # (Combined Logfile Format) you can use the following directive. - # - CustomLog logs/access.log combined - - - - # - # Redirect: Allows you to tell clients about documents that used to - # exist in your server's namespace, but do not anymore. The client - # will make a new request for the document at its new location. - # Example: - # Redirect permanent /foo http://www.example.com/bar - - # - # Alias: Maps web paths into filesystem paths and is used to - # access content that does not live under the DocumentRoot. - # Example: - # Alias /webpath /full/filesystem/path - # - # If you include a trailing / on /webpath then the server will - # require it to be present in the URL. You will also likely - # need to provide a section to allow access to - # the filesystem path. - - # - # ScriptAlias: This controls which directories contain server scripts. - # ScriptAliases are essentially the same as Aliases, except that - # documents in the target directory are treated as applications and - # run by the server when requested rather than as documents sent to the - # client. The same rules about trailing "/" apply to ScriptAlias - # directives as to Alias. - # - ScriptAlias /cgi-bin/ "/var/www/localhost/cgi-bin/" - - - - - # - # ScriptSock: On threaded servers, designate the path to the UNIX - # socket used to communicate with the CGI daemon of mod_cgid. - # - #Scriptsock cgisock - - -# -# "/var/www/localhost/cgi-bin" should be changed to whatever your ScriptAliased -# CGI directory exists, if you have that configured. -# - - AllowOverride None - Options None - Require all granted - - - - # - # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied - # backend servers which have lingering "httpoxy" defects. - # 'Proxy' request header is undefined by the IETF, not listed by IANA - # - RequestHeader unset Proxy early - - - - # - # TypesConfig points to the file containing the list of mappings from - # filename extension to MIME-type. - # - TypesConfig /etc/apache2/mime.types - - # - # AddType allows you to add to or override the MIME configuration - # file specified in TypesConfig for specific file types. - # - #AddType application/x-gzip .tgz - # - # AddEncoding allows you to have certain browsers uncompress - # information on the fly. Note: Not all browsers support this. - # - #AddEncoding x-compress .Z - #AddEncoding x-gzip .gz .tgz - # - # If the AddEncoding directives above are commented-out, then you - # probably should define those extensions to indicate media types: - # - AddType application/x-compress .Z - AddType application/x-gzip .gz .tgz - - # - # AddHandler allows you to map certain file extensions to "handlers": - # actions unrelated to filetype. These can be either built into the server - # or added with the Action directive (see below) - # - # To use CGI scripts outside of ScriptAliased directories: - # (You will also need to add "ExecCGI" to the "Options" directive.) - # - #AddHandler cgi-script .cgi - - # For type maps (negotiated resources): - #AddHandler type-map var - - # - # Filters allow you to process content before it is sent to the client. - # - # To parse .shtml files for server-side includes (SSI): - # (You will also need to add "Includes" to the "Options" directive.) - # - #AddType text/html .shtml - #AddOutputFilter INCLUDES .shtml - - -# -# The mod_mime_magic module allows the server to use various hints from the -# contents of the file itself to determine its type. The MIMEMagicFile -# directive tells the module where the hint definitions are located. -# - - MIMEMagicFile /etc/apache2/magic - - -# -# Customizable error responses come in three flavors: -# 1) plain text 2) local redirects 3) external redirects -# -# Some examples: -#ErrorDocument 500 "The server made a boo boo." -#ErrorDocument 404 /missing.html -#ErrorDocument 404 "/cgi-bin/missing_handler.pl" -#ErrorDocument 402 http://www.example.com/subscription_info.html -# - -# -# MaxRanges: Maximum number of Ranges in a request before -# returning the entire resource, or one of the special -# values 'default', 'none' or 'unlimited'. -# Default setting is to accept 200 Ranges. -#MaxRanges unlimited - -# -# EnableMMAP and EnableSendfile: On systems that support it, -# memory-mapping or the sendfile syscall may be used to deliver -# files. This usually improves server performance, but must -# be turned off when serving from networked-mounted -# filesystems or if support for these functions is otherwise -# broken on your system. -# Defaults: EnableMMAP On, EnableSendfile Off -# -#EnableMMAP off -#EnableSendfile on - -# Load config files from the config directory "/etc/apache2/conf.d". -# -IncludeOptional /etc/apache2/conf.d/*.conf \ No newline at end of file diff --git a/gemp-lotr/docker/docker-compose.yml b/gemp-lotr/docker/docker-compose.yml index 11da8a043..171b755ff 100644 --- a/gemp-lotr/docker/docker-compose.yml +++ b/gemp-lotr/docker/docker-compose.yml @@ -1,6 +1,8 @@ version: "3.4" services: + + build: container_name: gemp_app build: @@ -16,30 +18,24 @@ services: - target: 80 # published is what's on the host machine published: 1337 - #- "8080:108080" volumes: - # - type: bind - # source: X:/Projects/gemp-lotr/replays - # target: /etc/gemp - type: bind - source: X:/Projects/gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web + source: ../gemp-lotr-async/src/main/web target: /etc/gemp-lotr/web - type: bind - source: X:/Projects/gemp-lotr/gemp-lotr + source: ../../gemp-lotr target: /etc/gemp-lotr - type: bind - source: X:/Projects/gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web + source: ../gemp-lotr-async/src/main/web target: /var/www/localhost/htdocs/gemp-lotr #/etc/apache2/htdocs/gemp-lotr networks: gemp_net: ipv4_address: 172.28.1.1 tty: true - #command: /usr/sbin/httpd -D FOREGROUND command: nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & db: - #image: mariadb container_name: gemp_db build: context: .. @@ -53,7 +49,7 @@ services: restart: always volumes: - type: bind - source: X:/Projects/gemp-lotr/database + source: ../../database target: /var/lib/mysql networks: gemp_net: @@ -65,44 +61,6 @@ services: MYSQL_PASSWORD: gemppassword - # web: - # container_name: gemp_web - # build: - # context: . - # dockerfile: gemp_web.Dockerfile - # image: gemp_web - # expose: - # - "80" - # - "8080" - # ports: - # # target means in the container - # - target: 80 - # # published is what's on the host machine - # published: 1337 - # #- "8080:108080" - # volumes: - # - type: bind - # source: X:/Projects/gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web - # target: /usr/local/apache2/htdocs/gemp-lotr - # networks: - # gemp_net: - # ipv4_address: 172.28.1.3 - # extra_hosts: - # # by overridding localhost to go to the app container, we avoid issues with AJAX - # - "localhost:172.28.1.1" - - # wiki: - # container_name: lotr_wiki - # image: mediawiki - # ports: - # # target means in the container - # - target: 80 - # # published is what's on the host machine - # published: 1338 - # volumes: - # - type: bind - # source: X:/Projects/gemp-lotr/gemp-lotr/docker/wiki - # target: /usr/wiki networks: gemp_net: ipam: diff --git a/gemp-lotr/docker/gemp_app.Dockerfile b/gemp-lotr/docker/gemp_app.Dockerfile index 4a5b9554d..30c6e2bec 100644 --- a/gemp-lotr/docker/gemp_app.Dockerfile +++ b/gemp-lotr/docker/gemp_app.Dockerfile @@ -1,113 +1,3 @@ -#FROM store/oracle/jdk:11 AS Java -# copy files manually from the FROM statement image into the new container -#FROM maven AS JavaBuild -#FROM mariadb AS MariaDB -#FROM httpd AS ApacheWebServer - - - - -##################################################################### -# The following is pulled from the openjdk dockerfile: -# https://github.com/docker-library/openjdk/blob/29c17de6c8c0df6304d0c80f569deea1d4b6a23e/14/jdk/oracle/Dockerfile -##################################################################### - - -#RUN apt-get update -# -#RUN set -eux; \ - #apt-get install -y \ - #gzip \ - #curl \ - #tar \ -# -## jlink --strip-debug on 13+ needs objcopy: https://github.com/docker-library/openjdk/issues/351 -## Error: java.io.IOException: Cannot run program "objcopy": error=2, No such file or directory - #binutils \ -## java.lang.UnsatisfiedLinkError: /usr/java/openjdk-12/lib/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory -## https://github.com/docker-library/openjdk/pull/235#issuecomment-424466077 - #libfreetype6 fontconfig \ - #; \ - #rm -rf /var/cache/yum -# -## Default to UTF-8 file.encoding -#ENV LANG en_US.UTF-8 -# -#ENV JAVA_HOME /usr/java/openjdk-14 -#ENV PATH $JAVA_HOME/bin:$PATH -# -## https://jdk.java.net/ -## > Java Development Kit builds, from Oracle -#ENV JAVA_VERSION 14.0.2 -# -#RUN set -eux; \ -## amd64 - #downloadUrl=https://download.java.net/java/GA/jdk14.0.2/205943a0976c4ed48cb16f1043c5c647/12/GPL/openjdk-14.0.2_linux-x64_bin.tar.gz; \ - #downloadSha256=91310200f072045dc6cef2c8c23e7e6387b37c46e9de49623ce0fa461a24623d; \ -# - #curl -fkL -o /openjdk.tgz "$downloadUrl"; \ - #echo "$downloadSha256 */openjdk.tgz" | sha256sum -c -; \ -# - #mkdir -p "$JAVA_HOME"; \ - #tar --extract --file /openjdk.tgz --directory "$JAVA_HOME" --strip-components 1; \ - #rm /openjdk.tgz; \ -# -## https://github.com/oracle/docker-images/blob/a56e0d1ed968ff669d2e2ba8a1483d0f3acc80c0/OracleJava/java-8/Dockerfile#L17-L19 - #ln -sfT "$JAVA_HOME" /usr/java/default; \ - #ln -sfT "$JAVA_HOME" /usr/java/latest; \ - #for bin in "$JAVA_HOME/bin/"*; do \ - #base="$(basename "$bin")"; \ - #[ ! -e "/usr/bin/$base" ]; \ - #update-alternatives --install "/usr/bin/$base" "$base" "$bin" 20000; \ - #done; \ -# -## https://github.com/docker-library/openjdk/issues/212#issuecomment-420979840 -## https://openjdk.java.net/jeps/341 - #java -Xshare:dump; \ -# -## see "update-ca-trust" script which creates/maintains this cacerts bundle - #rm -rf "$JAVA_HOME/lib/security/cacerts"; \ - #ln -sT /etc/pki/ca-trust/extracted/java/cacerts "$JAVA_HOME/lib/security/cacerts"; \ -# -## basic smoke test - #java --version; \ - #javac --version -# -## https://docs.oracle.com/javase/10/tools/jshell.htm -## https://docs.oracle.com/javase/10/jshell/ -## https://en.wikipedia.org/wiki/JShell -##CMD ["jshell"] -# -###################################################################### -# -# -# -###################################################################### -## The following is pulled from the maven dockerfile: -## https://github.com/carlossg/docker-maven/blob/26ba49149787c85b9c51222b47c00879b2a0afde/openjdk-14/Dockerfile -###################################################################### -# -#ARG MAVEN_VERSION=3.6.3 -#ARG USER_HOME_DIR="/root" -#ARG SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0 -#ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries -# -#RUN mkdir -p /usr/share/maven /usr/share/maven/ref \ - #&& curl -fsSkL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \ - #&& echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c - \ - #&& tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \ - #&& rm -f /tmp/apache-maven.tar.gz \ - #&& ln -s /usr/share/maven/bin/mvn /usr/bin/mvn -# -#ENV MAVEN_HOME /usr/share/maven -#ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" -# -##COPY mvn-entrypoint.sh /usr/local/bin/mvn-entrypoint.sh -##COPY settings-docker.xml /usr/share/maven/ref/ -# -###################################################################### - - FROM alpine RUN apk update; \ @@ -129,7 +19,7 @@ RUN apk update; \ ##################################################################### -# The following is pulled from the maven dockerfile: +# The following is pulled from the official maven dockerfile: # https://github.com/carlossg/docker-maven/blob/26ba49149787c85b9c51222b47c00879b2a0afde/openjdk-14/Dockerfile ##################################################################### @@ -148,8 +38,6 @@ RUN mkdir -p /usr/share/maven /usr/share/maven/ref \ ENV MAVEN_HOME /usr/share/maven ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" -#COPY mvn-entrypoint.sh /usr/local/bin/mvn-entrypoint.sh -#COPY settings-docker.xml /usr/share/maven/ref/ ##################################################################### @@ -157,136 +45,6 @@ ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" RUN apk add --no-cache openrc; \ apk add --no-cache apache2 -RUN nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & - - # java prereqs - #gzip \ - #curl \ - #tar \ - #libfreetype6 fontconfig \ - #openjdk14 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community - - # apache prereqs - #bzip2 \ - #ca-certificates \ - #dirmngr \ - #dpkg-dev \ - #gcc \ - #gnupg \ - #libbrotli-dev \ - #libcurl4-openssl-dev \ - #libjansson-dev \ - #liblua5.2-dev \ - #libnghttp2-dev \ - #libpcre3-dev \ - #libssl-dev \ - #libxml2-dev \ - #make \ - #wget \ - #zlib1g-dev - - -##################################################################### -# The following is pulled from the openjdk dockerfile: -# https://github.com/docker-library/openjdk/blob/29c17de6c8c0df6304d0c80f569deea1d4b6a23e/14/jdk/oracle/Dockerfile -##################################################################### - - -## Default to UTF-8 file.encoding -#ENV LANG en_US.UTF-8 -# -#ENV JAVA_HOME /usr/java/openjdk-14 -#ENV PATH $JAVA_HOME/bin:$PATH -# -## https://jdk.java.net/ -## > Java Development Kit builds, from Oracle -#ENV JAVA_VERSION 14.0.2 -# -#RUN set -eux; \ -## amd64 - #downloadUrl=https://download.java.net/java/GA/jdk14.0.2/205943a0976c4ed48cb16f1043c5c647/12/GPL/openjdk-14.0.2_linux-x64_bin.tar.gz; \ - #downloadSha256=91310200f072045dc6cef2c8c23e7e6387b37c46e9de49623ce0fa461a24623d; \ -# - #curl -fkL -o /openjdk.tgz "$downloadUrl"; \ - #echo "$downloadSha256 */openjdk.tgz" | sha256sum -c -; \ -# - #mkdir -p "$JAVA_HOME"; \ - #tar --extract --file /openjdk.tgz --directory "$JAVA_HOME" --strip-components 1; \ - #rm /openjdk.tgz; - -## https://github.com/oracle/docker-images/blob/a56e0d1ed968ff669d2e2ba8a1483d0f3acc80c0/OracleJava/java-8/Dockerfile#L17-L19 - #ln -sfT "$JAVA_HOME" /usr/java/default; \ - #ln -sfT "$JAVA_HOME" /usr/java/latest; \ - #for bin in "$JAVA_HOME/bin/"*; do \ - #base="$(basename "$bin")"; \ - #[ ! -e "/usr/bin/$base" ]; \ - #update-alternatives --install "/usr/bin/$base" "$base" "$bin" 20000; \ - #done; \ -# - -# https://github.com/docker-library/openjdk/issues/212#issuecomment-420979840 -# https://openjdk.java.net/jeps/341 - #java -Xshare:dump; \ - -# see "update-ca-trust" script which creates/maintains this cacerts bundle - #rm -rf "$JAVA_HOME/lib/security/cacerts"; \ - #ln -sT /etc/pki/ca-trust/extracted/java/cacerts "$JAVA_HOME/lib/security/cacerts"; - -# basic smoke test - #java --version; \ - #javac --version - -# https://docs.oracle.com/javase/10/tools/jshell.htm -# https://docs.oracle.com/javase/10/jshell/ -# https://en.wikipedia.org/wiki/JShell -#CMD ["jshell"] - -##################################################################### - - - - - - - -#RUN yum install -y telnet && \ - #yum install -y iputils -# -# -#RUN yum install -y socat && \ - #socat TCP-LISTEN:3306,fork TCP:db:3306 & -#RUN socat TCP-LISTEN:80,fork TCP:web:80 & -#RUN yum install -y websocat && \ - #websocat WS-LISTEN:8080,fork WS:web:8080 & - -#RUN apt-get install -y websocat && \ -# websocat WS-LISTEN:8080,fork WS:build:8080 & - - - - - -#WORKDIR /usr/java/ -#COPY ./openjdk-14 /usr/java/openjdk-14 -#RUN apt-get update && apt-get -y install git - -#WORKDIR /etc/ - -#RUN git clone https://github.com/MarcinSc/gemp-lotr.git && \ - # The github files are all nested way too deep - #cp -R /etc/gemp-lotr/gemp-lotr/* /etc/gemp-lotr && \ - #rm -rf /etc/gemp-lotr/gemp-lotr/ - - -#WORKDIR /etc/gemp-lotr - -#CMD java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & -#"/bin/bash" -#ENTRYPOINT ["/bin/bash"] - -#ENV JAVA_HOME /usr/java/openjdk-14 -# 1. Install tools that are needed to build your application. -# 2. Install dependencies, libraries and packages. -# 3. Build your application. +#RUN nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & diff --git a/gemp-lotr/docker/gemp_web.Dockerfile b/gemp-lotr/docker/gemp_web.Dockerfile deleted file mode 100644 index d0cad1161..000000000 --- a/gemp-lotr/docker/gemp_web.Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM httpd AS ApacheWebServer - -RUN apt-get install -y socat && \ - socat TCP-LISTEN:80,fork TCP:build:80 & -RUN apt-get install -y websocat && \ - websocat WS-LISTEN:8080,fork WS:build:8080 & -RUN apt-get update && \ - apt-get install -y watch && \ - apt-get install -y net-tools && \ - apt-get install -y iputils-ping && \ - apt-get install -y telnet - - - -COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf \ No newline at end of file diff --git a/gemp-lotr/docker/httpd.conf b/gemp-lotr/docker/httpd.conf deleted file mode 100644 index 7cf1dc3b6..000000000 --- a/gemp-lotr/docker/httpd.conf +++ /dev/null @@ -1,553 +0,0 @@ -# -# This is the main Apache HTTP server configuration file. It contains the -# configuration directives that give the server its instructions. -# See for detailed information. -# In particular, see -# -# for a discussion of each configuration directive. -# -# Do NOT simply read the instructions in here without understanding -# what they do. They're here only as hints or reminders. If you are unsure -# consult the online docs. You have been warned. -# -# Configuration and logfile names: If the filenames you specify for many -# of the server's control files begin with "/" (or "drive:/" for Win32), the -# server will use that explicit path. If the filenames do *not* begin -# with "/", the value of ServerRoot is prepended -- so "logs/access_log" -# with ServerRoot set to "/usr/local/apache2" will be interpreted by the -# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" -# will be interpreted as '/logs/access_log'. - -# -# ServerRoot: The top of the directory tree under which the server's -# configuration, error, and log files are kept. -# -# Do not add a slash at the end of the directory path. If you point -# ServerRoot at a non-local disk, be sure to specify a local disk on the -# Mutex directive, if file-based mutexes are used. If you wish to share the -# same ServerRoot for multiple httpd daemons, you will need to change at -# least PidFile. -# -ServerRoot "/usr/local/apache2" - -# -# Mutex: Allows you to set the mutex mechanism and mutex file directory -# for individual mutexes, or change the global defaults -# -# Uncomment and change the directory if mutexes are file-based and the default -# mutex file directory is not on a local disk or is not appropriate for some -# other reason. -# -# Mutex default:logs - -# -# Listen: Allows you to bind Apache to specific IP addresses and/or -# ports, instead of the default. See also the -# directive. -# -# Change this to Listen on specific IP addresses as shown below to -# prevent Apache from glomming onto all bound IP addresses. -# -#Listen 12.34.56.78:80 -Listen 80 - -# -# Dynamic Shared Object (DSO) Support -# -# To be able to use the functionality of a module which was built as a DSO you -# have to place corresponding `LoadModule' lines at this location so the -# directives contained in it are actually available _before_ they are used. -# Statically compiled modules (those listed by `httpd -l') do not need -# to be loaded here. -# -# Example: -# LoadModule foo_module modules/mod_foo.so -# -LoadModule mpm_event_module modules/mod_mpm_event.so -#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so -#LoadModule mpm_worker_module modules/mod_mpm_worker.so -LoadModule authn_file_module modules/mod_authn_file.so -#LoadModule authn_dbm_module modules/mod_authn_dbm.so -#LoadModule authn_anon_module modules/mod_authn_anon.so -#LoadModule authn_dbd_module modules/mod_authn_dbd.so -#LoadModule authn_socache_module modules/mod_authn_socache.so -LoadModule authn_core_module modules/mod_authn_core.so -LoadModule authz_host_module modules/mod_authz_host.so -LoadModule authz_groupfile_module modules/mod_authz_groupfile.so -LoadModule authz_user_module modules/mod_authz_user.so -#LoadModule authz_dbm_module modules/mod_authz_dbm.so -#LoadModule authz_owner_module modules/mod_authz_owner.so -#LoadModule authz_dbd_module modules/mod_authz_dbd.so -LoadModule authz_core_module modules/mod_authz_core.so -#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so -#LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so -LoadModule access_compat_module modules/mod_access_compat.so -LoadModule auth_basic_module modules/mod_auth_basic.so -#LoadModule auth_form_module modules/mod_auth_form.so -#LoadModule auth_digest_module modules/mod_auth_digest.so -#LoadModule allowmethods_module modules/mod_allowmethods.so -#LoadModule isapi_module modules/mod_isapi.so -#LoadModule file_cache_module modules/mod_file_cache.so -#LoadModule cache_module modules/mod_cache.so -#LoadModule cache_disk_module modules/mod_cache_disk.so -#LoadModule cache_socache_module modules/mod_cache_socache.so -#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so -#LoadModule socache_dbm_module modules/mod_socache_dbm.so -#LoadModule socache_memcache_module modules/mod_socache_memcache.so -#LoadModule socache_redis_module modules/mod_socache_redis.so -#LoadModule watchdog_module modules/mod_watchdog.so -#LoadModule macro_module modules/mod_macro.so -#LoadModule dbd_module modules/mod_dbd.so -#LoadModule bucketeer_module modules/mod_bucketeer.so -#LoadModule dumpio_module modules/mod_dumpio.so -#LoadModule echo_module modules/mod_echo.so -#LoadModule example_hooks_module modules/mod_example_hooks.so -#LoadModule case_filter_module modules/mod_case_filter.so -#LoadModule case_filter_in_module modules/mod_case_filter_in.so -#LoadModule example_ipc_module modules/mod_example_ipc.so -#LoadModule buffer_module modules/mod_buffer.so -#LoadModule data_module modules/mod_data.so -#LoadModule ratelimit_module modules/mod_ratelimit.so -LoadModule reqtimeout_module modules/mod_reqtimeout.so -#LoadModule ext_filter_module modules/mod_ext_filter.so -#LoadModule request_module modules/mod_request.so -#LoadModule include_module modules/mod_include.so -LoadModule filter_module modules/mod_filter.so -#LoadModule reflector_module modules/mod_reflector.so -#LoadModule substitute_module modules/mod_substitute.so -#LoadModule sed_module modules/mod_sed.so -#LoadModule charset_lite_module modules/mod_charset_lite.so -#LoadModule deflate_module modules/mod_deflate.so -#LoadModule xml2enc_module modules/mod_xml2enc.so -#LoadModule proxy_html_module modules/mod_proxy_html.so -#LoadModule brotli_module modules/mod_brotli.so -LoadModule mime_module modules/mod_mime.so -#LoadModule ldap_module modules/mod_ldap.so -LoadModule log_config_module modules/mod_log_config.so -#LoadModule log_debug_module modules/mod_log_debug.so -#LoadModule log_forensic_module modules/mod_log_forensic.so -#LoadModule logio_module modules/mod_logio.so -#LoadModule lua_module modules/mod_lua.so -LoadModule env_module modules/mod_env.so -#LoadModule mime_magic_module modules/mod_mime_magic.so -#LoadModule cern_meta_module modules/mod_cern_meta.so -#LoadModule expires_module modules/mod_expires.so -LoadModule headers_module modules/mod_headers.so -#LoadModule ident_module modules/mod_ident.so -#LoadModule usertrack_module modules/mod_usertrack.so -#LoadModule unique_id_module modules/mod_unique_id.so -LoadModule setenvif_module modules/mod_setenvif.so -LoadModule version_module modules/mod_version.so -#LoadModule remoteip_module modules/mod_remoteip.so -#LoadModule proxy_module modules/mod_proxy.so -#LoadModule proxy_connect_module modules/mod_proxy_connect.so -#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so -#LoadModule proxy_http_module modules/mod_proxy_http.so -#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so -#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so -#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so -#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so -#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so -#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so -#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so -#LoadModule proxy_express_module modules/mod_proxy_express.so -#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so -#LoadModule session_module modules/mod_session.so -#LoadModule session_cookie_module modules/mod_session_cookie.so -#LoadModule session_crypto_module modules/mod_session_crypto.so -#LoadModule session_dbd_module modules/mod_session_dbd.so -#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so -#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so -#LoadModule ssl_module modules/mod_ssl.so -#LoadModule optional_hook_export_module modules/mod_optional_hook_export.so -#LoadModule optional_hook_import_module modules/mod_optional_hook_import.so -#LoadModule optional_fn_import_module modules/mod_optional_fn_import.so -#LoadModule optional_fn_export_module modules/mod_optional_fn_export.so -#LoadModule dialup_module modules/mod_dialup.so -#LoadModule http2_module modules/mod_http2.so -#LoadModule proxy_http2_module modules/mod_proxy_http2.so -#LoadModule md_module modules/mod_md.so -#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so -#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so -#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so -#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so -LoadModule unixd_module modules/mod_unixd.so -#LoadModule heartbeat_module modules/mod_heartbeat.so -#LoadModule heartmonitor_module modules/mod_heartmonitor.so -#LoadModule dav_module modules/mod_dav.so -LoadModule status_module modules/mod_status.so -LoadModule autoindex_module modules/mod_autoindex.so -#LoadModule asis_module modules/mod_asis.so -#LoadModule info_module modules/mod_info.so -#LoadModule suexec_module modules/mod_suexec.so - - #LoadModule cgid_module modules/mod_cgid.so - - - #LoadModule cgi_module modules/mod_cgi.so - -#LoadModule dav_fs_module modules/mod_dav_fs.so -#LoadModule dav_lock_module modules/mod_dav_lock.so -#LoadModule vhost_alias_module modules/mod_vhost_alias.so -#LoadModule negotiation_module modules/mod_negotiation.so -LoadModule dir_module modules/mod_dir.so -#LoadModule imagemap_module modules/mod_imagemap.so -#LoadModule actions_module modules/mod_actions.so -#LoadModule speling_module modules/mod_speling.so -#LoadModule userdir_module modules/mod_userdir.so -LoadModule alias_module modules/mod_alias.so -#LoadModule rewrite_module modules/mod_rewrite.so - - -# -# If you wish httpd to run as a different user or group, you must run -# httpd as root initially and it will switch. -# -# User/Group: The name (or #number) of the user/group to run httpd as. -# It is usually good practice to create a dedicated user and group for -# running httpd, as with most system services. -# -User daemon -Group daemon - - - -# 'Main' server configuration -# -# The directives in this section set up the values used by the 'main' -# server, which responds to any requests that aren't handled by a -# definition. These values also provide defaults for -# any containers you may define later in the file. -# -# All of these directives may appear inside containers, -# in which case these default settings will be overridden for the -# virtual host being defined. -# - -# -# ServerAdmin: Your address, where problems with the server should be -# e-mailed. This address appears on some server-generated pages, such -# as error documents. e.g. admin@your-domain.com -# -ServerAdmin you@example.com - -# -# ServerName gives the name and port that the server uses to identify itself. -# This can often be determined automatically, but we recommend you specify -# it explicitly to prevent problems during startup. -# -# If your host doesn't have a registered DNS name, enter its IP address here. -# -#ServerName www.example.com:80 - -# -# Deny access to the entirety of your server's filesystem. You must -# explicitly permit access to web content directories in other -# blocks below. -# - - AllowOverride none - Require all denied - - -# -# Note that from this point forward you must specifically allow -# particular features to be enabled - so if something's not working as -# you might expect, make sure that you have specifically enabled it -# below. -# - -# -# DocumentRoot: The directory out of which you will serve your -# documents. By default, all requests are taken from this directory, but -# symbolic links and aliases may be used to point to other locations. -# -DocumentRoot "/usr/local/apache2/htdocs" - - # - # Possible values for the Options directive are "None", "All", - # or any combination of: - # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews - # - # Note that "MultiViews" must be named *explicitly* --- "Options All" - # doesn't give it to you. - # - # The Options directive is both complicated and important. Please see - # http://httpd.apache.org/docs/2.4/mod/core.html#options - # for more information. - # - Options Indexes FollowSymLinks - - # - # AllowOverride controls what directives may be placed in .htaccess files. - # It can be "All", "None", or any combination of the keywords: - # AllowOverride FileInfo AuthConfig Limit - # - AllowOverride None - - # - # Controls who can get stuff from this server. - # - Require all granted - - -# -# DirectoryIndex: sets the file that Apache will serve if a directory -# is requested. -# - - DirectoryIndex index.html - - -# -# The following lines prevent .htaccess and .htpasswd files from being -# viewed by Web clients. -# - - Require all denied - - -# -# ErrorLog: The location of the error log file. -# If you do not specify an ErrorLog directive within a -# container, error messages relating to that virtual host will be -# logged here. If you *do* define an error logfile for a -# container, that host's errors will be logged there and not here. -# -ErrorLog /proc/self/fd/2 - -# -# LogLevel: Control the number of messages logged to the error_log. -# Possible values include: debug, info, notice, warn, error, crit, -# alert, emerg. -# -LogLevel warn - - - # - # The following directives define some format nicknames for use with - # a CustomLog directive (see below). - # - LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined - LogFormat "%h %l %u %t \"%r\" %>s %b" common - - - # You need to enable mod_logio.c to use %I and %O - LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio - - - # - # The location and format of the access logfile (Common Logfile Format). - # If you do not define any access logfiles within a - # container, they will be logged here. Contrariwise, if you *do* - # define per- access logfiles, transactions will be - # logged therein and *not* in this file. - # - CustomLog /proc/self/fd/1 common - - # - # If you prefer a logfile with access, agent, and referer information - # (Combined Logfile Format) you can use the following directive. - # - #CustomLog "logs/access_log" combined - - - - # - # Redirect: Allows you to tell clients about documents that used to - # exist in your server's namespace, but do not anymore. The client - # will make a new request for the document at its new location. - # Example: - # Redirect permanent /foo http://www.example.com/bar - - # - # Alias: Maps web paths into filesystem paths and is used to - # access content that does not live under the DocumentRoot. - # Example: - # Alias /webpath /full/filesystem/path - # - # If you include a trailing / on /webpath then the server will - # require it to be present in the URL. You will also likely - # need to provide a section to allow access to - # the filesystem path. - - # - # ScriptAlias: This controls which directories contain server scripts. - # ScriptAliases are essentially the same as Aliases, except that - # documents in the target directory are treated as applications and - # run by the server when requested rather than as documents sent to the - # client. The same rules about trailing "/" apply to ScriptAlias - # directives as to Alias. - # - ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/" - - - - - # - # ScriptSock: On threaded servers, designate the path to the UNIX - # socket used to communicate with the CGI daemon of mod_cgid. - # - #Scriptsock cgisock - - -# -# "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased -# CGI directory exists, if you have that configured. -# - - AllowOverride None - Options None - Require all granted - - - - # - # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied - # backend servers which have lingering "httpoxy" defects. - # 'Proxy' request header is undefined by the IETF, not listed by IANA - # - RequestHeader unset Proxy early - - - - # - # TypesConfig points to the file containing the list of mappings from - # filename extension to MIME-type. - # - TypesConfig conf/mime.types - - # - # AddType allows you to add to or override the MIME configuration - # file specified in TypesConfig for specific file types. - # - #AddType application/x-gzip .tgz - # - # AddEncoding allows you to have certain browsers uncompress - # information on the fly. Note: Not all browsers support this. - # - #AddEncoding x-compress .Z - #AddEncoding x-gzip .gz .tgz - # - # If the AddEncoding directives above are commented-out, then you - # probably should define those extensions to indicate media types: - # - AddType application/x-compress .Z - AddType application/x-gzip .gz .tgz - - # - # AddHandler allows you to map certain file extensions to "handlers": - # actions unrelated to filetype. These can be either built into the server - # or added with the Action directive (see below) - # - # To use CGI scripts outside of ScriptAliased directories: - # (You will also need to add "ExecCGI" to the "Options" directive.) - # - #AddHandler cgi-script .cgi - - # For type maps (negotiated resources): - #AddHandler type-map var - - # - # Filters allow you to process content before it is sent to the client. - # - # To parse .shtml files for server-side includes (SSI): - # (You will also need to add "Includes" to the "Options" directive.) - # - #AddType text/html .shtml - #AddOutputFilter INCLUDES .shtml - - -# -# The mod_mime_magic module allows the server to use various hints from the -# contents of the file itself to determine its type. The MIMEMagicFile -# directive tells the module where the hint definitions are located. -# -#MIMEMagicFile conf/magic - -# -# Customizable error responses come in three flavors: -# 1) plain text 2) local redirects 3) external redirects -# -# Some examples: -#ErrorDocument 500 "The server made a boo boo." -#ErrorDocument 404 /missing.html -#ErrorDocument 404 "/cgi-bin/missing_handler.pl" -#ErrorDocument 402 http://www.example.com/subscription_info.html -# - -# -# MaxRanges: Maximum number of Ranges in a request before -# returning the entire resource, or one of the special -# values 'default', 'none' or 'unlimited'. -# Default setting is to accept 200 Ranges. -#MaxRanges unlimited - -# -# EnableMMAP and EnableSendfile: On systems that support it, -# memory-mapping or the sendfile syscall may be used to deliver -# files. This usually improves server performance, but must -# be turned off when serving from networked-mounted -# filesystems or if support for these functions is otherwise -# broken on your system. -# Defaults: EnableMMAP On, EnableSendfile Off -# -#EnableMMAP off -#EnableSendfile on - -# Supplemental configuration -# -# The configuration files in the conf/extra/ directory can be -# included to add extra features or to modify the default configuration of -# the server, or you may simply copy their contents here and change as -# necessary. - -# Server-pool management (MPM specific) -#Include conf/extra/httpd-mpm.conf - -# Multi-language error messages -#Include conf/extra/httpd-multilang-errordoc.conf - -# Fancy directory listings -#Include conf/extra/httpd-autoindex.conf - -# Language settings -#Include conf/extra/httpd-languages.conf - -# User home directories -#Include conf/extra/httpd-userdir.conf - -# Real-time info on requests and configuration -#Include conf/extra/httpd-info.conf - -# Virtual hosts -#Include conf/extra/httpd-vhosts.conf - -# Local access to the Apache HTTP Server Manual -#Include conf/extra/httpd-manual.conf - -# Distributed authoring and versioning (WebDAV) -#Include conf/extra/httpd-dav.conf - -# Various default settings -#Include conf/extra/httpd-default.conf - -# Configure mod_proxy_html to understand HTML4/XHTML1 - -Include conf/extra/proxy-html.conf - - -# Secure (SSL/TLS) connections -#Include conf/extra/httpd-ssl.conf -# -# Note: The following must must be present to support -# starting without SSL on platforms with no /dev/random equivalent -# but a statically compiled-in mod_ssl. -# - -SSLRandomSeed startup builtin -SSLRandomSeed connect builtin - - - -RedirectMatch "^/gemp-lotr-server/(.*)" "http://gemp_app/gemp-lotr-server/$1" \ No newline at end of file diff --git a/gemp-lotr/docker/readme.txt b/gemp-lotr/docker/readme.txt index 458ed5f7c..d0f3373aa 100644 --- a/gemp-lotr/docker/readme.txt +++ b/gemp-lotr/docker/readme.txt @@ -1,60 +1,70 @@ Welcome to the wonderful world of containerized installation! -Using Docker, all the fiddly installation details can be coded into scripts so that people like you looking to set up an instance of the software don't have to worry about the database, server, Java installation, and all the hokey prerequisites that go along with it. Just copy the files, open docker, run the docker-compose, and your instance is ready to be accessed. +Using Docker, all the fiddly setup and installation details can be coded into scripts so that people like you looking to set up an instance of the software don't have to worry about the database, server, Java installation, and all the hokey prerequisites that go along with it. Just copy the files, open docker, run the docker-compose, and your instance is ready to be accessed. -The current state of the docker files is somewhere just north of "shambles". There were a lot of quirks that had to be figured out, and so as a result the files here are very messy, and have a *ton* of commented-out versions of the code that didn't work. Eventually this will all be cleaned up, but for now take it as a statement of how many ways there are /not/ to create a container. -As a result, however, there are a few files that currently need to be modified with respect to the host's machine to get these to work. Nothing complicated, just pointing to the location of where some of the subfolders of gemp's source code are. -So let's get right into it. The entry point is the docker-compose.yml, which defines two containers and all of their interfaces that are exposed to the outside world and to each other. These files call gemp_app.Dockerfile and gemp_db.Dockerfile which are concerned with actually constructing the environments on these two containers. +The entry point is the docker-compose.yml YAML file, which defines two containers and all of their interfaces that are exposed to the outside world and to each other. These files call gemp_app.Dockerfile and gemp_db.Dockerfile which are concerned with actually constructing the environments on these two containers. -gemp_db is straightforward: it's a bare-bones linux instance using the official MariaDB docker image (MariaDB is a variant of MySQL, if you weren't aware). It hosts the gemp database and doesn't do anything else. +gemp_db is straightforward: it's a bare-bones linux instance using the official MariaDB docker image (MariaDB is a variant of MySQL). It hosts the gemp database and doesn't do anything else. -gemp_app is slightly more complicated. Gemp is a Java server, is built using Maven, and utilizes Apache to serve http. All of those have to be installed and available. Unfortunately, Gemp expects its environment to be slightly different from what the defaults of either the official Apache or Maven images create, so this image starts with the Alpine Linux image (which includes Apache) and frankensteins the rest together to get both Maven and Java installed properly. +gemp_app is slightly more complicated. Gemp is a Java server, is built using Maven, and utilizes Apache to serve http. All of those have to be installed and available in the arrangement that Gemp expects, so this image starts with the Alpine Linux image (which includes Apache) and frankensteins the rest together to get both Maven and Java installed properly. -That's probably enough background. Here is the checklist to actually getting it all to run: -1- install Docker (Docker Desktop if on Windows). If you are on Windows, make sure that when you install it you check all boxes that have Docker behave more like it does on Linux. If you're installing this on Linux, I assume you know more than I do about how to set it up properly. + + + +1- install Docker (Docker Desktop if on Windows). If you are on Windows, make sure that when you install it you check all boxes that have Docker behave like it's on Linux. If you're installing this on Linux, I assume you know more than I do about how to set it up properly. 2- install your container manager of choice. I would HIGHLY recommend portainer.io, which itself runs in a docker container and exposes itself as an interactable web page. This will give you a graphical readout of all your currently running containers, registered images, networks, volumes, and just about anything else you might want, PLUS have interactive command lines for when the GUI just doesn't cut it. The manager that comes with Docker Desktop by default is pretty much only just barely enough to run portainer with, so don't bother with it otherwise. -3- pull the git repository down to your host machine and put it where you want the code to go. You will not be able to easily move this later, so choose a spot you want to work with permanently. Git repo here: https://github.com/ketura/gemp-lotr +3- pull the git repository down to your host machine; you may have already done this. -4- navigate to gemp-lotr/gemp-lotr/docker. There are some modifications that will need to be made before you can actually boot up the containers. +4- navigate to gemp-lotr/gemp-lotr/docker. Open up docker-compose.yml and change the defaults to suit your needs: -5- open up docker-compose.yml. Every location that you see an X:/Projects/... hard-coded absolute file path you will need to replace with your own hard-coded absolute file path to the corresponding locations. It should be possible later to modify this to be a relative path and no longer require this step, but for now absolute paths are required. There are 4 lines that need edited, three under gemp_app and one under gemp_db. Don't forget to save. + 4A- Note all the relative paths under each volume/source: these are all paths on your host system. If you want e.g. the database to be in a different location than what's listed, alter these relative paths to something else on your host system. -6- open a command line and navigate to the location you placed gemp-lotr, and navigate to gemp-lotr/gemp-lotr/docker. Run the following command: + 4B- under db/environment, note all of the username/password fields. If you are hosting this for something other than personal development, be sure to change all of these to something else. + + 4C- note the two "published" ports: 1337 for the app, and 3307 for the db. These are the ports that you will be accessing the site with (and the db if you connect with a database manager). If you are hosting this for something other than personal development, consider changing these to something else. DO NOT change the "target" ports. + +5- If you changed SQL credentials in step 4, navigate to gemp-lotr/gemp-lotr/gemp-lotr-commond/src/main/resources/ and open gemp-lotr.properties: + + 5A- DO NOT CHANGE the ports here. These ports listed are the "target" ports in step 4C, which you didn't edit because you followed the big "DO NOT" imperative. + + 5B- edit the db.connection.username and db.connection.password items to match the credentials you set in step 4B. + + 5C- note the origin.allowed.pattern. It is set to allow all connections, but if you are hosting this for something other than personal development, consider changing this to match your DNS hostname exactly. + +6- open a command line and navigate to gemp-lotr/gemp-lotr/docker. Run the following command: docker-compose up -d You should see "Starting gemp_app....done" and "Starting gemp_db....done" at the very end. This process will take a while the first time you do it, and will be near instantaneous every time after. -7- the database should have automatically created the gemp databases that are needed. You can verify this by connecting to the database on your host machine with your DB manager of choice (I recommend DBeaver). It is exposed on localhost:3307 and uses the user/pass of gempuser/gemppassword. If you can see the gemp_db database with league_participation and other tables, you're golden. - -Otherwise, run the script at gemp-lotr/gemp-lotr/database_script.sql manually in your database manager. This should not be necessary though and is an indication of a problem if it is. +7- the database should have automatically created the gemp databases that are needed. You can verify this by connecting to the database on your host machine with your DB manager of choice (I recommend DBeaver). It is exposed on localhost:3307 (unless you changed this port in step 4C) and uses the user/pass of gempuser/gemppassword (unless you changed this in step 4B). If you can see the gemp_db database with league_participation and other tables, you're golden. 8- Now we need to compile the gemp code. To do this, open a command line session in the gemp_app container (if using portainer.io, then log in, select your 'Local' endpoint, click the Containers tab on the left, click the >_ icon next to gemp_app, then click the Connect button). -Navigate to the gemp codebase (which is bound to the path on your host machine that you edited in step 5): + Navigate to the gemp codebase (which is bound to the path on your host machine that you edited in step 5): - cd etc/gemp-lotr + cd etc/gemp-lotr -Now tell Maven to compile the project: + Now tell Maven to compile the project: - mvn install + mvn install + + This process will take upwards of 5-10 minutes. You should see a green "BUILD SUCCESS" when it is successfully done. In portainer.io or another rich command line context, you should see lots of red text if it failed. + +9- open gemp-lotr/gemp-lotr/docker/docker-compose.yml again, and uncomment line 35 (the "command" line). This will ensure that the container runs the gemp server every time it is started automatically. + +10- Navigate in a command line on your host machine to gemp-lotr/gemp-lotr/docker and run the following commands: + + docker-compose down + docker-compose up -d -This process will take upwards of 5-10 minutes. You should see a green "BUILD SUCCESS" when it is successfully done. In portainer.io or another rich command line context, you should see lots of red text if it failed. - -9- At this point the gemp server needs to be ran. You could run the jar file directly in your command line session, but I find that this is sensitive to you closing that session. Instead, we'll shut the docker container down and bring it back up, as the docker-compose is set up to run the appropriate jar command on startup and leave it up in the background. - -Navigate in a command line on your host machine to gemp-lotr/gemp-lotr/docker and run the following commands: - - docker-compose down - docker-compose up -d - -10- if all has gone as planned, you should now be able to navigate to your own personal instance of Gemp. Open your browser of choice and navigate to http://localhost:1337/gemp-lotr/ . (If you need a different port to be bound to, then repeat step 5 and edit the exposed port.) +11- if all has gone as planned, you should now be able to navigate to your own personal instance of Gemp. Open your browser of choice and navigate to http://localhost:1337/gemp-lotr/ . (If you need a different port to be bound to, then repeat step 5 and edit the exposed port.) If you're presented with the home page, register a new user and log in. It's possible for the login page to present but login itself to fail if configured incorrectly, so don't celebrate until you see the (empty) lobby. If you get that far, then congrats, you now have a working local version of Gemp. @@ -65,42 +75,3 @@ If you're presented with the home page, register a new user and log in. It's pos At this point, editing the code is a matter of changing the files on your local machine and re-running step 8. As you have seen how long a process this is, choose carefully what you edit. - -The rest of this document may be safely ignored and is only in place to preserve the original documentation I received on how to get gemp to run. The information in this post is useful but has already been incorporated into the docker files and does not need to be performed manually. - - -~~~~~~~~~~~~~~ - - -Yeah, I've set up a low-key instance to test bug fixes and some new features: http://[REDACTED-IP]/gemp-lotr/ - -This guide is to roughly set up one of your own, but you can also submit changes to me and I'll reset afterwards. Really depends on what you want to do, I guess. I typed this up a while back for someone with less experience than you and made some changes, so it's possible some sections are way over-explained and others got edited into confusion :P - -Gemp's file structure expects Apache, so if you don't already have Linus available to you somewhere (could work on a Mac I guess) you'll want to do that. Easiest way IMO would be to install a distro on a flash drive, but you seem in-the-know enough to get dual boot going if you wanted. You can download Gemp from Github, although taking the day or two to learn Git and do it from the command line will pay off. - -Once you've got that, you'll need to install the Java Development Kit and some IDE or build tool. MarcinS uses Maven (and so do I), you can read the "Download, Install, Run Maven" guides here: https://maven.apache.org/. You also need to install SQL for the database. There's not much that needs to be done with this, it's kind of "set up and forget" so I've forgotten many of the details haha. MariaDB came standard on the OS I'm using, which appears to be a version of MySQL. Once you set it all up, you'll need to run "database_script.sql" in gemp-lotr/gemp-lotr/ to create the database that will store decks, user information, etc. - -Now that you've got everything ready, go to gemp-lotr/gemp-lotr/gemp-lotr-common/src/main/resources/gemp-lotr.properties and change it this way (my comments are in parenthesis): - - -## Application root, used for example for storing replay files -application.root=/etc/gemp-lotr (Should point to wherever you installed the source files) - -## DB connection -db.connection.class=org.gjt.mm.mysql.Driver -db.connection.url=jdbc:mysql://localhost/gemp-lotr -db.connection.username=gemp-lotr (whatever you set the SQL username to) -db.connection.password=gemp-lotr (whatever you set the SQL password to) -db.connection.validateQuery=/* ping */ select 1 - -port=80 -web.path=/env/gemp-lotr/web/ (change this to wherever the /web/ folder is on your computer. I kept mine in .../gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web/, but technically it's more secure to move the web files to its own location) -card.path= .../gemp-lotr/gemp-lotr/gemp-lotr-async/src/main/web/cards/ (this line you'll need to add, since MarcinS is currently moving all of the cards from one format to another) - - - -The stage is set, now the server has to be compiled. Open up the command line and navigate to the folder gemp-lotr/gemp-lotr/. The command "sudo mvn install" will compile all of the code of the server. This should not fail, since you haven't made any changes to the java. You should be able to start the server now. I do it from the command line, "sudo java -jar .../gemp-lotr/gemp-lotr/gemp-lotr-async/target/web.jar" (Maven will create the folder "/target/" for you). If you get the message "No appenders could be found for logger," just ignore it -- as long as that's the only error, that means it is working. - -If everything worked, you can open up a browser and go to "localhost/gemp-lotr" and see the Gemp server. I've gone through this process a few times trying to get everything to work, but not recently. Let me know if you hit any snags and I'll figure out what I forgot to mention. I've also been rooting around the code for a while now, if you need help on that front. I recommend using Git to keep track of it all, I did everything on Github for a while and you don't notice how much extra work you're doing until you stop doing it. Git makes it so much easier, if you're planning on sticking with this for any length of time I'd advise you (again) to figure that out. It's really not too hard, I just use a handful of commands and the world is a simpler place for it. - -Cheers!ā˜ŗā˜»ā™„ From 8ba8c6fd1ff1ecae68d023dc453c244b8f132f71 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 5 Jan 2021 21:07:49 -0600 Subject: [PATCH 04/74] Default docker config changes and startup improvements Altered the default configuration to be more compatible with parallel installations out-of-the-box. Added a SQL script that runs when the database is first created to add a pair of default users. --- gemp-lotr/docker/docker-compose.yml | 22 +++++++++++----------- gemp-lotr/docker/gemp.env | 1 - gemp-lotr/docker/gemp_db.Dockerfile | 2 +- gemp-lotr/docker/initial_user_setup.sql | 17 +++++++++++++++++ gemp-lotr/docker/readme.txt | 4 ++-- 5 files changed, 31 insertions(+), 15 deletions(-) delete mode 100644 gemp-lotr/docker/gemp.env create mode 100644 gemp-lotr/docker/initial_user_setup.sql diff --git a/gemp-lotr/docker/docker-compose.yml b/gemp-lotr/docker/docker-compose.yml index 171b755ff..5359eb1a9 100644 --- a/gemp-lotr/docker/docker-compose.yml +++ b/gemp-lotr/docker/docker-compose.yml @@ -4,7 +4,7 @@ services: build: - container_name: gemp_app + container_name: gemp_app_1 build: context: . dockerfile: gemp_app.Dockerfile @@ -17,7 +17,7 @@ services: # target means in the container - target: 80 # published is what's on the host machine - published: 1337 + published: 17001 volumes: - type: bind source: ../gemp-lotr-async/src/main/web @@ -29,14 +29,14 @@ services: source: ../gemp-lotr-async/src/main/web target: /var/www/localhost/htdocs/gemp-lotr #/etc/apache2/htdocs/gemp-lotr networks: - gemp_net: - ipv4_address: 172.28.1.1 + gemp_net_1: + ipv4_address: 172.28.1.2 tty: true - command: nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & + #command: nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & db: - container_name: gemp_db + container_name: gemp_db_1 build: context: .. dockerfile: docker/gemp_db.Dockerfile @@ -45,15 +45,15 @@ services: # target means in the container - target: 3306 # published is what's on the host machine - published: 3307 + published: 35001 restart: always volumes: - type: bind source: ../../database target: /var/lib/mysql networks: - gemp_net: - ipv4_address: 172.28.1.2 + gemp_net_1: + ipv4_address: 172.28.1.3 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: gemp_db @@ -62,8 +62,8 @@ services: networks: - gemp_net: + gemp_net_1: ipam: driver: default config: - - subnet: 172.28.0.0/16 \ No newline at end of file + - subnet: 172.28.1.0/16 \ No newline at end of file diff --git a/gemp-lotr/docker/gemp.env b/gemp-lotr/docker/gemp.env deleted file mode 100644 index aa185ea04..000000000 --- a/gemp-lotr/docker/gemp.env +++ /dev/null @@ -1 +0,0 @@ -COMPOSE_PROJECT_NAME=gemp-lotr-sandbox \ No newline at end of file diff --git a/gemp-lotr/docker/gemp_db.Dockerfile b/gemp-lotr/docker/gemp_db.Dockerfile index b18d1f928..9693eb717 100644 --- a/gemp-lotr/docker/gemp_db.Dockerfile +++ b/gemp-lotr/docker/gemp_db.Dockerfile @@ -1,4 +1,4 @@ FROM mariadb AS MariaDB -#COPY ./database_script.sql /etc/gemp/database_script.sql COPY ./database_script.sql /docker-entrypoint-initdb.d +COPY ./docker/initial_user_setup.sql /docker-entrypoint-initdb.d diff --git a/gemp-lotr/docker/initial_user_setup.sql b/gemp-lotr/docker/initial_user_setup.sql new file mode 100644 index 000000000..886c09954 --- /dev/null +++ b/gemp-lotr/docker/initial_user_setup.sql @@ -0,0 +1,17 @@ +INSERT INTO player (name, password, type, last_login_reward, last_ip, create_ip) +VALUES ( + 'asdf', + 'f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b', + 'aut', + '20170101', + '192.168.50.1', + '192.168.50.1' +), +( + 'qwer', + 'f6f2ea8f45d8a057c9566a33f99474da2e5c6a6604d736121650e2730c6fb0a3', + 'aut', + '20170101', + '192.168.50.1', + '192.168.50.1' +); \ No newline at end of file diff --git a/gemp-lotr/docker/readme.txt b/gemp-lotr/docker/readme.txt index d0f3373aa..76fc72e40 100644 --- a/gemp-lotr/docker/readme.txt +++ b/gemp-lotr/docker/readme.txt @@ -27,7 +27,7 @@ gemp_app is slightly more complicated. Gemp is a Java server, is built using Ma 4B- under db/environment, note all of the username/password fields. If you are hosting this for something other than personal development, be sure to change all of these to something else. - 4C- note the two "published" ports: 1337 for the app, and 3307 for the db. These are the ports that you will be accessing the site with (and the db if you connect with a database manager). If you are hosting this for something other than personal development, consider changing these to something else. DO NOT change the "target" ports. + 4C- note the two "published" ports: 17001 for the app, and 35001 for the db. These are the ports that you will be accessing the site with (and the db if you connect with a database manager). If you are hosting this for something other than personal development, consider changing these to something else. DO NOT change the "target" ports. 5- If you changed SQL credentials in step 4, navigate to gemp-lotr/gemp-lotr/gemp-lotr-commond/src/main/resources/ and open gemp-lotr.properties: @@ -64,7 +64,7 @@ You should see "Starting gemp_app....done" and "Starting gemp_db....done" at the docker-compose down docker-compose up -d -11- if all has gone as planned, you should now be able to navigate to your own personal instance of Gemp. Open your browser of choice and navigate to http://localhost:1337/gemp-lotr/ . (If you need a different port to be bound to, then repeat step 5 and edit the exposed port.) +11- if all has gone as planned, you should now be able to navigate to your own personal instance of Gemp. Open your browser of choice and navigate to http://localhost:17001/gemp-lotr/ . (If you need a different port to be bound to, then repeat step 5 and edit the exposed port.) If you're presented with the home page, register a new user and log in. It's possible for the login page to present but login itself to fail if configured incorrectly, so don't celebrate until you see the (empty) lobby. If you get that far, then congrats, you now have a working local version of Gemp. From f6493a1ecde320c4215494a6fa926646639d04a8 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 6 Jan 2021 00:15:56 -0600 Subject: [PATCH 05/74] Checking in stubs for the FOTR starter supplements Added set 21, which is intended to represent set 1+. Added this set to the card builder. Added a PC FOTR format. Updated the Race enum to include Warg. --- .../gemp-lotr-async/src/main/web/ban.html | 1 + .../src/main/web/cards/set21/set21.json | 391 ++++++++++++++++++ .../src/main/web/deckBuild.html | 1 + .../gemp-lotr-async/src/main/web/game.html | 1 + .../gemp-lotr-async/src/main/web/hall.html | 1 + .../gemp-lotr-async/src/main/web/index.html | 1 + gemp-lotr/gemp-lotr-async/src/main/web/js.inc | 1 + .../src/main/web/js/gemp-022/cardFilter.js | 2 + .../src/main/web/js/gemp-022/jCards.js | 3 + .../src/main/web/js/gemp-022/set21.js | 49 +++ .../src/main/web/leagueAdmin.html | 1 + .../src/main/web/merchant.html | 1 + .../src/main/web/soloDraft.html | 1 + .../src/main/resources/set21-rarity.txt | 47 +++ .../src/main/resources/setConfig.json | 9 + .../java/com/gempukku/lotro/common/Race.java | 5 +- .../src/main/resources/lotrFormats.json | 8 + 17 files changed, 522 insertions(+), 1 deletion(-) create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/ban.html b/gemp-lotr/gemp-lotr-async/src/main/web/ban.html index 5a5218a9b..678ed27a3 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/ban.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/ban.html @@ -36,6 +36,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json new file mode 100644 index 000000000..4757bb708 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json @@ -0,0 +1,391 @@ +{ + "21_1": { + "title": "Blue Mountain Dwarf", + "culture": "dwarven", + "type": "companion", + "race": "dwarf", + "cost": 2, + "strength": 6, + "vitality": 2 + }, + "21_2": { + "title": "Stand Together", + "culture": "gandalf", + "type": "event", + "keyword": "maneuver", + "cost": 3 + }, + "21_3": { + "title": "Thrice Worthy and Beloved Barliman", + "culture": "gandalf", + "type": "condition", + "cost": 0, + "strength": 1 + }, + "21_4": { + "title": "Gondorian Broadsword", + "culture": "gondor", + "type": "possession", + "possession": "hand weapon", + "cost": 2, + "strength": 2 + }, + "21_5": { + "title": "Relics of the Second Age", + "culture": "gondor", + "type": "condition", + "keyword": "support area", + "cost": 1 + }, + "21_6": { + "title": "Thrown Sword", + "culture": "gondor", + "type": "event", + "keyword": "skirmish", + "cost": 1 + }, + "21_7": { + "title": "Lurtz", + "subtitle": "Weapon of Saruman", + "culture": "isengard", + "type": "minion", + "race": "uruk-hai", + "cost": 7, + "strength": 12, + "vitality": 3, + "site": 5 + }, + "21_8": { + "title": "Strength of Servitude", + "culture": "isengard", + "type": "event", + "keyword": "response", + "cost": 1 + }, + "21_9": { + "title": "Uruk Swarmer", + "culture": "isengard", + "type": "minion", + "race": "uruk-hai", + "cost": 3, + "strength": 6, + "vitality": 2, + "site": 5 + }, + "21_10": { + "title": "Goblin Bow", + "culture": "moria", + "type": "possession", + "possession": "ranged weapon", + "cost": 1, + "strength": 1, + "vitality": 1 + }, + "21_11": { + "title": "Goblin Warchief", + "subtitle": "Captain of the Underhall", + "culture": "moria", + "type": "minion", + "race": "orc", + "cost": 4, + "strength": 9, + "vitality": 2, + "site": 4 + }, + "21_12": { + "title": "No Hope of Escape That Way", + "culture": "moria", + "type": "event", + "keyword": "maneuver", + "cost": 1 + }, + "21_13": { + "title": "The Old Forest", + "culture": "wraith", + "type": "condition", + "keyword": "support area", + "cost": 0 + }, + "21_14": { + "title": "Old Man Willow", + "subtitle": "Heart of the Withywindle", + "culture": "wraith", + "type": "minion", + "race": "tree", + "cost": 3, + "strength": 2, + "vitality": 6, + "site": 2 + }, + "21_15": { + "title": "And in the Darkness Bind Them", + "culture": "sauron", + "type": "condition", + "keyword": "support area", + "cost": 0 + }, + "21_16": { + "title": "Gladden Ambush", + "culture": "sauron", + "type": "event", + "keyword": "maneuver", + "cost": 0 + }, + "21_17": { + "title": "Bilbo", + "subtitle": "One Hundred and Eleventy", + "culture": "shire", + "type": "ally", + "race": "hobbit", + "cost": 2, + "strength": 2, + "vitality": 3, + "allyHome": "fellowship,1" + }, + "21_18": { + "title": "Hobbit Concealment", + "culture": "shire", + "type": "condition", + "keyword": "support area", + "cost": 1 + }, + "21_19": { + "title": "Sam", + "subtitle": "Hobbit of Hobbiton", + "culture": "shire", + "type": "companion", + "race": "hobbit", + "cost": 2, + "strength": 3, + "vitality": 4, + "signet": "frodo" + }, + "21_20": { + "title": "Walking Stick", + "culture": "shire", + "type": "possession", + "possession": "staff", + "strength": 0 + }, + "21_21": { + "title": "Barred the Gates", + "culture": "dwarven", + "type": "condition", + "keyword": "support area", + "cost": 0 + }, + "21_22": { + "title": "Light-shaft", + "culture": "dwarven", + "type": "event", + "keyword": "regroup", + "cost": 0 + }, + "21_23": { + "title": "Longbeard's Axe", + "culture": "dwarven", + "type": "possession", + "possession": "hand weapon", + "cost": 1, + "strength": 2 + }, + "21_24": { + "title": "Venturing Dwarf", + "culture": "dwarven", + "type": "companion", + "race": "dwarf", + "cost": 2, + "strength": 5, + "vitality": 3 + }, + "21_25": { + "title": "Dazzling Flash", + "culture": "gandalf", + "type": "event", + "keyword": "skirmish", + "cost": 1 + }, + "21_26": { + "title": "No Time for Wonder", + "culture": "gandalf", + "type": "condition", + "keyword": "support area", + "cost": 1 + }, + "21_27": { + "title": "Dagger of Westernesse", + "culture": "gondor", + "type": "artifact", + "possession": "hand weapon", + "cost": 0, + "strength": 2 + }, + "21_28": { + "title": "Goblin Avengers", + "culture": "moria", + "type": "minion", + "race": "orc", + "cost": 7, + "strength": 13, + "vitality": 3, + "site": 4 + }, + "21_29": { + "title": "Goblin Warren", + "culture": "moria", + "type": "condition", + "keyword": "support area", + "cost": 1 + }, + "21_30": { + "title": "Thither We Are Going Against My Wish", + "culture": "moria", + "type": "condition", + "keyword": "support area", + "cost": 1 + }, + "21_31": { + "title": "Hollin Snarler", + "culture": "sauron", + "type": "minion", + "race": "warg", + "cost": 3, + "strength": 8, + "vitality": 2, + "site": 3 + }, + "21_32": { + "title": "The Hunt is Up!", + "culture": "sauron", + "type": "condition", + "keyword": "support area", + "cost": 1 + }, + "21_33": { + "title": "Hunting Pack", + "culture": "sauron", + "type": "minion", + "race": "warg", + "cost": 5, + "strength": 11, + "vitality": 3, + "site": 5 + }, + "21_34": { + "title": "Pippin", + "subtitle": "Fool of a Took", + "culture": "shire", + "type": "companion", + "race": "hobbit", + "cost": 1, + "strength": 3, + "vitality": 4, + "signet": "gandalf" + }, + "21_35": { + "title": "Deft Aid", + "culture": "elven", + "type": "condition", + "site": 1 + }, + "21_36": { + "title": "Elven Flet", + "culture": "elven", + "type": "condition", + "keyword": "support area", + "cost": 1 + }, + "21_37": { + "title": "In Imladris it Dwells", + "culture": "elven", + "type": "event", + "keyword": "fellowship", + "cost": 0 + }, + "21_38": { + "title": "Rivendell Sentry", + "culture": "elven", + "type": "ally", + "race": "elf", + "cost": 2, + "strength": 5, + "vitality": 2, + "allyHome": "fellowship,4" + }, + "21_39": { + "title": "Arroch", + "culture": "gondor", + "type": "possession", + "possession": "mount", + "cost": 2, + "vitality": 1 + }, + "21_40": { + "title": "The Deeds of the Steward's House", + "culture": "gondor", + "type": "condition", + "keyword": "support area", + "cost": 2 + }, + "21_41": { + "title": "They Have a Cave Troll", + "culture": "gondor", + "type": "event", + "keyword": "maneuver", + "cost": 1 + }, + "21_42": { + "title": "Isengard Attendant", + "culture": "isengard", + "type": "minion", + "race": "orc", + "cost": 3, + "strength": 7, + "vitality": 2, + "site": 4 + }, + "21_43": { + "title": "Stirruk", + "culture": "isengard", + "type": "possession", + "possession": "hand weapon", + "cost": 1, + "strength": 3, + "vitality": 1 + }, + "21_44": { + "title": "Uruk Batch", + "culture": "isengard", + "type": "minion", + "race": "uruk-hai", + "cost": 3, + "strength": 7, + "vitality": 2, + "site": 5 + }, + "21_45": { + "title": "Influence of Shadow", + "culture": "sauron", + "type": "condition", + "keyword": "support area", + "cost": 0 + }, + "21_46": { + "title": "Tower Shaman", + "culture": "sauron", + "type": "minion", + "race": "orc", + "cost": 4, + "strength": 6, + "vitality": 3, + "site": 6 + }, + "21_47": { + "title": "Udun Scimitar", + "culture": "sauron", + "type": "possession", + "possession": "hand weapon", + "cost": 2, + "strength": 2 + }, +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html b/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html index 5bb640b4e..27c54a446 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html @@ -30,6 +30,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/game.html b/gemp-lotr/gemp-lotr-async/src/main/web/game.html index 7b4981d5a..ed5410d77 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/game.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/game.html @@ -30,6 +30,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html index 381faa6eb..d76529500 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html @@ -29,6 +29,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/index.html b/gemp-lotr/gemp-lotr-async/src/main/web/index.html index 0af95ee9f..5e86924b8 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/index.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/index.html @@ -39,6 +39,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js.inc b/gemp-lotr/gemp-lotr-async/src/main/web/js.inc index caca3b4a3..ea0607081 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js.inc +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js.inc @@ -22,6 +22,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js index 9ac4955d9..a8bdc1ae3 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js @@ -110,6 +110,7 @@ var CardFilter = Class.extend({ + "" + "" + "" + + "" + "" + "" + "" @@ -144,6 +145,7 @@ var CardFilter = Class.extend({ + "" + "" + "" + + "" + "" + "" + "" diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js index ddaba1044..12c9bd154 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js @@ -215,6 +215,9 @@ var Card = Class.extend({ return img; //Additional Hobbit Draft blueprints img = hobbit[blueprintId]; + if (img != null) + return img; + img = set21[blueprintId]; if (img != null) return img; return null; diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js new file mode 100644 index 000000000..48913b329 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -0,0 +1,49 @@ +var set21 = { + '21_1': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_1.jpg', + '21_2': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_2.jpg', + '21_3': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_3.jpg', + '21_4': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_4.jpg', + '21_5': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_5.jpg', + '21_6': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_6.jpg', + '21_7': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_7.jpg', + '21_8': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_8.jpg', + '21_9': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_9.jpg', + '21_10': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_10.jpg', + '21_11': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_11.jpg', + '21_12': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_12.jpg', + '21_13': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_13.jpg', + '21_14': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_14.jpg', + '21_15': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_15.jpg', + '21_16': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_16.jpg', + '21_17': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_17.jpg', + '21_18': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_18.jpg', + '21_19': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_19.jpg', + '21_20': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_20.jpg', + '21_21': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_21.jpg', + '21_22': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_22.jpg', + '21_23': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_23.jpg', + '21_24': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_24.jpg', + '21_25': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_25.jpg', + '21_26': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_26.jpg', + '21_27': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_27.jpg', + '21_28': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_28.jpg', + '21_29': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_29.jpg', + '21_30': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_30.jpg', + '21_31': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_31.jpg', + '21_32': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_32.jpg', + '21_33': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_33.jpg', + '21_34': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_34.jpg', + '21_35': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_35.jpg', + '21_36': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_36.jpg', + '21_37': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_37.jpg', + '21_38': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_38.jpg', + '21_39': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_39.jpg', + '21_40': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_40.jpg', + '21_41': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_41.jpg', + '21_42': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_42.jpg', + '21_43': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_43.jpg', + '21_44': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_44.jpg', + '21_45': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_45.jpg', + '21_46': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_46.jpg', + '21_47': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_47.jpg' +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html b/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html index 8d063c3c1..0fd83d3f2 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html @@ -44,6 +44,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html b/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html index 6d7efd7cd..3d510efa5 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html @@ -30,6 +30,7 @@ + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html b/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html index 6fb0573cc..c5199004f 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html @@ -30,6 +30,7 @@ + diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt new file mode 100644 index 000000000..e72c611a9 --- /dev/null +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt @@ -0,0 +1,47 @@ +21S1 +21S2 +21S3 +21S4 +21S5 +21S6 +21S7 +21S8 +21S9 +21S10 +21S11 +21S12 +21S13 +21S14 +21S15 +21S16 +21S17 +21S18 +21S19 +21S20 +21S21 +21S22 +21S23 +21S24 +21S25 +21S26 +21S27 +21S28 +21S29 +21S30 +21S31 +21S32 +21S33 +21S34 +21S35 +21S36 +21S37 +21S38 +21S39 +21S40 +21S41 +21S42 +21S43 +21S44 +21S45 +21S46 +21S47 \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json b/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json index 03ba11955..fbdd65f9b 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json @@ -146,5 +146,14 @@ "merchantable": false, "needsLoading": false, "playable": false + }, + { + "setId": "21", + "setName": "PC FOTR Supplements", + "rarityFile": "/set21-rarity.txt", + "originalSet": false, + "merchantable": false, + "needsLoading": false, + "playable": true } ] diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Race.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Race.java index 185c438a3..9e96a814d 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Race.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Race.java @@ -7,7 +7,10 @@ public enum Race implements Filterable { GOBLIN("Goblin"), //Additional Hobbit Draft races - DRAGON("Dragon"), EAGLE("Eagle"), BIRD("Bird"); + DRAGON("Dragon"), EAGLE("Eagle"), BIRD("Bird"), + + //PC Races + WARG("Warg"); private String _humanReadable; diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json index 5394e088c..c65e7fd28 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json @@ -402,5 +402,13 @@ "maximumSameName":100, "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "hall":false + }, + { + "name":"PC-Fellowship Block", + "code":"pc_fotr_block", + "sites":"FELLOWSHIP", + "cancelRingBearerSkirmish":true, + "set":[1, 2, 3, 21], + "banned":["1_1"] } ] From 89749672baa9ed981a6a84ea232a25fca19cdfc0 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 9 Jan 2021 02:12:21 -0600 Subject: [PATCH 06/74] Altered docker compose file to be parameterized. --- gemp-lotr/docker/.env | 15 ++++++++++++++ gemp-lotr/docker/docker-compose.yml | 32 ++++++++++++++--------------- 2 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 gemp-lotr/docker/.env diff --git a/gemp-lotr/docker/.env b/gemp-lotr/docker/.env new file mode 100644 index 000000000..3c530844d --- /dev/null +++ b/gemp-lotr/docker/.env @@ -0,0 +1,15 @@ +SERVID=1 +COMPOSE_PROJECT_NAME=gemp_${SERVID} + +APP_CONTAINER_NAME=gemp_app_${SERVID} +APP_IP=172.28.${SERVID}.2 +APP_PORT=17001 + +DB_CONTAINER_NAME=gemp_db_${SERVID} +DB_IP=172.28.${SERVID}.3 +DB_PORT=35001 + +MYSQL_ROOT_PASSWORD=rootpass +MYSQL_DATABASE=gemp_db +MYSQL_USER=gempuser +MYSQL_PASSWORD=gemppassword \ No newline at end of file diff --git a/gemp-lotr/docker/docker-compose.yml b/gemp-lotr/docker/docker-compose.yml index 5359eb1a9..6a75c7b30 100644 --- a/gemp-lotr/docker/docker-compose.yml +++ b/gemp-lotr/docker/docker-compose.yml @@ -1,10 +1,11 @@ version: "3.4" services: - - + build: - container_name: gemp_app_1 + env_file: + - .env + container_name: ${APP_CONTAINER_NAME} build: context: . dockerfile: gemp_app.Dockerfile @@ -17,7 +18,7 @@ services: # target means in the container - target: 80 # published is what's on the host machine - published: 17001 + published: "${APP_PORT}" volumes: - type: bind source: ../gemp-lotr-async/src/main/web @@ -29,14 +30,16 @@ services: source: ../gemp-lotr-async/src/main/web target: /var/www/localhost/htdocs/gemp-lotr #/etc/apache2/htdocs/gemp-lotr networks: - gemp_net_1: - ipv4_address: 172.28.1.2 + gemp_net: + ipv4_address: ${APP_IP} tty: true #command: nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & db: - container_name: gemp_db_1 + env_file: + - .env + container_name: ${DB_CONTAINER_NAME} build: context: .. dockerfile: docker/gemp_db.Dockerfile @@ -45,25 +48,20 @@ services: # target means in the container - target: 3306 # published is what's on the host machine - published: 35001 + published: "${DB_PORT}" restart: always volumes: - type: bind source: ../../database target: /var/lib/mysql networks: - gemp_net_1: - ipv4_address: 172.28.1.3 - environment: - MYSQL_ROOT_PASSWORD: rootpass - MYSQL_DATABASE: gemp_db - MYSQL_USER: gempuser - MYSQL_PASSWORD: gemppassword + gemp_net: + ipv4_address: ${DB_IP} networks: - gemp_net_1: + gemp_net: ipam: driver: default config: - - subnet: 172.28.1.0/16 \ No newline at end of file + - subnet: 172.28.0.0/16 \ No newline at end of file From 15646a9cf72e4bd2ce53495cdf2b5daff86c93e6 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 22 Jan 2021 02:05:14 -0600 Subject: [PATCH 07/74] Testing concealed inclusion --- .../src/main/web/cards/set21/set1-errata.json | 118 ++++++++++++++++ .../src/main/web/cards/set21/set21.json | 128 +++++++++++++++++- .../com/gempukku/lotro/common/Keyword.java | 5 +- .../lotro/logic/modifiers/ModifiersLogic.java | 5 +- 4 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json new file mode 100644 index 000000000..420a0d02a --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -0,0 +1,118 @@ +{ + "21_1040": { + "title": "*Elrond", + "subtitle": "Lord of Rivendell", + "culture": "elven", + "cost": 4, + "type": "ally", + "allyHome": "fellowship,3", + "race": "elf", + "strength": 8, + "vitality": 4, + "condition": { + "type": "canSpot", + "filter": "or(name(Gandalf),elf)" + }, + "effects": [ + { + "type": "trigger", + "trigger": { + "type": "startOfTurn" + }, + "effect": { + "type": "heal", + "filter": "choose(ally,allyHome(fellowship,3))", + "count": 2 + } + }, + { + "type": "activated", + "phase": "fellowship", + "cost": { + "type": "exert", + "filter": "self", + "times": 2 + }, + "effect": { + "type": "drawCards" + } + } + ] + }, + "21_1045": { + "title": "*Galadriel", + "subtitle": "Lady of Light", + "culture": "elven", + "cost": 3, + "type": "ally", + "allyHome": "fellowship,6", + "race": "elf", + "strength": 3, + "vitality": 3, + "effects": [ + { + "type": "trigger", + "trigger": { + "type": "startOfTurn" + }, + "effect": { + "type": "heal", + "filter": "choose(ally,allyHome(fellowship,6))", + "count": 2 + } + }, + { + "type": "activated", + "phase": "fellowship", + "cost": { + "type": "exert", + "filter": "self", + "times": 2 + }, + "effect": { + "type": "play", + "filter": "choose(elf)", + "cost": -2 + } + } + ] + }, + "21_1080": { + "title": "*Ottar", + "subtitle": "Man of Laketown", + "culture": "gandalf", + "cost": 1, + "type": "ally", + "allyHome": "fellowship,3", + "race": "man", + "strength": 2, + "vitality": 2, + "condition": { + "type": "canSpot", + "filter": "name(Gandalf)" + }, + "effects": { + "type": "activated", + "phase": "fellowship", + "cost": { + "type": "exert", + "filter": "self" + }, + "effect": [ + { + "type": "discardFromHand", + "forced": false, + "count": "0-3", + "memorize": "discardedCards" + }, + { + "type": "drawCards", + "count": { + "type": "forEachInMemory", + "memory": "discardedCards" + } + } + ] + } + }, +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json index 4757bb708..b221e8741 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json @@ -6,21 +6,72 @@ "race": "dwarf", "cost": 2, "strength": 6, - "vitality": 2 + "vitality": 2, + "resistance": 6, + "keyword": "damage+1", + "effects": { + "type": "extraCost", + "cost":{ + "type": "addBurdens", + "amount": { + "type": "condition", + "condition": { + "type": "canSpot", + "filter": "name(Bilbo)" + }, + "true": 0, + "false": 1 + } + } + } }, "21_2": { "title": "Stand Together", "culture": "gandalf", + "cost": 3, "type": "event", "keyword": "maneuver", - "cost": 3 + "condition": { + "type": "canSpot", + "filter": "name(Gandalf)" + }, + "effects": { + "type": "event", + "cost": { + "type": "exert", + "filter": "choose(another,companion,or(signet(aragorn),signet(gandalf),signet(frodo),signet(theoden)))", + "memorize": "exertedCompanion" + }, + "effect": { + "type": "heal", + "filter": "choose(companion,not(memory(exertedCompanion)),or(signet(aragorn),signet(gandalf),signet(frodo),signet(theoden)))", + "times": 2 + } + } }, "21_3": { "title": "Thrice Worthy and Beloved Barliman", "culture": "gandalf", "type": "condition", "cost": 0, - "strength": 1 + "vitality": 1, + "target": "name(Barliman Butterbur)", + "effects": { + "type": "activatedTrigger", + "trigger": { + "type": "discarded", + "filter": "your,mount", + "memorize": "discardedCard" + }, + "cost": { + "type": "exert", + "filter": "bearer" + }, + "effect": { + "type": "putCardsFromDiscardOnTopOfDrawDeck", + "filter": "memory(discardedCard)" + } + } }, "21_4": { "title": "Gondorian Broadsword", @@ -28,21 +79,69 @@ "type": "possession", "possession": "hand weapon", "cost": 2, - "strength": 2 + "strength": 2, + "target": "culture(gondor),man", + "effects": { + "type": "activated", + "phase": "maneuver", + "cost": { + "type": "exert", + "filter": "bearer", + "times": 2 + }, + "effect": { + "type": "addKeyword", + "filter": "bearer", + "keyword": "defender+1", + "until": "start(regroup)" + } + } }, "21_5": { "title": "Relics of the Second Age", "culture": "gondor", "type": "condition", "keyword": "support area", - "cost": 1 + "cost": 1, + "effects": { + "type": "activated", + "phase": "regroup", + "cost": [ + { + "type": "revealCardsFromHand", + "filter": "choose(culture(gondor))", + "count": 2, + "memorize": "revealedCards" + }, + { + "type": "putCardsFromHandOnTopOfDeck", + "filter": "memory(revealedCards)" + } + ], + "effect": { + "type": "putCardsFromDiscardIntoHand", + "filter": "choose(culture(gondor))" + } + } }, "21_6": { "title": "Thrown Sword", "culture": "gondor", "type": "event", "keyword": "skirmish", - "cost": 1 + "cost": 1, + "effects": { + "type" : "event", + "cost": { + "type": "discard", + "filter": "choose(weapon,attachedTo(character,culture(gondor),man))" + }, + "effect": { + "type": "wound", + "filter": "choose(or(orc,uruk-hai),inSkirmishAgainst(another,companion,not(ring bearer)))", + "times": 2 + } + } }, "21_7": { "title": "Lurtz", @@ -53,7 +152,22 @@ "cost": 7, "strength": 12, "vitality": 3, - "site": 5 + "site": 5, + "keyword": [ + "archer", + "damage+1" + ], + "effects": { + "type": "modifier", + "modifier": { + "type": "modifyStrength", + "filter": "self", + "amount": { + "type": "forEachWound", + "filter": "self" + } + } + } }, "21_8": { "title": "Strength of Servitude", diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java index 48ff68dab..d3c94f221 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java @@ -30,7 +30,10 @@ public enum Keyword implements Filterable { WARG_RIDER("Warg-rider", true), BESIEGER("Besieger", true), CORSAIR("Corsair", true), //Additional Hobbit Draft keywords - WISE("Wise", true), BURGLAR("Burglar", true); + WISE("Wise", true), BURGLAR("Burglar", true), + + //PC Keywords + CONCEALED("Concealed", true); private String _humanReadable; private boolean _infoDisplayable; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java index 938d9394e..e9f66fa66 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java @@ -384,9 +384,12 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying { @Override public boolean addsTwilightForCompanionMove(LotroGame game, PhysicalCard companion) { - for (Modifier modifier : getModifiersAffectingCard(game, ModifierEffect.MOVE_TWILIGHT_MODIFIER, companion)) + for (Modifier modifier : getModifiersAffectingCard(game, ModifierEffect.MOVE_TWILIGHT_MODIFIER, companion)) { + if (hasKeyword(game, companion, Keyword.CONCEALED)) + return false; if (!modifier.addsTwilightForCompanionMove(game, companion)) return false; + } return true; } From 6ed561b89aae8568638fea52e3505715b05fb3ad Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 22 Jan 2021 12:40:51 -0600 Subject: [PATCH 08/74] Fixing server crash when a rarity is not provided for a card --- .../java/com/gempukku/lotro/game/SortAndFilterCards.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java index ce100c672..ea204c8f5 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java @@ -142,6 +142,11 @@ public class SortAndFilterCards { SetDefinition setRarity = rarities.get(blueprintId.substring(0, blueprintId.indexOf("_"))); if (setRarity != null) { String cardRarity = setRarity.getCardRarity(library.stripBlueprintModifiers(blueprintId)); + if(cardRarity == null) { + //TODO: log that the rarity was not set + //real TODO: put the rarity in the friggin json + return false; + } for (String r : rarity) { if (cardRarity.equals(r)) return true; From a5987b1a70ca31a1be079a34d6af21138162571e Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 22 Jan 2021 12:41:10 -0600 Subject: [PATCH 09/74] Fixing missing rarities for errata test --- .../src/main/web/cards/set21/set1-errata.json | 47 ++++++++++++++++++- .../src/main/resources/set21-rarity.txt | 6 ++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 420a0d02a..3ff9a7799 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -83,7 +83,7 @@ "culture": "gandalf", "cost": 1, "type": "ally", - "allyHome": "fellowship,3", + "allyHome": "fellowship,10", "race": "man", "strength": 2, "vitality": 2, @@ -115,4 +115,49 @@ ] } }, + "21_10108": { + "title": "*No Stranger to the Shadows", + "culture": "gondor", + "cost": 0, + "type": "condition", + "target": "ranger,not(hasAttached(name(No Stranger to the Shadows)))", + "effects": { + "type": "modifier", + "modifier": { + "type": "modifyCost", + "filter": "site", + "amount": -1 + } + } + }, + "21_10109": { + "title": "One Whom Men Would Follow", + "culture": "gondor", + "cost": 0, + "type": "event", + "keyword": "maneuver", + "effects": { + "type": "event", + "cost": { + "type": "exert", + "filter": "choose(name(Aragorn))" + }, + "effect": [ + { + "type": "modifyStrength", + "filter": "choose(ally)", + "amount": 2, + "until": "start(regroup)", + "memorize": "exertedAlly" + }, + { + "type": "allyCanParticipateInArcheryFireAndSkirmishes", + "filter": "memory(exertedAlly)", + "until": "start(regroup)" + } + ] + } + }, + + } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt index e72c611a9..6343ef996 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt @@ -44,4 +44,8 @@ 21S44 21S45 21S46 -21S47 \ No newline at end of file +21S47 +21S1040 +21S1045 +21S1080 +21S10108 From ef901ca9077080225ca66a77fb6f718f167cd3a2 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 24 Jan 2021 11:05:22 -0600 Subject: [PATCH 10/74] FOTR Errata Added all set 1 errata and a couple set 2 errata. Hooked up the images and rarities. --- .../src/main/web/cards/set21/set1-errata.json | 365 +++++++++++++++++- .../src/main/web/js/gemp-022/set21.js | 107 ++--- .../src/main/resources/set21-rarity.txt | 17 +- 3 files changed, 421 insertions(+), 68 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 3ff9a7799..9b87b5902 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -83,7 +83,7 @@ "culture": "gandalf", "cost": 1, "type": "ally", - "allyHome": "fellowship,10", + "allyHome": "fellowship,1", "race": "man", "strength": 2, "vitality": 2, @@ -120,44 +120,375 @@ "culture": "gondor", "cost": 0, "type": "condition", + "keyword": [ + "stealth" + ], "target": "ranger,not(hasAttached(name(No Stranger to the Shadows)))", "effects": { "type": "modifier", "modifier": { - "type": "modifyCost", - "filter": "site", - "amount": -1 + "type": "addKeyword", + "filter": "bearer", + "keyword": "concealed" } } }, - "21_10109": { - "title": "One Whom Men Would Follow", - "culture": "gondor", + + "21_10139": { + "title": "Savagery To Match Their Numbers", + "culture": "isengard", "cost": 0, "type": "event", - "keyword": "maneuver", + "keyword": "skirmish", + "effects": { + "type": "event", + "effect": { + "type": "choice", + "texts": [ + "Make an Uruk-hai strength +2", + "Make an Uruk-hai fierce until the regroup phase, and strength +4 (this skirmish)" + ], + "effects": [ + { + "type": "modifyStrength", + "filter": "choose(uruk-hai)", + "amount": 2 + }, + { + "type": "conditional", + "condition": { + "type": "canSpot", + "count": 5, + "filter": "companion" + }, + "effect": [ + { + "type": "modifyStrength", + "filter": "choose(uruk-hai)", + "amount": 4, + "memorize": "chosenUrukHai" + }, + { + "type": "addKeyword", + "filter": "memory(chosenUrukHai)", + "keyword": "fierce", + "until": "start(regroup)" + } + ] + } + ] + } + } + }, + + "21_10195": { + "title": "*Relics of Moria", + "culture": "moria", + "cost": 1, + "type": "condition", + "keyword": "support area", + "effects": { + "type": "activated", + "phase": "shadow", + "cost": { + "type": "removeTwilight", + "amount": 2 + }, + "effect": { + "type": "playCardFromDiscard", + "removedTwilight": 2, + "filter": "choose(culture(moria),possession)" + } + } + }, + + "21_10234": { + "title": "*ÚlairĆ« NertĆ«a", + "subtitle": "Messenger of Dol Guldur", + "culture": "wraith", + "cost": 4, + "type": "minion", + "race": "nazgul", + "strength": 9, + "vitality": 2, + "site": 3, + "effects": { + "type": "trigger", + "trigger": { + "type": "played", + "filter": "self" + }, + "effect": { + "type": "duplicate", + "amount": { + "type": "forEachYouCanSpot", + "filter": "companion", + "over": 4 + }, + "effect": { + "type": "optional", + "text": "Would you like to play minion from your discard?", + "effect": { + "type": "playCardFromDiscard", + "filter": "choose(nazgul)" + } + } + } + } + }, + + "21_10248": { + "title": "Forces of Mordor", + "culture": "sauron", + "cost": 0, + "type": "event", + "keyword": "shadow", "effects": { "type": "event", "cost": { "type": "exert", - "filter": "choose(name(Aragorn))" + "filter": "choose(culture(sauron),minion)" + }, + "cost": { + "type": "chooseHowManyToSpot", + "filter": "culture(sauron),minion", + "memorize": "spottedCount" + }, + "effect": { + "type": "addTwilight", + "amount": { + "type": "forEachYouCanSpot", + "filter": "culture(sauron),orc", + } + } + } + }, + + "21_10311": { + "title": "*Sam", + "subtitle": "Son of Hamfast", + "culture": "shire", + "cost": 2, + "type": "companion", + "race": "hobbit", + "strength": 3, + "vitality": 4, + "resistance": 5, + "signet": "aragorn", + "effects": [ + { + "type": "activated", + "phase": "fellowship", + "cost": [ + { + "type": "spot", + "filter": "name(Frodo)" + }, + { + "type": "exert", + "filter": "self", + "times": 2 + } + ], + + "effect": { + "type": "preventable", + "text": "Would you like to discard a minion from hand (or place a Nazgul from hand on your draw deck) to prevent removing 2 burdens?", + "player": "shadowPlayer", + "cost": [ + { + "type": "putcardsfromhandontopofdeck", + "filter": "choose(nazgul)" + }, + { + "type": "discardFromHand", + "filter": "choose(minion)" + } + ], + "effect": { + "type": "removeBurdens", + "amount": 2 + } + } + }, + { + "type": "trigger", + "optional": true, + "trigger": { + "type": "killed", + "filter": "name(Frodo),ring bearer" + }, + "effect": { + "type": "makeSelfRingBearer" + } + } + ] + }, + + "21_10313": { + "title": "*Sting", + "culture": "shire", + "cost": 1, + "type": "possession", + "possession": "hand weapon", + "strength": 2, + "target": "name(Frodo)", + "effects": { + "type": "activated", + "phase": [ + "fellowship", + "regroup" + ], + "cost": { + "type": "exert", + "filter": "bearer" }, "effect": [ { - "type": "modifyStrength", - "filter": "choose(ally)", - "amount": 2, - "until": "start(regroup)", - "memorize": "exertedAlly" + "type": "revealrandomcardsfromhand", + "hand": "shadowPlayer", + "memorize": "revealedCards", + "amount":3 }, { - "type": "allyCanParticipateInArcheryFireAndSkirmishes", - "filter": "memory(exertedAlly)", - "until": "start(regroup)" + "type": "addKeyword", + "filter": "choose(companion)", + "keyword": "concealed", + "until": "start(regroup)", + "amount": { + "type": "forEachMatchingInMemory", + "memory": "revealedCards", + "filter": "orc", + "limit": 1 + } + } + ] + } + }, + + "21_10316": { + "title": "*A Talent for Not Being Seen", + "culture": "shire", + "cost": 0, + "type": "condition", + "keyword": [ + "stealth", + "support area" + ], + "effects": [ + { + "type": "extraCost", + "cost": { + "type": "exert", + "filter": "choose(hobbit)" + } + }, + { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "site,choose(companion)", + "keyword": "concealed", + "until": "start(regroup)", + "condition": { + "type": "canSpot", + "count": 2, + "filter": "companion", + }, + } + } + ] + }, + + "21_2032": { + "side": "free_people", + "cost": 0, + "strength": 1, + "culture": "Gondor", + "possession": "Hand Weapon", + "title": "Flaming Brand", + "type": "possession", + "target": "ranger", + "effects": [ + { + "type": "extrapossessionclass" + }, + { + "type": "activated", + "phase": "skirmish", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effects":[ + { + "type": "modifyStrength", + "filter": "bearer", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "bearer", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "21_2075": { + "title": "*Bill Ferny", + "subtitle": "Swarthy Sneering Fellow", + "culture": "wraith", + "cost": 2, + "type": "minion", + "race": "Man", + "strength": 4, + "vitality": 1, + "site": 2, + "effects": { + "type": "activated", + "phase": "skirmish", + "cost": { + "type": "removeTwilight" + }, + "effects": [ + { + "type": "modifier", + "modifier": { + "type": "removeKeyword", + "filter": "nazgul", + "keyword": "roaming" + } + }, + { + "type": "trigger", + "trigger": { + "type": "condition", + "condition": [ + { + "type": "location", + "filter": "underground" + } + ] + }, + "effect": { + "type": "discard", + "filter": "self" + } } ] } }, + } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index 48913b329..457bd55cb 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -1,49 +1,62 @@ var set21 = { - '21_1': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_1.jpg', - '21_2': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_2.jpg', - '21_3': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_3.jpg', - '21_4': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_4.jpg', - '21_5': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_5.jpg', - '21_6': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_6.jpg', - '21_7': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_7.jpg', - '21_8': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_8.jpg', - '21_9': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_9.jpg', - '21_10': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_10.jpg', - '21_11': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_11.jpg', - '21_12': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_12.jpg', - '21_13': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_13.jpg', - '21_14': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_14.jpg', - '21_15': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_15.jpg', - '21_16': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_16.jpg', - '21_17': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_17.jpg', - '21_18': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_18.jpg', - '21_19': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_19.jpg', - '21_20': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_20.jpg', - '21_21': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_21.jpg', - '21_22': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_22.jpg', - '21_23': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_23.jpg', - '21_24': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_24.jpg', - '21_25': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_25.jpg', - '21_26': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_26.jpg', - '21_27': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_27.jpg', - '21_28': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_28.jpg', - '21_29': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_29.jpg', - '21_30': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_30.jpg', - '21_31': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_31.jpg', - '21_32': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_32.jpg', - '21_33': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_33.jpg', - '21_34': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_34.jpg', - '21_35': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_35.jpg', - '21_36': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_36.jpg', - '21_37': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_37.jpg', - '21_38': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_38.jpg', - '21_39': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_39.jpg', - '21_40': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_40.jpg', - '21_41': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_41.jpg', - '21_42': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_42.jpg', - '21_43': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_43.jpg', - '21_44': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_44.jpg', - '21_45': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_45.jpg', - '21_46': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_46.jpg', - '21_47': 'http://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_47.jpg' + '21_1': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_1.jpg', + '21_2': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_2.jpg', + '21_3': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_3.jpg', + '21_4': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_4.jpg', + '21_5': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_5.jpg', + '21_6': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_6.jpg', + '21_7': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_7.jpg', + '21_8': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_8.jpg', + '21_9': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_9.jpg', + '21_10': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_10.jpg', + '21_11': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_11.jpg', + '21_12': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_12.jpg', + '21_13': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_13.jpg', + '21_14': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_14.jpg', + '21_15': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_15.jpg', + '21_16': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_16.jpg', + '21_17': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_17.jpg', + '21_18': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_18.jpg', + '21_19': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_19.jpg', + '21_20': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_20.jpg', + '21_21': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_21.jpg', + '21_22': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_22.jpg', + '21_23': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_23.jpg', + '21_24': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_24.jpg', + '21_25': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_25.jpg', + '21_26': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_26.jpg', + '21_27': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_27.jpg', + '21_28': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_28.jpg', + '21_29': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_29.jpg', + '21_30': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_30.jpg', + '21_31': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_31.jpg', + '21_32': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_32.jpg', + '21_33': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_33.jpg', + '21_34': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_34.jpg', + '21_35': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_35.jpg', + '21_36': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_36.jpg', + '21_37': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_37.jpg', + '21_38': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_38.jpg', + '21_39': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_39.jpg', + '21_40': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_40.jpg', + '21_41': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_41.jpg', + '21_42': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_42.jpg', + '21_43': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_43.jpg', + '21_44': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_44.jpg', + '21_45': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_45.jpg', + '21_46': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_46.jpg', + '21_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_47.jpg', + "21_1040": 'https://i.lotrtcgpc.net/errata/FOTR/21_40.jpg', + "21_1045": 'https://i.lotrtcgpc.net/errata/FOTR/21_45.jpg', + "21_1080": 'https://i.lotrtcgpc.net/errata/FOTR/21_80.jpg', + "21_10108": 'https://i.lotrtcgpc.net/errata/FOTR/21_108.jpg', + "21_10139": 'https://i.lotrtcgpc.net/errata/FOTR/21_139.jpg', + "21_10195": 'https://i.lotrtcgpc.net/errata/FOTR/21_195.jpg', + "21_10234": 'https://i.lotrtcgpc.net/errata/FOTR/21_234.jpg', + "21_10248": 'https://i.lotrtcgpc.net/errata/FOTR/21_248.jpg', + "21_10311": 'https://i.lotrtcgpc.net/errata/FOTR/21_311.jpg', + "21_10313": 'https://i.lotrtcgpc.net/errata/FOTR/21_313.jpg', + "21_10316": 'https://i.lotrtcgpc.net/errata/FOTR/21_316.jpg', + "21_2032": 'https://i.lotrtcgpc.net/errata/FOTR/22_32.jpg', + "21_2075": 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt index 6343ef996..4e3e9a3f5 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt @@ -45,7 +45,16 @@ 21S45 21S46 21S47 -21S1040 -21S1045 -21S1080 -21S10108 +21R1040 +21R1045 +21R1080 +21U10108 +21R10139 +21R10195 +21U10234 +21C10248 +21C10311 +21R10313 +21U10316 +21R2032 +21R2075 From 2a08b6c0635dcb106b793f140307d71e41126217 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 00:47:46 -0600 Subject: [PATCH 11/74] Set up individual card unit testing Added GenericCardTest, a helper class that extends AbstractAtTest with a focus on easily and clearly setting up unit tests for testing the implementation of card game text. Set up the PC errata for Elrond, Lord of Rivendell as a proof of concept. --- .../gempukku/lotro/cards/GenericCardTest.java | 223 ++++++++++++++++++ .../pc/errata/Elrond_LoRErrataTest.java | 142 +++++++++++ 2 files changed, 365 insertions(+) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java new file mode 100644 index 000000000..b22c29215 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -0,0 +1,223 @@ +package com.gempukku.lotro.cards; + +import com.gempukku.lotro.at.AbstractAtTest; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.AwaitingDecision; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class GenericCardTest extends AbstractAtTest { + + private int LastCardID; + + public Map freepsCards = new HashMap<>(); + public Map shadowCards = new HashMap<>(); + + public GenericCardTest(Map freepsIDs, Map shadowIDs, Collection freepsdeck, Collection shadowdeck) throws CardNotFoundException, DecisionResultInvalidException { + super(); + LastCardID = 100; + + + if(freepsIDs != null) + { + for(String name : freepsIDs.keySet()) + { + String id = freepsIDs.get(name); + freepsCards.put(name, CreateCard(P1, id)); + } + } + + if(shadowIDs != null) + { + for(String name : shadowIDs.keySet()) + { + String id = shadowIDs.get(name); + shadowCards.put(name, CreateCard(P2, id)); + } + } + + Map> deckCards = new HashMap>(); + + if(freepsdeck == null) + { + deckCards.put(P1, new ArrayList()); + } + else + { + deckCards.put(P1, freepsdeck); + } + + if(shadowdeck == null) + { + deckCards.put(P2, new ArrayList()); + } + else + { + deckCards.put(P2, shadowdeck); + } + + Setup(deckCards); + } + + public PhysicalCardImpl CreateCard(String playerID, String cardID) throws CardNotFoundException { + return new PhysicalCardImpl(LastCardID++, cardID, playerID, _library.getLotroCardBlueprint(cardID)); + } + + public void Setup(Map> deckCards) throws DecisionResultInvalidException + { + initializeSimplestGame(deckCards); + } + + public void StartGame() throws DecisionResultInvalidException { + skipMulligans(); + } + + public List FreepsGetAvailableActions() { return GetAvailableActions(P1); } + public List ShadowGetAvailableActions() { return GetAvailableActions(P2); } + public List GetAvailableActions(String playerID) + { + AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); + return Arrays.asList((String[])decision.getDecisionParameters().get("actionText")); + } + + public AwaitingDecision FreepsGetAwaitingDecision() { return GetAwaitingDecision(P1); } + public AwaitingDecision ShadowGetAwaitingDecision() { return GetAwaitingDecision(P2); } + public AwaitingDecision GetAwaitingDecision(String playerID) { return _userFeedback.getAwaitingDecision(playerID); } + + public void FreepsUseAction(String name) throws DecisionResultInvalidException { + playerDecided(P1, getCardActionId(P1, name)); + } + + public int FreepsGetWoundsOn(String cardName) + { + return GetWoundsOn(freepsCards.get(cardName)); + } + + public int ShadowGetWoundsOn(String cardName) + { + return GetWoundsOn(shadowCards.get(cardName)); + } + + public int GetWoundsOn(PhysicalCardImpl card) + { + return _game.getGameState().getWounds(card); + } + + public int GetFreepsHandCount() { return GetPlayerHandCount(P1); } + + public int GetPlayerHandCount(String player) + { + return _game.getGameState().getHand(player).size(); + } + + public int GetFreepsDeckCount() { return GetPlayerDeckCount(P1); } + + public int GetPlayerDeckCount(String player) + { + return _game.getGameState().getDeck(player).size(); + } + + public Phase GetCurrentPhase() + { + return _game.getGameState().getCurrentPhase(); + } + + public Boolean FreepsActionAvailable(String action) + { + return ActionAvailable(P1, action); + } + + public Boolean ActionAvailable(String player, String action) + { + List actions = GetAvailableActions(player); + return actions.stream().anyMatch(x -> x.startsWith(action)); + } + + + public void SetTwilight(int amount) + { + _game.getGameState().setTwilight(amount); + } + + public void FreepsMoveCardToHand(String cardName) { MoveCardToZone(P1, freepsCards.get(cardName), Zone.HAND); } + public void FreepsMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.HAND); } + + public void FreepsMoveCardToDeck(String cardName) { MoveCardToZone(P1, freepsCards.get(cardName), Zone.DECK); } + public void FreepsMoveCardToDeck(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.DECK); } + + public void FreepsMoveCharToTable(String cardName) { MoveCardToZone(P1, freepsCards.get(cardName), Zone.FREE_CHARACTERS); } + public void FreepsMoveCharToTable(PhysicalCardImpl card) + { + MoveCardToZone(P1, card, Zone.FREE_CHARACTERS); + } + + public void FreepsMove(String cardID, Zone zone) + { + MoveCardToZone(P1, freepsCards.get(cardID), zone); + } + public void ShadowMove(String cardID, Zone zone) + { + MoveCardToZone(P2, shadowCards.get(cardID), zone); + } + + public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) + { + _game.getGameState().addCardToZone(_game, card, zone); + } + + public List FreepsGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P1, paramName)); } + public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } + public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } + public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } + public Object GetAwaitingDecisionParam(String playerID, String paramName) + { + AwaitingDecision decision = _userFeedback.getAwaitingDecision(P1); + return decision.getDecisionParameters().get(paramName); + } + + public Map GetAwaitingDecisionParams(String playerID) + { + AwaitingDecision decision = _userFeedback.getAwaitingDecision(P1); + return decision.getDecisionParameters(); + } + + public void FreepsPlayCharFromHand(String cardName) throws DecisionResultInvalidException + { + PhysicalCardImpl card = freepsCards.get(cardName); + List availableIds = FreepsGetADParamAsList("cardId"); + + Integer index = availableIds.indexOf(String.valueOf(card.getCardId())); + playerDecided(P1, index.toString()); + } + + public void FreepsAddWoundsToChar(String cardName, int count) + { + AddWoundsToChar(freepsCards.get(cardName), count); + } + + public void AddWoundsToChar(PhysicalCardImpl card, int count) + { + for(int i = 0; i < count; i++) + { + AddWoundToChar(card); + } + } + + public void AddWoundToChar(PhysicalCardImpl card) + { + _game.getGameState().addWound(card); + } + + public void SkipToNextFreepsTurn() + { + + } + + +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java new file mode 100644 index 000000000..aa2760d27 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java @@ -0,0 +1,142 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.AwaitingDecision; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Assert; +import org.junit.Test; + +import java.util.*; + +import static junit.framework.Assert.assertEquals; + +public class Elrond_LoRErrataTest +{ + + protected GenericCardTest GetSimpleDeckScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("elrond", "21_1040"); + put("randomcard", "1_3"); + }}, + null, + null, + null + ); + } + + protected GenericCardTest GetSimpleSpotScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("elrond", "21_1040"); + put("gandalf", "1_72"); + put("arwen", "1_30"); + }}, + null, + null, + null + ); + } + + protected GenericCardTest GetHome3AllyScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("elrond", "21_1040"); + put("ally1", "1_60"); + put("ally2", "1_27"); + }}, + null, + null, + null + ); + } + + @Test + public void FellowshipActionExertsTwiceToDrawACard() throws DecisionResultInvalidException, CardNotFoundException + { + //Pre-game setup + GenericCardTest scenario = GetSimpleDeckScenario(); + PhysicalCardImpl elrond = scenario.freepsCards.get("elrond"); + scenario.FreepsMoveCharToTable(elrond); + + scenario.StartGame(); + + scenario.FreepsMoveCardToDeck("randomcard"); + + Assert.assertEquals(Phase.FELLOWSHIP, scenario.GetCurrentPhase()); + Assert.assertTrue(scenario.FreepsActionAvailable("Use Elrond")); + + Assert.assertEquals(0, scenario.GetWoundsOn(elrond)); + Assert.assertEquals(0, scenario.GetFreepsHandCount()); + Assert.assertEquals(1, scenario.GetFreepsDeckCount()); + + scenario.FreepsUseAction("Use Elrond"); + + Assert.assertEquals(2, scenario.GetWoundsOn(elrond)); + Assert.assertEquals(0, scenario.GetFreepsDeckCount()); + Assert.assertEquals(1, scenario.GetFreepsHandCount()); + + } + + @Test + public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException + { + //Pre-game setup + GenericCardTest scenario = GetSimpleSpotScenario(); + scenario.FreepsMoveCardToHand("elrond"); + scenario.FreepsMoveCardToHand("gandalf"); + + scenario.StartGame(); + + Assert.assertEquals(Phase.FELLOWSHIP, scenario.GetCurrentPhase()); + Assert.assertFalse(scenario.FreepsActionAvailable("Play Elrond")); + + scenario.FreepsPlayCharFromHand("gandalf"); + Assert.assertTrue(scenario.FreepsActionAvailable("Play Elrond")); + } + + @Test + public void CardCanPlayIfElfInPlay() throws DecisionResultInvalidException, CardNotFoundException + { + //Pre-game setup + GenericCardTest scenario = GetSimpleSpotScenario(); + scenario.FreepsMoveCardToHand("elrond"); + scenario.FreepsMoveCardToHand("arwen"); + + scenario.StartGame(); + + Assert.assertEquals(Phase.FELLOWSHIP, scenario.GetCurrentPhase()); + Assert.assertFalse(scenario.FreepsActionAvailable("Play Elrond")); + + scenario.FreepsPlayCharFromHand("arwen"); + Assert.assertTrue(scenario.FreepsActionAvailable("Play Elrond")); + } + + @Test + public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException + { + //Pre-game setup + GenericCardTest scenario = GetHome3AllyScenario(); + scenario.FreepsMoveCharToTable("elrond"); + scenario.FreepsMoveCharToTable("ally1"); + scenario.FreepsMoveCharToTable("ally2"); + + scenario.FreepsAddWoundsToChar("elrond", 1); + scenario.FreepsAddWoundsToChar("ally1", 1); + scenario.FreepsAddWoundsToChar("ally2", 1); + + scenario.StartGame(); + + Assert.assertEquals(Phase.BETWEEN_TURNS, scenario.GetCurrentPhase()); + + Assert.assertEquals(3, scenario.FreepsGetADParamAsList("cardId").size()); + Assert.assertEquals("0", scenario.FreepsGetADParam("min")); + Assert.assertEquals("2", scenario.FreepsGetADParam("max")); + } +} From 167ff78801205c29ca83b044590efe3c9cc248df Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 01:11:02 -0600 Subject: [PATCH 12/74] Code reformat Reformatted new unit tests to follow existing java style. Fleshed out existing helper functions to have shadow variants where any freeps variants existed. --- .../gempukku/lotro/cards/GenericCardTest.java | 141 +++++++----------- .../pc/errata/Elrond_LoRErrataTest.java | 17 +-- 2 files changed, 57 insertions(+), 101 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index b22c29215..54cd73333 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -24,19 +24,15 @@ public class GenericCardTest extends AbstractAtTest { LastCardID = 100; - if(freepsIDs != null) - { - for(String name : freepsIDs.keySet()) - { + if(freepsIDs != null) { + for(String name : freepsIDs.keySet()) { String id = freepsIDs.get(name); freepsCards.put(name, CreateCard(P1, id)); } } - if(shadowIDs != null) - { - for(String name : shadowIDs.keySet()) - { + if(shadowIDs != null) { + for(String name : shadowIDs.keySet()) { String id = shadowIDs.get(name); shadowCards.put(name, CreateCard(P2, id)); } @@ -44,21 +40,17 @@ public class GenericCardTest extends AbstractAtTest { Map> deckCards = new HashMap>(); - if(freepsdeck == null) - { + if(freepsdeck == null) { deckCards.put(P1, new ArrayList()); } - else - { + else { deckCards.put(P1, freepsdeck); } - if(shadowdeck == null) - { + if(shadowdeck == null) { deckCards.put(P2, new ArrayList()); } - else - { + else { deckCards.put(P2, shadowdeck); } @@ -69,8 +61,7 @@ public class GenericCardTest extends AbstractAtTest { return new PhysicalCardImpl(LastCardID++, cardID, playerID, _library.getLotroCardBlueprint(cardID)); } - public void Setup(Map> deckCards) throws DecisionResultInvalidException - { + public void Setup(Map> deckCards) throws DecisionResultInvalidException { initializeSimplestGame(deckCards); } @@ -78,10 +69,12 @@ public class GenericCardTest extends AbstractAtTest { skipMulligans(); } + public PhysicalCardImpl GetFreepsCard(String cardName) { return freepsCards.get(cardName); } + public PhysicalCardImpl GetShadowCard(String cardName) { return shadowCards.get(cardName); } + public List FreepsGetAvailableActions() { return GetAvailableActions(P1); } public List ShadowGetAvailableActions() { return GetAvailableActions(P2); } - public List GetAvailableActions(String playerID) - { + public List GetAvailableActions(String playerID) { AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); return Arrays.asList((String[])decision.getDecisionParameters().get("actionText")); } @@ -90,84 +83,66 @@ public class GenericCardTest extends AbstractAtTest { public AwaitingDecision ShadowGetAwaitingDecision() { return GetAwaitingDecision(P2); } public AwaitingDecision GetAwaitingDecision(String playerID) { return _userFeedback.getAwaitingDecision(playerID); } - public void FreepsUseAction(String name) throws DecisionResultInvalidException { - playerDecided(P1, getCardActionId(P1, name)); - } + public void FreepsUseAction(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); } + public void ShadowUseAction(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } - public int FreepsGetWoundsOn(String cardName) - { - return GetWoundsOn(freepsCards.get(cardName)); - } - - public int ShadowGetWoundsOn(String cardName) - { - return GetWoundsOn(shadowCards.get(cardName)); - } - - public int GetWoundsOn(PhysicalCardImpl card) - { - return _game.getGameState().getWounds(card); - } + public int FreepsGetWoundsOn(String cardName) { return GetWoundsOn(GetFreepsCard(cardName)); } + public int ShadowGetWoundsOn(String cardName) { return GetWoundsOn(GetShadowCard(cardName)); } + public int GetWoundsOn(PhysicalCardImpl card) { return _game.getGameState().getWounds(card); } public int GetFreepsHandCount() { return GetPlayerHandCount(P1); } - + public int GetShadowHandCount() { return GetPlayerHandCount(P2); } public int GetPlayerHandCount(String player) { return _game.getGameState().getHand(player).size(); } public int GetFreepsDeckCount() { return GetPlayerDeckCount(P1); } - + public int GetShadowDeckCount() { return GetPlayerDeckCount(P2); } public int GetPlayerDeckCount(String player) { return _game.getGameState().getDeck(player).size(); } - public Phase GetCurrentPhase() - { - return _game.getGameState().getCurrentPhase(); - } + public Phase GetCurrentPhase() { return _game.getGameState().getCurrentPhase(); } - public Boolean FreepsActionAvailable(String action) - { - return ActionAvailable(P1, action); - } - - public Boolean ActionAvailable(String player, String action) - { + public Boolean FreepsActionAvailable(String action) { return ActionAvailable(P1, action); } + public Boolean ShadowActionAvailable(String action) { return ActionAvailable(P2, action); } + public Boolean ActionAvailable(String player, String action) { List actions = GetAvailableActions(player); return actions.stream().anyMatch(x -> x.startsWith(action)); } - - public void SetTwilight(int amount) - { - _game.getGameState().setTwilight(amount); - } - - public void FreepsMoveCardToHand(String cardName) { MoveCardToZone(P1, freepsCards.get(cardName), Zone.HAND); } + public void FreepsMoveCardToHand(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.HAND); } public void FreepsMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.HAND); } + public void ShadowMoveCardToHand(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.HAND); } + public void ShadowMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.HAND); } - public void FreepsMoveCardToDeck(String cardName) { MoveCardToZone(P1, freepsCards.get(cardName), Zone.DECK); } + public void FreepsMoveCardToDeck(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.DECK); } public void FreepsMoveCardToDeck(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.DECK); } + public void ShadowMoveCardToDeck(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.DECK); } + public void ShadowMoveCardToDeck(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.DECK); } - public void FreepsMoveCharToTable(String cardName) { MoveCardToZone(P1, freepsCards.get(cardName), Zone.FREE_CHARACTERS); } + public void FreepsMoveCharToTable(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.FREE_CHARACTERS); } public void FreepsMoveCharToTable(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.FREE_CHARACTERS); } - - public void FreepsMove(String cardID, Zone zone) + public void ShadowMoveCharToTable(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.SHADOW_CHARACTERS); } + public void ShadowMoveCharToTable(PhysicalCardImpl card) { - MoveCardToZone(P1, freepsCards.get(cardID), zone); - } - public void ShadowMove(String cardID, Zone zone) - { - MoveCardToZone(P2, shadowCards.get(cardID), zone); + MoveCardToZone(P2, card, Zone.SHADOW_CHARACTERS); } - public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) + public void FreepsMoveCardToZone(String cardID, Zone zone) { + MoveCardToZone(P1, GetFreepsCard(cardID), zone); + } + public void ShadowMoveCardToZone(String cardID, Zone zone) + { + MoveCardToZone(P2, GetShadowCard(cardID), zone); + } + public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) { _game.getGameState().addCardToZone(_game, card, zone); } @@ -175,49 +150,35 @@ public class GenericCardTest extends AbstractAtTest { public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } - public Object GetAwaitingDecisionParam(String playerID, String paramName) - { + public Object GetAwaitingDecisionParam(String playerID, String paramName) { AwaitingDecision decision = _userFeedback.getAwaitingDecision(P1); return decision.getDecisionParameters().get(paramName); } - public Map GetAwaitingDecisionParams(String playerID) - { + public Map GetAwaitingDecisionParams(String playerID) { AwaitingDecision decision = _userFeedback.getAwaitingDecision(P1); return decision.getDecisionParameters(); } - public void FreepsPlayCharFromHand(String cardName) throws DecisionResultInvalidException - { - PhysicalCardImpl card = freepsCards.get(cardName); + public void FreepsPlayCharFromHand(String cardName) throws DecisionResultInvalidException { + PhysicalCardImpl card = GetFreepsCard(cardName); List availableIds = FreepsGetADParamAsList("cardId"); Integer index = availableIds.indexOf(String.valueOf(card.getCardId())); playerDecided(P1, index.toString()); } - public void FreepsAddWoundsToChar(String cardName, int count) - { - AddWoundsToChar(freepsCards.get(cardName), count); - } - - public void AddWoundsToChar(PhysicalCardImpl card, int count) - { + public void FreepsAddWoundsToChar(String cardName, int count) { AddWoundsToChar(GetFreepsCard(cardName), count); } + public void ShadowAddWoundsToChar(String cardName, int count) { AddWoundsToChar(GetShadowCard(cardName), count); } + public void AddWoundsToChar(PhysicalCardImpl card, int count) { for(int i = 0; i < count; i++) { AddWoundToChar(card); } } + public void AddWoundToChar(PhysicalCardImpl card) { _game.getGameState().addWound(card); } - public void AddWoundToChar(PhysicalCardImpl card) - { - _game.getGameState().addWound(card); - } - - public void SkipToNextFreepsTurn() - { - - } + public void SetTwilight(int amount) { _game.getGameState().setTwilight(amount); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java index aa2760d27..bf36f73f3 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java @@ -58,11 +58,10 @@ public class Elrond_LoRErrataTest } @Test - public void FellowshipActionExertsTwiceToDrawACard() throws DecisionResultInvalidException, CardNotFoundException - { + public void FellowshipActionExertsTwiceToDrawACard() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTest scenario = GetSimpleDeckScenario(); - PhysicalCardImpl elrond = scenario.freepsCards.get("elrond"); + PhysicalCardImpl elrond = scenario.GetFreepsCard("elrond"); scenario.FreepsMoveCharToTable(elrond); scenario.StartGame(); @@ -79,14 +78,12 @@ public class Elrond_LoRErrataTest scenario.FreepsUseAction("Use Elrond"); Assert.assertEquals(2, scenario.GetWoundsOn(elrond)); - Assert.assertEquals(0, scenario.GetFreepsDeckCount()); Assert.assertEquals(1, scenario.GetFreepsHandCount()); - + Assert.assertEquals(0, scenario.GetFreepsDeckCount()); } @Test - public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException - { + public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTest scenario = GetSimpleSpotScenario(); scenario.FreepsMoveCardToHand("elrond"); @@ -102,8 +99,7 @@ public class Elrond_LoRErrataTest } @Test - public void CardCanPlayIfElfInPlay() throws DecisionResultInvalidException, CardNotFoundException - { + public void CardCanPlayIfElfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTest scenario = GetSimpleSpotScenario(); scenario.FreepsMoveCardToHand("elrond"); @@ -119,8 +115,7 @@ public class Elrond_LoRErrataTest } @Test - public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException - { + public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTest scenario = GetHome3AllyScenario(); scenario.FreepsMoveCharToTable("elrond"); From fcac24c02d9ef8da334c55058e7143de71a0cf1a Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 20:33:22 -0600 Subject: [PATCH 13/74] log4j fixes Renamed and moved the log4j xml to the proper location in gemp-lotr-server to be found on startup. Added the log folder to gitignore. Put references to log4j in all project pom.xml files. --- .gitignore | 1 + gemp-lotr/gemp-lotr-async/pom.xml | 5 ++ gemp-lotr/gemp-lotr-cards/pom.xml | 5 ++ .../src/main/resources/log4j.xml} | 84 +++++++++---------- 4 files changed, 53 insertions(+), 42 deletions(-) rename gemp-lotr/{gemp-lotr-async/src/main/resources/test-log4j.xml => gemp-lotr-server/src/main/resources/log4j.xml} (97%) diff --git a/.gitignore b/.gitignore index 3edffecd8..3426ba07a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,6 @@ buildNumber.properties database/* !database/.placeholder +logs/* .idea/ *.iml \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/pom.xml b/gemp-lotr/gemp-lotr-async/pom.xml index 81ae6ae61..3f2b06757 100644 --- a/gemp-lotr/gemp-lotr-async/pom.xml +++ b/gemp-lotr/gemp-lotr-async/pom.xml @@ -22,6 +22,11 @@ netty-all 4.1.49.Final + + log4j + log4j + 1.2.16 + diff --git a/gemp-lotr/gemp-lotr-cards/pom.xml b/gemp-lotr/gemp-lotr-cards/pom.xml index 3e446bebf..15f199cdd 100644 --- a/gemp-lotr/gemp-lotr-cards/pom.xml +++ b/gemp-lotr/gemp-lotr-cards/pom.xml @@ -22,5 +22,10 @@ gemp-lotr-logic ${project.version} + + log4j + log4j + 1.2.16 + \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/resources/test-log4j.xml b/gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml similarity index 97% rename from gemp-lotr/gemp-lotr-async/src/main/resources/test-log4j.xml rename to gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml index 9cd6ca66d..4c5544080 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/resources/test-log4j.xml +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml @@ -1,43 +1,43 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 3ae4c3f6a317c4a2d772aa59a777163f47e31d23 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 21:16:21 -0600 Subject: [PATCH 14/74] Fixing minor errors in previous commit --- .gitignore | 2 +- gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 3426ba07a..c05776c19 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,6 @@ buildNumber.properties database/* !database/.placeholder -logs/* +logs/ .idea/ *.iml \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml b/gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml index 4c5544080..644c5a647 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/log4j.xml @@ -40,4 +40,4 @@ - \ No newline at end of file + From 8439ebbb7701ff20963ab41271dac89b2457f09c Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 21:19:44 -0600 Subject: [PATCH 15/74] Docker Update Fixed net naming schema for hopefully the last time. Added a log file binding so that gemp logs can be accessed outside the container. --- gemp-lotr/docker/.env | 4 ++-- gemp-lotr/docker/docker-compose.yml | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/gemp-lotr/docker/.env b/gemp-lotr/docker/.env index 3c530844d..63210db1d 100644 --- a/gemp-lotr/docker/.env +++ b/gemp-lotr/docker/.env @@ -3,11 +3,11 @@ COMPOSE_PROJECT_NAME=gemp_${SERVID} APP_CONTAINER_NAME=gemp_app_${SERVID} APP_IP=172.28.${SERVID}.2 -APP_PORT=17001 +APP_PORT=1700${SERVID} DB_CONTAINER_NAME=gemp_db_${SERVID} DB_IP=172.28.${SERVID}.3 -DB_PORT=35001 +DB_PORT=3500${SERVID} MYSQL_ROOT_PASSWORD=rootpass MYSQL_DATABASE=gemp_db diff --git a/gemp-lotr/docker/docker-compose.yml b/gemp-lotr/docker/docker-compose.yml index 6a75c7b30..083a7fedb 100644 --- a/gemp-lotr/docker/docker-compose.yml +++ b/gemp-lotr/docker/docker-compose.yml @@ -29,8 +29,11 @@ services: - type: bind source: ../gemp-lotr-async/src/main/web target: /var/www/localhost/htdocs/gemp-lotr #/etc/apache2/htdocs/gemp-lotr + - type: bind + source: ../../logs + target: /logs networks: - gemp_net: + gemp_net_1: ipv4_address: ${APP_IP} tty: true #command: nohup java -jar /etc/gemp-lotr/gemp-lotr-async/target/web.jar & @@ -55,13 +58,13 @@ services: source: ../../database target: /var/lib/mysql networks: - gemp_net: + gemp_net_1: ipv4_address: ${DB_IP} networks: - gemp_net: + gemp_net_1: ipam: driver: default config: - - subnet: 172.28.0.0/16 \ No newline at end of file + - subnet: 172.28.1.0/24 \ No newline at end of file From a6a7e360633a6184b966017fba3129c51f09ac69 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 21:43:24 -0600 Subject: [PATCH 16/74] Including placeholder for the default logs location --- .gitignore | 3 ++- logs/.placeholder | 0 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 logs/.placeholder diff --git a/.gitignore b/.gitignore index c05776c19..bb37eb203 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ buildNumber.properties database/* !database/.placeholder -logs/ +logs/* +!logs/.placeholder .idea/ *.iml \ No newline at end of file diff --git a/logs/.placeholder b/logs/.placeholder new file mode 100644 index 000000000..e69de29bb From 67952b9e869b42e11c508f56473779b65a223e38 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 21:44:03 -0600 Subject: [PATCH 17/74] Fixing subfolder log directories getting watched by git --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bb37eb203..32bc76000 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,6 @@ database/* !database/.placeholder logs/* !logs/.placeholder +**/logs .idea/ *.iml \ No newline at end of file From 80e655660152c19604333567d29eef1c4886947b Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 26 Jan 2021 22:04:27 -0600 Subject: [PATCH 18/74] Fixed elrond errata forcing 2 allies instead of 'up to 2' --- .../gemp-lotr-async/src/main/web/cards/set21/set1-errata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 9b87b5902..9314f8b55 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -22,7 +22,7 @@ "effect": { "type": "heal", "filter": "choose(ally,allyHome(fellowship,3))", - "count": 2 + "count": "0-2" } }, { From 87b27551b2173b338a93572406659760496f0e62 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Thu, 28 Jan 2021 23:09:02 -0600 Subject: [PATCH 19/74] Adding phase 1 errata candidates with unit tests --- .../src/main/web/cards/set21/set1-errata.json | 132 ++++++++--------- .../gempukku/lotro/cards/GenericCardTest.java | 131 ++++++++++++----- .../pc/errata/Elrond_LoRErrataTest.java | 101 +++++++------ .../pc/errata/FlamingBrandErrataTest.java | 134 ++++++++++++++++++ .../pc/errata/Galadriel_LoLErrataTest.java | 90 ++++++++++++ .../pc/errata/Sam_SoHErrataTest.java | 71 ++++++++++ 6 files changed, 495 insertions(+), 164 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 9314f8b55..1ac6cf340 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -58,7 +58,7 @@ "effect": { "type": "heal", "filter": "choose(ally,allyHome(fellowship,6))", - "count": 2 + "count": "0-2" } }, { @@ -279,36 +279,18 @@ { "type": "activated", "phase": "fellowship", - "cost": [ - { - "type": "spot", + "condition": { + "type": "canSpot", "filter": "name(Frodo)" - }, - { + }, + "cost": { "type": "exert", "filter": "self", "times": 2 - } - ], - - "effect": { - "type": "preventable", - "text": "Would you like to discard a minion from hand (or place a Nazgul from hand on your draw deck) to prevent removing 2 burdens?", - "player": "shadowPlayer", - "cost": [ - { - "type": "putcardsfromhandontopofdeck", - "filter": "choose(nazgul)" - }, - { - "type": "discardFromHand", - "filter": "choose(minion)" - } - ], + }, "effect": { "type": "removeBurdens", - "amount": 2 - } + "amount": 1 } }, { @@ -347,8 +329,9 @@ { "type": "revealrandomcardsfromhand", "hand": "shadowPlayer", + "forced": true, "memorize": "revealedCards", - "amount":3 + "count":3 }, { "type": "addKeyword", @@ -384,17 +367,19 @@ } }, { - "type": "modifier", - "modifier": { + "type": "trigger", + "trigger": { + "type": "moves" + }, + "cost": { + "type": "exert", + "filter": "choose(hobbit)" + }, + "effect": { "type": "addKeyword", - "filter": "site,choose(companion)", - "keyword": "concealed", - "until": "start(regroup)", - "condition": { - "type": "canSpot", - "count": 2, - "filter": "companion", - }, + "filter": "self", + "keyword": "defender+1", + "until": "start(regroup)" } } ] @@ -416,7 +401,10 @@ { "type": "activated", "phase": "skirmish", - "filter": "bearer,inSkirmishAgainst(Nazgul)", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, "cost": [ { "type": "memorize", @@ -428,15 +416,15 @@ "filter": "self" } ], - "effects":[ + "effect":[ { "type": "modifyStrength", - "filter": "bearer", + "filter": "memory(bearer)", "amount": 3 }, { "type": "addKeyword", - "filter": "bearer", + "filter": "memory(bearer)", "keyword": "damage+1" } ] @@ -444,46 +432,40 @@ ] }, - "21_2075": { - "title": "*Bill Ferny", - "subtitle": "Swarthy Sneering Fellow", - "culture": "wraith", - "cost": 2, - "type": "minion", - "race": "Man", - "strength": 4, - "vitality": 1, - "site": 2, + "21_3042": { + "side": "free_people", + "cost": 0, + "culture": "Gondor", + "title": "*Horn of Boromir", + "type": "possession", + "target": "name(Boromir)", "effects": { "type": "activated", - "phase": "skirmish", - "cost": { - "type": "removeTwilight" - }, - "effects": [ + "phase": "assignment", + "cost": [ { - "type": "modifier", - "modifier": { - "type": "removeKeyword", - "filter": "nazgul", - "keyword": "roaming" - } + "type": "exert", + "filter": "self" }, { - "type": "trigger", - "trigger": { - "type": "condition", - "condition": [ - { - "type": "location", - "filter": "underground" - } - ] - }, - "effect": { - "type": "discard", - "filter": "self" - } + "type": "assignFpCharacterToSkirmish", + "player": "fp", + "fpCharacter": "self", + "against": "minion" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "choose(ally,allyInCurrentRegion)", + "amount": 3, + "until": "start(regroup)", + "memorize": "summonedAlly" + }, + { + "type": "allyCanParticipateInArcheryFireAndSkirmishes", + "filter": "memory(summonedAlly)", + "until": "start(regroup)" } ] } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index 54cd73333..a635ecaf6 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -1,9 +1,12 @@ package com.gempukku.lotro.cards; import com.gempukku.lotro.at.AbstractAtTest; +import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Side; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -14,57 +17,42 @@ import static org.junit.Assert.assertEquals; public class GenericCardTest extends AbstractAtTest { - private int LastCardID; + private int LastCardID = 100; + //TODO: refactor this to not have different freeps/shadows collections public Map freepsCards = new HashMap<>(); public Map shadowCards = new HashMap<>(); - public GenericCardTest(Map freepsIDs, Map shadowIDs, Collection freepsdeck, Collection shadowdeck) throws CardNotFoundException, DecisionResultInvalidException { + public GenericCardTest(Map freepsIDs, Map shadowIDs) throws CardNotFoundException, DecisionResultInvalidException { super(); - LastCardID = 100; + initializeSimplestGame(); if(freepsIDs != null) { for(String name : freepsIDs.keySet()) { String id = freepsIDs.get(name); - freepsCards.put(name, CreateCard(P1, id)); + PhysicalCardImpl card = CreateCard(P1, id); + freepsCards.put(name, card); + FreepsMoveCardToDeck(card); + ShadowMoveCardToDeck(CreateCard(P2, id)); } } if(shadowIDs != null) { for(String name : shadowIDs.keySet()) { String id = shadowIDs.get(name); - shadowCards.put(name, CreateCard(P2, id)); + PhysicalCardImpl card = CreateCard(P2, id); + shadowCards.put(name, card); + ShadowMoveCardToDeck(card); + FreepsMoveCardToDeck(CreateCard(P1, id)); } } - - Map> deckCards = new HashMap>(); - - if(freepsdeck == null) { - deckCards.put(P1, new ArrayList()); - } - else { - deckCards.put(P1, freepsdeck); - } - - if(shadowdeck == null) { - deckCards.put(P2, new ArrayList()); - } - else { - deckCards.put(P2, shadowdeck); - } - - Setup(deckCards); } public PhysicalCardImpl CreateCard(String playerID, String cardID) throws CardNotFoundException { return new PhysicalCardImpl(LastCardID++, cardID, playerID, _library.getLotroCardBlueprint(cardID)); } - public void Setup(Map> deckCards) throws DecisionResultInvalidException { - initializeSimplestGame(deckCards); - } - public void StartGame() throws DecisionResultInvalidException { skipMulligans(); } @@ -90,6 +78,8 @@ public class GenericCardTest extends AbstractAtTest { public int ShadowGetWoundsOn(String cardName) { return GetWoundsOn(GetShadowCard(cardName)); } public int GetWoundsOn(PhysicalCardImpl card) { return _game.getGameState().getWounds(card); } + public int GetBurdens() { return _game.getGameState().getBurdens(); } + public int GetFreepsHandCount() { return GetPlayerHandCount(P1); } public int GetShadowHandCount() { return GetPlayerHandCount(P2); } public int GetPlayerHandCount(String player) @@ -110,7 +100,8 @@ public class GenericCardTest extends AbstractAtTest { public Boolean ShadowActionAvailable(String action) { return ActionAvailable(P2, action); } public Boolean ActionAvailable(String player, String action) { List actions = GetAvailableActions(player); - return actions.stream().anyMatch(x -> x.startsWith(action)); + String lowerAction = action.toLowerCase(); + return actions.stream().anyMatch(x -> x.toLowerCase().startsWith(lowerAction)); } public void FreepsMoveCardToHand(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.HAND); } @@ -134,32 +125,35 @@ public class GenericCardTest extends AbstractAtTest { MoveCardToZone(P2, card, Zone.SHADOW_CHARACTERS); } - public void FreepsMoveCardToZone(String cardID, Zone zone) - { - MoveCardToZone(P1, GetFreepsCard(cardID), zone); - } - public void ShadowMoveCardToZone(String cardID, Zone zone) - { - MoveCardToZone(P2, GetShadowCard(cardID), zone); - } + public void FreepsMoveCardToZone(String cardID, Zone zone) { MoveCardToZone(P1, GetFreepsCard(cardID), zone); } + public void FreepsMoveCardToZone(PhysicalCardImpl card, Zone zone) { MoveCardToZone(P1, card, zone); } + public void ShadowMoveCardToZone(String cardID, Zone zone) { MoveCardToZone(P2, GetShadowCard(cardID), zone); } + public void ShadowMoveCardToZone(PhysicalCardImpl card, Zone zone) { MoveCardToZone(P2, card, zone); } public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) { + if(card.getZone() != null) + { + _game.getGameState().removeCardsFromZone(player, new ArrayList() {{ add(card); }}); + } _game.getGameState().addCardToZone(_game, card, zone); } + + public List FreepsGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P1, paramName)); } public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } public Object GetAwaitingDecisionParam(String playerID, String paramName) { - AwaitingDecision decision = _userFeedback.getAwaitingDecision(P1); + AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); return decision.getDecisionParameters().get(paramName); } public Map GetAwaitingDecisionParams(String playerID) { - AwaitingDecision decision = _userFeedback.getAwaitingDecision(P1); + AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); return decision.getDecisionParameters(); } + public void FreepsPlayCharFromHand(String cardName) throws DecisionResultInvalidException { PhysicalCardImpl card = GetFreepsCard(cardName); List availableIds = FreepsGetADParamAsList("cardId"); @@ -178,7 +172,68 @@ public class GenericCardTest extends AbstractAtTest { } public void AddWoundToChar(PhysicalCardImpl card) { _game.getGameState().addWound(card); } + public int GetTwilight() { return _game.getGameState().getTwilightPool(); } public void SetTwilight(int amount) { _game.getGameState().setTwilight(amount); } + public PhysicalCardImpl GetRingBearer() + { + return (PhysicalCardImpl)_game.getGameState().getRingBearer(P1); + } + public void SkipToPhase(Phase target) throws DecisionResultInvalidException { + for(int attempts = 1; attempts <= 20; attempts++) + { + Phase current = _game.getGameState().getCurrentPhase(); + if(current == target) + break; + + SkipCurrentPhaseActions(); + + if(attempts == 20) + { + throw new DecisionResultInvalidException("Could not arrive at target '" + target + "' after 20 attempts!"); + } + } + } + + public void SkipCurrentPhaseActions() throws DecisionResultInvalidException { + Phase current = _game.getGameState().getCurrentPhase(); + + if(_userFeedback.getAwaitingDecision(P1) != null) { + playerDecided(P1, ""); + } + + if(_userFeedback.getAwaitingDecision(P2) != null) { + playerDecided(P2, ""); + } + } + + + public void FreepsAssignToMinion(String name, String target) throws DecisionResultInvalidException { FreepsAssignToMinion(GetFreepsCard(name), GetShadowCard(target)); } + public void FreepsAssignToMinion(PhysicalCardImpl comp, PhysicalCardImpl minion) throws DecisionResultInvalidException { + playerDecided(P1, comp.getCardId() + " " + minion.getCardId()); + } + + public List FreepsGetAttachedCards(String name) { return GetAttachedCards(GetFreepsCard(name)); } + public List GetAttachedCards(PhysicalCardImpl card) + { + return (List)(List)_game.getGameState().getAttachedCards(card); + } + + public void FreepsResolveSkirmish(String name) throws DecisionResultInvalidException { FreepsResolveSkirmish(GetFreepsCard(name)); } + public void FreepsResolveSkirmish(PhysicalCardImpl comp) throws DecisionResultInvalidException { + playerDecided(P1, String.valueOf(comp.getCardId())); + } + + public int FreepsGetStrength(String name) { return GetStrength(GetFreepsCard(name)); } + public int ShadowGetStrength(String name) { return GetStrength(GetShadowCard(name)); } + public int GetStrength(PhysicalCardImpl card) + { + return _game.getModifiersQuerying().getStrength(_game, card); + } + + public boolean HasKeyword(PhysicalCardImpl card, Keyword keyword) + { + return _game.getModifiersQuerying().hasKeyword(_game, card, keyword); + } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java index bf36f73f3..342f2e0d4 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java @@ -6,7 +6,7 @@ import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; -import org.junit.Assert; +import static org.junit.Assert.*; import org.junit.Test; import java.util.*; @@ -23,8 +23,6 @@ public class Elrond_LoRErrataTest put("elrond", "21_1040"); put("randomcard", "1_3"); }}, - null, - null, null ); } @@ -37,8 +35,6 @@ public class Elrond_LoRErrataTest put("gandalf", "1_72"); put("arwen", "1_30"); }}, - null, - null, null ); } @@ -48,11 +44,11 @@ public class Elrond_LoRErrataTest new HashMap() {{ put("elrond", "21_1040"); - put("ally1", "1_60"); - put("ally2", "1_27"); + put("allyHome3_1", "1_60"); + put("allyHome3_2", "1_27"); + put("allyHome6_1", "1_56"); + put("allyHome6_2", "1_57"); }}, - null, - null, null ); } @@ -60,78 +56,81 @@ public class Elrond_LoRErrataTest @Test public void FellowshipActionExertsTwiceToDrawACard() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scenario = GetSimpleDeckScenario(); - PhysicalCardImpl elrond = scenario.GetFreepsCard("elrond"); - scenario.FreepsMoveCharToTable(elrond); + GenericCardTest scn = GetSimpleDeckScenario(); + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); - scenario.StartGame(); + scn.FreepsMoveCharToTable(elrond); - scenario.FreepsMoveCardToDeck("randomcard"); + scn.StartGame(); - Assert.assertEquals(Phase.FELLOWSHIP, scenario.GetCurrentPhase()); - Assert.assertTrue(scenario.FreepsActionAvailable("Use Elrond")); + assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); + assertTrue(scn.FreepsActionAvailable("Use Elrond")); - Assert.assertEquals(0, scenario.GetWoundsOn(elrond)); - Assert.assertEquals(0, scenario.GetFreepsHandCount()); - Assert.assertEquals(1, scenario.GetFreepsDeckCount()); + assertEquals(0, scn.GetWoundsOn(elrond)); + assertEquals(0, scn.GetFreepsHandCount()); + assertEquals(1, scn.GetFreepsDeckCount()); - scenario.FreepsUseAction("Use Elrond"); + scn.FreepsUseAction("Use Elrond"); - Assert.assertEquals(2, scenario.GetWoundsOn(elrond)); - Assert.assertEquals(1, scenario.GetFreepsHandCount()); - Assert.assertEquals(0, scenario.GetFreepsDeckCount()); + assertEquals(2, scn.GetWoundsOn(elrond)); + assertEquals(1, scn.GetFreepsHandCount()); + assertEquals(0, scn.GetFreepsDeckCount()); } @Test public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scenario = GetSimpleSpotScenario(); - scenario.FreepsMoveCardToHand("elrond"); - scenario.FreepsMoveCardToHand("gandalf"); + GenericCardTest scn = GetSimpleSpotScenario(); + scn.FreepsMoveCardToHand("elrond"); + scn.FreepsMoveCardToHand("gandalf"); - scenario.StartGame(); + scn.StartGame(); - Assert.assertEquals(Phase.FELLOWSHIP, scenario.GetCurrentPhase()); - Assert.assertFalse(scenario.FreepsActionAvailable("Play Elrond")); + assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); + assertFalse(scn.FreepsActionAvailable("Play Elrond")); - scenario.FreepsPlayCharFromHand("gandalf"); - Assert.assertTrue(scenario.FreepsActionAvailable("Play Elrond")); + scn.FreepsPlayCharFromHand("gandalf"); + assertTrue(scn.FreepsActionAvailable("Play Elrond")); } @Test public void CardCanPlayIfElfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scenario = GetSimpleSpotScenario(); - scenario.FreepsMoveCardToHand("elrond"); - scenario.FreepsMoveCardToHand("arwen"); + GenericCardTest scn = GetSimpleSpotScenario(); + scn.FreepsMoveCardToHand("elrond"); + scn.FreepsMoveCardToHand("arwen"); - scenario.StartGame(); + scn.StartGame(); - Assert.assertEquals(Phase.FELLOWSHIP, scenario.GetCurrentPhase()); - Assert.assertFalse(scenario.FreepsActionAvailable("Play Elrond")); + assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); + assertFalse(scn.FreepsActionAvailable("Play Elrond")); - scenario.FreepsPlayCharFromHand("arwen"); - Assert.assertTrue(scenario.FreepsActionAvailable("Play Elrond")); + scn.FreepsPlayCharFromHand("arwen"); + assertTrue(scn.FreepsActionAvailable("Play Elrond")); } @Test public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scenario = GetHome3AllyScenario(); - scenario.FreepsMoveCharToTable("elrond"); - scenario.FreepsMoveCharToTable("ally1"); - scenario.FreepsMoveCharToTable("ally2"); + GenericCardTest scn = GetHome3AllyScenario(); + scn.FreepsMoveCharToTable("elrond"); + scn.FreepsMoveCharToTable("allyHome3_1"); + scn.FreepsMoveCharToTable("allyHome3_2"); + scn.FreepsMoveCharToTable("allyHome6_1"); + scn.FreepsMoveCharToTable("allyHome6_2"); - scenario.FreepsAddWoundsToChar("elrond", 1); - scenario.FreepsAddWoundsToChar("ally1", 1); - scenario.FreepsAddWoundsToChar("ally2", 1); + scn.FreepsAddWoundsToChar("elrond", 1); + scn.FreepsAddWoundsToChar("allyHome3_1", 1); + scn.FreepsAddWoundsToChar("allyHome3_2", 1); + scn.FreepsAddWoundsToChar("allyHome6_1", 1); + scn.FreepsAddWoundsToChar("allyHome6_2", 1); - scenario.StartGame(); + scn.StartGame(); - Assert.assertEquals(Phase.BETWEEN_TURNS, scenario.GetCurrentPhase()); + assertEquals(Phase.BETWEEN_TURNS, scn.GetCurrentPhase()); - Assert.assertEquals(3, scenario.FreepsGetADParamAsList("cardId").size()); - Assert.assertEquals("0", scenario.FreepsGetADParam("min")); - Assert.assertEquals("2", scenario.FreepsGetADParam("max")); + assertEquals(3, scn.FreepsGetADParamAsList("cardId").size()); + assertEquals("0", scn.FreepsGetADParam("min")); + assertEquals("2", scn.FreepsGetADParam("max")); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java new file mode 100644 index 000000000..9815a3b33 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java @@ -0,0 +1,134 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.*; + +public class FlamingBrandErrataTest +{ + protected GenericCardTest GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("brand", "21_2032"); + put("brand2", "21_2032"); + put("arwen", "1_30"); + put("boromir", "1_97"); + put("aragorn", "1_89"); + }}, + new HashMap() + {{ + put("nazgul", "1_229"); + put("runner", "1_178"); + }} + ); + } + + @Test + public void CanBeBorneByRangers() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetSimpleScenario(); + + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl brand = scn.GetFreepsCard("brand"); + + scn.FreepsMoveCharToTable(arwen); + scn.FreepsMoveCharToTable(boromir); + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCardToHand(brand); + + scn.StartGame(); + + + assertTrue(scn.FreepsActionAvailable("Play Flaming Brand")); + + scn.FreepsUseAction("Play Flaming Brand"); + + //There are 3 companions in play, but only 2 rangers, so we should only see 2 options + assertEquals(2, scn.FreepsGetADParamAsList("cardId").size()); + + } + + @Test + public void CanBeBorneTwice() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetSimpleScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl brand = scn.GetFreepsCard("brand"); + PhysicalCardImpl brand2 = scn.GetFreepsCard("brand2"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCardToHand(brand); + scn.FreepsMoveCardToHand(brand2); + + scn.StartGame(); + + scn.FreepsUseAction("Play Flaming Brand"); + assertTrue(scn.FreepsActionAvailable("Play Flaming Brand")); + scn.FreepsUseAction("Play Flaming Brand"); + + assertEquals(2, scn.GetAttachedCards(aragorn).size()); + } + + @Test + public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetSimpleScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl brand = scn.GetFreepsCard("brand"); + PhysicalCardImpl runner = scn.GetShadowCard("runner"); + PhysicalCardImpl nazgul = scn.GetShadowCard("nazgul"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCardToHand(brand); + + scn.ShadowMoveCharToTable(runner); + scn.ShadowMoveCharToTable(nazgul); + + scn.StartGame(); + + assertEquals(8, scn.GetStrength(aragorn)); + scn.FreepsUseAction("Play Flaming Brand"); + assertEquals(9, scn.GetStrength(aragorn)); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.SkipCurrentPhaseActions(); + scn.FreepsAssignToMinion(aragorn, runner); + //skip assigning the nazgul + scn.SkipCurrentPhaseActions(); + + //start goblin skirmish + scn.FreepsResolveSkirmish(aragorn); + + //goblin shouldn't trigger Flaming Brand's action + assertEquals(0, scn.FreepsGetAvailableActions().size()); + scn.SkipCurrentPhaseActions(); + + //assignment for fierce skirmish + scn.SkipCurrentPhaseActions(); + scn.FreepsAssignToMinion(aragorn, nazgul); + scn.FreepsResolveSkirmish(aragorn); + + assertEquals(1, scn.FreepsGetAvailableActions().size()); + assertTrue(scn.FreepsActionAvailable("Use Flaming Brand")); + + assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + scn.FreepsUseAction("Use Flaming Brand"); + assertEquals(11, scn.GetStrength(aragorn)); + assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java new file mode 100644 index 000000000..974d47b14 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java @@ -0,0 +1,90 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import static org.junit.Assert.*; +import org.junit.Test; + +import java.util.HashMap; + +public class Galadriel_LoLErrataTest +{ + protected GenericCardTest GetSimplePlayScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("galadriel", "21_1045"); + put("elrond", "1_40"); + }}, + null + ); + } + + protected GenericCardTest GetHome6AllyScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("galadriel", "21_1045"); + put("allyHome3_1", "1_60"); + put("allyHome3_2", "1_27"); + put("allyHome6_1", "1_56"); + put("allyHome6_2", "1_57"); + }}, + null + ); + } + + @Test + public void FellowshipActionExertsTwiceToDiscountAnElf() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetSimplePlayScenario(); + + PhysicalCardImpl galadriel = scn.GetFreepsCard("galadriel"); + scn.FreepsMoveCharToTable(galadriel); + scn.FreepsMoveCardToHand("elrond"); + + scn.StartGame(); + + assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); + assertTrue(scn.FreepsActionAvailable("Use Galadriel")); + + assertEquals(0, scn.GetWoundsOn(galadriel)); + assertEquals(1, scn.GetFreepsHandCount()); + assertEquals(0, scn.GetTwilight()); + + scn.FreepsUseAction("Use Galadriel"); + + assertEquals(2, scn.GetWoundsOn(galadriel)); + assertEquals(0, scn.GetFreepsHandCount()); + assertEquals(2, scn.GetTwilight()); + } + + + @Test + public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetHome6AllyScenario(); + scn.FreepsMoveCharToTable("galadriel"); + scn.FreepsMoveCharToTable("allyHome3_1"); + scn.FreepsMoveCharToTable("allyHome3_2"); + scn.FreepsMoveCharToTable("allyHome6_1"); + scn.FreepsMoveCharToTable("allyHome6_2"); + + scn.FreepsAddWoundsToChar("galadriel", 1); + scn.FreepsAddWoundsToChar("allyHome3_1", 1); + scn.FreepsAddWoundsToChar("allyHome3_2", 1); + scn.FreepsAddWoundsToChar("allyHome6_1", 1); + scn.FreepsAddWoundsToChar("allyHome6_2", 1); + + scn.StartGame(); + + assertEquals(Phase.BETWEEN_TURNS, scn.GetCurrentPhase()); + + assertEquals(3, scn.FreepsGetADParamAsList("cardId").size()); + assertEquals("0", scn.FreepsGetADParam("min")); + assertEquals("2", scn.FreepsGetADParam("max")); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java new file mode 100644 index 000000000..12406463d --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java @@ -0,0 +1,71 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import static org.junit.Assert.*; +import org.junit.Test; + +import java.util.HashMap; + +public class Sam_SoHErrataTest +{ + protected GenericCardTest GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("sam", "21_10311"); + }}, + new HashMap() + {{ + put("orc", "1_272"); + }} + ); + } + + @Test + public void FellowshipActionExertsTwiceToRemoveABurden() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetSimpleScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + scn.FreepsMoveCharToTable(sam); + + scn.StartGame(); + + assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); + assertTrue(scn.FreepsActionAvailable("Use Sam")); + + assertEquals(0, scn.GetWoundsOn(sam)); + assertEquals(1, scn.GetBurdens()); + + scn.FreepsUseAction("Use Sam"); + + assertEquals(2, scn.GetWoundsOn(sam)); + assertEquals(0, scn.GetBurdens()); + } + + + @Test + public void RBDeathMakesSamTheRB() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetSimpleScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + PhysicalCardImpl orc = scn.GetShadowCard("orc"); + scn.FreepsMoveCharToTable(sam); + + scn.StartGame(); + + assertNotSame(scn.GetRingBearer(), sam); + scn.AddWoundsToChar(frodo, 4); + + scn.SkipCurrentPhaseActions(); + + assertTrue(scn.FreepsActionAvailable("Optional Trigger")); + } +} From 31d65e06839040a714b86be97a30d362aef90c1b Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 30 Jan 2021 03:34:46 -0600 Subject: [PATCH 20/74] AllyRegion filter added for Horn of Boromir errata Added errata'd Horn of Boromir and unit tests. Added new "AllyInCurrentRegion" and "AllyInRegion" filters to facilitate it. Refactored base of PC card unit tests to be a bit easier to customize card lists. --- .../src/main/web/cards/set21/set1-errata.json | 18 ++- .../field/effect/filter/FilterFactory.java | 11 ++ .../com/gempukku/lotro/filters/Filters.java | 24 +++ .../lotro/logic/timing/RuleUtils.java | 16 ++ .../com/gempukku/lotro/at/AbstractAtTest.java | 2 +- .../gempukku/lotro/cards/GenericCardTest.java | 108 ++++++++++--- .../pc/errata/Elrond_LoRErrataTest.java | 9 +- .../pc/errata/FlamingBrandErrataTest.java | 4 +- .../pc/errata/Galadriel_LoLErrataTest.java | 6 +- .../pc/errata/HornOfBoromirErrataTest.java | 149 ++++++++++++++++++ .../pc/errata/Sam_SoHErrataTest.java | 4 +- 11 files changed, 302 insertions(+), 49 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 1ac6cf340..cd562e191 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -442,19 +442,23 @@ "effects": { "type": "activated", "phase": "assignment", + "condition": { + "type": "canSpot", + "filter": "bearer,notAssignedToSkirmish" + }, "cost": [ { "type": "exert", - "filter": "self" - }, + "filter": "bearer" + } + ], + "effect":[ { "type": "assignFpCharacterToSkirmish", "player": "fp", - "fpCharacter": "self", - "against": "minion" - } - ], - "effect":[ + "fpCharacter": "bearer", + "against": "choose(minion)" + }, { "type": "modifyStrength", "filter": "choose(ally,allyInCurrentRegion)", diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java index 4af6a945d..851190fb0 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java @@ -199,6 +199,17 @@ public class FilterFactory { int number = Integer.parseInt(parameterSplit[1]); return (actionContext) -> Filters.isAllyHome(number, sitesBlock); }); + parameterFilters.put("allyInRegion", + (parameter, environment) -> { + final String[] parameterSplit = parameter.split(","); + final SitesBlock sitesBlock = Enum.valueOf(SitesBlock.class, parameterSplit[0].toUpperCase().replace('_', ' ')); + int number = Integer.parseInt(parameterSplit[1]); + return (actionContext) -> Filters.isAllyInRegion(number, sitesBlock); + }); + parameterFilters.put("allyInCurrentRegion", + (parameter, environment) -> { + return (actionContext) -> Filters.isAllyInCurrentRegion(); + }); parameterFilters.put("siteBlock", (parameter, environment) -> { final SitesBlock sitesBlock = Enum.valueOf(SitesBlock.class, parameter.toUpperCase().replace(' ', '_')); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java index ac3ce177d..6513aa6cb 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java @@ -665,6 +665,28 @@ public class Filters { }); } + public static Filter isAllyInRegion(final int regionNumber, final SitesBlock siteBlock) { + return Filters.and( + CardType.ALLY, + new Filter() { + @Override + public boolean accepts(LotroGame game, PhysicalCard physicalCard) { + return RuleUtils.isAllyInRegion(physicalCard, regionNumber, siteBlock); + } + }); + } + + public static Filter isAllyInCurrentRegion() { + return Filters.and( + CardType.ALLY, + new Filter() { + @Override + public boolean accepts(LotroGame game, PhysicalCard physicalCard) { + return RuleUtils.isAllyInRegion(physicalCard, GameUtils.getRegion(game), game.getGameState().getCurrentSiteBlock()); + } + }); + } + public static final Filter allyAtHome = Filters.and( CardType.ALLY, new Filter() { @@ -709,6 +731,8 @@ public class Filters { } }; + + public static Filter siteNumber(final int siteNumber) { return siteNumberBetweenInclusive(siteNumber, siteNumber); } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java index 0803ac7ac..9b6184b1d 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleUtils.java @@ -7,8 +7,10 @@ import com.gempukku.lotro.game.LotroCardBlueprint; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.game.state.Skirmish; +import com.gempukku.lotro.logic.GameUtils; import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; @@ -186,4 +188,18 @@ public class RuleUtils { return true; return false; } + + public static boolean isAllyInRegion(PhysicalCard ally, int regionNumber, SitesBlock siteBlock) { + final SitesBlock allySiteBlock = ally.getBlueprint().getAllyHomeSiteBlock(); + final int[] allyHomeSites = ally.getBlueprint().getAllyHomeSiteNumbers(); + if (allySiteBlock != siteBlock) + return false; +// for (int number : allyHomeSites) +// if (regionNumber == GameUtils.getRegion(number)) +// return true; +// return false; + + return Arrays.stream(ally.getBlueprint().getAllyHomeSiteNumbers()).anyMatch(x -> regionNumber == GameUtils.getRegion(x)); + } + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java index bccc23d87..3f3e6d318 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/AbstractAtTest.java @@ -53,7 +53,7 @@ public abstract class AbstractAtTest { _userFeedback = new DefaultUserFeedback(); LotroFormatLibrary formatLibrary = new LotroFormatLibrary(new DefaultAdventureLibrary(), _library); - LotroFormat format = formatLibrary.getFormat("movie"); + LotroFormat format = formatLibrary.getFormat("multipath"); _game = new DefaultLotroGame(format, decks, _userFeedback, _library); _userFeedback.setGame(_game); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index a635ecaf6..4e0140a16 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -8,8 +8,10 @@ import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.game.state.Assignment; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.vo.LotroDeck; import java.util.*; @@ -19,32 +21,68 @@ public class GenericCardTest extends AbstractAtTest { private int LastCardID = 100; - //TODO: refactor this to not have different freeps/shadows collections - public Map freepsCards = new HashMap<>(); - public Map shadowCards = new HashMap<>(); + public static final HashMap FellowshipSites = new HashMap() {{ + put("site1", "1_319"); + put("site2", "1_327"); + put("site3", "1_337"); + put("site4", "1_343"); + put("site5", "1_349"); + put("site6", "1_350"); + put("site7", "1_353"); + put("site8", "1_356"); + put("site9", "1_360"); + }}; - public GenericCardTest(Map freepsIDs, Map shadowIDs) throws CardNotFoundException, DecisionResultInvalidException { + public static final String FOTRFrodo = "1_290"; + public static final String FOTRRing = "1_2"; + + + // Player key, then name/card + public Map> Cards = new HashMap<>(); + + public GenericCardTest(Map cardIDs) throws CardNotFoundException, DecisionResultInvalidException { + this(cardIDs, null, null, null); + } + + public GenericCardTest(Map cardIDs, Map siteIDs, String ringBearerID, String ringID) throws CardNotFoundException, DecisionResultInvalidException { super(); - initializeSimplestGame(); + if(siteIDs == null || ringBearerID == null || ringID == null) { + initializeSimplestGame(); + } + else { + Map decks = new HashMap(); + decks.put(P1, new LotroDeck(P1)); + decks.put(P2, new LotroDeck(P2)); - if(freepsIDs != null) { - for(String name : freepsIDs.keySet()) { - String id = freepsIDs.get(name); - PhysicalCardImpl card = CreateCard(P1, id); - freepsCards.put(name, card); - FreepsMoveCardToDeck(card); - ShadowMoveCardToDeck(CreateCard(P2, id)); + for(String name : siteIDs.keySet()) { + String id = siteIDs.get(name); + decks.get(P1).addSite(id); + decks.get(P2).addSite(id); } + + decks.get(P1).setRingBearer(ringBearerID); + decks.get(P2).setRingBearer(ringBearerID); + + decks.get(P1).setRing(ringID); + decks.get(P2).setRing(ringID); + + initializeGameWithDecks(decks); } - if(shadowIDs != null) { - for(String name : shadowIDs.keySet()) { - String id = shadowIDs.get(name); - PhysicalCardImpl card = CreateCard(P2, id); - shadowCards.put(name, card); - ShadowMoveCardToDeck(card); - FreepsMoveCardToDeck(CreateCard(P1, id)); + Cards.put(P1, new HashMap<>()); + Cards.put(P2, new HashMap<>()); + + if(cardIDs != null) { + for(String name : cardIDs.keySet()) { + String id = cardIDs.get(name); + PhysicalCardImpl card = CreateCard(P1, id); + Cards.get(P1).put(name, card); + FreepsMoveCardToDeck(card); + + card = CreateCard(P2, id); + Cards.get(P2).put(name, card); + FreepsMoveCardToDeck(card); } } } @@ -57,8 +95,8 @@ public class GenericCardTest extends AbstractAtTest { skipMulligans(); } - public PhysicalCardImpl GetFreepsCard(String cardName) { return freepsCards.get(cardName); } - public PhysicalCardImpl GetShadowCard(String cardName) { return shadowCards.get(cardName); } + public PhysicalCardImpl GetFreepsCard(String cardName) { return Cards.get(P1).get(cardName); } + public PhysicalCardImpl GetShadowCard(String cardName) { return Cards.get(P2).get(cardName); } public List FreepsGetAvailableActions() { return GetAvailableActions(P1); } public List ShadowGetAvailableActions() { return GetAvailableActions(P2); } @@ -213,18 +251,38 @@ public class GenericCardTest extends AbstractAtTest { public void FreepsAssignToMinion(PhysicalCardImpl comp, PhysicalCardImpl minion) throws DecisionResultInvalidException { playerDecided(P1, comp.getCardId() + " " + minion.getCardId()); } + public void FreepsAssignToMinions(PhysicalCardImpl[]... groups) throws DecisionResultInvalidException { + String result = ""; + + for (PhysicalCardImpl[] group : groups) { + result += group[0].getCardId(); + for(int i = 1; i < group.length; i++) + { + result += " " + group[i].getCardId(); + } + result += ","; + } + + playerDecided(P1, result); + } public List FreepsGetAttachedCards(String name) { return GetAttachedCards(GetFreepsCard(name)); } - public List GetAttachedCards(PhysicalCardImpl card) - { + public List GetAttachedCards(PhysicalCardImpl card) { return (List)(List)_game.getGameState().getAttachedCards(card); } public void FreepsResolveSkirmish(String name) throws DecisionResultInvalidException { FreepsResolveSkirmish(GetFreepsCard(name)); } - public void FreepsResolveSkirmish(PhysicalCardImpl comp) throws DecisionResultInvalidException { - playerDecided(P1, String.valueOf(comp.getCardId())); + public void FreepsResolveSkirmish(PhysicalCardImpl comp) throws DecisionResultInvalidException { FreepsChooseCard(comp); } + public void FreepsChooseCard(PhysicalCardImpl card) throws DecisionResultInvalidException { + playerDecided(P1, String.valueOf(card.getCardId())); } + public boolean IsCharAssigned(PhysicalCardImpl card) { + List assigns = _game.getGameState().getAssignments(); + return assigns.stream().anyMatch(x -> x.getFellowshipCharacter() == card || x.getShadowCharacters().contains(card)); + } + + public int FreepsGetStrength(String name) { return GetStrength(GetFreepsCard(name)); } public int ShadowGetStrength(String name) { return GetStrength(GetShadowCard(name)); } public int GetStrength(PhysicalCardImpl card) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java index 342f2e0d4..e822974a5 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java @@ -22,8 +22,7 @@ public class Elrond_LoRErrataTest {{ put("elrond", "21_1040"); put("randomcard", "1_3"); - }}, - null + }} ); } @@ -34,8 +33,7 @@ public class Elrond_LoRErrataTest put("elrond", "21_1040"); put("gandalf", "1_72"); put("arwen", "1_30"); - }}, - null + }} ); } @@ -48,8 +46,7 @@ public class Elrond_LoRErrataTest put("allyHome3_2", "1_27"); put("allyHome6_1", "1_56"); put("allyHome6_2", "1_57"); - }}, - null + }} ); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java index 9815a3b33..7a22cd4f1 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java @@ -25,9 +25,7 @@ public class FlamingBrandErrataTest put("arwen", "1_30"); put("boromir", "1_97"); put("aragorn", "1_89"); - }}, - new HashMap() - {{ + put("nazgul", "1_229"); put("runner", "1_178"); }} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java index 974d47b14..7d7490e16 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java @@ -18,8 +18,7 @@ public class Galadriel_LoLErrataTest {{ put("galadriel", "21_1045"); put("elrond", "1_40"); - }}, - null + }} ); } @@ -32,8 +31,7 @@ public class Galadriel_LoLErrataTest put("allyHome3_2", "1_27"); put("allyHome6_1", "1_56"); put("allyHome6_2", "1_57"); - }}, - null + }} ); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java new file mode 100644 index 000000000..83887855f --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java @@ -0,0 +1,149 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.*; + +public class HornOfBoromirErrataTest +{ + protected GenericCardTest GetFOTRScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("horn", "21_3042"); + put("elrond", "1_40"); + put("boromir", "1_97"); + put("aragorn", "1_89"); + + put("runner1", "1_178"); + put("runner2", "1_178"); + }}, + GenericCardTest.FellowshipSites, + GenericCardTest.FOTRFrodo, + GenericCardTest.FOTRRing + ); + } + + protected GenericCardTest GetMovieScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("horn", "21_3042"); + put("elrond", "1_40"); + put("boromir", "1_97"); + put("aragorn", "1_89"); + + put("runner1", "1_178"); + put("runner2", "1_178"); + }} + ); + } + + @Test + public void CanBeBorneByBoromir() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetFOTRScenario(); + + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl horn = scn.GetFreepsCard("horn"); + + scn.FreepsMoveCharToTable(elrond); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCardToHand(horn); + scn.FreepsMoveCardToHand(boromir); + + scn.StartGame(); + + assertFalse(scn.FreepsActionAvailable("Play Horn of Boromir")); + scn.FreepsUseAction("Play Boromir"); + assertTrue(scn.FreepsActionAvailable("Play Horn of Boromir")); + scn.FreepsUseAction("Play Horn of Boromir"); + + Assert.assertEquals(Zone.ATTACHED, horn.getZone()); + Assert.assertEquals(boromir, horn.getAttachedTo()); + } + + @Test + public void AbilityExertsAndAssignsBoromir() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetFOTRScenario(); + + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl horn = scn.GetFreepsCard("horn"); + PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); + PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); + + scn.FreepsMoveCharToTable(elrond); + scn.FreepsMoveCharToTable(boromir); + scn.FreepsMoveCardToHand(horn); + + scn.ShadowMoveCharToTable(runner1); + scn.ShadowMoveCharToTable(runner2); + + scn.StartGame(); + + scn.FreepsUseAction("Play Horn of Boromir"); + + scn.SkipToPhase(Phase.ASSIGNMENT); + assertTrue(scn.FreepsActionAvailable("Use Horn of Boromir")); + scn.FreepsUseAction("Use Horn of Boromir"); + scn.FreepsChooseCard(runner1); + + assertEquals(1, scn.GetWoundsOn(boromir)); + assertEquals(11, scn.GetStrength(elrond)); + //Skip shadow player's action + scn.SkipCurrentPhaseActions(); + assertFalse(scn.FreepsActionAvailable("Use Horn of Boromir")); + scn.SkipCurrentPhaseActions(); + assertTrue(scn.IsCharAssigned(boromir)); + + scn.FreepsAssignToMinion(elrond, runner2); + assertTrue(scn.IsCharAssigned(elrond)); + } + + @Test + public void AbilityDoesNotPumpFarAwayAllies() throws DecisionResultInvalidException, CardNotFoundException { + GenericCardTest scn = GetMovieScenario(); + + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl horn = scn.GetFreepsCard("horn"); + PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); + PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); + + scn.FreepsMoveCharToTable(elrond); + scn.FreepsMoveCharToTable(boromir); + scn.FreepsMoveCardToHand(horn); + + scn.ShadowMoveCharToTable(runner1); + scn.ShadowMoveCharToTable(runner2); + + scn.StartGame(); + + scn.FreepsUseAction("Play Horn of Boromir"); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.FreepsUseAction("Use Horn of Boromir"); + scn.FreepsChooseCard(runner1); + + assertEquals(1, scn.GetWoundsOn(boromir)); + assertEquals(8, scn.GetStrength(elrond)); + //Skip shadow player's action + scn.SkipCurrentPhaseActions(); + + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java index 12406463d..7bd48f246 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java @@ -17,9 +17,7 @@ public class Sam_SoHErrataTest new HashMap() {{ put("sam", "21_10311"); - }}, - new HashMap() - {{ + put("orc", "1_272"); }} ); From 247460c5bb862992c13c13403dc225125951c1a7 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 30 Jan 2021 03:42:25 -0600 Subject: [PATCH 21/74] Added missing card image link --- .../src/main/web/js/gemp-022/set21.js | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index 457bd55cb..68a205d71 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -46,17 +46,18 @@ var set21 = { '21_45': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_45.jpg', '21_46': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_46.jpg', '21_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_47.jpg', - "21_1040": 'https://i.lotrtcgpc.net/errata/FOTR/21_40.jpg', - "21_1045": 'https://i.lotrtcgpc.net/errata/FOTR/21_45.jpg', - "21_1080": 'https://i.lotrtcgpc.net/errata/FOTR/21_80.jpg', - "21_10108": 'https://i.lotrtcgpc.net/errata/FOTR/21_108.jpg', - "21_10139": 'https://i.lotrtcgpc.net/errata/FOTR/21_139.jpg', - "21_10195": 'https://i.lotrtcgpc.net/errata/FOTR/21_195.jpg', - "21_10234": 'https://i.lotrtcgpc.net/errata/FOTR/21_234.jpg', - "21_10248": 'https://i.lotrtcgpc.net/errata/FOTR/21_248.jpg', - "21_10311": 'https://i.lotrtcgpc.net/errata/FOTR/21_311.jpg', - "21_10313": 'https://i.lotrtcgpc.net/errata/FOTR/21_313.jpg', - "21_10316": 'https://i.lotrtcgpc.net/errata/FOTR/21_316.jpg', - "21_2032": 'https://i.lotrtcgpc.net/errata/FOTR/22_32.jpg', - "21_2075": 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', + '21_1040': 'https://i.lotrtcgpc.net/errata/FOTR/21_40.jpg', + '21_1045': 'https://i.lotrtcgpc.net/errata/FOTR/21_45.jpg', + '21_1080': 'https://i.lotrtcgpc.net/errata/FOTR/21_80.jpg', + '21_10108': 'https://i.lotrtcgpc.net/errata/FOTR/21_108.jpg', + '21_10139': 'https://i.lotrtcgpc.net/errata/FOTR/21_139.jpg', + '21_10195': 'https://i.lotrtcgpc.net/errata/FOTR/21_195.jpg', + '21_10234': 'https://i.lotrtcgpc.net/errata/FOTR/21_234.jpg', + '21_10248': 'https://i.lotrtcgpc.net/errata/FOTR/21_248.jpg', + '21_10311': 'https://i.lotrtcgpc.net/errata/FOTR/21_311.jpg', + '21_10313': 'https://i.lotrtcgpc.net/errata/FOTR/21_313.jpg', + '21_10316': 'https://i.lotrtcgpc.net/errata/FOTR/21_316.jpg', + '21_2032': 'https://i.lotrtcgpc.net/errata/FOTR/22_32.jpg', + '21_2075': 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', + '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg' } \ No newline at end of file From 01c6b90a30560779071d1e326c1f92205925793c Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 31 Jan 2021 20:38:16 -0600 Subject: [PATCH 22/74] Added additional generic Exception catch clause to ensure that unexpected parsing errors do not cause the entire server to crash. --- .../com/gempukku/lotro/game/LotroCardBlueprintLibrary.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java index 038404fd3..fd47bcc9a 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroCardBlueprintLibrary.java @@ -117,6 +117,9 @@ public class LotroCardBlueprintLibrary { } catch (ParseException exp) { logger.error("Failed to parse file " + file.getAbsolutePath(), exp); } + catch (Exception exp) { + logger.error("Unexpected error while parsing file " + file.getAbsolutePath(), exp); + } logger.debug("Loaded card file " + file.getName()); } From b60b2b2df8a033a0114e7eb8931cf8c00f8c7181 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 31 Jan 2021 21:49:47 -0600 Subject: [PATCH 23/74] Improved blueprint json parsing to support multiple home sites on allies. --- .../cards/build/field/AllyHomeFieldProcessor.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/AllyHomeFieldProcessor.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/AllyHomeFieldProcessor.java index fb5f747d6..e5a07d8c5 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/AllyHomeFieldProcessor.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/AllyHomeFieldProcessor.java @@ -6,14 +6,18 @@ import com.gempukku.lotro.cards.build.FieldProcessor; import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; import com.gempukku.lotro.common.SitesBlock; +import java.util.Arrays; + public class AllyHomeFieldProcessor implements FieldProcessor { @Override public void processField(String key, Object value, BuiltLotroCardBlueprint blueprint, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { final String allyHome = FieldUtils.getString(value, "allyHome"); - final String[] allyHomeSplit = allyHome.split(",", 2); + final String[] allyHomeSplit = allyHome.split(",", 4); SitesBlock sitesBlock = Enum.valueOf(SitesBlock.class, allyHomeSplit[0].toUpperCase().replace(' ', '_')); - final int number = Integer.parseInt(allyHomeSplit[1]); - blueprint.setAllyHomeSites(sitesBlock, new int[]{number}); + String[] sites = Arrays.copyOfRange(allyHomeSplit, 1, allyHomeSplit.length); + int[] numbers = Arrays.stream(sites).mapToInt(Integer::parseInt).toArray(); + + blueprint.setAllyHomeSites(sitesBlock, numbers); } } From c71ac3a2ccff8dfc70c28bacaecd36afcd172c27 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 2 Feb 2021 23:09:40 -0600 Subject: [PATCH 24/74] Saruman, Keeper of Isengard errata and associated changes Added Saruman, KoI errata. Added CantBeAssignedToSkirmish to the blueprint json loading. Edited the PreventWound effect to support the Memorize directive (so saruman could remember the blocked uruk's id and make it fierce). Revamped the unit tests to support playing cards and using actions based on a card reference rather than a hard-coded string. Edited existing unit tests to use the new functionality. --- .../src/main/web/cards/set21/set1-errata.json | 57 ++++++++- .../field/effect/appender/PreventWound.java | 7 +- .../modifier/CantBeAssignedToSkirmish.java | 49 ++++++++ .../modifier/ModifierSourceFactory.java | 1 + .../gempukku/lotro/cards/GenericCardTest.java | 75 +++++++----- .../pc/errata/Elrond_LoRErrataTest.java | 5 +- .../pc/errata/FlamingBrandErrataTest.java | 17 ++- .../pc/errata/Galadriel_LoLErrataTest.java | 4 +- .../pc/errata/HornOfBoromirErrataTest.java | 20 ++-- .../pc/errata/Sam_SoHErrataTest.java | 4 +- .../pc/errata/Saruman_KoIErrataTest.java | 111 ++++++++++++++++++ 11 files changed, 293 insertions(+), 57 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CantBeAssignedToSkirmish.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Saruman_KoIErrataTest.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index cd562e191..e487416ca 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -475,6 +475,61 @@ } }, - + "21_3068": { + "side": "shadow", + "site": 4, + "cost": 4, + "race": "Wizard", + "strength": 8, + "culture": "Isengard", + "vitality": 4, + "subtitle": "Keeper of Isengard", + "title": "*Saruman", + "type": "minion", + "effects": [ + { + "type": "modifier", + "modifier": { + "type": "cantbeassignedtoskirmish", + "filter": "self" + } + }, + { + "type": "modifier", + "modifier": { + "type": "cantTakeWounds", + "filter": "self", + "condition": { + "type": "phase", + "phase": "archery" + } + } + }, + { + "type": "activatedTrigger", + "trigger": { + "type": "aboutToTakeWound", + "filter": "uruk-hai" + }, + "cost": { + "type": "exert", + "filter": "self", + "times": 1 + }, + "effect": [ + { + "type": "preventWound", + "filter": "choose(uruk-hai)", + "memorize": "uruk" + }, + { + "type": "addKeyword", + "filter": "memory(uruk)", + "keyword": "fierce" + } + ] + }, + ] + }, } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventWound.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventWound.java index 03bf447b2..e457d4518 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventWound.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventWound.java @@ -23,9 +23,10 @@ import java.util.Collection; public class PreventWound implements EffectAppenderProducer { @Override public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(effectObject, "filter"); + FieldUtils.validateAllowedFields(effectObject, "filter", "memorize"); final String filter = FieldUtils.getString(effectObject.get("filter"), "filter", "all(any)"); + final String memory = FieldUtils.getString(effectObject.get("memorize"), "memorize", "_temp"); MultiEffectAppender result = new MultiEffectAppender(); @@ -34,12 +35,12 @@ public class PreventWound implements EffectAppenderProducer { (actionContext) -> { final PreventableCardEffect preventableEffect = (PreventableCardEffect) actionContext.getEffect(); return Filters.in(preventableEffect.getAffectedCardsMinusPrevented(actionContext.getGame())); - }, new ConstantEvaluator(1), "_temp", "you", "Choose characters to prevent effect to", environment)); + }, new ConstantEvaluator(1), memory, "you", "Choose characters to prevent effect to", environment)); result.addEffectAppender( new DelayedAppender() { @Override protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) { - final Collection cards = actionContext.getCardsFromMemory("_temp"); + final Collection cards = actionContext.getCardsFromMemory(memory); final PreventableCardEffect preventableEffect = (PreventableCardEffect) actionContext.getEffect(); return new PreventCardEffect(preventableEffect, Filters.in(cards)); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CantBeAssignedToSkirmish.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CantBeAssignedToSkirmish.java new file mode 100644 index 000000000..7b66e5c4a --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/CantBeAssignedToSkirmish.java @@ -0,0 +1,49 @@ +package com.gempukku.lotro.cards.build.field.effect.modifier; + +import com.gempukku.lotro.cards.build.*; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.cards.build.field.effect.EffectAppender; +import com.gempukku.lotro.cards.build.field.effect.appender.DelayedAppender; +import com.gempukku.lotro.cards.build.field.effect.appender.MultiEffectAppender; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.CardResolver; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.TimeResolver; +import com.gempukku.lotro.common.Filterable; +import com.gempukku.lotro.filters.Filters; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.logic.actions.CostToEffectAction; +import com.gempukku.lotro.logic.effects.AddUntilModifierEffect; +import com.gempukku.lotro.logic.modifiers.CantBeAssignedToSkirmishModifier; +import com.gempukku.lotro.logic.modifiers.KeywordModifier; +import com.gempukku.lotro.logic.modifiers.Modifier; +import com.gempukku.lotro.logic.modifiers.OverwhelmedByMultiplierModifier; +import com.gempukku.lotro.logic.modifiers.evaluator.ConstantEvaluator; +import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator; +import com.gempukku.lotro.logic.timing.Effect; +import org.json.simple.JSONObject; + +import java.util.Collection; + +public class CantBeAssignedToSkirmish implements ModifierSourceProducer { + + @Override + public ModifierSource getModifierSource(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject, "filter", "condition"); + + final JSONObject[] conditionArray = FieldUtils.getObjectArray(effectObject.get("condition"), "condition"); + final String filter = FieldUtils.getString(effectObject.get("filter"), "filter"); + + final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); + final Requirement[] requirements = environment.getRequirementFactory().getRequirements(conditionArray, environment); + + MultiEffectAppender result = new MultiEffectAppender(); + + return new ModifierSource() { + @Override + public Modifier getModifier(ActionContext actionContext) { + return new CantBeAssignedToSkirmishModifier(actionContext.getSource(), + new RequirementCondition(requirements, actionContext), + filterableSource.getFilterable(actionContext)); + } + }; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java index f5b33ca35..076147941 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java @@ -54,6 +54,7 @@ public class ModifierSourceFactory { modifierProducers.put("hastomoveifable", new HasToMoveIfAble()); modifierProducers.put("allycanparticipateinarcheryfireandskirmishes", new AllyCanParticipateInArcheryFireAndSkirmishes()); modifierProducers.put("cantlookorrevealhand", new CantLookOrRevealHand()); + modifierProducers.put("cantbeassignedtoskirmish", new CantBeAssignedToSkirmish()); } public ModifierSource getModifier(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index 4e0140a16..718555615 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -9,6 +9,7 @@ import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.game.state.Assignment; +import com.gempukku.lotro.logic.GameUtils; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import com.gempukku.lotro.logic.vo.LotroDeck; @@ -109,8 +110,41 @@ public class GenericCardTest extends AbstractAtTest { public AwaitingDecision ShadowGetAwaitingDecision() { return GetAwaitingDecision(P2); } public AwaitingDecision GetAwaitingDecision(String playerID) { return _userFeedback.getAwaitingDecision(playerID); } - public void FreepsUseAction(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); } - public void ShadowUseAction(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } + public Boolean FreepsActionAvailable(String action) { return ActionAvailable(P1, action); } + public Boolean FreepsCardActionAvailable(PhysicalCardImpl card) { return ActionAvailable(P1, "Use " + GameUtils.getFullName(card)); } + public Boolean FreepsCardPlayAvailable(PhysicalCardImpl card) { return ActionAvailable(P1, "Play " + GameUtils.getFullName(card)); } + public Boolean ShadowActionAvailable(String action) { return ActionAvailable(P2, action); } + public Boolean ShadowCardActionAvailable(PhysicalCardImpl card) { return ActionAvailable(P2, "Use " + GameUtils.getFullName(card)); } + public Boolean ShadowCardPlayAvailable(PhysicalCardImpl card) { return ActionAvailable(P2, "Play " + GameUtils.getFullName(card)); } + public Boolean ActionAvailable(String player, String action) { + List actions = GetAvailableActions(player); + String lowerAction = action.toLowerCase(); + return actions.stream().anyMatch(x -> x.toLowerCase().startsWith(lowerAction)); + } + + public List FreepsGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P1, paramName)); } + public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } + public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } + public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } + public Object GetAwaitingDecisionParam(String playerID, String paramName) { + AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); + return decision.getDecisionParameters().get(paramName); + } + + public Map GetAwaitingDecisionParams(String playerID) { + AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); + return decision.getDecisionParameters(); + } + + public void FreepsUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); } + public void FreepsUseCardAction(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Use " + GameUtils.getFullName(card))); } + public void ShadowUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } + public void ShadowUseCardAction(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, "Use " + GameUtils.getFullName(card))); } + + public void FreepsPlayCard(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); } + public void FreepsPlayCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Play " + GameUtils.getFullName(card))); } + public void ShadowPlayCard(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } + public void ShadowPlayCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, "Play " + GameUtils.getFullName(card))); } public int FreepsGetWoundsOn(String cardName) { return GetWoundsOn(GetFreepsCard(cardName)); } public int ShadowGetWoundsOn(String cardName) { return GetWoundsOn(GetShadowCard(cardName)); } @@ -134,13 +168,7 @@ public class GenericCardTest extends AbstractAtTest { public Phase GetCurrentPhase() { return _game.getGameState().getCurrentPhase(); } - public Boolean FreepsActionAvailable(String action) { return ActionAvailable(P1, action); } - public Boolean ShadowActionAvailable(String action) { return ActionAvailable(P2, action); } - public Boolean ActionAvailable(String player, String action) { - List actions = GetAvailableActions(player); - String lowerAction = action.toLowerCase(); - return actions.stream().anyMatch(x -> x.toLowerCase().startsWith(lowerAction)); - } + public void FreepsMoveCardToHand(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.HAND); } public void FreepsMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.HAND); } @@ -175,23 +203,6 @@ public class GenericCardTest extends AbstractAtTest { _game.getGameState().addCardToZone(_game, card, zone); } - - - public List FreepsGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P1, paramName)); } - public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } - public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } - public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } - public Object GetAwaitingDecisionParam(String playerID, String paramName) { - AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); - return decision.getDecisionParameters().get(paramName); - } - - public Map GetAwaitingDecisionParams(String playerID) { - AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); - return decision.getDecisionParameters(); - } - - public void FreepsPlayCharFromHand(String cardName) throws DecisionResultInvalidException { PhysicalCardImpl card = GetFreepsCard(cardName); List availableIds = FreepsGetADParamAsList("cardId"); @@ -235,12 +246,17 @@ public class GenericCardTest extends AbstractAtTest { } public void SkipCurrentPhaseActions() throws DecisionResultInvalidException { - Phase current = _game.getGameState().getCurrentPhase(); + FreepsSkipCurrentPhaseAction(); + ShadowSkipCurrentPhaseAction(); + } + public void FreepsSkipCurrentPhaseAction() throws DecisionResultInvalidException { if(_userFeedback.getAwaitingDecision(P1) != null) { playerDecided(P1, ""); } + } + public void ShadowSkipCurrentPhaseAction() throws DecisionResultInvalidException { if(_userFeedback.getAwaitingDecision(P2) != null) { playerDecided(P2, ""); } @@ -276,6 +292,11 @@ public class GenericCardTest extends AbstractAtTest { public void FreepsChooseCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, String.valueOf(card.getCardId())); } + public void ShadowChooseCard(PhysicalCardImpl card) throws DecisionResultInvalidException { + playerDecided(P2, String.valueOf(card.getCardId())); + } + public boolean FreepsCanChooseCharacter(PhysicalCardImpl card) { return FreepsGetADParamAsList("cardId").contains(card.getCardId()); } + public boolean ShadowCanChooseCharacter(PhysicalCardImpl card) { return ShadowGetADParamAsList("cardId").contains(card.getCardId()); } public boolean IsCharAssigned(PhysicalCardImpl card) { List assigns = _game.getGameState().getAssignments(); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java index e822974a5..2744dd620 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java @@ -4,7 +4,6 @@ import com.gempukku.lotro.cards.GenericCardTest; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; -import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import static org.junit.Assert.*; import org.junit.Test; @@ -61,13 +60,13 @@ public class Elrond_LoRErrataTest scn.StartGame(); assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); - assertTrue(scn.FreepsActionAvailable("Use Elrond")); + assertTrue(scn.FreepsCardActionAvailable(elrond)); assertEquals(0, scn.GetWoundsOn(elrond)); assertEquals(0, scn.GetFreepsHandCount()); assertEquals(1, scn.GetFreepsDeckCount()); - scn.FreepsUseAction("Use Elrond"); + scn.FreepsUseCardAction(elrond); assertEquals(2, scn.GetWoundsOn(elrond)); assertEquals(1, scn.GetFreepsHandCount()); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java index 7a22cd4f1..57894af7a 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java @@ -9,7 +9,6 @@ import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import org.junit.Test; import java.util.HashMap; -import java.util.List; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.*; @@ -50,9 +49,9 @@ public class FlamingBrandErrataTest scn.StartGame(); - assertTrue(scn.FreepsActionAvailable("Play Flaming Brand")); + assertTrue(scn.FreepsCardPlayAvailable(brand)); - scn.FreepsUseAction("Play Flaming Brand"); + scn.FreepsPlayCard(brand); //There are 3 companions in play, but only 2 rangers, so we should only see 2 options assertEquals(2, scn.FreepsGetADParamAsList("cardId").size()); @@ -74,9 +73,9 @@ public class FlamingBrandErrataTest scn.StartGame(); - scn.FreepsUseAction("Play Flaming Brand"); - assertTrue(scn.FreepsActionAvailable("Play Flaming Brand")); - scn.FreepsUseAction("Play Flaming Brand"); + scn.FreepsPlayCard(brand); + assertTrue(scn.FreepsCardPlayAvailable(brand2)); + scn.FreepsPlayCard(brand2); assertEquals(2, scn.GetAttachedCards(aragorn).size()); } @@ -100,7 +99,7 @@ public class FlamingBrandErrataTest scn.StartGame(); assertEquals(8, scn.GetStrength(aragorn)); - scn.FreepsUseAction("Play Flaming Brand"); + scn.FreepsPlayCard(brand); assertEquals(9, scn.GetStrength(aragorn)); scn.SkipToPhase(Phase.ASSIGNMENT); @@ -122,10 +121,10 @@ public class FlamingBrandErrataTest scn.FreepsResolveSkirmish(aragorn); assertEquals(1, scn.FreepsGetAvailableActions().size()); - assertTrue(scn.FreepsActionAvailable("Use Flaming Brand")); + assertTrue(scn.FreepsCardActionAvailable(brand)); assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); - scn.FreepsUseAction("Use Flaming Brand"); + scn.FreepsUseCardAction(brand); assertEquals(11, scn.GetStrength(aragorn)); assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java index 7d7490e16..4b19a50b6 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java @@ -47,13 +47,13 @@ public class Galadriel_LoLErrataTest scn.StartGame(); assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); - assertTrue(scn.FreepsActionAvailable("Use Galadriel")); + assertTrue(scn.FreepsCardActionAvailable(galadriel)); assertEquals(0, scn.GetWoundsOn(galadriel)); assertEquals(1, scn.GetFreepsHandCount()); assertEquals(0, scn.GetTwilight()); - scn.FreepsUseAction("Use Galadriel"); + scn.FreepsUseCardAction(galadriel); assertEquals(2, scn.GetWoundsOn(galadriel)); assertEquals(0, scn.GetFreepsHandCount()); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java index 83887855f..693e46c15 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java @@ -67,10 +67,10 @@ public class HornOfBoromirErrataTest scn.StartGame(); - assertFalse(scn.FreepsActionAvailable("Play Horn of Boromir")); - scn.FreepsUseAction("Play Boromir"); - assertTrue(scn.FreepsActionAvailable("Play Horn of Boromir")); - scn.FreepsUseAction("Play Horn of Boromir"); + assertFalse(scn.FreepsCardPlayAvailable(horn)); + scn.FreepsPlayCard(boromir); + assertTrue(scn.FreepsCardPlayAvailable(horn)); + scn.FreepsPlayCard(horn); Assert.assertEquals(Zone.ATTACHED, horn.getZone()); Assert.assertEquals(boromir, horn.getAttachedTo()); @@ -96,18 +96,18 @@ public class HornOfBoromirErrataTest scn.StartGame(); - scn.FreepsUseAction("Play Horn of Boromir"); + scn.FreepsPlayCard(horn); scn.SkipToPhase(Phase.ASSIGNMENT); - assertTrue(scn.FreepsActionAvailable("Use Horn of Boromir")); - scn.FreepsUseAction("Use Horn of Boromir"); + assertTrue(scn.FreepsCardActionAvailable(horn)); + scn.FreepsUseCardAction(horn); scn.FreepsChooseCard(runner1); assertEquals(1, scn.GetWoundsOn(boromir)); assertEquals(11, scn.GetStrength(elrond)); //Skip shadow player's action scn.SkipCurrentPhaseActions(); - assertFalse(scn.FreepsActionAvailable("Use Horn of Boromir")); + assertFalse(scn.FreepsCardActionAvailable(horn)); scn.SkipCurrentPhaseActions(); assertTrue(scn.IsCharAssigned(boromir)); @@ -134,10 +134,10 @@ public class HornOfBoromirErrataTest scn.StartGame(); - scn.FreepsUseAction("Play Horn of Boromir"); + scn.FreepsPlayCard(horn); scn.SkipToPhase(Phase.ASSIGNMENT); - scn.FreepsUseAction("Use Horn of Boromir"); + scn.FreepsUseCardAction(horn); scn.FreepsChooseCard(runner1); assertEquals(1, scn.GetWoundsOn(boromir)); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java index 7bd48f246..51fc84626 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java @@ -35,12 +35,12 @@ public class Sam_SoHErrataTest scn.StartGame(); assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); - assertTrue(scn.FreepsActionAvailable("Use Sam")); + assertTrue(scn.FreepsCardActionAvailable(sam)); assertEquals(0, scn.GetWoundsOn(sam)); assertEquals(1, scn.GetBurdens()); - scn.FreepsUseAction("Use Sam"); + scn.FreepsUseCardAction(sam); assertEquals(2, scn.GetWoundsOn(sam)); assertEquals(0, scn.GetBurdens()); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Saruman_KoIErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Saruman_KoIErrataTest.java new file mode 100644 index 000000000..ca53f1648 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Saruman_KoIErrataTest.java @@ -0,0 +1,111 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Saruman_KoIErrataTest +{ + protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("legolas", "1_50"); + put("tale", "1_66"); + put("doubleshot", "1_38"); + + put("saruman", "21_3068"); + put("uruk1", "1_151"); + put("uruk2", "1_151"); + }} + ); + } + + + @Test + public void SarumanWorks() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl legolas = scn.GetFreepsCard("legolas"); + PhysicalCardImpl tale = scn.GetFreepsCard("tale"); + PhysicalCardImpl doubleshot = scn.GetFreepsCard("doubleshot"); + + PhysicalCardImpl saruman = scn.GetShadowCard("saruman"); + PhysicalCardImpl uruk1 = scn.GetShadowCard("uruk1"); + PhysicalCardImpl uruk2 = scn.GetShadowCard("uruk2"); + + scn.FreepsMoveCharToTable(legolas); + scn.FreepsMoveCardToHand(tale); + scn.FreepsMoveCardToHand(doubleshot); + + scn.ShadowMoveCharToTable(saruman); + scn.ShadowMoveCharToTable(uruk1); + scn.ShadowMoveCharToTable(uruk2); + + + scn.StartGame(); + + scn.FreepsPlayCard(tale); + + scn.SkipToPhase(Phase.ARCHERY); + + //can't hit saruman + scn.FreepsUseCardAction(legolas); + assertFalse(scn.FreepsCanChooseCharacter(saruman)); + + scn.FreepsChooseCard(uruk1); + assertTrue(scn.ShadowCardActionAvailable(saruman)); + + //saruman blocks the uruk hit + scn.ShadowUseCardAction(saruman); + + assertEquals(0, scn.GetWoundsOn(uruk1)); + assertEquals(1, scn.GetWoundsOn(saruman)); + assertTrue(scn.HasKeyword(uruk1, Keyword.FIERCE)); + + //shadow has to skip archery actions + scn.ShadowSkipCurrentPhaseAction(); + + //Repeat the greenleaf ability to ensure the last can't be blocked by saruman + scn.FreepsUseCardAction(legolas); + scn.FreepsChooseCard(uruk1); + scn.ShadowUseCardAction(saruman); + scn.ShadowSkipCurrentPhaseAction(); + + scn.FreepsUseCardAction(legolas); + scn.FreepsChooseCard(uruk1); + scn.ShadowUseCardAction(saruman); + scn.ShadowSkipCurrentPhaseAction(); + + //greenleaf is out of vitality, so play doubleshot + scn.FreepsPlayCard(doubleshot); + scn.ShadowSkipCurrentPhaseAction(); + scn.FreepsSkipCurrentPhaseAction(); + + //Archery wound + scn.ShadowChooseCard(uruk1); + + //Now that we've done 4 total wounds, we should see an exhausted saruman and an uruk1 with 1 wound + assertEquals(1, scn.GetWoundsOn(uruk1)); + assertEquals(3, scn.GetWoundsOn(saruman)); + + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.SkipCurrentPhaseActions(); + + //saruman is not on the list of assignable minions + assertEquals(2, scn.FreepsGetADParamAsList("minions").size()); + + } +} From 9ebd3dc6fa8d3c47d11d853a1e12168d1997ad17 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 2 Feb 2021 23:14:13 -0600 Subject: [PATCH 25/74] Including missed image info for Saruman, KoI and missing rarity info --- gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js | 3 ++- gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index 68a205d71..d97a5b151 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -59,5 +59,6 @@ var set21 = { '21_10316': 'https://i.lotrtcgpc.net/errata/FOTR/21_316.jpg', '21_2032': 'https://i.lotrtcgpc.net/errata/FOTR/22_32.jpg', '21_2075': 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', - '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg' + '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', + '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt index 4e3e9a3f5..f7bea1926 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt @@ -58,3 +58,5 @@ 21U10316 21R2032 21R2075 +21R3042 +21R3068 \ No newline at end of file From 01e10c574d5892f09685d22572efb6a790810c5d Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 3 Feb 2021 01:08:15 -0600 Subject: [PATCH 26/74] Concealed work, No Stranger to the Shadows errata. Concealed and Exposed keywords added. No Stranger errata added. Unit test for No Stranger added; it also puts the two keywords through its paces. --- .../src/main/web/cards/set21/set1-errata.json | 196 +++++++++--------- .../src/main/web/js/gemp-022/set21.js | 1 + .../src/main/resources/set21-rarity.txt | 3 +- .../com/gempukku/lotro/common/Keyword.java | 2 +- .../lotro/logic/modifiers/ModifiersLogic.java | 2 - .../gempukku/lotro/logic/timing/RuleSet.java | 1 + .../logic/timing/rules/ConcealedRule.java | 64 ++++++ .../gempukku/lotro/cards/GenericCardTest.java | 21 ++ .../pc/errata/NoStrangerErrataTest.java | 139 +++++++++++++ 9 files changed, 328 insertions(+), 101 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/ConcealedRule.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index e487416ca..1eca1dea3 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -115,25 +115,7 @@ ] } }, - "21_10108": { - "title": "*No Stranger to the Shadows", - "culture": "gondor", - "cost": 0, - "type": "condition", - "keyword": [ - "stealth" - ], - "target": "ranger,not(hasAttached(name(No Stranger to the Shadows)))", - "effects": { - "type": "modifier", - "modifier": { - "type": "addKeyword", - "filter": "bearer", - "keyword": "concealed" - } - } - }, - + "21_10139": { "title": "Savagery To Match Their Numbers", "culture": "isengard", @@ -307,84 +289,6 @@ ] }, - "21_10313": { - "title": "*Sting", - "culture": "shire", - "cost": 1, - "type": "possession", - "possession": "hand weapon", - "strength": 2, - "target": "name(Frodo)", - "effects": { - "type": "activated", - "phase": [ - "fellowship", - "regroup" - ], - "cost": { - "type": "exert", - "filter": "bearer" - }, - "effect": [ - { - "type": "revealrandomcardsfromhand", - "hand": "shadowPlayer", - "forced": true, - "memorize": "revealedCards", - "count":3 - }, - { - "type": "addKeyword", - "filter": "choose(companion)", - "keyword": "concealed", - "until": "start(regroup)", - "amount": { - "type": "forEachMatchingInMemory", - "memory": "revealedCards", - "filter": "orc", - "limit": 1 - } - } - ] - } - }, - - "21_10316": { - "title": "*A Talent for Not Being Seen", - "culture": "shire", - "cost": 0, - "type": "condition", - "keyword": [ - "stealth", - "support area" - ], - "effects": [ - { - "type": "extraCost", - "cost": { - "type": "exert", - "filter": "choose(hobbit)" - } - }, - { - "type": "trigger", - "trigger": { - "type": "moves" - }, - "cost": { - "type": "exert", - "filter": "choose(hobbit)" - }, - "effect": { - "type": "addKeyword", - "filter": "self", - "keyword": "defender+1", - "until": "start(regroup)" - } - } - ] - }, - "21_2032": { "side": "free_people", "cost": 0, @@ -532,4 +436,102 @@ ] }, + + "21_10108": { + "title": "No Stranger to the Shadows", + "culture": "gondor", + "cost": 0, + "type": "condition", + "keyword": [ + "stealth" + ], + "target": "ranger,not(hasAttached(name(No Stranger to the Shadows)))", + "effects": { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "bearer", + "keyword": "concealed" + } + } + }, + + + "21_10313": { + "title": "*Sting", + "culture": "shire", + "cost": 1, + "type": "possession", + "possession": "hand weapon", + "strength": 2, + "target": "name(Frodo)", + "effects": { + "type": "activated", + "phase": [ + "fellowship", + "regroup" + ], + "cost": { + "type": "exert", + "filter": "bearer" + }, + "effect": [ + { + "type": "revealrandomcardsfromhand", + "hand": "shadowPlayer", + "forced": true, + "memorize": "revealedCards", + "count":3 + }, + { + "type": "addKeyword", + "filter": "choose(companion)", + "keyword": "concealed", + "until": "start(regroup)", + "amount": { + "type": "forEachMatchingInMemory", + "memory": "revealedCards", + "filter": "orc", + "limit": 1 + } + } + ] + } + }, + + "21_10316": { + "title": "*A Talent for Not Being Seen", + "culture": "shire", + "cost": 0, + "type": "condition", + "keyword": [ + "stealth", + "support area" + ], + "effects": [ + { + "type": "extraCost", + "cost": { + "type": "exert", + "filter": "choose(hobbit)" + } + }, + { + "type": "trigger", + "trigger": { + "type": "moves" + }, + "cost": { + "type": "exert", + "filter": "choose(hobbit)" + }, + "effect": { + "type": "addKeyword", + "filter": "self", + "keyword": "defender+1", + "until": "start(regroup)" + } + } + ] + }, } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index d97a5b151..160b6c12e 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -61,4 +61,5 @@ var set21 = { '21_2075': 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', + '21_10108': 'https://i.lotrtcgpc.net/errata/FOTR/21_108.jpg', } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt index f7bea1926..b861849d3 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt @@ -59,4 +59,5 @@ 21R2032 21R2075 21R3042 -21R3068 \ No newline at end of file +21R3068 +21U10108 \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java index d3c94f221..a5f3879a0 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Keyword.java @@ -33,7 +33,7 @@ public enum Keyword implements Filterable { WISE("Wise", true), BURGLAR("Burglar", true), //PC Keywords - CONCEALED("Concealed", true); + CONCEALED("Concealed", true), EXPOSED("Exposed", true); private String _humanReadable; private boolean _infoDisplayable; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java index b1341de9c..dbac1beb9 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/modifiers/ModifiersLogic.java @@ -385,8 +385,6 @@ public class ModifiersLogic implements ModifiersEnvironment, ModifiersQuerying { @Override public boolean addsTwilightForCompanionMove(LotroGame game, PhysicalCard companion) { for (Modifier modifier : getModifiersAffectingCard(game, ModifierEffect.MOVE_TWILIGHT_MODIFIER, companion)) { - if (hasKeyword(game, companion, Keyword.CONCEALED)) - return false; if (!modifier.addsTwilightForCompanionMove(game, companion)) return false; } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleSet.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleSet.java index 41631ec95..f7a42f5be 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleSet.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/RuleSet.java @@ -65,5 +65,6 @@ public class RuleSet { new HealByDiscardRule(_actionsEnvironment).applyRule(); new TakeOffRingRule(_actionsEnvironment).applyRule(); + new ConcealedRule(_actionsEnvironment).applyRule(); } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/ConcealedRule.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/ConcealedRule.java new file mode 100644 index 000000000..13561a237 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/ConcealedRule.java @@ -0,0 +1,64 @@ +package com.gempukku.lotro.logic.timing.rules; + +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.filters.Filters; +import com.gempukku.lotro.game.AbstractActionProxy; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.game.state.actions.DefaultActionsEnvironment; +import com.gempukku.lotro.logic.GameUtils; +import com.gempukku.lotro.logic.actions.OptionalTriggerAction; +import com.gempukku.lotro.logic.actions.RequiredTriggerAction; +import com.gempukku.lotro.logic.effects.*; +import com.gempukku.lotro.logic.modifiers.evaluator.ConstantEvaluator; +import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator; +import com.gempukku.lotro.logic.modifiers.evaluator.LocationEvaluator; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; +import com.gempukku.lotro.logic.timing.PlayConditions; +import com.gempukku.lotro.logic.timing.TriggerConditions; + +import java.util.*; + +public class ConcealedRule { + private DefaultActionsEnvironment _actionsEnvironment; + + public ConcealedRule(DefaultActionsEnvironment actionsEnvironment) { + _actionsEnvironment = actionsEnvironment; + } + + public void applyRule() { + _actionsEnvironment.addAlwaysOnActionProxy( + new AbstractActionProxy() { + @Override + public List getRequiredAfterTriggers(final LotroGame game, EffectResult effectResult) { + if (TriggerConditions.moves(game, effectResult) + && game.getGameState().getCurrentPhase() == Phase.FELLOWSHIP) { + List actions = new ArrayList<>(); + + int twilight = Filters.filterActive(game, CardType.COMPANION, Keyword.CONCEALED).size(); + + if(twilight == 0) + return null; + + final RequiredTriggerAction action = new RequiredTriggerAction(null); + LocationEvaluator loc = new LocationEvaluator(twilight, 0, Keyword.EXPOSED); + action.appendEffect(new RemoveTwilightEffect(new LocationEvaluator(twilight, 0, Keyword.EXPOSED))); + + if(loc.evaluateExpression(game, null) == 0) { + action.setText("Concealed companions were exposed! No twilight was removed."); + } + else { + action.setText("Concealed companions trigger removal of " + twilight + " twilight."); + } + actions.add(action); + + return actions; + } + return null; + } + }); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index 718555615..c229501e9 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -12,6 +12,7 @@ import com.gempukku.lotro.game.state.Assignment; import com.gempukku.lotro.logic.GameUtils; import com.gempukku.lotro.logic.decisions.AwaitingDecision; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.Modifier; import com.gempukku.lotro.logic.vo.LotroDeck; import java.util.*; @@ -99,6 +100,19 @@ public class GenericCardTest extends AbstractAtTest { public PhysicalCardImpl GetFreepsCard(String cardName) { return Cards.get(P1).get(cardName); } public PhysicalCardImpl GetShadowCard(String cardName) { return Cards.get(P2).get(cardName); } + public PhysicalCardImpl GetFreepsSite(int siteNum) { return GetSite(P1, siteNum); } + public PhysicalCardImpl GetShadowSite(int siteNum) { return GetSite(P2, siteNum); } + public PhysicalCardImpl GetSite(String playerID, int siteNum) + { + List advDeck = (List)_game.getGameState().getAdventureDeck(playerID); +// for (PhysicalCardImpl card : advDeck) { +// if (card.getSiteNumber() == siteNum){ +// return card; +// } +// } + return advDeck.stream().filter(x -> x.getBlueprint().getSiteNumber() == siteNum).findFirst().get(); + } + public List FreepsGetAvailableActions() { return GetAvailableActions(P1); } public List ShadowGetAvailableActions() { return GetAvailableActions(P2); } public List GetAvailableActions(String playerID) { @@ -315,4 +329,11 @@ public class GenericCardTest extends AbstractAtTest { { return _game.getModifiersQuerying().hasKeyword(_game, card, keyword); } + + + public void InsertAdHocModifier(Modifier mod) + { + _game.getModifiersEnvironment().addUntilEndOfTurnModifier(mod); + } + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java new file mode 100644 index 000000000..389043245 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java @@ -0,0 +1,139 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.KeywordModifier; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class NoStrangerErrataTest +{ + protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("aragorn", "1_89"); + put("arwen", "1_30"); + put("nostranger", "21_10108"); + put("nostranger2", "21_10108"); + }} + ); + } + + + @Test + public void ConcealedDoesNothingIfNoTwilight() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCardToHand(nostranger); + + scn.StartGame(); + + assertTrue(scn.FreepsCardPlayAvailable(nostranger)); + scn.FreepsPlayCard(nostranger); + + assertTrue(scn.HasKeyword(aragorn, Keyword.CONCEALED)); + + assertEquals(0, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent) + assertEquals(3, scn.GetTwilight()); + } + + @Test + public void ConcealedRemovesOneIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + + scn.FreepsMoveCardToHand(aragorn); + scn.FreepsMoveCardToHand(nostranger); + + scn.StartGame(); + + scn.FreepsPlayCard(aragorn); + scn.FreepsPlayCard(nostranger); + + //4 from playing aragorn + assertEquals(4, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //4 from playing aragorn, 1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent), -1 for concealed + assertEquals(6, scn.GetTwilight()); + } + + @Test + public void TwoConcealedRemovesTwoIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + PhysicalCardImpl nostranger2 = scn.GetFreepsCard("nostranger2"); + + scn.FreepsMoveCardToHand(aragorn); + scn.FreepsMoveCharToTable(arwen); + scn.FreepsMoveCardToHand(nostranger); + scn.FreepsMoveCardToHand(nostranger2); + + scn.StartGame(); + + scn.FreepsPlayCard(aragorn); + scn.FreepsPlayCard(nostranger); + scn.FreepsChooseCard(aragorn); + scn.FreepsPlayCard(nostranger2); + + + //4 from playing aragorn + assertEquals(4, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //4 from playing aragorn, 1+1+1 for companions, 1 for the site (King's Tent), -2 for concealed + assertEquals(6, scn.GetTwilight()); + } + + @Test + public void ConcealedRemovesNothingIfExposed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + + scn.FreepsMoveCardToHand(aragorn); + scn.FreepsMoveCardToHand(nostranger); + + scn.StartGame(); + + scn.FreepsPlayCard(aragorn); + scn.FreepsPlayCard(nostranger); + + scn.InsertAdHocModifier(new KeywordModifier(null, CardType.SITE, Keyword.EXPOSED)); + + //4 from playing aragorn + assertEquals(4, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //4 from playing aragorn, 1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent), 0 for exposed concealed + assertEquals(7, scn.GetTwilight()); + } +} From 65d40dd1d645470da5cb61b9ea6ceab02dd72a6b Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 3 Feb 2021 18:43:23 -0600 Subject: [PATCH 27/74] Sting Errata. Exposed testing fleshed out. Introduced Sting errata and unit tests. Pulled out the concealed/exposed specific parts of the No Stranger tests and put them in their own place, replacing the No Stranger tests with ones that are more specific to that card. --- .../src/main/web/cards/set21/set1-errata.json | 2 +- .../lotro/at/ConcealedExposedAtTest.java | 125 ++++++++++++ .../gempukku/lotro/cards/GenericCardTest.java | 49 ++++- .../pc/errata/NoStrangerErrataTest.java | 154 ++++++--------- .../unofficial/pc/errata/StingErrataTest.java | 183 ++++++++++++++++++ 5 files changed, 414 insertions(+), 99 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 1eca1dea3..0265f10ad 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -485,7 +485,7 @@ }, { "type": "addKeyword", - "filter": "choose(companion)", + "filter": "choose(companion,not(concealed))", "keyword": "concealed", "until": "start(regroup)", "amount": { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java new file mode 100644 index 000000000..931a0f37f --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java @@ -0,0 +1,125 @@ +package com.gempukku.lotro.at; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.AwaitingDecision; +import com.gempukku.lotro.logic.decisions.AwaitingDecisionType; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.KeywordModifier; +import org.junit.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static junit.framework.Assert.*; +import static org.junit.Assert.assertTrue; + +public class ConcealedExposedAtTest extends AbstractAtTest { + protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("aragorn", "1_89"); + put("arwen", "1_30"); + }} + ); + } + + + @Test + public void ConcealedDoesNothingIfNoTwilight() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + scn.FreepsMoveCharToTable(aragorn); + + scn.StartGame(); + + scn.InsertAdHocModifier(new KeywordModifier(aragorn, aragorn, Keyword.CONCEALED)); + + assertEquals(0, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent) + assertEquals(3, scn.GetTwilight()); + } + + @Test + public void ConcealedRemovesOneIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + + scn.FreepsMoveCardToHand(aragorn); + + scn.StartGame(); + + scn.FreepsPlayCard(aragorn); + scn.InsertAdHocModifier(new KeywordModifier(aragorn, aragorn, Keyword.CONCEALED)); + + //4 from playing aragorn + assertEquals(4, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //4 from playing aragorn, 1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent), -1 for concealed + assertEquals(6, scn.GetTwilight()); + } + + @Test + public void TwoConcealedRemovesTwoIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + + scn.FreepsMoveCardToHand(aragorn); + scn.FreepsMoveCharToTable(arwen); + + scn.StartGame(); + + scn.FreepsPlayCard(aragorn); + scn.InsertAdHocModifier(new KeywordModifier(aragorn, Keyword.RANGER, Keyword.CONCEALED)); + + + //4 from playing aragorn + assertEquals(4, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //4 from playing aragorn, 1+1+1 for companions, 1 for the site (King's Tent), -2 for concealed + assertEquals(6, scn.GetTwilight()); + } + + @Test + public void ConcealedRemovesNothingIfExposed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + scn.FreepsMoveCardToHand(aragorn); + + scn.StartGame(); + + scn.FreepsPlayCard(aragorn); + scn.InsertAdHocModifier(new KeywordModifier(aragorn, Keyword.RANGER, Keyword.CONCEALED)); + + scn.InsertAdHocModifier(new KeywordModifier(null, CardType.SITE, Keyword.EXPOSED)); + + //4 from playing aragorn + assertEquals(4, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + //4 from playing aragorn, 1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent), 0 for exposed concealed + assertEquals(7, scn.GetTwilight()); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index c229501e9..7eaa76dce 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -136,6 +136,13 @@ public class GenericCardTest extends AbstractAtTest { return actions.stream().anyMatch(x -> x.toLowerCase().startsWith(lowerAction)); } + public Boolean FreepsAnyActionsAvailable() { return AnyActionsAvailable(P1); } + public Boolean ShadowAnyActionsAvailable() { return AnyActionsAvailable(P2); } + public Boolean AnyActionsAvailable(String player) { + List actions = GetAvailableActions(player); + return actions.size() > 0; + } + public List FreepsGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P1, paramName)); } public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } @@ -186,23 +193,41 @@ public class GenericCardTest extends AbstractAtTest { public void FreepsMoveCardToHand(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.HAND); } public void FreepsMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.HAND); } + public void FreepsMoveCardsToHand(PhysicalCardImpl...cards) { + for(PhysicalCardImpl card : cards) { + FreepsMoveCardToHand(card); + } + } public void ShadowMoveCardToHand(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.HAND); } public void ShadowMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.HAND); } + public void ShadowMoveCardsToHand(PhysicalCardImpl...cards) { + for(PhysicalCardImpl card : cards) { + ShadowMoveCardToHand(card); + } + } + + + public void AttachCard(PhysicalCardImpl card, PhysicalCardImpl bearer) { _game.getGameState().attachCard(_game, card, bearer); } + public void FreepsMoveCardToDeck(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.DECK); } public void FreepsMoveCardToDeck(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.DECK); } public void ShadowMoveCardToDeck(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.DECK); } public void ShadowMoveCardToDeck(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.DECK); } public void FreepsMoveCharToTable(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.FREE_CHARACTERS); } - public void FreepsMoveCharToTable(PhysicalCardImpl card) - { - MoveCardToZone(P1, card, Zone.FREE_CHARACTERS); + public void FreepsMoveCharToTable(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.FREE_CHARACTERS); } + public void FreepsMoveCharsToTable(PhysicalCardImpl...cards) { + for(PhysicalCardImpl card : cards) { + FreepsMoveCharToTable(card); + } } public void ShadowMoveCharToTable(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.SHADOW_CHARACTERS); } - public void ShadowMoveCharToTable(PhysicalCardImpl card) - { - MoveCardToZone(P2, card, Zone.SHADOW_CHARACTERS); + public void ShadowMoveCharToTable(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.SHADOW_CHARACTERS); } + public void ShadowMoveCharsToTable(PhysicalCardImpl...cards) { + for(PhysicalCardImpl card : cards) { + ShadowMoveCharToTable(card); + } } public void FreepsMoveCardToZone(String cardID, Zone zone) { MoveCardToZone(P1, GetFreepsCard(cardID), zone); } @@ -309,8 +334,8 @@ public class GenericCardTest extends AbstractAtTest { public void ShadowChooseCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, String.valueOf(card.getCardId())); } - public boolean FreepsCanChooseCharacter(PhysicalCardImpl card) { return FreepsGetADParamAsList("cardId").contains(card.getCardId()); } - public boolean ShadowCanChooseCharacter(PhysicalCardImpl card) { return ShadowGetADParamAsList("cardId").contains(card.getCardId()); } + public boolean FreepsCanChooseCharacter(PhysicalCardImpl card) { return FreepsGetADParamAsList("cardId").contains(String.valueOf(card.getCardId())); } + public boolean ShadowCanChooseCharacter(PhysicalCardImpl card) { return ShadowGetADParamAsList("cardId").contains(String.valueOf(card.getCardId())); } public boolean IsCharAssigned(PhysicalCardImpl card) { List assigns = _game.getGameState().getAssignments(); @@ -336,4 +361,12 @@ public class GenericCardTest extends AbstractAtTest { _game.getModifiersEnvironment().addUntilEndOfTurnModifier(mod); } + public void FreepsChooseToMove() throws DecisionResultInvalidException { + playerDecided(P1, "0"); + } + + public void FreepsChooseToStay() throws DecisionResultInvalidException { + playerDecided(P1, "1"); + } + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java index 389043245..09f6933ef 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java @@ -24,6 +24,7 @@ public class NoStrangerErrataTest {{ put("aragorn", "1_89"); put("arwen", "1_30"); + put("boromir", "1_97"); put("nostranger", "21_10108"); put("nostranger2", "21_10108"); }} @@ -32,7 +33,68 @@ public class NoStrangerErrataTest @Test - public void ConcealedDoesNothingIfNoTwilight() throws DecisionResultInvalidException, CardNotFoundException { + public void NoStrangerHasStealth() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + + assertTrue(scn.HasKeyword(nostranger, Keyword.STEALTH)); + } + + @Test + public void NoStrangerCanOnlyPlayOnRanger() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCharToTable(arwen); + scn.FreepsMoveCharToTable(boromir); + scn.FreepsMoveCardToHand(nostranger); + + scn.StartGame(); + + assertTrue(scn.FreepsCardPlayAvailable(nostranger)); + + scn.FreepsPlayCard(nostranger); + + //There are 3 companions in play, but only 2 rangers, so we should only see 2 options + assertEquals(2, scn.FreepsGetADParamAsList("cardId").size()); + } + + @Test + public void NoStrangerLimitOnePerBearer() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); + PhysicalCardImpl nostranger2 = scn.GetFreepsCard("nostranger2"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCharToTable(arwen); + scn.FreepsMoveCardToHand(nostranger); + scn.FreepsMoveCardToHand(nostranger2); + + scn.StartGame(); + + scn.FreepsPlayCard(nostranger); + scn.FreepsChooseCard(aragorn); + scn.FreepsPlayCard(nostranger2); + + //No prompt means it was placed automatically on Arwen, with no choice between Arwen and Aragorn + assertFalse(scn.FreepsAnyActionsAvailable()); + + } + + @Test + public void NoStrangerAddsConcealed() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTest scn = GetScenario(); @@ -44,96 +106,8 @@ public class NoStrangerErrataTest scn.StartGame(); - assertTrue(scn.FreepsCardPlayAvailable(nostranger)); scn.FreepsPlayCard(nostranger); - assertTrue(scn.HasKeyword(aragorn, Keyword.CONCEALED)); - - assertEquals(0, scn.GetTwilight()); - scn.FreepsSkipCurrentPhaseAction(); - - //1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent) - assertEquals(3, scn.GetTwilight()); - } - - @Test - public void ConcealedRemovesOneIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTest scn = GetScenario(); - - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); - - scn.FreepsMoveCardToHand(aragorn); - scn.FreepsMoveCardToHand(nostranger); - - scn.StartGame(); - - scn.FreepsPlayCard(aragorn); - scn.FreepsPlayCard(nostranger); - - //4 from playing aragorn - assertEquals(4, scn.GetTwilight()); - scn.FreepsSkipCurrentPhaseAction(); - - //4 from playing aragorn, 1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent), -1 for concealed - assertEquals(6, scn.GetTwilight()); - } - - @Test - public void TwoConcealedRemovesTwoIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTest scn = GetScenario(); - - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); - PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); - PhysicalCardImpl nostranger2 = scn.GetFreepsCard("nostranger2"); - - scn.FreepsMoveCardToHand(aragorn); - scn.FreepsMoveCharToTable(arwen); - scn.FreepsMoveCardToHand(nostranger); - scn.FreepsMoveCardToHand(nostranger2); - - scn.StartGame(); - - scn.FreepsPlayCard(aragorn); - scn.FreepsPlayCard(nostranger); - scn.FreepsChooseCard(aragorn); - scn.FreepsPlayCard(nostranger2); - - - //4 from playing aragorn - assertEquals(4, scn.GetTwilight()); - scn.FreepsSkipCurrentPhaseAction(); - - //4 from playing aragorn, 1+1+1 for companions, 1 for the site (King's Tent), -2 for concealed - assertEquals(6, scn.GetTwilight()); - } - - @Test - public void ConcealedRemovesNothingIfExposed() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTest scn = GetScenario(); - - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); - - scn.FreepsMoveCardToHand(aragorn); - scn.FreepsMoveCardToHand(nostranger); - - scn.StartGame(); - - scn.FreepsPlayCard(aragorn); - scn.FreepsPlayCard(nostranger); - - scn.InsertAdHocModifier(new KeywordModifier(null, CardType.SITE, Keyword.EXPOSED)); - - //4 from playing aragorn - assertEquals(4, scn.GetTwilight()); - scn.FreepsSkipCurrentPhaseAction(); - - //4 from playing aragorn, 1 for the ring-bearer, 1 for aragorn, 1 for the site (King's Tent), 0 for exposed concealed - assertEquals(7, scn.GetTwilight()); + scn.HasKeyword(aragorn, Keyword.CONCEALED); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java new file mode 100644 index 000000000..f353f5152 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java @@ -0,0 +1,183 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class StingErrataTest +{ + protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("sting", "21_10313"); + put("sam", "1_311"); + put("merry", "1_302"); + + put("orc1", "1_178"); + put("orc2", "1_178"); + put("orc3", "1_178"); + put("scimitar1", "1_180"); + put("scimitar2", "1_180"); + put("scimitar3", "1_180"); + }} + ); + } + + + @Test + public void StingCanOnlyBeBorneByFrodo() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + PhysicalCardImpl sting = scn.GetFreepsCard("sting"); + + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCardToHand(sting); + + scn.StartGame(); + + scn.FreepsPlayCard(sting); + + //should have automatically gone to frodo as the only valid target + Assert.assertEquals(Zone.ATTACHED, sting.getZone()); + Assert.assertEquals(frodo, sting.getAttachedTo()); + } + + @Test + public void StingAbilityAvailableInBothFellowshipAndRegroup() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sting = scn.GetFreepsCard("sting"); + + scn.AttachCard(sting, frodo); + + scn.StartGame(); + + assertTrue(scn.FreepsCardActionAvailable(sting)); + + scn.SkipToPhase(Phase.REGROUP); + + assertTrue(scn.FreepsCardActionAvailable(sting)); + } + + @Test + public void StingAbilityExertsFrodoAndRevealsThreeCards() throws DecisionResultInvalidException, CardNotFoundException { + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sting = scn.GetFreepsCard("sting"); + + PhysicalCardImpl orc1 = scn.GetShadowCard("orc1"); + PhysicalCardImpl orc2 = scn.GetShadowCard("orc2"); + PhysicalCardImpl orc3 = scn.GetShadowCard("orc3"); + PhysicalCardImpl scimitar1 = scn.GetShadowCard("scimitar1"); + + scn.AttachCard(sting, frodo); + + scn.ShadowMoveCardsToHand(orc1, orc2, orc3, scimitar1); + + scn.StartGame(); + + scn.FreepsUseCardAction(sting); + + //Reveals 3 cards + assertEquals(3, scn.FreepsGetADParamAsList("blueprintId").size()); + assertEquals(1, scn.GetWoundsOn(frodo)); + } + + @Test + public void StingAbilityMakesConcealedIfOrcRevealed() throws DecisionResultInvalidException, CardNotFoundException { + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sting = scn.GetFreepsCard("sting"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + PhysicalCardImpl merry = scn.GetFreepsCard("merry"); + + PhysicalCardImpl orc1 = scn.GetShadowCard("orc1"); + + scn.FreepsMoveCharsToTable(sam, merry); + scn.AttachCard(sting, frodo); + + scn.ShadowMoveCardToHand(orc1); + + scn.StartGame(); + + scn.FreepsUseCardAction(sting); + + //Both players have revealed cards as an action to dismiss + scn.SkipCurrentPhaseActions(); + + assertTrue(scn.FreepsCanChooseCharacter(frodo)); + assertTrue(scn.FreepsCanChooseCharacter(sam)); + assertTrue(scn.FreepsCanChooseCharacter(merry)); + + scn.FreepsChooseCard(frodo); + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + + scn.FreepsUseCardAction(sting); + scn.SkipCurrentPhaseActions(); + assertFalse(scn.FreepsCanChooseCharacter(frodo)); + assertTrue(scn.FreepsCanChooseCharacter(sam)); + assertTrue(scn.FreepsCanChooseCharacter(merry)); + + scn.FreepsChooseCard(sam); + assertTrue(scn.HasKeyword(sam, Keyword.CONCEALED)); + } + + + @Test + public void StingConcealedLastsUntilNextRegroup() throws DecisionResultInvalidException, CardNotFoundException { + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sting = scn.GetFreepsCard("sting"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + PhysicalCardImpl orc1 = scn.GetShadowCard("orc1"); + + scn.FreepsMoveCharsToTable(sam); + scn.AttachCard(sting, frodo); + + scn.ShadowMoveCardToHand(orc1); + + scn.StartGame(); + + scn.SkipToPhase(Phase.REGROUP); + + scn.FreepsUseCardAction(sting); + scn.FreepsChooseCard(frodo); + //Both players have revealed cards as an action to dismiss + scn.SkipCurrentPhaseActions(); + + scn.FreepsChooseCard(frodo); + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + + scn.ShadowSkipCurrentPhaseAction(); + scn.FreepsSkipCurrentPhaseAction(); + //shadow reconcile + scn.ShadowSkipCurrentPhaseAction(); + + scn.FreepsChooseToMove(); + + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + } +} From 2fd2726e4a620d348a59d490e386b342396cb091 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 3 Feb 2021 21:13:59 -0600 Subject: [PATCH 28/74] Talent For Not Being Seen Errata and tests --- .../src/main/web/cards/set21/set1-errata.json | 12 +- .../src/main/web/js/gemp-022/set21.js | 1 - .../gempukku/lotro/cards/GenericCardTest.java | 65 +++++---- .../pc/errata/Elrond_LoRErrataTest.java | 26 ++-- .../unofficial/pc/errata/StingErrataTest.java | 5 +- .../pc/errata/TalentForNBSErrataTest.java | 131 ++++++++++++++++++ 6 files changed, 188 insertions(+), 52 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/TalentForNBSErrataTest.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 0265f10ad..b25316080 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -521,17 +521,19 @@ "trigger": { "type": "moves" }, - "cost": { - "type": "exert", - "filter": "choose(hobbit)" + "condition": { + "type": "canSpot", + "count": 2, + "filter": "hobbit,companion" }, "effect": { "type": "addKeyword", - "filter": "self", - "keyword": "defender+1", + "filter": "choose(hobbit,companion)", + "keyword": "concealed", "until": "start(regroup)" } } + ] }, } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index 160b6c12e..d97a5b151 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -61,5 +61,4 @@ var set21 = { '21_2075': 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', - '21_10108': 'https://i.lotrtcgpc.net/errata/FOTR/21_108.jpg', } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index 7eaa76dce..345ddd853 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -143,6 +143,8 @@ public class GenericCardTest extends AbstractAtTest { return actions.size() > 0; } + public List FreepsGetCardChoices() { return FreepsGetADParamAsList("cardId"); } + public List ShadowGetCardChoices() { return FreepsGetADParamAsList("cardId"); } public List FreepsGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P1, paramName)); } public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } @@ -210,30 +212,33 @@ public class GenericCardTest extends AbstractAtTest { public void AttachCard(PhysicalCardImpl card, PhysicalCardImpl bearer) { _game.getGameState().attachCard(_game, card, bearer); } - public void FreepsMoveCardToDeck(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.DECK); } - public void FreepsMoveCardToDeck(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.DECK); } - public void ShadowMoveCardToDeck(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.DECK); } - public void ShadowMoveCardToDeck(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.DECK); } - - public void FreepsMoveCharToTable(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.FREE_CHARACTERS); } - public void FreepsMoveCharToTable(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.FREE_CHARACTERS); } - public void FreepsMoveCharsToTable(PhysicalCardImpl...cards) { - for(PhysicalCardImpl card : cards) { - FreepsMoveCharToTable(card); - } + public void FreepsMoveCardToDeck(String cardName) { FreepsMoveCardToDeck(GetFreepsCard(cardName)); } + public void FreepsMoveCardToDeck(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DECK)); } - public void ShadowMoveCharToTable(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.SHADOW_CHARACTERS); } - public void ShadowMoveCharToTable(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.SHADOW_CHARACTERS); } - public void ShadowMoveCharsToTable(PhysicalCardImpl...cards) { - for(PhysicalCardImpl card : cards) { - ShadowMoveCharToTable(card); - } + public void ShadowMoveCardToDeck(String cardName) { ShadowMoveCardToDeck(GetShadowCard(cardName)); } + public void ShadowMoveCardToDeck(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DECK)); + } + + public void FreepsMoveCharToTable(String cardName) { FreepsMoveCharToTable(GetFreepsCard(cardName)); } + public void FreepsMoveCharToTable(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.FREE_CHARACTERS)); + } + public void ShadowMoveCharToTable(String cardName) { FreepsMoveCharToTable(GetShadowCard(cardName)); } + public void ShadowMoveCharToTable(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P2, card, Zone.FREE_CHARACTERS)); + } + + public void FreepsMoveCardToSupportArea(String cardName) { FreepsMoveCardToSupportArea(GetFreepsCard(cardName)); } + public void FreepsMoveCardToSupportArea(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.SUPPORT)); + } + public void ShadowMoveCardToSupportArea(String cardName) { ShadowMoveCardToSupportArea(GetShadowCard(cardName)); } + public void ShadowMoveCardToSupportArea(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.SUPPORT)); } - public void FreepsMoveCardToZone(String cardID, Zone zone) { MoveCardToZone(P1, GetFreepsCard(cardID), zone); } - public void FreepsMoveCardToZone(PhysicalCardImpl card, Zone zone) { MoveCardToZone(P1, card, zone); } - public void ShadowMoveCardToZone(String cardID, Zone zone) { MoveCardToZone(P2, GetShadowCard(cardID), zone); } - public void ShadowMoveCardToZone(PhysicalCardImpl card, Zone zone) { MoveCardToZone(P2, card, zone); } public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) { if(card.getZone() != null) { @@ -242,23 +247,14 @@ public class GenericCardTest extends AbstractAtTest { _game.getGameState().addCardToZone(_game, card, zone); } - public void FreepsPlayCharFromHand(String cardName) throws DecisionResultInvalidException { - PhysicalCardImpl card = GetFreepsCard(cardName); - List availableIds = FreepsGetADParamAsList("cardId"); - - Integer index = availableIds.indexOf(String.valueOf(card.getCardId())); - playerDecided(P1, index.toString()); - } - public void FreepsAddWoundsToChar(String cardName, int count) { AddWoundsToChar(GetFreepsCard(cardName), count); } public void ShadowAddWoundsToChar(String cardName, int count) { AddWoundsToChar(GetShadowCard(cardName), count); } public void AddWoundsToChar(PhysicalCardImpl card, int count) { for(int i = 0; i < count; i++) { - AddWoundToChar(card); + _game.getGameState().addWound(card); } } - public void AddWoundToChar(PhysicalCardImpl card) { _game.getGameState().addWound(card); } public int GetTwilight() { return _game.getGameState().getTwilightPool(); } public void SetTwilight(int amount) { _game.getGameState().setTwilight(amount); } @@ -334,8 +330,11 @@ public class GenericCardTest extends AbstractAtTest { public void ShadowChooseCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, String.valueOf(card.getCardId())); } - public boolean FreepsCanChooseCharacter(PhysicalCardImpl card) { return FreepsGetADParamAsList("cardId").contains(String.valueOf(card.getCardId())); } - public boolean ShadowCanChooseCharacter(PhysicalCardImpl card) { return ShadowGetADParamAsList("cardId").contains(String.valueOf(card.getCardId())); } + public boolean FreepsCanChooseCharacter(PhysicalCardImpl card) { return FreepsGetCardChoices().contains(String.valueOf(card.getCardId())); } + public boolean ShadowCanChooseCharacter(PhysicalCardImpl card) { return ShadowGetCardChoices().contains(String.valueOf(card.getCardId())); } + + public int FreepsCardChoiceCount() { return FreepsGetCardChoices().size(); } + public int ShadowCardChoiceCount() { return ShadowGetCardChoices().size(); } public boolean IsCharAssigned(PhysicalCardImpl card) { List assigns = _game.getGameState().getAssignments(); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java index 2744dd620..82edd4cf9 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java @@ -77,32 +77,38 @@ public class Elrond_LoRErrataTest public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTest scn = GetSimpleSpotScenario(); - scn.FreepsMoveCardToHand("elrond"); - scn.FreepsMoveCardToHand("gandalf"); + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); + PhysicalCardImpl gandalf = scn.GetFreepsCard("gandalf"); + + scn.FreepsMoveCardToHand(elrond); + scn.FreepsMoveCardToHand(gandalf); scn.StartGame(); assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); - assertFalse(scn.FreepsActionAvailable("Play Elrond")); + assertFalse(scn.FreepsCardPlayAvailable(elrond)); - scn.FreepsPlayCharFromHand("gandalf"); - assertTrue(scn.FreepsActionAvailable("Play Elrond")); + scn.FreepsPlayCard(gandalf); + assertTrue(scn.FreepsCardPlayAvailable(elrond)); } @Test public void CardCanPlayIfElfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTest scn = GetSimpleSpotScenario(); - scn.FreepsMoveCardToHand("elrond"); - scn.FreepsMoveCardToHand("arwen"); + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); + PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); + + scn.FreepsMoveCardToHand(elrond); + scn.FreepsMoveCardToHand(arwen); scn.StartGame(); assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); - assertFalse(scn.FreepsActionAvailable("Play Elrond")); + assertFalse(scn.FreepsCardPlayAvailable(elrond)); - scn.FreepsPlayCharFromHand("arwen"); - assertTrue(scn.FreepsActionAvailable("Play Elrond")); + scn.FreepsPlayCard(arwen); + assertTrue(scn.FreepsCardPlayAvailable(elrond)); } @Test diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java index f353f5152..23e2fe8ff 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java @@ -11,7 +11,6 @@ import junit.framework.Assert; import org.junit.Test; import java.util.HashMap; -import java.util.List; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -114,7 +113,7 @@ public class StingErrataTest PhysicalCardImpl orc1 = scn.GetShadowCard("orc1"); - scn.FreepsMoveCharsToTable(sam, merry); + scn.FreepsMoveCharToTable(sam, merry); scn.AttachCard(sting, frodo); scn.ShadowMoveCardToHand(orc1); @@ -154,7 +153,7 @@ public class StingErrataTest PhysicalCardImpl orc1 = scn.GetShadowCard("orc1"); - scn.FreepsMoveCharsToTable(sam); + scn.FreepsMoveCharToTable(sam); scn.AttachCard(sting, frodo); scn.ShadowMoveCardToHand(orc1); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/TalentForNBSErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/TalentForNBSErrataTest.java new file mode 100644 index 000000000..9c492a5cc --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/TalentForNBSErrataTest.java @@ -0,0 +1,131 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TalentForNBSErrataTest +{ + protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("talent", "21_10316"); + put("sam", "1_311"); + put("gaffer", "1_291"); + put("boromir", "1_97"); + }} + ); + } + + @Test + public void TalentHasStealth() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl talent = scn.GetFreepsCard("talent"); + + assertTrue(scn.HasKeyword(talent, Keyword.STEALTH)); + } + + + @Test + public void TalentExertsAHobbitOnPlay() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + PhysicalCardImpl gaffer = scn.GetFreepsCard("gaffer"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl talent = scn.GetFreepsCard("talent"); + + scn.FreepsMoveCharToTable(sam, gaffer, boromir); + scn.FreepsMoveCardToHand(talent); + + scn.StartGame(); + + scn.FreepsPlayCard(talent); + //Frodo, Sam, Gaffer, but not Boromir + assertEquals(3, scn.FreepsCardChoiceCount()); + + scn.FreepsChooseCard(frodo); + assertEquals(1, scn.GetWoundsOn(frodo)); + } + + @Test + public void TalentAbilityTriggersConcealedOnMove() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + PhysicalCardImpl gaffer = scn.GetFreepsCard("gaffer"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl talent = scn.GetFreepsCard("talent"); + + scn.FreepsMoveCharToTable(sam, gaffer, boromir); + scn.FreepsMoveCardToHand(talent); + + scn.StartGame(); + + scn.FreepsPlayCard(talent); + scn.FreepsChooseCard(frodo); + scn.FreepsSkipCurrentPhaseAction(); + + //Sam and Frodo, but not Gaffer or Boromir + assertEquals(2, scn.FreepsCardChoiceCount()); + scn.FreepsChooseCard(frodo); + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + + scn.SkipToPhase(Phase.REGROUP); + scn.SkipCurrentPhaseActions(); + + scn.FreepsChooseToMove(); + //Sam and Frodo, but not Gaffer or Boromir + assertEquals(2, scn.FreepsCardChoiceCount()); + scn.FreepsChooseCard(sam); + assertEquals(Phase.SHADOW, scn.GetCurrentPhase()); + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + assertTrue(scn.HasKeyword(sam, Keyword.CONCEALED)); + + } + + @Test + public void TalentOnlyTriggersWithTwoHobbitCompanions() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + PhysicalCardImpl gaffer = scn.GetFreepsCard("gaffer"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl talent = scn.GetFreepsCard("talent"); + + scn.FreepsMoveCharToTable(gaffer, boromir); + scn.FreepsMoveCardToHand(talent); + + scn.StartGame(); + + scn.FreepsPlayCard(talent); + scn.FreepsChooseCard(frodo); + scn.FreepsSkipCurrentPhaseAction(); + + //neither gaffer nor boromir should permit the move trigger to choose a companion + assertEquals(Phase.SHADOW, scn.GetCurrentPhase()); + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + } + + +} From da93ab9bca44f8534d8ece10573a750d55e57012 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 3 Feb 2021 21:17:55 -0600 Subject: [PATCH 29/74] Checking in fix for PC formats that was floating on the server --- gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json index ce811b805..1c105ba23 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json @@ -83,7 +83,7 @@ "code":"rev_tow_sta", "sites": "SPECIAL", "cancelRingBearerSkirmish":true, - "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21] }, { "name":"Towers standard - Sets 1-4", From fa39f015645beafc4b44dda634b928b060fcae87 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 3 Feb 2021 21:19:09 -0600 Subject: [PATCH 30/74] Backup of the current server set 21 json --- .../src/main/web/cards/set21/set21.json | 320 ++++++++++++++++-- 1 file changed, 294 insertions(+), 26 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json index b221e8741..83195d6c6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json @@ -10,20 +10,20 @@ "resistance": 6, "keyword": "damage+1", "effects": { - "type": "extraCost", - "cost":{ - "type": "addBurdens", - "amount": { - "type": "condition", - "condition": { - "type": "canSpot", - "filter": "name(Bilbo)" - }, - "true": 0, - "false": 1 - } + "type": "extraCost", + "cost":{ + "type": "addBurdens", + "amount": { + "type": "condition", + "condition": { + "type": "canSpot", + "filter": "name(Bilbo)" + }, + "true": 0, + "false": 1 } - } + } + } }, "21_2": { "title": "Stand Together", @@ -134,11 +134,11 @@ "type" : "event", "cost": { "type": "discard", - "filter": "choose(weapon,attachedTo(character,culture(gondor),man))" + "filter": "choose(hand weapon,attachedTo(character,culture(gondor),man))" }, "effect": { "type": "wound", - "filter": "choose(or(orc,uruk-hai),inSkirmishAgainst(another,companion,not(ring bearer)))", + "filter": "choose(orc,uruk-hai,inSkirmishAgainst(another,companion,not(ring bearer)))", "times": 2 } } @@ -174,7 +174,18 @@ "culture": "isengard", "type": "event", "keyword": "response", - "cost": 1 + "cost": 1, + "effects": { + "type": "responseEvent", + "trigger": { + "type": "aboutToExert", + "filter": "your,uruk hai" + }, + "effect": { + "type": "placeNoWoundForExert", + "filter": "choose(uruk-hai)" + } + } }, "21_9": { "title": "Uruk Swarmer", @@ -184,7 +195,30 @@ "cost": 3, "strength": 6, "vitality": 2, - "site": 5 + "site": 5, + "keyword" : "damage+1", + "effects" : { + "type": "trigger", + "optional": true, + "trigger": { + "type": "assignedToSkirmish", + "filter": "self", + "against": "companion" + }, + "effect": [ + { + "type": "playCardFromDiscard", + "filter": "choose(uruk-hai)", + "memorize": "playedUrukhai" + }, + { + "type": "addKeyword", + "filter": "memory(playedUrukhai)", + "keyword": "fierce", + "until": "start(regroup)" + } + ] + } }, "21_10": { "title": "Goblin Bow", @@ -193,7 +227,38 @@ "possession": "ranged weapon", "cost": 1, "strength": 1, - "vitality": 1 + "vitality": 1, + "target": "culture(moria),orc", + "effects": [ + { + "type": "trigger", + "trigger": { + "type": "played", + "filter": "self" + }, + "effect": { + "type": "discard", + "filter": "all(possession,not(self),attachedTo(bearer))" + } + }, + { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "bearer", + "keyword": "archer" + } + }, + { + "type": "modifier", + "modifier": + { + "type": "cantBear", + "filter": "bearer", + "cardFilter": "possession" + } + } + ] }, "21_11": { "title": "Goblin Warchief", @@ -204,21 +269,97 @@ "cost": 4, "strength": 9, "vitality": 2, - "site": 4 + "site": 4, + "keyword": "fierce", + "condition": { + "type": "canSpot", + "filter": "culture(moria),orc" + }, + "effects": { + "type": "trigger", + "optional": true, + "trigger": { + "type": "played", + "filter": "self" + }, + "cost": { + "type": "revealBottomCardsOfDrawDeck", + "count": 4, + "memorize": "revealedCards" + }, + "effect": [ + { + "type": "playCardFromDrawDeck", + "filter": "all(memory(revealedCards),culture(moria),orc)" + }, + { + "type": "discardCardsFromDrawDeck", + "filter": "all(memory(revealedCards),zone(deck))" + } + ] + } }, "21_12": { "title": "No Hope of Escape That Way", "culture": "moria", "type": "event", "keyword": "maneuver", - "cost": 1 + "cost": 1, + "condition": { + "type": "canSpot", + "filter": "culture(moria),orc" + }, + "effects": { + "type": "event", + "effect": { + "type": "returnToHand", + "filter": "choose(possession,attachedTo(companion,not(ring bearer)))" + } + } }, "21_13": { "title": "The Old Forest", "culture": "wraith", "type": "condition", "keyword": "support area", - "cost": 0 + "cost": 0, + "effects": [ + { + "type": "trigger", + "optional": true, + "trigger": { + "type": "played", + "filter": "self" + }, + "effect": { + "type": "playCardFromDrawDeck", + "filter": "choose(tree)" + } + }, + { + "type": "activated", + "phase": "shadow", + "condition": { + "type": "canSpot", + "filter": "side(free people),not(name(Frodo)),maxTwilight(0)", + "count": 3 + }, + "cost": { + "type": "play", + "filter": "choose(minion,culture(wraith),unique)" + }, + "effect": [ + { + "type": "addTwilight", + "amount": 3 + }, + { + "type": "discard", + "filter": "self" + } + ] + } + ] }, "21_14": { "title": "Old Man Willow", @@ -229,20 +370,132 @@ "cost": 3, "strength": 2, "vitality": 6, - "site": 2 + "site": 2, + "effects" : [ + { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "self", + "condition": { + "type": "location", + "filter": "not(forest)" + }, + "keyword": "roaming" + } + }, + { + "type": "activatedTrigger", + "trigger": { + "type": "startOfPhase", + "phase": "assignment" + }, + "cost": { + "type": "exert", + "filter": "self", + "times": 2 + }, + "effect": [ + { + "type": "spot", + "filter": "choose(companion,hobbit,strengthLessThan(7))", + "memorize": "chosenHobbit" + }, + { + "type": "addModifier", + "modifier": { + "type": "cantBeAssignedToSkirmishAgainst", + "side": "free people", + "fpCharacter": "memory(chosenHobbit)", + "minion": "any" + } + } + ] + } + ] }, "21_15": { "title": "And in the Darkness Bind Them", "culture": "sauron", "type": "condition", "keyword": "support area", - "cost": 0 + "cost": 0, + "effects": { + "type": "activated", + "phase": "skirmish", + "effect": { + "type": "choice", + "texts": [ + "Discard a WRAITH card to make a SAURON orc strength +1", + "Discard a SAURON card to make a Nazgūl strength +1" + ], + "effects": [ + { + "type": "costToEffect", + "cost": { + "type": "discardFromHand", + "forced": true, + "filter": "choose(culture(wraith))" + }, + "effect": { + "type": "conditional", + "condition": { + "type": "perPhaseLimit", + "limit": 2 + }, + "effect": [ + { + "type": "incrementPerPhaseLimit", + "limit": 2 + }, + { + "type": "modifyStrength", + "filter": "choose(culture(sauron),orc)", + "amount": 1 + } + ] + } + + }, + { + "type": "costToEffect", + "cost": { + "type": "discardFromHand", + "forced": true, + "filter": "choose(culture(sauron))" + }, + "effect": { + "type": "conditional", + "condition": { + "type": "perPhaseLimit", + "limit": 2 + }, + "effect": [ + { + "type": "incrementPerPhaseLimit", + "limit": 2 + }, + { + "type": "modifyStrength", + "filter": "choose(nazgul)", + "amount": 1 + } + ] + } + + } + ] + } + } }, "21_16": { "title": "Gladden Ambush", "culture": "sauron", "type": "event", - "keyword": "maneuver", + "keyword": [ + "search", + "maneuver" + ], "cost": 0 }, "21_17": { @@ -254,7 +507,22 @@ "cost": 2, "strength": 2, "vitality": 3, - "allyHome": "fellowship,1" + "allyHome": [ + "fellowship,1", + "fellowship,3" + ], + "effects": { + "type": "activated", + "phase": "or(maneuver,regroup)", + "cost": { + "type": "exert", + "filter": "self" + }, + "effect": { + "type": "returnToHand", + "filter": "choose(hobbit,not(ring bearer))" + } + } }, "21_18": { "title": "Hobbit Concealment", @@ -501,5 +769,5 @@ "possession": "hand weapon", "cost": 2, "strength": 2 - }, + } } \ No newline at end of file From 169aa49dd266713b60787bc6eb1426369c0bb8a5 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 3 Feb 2021 23:21:47 -0600 Subject: [PATCH 31/74] Adding Gimli, Dwarf of the Mountain-race errata / tests --- .../src/main/web/cards/set21/set1-errata.json | 70 ++++++++++++++ .../src/main/web/js/gemp-022/set21.js | 1 + .../gempukku/lotro/cards/GenericCardTest.java | 17 ++-- .../pc/errata/Gimli_DotMrErrataTest.java | 94 +++++++++++++++++++ 4 files changed, 172 insertions(+), 10 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Gimli_DotMrErrataTest.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index b25316080..5572c4fa1 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -536,4 +536,74 @@ ] }, + + "21_20121": + { + "title": "*Gimli", + "subtitle": "Dwarf of the Mountain-race", + "culture": "dwarven", + "cost": 2, + "type": "companion", + "race": "dwarf", + "strength": 6, + "vitality": 3, + "resistance": 6, + "signet": "frodo", + "keyword": "damage+1", + "effects": [ + { + "type": "modifier", + + "modifier": { + "type": "addKeyword", + "filter": "self", + "keyword": "concealed", + "condition": { + "type": "location", + "filter": "underground" + } + }, + }, + { + "type": "trigger", + "optional": true, + "trigger": { + "type": "movesTo", + "filter": "underground", + + }, + "cost": { + "type": "exert", + "filter": "self" + }, + "effect": { + "type": "addKeyword", + "filter": "choose(another,companion)", + "keyword": "concealed", + "until": "start(regroup)" + } + }, + { + "type": "trigger", + "optional": true, + "trigger": { + "type": "movesFrom", + "filter": "underground", + + }, + "cost": { + "type": "exert", + "filter": "self" + }, + "effect": { + "type": "addKeyword", + "filter": "choose(another,companion)", + "keyword": "concealed", + "until": "start(regroup)" + } + } + ] + }, + + } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index d97a5b151..38ca1db74 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -61,4 +61,5 @@ var set21 = { '21_2075': 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', + '21_20121': 'https://i.lotrtcgpc.net/errata/FOTR/22_121.jpg' } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java index 345ddd853..eadbce5d6 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java @@ -259,10 +259,9 @@ public class GenericCardTest extends AbstractAtTest { public int GetTwilight() { return _game.getGameState().getTwilightPool(); } public void SetTwilight(int amount) { _game.getGameState().setTwilight(amount); } - public PhysicalCardImpl GetRingBearer() - { - return (PhysicalCardImpl)_game.getGameState().getRingBearer(P1); - } + public PhysicalCardImpl GetRingBearer() { return (PhysicalCardImpl)_game.getGameState().getRingBearer(P1); } + + public PhysicalCardImpl GetCurrentSite() { return (PhysicalCardImpl)_game.getGameState().getCurrentSite(); } public void SkipToPhase(Phase target) throws DecisionResultInvalidException { for(int attempts = 1; attempts <= 20; attempts++) @@ -360,12 +359,10 @@ public class GenericCardTest extends AbstractAtTest { _game.getModifiersEnvironment().addUntilEndOfTurnModifier(mod); } - public void FreepsChooseToMove() throws DecisionResultInvalidException { - playerDecided(P1, "0"); - } + public void FreepsChooseToMove() throws DecisionResultInvalidException { playerDecided(P1, "0"); } + public void FreepsChooseToStay() throws DecisionResultInvalidException { playerDecided(P1, "1"); } - public void FreepsChooseToStay() throws DecisionResultInvalidException { - playerDecided(P1, "1"); - } + public void FreepsActivateOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "0"); } + public void ShadowActivateOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Gimli_DotMrErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Gimli_DotMrErrataTest.java new file mode 100644 index 000000000..dec6d8bbd --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Gimli_DotMrErrataTest.java @@ -0,0 +1,94 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata; + +import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.filters.Filters; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.KeywordModifier; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Gimli_DotMrErrataTest +{ + protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTest( + new HashMap() + {{ + put("gimli", "21_20121"); + }} + ); + } + + @Test + public void GimliHasDamage() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + + assertTrue(scn.HasKeyword(gimli, Keyword.DAMAGE)); + } + + + @Test + public void GimliHasConcealedOnlyWhileUnderground() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + scn.FreepsMoveCharToTable(gimli); + + scn.StartGame(); + + assertFalse(scn.HasKeyword(gimli, Keyword.CONCEALED)); + + scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND)); + + scn.FreepsSkipCurrentPhaseAction(); + + assertTrue(scn.HasKeyword(gimli, Keyword.CONCEALED)); + } + + @Test + public void GimliAbilityTriggersMovingFromAndTo() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTest scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + + scn.FreepsMoveCharToTable(gimli); + + scn.StartGame(); + + scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND)); + + scn.FreepsSkipCurrentPhaseAction(); + + assertTrue(scn.FreepsActionAvailable("Optional")); + scn.FreepsActivateOptionalTrigger(); + assertEquals(1, scn.GetWoundsOn(gimli)); + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + + scn.SkipToPhase(Phase.REGROUP); + scn.SkipCurrentPhaseActions(); + scn.ShadowSkipCurrentPhaseAction(); + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + scn.FreepsChooseToMove(); + + assertTrue(scn.FreepsActionAvailable("Optional")); + scn.FreepsActivateOptionalTrigger(); + assertEquals(2, scn.GetWoundsOn(gimli)); + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + } + +} From c2b855cf7b57b6af846d8f85514530450a263e04 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Thu, 4 Feb 2021 00:24:26 -0600 Subject: [PATCH 32/74] Fixing typo and what appears to be a copy-paste error with the remove keyword prompt having the same text as add keyword. --- .../lotro/cards/build/field/effect/appender/AddKeyword.java | 2 +- .../lotro/cards/build/field/effect/appender/RemoveKeyword.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddKeyword.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddKeyword.java index 872a02c99..e0b8a72fb 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddKeyword.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddKeyword.java @@ -56,7 +56,7 @@ public class AddKeyword implements EffectAppenderProducer { MultiEffectAppender result = new MultiEffectAppender(); result.addEffectAppender( - CardResolver.resolveCards(filter, valueSource, memory, "you", "Choose cards to add keywork to", environment)); + CardResolver.resolveCards(filter, valueSource, memory, "you", "Choose cards to add keyword to", environment)); result.addEffectAppender( new DelayedAppender() { @Override diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveKeyword.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveKeyword.java index f37615831..f1bb67440 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveKeyword.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveKeyword.java @@ -35,7 +35,7 @@ public class RemoveKeyword implements EffectAppenderProducer { MultiEffectAppender result = new MultiEffectAppender(); result.addEffectAppender( - CardResolver.resolveCards(filter, valueSource, memory, "you", "Choose cards to add keywork to", environment)); + CardResolver.resolveCards(filter, valueSource, memory, "you", "Choose cards to remove keyword from", environment)); result.addEffectAppender( new DelayedAppender() { @Override From 2ec67d6858fa0cc7682b9ff49036fde983bd5ddf Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 5 Feb 2021 08:31:32 -0600 Subject: [PATCH 33/74] Updated RevealCardsFromHand and typos Updated RevealCardsFromHand to be player agnostic. The "hand" option now specifies which player to use (instead of defaulting always to self). Fixed typo in Error message of MultipleChoiceAwaitingDecision. --- .../field/effect/appender/RevealCardsFromHand.java | 13 +++++++------ .../decisions/MultipleChoiceAwaitingDecision.java | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java index fead90e7a..31763f8c7 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java @@ -1,13 +1,11 @@ package com.gempukku.lotro.cards.build.field.effect.appender; -import com.gempukku.lotro.cards.build.ActionContext; -import com.gempukku.lotro.cards.build.CardGenerationEnvironment; -import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; -import com.gempukku.lotro.cards.build.ValueSource; +import com.gempukku.lotro.cards.build.*; import com.gempukku.lotro.cards.build.field.FieldUtils; import com.gempukku.lotro.cards.build.field.effect.EffectAppender; import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer; import com.gempukku.lotro.cards.build.field.effect.appender.resolver.CardResolver; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver; import com.gempukku.lotro.cards.build.field.effect.appender.resolver.ValueResolver; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.logic.actions.CostToEffectAction; @@ -20,17 +18,20 @@ import java.util.Collection; public class RevealCardsFromHand implements EffectAppenderProducer { @Override public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(effectObject, "count", "filter", "memorize"); + FieldUtils.validateAllowedFields(effectObject, "count", "filter", "memorize", "hand"); + final String hand = FieldUtils.getString(effectObject.get("hand"), "hand", "you"); final String filter = FieldUtils.getString(effectObject.get("filter"), "filter", "choose(any)"); final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize", "_temp"); final ValueSource countSource = ValueResolver.resolveEvaluator(effectObject.get("count"), 1, environment); + final PlayerSource handSource = PlayerResolver.resolvePlayer(hand, environment); + MultiEffectAppender result = new MultiEffectAppender(); result.addEffectAppender( - CardResolver.resolveCardsInHand(filter, countSource, memorize, "you", "you", "Choose cards to reveal", environment)); + CardResolver.resolveCardsInHand(filter, countSource, memorize, hand, hand, "Choose cards to reveal", environment)); result.addEffectAppender( new DelayedAppender() { @Override diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/decisions/MultipleChoiceAwaitingDecision.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/decisions/MultipleChoiceAwaitingDecision.java index 04e1fe11e..cde31ef92 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/decisions/MultipleChoiceAwaitingDecision.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/decisions/MultipleChoiceAwaitingDecision.java @@ -20,7 +20,7 @@ public abstract class MultipleChoiceAwaitingDecision extends AbstractAwaitingDec try { index = Integer.parseInt(result); } catch (NumberFormatException exp) { - throw new DecisionResultInvalidException("Unkown response number"); + throw new DecisionResultInvalidException("Unknown response number"); } validDecisionMade(index, _possibleResults[index]); } From 23e5e21fc7709eddcf93e9c80a1da9cc37fcf775 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 5 Feb 2021 08:32:34 -0600 Subject: [PATCH 34/74] Preliminary commit for HttWC, which appears to be inconsistent in unit tests but may work in a regular game --- .../src/main/web/cards/set21/set1-errata.json | 54 +++++++++++++++++++ .../src/main/web/js/gemp-022/set21.js | 3 +- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 5572c4fa1..686e47784 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -606,4 +606,58 @@ }, + "21_3038": { + "side": "free_people", + "title": "*Aragorn", + "subtitle": "Heir to the White City", + "culture": "Gondor", + "type": "companion", + "race": "Man", + "cost": 4, + "strength": 8, + "vitality": 4, + "resistance": 6, + "signet": "frodo", + "keyword": [ + "Ranger", + "concealed" + ], + "effects": { + "type": "trigger", + "optional": true, + "trigger": { + "type": "moves" + }, + "condition": { + "type": "phase", + "phase": "fellowship" + }, + "effect": { + "type": "preventable", + "effect": { + "type": "addKeyword", + "filter": "choose(another,companion)", + "keyword": "concealed", + "until": "start(regroup)" + }, + "text": "Would you like to discard a minion or reveal a tracker from hand to prevent a companion becoming concealed?", + "player": "shadowPlayer", + "cost": [ + { + "type": "revealCardsFromHand", + "filter": "choose(tracker)", + "hand": "shadowPlayer", + }, + { + "type": "discardFromHand", + "filter": "choose(minion)", + "forced": false, + "hand": "shadowPlayer", + } + ], + }, + } + + }, + } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index 38ca1db74..5cd3bff43 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -61,5 +61,6 @@ var set21 = { '21_2075': 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', - '21_20121': 'https://i.lotrtcgpc.net/errata/FOTR/22_121.jpg' + '21_20121': 'https://i.lotrtcgpc.net/errata/FOTR/22_121.jpg', + '21_3038': 'https://i.lotrtcgpc.net/errata/FOTR/23_38.jpg' } \ No newline at end of file From 24b373a3c150b1e96282c84f59141517f7738c41 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 6 Feb 2021 13:34:59 -0600 Subject: [PATCH 35/74] HttWC Errata and Test Overhaul Added Aragorn, Heir to the White City errata and associated tests. Rearranged all errata tests to be in folders corresponding to their set of origin. Added some unit tests for existing cards which were used while debugging multiple choice functionality. --- .../src/main/web/cards/set21/set1-errata.json | 39 ++-- .../effect/appender/RevealCardsFromHand.java | 1 - .../lotro/at/ConcealedExposedAtTest.java | 19 +- ...rdTest.java => GenericCardTestHelper.java} | 93 ++++++--- .../cards/official/set18/Card18_118Tests.java | 64 ++++++ .../cards/official/set2/Card2_013Tests.java | 65 +++++++ .../cards/official/set2/Card2_028Tests.java | 60 ++++++ .../Elrond_LoRErrataTests.java} | 26 +-- .../Galadriel_LoLErrataTests.java} | 18 +- .../NoStrangerErrataTests.java} | 21 +- .../Sam_SoHErrataTests.java} | 14 +- .../StingErrataTests.java} | 22 +-- .../TalentForNBSErrataTests.java} | 19 +- .../FlamingBrandErrataTests.java} | 16 +- .../Gimli_DotMrErrataTests.java} | 21 +- .../errata/set3/Aragorn_HttWCErrataTests.java | 184 ++++++++++++++++++ .../HornOfBoromirErrataTests.java} | 26 +-- .../Saruman_KoIErrataTests.java} | 12 +- 18 files changed, 568 insertions(+), 152 deletions(-) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/{GenericCardTest.java => GenericCardTestHelper.java} (78%) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set18/Card18_118Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_013Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_028Tests.java rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{Elrond_LoRErrataTest.java => set1/Elrond_LoRErrataTests.java} (81%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{Galadriel_LoLErrataTest.java => set1/Galadriel_LoLErrataTests.java} (81%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{NoStrangerErrataTest.java => set1/NoStrangerErrataTests.java} (84%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{Sam_SoHErrataTest.java => set1/Sam_SoHErrataTests.java} (80%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{StingErrataTest.java => set1/StingErrataTests.java} (89%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{TalentForNBSErrataTest.java => set1/TalentForNBSErrataTests.java} (88%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{FlamingBrandErrataTest.java => set2/FlamingBrandErrataTests.java} (89%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{Gimli_DotMrErrataTest.java => set2/Gimli_DotMrErrataTests.java} (82%) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{HornOfBoromirErrataTest.java => set3/HornOfBoromirErrataTests.java} (84%) rename gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/{Saruman_KoIErrataTest.java => set3/Saruman_KoIErrataTests.java} (90%) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 686e47784..bf87e7051 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -626,7 +626,7 @@ "type": "trigger", "optional": true, "trigger": { - "type": "moves" + "type": "movesfrom" }, "condition": { "type": "phase", @@ -640,21 +640,30 @@ "keyword": "concealed", "until": "start(regroup)" }, - "text": "Would you like to discard a minion or reveal a tracker from hand to prevent a companion becoming concealed?", + "text": "Would you like to discard a minion (or reveal a tracker) from hand to prevent a companion becoming concealed?", "player": "shadowPlayer", - "cost": [ - { - "type": "revealCardsFromHand", - "filter": "choose(tracker)", - "hand": "shadowPlayer", - }, - { - "type": "discardFromHand", - "filter": "choose(minion)", - "forced": false, - "hand": "shadowPlayer", - } - ], + "cost": { + "type": "choice", + "player": "shadowPlayer", + "texts": [ + "Discard a minion from hand", + "Reveal a tracker from hand" + ], + "effects": [ + { + "type": "revealCardsFromHand", + "filter": "choose(tracker)", + "hand": "shadowPlayer" + }, + { + "type": "discardFromHand", + "filter": "choose(minion)", + "forced": false, + "hand": "shadowPlayer", + } + ] + } + }, } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java index 31763f8c7..bec304a06 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RevealCardsFromHand.java @@ -25,7 +25,6 @@ public class RevealCardsFromHand implements EffectAppenderProducer { final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize", "_temp"); final ValueSource countSource = ValueResolver.resolveEvaluator(effectObject.get("count"), 1, environment); - final PlayerSource handSource = PlayerResolver.resolvePlayer(hand, environment); MultiEffectAppender result = new MultiEffectAppender(); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java index 931a0f37f..7efefcd71 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/ConcealedExposedAtTest.java @@ -1,27 +1,22 @@ package com.gempukku.lotro.at; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.common.Keyword; -import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; -import com.gempukku.lotro.logic.decisions.AwaitingDecision; -import com.gempukku.lotro.logic.decisions.AwaitingDecisionType; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import com.gempukku.lotro.logic.modifiers.KeywordModifier; import org.junit.Test; -import java.util.Collection; import java.util.HashMap; -import java.util.Map; import static junit.framework.Assert.*; import static org.junit.Assert.assertTrue; public class ConcealedExposedAtTest extends AbstractAtTest { - protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("aragorn", "1_89"); @@ -34,7 +29,7 @@ public class ConcealedExposedAtTest extends AbstractAtTest { @Test public void ConcealedDoesNothingIfNoTwilight() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); @@ -54,7 +49,7 @@ public class ConcealedExposedAtTest extends AbstractAtTest { @Test public void ConcealedRemovesOneIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); @@ -77,7 +72,7 @@ public class ConcealedExposedAtTest extends AbstractAtTest { @Test public void TwoConcealedRemovesTwoIfAvailable() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); @@ -102,7 +97,7 @@ public class ConcealedExposedAtTest extends AbstractAtTest { @Test public void ConcealedRemovesNothingIfExposed() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java similarity index 78% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index eadbce5d6..e114163aa 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -3,7 +3,6 @@ package com.gempukku.lotro.cards; import com.gempukku.lotro.at.AbstractAtTest; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; -import com.gempukku.lotro.common.Side; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCard; @@ -19,7 +18,7 @@ import java.util.*; import static org.junit.Assert.assertEquals; -public class GenericCardTest extends AbstractAtTest { +public class GenericCardTestHelper extends AbstractAtTest { private int LastCardID = 100; @@ -42,11 +41,11 @@ public class GenericCardTest extends AbstractAtTest { // Player key, then name/card public Map> Cards = new HashMap<>(); - public GenericCardTest(Map cardIDs) throws CardNotFoundException, DecisionResultInvalidException { + public GenericCardTestHelper(Map cardIDs) throws CardNotFoundException, DecisionResultInvalidException { this(cardIDs, null, null, null); } - public GenericCardTest(Map cardIDs, Map siteIDs, String ringBearerID, String ringID) throws CardNotFoundException, DecisionResultInvalidException { + public GenericCardTestHelper(Map cardIDs, Map siteIDs, String ringBearerID, String ringID) throws CardNotFoundException, DecisionResultInvalidException { super(); if(siteIDs == null || ringBearerID == null || ringID == null) { @@ -116,7 +115,10 @@ public class GenericCardTest extends AbstractAtTest { public List FreepsGetAvailableActions() { return GetAvailableActions(P1); } public List ShadowGetAvailableActions() { return GetAvailableActions(P2); } public List GetAvailableActions(String playerID) { - AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); + AwaitingDecision decision = GetAwaitingDecision(playerID); + if(decision == null) { + return new ArrayList(); + } return Arrays.asList((String[])decision.getDecisionParameters().get("actionText")); } @@ -124,6 +126,15 @@ public class GenericCardTest extends AbstractAtTest { public AwaitingDecision ShadowGetAwaitingDecision() { return GetAwaitingDecision(P2); } public AwaitingDecision GetAwaitingDecision(String playerID) { return _userFeedback.getAwaitingDecision(playerID); } + public Boolean FreepsDecisionAvailable(String text) { return DecisionAvailable(P1, text); } + public Boolean ShadowDecisionAvailable(String text) { return DecisionAvailable(P2, text); } + public Boolean DecisionAvailable(String playerID, String text) + { + AwaitingDecision ad = GetAwaitingDecision(playerID); + String lowerText = text.toLowerCase(); + return ad.getText().toLowerCase().contains(lowerText); + } + public Boolean FreepsActionAvailable(String action) { return ActionAvailable(P1, action); } public Boolean FreepsCardActionAvailable(PhysicalCardImpl card) { return ActionAvailable(P1, "Use " + GameUtils.getFullName(card)); } public Boolean FreepsCardPlayAvailable(PhysicalCardImpl card) { return ActionAvailable(P1, "Play " + GameUtils.getFullName(card)); } @@ -133,7 +144,7 @@ public class GenericCardTest extends AbstractAtTest { public Boolean ActionAvailable(String player, String action) { List actions = GetAvailableActions(player); String lowerAction = action.toLowerCase(); - return actions.stream().anyMatch(x -> x.toLowerCase().startsWith(lowerAction)); + return actions.stream().anyMatch(x -> x.toLowerCase().contains(lowerAction)); } public Boolean FreepsAnyActionsAvailable() { return AnyActionsAvailable(P1); } @@ -143,10 +154,20 @@ public class GenericCardTest extends AbstractAtTest { return actions.size() > 0; } - public List FreepsGetCardChoices() { return FreepsGetADParamAsList("cardId"); } - public List ShadowGetCardChoices() { return FreepsGetADParamAsList("cardId"); } - public List FreepsGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P1, paramName)); } - public List ShadowGetADParamAsList(String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(P2, paramName)); } + public Boolean FreepsAnyDecisionsAvailable() { return AnyDecisionsAvailable(P1); } + public Boolean ShadowAnyDecisionsAvailable() { return AnyDecisionsAvailable(P2); } + public Boolean AnyDecisionsAvailable(String player) { + AwaitingDecision ad = GetAwaitingDecision(player); + return ad != null; + } + + public List FreepsGetCardChoices() { return GetADParamAsList(P1, "cardId"); } + public List ShadowGetCardChoices() { return GetADParamAsList(P2, "cardId"); } + public List FreepsGetMultipleChoices() { return GetADParamAsList(P1, "results"); } + public List ShadowGetMultipleChoices() { return GetADParamAsList(P2, "results"); } + public List FreepsGetADParamAsList(String paramName) { return GetADParamAsList(P1, paramName); } + public List ShadowGetADParamAsList(String paramName) { return GetADParamAsList(P2, paramName); } + public List GetADParamAsList(String playerID, String paramName) { return Arrays.asList((String[])GetAwaitingDecisionParam(playerID, paramName)); } public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } public Object GetAwaitingDecisionParam(String playerID, String paramName) { @@ -164,9 +185,9 @@ public class GenericCardTest extends AbstractAtTest { public void ShadowUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } public void ShadowUseCardAction(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, "Use " + GameUtils.getFullName(card))); } - public void FreepsPlayCard(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); } + public void FreepsPlayCard(String name) throws DecisionResultInvalidException { FreepsPlayCard(GetFreepsCard(name)); } public void FreepsPlayCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Play " + GameUtils.getFullName(card))); } - public void ShadowPlayCard(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } + public void ShadowPlayCard(String name) throws DecisionResultInvalidException { ShadowPlayCard(GetShadowCard(name)); } public void ShadowPlayCard(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, "Play " + GameUtils.getFullName(card))); } public int FreepsGetWoundsOn(String cardName) { return GetWoundsOn(GetFreepsCard(cardName)); } @@ -189,34 +210,42 @@ public class GenericCardTest extends AbstractAtTest { return _game.getGameState().getDeck(player).size(); } + public int GetFreepsDiscardCount() { return GetPlayerDiscardCount(P1); } + public int GetShadowDiscardCount() { return GetPlayerDiscardCount(P2); } + public int GetPlayerDiscardCount(String player) + { + return _game.getGameState().getDiscard(player).size(); + } + public Phase GetCurrentPhase() { return _game.getGameState().getCurrentPhase(); } public void FreepsMoveCardToHand(String cardName) { MoveCardToZone(P1, GetFreepsCard(cardName), Zone.HAND); } - public void FreepsMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P1, card, Zone.HAND); } - public void FreepsMoveCardsToHand(PhysicalCardImpl...cards) { + public void FreepsMoveCardToHand(PhysicalCardImpl...cards) { for(PhysicalCardImpl card : cards) { - FreepsMoveCardToHand(card); + MoveCardToZone(P1, card, Zone.HAND); } } public void ShadowMoveCardToHand(String cardName) { MoveCardToZone(P2, GetShadowCard(cardName), Zone.HAND); } - public void ShadowMoveCardToHand(PhysicalCardImpl card) { MoveCardToZone(P2, card, Zone.HAND); } - - public void ShadowMoveCardsToHand(PhysicalCardImpl...cards) { + public void ShadowMoveCardToHand(PhysicalCardImpl...cards) { for(PhysicalCardImpl card : cards) { - ShadowMoveCardToHand(card); + MoveCardToZone(P2, card, Zone.HAND); } } public void AttachCard(PhysicalCardImpl card, PhysicalCardImpl bearer) { _game.getGameState().attachCard(_game, card, bearer); } - public void FreepsMoveCardToDeck(String cardName) { FreepsMoveCardToDeck(GetFreepsCard(cardName)); } + public void FreepsMoveCardToDeck(String...cardNames) { + Arrays.stream(cardNames).forEach(cardName -> FreepsMoveCardToDeck(GetFreepsCard(cardName))); + } public void FreepsMoveCardToDeck(PhysicalCardImpl...cards) { Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DECK)); } - public void ShadowMoveCardToDeck(String cardName) { ShadowMoveCardToDeck(GetShadowCard(cardName)); } + public void ShadowMoveCardToDeck(String...cardNames) { + Arrays.stream(cardNames).forEach(cardName -> ShadowMoveCardToDeck(GetShadowCard(cardName))); + } public void ShadowMoveCardToDeck(PhysicalCardImpl...cards) { Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DECK)); } @@ -227,7 +256,7 @@ public class GenericCardTest extends AbstractAtTest { } public void ShadowMoveCharToTable(String cardName) { FreepsMoveCharToTable(GetShadowCard(cardName)); } public void ShadowMoveCharToTable(PhysicalCardImpl...cards) { - Arrays.stream(cards).forEach(card -> MoveCardToZone(P2, card, Zone.FREE_CHARACTERS)); + Arrays.stream(cards).forEach(card -> MoveCardToZone(P2, card, Zone.SHADOW_CHARACTERS)); } public void FreepsMoveCardToSupportArea(String cardName) { FreepsMoveCardToSupportArea(GetFreepsCard(cardName)); } @@ -362,7 +391,23 @@ public class GenericCardTest extends AbstractAtTest { public void FreepsChooseToMove() throws DecisionResultInvalidException { playerDecided(P1, "0"); } public void FreepsChooseToStay() throws DecisionResultInvalidException { playerDecided(P1, "1"); } - public void FreepsActivateOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "0"); } - public void ShadowActivateOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); } + public void FreepsAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "0"); } + public void FreepsDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "1"); } + public void ShadowAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); } + public void ShadowDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "1"); } + + public void FreepsAcceptMultipleChoiceOption(String option) throws DecisionResultInvalidException { AcceptMultipleChoiceOption(P1, option); } + public void ShadowAcceptMultipleChoiceOption(String option) throws DecisionResultInvalidException { AcceptMultipleChoiceOption(P2, option); } + public void AcceptMultipleChoiceOption(String playerID, String option) throws DecisionResultInvalidException { + List choices = GetADParamAsList(playerID, "results"); + for(String choice : choices){ + if(choice.toLowerCase().contains(option.toLowerCase())) { + playerDecided(playerID, String.valueOf(choices.indexOf(choice))); + return; + } + } + //couldn't find an exact match, so maybe it's a direct index: + playerDecided(playerID, option); + } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set18/Card18_118Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set18/Card18_118Tests.java new file mode 100644 index 000000000..592704444 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set18/Card18_118Tests.java @@ -0,0 +1,64 @@ +package com.gempukku.lotro.cards.official.set18; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +// Wielder of the Flame +public class Card18_118Tests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("aragorn", "1_89"); + + put("lurtz", "18_118"); + + }} + ); + } + + @Test + public void LurtzAbilityOffersChoiceOfPrevention() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + scn.FreepsMoveCharToTable(aragorn); + + PhysicalCardImpl lurtz = scn.GetShadowCard("lurtz"); + scn.ShadowMoveCharToTable(lurtz); + + scn.StartGame(); + + scn.SkipToPhase(Phase.ARCHERY); + scn.SkipCurrentPhaseActions(); + scn.FreepsChooseCard(frodo); + + //assignment phase + scn.FreepsSkipCurrentPhaseAction(); + assertEquals(0, scn.GetWoundsOn(lurtz)); + + scn.ShadowUseCardAction(lurtz); + assertEquals(2, scn.GetWoundsOn(lurtz)); + assertTrue(scn.FreepsAnyDecisionsAvailable()); + scn.FreepsAcceptOptionalTrigger(); + assertTrue(scn.FreepsAnyDecisionsAvailable()); + assertEquals("Exert - Aragorn, Ranger of the North", scn.FreepsGetADParamAsList("results").toArray()[0]); + assertEquals("Add 1 burden", scn.FreepsGetADParamAsList("results").toArray()[1]); + } + + + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_013Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_013Tests.java new file mode 100644 index 000000000..ca136238d --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_013Tests.java @@ -0,0 +1,65 @@ +package com.gempukku.lotro.cards.official.set2; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +// Tidings of Erebor +public class Card2_013Tests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("tidings", "2_13"); + put("gimli", "1_13"); + + put("deckcard1", "1_13"); + put("deckcard2", "1_13"); + put("deckcard3", "1_13"); + + }} + ); + } + + @Test + public void TidingsAbilityCanBePrevented() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl tidings = scn.GetFreepsCard("tidings"); + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + scn.FreepsMoveCharToTable(gimli); + scn.FreepsMoveCardToHand(tidings); + scn.FreepsMoveCardToDeck("deckcard1", "deckcard2", "deckcard3"); + + scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); + + scn.SkipToPhase(Phase.REGROUP); + + + scn.FreepsPlayCard(tidings); + assertEquals(3, scn.GetTwilight()); + assertEquals(0, scn.GetFreepsHandCount()); + assertEquals(3, scn.GetFreepsDeckCount()); + scn.ShadowAcceptOptionalTrigger(); + assertEquals(0, scn.GetTwilight()); + assertEquals(0, scn.GetFreepsHandCount()); + assertEquals(3, scn.GetFreepsDeckCount()); + + } + + + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_028Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_028Tests.java new file mode 100644 index 000000000..d41fde517 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set2/Card2_028Tests.java @@ -0,0 +1,60 @@ +package com.gempukku.lotro.cards.official.set2; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; + +// Wielder of the Flame +public class Card2_028Tests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("wielder", "2_28"); + put("gandalf", "1_364"); + + put("runner", "1_178"); + + }} + ); + } + + @Test + public void WielderAbilityCanBePrevented() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl wielder = scn.GetFreepsCard("wielder"); + PhysicalCardImpl gandalf = scn.GetFreepsCard("gandalf"); + scn.FreepsMoveCharToTable(gandalf); + scn.FreepsMoveCardToHand(wielder); + + PhysicalCardImpl runner = scn.GetShadowCard("runner"); + scn.ShadowMoveCharToTable(runner); + + scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); + + scn.SkipToPhase(Phase.MANEUVER); + + + scn.FreepsPlayCard(wielder); + assertEquals(4, scn.GetTwilight()); + scn.ShadowAcceptOptionalTrigger(); + assertEquals(1, scn.GetTwilight()); + assertFalse(scn.FreepsAnyActionsAvailable()); + + } + + + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java similarity index 81% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java index 82edd4cf9..4f0fdfc80 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Elrond_LoRErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java @@ -1,6 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set1; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; @@ -12,11 +12,11 @@ import java.util.*; import static junit.framework.Assert.assertEquals; -public class Elrond_LoRErrataTest +public class Elrond_LoRErrataTests { - protected GenericCardTest GetSimpleDeckScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetSimpleDeckScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("elrond", "21_1040"); @@ -25,8 +25,8 @@ public class Elrond_LoRErrataTest ); } - protected GenericCardTest GetSimpleSpotScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetSimpleSpotScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("elrond", "21_1040"); @@ -36,8 +36,8 @@ public class Elrond_LoRErrataTest ); } - protected GenericCardTest GetHome3AllyScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetHome3AllyScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("elrond", "21_1040"); @@ -52,7 +52,7 @@ public class Elrond_LoRErrataTest @Test public void FellowshipActionExertsTwiceToDrawACard() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleDeckScenario(); + GenericCardTestHelper scn = GetSimpleDeckScenario(); PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); scn.FreepsMoveCharToTable(elrond); @@ -76,7 +76,7 @@ public class Elrond_LoRErrataTest @Test public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleSpotScenario(); + GenericCardTestHelper scn = GetSimpleSpotScenario(); PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); PhysicalCardImpl gandalf = scn.GetFreepsCard("gandalf"); @@ -95,7 +95,7 @@ public class Elrond_LoRErrataTest @Test public void CardCanPlayIfElfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleSpotScenario(); + GenericCardTestHelper scn = GetSimpleSpotScenario(); PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); @@ -114,7 +114,7 @@ public class Elrond_LoRErrataTest @Test public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetHome3AllyScenario(); + GenericCardTestHelper scn = GetHome3AllyScenario(); scn.FreepsMoveCharToTable("elrond"); scn.FreepsMoveCharToTable("allyHome3_1"); scn.FreepsMoveCharToTable("allyHome3_2"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java similarity index 81% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java index 4b19a50b6..e65500859 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Galadriel_LoLErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java @@ -1,6 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set1; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; @@ -10,10 +10,10 @@ import org.junit.Test; import java.util.HashMap; -public class Galadriel_LoLErrataTest +public class Galadriel_LoLErrataTests { - protected GenericCardTest GetSimplePlayScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetSimplePlayScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("galadriel", "21_1045"); @@ -22,8 +22,8 @@ public class Galadriel_LoLErrataTest ); } - protected GenericCardTest GetHome6AllyScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetHome6AllyScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("galadriel", "21_1045"); @@ -38,7 +38,7 @@ public class Galadriel_LoLErrataTest @Test public void FellowshipActionExertsTwiceToDiscountAnElf() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimplePlayScenario(); + GenericCardTestHelper scn = GetSimplePlayScenario(); PhysicalCardImpl galadriel = scn.GetFreepsCard("galadriel"); scn.FreepsMoveCharToTable(galadriel); @@ -64,7 +64,7 @@ public class Galadriel_LoLErrataTest @Test public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetHome6AllyScenario(); + GenericCardTestHelper scn = GetHome6AllyScenario(); scn.FreepsMoveCharToTable("galadriel"); scn.FreepsMoveCharToTable("allyHome3_1"); scn.FreepsMoveCharToTable("allyHome3_2"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java similarity index 84% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java index 09f6933ef..ddd6197f8 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/NoStrangerErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java @@ -1,13 +1,10 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set1; -import com.gempukku.lotro.cards.GenericCardTest; -import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; -import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; -import com.gempukku.lotro.logic.modifiers.KeywordModifier; import org.junit.Test; import java.util.HashMap; @@ -16,10 +13,10 @@ import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class NoStrangerErrataTest +public class NoStrangerErrataTests { - protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("aragorn", "1_89"); @@ -35,7 +32,7 @@ public class NoStrangerErrataTest @Test public void NoStrangerHasStealth() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); @@ -45,7 +42,7 @@ public class NoStrangerErrataTest @Test public void NoStrangerCanOnlyPlayOnRanger() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); @@ -70,7 +67,7 @@ public class NoStrangerErrataTest @Test public void NoStrangerLimitOnePerBearer() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); @@ -96,7 +93,7 @@ public class NoStrangerErrataTest @Test public void NoStrangerAddsConcealed() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java similarity index 80% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java index 51fc84626..2c84abd38 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Sam_SoHErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java @@ -1,6 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set1; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; @@ -10,10 +10,10 @@ import org.junit.Test; import java.util.HashMap; -public class Sam_SoHErrataTest +public class Sam_SoHErrataTests { - protected GenericCardTest GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("sam", "21_10311"); @@ -26,7 +26,7 @@ public class Sam_SoHErrataTest @Test public void FellowshipActionExertsTwiceToRemoveABurden() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetSimpleScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); @@ -50,7 +50,7 @@ public class Sam_SoHErrataTest @Test public void RBDeathMakesSamTheRB() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetSimpleScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java similarity index 89% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java index 23e2fe8ff..95ab5742f 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/StingErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java @@ -1,6 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set1; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.common.Zone; @@ -16,10 +16,10 @@ import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class StingErrataTest +public class StingErrataTests { - protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("sting", "21_10313"); @@ -40,7 +40,7 @@ public class StingErrataTest @Test public void StingCanOnlyBeBorneByFrodo() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); @@ -61,7 +61,7 @@ public class StingErrataTest @Test public void StingAbilityAvailableInBothFellowshipAndRegroup() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sting = scn.GetFreepsCard("sting"); @@ -79,7 +79,7 @@ public class StingErrataTest @Test public void StingAbilityExertsFrodoAndRevealsThreeCards() throws DecisionResultInvalidException, CardNotFoundException { - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sting = scn.GetFreepsCard("sting"); @@ -91,7 +91,7 @@ public class StingErrataTest scn.AttachCard(sting, frodo); - scn.ShadowMoveCardsToHand(orc1, orc2, orc3, scimitar1); + scn.ShadowMoveCardToHand(orc1, orc2, orc3, scimitar1); scn.StartGame(); @@ -104,7 +104,7 @@ public class StingErrataTest @Test public void StingAbilityMakesConcealedIfOrcRevealed() throws DecisionResultInvalidException, CardNotFoundException { - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sting = scn.GetFreepsCard("sting"); @@ -145,7 +145,7 @@ public class StingErrataTest @Test public void StingConcealedLastsUntilNextRegroup() throws DecisionResultInvalidException, CardNotFoundException { - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sting = scn.GetFreepsCard("sting"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/TalentForNBSErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java similarity index 88% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/TalentForNBSErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java index 9c492a5cc..f9873e6d7 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/TalentForNBSErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java @@ -1,12 +1,11 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set1; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; -import junit.framework.Assert; import org.junit.Test; import java.util.HashMap; @@ -15,10 +14,10 @@ import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class TalentForNBSErrataTest +public class TalentForNBSErrataTests { - protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("talent", "21_10316"); @@ -32,7 +31,7 @@ public class TalentForNBSErrataTest @Test public void TalentHasStealth() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl talent = scn.GetFreepsCard("talent"); @@ -43,7 +42,7 @@ public class TalentForNBSErrataTest @Test public void TalentExertsAHobbitOnPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); @@ -67,7 +66,7 @@ public class TalentForNBSErrataTest @Test public void TalentAbilityTriggersConcealedOnMove() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); @@ -105,7 +104,7 @@ public class TalentForNBSErrataTest @Test public void TalentOnlyTriggersWithTwoHobbitCompanions() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java similarity index 89% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index 57894af7a..bd82de3ce 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/FlamingBrandErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -1,6 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set2; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; @@ -13,10 +13,10 @@ import java.util.HashMap; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.*; -public class FlamingBrandErrataTest +public class FlamingBrandErrataTests { - protected GenericCardTest GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("brand", "21_2032"); @@ -34,7 +34,7 @@ public class FlamingBrandErrataTest @Test public void CanBeBorneByRangers() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetSimpleScenario(); PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); @@ -61,7 +61,7 @@ public class FlamingBrandErrataTest @Test public void CanBeBorneTwice() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetSimpleScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl brand = scn.GetFreepsCard("brand"); @@ -83,7 +83,7 @@ public class FlamingBrandErrataTest @Test public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetSimpleScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl brand = scn.GetFreepsCard("brand"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Gimli_DotMrErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java similarity index 82% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Gimli_DotMrErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java index dec6d8bbd..28194cc3c 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Gimli_DotMrErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java @@ -1,7 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set2; -import com.gempukku.lotro.cards.GenericCardTest; -import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.filters.Filters; @@ -17,10 +16,10 @@ import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class Gimli_DotMrErrataTest +public class Gimli_DotMrErrataTests { - protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("gimli", "21_20121"); @@ -31,7 +30,7 @@ public class Gimli_DotMrErrataTest @Test public void GimliHasDamage() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); @@ -42,7 +41,7 @@ public class Gimli_DotMrErrataTest @Test public void GimliHasConcealedOnlyWhileUnderground() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); scn.FreepsMoveCharToTable(gimli); @@ -61,7 +60,7 @@ public class Gimli_DotMrErrataTest @Test public void GimliAbilityTriggersMovingFromAndTo() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); @@ -75,7 +74,7 @@ public class Gimli_DotMrErrataTest scn.FreepsSkipCurrentPhaseAction(); assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsActivateOptionalTrigger(); + scn.FreepsAcceptOptionalTrigger(); assertEquals(1, scn.GetWoundsOn(gimli)); assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); @@ -86,7 +85,7 @@ public class Gimli_DotMrErrataTest scn.FreepsChooseToMove(); assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsActivateOptionalTrigger(); + scn.FreepsAcceptOptionalTrigger(); assertEquals(2, scn.GetWoundsOn(gimli)); assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java new file mode 100644 index 000000000..75ac86885 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -0,0 +1,184 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata.set3; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Aragorn_HttWCErrataTests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("aragorn", "21_3038"); + put("gimli", "1_13"); + + put("minion", "1_268"); + put("tracker", "1_270"); + }} + ); + } + + @Test + public void AragornHasRangerAndConcealed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + assertTrue(scn.HasKeyword(aragorn, Keyword.RANGER)); + assertTrue(scn.HasKeyword(aragorn, Keyword.CONCEALED)); + } + + + @Test + public void AragornAbilityOnlyWorksDuringFellowship() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + scn.FreepsMoveCharToTable(aragorn, gimli); + + scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); + + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + assertTrue(scn.FreepsActionAvailable("Optional")); + scn.FreepsAcceptOptionalTrigger(); + scn.FreepsChooseCard(frodo); + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + + scn.SkipToPhase(Phase.REGROUP); + + scn.SkipCurrentPhaseActions(); + scn.ShadowSkipCurrentPhaseAction(); + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + scn.FreepsChooseToMove(); + + assertFalse(scn.FreepsActionAvailable("Optional")); + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + } + + @Test + public void AragornAbilityTriggersBeforeConcealedTwilightIsRemoved() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + scn.FreepsMoveCardToHand(aragorn, gimli); + + scn.StartGame(); + scn.FreepsPlayCard(aragorn); + scn.FreepsPlayCard(gimli); + assertEquals(6, scn.GetTwilight()); + scn.FreepsSkipCurrentPhaseAction(); + + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + assertTrue(scn.FreepsActionAvailable("Optional")); + scn.FreepsAcceptOptionalTrigger(); + scn.FreepsChooseCard(frodo); + assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + //6 from playing aragorn/gimli, 1+1+1 for companions, 1 for the site (King's Tent), -2 for concealed + assertEquals(8, scn.GetTwilight()); + } + + @Test + public void AragornAbilityOffersChoiceOfPrevention() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + PhysicalCardImpl minion = scn.GetShadowCard("minion"); + PhysicalCardImpl tracker = scn.GetShadowCard("tracker"); + + scn.FreepsMoveCharToTable(aragorn); + scn.ShadowMoveCardToHand(minion, tracker); + + scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); + + assertTrue(scn.FreepsActionAvailable("Optional")); + scn.FreepsAcceptOptionalTrigger(); + assertTrue(scn.ShadowDecisionAvailable("discard a minion (or reveal a tracker")); + scn.ShadowAcceptOptionalTrigger(); + + assertTrue(scn.ShadowAnyDecisionsAvailable()); + assertEquals("Discard a minion from hand", scn.ShadowGetADParamAsList("results").toArray()[0]); + assertEquals("Reveal a tracker from hand", scn.ShadowGetADParamAsList("results").toArray()[1]); + } + + @Test + public void AragornAbilityCanBePreventedWithMinionDiscard() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + PhysicalCardImpl minion = scn.GetShadowCard("minion"); + + scn.FreepsMoveCharToTable(aragorn); + scn.ShadowMoveCardToHand(minion); + + scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); + + assertTrue(scn.FreepsActionAvailable("Optional")); + scn.FreepsAcceptOptionalTrigger(); + assertTrue(scn.ShadowDecisionAvailable("discard a minion")); + assertEquals(1, scn.GetShadowHandCount()); + assertEquals(0, scn.GetShadowDiscardCount()); + scn.ShadowAcceptOptionalTrigger(); + assertEquals(0, scn.GetShadowHandCount()); + assertEquals(1, scn.GetShadowDiscardCount()); + assertFalse(scn.FreepsAnyDecisionsAvailable()); + + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + } + + @Test + public void AragornAbilityCanBePreventedWithTrackerReveal() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + PhysicalCardImpl tracker = scn.GetShadowCard("tracker"); + + scn.FreepsMoveCharToTable(aragorn); + scn.ShadowMoveCardToHand(tracker); + + scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); + + assertTrue(scn.FreepsActionAvailable("Optional")); + scn.FreepsAcceptOptionalTrigger(); + assertTrue(scn.ShadowDecisionAvailable("reveal a tracker")); + assertEquals(1, scn.GetShadowHandCount()); + scn.ShadowAcceptOptionalTrigger(); + assertEquals(1, scn.GetShadowHandCount()); + assertTrue(scn.ShadowDecisionAvailable("Choose action to perform")); + scn.ShadowAcceptMultipleChoiceOption("Reveal a tracker"); + + assertFalse(scn.FreepsAnyDecisionsAvailable()); + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + + } + +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java similarity index 84% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index 693e46c15..8a2c0f633 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/HornOfBoromirErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -1,6 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set3; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; @@ -14,10 +14,10 @@ import java.util.HashMap; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.*; -public class HornOfBoromirErrataTest +public class HornOfBoromirErrataTests { - protected GenericCardTest GetFOTRScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetFOTRScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("horn", "21_3042"); @@ -28,14 +28,14 @@ public class HornOfBoromirErrataTest put("runner1", "1_178"); put("runner2", "1_178"); }}, - GenericCardTest.FellowshipSites, - GenericCardTest.FOTRFrodo, - GenericCardTest.FOTRRing + GenericCardTestHelper.FellowshipSites, + GenericCardTestHelper.FOTRFrodo, + GenericCardTestHelper.FOTRRing ); } - protected GenericCardTest GetMovieScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetMovieScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("horn", "21_3042"); @@ -52,7 +52,7 @@ public class HornOfBoromirErrataTest @Test public void CanBeBorneByBoromir() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetFOTRScenario(); + GenericCardTestHelper scn = GetFOTRScenario(); PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); @@ -79,7 +79,7 @@ public class HornOfBoromirErrataTest @Test public void AbilityExertsAndAssignsBoromir() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetFOTRScenario(); + GenericCardTestHelper scn = GetFOTRScenario(); PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); @@ -117,7 +117,7 @@ public class HornOfBoromirErrataTest @Test public void AbilityDoesNotPumpFarAwayAllies() throws DecisionResultInvalidException, CardNotFoundException { - GenericCardTest scn = GetMovieScenario(); + GenericCardTestHelper scn = GetMovieScenario(); PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Saruman_KoIErrataTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java similarity index 90% rename from gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Saruman_KoIErrataTest.java rename to gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java index ca53f1648..c0bd5f1b2 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/Saruman_KoIErrataTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java @@ -1,6 +1,6 @@ -package com.gempukku.lotro.cards.unofficial.pc.errata; +package com.gempukku.lotro.cards.unofficial.pc.errata.set3; -import com.gempukku.lotro.cards.GenericCardTest; +import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; @@ -14,10 +14,10 @@ import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class Saruman_KoIErrataTest +public class Saruman_KoIErrataTests { - protected GenericCardTest GetScenario() throws CardNotFoundException, DecisionResultInvalidException { - return new GenericCardTest( + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( new HashMap() {{ put("legolas", "1_50"); @@ -35,7 +35,7 @@ public class Saruman_KoIErrataTest @Test public void SarumanWorks() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTest scn = GetScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl legolas = scn.GetFreepsCard("legolas"); PhysicalCardImpl tale = scn.GetFreepsCard("tale"); From af642546e79c79166b7169086027a90fff940905 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 6 Feb 2021 15:19:09 -0600 Subject: [PATCH 36/74] Bill The Pony Errata Added Bill the Pony errata and unit tests. Added the Pony possession class. --- .../src/main/web/cards/set21/set1-errata.json | 52 +++++++ .../src/main/web/js/gemp-022/set21.js | 3 +- .../lotro/common/PossessionClass.java | 7 +- .../lotro/cards/GenericCardTestHelper.java | 35 +++-- .../errata/set2/FlamingBrandErrataTests.java | 2 + .../errata/set3/Aragorn_HttWCErrataTests.java | 2 +- .../errata/set3/BillThePonyErrataTests.java | 137 ++++++++++++++++++ .../errata/set3/HornOfBoromirErrataTests.java | 3 +- 8 files changed, 224 insertions(+), 17 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index bf87e7051..650dac80c 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -669,4 +669,56 @@ }, + + "21_30106": { + "title": "*Bill the Pony", + "culture": "Shire", + "side": "free_people", + "cost": 0, + "type": "possession", + "possession": "Pony", + "target": "name(Sam)", + "effects": [ + { + "type": "trigger", + "trigger": { + "type": "played", + "filter": "self" + }, + "effect": { + "type": "heal", + "filter": "bearer" + } + }, + { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "bearer", + "keyword": "concealed" + } + }, + { + "type": "trigger", + "trigger": { + "type": "condition", + "condition": [ + { + "type": "location", + "filter": "underground" + }, + { + "type": "canSpot", + "filter": "self,attachedTo(companion)" + } + ] + }, + "effect": { + "type": "discard", + "filter": "self" + } + } + ] + }, + } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js index 5cd3bff43..c25353bdf 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js @@ -62,5 +62,6 @@ var set21 = { '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', '21_20121': 'https://i.lotrtcgpc.net/errata/FOTR/22_121.jpg', - '21_3038': 'https://i.lotrtcgpc.net/errata/FOTR/23_38.jpg' + '21_3038': 'https://i.lotrtcgpc.net/errata/FOTR/23_38.jpg', + '21_30106': 'https://i.lotrtcgpc.net/errata/FOTR/23_106.jpg' } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java index 39c2da085..265b5bf97 100644 --- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java +++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/PossessionClass.java @@ -4,7 +4,12 @@ public enum PossessionClass implements Filterable { HAND_WEAPON("Hand Weapon"), ARMOR("Armor"), HELM("Helm"), MOUNT("Mount"), RANGED_WEAPON("Ranged Weapon"), CLOAK("Cloak"), PIPE("Pipe"), SHIELD("Shield"), BRACERS("Bracers"), STAFF("Staff"), RING("Ring"), BROOCH("Brooch"), GAUNTLETS("Gauntlets"), BOX("Box"), PALANTIR("Palantir"), PHIAL("Phial"), HORN("Horn"), - CLASSLESS("Classless"); + CLASSLESS("Classless"), + + //PC Classes + PONY("Pony") + + ; private String _humanReadable; diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index e114163aa..2cef73d10 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -369,6 +369,14 @@ public class GenericCardTestHelper extends AbstractAtTest { return assigns.stream().anyMatch(x -> x.getFellowshipCharacter() == card || x.getShadowCharacters().contains(card)); } + public boolean IsAttachedTo(PhysicalCardImpl card, PhysicalCardImpl bearer) { + if(card.getZone() != Zone.ATTACHED) { + return false; + } + + return bearer == card.getAttachedTo(); + } + public int FreepsGetStrength(String name) { return GetStrength(GetFreepsCard(name)); } public int ShadowGetStrength(String name) { return GetStrength(GetShadowCard(name)); } @@ -396,18 +404,21 @@ public class GenericCardTestHelper extends AbstractAtTest { public void ShadowAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); } public void ShadowDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "1"); } - public void FreepsAcceptMultipleChoiceOption(String option) throws DecisionResultInvalidException { AcceptMultipleChoiceOption(P1, option); } - public void ShadowAcceptMultipleChoiceOption(String option) throws DecisionResultInvalidException { AcceptMultipleChoiceOption(P2, option); } - public void AcceptMultipleChoiceOption(String playerID, String option) throws DecisionResultInvalidException { - List choices = GetADParamAsList(playerID, "results"); - for(String choice : choices){ - if(choice.toLowerCase().contains(option.toLowerCase())) { - playerDecided(playerID, String.valueOf(choices.indexOf(choice))); - return; - } - } - //couldn't find an exact match, so maybe it's a direct index: - playerDecided(playerID, option); + public void FreepsChooseMultipleChoiceOption(String option) throws DecisionResultInvalidException { ChooseMultipleChoiceOption(P1, option); } + public void ShadowChooseMultipleChoiceOption(String option) throws DecisionResultInvalidException { ChooseMultipleChoiceOption(P2, option); } + public void ChooseMultipleChoiceOption(String playerID, String option) throws DecisionResultInvalidException { ChooseAction(playerID, "results", option); } + public void ChooseAction(String playerID, String paramName, String option) throws DecisionResultInvalidException { + List choices = GetADParamAsList(playerID, paramName); + for(String choice : choices){ + if(choice.toLowerCase().contains(option.toLowerCase())) { + playerDecided(playerID, String.valueOf(choices.indexOf(choice))); + return; + } + } + //couldn't find an exact match, so maybe it's a direct index: + playerDecided(playerID, option); } + public void FreepsResolveActionOrder(String option) throws DecisionResultInvalidException { ChooseAction(P1, "actionText", option); } + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index bd82de3ce..094deca74 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -55,6 +55,8 @@ public class FlamingBrandErrataTests //There are 3 companions in play, but only 2 rangers, so we should only see 2 options assertEquals(2, scn.FreepsGetADParamAsList("cardId").size()); + scn.FreepsChooseCard(aragorn); + assertTrue(scn.IsAttachedTo(brand, aragorn)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java index 75ac86885..4333401af 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -174,7 +174,7 @@ public class Aragorn_HttWCErrataTests scn.ShadowAcceptOptionalTrigger(); assertEquals(1, scn.GetShadowHandCount()); assertTrue(scn.ShadowDecisionAvailable("Choose action to perform")); - scn.ShadowAcceptMultipleChoiceOption("Reveal a tracker"); + scn.ShadowChooseMultipleChoiceOption("Reveal a tracker"); assertFalse(scn.FreepsAnyDecisionsAvailable()); assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java new file mode 100644 index 000000000..4ee3f1c17 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java @@ -0,0 +1,137 @@ +package com.gempukku.lotro.cards.unofficial.pc.errata.set3; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.CardType; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.filters.Filters; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import com.gempukku.lotro.logic.modifiers.KeywordModifier; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class BillThePonyErrataTests +{ + protected GenericCardTestHelper GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("bill", "21_30106"); + put("sam", "1_311"); + }} + ); + } + + @Test + public void BillCanBeBorneBySam() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.StartGame(); + + + assertFalse(scn.FreepsCardPlayAvailable(bill)); + scn.FreepsPlayCard(sam); + assertTrue(scn.FreepsCardPlayAvailable(bill)); + scn.FreepsPlayCard(bill); + + Assert.assertTrue(scn.IsAttachedTo(bill, sam)); + } + + @Test + public void BillHealsWhenPlayed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsUseCardAction(sam); + assertEquals(1, scn.GetWoundsOn(sam)); + scn.FreepsPlayCard(bill); + assertEquals(0, scn.GetWoundsOn(sam)); + } + + @Test + public void BillGrantsConcealed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsPlayCard(bill); + assertTrue(scn.HasKeyword(sam, Keyword.CONCEALED)); + } + + @Test + public void BillDiscardedWhenMovingToUnderground() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND)); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsPlayCard(bill); + + scn.FreepsSkipCurrentPhaseAction(); + //Get a timing choice between resolving concealed or discarding bill + scn.FreepsResolveActionOrder("Concealed"); + assertFalse(scn.IsAttachedTo(bill, sam)); + assertEquals(Zone.DISCARD, bill.getZone()); + } + + @Test + public void BillHealsWhenPlayedAtUnderground() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetSimpleScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + scn.FreepsMoveCardToHand(bill, sam); + + scn.InsertAdHocModifier(new KeywordModifier(null, CardType.SITE, Keyword.UNDERGROUND)); + + scn.StartGame(); + + scn.FreepsPlayCard(sam); + scn.FreepsUseCardAction(sam); + assertEquals(1, scn.GetWoundsOn(sam)); + scn.FreepsPlayCard(bill); + assertEquals(0, scn.GetWoundsOn(sam)); + assertFalse(scn.IsAttachedTo(bill, sam)); + assertEquals(Zone.DISCARD, bill.getZone()); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index 8a2c0f633..95ad88ffa 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -72,8 +72,7 @@ public class HornOfBoromirErrataTests assertTrue(scn.FreepsCardPlayAvailable(horn)); scn.FreepsPlayCard(horn); - Assert.assertEquals(Zone.ATTACHED, horn.getZone()); - Assert.assertEquals(boromir, horn.getAttachedTo()); + Assert.assertTrue(scn.IsAttachedTo(horn, boromir)); } @Test From c29c28814c622e9ba17975f96ad9403c1bfa3ad7 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 6 Feb 2021 15:49:56 -0600 Subject: [PATCH 37/74] Updates to Gimli and Aragorn errata --- .../src/main/web/cards/set21/set1-errata.json | 34 ++++++------------- .../errata/set2/Gimli_DotMrErrataTests.java | 6 ++-- .../errata/set3/Aragorn_HttWCErrataTests.java | 6 ++-- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index 650dac80c..b9b9ca654 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -571,25 +571,6 @@ "type": "movesTo", "filter": "underground", - }, - "cost": { - "type": "exert", - "filter": "self" - }, - "effect": { - "type": "addKeyword", - "filter": "choose(another,companion)", - "keyword": "concealed", - "until": "start(regroup)" - } - }, - { - "type": "trigger", - "optional": true, - "trigger": { - "type": "movesFrom", - "filter": "underground", - }, "cost": { "type": "exert", @@ -614,13 +595,12 @@ "type": "companion", "race": "Man", "cost": 4, - "strength": 8, + "strength": 7, "vitality": 4, "resistance": 6, "signet": "frodo", "keyword": [ "Ranger", - "concealed" ], "effects": { "type": "trigger", @@ -634,12 +614,20 @@ }, "effect": { "type": "preventable", - "effect": { + "effect": [ + { "type": "addKeyword", "filter": "choose(another,companion)", "keyword": "concealed", "until": "start(regroup)" - }, + }, + { + "type": "addKeyword", + "filter": "self", + "keyword": "concealed", + "until": "start(regroup)" + }, + ], "text": "Would you like to discard a minion (or reveal a tracker) from hand to prevent a companion becoming concealed?", "player": "shadowPlayer", "cost": { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java index 28194cc3c..50fa69cf2 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java @@ -58,7 +58,7 @@ public class Gimli_DotMrErrataTests } @Test - public void GimliAbilityTriggersMovingFromAndTo() throws DecisionResultInvalidException, CardNotFoundException { + public void GimliAbilityTriggersMovingToUnderground() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); @@ -84,8 +84,8 @@ public class Gimli_DotMrErrataTests assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); scn.FreepsChooseToMove(); - assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsAcceptOptionalTrigger(); + assertFalse(scn.FreepsActionAvailable("Optional")); + //scn.FreepsAcceptOptionalTrigger(); assertEquals(2, scn.GetWoundsOn(gimli)); assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java index 4333401af..da444111a 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -30,14 +30,14 @@ public class Aragorn_HttWCErrataTests } @Test - public void AragornHasRangerAndConcealed() throws DecisionResultInvalidException, CardNotFoundException { + public void AragornHasRanger() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); assertTrue(scn.HasKeyword(aragorn, Keyword.RANGER)); - assertTrue(scn.HasKeyword(aragorn, Keyword.CONCEALED)); + assertFalse(scn.HasKeyword(aragorn, Keyword.CONCEALED)); } @@ -88,10 +88,12 @@ public class Aragorn_HttWCErrataTests scn.FreepsSkipCurrentPhaseAction(); assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + assertFalse(scn.HasKeyword(aragorn, Keyword.CONCEALED)); assertTrue(scn.FreepsActionAvailable("Optional")); scn.FreepsAcceptOptionalTrigger(); scn.FreepsChooseCard(frodo); assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + assertTrue(scn.HasKeyword(aragorn, Keyword.CONCEALED)); //6 from playing aragorn/gimli, 1+1+1 for companions, 1 for the site (King's Tent), -2 for concealed assertEquals(8, scn.GetTwilight()); } From a2906e69569965f9c71626855e57d2fb08ebe857 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 7 Feb 2021 11:11:07 -0600 Subject: [PATCH 38/74] Fixing HttWC strength 7 -> 8 --- .../gemp-lotr-async/src/main/web/cards/set21/set1-errata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json index b9b9ca654..9d6d8e2b6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json @@ -595,7 +595,7 @@ "type": "companion", "race": "Man", "cost": 4, - "strength": 7, + "strength": 8, "vitality": 4, "resistance": 6, "signet": "frodo", From b6a15e14fb131f83d788454d5299a777bdad337c Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 15 Feb 2021 11:17:16 -0600 Subject: [PATCH 39/74] Importing format changes from playtest branch --- .../src/main/resources/lotrFormats.json | 78 +++++++++++++------ 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json index 1c105ba23..6649d091f 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json @@ -1,4 +1,11 @@ [ + { + "name": "Debug", + "code":"debug_hall", + "sites": "SPECIAL", + "maximumSameName":100, + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21] + }, { "name":"Fellowship block", "code":"fotr_block", @@ -6,6 +13,14 @@ "cancelRingBearerSkirmish":true, "set":[1, 2, 3] }, + { + "name":"PC-Fellowship Block", + "code":"pc_fotr_block", + "sites":"FELLOWSHIP", + "cancelRingBearerSkirmish":true, + "set":[1, 2, 3, 21], + "banned":["1_40","1_311","2_32","3_42","3_68",] + }, { "name":"Fellowship block - Set 1", "code":"fotr1_block", @@ -52,7 +67,8 @@ "code":"ttt_block", "sites":"TWO_TOWERS", "cancelRingBearerSkirmish":true, - "set":[4, 5, 6] + "set":[4, 5, 6], + "hall":false }, { "name":"Towers block - Set 4", @@ -76,14 +92,16 @@ "sites":"TWO_TOWERS", "cancelRingBearerSkirmish":true, "banned":["1_40", "1_45", "1_80", "1_108", "1_139", "1_234", "1_248", "1_313", "2_32", "2_101", "2_108", "3_38", "3_42", "3_68", "4_192"], - "set":[1, 2, 3, 4, 5, 6] + "set":[1, 2, 3, 4, 5, 6], + "hall":false }, { "name": "Anything goes", "code":"rev_tow_sta", "sites": "SPECIAL", "cancelRingBearerSkirmish":true, - "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21] + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21], + "hall":false }, { "name":"Towers standard - Sets 1-4", @@ -127,7 +145,8 @@ "sites":"KING", "cancelRingBearerSkirmish":true, "banned":["1_40", "1_45","1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "2_32", "2_101", "2_108", "3_38", "3_42", "3_67", "3_68", "3_106", "3_108"], - "set":[1, 2, 3, 4, 5, 6, 7] + "set":[1, 2, 3, 4, 5, 6, 7], + "hall":false }, { "name":"King block", @@ -135,7 +154,8 @@ "sites":"KING", "cancelRingBearerSkirmish":true, "restricted":["7_49"], - "set":[7, 8, 10] + "set":[7, 8, 10], + "hall":false }, { "name":"King block - Set 7", @@ -159,9 +179,16 @@ "name":"Movie block", "code":"movie", "sites":"KING", - "banned":["8_1", "3_38", "3_106", "1_40", "2_32", "1_248", "3_108", "1_45", "7_96", "3_42", "10_2", "10_91", "1_108", "1_80", "3_67", "1_195", "3_68", "1_139", "7_49", "1_313", "1_234"], + "banned":["1_40", "1_45", "1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "2_32", "3_106", "3_108", "3_38", "3_42", "3_67", "3_68", "7_49", "7_96", "8_1", "10_2", "10_91"], "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, + { + "name":"PC-Movie", + "code":"pc_movie", + "sites":"KING", + "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21], + "banned":["1_40","1_311","2_32","3_42","3_68", "1_45", "1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "3_106", "3_108", "3_38", "3_67", "7_49", "7_96", "8_1", "10_2", "10_91"], + }, { "name":"Movie block - Sets 1-7", "code":"movie7", @@ -199,34 +226,39 @@ "code":"war_block", "sites":"SHADOWS", "restricted":["11_132", "11_100"], - "set":[11, 12, 13] + "set":[11, 12, 13], + "hall":false }, { "name":"Hunter block", "code":"hunter_block", "sites":"SHADOWS", - "set":[15, 17, 18] + "set":[15, 17, 18], + "hall":false }, { "name":"War of the Ring standard", "code":"war_standard", "sites":"SHADOWS", "banned":["4_73", "4_276", "4_304", "7_49", "8_1", "10_2", "10_11", "10_91", "11_31", "11_100", "11_132"], - "set":[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] + "set":[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], + "hall":false }, { "name":"Standard", "code":"standard", "sites":"SHADOWS", "banned":["0_1-19", "0_21", "0_22", "0_30-47", "0_62-67", "8_1", "13_188", "11_114", "11_31", "10_11", "15_64", "10_2", "10_91", "11_132", "7_49", "11_100"], - "set":[0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] + "set":[0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], + "hall":false }, { "name":"Open", "code":"open", "sites":"SHADOWS", "restricted":["1_248", "7_49", "10_2", "10_91", "11_100", "11_132"], - "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], + "hall":false }, { "name":"Expanded", @@ -236,6 +268,14 @@ "restricted":["1_40", "1_80", "1_108", "1_139", "1_195", "1_248", "2_32", "2_75", "3_106", "4_276", "4_304"], "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] }, + { + "name":"PC-Expanded", + "code":"pc_expanded", + "sites":"SHADOWS", + "banned":["1_40","1_311","2_32","3_42","3_68","1_45", "1_138", "1_234", "1_313", "1_316", "2_121", "3_17", "3_38", "3_67", "3_108", "3_113", "4_73", "7_49", "8_1", "10_2", "10_11", "10_91", "11_31", "11_100", "11_132"], + "restricted":["1_80", "1_108", "1_139", "1_195", "1_248", "2_75", "3_106", "4_276", "4_304"], + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,21] + }, { "name":"War of the Ring block - Set 11", "code":"war_block11", @@ -267,7 +307,8 @@ "banned":["1_138", "1_311", "1_316", "1_331", "1_338", "1_354", "1_355", "1_360", "2_14", "2_75", "3_1", "3_113", "4_73", "4_338", "4_355", "4_357", "7_190", "8_20", "10_11", "8_1", "8_3", "3_38", "3_106", "1_40", "2_32", "1_248", "3_108", "1_45", "7_96", "3_42", "10_2", "10_91", "1_108", "1_80", "3_67", "1_195", "3_68", "1_139", "7_49", "1_313", "1_234", "7_156"], "valid":["0_56-60"], - "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + "hall":false }, { "name":"Movie block, no GLR (10R11)", @@ -301,7 +342,7 @@ "limit3":[], "set":[30, 31], "restrictedName":["Gandalf", "Bilbo"], - "hall":true + "hall":false }, { "name": "Hobbit: The Clouds Burst", @@ -313,7 +354,7 @@ "limit3": [], "set": [30, 32], "restrictedName": ["Gandalf", "Bilbo"], - "hall": true + "hall":false }, { "name": "Hobbit: Fire and Water", @@ -399,12 +440,5 @@ "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "hall":false }, - { - "name":"PC-Fellowship Block", - "code":"pc_fotr_block", - "sites":"FELLOWSHIP", - "cancelRingBearerSkirmish":true, - "set":[1, 2, 3, 21], - "banned":["1_1"] - } + ] From 7823c36fcfe54119f753c0a600ed74f976d79806 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 15 Feb 2021 11:21:13 -0600 Subject: [PATCH 40/74] Rearranged PC set numbering Moved all errata cards to set 51 (with the intent being to use sets 50-69 as errata proxies for sets 0-19). Moved original PC cards to set 101, with the intent being for sets 101-119 to reflect supplements for sets 1-19, and sets 120+ to be original PC sets. --- .../gemp-lotr-async/src/main/web/ban.html | 2 +- .../fotr-starter-supplement.json} | 0 .../set01-errata.json} | 316 +----------------- .../main/web/cards/set51/set02-errata.json | 98 ++++++ .../main/web/cards/set51/set03-errata.json | 222 ++++++++++++ .../src/main/web/deckBuild.html | 2 +- .../gemp-lotr-async/src/main/web/game.html | 2 +- .../gemp-lotr-async/src/main/web/hall.html | 2 +- .../gemp-lotr-async/src/main/web/index.html | 2 +- .../src/main/web/js/gemp-022/PC_Cards.js | 67 ++++ .../src/main/web/js/gemp-022/jCards.js | 2 +- .../src/main/web/js/gemp-022/set21.js | 67 ---- .../src/main/web/leagueAdmin.html | 2 +- .../src/main/web/merchant.html | 2 +- .../src/main/web/soloDraft.html | 2 +- .../src/main/resources/set101-rarity.txt | 16 + .../src/main/resources/set21-rarity.txt | 63 ---- .../src/main/resources/set51-rarity.txt | 47 +++ .../src/main/resources/setConfig.json | 13 +- .../src/main/resources/lotrFormats.json | 8 +- 20 files changed, 477 insertions(+), 458 deletions(-) rename gemp-lotr/gemp-lotr-async/src/main/web/cards/{set21/set21.json => set101/fotr-starter-supplement.json} (100%) rename gemp-lotr/gemp-lotr-async/src/main/web/cards/{set21/set1-errata.json => set51/set01-errata.json} (54%) create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js delete mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt delete mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/ban.html b/gemp-lotr/gemp-lotr-async/src/main/web/ban.html index 678ed27a3..f1236e8d6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/ban.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/ban.html @@ -36,7 +36,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json similarity index 100% rename from gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set21.json rename to gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json similarity index 54% rename from gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json rename to gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index 9d6d8e2b6..79b647819 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set21/set1-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -116,7 +116,7 @@ } }, - "21_10139": { + "21_10139": { "title": "Savagery To Match Their Numbers", "culture": "isengard", "cost": 0, @@ -289,152 +289,9 @@ ] }, - "21_2032": { - "side": "free_people", - "cost": 0, - "strength": 1, - "culture": "Gondor", - "possession": "Hand Weapon", - "title": "Flaming Brand", - "type": "possession", - "target": "ranger", - "effects": [ - { - "type": "extrapossessionclass" - }, - { - "type": "activated", - "phase": "skirmish", - "condition": { - "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", - }, - "cost": [ - { - "type": "memorize", - "filter": "bearer", - "memory": "bearer" - }, - { - "type": "discard", - "filter": "self" - } - ], - "effect":[ - { - "type": "modifyStrength", - "filter": "memory(bearer)", - "amount": 3 - }, - { - "type": "addKeyword", - "filter": "memory(bearer)", - "keyword": "damage+1" - } - ] - }, - ] - }, + - "21_3042": { - "side": "free_people", - "cost": 0, - "culture": "Gondor", - "title": "*Horn of Boromir", - "type": "possession", - "target": "name(Boromir)", - "effects": { - "type": "activated", - "phase": "assignment", - "condition": { - "type": "canSpot", - "filter": "bearer,notAssignedToSkirmish" - }, - "cost": [ - { - "type": "exert", - "filter": "bearer" - } - ], - "effect":[ - { - "type": "assignFpCharacterToSkirmish", - "player": "fp", - "fpCharacter": "bearer", - "against": "choose(minion)" - }, - { - "type": "modifyStrength", - "filter": "choose(ally,allyInCurrentRegion)", - "amount": 3, - "until": "start(regroup)", - "memorize": "summonedAlly" - }, - { - "type": "allyCanParticipateInArcheryFireAndSkirmishes", - "filter": "memory(summonedAlly)", - "until": "start(regroup)" - } - ] - } - }, - "21_3068": { - "side": "shadow", - "site": 4, - "cost": 4, - "race": "Wizard", - "strength": 8, - "culture": "Isengard", - "vitality": 4, - "subtitle": "Keeper of Isengard", - "title": "*Saruman", - "type": "minion", - "effects": [ - { - "type": "modifier", - "modifier": { - "type": "cantbeassignedtoskirmish", - "filter": "self" - } - }, - { - "type": "modifier", - "modifier": { - "type": "cantTakeWounds", - "filter": "self", - "condition": { - "type": "phase", - "phase": "archery" - } - } - }, - { - "type": "activatedTrigger", - "trigger": { - "type": "aboutToTakeWound", - "filter": "uruk-hai" - }, - "cost": { - "type": "exert", - "filter": "self", - "times": 1 - }, - "effect": [ - { - "type": "preventWound", - "filter": "choose(uruk-hai)", - "memorize": "uruk" - }, - { - "type": "addKeyword", - "filter": "memory(uruk)", - "keyword": "fierce" - } - ] - }, - ] - }, "21_10108": { @@ -537,176 +394,9 @@ ] }, - "21_20121": - { - "title": "*Gimli", - "subtitle": "Dwarf of the Mountain-race", - "culture": "dwarven", - "cost": 2, - "type": "companion", - "race": "dwarf", - "strength": 6, - "vitality": 3, - "resistance": 6, - "signet": "frodo", - "keyword": "damage+1", - "effects": [ - { - "type": "modifier", - - "modifier": { - "type": "addKeyword", - "filter": "self", - "keyword": "concealed", - "condition": { - "type": "location", - "filter": "underground" - } - }, - }, - { - "type": "trigger", - "optional": true, - "trigger": { - "type": "movesTo", - "filter": "underground", - - }, - "cost": { - "type": "exert", - "filter": "self" - }, - "effect": { - "type": "addKeyword", - "filter": "choose(another,companion)", - "keyword": "concealed", - "until": "start(regroup)" - } - } - ] - }, - "21_3038": { - "side": "free_people", - "title": "*Aragorn", - "subtitle": "Heir to the White City", - "culture": "Gondor", - "type": "companion", - "race": "Man", - "cost": 4, - "strength": 8, - "vitality": 4, - "resistance": 6, - "signet": "frodo", - "keyword": [ - "Ranger", - ], - "effects": { - "type": "trigger", - "optional": true, - "trigger": { - "type": "movesfrom" - }, - "condition": { - "type": "phase", - "phase": "fellowship" - }, - "effect": { - "type": "preventable", - "effect": [ - { - "type": "addKeyword", - "filter": "choose(another,companion)", - "keyword": "concealed", - "until": "start(regroup)" - }, - { - "type": "addKeyword", - "filter": "self", - "keyword": "concealed", - "until": "start(regroup)" - }, - ], - "text": "Would you like to discard a minion (or reveal a tracker) from hand to prevent a companion becoming concealed?", - "player": "shadowPlayer", - "cost": { - "type": "choice", - "player": "shadowPlayer", - "texts": [ - "Discard a minion from hand", - "Reveal a tracker from hand" - ], - "effects": [ - { - "type": "revealCardsFromHand", - "filter": "choose(tracker)", - "hand": "shadowPlayer" - }, - { - "type": "discardFromHand", - "filter": "choose(minion)", - "forced": false, - "hand": "shadowPlayer", - } - ] - } - - }, - } - - }, - - "21_30106": { - "title": "*Bill the Pony", - "culture": "Shire", - "side": "free_people", - "cost": 0, - "type": "possession", - "possession": "Pony", - "target": "name(Sam)", - "effects": [ - { - "type": "trigger", - "trigger": { - "type": "played", - "filter": "self" - }, - "effect": { - "type": "heal", - "filter": "bearer" - } - }, - { - "type": "modifier", - "modifier": { - "type": "addKeyword", - "filter": "bearer", - "keyword": "concealed" - } - }, - { - "type": "trigger", - "trigger": { - "type": "condition", - "condition": [ - { - "type": "location", - "filter": "underground" - }, - { - "type": "canSpot", - "filter": "self,attachedTo(companion)" - } - ] - }, - "effect": { - "type": "discard", - "filter": "self" - } - } - ] - }, + } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json new file mode 100644 index 000000000..903edafa6 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json @@ -0,0 +1,98 @@ +{ + "21_2032": { + "side": "free_people", + "cost": 0, + "strength": 1, + "culture": "Gondor", + "possession": "Hand Weapon", + "title": "Flaming Brand", + "type": "possession", + "target": "ranger", + "effects": [ + { + "type": "extrapossessionclass" + }, + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "21_20121": { + "title": "*Gimli", + "subtitle": "Dwarf of the Mountain-race", + "culture": "dwarven", + "cost": 2, + "type": "companion", + "race": "dwarf", + "strength": 6, + "vitality": 3, + "resistance": 6, + "signet": "frodo", + "keyword": "damage+1", + "effects": [ + { + "type": "modifier", + + "modifier": { + "type": "addKeyword", + "filter": "self", + "keyword": "concealed", + "condition": { + "type": "location", + "filter": "underground" + } + }, + }, + { + "type": "trigger", + "optional": true, + "trigger": { + "type": "movesTo", + "filter": "underground", + + }, + "cost": { + "type": "exert", + "filter": "self" + }, + "effect": { + "type": "addKeyword", + "filter": "choose(another,companion)", + "keyword": "concealed", + "until": "start(regroup)" + } + } + ] + }, + + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json new file mode 100644 index 000000000..5de768fc5 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -0,0 +1,222 @@ +{ + "21_3042": { + "side": "free_people", + "cost": 0, + "culture": "Gondor", + "title": "*Horn of Boromir", + "type": "possession", + "target": "name(Boromir)", + "effects": { + "type": "activated", + "phase": "assignment", + "condition": { + "type": "canSpot", + "filter": "bearer,notAssignedToSkirmish" + }, + "cost": [ + { + "type": "exert", + "filter": "bearer" + } + ], + "effect":[ + { + "type": "assignFpCharacterToSkirmish", + "player": "fp", + "fpCharacter": "bearer", + "against": "choose(minion)" + }, + { + "type": "modifyStrength", + "filter": "choose(ally,allyInCurrentRegion)", + "amount": 3, + "until": "start(regroup)", + "memorize": "summonedAlly" + }, + { + "type": "allyCanParticipateInArcheryFireAndSkirmishes", + "filter": "memory(summonedAlly)", + "until": "start(regroup)" + } + ] + } + }, + + "21_3068": { + "side": "shadow", + "site": 4, + "cost": 4, + "race": "Wizard", + "strength": 8, + "culture": "Isengard", + "vitality": 4, + "subtitle": "Keeper of Isengard", + "title": "*Saruman", + "type": "minion", + "effects": [ + { + "type": "modifier", + "modifier": { + "type": "cantbeassignedtoskirmish", + "filter": "self" + } + }, + { + "type": "modifier", + "modifier": { + "type": "cantTakeWounds", + "filter": "self", + "condition": { + "type": "phase", + "phase": "archery" + } + } + }, + { + "type": "activatedTrigger", + "trigger": { + "type": "aboutToTakeWound", + "filter": "uruk-hai" + }, + "cost": { + "type": "exert", + "filter": "self", + "times": 1 + }, + "effect": [ + { + "type": "preventWound", + "filter": "choose(uruk-hai)", + "memorize": "uruk" + }, + { + "type": "addKeyword", + "filter": "memory(uruk)", + "keyword": "fierce" + } + ] + }, + ] + }, + + "21_3038": { + "side": "free_people", + "title": "*Aragorn", + "subtitle": "Heir to the White City", + "culture": "Gondor", + "type": "companion", + "race": "Man", + "cost": 4, + "strength": 8, + "vitality": 4, + "resistance": 6, + "signet": "frodo", + "keyword": [ + "Ranger", + ], + "effects": { + "type": "trigger", + "optional": true, + "trigger": { + "type": "movesfrom" + }, + "condition": { + "type": "phase", + "phase": "fellowship" + }, + "effect": { + "type": "preventable", + "effect": [ + { + "type": "addKeyword", + "filter": "choose(another,companion)", + "keyword": "concealed", + "until": "start(regroup)" + }, + { + "type": "addKeyword", + "filter": "self", + "keyword": "concealed", + "until": "start(regroup)" + }, + ], + "text": "Would you like to discard a minion (or reveal a tracker) from hand to prevent a companion becoming concealed?", + "player": "shadowPlayer", + "cost": { + "type": "choice", + "player": "shadowPlayer", + "texts": [ + "Discard a minion from hand", + "Reveal a tracker from hand" + ], + "effects": [ + { + "type": "revealCardsFromHand", + "filter": "choose(tracker)", + "hand": "shadowPlayer" + }, + { + "type": "discardFromHand", + "filter": "choose(minion)", + "forced": false, + "hand": "shadowPlayer", + } + ] + } + + }, + } + }, + + + "21_30106": { + "title": "*Bill the Pony", + "culture": "Shire", + "side": "free_people", + "cost": 0, + "type": "possession", + "possession": "Pony", + "target": "name(Sam)", + "effects": [ + { + "type": "trigger", + "trigger": { + "type": "played", + "filter": "self" + }, + "effect": { + "type": "heal", + "filter": "bearer" + } + }, + { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "bearer", + "keyword": "concealed" + } + }, + { + "type": "trigger", + "trigger": { + "type": "condition", + "condition": [ + { + "type": "location", + "filter": "underground" + }, + { + "type": "canSpot", + "filter": "self,attachedTo(companion)" + } + ] + }, + "effect": { + "type": "discard", + "filter": "self" + } + } + ] + }, +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html b/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html index 27c54a446..27f241342 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/deckBuild.html @@ -30,7 +30,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/game.html b/gemp-lotr/gemp-lotr-async/src/main/web/game.html index ed5410d77..b7b3317f7 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/game.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/game.html @@ -30,7 +30,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html index 9e647de8a..9fcd32ae9 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html @@ -29,7 +29,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/index.html b/gemp-lotr/gemp-lotr-async/src/main/web/index.html index 9656605b1..7b41873c5 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/index.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/index.html @@ -39,7 +39,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js new file mode 100644 index 000000000..56c87a372 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -0,0 +1,67 @@ +var PCCards = { + '101_1': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_1.jpg', + '101_2': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_2.jpg', + '101_3': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_3.jpg', + '101_4': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_4.jpg', + '101_5': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_5.jpg', + '101_6': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_6.jpg', + '101_7': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_7.jpg', + '101_8': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_8.jpg', + '101_9': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_9.jpg', + '101_10': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_10.jpg', + '101_11': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_11.jpg', + '101_12': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_12.jpg', + '101_13': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_13.jpg', + '101_14': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_14.jpg', + '101_15': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_15.jpg', + '101_16': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_16.jpg', + '101_17': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_17.jpg', + '101_18': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_18.jpg', + '101_19': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_19.jpg', + '101_20': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_20.jpg', + '101_21': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_21.jpg', + '101_22': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_22.jpg', + '101_23': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_23.jpg', + '101_24': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_24.jpg', + '101_25': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_25.jpg', + '101_26': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_26.jpg', + '101_27': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_27.jpg', + '101_28': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_28.jpg', + '101_29': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_29.jpg', + '101_30': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_30.jpg', + '101_31': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_31.jpg', + '101_32': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_32.jpg', + '101_33': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_33.jpg', + '101_34': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_34.jpg', + '101_35': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_35.jpg', + '101_36': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_36.jpg', + '101_37': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_37.jpg', + '101_38': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_38.jpg', + '101_39': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_39.jpg', + '101_40': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_40.jpg', + '101_41': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_41.jpg', + '101_42': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_42.jpg', + '101_43': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_43.jpg', + '101_44': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_44.jpg', + '101_45': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_45.jpg', + '101_46': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_46.jpg', + '101_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_47.jpg', + '51_1040': 'https://i.lotrtcgpc.net/errata/FOTR/51_40.jpg', + '51_1045': 'https://i.lotrtcgpc.net/errata/FOTR/51_45.jpg', + '51_1080': 'https://i.lotrtcgpc.net/errata/FOTR/51_80.jpg', + '51_10108': 'https://i.lotrtcgpc.net/errata/FOTR/51_108.jpg', + '51_10139': 'https://i.lotrtcgpc.net/errata/FOTR/51_139.jpg', + '51_10195': 'https://i.lotrtcgpc.net/errata/FOTR/51_195.jpg', + '51_10234': 'https://i.lotrtcgpc.net/errata/FOTR/51_234.jpg', + '51_10248': 'https://i.lotrtcgpc.net/errata/FOTR/51_248.jpg', + '51_10311': 'https://i.lotrtcgpc.net/errata/FOTR/51_311.jpg', + '51_10313': 'https://i.lotrtcgpc.net/errata/FOTR/51_313.jpg', + '51_10316': 'https://i.lotrtcgpc.net/errata/FOTR/51_316.jpg', + '51_2032': 'https://i.lotrtcgpc.net/errata/FOTR/52_32.jpg', + '51_2075': 'https://i.lotrtcgpc.net/errata/FOTR/52_75.jpg', + '51_3042': 'https://i.lotrtcgpc.net/errata/FOTR/53_42.jpg', + '51_3068': 'https://i.lotrtcgpc.net/errata/FOTR/53_68.jpg', + '51_20121': 'https://i.lotrtcgpc.net/errata/FOTR/52_121.jpg', + '51_3038': 'https://i.lotrtcgpc.net/errata/FOTR/53_38.jpg', + '51_30106': 'https://i.lotrtcgpc.net/errata/FOTR/53_106.jpg' +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js index 9764074bd..f931c8611 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/jCards.js @@ -217,7 +217,7 @@ var Card = Class.extend({ img = hobbit[blueprintId]; if (img != null) return img; - img = set21[blueprintId]; + img = PCCards[blueprintId]; if (img != null) return img; return null; diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js deleted file mode 100644 index c25353bdf..000000000 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/set21.js +++ /dev/null @@ -1,67 +0,0 @@ -var set21 = { - '21_1': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_1.jpg', - '21_2': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_2.jpg', - '21_3': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_3.jpg', - '21_4': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_4.jpg', - '21_5': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_5.jpg', - '21_6': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_6.jpg', - '21_7': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_7.jpg', - '21_8': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_8.jpg', - '21_9': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_9.jpg', - '21_10': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_10.jpg', - '21_11': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_11.jpg', - '21_12': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_12.jpg', - '21_13': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_13.jpg', - '21_14': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_14.jpg', - '21_15': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_15.jpg', - '21_16': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_16.jpg', - '21_17': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_17.jpg', - '21_18': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_18.jpg', - '21_19': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_19.jpg', - '21_20': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_20.jpg', - '21_21': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_21.jpg', - '21_22': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_22.jpg', - '21_23': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_23.jpg', - '21_24': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_24.jpg', - '21_25': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_25.jpg', - '21_26': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_26.jpg', - '21_27': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_27.jpg', - '21_28': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_28.jpg', - '21_29': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_29.jpg', - '21_30': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_30.jpg', - '21_31': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_31.jpg', - '21_32': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_32.jpg', - '21_33': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_33.jpg', - '21_34': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_34.jpg', - '21_35': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_35.jpg', - '21_36': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_36.jpg', - '21_37': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_37.jpg', - '21_38': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_38.jpg', - '21_39': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_39.jpg', - '21_40': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_40.jpg', - '21_41': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_41.jpg', - '21_42': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_42.jpg', - '21_43': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_43.jpg', - '21_44': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_44.jpg', - '21_45': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_45.jpg', - '21_46': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_46.jpg', - '21_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/21_47.jpg', - '21_1040': 'https://i.lotrtcgpc.net/errata/FOTR/21_40.jpg', - '21_1045': 'https://i.lotrtcgpc.net/errata/FOTR/21_45.jpg', - '21_1080': 'https://i.lotrtcgpc.net/errata/FOTR/21_80.jpg', - '21_10108': 'https://i.lotrtcgpc.net/errata/FOTR/21_108.jpg', - '21_10139': 'https://i.lotrtcgpc.net/errata/FOTR/21_139.jpg', - '21_10195': 'https://i.lotrtcgpc.net/errata/FOTR/21_195.jpg', - '21_10234': 'https://i.lotrtcgpc.net/errata/FOTR/21_234.jpg', - '21_10248': 'https://i.lotrtcgpc.net/errata/FOTR/21_248.jpg', - '21_10311': 'https://i.lotrtcgpc.net/errata/FOTR/21_311.jpg', - '21_10313': 'https://i.lotrtcgpc.net/errata/FOTR/21_313.jpg', - '21_10316': 'https://i.lotrtcgpc.net/errata/FOTR/21_316.jpg', - '21_2032': 'https://i.lotrtcgpc.net/errata/FOTR/22_32.jpg', - '21_2075': 'https://i.lotrtcgpc.net/errata/FOTR/22_75.jpg', - '21_3042': 'https://i.lotrtcgpc.net/errata/FOTR/23_42.jpg', - '21_3068': 'https://i.lotrtcgpc.net/errata/FOTR/23_68.jpg', - '21_20121': 'https://i.lotrtcgpc.net/errata/FOTR/22_121.jpg', - '21_3038': 'https://i.lotrtcgpc.net/errata/FOTR/23_38.jpg', - '21_30106': 'https://i.lotrtcgpc.net/errata/FOTR/23_106.jpg' -} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html b/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html index 0fd83d3f2..507baab6b 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/leagueAdmin.html @@ -44,7 +44,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html b/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html index 3d510efa5..3e19945fb 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/merchant.html @@ -30,7 +30,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html b/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html index c5199004f..b0312fca2 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/soloDraft.html @@ -30,7 +30,7 @@ - + diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt new file mode 100644 index 000000000..702bdb54a --- /dev/null +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt @@ -0,0 +1,16 @@ +51R1040 +51R1045 +51R1080 +51U10108 +51R10139 +51R10195 +51U10234 +51C10248 +51C10311 +51R10313 +51U10316 +51R2032 +51R2075 +51R3042 +51R3068 +51U10108 \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt deleted file mode 100644 index b861849d3..000000000 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set21-rarity.txt +++ /dev/null @@ -1,63 +0,0 @@ -21S1 -21S2 -21S3 -21S4 -21S5 -21S6 -21S7 -21S8 -21S9 -21S10 -21S11 -21S12 -21S13 -21S14 -21S15 -21S16 -21S17 -21S18 -21S19 -21S20 -21S21 -21S22 -21S23 -21S24 -21S25 -21S26 -21S27 -21S28 -21S29 -21S30 -21S31 -21S32 -21S33 -21S34 -21S35 -21S36 -21S37 -21S38 -21S39 -21S40 -21S41 -21S42 -21S43 -21S44 -21S45 -21S46 -21S47 -21R1040 -21R1045 -21R1080 -21U10108 -21R10139 -21R10195 -21U10234 -21C10248 -21C10311 -21R10313 -21U10316 -21R2032 -21R2075 -21R3042 -21R3068 -21U10108 \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt new file mode 100644 index 000000000..743e3b02c --- /dev/null +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt @@ -0,0 +1,47 @@ +101S1 +101S2 +101S3 +101S4 +101S5 +101S6 +101S7 +101S8 +101S9 +101S10 +101S11 +101S12 +101S13 +101S14 +101S15 +101S16 +101S17 +101S18 +101S19 +101S20 +101S21 +101S22 +101S23 +101S24 +101S25 +101S26 +101S27 +101S28 +101S29 +101S30 +101S31 +101S32 +101S33 +101S34 +101S35 +101S36 +101S37 +101S38 +101S39 +101S40 +101S41 +101S42 +101S43 +101S44 +101S45 +101S46 +101S47 diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json b/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json index fbdd65f9b..efb2eec22 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json @@ -148,9 +148,18 @@ "playable": false }, { - "setId": "21", + "setId": "51", + "setName": "PC Errata", + "rarityFile": "/set51-rarity.txt", + "originalSet": false, + "merchantable": false, + "needsLoading": false, + "playable": true + }, + { + "setId": "101", "setName": "PC FOTR Supplements", - "rarityFile": "/set21-rarity.txt", + "rarityFile": "/set101-rarity.txt", "originalSet": false, "merchantable": false, "needsLoading": false, diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json index 6649d091f..d2f122ef1 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json @@ -4,7 +4,7 @@ "code":"debug_hall", "sites": "SPECIAL", "maximumSameName":100, - "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21] + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 101] }, { "name":"Fellowship block", @@ -18,7 +18,7 @@ "code":"pc_fotr_block", "sites":"FELLOWSHIP", "cancelRingBearerSkirmish":true, - "set":[1, 2, 3, 21], + "set":[1, 2, 3, 51, 101], "banned":["1_40","1_311","2_32","3_42","3_68",] }, { @@ -186,7 +186,7 @@ "name":"PC-Movie", "code":"pc_movie", "sites":"KING", - "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21], + "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 51, 101], "banned":["1_40","1_311","2_32","3_42","3_68", "1_45", "1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "3_106", "3_108", "3_38", "3_67", "7_49", "7_96", "8_1", "10_2", "10_91"], }, { @@ -274,7 +274,7 @@ "sites":"SHADOWS", "banned":["1_40","1_311","2_32","3_42","3_68","1_45", "1_138", "1_234", "1_313", "1_316", "2_121", "3_17", "3_38", "3_67", "3_108", "3_113", "4_73", "7_49", "8_1", "10_2", "10_11", "10_91", "11_31", "11_100", "11_132"], "restricted":["1_80", "1_108", "1_139", "1_195", "1_248", "2_75", "3_106", "4_276", "4_304"], - "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,21] + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 101] }, { "name":"War of the Ring block - Set 11", From 863279c6b920bc0c3d3c650b7750e96d6f409007 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 15 Feb 2021 11:37:07 -0600 Subject: [PATCH 41/74] Fixing set 101 and 51 cards still being listed as 21 in various places, including unit tests. --- .../cards/set101/fotr-starter-supplement.json | 94 +++++++++---------- .../main/web/cards/set51/set01-errata.json | 22 ++--- .../main/web/cards/set51/set02-errata.json | 4 +- .../main/web/cards/set51/set03-errata.json | 8 +- .../src/main/resources/set101-rarity.txt | 63 +++++++++---- .../src/main/resources/set51-rarity.txt | 63 ++++--------- .../pc/errata/set1/Elrond_LoRErrataTests.java | 6 +- .../errata/set1/Galadriel_LoLErrataTests.java | 4 +- .../pc/errata/set1/NoStrangerErrataTests.java | 4 +- .../pc/errata/set1/Sam_SoHErrataTests.java | 2 +- .../pc/errata/set1/StingErrataTests.java | 2 +- .../errata/set1/TalentForNBSErrataTests.java | 2 +- .../errata/set2/FlamingBrandErrataTests.java | 4 +- .../errata/set2/Gimli_DotMrErrataTests.java | 2 +- .../errata/set3/Aragorn_HttWCErrataTests.java | 2 +- .../errata/set3/BillThePonyErrataTests.java | 2 +- .../errata/set3/HornOfBoromirErrataTests.java | 4 +- .../errata/set3/Saruman_KoIErrataTests.java | 2 +- 18 files changed, 145 insertions(+), 145 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json index 83195d6c6..0dc136748 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json @@ -1,5 +1,5 @@ { - "21_1": { + "101_1": { "title": "Blue Mountain Dwarf", "culture": "dwarven", "type": "companion", @@ -25,7 +25,7 @@ } } }, - "21_2": { + "101_2": { "title": "Stand Together", "culture": "gandalf", "cost": 3, @@ -49,7 +49,7 @@ } } }, - "21_3": { + "101_3": { "title": "Thrice Worthy and Beloved Barliman", "culture": "gandalf", "type": "condition", @@ -73,7 +73,7 @@ } } }, - "21_4": { + "101_4": { "title": "Gondorian Broadsword", "culture": "gondor", "type": "possession", @@ -97,7 +97,7 @@ } } }, - "21_5": { + "101_5": { "title": "Relics of the Second Age", "culture": "gondor", "type": "condition", @@ -124,7 +124,7 @@ } } }, - "21_6": { + "101_6": { "title": "Thrown Sword", "culture": "gondor", "type": "event", @@ -143,7 +143,7 @@ } } }, - "21_7": { + "101_7": { "title": "Lurtz", "subtitle": "Weapon of Saruman", "culture": "isengard", @@ -169,7 +169,7 @@ } } }, - "21_8": { + "101_8": { "title": "Strength of Servitude", "culture": "isengard", "type": "event", @@ -187,7 +187,7 @@ } } }, - "21_9": { + "101_9": { "title": "Uruk Swarmer", "culture": "isengard", "type": "minion", @@ -220,7 +220,7 @@ ] } }, - "21_10": { + "101_10": { "title": "Goblin Bow", "culture": "moria", "type": "possession", @@ -260,7 +260,7 @@ } ] }, - "21_11": { + "101_11": { "title": "Goblin Warchief", "subtitle": "Captain of the Underhall", "culture": "moria", @@ -299,7 +299,7 @@ ] } }, - "21_12": { + "101_12": { "title": "No Hope of Escape That Way", "culture": "moria", "type": "event", @@ -317,7 +317,7 @@ } } }, - "21_13": { + "101_13": { "title": "The Old Forest", "culture": "wraith", "type": "condition", @@ -361,7 +361,7 @@ } ] }, - "21_14": { + "101_14": { "title": "Old Man Willow", "subtitle": "Heart of the Withywindle", "culture": "wraith", @@ -414,7 +414,7 @@ } ] }, - "21_15": { + "101_15": { "title": "And in the Darkness Bind Them", "culture": "sauron", "type": "condition", @@ -488,7 +488,7 @@ } } }, - "21_16": { + "101_16": { "title": "Gladden Ambush", "culture": "sauron", "type": "event", @@ -498,7 +498,7 @@ ], "cost": 0 }, - "21_17": { + "101_17": { "title": "Bilbo", "subtitle": "One Hundred and Eleventy", "culture": "shire", @@ -524,14 +524,14 @@ } } }, - "21_18": { + "101_18": { "title": "Hobbit Concealment", "culture": "shire", "type": "condition", "keyword": "support area", "cost": 1 }, - "21_19": { + "101_19": { "title": "Sam", "subtitle": "Hobbit of Hobbiton", "culture": "shire", @@ -542,28 +542,28 @@ "vitality": 4, "signet": "frodo" }, - "21_20": { + "101_20": { "title": "Walking Stick", "culture": "shire", "type": "possession", "possession": "staff", "strength": 0 }, - "21_21": { + "101_21": { "title": "Barred the Gates", "culture": "dwarven", "type": "condition", "keyword": "support area", "cost": 0 }, - "21_22": { + "101_22": { "title": "Light-shaft", "culture": "dwarven", "type": "event", "keyword": "regroup", "cost": 0 }, - "21_23": { + "101_23": { "title": "Longbeard's Axe", "culture": "dwarven", "type": "possession", @@ -571,7 +571,7 @@ "cost": 1, "strength": 2 }, - "21_24": { + "101_24": { "title": "Venturing Dwarf", "culture": "dwarven", "type": "companion", @@ -580,21 +580,21 @@ "strength": 5, "vitality": 3 }, - "21_25": { + "101_25": { "title": "Dazzling Flash", "culture": "gandalf", "type": "event", "keyword": "skirmish", "cost": 1 }, - "21_26": { + "101_26": { "title": "No Time for Wonder", "culture": "gandalf", "type": "condition", "keyword": "support area", "cost": 1 }, - "21_27": { + "101_27": { "title": "Dagger of Westernesse", "culture": "gondor", "type": "artifact", @@ -602,7 +602,7 @@ "cost": 0, "strength": 2 }, - "21_28": { + "101_28": { "title": "Goblin Avengers", "culture": "moria", "type": "minion", @@ -612,21 +612,21 @@ "vitality": 3, "site": 4 }, - "21_29": { + "101_29": { "title": "Goblin Warren", "culture": "moria", "type": "condition", "keyword": "support area", "cost": 1 }, - "21_30": { + "101_30": { "title": "Thither We Are Going Against My Wish", "culture": "moria", "type": "condition", "keyword": "support area", "cost": 1 }, - "21_31": { + "101_31": { "title": "Hollin Snarler", "culture": "sauron", "type": "minion", @@ -636,14 +636,14 @@ "vitality": 2, "site": 3 }, - "21_32": { + "101_32": { "title": "The Hunt is Up!", "culture": "sauron", "type": "condition", "keyword": "support area", "cost": 1 }, - "21_33": { + "101_33": { "title": "Hunting Pack", "culture": "sauron", "type": "minion", @@ -653,7 +653,7 @@ "vitality": 3, "site": 5 }, - "21_34": { + "101_34": { "title": "Pippin", "subtitle": "Fool of a Took", "culture": "shire", @@ -664,27 +664,27 @@ "vitality": 4, "signet": "gandalf" }, - "21_35": { + "101_35": { "title": "Deft Aid", "culture": "elven", "type": "condition", "site": 1 }, - "21_36": { + "101_36": { "title": "Elven Flet", "culture": "elven", "type": "condition", "keyword": "support area", "cost": 1 }, - "21_37": { + "101_37": { "title": "In Imladris it Dwells", "culture": "elven", "type": "event", "keyword": "fellowship", "cost": 0 }, - "21_38": { + "101_38": { "title": "Rivendell Sentry", "culture": "elven", "type": "ally", @@ -694,7 +694,7 @@ "vitality": 2, "allyHome": "fellowship,4" }, - "21_39": { + "101_39": { "title": "Arroch", "culture": "gondor", "type": "possession", @@ -702,21 +702,21 @@ "cost": 2, "vitality": 1 }, - "21_40": { + "101_40": { "title": "The Deeds of the Steward's House", "culture": "gondor", "type": "condition", "keyword": "support area", "cost": 2 }, - "21_41": { + "101_41": { "title": "They Have a Cave Troll", "culture": "gondor", "type": "event", "keyword": "maneuver", "cost": 1 }, - "21_42": { + "101_42": { "title": "Isengard Attendant", "culture": "isengard", "type": "minion", @@ -726,7 +726,7 @@ "vitality": 2, "site": 4 }, - "21_43": { + "101_43": { "title": "Stirruk", "culture": "isengard", "type": "possession", @@ -735,7 +735,7 @@ "strength": 3, "vitality": 1 }, - "21_44": { + "101_44": { "title": "Uruk Batch", "culture": "isengard", "type": "minion", @@ -745,14 +745,14 @@ "vitality": 2, "site": 5 }, - "21_45": { + "101_45": { "title": "Influence of Shadow", "culture": "sauron", "type": "condition", "keyword": "support area", "cost": 0 }, - "21_46": { + "101_46": { "title": "Tower Shaman", "culture": "sauron", "type": "minion", @@ -762,7 +762,7 @@ "vitality": 3, "site": 6 }, - "21_47": { + "101_47": { "title": "Udun Scimitar", "culture": "sauron", "type": "possession", diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index 79b647819..d72e9e029 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -1,5 +1,5 @@ { - "21_1040": { + "51_1040": { "title": "*Elrond", "subtitle": "Lord of Rivendell", "culture": "elven", @@ -39,7 +39,7 @@ } ] }, - "21_1045": { + "51_1045": { "title": "*Galadriel", "subtitle": "Lady of Light", "culture": "elven", @@ -77,7 +77,7 @@ } ] }, - "21_1080": { + "51_1080": { "title": "*Ottar", "subtitle": "Man of Laketown", "culture": "gandalf", @@ -116,7 +116,7 @@ } }, - "21_10139": { + "51_10139": { "title": "Savagery To Match Their Numbers", "culture": "isengard", "cost": 0, @@ -163,7 +163,7 @@ } }, - "21_10195": { + "51_10195": { "title": "*Relics of Moria", "culture": "moria", "cost": 1, @@ -184,7 +184,7 @@ } }, - "21_10234": { + "51_10234": { "title": "*ÚlairĆ« NertĆ«a", "subtitle": "Messenger of Dol Guldur", "culture": "wraith", @@ -219,7 +219,7 @@ } }, - "21_10248": { + "51_10248": { "title": "Forces of Mordor", "culture": "sauron", "cost": 0, @@ -246,7 +246,7 @@ } }, - "21_10311": { + "51_10311": { "title": "*Sam", "subtitle": "Son of Hamfast", "culture": "shire", @@ -294,7 +294,7 @@ - "21_10108": { + "51_10108": { "title": "No Stranger to the Shadows", "culture": "gondor", "cost": 0, @@ -314,7 +314,7 @@ }, - "21_10313": { + "51_10313": { "title": "*Sting", "culture": "shire", "cost": 1, @@ -356,7 +356,7 @@ } }, - "21_10316": { + "51_10316": { "title": "*A Talent for Not Being Seen", "culture": "shire", "cost": 0, diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json index 903edafa6..18cc1038d 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json @@ -1,5 +1,5 @@ { - "21_2032": { + "51_2032": { "side": "free_people", "cost": 0, "strength": 1, @@ -46,7 +46,7 @@ ] }, - "21_20121": { + "51_20121": { "title": "*Gimli", "subtitle": "Dwarf of the Mountain-race", "culture": "dwarven", diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index 5de768fc5..dff2ee944 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -1,5 +1,5 @@ { - "21_3042": { + "51_3042": { "side": "free_people", "cost": 0, "culture": "Gondor", @@ -42,7 +42,7 @@ } }, - "21_3068": { + "51_3068": { "side": "shadow", "site": 4, "cost": 4, @@ -99,7 +99,7 @@ ] }, - "21_3038": { + "51_3038": { "side": "free_people", "title": "*Aragorn", "subtitle": "Heir to the White City", @@ -169,7 +169,7 @@ }, - "21_30106": { + "51_30106": { "title": "*Bill the Pony", "culture": "Shire", "side": "free_people", diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt index 702bdb54a..743e3b02c 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set101-rarity.txt @@ -1,16 +1,47 @@ -51R1040 -51R1045 -51R1080 -51U10108 -51R10139 -51R10195 -51U10234 -51C10248 -51C10311 -51R10313 -51U10316 -51R2032 -51R2075 -51R3042 -51R3068 -51U10108 \ No newline at end of file +101S1 +101S2 +101S3 +101S4 +101S5 +101S6 +101S7 +101S8 +101S9 +101S10 +101S11 +101S12 +101S13 +101S14 +101S15 +101S16 +101S17 +101S18 +101S19 +101S20 +101S21 +101S22 +101S23 +101S24 +101S25 +101S26 +101S27 +101S28 +101S29 +101S30 +101S31 +101S32 +101S33 +101S34 +101S35 +101S36 +101S37 +101S38 +101S39 +101S40 +101S41 +101S42 +101S43 +101S44 +101S45 +101S46 +101S47 diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt index 743e3b02c..b7c64de13 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/set51-rarity.txt @@ -1,47 +1,16 @@ -101S1 -101S2 -101S3 -101S4 -101S5 -101S6 -101S7 -101S8 -101S9 -101S10 -101S11 -101S12 -101S13 -101S14 -101S15 -101S16 -101S17 -101S18 -101S19 -101S20 -101S21 -101S22 -101S23 -101S24 -101S25 -101S26 -101S27 -101S28 -101S29 -101S30 -101S31 -101S32 -101S33 -101S34 -101S35 -101S36 -101S37 -101S38 -101S39 -101S40 -101S41 -101S42 -101S43 -101S44 -101S45 -101S46 -101S47 +51R1040 +51R1045 +51R1080 +51U10108 +51R10139 +51R10195 +51U10234 +51C10248 +51C10311 +51R10313 +51U10316 +51R2032 +51R2075 +51R3042 +51R3068 +51U10108 diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java index 4f0fdfc80..220648842 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java @@ -19,7 +19,7 @@ public class Elrond_LoRErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("elrond", "21_1040"); + put("elrond", "51_1040"); put("randomcard", "1_3"); }} ); @@ -29,7 +29,7 @@ public class Elrond_LoRErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("elrond", "21_1040"); + put("elrond", "51_1040"); put("gandalf", "1_72"); put("arwen", "1_30"); }} @@ -40,7 +40,7 @@ public class Elrond_LoRErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("elrond", "21_1040"); + put("elrond", "51_1040"); put("allyHome3_1", "1_60"); put("allyHome3_2", "1_27"); put("allyHome6_1", "1_56"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java index e65500859..c7ce923aa 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java @@ -16,7 +16,7 @@ public class Galadriel_LoLErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("galadriel", "21_1045"); + put("galadriel", "51_1045"); put("elrond", "1_40"); }} ); @@ -26,7 +26,7 @@ public class Galadriel_LoLErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("galadriel", "21_1045"); + put("galadriel", "51_1045"); put("allyHome3_1", "1_60"); put("allyHome3_2", "1_27"); put("allyHome6_1", "1_56"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java index ddd6197f8..e521ecbfe 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java @@ -22,8 +22,8 @@ public class NoStrangerErrataTests put("aragorn", "1_89"); put("arwen", "1_30"); put("boromir", "1_97"); - put("nostranger", "21_10108"); - put("nostranger2", "21_10108"); + put("nostranger", "51_10108"); + put("nostranger2", "51_10108"); }} ); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java index 2c84abd38..f76a955cb 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java @@ -16,7 +16,7 @@ public class Sam_SoHErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("sam", "21_10311"); + put("sam", "51_10311"); put("orc", "1_272"); }} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java index 95ab5742f..e3f145c49 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java @@ -22,7 +22,7 @@ public class StingErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("sting", "21_10313"); + put("sting", "51_10313"); put("sam", "1_311"); put("merry", "1_302"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java index f9873e6d7..41aa8643d 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java @@ -20,7 +20,7 @@ public class TalentForNBSErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("talent", "21_10316"); + put("talent", "51_10316"); put("sam", "1_311"); put("gaffer", "1_291"); put("boromir", "1_97"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index 094deca74..96aff87c0 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -19,8 +19,8 @@ public class FlamingBrandErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("brand", "21_2032"); - put("brand2", "21_2032"); + put("brand", "51_2032"); + put("brand2", "51_2032"); put("arwen", "1_30"); put("boromir", "1_97"); put("aragorn", "1_89"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java index 50fa69cf2..c0aa331ad 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java @@ -22,7 +22,7 @@ public class Gimli_DotMrErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("gimli", "21_20121"); + put("gimli", "51_20121"); }} ); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java index da444111a..a57849a37 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -20,7 +20,7 @@ public class Aragorn_HttWCErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("aragorn", "21_3038"); + put("aragorn", "51_3038"); put("gimli", "1_13"); put("minion", "1_268"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java index 4ee3f1c17..022e57d48 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java @@ -25,7 +25,7 @@ public class BillThePonyErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("bill", "21_30106"); + put("bill", "51_30106"); put("sam", "1_311"); }} ); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index 95ad88ffa..1cea03749 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -20,7 +20,7 @@ public class HornOfBoromirErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("horn", "21_3042"); + put("horn", "51_3042"); put("elrond", "1_40"); put("boromir", "1_97"); put("aragorn", "1_89"); @@ -38,7 +38,7 @@ public class HornOfBoromirErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("horn", "21_3042"); + put("horn", "51_3042"); put("elrond", "1_40"); put("boromir", "1_97"); put("aragorn", "1_89"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java index c0bd5f1b2..f05ec2222 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java @@ -24,7 +24,7 @@ public class Saruman_KoIErrataTests put("tale", "1_66"); put("doubleshot", "1_38"); - put("saruman", "21_3068"); + put("saruman", "51_3068"); put("uruk1", "1_151"); put("uruk2", "1_151"); }} From 1bd2e2b001e5904067567a4420a6d28c924463b2 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 15 Feb 2021 11:43:54 -0600 Subject: [PATCH 42/74] Fixed Gimli errata test (site 3 in movie is underground) --- .../pc/errata/set2/Gimli_DotMrErrataTests.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java index c0aa331ad..7a9b3ccf2 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java @@ -23,7 +23,10 @@ public class Gimli_DotMrErrataTests new HashMap() {{ put("gimli", "51_20121"); - }} + }}, + GenericCardTestHelper.FellowshipSites, + GenericCardTestHelper.FOTRFrodo, + GenericCardTestHelper.FOTRRing ); } @@ -86,8 +89,8 @@ public class Gimli_DotMrErrataTests assertFalse(scn.FreepsActionAvailable("Optional")); //scn.FreepsAcceptOptionalTrigger(); - assertEquals(2, scn.GetWoundsOn(gimli)); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + assertEquals(1, scn.GetWoundsOn(gimli)); + assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); } } From cdcf986262b6d08df65806e409e4ec211ed05fef Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 15 Feb 2021 12:23:58 -0600 Subject: [PATCH 43/74] Fixing the new 51/101 sets not showing up in the deckbuilder set filter UI --- .../src/main/web/js/gemp-022/cardFilter.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js index a8bdc1ae3..68871f571 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cardFilter.js @@ -110,7 +110,7 @@ var CardFilter = Class.extend({ + "" + "" + "" - + "" + + "" + "" + "" + "" @@ -125,8 +125,13 @@ var CardFilter = Class.extend({ + "" + "" + "" + + "" + + "" + + "" + + "" + "" + "" + + "" + "" + "" + "" @@ -145,7 +150,7 @@ var CardFilter = Class.extend({ + "" + "" + "" - + "" + + "" + "" + "" + "" From cc77db87625123007919db7612f40986a191921f Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 28 Feb 2021 23:22:31 -0600 Subject: [PATCH 44/74] Updated April errata batch to the latest design. Updated tests to match. --- .../main/web/cards/set51/set01-errata.json | 34 ++++++---- .../main/web/cards/set51/set03-errata.json | 59 ++++++++--------- .../pc/errata/set1/Elrond_LoRErrataTests.java | 34 ++++++++-- .../pc/errata/set1/Sam_SoHErrataTests.java | 4 +- .../errata/set3/HornOfBoromirErrataTests.java | 46 +++---------- .../errata/set3/Saruman_KoIErrataTests.java | 65 ++++++++++--------- 6 files changed, 126 insertions(+), 116 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index d72e9e029..2a4b25294 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -22,7 +22,7 @@ "effect": { "type": "heal", "filter": "choose(ally,allyHome(fellowship,3))", - "count": "0-2" + "count": "0-3" } }, { @@ -31,7 +31,16 @@ "cost": { "type": "exert", "filter": "self", - "times": 2 + "times": { + "type": "condition", + "condition": { + "type": "canSpot", + "count": 2, + "filter": "not(self),culture(elven),ally" + }, + "true": 1, + "false": 2 + } }, "effect": { "type": "drawCards" @@ -261,15 +270,18 @@ { "type": "activated", "phase": "fellowship", - "condition": { - "type": "canSpot", - "filter": "name(Frodo)" - }, - "cost": { - "type": "exert", - "filter": "self", - "times": 2 - }, + "cost": [ + { + "type": "exert", + "filter": "self", + "times": 1 + }, + { + "type": "exert", + "filter": "choose(another,companion)", + "times": 1 + } + ], "effect": { "type": "removeBurdens", "amount": 1 diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index dff2ee944..ad682cb9f 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -8,31 +8,21 @@ "target": "name(Boromir)", "effects": { "type": "activated", - "phase": "assignment", - "condition": { - "type": "canSpot", - "filter": "bearer,notAssignedToSkirmish" - }, + "phase": "maneuver", "cost": [ { "type": "exert", - "filter": "bearer" + "filter": "bearer", + "times": 1 + }, + { + "type": "exert", + "filter": "choose(ally)", + "memorize": "summonedAlly", + "times": 1 } ], "effect":[ - { - "type": "assignFpCharacterToSkirmish", - "player": "fp", - "fpCharacter": "bearer", - "against": "choose(minion)" - }, - { - "type": "modifyStrength", - "filter": "choose(ally,allyInCurrentRegion)", - "amount": 3, - "until": "start(regroup)", - "memorize": "summonedAlly" - }, { "type": "allyCanParticipateInArcheryFireAndSkirmishes", "filter": "memory(summonedAlly)", @@ -83,18 +73,25 @@ "filter": "self", "times": 1 }, - "effect": [ - { - "type": "preventWound", - "filter": "choose(uruk-hai)", - "memorize": "uruk" - }, - { - "type": "addKeyword", - "filter": "memory(uruk)", - "keyword": "fierce" - } - ] + "effect": + { + "type": "preventWound", + "filter": "choose(uruk-hai)" + } + }, + { + "type": "activated", + "phase": "maneuver", + "cost": { + "type": "exert", + "filter": "self", + "times": 1 + }, + "effect": { + "type": "addKeyword", + "filter": "choose(uruk-hai)", + "keyword": "fierce" + } }, ] }, diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java index 220648842..afd4be1de 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java @@ -42,7 +42,7 @@ public class Elrond_LoRErrataTests {{ put("elrond", "51_1040"); put("allyHome3_1", "1_60"); - put("allyHome3_2", "1_27"); + put("allyHome3_2", "1_27"); // tharin put("allyHome6_1", "1_56"); put("allyHome6_2", "1_57"); }} @@ -50,7 +50,7 @@ public class Elrond_LoRErrataTests } @Test - public void FellowshipActionExertsTwiceToDrawACard() throws DecisionResultInvalidException, CardNotFoundException { + public void FellowshipActionExertsTwiceToDrawACardIfNoAllies() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetSimpleDeckScenario(); PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); @@ -73,6 +73,32 @@ public class Elrond_LoRErrataTests assertEquals(0, scn.GetFreepsDeckCount()); } + @Test + public void FellowshipActionExertsOnceToDrawACardIf2Allies() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetHome3AllyScenario(); + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); + scn.FreepsMoveCharToTable("allyHome3_1"); + scn.FreepsMoveCharToTable("allyHome6_1"); + + scn.FreepsMoveCharToTable(elrond); + + scn.StartGame(); + + assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); + assertTrue(scn.FreepsCardActionAvailable(elrond)); + + assertEquals(0, scn.GetWoundsOn(elrond)); + assertEquals(0, scn.GetFreepsHandCount()); + //assertEquals(2, scn.GetFreepsDeckCount()); + + scn.FreepsUseCardAction(elrond); + + assertEquals(1, scn.GetWoundsOn(elrond)); + assertEquals(1, scn.GetFreepsHandCount()); + //assertEquals(1, scn.GetFreepsDeckCount()); + } + @Test public void CardCanPlayIfGandalfInPlay() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup @@ -112,7 +138,7 @@ public class Elrond_LoRErrataTests } @Test - public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException { + public void AllyHealsCappedAt3() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetHome3AllyScenario(); scn.FreepsMoveCharToTable("elrond"); @@ -133,6 +159,6 @@ public class Elrond_LoRErrataTests assertEquals(3, scn.FreepsGetADParamAsList("cardId").size()); assertEquals("0", scn.FreepsGetADParam("min")); - assertEquals("2", scn.FreepsGetADParam("max")); + assertEquals("3", scn.FreepsGetADParam("max")); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java index f76a955cb..844f92fb9 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java @@ -38,11 +38,13 @@ public class Sam_SoHErrataTests assertTrue(scn.FreepsCardActionAvailable(sam)); assertEquals(0, scn.GetWoundsOn(sam)); + assertEquals(0, scn.GetWoundsOn(frodo)); assertEquals(1, scn.GetBurdens()); scn.FreepsUseCardAction(sam); - assertEquals(2, scn.GetWoundsOn(sam)); + assertEquals(1, scn.GetWoundsOn(sam)); + assertEquals(1, scn.GetWoundsOn(frodo)); assertEquals(0, scn.GetBurdens()); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index 1cea03749..1e495e97e 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -76,7 +76,7 @@ public class HornOfBoromirErrataTests } @Test - public void AbilityExertsAndAssignsBoromir() throws DecisionResultInvalidException, CardNotFoundException { + public void AbilityExertsAndBoromirAndAllyToSkirmish() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetFOTRScenario(); @@ -97,52 +97,22 @@ public class HornOfBoromirErrataTests scn.FreepsPlayCard(horn); - scn.SkipToPhase(Phase.ASSIGNMENT); + scn.SkipToPhase(Phase.MANEUVER); assertTrue(scn.FreepsCardActionAvailable(horn)); scn.FreepsUseCardAction(horn); - scn.FreepsChooseCard(runner1); assertEquals(1, scn.GetWoundsOn(boromir)); - assertEquals(11, scn.GetStrength(elrond)); - //Skip shadow player's action + assertEquals(1, scn.GetWoundsOn(elrond)); + //Base version pumps strength, ensure that's not the case here. + assertEquals(8, scn.GetStrength(elrond)); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.SkipCurrentPhaseActions(); - assertFalse(scn.FreepsCardActionAvailable(horn)); - scn.SkipCurrentPhaseActions(); - assertTrue(scn.IsCharAssigned(boromir)); scn.FreepsAssignToMinion(elrond, runner2); assertTrue(scn.IsCharAssigned(elrond)); } - @Test - public void AbilityDoesNotPumpFarAwayAllies() throws DecisionResultInvalidException, CardNotFoundException { - GenericCardTestHelper scn = GetMovieScenario(); - PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); - PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); - PhysicalCardImpl horn = scn.GetFreepsCard("horn"); - PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); - PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); - - scn.FreepsMoveCharToTable(elrond); - scn.FreepsMoveCharToTable(boromir); - scn.FreepsMoveCardToHand(horn); - - scn.ShadowMoveCharToTable(runner1); - scn.ShadowMoveCharToTable(runner2); - - scn.StartGame(); - - scn.FreepsPlayCard(horn); - - scn.SkipToPhase(Phase.ASSIGNMENT); - scn.FreepsUseCardAction(horn); - scn.FreepsChooseCard(runner1); - - assertEquals(1, scn.GetWoundsOn(boromir)); - assertEquals(8, scn.GetStrength(elrond)); - //Skip shadow player's action - scn.SkipCurrentPhaseActions(); - - } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java index f05ec2222..469dbcf27 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java @@ -31,33 +31,26 @@ public class Saruman_KoIErrataTests ); } - @Test - public void SarumanWorks() throws DecisionResultInvalidException, CardNotFoundException { + public void SarumanImmunityAndWoundBlock() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl legolas = scn.GetFreepsCard("legolas"); - PhysicalCardImpl tale = scn.GetFreepsCard("tale"); - PhysicalCardImpl doubleshot = scn.GetFreepsCard("doubleshot"); PhysicalCardImpl saruman = scn.GetShadowCard("saruman"); PhysicalCardImpl uruk1 = scn.GetShadowCard("uruk1"); PhysicalCardImpl uruk2 = scn.GetShadowCard("uruk2"); + scn.FreepsMoveCharToTable(legolas); - scn.FreepsMoveCardToHand(tale); - scn.FreepsMoveCardToHand(doubleshot); scn.ShadowMoveCharToTable(saruman); scn.ShadowMoveCharToTable(uruk1); scn.ShadowMoveCharToTable(uruk2); - scn.StartGame(); - scn.FreepsPlayCard(tale); - scn.SkipToPhase(Phase.ARCHERY); //can't hit saruman @@ -72,33 +65,15 @@ public class Saruman_KoIErrataTests assertEquals(0, scn.GetWoundsOn(uruk1)); assertEquals(1, scn.GetWoundsOn(saruman)); - assertTrue(scn.HasKeyword(uruk1, Keyword.FIERCE)); + //Old version made them fierc, ensure that was removed + assertFalse(scn.HasKeyword(uruk1, Keyword.FIERCE)); //shadow has to skip archery actions scn.ShadowSkipCurrentPhaseAction(); - //Repeat the greenleaf ability to ensure the last can't be blocked by saruman - scn.FreepsUseCardAction(legolas); - scn.FreepsChooseCard(uruk1); - scn.ShadowUseCardAction(saruman); - scn.ShadowSkipCurrentPhaseAction(); - scn.FreepsUseCardAction(legolas); - scn.FreepsChooseCard(uruk1); - scn.ShadowUseCardAction(saruman); - scn.ShadowSkipCurrentPhaseAction(); - - //greenleaf is out of vitality, so play doubleshot - scn.FreepsPlayCard(doubleshot); - scn.ShadowSkipCurrentPhaseAction(); - scn.FreepsSkipCurrentPhaseAction(); - - //Archery wound - scn.ShadowChooseCard(uruk1); - - //Now that we've done 4 total wounds, we should see an exhausted saruman and an uruk1 with 1 wound - assertEquals(1, scn.GetWoundsOn(uruk1)); - assertEquals(3, scn.GetWoundsOn(saruman)); + assertEquals(0, scn.GetWoundsOn(uruk1)); + assertEquals(1, scn.GetWoundsOn(saruman)); scn.SkipToPhase(Phase.ASSIGNMENT); @@ -108,4 +83,32 @@ public class Saruman_KoIErrataTests assertEquals(2, scn.FreepsGetADParamAsList("minions").size()); } + + + @Test + public void SarumanAbilityGrantsFierce() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl saruman = scn.GetShadowCard("saruman"); + PhysicalCardImpl uruk1 = scn.GetShadowCard("uruk1"); + + scn.ShadowMoveCharToTable(saruman); + scn.ShadowMoveCharToTable(uruk1); + + scn.StartGame(); + + scn.SkipToPhase(Phase.MANEUVER); + scn.FreepsSkipCurrentPhaseAction(); + + assertTrue(scn.ShadowCardActionAvailable(saruman)); + + scn.ShadowUseCardAction(saruman); + + assertTrue(scn.HasKeyword(uruk1, Keyword.FIERCE)); + + assertEquals(0, scn.GetWoundsOn(uruk1)); + assertEquals(1, scn.GetWoundsOn(saruman)); + + } } From 4fa28af0abbf9089348f54ea487581de38390663 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 28 Feb 2021 23:57:44 -0600 Subject: [PATCH 45/74] Updated all existing PC errata and tests to use updated id numbers that correspond to being divided by set. --- .../main/web/cards/set51/set01-errata.json | 22 +++++++++---------- .../main/web/cards/set51/set02-errata.json | 4 ++-- .../main/web/cards/set51/set03-errata.json | 8 +++---- .../pc/errata/set1/Elrond_LoRErrataTests.java | 6 ++--- .../errata/set1/Galadriel_LoLErrataTests.java | 4 ++-- .../pc/errata/set1/NoStrangerErrataTests.java | 4 ++-- .../pc/errata/set1/Sam_SoHErrataTests.java | 2 +- .../pc/errata/set1/StingErrataTests.java | 2 +- .../errata/set1/TalentForNBSErrataTests.java | 2 +- .../errata/set2/FlamingBrandErrataTests.java | 4 ++-- .../errata/set2/Gimli_DotMrErrataTests.java | 2 +- .../errata/set3/Aragorn_HttWCErrataTests.java | 2 +- .../errata/set3/BillThePonyErrataTests.java | 2 +- .../errata/set3/HornOfBoromirErrataTests.java | 4 ++-- .../errata/set3/Saruman_KoIErrataTests.java | 2 +- 15 files changed, 35 insertions(+), 35 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index 2a4b25294..e76d3cbb7 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -1,5 +1,5 @@ { - "51_1040": { + "51_40": { "title": "*Elrond", "subtitle": "Lord of Rivendell", "culture": "elven", @@ -48,7 +48,7 @@ } ] }, - "51_1045": { + "51_45": { "title": "*Galadriel", "subtitle": "Lady of Light", "culture": "elven", @@ -86,7 +86,7 @@ } ] }, - "51_1080": { + "51_80": { "title": "*Ottar", "subtitle": "Man of Laketown", "culture": "gandalf", @@ -125,7 +125,7 @@ } }, - "51_10139": { + "51_139": { "title": "Savagery To Match Their Numbers", "culture": "isengard", "cost": 0, @@ -172,7 +172,7 @@ } }, - "51_10195": { + "51_195": { "title": "*Relics of Moria", "culture": "moria", "cost": 1, @@ -193,7 +193,7 @@ } }, - "51_10234": { + "51_234": { "title": "*ÚlairĆ« NertĆ«a", "subtitle": "Messenger of Dol Guldur", "culture": "wraith", @@ -228,7 +228,7 @@ } }, - "51_10248": { + "51_248": { "title": "Forces of Mordor", "culture": "sauron", "cost": 0, @@ -255,7 +255,7 @@ } }, - "51_10311": { + "51_311": { "title": "*Sam", "subtitle": "Son of Hamfast", "culture": "shire", @@ -306,7 +306,7 @@ - "51_10108": { + "51_108": { "title": "No Stranger to the Shadows", "culture": "gondor", "cost": 0, @@ -326,7 +326,7 @@ }, - "51_10313": { + "51_313": { "title": "*Sting", "culture": "shire", "cost": 1, @@ -368,7 +368,7 @@ } }, - "51_10316": { + "51_316": { "title": "*A Talent for Not Being Seen", "culture": "shire", "cost": 0, diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json index 18cc1038d..9635c4397 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json @@ -1,5 +1,5 @@ { - "51_2032": { + "52_32": { "side": "free_people", "cost": 0, "strength": 1, @@ -46,7 +46,7 @@ ] }, - "51_20121": { + "52_121": { "title": "*Gimli", "subtitle": "Dwarf of the Mountain-race", "culture": "dwarven", diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index ad682cb9f..bbeb261a7 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -1,5 +1,5 @@ { - "51_3042": { + "53_42": { "side": "free_people", "cost": 0, "culture": "Gondor", @@ -32,7 +32,7 @@ } }, - "51_3068": { + "53_68": { "side": "shadow", "site": 4, "cost": 4, @@ -96,7 +96,7 @@ ] }, - "51_3038": { + "53_38": { "side": "free_people", "title": "*Aragorn", "subtitle": "Heir to the White City", @@ -166,7 +166,7 @@ }, - "51_30106": { + "53_106": { "title": "*Bill the Pony", "culture": "Shire", "side": "free_people", diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java index afd4be1de..dd66e3362 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java @@ -19,7 +19,7 @@ public class Elrond_LoRErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("elrond", "51_1040"); + put("elrond", "51_40"); put("randomcard", "1_3"); }} ); @@ -29,7 +29,7 @@ public class Elrond_LoRErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("elrond", "51_1040"); + put("elrond", "51_40"); put("gandalf", "1_72"); put("arwen", "1_30"); }} @@ -40,7 +40,7 @@ public class Elrond_LoRErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("elrond", "51_1040"); + put("elrond", "51_40"); put("allyHome3_1", "1_60"); put("allyHome3_2", "1_27"); // tharin put("allyHome6_1", "1_56"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java index c7ce923aa..da0dc2b5c 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java @@ -16,7 +16,7 @@ public class Galadriel_LoLErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("galadriel", "51_1045"); + put("galadriel", "51_45"); put("elrond", "1_40"); }} ); @@ -26,7 +26,7 @@ public class Galadriel_LoLErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("galadriel", "51_1045"); + put("galadriel", "51_45"); put("allyHome3_1", "1_60"); put("allyHome3_2", "1_27"); put("allyHome6_1", "1_56"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java index e521ecbfe..36c3e889b 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java @@ -22,8 +22,8 @@ public class NoStrangerErrataTests put("aragorn", "1_89"); put("arwen", "1_30"); put("boromir", "1_97"); - put("nostranger", "51_10108"); - put("nostranger2", "51_10108"); + put("nostranger", "51_108"); + put("nostranger2", "51_108"); }} ); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java index 844f92fb9..33b53d897 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java @@ -16,7 +16,7 @@ public class Sam_SoHErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("sam", "51_10311"); + put("sam", "51_311"); put("orc", "1_272"); }} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java index e3f145c49..64cc421aa 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java @@ -22,7 +22,7 @@ public class StingErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("sting", "51_10313"); + put("sting", "51_313"); put("sam", "1_311"); put("merry", "1_302"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java index 41aa8643d..97392dbb7 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java @@ -20,7 +20,7 @@ public class TalentForNBSErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("talent", "51_10316"); + put("talent", "51_316"); put("sam", "1_311"); put("gaffer", "1_291"); put("boromir", "1_97"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index 96aff87c0..f8d0a3600 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -19,8 +19,8 @@ public class FlamingBrandErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("brand", "51_2032"); - put("brand2", "51_2032"); + put("brand", "52_32"); + put("brand2", "52_32"); put("arwen", "1_30"); put("boromir", "1_97"); put("aragorn", "1_89"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java index 7a9b3ccf2..86ba56be1 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java @@ -22,7 +22,7 @@ public class Gimli_DotMrErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("gimli", "51_20121"); + put("gimli", "52_121"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java index a57849a37..e2aa08767 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -20,7 +20,7 @@ public class Aragorn_HttWCErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("aragorn", "51_3038"); + put("aragorn", "53_38"); put("gimli", "1_13"); put("minion", "1_268"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java index 022e57d48..f68db8760 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java @@ -25,7 +25,7 @@ public class BillThePonyErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("bill", "51_30106"); + put("bill", "53_106"); put("sam", "1_311"); }} ); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index 1e495e97e..ec7937abb 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -20,7 +20,7 @@ public class HornOfBoromirErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("horn", "51_3042"); + put("horn", "53_42"); put("elrond", "1_40"); put("boromir", "1_97"); put("aragorn", "1_89"); @@ -38,7 +38,7 @@ public class HornOfBoromirErrataTests return new GenericCardTestHelper( new HashMap() {{ - put("horn", "51_3042"); + put("horn", "53_42"); put("elrond", "1_40"); put("boromir", "1_97"); put("aragorn", "1_89"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java index 469dbcf27..5b417aff7 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java @@ -24,7 +24,7 @@ public class Saruman_KoIErrataTests put("tale", "1_66"); put("doubleshot", "1_38"); - put("saruman", "51_3068"); + put("saruman", "53_68"); put("uruk1", "1_151"); put("uruk2", "1_151"); }} From 3c7d87f068d10234a1e88916959e01eac989d260 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 1 Mar 2021 00:01:26 -0600 Subject: [PATCH 46/74] Adding placeholder cards for VPack1. Adding image links for VPack1 and the previously altered erratas. --- .../src/main/web/cards/set101/vpack1.json | 450 ++++++++++++++++++ .../src/main/web/js/gemp-022/PC_Cards.js | 54 ++- 2 files changed, 486 insertions(+), 18 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json new file mode 100644 index 000000000..86c488a59 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json @@ -0,0 +1,450 @@ +{ + "101_1001": { + "side": "free_people", + "culture": "Gondor", + "title": "*The Lords of Gondor Have Returned", + "type": "condition", + "cost": 2, + "keyword": "support area", + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1002": { + "side": "free_people", + "culture": "Gondor", + "title": "*I Will not Let the White City Fall", + "type": "condition", + "cost": 2, + "keyword": "support area", + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1003": { + "side": "free_people", + "culture": "Gondor", + "title": "*Boromir", + "subtitle": "The Redeemed", + "type": "companion", + "cost": 2, + "race": "man", + "strength": 7, + "vitality": 3, + "resistance": 6, + "signet": "aragorn", + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1004": { + "side": "free_people", + "culture": "Gondor", + "title": "*Loud and Clear It Sounds", + "type": "condition", + "cost": 1, + "keyword": "support area", + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1005": { + "side": "free_people", + "culture": "Gondor", + "title": "Remnant of Numenor", + "type": "condition", + "cost": 1, + "keyword": "support area", + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1006": { + "side": "shadow", + "culture": "Sauron", + "title": "*Great Wolf Chief", + "type": "minion", + "cost": 5, + "race": "warg", + "strength": 10, + "vitality": 3, + "site": 6, + "keyword": [ + "tracker", + "fierce" + ], + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1007": { + "side": "shadow", + "culture": "Sauron", + "title": "Hollin Snarler", + "type": "minion", + "cost": 3, + "race": "warg", + "strength": 6, + "vitality": 3, + "site": 6, + "keyword": [ + "tracker", + "fierce" + ], + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1008": { + "side": "shadow", + "culture": "Sauron", + "title": "Hound of Sauron", + "type": "minion", + "cost": 2, + "race": "warg", + "strength": 6, + "vitality": 2, + "site": 6, + "keyword": [ + "tracker", + "fierce" + ], + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1009": { + "side": "shadow", + "culture": "Sauron", + "title": "*The Hunt is Up!", + "type": "condition", + "cost": 1, + "keyword": "support area", + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + "101_1010": { + "side": "shadow", + "culture": "Sauron", + "title": "I See You", + "type": "event", + "cost": 1, + "keyword": "assignment", + "effects": [ + { + "type": "activated", + "phase": "skirmish", + "condition": { + "type": "canSpot", + "filter": "bearer,inSkirmishAgainst(Nazgul)", + }, + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect":[ + { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 3 + }, + { + "type": "addKeyword", + "filter": "memory(bearer)", + "keyword": "damage+1" + } + ] + }, + ] + }, + + + +} \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index 56c87a372..cfc70eff0 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -1,4 +1,6 @@ var PCCards = { + + //fotr supplements '101_1': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_1.jpg', '101_2': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_2.jpg', '101_3': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_3.jpg', @@ -46,22 +48,38 @@ var PCCards = { '101_45': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_45.jpg', '101_46': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_46.jpg', '101_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_47.jpg', - '51_1040': 'https://i.lotrtcgpc.net/errata/FOTR/51_40.jpg', - '51_1045': 'https://i.lotrtcgpc.net/errata/FOTR/51_45.jpg', - '51_1080': 'https://i.lotrtcgpc.net/errata/FOTR/51_80.jpg', - '51_10108': 'https://i.lotrtcgpc.net/errata/FOTR/51_108.jpg', - '51_10139': 'https://i.lotrtcgpc.net/errata/FOTR/51_139.jpg', - '51_10195': 'https://i.lotrtcgpc.net/errata/FOTR/51_195.jpg', - '51_10234': 'https://i.lotrtcgpc.net/errata/FOTR/51_234.jpg', - '51_10248': 'https://i.lotrtcgpc.net/errata/FOTR/51_248.jpg', - '51_10311': 'https://i.lotrtcgpc.net/errata/FOTR/51_311.jpg', - '51_10313': 'https://i.lotrtcgpc.net/errata/FOTR/51_313.jpg', - '51_10316': 'https://i.lotrtcgpc.net/errata/FOTR/51_316.jpg', - '51_2032': 'https://i.lotrtcgpc.net/errata/FOTR/52_32.jpg', - '51_2075': 'https://i.lotrtcgpc.net/errata/FOTR/52_75.jpg', - '51_3042': 'https://i.lotrtcgpc.net/errata/FOTR/53_42.jpg', - '51_3068': 'https://i.lotrtcgpc.net/errata/FOTR/53_68.jpg', - '51_20121': 'https://i.lotrtcgpc.net/errata/FOTR/52_121.jpg', - '51_3038': 'https://i.lotrtcgpc.net/errata/FOTR/53_38.jpg', - '51_30106': 'https://i.lotrtcgpc.net/errata/FOTR/53_106.jpg' + + // April 2021 Errata Batch + '51_40': 'https://i.lotrtcgpc.net/errata/FOTR/51_40.jpg', + '51_311': 'https://i.lotrtcgpc.net/errata/FOTR/51_311.jpg', + '52_32': 'https://i.lotrtcgpc.net/errata/FOTR/52_32.jpg', + '53_42': 'https://i.lotrtcgpc.net/errata/FOTR/53_42.jpg', + '53_68': 'https://i.lotrtcgpc.net/errata/FOTR/53_68.jpg', + + // May 2021 VPack1 + '101_1001': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_001.jpg', + '101_1002': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_002.jpg', + '101_1003': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_003.jpg', + '101_1004': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_004.jpg', + '101_1005': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_005.jpg', + '101_1006': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_006.jpg', + '101_1007': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_007.jpg', + '101_1008': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_008.jpg', + '101_1009': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_009.jpg', + '101_1010': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_010.jpg', + + // Future Errata + '51_45': 'https://i.lotrtcgpc.net/errata/FOTR/51_45.jpg', + '51_80': 'https://i.lotrtcgpc.net/errata/FOTR/51_80.jpg', + '51_108': 'https://i.lotrtcgpc.net/errata/FOTR/51_108.jpg', + '51_139': 'https://i.lotrtcgpc.net/errata/FOTR/51_139.jpg', + '51_195': 'https://i.lotrtcgpc.net/errata/FOTR/51_195.jpg', + '51_234': 'https://i.lotrtcgpc.net/errata/FOTR/51_234.jpg', + '51_248': 'https://i.lotrtcgpc.net/errata/FOTR/51_248.jpg', + '51_313': 'https://i.lotrtcgpc.net/errata/FOTR/51_313.jpg', + '51_316': 'https://i.lotrtcgpc.net/errata/FOTR/51_316.jpg', + '52_75': 'https://i.lotrtcgpc.net/errata/FOTR/52_75.jpg', + '52_121': 'https://i.lotrtcgpc.net/errata/FOTR/52_121.jpg', + '53_38': 'https://i.lotrtcgpc.net/errata/FOTR/53_38.jpg', + '53_106': 'https://i.lotrtcgpc.net/errata/FOTR/53_106.jpg', } \ No newline at end of file From a91bc6091f28a34b4f72c7fffa3b0ab4bf4743b1 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Mon, 1 Mar 2021 12:51:01 -0600 Subject: [PATCH 47/74] Adding PC formats to the hard-coded site path filtering for presentation in the deck builder --- .../main/java/com/gempukku/lotro/game/SortAndFilterCards.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java index 0f203201d..6a0d33d9d 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/SortAndFilterCards.java @@ -170,7 +170,7 @@ public class SortAndFilterCards { final LotroCardBlueprint blueprint = cardBlueprint.get(blueprintId); if (blueprint.getCardType() == CardType.SITE) { if (blueprint.getSiteBlock() == SitesBlock.FELLOWSHIP) { - if ("fotr_block".contains(set)) { + if ("fotr_block,pc_fotr_block".contains(set)) { return true; } return false; @@ -182,7 +182,7 @@ public class SortAndFilterCards { return false; } if (blueprint.getSiteBlock() == SitesBlock.KING) { - if ("king_block,rotk_sta,movie".contains(set)) { + if ("king_block,rotk_sta,movie,pc_movie_block".contains(set)) { return true; } return false; From 720c5acfc4250df0080f094f3cb284e933e30dcd Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 2 Mar 2021 00:27:05 -0600 Subject: [PATCH 48/74] Updated all PC errata card images to use 000 padded image URLs --- .../src/main/web/js/gemp-022/PC_Cards.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index cfc70eff0..5e2d2fadd 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -50,11 +50,11 @@ var PCCards = { '101_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_47.jpg', // April 2021 Errata Batch - '51_40': 'https://i.lotrtcgpc.net/errata/FOTR/51_40.jpg', + '51_40': 'https://i.lotrtcgpc.net/errata/FOTR/51_040.jpg', '51_311': 'https://i.lotrtcgpc.net/errata/FOTR/51_311.jpg', - '52_32': 'https://i.lotrtcgpc.net/errata/FOTR/52_32.jpg', - '53_42': 'https://i.lotrtcgpc.net/errata/FOTR/53_42.jpg', - '53_68': 'https://i.lotrtcgpc.net/errata/FOTR/53_68.jpg', + '52_32': 'https://i.lotrtcgpc.net/errata/FOTR/52_032.jpg', + '53_42': 'https://i.lotrtcgpc.net/errata/FOTR/53_042.jpg', + '53_68': 'https://i.lotrtcgpc.net/errata/FOTR/53_068.jpg', // May 2021 VPack1 '101_1001': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_001.jpg', @@ -69,8 +69,8 @@ var PCCards = { '101_1010': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_010.jpg', // Future Errata - '51_45': 'https://i.lotrtcgpc.net/errata/FOTR/51_45.jpg', - '51_80': 'https://i.lotrtcgpc.net/errata/FOTR/51_80.jpg', + '51_45': 'https://i.lotrtcgpc.net/errata/FOTR/51_045.jpg', + '51_80': 'https://i.lotrtcgpc.net/errata/FOTR/51_080.jpg', '51_108': 'https://i.lotrtcgpc.net/errata/FOTR/51_108.jpg', '51_139': 'https://i.lotrtcgpc.net/errata/FOTR/51_139.jpg', '51_195': 'https://i.lotrtcgpc.net/errata/FOTR/51_195.jpg', @@ -78,8 +78,8 @@ var PCCards = { '51_248': 'https://i.lotrtcgpc.net/errata/FOTR/51_248.jpg', '51_313': 'https://i.lotrtcgpc.net/errata/FOTR/51_313.jpg', '51_316': 'https://i.lotrtcgpc.net/errata/FOTR/51_316.jpg', - '52_75': 'https://i.lotrtcgpc.net/errata/FOTR/52_75.jpg', + '52_75': 'https://i.lotrtcgpc.net/errata/FOTR/52_075.jpg', '52_121': 'https://i.lotrtcgpc.net/errata/FOTR/52_121.jpg', - '53_38': 'https://i.lotrtcgpc.net/errata/FOTR/53_38.jpg', + '53_38': 'https://i.lotrtcgpc.net/errata/FOTR/53_038.jpg', '53_106': 'https://i.lotrtcgpc.net/errata/FOTR/53_106.jpg', } \ No newline at end of file From 8712e43c1c139f845ee39d46a4824ad8203d0f2e Mon Sep 17 00:00:00 2001 From: Christian McCarty Date: Thu, 4 Mar 2021 15:25:22 -0600 Subject: [PATCH 49/74] Fixed PC formats not having sets 52 and 53. --- .../gemp-lotr-server/src/main/resources/lotrFormats.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json index 4cc1c19c3..d5cea19aa 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json @@ -18,7 +18,7 @@ "code":"pc_fotr_block", "sites":"FELLOWSHIP", "cancelRingBearerSkirmish":true, - "set":[1, 2, 3, 51, 101], + "set":[1, 2, 3, 51, 52, 53, 101], "banned":["1_40","1_311","2_32","3_42","3_68",] }, { @@ -186,7 +186,7 @@ "name":"PC-Movie", "code":"pc_movie", "sites":"KING", - "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 51, 101], + "set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 51, 52, 53, 101], "banned":["1_40","1_311","2_32","3_42","3_68", "1_45", "1_80", "1_108", "1_139", "1_195", "1_234", "1_248", "1_313", "3_106", "3_108", "3_38", "3_67", "7_49", "7_96", "8_1", "10_2", "10_91"], }, { @@ -274,7 +274,7 @@ "sites":"SHADOWS", "banned":["1_40","1_311","2_32","3_42","3_68","1_45", "1_138", "1_234", "1_313", "1_316", "2_121", "3_17", "3_38", "3_67", "3_108", "3_113", "4_73", "7_49", "8_1", "10_2", "10_11", "10_91", "11_31", "11_100", "11_132"], "restricted":["1_80", "1_108", "1_139", "1_195", "1_248", "2_75", "3_106", "4_276", "4_304"], - "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 101] + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 52, 53, 101] }, { "name":"War of the Ring block - Set 11", From 815ee8e65a3408863d64ccd5af09f00c36122555 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Thu, 4 Mar 2021 23:47:13 -0600 Subject: [PATCH 50/74] Fixed Debug format not having the set 52/53 errata. --- gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json index d5cea19aa..f0344323a 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json +++ b/gemp-lotr/gemp-lotr-server/src/main/resources/lotrFormats.json @@ -4,7 +4,7 @@ "code":"debug_hall", "sites": "SPECIAL", "maximumSameName":100, - "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 101] + "set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 51, 52, 53, 101] }, { "name":"Fellowship block", From 19cab722c493542dd93c84f893e73d144132b0b4 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 6 Mar 2021 19:50:16 -0600 Subject: [PATCH 51/74] Errata Pack 1 and most of Errata Pack 2 complete --- .../main/web/cards/set51/set01-errata.json | 76 ++++++++---------- .../main/web/cards/set51/set02-errata.json | 40 ++-------- .../main/web/cards/set51/set03-errata.json | 62 ++------------- .../errata/set1/Galadriel_LoLErrataTests.java | 13 ++-- .../pc/errata/set1/NoStrangerErrataTests.java | 36 ++------- .../pc/errata/set1/StingErrataTests.java | 77 +++++-------------- .../errata/set1/TalentForNBSErrataTests.java | 62 ++++++--------- .../errata/set2/FlamingBrandErrataTests.java | 3 + .../errata/set3/HornOfBoromirErrataTests.java | 14 ++-- .../errata/set3/Saruman_KoIErrataTests.java | 2 +- 10 files changed, 115 insertions(+), 270 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index e76d3cbb7..d033d0ad6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -66,7 +66,7 @@ }, "effect": { "type": "heal", - "filter": "choose(ally,allyHome(fellowship,6))", + "filter": "choose(another,ally,allyHome(fellowship,6))", "count": "0-2" } }, @@ -76,12 +76,12 @@ "cost": { "type": "exert", "filter": "self", - "times": 2 + "times": 1 }, "effect": { "type": "play", "filter": "choose(elf)", - "cost": -2 + "cost": -1 } } ] @@ -307,7 +307,7 @@ "51_108": { - "title": "No Stranger to the Shadows", + "title": "*No Stranger to the Shadows", "culture": "gondor", "cost": 0, "type": "condition", @@ -318,9 +318,9 @@ "effects": { "type": "modifier", "modifier": { - "type": "addKeyword", - "filter": "bearer", - "keyword": "concealed" + "type": "modifyCost", + "filter": "site", + "amount": -1 } } }, @@ -350,18 +350,19 @@ "hand": "shadowPlayer", "forced": true, "memorize": "revealedCards", - "count":3 + "count":2 }, { - "type": "addKeyword", - "filter": "choose(companion,not(concealed))", - "keyword": "concealed", - "until": "start(regroup)", + "type": "removeTwilight", "amount": { - "type": "forEachMatchingInMemory", - "memory": "revealedCards", - "filter": "orc", - "limit": 1 + "type": "cardPhaseLimit", + "limit": 2, + "amount": { + "type": "forEachMatchingInMemory", + "memory": "revealedCards", + "filter": "orc", + "limit": 2 + } } } ] @@ -373,37 +374,26 @@ "culture": "shire", "cost": 0, "type": "condition", + "target": "or(name(Merry),name(Pippin))", "keyword": [ - "stealth", - "support area" + "stealth" ], - "effects": [ - { - "type": "extraCost", - "cost": { - "type": "exert", - "filter": "choose(hobbit)" - } - }, - { - "type": "trigger", - "trigger": { - "type": "moves" - }, - "condition": { - "type": "canSpot", - "count": 2, - "filter": "hobbit,companion" - }, - "effect": { - "type": "addKeyword", - "filter": "choose(hobbit,companion)", - "keyword": "concealed", - "until": "start(regroup)" + "effects": { + "type": "modifier", + "modifier": { + "type": "modifyCost", + "filter": "site", + "amount": { + "type": "condition", + "condition": { + "type": "cantSpot", + "filter": "companion,not(hobbit)" + }, + "true": -1, + "false": 0 } } - - ] + } }, diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json index 9635c4397..77d0acf94 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json @@ -58,40 +58,14 @@ "resistance": 6, "signet": "frodo", "keyword": "damage+1", - "effects": [ - { - "type": "modifier", - - "modifier": { - "type": "addKeyword", - "filter": "self", - "keyword": "concealed", - "condition": { - "type": "location", - "filter": "underground" - } - }, - }, - { - "type": "trigger", - "optional": true, - "trigger": { - "type": "movesTo", - "filter": "underground", - - }, - "cost": { - "type": "exert", - "filter": "self" - }, - "effect": { - "type": "addKeyword", - "filter": "choose(another,companion)", - "keyword": "concealed", - "until": "start(regroup)" - } + "effects": { + "type": "modifier", + "modifier": { + "type": "modifyCost", + "filter": "underground,site", + "amount": -1 } - ] + } }, diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index bbeb261a7..1f2c4cbfa 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -113,7 +113,7 @@ ], "effects": { "type": "trigger", - "optional": true, + "optional": false, "trigger": { "type": "movesfrom" }, @@ -122,46 +122,9 @@ "phase": "fellowship" }, "effect": { - "type": "preventable", - "effect": [ - { - "type": "addKeyword", - "filter": "choose(another,companion)", - "keyword": "concealed", - "until": "start(regroup)" - }, - { - "type": "addKeyword", - "filter": "self", - "keyword": "concealed", - "until": "start(regroup)" - }, - ], - "text": "Would you like to discard a minion (or reveal a tracker) from hand to prevent a companion becoming concealed?", - "player": "shadowPlayer", - "cost": { - "type": "choice", - "player": "shadowPlayer", - "texts": [ - "Discard a minion from hand", - "Reveal a tracker from hand" - ], - "effects": [ - { - "type": "revealCardsFromHand", - "filter": "choose(tracker)", - "hand": "shadowPlayer" - }, - { - "type": "discardFromHand", - "filter": "choose(minion)", - "forced": false, - "hand": "shadowPlayer", - } - ] - } - - }, + "type": "removeTwilight", + "amount": 1 + } } }, @@ -175,23 +138,12 @@ "possession": "Pony", "target": "name(Sam)", "effects": [ - { - "type": "trigger", - "trigger": { - "type": "played", - "filter": "self" - }, - "effect": { - "type": "heal", - "filter": "bearer" - } - }, { "type": "modifier", "modifier": { - "type": "addKeyword", - "filter": "bearer", - "keyword": "concealed" + "type": "modifyCost", + "filter": "site", + "amount": -1 } }, { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java index da0dc2b5c..872c12514 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java @@ -28,15 +28,15 @@ public class Galadriel_LoLErrataTests {{ put("galadriel", "51_45"); put("allyHome3_1", "1_60"); - put("allyHome3_2", "1_27"); put("allyHome6_1", "1_56"); put("allyHome6_2", "1_57"); + put("allyHome6_3", "1_34"); }} ); } @Test - public void FellowshipActionExertsTwiceToDiscountAnElf() throws DecisionResultInvalidException, CardNotFoundException { + public void FellowshipActionExertsToDiscountAnElf() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetSimplePlayScenario(); @@ -55,9 +55,9 @@ public class Galadriel_LoLErrataTests scn.FreepsUseCardAction(galadriel); - assertEquals(2, scn.GetWoundsOn(galadriel)); + assertEquals(1, scn.GetWoundsOn(galadriel)); assertEquals(0, scn.GetFreepsHandCount()); - assertEquals(2, scn.GetTwilight()); + assertEquals(3, scn.GetTwilight()); } @@ -67,20 +67,21 @@ public class Galadriel_LoLErrataTests GenericCardTestHelper scn = GetHome6AllyScenario(); scn.FreepsMoveCharToTable("galadriel"); scn.FreepsMoveCharToTable("allyHome3_1"); - scn.FreepsMoveCharToTable("allyHome3_2"); scn.FreepsMoveCharToTable("allyHome6_1"); scn.FreepsMoveCharToTable("allyHome6_2"); + scn.FreepsMoveCharToTable("allyHome6_3"); scn.FreepsAddWoundsToChar("galadriel", 1); scn.FreepsAddWoundsToChar("allyHome3_1", 1); - scn.FreepsAddWoundsToChar("allyHome3_2", 1); scn.FreepsAddWoundsToChar("allyHome6_1", 1); scn.FreepsAddWoundsToChar("allyHome6_2", 1); + scn.FreepsAddWoundsToChar("allyHome6_3", 1); scn.StartGame(); assertEquals(Phase.BETWEEN_TURNS, scn.GetCurrentPhase()); + //There are 5 total elf allies in play: 1 is home 3, and 1 is Galadriel herself. The rest should be eligible. assertEquals(3, scn.FreepsGetADParamAsList("cardId").size()); assertEquals("0", scn.FreepsGetADParam("min")); assertEquals("2", scn.FreepsGetADParam("max")); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java index 36c3e889b..874951fce 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java @@ -2,6 +2,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set1; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -30,13 +31,14 @@ public class NoStrangerErrataTests @Test - public void NoStrangerHasStealth() throws DecisionResultInvalidException, CardNotFoundException { + public void NoStrangerIsUniqueAndHasStealth() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); assertTrue(scn.HasKeyword(nostranger, Keyword.STEALTH)); + assertTrue(nostranger.getBlueprint().isUnique()); } @Test @@ -64,34 +66,9 @@ public class NoStrangerErrataTests assertEquals(2, scn.FreepsGetADParamAsList("cardId").size()); } - @Test - public void NoStrangerLimitOnePerBearer() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetScenario(); - - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); - PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); - PhysicalCardImpl nostranger2 = scn.GetFreepsCard("nostranger2"); - - scn.FreepsMoveCharToTable(aragorn); - scn.FreepsMoveCharToTable(arwen); - scn.FreepsMoveCardToHand(nostranger); - scn.FreepsMoveCardToHand(nostranger2); - - scn.StartGame(); - - scn.FreepsPlayCard(nostranger); - scn.FreepsChooseCard(aragorn); - scn.FreepsPlayCard(nostranger2); - - //No prompt means it was placed automatically on Arwen, with no choice between Arwen and Aragorn - assertFalse(scn.FreepsAnyActionsAvailable()); - - } @Test - public void NoStrangerAddsConcealed() throws DecisionResultInvalidException, CardNotFoundException { + public void NoStrangerReducesTwilight() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); @@ -105,6 +82,9 @@ public class NoStrangerErrataTests scn.FreepsPlayCard(nostranger); - scn.HasKeyword(aragorn, Keyword.CONCEALED); + scn.FreepsSkipCurrentPhaseAction(); + + // 2 for Frodo/Aragorn, 1 for the site, -1 for No Stranger + assertEquals(2, scn.GetTwilight()); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java index 64cc421aa..7a14a7d04 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java @@ -78,7 +78,7 @@ public class StingErrataTests } @Test - public void StingAbilityExertsFrodoAndRevealsThreeCards() throws DecisionResultInvalidException, CardNotFoundException { + public void StingAbilityExertsFrodoAndRevealsTwoCards() throws DecisionResultInvalidException, CardNotFoundException { GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); @@ -97,13 +97,13 @@ public class StingErrataTests scn.FreepsUseCardAction(sting); - //Reveals 3 cards - assertEquals(3, scn.FreepsGetADParamAsList("blueprintId").size()); + //Reveals 2 cards + assertEquals(2, scn.FreepsGetADParamAsList("blueprintId").size()); assertEquals(1, scn.GetWoundsOn(frodo)); } @Test - public void StingAbilityMakesConcealedIfOrcRevealed() throws DecisionResultInvalidException, CardNotFoundException { + public void StingAbilityRemovesTwilight() throws DecisionResultInvalidException, CardNotFoundException { GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); @@ -120,63 +120,28 @@ public class StingErrataTests scn.StartGame(); - scn.FreepsUseCardAction(sting); - - //Both players have revealed cards as an action to dismiss - scn.SkipCurrentPhaseActions(); - - assertTrue(scn.FreepsCanChooseCharacter(frodo)); - assertTrue(scn.FreepsCanChooseCharacter(sam)); - assertTrue(scn.FreepsCanChooseCharacter(merry)); - - scn.FreepsChooseCard(frodo); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + scn.SetTwilight(10); scn.FreepsUseCardAction(sting); - scn.SkipCurrentPhaseActions(); - assertFalse(scn.FreepsCanChooseCharacter(frodo)); - assertTrue(scn.FreepsCanChooseCharacter(sam)); - assertTrue(scn.FreepsCanChooseCharacter(merry)); - - scn.FreepsChooseCard(sam); - assertTrue(scn.HasKeyword(sam, Keyword.CONCEALED)); - } - - - @Test - public void StingConcealedLastsUntilNextRegroup() throws DecisionResultInvalidException, CardNotFoundException { - GenericCardTestHelper scn = GetScenario(); - - PhysicalCardImpl frodo = scn.GetRingBearer(); - PhysicalCardImpl sting = scn.GetFreepsCard("sting"); - PhysicalCardImpl sam = scn.GetFreepsCard("sam"); - - PhysicalCardImpl orc1 = scn.GetShadowCard("orc1"); - - scn.FreepsMoveCharToTable(sam); - scn.AttachCard(sting, frodo); - - scn.ShadowMoveCardToHand(orc1); - - scn.StartGame(); - - scn.SkipToPhase(Phase.REGROUP); - - scn.FreepsUseCardAction(sting); - scn.FreepsChooseCard(frodo); - //Both players have revealed cards as an action to dismiss - scn.SkipCurrentPhaseActions(); - - scn.FreepsChooseCard(frodo); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); - - scn.ShadowSkipCurrentPhaseAction(); + //Both players need to dismiss the card reveal dialog. scn.FreepsSkipCurrentPhaseAction(); - //shadow reconcile scn.ShadowSkipCurrentPhaseAction(); - scn.FreepsChooseToMove(); + // 10 twilight - 1 orc in the hand = 9 twilight + assertEquals(9, scn.GetTwilight()); + + scn.FreepsUseCardAction(sting); + scn.FreepsSkipCurrentPhaseAction(); + scn.ShadowSkipCurrentPhaseAction(); + // 9 twilight - 1 orc in the hand = 8 twilight + assertEquals(8, scn.GetTwilight()); + + scn.FreepsUseCardAction(sting); + scn.FreepsSkipCurrentPhaseAction(); + scn.ShadowSkipCurrentPhaseAction(); + // limit of 2 should have been hit, so no twilight should be removed + assertEquals(8, scn.GetTwilight()); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); } + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java index 97392dbb7..5a9702568 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java @@ -3,9 +3,11 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set1; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import junit.framework.Assert; import org.junit.Test; import java.util.HashMap; @@ -22,7 +24,8 @@ public class TalentForNBSErrataTests {{ put("talent", "51_316"); put("sam", "1_311"); - put("gaffer", "1_291"); + put("merry", "1_302"); + put("pippin", "1_307"); put("boromir", "1_97"); }} ); @@ -38,92 +41,73 @@ public class TalentForNBSErrataTests assertTrue(scn.HasKeyword(talent, Keyword.STEALTH)); } - @Test - public void TalentExertsAHobbitOnPlay() throws DecisionResultInvalidException, CardNotFoundException { + public void TalentOnlyPlaysOnMerryOrPippin() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); - PhysicalCardImpl gaffer = scn.GetFreepsCard("gaffer"); - PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl merry = scn.GetFreepsCard("merry"); + PhysicalCardImpl pippin = scn.GetFreepsCard("pippin"); PhysicalCardImpl talent = scn.GetFreepsCard("talent"); - scn.FreepsMoveCharToTable(sam, gaffer, boromir); + scn.FreepsMoveCharToTable(sam); + scn.FreepsMoveCharToTable(merry); + scn.FreepsMoveCharToTable(pippin); scn.FreepsMoveCardToHand(talent); scn.StartGame(); scn.FreepsPlayCard(talent); - //Frodo, Sam, Gaffer, but not Boromir - assertEquals(3, scn.FreepsCardChoiceCount()); - scn.FreepsChooseCard(frodo); - assertEquals(1, scn.GetWoundsOn(frodo)); + //There are 4 companions in play, but only 2 valid targets + assertEquals(2, scn.FreepsGetADParamAsList("cardId").size()); } + @Test - public void TalentAbilityTriggersConcealedOnMove() throws DecisionResultInvalidException, CardNotFoundException { + public void TalentReducesTwilightIfOnlyHobbits() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); - PhysicalCardImpl sam = scn.GetFreepsCard("sam"); - PhysicalCardImpl gaffer = scn.GetFreepsCard("gaffer"); - PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl merry = scn.GetFreepsCard("merry"); PhysicalCardImpl talent = scn.GetFreepsCard("talent"); - scn.FreepsMoveCharToTable(sam, gaffer, boromir); + scn.FreepsMoveCharToTable(merry); scn.FreepsMoveCardToHand(talent); scn.StartGame(); scn.FreepsPlayCard(talent); - scn.FreepsChooseCard(frodo); scn.FreepsSkipCurrentPhaseAction(); - //Sam and Frodo, but not Gaffer or Boromir - assertEquals(2, scn.FreepsCardChoiceCount()); - scn.FreepsChooseCard(frodo); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); - - scn.SkipToPhase(Phase.REGROUP); - scn.SkipCurrentPhaseActions(); - - scn.FreepsChooseToMove(); - //Sam and Frodo, but not Gaffer or Boromir - assertEquals(2, scn.FreepsCardChoiceCount()); - scn.FreepsChooseCard(sam); - assertEquals(Phase.SHADOW, scn.GetCurrentPhase()); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); - assertTrue(scn.HasKeyword(sam, Keyword.CONCEALED)); + // 2 for Frodo/Merry, 1 for the site, -1 for Talent + assertEquals(2, scn.GetTwilight()); } @Test - public void TalentOnlyTriggersWithTwoHobbitCompanions() throws DecisionResultInvalidException, CardNotFoundException { + public void TalentDoesNotReduceIfNonHobbitCompanions() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); - PhysicalCardImpl sam = scn.GetFreepsCard("sam"); - PhysicalCardImpl gaffer = scn.GetFreepsCard("gaffer"); + PhysicalCardImpl merry = scn.GetFreepsCard("merry"); PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); PhysicalCardImpl talent = scn.GetFreepsCard("talent"); - scn.FreepsMoveCharToTable(gaffer, boromir); + scn.FreepsMoveCharToTable(merry, boromir); scn.FreepsMoveCardToHand(talent); scn.StartGame(); scn.FreepsPlayCard(talent); - scn.FreepsChooseCard(frodo); scn.FreepsSkipCurrentPhaseAction(); - //neither gaffer nor boromir should permit the move trigger to choose a companion - assertEquals(Phase.SHADOW, scn.GetCurrentPhase()); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + // 3 for Frodo/Merry/Boromir, 1 for the site, Talent does not trigger + assertEquals(4, scn.GetTwilight()); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index f8d0a3600..4ca5653bc 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -129,5 +129,8 @@ public class FlamingBrandErrataTests scn.FreepsUseCardAction(brand); assertEquals(11, scn.GetStrength(aragorn)); assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + + //Brand is discarded + assertFalse(scn.IsAttachedTo(brand, aragorn)); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index ec7937abb..424c0132b 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -26,7 +26,6 @@ public class HornOfBoromirErrataTests put("aragorn", "1_89"); put("runner1", "1_178"); - put("runner2", "1_178"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, @@ -44,7 +43,6 @@ public class HornOfBoromirErrataTests put("aragorn", "1_89"); put("runner1", "1_178"); - put("runner2", "1_178"); }} ); } @@ -76,7 +74,7 @@ public class HornOfBoromirErrataTests } @Test - public void AbilityExertsAndBoromirAndAllyToSkirmish() throws DecisionResultInvalidException, CardNotFoundException { + public void AbilityExertsAndDiscardsToPermitAllyToSkirmish() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetFOTRScenario(); @@ -84,14 +82,12 @@ public class HornOfBoromirErrataTests PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); PhysicalCardImpl horn = scn.GetFreepsCard("horn"); PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); - PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); scn.FreepsMoveCharToTable(elrond); scn.FreepsMoveCharToTable(boromir); scn.FreepsMoveCardToHand(horn); scn.ShadowMoveCharToTable(runner1); - scn.ShadowMoveCharToTable(runner2); scn.StartGame(); @@ -101,16 +97,16 @@ public class HornOfBoromirErrataTests assertTrue(scn.FreepsCardActionAvailable(horn)); scn.FreepsUseCardAction(horn); + //discards + assertFalse(scn.IsAttachedTo(horn, boromir)); assertEquals(1, scn.GetWoundsOn(boromir)); - assertEquals(1, scn.GetWoundsOn(elrond)); - //Base version pumps strength, ensure that's not the case here. - assertEquals(8, scn.GetStrength(elrond)); + assertEquals(11, scn.GetStrength(elrond)); scn.SkipToPhase(Phase.ASSIGNMENT); scn.SkipCurrentPhaseActions(); - scn.FreepsAssignToMinion(elrond, runner2); + scn.FreepsAssignToMinion(elrond, runner1); assertTrue(scn.IsCharAssigned(elrond)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java index 5b417aff7..3e8f2272b 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java @@ -65,7 +65,7 @@ public class Saruman_KoIErrataTests assertEquals(0, scn.GetWoundsOn(uruk1)); assertEquals(1, scn.GetWoundsOn(saruman)); - //Old version made them fierc, ensure that was removed + //Old version made them fierce, ensure that was removed assertFalse(scn.HasKeyword(uruk1, Keyword.FIERCE)); //shadow has to skip archery actions From e5aac728221868177487cd335d01bc513bf9a1bb Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 7 Mar 2021 01:08:40 -0600 Subject: [PATCH 52/74] Completing unit tests for the last cards of Errata Pack 2 --- .../errata/set2/Gimli_DotMrErrataTests.java | 36 ++--- .../errata/set3/Aragorn_HttWCErrataTests.java | 124 +++--------------- .../errata/set3/BillThePonyErrataTests.java | 50 +------ 3 files changed, 29 insertions(+), 181 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java index 86ba56be1..f97bf32ac 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java @@ -23,10 +23,7 @@ public class Gimli_DotMrErrataTests new HashMap() {{ put("gimli", "52_121"); - }}, - GenericCardTestHelper.FellowshipSites, - GenericCardTestHelper.FOTRFrodo, - GenericCardTestHelper.FOTRRing + }} ); } @@ -42,7 +39,7 @@ public class Gimli_DotMrErrataTests @Test - public void GimliHasConcealedOnlyWhileUnderground() throws DecisionResultInvalidException, CardNotFoundException { + public void GimliRemovesTwilightWhenUnderground() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); @@ -51,46 +48,29 @@ public class Gimli_DotMrErrataTests scn.StartGame(); - assertFalse(scn.HasKeyword(gimli, Keyword.CONCEALED)); - scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND)); scn.FreepsSkipCurrentPhaseAction(); - assertTrue(scn.HasKeyword(gimli, Keyword.CONCEALED)); + // 2 for Frodo/Gimli, 1 for the site, -1 for Gimli's text + assertEquals(2, scn.GetTwilight()); } @Test - public void GimliAbilityTriggersMovingToUnderground() throws DecisionResultInvalidException, CardNotFoundException { + public void GimliDoesNotRemoveTwilightWhenNotUnderground() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); - PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); - scn.FreepsMoveCharToTable(gimli); scn.StartGame(); - scn.InsertAdHocModifier(new KeywordModifier(null, Filters.siteNumber(2), Keyword.UNDERGROUND)); - scn.FreepsSkipCurrentPhaseAction(); - assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsAcceptOptionalTrigger(); - assertEquals(1, scn.GetWoundsOn(gimli)); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); - - scn.SkipToPhase(Phase.REGROUP); - scn.SkipCurrentPhaseActions(); - scn.ShadowSkipCurrentPhaseAction(); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); - scn.FreepsChooseToMove(); - - assertFalse(scn.FreepsActionAvailable("Optional")); - //scn.FreepsAcceptOptionalTrigger(); - assertEquals(1, scn.GetWoundsOn(gimli)); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + // 2 for Frodo/Gimli, 1 for the site + assertEquals(3, scn.GetTwilight()); } + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java index e2aa08767..83c4c129a 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -37,7 +37,6 @@ public class Aragorn_HttWCErrataTests PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); assertTrue(scn.HasKeyword(aragorn, Keyword.RANGER)); - assertFalse(scn.HasKeyword(aragorn, Keyword.CONCEALED)); } @@ -48,139 +47,46 @@ public class Aragorn_HttWCErrataTests PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); - scn.FreepsMoveCharToTable(aragorn, gimli); + scn.FreepsMoveCharToTable(aragorn); scn.StartGame(); + scn.SetTwilight(2); + scn.FreepsSkipCurrentPhaseAction(); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); - assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsAcceptOptionalTrigger(); - scn.FreepsChooseCard(frodo); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); + // 2 for Frodo/Aragorn, 1 for the site, 2 in the pool, -1 for Aragorn's text + assertEquals(4, scn.GetTwilight()); + scn.SkipToPhase(Phase.REGROUP); scn.SkipCurrentPhaseActions(); scn.ShadowSkipCurrentPhaseAction(); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + assertEquals(4, scn.GetTwilight()); scn.FreepsChooseToMove(); - assertFalse(scn.FreepsActionAvailable("Optional")); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + // 2 for Frodo/Aragorn, 1 for the site, 4 in the pool, no removal from Aragorn + assertEquals(7, scn.GetTwilight()); } @Test - public void AragornAbilityTriggersBeforeConcealedTwilightIsRemoved() throws DecisionResultInvalidException, CardNotFoundException { + public void AragornAbilityOnlyWorksIfTwilightInPool() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); - scn.FreepsMoveCardToHand(aragorn, gimli); - - scn.StartGame(); - scn.FreepsPlayCard(aragorn); - scn.FreepsPlayCard(gimli); - assertEquals(6, scn.GetTwilight()); - scn.FreepsSkipCurrentPhaseAction(); - - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); - assertFalse(scn.HasKeyword(aragorn, Keyword.CONCEALED)); - assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsAcceptOptionalTrigger(); - scn.FreepsChooseCard(frodo); - assertTrue(scn.HasKeyword(frodo, Keyword.CONCEALED)); - assertTrue(scn.HasKeyword(aragorn, Keyword.CONCEALED)); - //6 from playing aragorn/gimli, 1+1+1 for companions, 1 for the site (King's Tent), -2 for concealed - assertEquals(8, scn.GetTwilight()); - } - - @Test - public void AragornAbilityOffersChoiceOfPrevention() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetScenario(); - - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - - PhysicalCardImpl minion = scn.GetShadowCard("minion"); - PhysicalCardImpl tracker = scn.GetShadowCard("tracker"); - scn.FreepsMoveCharToTable(aragorn); - scn.ShadowMoveCardToHand(minion, tracker); scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); - assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsAcceptOptionalTrigger(); - assertTrue(scn.ShadowDecisionAvailable("discard a minion (or reveal a tracker")); - scn.ShadowAcceptOptionalTrigger(); - - assertTrue(scn.ShadowAnyDecisionsAvailable()); - assertEquals("Discard a minion from hand", scn.ShadowGetADParamAsList("results").toArray()[0]); - assertEquals("Reveal a tracker from hand", scn.ShadowGetADParamAsList("results").toArray()[1]); - } - - @Test - public void AragornAbilityCanBePreventedWithMinionDiscard() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetScenario(); - - PhysicalCardImpl frodo = scn.GetRingBearer(); - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - - PhysicalCardImpl minion = scn.GetShadowCard("minion"); - - scn.FreepsMoveCharToTable(aragorn); - scn.ShadowMoveCardToHand(minion); - - scn.StartGame(); - scn.FreepsSkipCurrentPhaseAction(); - - assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsAcceptOptionalTrigger(); - assertTrue(scn.ShadowDecisionAvailable("discard a minion")); - assertEquals(1, scn.GetShadowHandCount()); - assertEquals(0, scn.GetShadowDiscardCount()); - scn.ShadowAcceptOptionalTrigger(); - assertEquals(0, scn.GetShadowHandCount()); - assertEquals(1, scn.GetShadowDiscardCount()); - assertFalse(scn.FreepsAnyDecisionsAvailable()); - - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); - } - - @Test - public void AragornAbilityCanBePreventedWithTrackerReveal() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetScenario(); - - PhysicalCardImpl frodo = scn.GetRingBearer(); - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - - PhysicalCardImpl tracker = scn.GetShadowCard("tracker"); - - scn.FreepsMoveCharToTable(aragorn); - scn.ShadowMoveCardToHand(tracker); - - scn.StartGame(); - scn.FreepsSkipCurrentPhaseAction(); - - assertTrue(scn.FreepsActionAvailable("Optional")); - scn.FreepsAcceptOptionalTrigger(); - assertTrue(scn.ShadowDecisionAvailable("reveal a tracker")); - assertEquals(1, scn.GetShadowHandCount()); - scn.ShadowAcceptOptionalTrigger(); - assertEquals(1, scn.GetShadowHandCount()); - assertTrue(scn.ShadowDecisionAvailable("Choose action to perform")); - scn.ShadowChooseMultipleChoiceOption("Reveal a tracker"); - - assertFalse(scn.FreepsAnyDecisionsAvailable()); - assertFalse(scn.HasKeyword(frodo, Keyword.CONCEALED)); + // 2 for Frodo/Aragorn, 1 for the site, no removal since there was nothing in the pool before moving + assertEquals(3, scn.GetTwilight()); } + + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java index f68db8760..6efc95e76 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java @@ -52,27 +52,9 @@ public class BillThePonyErrataTests Assert.assertTrue(scn.IsAttachedTo(bill, sam)); } - @Test - public void BillHealsWhenPlayed() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); - - PhysicalCardImpl bill = scn.GetFreepsCard("bill"); - PhysicalCardImpl sam = scn.GetFreepsCard("sam"); - - scn.FreepsMoveCardToHand(bill, sam); - - scn.StartGame(); - - scn.FreepsPlayCard(sam); - scn.FreepsUseCardAction(sam); - assertEquals(1, scn.GetWoundsOn(sam)); - scn.FreepsPlayCard(bill); - assertEquals(0, scn.GetWoundsOn(sam)); - } @Test - public void BillGrantsConcealed() throws DecisionResultInvalidException, CardNotFoundException { + public void BillReducesTwilight() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetSimpleScenario(); @@ -85,9 +67,12 @@ public class BillThePonyErrataTests scn.FreepsPlayCard(sam); scn.FreepsPlayCard(bill); - assertTrue(scn.HasKeyword(sam, Keyword.CONCEALED)); + + // 2 for Frodo/Sam, 1 for the site, -1 for Bill + assertEquals(2, scn.GetTwilight()); } + @Test public void BillDiscardedWhenMovingToUnderground() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup @@ -106,32 +91,9 @@ public class BillThePonyErrataTests scn.FreepsPlayCard(bill); scn.FreepsSkipCurrentPhaseAction(); - //Get a timing choice between resolving concealed or discarding bill - scn.FreepsResolveActionOrder("Concealed"); + assertFalse(scn.IsAttachedTo(bill, sam)); assertEquals(Zone.DISCARD, bill.getZone()); } - @Test - public void BillHealsWhenPlayedAtUnderground() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); - - PhysicalCardImpl bill = scn.GetFreepsCard("bill"); - PhysicalCardImpl sam = scn.GetFreepsCard("sam"); - - scn.FreepsMoveCardToHand(bill, sam); - - scn.InsertAdHocModifier(new KeywordModifier(null, CardType.SITE, Keyword.UNDERGROUND)); - - scn.StartGame(); - - scn.FreepsPlayCard(sam); - scn.FreepsUseCardAction(sam); - assertEquals(1, scn.GetWoundsOn(sam)); - scn.FreepsPlayCard(bill); - assertEquals(0, scn.GetWoundsOn(sam)); - assertFalse(scn.IsAttachedTo(bill, sam)); - assertEquals(Zone.DISCARD, bill.getZone()); - } } From a1e98128f24403093d6c714fce7a57d690c55a87 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 7 Mar 2021 18:20:09 -0600 Subject: [PATCH 53/74] Fixing Horn of Boromir having old text. --- .../src/main/web/cards/set51/set03-errata.json | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index 1f2c4cbfa..cf9737181 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -16,13 +16,19 @@ "times": 1 }, { - "type": "exert", - "filter": "choose(ally)", - "memorize": "summonedAlly", - "times": 1 - } + "type": "discard", + "filter": "self", + }, + ], "effect":[ + { + "type": "modifyStrength", + "filter": "choose(ally)", + "amount": 3, + "until": "start(regroup)", + "memorize": "summonedAlly" + }, { "type": "allyCanParticipateInArcheryFireAndSkirmishes", "filter": "memory(summonedAlly)", From 862d90d42ec086a6ac0ee34b7cf913b6981b7fc7 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Tue, 9 Mar 2021 12:57:21 -0600 Subject: [PATCH 54/74] Fixing Keeper of Isengard errata fierce not applying until regroup --- .../gemp-lotr-async/src/main/web/cards/set51/set03-errata.json | 3 ++- .../unofficial/pc/errata/set3/Saruman_KoIErrataTests.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index cf9737181..e8b63a883 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -96,7 +96,8 @@ "effect": { "type": "addKeyword", "filter": "choose(uruk-hai)", - "keyword": "fierce" + "keyword": "fierce", + "until": "start(regroup)" } }, ] diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java index 3e8f2272b..09a215daf 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java @@ -110,5 +110,7 @@ public class Saruman_KoIErrataTests assertEquals(0, scn.GetWoundsOn(uruk1)); assertEquals(1, scn.GetWoundsOn(saruman)); + scn.SkipToPhase(Phase.ASSIGNMENT); + assertTrue(scn.HasKeyword(uruk1, Keyword.FIERCE)); } } From 33eb217ef25192a23a3e316451cf772805ec11e4 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 10 Mar 2021 01:10:11 -0600 Subject: [PATCH 55/74] Updated all errata unit tests to contain the text of the card that it is tested against. Fixed Horn of Boromir not having its regroup duration tested. --- .../main/web/cards/set51/set02-errata.json | 2 +- .../main/web/cards/set51/set03-errata.json | 5 ++- .../pc/errata/set1/Elrond_LoRErrataTests.java | 34 +++++++++++++++ .../errata/set1/Galadriel_LoLErrataTests.java | 35 ++++++++++++++++ .../pc/errata/set1/NoStrangerErrataTests.java | 18 +++++++- .../pc/errata/set1/Sam_SoHErrataTests.java | 42 +++++++++++++++++-- .../pc/errata/set1/StingErrataTests.java | 26 ++++++++++++ .../errata/set1/TalentForNBSErrataTests.java | 17 +++++++- .../errata/set2/FlamingBrandErrataTests.java | 37 +++++++++++++--- .../errata/set2/Gimli_DotMrErrataTests.java | 26 +++++++++++- .../errata/set3/Aragorn_HttWCErrataTests.java | 34 +++++++++++++++ .../errata/set3/BillThePonyErrataTests.java | 36 +++++++++++++--- .../errata/set3/HornOfBoromirErrataTests.java | 30 ++++++++++++- .../errata/set3/Saruman_KoIErrataTests.java | 35 ++++++++++++++++ 14 files changed, 354 insertions(+), 23 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json index 77d0acf94..284d29ae6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json @@ -1,7 +1,7 @@ { "52_32": { "side": "free_people", - "cost": 0, + "cost": 1, "strength": 1, "culture": "Gondor", "possession": "Hand Weapon", diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index e8b63a883..5f981baa7 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -1,7 +1,7 @@ { "53_42": { "side": "free_people", - "cost": 0, + "cost": 1, "culture": "Gondor", "title": "*Horn of Boromir", "type": "possession", @@ -143,6 +143,9 @@ "cost": 0, "type": "possession", "possession": "Pony", + "keyword": [ + "stealth" + ], "target": "name(Sam)", "effects": [ { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java index dd66e3362..b89d37ea7 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java @@ -1,6 +1,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set1; import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; @@ -49,6 +50,39 @@ public class Elrond_LoRErrataTests ); } + @Test + public void ElrondStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Elrond + * Subtitle: Lord of Rivendell + * Side: Free Peoples + * Culture: Elven + * Twilight Cost: 4 + * Type: Ally + * Subtype: Elf + * Home: 3 + * Strength: 8 + * Vitality: 4 + * Errata Game Text: To play, spot Gandalf or an Elf. + * At the start of each of your turns, heal up to 3 allies whose home is site 3. + * Fellowship: Exert Elrond twice (or once if you can spot 2 other [elven] allies) to draw a card. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetSimpleDeckScenario(); + + PhysicalCardImpl elrond = scn.GetFreepsCard("elrond"); + + assertTrue(elrond.getBlueprint().isUnique()); + assertEquals(4, elrond.getBlueprint().getTwilightCost()); + + assertEquals(8, elrond.getBlueprint().getStrength()); + assertEquals(4, elrond.getBlueprint().getVitality()); + assertEquals(3, Arrays.stream(elrond.getBlueprint().getAllyHomeSiteNumbers()).findFirst().getAsInt()); + } + @Test public void FellowshipActionExertsTwiceToDrawACardIfNoAllies() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java index 872c12514..95e435ead 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java @@ -5,9 +5,12 @@ import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; + +import static junit.framework.Assert.assertEquals; import static org.junit.Assert.*; import org.junit.Test; +import java.util.Arrays; import java.util.HashMap; public class Galadriel_LoLErrataTests @@ -35,6 +38,38 @@ public class Galadriel_LoLErrataTests ); } + @Test + public void GaladrielStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Galadriel + * Subtitle: Lady of Light + * Side: Free Peoples + * Culture: Elven + * Twilight Cost: 3 + * Type: Ally + * Subtype: Elf + * Home: 6 + * Strength: 3 + * Vitality: 3 + * Errata Game Text: At the start of each of your turns, heal up to 3 allies whose home is site 6. + * Fellowship: Exert Galadriel to play an Elf; that Elf's twilight cost is -1. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetSimplePlayScenario(); + + PhysicalCardImpl galadriel = scn.GetFreepsCard("galadriel"); + + assertTrue(galadriel.getBlueprint().isUnique()); + assertEquals(3, galadriel.getBlueprint().getTwilightCost()); + + assertEquals(3, galadriel.getBlueprint().getStrength()); + assertEquals(3, galadriel.getBlueprint().getVitality()); + assertEquals(6, Arrays.stream(galadriel.getBlueprint().getAllyHomeSiteNumbers()).findFirst().getAsInt()); + } + @Test public void FellowshipActionExertsToDiscountAnElf() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java index 874951fce..61ac53d78 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/NoStrangerErrataTests.java @@ -8,6 +8,7 @@ import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; import org.junit.Test; +import java.util.Arrays; import java.util.HashMap; import static junit.framework.Assert.assertEquals; @@ -31,14 +32,27 @@ public class NoStrangerErrataTests @Test - public void NoStrangerIsUniqueAndHasStealth() throws DecisionResultInvalidException, CardNotFoundException { + public void NoStrangerStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *No Stranger to the Shadows + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 0 + * Type: Condition + * Errata Game Text: At the start of each of your turns, heal up to 3 allies whose home is site 6. + * Fellowship: Exert Galadriel to play an Elf; that Elf's twilight cost is -1. + */ + //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl nostranger = scn.GetFreepsCard("nostranger"); - assertTrue(scn.HasKeyword(nostranger, Keyword.STEALTH)); assertTrue(nostranger.getBlueprint().isUnique()); + assertEquals(0, nostranger.getBlueprint().getTwilightCost()); + assertTrue(scn.HasKeyword(nostranger, Keyword.STEALTH)); } @Test diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java index 33b53d897..6116365b8 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Sam_SoHErrataTests.java @@ -2,9 +2,12 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set1; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Signet; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; + +import static junit.framework.Assert.assertEquals; import static org.junit.Assert.*; import org.junit.Test; @@ -12,7 +15,7 @@ import java.util.HashMap; public class Sam_SoHErrataTests { - protected GenericCardTestHelper GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { return new GenericCardTestHelper( new HashMap() {{ @@ -23,10 +26,43 @@ public class Sam_SoHErrataTests ); } + @Test + public void SamStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Sam + * Subtitle: Son of Hamfast + * Side: Free Peoples + * Culture: Shire + * Twilight Cost: 2 + * Type: Companion + * Subtype: Hobbit + * Strength: 3 + * Vitality: 4 + * Signet: Aragorn + * Errata Game Text: Fellowship: Exert Sam and another companion to remove a burden. + * Response: If Frodo dies, make Sam the Ring-bearer (resistance 5). + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + + assertTrue(sam.getBlueprint().isUnique()); + assertEquals(2, sam.getBlueprint().getTwilightCost()); + + assertEquals(3, sam.getBlueprint().getStrength()); + assertEquals(4, sam.getBlueprint().getVitality()); + assertEquals(Signet.ARAGORN, sam.getBlueprint().getSignet()); + + } + @Test public void FellowshipActionExertsTwiceToRemoveABurden() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); @@ -52,7 +88,7 @@ public class Sam_SoHErrataTests @Test public void RBDeathMakesSamTheRB() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java index 7a14a7d04..a34ee5cb5 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java @@ -36,6 +36,32 @@ public class StingErrataTests ); } + @Test + public void StingStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Sting + * Side: Free Peoples + * Culture: Shire + * Twilight Cost: 1 + * Strength: +2 + * Type: Possession + * Subtype: Hand Weapon + * Errata Game Text: Bearer must be Frodo. + * Fellowship or Regroup: Exert Frodo to reveal 4 cards at random from an opponent's hand. Remove (1) for each Orc revealed (limit (2)). + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl sting = scn.GetFreepsCard("sting"); + + assertTrue(sting.getBlueprint().isUnique()); + assertEquals(1, sting.getBlueprint().getTwilightCost()); + assertEquals(2, sting.getBlueprint().getStrength()); + } + @Test public void StingCanOnlyBeBorneByFrodo() throws DecisionResultInvalidException, CardNotFoundException { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java index 5a9702568..48a59040d 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java @@ -32,12 +32,27 @@ public class TalentForNBSErrataTests } @Test - public void TalentHasStealth() throws DecisionResultInvalidException, CardNotFoundException { + public void TalentStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *A Talent for Not Being Seen + * Side: Free Peoples + * Culture: Shire + * Twilight Cost: 0 + * Type: Condition + * Errata Game Text: Stealth. Bearer must be Merry or Pippin. Limit 1 per character. + * Each site's Shadow number is -1. + */ + //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl talent = scn.GetFreepsCard("talent"); + assertTrue(talent.getBlueprint().isUnique()); + assertEquals(0, talent.getBlueprint().getTwilightCost()); + assertTrue(scn.HasKeyword(talent, Keyword.STEALTH)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index 4ca5653bc..5dec844d3 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -15,7 +15,7 @@ import static org.junit.Assert.*; public class FlamingBrandErrataTests { - protected GenericCardTestHelper GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { return new GenericCardTestHelper( new HashMap() {{ @@ -31,10 +31,35 @@ public class FlamingBrandErrataTests ); } + @Test + public void BrandStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: Flaming Brand + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 1 + * Type: Possession + * Subtype: Hand Weapon + * Errata Game Text: Bearer must be a ranger. This weapon may be borne in addition to 1 other hand weapon. + * Skirmish: If bearer is skirmishing a Nazgul, discard this possession to make bearer strength +3 and damage +1. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl brand = scn.GetFreepsCard("brand"); + + assertFalse(brand.getBlueprint().isUnique()); + assertEquals(1, brand.getBlueprint().getTwilightCost()); + assertEquals(1, brand.getBlueprint().getStrength()); + } + @Test public void CanBeBorneByRangers() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl arwen = scn.GetFreepsCard("arwen"); PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); @@ -63,7 +88,7 @@ public class FlamingBrandErrataTests @Test public void CanBeBorneTwice() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl brand = scn.GetFreepsCard("brand"); @@ -85,7 +110,7 @@ public class FlamingBrandErrataTests @Test public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); PhysicalCardImpl brand = scn.GetFreepsCard("brand"); @@ -106,7 +131,7 @@ public class FlamingBrandErrataTests scn.SkipToPhase(Phase.ASSIGNMENT); scn.SkipCurrentPhaseActions(); - scn.FreepsAssignToMinion(aragorn, runner); + scn.FreepsAssignToMinions(aragorn, runner); //skip assigning the nazgul scn.SkipCurrentPhaseActions(); @@ -119,7 +144,7 @@ public class FlamingBrandErrataTests //assignment for fierce skirmish scn.SkipCurrentPhaseActions(); - scn.FreepsAssignToMinion(aragorn, nazgul); + scn.FreepsAssignToMinions(aragorn, nazgul); scn.FreepsResolveSkirmish(aragorn); assertEquals(1, scn.FreepsGetAvailableActions().size()); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java index f97bf32ac..f7feea04f 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/Gimli_DotMrErrataTests.java @@ -3,6 +3,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set2; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Signet; import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; @@ -28,12 +29,35 @@ public class Gimli_DotMrErrataTests } @Test - public void GimliHasDamage() throws DecisionResultInvalidException, CardNotFoundException { + public void GimliStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Gimli + * Subtitle: Dwarf of the Mountain-race + * Side: Free Peoples + * Culture: Dwarven + * Twilight Cost: 2 + * Type: Companion + * Subtype: Dwarf + * Strength: 6 + * Vitality: 3 + * Signet: Frodo + * Errata Game Text: Damage +1. Each underground site's Shadow number is -1. While the fellowship is at an underground site, Gimli is strength +1. + */ + //Pre-game setup GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl gimli = scn.GetFreepsCard("gimli"); + assertTrue(gimli.getBlueprint().isUnique()); + assertEquals(2, gimli.getBlueprint().getTwilightCost()); + + assertEquals(6, gimli.getBlueprint().getStrength()); + assertEquals(3, gimli.getBlueprint().getVitality()); + assertEquals(Signet.FRODO, gimli.getBlueprint().getSignet()); + assertTrue(scn.HasKeyword(gimli, Keyword.DAMAGE)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java index 83c4c129a..17aa95db5 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Aragorn_HttWCErrataTests.java @@ -3,6 +3,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set3; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Signet; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -36,6 +37,39 @@ public class Aragorn_HttWCErrataTests PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + } + + @Test + public void AragornStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Aragorn + * Subtitle: Heir to the White City + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 4 + * Type: Companion + * Subtype: Man + * Strength: 8 + * Vitality: 4 + * Signet: Frodo + * Errata Game Text: Ranger. Each time the fellowship moves during the fellowship phase, remove (1). + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + + assertTrue(aragorn.getBlueprint().isUnique()); + assertEquals(4, aragorn.getBlueprint().getTwilightCost()); + + assertEquals(8, aragorn.getBlueprint().getStrength()); + assertEquals(4, aragorn.getBlueprint().getVitality()); + assertEquals(Signet.FRODO, aragorn.getBlueprint().getSignet()); + assertTrue(scn.HasKeyword(aragorn, Keyword.RANGER)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java index 6efc95e76..ff577d784 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/BillThePonyErrataTests.java @@ -1,9 +1,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set3; import com.gempukku.lotro.cards.GenericCardTestHelper; -import com.gempukku.lotro.common.CardType; import com.gempukku.lotro.common.Keyword; -import com.gempukku.lotro.common.Phase; import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.CardNotFoundException; @@ -21,7 +19,7 @@ import static org.junit.Assert.assertTrue; public class BillThePonyErrataTests { - protected GenericCardTestHelper GetSimpleScenario() throws CardNotFoundException, DecisionResultInvalidException { + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { return new GenericCardTestHelper( new HashMap() {{ @@ -31,10 +29,36 @@ public class BillThePonyErrataTests ); } + @Test + public void BillStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Bill the Pony + * Side: Free Peoples + * Culture: Shire + * Twilight Cost: 0 + * Type: Possession + * Subtype: Pony + * Errata Game Text: Stealth. Bearer must be Sam. + * Each site's Shadow number is -1. Discard this possession when at an underground site. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl bill = scn.GetFreepsCard("bill"); + + assertTrue(bill.getBlueprint().isUnique()); + assertEquals(0, bill.getBlueprint().getTwilightCost()); + + assertTrue(scn.HasKeyword(bill, Keyword.STEALTH)); + } + @Test public void BillCanBeBorneBySam() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl bill = scn.GetFreepsCard("bill"); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); @@ -56,7 +80,7 @@ public class BillThePonyErrataTests @Test public void BillReducesTwilight() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl bill = scn.GetFreepsCard("bill"); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); @@ -76,7 +100,7 @@ public class BillThePonyErrataTests @Test public void BillDiscardedWhenMovingToUnderground() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup - GenericCardTestHelper scn = GetSimpleScenario(); + GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl bill = scn.GetFreepsCard("bill"); PhysicalCardImpl sam = scn.GetFreepsCard("sam"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java index 424c0132b..16fe9c1fb 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/HornOfBoromirErrataTests.java @@ -1,8 +1,8 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set3; import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; -import com.gempukku.lotro.common.Zone; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -43,10 +43,34 @@ public class HornOfBoromirErrataTests put("aragorn", "1_89"); put("runner1", "1_178"); + put("runner2", "1_178"); }} ); } + @Test + public void HornStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Horn of Boromir + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 1 + * Type: Possession + * Errata Game Text: Bearer must be Boromir. + * Maneuver: Exert Boromir and discard this possession to spot an ally. Until the regroup phase, that ally is strength +3 and participates in archery fire and skirmishes. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetFOTRScenario(); + + PhysicalCardImpl horn = scn.GetFreepsCard("horn"); + + assertTrue(horn.getBlueprint().isUnique()); + assertEquals(1, horn.getBlueprint().getTwilightCost()); + } + @Test public void CanBeBorneByBoromir() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup @@ -106,8 +130,10 @@ public class HornOfBoromirErrataTests scn.SkipCurrentPhaseActions(); - scn.FreepsAssignToMinion(elrond, runner1); + scn.FreepsAssignToMinions(elrond, runner1); assertTrue(scn.IsCharAssigned(elrond)); + assertEquals(11, scn.GetStrength(elrond)); + } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java index 09a215daf..a1483984e 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set3/Saruman_KoIErrataTests.java @@ -3,6 +3,7 @@ package com.gempukku.lotro.cards.unofficial.pc.errata.set3; import com.gempukku.lotro.cards.GenericCardTestHelper; import com.gempukku.lotro.common.Keyword; import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Signet; import com.gempukku.lotro.game.CardNotFoundException; import com.gempukku.lotro.game.PhysicalCardImpl; import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; @@ -31,6 +32,40 @@ public class Saruman_KoIErrataTests ); } + @Test + public void SarumanStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: 1E + * Title: *Saruman + * Subtitle: Keeper of Isengard + * Side: Shadow + * Culture: Isengard + * Twilight Cost: 4 + * Type: Minion + * Subtype: Wizard + * Strength: 8 + * Vitality: 4 + * Home Site: 4 + * Errata Game Text: Saruman may not take wounds during the archery phase and may not be assigned to a skirmish. + * Maneuver: Exert Saruman to make an Uruk-hai fierce until the regroup phase. + * Response: If an Uruk-hai is about to take a wound, exert Saruman to prevent that wound. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl saruman = scn.GetFreepsCard("saruman"); + + assertTrue(saruman.getBlueprint().isUnique()); + assertEquals(4, saruman.getBlueprint().getTwilightCost()); + + assertEquals(8, saruman.getBlueprint().getStrength()); + assertEquals(4, saruman.getBlueprint().getVitality()); + assertEquals(4, saruman.getBlueprint().getSiteNumber()); + + } + @Test public void SarumanImmunityAndWoundBlock() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup From 1a2593bb2cf9e0af1d1ee30b495b9711dafda8c8 Mon Sep 17 00:00:00 2001 From: Troy Biesterfeld Date: Wed, 10 Mar 2021 03:43:33 -0600 Subject: [PATCH 56/74] Help implement FOTR block errata --- .../main/web/cards/set51/set01-errata.json | 173 ++++++----- .../main/web/cards/set51/set02-errata.json | 157 +++++++++- .../main/web/cards/set51/set03-errata.json | 288 ++++++++++++------ .../field/effect/appender/PlayNextSite.java | 39 ++- .../field/effect/filter/FilterFactory.java | 1 + ...FreePeoplePlayerMayNotAssignCharacter.java | 34 +++ .../modifier/ModifierSourceFactory.java | 2 + .../field/effect/trigger/RemovesBurden.java | 33 ++ .../effect/trigger/TriggerCheckerFactory.java | 1 + .../com/gempukku/lotro/filters/Filters.java | 12 + .../logic/effects/PlayNextSiteEffect.java | 5 + .../lotro/logic/timing/TriggerConditions.java | 8 + 12 files changed, 561 insertions(+), 192 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesBurden.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index d033d0ad6..97a2a14ab 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -66,8 +66,8 @@ }, "effect": { "type": "heal", - "filter": "choose(another,ally,allyHome(fellowship,6))", - "count": "0-2" + "filter": "choose(ally,allyHome(fellowship,6))", + "count": "0-3" } }, { @@ -92,7 +92,7 @@ "culture": "gandalf", "cost": 1, "type": "ally", - "allyHome": "fellowship,1", + "allyHome": "fellowship,3", "race": "man", "strength": 2, "vitality": 2, @@ -103,32 +103,90 @@ "effects": { "type": "activated", "phase": "fellowship", - "cost": { - "type": "exert", - "filter": "self" - }, - "effect": [ + "cost": [ { - "type": "discardFromHand", - "forced": false, - "count": "0-3", - "memorize": "discardedCards" + "type": "exert", + "filter": "self" }, { - "type": "drawCards", - "count": { - "type": "forEachInMemory", - "memory": "discardedCards" - } + "type": "discardFromHand", + "forced": false } - ] + ], + "effect": { + "type": "drawCards" + } } }, - + "51_108": { + "title": "*No Stranger to the Shadows", + "culture": "gondor", + "cost": 0, + "type": "condition", + "keyword": [ + "stealth" + ], + "target": "ranger", + "effects": { + "type": "modifier", + "modifier": { + "type": "modifyCost", + "filter": "site", + "amount": -1 + } + } + }, + "51_138": { + "title": "Saruman's Snows", + "culture": "isengard", + "cost": 2, + "type": "condition", + "keyword": [ + "spell", + "weather" + ], + "target": "site", + "effects": [ + { + "type": "extraCost", + "cost": { + "type": "exert", + "filter": "choose(culture(isengard),minion)" + } + }, + { + "type": "modifier", + "modifier": { + "type": "cantPlayPhaseEventsOrPhaseSpecialAbilities", + "condition": [ + { + "type": "location", + "filter": "hasAttached(self)" + }, + { + "type": "canSpot", + "filter": "culture(isengard),minion,inSkirmish" + } + ], + "phase": "skirmish" + } + }, + { + "type": "trigger", + "trigger": { + "type": "endOfTurn" + }, + "effect": { + "type": "discard", + "filter": "self" + } + } + ] + }, "51_139": { "title": "Savagery To Match Their Numbers", "culture": "isengard", - "cost": 0, + "cost": 1, "type": "event", "keyword": "skirmish", "effects": { @@ -137,7 +195,7 @@ "type": "choice", "texts": [ "Make an Uruk-hai strength +2", - "Make an Uruk-hai fierce until the regroup phase, and strength +4 (this skirmish)" + "Make an Uruk-hai strength +4, and fierce until the regroup phase" ], "effects": [ { @@ -171,7 +229,6 @@ } } }, - "51_195": { "title": "*Relics of Moria", "culture": "moria", @@ -192,7 +249,6 @@ } } }, - "51_234": { "title": "*ÚlairĆ« NertĆ«a", "subtitle": "Messenger of Dol Guldur", @@ -218,16 +274,15 @@ }, "effect": { "type": "optional", - "text": "Would you like to play minion from your discard?", + "text": "Would you like to play a wraith minion from your discard?", "effect": { "type": "playCardFromDiscard", - "filter": "choose(nazgul)" + "filter": "choose(culture(wraith),minion)" } } } } }, - "51_248": { "title": "Forces of Mordor", "culture": "sauron", @@ -240,21 +295,16 @@ "type": "exert", "filter": "choose(culture(sauron),minion)" }, - "cost": { - "type": "chooseHowManyToSpot", - "filter": "culture(sauron),minion", - "memorize": "spottedCount" - }, "effect": { "type": "addTwilight", "amount": { "type": "forEachYouCanSpot", "filter": "culture(sauron),orc", + "limit": 3 } } } }, - "51_311": { "title": "*Sam", "subtitle": "Son of Hamfast", @@ -273,13 +323,11 @@ "cost": [ { "type": "exert", - "filter": "self", - "times": 1 + "filter": "self" }, { "type": "exert", - "filter": "choose(another,companion)", - "times": 1 + "filter": "choose(another,companion)" } ], "effect": { @@ -300,32 +348,6 @@ } ] }, - - - - - - - "51_108": { - "title": "*No Stranger to the Shadows", - "culture": "gondor", - "cost": 0, - "type": "condition", - "keyword": [ - "stealth" - ], - "target": "ranger,not(hasAttached(name(No Stranger to the Shadows)))", - "effects": { - "type": "modifier", - "modifier": { - "type": "modifyCost", - "filter": "site", - "amount": -1 - } - } - }, - - "51_313": { "title": "*Sting", "culture": "shire", @@ -350,13 +372,13 @@ "hand": "shadowPlayer", "forced": true, "memorize": "revealedCards", - "count":2 + "count": 4 }, { "type": "removeTwilight", "amount": { "type": "cardPhaseLimit", - "limit": 2, + "limit": 2, "amount": { "type": "forEachMatchingInMemory", "memory": "revealedCards", @@ -368,13 +390,12 @@ ] } }, - "51_316": { - "title": "*A Talent for Not Being Seen", + "title": "A Talent for Not Being Seen", "culture": "shire", "cost": 0, "type": "condition", - "target": "or(name(Merry),name(Pippin))", + "target": "or(name(Merry),name(Pippin)),not(hasAttached(name(A Talent for Not Being Seen)))", "keyword": [ "stealth" ], @@ -383,22 +404,8 @@ "modifier": { "type": "modifyCost", "filter": "site", - "amount": { - "type": "condition", - "condition": { - "type": "cantSpot", - "filter": "companion,not(hobbit)" - }, - "true": -1, - "false": 0 - } + "amount": -1 } } - }, - - - - - - + } } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json index 77d0acf94..115cead9d 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json @@ -1,7 +1,7 @@ { - "52_32": { + "52_32": { "side": "free_people", - "cost": 0, + "cost": 1, "strength": 1, "culture": "Gondor", "possession": "Hand Weapon", @@ -17,7 +17,7 @@ "phase": "skirmish", "condition": { "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", + "filter": "bearer,inSkirmishAgainst(Nazgul)" }, "cost": [ { @@ -30,7 +30,7 @@ "filter": "self" } ], - "effect":[ + "effect": [ { "type": "modifyStrength", "filter": "memory(bearer)", @@ -42,10 +42,123 @@ "keyword": "damage+1" } ] - }, + } ] }, - + "52_75": { + "title": "*Bill Ferny", + "subtitle": "Swarthy Sneering Fellow", + "culture": "wraith", + "cost": 2, + "type": "minion", + "race": "man", + "strength": 4, + "vitality": 1, + "site": 2, + "effects": [ + { + "type": "modifier", + "modifier": { + "type": "removeKeyword", + "filter": "nazgul", + "keyword": "roaming" + } + }, + { + "type": "modifier", + "modifier": { + "type": "cantBeAssignedToSkirmishByFpPlayer", + "condition": { + "type": "canSpot", + "filter": "hobbit" + }, + "filter": "self" + } + }, + { + "type": "trigger", + "trigger": { + "type": "condition", + "condition": { + "type": "location", + "filter": "underground" + } + }, + "effect": { + "type": "discard", + "filter": "self" + } + } + ] + }, + "52_101": { + "title": "*Filibert Bolger", + "subtitle": "Wily Rascal", + "culture": "shire", + "cost": 1, + "type": "ally", + "allyHome": "fellowship,1", + "race": "hobbit", + "strength": 1, + "vitality": 2, + "effects": { + "type": "activated", + "phase": "skirmish", + "cost": [ + { + "type": "exert", + "filter": "choose(hobbit,companion,not(ring bearer))", + "times": 2, + "memorize": "exertedHobbit" + } + ], + "effect": { + "type": "cancelSkirmish", + "filter": "memory(exertedHobbit),infierceskirmish" + } + } + }, + "52_108": { + "title": "*O Elbereth! Gilthoniel!", + "culture": "shire", + "cost": 1, + "type": "condition", + "strength": 1, + "keyword": "tale", + "target": "ring bearer", + "effects": { + "type": "activated", + "phase": "skirmish", + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect": { + "type": "choice", + "texts": [ + "Make the Ring-bearer strength +3 if skirmishing a Nazgul", + "Take off The One Ring" + ], + "effects": [ + { + "type": "modifyStrength", + "filter": "memory(bearer),inSkirmishAgainst(nazgul)", + "amount": 3 + }, + { + "type": "takeOffRing" + } + ] + } + } + }, "52_121": { "title": "*Gimli", "subtitle": "Dwarf of the Mountain-race", @@ -58,15 +171,27 @@ "resistance": 6, "signet": "frodo", "keyword": "damage+1", - "effects": { - "type": "modifier", - "modifier": { - "type": "modifyCost", - "filter": "underground,site", - "amount": -1 + "effects": [ + { + "type": "modifier", + "modifier": { + "type": "modifyCost", + "filter": "underground,site", + "amount": -1 + } + }, + { + "type": "modifier", + "modifier": { + "type": "modifyStrength", + "amount": 1, + "condition": { + "type": "location", + "filter": "underground" + }, + "filter": "self" + } } - } - }, - - + ] + } } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index e8b63a883..ae7f0c940 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -1,7 +1,73 @@ { - "53_42": { + "53_17": { + "title": "*Galadriel", + "subtitle": "Lady of the Golden Wood", + "culture": "elven", + "cost": 3, + "type": "ally", + "allyHome": "fellowship,6", + "race": "elf", + "strength": 3, + "vitality": 3, + "effects": [ + { + "type": "trigger", + "optional": true, + "trigger": { + "type": "startOfTurn" + }, + "effect": { + "type": "heal", + "filter": "another,elf" + } + }, + { + "type": "activated", + "phase": "fellowship", + "cost": { + "type": "exert", + "filter": "self", + "times": 2 + }, + "effect": { + "type": "playNextSite", + "filter": "forest" + } + } + ] + }, + "53_38": { + "title": "*Aragorn", + "subtitle": "Heir to the White City", + "culture": "Gondor", + "type": "companion", + "race": "Man", + "cost": 4, + "strength": 8, + "vitality": 4, + "resistance": 6, + "signet": "frodo", + "keyword": [ + "Ranger" + ], + "effects": { + "type": "trigger", + "trigger": { + "type": "moves" + }, + "condition": { + "type": "phase", + "phase": "fellowship" + }, + "effect": { + "type": "removeTwilight", + "amount": 1 + } + } + }, + "53_42": { "side": "free_people", - "cost": 0, + "cost": 1, "culture": "Gondor", "title": "*Horn of Boromir", "type": "possession", @@ -12,32 +78,76 @@ "cost": [ { "type": "exert", - "filter": "bearer", - "times": 1 + "filter": "bearer" }, { "type": "discard", - "filter": "self", - }, - + "filter": "self" + } ], - "effect":[ + "effect": [ { - "type": "modifyStrength", + "type": "spot", "filter": "choose(ally)", - "amount": 3, - "until": "start(regroup)", - "memorize": "summonedAlly" + "memorize": "chosenAlly" + }, + { + "type": "addModifier", + "modifier": { + "type": "modifyStrength", + "filter": "memory(chosenAlly)", + "amount": 3, + "until": "start(regroup)" + } }, { "type": "allyCanParticipateInArcheryFireAndSkirmishes", - "filter": "memory(summonedAlly)", + "filter": "memory(chosenAlly)", "until": "start(regroup)" } ] } }, - + "53_67": { + "title": "*The Palantir of Orthanc", + "culture": "isengard", + "cost": 0, + "type": "artifact", + "possession": "palantir", + "keyword": "support area", + "condition": { + "type": "canSpot", + "filter": "culture(isengard),minion" + }, + "effects": { + "type": "activated", + "phase": "shadow", + "cost": [ + { + "type": "removeTwilight", + "amount": 2 + }, + { + "type": "canSpot", + "count": 2, + "memorize": "culture(isengard),minion" + } + ], + "effect": [ + { + "type": "revealRandomCardsFromHand", + "forced": true, + "hand": "fp", + "count": 1, + "memorize": "revealedCard" + }, + { + "type": "putCardsFromHandOnTopOfDeck", + "filter": "choose(memory(revealedCard))" + } + ] + } + }, "53_68": { "side": "shadow", "site": 4, @@ -50,13 +160,6 @@ "title": "*Saruman", "type": "minion", "effects": [ - { - "type": "modifier", - "modifier": { - "type": "cantbeassignedtoskirmish", - "filter": "self" - } - }, { "type": "modifier", "modifier": { @@ -68,6 +171,27 @@ } } }, + { + "type": "modifier", + "modifier": { + "type": "cantbeassignedtoskirmish", + "filter": "self" + } + }, + { + "type": "activated", + "phase": "maneuver", + "cost": { + "type": "exert", + "filter": "self" + }, + "effect": { + "type": "addKeyword", + "filter": "choose(uruk-hai)", + "keyword": "fierce", + "until": "start(regroup)" + } + }, { "type": "activatedTrigger", "trigger": { @@ -76,73 +200,25 @@ }, "cost": { "type": "exert", - "filter": "self", - "times": 1 + "filter": "self" }, "effect": { "type": "preventWound", "filter": "choose(uruk-hai)" } - }, - { - "type": "activated", - "phase": "maneuver", - "cost": { - "type": "exert", - "filter": "self", - "times": 1 - }, - "effect": { - "type": "addKeyword", - "filter": "choose(uruk-hai)", - "keyword": "fierce", - "until": "start(regroup)" - } - }, + } ] }, - - "53_38": { - "side": "free_people", - "title": "*Aragorn", - "subtitle": "Heir to the White City", - "culture": "Gondor", - "type": "companion", - "race": "Man", - "cost": 4, - "strength": 8, - "vitality": 4, - "resistance": 6, - "signet": "frodo", - "keyword": [ - "Ranger", - ], - "effects": { - "type": "trigger", - "optional": false, - "trigger": { - "type": "movesfrom" - }, - "condition": { - "type": "phase", - "phase": "fellowship" - }, - "effect": { - "type": "removeTwilight", - "amount": 1 - } - } - }, - - "53_106": { "title": "*Bill the Pony", "culture": "Shire", "side": "free_people", "cost": 0, "type": "possession", - "possession": "Pony", + "keyword": [ + "stealth" + ], "target": "name(Sam)", "effects": [ { @@ -157,22 +233,62 @@ "type": "trigger", "trigger": { "type": "condition", - "condition": [ - { - "type": "location", - "filter": "underground" - }, - { - "type": "canSpot", - "filter": "self,attachedTo(companion)" - } - ] + "condition": { + "type": "location", + "filter": "underground" + } }, "effect": { "type": "discard", "filter": "self" } } - ] - }, + ] + }, + "53_108": { + "title": "Frying Pan", + "culture": "Shire", + "cost": 1, + "type": "possession", + "possession": "hand weapon", + "strength": 1, + "target": "hobbit", + "effects": { + "type": "activated", + "phase": "skirmish", + "cost": { + "type": "exert", + "filter": "bearer" + }, + "effect": { + "type": "wound", + "filter": "choose(orc,inSkirmishAgainst(bearer))" + } + } + }, + "53_113": { + "title": "*The Shire Countryside", + "culture": "shire", + "cost": 1, + "type": "condition", + "keyword": "support area", + "condition": { + "type": "canSpot", + "count": 2, + "filter": "culture(shire),companion" + }, + "effects": { + "type": "trigger", + "optional": true, + "trigger": { + "type": "removesBurden", + "filter": "not(hobbit)" + }, + "effect": { + "type": "heal", + "count": "0-2", + "filter": "choose(companion)" + } + } + } } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java index 295da5510..0829dda5b 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayNextSite.java @@ -2,10 +2,14 @@ package com.gempukku.lotro.cards.build.field.effect.appender; import com.gempukku.lotro.cards.build.ActionContext; import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.FilterableSource; import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; import com.gempukku.lotro.cards.build.field.FieldUtils; import com.gempukku.lotro.cards.build.field.effect.EffectAppender; import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer; +import com.gempukku.lotro.common.Filterable; +import com.gempukku.lotro.filters.Filter; +import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.PhysicalCard; import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.logic.actions.CostToEffectAction; @@ -16,23 +20,44 @@ import org.json.simple.JSONObject; public class PlayNextSite implements EffectAppenderProducer { @Override public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(effectObject, "memorize"); - + FieldUtils.validateAllowedFields(effectObject, "filter", "memorize"); + final String filter = FieldUtils.getString(effectObject.get("filter"), "filter", "any"); final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize"); + final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); + return new DelayedAppender() { @Override public boolean isPlayableInFull(ActionContext actionContext) { final LotroGame game = actionContext.getGame(); - final int currentSiteNumber = game.getGameState().getCurrentSiteNumber(); - final PhysicalCard nextSite = game.getGameState().getSite(currentSiteNumber + 1); - return currentSiteNumber < 9 - && (nextSite == null || game.getModifiersQuerying().canReplaceSite(game, actionContext.getPerformingPlayer(), nextSite)); + final int nextSiteNumber = game.getGameState().getCurrentSiteNumber() + 1; + final PhysicalCard nextSite = game.getGameState().getSite(nextSiteNumber); + final Filterable filterable = filterableSource.getFilterable(actionContext); + final String playerId = actionContext.getPerformingPlayer(); + + if (nextSiteNumber > 9 || nextSiteNumber < 1) + return false; + + if (nextSite != null && !game.getModifiersQuerying().canReplaceSite(game, actionContext.getPerformingPlayer(), nextSite)) + return false; + + if (game.getFormat().isOrderedSites()) { + Filter printedSiteNumber = new Filter() { + @Override + public boolean accepts(LotroGame game, PhysicalCard physicalCard) { + return physicalCard.getBlueprint().getSiteNumber() == nextSiteNumber; + } + }; + return Filters.filter(game.getGameState().getAdventureDeck(playerId), game, Filters.and(filterable, printedSiteNumber)).size() > 0; + } else { + return Filters.filter(game.getGameState().getAdventureDeck(playerId), game, filterable).size() > 0; + } } @Override protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) { - return new PlayNextSiteEffect(action, actionContext.getPerformingPlayer()) { + final Filterable filterable = filterableSource.getFilterable(actionContext); + return new PlayNextSiteEffect(action, actionContext.getPerformingPlayer(), filterable) { @Override protected void sitePlayedCallback(PhysicalCard site) { if (memorize != null) { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java index 851190fb0..291c95543 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/filter/FilterFactory.java @@ -41,6 +41,7 @@ public class FilterFactory { simpleFilters.put("unwounded", (actionContext) -> Filters.unwounded); simpleFilters.put("exhausted", (actionContext) -> Filters.exhausted); simpleFilters.put("inskirmish", (actionContext) -> Filters.inSkirmish); + simpleFilters.put("infierceskirmish", (actionContext) -> Filters.inFierceSkirmish); simpleFilters.put("inplay", (actionContext) -> Filters.inPlay); simpleFilters.put("notassignedtoskirmish", (actionContext) -> Filters.notAssignedToSkirmish); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java new file mode 100644 index 000000000..6367b29ad --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java @@ -0,0 +1,34 @@ +package com.gempukku.lotro.cards.build.field.effect.modifier; + +import com.gempukku.lotro.cards.build.*; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.cards.build.field.effect.appender.MultiEffectAppender; +import com.gempukku.lotro.logic.modifiers.CantBeAssignedToSkirmishModifier; +import com.gempukku.lotro.logic.modifiers.FreePeoplePlayerMayNotAssignCharacterModifier; +import com.gempukku.lotro.logic.modifiers.Modifier; +import org.json.simple.JSONObject; + +public class FreePeoplePlayerMayNotAssignCharacter implements ModifierSourceProducer { + + @Override + public ModifierSource getModifierSource(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject, "filter", "condition"); + + final JSONObject[] conditionArray = FieldUtils.getObjectArray(effectObject.get("condition"), "condition"); + final String filter = FieldUtils.getString(effectObject.get("filter"), "filter"); + + final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); + final Requirement[] requirements = environment.getRequirementFactory().getRequirements(conditionArray, environment); + + MultiEffectAppender result = new MultiEffectAppender(); + + return new ModifierSource() { + @Override + public Modifier getModifier(ActionContext actionContext) { + return new FreePeoplePlayerMayNotAssignCharacterModifier(actionContext.getSource(), + new RequirementCondition(requirements, actionContext), + filterableSource.getFilterable(actionContext)); + } + }; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java index 076147941..680505bc7 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java @@ -4,6 +4,7 @@ import com.gempukku.lotro.cards.build.CardGenerationEnvironment; import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; import com.gempukku.lotro.cards.build.ModifierSource; import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.logic.modifiers.FreePeoplePlayerMayNotAssignCharacterModifier; import org.json.simple.JSONObject; import java.util.HashMap; @@ -55,6 +56,7 @@ public class ModifierSourceFactory { modifierProducers.put("allycanparticipateinarcheryfireandskirmishes", new AllyCanParticipateInArcheryFireAndSkirmishes()); modifierProducers.put("cantlookorrevealhand", new CantLookOrRevealHand()); modifierProducers.put("cantbeassignedtoskirmish", new CantBeAssignedToSkirmish()); + modifierProducers.put("fpplayermaynotassigncharacter", new FreePeoplePlayerMayNotAssignCharacter()); } public ModifierSource getModifier(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesBurden.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesBurden.java new file mode 100644 index 000000000..37a425982 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesBurden.java @@ -0,0 +1,33 @@ +package com.gempukku.lotro.cards.build.field.effect.trigger; + +import com.gempukku.lotro.cards.build.ActionContext; +import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.FilterableSource; +import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.logic.timing.TriggerConditions; +import org.json.simple.JSONObject; + +public class RemovesBurden implements TriggerCheckerProducer { + @Override + public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(value, "filter"); + + String filter = FieldUtils.getString(value.get("filter"), "filter", "any"); + + final FilterableSource sourceFilter = environment.getFilterFactory().generateFilter(filter, environment); + + return new TriggerChecker() { + @Override + public boolean accepts(ActionContext actionContext) { + return TriggerConditions.removedBurden(actionContext.getGame(), actionContext.getEffectResult(), + sourceFilter.getFilterable(actionContext)); + } + + @Override + public boolean isBefore() { + return false; + } + }; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java index ba8cf0962..eb7a61b36 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java @@ -39,6 +39,7 @@ public class TriggerCheckerFactory { triggerCheckers.put("discardfromhand", new DiscardFromHand()); triggerCheckers.put("putsonring", new PutsOnRing()); triggerCheckers.put("addsburden", new AddsBurden()); + triggerCheckers.put("removesburden", new RemovesBurden()); triggerCheckers.put("addsthreat", new AddsThreat()); triggerCheckers.put("transferred", new Transferred()); triggerCheckers.put("killed", new Killed()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java index 6513aa6cb..55deea50c 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java @@ -431,6 +431,18 @@ public class Filters { } }; + public static final Filter inFierceSkirmish = new Filter() { + @Override + public boolean accepts(LotroGame game, PhysicalCard physicalCard) { + Skirmish skirmish = game.getGameState().getSkirmish(); + if (skirmish != null && game.getGameState().isFierceSkirmishes()) { + return (skirmish.getFellowshipCharacter() == physicalCard) + || skirmish.getShadowCharacters().contains(physicalCard); + } + return false; + } + }; + public static final Filter inPlay = new Filter() { @Override public boolean accepts(LotroGame game, PhysicalCard physicalCard) { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java index b792bb307..c8ad311a9 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/PlayNextSiteEffect.java @@ -1,5 +1,6 @@ package com.gempukku.lotro.logic.effects; +import com.gempukku.lotro.common.Filterable; import com.gempukku.lotro.game.state.LotroGame; import com.gempukku.lotro.logic.timing.Action; @@ -8,6 +9,10 @@ public class PlayNextSiteEffect extends PlaySiteEffect { super(action, playerId, null, 0); } + public PlayNextSiteEffect(Action action, String playerId, Filterable... extraSiteFilters) { + super(action, playerId, null, 0, extraSiteFilters); + } + @Override protected int getSiteNumberToPlay(LotroGame game) { return game.getGameState().getCurrentSiteNumber() + 1; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java index d7c45f41e..a89701c00 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java @@ -108,6 +108,14 @@ public class TriggerConditions { return false; } + public static boolean removedBurden(LotroGame game, EffectResult effectResult, Filterable... sourceFilters) { + if (effectResult.getType() == EffectResult.Type.REMOVE_BURDEN) { + RemoveBurdenResult burdenResult = (RemoveBurdenResult) effectResult; + return (Filters.and(sourceFilters).accepts(game, burdenResult.getSource())); + } + return false; + } + public static boolean addedThreat(LotroGame game, EffectResult effectResult, Filterable... sourceFilters) { if (effectResult.getType() == EffectResult.Type.ADD_THREAT) { AddThreatResult burdenResult = (AddThreatResult) effectResult; From 08b99c36ae6ac195c5136d642370f9f62ef69827 Mon Sep 17 00:00:00 2001 From: Troy Biesterfeld Date: Wed, 10 Mar 2021 19:14:37 -0600 Subject: [PATCH 57/74] Updates to JSON files for FOTR errata --- .../main/web/cards/set51/set03-errata.json | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index ae7f0c940..8f54429a5 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -284,11 +284,21 @@ "type": "removesBurden", "filter": "not(hobbit)" }, - "effect": { - "type": "heal", - "count": "0-2", - "filter": "choose(companion)" - } + "condition": { + "type": "perPhaseLimit", + "limit": 1 + }, + "effect": [ + { + "type": "incrementPerPhaseLimit", + "limit": 1 + }, + { + "type": "heal", + "count": "0-2", + "filter": "choose(companion)" + } + ] } } } \ No newline at end of file From a1d809778cf2ee3cc1a46e9fe39f833b58c7cfbc Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Thu, 11 Mar 2021 08:52:06 -0600 Subject: [PATCH 58/74] Adjusting merged errata Fixing some issues that weren't compiling. Removed the unneeded cantBeAssignedToSkirmishByFpPlayer modifier and replaced references to it with cantBeAssignedToSkirmishAgainst, which has a side filter. Fixed affected unit tests to pass. --- .../main/web/cards/set51/set02-errata.json | 17 +++++++--- .../main/web/cards/set51/set03-errata.json | 16 ++++----- ...FreePeoplePlayerMayNotAssignCharacter.java | 34 ------------------- .../modifier/ModifierSourceFactory.java | 1 - .../errata/set1/Galadriel_LoLErrataTests.java | 8 ++--- .../pc/errata/set1/StingErrataTests.java | 4 +-- .../errata/set1/TalentForNBSErrataTests.java | 25 ++------------ 7 files changed, 28 insertions(+), 77 deletions(-) delete mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json index 115cead9d..72a89950a 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set02-errata.json @@ -67,12 +67,14 @@ { "type": "modifier", "modifier": { - "type": "cantBeAssignedToSkirmishByFpPlayer", + "type": "cantBeAssignedToSkirmishAgainst", "condition": { "type": "canSpot", "filter": "hobbit" }, - "filter": "self" + "minion": "self", + "fpCharacter": "any", + "side": "free people" } }, { @@ -148,9 +150,14 @@ ], "effects": [ { - "type": "modifyStrength", - "filter": "memory(bearer),inSkirmishAgainst(nazgul)", - "amount": 3 + "type": "addmodifier", + "modifier": { + "type": "modifyStrength", + "filter": "memory(bearer),inSkirmishAgainst(nazgul)", + + "amount": 3 + }, + }, { "type": "takeOffRing" diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json index 8f54429a5..17f36c5b6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set03-errata.json @@ -18,7 +18,7 @@ }, "effect": { "type": "heal", - "filter": "another,elf" + "filter": "choose(another,elf)" } }, { @@ -97,8 +97,8 @@ "type": "modifyStrength", "filter": "memory(chosenAlly)", "amount": 3, - "until": "start(regroup)" - } + }, + "until": "start(regroup)" }, { "type": "allyCanParticipateInArcheryFireAndSkirmishes", @@ -126,13 +126,13 @@ { "type": "removeTwilight", "amount": 2 - }, - { - "type": "canSpot", - "count": 2, - "memorize": "culture(isengard),minion" } ], + "condition": { + "type": "canSpot", + "filter": "culture(isengard),minion", + "count": 2, + }, "effect": [ { "type": "revealRandomCardsFromHand", diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java deleted file mode 100644 index 6367b29ad..000000000 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/FreePeoplePlayerMayNotAssignCharacter.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gempukku.lotro.cards.build.field.effect.modifier; - -import com.gempukku.lotro.cards.build.*; -import com.gempukku.lotro.cards.build.field.FieldUtils; -import com.gempukku.lotro.cards.build.field.effect.appender.MultiEffectAppender; -import com.gempukku.lotro.logic.modifiers.CantBeAssignedToSkirmishModifier; -import com.gempukku.lotro.logic.modifiers.FreePeoplePlayerMayNotAssignCharacterModifier; -import com.gempukku.lotro.logic.modifiers.Modifier; -import org.json.simple.JSONObject; - -public class FreePeoplePlayerMayNotAssignCharacter implements ModifierSourceProducer { - - @Override - public ModifierSource getModifierSource(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(effectObject, "filter", "condition"); - - final JSONObject[] conditionArray = FieldUtils.getObjectArray(effectObject.get("condition"), "condition"); - final String filter = FieldUtils.getString(effectObject.get("filter"), "filter"); - - final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); - final Requirement[] requirements = environment.getRequirementFactory().getRequirements(conditionArray, environment); - - MultiEffectAppender result = new MultiEffectAppender(); - - return new ModifierSource() { - @Override - public Modifier getModifier(ActionContext actionContext) { - return new FreePeoplePlayerMayNotAssignCharacterModifier(actionContext.getSource(), - new RequirementCondition(requirements, actionContext), - filterableSource.getFilterable(actionContext)); - } - }; - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java index 680505bc7..dc6529c9f 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/modifier/ModifierSourceFactory.java @@ -56,7 +56,6 @@ public class ModifierSourceFactory { modifierProducers.put("allycanparticipateinarcheryfireandskirmishes", new AllyCanParticipateInArcheryFireAndSkirmishes()); modifierProducers.put("cantlookorrevealhand", new CantLookOrRevealHand()); modifierProducers.put("cantbeassignedtoskirmish", new CantBeAssignedToSkirmish()); - modifierProducers.put("fpplayermaynotassigncharacter", new FreePeoplePlayerMayNotAssignCharacter()); } public ModifierSource getModifier(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java index 95e435ead..8e59a5ad0 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java @@ -97,7 +97,7 @@ public class Galadriel_LoLErrataTests @Test - public void AllyHealsCappedAt2() throws DecisionResultInvalidException, CardNotFoundException { + public void AllyHealsCappedAt3() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup GenericCardTestHelper scn = GetHome6AllyScenario(); scn.FreepsMoveCharToTable("galadriel"); @@ -116,9 +116,9 @@ public class Galadriel_LoLErrataTests assertEquals(Phase.BETWEEN_TURNS, scn.GetCurrentPhase()); - //There are 5 total elf allies in play: 1 is home 3, and 1 is Galadriel herself. The rest should be eligible. - assertEquals(3, scn.FreepsGetADParamAsList("cardId").size()); + //There are 5 total elf allies in play: 1 is home 3. The rest should be eligible. + assertEquals(4, scn.FreepsGetADParamAsList("cardId").size()); assertEquals("0", scn.FreepsGetADParam("min")); - assertEquals("2", scn.FreepsGetADParam("max")); + assertEquals("3", scn.FreepsGetADParam("max")); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java index a34ee5cb5..f9537d39d 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/StingErrataTests.java @@ -104,7 +104,7 @@ public class StingErrataTests } @Test - public void StingAbilityExertsFrodoAndRevealsTwoCards() throws DecisionResultInvalidException, CardNotFoundException { + public void StingAbilityExertsFrodoAndRevealsFourCards() throws DecisionResultInvalidException, CardNotFoundException { GenericCardTestHelper scn = GetScenario(); PhysicalCardImpl frodo = scn.GetRingBearer(); @@ -124,7 +124,7 @@ public class StingErrataTests scn.FreepsUseCardAction(sting); //Reveals 2 cards - assertEquals(2, scn.FreepsGetADParamAsList("blueprintId").size()); + assertEquals(4, scn.FreepsGetADParamAsList("blueprintId").size()); assertEquals(1, scn.GetWoundsOn(frodo)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java index 48a59040d..9f6a8ad6f 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/TalentForNBSErrataTests.java @@ -36,7 +36,7 @@ public class TalentForNBSErrataTests /** * Set: 1E - * Title: *A Talent for Not Being Seen + * Title: A Talent for Not Being Seen * Side: Free Peoples * Culture: Shire * Twilight Cost: 0 @@ -50,7 +50,7 @@ public class TalentForNBSErrataTests PhysicalCardImpl talent = scn.GetFreepsCard("talent"); - assertTrue(talent.getBlueprint().isUnique()); + assertFalse(talent.getBlueprint().isUnique()); assertEquals(0, talent.getBlueprint().getTwilightCost()); assertTrue(scn.HasKeyword(talent, Keyword.STEALTH)); @@ -103,27 +103,6 @@ public class TalentForNBSErrataTests } - @Test - public void TalentDoesNotReduceIfNonHobbitCompanions() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetScenario(); - - PhysicalCardImpl frodo = scn.GetRingBearer(); - PhysicalCardImpl merry = scn.GetFreepsCard("merry"); - PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); - PhysicalCardImpl talent = scn.GetFreepsCard("talent"); - - scn.FreepsMoveCharToTable(merry, boromir); - scn.FreepsMoveCardToHand(talent); - - scn.StartGame(); - - scn.FreepsPlayCard(talent); - scn.FreepsSkipCurrentPhaseAction(); - - // 3 for Frodo/Merry/Boromir, 1 for the site, Talent does not trigger - assertEquals(4, scn.GetTwilight()); - } } From b1a42431d85d0f97d2d6fb8b6e297c615c8ad73b Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 12 Mar 2021 20:23:36 -0600 Subject: [PATCH 59/74] Quick Savagery test --- .../src/main/web/cards/set51/set01-errata.json | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index 97a2a14ab..3b71edc98 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -191,13 +191,7 @@ "keyword": "skirmish", "effects": { "type": "event", - "effect": { - "type": "choice", - "texts": [ - "Make an Uruk-hai strength +2", - "Make an Uruk-hai strength +4, and fierce until the regroup phase" - ], - "effects": [ + "effect": [ { "type": "modifyStrength", "filter": "choose(uruk-hai)", @@ -211,12 +205,6 @@ "filter": "companion" }, "effect": [ - { - "type": "modifyStrength", - "filter": "choose(uruk-hai)", - "amount": 4, - "memorize": "chosenUrukHai" - }, { "type": "addKeyword", "filter": "memory(chosenUrukHai)", @@ -226,7 +214,7 @@ ] } ] - } + } }, "51_195": { From 1ee5611dd58b9f8f59195814a9fea061cd49e6d4 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 12 Mar 2021 20:30:57 -0600 Subject: [PATCH 60/74] removing tests temporarily --- .../errata/set2/FlamingBrandErrataTests.java | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index 5dec844d3..932cd05b7 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -107,55 +107,55 @@ public class FlamingBrandErrataTests assertEquals(2, scn.GetAttachedCards(aragorn).size()); } - @Test - public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException { - //Pre-game setup - GenericCardTestHelper scn = GetScenario(); - - PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); - PhysicalCardImpl brand = scn.GetFreepsCard("brand"); - PhysicalCardImpl runner = scn.GetShadowCard("runner"); - PhysicalCardImpl nazgul = scn.GetShadowCard("nazgul"); - - scn.FreepsMoveCharToTable(aragorn); - scn.FreepsMoveCardToHand(brand); - - scn.ShadowMoveCharToTable(runner); - scn.ShadowMoveCharToTable(nazgul); - - scn.StartGame(); - - assertEquals(8, scn.GetStrength(aragorn)); - scn.FreepsPlayCard(brand); - assertEquals(9, scn.GetStrength(aragorn)); - - scn.SkipToPhase(Phase.ASSIGNMENT); - scn.SkipCurrentPhaseActions(); - scn.FreepsAssignToMinions(aragorn, runner); - //skip assigning the nazgul - scn.SkipCurrentPhaseActions(); - - //start goblin skirmish - scn.FreepsResolveSkirmish(aragorn); - - //goblin shouldn't trigger Flaming Brand's action - assertEquals(0, scn.FreepsGetAvailableActions().size()); - scn.SkipCurrentPhaseActions(); - - //assignment for fierce skirmish - scn.SkipCurrentPhaseActions(); - scn.FreepsAssignToMinions(aragorn, nazgul); - scn.FreepsResolveSkirmish(aragorn); - - assertEquals(1, scn.FreepsGetAvailableActions().size()); - assertTrue(scn.FreepsCardActionAvailable(brand)); - - assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); - scn.FreepsUseCardAction(brand); - assertEquals(11, scn.GetStrength(aragorn)); - assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); - - //Brand is discarded - assertFalse(scn.IsAttachedTo(brand, aragorn)); - } +// @Test +// public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException { +// //Pre-game setup +// GenericCardTestHelper scn = GetScenario(); +// +// PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); +// PhysicalCardImpl brand = scn.GetFreepsCard("brand"); +// PhysicalCardImpl runner = scn.GetShadowCard("runner"); +// PhysicalCardImpl nazgul = scn.GetShadowCard("nazgul"); +// +// scn.FreepsMoveCharToTable(aragorn); +// scn.FreepsMoveCardToHand(brand); +// +// scn.ShadowMoveCharToTable(runner); +// scn.ShadowMoveCharToTable(nazgul); +// +// scn.StartGame(); +// +// assertEquals(8, scn.GetStrength(aragorn)); +// scn.FreepsPlayCard(brand); +// assertEquals(9, scn.GetStrength(aragorn)); +// +// scn.SkipToPhase(Phase.ASSIGNMENT); +// scn.SkipCurrentPhaseActions(); +// scn.FreepsAssignToMinions(aragorn, runner); +// //skip assigning the nazgul +// scn.SkipCurrentPhaseActions(); +// +// //start goblin skirmish +// scn.FreepsResolveSkirmish(aragorn); +// +// //goblin shouldn't trigger Flaming Brand's action +// assertEquals(0, scn.FreepsGetAvailableActions().size()); +// scn.SkipCurrentPhaseActions(); +// +// //assignment for fierce skirmish +// scn.SkipCurrentPhaseActions(); +// scn.FreepsAssignToMinions(aragorn, nazgul); +// scn.FreepsResolveSkirmish(aragorn); +// +// assertEquals(1, scn.FreepsGetAvailableActions().size()); +// assertTrue(scn.FreepsCardActionAvailable(brand)); +// +// assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); +// scn.FreepsUseCardAction(brand); +// assertEquals(11, scn.GetStrength(aragorn)); +// assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); +// +// //Brand is discarded +// assertFalse(scn.IsAttachedTo(brand, aragorn)); +// } } From e64f8acdba7733277d27ffdd5c66715971440f0c Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 12 Mar 2021 21:57:57 -0600 Subject: [PATCH 61/74] Committing missing unit test file --- .../lotro/cards/GenericCardTestHelper.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index 2cef73d10..016e05992 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -180,6 +180,8 @@ public class GenericCardTestHelper extends AbstractAtTest { return decision.getDecisionParameters(); } + //public boolean HasItemIn + public void FreepsUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, name)); } public void FreepsUseCardAction(PhysicalCardImpl card) throws DecisionResultInvalidException { playerDecided(P1, getCardActionId(P1, "Use " + GameUtils.getFullName(card))); } public void ShadowUseCardAction(String name) throws DecisionResultInvalidException { playerDecided(P2, getCardActionId(P2, name)); } @@ -326,11 +328,21 @@ public class GenericCardTestHelper extends AbstractAtTest { } - public void FreepsAssignToMinion(String name, String target) throws DecisionResultInvalidException { FreepsAssignToMinion(GetFreepsCard(name), GetShadowCard(target)); } - public void FreepsAssignToMinion(PhysicalCardImpl comp, PhysicalCardImpl minion) throws DecisionResultInvalidException { - playerDecided(P1, comp.getCardId() + " " + minion.getCardId()); + public void FreepsAssignToMinions(PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException { AssignToMinions(P1, comp, minions); } + public void ShadowAssignToMinions(PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException { AssignToMinions(P2, comp, minions); } + public void AssignToMinions(String player, PhysicalCardImpl comp, PhysicalCardImpl...minions) throws DecisionResultInvalidException { + String result = comp.getCardId() + ""; + + for (PhysicalCardImpl minion : minions) { + result += " " + minion.getCardId(); + } + + playerDecided(player, result); } - public void FreepsAssignToMinions(PhysicalCardImpl[]... groups) throws DecisionResultInvalidException { + + public void FreepsAssignToMinions(PhysicalCardImpl[]...groups) throws DecisionResultInvalidException { AssignToMinions(P1, groups); } + public void ShadowAssignToMinions(PhysicalCardImpl[]...groups) throws DecisionResultInvalidException { AssignToMinions(P2, groups); } + public void AssignToMinions(String player, PhysicalCardImpl[]...groups) throws DecisionResultInvalidException { String result = ""; for (PhysicalCardImpl[] group : groups) { @@ -342,9 +354,10 @@ public class GenericCardTestHelper extends AbstractAtTest { result += ","; } - playerDecided(P1, result); + playerDecided(player, result); } + public List FreepsGetAttachedCards(String name) { return GetAttachedCards(GetFreepsCard(name)); } public List GetAttachedCards(PhysicalCardImpl card) { return (List)(List)_game.getGameState().getAttachedCards(card); @@ -399,6 +412,9 @@ public class GenericCardTestHelper extends AbstractAtTest { public void FreepsChooseToMove() throws DecisionResultInvalidException { playerDecided(P1, "0"); } public void FreepsChooseToStay() throws DecisionResultInvalidException { playerDecided(P1, "1"); } + public boolean FreepsHasOptionalTriggerAvailable() throws DecisionResultInvalidException { return FreepsDecisionAvailable("Optional Response"); } + public boolean ShadowHasOptionalTriggerAvailable() throws DecisionResultInvalidException { return ShadowDecisionAvailable("Optional Response"); } + public void FreepsAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "0"); } public void FreepsDeclineOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P1, "1"); } public void ShadowAcceptOptionalTrigger() throws DecisionResultInvalidException { playerDecided(P2, "0"); } From 8fe56b02f0da92120815ae148c936df3e8716ac5 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 12 Mar 2021 21:59:02 -0600 Subject: [PATCH 62/74] Reverting brand test removal --- .../errata/set2/FlamingBrandErrataTests.java | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java index 932cd05b7..5dec844d3 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set2/FlamingBrandErrataTests.java @@ -107,55 +107,55 @@ public class FlamingBrandErrataTests assertEquals(2, scn.GetAttachedCards(aragorn).size()); } -// @Test -// public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException { -// //Pre-game setup -// GenericCardTestHelper scn = GetScenario(); -// -// PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); -// PhysicalCardImpl brand = scn.GetFreepsCard("brand"); -// PhysicalCardImpl runner = scn.GetShadowCard("runner"); -// PhysicalCardImpl nazgul = scn.GetShadowCard("nazgul"); -// -// scn.FreepsMoveCharToTable(aragorn); -// scn.FreepsMoveCardToHand(brand); -// -// scn.ShadowMoveCharToTable(runner); -// scn.ShadowMoveCharToTable(nazgul); -// -// scn.StartGame(); -// -// assertEquals(8, scn.GetStrength(aragorn)); -// scn.FreepsPlayCard(brand); -// assertEquals(9, scn.GetStrength(aragorn)); -// -// scn.SkipToPhase(Phase.ASSIGNMENT); -// scn.SkipCurrentPhaseActions(); -// scn.FreepsAssignToMinions(aragorn, runner); -// //skip assigning the nazgul -// scn.SkipCurrentPhaseActions(); -// -// //start goblin skirmish -// scn.FreepsResolveSkirmish(aragorn); -// -// //goblin shouldn't trigger Flaming Brand's action -// assertEquals(0, scn.FreepsGetAvailableActions().size()); -// scn.SkipCurrentPhaseActions(); -// -// //assignment for fierce skirmish -// scn.SkipCurrentPhaseActions(); -// scn.FreepsAssignToMinions(aragorn, nazgul); -// scn.FreepsResolveSkirmish(aragorn); -// -// assertEquals(1, scn.FreepsGetAvailableActions().size()); -// assertTrue(scn.FreepsCardActionAvailable(brand)); -// -// assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); -// scn.FreepsUseCardAction(brand); -// assertEquals(11, scn.GetStrength(aragorn)); -// assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); -// -// //Brand is discarded -// assertFalse(scn.IsAttachedTo(brand, aragorn)); -// } + @Test + public void SkirmishAbilityAvailableWhenSkirmishingNazgul() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl brand = scn.GetFreepsCard("brand"); + PhysicalCardImpl runner = scn.GetShadowCard("runner"); + PhysicalCardImpl nazgul = scn.GetShadowCard("nazgul"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCardToHand(brand); + + scn.ShadowMoveCharToTable(runner); + scn.ShadowMoveCharToTable(nazgul); + + scn.StartGame(); + + assertEquals(8, scn.GetStrength(aragorn)); + scn.FreepsPlayCard(brand); + assertEquals(9, scn.GetStrength(aragorn)); + + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.SkipCurrentPhaseActions(); + scn.FreepsAssignToMinions(aragorn, runner); + //skip assigning the nazgul + scn.SkipCurrentPhaseActions(); + + //start goblin skirmish + scn.FreepsResolveSkirmish(aragorn); + + //goblin shouldn't trigger Flaming Brand's action + assertEquals(0, scn.FreepsGetAvailableActions().size()); + scn.SkipCurrentPhaseActions(); + + //assignment for fierce skirmish + scn.SkipCurrentPhaseActions(); + scn.FreepsAssignToMinions(aragorn, nazgul); + scn.FreepsResolveSkirmish(aragorn); + + assertEquals(1, scn.FreepsGetAvailableActions().size()); + assertTrue(scn.FreepsCardActionAvailable(brand)); + + assertFalse(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + scn.FreepsUseCardAction(brand); + assertEquals(11, scn.GetStrength(aragorn)); + assertTrue(scn.HasKeyword(aragorn, Keyword.DAMAGE)); + + //Brand is discarded + assertFalse(scn.IsAttachedTo(brand, aragorn)); + } } From 9461ed755c75a1ea421e22844d5f99de8df785d7 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 12 Mar 2021 22:37:39 -0600 Subject: [PATCH 63/74] Updating image js file with all X-list images --- .../src/main/web/js/gemp-022/PC_Cards.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index 5e2d2fadd..4ef29e375 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -78,8 +78,39 @@ var PCCards = { '51_248': 'https://i.lotrtcgpc.net/errata/FOTR/51_248.jpg', '51_313': 'https://i.lotrtcgpc.net/errata/FOTR/51_313.jpg', '51_316': 'https://i.lotrtcgpc.net/errata/FOTR/51_316.jpg', + '52_75': 'https://i.lotrtcgpc.net/errata/FOTR/52_075.jpg', + '52_101': 'https://i.lotrtcgpc.net/errata/FOTR/52_101.jpg', + '52_108': 'https://i.lotrtcgpc.net/errata/FOTR/52_108.jpg', '52_121': 'https://i.lotrtcgpc.net/errata/FOTR/52_121.jpg', + + '53_17': 'https://i.lotrtcgpc.net/errata/FOTR/53_017.jpg', '53_38': 'https://i.lotrtcgpc.net/errata/FOTR/53_038.jpg', + '53_67': 'https://i.lotrtcgpc.net/errata/FOTR/53_067.jpg', '53_106': 'https://i.lotrtcgpc.net/errata/FOTR/53_106.jpg', + '53_108': 'https://i.lotrtcgpc.net/errata/FOTR/53_108.jpg', + '53_113': 'https://i.lotrtcgpc.net/errata/FOTR/53_113.jpg', + + '54_73': 'https://i.lotrtcgpc.net/errata/FOTR/54_073.jpg', + '54_192': 'https://i.lotrtcgpc.net/errata/FOTR/54_192.jpg', + '54_276': 'https://i.lotrtcgpc.net/errata/FOTR/54_276.jpg', + '54_304': 'https://i.lotrtcgpc.net/errata/FOTR/54_304.jpg', + + '57_49': 'https://i.lotrtcgpc.net/errata/FOTR/57_049.jpg', + '57_96': 'https://i.lotrtcgpc.net/errata/FOTR/57_096.jpg', + + '58_1': 'https://i.lotrtcgpc.net/errata/FOTR/58_001.jpg', + + '60_2': 'https://i.lotrtcgpc.net/errata/FOTR/60_002.jpg', + '60_11': 'https://i.lotrtcgpc.net/errata/FOTR/60_011.jpg', + '60_91': 'https://i.lotrtcgpc.net/errata/FOTR/60_091.jpg', + + '61_100': 'https://i.lotrtcgpc.net/errata/FOTR/61_100.jpg', + '61_114': 'https://i.lotrtcgpc.net/errata/FOTR/61_114.jpg', + '61_132': 'https://i.lotrtcgpc.net/errata/FOTR/61_132.jpg', + '61_31': 'https://i.lotrtcgpc.net/errata/FOTR/61_031.jpg', + + '63_188': 'https://i.lotrtcgpc.net/errata/FOTR/63_188.jpg', + + '65_64': 'https://i.lotrtcgpc.net/errata/FOTR/65_064.jpg', } \ No newline at end of file From 935f3c10e5bb112526a9894de2bb2aa03952125a Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 12 Mar 2021 22:39:24 -0600 Subject: [PATCH 64/74] Fixed missing Saruman's Snows image --- gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js | 1 + 1 file changed, 1 insertion(+) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index 4ef29e375..af6c3e4c9 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -72,6 +72,7 @@ var PCCards = { '51_45': 'https://i.lotrtcgpc.net/errata/FOTR/51_045.jpg', '51_80': 'https://i.lotrtcgpc.net/errata/FOTR/51_080.jpg', '51_108': 'https://i.lotrtcgpc.net/errata/FOTR/51_108.jpg', + '51_138': 'https://i.lotrtcgpc.net/errata/FOTR/51_138.jpg', '51_139': 'https://i.lotrtcgpc.net/errata/FOTR/51_139.jpg', '51_195': 'https://i.lotrtcgpc.net/errata/FOTR/51_195.jpg', '51_234': 'https://i.lotrtcgpc.net/errata/FOTR/51_234.jpg', From 769badd1327e76939ac1d2a7b6b56670c30ecc39 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 12 Mar 2021 23:53:10 -0600 Subject: [PATCH 65/74] fixing savagery --- .../gemp-lotr-async/src/main/web/cards/set51/set01-errata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index 7b3d2b550..46a85fec6 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -195,12 +195,13 @@ { "type": "modifyStrength", "filter": "choose(uruk-hai)", + "memorize": "chosenUrukHai", "amount": 2 }, { "type": "conditional", "condition": { - "type": "canSpot", + "type": "chooseHowManyToSpot", "count": 5, "filter": "companion" }, From f8d7c6b5a35d96fed59438121be2ebfaa05b1f9f Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 13 Mar 2021 02:36:56 -0600 Subject: [PATCH 66/74] VPack1 Gondor Implementation The five gondor cards are now implemented. Lords of Gondor requires additional development to be complete (see commented out failing test). Added ReplaceInAssignment effect. Updated DiscardFromHand effect to be sensitive to the side performing the discarding. --- .../src/main/web/cards/set101/vpack1.json | 234 +++++++++--------- .../main/web/cards/set51/set01-errata.json | 2 +- .../field/effect/EffectAppenderFactory.java | 1 + .../effect/appender/ReplaceInAssignment.java | 47 ++++ .../field/effect/trigger/DiscardFromHand.java | 19 +- .../lotro/cards/GenericCardTestHelper.java | 12 + .../pc/vset1/vpack1/Card_V1_001Tests.java | 147 +++++++++++ .../pc/vset1/vpack1/Card_V1_002Tests.java | 125 ++++++++++ .../pc/vset1/vpack1/Card_V1_003Tests.java | 95 +++++++ .../pc/vset1/vpack1/Card_V1_004Tests.java | 106 ++++++++ .../pc/vset1/vpack1/Card_V1_005Tests.java | 126 ++++++++++ 11 files changed, 785 insertions(+), 129 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReplaceInAssignment.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json index 86c488a59..393d3d096 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json @@ -1,5 +1,5 @@ { - "101_1001": { + "101_001": { "side": "free_people", "culture": "Gondor", "title": "*The Lords of Gondor Have Returned", @@ -41,55 +41,50 @@ ] }, - "101_1002": { + "101_002": { "side": "free_people", "culture": "Gondor", - "title": "*I Will not Let the White City Fall", + "title": "*I Will Not Let the White City Fall", "type": "condition", "cost": 2, "keyword": "support area", "effects": [ { - "type": "activated", - "phase": "skirmish", - "condition": { - "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", + "type": "trigger", + "trigger": { + "type": "losesSkirmish", + "filter": "name(Boromir)" + }, + "effect": { + "type": "modifyStrength", + "filter": "choose(name(Aragorn))", + "amount": 2, + "until": "start(regroup)" }, - "cost": [ - { - "type": "memorize", - "filter": "bearer", - "memory": "bearer" - }, - { - "type": "discard", - "filter": "self" - } - ], - "effect":[ - { - "type": "modifyStrength", - "filter": "memory(bearer)", - "amount": 3 - }, - { - "type": "addKeyword", - "filter": "memory(bearer)", - "keyword": "damage+1" - } - ] }, + { + "type": "trigger", + "trigger": { + "type": "losesSkirmish", + "filter": "name(Aragorn)" + }, + "effect": { + "type": "modifyStrength", + "filter": "choose(name(Boromir))", + "amount": 2, + "until": "start(regroup)" + }, + } ] }, - "101_1003": { + "101_003": { "side": "free_people", "culture": "Gondor", "title": "*Boromir", "subtitle": "The Redeemed", "type": "companion", - "cost": 2, + "cost": 3, "race": "man", "strength": 7, "vitality": 3, @@ -97,40 +92,49 @@ "signet": "aragorn", "effects": [ { - "type": "activated", - "phase": "skirmish", - "condition": { - "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", - }, - "cost": [ - { - "type": "memorize", - "filter": "bearer", - "memory": "bearer" - }, - { - "type": "discard", - "filter": "self" + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "self", + "keyword": "defender+1", + "condition": { + "type": "canSpot", + "filter": "companion,culture(shire)", + "count": 2 } - ], - "effect":[ - { - "type": "modifyStrength", - "filter": "memory(bearer)", - "amount": 3 - }, - { - "type": "addKeyword", - "filter": "memory(bearer)", - "keyword": "damage+1" - } - ] + } }, + { + "type": "modifier", + "modifier": { + "type": "modifyStrength", + "filter": "self", + "amount": 1, + "condition": { + "type": "canSpot", + "filter": "companion,culture(shire)", + "count": 4 + } + } + }, + { + "type": "modifier", + "modifier": { + "type": "addKeyword", + "filter": "self", + "keyword": "damage+1", + "condition": { + "type": "canSpot", + "filter": "companion,culture(shire)", + "count": 4 + } + } + }, + ] }, - "101_1004": { + "101_004": { "side": "free_people", "culture": "Gondor", "title": "*Loud and Clear It Sounds", @@ -139,82 +143,68 @@ "keyword": "support area", "effects": [ { - "type": "activated", - "phase": "skirmish", - "condition": { - "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", + "type": "trigger", + "optional": true, + "trigger": { + "type": "assignedToSkirmish", + "filter": "companion,culture(shire)", + "side": "shadow", + "memorizeAssigned": "assignedHobbit", + "memorizeAgainst": "assignedMinion" }, "cost": [ { - "type": "memorize", - "filter": "bearer", - "memory": "bearer" - }, + "type": "exert", + "count": 1, + "filter": "choose(companion,culture(gondor))", + "memorize": "newAssignee" + }, { "type": "discard", "filter": "self" } ], - "effect":[ - { - "type": "modifyStrength", - "filter": "memory(bearer)", - "amount": 3 - }, - { - "type": "addKeyword", - "filter": "memory(bearer)", - "keyword": "damage+1" - } - ] - }, + "effect": { + "type": "replaceInAssignment", + "filter": "memory(assignedHobbit)", + "with": "memory(newAssignee)" + } + } ] }, - "101_1005": { + "101_005": { "side": "free_people", "culture": "Gondor", "title": "Remnant of Numenor", "type": "condition", "cost": 1, "keyword": "support area", - "effects": [ - { - "type": "activated", - "phase": "skirmish", - "condition": { - "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", - }, - "cost": [ - { - "type": "memorize", - "filter": "bearer", - "memory": "bearer" - }, - { - "type": "discard", - "filter": "self" - } - ], - "effect":[ - { - "type": "modifyStrength", - "filter": "memory(bearer)", - "amount": 3 - }, - { - "type": "addKeyword", - "filter": "memory(bearer)", - "keyword": "damage+1" - } - ] + "condition": { + "type": "canSpot", + "filter": "companion,culture(gondor)" + }, + "effects": { + "type": "trigger", + "optional": true, + "trigger": { + "type": "discardFromHand", + "filter": "any", + "player": "shadowPlayer" }, - ] + "cost": { + "type": "addTwilight", + "amount": 1 + }, + "effect": { + "type": "shuffleCardsFromDiscardIntoDrawDeck", + "filter": "choose(culture(gondor))", + "count": 1 + } + } }, - "101_1006": { + "101_006": { "side": "shadow", "culture": "Sauron", "title": "*Great Wolf Chief", @@ -263,7 +253,7 @@ ] }, - "101_1007": { + "101_007": { "side": "shadow", "culture": "Sauron", "title": "Hollin Snarler", @@ -312,7 +302,7 @@ ] }, - "101_1008": { + "101_008": { "side": "shadow", "culture": "Sauron", "title": "Hound of Sauron", @@ -361,7 +351,7 @@ ] }, - "101_1009": { + "101_009": { "side": "shadow", "culture": "Sauron", "title": "*The Hunt is Up!", @@ -403,7 +393,7 @@ ] }, - "101_1010": { + "101_010": { "side": "shadow", "culture": "Sauron", "title": "I See You", diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json index 46a85fec6..dbc6aa7ee 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set51/set01-errata.json @@ -201,7 +201,7 @@ { "type": "conditional", "condition": { - "type": "chooseHowManyToSpot", + "type": "canSpot", "count": 5, "filter": "companion" }, diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java index 8a17b3b19..3e02e103e 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java @@ -29,6 +29,7 @@ public class EffectAppenderFactory { effectAppenderProducers.put("wound", new Wound()); effectAppenderProducers.put("heal", new Heal()); effectAppenderProducers.put("replaceinskirmish", new ReplaceInSkirmish()); + effectAppenderProducers.put("replaceinassignment", new ReplaceInAssignment()); effectAppenderProducers.put("canttakemorewoundsthan", new CantTakeMoreWoundsThan()); effectAppenderProducers.put("canttakewounds", new CantTakeWounds()); effectAppenderProducers.put("choice", new Choice()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReplaceInAssignment.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReplaceInAssignment.java new file mode 100644 index 000000000..858fef97e --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReplaceInAssignment.java @@ -0,0 +1,47 @@ +package com.gempukku.lotro.cards.build.field.effect.appender; + +import com.gempukku.lotro.cards.build.ActionContext; +import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.FilterableSource; +import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.cards.build.field.effect.EffectAppender; +import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.CardResolver; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.logic.actions.CostToEffectAction; +import com.gempukku.lotro.logic.effects.ReplaceFpCharacterInAssignmentEffect; +import com.gempukku.lotro.logic.timing.DoNothingEffect; +import com.gempukku.lotro.logic.timing.Effect; +import org.json.simple.JSONObject; + +public class ReplaceInAssignment implements EffectAppenderProducer { + @Override + public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject, "filter", "with"); + + final String filter = FieldUtils.getString(effectObject.get("filter"), "filter"); + final String with = FieldUtils.getString(effectObject.get("with"), "with"); + + MultiEffectAppender result = new MultiEffectAppender(); + result.addEffectAppender( + CardResolver.resolveCard(filter, "_oldAssignee", "you", "Choose assigned character to replace", environment)); + result.addEffectAppender( + CardResolver.resolveCard(with, "_newAssignee", "you", "Choose character to replace with in assignment", environment)); + result.addEffectAppender( + new DelayedAppender() { + @Override + protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) { + final PhysicalCard oldCard = actionContext.getCardFromMemory("_oldAssignee"); + final PhysicalCard newCard = actionContext.getCardFromMemory("_newAssignee"); + if (oldCard != null && newCard != null) + return new ReplaceFpCharacterInAssignmentEffect(newCard, oldCard); + else + return new DoNothingEffect(); + } + }); + + return result; + } + +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java index c5189bd66..5cf299eb5 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/DiscardFromHand.java @@ -1,22 +1,23 @@ package com.gempukku.lotro.cards.build.field.effect.trigger; -import com.gempukku.lotro.cards.build.ActionContext; -import com.gempukku.lotro.cards.build.CardGenerationEnvironment; -import com.gempukku.lotro.cards.build.FilterableSource; -import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.*; import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver; import com.gempukku.lotro.logic.timing.TriggerConditions; import com.gempukku.lotro.logic.timing.results.DiscardCardFromHandResult; +import com.gempukku.lotro.logic.timing.results.DiscardCardsFromPlayResult; import org.json.simple.JSONObject; public class DiscardFromHand implements TriggerCheckerProducer { @Override public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value, "filter", "memorize"); + FieldUtils.validateAllowedFields(value, "filter", "memorize", "player"); final String filter = FieldUtils.getString(value.get("filter"), "filter", "any"); final String memorize = FieldUtils.getString(value.get("memorize"), "memorize"); + final String player = FieldUtils.getString(value.get("player"), "player"); + PlayerSource playerSource = (player != null) ? PlayerResolver.resolvePlayer(player, environment) : null; final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment); return new TriggerChecker() { @@ -27,8 +28,14 @@ public class DiscardFromHand implements TriggerCheckerProducer { @Override public boolean accepts(ActionContext actionContext) { - final boolean result = TriggerConditions.forEachDiscardedFromHand(actionContext.getGame(), actionContext.getEffectResult(), + boolean result = TriggerConditions.forEachDiscardedFromHand(actionContext.getGame(), actionContext.getEffectResult(), filterableSource.getFilterable(actionContext)); + if (result && playerSource != null) { + // Need to check if it was that player discarding the card + final String performingPlayer = ((DiscardCardFromHandResult) actionContext.getEffectResult()).getSource().getOwner(); + if (performingPlayer == null || !performingPlayer.equals(playerSource.getPlayer(actionContext))) + result = false; + } if (result && memorize != null) { actionContext.setCardMemory(memorize, ((DiscardCardFromHandResult) actionContext.getEffectResult()).getDiscardedCard()); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index 016e05992..fa6237a35 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -270,6 +270,15 @@ public class GenericCardTestHelper extends AbstractAtTest { Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.SUPPORT)); } + public void FreepsMoveCardToDiscard(String cardName) { FreepsMoveCardToSupportArea(GetFreepsCard(cardName)); } + public void FreepsMoveCardToDiscard(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DISCARD)); + } + public void ShadowMoveCardToDiscard(String cardName) { ShadowMoveCardToSupportArea(GetShadowCard(cardName)); } + public void ShadowMoveCardToDiscard(PhysicalCardImpl...cards) { + Arrays.stream(cards).forEach(card -> MoveCardToZone(P1, card, Zone.DISCARD)); + } + public void MoveCardToZone(String player, PhysicalCardImpl card, Zone zone) { if(card.getZone() != null) { @@ -409,6 +418,9 @@ public class GenericCardTestHelper extends AbstractAtTest { _game.getModifiersEnvironment().addUntilEndOfTurnModifier(mod); } + public void FreepsChoose(String choice) throws DecisionResultInvalidException { playerDecided(P1, choice); } + public void ShadowChoose(String choice) throws DecisionResultInvalidException { playerDecided(P2, choice); } + public void FreepsChooseToMove() throws DecisionResultInvalidException { playerDecided(P1, "0"); } public void FreepsChooseToStay() throws DecisionResultInvalidException { playerDecided(P1, "1"); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java new file mode 100644 index 000000000..2e1b7a6d4 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java @@ -0,0 +1,147 @@ +package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class Card_V1_001Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("aragorn", "1_89"); + put("boromir", "1_97"); + put("lords", "101_001"); + + put("runner1", "1_178"); + put("runner2", "1_178"); + }} + ); + } + + + @Test + public void LordsStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: VSet1, VPack1 + * Title: The Lords of Gondor Have Returned + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 2 + * Type: Condition + * Subtype: Support Area + * Game Text: While Boromir is assigned to skirmish more than one minion, Aragorn is strength +3. + * While Aragorn is assigned to skirmish more than one minion, Boromir is strength +3. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl lords = scn.GetFreepsCard("lords"); + + assertTrue(scn.HasKeyword(lords, Keyword.SUPPORT_AREA)); + assertEquals(2, lords.getBlueprint().getTwilightCost()); + assertTrue(lords.getBlueprint().isUnique()); + } + +// @Test +// public void OneIsBuffedWhenOtherAssignedMultiple() throws DecisionResultInvalidException, CardNotFoundException { +// //Pre-game setup +// GenericCardTestHelper scn = GetScenario(); +// +// PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); +// PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); +// PhysicalCardImpl lords = scn.GetFreepsCard("lords"); +// +// scn.FreepsMoveCharToTable(aragorn); +// scn.FreepsMoveCharToTable(boromir); +// scn.FreepsMoveCardToHand(lords); +// +// PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); +// PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); +// +// scn.ShadowMoveCharToTable(runner1); +// scn.ShadowMoveCharToTable(runner2); +// +// scn.StartGame(); +// scn.FreepsPlayCard(lords); +// scn.SkipToPhase(Phase.ASSIGNMENT); +// +// assertEquals(7, scn.GetStrength(boromir)); +// assertEquals(8, scn.GetStrength(aragorn)); +// +// scn.FreepsSkipCurrentPhaseAction(); +// scn.ShadowSkipCurrentPhaseAction(); +// +// //Let shadow assign so we don't have to worry about defender bonuses +// scn.FreepsSkipCurrentPhaseAction(); +// scn.ShadowAssignToMinions(boromir, runner1, runner2); +// +// assertEquals(7, scn.GetStrength(boromir)); +// assertEquals(11, scn.GetStrength(aragorn)); +// +// scn.FreepsResolveSkirmish(boromir); +// +// scn.SkipToPhase(Phase.REGROUP); +// scn.SkipCurrentPhaseActions(); +// scn.ShadowSkipCurrentPhaseAction(); +// scn.FreepsChooseToMove(); +// +// scn.SkipToPhase(Phase.ASSIGNMENT); +// +// //Let shadow assign so we don't have to worry about defender bonuses +// scn.FreepsSkipCurrentPhaseAction(); +// scn.ShadowAssignToMinions(aragorn, runner1, runner2); +// +// assertEquals(10, scn.GetStrength(boromir)); +// assertEquals(8, scn.GetStrength(aragorn)); +// } + + + @Test + public void NoBuffsWhenAssignedSingle() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl lords = scn.GetFreepsCard("lords"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCharToTable(boromir); + scn.FreepsMoveCardToHand(lords); + + PhysicalCardImpl runner1 = scn.GetShadowCard("runner1"); + PhysicalCardImpl runner2 = scn.GetShadowCard("runner2"); + + scn.ShadowMoveCharToTable(runner1); + scn.ShadowMoveCharToTable(runner2); + + scn.StartGame(); + scn.FreepsPlayCard(lords); + scn.SkipToPhase(Phase.ASSIGNMENT); + + assertEquals(7, scn.GetStrength(boromir)); + assertEquals(8, scn.GetStrength(aragorn)); + + scn.SkipCurrentPhaseActions(); + + scn.FreepsAssignToMinions(new PhysicalCardImpl[]{ boromir, runner1 }, new PhysicalCardImpl[]{ aragorn, runner2 }); + + assertEquals(7, scn.GetStrength(boromir)); + assertEquals(8, scn.GetStrength(aragorn)); + + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java new file mode 100644 index 000000000..1feef137d --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java @@ -0,0 +1,125 @@ +package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class Card_V1_002Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("aragorn", "1_89"); + put("boromir", "1_97"); + put("whitecity", "101_002"); + + put("attea", "1_229"); + put("cantea", "1_230"); + }} + ); + } + + + @Test + public void WhiteCityStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: VSet1, VPack1 + * Title: *I Will Not Let the White City Fall + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 2 + * Type: Condition + * Subtype: Support Area + * Game Text: Each time Boromir loses a skirmish, make Aragorn strength +2 until the regroup phase. + * Each time Aragorn loses a skirmish, make Boromir strength +2 until the regroup phase. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl whitecity = scn.GetFreepsCard("whitecity"); + + assertTrue(scn.HasKeyword(whitecity, Keyword.SUPPORT_AREA)); + assertEquals(2, whitecity.getBlueprint().getTwilightCost()); + assertTrue(whitecity.getBlueprint().isUnique()); + } + + @Test + public void OneIsBuffedWhenOtherLosesSkirmish() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl whitecity = scn.GetFreepsCard("whitecity"); + + scn.FreepsMoveCharToTable(aragorn); + scn.FreepsMoveCharToTable(boromir); + scn.FreepsMoveCardToHand(whitecity); + + PhysicalCardImpl cantea = scn.GetShadowCard("cantea"); + PhysicalCardImpl attea = scn.GetShadowCard("attea"); + scn.ShadowMoveCharToTable(cantea, attea); + + scn.StartGame(); + scn.FreepsPlayCard(whitecity); + scn.SkipToPhase(Phase.ASSIGNMENT); + + assertEquals(7, scn.GetStrength(boromir)); + assertEquals(8, scn.GetStrength(aragorn)); + + scn.SkipCurrentPhaseActions(); + + //Standard assignment + scn.FreepsAssignToMinions(new PhysicalCardImpl[] { aragorn, cantea}, new PhysicalCardImpl[] { boromir, attea}); + + scn.FreepsResolveSkirmish(aragorn); + scn.SkipCurrentPhaseActions(); + scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger + // 14 > 8, Aragorn lost, Boromir should be buffed + assertEquals(9, scn.GetStrength(boromir)); + assertEquals(8, scn.GetStrength(aragorn)); + + scn.FreepsResolveSkirmish(boromir); + scn.SkipCurrentPhaseActions(); + scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger + // 12 > 9, Boromir lost, Aragorn should be buffed + assertEquals(9, scn.GetStrength(boromir)); + assertEquals(10, scn.GetStrength(aragorn)); + + //Fierce assignment + scn.FreepsSkipCurrentPhaseAction(); + scn.ShadowSkipCurrentPhaseAction(); + + scn.FreepsAssignToMinions(new PhysicalCardImpl[] { aragorn, cantea}, new PhysicalCardImpl[] { boromir, attea}); + scn.FreepsResolveSkirmish(boromir); + scn.SkipCurrentPhaseActions(); + scn.FreepsAcceptOptionalTrigger(); //Have to resolve the skirmish and the condition trigger + // 10 > 9, Boromir lost again, Aragorn should be buffed again + assertEquals(9, scn.GetStrength(boromir)); + assertEquals(12, scn.GetStrength(aragorn)); + + scn.FreepsResolveSkirmish(aragorn); + //Aragorn now wins his skirmish, so there's no loss trigger to evaluate + + scn.SkipToPhase(Phase.REGROUP); + + //strength should be back to normal + assertEquals(7, scn.GetStrength(boromir)); + assertEquals(8, scn.GetStrength(aragorn)); + } + + +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java new file mode 100644 index 000000000..054ce46b7 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java @@ -0,0 +1,95 @@ +package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Signet; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Card_V1_003Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("boromir", "101_003"); + put("sam", "1_311"); + put("merry", "1_302"); + put("pippin", "1_307"); + }} + ); + } + + + @Test + public void BoromirStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: VSet1, VPack1 + * Title: *Boromir + * Subtitle: The Redeemed + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 3 + * Type: Companion + * Subtype: Man + * Strength: 7 + * Vitality: 3 + * Signet: Aragorn + * Game Text: While you can spot 2 [shire] companions, Boromir is defender +1. + * While you can spot 4 [shire] companions, Boromir is strength +2 and damage +1. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + + assertTrue(boromir.getBlueprint().isUnique()); + assertEquals(3, boromir.getBlueprint().getTwilightCost()); + assertEquals(7, boromir.getBlueprint().getStrength()); + assertEquals(3, boromir.getBlueprint().getVitality()); + assertEquals(Signet.ARAGORN, boromir.getBlueprint().getSignet()); + } + + @Test + public void TwoAndFourHobbitsTriggerBuffs() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl sam = scn.GetFreepsCard("sam"); + PhysicalCardImpl merry = scn.GetFreepsCard("merry"); + PhysicalCardImpl pippin = scn.GetFreepsCard("pippin"); + + scn.FreepsMoveCardToHand(sam, merry, pippin); + scn.FreepsMoveCharToTable(boromir); + + scn.StartGame(); + + assertFalse(scn.HasKeyword(boromir, Keyword.DEFENDER)); + assertFalse(scn.HasKeyword(boromir, Keyword.DAMAGE)); + assertEquals(7, scn.GetStrength(boromir)); + + scn.FreepsPlayCard(sam); + assertTrue(scn.HasKeyword(boromir, Keyword.DEFENDER)); + assertEquals(7, scn.GetStrength(boromir)); + + scn.FreepsPlayCard(merry); + scn.FreepsPlayCard(pippin); + assertTrue(scn.HasKeyword(boromir, Keyword.DAMAGE)); + assertEquals(9, scn.GetStrength(boromir)); + } + + +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java new file mode 100644 index 000000000..ad5955514 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java @@ -0,0 +1,106 @@ +package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Card_V1_004Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("aragorn", "1_89"); + put("boromir", "1_97"); + put("loud", "101_004"); + + put("attea", "1_229"); + }} + ); + } + + + @Test + public void LoudAndClearStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: VSet1, VPack1 + * Title: *Loud and Clear It Sounds + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 1 + * Type: Condition + * Subtype: Support Area + * Game Text: Each time the Shadow player assigns as minion to a [shire] companion, you may exert a [gondor] companion and discard this condition to assign that minion to that [gondor] companion instead. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl loud = scn.GetFreepsCard("loud"); + + assertTrue(scn.HasKeyword(loud, Keyword.SUPPORT_AREA)); + assertEquals(1, loud.getBlueprint().getTwilightCost()); + assertTrue(loud.getBlueprint().isUnique()); + } + + @Test + public void LoudAndClearInterceptsShadowAssignment() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl loud = scn.GetFreepsCard("loud"); + + scn.FreepsMoveCharToTable(boromir, aragorn); + scn.FreepsMoveCardToSupportArea(loud); + + PhysicalCardImpl attea = scn.GetShadowCard("attea"); + scn.ShadowMoveCharToTable(attea); + + scn.StartGame(); + scn.SkipToPhase(Phase.ASSIGNMENT); + + //Assignment actions + scn.SkipCurrentPhaseActions(); + + //Skip standard assignment so shadow assigns + scn.FreepsSkipCurrentPhaseAction(); + + scn.ShadowAssignToMinions(frodo, attea); + + assertTrue(scn.FreepsHasOptionalTriggerAvailable()); + scn.FreepsAcceptOptionalTrigger(); + scn.FreepsChooseCard(boromir); + + assertTrue(loud.getZone() == Zone.DISCARD); + assertTrue(scn.IsCharAssigned(boromir)); + assertEquals(1, scn.GetWoundsOn(boromir)); + assertFalse(scn.IsCharAssigned(frodo)); + + scn.FreepsResolveSkirmish(boromir); + scn.SkipCurrentPhaseActions(); + + //fierce skirmish + scn.SkipCurrentPhaseActions(); + scn.FreepsAssignToMinions(frodo, attea); + //should only trigger if shadow assigns + assertFalse(scn.FreepsHasOptionalTriggerAvailable()); + } + + +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java new file mode 100644 index 000000000..67194eecb --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java @@ -0,0 +1,126 @@ +package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Card_V1_005Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("aragorn", "1_89"); + put("boromir", "1_97"); + put("remnant", "101_005"); + + put("inquisitor", "1_268"); + }} + ); + } + + + @Test + public void RemnantStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: VSet1, VPack1 + * Title: *Remnant of Numenor + * Side: Free Peoples + * Culture: Gondor + * Twilight Cost: 1 + * Type: Condition + * Subtype: Support Area + * Game Text: To play, spot a [gondor] companion. + * Each time a card is discarded from your hand by a Shadow card, you may add (1) to shuffle a [gondor] card from your discard pile into your draw deck. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl remnant = scn.GetFreepsCard("remnant"); + + assertTrue(scn.HasKeyword(remnant, Keyword.SUPPORT_AREA)); + assertEquals(1, remnant.getBlueprint().getTwilightCost()); + } + + @Test + public void RemnantSpotsAGondorCompanionToPlay() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl remnant = scn.GetFreepsCard("remnant"); + + scn.FreepsMoveCardToHand(aragorn, remnant); + + scn.StartGame(); + + assertEquals(Phase.FELLOWSHIP, scn.GetCurrentPhase()); + Assert.assertFalse(scn.FreepsCardPlayAvailable(remnant)); + + scn.FreepsPlayCard(aragorn); + assertTrue(scn.FreepsCardPlayAvailable(remnant)); + } + + @Test + public void RemnantTriggersOnShadowDiscardFromHand() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl aragorn = scn.GetFreepsCard("aragorn"); + PhysicalCardImpl boromir = scn.GetFreepsCard("boromir"); + PhysicalCardImpl remnant = scn.GetFreepsCard("remnant"); + + scn.FreepsMoveCardToDiscard(boromir); + scn.FreepsMoveCardToHand(aragorn); + scn.FreepsMoveCardToSupportArea(remnant); + + PhysicalCardImpl inquisitor = scn.GetShadowCard("inquisitor"); + scn.ShadowMoveCardToHand(inquisitor); + + scn.StartGame(); + + scn.SetTwilight(10); + + scn.FreepsSkipCurrentPhaseAction(); + + assertEquals(1, scn.GetFreepsHandCount()); + assertEquals(1, scn.GetFreepsDeckCount()); //the orc is also in the deck + assertEquals(1, scn.GetFreepsDiscardCount()); + + scn.ShadowPlayCard(inquisitor); + scn.ShadowAcceptOptionalTrigger(); + + assertTrue(scn.FreepsHasOptionalTriggerAvailable()); + scn.FreepsAcceptOptionalTrigger(); + + //scn.FreepsGetADParamAsList() + + scn.FreepsChoose("temp0"); + + //Card from hand was discarded, one of the two cards in the discard was shuffled in with the orc + assertEquals(0, scn.GetFreepsHandCount()); + assertEquals(2, scn.GetFreepsDeckCount()); + assertEquals(1, scn.GetFreepsDiscardCount()); + + // 10 starting + 2 for moving - 5 for the orc + 1 for Remnant triggering + assertEquals(8, scn.GetTwilight()); + + } + + +} From 32fe008342326ea03123a9d78612f68504caa09a Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 13 Mar 2021 02:41:07 -0600 Subject: [PATCH 67/74] Fixing missing images --- .../src/main/web/js/gemp-022/PC_Cards.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index af6c3e4c9..323ddb660 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -57,16 +57,16 @@ var PCCards = { '53_68': 'https://i.lotrtcgpc.net/errata/FOTR/53_068.jpg', // May 2021 VPack1 - '101_1001': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_001.jpg', - '101_1002': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_002.jpg', - '101_1003': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_003.jpg', - '101_1004': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_004.jpg', - '101_1005': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_005.jpg', - '101_1006': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_006.jpg', - '101_1007': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_007.jpg', - '101_1008': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_008.jpg', - '101_1009': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_009.jpg', - '101_1010': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_010.jpg', + '101_1': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_001.jpg', + '101_2': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_002.jpg', + '101_3': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_003.jpg', + '101_4': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_004.jpg', + '101_5': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_005.jpg', + '101_6': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_006.jpg', + '101_7': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_007.jpg', + '101_8': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_008.jpg', + '101_9': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_009.jpg', + '101_10': 'https://i.lotrtcgpc.net/sets/vset1/vpack1/v1_010.jpg', // Future Errata '51_45': 'https://i.lotrtcgpc.net/errata/FOTR/51_045.jpg', From cb093c1ef8285d7360bbc093b6843ba18af9c513 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 13 Mar 2021 02:44:18 -0600 Subject: [PATCH 68/74] Fixing erroneous padding in new card ids --- .../src/main/web/cards/set101/vpack1.json | 20 +++++++++---------- .../pc/vset1/vpack1/Card_V1_001Tests.java | 2 +- .../pc/vset1/vpack1/Card_V1_002Tests.java | 2 +- .../pc/vset1/vpack1/Card_V1_003Tests.java | 2 +- .../pc/vset1/vpack1/Card_V1_004Tests.java | 2 +- .../pc/vset1/vpack1/Card_V1_005Tests.java | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json index 393d3d096..a5ba14c7d 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json @@ -1,5 +1,5 @@ { - "101_001": { + "101_1": { "side": "free_people", "culture": "Gondor", "title": "*The Lords of Gondor Have Returned", @@ -41,7 +41,7 @@ ] }, - "101_002": { + "101_2": { "side": "free_people", "culture": "Gondor", "title": "*I Will Not Let the White City Fall", @@ -78,7 +78,7 @@ ] }, - "101_003": { + "101_3": { "side": "free_people", "culture": "Gondor", "title": "*Boromir", @@ -134,7 +134,7 @@ ] }, - "101_004": { + "101_4": { "side": "free_people", "culture": "Gondor", "title": "*Loud and Clear It Sounds", @@ -173,7 +173,7 @@ ] }, - "101_005": { + "101_5": { "side": "free_people", "culture": "Gondor", "title": "Remnant of Numenor", @@ -204,7 +204,7 @@ } }, - "101_006": { + "101_6": { "side": "shadow", "culture": "Sauron", "title": "*Great Wolf Chief", @@ -253,7 +253,7 @@ ] }, - "101_007": { + "101_7": { "side": "shadow", "culture": "Sauron", "title": "Hollin Snarler", @@ -302,7 +302,7 @@ ] }, - "101_008": { + "101_8": { "side": "shadow", "culture": "Sauron", "title": "Hound of Sauron", @@ -351,7 +351,7 @@ ] }, - "101_009": { + "101_9": { "side": "shadow", "culture": "Sauron", "title": "*The Hunt is Up!", @@ -393,7 +393,7 @@ ] }, - "101_010": { + "101_10": { "side": "shadow", "culture": "Sauron", "title": "I See You", diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java index 2e1b7a6d4..8b603c12a 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_001Tests.java @@ -22,7 +22,7 @@ public class Card_V1_001Tests {{ put("aragorn", "1_89"); put("boromir", "1_97"); - put("lords", "101_001"); + put("lords", "101_1"); put("runner1", "1_178"); put("runner2", "1_178"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java index 1feef137d..702475e33 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_002Tests.java @@ -22,7 +22,7 @@ public class Card_V1_002Tests {{ put("aragorn", "1_89"); put("boromir", "1_97"); - put("whitecity", "101_002"); + put("whitecity", "101_2"); put("attea", "1_229"); put("cantea", "1_230"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java index 054ce46b7..b4b263a23 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java @@ -22,7 +22,7 @@ public class Card_V1_003Tests return new GenericCardTestHelper( new HashMap() {{ - put("boromir", "101_003"); + put("boromir", "101_3"); put("sam", "1_311"); put("merry", "1_302"); put("pippin", "1_307"); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java index ad5955514..5a32b7a25 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_004Tests.java @@ -24,7 +24,7 @@ public class Card_V1_004Tests {{ put("aragorn", "1_89"); put("boromir", "1_97"); - put("loud", "101_004"); + put("loud", "101_4"); put("attea", "1_229"); }} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java index 67194eecb..2c1cd710f 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_005Tests.java @@ -25,7 +25,7 @@ public class Card_V1_005Tests {{ put("aragorn", "1_89"); put("boromir", "1_97"); - put("remnant", "101_005"); + put("remnant", "101_5"); put("inquisitor", "1_268"); }} From 8644dfbd059344bfa328d2f28f59f7b408406638 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 13 Mar 2021 02:50:21 -0600 Subject: [PATCH 69/74] Hiding christmas starter supplement images --- .../src/main/web/js/gemp-022/PC_Cards.js | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js index 323ddb660..65604a00c 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/PC_Cards.js @@ -1,53 +1,53 @@ var PCCards = { //fotr supplements - '101_1': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_1.jpg', - '101_2': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_2.jpg', - '101_3': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_3.jpg', - '101_4': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_4.jpg', - '101_5': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_5.jpg', - '101_6': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_6.jpg', - '101_7': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_7.jpg', - '101_8': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_8.jpg', - '101_9': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_9.jpg', - '101_10': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_10.jpg', - '101_11': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_11.jpg', - '101_12': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_12.jpg', - '101_13': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_13.jpg', - '101_14': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_14.jpg', - '101_15': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_15.jpg', - '101_16': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_16.jpg', - '101_17': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_17.jpg', - '101_18': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_18.jpg', - '101_19': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_19.jpg', - '101_20': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_20.jpg', - '101_21': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_21.jpg', - '101_22': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_22.jpg', - '101_23': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_23.jpg', - '101_24': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_24.jpg', - '101_25': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_25.jpg', - '101_26': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_26.jpg', - '101_27': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_27.jpg', - '101_28': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_28.jpg', - '101_29': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_29.jpg', - '101_30': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_30.jpg', - '101_31': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_31.jpg', - '101_32': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_32.jpg', - '101_33': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_33.jpg', - '101_34': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_34.jpg', - '101_35': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_35.jpg', - '101_36': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_36.jpg', - '101_37': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_37.jpg', - '101_38': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_38.jpg', - '101_39': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_39.jpg', - '101_40': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_40.jpg', - '101_41': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_41.jpg', - '101_42': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_42.jpg', - '101_43': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_43.jpg', - '101_44': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_44.jpg', - '101_45': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_45.jpg', - '101_46': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_46.jpg', - '101_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_47.jpg', + // '101_1': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_1.jpg', + // '101_2': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_2.jpg', + // '101_3': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_3.jpg', + // '101_4': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_4.jpg', + // '101_5': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_5.jpg', + // '101_6': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_6.jpg', + // '101_7': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_7.jpg', + // '101_8': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_8.jpg', + // '101_9': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_9.jpg', + // '101_10': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_10.jpg', + // '101_11': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_11.jpg', + // '101_12': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_12.jpg', + // '101_13': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_13.jpg', + // '101_14': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_14.jpg', + // '101_15': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_15.jpg', + // '101_16': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_16.jpg', + // '101_17': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_17.jpg', + // '101_18': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_18.jpg', + // '101_19': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_19.jpg', + // '101_20': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_20.jpg', + // '101_21': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_21.jpg', + // '101_22': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_22.jpg', + // '101_23': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_23.jpg', + // '101_24': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_24.jpg', + // '101_25': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_25.jpg', + // '101_26': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_26.jpg', + // '101_27': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_27.jpg', + // '101_28': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_28.jpg', + // '101_29': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_29.jpg', + // '101_30': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_30.jpg', + // '101_31': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_31.jpg', + // '101_32': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_32.jpg', + // '101_33': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_33.jpg', + // '101_34': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_34.jpg', + // '101_35': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_35.jpg', + // '101_36': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_36.jpg', + // '101_37': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_37.jpg', + // '101_38': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_38.jpg', + // '101_39': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_39.jpg', + // '101_40': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_40.jpg', + // '101_41': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_41.jpg', + // '101_42': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_42.jpg', + // '101_43': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_43.jpg', + // '101_44': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_44.jpg', + // '101_45': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_45.jpg', + // '101_46': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_46.jpg', + // '101_47': 'https://i.lotrtcgpc.net/sets/fotr_starters/playtest/101_47.jpg', // April 2021 Errata Batch '51_40': 'https://i.lotrtcgpc.net/errata/FOTR/51_040.jpg', From 70132521976a1a3c3cdea7e4f70a942da5049d43 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 13 Mar 2021 02:55:01 -0600 Subject: [PATCH 70/74] Removing christmas starter supplements for now --- .../cards/set101/fotr-starter-supplement.json | 773 ------------------ 1 file changed, 773 deletions(-) delete mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json deleted file mode 100644 index 0dc136748..000000000 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/fotr-starter-supplement.json +++ /dev/null @@ -1,773 +0,0 @@ -{ - "101_1": { - "title": "Blue Mountain Dwarf", - "culture": "dwarven", - "type": "companion", - "race": "dwarf", - "cost": 2, - "strength": 6, - "vitality": 2, - "resistance": 6, - "keyword": "damage+1", - "effects": { - "type": "extraCost", - "cost":{ - "type": "addBurdens", - "amount": { - "type": "condition", - "condition": { - "type": "canSpot", - "filter": "name(Bilbo)" - }, - "true": 0, - "false": 1 - } - } - } - }, - "101_2": { - "title": "Stand Together", - "culture": "gandalf", - "cost": 3, - "type": "event", - "keyword": "maneuver", - "condition": { - "type": "canSpot", - "filter": "name(Gandalf)" - }, - "effects": { - "type": "event", - "cost": { - "type": "exert", - "filter": "choose(another,companion,or(signet(aragorn),signet(gandalf),signet(frodo),signet(theoden)))", - "memorize": "exertedCompanion" - }, - "effect": { - "type": "heal", - "filter": "choose(companion,not(memory(exertedCompanion)),or(signet(aragorn),signet(gandalf),signet(frodo),signet(theoden)))", - "times": 2 - } - } - }, - "101_3": { - "title": "Thrice Worthy and Beloved Barliman", - "culture": "gandalf", - "type": "condition", - "cost": 0, - "vitality": 1, - "target": "name(Barliman Butterbur)", - "effects": { - "type": "activatedTrigger", - "trigger": { - "type": "discarded", - "filter": "your,mount", - "memorize": "discardedCard" - }, - "cost": { - "type": "exert", - "filter": "bearer" - }, - "effect": { - "type": "putCardsFromDiscardOnTopOfDrawDeck", - "filter": "memory(discardedCard)" - } - } - }, - "101_4": { - "title": "Gondorian Broadsword", - "culture": "gondor", - "type": "possession", - "possession": "hand weapon", - "cost": 2, - "strength": 2, - "target": "culture(gondor),man", - "effects": { - "type": "activated", - "phase": "maneuver", - "cost": { - "type": "exert", - "filter": "bearer", - "times": 2 - }, - "effect": { - "type": "addKeyword", - "filter": "bearer", - "keyword": "defender+1", - "until": "start(regroup)" - } - } - }, - "101_5": { - "title": "Relics of the Second Age", - "culture": "gondor", - "type": "condition", - "keyword": "support area", - "cost": 1, - "effects": { - "type": "activated", - "phase": "regroup", - "cost": [ - { - "type": "revealCardsFromHand", - "filter": "choose(culture(gondor))", - "count": 2, - "memorize": "revealedCards" - }, - { - "type": "putCardsFromHandOnTopOfDeck", - "filter": "memory(revealedCards)" - } - ], - "effect": { - "type": "putCardsFromDiscardIntoHand", - "filter": "choose(culture(gondor))" - } - } - }, - "101_6": { - "title": "Thrown Sword", - "culture": "gondor", - "type": "event", - "keyword": "skirmish", - "cost": 1, - "effects": { - "type" : "event", - "cost": { - "type": "discard", - "filter": "choose(hand weapon,attachedTo(character,culture(gondor),man))" - }, - "effect": { - "type": "wound", - "filter": "choose(orc,uruk-hai,inSkirmishAgainst(another,companion,not(ring bearer)))", - "times": 2 - } - } - }, - "101_7": { - "title": "Lurtz", - "subtitle": "Weapon of Saruman", - "culture": "isengard", - "type": "minion", - "race": "uruk-hai", - "cost": 7, - "strength": 12, - "vitality": 3, - "site": 5, - "keyword": [ - "archer", - "damage+1" - ], - "effects": { - "type": "modifier", - "modifier": { - "type": "modifyStrength", - "filter": "self", - "amount": { - "type": "forEachWound", - "filter": "self" - } - } - } - }, - "101_8": { - "title": "Strength of Servitude", - "culture": "isengard", - "type": "event", - "keyword": "response", - "cost": 1, - "effects": { - "type": "responseEvent", - "trigger": { - "type": "aboutToExert", - "filter": "your,uruk hai" - }, - "effect": { - "type": "placeNoWoundForExert", - "filter": "choose(uruk-hai)" - } - } - }, - "101_9": { - "title": "Uruk Swarmer", - "culture": "isengard", - "type": "minion", - "race": "uruk-hai", - "cost": 3, - "strength": 6, - "vitality": 2, - "site": 5, - "keyword" : "damage+1", - "effects" : { - "type": "trigger", - "optional": true, - "trigger": { - "type": "assignedToSkirmish", - "filter": "self", - "against": "companion" - }, - "effect": [ - { - "type": "playCardFromDiscard", - "filter": "choose(uruk-hai)", - "memorize": "playedUrukhai" - }, - { - "type": "addKeyword", - "filter": "memory(playedUrukhai)", - "keyword": "fierce", - "until": "start(regroup)" - } - ] - } - }, - "101_10": { - "title": "Goblin Bow", - "culture": "moria", - "type": "possession", - "possession": "ranged weapon", - "cost": 1, - "strength": 1, - "vitality": 1, - "target": "culture(moria),orc", - "effects": [ - { - "type": "trigger", - "trigger": { - "type": "played", - "filter": "self" - }, - "effect": { - "type": "discard", - "filter": "all(possession,not(self),attachedTo(bearer))" - } - }, - { - "type": "modifier", - "modifier": { - "type": "addKeyword", - "filter": "bearer", - "keyword": "archer" - } - }, - { - "type": "modifier", - "modifier": - { - "type": "cantBear", - "filter": "bearer", - "cardFilter": "possession" - } - } - ] - }, - "101_11": { - "title": "Goblin Warchief", - "subtitle": "Captain of the Underhall", - "culture": "moria", - "type": "minion", - "race": "orc", - "cost": 4, - "strength": 9, - "vitality": 2, - "site": 4, - "keyword": "fierce", - "condition": { - "type": "canSpot", - "filter": "culture(moria),orc" - }, - "effects": { - "type": "trigger", - "optional": true, - "trigger": { - "type": "played", - "filter": "self" - }, - "cost": { - "type": "revealBottomCardsOfDrawDeck", - "count": 4, - "memorize": "revealedCards" - }, - "effect": [ - { - "type": "playCardFromDrawDeck", - "filter": "all(memory(revealedCards),culture(moria),orc)" - }, - { - "type": "discardCardsFromDrawDeck", - "filter": "all(memory(revealedCards),zone(deck))" - } - ] - } - }, - "101_12": { - "title": "No Hope of Escape That Way", - "culture": "moria", - "type": "event", - "keyword": "maneuver", - "cost": 1, - "condition": { - "type": "canSpot", - "filter": "culture(moria),orc" - }, - "effects": { - "type": "event", - "effect": { - "type": "returnToHand", - "filter": "choose(possession,attachedTo(companion,not(ring bearer)))" - } - } - }, - "101_13": { - "title": "The Old Forest", - "culture": "wraith", - "type": "condition", - "keyword": "support area", - "cost": 0, - "effects": [ - { - "type": "trigger", - "optional": true, - "trigger": { - "type": "played", - "filter": "self" - }, - "effect": { - "type": "playCardFromDrawDeck", - "filter": "choose(tree)" - } - }, - { - "type": "activated", - "phase": "shadow", - "condition": { - "type": "canSpot", - "filter": "side(free people),not(name(Frodo)),maxTwilight(0)", - "count": 3 - }, - "cost": { - "type": "play", - "filter": "choose(minion,culture(wraith),unique)" - }, - "effect": [ - { - "type": "addTwilight", - "amount": 3 - }, - { - "type": "discard", - "filter": "self" - } - ] - } - ] - }, - "101_14": { - "title": "Old Man Willow", - "subtitle": "Heart of the Withywindle", - "culture": "wraith", - "type": "minion", - "race": "tree", - "cost": 3, - "strength": 2, - "vitality": 6, - "site": 2, - "effects" : [ - { - "type": "modifier", - "modifier": { - "type": "addKeyword", - "filter": "self", - "condition": { - "type": "location", - "filter": "not(forest)" - }, - "keyword": "roaming" - } - }, - { - "type": "activatedTrigger", - "trigger": { - "type": "startOfPhase", - "phase": "assignment" - }, - "cost": { - "type": "exert", - "filter": "self", - "times": 2 - }, - "effect": [ - { - "type": "spot", - "filter": "choose(companion,hobbit,strengthLessThan(7))", - "memorize": "chosenHobbit" - }, - { - "type": "addModifier", - "modifier": { - "type": "cantBeAssignedToSkirmishAgainst", - "side": "free people", - "fpCharacter": "memory(chosenHobbit)", - "minion": "any" - } - } - ] - } - ] - }, - "101_15": { - "title": "And in the Darkness Bind Them", - "culture": "sauron", - "type": "condition", - "keyword": "support area", - "cost": 0, - "effects": { - "type": "activated", - "phase": "skirmish", - "effect": { - "type": "choice", - "texts": [ - "Discard a WRAITH card to make a SAURON orc strength +1", - "Discard a SAURON card to make a Nazgūl strength +1" - ], - "effects": [ - { - "type": "costToEffect", - "cost": { - "type": "discardFromHand", - "forced": true, - "filter": "choose(culture(wraith))" - }, - "effect": { - "type": "conditional", - "condition": { - "type": "perPhaseLimit", - "limit": 2 - }, - "effect": [ - { - "type": "incrementPerPhaseLimit", - "limit": 2 - }, - { - "type": "modifyStrength", - "filter": "choose(culture(sauron),orc)", - "amount": 1 - } - ] - } - - }, - { - "type": "costToEffect", - "cost": { - "type": "discardFromHand", - "forced": true, - "filter": "choose(culture(sauron))" - }, - "effect": { - "type": "conditional", - "condition": { - "type": "perPhaseLimit", - "limit": 2 - }, - "effect": [ - { - "type": "incrementPerPhaseLimit", - "limit": 2 - }, - { - "type": "modifyStrength", - "filter": "choose(nazgul)", - "amount": 1 - } - ] - } - - } - ] - } - } - }, - "101_16": { - "title": "Gladden Ambush", - "culture": "sauron", - "type": "event", - "keyword": [ - "search", - "maneuver" - ], - "cost": 0 - }, - "101_17": { - "title": "Bilbo", - "subtitle": "One Hundred and Eleventy", - "culture": "shire", - "type": "ally", - "race": "hobbit", - "cost": 2, - "strength": 2, - "vitality": 3, - "allyHome": [ - "fellowship,1", - "fellowship,3" - ], - "effects": { - "type": "activated", - "phase": "or(maneuver,regroup)", - "cost": { - "type": "exert", - "filter": "self" - }, - "effect": { - "type": "returnToHand", - "filter": "choose(hobbit,not(ring bearer))" - } - } - }, - "101_18": { - "title": "Hobbit Concealment", - "culture": "shire", - "type": "condition", - "keyword": "support area", - "cost": 1 - }, - "101_19": { - "title": "Sam", - "subtitle": "Hobbit of Hobbiton", - "culture": "shire", - "type": "companion", - "race": "hobbit", - "cost": 2, - "strength": 3, - "vitality": 4, - "signet": "frodo" - }, - "101_20": { - "title": "Walking Stick", - "culture": "shire", - "type": "possession", - "possession": "staff", - "strength": 0 - }, - "101_21": { - "title": "Barred the Gates", - "culture": "dwarven", - "type": "condition", - "keyword": "support area", - "cost": 0 - }, - "101_22": { - "title": "Light-shaft", - "culture": "dwarven", - "type": "event", - "keyword": "regroup", - "cost": 0 - }, - "101_23": { - "title": "Longbeard's Axe", - "culture": "dwarven", - "type": "possession", - "possession": "hand weapon", - "cost": 1, - "strength": 2 - }, - "101_24": { - "title": "Venturing Dwarf", - "culture": "dwarven", - "type": "companion", - "race": "dwarf", - "cost": 2, - "strength": 5, - "vitality": 3 - }, - "101_25": { - "title": "Dazzling Flash", - "culture": "gandalf", - "type": "event", - "keyword": "skirmish", - "cost": 1 - }, - "101_26": { - "title": "No Time for Wonder", - "culture": "gandalf", - "type": "condition", - "keyword": "support area", - "cost": 1 - }, - "101_27": { - "title": "Dagger of Westernesse", - "culture": "gondor", - "type": "artifact", - "possession": "hand weapon", - "cost": 0, - "strength": 2 - }, - "101_28": { - "title": "Goblin Avengers", - "culture": "moria", - "type": "minion", - "race": "orc", - "cost": 7, - "strength": 13, - "vitality": 3, - "site": 4 - }, - "101_29": { - "title": "Goblin Warren", - "culture": "moria", - "type": "condition", - "keyword": "support area", - "cost": 1 - }, - "101_30": { - "title": "Thither We Are Going Against My Wish", - "culture": "moria", - "type": "condition", - "keyword": "support area", - "cost": 1 - }, - "101_31": { - "title": "Hollin Snarler", - "culture": "sauron", - "type": "minion", - "race": "warg", - "cost": 3, - "strength": 8, - "vitality": 2, - "site": 3 - }, - "101_32": { - "title": "The Hunt is Up!", - "culture": "sauron", - "type": "condition", - "keyword": "support area", - "cost": 1 - }, - "101_33": { - "title": "Hunting Pack", - "culture": "sauron", - "type": "minion", - "race": "warg", - "cost": 5, - "strength": 11, - "vitality": 3, - "site": 5 - }, - "101_34": { - "title": "Pippin", - "subtitle": "Fool of a Took", - "culture": "shire", - "type": "companion", - "race": "hobbit", - "cost": 1, - "strength": 3, - "vitality": 4, - "signet": "gandalf" - }, - "101_35": { - "title": "Deft Aid", - "culture": "elven", - "type": "condition", - "site": 1 - }, - "101_36": { - "title": "Elven Flet", - "culture": "elven", - "type": "condition", - "keyword": "support area", - "cost": 1 - }, - "101_37": { - "title": "In Imladris it Dwells", - "culture": "elven", - "type": "event", - "keyword": "fellowship", - "cost": 0 - }, - "101_38": { - "title": "Rivendell Sentry", - "culture": "elven", - "type": "ally", - "race": "elf", - "cost": 2, - "strength": 5, - "vitality": 2, - "allyHome": "fellowship,4" - }, - "101_39": { - "title": "Arroch", - "culture": "gondor", - "type": "possession", - "possession": "mount", - "cost": 2, - "vitality": 1 - }, - "101_40": { - "title": "The Deeds of the Steward's House", - "culture": "gondor", - "type": "condition", - "keyword": "support area", - "cost": 2 - }, - "101_41": { - "title": "They Have a Cave Troll", - "culture": "gondor", - "type": "event", - "keyword": "maneuver", - "cost": 1 - }, - "101_42": { - "title": "Isengard Attendant", - "culture": "isengard", - "type": "minion", - "race": "orc", - "cost": 3, - "strength": 7, - "vitality": 2, - "site": 4 - }, - "101_43": { - "title": "Stirruk", - "culture": "isengard", - "type": "possession", - "possession": "hand weapon", - "cost": 1, - "strength": 3, - "vitality": 1 - }, - "101_44": { - "title": "Uruk Batch", - "culture": "isengard", - "type": "minion", - "race": "uruk-hai", - "cost": 3, - "strength": 7, - "vitality": 2, - "site": 5 - }, - "101_45": { - "title": "Influence of Shadow", - "culture": "sauron", - "type": "condition", - "keyword": "support area", - "cost": 0 - }, - "101_46": { - "title": "Tower Shaman", - "culture": "sauron", - "type": "minion", - "race": "orc", - "cost": 4, - "strength": 6, - "vitality": 3, - "site": 6 - }, - "101_47": { - "title": "Udun Scimitar", - "culture": "sauron", - "type": "possession", - "possession": "hand weapon", - "cost": 2, - "strength": 2 - } -} \ No newline at end of file From 7c6be3e2ae5eed074f8a545222f365e6357b19b3 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 14 Mar 2021 00:15:38 -0600 Subject: [PATCH 71/74] Adding two Wargs from vpack1 These cards are broken + new Boromir; strength modifiers seem to be applied on the stack twice. Pushing to verify in-client behavior. --- .../src/main/web/cards/set101/vpack1.json | 107 ++++++++--------- .../lotro/cards/GenericCardTestHelper.java | 5 + .../pc/vset1/vpack1/Card_V1_003Tests.java | 2 +- .../pc/vset1/vpack1/Card_V1_006Tests.java | 113 ++++++++++++++++++ .../pc/vset1/vpack1/Card_V1_007Tests.java | 112 +++++++++++++++++ 5 files changed, 280 insertions(+), 59 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json index a5ba14c7d..516757063 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set101/vpack1.json @@ -109,7 +109,7 @@ "modifier": { "type": "modifyStrength", "filter": "self", - "amount": 1, + "amount": 2, "condition": { "type": "canSpot", "filter": "companion,culture(shire)", @@ -220,36 +220,32 @@ ], "effects": [ { - "type": "activated", - "phase": "skirmish", - "condition": { - "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", - }, - "cost": [ - { - "type": "memorize", - "filter": "bearer", - "memory": "bearer" - }, - { - "type": "discard", - "filter": "self" + "type": "modifier", + "modifier": { + "type": "ModifySiteNumber", + "filter": "self", + "amount": { + "type": "forEachYouCanSpot", + "filter": "stealth", + "multiplier": -1 } - ], - "effect":[ - { - "type": "modifyStrength", - "filter": "memory(bearer)", - "amount": 3 - }, - { - "type": "addKeyword", - "filter": "memory(bearer)", - "keyword": "damage+1" - } - ] + } }, + + { + "type": "trigger", + "optional": true, + "trigger": { + "type": "played", + "filter": "another,culture(sauron),warg" + }, + "effect": { + "type": "exert", + "player": "fp", + "filter": "choose(companion)", + "count": 1 + } + } ] }, @@ -260,7 +256,7 @@ "type": "minion", "cost": 3, "race": "warg", - "strength": 6, + "strength": 4, "vitality": 3, "site": 6, "keyword": [ @@ -269,36 +265,31 @@ ], "effects": [ { - "type": "activated", - "phase": "skirmish", - "condition": { - "type": "canSpot", - "filter": "bearer,inSkirmishAgainst(Nazgul)", - }, - "cost": [ - { - "type": "memorize", - "filter": "bearer", - "memory": "bearer" - }, - { - "type": "discard", - "filter": "self" + "type": "modifier", + "modifier": { + "type": "ModifySiteNumber", + "filter": "self", + "amount": { + "type": "forEachYouCanSpot", + "filter": "stealth", + "multiplier": -1 } - ], - "effect":[ - { - "type": "modifyStrength", - "filter": "memory(bearer)", - "amount": 3 - }, - { - "type": "addKeyword", - "filter": "memory(bearer)", - "keyword": "damage+1" - } - ] + } }, + + { + "type": "modifier", + "modifier": { + "type": "ModifyStrength", + "filter": "self", + "amount": { + "type": "forEachYouCanSpot", + "filter": "or(stealth,and(companion,wounded))", + + } + } + }, + ] }, diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index fa6237a35..564e6ca77 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -406,6 +406,11 @@ public class GenericCardTestHelper extends AbstractAtTest { { return _game.getModifiersQuerying().getStrength(_game, card); } + public int GetVitality(PhysicalCardImpl card) + { + return _game.getModifiersQuerying().getVitality(_game, card); + } + public int GetSiteNumber(PhysicalCardImpl card) { return _game.getModifiersQuerying().getMinionSiteNumber(_game, card); } public boolean HasKeyword(PhysicalCardImpl card, Keyword keyword) { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java index b4b263a23..3d2ee480e 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java @@ -88,7 +88,7 @@ public class Card_V1_003Tests scn.FreepsPlayCard(merry); scn.FreepsPlayCard(pippin); assertTrue(scn.HasKeyword(boromir, Keyword.DAMAGE)); - assertEquals(9, scn.GetStrength(boromir)); + //assertEquals(9, scn.GetStrength(boromir)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java new file mode 100644 index 000000000..08897e92d --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java @@ -0,0 +1,113 @@ +package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.common.Signet; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Card_V1_006Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("stealth1", "2_106"); + put("stealth2", "2_106"); + + put("chief", "101_6"); + put("snarler", "101_7"); + + }} + ); + } + + + @Test + public void ChiefStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: VSet1, VPack1 + * Title: *Great Wolf Chief + * Side: Shadow + * Culture: Sauron + * Twilight Cost: 5 + * Type: Minion + * Subtype: Warg + * Strength: 10 + * Vitality: 3 + * Home Site: 6 + * Game Text: Tracker. Fierce. The site number of this minion is -1 for each stealth card you can spot. + * Each time you play another [sauron] Warg, you may make the Free Peoples player exert a companion. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl chief = scn.GetFreepsCard("chief"); + + assertTrue(chief.getBlueprint().isUnique()); + assertEquals(5, chief.getBlueprint().getTwilightCost()); + assertEquals(10, chief.getBlueprint().getStrength()); + assertEquals(3, chief.getBlueprint().getVitality()); + assertEquals(6, chief.getBlueprint().getSiteNumber()); + assertTrue(scn.HasKeyword(chief, Keyword.TRACKER)); + assertTrue(scn.HasKeyword(chief, Keyword.FIERCE)); + } + + @Test + public void ChiefSiteNumberReducedForEachStealthCard() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl stealth1 = scn.GetFreepsCard("stealth1"); + PhysicalCardImpl stealth2 = scn.GetFreepsCard("stealth2"); + + scn.FreepsMoveCardToSupportArea(stealth1, stealth2); + + PhysicalCardImpl chief = scn.GetShadowCard("chief"); + + scn.ShadowMoveCharToTable(chief); + + scn.StartGame(); + + // 6 base, -2 for the 2 Nice Imitations on the table. + //assertEquals(4, scn.GetSiteNumber(chief)); + } + + @Test + public void ChiefExertsACompanionWhenEachWargPlayed() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + + PhysicalCardImpl chief = scn.GetShadowCard("chief"); + PhysicalCardImpl snarler = scn.GetShadowCard("snarler"); + + scn.ShadowMoveCharToTable(chief); + scn.ShadowMoveCardToHand(snarler); + + scn.StartGame(); + + scn.SetTwilight(10); + scn.FreepsSkipCurrentPhaseAction(); + + scn.ShadowPlayCard(snarler); + assertTrue(scn.ShadowHasOptionalTriggerAvailable()); + scn.ShadowAcceptOptionalTrigger(); + + assertEquals(1, scn.GetWoundsOn(frodo)); + } + + +} diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java new file mode 100644 index 000000000..7327b4ee6 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java @@ -0,0 +1,112 @@ +package com.gempukku.lotro.cards.unofficial.pc.vset1.vpack1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Keyword; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class Card_V1_007Tests +{ + + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("stealth1", "2_106"); + put("stealth2", "2_106"); + + put("snarler", "101_7"); + + }} + ); + } + + + @Test + public void SnarlerStatsAndKeywordsAreCorrect() throws DecisionResultInvalidException, CardNotFoundException { + + /** + * Set: VSet1, VPack1 + * Title: Hollin Snarler + * Side: Shadow + * Culture: Sauron + * Twilight Cost: 3 + * Type: Minion + * Subtype: Warg + * Strength: 4 + * Vitality: 2 + * Home Site: 6 + * Game Text: Tracker. Fierce. The site number of this minion is -1 for each stealth card you can spot. + * This minion is strength +1 for each wounded companion or stealth card you can spot. + */ + + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl snarler = scn.GetFreepsCard("snarler"); + + assertFalse(snarler.getBlueprint().isUnique()); + assertEquals(3, snarler.getBlueprint().getTwilightCost()); + assertEquals(4, snarler.getBlueprint().getStrength()); + assertEquals(3, snarler.getBlueprint().getVitality()); + assertEquals(6, snarler.getBlueprint().getSiteNumber()); + assertTrue(scn.HasKeyword(snarler, Keyword.TRACKER)); + assertTrue(scn.HasKeyword(snarler, Keyword.FIERCE)); + } + + @Test + public void SnarlerSiteNumberReducedForEachStealthCard() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl stealth1 = scn.GetFreepsCard("stealth1"); + PhysicalCardImpl stealth2 = scn.GetFreepsCard("stealth2"); + + scn.FreepsMoveCardToSupportArea(stealth1, stealth2); + + PhysicalCardImpl snarler = scn.GetShadowCard("snarler"); + + scn.ShadowMoveCharToTable(snarler); + + scn.StartGame(); + + // 6 base, -2 for the 2 Nice Imitations on the table. + //assertEquals(4, scn.GetSiteNumber(snarler)); + } + + @Test + public void SnarlerStrengthIncreasesWithWoundedCompanionsAndStealth() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl frodo = scn.GetRingBearer(); + PhysicalCardImpl stealth1 = scn.GetFreepsCard("stealth1"); + PhysicalCardImpl stealth2 = scn.GetFreepsCard("stealth2"); + + scn.FreepsMoveCardToSupportArea(stealth1,stealth2); + + PhysicalCardImpl snarler = scn.GetShadowCard("snarler"); + + scn.ShadowMoveCharToTable(snarler); + + scn.StartGame(); + + scn.AddWoundsToChar(frodo, 1); + scn.FreepsSkipCurrentPhaseAction(); + + //assertEquals(1, scn.GetWoundsOn(frodo)); + + // Base of 4, +2 for stealth cards, +1 for wounded frodo + //assertEquals(7, scn.GetStrength(snarler)); + } + + +} From 46707410a5cbe69ca0cc16ee25268777906474ce Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Wed, 17 Mar 2021 13:51:43 -0500 Subject: [PATCH 72/74] Farin tests --- .../cards/official/set1/Card1_011Tests.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set1/Card1_011Tests.java diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set1/Card1_011Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set1/Card1_011Tests.java new file mode 100644 index 000000000..fd28da7c3 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set1/Card1_011Tests.java @@ -0,0 +1,55 @@ +package com.gempukku.lotro.cards.official.set1; + +import com.gempukku.lotro.cards.GenericCardTestHelper; +import com.gempukku.lotro.common.Phase; +import com.gempukku.lotro.game.CardNotFoundException; +import com.gempukku.lotro.game.PhysicalCardImpl; +import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException; +import org.junit.Test; + +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; + +// Tidings of Erebor +public class Card1_011Tests +{ + protected GenericCardTestHelper GetScenario() throws CardNotFoundException, DecisionResultInvalidException { + return new GenericCardTestHelper( + new HashMap() + {{ + put("farin", "1_11"); + + put("goblin", "1_178"); + }} + ); + } + + @Test + public void FarinStrengthBoostWhileSkirmishingOrc() throws DecisionResultInvalidException, CardNotFoundException { + //Pre-game setup + GenericCardTestHelper scn = GetScenario(); + + PhysicalCardImpl farin = scn.GetFreepsCard("farin"); + scn.FreepsMoveCharToTable(farin); + + PhysicalCardImpl goblin = scn.GetShadowCard("goblin"); + scn.ShadowMoveCharToTable(goblin); + + scn.StartGame(); + scn.FreepsSkipCurrentPhaseAction(); + + scn.SkipToPhase(Phase.ASSIGNMENT); + + scn.SkipCurrentPhaseActions(); + + scn.FreepsAssignToMinions(farin, goblin); + scn.FreepsResolveSkirmish(farin); + + assertEquals(7, scn.GetStrength(farin)); + + } + + + +} \ No newline at end of file From c420d4e483752b06833d455b7584456d55f2e7eb Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Thu, 18 Mar 2021 22:08:03 -0500 Subject: [PATCH 73/74] Fixing PC unit tests to fit with the new fixes --- .../com/gempukku/lotro/cards/GenericCardTestHelper.java | 4 ++-- .../unofficial/pc/errata/set1/Elrond_LoRErrataTests.java | 4 ++-- .../unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java | 4 ++-- .../cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java | 2 +- .../cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java | 2 +- .../cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java | 6 ++---- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java index add3f1cae..f2a88f690 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/GenericCardTestHelper.java @@ -168,8 +168,8 @@ public class GenericCardTestHelper extends AbstractAtTest { public List FreepsGetADParamAsList(String paramName) { return GetADParamAsList(P1, paramName); } public List ShadowGetADParamAsList(String paramName) { return GetADParamAsList(P2, paramName); } public List GetADParamAsList(String playerID, String paramName) { return Arrays.asList(GetAwaitingDecisionParam(playerID, paramName)); } - public Object FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } - public Object ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } + public String[] FreepsGetADParam(String paramName) { return GetAwaitingDecisionParam(P1, paramName); } + public String[] ShadowGetADParam(String paramName) { return GetAwaitingDecisionParam(P2, paramName); } public String[] GetAwaitingDecisionParam(String playerID, String paramName) { AwaitingDecision decision = _userFeedback.getAwaitingDecision(playerID); return decision.getDecisionParameters().get(paramName); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java index b89d37ea7..2b57ef072 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Elrond_LoRErrataTests.java @@ -192,7 +192,7 @@ public class Elrond_LoRErrataTests assertEquals(Phase.BETWEEN_TURNS, scn.GetCurrentPhase()); assertEquals(3, scn.FreepsGetADParamAsList("cardId").size()); - assertEquals("0", scn.FreepsGetADParam("min")); - assertEquals("3", scn.FreepsGetADParam("max")); + assertEquals("0", scn.FreepsGetADParam("min")[0]); + assertEquals("3", scn.FreepsGetADParam("max")[0]); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java index 8e59a5ad0..20ee8d921 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set1/Galadriel_LoLErrataTests.java @@ -118,7 +118,7 @@ public class Galadriel_LoLErrataTests //There are 5 total elf allies in play: 1 is home 3. The rest should be eligible. assertEquals(4, scn.FreepsGetADParamAsList("cardId").size()); - assertEquals("0", scn.FreepsGetADParam("min")); - assertEquals("3", scn.FreepsGetADParam("max")); + assertEquals("0", scn.FreepsGetADParam("min")[0]); + assertEquals("3", scn.FreepsGetADParam("max")[0]); } } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java index 3d2ee480e..b4b263a23 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_003Tests.java @@ -88,7 +88,7 @@ public class Card_V1_003Tests scn.FreepsPlayCard(merry); scn.FreepsPlayCard(pippin); assertTrue(scn.HasKeyword(boromir, Keyword.DAMAGE)); - //assertEquals(9, scn.GetStrength(boromir)); + assertEquals(9, scn.GetStrength(boromir)); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java index 08897e92d..c5518640f 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_006Tests.java @@ -81,7 +81,7 @@ public class Card_V1_006Tests scn.StartGame(); // 6 base, -2 for the 2 Nice Imitations on the table. - //assertEquals(4, scn.GetSiteNumber(chief)); + assertEquals(4, scn.GetSiteNumber(chief)); } @Test diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java index 7327b4ee6..c8017e1b9 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vset1/vpack1/Card_V1_007Tests.java @@ -79,7 +79,7 @@ public class Card_V1_007Tests scn.StartGame(); // 6 base, -2 for the 2 Nice Imitations on the table. - //assertEquals(4, scn.GetSiteNumber(snarler)); + assertEquals(4, scn.GetSiteNumber(snarler)); } @Test @@ -102,10 +102,8 @@ public class Card_V1_007Tests scn.AddWoundsToChar(frodo, 1); scn.FreepsSkipCurrentPhaseAction(); - //assertEquals(1, scn.GetWoundsOn(frodo)); - // Base of 4, +2 for stealth cards, +1 for wounded frodo - //assertEquals(7, scn.GetStrength(snarler)); + assertEquals(7, scn.GetStrength(snarler)); } From f958f11dec31ff621a6be0976ef1261ea8c60920 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sun, 21 Mar 2021 00:54:19 -0500 Subject: [PATCH 74/74] Fixing missing rarity files and misconfigured rarity paths. --- .../src/main/resources/errata/set50-rarity.txt | 0 .../src/main/resources/errata/set51-rarity.txt | 18 ++---------------- .../src/main/resources/errata/set70-rarity.txt | 0 .../src/main/resources/errata/set71-rarity.txt | 10 ++++++++++ .../src/main/resources/errata/set72-rarity.txt | 4 ++++ .../src/main/resources/errata/set73-rarity.txt | 6 ++++++ .../src/main/resources/setConfig.json | 4 ++-- 7 files changed, 24 insertions(+), 18 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set50-rarity.txt create mode 100644 gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set70-rarity.txt diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set50-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set50-rarity.txt new file mode 100644 index 000000000..e69de29bb diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set51-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set51-rarity.txt index b7c64de13..d6e1d6f62 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set51-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set51-rarity.txt @@ -1,16 +1,2 @@ -51R1040 -51R1045 -51R1080 -51U10108 -51R10139 -51R10195 -51U10234 -51C10248 -51C10311 -51R10313 -51U10316 -51R2032 -51R2075 -51R3042 -51R3068 -51U10108 +51R40 +51C311 diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set70-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set70-rarity.txt new file mode 100644 index 000000000..e69de29bb diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set71-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set71-rarity.txt index e69de29bb..2bba7ce1d 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set71-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set71-rarity.txt @@ -0,0 +1,10 @@ +71C138 +71C248 +71R139 +71R195 +71R313 +71R45 +71R80 +71U108 +71U234 +71U316 diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set72-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set72-rarity.txt index e69de29bb..f8186faa4 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set72-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set72-rarity.txt @@ -0,0 +1,4 @@ +72C101 +72P121 +72R108 +72R75 \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set73-rarity.txt b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set73-rarity.txt index e69de29bb..11e4a572f 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set73-rarity.txt +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/errata/set73-rarity.txt @@ -0,0 +1,6 @@ +73C108 +73R113 +73R17 +73R38 +73R67 +73U106 \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json b/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json index 09f40123b..9fda2bc5e 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/setConfig.json @@ -152,7 +152,7 @@ { "setId": "50", "setName": "PC Promo Errata", - "rarityFile": "/errata/set51-rarity.txt", + "rarityFile": "/errata/set50-rarity.txt", "originalSet": false, "merchantable": false, "needsLoading": false, @@ -334,7 +334,7 @@ { "setId": "70", "setName": "TEST-PC Promo Errata", - "rarityFile": "/errata/set71-rarity.txt", + "rarityFile": "/errata/set70-rarity.txt", "originalSet": false, "merchantable": false, "needsLoading": false,