diff --git a/src/client/components/FlagInput.ts b/src/client/components/FlagInput.ts index e4334d27f..27e31bab7 100644 --- a/src/client/components/FlagInput.ts +++ b/src/client/components/FlagInput.ts @@ -1,230 +1,231 @@ -import { LitElement, html, css } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import Countries from "../data/countries.json"; +import { LitElement, html, css } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import Countries from '../data/countries.json'; -const flagKey: string = "flag"; +const flagKey: string = 'flag'; -@customElement("flag-input") +@customElement('flag-input') export class FlagInput extends LitElement { - @state() private flag: string = ""; - @state() private search: string = ""; - @state() private showModal: boolean = false; + @state() private flag: string = ''; + @state() private search: string = ''; + @state() private showModal: boolean = false; - static styles = css` - .hidden { - display: none; - } + static styles = css` + .hidden { + display: none; + } - .flag-container { - display: flex; - } + .flag-container { + display: flex; + } - .no-selected-flag { - position: absolute; - left: 8px; - top: 8px; - height: 50px; - border-radius: 0.75rem; - border: none; - background: none; - font-size: 1rem; - cursor: pointer; - } + .no-selected-flag { + position: absolute; + left: 8px; + top: 8px; + height: 50px; + border-radius: 0.75rem; + border: none; + background: none; + font-size: 1rem; + cursor: pointer; + } - .selected-flag { - width: 48px; - cursor: pointer; - position: absolute; - left: 24px; - top: 14px; - border: 1px solid black; - } + .selected-flag { + width: 48px; + cursor: pointer; + position: absolute; + left: 24px; + top: 14px; + border: 1px solid black; + } - .flag-modal { - display: flex; - flex-direction: column; - gap: 0.5rem; - position: absolute; - top: 60px; - left: 0; - width: 560px; - height: 500px; - background-color: rgb(35 35 35 / 0.8); - -webkit-backdrop-filter: blur(12px); - backdrop-filter: blur(12px); - padding: 10px; - border-radius: 8px; - } + .flag-modal { + display: flex; + flex-direction: column; + gap: 0.5rem; + position: absolute; + top: 60px; + left: 0; + width: 560px; + height: 500px; + max-height: 50vh; + background-color: rgb(35 35 35 / 0.8); + -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(12px); + padding: 10px; + border-radius: 8px; + } - .flag-search { - height: 2rem; - border-radius: 8px; - border: none; - text-align: center; - font-size: 1.3rem; - } + .flag-search { + height: 2rem; + border-radius: 8px; + border: none; + text-align: center; + font-size: 1.3rem; + } - .flag-dropdown { - overflow-y: auto; - display: flex; - flex-direction: row; - flex-wrap: wrap; - gap: 1rem; - } + .flag-dropdown { + overflow-y: auto; + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1rem; + } - .dropdown-item { - opacity: 0.7; - width: calc(100% / 4 - 15px); - text-align: center; - color: white; - cursor: pointer; - border: none; - background: none; - } + .dropdown-item { + opacity: 0.7; + width: calc(100% / 4 - 15px); + text-align: center; + color: white; + cursor: pointer; + border: none; + background: none; + } - .dropdown-item:hover { - opacity: 1; - } + .dropdown-item:hover { + opacity: 1; + } - .country-flag { - width: 100%; - height: auto; - } + .country-flag { + width: 100%; + height: auto; + } - @media (max-width: 768px) { - .flag-modal { - left: 0px; - width: calc(100% - 16px); - height: 50vh; - } + @media (max-width: 768px) { + .flag-modal { + left: 0px; + width: calc(100% - 16px); + height: 50vh; + } - .dropdown-item { - width: calc(100% / 3 - 15px); - } - } - `; + .dropdown-item { + width: calc(100% / 3 - 15px); + } + } + `; - private handleSearch(e: Event) { - this.search = String((e.target as HTMLInputElement).value); - } + private handleSearch(e: Event) { + this.search = String((e.target as HTMLInputElement).value); + } - private setFlag(flag: string) { - this.flag = flag; - this.showModal = false; - this.storeFlag(flag); - } + private setFlag(flag: string) { + this.flag = flag; + this.showModal = false; + this.storeFlag(flag); + } - public getCurrentFlag(): string { - return this.flag; - } + public getCurrentFlag(): string { + return this.flag; + } - private getStoredFlag(): string { - const storedFlag = localStorage.getItem(flagKey); - if (storedFlag) { - return storedFlag; - } - return ""; - } + private getStoredFlag(): string { + const storedFlag = localStorage.getItem(flagKey); + if (storedFlag) { + return storedFlag; + } + return ''; + } - private storeFlag(flag: string) { - if (flag) { - localStorage.setItem(flagKey, flag); - } else if (flag === "") { - localStorage.removeItem(flagKey); - } - } + private storeFlag(flag: string) { + if (flag) { + localStorage.setItem(flagKey, flag); + } else if (flag === '') { + localStorage.removeItem(flagKey); + } + } - private dispatchFlagEvent() { - this.dispatchEvent( - new CustomEvent("flag-change", { - detail: { flag: this.flag }, - bubbles: true, - composed: true, - }) - ); - } + private dispatchFlagEvent() { + this.dispatchEvent( + new CustomEvent('flag-change', { + detail: { flag: this.flag }, + bubbles: true, + composed: true, + }) + ); + } - connectedCallback() { - super.connectedCallback(); - this.flag = this.getStoredFlag(); - this.dispatchFlagEvent(); - } + connectedCallback() { + super.connectedCallback(); + this.flag = this.getStoredFlag(); + this.dispatchFlagEvent(); + } - render() { - return html` -
- ${this.flag === "" - ? html` ` - : html` (this.showModal = true)} - />`} - ${this.showModal - ? html` -
- -
- - - ${Countries.filter( - (country) => - country.name - .toLowerCase() - .includes( - this.search.toLowerCase() - ) || - country.code - .toLowerCase() - .includes( - this.search.toLowerCase() - ) - ).map( - (country) => html` - - ` - )} -
-
- ` - : ""} -
- `; - } + render() { + return html` +
+ ${this.flag === '' + ? html` ` + : html` (this.showModal = true)} + />`} + ${this.showModal + ? html` +
+ +
+ + + ${Countries.filter( + (country) => + country.name + .toLowerCase() + .includes( + this.search.toLowerCase() + ) || + country.code + .toLowerCase() + .includes( + this.search.toLowerCase() + ) + ).map( + (country) => html` + + ` + )} +
+
+ ` + : ''} +
+ `; + } } diff --git a/src/client/data/countries.json b/src/client/data/countries.json index 07bac0fa5..a3f9e6234 100644 --- a/src/client/data/countries.json +++ b/src/client/data/countries.json @@ -1,974 +1,1336 @@ [ - { - "name": "Afghanistan", - "code": "af" - }, - { - "name": "Åland Islands", - "code": "ax" - }, - { - "name": "Albania", - "code": "al" - }, - { - "name": "Algeria", - "code": "dz" - }, - { - "name": "American Samoa", - "code": "as" - }, - { - "name": "AndorrA", - "code": "ad" - }, - { - "name": "Angola", - "code": "ao" - }, - { - "name": "Anguilla", - "code": "ai" - }, - { - "name": "Antarctica", - "code": "aq" - }, - { - "name": "Antigua and Barbuda", - "code": "ag" - }, - { - "name": "Argentina", - "code": "ar" - }, - { - "name": "Armenia", - "code": "am" - }, - { - "name": "Aruba", - "code": "aw" - }, - { - "name": "Australia", - "code": "au" - }, - { - "name": "Austria", - "code": "at" - }, - { - "name": "Azerbaijan", - "code": "az" - }, - { - "name": "Bahamas", - "code": "bs" - }, - { - "name": "Bahrain", - "code": "bh" - }, - { - "name": "Bangladesh", - "code": "bd" - }, - { - "name": "Barbados", - "code": "bb" - }, - { - "name": "Belarus", - "code": "by" - }, - { - "name": "Belgium", - "code": "be" - }, - { - "name": "Belize", - "code": "bz" - }, - { - "name": "Benin", - "code": "bj" - }, - { - "name": "Bermuda", - "code": "bm" - }, - { - "name": "Bhutan", - "code": "bt" - }, - { - "name": "Bolivia", - "code": "bo" - }, - { - "name": "Bosnia and Herzegovina", - "code": "ba" - }, - { - "name": "Botswana", - "code": "bw" - }, - { - "name": "Bouvet Island", - "code": "bv" - }, - { - "name": "Brazil", - "code": "br" - }, - { - "name": "British Indian Ocean Territory", - "code": "io" - }, - { - "name": "Brunei Darussalam", - "code": "bn" - }, - { - "name": "Bulgaria", - "code": "bg" - }, - { - "name": "Burkina Faso", - "code": "bf" - }, - { - "name": "Burundi", - "code": "bi" - }, - { - "name": "Cambodia", - "code": "kh" - }, - { - "name": "Cameroon", - "code": "cm" - }, - { - "name": "Canada", - "code": "ca" - }, - { - "name": "Cape Verde", - "code": "cv" - }, - { - "name": "Cayman Islands", - "code": "ky" - }, - { - "name": "Central African Republic", - "code": "cf" - }, - { - "name": "Chad", - "code": "td" - }, - { - "name": "Chile", - "code": "cl" - }, - { - "name": "China", - "code": "cn" - }, - { - "name": "Christmas Island", - "code": "cx" - }, - { - "name": "Cocos (Keeling) Islands", - "code": "cc" - }, - { - "name": "Colombia", - "code": "co" - }, - { - "name": "Comoros", - "code": "km" - }, - { - "name": "Congo", - "code": "cg" - }, - { - "name": "Congo, The Democratic Republic of the", - "code": "cd" - }, - { - "name": "Cook Islands", - "code": "ck" - }, - { - "name": "Costa Rica", - "code": "cr" - }, - { - "name": "Cote D'Ivoire", - "code": "ci" - }, - { - "name": "Croatia", - "code": "hr" - }, - { - "name": "Cuba", - "code": "cu" - }, - { - "name": "Cyprus", - "code": "cy" - }, - { - "name": "Czech Republic", - "code": "cz" - }, - { - "name": "Denmark", - "code": "dk" - }, - { - "name": "Djibouti", - "code": "dj" - }, - { - "name": "Dominica", - "code": "dm" - }, - { - "name": "Dominican Republic", - "code": "do" - }, - { - "name": "Ecuador", - "code": "ec" - }, - { - "name": "Egypt", - "code": "eg" - }, - { - "name": "El Salvador", - "code": "sv" - }, - { - "name": "Equatorial Guinea", - "code": "gq" - }, - { - "name": "Eritrea", - "code": "er" - }, - { - "name": "Estonia", - "code": "ee" - }, - { - "name": "Ethiopia", - "code": "et" - }, - { - "name": "Falkland Islands (Malvinas)", - "code": "fk" - }, - { - "name": "Faroe Islands", - "code": "fo" - }, - { - "name": "Fiji", - "code": "fj" - }, - { - "name": "Finland", - "code": "fi" - }, - { - "name": "France", - "code": "fr" - }, - { - "name": "French Guiana", - "code": "gf" - }, - { - "name": "French Polynesia", - "code": "pf" - }, - { - "name": "French Southern Territories", - "code": "tf" - }, - { - "name": "Gabon", - "code": "ga" - }, - { - "name": "Gambia", - "code": "gm" - }, - { - "name": "Georgia", - "code": "ge" - }, - { - "name": "Germany", - "code": "de" - }, - { - "name": "Ghana", - "code": "gh" - }, - { - "name": "Gibraltar", - "code": "gi" - }, - { - "name": "Greece", - "code": "gr" - }, - { - "name": "Greenland", - "code": "gl" - }, - { - "name": "Grenada", - "code": "gd" - }, - { - "name": "Guadeloupe", - "code": "gp" - }, - { - "name": "Guam", - "code": "gu" - }, - { - "name": "Guatemala", - "code": "gt" - }, - { - "name": "Guernsey", - "code": "gg" - }, - { - "name": "Guinea", - "code": "gn" - }, - { - "name": "Guinea-Bissau", - "code": "gw" - }, - { - "name": "Guyana", - "code": "gy" - }, - { - "name": "Haiti", - "code": "ht" - }, - { - "name": "Heard Island and Mcdonald Islands", - "code": "hm" - }, - { - "name": "Holy See (Vatican City State)", - "code": "va" - }, - { - "name": "Honduras", - "code": "hn" - }, - { - "name": "Hong Kong", - "code": "hk" - }, - { - "name": "Hungary", - "code": "hu" - }, - { - "name": "Iceland", - "code": "is" - }, - { - "name": "India", - "code": "in" - }, - { - "name": "Indonesia", - "code": "id" - }, - { - "name": "Iran, Islamic Republic Of", - "code": "ir" - }, - { - "name": "Iraq", - "code": "iq" - }, - { - "name": "Ireland", - "code": "ie" - }, - { - "name": "Isle of Man", - "code": "im" - }, - { - "name": "Israel", - "code": "il" - }, - { - "name": "Italy", - "code": "it" - }, - { - "name": "Jamaica", - "code": "jm" - }, - { - "name": "Japan", - "code": "jp" - }, - { - "name": "Jersey", - "code": "je" - }, - { - "name": "Jordan", - "code": "jo" - }, - { - "name": "Kazakhstan", - "code": "kz" - }, - { - "name": "Kenya", - "code": "ke" - }, - { - "name": "Kiribati", - "code": "ki" - }, - { - "name": "Korea, Democratic People'S Republic of", - "code": "kp" - }, - { - "name": "Korea, Republic of", - "code": "kr" - }, - { - "name": "Kuwait", - "code": "kw" - }, - { - "name": "Kyrgyzstan", - "code": "kg" - }, - { - "name": "Lao People'S Democratic Republic", - "code": "la" - }, - { - "name": "Latvia", - "code": "lv" - }, - { - "name": "Lebanon", - "code": "lb" - }, - { - "name": "Lesotho", - "code": "ls" - }, - { - "name": "Liberia", - "code": "lr" - }, - { - "name": "Libyan Arab Jamahiriya", - "code": "ly" - }, - { - "name": "Liechtenstein", - "code": "li" - }, - { - "name": "Lithuania", - "code": "lt" - }, - { - "name": "Luxembourg", - "code": "lu" - }, - { - "name": "Macao", - "code": "mo" - }, - { - "name": "Macedonia, The Former Yugoslav Republic of", - "code": "mk" - }, - { - "name": "Madagascar", - "code": "mg" - }, - { - "name": "Malawi", - "code": "mw" - }, - { - "name": "Malaysia", - "code": "my" - }, - { - "name": "Maldives", - "code": "mv" - }, - { - "name": "Mali", - "code": "ml" - }, - { - "name": "Malta", - "code": "mt" - }, - { - "name": "Marshall Islands", - "code": "mh" - }, - { - "name": "Martinique", - "code": "mq" - }, - { - "name": "Mauritania", - "code": "mr" - }, - { - "name": "Mauritius", - "code": "mu" - }, - { - "name": "Mayotte", - "code": "yt" - }, - { - "name": "Mexico", - "code": "mx" - }, - { - "name": "Micronesia, Federated States of", - "code": "fm" - }, - { - "name": "Moldova, Republic of", - "code": "md" - }, - { - "name": "Monaco", - "code": "mc" - }, - { - "name": "Mongolia", - "code": "mn" - }, - { - "name": "Montserrat", - "code": "ms" - }, - { - "name": "Morocco", - "code": "ma" - }, - { - "name": "Mozambique", - "code": "mz" - }, - { - "name": "Myanmar", - "code": "mm" - }, - { - "name": "Namibia", - "code": "na" - }, - { - "name": "Nauru", - "code": "nr" - }, - { - "name": "Nepal", - "code": "np" - }, - { - "name": "Netherlands", - "code": "nl" - }, - { - "name": "Netherlands Antilles", - "code": "an" - }, - { - "name": "New Caledonia", - "code": "nc" - }, - { - "name": "New Zealand", - "code": "nz" - }, - { - "name": "Nicaragua", - "code": "ni" - }, - { - "name": "Niger", - "code": "ne" - }, - { - "name": "Nigeria", - "code": "ng" - }, - { - "name": "Niue", - "code": "nu" - }, - { - "name": "Norfolk Island", - "code": "nf" - }, - { - "name": "Northern Mariana Islands", - "code": "mp" - }, - { - "name": "Norway", - "code": "no" - }, - { - "name": "Oman", - "code": "om" - }, - { - "name": "Pakistan", - "code": "pk" - }, - { - "name": "Palau", - "code": "pw" - }, - { - "name": "Palestinian Territory, Occupied", - "code": "ps" - }, - { - "name": "Panama", - "code": "pa" - }, - { - "name": "Papua New Guinea", - "code": "pg" - }, - { - "name": "Paraguay", - "code": "py" - }, - { - "name": "Peru", - "code": "pe" - }, - { - "name": "Philippines", - "code": "ph" - }, - { - "name": "Pitcairn", - "code": "pn" - }, - { - "name": "Poland", - "code": "pl" - }, - { - "name": "Portugal", - "code": "pt" - }, - { - "name": "Puerto Rico", - "code": "pr" - }, - { - "name": "Qatar", - "code": "qa" - }, - { - "name": "Reunion", - "code": "re" - }, - { - "name": "Romania", - "code": "ro" - }, - { - "name": "Russian Federation", - "code": "ru" - }, - { - "name": "RWANDA", - "code": "rw" - }, - { - "name": "Saint Helena", - "code": "sh" - }, - { - "name": "Saint Kitts and Nevis", - "code": "kn" - }, - { - "name": "Saint Lucia", - "code": "lc" - }, - { - "name": "Saint Pierre and Miquelon", - "code": "pm" - }, - { - "name": "Saint Vincent and the Grenadines", - "code": "vc" - }, - { - "name": "Samoa", - "code": "ws" - }, - { - "name": "San Marino", - "code": "sm" - }, - { - "name": "Sao Tome and Principe", - "code": "st" - }, - { - "name": "Saudi Arabia", - "code": "sa" - }, - { - "name": "Senegal", - "code": "sn" - }, - { - "name": "Serbia and Montenegro", - "code": "cs" - }, - { - "name": "Seychelles", - "code": "sc" - }, - { - "name": "Sierra Leone", - "code": "sl" - }, - { - "name": "Singapore", - "code": "sg" - }, - { - "name": "Slovakia", - "code": "sk" - }, - { - "name": "Slovenia", - "code": "si" - }, - { - "name": "Solomon Islands", - "code": "sb" - }, - { - "name": "Somalia", - "code": "so" - }, - { - "name": "South Africa", - "code": "za" - }, - { - "name": "South Georgia and the South Sandwich Islands", - "code": "gs" - }, - { - "name": "Spain", - "code": "es" - }, - { - "name": "Sri Lanka", - "code": "lk" - }, - { - "name": "Sudan", - "code": "sd" - }, - { - "name": "Suriname", - "code": "sr" - }, - { - "name": "Svalbard and Jan Mayen", - "code": "sj" - }, - { - "name": "Swaziland", - "code": "sz" - }, - { - "name": "Sweden", - "code": "se" - }, - { - "name": "Switzerland", - "code": "ch" - }, - { - "name": "Syrian Arab Republic", - "code": "sy" - }, - { - "name": "Taiwan, Province of China", - "code": "tw" - }, - { - "name": "Tajikistan", - "code": "tj" - }, - { - "name": "Tanzania, United Republic of", - "code": "tz" - }, - { - "name": "Thailand", - "code": "th" - }, - { - "name": "Timor-Leste", - "code": "tl" - }, - { - "name": "Togo", - "code": "tg" - }, - { - "name": "Tokelau", - "code": "tk" - }, - { - "name": "Tonga", - "code": "to" - }, - { - "name": "Trinidad and Tobago", - "code": "tt" - }, - { - "name": "Tunisia", - "code": "tn" - }, - { - "name": "Turkey", - "code": "tr" - }, - { - "name": "Turkmenistan", - "code": "tm" - }, - { - "name": "Turks and Caicos Islands", - "code": "tc" - }, - { - "name": "Tuvalu", - "code": "tv" - }, - { - "name": "Uganda", - "code": "ug" - }, - { - "name": "Ukraine", - "code": "ua" - }, - { - "name": "United Arab Emirates", - "code": "ae" - }, - { - "name": "United Kingdom", - "code": "gb" - }, - { - "name": "United States", - "code": "us" - }, - { - "name": "United States Minor Outlying Islands", - "code": "um" - }, - { - "name": "Uruguay", - "code": "uy" - }, - { - "name": "Uzbekistan", - "code": "uz" - }, - { - "name": "Vanuatu", - "code": "vu" - }, - { - "name": "Venezuela", - "code": "ve" - }, - { - "name": "Viet Nam", - "code": "vn" - }, - { - "name": "Virgin Islands, British", - "code": "vg" - }, - { - "name": "Virgin Islands, U.S.", - "code": "vi" - }, - { - "name": "Wallis and Futuna", - "code": "wf" - }, - { - "name": "Western Sahara", - "code": "eh" - }, - { - "name": "Yemen", - "code": "ye" - }, - { - "name": "Zambia", - "code": "zm" - }, - { - "name": "Zimbabwe", - "code": "zw" - } -] \ No newline at end of file + { + "code": "af", + "continent": "Asia", + "name": "Afghanistan" + }, + { + "code": "ax", + "continent": "Europe", + "name": "Aland Islands" + }, + { + "code": "al", + "continent": "Europe", + "name": "Albania" + }, + { + "code": "dz", + "continent": "Africa", + "name": "Algeria" + }, + { + "code": "as", + "continent": "Oceania", + "name": "American Samoa" + }, + { + "code": "ad", + "continent": "Europe", + "name": "Andorra" + }, + { + "code": "ao", + "continent": "Africa", + "name": "Angola" + }, + { + "code": "ai", + "continent": "North America", + "name": "Anguilla" + }, + { + "code": "aq", + "name": "Antarctica" + }, + { + "code": "ag", + "continent": "North America", + "name": "Antigua and Barbuda" + }, + { + "code": "ar", + "continent": "South America", + "name": "Argentina" + }, + { + "code": "am", + "continent": "Asia", + "name": "Armenia" + }, + { + "code": "aw", + "continent": "South America", + "name": "Aruba" + }, + { + "code": "sh-ac", + "continent": "Africa", + "name": "Ascension Island" + }, + { + "code": "asean", + "name": "Association of Southeast Asian Nations" + }, + { + "code": "au", + "continent": "Oceania", + "name": "Australia" + }, + { + "code": "at", + "continent": "Europe", + "name": "Austria" + }, + { + "code": "az", + "continent": "Asia", + "name": "Azerbaijan" + }, + { + "code": "bs", + "continent": "North America", + "name": "Bahamas" + }, + { + "code": "bh", + "continent": "Asia", + "name": "Bahrain" + }, + { + "code": "bd", + "continent": "Asia", + "name": "Bangladesh" + }, + { + "code": "bb", + "continent": "North America", + "name": "Barbados" + }, + { + "code": "es-pv", + "name": "Basque Country" + }, + { + "code": "by", + "continent": "Europe", + "name": "Belarus" + }, + { + "code": "be", + "continent": "Europe", + "name": "Belgium" + }, + { + "code": "bz", + "continent": "North America", + "name": "Belize" + }, + { + "code": "bj", + "continent": "Africa", + "name": "Benin" + }, + { + "code": "bm", + "continent": "North America", + "name": "Bermuda" + }, + { + "code": "bt", + "continent": "Asia", + "name": "Bhutan" + }, + { + "code": "bo", + "continent": "South America", + "name": "Bolivia" + }, + { + "code": "bq", + "continent": "South America", + "name": "Bonaire, Sint Eustatius and Saba" + }, + { + "code": "ba", + "continent": "Europe", + "name": "Bosnia and Herzegovina" + }, + { + "code": "bw", + "continent": "Africa", + "name": "Botswana" + }, + { + "code": "bv", + "name": "Bouvet Island" + }, + { + "code": "br", + "continent": "South America", + "name": "Brazil" + }, + { + "code": "io", + "continent": "Asia", + "name": "British Indian Ocean Territory" + }, + { + "code": "bn", + "continent": "Asia", + "name": "Brunei Darussalam" + }, + { + "code": "bg", + "continent": "Europe", + "name": "Bulgaria" + }, + { + "code": "bf", + "continent": "Africa", + "name": "Burkina Faso" + }, + { + "code": "bi", + "continent": "Africa", + "name": "Burundi" + }, + { + "code": "cv", + "continent": "Africa", + "name": "Cabo Verde" + }, + { + "code": "kh", + "continent": "Asia", + "name": "Cambodia" + }, + { + "code": "cm", + "continent": "Africa", + "name": "Cameroon" + }, + { + "code": "ca", + "continent": "North America", + "name": "Canada" + }, + { + "code": "ic", + "name": "Canary Islands" + }, + { + "code": "es-ct", + "name": "Catalonia" + }, + { + "code": "ky", + "continent": "North America", + "name": "Cayman Islands" + }, + { + "code": "cf", + "continent": "Africa", + "name": "Central African Republic" + }, + { + "code": "cefta", + "name": "Central European Free Trade Agreement" + }, + { + "code": "td", + "continent": "Africa", + "name": "Chad" + }, + { + "code": "cl", + "continent": "South America", + "name": "Chile" + }, + { + "code": "cn", + "continent": "Asia", + "name": "China" + }, + { + "code": "cx", + "continent": "Asia", + "name": "Christmas Island" + }, + { + "code": "cp", + "name": "Clipperton Island" + }, + { + "code": "cc", + "continent": "Asia", + "name": "Cocos (Keeling) Islands" + }, + { + "code": "co", + "continent": "South America", + "name": "Colombia" + }, + { + "code": "km", + "continent": "Africa", + "name": "Comoros" + }, + { + "code": "ck", + "continent": "Oceania", + "name": "Cook Islands" + }, + { + "code": "cr", + "continent": "North America", + "name": "Costa Rica" + }, + { + "code": "hr", + "continent": "Europe", + "name": "Croatia" + }, + { + "code": "cu", + "continent": "North America", + "name": "Cuba" + }, + { + "code": "cw", + "continent": "South America", + "name": "Curaçao" + }, + { + "code": "cy", + "continent": "Europe", + "name": "Cyprus" + }, + { + "code": "cz", + "continent": "Europe", + "name": "Czech Republic" + }, + { + "code": "ci", + "continent": "Africa", + "name": "Côte d'Ivoire" + }, + { + "code": "cd", + "continent": "Africa", + "name": "Democratic Republic of the Congo" + }, + { + "code": "dk", + "continent": "Europe", + "name": "Denmark" + }, + { + "code": "dg", + "name": "Diego Garcia" + }, + { + "code": "dj", + "continent": "Africa", + "name": "Djibouti" + }, + { + "code": "dm", + "continent": "North America", + "name": "Dominica" + }, + { + "code": "do", + "continent": "North America", + "name": "Dominican Republic" + }, + { + "code": "eac", + "name": "East African Community" + }, + { + "code": "ec", + "continent": "South America", + "name": "Ecuador" + }, + { + "code": "eg", + "continent": "Africa", + "name": "Egypt" + }, + { + "code": "sv", + "continent": "North America", + "name": "El Salvador" + }, + { + "code": "gb-eng", + "continent": "Europe", + "name": "England" + }, + { + "code": "gq", + "continent": "Africa", + "name": "Equatorial Guinea" + }, + { + "code": "er", + "continent": "Africa", + "name": "Eritrea" + }, + { + "code": "ee", + "continent": "Europe", + "name": "Estonia" + }, + { + "code": "sz", + "continent": "Africa", + "name": "Eswatini" + }, + { + "code": "et", + "continent": "Africa", + "name": "Ethiopia" + }, + { + "code": "eu", + "name": "Europe" + }, + { + "code": "fk", + "continent": "South America", + "name": "Falkland Islands" + }, + { + "code": "fo", + "continent": "Europe", + "name": "Faroe Islands" + }, + { + "code": "fm", + "continent": "Oceania", + "name": "Federated States of Micronesia" + }, + { + "code": "fj", + "continent": "Oceania", + "name": "Fiji" + }, + { + "code": "fi", + "continent": "Europe", + "name": "Finland" + }, + { + "code": "fr", + "continent": "Europe", + "name": "France" + }, + { + "code": "gf", + "continent": "South America", + "name": "French Guiana" + }, + { + "code": "pf", + "continent": "Oceania", + "name": "French Polynesia" + }, + { + "code": "tf", + "continent": "Africa", + "name": "French Southern Territories" + }, + { + "code": "ga", + "continent": "Africa", + "name": "Gabon" + }, + { + "code": "es-ga", + "name": "Galicia" + }, + { + "code": "gm", + "continent": "Africa", + "name": "Gambia" + }, + { + "code": "ge", + "continent": "Asia", + "name": "Georgia" + }, + { + "code": "de", + "continent": "Europe", + "name": "Germany" + }, + { + "code": "gh", + "continent": "Africa", + "name": "Ghana" + }, + { + "code": "gi", + "continent": "Europe", + "name": "Gibraltar" + }, + { + "code": "gr", + "continent": "Europe", + "name": "Greece" + }, + { + "code": "gl", + "continent": "North America", + "name": "Greenland" + }, + { + "code": "gd", + "continent": "North America", + "name": "Grenada" + }, + { + "code": "gp", + "continent": "North America", + "name": "Guadeloupe" + }, + { + "code": "gu", + "continent": "Oceania", + "name": "Guam" + }, + { + "code": "gt", + "continent": "North America", + "name": "Guatemala" + }, + { + "code": "gg", + "continent": "Europe", + "name": "Guernsey" + }, + { + "code": "gn", + "continent": "Africa", + "name": "Guinea" + }, + { + "code": "gw", + "continent": "Africa", + "name": "Guinea-Bissau" + }, + { + "code": "gy", + "continent": "South America", + "name": "Guyana" + }, + { + "code": "ht", + "continent": "North America", + "name": "Haiti" + }, + { + "code": "hm", + "name": "Heard Island and McDonald Islands" + }, + { + "code": "va", + "continent": "Europe", + "name": "Holy See" + }, + { + "code": "hn", + "continent": "North America", + "name": "Honduras" + }, + { + "code": "hk", + "continent": "Asia", + "name": "Hong Kong" + }, + { + "code": "hu", + "continent": "Europe", + "name": "Hungary" + }, + { + "code": "is", + "continent": "Europe", + "name": "Iceland" + }, + { + "code": "in", + "continent": "Asia", + "name": "India" + }, + { + "code": "id", + "continent": "Asia", + "name": "Indonesia" + }, + { + "code": "ir", + "continent": "Asia", + "name": "Iran" + }, + { + "code": "iq", + "continent": "Asia", + "name": "Iraq" + }, + { + "code": "ie", + "continent": "Europe", + "name": "Ireland" + }, + { + "code": "im", + "continent": "Europe", + "name": "Isle of Man" + }, + { + "code": "il", + "continent": "Asia", + "name": "Israel" + }, + { + "code": "it", + "continent": "Europe", + "name": "Italy" + }, + { + "code": "jm", + "continent": "North America", + "name": "Jamaica" + }, + { + "code": "jp", + "continent": "Asia", + "name": "Japan" + }, + { + "code": "je", + "continent": "Europe", + "name": "Jersey" + }, + { + "code": "jo", + "continent": "Asia", + "name": "Jordan" + }, + { + "code": "kz", + "continent": "Asia", + "name": "Kazakhstan" + }, + { + "code": "ke", + "continent": "Africa", + "name": "Kenya" + }, + { + "code": "ki", + "continent": "Oceania", + "name": "Kiribati" + }, + { + "code": "xk", + "continent": "Europe", + "name": "Kosovo" + }, + { + "code": "kw", + "continent": "Asia", + "name": "Kuwait" + }, + { + "code": "kg", + "continent": "Asia", + "name": "Kyrgyzstan" + }, + { + "code": "la", + "continent": "Asia", + "name": "Laos" + }, + { + "code": "lv", + "continent": "Europe", + "name": "Latvia" + }, + { + "code": "arab", + "name": "League of Arab States" + }, + { + "code": "lb", + "continent": "Asia", + "name": "Lebanon" + }, + { + "code": "ls", + "continent": "Africa", + "name": "Lesotho" + }, + { + "code": "lr", + "continent": "Africa", + "name": "Liberia" + }, + { + "code": "ly", + "continent": "Africa", + "name": "Libya" + }, + { + "code": "li", + "continent": "Europe", + "name": "Liechtenstein" + }, + { + "code": "lt", + "continent": "Europe", + "name": "Lithuania" + }, + { + "code": "lu", + "continent": "Europe", + "name": "Luxembourg" + }, + { + "code": "mo", + "continent": "Asia", + "name": "Macau" + }, + { + "code": "mg", + "continent": "Africa", + "name": "Madagascar" + }, + { + "code": "mw", + "continent": "Africa", + "name": "Malawi" + }, + { + "code": "my", + "continent": "Asia", + "name": "Malaysia" + }, + { + "code": "mv", + "continent": "Asia", + "name": "Maldives" + }, + { + "code": "ml", + "continent": "Africa", + "name": "Mali" + }, + { + "code": "mt", + "continent": "Europe", + "name": "Malta" + }, + { + "code": "mh", + "continent": "Oceania", + "name": "Marshall Islands" + }, + { + "code": "mq", + "continent": "North America", + "name": "Martinique" + }, + { + "code": "mr", + "continent": "Africa", + "name": "Mauritania" + }, + { + "code": "mu", + "continent": "Africa", + "name": "Mauritius" + }, + { + "code": "yt", + "continent": "Africa", + "name": "Mayotte" + }, + { + "code": "mx", + "continent": "North America", + "name": "Mexico" + }, + { + "code": "md", + "continent": "Europe", + "name": "Moldova" + }, + { + "code": "mc", + "continent": "Europe", + "name": "Monaco" + }, + { + "code": "mn", + "continent": "Asia", + "name": "Mongolia" + }, + { + "code": "me", + "continent": "Europe", + "name": "Montenegro" + }, + { + "code": "ms", + "continent": "North America", + "name": "Montserrat" + }, + { + "code": "ma", + "continent": "Africa", + "name": "Morocco" + }, + { + "code": "mz", + "continent": "Africa", + "name": "Mozambique" + }, + { + "code": "mm", + "continent": "Asia", + "name": "Myanmar" + }, + { + "code": "na", + "continent": "Africa", + "name": "Namibia" + }, + { + "code": "nr", + "continent": "Oceania", + "name": "Nauru" + }, + { + "code": "np", + "continent": "Asia", + "name": "Nepal" + }, + { + "code": "nl", + "continent": "Europe", + "name": "Netherlands" + }, + { + "code": "nc", + "continent": "Oceania", + "name": "New Caledonia" + }, + { + "code": "nz", + "continent": "Oceania", + "name": "New Zealand" + }, + { + "code": "ni", + "continent": "North America", + "name": "Nicaragua" + }, + { + "code": "ne", + "continent": "Africa", + "name": "Niger" + }, + { + "code": "ng", + "continent": "Africa", + "name": "Nigeria" + }, + { + "code": "nu", + "continent": "Oceania", + "name": "Niue" + }, + { + "code": "nf", + "continent": "Oceania", + "name": "Norfolk Island" + }, + { + "code": "kp", + "continent": "Asia", + "name": "North Korea" + }, + { + "code": "mk", + "continent": "Europe", + "name": "North Macedonia" + }, + { + "code": "gb-nir", + "continent": "Europe", + "name": "Northern Ireland" + }, + { + "code": "mp", + "continent": "Oceania", + "name": "Northern Mariana Islands" + }, + { + "code": "no", + "continent": "Europe", + "name": "Norway" + }, + { + "code": "om", + "continent": "Asia", + "name": "Oman" + }, + { + "code": "pc", + "name": "Pacific Community" + }, + { + "code": "pk", + "continent": "Asia", + "name": "Pakistan" + }, + { + "code": "pw", + "continent": "Oceania", + "name": "Palau" + }, + { + "code": "pa", + "continent": "North America", + "name": "Panama" + }, + { + "code": "pg", + "continent": "Oceania", + "name": "Papua New Guinea" + }, + { + "code": "py", + "continent": "South America", + "name": "Paraguay" + }, + { + "code": "pe", + "continent": "South America", + "name": "Peru" + }, + { + "code": "ph", + "continent": "Asia", + "name": "Philippines" + }, + { + "code": "pn", + "continent": "Oceania", + "name": "Pitcairn" + }, + { + "code": "pl", + "continent": "Europe", + "name": "Poland" + }, + { + "code": "pt", + "continent": "Europe", + "name": "Portugal" + }, + { + "code": "pr", + "continent": "North America", + "name": "Puerto Rico" + }, + { + "code": "qa", + "continent": "Asia", + "name": "Qatar" + }, + { + "code": "cg", + "continent": "Africa", + "name": "Republic of the Congo" + }, + { + "code": "ro", + "continent": "Europe", + "name": "Romania" + }, + { + "code": "ru", + "continent": "Europe", + "name": "Russia" + }, + { + "code": "rw", + "continent": "Africa", + "name": "Rwanda" + }, + { + "code": "re", + "continent": "Africa", + "name": "Réunion" + }, + { + "code": "bl", + "continent": "North America", + "name": "Saint Barthélemy" + }, + { + "code": "sh-hl", + "continent": "Africa", + "name": "Saint Helena" + }, + { + "code": "sh", + "continent": "Africa", + "name": "Saint Helena, Ascension and Tristan da Cunha" + }, + { + "code": "kn", + "continent": "North America", + "name": "Saint Kitts and Nevis" + }, + { + "code": "lc", + "continent": "North America", + "name": "Saint Lucia" + }, + { + "code": "mf", + "continent": "North America", + "name": "Saint Martin" + }, + { + "code": "pm", + "continent": "North America", + "name": "Saint Pierre and Miquelon" + }, + { + "code": "vc", + "continent": "North America", + "name": "Saint Vincent and the Grenadines" + }, + { + "code": "ws", + "continent": "Oceania", + "name": "Samoa" + }, + { + "code": "sm", + "continent": "Europe", + "name": "San Marino" + }, + { + "code": "st", + "continent": "Africa", + "name": "Sao Tome and Principe" + }, + { + "code": "sa", + "continent": "Asia", + "name": "Saudi Arabia" + }, + { + "code": "gb-sct", + "continent": "Europe", + "name": "Scotland" + }, + { + "code": "sn", + "continent": "Africa", + "name": "Senegal" + }, + { + "code": "rs", + "continent": "Europe", + "name": "Serbia" + }, + { + "code": "sc", + "continent": "Africa", + "name": "Seychelles" + }, + { + "code": "sl", + "continent": "Africa", + "name": "Sierra Leone" + }, + { + "code": "sg", + "continent": "Asia", + "name": "Singapore" + }, + { + "code": "sx", + "continent": "North America", + "name": "Sint Maarten" + }, + { + "code": "sk", + "continent": "Europe", + "name": "Slovakia" + }, + { + "code": "si", + "continent": "Europe", + "name": "Slovenia" + }, + { + "code": "sb", + "continent": "Oceania", + "name": "Solomon Islands" + }, + { + "code": "so", + "continent": "Africa", + "name": "Somalia" + }, + { + "code": "za", + "continent": "Africa", + "name": "South Africa" + }, + { + "code": "gs", + "continent": "Antarctica", + "name": "South Georgia and the South Sandwich Islands" + }, + { + "code": "kr", + "continent": "Asia", + "name": "South Korea" + }, + { + "code": "ss", + "continent": "Africa", + "name": "South Sudan" + }, + { + "code": "es", + "continent": "Europe", + "name": "Spain" + }, + { + "code": "lk", + "continent": "Asia", + "name": "Sri Lanka" + }, + { + "code": "ps", + "continent": "Asia", + "name": "State of Palestine" + }, + { + "code": "sd", + "continent": "Africa", + "name": "Sudan" + }, + { + "code": "sr", + "continent": "South America", + "name": "Suriname" + }, + { + "code": "sj", + "continent": "Europe", + "name": "Svalbard and Jan Mayen" + }, + { + "code": "se", + "continent": "Europe", + "name": "Sweden" + }, + { + "code": "ch", + "continent": "Europe", + "name": "Switzerland" + }, + { + "code": "sy", + "continent": "Asia", + "name": "Syria" + }, + { + "code": "tw", + "continent": "Asia", + "name": "Taiwan" + }, + { + "code": "tj", + "continent": "Asia", + "name": "Tajikistan" + }, + { + "code": "tz", + "continent": "Africa", + "name": "Tanzania" + }, + { + "code": "th", + "continent": "Asia", + "name": "Thailand" + }, + { + "code": "tl", + "continent": "Asia", + "name": "Timor-Leste" + }, + { + "code": "tg", + "continent": "Africa", + "name": "Togo" + }, + { + "code": "tk", + "continent": "Oceania", + "name": "Tokelau" + }, + { + "code": "to", + "continent": "Oceania", + "name": "Tonga" + }, + { + "code": "tt", + "continent": "South America", + "name": "Trinidad and Tobago" + }, + { + "code": "sh-ta", + "continent": "Africa", + "name": "Tristan da Cunha" + }, + { + "code": "tn", + "continent": "Africa", + "name": "Tunisia" + }, + { + "code": "tm", + "continent": "Asia", + "name": "Turkmenistan" + }, + { + "code": "tc", + "continent": "North America", + "name": "Turks and Caicos Islands" + }, + { + "code": "tv", + "continent": "Oceania", + "name": "Tuvalu" + }, + { + "code": "tr", + "continent": "Asia", + "name": "Türkiye" + }, + { + "code": "ug", + "continent": "Africa", + "name": "Uganda" + }, + { + "code": "ua", + "continent": "Europe", + "name": "Ukraine" + }, + { + "code": "ae", + "continent": "Asia", + "name": "United Arab Emirates" + }, + { + "code": "gb", + "continent": "Europe", + "name": "United Kingdom" + }, + { + "code": "un", + "name": "United Nations" + }, + { + "code": "um", + "continent": "North America", + "name": "United States Minor Outlying Islands" + }, + { + "code": "us", + "continent": "North America", + "name": "United States of America" + }, + { + "code": "uy", + "continent": "South America", + "name": "Uruguay" + }, + { + "code": "uz", + "continent": "Asia", + "name": "Uzbekistan" + }, + { + "code": "vu", + "continent": "Oceania", + "name": "Vanuatu" + }, + { + "code": "ve", + "continent": "South America", + "name": "Venezuela" + }, + { + "code": "vn", + "continent": "Asia", + "name": "Vietnam" + }, + { + "code": "vg", + "continent": "North America", + "name": "Virgin Islands (British)" + }, + { + "code": "vi", + "continent": "North America", + "name": "Virgin Islands (U.S.)" + }, + { + "code": "gb-wls", + "continent": "Europe", + "name": "Wales" + }, + { + "code": "wf", + "continent": "Oceania", + "name": "Wallis and Futuna" + }, + { + "code": "eh", + "continent": "Africa", + "name": "Western Sahara" + }, + { + "code": "ye", + "continent": "Asia", + "name": "Yemen" + }, + { + "code": "zm", + "continent": "Africa", + "name": "Zambia" + }, + { + "code": "zw", + "continent": "Africa", + "name": "Zimbabwe" + } +] diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 39e58abbd..000eb3a0a 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -1,435 +1,450 @@ import { - Difficulty, - Game, - GameType, - Gold, - Player, - PlayerInfo, - PlayerType, - TerrainType, - TerraNullius, - Tick, - UnitInfo, - UnitType, -} from "../game/Game"; -import { GameMap, TileRef } from "../game/GameMap"; -import { PlayerView } from "../game/GameView"; -import { GameConfig } from "../Schemas"; -import { assertNever, within } from "../Util"; -import { Config, ServerConfig, Theme } from "./Config"; -import { pastelTheme } from "./PastelTheme"; + Difficulty, + Game, + GameType, + Gold, + Player, + PlayerInfo, + PlayerType, + TerrainType, + TerraNullius, + Tick, + UnitInfo, + UnitType, +} from '../game/Game'; +import { GameMap, TileRef } from '../game/GameMap'; +import { PlayerView } from '../game/GameView'; +import { GameConfig } from '../Schemas'; +import { assertNever, within } from '../Util'; +import { Config, ServerConfig, Theme } from './Config'; +import { pastelTheme } from './PastelTheme'; export abstract class DefaultServerConfig implements ServerConfig { - turnIntervalMs(): number { - return 100; - } - gameCreationRate(): number { - return 1 * 60 * 1000; - } - lobbyLifetime(): number { - return 2 * 60 * 1000; - } + turnIntervalMs(): number { + return 100; + } + gameCreationRate(): number { + return 1 * 60 * 1000; + } + lobbyLifetime(): number { + return 2 * 60 * 1000; + } } export class DefaultConfig implements Config { - constructor( - private _serverConfig: ServerConfig, - private _gameConfig: GameConfig - ) {} - spawnImmunityDuration(): Tick { - return 5 * 10; - } + constructor( + private _serverConfig: ServerConfig, + private _gameConfig: GameConfig + ) {} + spawnImmunityDuration(): Tick { + return 5 * 10; + } - gameConfig(): GameConfig { - return this._gameConfig; - } + gameConfig(): GameConfig { + return this._gameConfig; + } - serverConfig(): ServerConfig { - return this._serverConfig; - } + serverConfig(): ServerConfig { + return this._serverConfig; + } - difficultyModifier(difficulty: Difficulty): number { - switch (difficulty) { - case Difficulty.Easy: - return 1; - case Difficulty.Medium: - return 3; - case Difficulty.Hard: - return 9; - case Difficulty.Impossible: - return 18; - } - } + difficultyModifier(difficulty: Difficulty): number { + switch (difficulty) { + case Difficulty.Easy: + return 1; + case Difficulty.Medium: + return 3; + case Difficulty.Hard: + return 9; + case Difficulty.Impossible: + return 18; + } + } - cityPopulationIncrease(): number { - return 250_000; - } + cityPopulationIncrease(): number { + return 250_000; + } - falloutDefenseModifier(): number { - return 5; - } + falloutDefenseModifier(): number { + return 5; + } - defensePostRange(): number { - return 30; - } - defensePostDefenseBonus(): number { - return 5; - } - spawnNPCs(): boolean { - return !this._gameConfig.disableNPCs; - } - spawnBots(): boolean { - return !this._gameConfig.disableBots; - } - creativeMode(): boolean { - return this._gameConfig.creativeMode; - } - tradeShipGold(dist: number): Gold { - return 10000 + 100 * Math.pow(dist, 1.1); - } - tradeShipSpawnRate(): number { - return 500; - } + defensePostRange(): number { + return 30; + } + defensePostDefenseBonus(): number { + return 5; + } + spawnNPCs(): boolean { + return !this._gameConfig.disableNPCs; + } + spawnBots(): boolean { + return !this._gameConfig.disableBots; + } + creativeMode(): boolean { + return this._gameConfig.creativeMode; + } + tradeShipGold(dist: number): Gold { + return 10000 + 100 * Math.pow(dist, 1.1); + } + tradeShipSpawnRate(): number { + return 500; + } - unitInfo(type: UnitType): UnitInfo { - switch (type) { - case UnitType.TransportShip: - return { - cost: () => 0, - territoryBound: false, - }; - case UnitType.Warship: - return { - cost: (p: Player) => - this.creativeMode() - ? 0 - : (p.units(UnitType.Warship).length + 1) * 250_000, - territoryBound: false, - maxHealth: 1000, - }; - case UnitType.Shell: - return { - cost: () => 0, - territoryBound: false, - damage: 250, - }; - case UnitType.Port: - return { - cost: (p: Player) => - this.creativeMode() - ? 0 - : Math.min( - 1_000_000, - Math.pow(2, p.units(UnitType.Port).length) * 250_000 - ), - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 2 * 10, - }; - case UnitType.AtomBomb: - return { - cost: () => (this.creativeMode() ? 0 : 750_000), - territoryBound: false, - }; - case UnitType.HydrogenBomb: - return { - cost: () => (this.creativeMode() ? 0 : 5_000_000), - territoryBound: false, - }; - case UnitType.MIRV: - return { - cost: () => (this.creativeMode() ? 0 : 10_000_000), - territoryBound: false, - }; - case UnitType.MIRVWarhead: - return { - cost: () => 0, - territoryBound: false, - }; - case UnitType.TradeShip: - return { - cost: () => 0, - territoryBound: false, - }; - case UnitType.MissileSilo: - return { - cost: () => (this.creativeMode() ? 0 : 1_000_000), - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 10 * 10, - }; - case UnitType.DefensePost: - return { - cost: (p: Player) => - this.creativeMode() - ? 0 - : Math.min( - 250_000, - (p.units(UnitType.DefensePost).length + 1) * 50_000 - ), - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 5 * 10, - }; - case UnitType.City: - return { - cost: (p: Player) => - this.creativeMode() - ? 0 - : Math.min( - 1_000_000, - Math.pow(2, p.units(UnitType.City).length) * 125_000 - ), - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 2 * 10, - }; - case UnitType.Construction: - return { - cost: () => 0, - territoryBound: true, - }; - default: - assertNever(type); - } - } - defaultDonationAmount(sender: Player): number { - return Math.floor(sender.troops() / 3); - } - donateCooldown(): Tick { - return 10 * 10; - } - emojiMessageDuration(): Tick { - return 5 * 10; - } - emojiMessageCooldown(): Tick { - return 15 * 10; - } - targetDuration(): Tick { - return 10 * 10; - } - targetCooldown(): Tick { - return 15 * 10; - } - allianceRequestCooldown(): Tick { - return 30 * 10; - } - allianceDuration(): Tick { - return 600 * 10; - } - percentageTilesOwnedToWin(): number { - return 80; - } - boatMaxNumber(): number { - return 3; - } - boatMaxDistance(): number { - return 500; - } - numSpawnPhaseTurns(): number { - return this._gameConfig.gameType == GameType.Singleplayer ? 100 : 300; - } - numBots(): number { - return 400; - } - theme(): Theme { - return pastelTheme; - } + unitInfo(type: UnitType): UnitInfo { + switch (type) { + case UnitType.TransportShip: + return { + cost: () => 0, + territoryBound: false, + }; + case UnitType.Warship: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : (p.units(UnitType.Warship).length + 1) * 250_000, + territoryBound: false, + maxHealth: 1000, + }; + case UnitType.Shell: + return { + cost: () => 0, + territoryBound: false, + damage: 250, + }; + case UnitType.Port: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : Math.min( + 1_000_000, + Math.pow(2, p.units(UnitType.Port).length) * + 250_000 + ), + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 2 * 10, + }; + case UnitType.AtomBomb: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : 750_000, + territoryBound: false, + }; + case UnitType.HydrogenBomb: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : 5_000_000, + territoryBound: false, + }; + case UnitType.MIRV: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : 10_000_000, + territoryBound: false, + }; + case UnitType.MIRVWarhead: + return { + cost: () => 0, + territoryBound: false, + }; + case UnitType.TradeShip: + return { + cost: () => 0, + territoryBound: false, + }; + case UnitType.MissileSilo: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : 1_000_000, + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 10 * 10, + }; + case UnitType.DefensePost: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : Math.min( + 250_000, + (p.units(UnitType.DefensePost).length + 1) * + 50_000 + ), + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 5 * 10, + }; + case UnitType.City: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : Math.min( + 1_000_000, + Math.pow(2, p.units(UnitType.City).length) * + 125_000 + ), + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 2 * 10, + }; + case UnitType.Construction: + return { + cost: () => 0, + territoryBound: true, + }; + default: + assertNever(type); + } + } + defaultDonationAmount(sender: Player): number { + return Math.floor(sender.troops() / 3); + } + donateCooldown(): Tick { + return 10 * 10; + } + emojiMessageDuration(): Tick { + return 5 * 10; + } + emojiMessageCooldown(): Tick { + return 15 * 10; + } + targetDuration(): Tick { + return 10 * 10; + } + targetCooldown(): Tick { + return 15 * 10; + } + allianceRequestCooldown(): Tick { + return 30 * 10; + } + allianceDuration(): Tick { + return 600 * 10; + } + percentageTilesOwnedToWin(): number { + return 80; + } + boatMaxNumber(): number { + return 3; + } + boatMaxDistance(): number { + return 500; + } + numSpawnPhaseTurns(): number { + return this._gameConfig.gameType == GameType.Singleplayer ? 100 : 300; + } + numBots(): number { + return 400; + } + theme(): Theme { + return pastelTheme; + } - attackLogic( - gm: Game, - attackTroops: number, - attacker: Player, - defender: Player | TerraNullius, - tileToConquer: TileRef - ): { - attackerTroopLoss: number; - defenderTroopLoss: number; - tilesPerTickUsed: number; - } { - let mag = 0; - let speed = 0; - const type = gm.terrainType(tileToConquer); - switch (type) { - case TerrainType.Plains: - mag = 80; - speed = 15; - break; - case TerrainType.Highland: - mag = 100; - speed = 20; - break; - case TerrainType.Mountain: - mag = 120; - speed = 25; - break; - default: - throw new Error(`terrain type ${type} not supported`); - } - if (defender.isPlayer()) { - for (const dp of gm.nearbyDefensePosts(tileToConquer)) { - if (dp.owner() == defender) { - mag *= this.defensePostDefenseBonus(); - speed *= this.defensePostDefenseBonus(); - break; - } - } - } + attackLogic( + gm: Game, + attackTroops: number, + attacker: Player, + defender: Player | TerraNullius, + tileToConquer: TileRef + ): { + attackerTroopLoss: number; + defenderTroopLoss: number; + tilesPerTickUsed: number; + } { + let mag = 0; + let speed = 0; + const type = gm.terrainType(tileToConquer); + switch (type) { + case TerrainType.Plains: + mag = 80; + speed = 15; + break; + case TerrainType.Highland: + mag = 100; + speed = 20; + break; + case TerrainType.Mountain: + mag = 120; + speed = 25; + break; + default: + throw new Error(`terrain type ${type} not supported`); + } + if (defender.isPlayer()) { + for (const dp of gm.nearbyDefensePosts(tileToConquer)) { + if (dp.owner() == defender) { + mag *= this.defensePostDefenseBonus(); + speed *= this.defensePostDefenseBonus(); + break; + } + } + } - if (gm.hasFallout(tileToConquer)) { - mag *= this.falloutDefenseModifier(); - speed *= this.falloutDefenseModifier(); - } + if (gm.hasFallout(tileToConquer)) { + mag *= this.falloutDefenseModifier(); + speed *= this.falloutDefenseModifier(); + } - if (attacker.isPlayer() && defender.isPlayer()) { - if ( - attacker.type() == PlayerType.Human && - defender.type() == PlayerType.Bot - ) { - mag *= 0.8; - } - if ( - attacker.type() == PlayerType.FakeHuman && - defender.type() == PlayerType.Bot - ) { - mag *= 0.8; - } - } + if (attacker.isPlayer() && defender.isPlayer()) { + if ( + attacker.type() == PlayerType.Human && + defender.type() == PlayerType.Bot + ) { + mag *= 0.8; + } + if ( + attacker.type() == PlayerType.FakeHuman && + defender.type() == PlayerType.Bot + ) { + mag *= 0.8; + } + } - let largeTerritoryBonus = 1; - if (attacker.numTilesOwned() > 100_000) { - // Speed up the late game - largeTerritoryBonus = 100_000 / attacker.numTilesOwned(); - } + if (defender.isPlayer()) { + return { + attackerTroopLoss: + within(defender.troops() / (2.5 * attackTroops), 0.1, 10) * + mag, + defenderTroopLoss: defender.troops() / defender.numTilesOwned(), + tilesPerTickUsed: + within(defender.troops() / (5 * attackTroops), 0.2, 1.5) * + speed, + }; + } else { + return { + attackerTroopLoss: + attacker.type() == PlayerType.Bot ? mag / 10 : mag / 5, + defenderTroopLoss: 0, + tilesPerTickUsed: within( + (2000 * Math.max(10, speed)) / attackTroops, + 5, + 100 + ), + }; + } + } - if (defender.isPlayer()) { - return { - attackerTroopLoss: - within(defender.troops() / (attackTroops * 0.5), 0.25, 4) * - mag * - 0.5 * - largeTerritoryBonus, - defenderTroopLoss: defender.troops() / defender.numTilesOwned(), - tilesPerTickUsed: - within(defender.troops() / (5 * attackTroops), 0.2, 1.5) * - speed * - largeTerritoryBonus, - }; - } else { - return { - attackerTroopLoss: - attacker.type() == PlayerType.Bot ? mag / 10 : mag / 5, - defenderTroopLoss: 0, - tilesPerTickUsed: within( - (2000 * Math.max(10, speed)) / attackTroops, - 5, - 100 - ), - }; - } - } + attackTilesPerTick( + attackTroops: number, + attacker: Player, + defender: Player | TerraNullius, + numAdjacentTilesWithEnemy: number + ): number { + if (defender.isPlayer()) { + return ( + within( + ((5 * attackTroops) / defender.troops()) * 2, + 0.01, + 0.5 + ) * + numAdjacentTilesWithEnemy * + 3 + ); + } else { + return numAdjacentTilesWithEnemy * 2; + } + } - attackTilesPerTick( - attackTroops: number, - attacker: Player, - defender: Player | TerraNullius, - numAdjacentTilesWithEnemy: number - ): number { - if (defender.isPlayer()) { - return ( - within(((5 * attackTroops) / defender.troops()) * 2, 0.01, 0.5) * - numAdjacentTilesWithEnemy * - 3 - ); - } else { - return numAdjacentTilesWithEnemy * 2; - } - } + boatAttackAmount( + attacker: Player, + defender: Player | TerraNullius + ): number { + return Math.floor(attacker.troops() / 5); + } - boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number { - return Math.floor(attacker.troops() / 5); - } + attackAmount(attacker: Player, defender: Player | TerraNullius) { + if (attacker.type() == PlayerType.Bot) { + return attacker.troops() / 20; + } else { + return attacker.troops() / 5; + } + } - attackAmount(attacker: Player, defender: Player | TerraNullius) { - if (attacker.type() == PlayerType.Bot) { - return attacker.troops() / 20; - } else { - return attacker.troops() / 5; - } - } + startManpower(playerInfo: PlayerInfo): number { + if (playerInfo.playerType == PlayerType.Bot) { + return 10_000; + } + if (playerInfo.playerType == PlayerType.FakeHuman) { + switch (this._gameConfig.difficulty) { + case Difficulty.Easy: + return 2_500 * (playerInfo?.nation?.strength ?? 1); + case Difficulty.Medium: + return 5_000 * (playerInfo?.nation?.strength ?? 1); + case Difficulty.Hard: + return 15_000 * (playerInfo?.nation?.strength ?? 1); + case Difficulty.Impossible: + return 20_000 * (playerInfo?.nation?.strength ?? 1); + } + } + return this.creativeMode() ? 1_000_000 : 25_000; + } - startManpower(playerInfo: PlayerInfo): number { - if (playerInfo.playerType == PlayerType.Bot) { - return 10_000; - } - if (playerInfo.playerType == PlayerType.FakeHuman) { - switch (this._gameConfig.difficulty) { - case Difficulty.Easy: - return 2_500 * (playerInfo?.nation?.strength ?? 1); - case Difficulty.Medium: - return 5_000 * (playerInfo?.nation?.strength ?? 1); - case Difficulty.Hard: - return 15_000 * (playerInfo?.nation?.strength ?? 1); - case Difficulty.Impossible: - return 20_000 * (playerInfo?.nation?.strength ?? 1); - } - } - return this.creativeMode() ? 1_000_000 : 25_000; - } + maxPopulation(player: Player | PlayerView): number { + let maxPop = + player.type() == PlayerType.Human && this.creativeMode() + ? 999_999_999_999 + : 2 * (Math.pow(player.numTilesOwned(), 0.6) * 1000 + 50000) + + player.units(UnitType.City).length * + this.cityPopulationIncrease(); - maxPopulation(player: Player | PlayerView): number { - let maxPop = this.creativeMode() - ? 999_999_999_999 - : 2 * (Math.pow(player.numTilesOwned(), 0.6) * 1000 + 50000) + - player.units(UnitType.City).length * this.cityPopulationIncrease(); + if (player.type() == PlayerType.Bot) { + return maxPop / 2; + } - if (player.type() == PlayerType.Bot) { - return maxPop / 2; - } + if (player.type() == PlayerType.Human) { + return maxPop; + } - if (player.type() == PlayerType.Human) { - return maxPop; - } + switch (this._gameConfig.difficulty) { + case Difficulty.Easy: + return maxPop * 0.5; + case Difficulty.Medium: + return maxPop * 0.7; + case Difficulty.Hard: + return maxPop * 1; + case Difficulty.Impossible: + return maxPop * 1.5; + } + } - switch (this._gameConfig.difficulty) { - case Difficulty.Easy: - return maxPop * 0.5; - case Difficulty.Medium: - return maxPop * 0.7; - case Difficulty.Hard: - return maxPop * 1; - case Difficulty.Impossible: - return maxPop * 1.5; - } - } + populationIncreaseRate(player: Player): number { + let max = this.maxPopulation(player); - populationIncreaseRate(player: Player): number { - let max = this.maxPopulation(player); + let toAdd = 10 + Math.pow(player.population(), 0.73) / 4; - let toAdd = 10 + Math.pow(player.population(), 0.73) / 4; + const ratio = 1 - player.population() / max; + toAdd *= ratio; - const ratio = 1 - player.population() / max; - toAdd *= ratio; + if (player.type() == PlayerType.Bot) { + toAdd *= 0.7; + } - if (player.type() == PlayerType.Bot) { - toAdd *= 0.7; - } + return Math.min(player.population() + toAdd, max) - player.population(); + } - return Math.min(player.population() + toAdd, max) - player.population(); - } + goldAdditionRate(player: Player): number { + return Math.sqrt(player.workers() * player.numTilesOwned()) / 200; + } - goldAdditionRate(player: Player): number { - return Math.sqrt(player.workers() * player.numTilesOwned()) / 200; - } - - troopAdjustmentRate(player: Player): number { - const maxDiff = this.maxPopulation(player) / 1000; - const target = player.population() * player.targetTroopRatio(); - const diff = target - player.troops(); - if (Math.abs(diff) < maxDiff) { - return diff; - } - const adjustment = maxDiff * Math.sign(diff); - // Can ramp down troops much faster - if (adjustment < 0) { - return adjustment * 5; - } - return adjustment; - } + troopAdjustmentRate(player: Player): number { + const maxDiff = this.maxPopulation(player) / 1000; + const target = player.population() * player.targetTroopRatio(); + const diff = target - player.troops(); + if (Math.abs(diff) < maxDiff) { + return diff; + } + const adjustment = maxDiff * Math.sign(diff); + // Can ramp down troops much faster + if (adjustment < 0) { + return adjustment * 5; + } + return adjustment; + } }