Forlage zu Erweiterte Befehle

Hier können nach Lust und Laune über alles außerhalb von Fantasya geschrieben werden.
Tsaria
Hauptmann
Beiträge: 50
Registriert: Mi 16. Mär 2016, 11:11
Wohnort: Kassel

Forlage zu Erweiterte Befehle

Beitrag von Tsaria » Fr 25. Mär 2016, 12:04

In diesem thread werde ich in den nächsten Tagen so nach und nach Forlage in Scripte für Erweiterte Befehle umsetzen. Zum einen als Fingerübung für mich, zum anderen, damit sie von anderen genutzt werden können ... und evtl. weiterentwickelt. Viel Spaß.

Die Dokumentation von Forlage findet ihr hier.

Aktuelle Version: #auslastung, #magbest, #immer, #next, #mal, #rotate, #forst und #herde.

An roten Funktionen habe ich kompatibilitätsbeeinträchtigende Änderungen vornehmen müssen.

Code: Alles auswählen

import magellan.client.*;
import magellan.client.extern.*;
import magellan.library.*;
import magellan.library.rules.*;
import magellan.plugin.extendedcommands.*;

import java.util.ArrayList;
import java.util.regex.*;

// mOrdersauswertung

String regex = "(?<mPrefix>// #)(?<mOrder>[A-Za-z_]{3,10})\\u0020?(?<mCounter>[\\d]{0,4})\\u0020(?<mCounter2>[\\d]{0,4})\\u0020?(?<mSubOrders>.*$)?";
Pattern p = Pattern.compile(regex);
Matcher m;
int eff = 100;

for (Region region : world.regions().values()) {
	for (Unit unit : region.units()) {
		int index = 0;
		for (String subOrder : unit.getOrders()) {
			m = p.matcher(subOrder);
			if (m.find()) {
				String mPrefix = m.group("mPrefix");
				String mOrder = m.group("mOrder");
				int mCounter = 0;
				if (!(m.group("mCounter").isEmpty()))
					mCounter = Integer.parseInt(m.group("mCounter"));
				String mSubOrders = m.group("mSubOrders");
				ArrayList mOrdersListe = new ArrayList();
				switch (mOrder) {
				case "auslastung":
					eff = mCounter;
					break;
				case "magbest":
					if (!unit.isOrdersConfirmed()) {
						unit.setOrdersConfirmed(true);
					}
				case "immer":
					if (mSubOrders.contains(":")) {
						for (String so : mSubOrders.split(":"))
							mOrdersListe.add(so.trim());
					} else {
						mOrdersListe.add(mSubOrders.trim());
					}
					break;
				case "next":
					mCounter--;
					unit.removeOrderAt(index);
					if (mCounter > 0) {
						mOrdersListe.add(mPrefix + mOrder + " " + mCounter + " " + mSubOrders);
					} else {
						if (mSubOrders.contains(":")) {
							for (String so : mSubOrders.split(":"))
								mOrdersListe.add(so);
						} else {
							mOrdersListe.add(mSubOrders);
						}
					}
					break;
				case "mal":
					mCounter--;
					unit.removeOrderAt(index);
					if (mCounter > 0) {
						mOrdersListe.add(mPrefix + mOrder + " " + mCounter + " " + mSubOrders);
						if (mSubOrders.contains(":")) {
							for (String so : mSubOrders.split(":"))
								mOrdersListe.add(so);
						} else {
							mOrdersListe.add(mSubOrders);
						}
					}
					break;
				case "rotate":
					mCounter++;
					String[] mso = mSubOrders.split(":");
					int numRotate = mso.length;
					if (mCounter > numRotate)
						mCounter = 1;
					unit.removeOrderAt(index);
					mOrdersListe.add(mPrefix + mOrder + " " + mCounter + " " + mSubOrders);
					int i = 1;
					for (String so : mso) {
						if (i == mCounter)
							mOrdersListe.add(so);
						i++;
					}
					break;
				case "forst":
					int rTrees = unit.getRegion()
							.getResource(region.data.getRules().getItemType(StringID.create("Holz")))
							.getAmount();
					int mCounter2 = -1;
					if (!(m.group("mCounter2").isEmpty()))
						mCounter2 = Integer.parseInt(m.group("mCounter2"));
					int uCapWood = helper.getLevel(unit, "Holzfällen") * unit.getPersons();
					int fellTrees = 0;

					if (mCounter2 > 0) {
						if (rTrees > mCounter2) {
							if ((mCounter2 - mCounter) > uCapWood) {
								fellTrees = uCapWood;
							} else {
								fellTrees = mCounter2 - mCounter;
							}
						}
					} else {
						if (rTrees > mCounter) {
							fellTrees = rTrees - mCounter;
						}
					}

					if (fellTrees > 0) {
						mOrdersListe.add("MACHE " + fellTrees + " Holz");
					} else {
						mOrdersListe.add(mSubOrders);
					}
					break;
				case "herde":
					String mAnimSO;
					String mAnim;
					int uCapAnimal = helper.getLevel(unit, "Pferdedressur") * unit.getPersons();
					int herdAnimals = 0;

					for (String so : mSubOrders.split(":")) {
						String animRegex = "(?i)(?<mAnim>pferd|kamel|elefant|zotte|alpaka|mastodon)\\u0020(?<mAnimC1>[\\d]{1,4})\\u0020(?<mAnimC2>[\\d]{1,4})?\\u0020?(?<mAnimSO>.*$)?";
						Pattern animP = Pattern.compile(animRegex);
						Matcher animM;
						animM = animP.matcher(so);

						if (animM.find()) {
							mAnim = animM.group("mAnim");
							int rHerd = unit.getRegion().getResource(region.data.getRules().getItemType(StringID.create(mAnim))).getAmount();
							int mAnimC1 = Integer.parseInt(animM.group("mAnimC1"));
							int mAnimC2 = (animM.group("mAnimC2") != null) ? Integer.parseInt(animM.group("mAnimC2")) : mAnimC1;
							
							if (rHerd > mAnimC2) {
								String s = mAnim.toLowerCase();
								int eFactor = (s.contains("elefant") || s.contains("mastodon")) ? 2 : 1;
								herdAnimals = Math.min((int)(uCapAnimal/eFactor), rHerd - mAnimC2);
								break;
							}
						}
					}
					if (herdAnimals > 0) {
						mOrdersListe.add("MACHE " + herdAnimals + " " + mAnim);
					} else {
						mOrdersListe.add(mAnimSO);
					}
					break;
				default:
				}
				unit.addOrders(mOrdersListe);
			}
			index++;
		}
	}
}
Änderungen zu Forlage:

#auslastung

Dieser neue Befehl erlaubt euch eine Variable zu setzen, die beeinflußt bei wieviel mindest % Effizienz eure #forst und #herde Metabefehl arbeiten. #auslastung 90 z.B. würde bewirken, das eine 10er Holzfällereinheit mit Holzfällen 2 nur dann arbeitet, wenn sie mindestens 10*2*90% = 18 Holz machen kann.

WIP: Momentan nicht in Funktion. Wird vermutlich noch heftig überarbeitet.

#rotate

sieht bei mir nicht so:

Code: Alles auswählen

// #rotate1 MACHE Holz
// #rotate2 MACHE Speer
// #rotate3 TREIBE
sondern so aus:

Code: Alles auswählen

// #rotate0 MACHE Holz : MACHE Speer :TREIBE
Mit jedem Durchlauf setzt das script diese Zahl um eins hoch, und führt danach den passenden Befehl aus. rotate0 bedeutet also das der folgende, der 1. Befehl ausgeführt wird. Sobald alle Befehle einmal ausgeführt wurden, geht es am Anfang wieder los. Hierdurch ist es NICHT mehr möglich mit einem rotate mehrere Befehle in einem turn auszuführen, dafür braucht man aber nur noch einen rotate Befehl für einen ganzen Durchgang.

Will man mehrere Befehle pro Zug ausführen, muß man 2 #rotate benutzen. Z.B.:

Code: Alles auswählen

// #rotate0 MACHE Holz : MACHE Speer :TREIBE
// #rotate0  : : GIB xyz 1 Speer
Dies würde in der ersten Runde Holz machen, in der zweiten einen Speer anfertigen, in der 3. Runde Steuern eintreiben und einen Speer übergeben. Wichtig sind hierbei die : und Leerzeichen, sie zeigen beim zweiten rotate an, das diese Rotation 3 Runden andauert, aber in den beiden ersten nichts (zusätzliches) passiert. Ich würde empfehlen ein #rotate für lange Befehle, und ggf. weitere #rotate für die zusätzlichen kurzen Befehle zu verwenden.[/quote]

#forst

berücksichtigt bisher kein Sägewerk, da ich die passende Funktion noch nicht ausgegraben habe.

#herde

Trenner ist : statt |. Hintergrund ist eine von mir beabsichtigte Vereinheitlichung (forlage verwendet überall : um Unterbefehle zu trennen. Wer | verwenden will... einfach das Zeichen im Split austauschen. Ja ich weiß das | hier als "oder" Sinn macht... Wie gesagt, es ist ein Zeichen zu ändern, wenn ihr alle sagt "wir wollen |" dann änder ich es.

SUMMA

Ihr müsst also eure Forlage Befehle evtl. anpassen, und die vollständige Kompatibilität ist leider auch pfutsch. :/ Ich mach das auch nicht gern, aber ohne lokale Speicherung geht vor allem der #rotate nicht anders :/.
Großer Vorteil allerdings: Diese Version kommt eben komplett ohne lokal gespeicherte Daten aus, sprich wenn ihr mal an einem anderen Rechner sitzt, oder euer Magellan wrecked, zieht ihr alle nötigen Infos aus den comments im CR.[/spoiler]
Zuletzt geändert von Tsaria am Do 31. Mär 2016, 08:55, insgesamt 21-mal geändert.

Tsaria
Hauptmann
Beiträge: 50
Registriert: Mi 16. Mär 2016, 11:11
Wohnort: Kassel

Re: Forlage zu Erweiterte Befehle

Beitrag von Tsaria » Fr 25. Mär 2016, 12:10

Platzhalter für das pure #immer script:

Code: Alles auswählen

String metaPrefix = "/" + "/ #";

for (Region region : world.regions().values()) {
   for (Unit unit : region.units()) {      
      for (String befehl : unit.getOrders()){
         if (befehl.startsWith(metaPrefix)) {
            metaBefehlsListe = new ArrayList();
            if (befehl.contains("#immer")) {
               befehl = befehl.substring(befehl.indexOf("#immer ")+7);
               while (befehl.contains(":")) {
                  metaBefehlsListe.add(befehl.substring(0, befehl.indexOf(":")).trim());
                  befehl = befehl.substring(befehl.indexOf(":")+1);
               }
               metaBefehlsListe.add(befehl.trim());
            }
            unit.addOrders(metaBefehlsListe);
         }
      }
   }
}
Zuletzt geändert von Tsaria am Fr 25. Mär 2016, 12:11, insgesamt 1-mal geändert.

Tsaria
Hauptmann
Beiträge: 50
Registriert: Mi 16. Mär 2016, 11:11
Wohnort: Kassel

Re: Forlage zu Erweiterte Befehle

Beitrag von Tsaria » Fr 25. Mär 2016, 12:10

Und hier #immer und #next:

Code: Alles auswählen

String metaPrefix = "/" + "/ #";
String checkNumeric = "0123456789";

for (Region region : world.regions().values()) {
	for (Unit unit : region.units()) {
		int index = 0;
		for (String befehl : unit.getOrders()) {
			if (befehl.startsWith(metaPrefix)) {
				ArrayList metaBefehlsListe = new ArrayList();
				// #immer
				if (befehl.contains("#immer")) {
					befehl = befehl.substring(befehl.indexOf("#immer") + 6);
					while (befehl.contains(":")) {
						metaBefehlsListe.add(befehl.substring(0, befehl.indexOf(":")).trim());
						befehl = befehl.substring(befehl.indexOf(":") + 1);
					}
					metaBefehlsListe.add(befehl.trim());
				}
				// #next
				if (befehl.contains("#next")) {
					befehl = befehl.substring(befehl.indexOf("#next") + 5);
					String strTurns = befehl.substring(0, befehl.indexOf(" "));
					int turns = Integer.parseInt(strTurns) - 1;
					befehl = befehl.substring(befehl.indexOf(" ") + 1);
					unit.removeOrderAt(index);
					if (turns > 0) {
						metaBefehlsListe.add(metaPrefix + "next" + turns + " " + befehl);
					} else {
						while (befehl.contains(":")) {
							metaBefehlsListe.add(befehl.substring(0, befehl.indexOf(":")).trim());
							befehl = befehl.substring(befehl.indexOf(":") + 1);
						}
						metaBefehlsListe.add(befehl);
					}	
				}
				unit.addOrders(metaBefehlsListe);
			}
			index++;
		}
	}
}

Benutzeravatar
Thalian
Administrator
Beiträge: 653
Registriert: Mo 5. Jan 2015, 14:25
Kontaktdaten:

Re: Forlage zu Erweiterte Befehle

Beitrag von Thalian » Fr 25. Mär 2016, 16:09

Mir als Noch-Nie-Forlage-Oder-Sowas-Nutzer fehlt die "Dokumentation" zu den Makros. Kann man die Anwendungsregeln irgendwo nachlesen?

Benutzeravatar
nemo
Heerführer
Beiträge: 232
Registriert: Mi 25. Feb 2015, 12:06

Re: Forlage zu Erweiterte Befehle

Beitrag von nemo » Fr 25. Mär 2016, 18:36

http://www.metadrei.org/toolbelt/forlag ... -doku.html

...und eine leicht andere Frage: wenn das Projekt jetzt ernst wird, könnte es dann ein eigenes Unter Forum bekommen?

@Tsaria: Verständnis Frage zu #next: ist das technisch momentan auf 0-9 als Argument beschränkt?
I may go pop -- Excuse me!

Tsaria
Hauptmann
Beiträge: 50
Registriert: Mi 16. Mär 2016, 11:11
Wohnort: Kassel

Re: Forlage zu Erweiterte Befehle

Beitrag von Tsaria » Fr 25. Mär 2016, 19:14

Nö, der Counter hinter next darf nach der momentanen Variante INT_MAX annehmen, also 2^31 -1 oder 2.147.483.647.

In der nächsten Variante an der ich arbeite, welche reguläre Ausdrücke beinhaltet, werde ich dies aber wohl auf vierstellig begrenzen. Vierstellig sollte aber ausreichen ... ich meine Enno wird Eressea wohl nicht noch more than 9000 turns weiterführen. ;)
EDIT: steht seit neuer Version auf 4stellig.

Und hier die neueste Version. gleiche Funktionalität wie bisher, aber eleganter und zukunftsfähiger gelöst.

Code: Alles auswählen

import magellan.client.*;
import magellan.client.extern.*;
import magellan.library.*;
import magellan.library.rules.*;
import magellan.plugin.extendedcommands.*;
import java.util.regex.*;

// metaOrdersauswertung

String regex = "(?<metaPrefix>// #)(?<metaOrder>[A-Za-z_]{3,10})(?<metaCounter>[\\d]{0,4})(?<metaSubOrders>.*$)?";
Pattern p = Pattern.compile(regex);
Matcher m;

for (Region region : world.regions().values()) {
	for (Unit unit : region.units()) {
		int index = 0;
		for (String befehl : unit.getOrders()) {
			m = p.matcher(befehl);
			if (m.find()) {
				String metaPrefix = m.group("metaPrefix");
				String metaOrder = m.group("metaOrder");
				String metaCounter = m.group("metaCounter");
				String metaSubOrders = m.group("metaSubOrders");
				ArrayList metaOrdersListe = new ArrayList();
				switch (metaOrder) {
				case "immer":
					if (metaSubOrders.contains(":")) {
						String[] mso = metaSubOrders.split(":");
						for (String so : mso)
							metaOrdersListe.add(so.trim());
					} else {
						metaOrdersListe.add(metaSubOrders.trim());
					}
					break;
				case "next":
					int turns = Integer.parseInt(metaCounter) - 1;
					unit.removeOrderAt(index);
					if (turns > 0) {
						metaOrdersListe.add(metaPrefix + metaOrder + turns + metaSubOrders);
					} else {
						if (metaSubOrders.contains(":")) {
							String[] mso = metaSubOrders.split(":");
							for (String so : mso)
								metaOrdersListe.add(so.trim());
						} else {
							metaOrdersListe.add(metaSubOrders.trim());
						}
					}
					break;
				default:
				}
				unit.addOrders(metaOrdersListe);
			}
			index++;
		}
	}
}
Für Interessierte: ja, die regex und switch case machen den momentanen Code etwas länger, erleichtern mir aber langfristig die Arbeit. Bin halt Anfänger. :D

Tsaria
Hauptmann
Beiträge: 50
Registriert: Mi 16. Mär 2016, 11:11
Wohnort: Kassel

Re: Forlage zu Erweiterte Befehle

Beitrag von Tsaria » Sa 26. Mär 2016, 07:40

Und die nächste Version, diesmal inkl: #magbest, #mal und #rotate(geändert).

Code: Alles auswählen

// metaOrdersauswertung

String regex = "(?<metaPrefix>// #)(?<metaOrder>[A-Za-z_]{3,10})(?<metaCounter>[\\d]{0,4})(?<metaSubOrders>.*$)?";
Pattern p = Pattern.compile(regex);
Matcher m;

for (Region region : world.regions().values()) {
	for (Unit unit : region.units()) {
		int index = 0;
		for (String befehl : unit.getOrders()) {
			m = p.matcher(befehl);
			if (m.find()) {
				String metaPrefix = m.group("metaPrefix");
				String metaOrder = m.group("metaOrder");
				String metaCounter = m.group("metaCounter");
				String metaSubOrders = m.group("metaSubOrders");
				ArrayList metaOrdersListe = new ArrayList();
				int turns;
				switch (metaOrder) {
				case "magbest":
					if (!unit.isOrdersConfirmed()) {
						unit.setOrdersConfirmed(true);
					}
				case "immer":
					if (metaSubOrders.contains(":")) {
						String[] mso = metaSubOrders.split(":");
						for (String so : mso)
							metaOrdersListe.add(so.trim());
					} else {
						metaOrdersListe.add(metaSubOrders.trim());
					}
					break;
				case "next":
					turns = Integer.parseInt(metaCounter) - 1;
					unit.removeOrderAt(index);
					if (turns > 0) {
						metaOrdersListe.add(metaPrefix + metaOrder + turns + metaSubOrders);
					} else {
						if (metaSubOrders.contains(":")) {
							String[] mso = metaSubOrders.split(":");
							for (String so : mso)
								metaOrdersListe.add(so.trim());
						} else {
							metaOrdersListe.add(metaSubOrders.trim());
						}
					}
					break;
				case "mal":
					turns = Integer.parseInt(metaCounter) - 1;
					unit.removeOrderAt(index);
					if (turns > 0) {
						metaOrdersListe.add(metaPrefix + metaOrder + turns + metaSubOrders);
						if (metaSubOrders.contains(":")) {
							String[] mso = metaSubOrders.split(":");
							for (String so : mso)
								metaOrdersListe.add(so.trim());
						} else {
							metaOrdersListe.add(metaSubOrders.trim());
						}
					}
					break;
				case "rotate":
					turns = Integer.parseInt(metaCounter) + 1;
					String[] mso = metaSubOrders.split(":");
					int numRotate = mso.length;
					if (turns > numRotate) turns = 1;
					unit.removeOrderAt(index);
					metaOrdersListe.add(metaPrefix + metaOrder + turns + metaSubOrders);	
					int i = 1;
					for (String so : mso) {
						if (i == turns) metaOrdersListe.add(so.trim());
						i++;
					}
					break;
				default:
				}
				unit.addOrders(metaOrdersListe);
			}
			index++;
		}
	}
}
WICHTIG: Ich habe eine Änderung am Parsing des #rotate Befehls vorgenommen. In meiner Version sieht Rotate nicht mehr so:
// #rotate<n> Befehl [:Befehl] [:Befehl]

Beispiel:
// #rotate1 MACHE Holz
// #rotate2 MACHE Speer
// #rotate3 TREIBE
sondern so aus:
Ein #rotate Befehl wird folgendermaßen gesetzt:

// #rotate0 Befehl [:Befehl] [:Befehl]

Beispiel:
// #rotate0 MACHE Holz : MACHE Speer :TREIBE

Mit jedem Durchlauf setzt das script diese Zahl um eins hoch, und führt danach den passenden Befehl aus. rotate0 bedeutet also das der folgende, der 1. Befehl ausgeführt wird. Sobald alle Befehle einmal ausgeführt wurden, geht es am Anfang wieder los. Hierdurch ist es NICHT mehr möglich mit einem rotate mehrere Befehle in einem turn auszuführen, dafür braucht man aber nur noch einen rotate Befehl für den ganzen Durchgang.

Will man mehrere Befehle pro Zug ausführen, muß man 2 #rotate benutzen. Z.B.:

// #rotate0 MACHE Holz : MACHE Speer :TREIBE
// #rotate0 : : GIB xyz 1 Speer

Dies würde in der ersten Runde Holz machen, in der zweiten einen Speer anfertigen, in der 3. Runde Steuern eintreiben und einen Speer übergeben. Wichtig sind hierbei die : und Leerzeichen, sie zeigen beim zweiten rotate an, das diese Rotation 3 Runden andauert, aber in den beiden ersten nichts (zusätzliches) passiert.
Ihr müsst also eure Forlage Befehle evtl. anpassen, und die vollständige Kompatibilität ist leider auch pfutsch. :/
Sorry, ohne größere Anpassungen geht das leider nicht anders :/. Großer Vorteil: Diese Version kommt komplett ohne lokal gespeicherte Daten aus, sprich wenn ihr mal an einem anderen Rechner sitzt, zieht das alle nötigen Infos aus den comments im CR.

Benutzeravatar
Thalian
Administrator
Beiträge: 653
Registriert: Mo 5. Jan 2015, 14:25
Kontaktdaten:

Re: Forlage zu Erweiterte Befehle

Beitrag von Thalian » Sa 26. Mär 2016, 07:56

nemo hat geschrieben:http://www.metadrei.org/toolbelt/forlag ... -doku.html
...und eine leicht andere Frage: wenn das Projekt jetzt ernst wird, könnte es dann ein eigenes Unter Forum bekommen?
Sollen wir den Thread nicht einfach nach Entwicklung schieben?

Tsaria
Hauptmann
Beiträge: 50
Registriert: Mi 16. Mär 2016, 11:11
Wohnort: Kassel

Re: Forlage zu Erweiterte Befehle

Beitrag von Tsaria » Sa 26. Mär 2016, 08:17

Hmm, können wir machen, wobei da dann die Frage ist, ob er übersehen wird. Vielleicht wäre es sinnvoll, im Fantasya Hauptspiel nochmal einen Bereich "Tools" einzurichten? Weil auch der thread zu den erweiterten Befehlen generell wird von manchen sicher nicht wahrgenommen, weil er eben unter "Weiterentwicklung" steht. Viele Spieler wollen ja gar nicht weiterentwickeln, sondern sind einfach nur user.

Benutzeravatar
nemo
Heerführer
Beiträge: 232
Registriert: Mi 25. Feb 2015, 12:06

Re: Forlage zu Erweiterte Befehle

Beitrag von nemo » Sa 26. Mär 2016, 19:02

@Thalian: macht wie denkt Ihr. Ich denke bloß, dass FzEB was anderes ist, als ein allgemeiner Austausch über erweiterte Befehle, und, dass Tsaria der Ruhm für FzEB gebührt :D

@ Tsaria: Ab einer gewissen Parteigröße kommt man eh nicht drum herum, Irgentetwas zu entwickeln, wenn die eigenen Bedürfnisse noch nicht von einem vorhandenen Tool abgedeckt sind. Nur, dass Entwickler-Forum eigtl. Fantasya betrifft (mein Eindruck jdflls.).
I may go pop -- Excuse me!

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste