Koraidon-EV.pngPokémon Écarlate et Pokémon Violet sont là, et tout le monde est invité à contribuer !
Des éléments du jeu sont présents sur le site, donc prenez garde lors de votre lecture.
Une nouvelle génération qui apporte de nombreuses nouveautés, donc beaucoup de travail sur Poképédia !
N'hésitez pas à consulter les pages d'aide et le serveur Discord en cas de doute sur la rédaction, et n'oubliez pas de prévisualiser vos modifications avant de les publier.
Miraidon-EV.png
Pokémon Écarlate et Pokémon Violet sont là, et tout le monde est invité à contribuer !
Des éléments du jeu sont présents sur le site, donc prenez garde lors de votre lecture.
Une nouvelle génération qui apporte de nombreuses nouveautés, donc beaucoup de travail sur Poképédia !
N'hésitez pas à consulter les pages d'aide et le serveur Discord en cas de doute sur la rédaction, et n'oubliez pas de prévisualiser vos modifications avant de les publier.

Module:Localisations

De Poképédia
Aller à la navigation Aller à la recherche

Fonction « pokemon »[modifier]

Cette fonction sert à générer automatiquement un tableau de localisations pour les Pokémon.

Comment ça fonctionne ?[modifier]

Dans les pages de lieux, comme Carmin sur Mer ou Route 204, sont définis des tableaux de rencontre, à l'aide du Module:Tableau Pokémon. Ces données, en plus de renseigner les Pokémon disponibles dans le lieu, peuvent ensuite être agrégées automatiquement par un outil externe. Cet outil permet de mettre à jour une base de données de localisations, disponible ici.

Comment modifier un tableau de localisations ?[modifier]

Loupe.png Pour plus d'informations sur le sujet, référez-vous à cette page.

S'il y a une erreur ou une information manquante dans un tableau de localisations sur la page d'un Pokémon, c'est que l'erreur est aussi présente dans la page du lieu correspondant. Dans ce cas, il est nécessaire de modifier la page du lieu en question, ce qui mettra à jour les bases de données (et donc les tableaux de localisations) avec les informations corrigées ou ajoutées au prochain passage de l'outil externe qui les remplit. Dans tous les cas, les bases de données évoquées dans la section précédente n'ont pas vocation à être manuellement modifiées. Pour plus d'informations, consulter cette page, ou contacter Matt.(d).

Paramètres[modifier]

Légende des icônes
Certains paramètres sont accompagnés d'une ou plusieurs icône indiquant leur(s) caractéristique(s) :
Facultatif.png : Ce paramètre est facultatif, et n'a donc pas besoin d'être systématiquement défini.
Icône catégorie.png : Ce paramètre classe automatiquement l'article dans une catégorie.
Données sémantiques.png : Ce paramètre influe sur les données sémantiques présentes en pied de page.
  • paramètre non nommé Facultatif.png : permet de forcer le nom du Pokémon à partir duquel former le tableau. Par défaut, le nom est réglé sur celui de la page en cours ({{PAGENAME}}).
  • type Facultatif.png : la couleur de fond du tableau. Par défaut, elle est égale à la couleur du premier type du Pokémon.
  • ids Facultatif.png : permet de spécifier un ou plusieurs identifiants, séparés par un slash entouré d'espaces  / . Les identifiants sont ceux utilisés dans les tableaux pour préciser des formes spécifiques, au sens du Module:Ressources/infosPokemon. Par exemple, pour afficher les localisations de Sancoki, on pourra indiquer ids=Sancoki forme(Occident) nom(Mer Occident) / Sancoki forme(Orient) nom(Mer Orient). Pour savoir les identifiants utilisés dans un jeu, utiliser la fonction pokeliste.
  • génération Facultatif.png : permet de définir une génération pour les jeux indiqués. Par défaut, la génération est 8. Sur les pages du type "XXX/Génération Y", la génération par défaut est Y. Indiquer génération=toutes permet d'afficher toutes les générations dans un seul tableau, même si cette option n'a pas vocation à figurer dans des articles.

Exemples d'utilisation[modifier]

Exemple général[modifier]

{{#invoke:Localisations|pokemon}}

sur la page « Étourmi/Génération 4 » donne :

VersionsLocalisationsDétails
Diamant et PerleRoute 201, Route 202, Route 203, Route 204, Route 209, Route 212, Grand Marais, Lac Vérité
PlatineRoute 201, Route 202, Route 203, Route 204, Lac Vérité
Or HeartGold et Argent SoulSilverArgenta
Ce tableau est généré automatiquement. Pour que son contenu soit modifié, il faut modifier les pages de lieux. Informations détaillées sur cette page.
LieuNiveauTaux
Pokémon Diamant et Perle
MatinJourNuit
Route 201 – Hautes herbes2–350 %50 %40 %
Route 201 – En insérant Vert Feuille24 %
Route 201 – En insérant Rubis24 %
Route 201 – En insérant Saphir24 %
Route 201 – En insérant Émeraude24 %
Route 202 – Hautes herbes330 %40 %30 %
Route 203 – Hautes herbes335 %45 %35 %
Route 204 (zone sud) – Hautes herbes425 %35 %25 %
Route 204 (zone nord) – Hautes herbes625 %35 %25 %
Route 209 – Hautes herbes1620 %
Route 212 (partie nord) – Hautes herbes1620 %
Grand Marais (Pokémon apparaissant tous les jours) – Hautes herbes22–2610 %10 %
Lac Vérité – Hautes herbes2–450 %50 %40 %
LieuNiveauTaux
Pokémon Platine
MatinJourNuit
Route 201 – Hautes herbes2–350 %50 %40 %
Route 202 – Hautes herbes2–320 %30 %20 %
Route 203 – Hautes herbes335 %35 %25 %
Route 204 (zone nord) – Hautes herbes9–1125 %
Route 204 (zone sud) – Hautes herbes4–625 %
Lac Vérité – Hautes herbes2–450 %
LieuNiveauTaux
Pokémon Or HeartGold et Argent SoulSilver
Argenta – Coup d'Boule (arbres isolés près de la Route 2)VariableVariable

Exemple avec des identifiants[modifier]

Pour afficher toutes les formes de Vivaldaim dans un même tableau :

{{#invoke:Localisations|pokemon|ids=Vivaldaim / Vivaldaim forme(Printemps) / Vivaldaim forme(Été) / Vivaldaim forme(Automne) / Vivaldaim forme(Hiver)}}

sur la page « Vivadaim/Génération 5 » donne :

VersionsLocalisationsDétails
Noir et BlancRoute 6, Route 7, Tour Dragospire
Noir 2 et Blanc 2Route 6, Route 7
Ce tableau est généré automatiquement. Pour que son contenu soit modifié, il faut modifier les pages de lieux. Informations détaillées sur cette page.
FormeLieuNiveauTaux
Pokémon Noir et Blanc
PrintempsÉtéAutomneHiver
Vivaldaim (Forme Printemps)Route 6 – Hautes herbes22–2435 %
Vivaldaim (Forme Printemps)Route 6 – Herbes sombres26–2835 %
Vivaldaim (Forme Été)Route 6 – Hautes herbes22–2435 %
Vivaldaim (Forme Été)Route 6 – Herbes sombres26–2835 %
Vivaldaim (Forme Automne)Route 6 – Hautes herbes22–2435 %
Vivaldaim (Forme Automne)Route 6 – Herbes sombres26–2835 %
Vivaldaim (Forme Hiver)Route 6 – Hautes herbes22–2435 %
Vivaldaim (Forme Hiver)Route 6 – Herbes sombres26–2835 %
Vivaldaim (Forme Été)Route 7 – Longues herbes2620 %
Vivaldaim (Forme Été)Route 7 – Longues herbes sombres30–3220 %
Vivaldaim (Forme Printemps)Route 7 – Longues herbes2620 %
Vivaldaim (Forme Printemps)Route 7 – Longues herbes sombres30–3220 %
Vivaldaim (Forme Hiver)Route 7 – Longues herbes2620 %
Vivaldaim (Forme Hiver)Route 7 – Longues herbes sombres30–3220 %
Vivaldaim (Forme Automne)Route 7 – Longues herbes2620 %
Vivaldaim (Forme Automne)Route 7 – Longues herbes sombres30–3220 %
Vivaldaim (Forme Hiver)Tour Dragospire (entrée) – Hautes herbes30–3330 %
Vivaldaim (Forme Automne)Tour Dragospire (entrée) – Hautes herbes30–3330 %
Vivaldaim (Forme Printemps)Tour Dragospire (entrée) – Hautes herbes30–3330 %
Vivaldaim (Forme Été)Tour Dragospire (entrée) – Hautes herbes30–3330 %
Vivaldaim (Forme Printemps)Tour Dragospire (extérieur) – Hautes herbes31–3230 %
Vivaldaim (Forme Hiver)Tour Dragospire (extérieur) – Hautes herbes31–3230 %
Vivaldaim (Forme Automne)Tour Dragospire (extérieur) – Hautes herbes31–3230 %
Vivaldaim (Forme Été)Tour Dragospire (extérieur) – Hautes herbes31–3230 %
FormeLieuNiveauTaux
Pokémon Noir 2 et Blanc 2
PrintempsÉtéAutomneHiver
Vivaldaim (Forme Hiver)Route 6 – Hautes herbes23–2530 %
Vivaldaim (Forme Hiver)Route 6 – Herbes sombres26–2830 %
Vivaldaim (Forme Été)Route 6 – Hautes herbes23–2530 %
Vivaldaim (Forme Été)Route 6 – Herbes sombres26–2830 %
Vivaldaim (Forme Automne)Route 6 – Hautes herbes23–2530 %
Vivaldaim (Forme Automne)Route 6 – Herbes sombres26–2830 %
Vivaldaim (Forme Printemps)Route 6 – Hautes herbes23–2530 %
Vivaldaim (Forme Printemps)Route 6 – Herbes sombres26–2830 %
Vivaldaim (Forme Automne)Route 7 – Longues herbes3020 %
Vivaldaim (Forme Automne)Route 7 – Longues herbes sombres3320 %
Vivaldaim (Forme Été)Route 7 – Longues herbes3020 %
Vivaldaim (Forme Été)Route 7 – Longues herbes sombres3320 %
Vivaldaim (Forme Printemps)Route 7 – Longues herbes3020 %
Vivaldaim (Forme Printemps)Route 7 – Longues herbes sombres3320 %
Vivaldaim (Forme Hiver)Route 7 – Longues herbes3020 %
Vivaldaim (Forme Hiver)Route 7 – Longues herbes sombres3320 %

Utiliser la fonction pokeliste pour savoir quels identifiants utiliser.

Fonction « pokeliste »[modifier]

Cette fonction renvoie un tableau triable, qui sert à donner un point de vue global des Pokémon trouvables directement dans un certain jeu. Elle n'a pas vocation à être utilisée directement dans les articles, mais plutôt à se rendre compte des identifiants utilisés, au sens du Module:Ressources/infosPokemon.

Paramètres[modifier]

  • jeu : l'abréviation du jeu dont on souhaite voir la liste des Pokémon trouvables.

Exemple d'utilisation[modifier]

{{#invoke:Localisations|pokeliste|jeu=J}}

donne :

infosPokemonPokémonLieux
142 PtéraPtéraLaboratoire de Cramois'Île
037 GoupixGoupixCasino de Céladopole
120 StariStariChenal 20, Bourg Palette, Îles Écume, Chenal 19, Carmin sur Mer, Chenal 21, Cramois'Île
075 GravalanchGravalanchCaverne Azurée, Route Victoire
080 FlagadossFlagadossÎles Écume
040 GrodoudouGrodoudouCasino de Céladopole
118 PoissirènePoissirèneRoute 11, Parc Safari, Chenal 20, Caverne Azurée, Route 23, Route 22, Parc Safari, Route 25, Bourg Palette, Arène d'Azuria, Îles Écume, Jadielle, Parc Safari, Chenal 19, Carmin sur Mer, Route 18, Chenal 21, Route 10, Route 6, Route 24, Azuria, Cramois'Île, Route 17, Route 13, Route 12, Parc Safari, Céladopole, Parmanie
113 LeveinardLeveinardParc Safari, Caverne Azurée, Parc Safari
044 OrtideOrtideCaverne Azurée, Route 14, Route 15, Route 13, Route 12
063 AbraAbraRoute 7, Route 5, Casino de Céladopole, Route 6, Route 8
043 MystherbeMystherbeRoute 25, Route 14, Route 24, Route 15, Route 13, Route 12
128 TaurosTaurosParc Safari, Parc Safari
056 FérosingeFérosingeRoute 23, Route 3, Route 22, Route 4
088 TadmorvTadmorvManoir Pokémon, Centrale abandonnée
137 PorygonPorygonCasino de Céladopole
133 ÉvoliÉvoliRésidence Céladon
123 InsécateurInsécateurParc Safari, Parc Safari, Casino de Céladopole
112 RhinoférosRhinoférosCaverne Azurée, Laboratoire de Cramois'Île
035 MéloféeMéloféeMont Sélénite
020 RattatacRattatacRoute 11, Route 16, Manoir Pokémon, Route 9, Route 18, Chenal 21, Route 10
032 Nidoran♂Nidoran♂Parc Safari, Route 22, Parc Safari, Route 2, Parc Safari, Route 9, Route 10, Parc Safari
111 RhinocorneRhinocorneCaverne Azurée, Parc Safari, Parc Safari
046 ParasParasMont Sélénite
130 LéviatorLéviatorParmanie
104 OsselaitOsselaitParc Safari, Parc Safari, Tour Pokémon, Parc Safari
114 SaquedeneuSaquedeneuParc Safari, Parc Safari
061 TêtarteTêtarteRoute 23, Route 22
079 RamolossRamolossÎles Écume
081 MagnétiMagnétiRoute 10, Centrale abandonnée
100 VoltorbeVoltorbeCentrale abandonnée
066 MachocMachocGrotte Sombre, Route 10
122 M. MimeM. MimeRoute 2
145 ÉlecthorÉlecthorCentrale abandonnée
116 HypotrempeHypotrempeRoute 11, Carmin sur Mer, Route 10, Route 13, Route 12
101 ÉlectrodeÉlectrodeCentrale abandonnée
117 HypocéanHypocéanRoute 13, Route 12
042 NosferaltoNosferaltoCaverne Azurée, Îles Écume, Route Victoire
147 MinidracoMinidracoParc Safari, Parc Safari, Parc Safari, Parc Safari
083 CanartichoCanartichoRoute 13, Route 12
105 OssatueurOssatueurParc Safari, Tour Pokémon, Parc Safari
085 DodrioDodrioRoute 17
064 KadabraKadabraRoute 8
047 ParasectParasectCaverne Azurée, Parc Safari, Route 18
074 RacaillouRacaillouGrotte Sombre, Route Victoire, Mont Sélénite
057 ColossingeColossingeRoute 23
143 RonflexRonflexRoute 16, Route 12
030 NidorinaNidorinaParc Safari, Route 23, Parc Safari, Route 9
119 PoissoroyPoissoroyCaverne Azurée, Route 24, Azuria
069 ChétiflorChétiflorRoute 25, Route 14, Route 24, Route 15, Route 13, Route 12
102 NoeunoeufNoeunoeufParc Safari, Parc Safari, Parc Safari, Parc Safari
144 ArtikodinArtikodinÎles Écume
098 KrabbyKrabbyRoute 25, Îles Écume, Route 10
028 SablaireauSablaireauCaverne Azurée
086 OtariaOtariaÎles Écume
025 PikachuPikachuLaboratoire Pokémon du Professeur Chen
148 DracoDracoParc Safari
050 TaupiqueurTaupiqueurGrotte Taupiqueur
151 MewMewRoute 24
131 LokhlassLokhlassSylphe SARL
055 AkwakwakAkwakwakRoute 6
010 ChenipanChenipanForêt de Jade
054 PsykokwakPsykokwakRoute 6
073 TentacruelTentacruelChenal 20, Chenal 19, Chenal 21
108 ExcelangueExcelangueCaverne Azurée
089 GrotadmorvGrotadmorvLaboratoire de Cramois'Île, Manoir Pokémon, Centrale abandonnée
146 SulfuraSulfuraRoute Victoire
048 MimitossMimitossRoute 25, Parc Safari, Route 14, Route 24, Route 15
093 SpectrumSpectrumTour Pokémon
106 KickleeKickleeDojo de Safrania
049 AéromiteAéromiteCaverne Azurée, Route 14, Route 15
140 KabutoKabutoLaboratoire de Cramois'Île
092 FantominusFantominusTour Pokémon
027 SabeletteSabeletteRoute 3, Route 4, Mont Sélénite
090 KokiyasKokiyasCarmin sur Mer, Route 18, Route 17
041 NosferaptiNosferaptiGrotte Sombre, Îles Écume, Route Victoire, Mont Sélénite
138 AmonitaAmonitaLaboratoire de Cramois'Île
051 TriopikeurTriopikeurRoute 11, Grotte Taupiqueur
060 PtitardPtitardRoute 11, Parc Safari, Chenal 20, Caverne Azurée, Route 23, Route 22, Parc Safari, Route 25, Bourg Palette, Arène d'Azuria, Îles Écume, Jadielle, Parc Safari, Chenal 19, Carmin sur Mer, Route 18, Chenal 21, Route 10, Route 6, Route 24, Azuria, Cramois'Île, Route 17, Route 13, Route 12, Parc Safari, Céladopole, Parmanie
058 CaninosCaninosManoir Pokémon
099 KrabbossKrabbossRoute 25, Îles Écume, Route 10
007 CarapuceCarapuceCarmin sur Mer
132 MétamorphMétamorphCaverne Azurée, Manoir Pokémon
004 SalamècheSalamècheRoute 24
021 PiafabecPiafabecRoute 16, Route 3, Route 22, Route 4, Route 9, Route 18
001 BulbizarreBulbizarreAzuria
077 PonytaPonytaRoute 17
096 SoporifikSoporifikRoute 11
115 KangourexKangourexParc Safari
129 MagicarpeMagicarpeRoute 11, Parc Safari, Chenal 20, Caverne Azurée, Route 23, Route 22, Parc Safari, Route 25, Bourg Palette, Arène d'Azuria, Îles Écume, Jadielle, Parc Safari, Chenal 19, Carmin sur Mer, Route 4, Route 18, Chenal 21, Route 10, Route 6, Route 24, Azuria, Cramois'Île, Route 17, Route 13, Route 12, Parc Safari, Céladopole, Parmanie
150 MewtwoMewtwoCaverne Azurée
087 LamantineLamantineLaboratoire de Cramois'Île, Îles Écume
072 TentacoolTentacoolRoute 11, Chenal 20, Bourg Palette, Chenal 19, Carmin sur Mer, Route 18, Chenal 21, Cramois'Île, Route 17, Route 13
082 MagnétonMagnétonCentrale abandonnée
084 DoduoDoduoRoute 16, Route 18, Route 17
039 RondoudouRondoudouRoute 7, Route 5, Route 6, Route 8
067 MachopeurMachopeurRoute 5, Route Victoire
022 RapasdepicRapasdepicRoute 23, Route 16, Route 9, Route 18, Route 17
029 Nidoran♀Nidoran♀Parc Safari, Route 22, Parc Safari, Route 2, Parc Safari, Route 9, Route 10, Parc Safari
019 RattataRattataRoute 7, Route 11, Route 16, Route 3, Route 22, Route 5, Route 2, Manoir Pokémon, Route 4, Route 9, Route 1, Route 18, Chenal 21, Route 10, Route 6, Route 8
017 RoucoupsRoucoupsRoute 7, Route 11, Forêt de Jade, Route 25, Route 5, Route 14, Chenal 21, Route 6, Route 24, Route 8, Route 15, Route 13, Route 12
033 NidorinoNidorinoRoute 23, Parc Safari, Route 9, Parc Safari
016 RoucoolRoucoolRoute 7, Route 11, Forêt de Jade, Route 25, Route 5, Route 2, Route 1, Chenal 21, Route 6, Route 24, Route 8, Route 13, Route 12
011 ChrysacierChrysacierForêt de Jade
095 OnixOnixGrotte Sombre, Route Victoire
127 ScarabruteScarabruteParc Safari, Casino de Céladopole, Parc Safari
107 TygnonTygnonDojo de Safrania
070 BoustiflorBoustiflorCaverne Azurée, Route 14, Route 15, Route 13, Route 12

local p = {}
local ressources = {
	["infosPokemon"] = require("Module:Ressources/infosPokemon")
}
local data_border = require("Module:Data/Bordure")
local game_to_game_long = require("Module:Data/NomsJeux")
local subareas = require("Module:Localisations/sousZones")

function p.pokemon(frame)
	local maths = require("Module:Maths")

	local result = {}
	local result_header = {}
	local full_table = {}
	
	local pokemon = frame.args[1]
	local generation
	if pokemon == nil or pokemon == ""
	then pokemon = frame:getParent():getTitle()
		local title_split = mw.text.split(pokemon, "/")
		pokemon = title_split[1]	-- remove the subpages
		if title_split[2]
		then generation = mw.ustring.gsub(title_split[2], "Génération ", "")
		end
	end
	
	local pokemon_ids = frame.args["ids"]
	local multiple_ids = false
	if pokemon_ids
	then pokemon_ids = mw.text.split(pokemon_ids, " / ")
		if pokemon_ids[2] then multiple_ids = true end
	else pokemon_ids = {pokemon}
	end
	local replacement_ids = {
		[" d'Alola"] = "Alola",
		[" de Galar"] = "Galar",
		[" de Hisui"] = "Hisui",
		[" de Paldea"] = "Paldea",
		["Méga%-"] = "Méga",
		[" Gigamax"] = "Gigamax"
	}
	for i, id in pairs(pokemon_ids) do
		local j = 1
		for replacing, replaced in pairs(replacement_ids) do
			if mw.ustring.find(pokemon_ids[i], replacing)
			then pokemon_ids[i] = mw.ustring.gsub(pokemon_ids[i], replacing, "") .. " forme(" .. replaced .. ")"
			end
		end
	end
	
	local pokemon_type = frame.args["type"]
	if not pokemon_type
	then local data_types = require("Module:Data/TypesPokémon")
		for replacing, replaced in pairs(replacement_ids) do
			if mw.ustring.find(pokemon, replacing)
			then local pokemon_without_form = mw.ustring.gsub(pokemon, replacing, "")
				local form = replaced
				local pokemon_types = data_types[pokemon_without_form]
				if pokemon_types
				then local pokemon_types_form = pokemon_types[form]
					if pokemon_types_form
					then pokemon_type = pokemon_types_form[1]
					else pokemon_type = pokemon_types[1][1]
					end
				else pokemon_type = ""
				end
				break
			end
		end
		if not pokemon_type
		then local pokemon_types = data_types[pokemon]
			if pokemon_types
			then pokemon_type = pokemon_types[1][1]
			else pokemon_type = ""
			end
		end
	end
	pokemon_type = mw.ustring.lower(pokemon_type)
	
	
	local generation_to_games = {
		{"RB", "J"},
		{"OA", "C"},
		{"RS", "RFVF", "E"},
		{"DP", "Pt", "HGSS"},
		{"NB", "NB2"},
		{"XY", "ROSA"},
		{"SL", "USUL", "LGPE"},
		{"EB", "DEPS", "LPA"},
		{"EV"}
	}
	
	local games = {}
	if frame.args["génération"] then generation = frame.args["génération"] end
	if generation == "toutes"
	then
		local n = 1
		local g = 1
		while generation_to_games[g] do
			local i = 1
			local gen_games = generation_to_games[g]
			
			while gen_games[i] do
				games[n] = gen_games[i]
				n = n + 1
				i = i + 1
			end
			g = g + 1
		end
	else
		if not tonumber(generation) then generation = 8 else generation = tonumber(generation) end
		
		games = generation_to_games[generation]
		if games == nil
		then return "<i>Erreur : numéro de génération invalide.</i>"
		end
	end
	
	if frame.args["jeux"] then games = mw.text.split(frame.args["jeux"], ", ") end
	
	
	
	local borders = {}
	local game_displays = {}
	local game_links = {}
	local locdatas = {}
	for _, game in pairs(games) do
		borders[game] = data_border[game]
		game_displays[game] = game_to_game_long[game]
		local game_link = game_to_game_long[game]
		if game ~= "LPA"
		then game_link = "Pokémon " .. game_to_game_long[game]
		end
		game_links[game] = game_link
		table.insert(locdatas, require("Module:Localisations/Données/" .. game_link))
	end
	
	
	local places = {}
	local game_id = 1
	local first_game = nil
	for _, game in pairs(games) do
		if game_id == 1 then first_game = game end
		
		local game_has_place = false
		for place_name, pokemon_list in pairs(locdatas[game_id]) do
			for _, pokemon_id in pairs(pokemon_ids) do
				local place_info = pokemon_list[pokemon_id]
				if place_info
				then table.insert(places, {["id"] = pokemon_id, ["game_id"] = game_id, ["game"] = game, ["name"] = place_name, ["contents"] = place_info})
					game_has_place = true
				end
			end
		end
		
		if not game_has_place
		then table.insert(places, {["game_id"] = game_id, ["game"] = game, ["name"] = "", ["contents"] = nil})
		end
		
		game_id = game_id + 1
	end
	
	local remove_accents = require("Module:Ressources/enleverAccents")
	table.sort(places, function(x,y)
		if x.game_id ~= y.game_id
		then return x.game_id < y.game_id
		else local x_placename = mw.text.split(mw.text.split(x.name, "@")[1], "|")[1]
			local y_placename = mw.text.split(mw.text.split(y.name, "@")[1], "|")[1]
			local x_placeid = subareas.get_subarea_id_from_place(x_placename)
			local y_placeid = subareas.get_subarea_id_from_place(y_placename)
			if x_placeid ~= y_placeid
			then return x_placeid < y_placeid
			else x_routenumber = tonumber(tostring(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(x_placename, "%(.-%).-", ""), "Route ", ""), "Chenal ", ""), "Antre ", "")))
				y_routenumber = tonumber(tostring(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(y_placename, "%(.-%).-", ""), "Route ", ""), "Chenal ", ""), "Antre ", "")))
		
				if x_routenumber
				then if y_routenumber
					then return x_routenumber < y_routenumber
					else return true
					end
				else if y_routenumber
					then return false
					else return remove_accents(x.name) < remove_accents(y.name)
					end
				end
			end
		end
	end)
	
	-- subrate precomputation
	local subrates = require("Module:Tableau Pokémon/sousTaux")

	local subarea_subrates_list = {}
	local colspan_rates = {}
	local reduced_colspan_rates = {} -- in case total colspan exceeds the 1000 limit
	local colspan_rates_decomposed = {}
	local max_rates = {}
	for _, game in pairs(games) do
		subarea_subrates_list[game] = {}
		colspan_rates[game] = 1
		reduced_colspan_rates[game] = 1
		colspan_rates_decomposed[game] = {}
		max_rates[game] = 1
	end
	
	local i = 1
	local last_place = nil
	local last_subarea = nil
	local last_game_id = nil
	local last_game = nil
	local current_subarea_has_subrates = false
	
	local rates_width = {}
	local base_rate_width = 45
	for game, _ in pairs(max_rates) do
		rates_width[game] = base_rate_width
	end
	
	function add_to_subrates(game, subarea, subarea_has_subrates)
		if subarea == nil then subarea = "" end
		
		if subarea_has_subrates
		then local subrates_subarea = subrates.raccourcis[mw.ustring.lower(subarea)]

			if subrates_subarea == nil
			then subrates_subarea = subrates[game]
			end
			
			local count = 1
			if subrates_subarea ~= nil
			then 
				while subrates_subarea[1][count + 1] do
					count = count + 1
				end
				local new_colspan_rates = maths.lcm(colspan_rates[game], count)
				colspan_rates[game] = new_colspan_rates
				table.insert(colspan_rates_decomposed[game], count)
				
				reduced_colspan_rates[game] = math.floor(colspan_rates[game] / (math.floor((new_colspan_rates - 1) / 1000) + 1))
				
				local minwidth = subrates_subarea.minwidth
				if not minwidth then minwidth = base_rate_width end
				
				rates_width[game] = math.max(rates_width[game], minwidth * count)
			end
			if not max_rates[game] or max_rates[game] < count then max_rates[game] = count end
			subarea_subrates_list[game][subarea] = {["subrates"] = subrates_subarea, ["number"] = count}
		else subarea_subrates_list[game][subarea] = {["subrates"] = nil, ["number"] = 0}
		end
	end
	
	
	-- actual subrate precomputation
	local current_game
	local current_subarea
	while places[i] do
		local current_place_id = places[i]["name"]
		local current_place_split = mw.text.split(current_place_id, "@")
		local current_place = current_place_split[1]
		local current_game_id = places[i]["game_id"]
		
		current_game = places[i]["game"]
		current_subarea = subareas.get_subarea_from_place(mw.text.split(current_place, "|")[1])
		if last_place == nil or subareas.get_subarea_id_from_place(last_place) ~= subareas.get_subarea_id_from_place(current_place) or last_game_id ~= current_game_id
		then if last_place ~= nil
			then add_to_subrates(last_game, last_subarea, current_subarea_has_subrates)
			end
			current_subarea_has_subrates = false
		end
		last_place = current_place
		last_subarea = current_subarea
		last_game = current_game
		last_game_id = current_game_id
		
		local place_info = places[i]["contents"]
		
		if place_info
		then local j = 1
			while not current_subarea_has_subrates and place_info[j] do
				if not place_info[j]["taux"]
				then current_subarea_has_subrates = true
				end
				j = j + 1
			end
		end
		i = i + 1
	end
	add_to_subrates(current_game, current_subarea, current_subarea_has_subrates)
	
	-- locations
	local current_game_locations = {}
	local current_game_locations_first_subarea = {}
	local current_game_full_locations = {}
	local current_subarea_full_locations = {}
	local seen_games_place = nil
	local number_subareas = 0
	local last_place = nil
	local current_game = nil
	local current_game_id = nil

	local last_game_id = nil
	local places_end = false
	local is_there_full_table = false
	local is_there_full_table_game = false
	local i = 1
	while true do
		last_game = current_game
		last_game_id = current_game_id
			
		if not places[i]
		then places_end = true
		else 
			current_game = places[i]["game"]
			current_game_id = places[i]["game_id"]
		end
		
		if places_end or last_game_id ~= current_game_id
		then 
			local full_table_header = {}
			
			if last_game_id ~= nil then
				-- game specifier in the simplified table, at the end of last area locations
				if last_game ~= first_game
				then table.insert(result, '</td></tr>')
				end
				table.insert(result, '<tr><td rowspan="' .. number_subareas .. '" class="' .. borders[last_game] .. '">[[' .. game_links[last_game] .. '|' .. game_displays[last_game] .. ']]</td>')
				
				-- if all encounters in the place are restricted to a single game of the two
				if seen_games_place and seen_games_place ~= "all" then table.insert(current_game_locations, frame:expandTemplate{title='Sup', args={seen_games_place}}) end
				seen_games_place = nil
				table.insert(current_game_locations, '</span></td>')
			
				if is_there_full_table_game
				then local form_header = ""
					if multiple_ids then form_header = "<th>Forme</th>" end
					table.insert(full_table_header, '<table class="tableaustandard centre ' .. pokemon_type .. '"><tbody><tr>' .. form_header
						.. '<th width="450px">Lieu</th><th width="50px">Niveau</th><th colspan="' .. reduced_colspan_rates[last_game] .. '" >Taux</th></tr>')
					
					local left_cell_colspan = 2
					if multiple_ids then left_cell_colspan = 3 end
						
					if colspan_rates[last_game] > 1
					then
						table.insert(full_table_header, '<tr><td style="padding:0px;border:0px" colspan="' .. left_cell_colspan .. '"></td>')
						local current_colspan = 0
						local factorize = reduced_colspan_rates[last_game] * 2 > rates_width[last_game]
						local is_multiple
						
						for c = 1, reduced_colspan_rates[last_game] do
							current_colspan = current_colspan + 1
							is_multiple = false
							
							local factor = 1
							if factorize
							then for _, fac in pairs(colspan_rates_decomposed[last_game]) do
									if fac ~= 1 and c % (reduced_colspan_rates[last_game] / fac) == 0
									then factor = fac
										is_multiple = true
										break
									end
								end
							end
							
							if not factorize or is_multiple
							then local colspan_text = ""
								if current_colspan ~= 1 then colspan_text = ' colspan="' .. current_colspan .. '"' end
								table.insert(full_table_header, '<td style="padding:0px;border:0px"' .. colspan_text .. '></td>')
								current_colspan = 0
							end
						end
						table.insert(full_table_header, '</tr>')
					end
					
					table.insert(full_table_header, '<tr><td colspan="' .. left_cell_colspan + reduced_colspan_rates[last_game] .. '" class="' .. borders[last_game] .. '">' .. frame:expandTemplate{title='Jeu', args={last_game}} .. '</td></tr>')
				end
				
				table.insert(current_game_full_locations, table.concat(current_subarea_full_locations, ""))
				table.insert(full_table_header, table.concat(current_game_full_locations, ""))
				table.insert(full_table, table.concat(full_table_header, ""))
				table.insert(full_table, '</tbody></table></div>')
				
			end
			
			if is_there_full_table_game
			then if number_subareas == 1
				then current_game_locations_first_subarea = current_game_locations
					current_game_locations = {}
				end
				table.insert(current_game_locations_first_subarea,
					'<td rowspan="' .. number_subareas .. '"><button type="button" name="tauxdétaillés-' .. last_game .. '" value="afficher" title="[–]">[+]</button></td></th>')
				
			else table.insert(current_game_locations, "</th>")
			end
			
			table.insert(current_game_locations_first_subarea, table.concat(current_game_locations, ""))
			table.insert(result, table.concat(current_game_locations_first_subarea, ""))
			
			current_game_locations = {}
			current_game_locations_first_subarea = {}
			current_game_full_locations = {}
			current_subarea_full_locations = {}
			
			table.insert(current_game_locations, '<td>')
			
			number_subareas = 0
			
			if places_end
			then 
				break
			else
				-- row to specify the game, at the end of last area full locations; only if the game has places
				is_there_full_table_game = (places[i]["name"] ~= "")
				if is_there_full_table_game
				then is_there_full_table = true
					table.insert(full_table, '\n<div class="tauxdétaillés-' .. current_game .. '">')
				end
			end
			
			last_place = nil
		end
		
		local place_name = places[i]["name"]
		local place_name_split = mw.text.split(place_name, "@")
		local place_link_split = mw.text.split(place_name_split[1], "|")
		local place_link = place_link_split[1]
		
		local place_link_display
		if place_link_split[2]
		then place_link_display = '[[' .. place_link_split[1] .. '|' .. place_link_split[2] .. ']]'
		else local place_link_filtered = mw.ustring.gsub(place_link, " %(.-%)", "")
			if place_link_filtered == place_link
			then place_link_display = '[[' .. place_link .. ']]'
			else place_link_display = '[[' .. place_link .. '|' .. place_link_filtered .. ']]'
			end
		end
		
		local place_suffix = ""
		
		if place_name_split[2]
		then place_suffix = " (" .. place_name_split[2] .. ")"
		end
		
		local comma_string = ""
		local subarea = subareas.get_subarea_from_place(mw.text.split(place_link, "|")[1])
		local subarea_text
		if subarea then subarea_text = subarea else subarea_text = "" end
		
		if last_place ~= place_link
		then if last_place ~= nil
			then 
				-- if all encounters in the place are restricted to a single game of the two
				if seen_games_place and seen_games_place ~= "all" then table.insert(current_game_locations, frame:expandTemplate{title='Sup', args={seen_games_place}}) end
				seen_games_place = nil
				table.insert(current_game_locations, '</span>')
			end
			
			if last_place == nil or subareas.get_subarea_id_from_place(last_place) ~= subareas.get_subarea_id_from_place(place_link)
			then 
				if last_place ~= nil
				then table.insert(current_game_locations, '</td>')
					if number_subareas == 1
					then current_game_locations_first_subarea = current_game_locations
						current_game_locations = {'</tr><tr><td>'}
					else table.insert(current_game_locations, '</tr><tr><td>')
					end
				end
				table.insert(current_game_full_locations, table.concat(current_subarea_full_locations, ""))
				current_subarea_full_locations = {}
				local subarea_text = subarea
				if not subarea then subarea_text = "" end
				local subrates_list = subarea_subrates_list[current_game][subarea_text]
				
				number_subareas = number_subareas + 1
				
				if subarea or (subrates_list and subrates_list.subrates)
				then
					local colspan_th = 2
					if multiple_ids then colspan_th = 3 end
					if subarea
					then table.insert(current_game_locations, "[[" .. subarea .. "]] : ")
						if not (subrates_list and subrates_list.subrates) then colspan_th = colspan_th + reduced_colspan_rates[current_game] end
						table.insert(current_subarea_full_locations, "<tr><th colspan='" .. colspan_th .. "'>[[" .. subarea .. "]]</th>")
					else table.insert(current_subarea_full_locations, '<tr><td style="background:transparent" colspan="' .. colspan_th .. '"></td>')
					end
					
					if subrates_list
					then local colspan_local = math.floor(reduced_colspan_rates[current_game] / subrates_list.number)
						local width_local = math.floor(rates_width[current_game] / subrates_list.number)
						
						for s = 1, subrates_list.number do
							local subrate_s = subrates_list.subrates[1][s]
							table.insert(current_subarea_full_locations, '<td class="' .. subrates_list.subrates[3][s] .. '" width="' .. width_local .. 'px" colspan="' .. colspan_local .. '">')
							if subrates_list.subrates["no_icon"]
							then table.insert(current_subarea_full_locations, subrate_s .. '</td>')
							else table.insert(current_subarea_full_locations, '[[Fichier:Icône ' .. subrate_s .. ' ' .. current_game .. '.png|' .. subrate_s .. '|link=' .. subrates_list.subrates[4][1] .. '|x25px]]</td>')
							end
						end
					end
					table.insert(current_subarea_full_locations, '</tr>')
				end
				
			else comma_string = ", "
			end
			last_place = place_link
			
			if places[i]["name"] == ""
			then 
				local unavailable_sentence = "<i>Indisponible</i>"
				-- if current_game == "EV" then unavailable_sentence = "<i>À venir</i>" end
				
				local unavailable_table = require("Module:Localisations/Données/" .. game_links[current_game] .. "/Indisponibles")
				local custom_unavailable_sentence = false
				for _, pokemon_id in pairs(pokemon_ids) do
					local unavailable_sentence_tmp = unavailable_table[pokemon_id]
					
					if unavailable_sentence_tmp
					then unavailable_sentence = unavailable_sentence_tmp
						custom_unavailable_sentence = true
						break
					end
				end
				
				if not custom_unavailable_sentence
				then local unavailable_sentence_tmp = unavailable_table[pokemon]
					if unavailable_sentence_tmp
					then unavailable_sentence = unavailable_sentence_tmp
					end
				end
				
				-- template expansion
				local template = mw.ustring.gsub(unavailable_sentence, "(.*){{(.-)|(.-)}}(.*)", "%2")
				if template and template ~= unavailable_sentence
				then local arg = mw.ustring.gsub(unavailable_sentence, "(.*){{(.-)|(.-)}}(.*)", "%3")
					local template_expanded = frame:expandTemplate{title=template, args={arg}}
					unavailable_sentence = mw.ustring.gsub(unavailable_sentence, "(.*){{(.-)|(.-)}}(.*)", "%1" .. template_expanded .. "%4")
				end
					
				current_game_locations = {'<td>' .. unavailable_sentence .. '</td><td></td>'}
			else table.insert(current_game_locations, comma_string .. '<span style="white-space:nowrap">' .. place_link_display)
				-- '</span>' is added after the end of the rate calculation, to add a possible {{Sup|.}} after the rate
			end
			
		end
		
		
		
		function add_rate(rate, rate_precision, colspan, class)
			local seen_games_here = nil
			
			rate = mw.ustring.gsub(rate, "-", "—")
			rate = mw.text.split(rate, ", ")
			if tonumber(rate[1])
			then rate[1] = string.gsub(rate[1], "%.", ",") .. "&nbsp;%"
			else rate[1] = mw.ustring.gsub(rate[1], "{{!}}", "|")
			end
			if rate[1] == "Fixe" then rate[1] = "[[Fichier:Icône Fixe.svg|27px|Fixe]]" end
			
			table.insert(current_subarea_full_locations, "<td")
			if class then table.insert(current_subarea_full_locations, ' class="' .. class .. '"') end
			if colspan then table.insert(current_subarea_full_locations, ' colspan="' .. colspan .. '"') end
			table.insert(current_subarea_full_locations, '>' .. rate[1])
			
			local k = 2
			while rate[k] do	-- Gestion des taux spécifiques à des jeux
				if tonumber(rate[k])
				then table.insert(current_subarea_full_locations, "<br>" .. string.gsub(rate[k], "%.", ",") .. "&nbsp;%")
				else table.insert(current_subarea_full_locations, frame:expandTemplate{title='Sup', args={rate[k]}})
					if seen_games_here and seen_games_here ~= rate[k] then seen_games_here = "all" else seen_games_here = rate[k] end
				end
				k = k + 1
			end
			if rate_precision then table.insert(current_subarea_full_locations, '<br><small><i>' .. rate_precision .. '</i></small>') end
			table.insert(current_subarea_full_locations, "</td>")
			
			-- might want rework if there is a trio of games at some point
			if rate[2] or rate[1] ~= "—"
			then if seen_games_place and seen_games_place ~= seen_games_here
				then seen_games_place = "all"
				else seen_games_place = seen_games_here
				end
			end
		end
		
		local place_info = places[i]["contents"]
		if place_info
		then local j = 1
			while place_info[j] do
				local id = places[i]["id"]
				local milieu = place_info[j]["milieu"]
				local emplacement = place_info[j]["emplacement"]
				
				if milieu
				then milieu = mw.ustring.gsub(milieu, "<br>", " ")
					milieu_split = mw.ustring.gsub(milieu, ',', '')
				else milieu = ""
				end
				
				-- précision de localisation par rapport au "milieu"
				if emplacement
				then emplacement = ', ' .. mw.ustring.gsub(emplacement, "<br>", " ")
				else emplacement = ""
				end
				
				local endroit_unsplit = mw.text.split(milieu, ",, ")
				local prefixe_endroit = endroit_unsplit[2] -- éventuellement nil
				local endroit = mw.text.split(endroit_unsplit[1], ",")
				local endroit_untouched = endroit[1]
				if prefixe_endroit == nil
				then prefixe_endroit = ""
				else prefixe_endroit = prefixe_endroit .. " "
					endroit[1] = mw.ustring.lower(mw.ustring.sub(endroit[1],1,1)) .. mw.ustring.sub(endroit[1],2,endroit[1]:len())
					-- on a mis la première lettre de l'endroit en minuscule, puisqu'elle est précédée de prefixe_endroit
				end
				endroit[1] = mw.ustring.gsub(endroit[1], " %([^%)]*%)", "")
				-- on retire les parenthèses des milieux, elles ne servent qu'à spécifier l'image, inutile ici
				
				if endroit[2] == nil then endroit[2] = "" end
				endroit[1] = mw.ustring.gsub(endroit[1], " – ", ", ")
				endroit[2] = mw.ustring.gsub(endroit[2], " – ", ", ")
			
				local jeu_abreviation = endroit[2]:gsub(".*{{Abréviation{{!}}(.-)}}.*", "%1") -- il faut renseigner le modèle Abréviation avec "{{!}}" et non "|"
				if jeu_abreviation ~= endroit[2]
				then jeu_abreviation = frame:expandTemplate{title='Abréviation', args={jeu_abreviation}}
					endroit[2] = endroit[2]:gsub("(.*){{Abréviation{{!}}(.-)}}(.*)", "%1" .. jeu_abreviation .. "%3")
				end
				
				milieu = prefixe_endroit .. endroit[1] .. endroit[2] .. emplacement
				if milieu ~= "" then milieu = " – " .. milieu end
				
				table.insert(current_subarea_full_locations, "<tr>")
				if multiple_ids
				then if id
					then table.insert(current_subarea_full_locations, "<td>" .. ressources.infosPokemon(id, "miniature") .. "</td>")
					else table.insert(current_subarea_full_locations, "<td></td>")
					end
				end
				table.insert(current_subarea_full_locations, "<td>" .. place_link_display .. place_suffix .. milieu .. '</td><td>')
				
				local level = place_info[j]["niveau"]
				if level then level = mw.ustring.gsub(level, "-", "–") else level = "—" end
				level = mw.text.split(level, ", ")
				
				table.insert(current_subarea_full_locations, '<span style="white-space:nowrap">' .. level[1])
				local k = 2
				while level[k] do
					level_k = mw.ustring.gsub(level[k], "–", "")
					if tonumber(level_k)
					then table.insert(current_subarea_full_locations, '</span><br><span style="white-space:nowrap">' .. level[k])
					else table.insert(current_subarea_full_locations, frame:expandTemplate{title='Sup', args={level[k]}})
					end
					k = k + 1
				end
				table.insert(current_subarea_full_locations, "</span></td>")
				
				local rate = place_info[j]["taux"]
				if rate
				then local rate_precision = place_info[j]["précision-taux"]
					add_rate(rate, rate_precision, reduced_colspan_rates[current_game], nil)
					
				else local subarea_info = subarea_subrates_list[current_game][subarea_text]
					if subarea_info.subrates
					then local colspan_local = math.floor(reduced_colspan_rates[current_game] / subarea_info.number)
						for s = 1, subarea_info.number do
							local subrate_s = place_info[j][subarea_info.subrates[2][s]]
							if not subrate_s then subrate_s = "—" end
							local subrate_s_precision = place_info[j]["précision-" .. subarea_info.subrates[2][s]]
							add_rate(subrate_s, subrate_s_precision, colspan_local, subarea_info.subrates[3][s])
						end
					else add_rate("—", nil, reduced_colspan_rates[current_game], nil)
					end
						
				end
				table.insert(current_subarea_full_locations, "</tr>")
				
				j = j + 1
			end
		end
		
		i = i + 1
	end
	table.insert(result, '<caption style="caption-side:bottom; font-weight:normal"><small><i>Ce tableau est généré automatiquement. Pour que son contenu soit modifié, il faut modifier les pages de lieux. Informations détaillées sur [[Module:Localisations|cette page]].</i></small></caption></tbody></table>')
	
	-- if is_there_full_table
	-- then
		table.insert(result_header, '<table class="tableaustandard centre ' .. pokemon_type .. '"><tbody><tr><th width="150px">Versions</th><th width="600px">Localisations</th><th width="60px">Détails</th>')
		table.insert(result, table.concat(full_table, ""))
	-- else table.insert(result_header, '<table class="tableaustandard centre ' .. pokemon_type .. '"><tbody><tr><th width="150px">Versions</th><th width="600px" colspan="2">Localisations</th>')
	-- end
	
	table.insert(result_header, '</tr>')
	table.insert(result_header, table.concat(result, ""))
	return table.concat(result_header, "")
end



-- Fonction pour recenser les endroits de tous les Pokémon détectés pour un même jeu, donné en argument
function p.pokeliste(frame)
	local result = {}
	local game = frame.args["jeu"]
	if not game then game = frame.args[1] end
	local game_long = game_to_game_long[game]
	if not game_long then return "<i>Erreur : jeu invalide.</i>" end
	
	if game ~= "LPA"
	then game_long = "Pokémon " .. game_to_game_long[game]
	end
	
	local locdata = require("Module:Localisations/Données/" .. game_long)
	local pokemon_global_list = {}
	for place_name, pokemon_list in pairs(locdata) do
		local place_name_stripped = mw.text.split(mw.text.split(place_name, "@")[1], "|")[1]
		local place_name_link = "[[" .. place_name_stripped .. "|" .. mw.ustring.gsub(place_name_stripped, " %(.-%).-", "") .. "]]"
		for pokemon, _ in pairs(pokemon_list) do
			if pokemon_global_list[pokemon]
			then pokemon_global_list[pokemon] = pokemon_global_list[pokemon] .. ", " .. place_name_link
			else pokemon_global_list[pokemon] = place_name_link
			end
		end
	end
	
	table.insert(result, '<table class="tableaustandard sortable entetefixe"><tr><th>infosPokemon</th><th>Pokémon</th><th>Lieux</th></tr>')
	
	for pokemon, places in pairs(pokemon_global_list) do
		table.insert(result, '<tr><td>' .. ressources.infosPokemon(pokemon) .. '</td><td>' .. pokemon .. '</td><td>' .. places .. '</td></tr>')
	end
	
	table.insert(result, '</table>')
	
	return table.concat(result, "")
end

return p